home *** CD-ROM | disk | FTP | other *** search
- /* $Source: /u/mark/src/pax/RCS/fileio.c,v $
- *
- * $Revision: 1.2 $
- *
- * fileio.c - file I/O functions for all archive interfaces
- *
- * DESCRIPTION
- *
- * These function all do I/O of some form or another. They are
- * grouped here mainly for convienence.
- *
- * AUTHOR
- *
- * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
- *
- * Sponsored by The USENIX Association for public distribution.
- *
- * Copyright (c) 1989 Mark H. Colburn.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice is duplicated in all such
- * forms and that any documentation, advertising materials, and other
- * materials related to such distribution and use acknowledge that the
- * software was developed * by Mark H. Colburn and sponsored by The
- * USENIX Association.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $Log: fileio.c,v $
- * Revision 1.2 89/02/12 10:04:31 mark
- * 1.2 release fixes
- *
- * Revision 1.1 88/12/23 18:02:09 mark
- * Initial revision
- *
- */
-
- #ifndef lint
- static char *ident = "$Id: fileio.c,v 1.2 89/02/12 10:04:31 mark Exp $";
- static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
- #endif /* ! lint */
-
-
- /* Headers */
-
- #include "pax.h"
-
-
- /* open_archive - open an archive file.
- *
- * DESCRIPTION
- *
- * Open_archive will open an archive file for reading or writing,
- * setting the proper file mode, depending on the "mode" passed to
- * it. All buffer pointers are reset according to the mode
- * specified.
- *
- * PARAMETERS
- *
- * int mode - specifies whether we are reading or writing.
- *
- * RETURNS
- *
- * Returns a zero if successfull, or -1 if an error occured during
- * the open.
- */
-
- #ifdef __STDC__
-
- int open_archive(int mode)
-
- #else
-
- int open_archive(mode)
- int mode;
-
- #endif
- {
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: int open_archive() in fileio.c\n");
- #endif
- if (ar_file[0] == '-' && ar_file[1] == '\0') {
- if (mode == AR_READ) {
- archivefd = STDIN;
- bufend = bufidx = bufstart;
- } else {
- archivefd = STDOUT;
- }
- } else if (mode == AR_READ) {
- archivefd = open(ar_file, O_RDONLY | O_BINARY);
- bufend = bufidx = bufstart; /* set up for initial read */
- } else if (mode == AR_WRITE) {
- archivefd = open(ar_file, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, /* Xn */
- S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); /* Xn */
- } else if (mode == AR_APPEND) {
- archivefd = open(ar_file, O_RDWR | O_BINARY, /* Xn */
- S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); /* Xn */
- bufend = bufidx = bufstart; /* set up for initial read */
- }
-
- if (archivefd < 0) {
- warnarch(strerror(errno), (OFFSET) 0); /* Xn */
- return (-1);
- }
- ++arvolume;
- return (0);
- }
-
-
- /* close_archive - close the archive file
- *
- * DESCRIPTION
- *
- * Closes the current archive and resets the archive end of file
- * marker.
- */
-
- #ifdef __STDC__
-
- void close_archive(void)
-
- #else
-
- void close_archive()
-
- #endif
- {
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: void close_archive() in fileio.c\n");
- #endif
- if (archivefd != STDIN && archivefd != STDOUT) {
- close(archivefd);
- }
- areof = 0;
- }
-
-
- /* openout - open an output file
- *
- * DESCRIPTION
- *
- * Openo opens the named file for output. The file mode and type are
- * set based on the values stored in the stat structure for the file.
- * If the file is a special file, then no data will be written, the
- * file/directory/Fifo, etc., will just be created. Appropriate
- * permission may be required to create special files.
- *
- * PARAMETERS
- *
- * char *name - The name of the file to create
- * Stat *asb - Stat structure for the file
- * Link *linkp; - pointer to link chain for this file
- * int ispass - true if we are operating in "pass" mode
- *
- * RETURNS
- *
- * Returns the output file descriptor, 0 if no data is required or -1
- * if unsuccessful. Note that UNIX open() will never return 0 because
- * the standard input is in use.
- */
-
- #ifdef __STDC__
-
- int openout(char *name, Stat *asb, Link *linkp, int ispass)
-
- #else
-
- int openout(name, asb, linkp, ispass)
- char *name;
- Stat *asb;
- Link *linkp;
- int ispass;
-
- #endif
- {
- int exists;
- int fd;
- #ifdef _POSIX_SOURCE /* Xn */
- mode_t perm; /* Xn */
- mode_t operm = (mode_t)0; /* Xn */
- #else /* Xn */
- ushort perm;
- ushort operm = 0;
- #endif /* Xn */
- Stat osb;
- #ifdef S_IFLNK
- int ssize;
- char sname[PATH_MAX + 1];
- #endif /* S_IFLNK */
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: int openout() in fileio.c\n");
- #endif
- if ((exists = (LSTAT(name, &osb) == 0)) != 0) { /* Xn */
- if (ispass && osb.sb_ino == asb->sb_ino && osb.sb_dev == asb->sb_dev) {
- warn(name, "Same file");
- return (-1);
- } else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT)) {
- operm = osb.sb_mode & S_IPERM;
- } else if (REMOVE(name, &osb) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- } else {
- exists = 0;
- }
- }
- if (linkp) {
- if (exists) {
- if (asb->sb_ino == osb.sb_ino && asb->sb_dev == osb.sb_dev) {
- return (0);
- } else if (unlink(name) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- } else {
- exists = 0;
- }
- }
- if (link(linkp->l_name, name) != 0) {
- if (errno == ENOENT) {
- if (f_dir_create) {
- if (dirneed(name) != 0 ||
- link(linkp->l_name, name) != 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- } else {
- warn(name,
- "Directories are not being created (-d option)");
- }
- return(0);
- } else if (errno != EXDEV) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- } else {
- return(0);
- }
- }
- perm = asb->sb_mode & S_IPERM;
- switch (asb->sb_mode & S_IFMT) {
- case S_IFBLK:
- case S_IFCHR:
- fd = 0;
- if (exists) {
- #ifndef _POSIX_SOURCE
- if (asb->sb_rdev == osb.sb_rdev) {
- if (perm != operm && chmod(name, (int) perm) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- } else {
- break;
- }
- } else if (REMOVE(name, &osb) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- } else {
- exists = 0;
- }
- #else
- if (REMOVE(name, &osb) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- } else {
- exists = 0;
- }
- #endif /* _POSIX_SOURCE */
- }
- #ifdef _POSIX_SOURCE
- if (mknod(name, asb->sb_mode, (dev_t)0))
- #else
- if (mknod(name, (int) asb->sb_mode, (int) asb->sb_rdev) < 0)
- #endif
- {
- if (errno == ENOENT) {
- if (f_dir_create) {
- if (dirneed(name) < 0 || mknod(name, (int) asb->sb_mode,
- #ifdef _POSIX_SOURCE
- 0))
- #else
- (int) asb->sb_rdev) < 0)
- #endif
- {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- } else {
- warn(name, "Directories are not being created (-d option)");
- }
- } else {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- }
- return(0);
- break;
- case S_IFDIR:
- if (exists) {
- if (perm != operm && chmod(name, (int) perm) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- } else if (f_dir_create) {
- if (dirmake(name, asb) < 0 || dirneed(name) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- } else {
- warn(name, "Directories are not being created (-d option)");
- }
- return (0);
- #ifdef S_IFIFO
- case S_IFIFO:
- fd = 0;
- if (exists) {
- if (perm != operm && chmod(name, (int) perm) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- }
- # ifdef _POSIX_SOURCE /* Xn */
- else if (mkfifo(name, asb->sb_mode) < 0) /* Xn */
- # else /* Xn */
- else if (mknod(name, (int) asb->sb_mode, 0) < 0)
- # endif /* Xn */
- {
- if (errno == ENOENT) {
- if (f_dir_create) {
- if (dirneed(name) < 0
- # ifdef _POSIX_SOURCE /* Xn */
- || mkfifo(name, asb->sb_mode) < 0) /* Xn */
- # else /* Xn */
- || mknod(name, (int) asb->sb_mode, 0) < 0)
- # endif /* _POSIX_SOURCE */ /* Xn */
- {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- } else {
- warn(name, "Directories are not being created (-d option)");
- }
- } else {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- }
- return(0);
- break;
- #endif /* S_IFIFO */
- #ifdef S_IFLNK
- case S_IFLNK:
- if (exists) {
- if ((ssize = readlink(name, sname, sizeof(sname))) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- } else if (strncmp(sname, asb->sb_link, ssize) == 0) {
- return (0);
- } else if (REMOVE(name, &osb) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- } else {
- exists = 0;
- }
- }
- if (symlink(asb->sb_link, name) < 0) {
- if (errno == ENOENT) {
- if (f_dir_create) {
- if (dirneed(name) < 0 || symlink(asb->sb_link, name) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- } else {
- warn(name, "Directories are not being created (-d option)");
- }
- } else {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- }
- return (0); /* Can't chown()/chmod() a symbolic link */
- #endif /* S_IFLNK */
- case S_IFREG:
- if (exists) {
- if (!f_unconditional && osb.sb_mtime > asb->sb_mtime) {
- warn(name, "Newer file exists");
- return (-1);
- } else if (unlink(name) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- } else {
- exists = 0;
- }
- }
- if ((fd = creat(name, (int) perm)) < 0) {
- if (errno == ENOENT) {
- if (f_dir_create) {
- if (dirneed(name) < 0 ||
- (fd = creat(name, (int) perm)) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- } else {
- /*
- * the file requires a directory which does not exist
- * and which the user does not want created, so skip
- * the file...
- */
- warn(name, "Directories are not being created (-d option)");
- return(0);
- }
- } else {
- warn(name, strerror(errno)); /* Xn */
- return (-1);
- }
- }
- break;
- default:
- warn(name, "Unknown filetype");
- return (-1);
- }
- if (f_owner) {
- if (!exists || asb->sb_uid != osb.sb_uid || asb->sb_gid != osb.sb_gid) {
- chown(name, (int) asb->sb_uid, (int) asb->sb_gid);
- }
- }
- return (fd);
- }
-
-
- /* openin - open the next input file
- *
- * DESCRIPTION
- *
- * Openi will attempt to open the next file for input. If the file is
- * a special file, such as a directory, FIFO, link, character- or
- * block-special file, then the file size field of the stat structure
- * is zeroed to make sure that no data is written out for the file.
- * If the file is a special file, then a file descriptor of 0 is
- * returned to the caller, which is handled specially. If the file
- * is a regular file, then the file is opened and a file descriptor
- * to the open file is returned to the caller.
- *
- * PARAMETERS
- *
- * char *name - pointer to the name of the file to open
- * Stat *asb - pointer to the stat block for the file to open
- *
- * RETURNS
- *
- * Returns a file descriptor, 0 if no data exists, or -1 at EOF. This
- * kludge works because standard input is in use, preventing open() from
- * returning zero.
- */
-
- #ifdef __STDC__
-
- int openin(char *name, Stat *asb)
-
- #else
-
- int openin(name, asb)
- char *name; /* name of file to open */
- Stat *asb; /* pointer to stat structure for file */
-
- #endif
- {
- int fd;
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: int openin() in fileio.c\n");
- #endif
- switch (asb->sb_mode & S_IFMT) {
- case S_IFDIR:
- #if 0 /* NIST-PCTS */
- asb->sb_nlink = 1;
- #endif /* NIST-PCTS */
- asb->sb_size = 0;
- return (0);
- #ifdef S_IFLNK
- case S_IFLNK:
- if ((asb->sb_size = readlink(name,
- asb->sb_link, sizeof(asb->sb_link) - 1)) < 0) {
- warn(name, strerror(errno)); /* Xn */
- return(0);
- }
- asb->sb_link[asb->sb_size] = '\0';
- return (0);
- #endif /* S_IFLNK */
- case S_IFREG:
- if (asb->sb_size == 0) {
- return (0);
- }
- if ((fd = open(name, O_RDONLY | O_BINARY)) < 0) {
- warn(name, strerror(errno)); /* Xn */
- }
- return (fd);
- default:
- asb->sb_size = 0;
- return (0);
- }
- }
-