pax.c

Go to the documentation of this file.
00001 /*-
00002  * Copyright (c) 1992 Keith Muller.
00003  * Copyright (c) 1992, 1993
00004  *      The Regents of the University of California.  All rights reserved.
00005  *
00006  * This code is derived from software contributed to Berkeley by
00007  * Keith Muller of the University of California, San Diego.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  * 1. Redistributions of source code must retain the above copyright
00013  *    notice, this list of conditions and the following disclaimer.
00014  * 2. Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the
00016  *    documentation and/or other materials provided with the distribution.
00017  * 4. Neither the name of the University nor the names of its contributors
00018  *    may be used to endorse or promote products derived from this software
00019  *    without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  */
00033 
00034 #if 0
00035 #ifndef lint
00036 static char const copyright[] =
00037 "@(#) Copyright (c) 1992, 1993\n\
00038         The Regents of the University of California.  All rights reserved.\n";
00039 #endif /* not lint */
00040 
00041 #ifndef lint
00042 static char sccsid[] = "@(#)pax.c       8.2 (Berkeley) 4/18/94";
00043 #endif /* not lint */
00044 #endif
00045 
00046 #include <sys/types.h>
00047 #include <sys/stat.h>
00048 #include <sys/time.h>
00049 #include <sys/resource.h>
00050 #include <errno.h>
00051 #include <fcntl.h>
00052 #include <locale.h>
00053 #include <minix/paths.h>
00054 #include <signal.h>
00055 #include <stdio.h>
00056 #include <stdlib.h>
00057 #include <string.h>
00058 #include <unistd.h>
00059 #include "pax.h"
00060 #include "extern.h"
00061 static int gen_init(void);
00062 
00063 /*
00064  * PAX main routines, general globals and some simple start up routines
00065  */
00066 
00067 /*
00068  * Variables that can be accessed by any routine within pax
00069  */
00070 int     act = DEFOP;            /* read/write/append/copy */
00071 FSUB    *frmt = NULL;           /* archive format type */
00072 int     cflag;                  /* match all EXCEPT pattern/file */
00073 int     cwdfd;                  /* starting cwd */
00074 int     dflag;                  /* directory member match only  */
00075 int     iflag;                  /* interactive file/archive rename */
00076 int     kflag;                  /* do not overwrite existing files */
00077 int     lflag;                  /* use hard links when possible */
00078 int     nflag;                  /* select first archive member match */
00079 int     tflag;                  /* restore access time after read */
00080 int     uflag;                  /* ignore older modification time files */
00081 int     vflag;                  /* produce verbose output */
00082 int     Dflag;                  /* same as uflag except inode change time */
00083 int     Hflag;                  /* follow command line symlinks (write only) */
00084 int     Lflag;                  /* follow symlinks when writing */
00085 int     Xflag;                  /* archive files with same device id only */
00086 int     Yflag;                  /* same as Dflg except after name mode */
00087 int     Zflag;                  /* same as uflg except after name mode */
00088 int     vfpart;                 /* is partial verbose output in progress */
00089 int     patime = 1;             /* preserve file access time */
00090 int     pmtime = 1;             /* preserve file modification times */
00091 int     nodirs;                 /* do not create directories as needed */
00092 int     pmode;                  /* preserve file mode bits */
00093 int     pids;                   /* preserve file uid/gid */
00094 int     rmleadslash = 0;        /* remove leading '/' from pathnames */
00095 int     exit_val;               /* exit value */
00096 int     docrc;                  /* check/create file crc */
00097 char    *dirptr;                /* destination dir in a copy */
00098 const   char *argv0;            /* root of argv[0] */
00099 sigset_t s_mask;                /* signal mask for cleanup critical sect */
00100 FILE    *listf;                 /* file pointer to print file list to */
00101 char    *tempfile;              /* tempfile to use for mkstemp(3) */
00102 char    *tempbase;              /* basename of tempfile to use for mkstemp(3) */
00103 
00104 /*
00105  *      PAX - Portable Archive Interchange
00106  *
00107  *      A utility to read, write, and write lists of the members of archive
00108  *      files and copy directory hierarchies. A variety of archive formats
00109  *      are supported (some are described in POSIX 1003.1 10.1):
00110  *
00111  *              ustar - 10.1.1 extended tar interchange format
00112  *              cpio  - 10.1.2 extended cpio interchange format
00113  *              tar - old BSD 4.3 tar format
00114  *              binary cpio - old cpio with binary header format
00115  *              sysVR4 cpio -  with and without CRC
00116  *
00117  * This version is a superset of IEEE Std 1003.2b-d3
00118  *
00119  * Summary of Extensions to the IEEE Standard:
00120  *
00121  * 1    READ ENHANCEMENTS
00122  * 1.1  Operations which read archives will continue to operate even when
00123  *      processing archives which may be damaged, truncated, or fail to meet
00124  *      format specs in several different ways. Damaged sections of archives
00125  *      are detected and avoided if possible. Attempts will be made to resync
00126  *      archive read operations even with badly damaged media.
00127  * 1.2  Blocksize requirements are not strictly enforced on archive read.
00128  *      Tapes which have variable sized records can be read without errors.
00129  * 1.3  The user can specify via the non-standard option flag -E if error
00130  *      resync operation should stop on a media error, try a specified number
00131  *      of times to correct, or try to correct forever.
00132  * 1.4  Sparse files (lseek holes) stored on the archive (but stored with blocks
00133  *      of all zeros will be restored with holes appropriate for the target
00134  *      file system
00135  * 1.5  The user is notified whenever something is found during archive
00136  *      read operations which violates spec (but the read will continue).
00137  * 1.6  Multiple archive volumes can be read and may span over different
00138  *      archive devices
00139  * 1.7  Rigidly restores all file attributes exactly as they are stored on the
00140  *      archive.
00141  * 1.8  Modification change time ranges can be specified via multiple -T
00142  *      options. These allow a user to select files whose modification time
00143  *      lies within a specific time range.
00144  * 1.9  Files can be selected based on owner (user name or uid) via one or more
00145  *      -U options.
00146  * 1.10 Files can be selected based on group (group name or gid) via one o
00147  *      more -G options.
00148  * 1.11 File modification time can be checked against existing file after
00149  *      name modification (-Z)
00150  *
00151  * 2    WRITE ENHANCEMENTS
00152  * 2.1  Write operation will stop instead of allowing a user to create a flawed
00153  *      flawed archive (due to any problem).
00154  * 2.2  Archives written by pax are forced to strictly conform to both the
00155  *      archive and pax the specific format specifications.
00156  * 2.3  Blocking size and format is rigidly enforced on writes.
00157  * 2.4  Formats which may exhibit header overflow problems (they have fields
00158  *      too small for large file systems, such as inode number storage), use
00159  *      routines designed to repair this problem. These techniques still
00160  *      conform to both pax and format specifications, but no longer truncate
00161  *      these fields. This removes any restrictions on using these archive
00162  *      formats on large file systems.
00163  * 2.5  Multiple archive volumes can be written and may span over different
00164  *      archive devices
00165  * 2.6  A archive volume record limit allows the user to specify the number
00166  *      of bytes stored on an archive volume. When reached the user is
00167  *      prompted for the next archive volume. This is specified with the
00168  *      non-standard -B flag. The limit is rounded up to the next blocksize.
00169  * 2.7  All archive padding during write use zero filled sections. This makes
00170  *      it much easier to pull data out of flawed archive during read
00171  *      operations.
00172  * 2.8  Access time reset with the -t applies to all file nodes (including
00173  *      directories).
00174  * 2.9  Symbolic links can be followed with -L (optional in the spec).
00175  * 2.10 Modification or inode change time ranges can be specified via
00176  *      multiple -T options. These allow a user to select files whose
00177  *      modification or inode change time lies within a specific time range.
00178  * 2.11 Files can be selected based on owner (user name or uid) via one or more
00179  *      -U options.
00180  * 2.12 Files can be selected based on group (group name or gid) via one o
00181  *      more -G options.
00182  * 2.13 Symlinks which appear on the command line can be followed (without
00183  *      following other symlinks; -H flag)
00184  *
00185  * 3    COPY ENHANCEMENTS
00186  * 3.1  Sparse files (lseek holes) can be copied without expanding the holes
00187  *      into zero filled blocks. The file copy is created with holes which are
00188  *      appropriate for the target file system
00189  * 3.2  Access time as well as modification time on copied file trees can be
00190  *      preserved with the appropriate -p options.
00191  * 3.3  Access time reset with the -t applies to all file nodes (including
00192  *      directories).
00193  * 3.4  Symbolic links can be followed with -L (optional in the spec).
00194  * 3.5  Modification or inode change time ranges can be specified via
00195  *      multiple -T options. These allow a user to select files whose
00196  *      modification or inode change time lies within a specific time range.
00197  * 3.6  Files can be selected based on owner (user name or uid) via one or more
00198  *      -U options.
00199  * 3.7  Files can be selected based on group (group name or gid) via one o
00200  *      more -G options.
00201  * 3.8  Symlinks which appear on the command line can be followed (without
00202  *      following other symlinks; -H flag)
00203  * 3.9  File inode change time can be checked against existing file before
00204  *      name modification (-D)
00205  * 3.10 File inode change time can be checked against existing file after
00206  *      name modification (-Y)
00207  * 3.11 File modification time can be checked against existing file after
00208  *      name modification (-Z)
00209  *
00210  * 4    GENERAL ENHANCEMENTS
00211  * 4.1  Internal structure is designed to isolate format dependent and
00212  *      independent functions. Formats are selected via a format driver table.
00213  *      This encourages the addition of new archive formats by only having to
00214  *      write those routines which id, read and write the archive header.
00215  */
00216 
00217 /*
00218  * main()
00219  *      parse options, set up and operate as specified by the user.
00220  *      any operational flaw will set exit_val to non-zero
00221  * Return: 0 if ok, 1 otherwise
00222  */
00223 
00224 int
00225 main(int argc, char *argv[])
00226 {
00227         const char *tmpdir;
00228         size_t tdlen;
00229 
00230         (void) setlocale(LC_ALL, "");
00231         listf = stderr;
00232         /*
00233          * Keep a reference to cwd, so we can always come back home.
00234          */
00235         cwdfd = open(".", O_RDONLY);
00236         if (cwdfd < 0) {
00237                 syswarn(0, errno, "Can't open current working directory.");
00238                 return(exit_val);
00239         }
00240 
00241         /*
00242          * Where should we put temporary files?
00243          */
00244         if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
00245                 tmpdir = _PATH_TMP;
00246         tdlen = strlen(tmpdir);
00247         while(tdlen > 0 && tmpdir[tdlen - 1] == '/')
00248                 tdlen--;
00249         tempfile = malloc(tdlen + 1 + sizeof(_TFILE_BASE));
00250         if (tempfile == NULL) {
00251                 paxwarn(1, "Cannot allocate memory for temp file name.");
00252                 return(exit_val);
00253         }
00254         if (tdlen)
00255                 memcpy(tempfile, tmpdir, tdlen);
00256         tempbase = tempfile + tdlen;
00257         *tempbase++ = '/';
00258 
00259         /*
00260          * parse options, determine operational mode, general init
00261          */
00262         options(argc, argv);
00263         if ((gen_init() < 0) || (tty_init() < 0))
00264                 return(exit_val);
00265 
00266         /*
00267          * select a primary operation mode
00268          */
00269         switch(act) {
00270         case EXTRACT:
00271                 extract();
00272                 break;
00273         case ARCHIVE:
00274                 archive();
00275                 break;
00276         case APPND:
00277                 if (gzip_program != NULL)
00278                         err(1, "can not gzip while appending");
00279                 append();
00280                 break;
00281         case COPY:
00282                 copy();
00283                 break;
00284         default:
00285         case LIST:
00286                 list();
00287                 break;
00288         }
00289         return(exit_val);
00290 }
00291 
00292 /*
00293  * sig_cleanup()
00294  *      when interrupted we try to do whatever delayed processing we can.
00295  *      This is not critical, but we really ought to limit our damage when we
00296  *      are aborted by the user.
00297  * Return:
00298  *      never....
00299  */
00300 
00301 void
00302 sig_cleanup(int which_sig)
00303 {
00304         /*
00305          * restore modes and times for any dirs we may have created
00306          * or any dirs we may have read. Set vflag and vfpart so the user
00307          * will clearly see the message on a line by itself.
00308          */
00309         vflag = vfpart = 1;
00310 #if 0
00311         /* ignore this under minix */
00312         if (which_sig == SIGXCPU)
00313                 paxwarn(0, "Cpu time limit reached, cleaning up.");
00314         else
00315 #endif
00316                 paxwarn(0, "Signal caught, cleaning up.");
00317 
00318         ar_close();
00319         proc_dir();
00320         if (tflag)
00321                 atdir_end();
00322         exit(1);
00323 }
00324 
00325 /*
00326  * gen_init()
00327  *      general setup routines. Not all are required, but they really help
00328  *      when dealing with a medium to large sized archives.
00329  */
00330 
00331 static int
00332 gen_init(void)
00333 {
00334 #if 0
00335         struct rlimit reslimit;
00336 #endif
00337         struct sigaction n_hand;
00338         struct sigaction o_hand;
00339 
00340 #if 0
00341         /*
00342          * Really needed to handle large archives. We can run out of memory for
00343          * internal tables really fast when we have a whole lot of files...
00344          */
00345         if (getrlimit(RLIMIT_DATA , &reslimit) == 0){
00346                 reslimit.rlim_cur = reslimit.rlim_max;
00347                 (void)setrlimit(RLIMIT_DATA , &reslimit);
00348         }
00349 
00350         /*
00351          * should file size limits be waived? if the os limits us, this is
00352          * needed if we want to write a large archive
00353          */
00354         if (getrlimit(RLIMIT_FSIZE , &reslimit) == 0){
00355                 reslimit.rlim_cur = reslimit.rlim_max;
00356                 (void)setrlimit(RLIMIT_FSIZE , &reslimit);
00357         }
00358 
00359         /*
00360          * increase the size the stack can grow to
00361          */
00362         if (getrlimit(RLIMIT_STACK , &reslimit) == 0){
00363                 reslimit.rlim_cur = reslimit.rlim_max;
00364                 (void)setrlimit(RLIMIT_STACK , &reslimit);
00365         }
00366 
00367         /*
00368          * not really needed, but doesn't hurt
00369          */
00370         if (getrlimit(RLIMIT_RSS , &reslimit) == 0){
00371                 reslimit.rlim_cur = reslimit.rlim_max;
00372                 (void)setrlimit(RLIMIT_RSS , &reslimit);
00373         }
00374 #endif
00375 
00376         /*
00377          * signal handling to reset stored directory times and modes. Since
00378          * we deal with broken pipes via failed writes we ignore it. We also
00379          * deal with any file size limit thorugh failed writes. Cpu time
00380          * limits are caught and a cleanup is forced.
00381          */
00382 
00383         if ((sigemptyset(&s_mask) < 0) || (sigaddset(&s_mask, SIGTERM) < 0) ||
00384             (sigaddset(&s_mask,SIGINT) < 0)||(sigaddset(&s_mask,SIGHUP) < 0) ||
00385             (sigaddset(&s_mask,SIGPIPE) < 0)||(sigaddset(&s_mask,SIGQUIT)<0) 
00386 #if 0
00387             || (sigaddset(&s_mask,SIGXCPU) < 0)||(sigaddset(&s_mask,SIGXFSZ)<0)
00388 #endif
00389             ) {
00390                 paxwarn(1, "Unable to set up signal mask");
00391                 return(-1);
00392         }
00393         memset(&n_hand, 0, sizeof n_hand);
00394         n_hand.sa_mask = s_mask;
00395         n_hand.sa_flags = 0;
00396         n_hand.sa_handler = sig_cleanup;
00397 
00398         if ((sigaction(SIGHUP, &n_hand, &o_hand) < 0) &&
00399             (o_hand.sa_handler == SIG_IGN) &&
00400             (sigaction(SIGHUP, &o_hand, &o_hand) < 0))
00401                 goto out;
00402 
00403         if ((sigaction(SIGTERM, &n_hand, &o_hand) < 0) &&
00404             (o_hand.sa_handler == SIG_IGN) &&
00405             (sigaction(SIGTERM, &o_hand, &o_hand) < 0))
00406                 goto out;
00407 
00408         if ((sigaction(SIGINT, &n_hand, &o_hand) < 0) &&
00409             (o_hand.sa_handler == SIG_IGN) &&
00410             (sigaction(SIGINT, &o_hand, &o_hand) < 0))
00411                 goto out;
00412 
00413         if ((sigaction(SIGQUIT, &n_hand, &o_hand) < 0) &&
00414             (o_hand.sa_handler == SIG_IGN) &&
00415             (sigaction(SIGQUIT, &o_hand, &o_hand) < 0))
00416                 goto out;
00417 
00418 #if 0
00419         if ((sigaction(SIGXCPU, &n_hand, &o_hand) < 0) &&
00420             (o_hand.sa_handler == SIG_IGN) &&
00421             (sigaction(SIGXCPU, &o_hand, &o_hand) < 0))
00422                 goto out;
00423 #endif
00424 
00425         n_hand.sa_handler = SIG_IGN;
00426         if ((sigaction(SIGPIPE, &n_hand, &o_hand) < 0)
00427 #if 0
00428          || (sigaction(SIGXFSZ, &n_hand, &o_hand) < 0)
00429 #endif
00430             )
00431 
00432 
00433                 goto out;
00434         return(0);
00435 
00436     out:
00437         syswarn(1, errno, "Unable to set up signal handler");
00438         return(-1);
00439 }

Generated on Fri Apr 14 22:57:01 2006 for minix by  doxygen 1.4.6