157112Smuller /*-
257112Smuller * Copyright (c) 1992 Keith Muller.
360676Sbostic * Copyright (c) 1992, 1993
460676Sbostic * The Regents of the University of California. All rights reserved.
557112Smuller *
657112Smuller * This code is derived from software contributed to Berkeley by
757112Smuller * Keith Muller of the University of California, San Diego.
857112Smuller *
957112Smuller * %sccs.include.redist.c%
1057112Smuller */
1157112Smuller
1257112Smuller #ifndef lint
1357579Smuller static char copyright[] =
1460676Sbostic "@(#) Copyright (c) 1992, 1993\n\
1560676Sbostic The Regents of the University of California. All rights reserved.\n";
1657112Smuller #endif /* not lint */
1757112Smuller
1857112Smuller #ifndef lint
19*66890Sbostic static char sccsid[] = "@(#)pax.c 8.2 (Berkeley) 04/18/94";
2057112Smuller #endif /* not lint */
2157112Smuller
2257112Smuller #include <stdio.h>
2357112Smuller #include <sys/types.h>
2457112Smuller #include <sys/param.h>
2557112Smuller #include <sys/stat.h>
2657112Smuller #include <sys/time.h>
2757112Smuller #include <sys/resource.h>
2857112Smuller #include <signal.h>
2957112Smuller #include <unistd.h>
3057112Smuller #include <stdlib.h>
3157112Smuller #include <errno.h>
3257112Smuller #include "pax.h"
3357112Smuller #include "extern.h"
3457112Smuller static int gen_init __P((void));
3557112Smuller
3657112Smuller /*
3757543Smuller * PAX main routines, general globals and some simple start up routines
3857112Smuller */
3957112Smuller
4057112Smuller /*
4157112Smuller * Variables that can be accessed by any routine within pax
4257112Smuller */
4357112Smuller int act = DEFOP; /* read/write/append/copy */
4457112Smuller FSUB *frmt = NULL; /* archive format type */
4557112Smuller int cflag; /* match all EXCEPT pattern/file */
4657112Smuller int dflag; /* directory member match only */
4757112Smuller int iflag; /* interactive file/archive rename */
4857112Smuller int kflag; /* do not overwrite existing files */
4957112Smuller int lflag; /* use hard links when possible */
5057112Smuller int nflag; /* select first archive member match */
5157112Smuller int tflag; /* restore access time after read */
5257112Smuller int uflag; /* ignore older modification time files */
5357112Smuller int vflag; /* produce verbose output */
5457543Smuller int Dflag; /* same as uflag except inode change time */
5557112Smuller int Hflag; /* follow command line symlinks (write only) */
56*66890Sbostic int Lflag; /* follow symlinks when writing */
5757112Smuller int Xflag; /* archive files with same device id only */
5857543Smuller int Yflag; /* same as Dflg except after name mode */
5957543Smuller int Zflag; /* same as uflg except after name mode */
6057112Smuller int vfpart; /* is partial verbose output in progress */
6157112Smuller int patime = 1; /* preserve file access time */
6257112Smuller int pmtime = 1; /* preserve file modification times */
6357112Smuller int pmode; /* preserve file mode bits */
6457112Smuller int pids; /* preserve file uid/gid */
6557112Smuller int exit_val; /* exit value */
6657112Smuller int docrc; /* check/create file crc */
6757112Smuller char *dirptr; /* destination dir in a copy */
6857112Smuller char *ltmfrmt; /* -v locale time format (if any) */
69*66890Sbostic char *argv0; /* root of argv[0] */
7057112Smuller sigset_t s_mask; /* signal mask for cleanup critical sect */
7157112Smuller
7257112Smuller /*
7357112Smuller * PAX - Portable Archive Interchange
7457112Smuller *
7557112Smuller * A utility to read, write, and write lists of the members of archive
7657112Smuller * files and copy directory hierarchies. A variety of archive formats
7757112Smuller * are supported (some are described in POSIX 1003.1 10.1):
7857112Smuller *
7957112Smuller * ustar - 10.1.1 extended tar interchange format
8057112Smuller * cpio - 10.1.2 extended cpio interchange format
8157112Smuller * tar - old BSD 4.3 tar format
8257112Smuller * binary cpio - old cpio with binary header format
8357112Smuller * sysVR4 cpio - with and without CRC
8457112Smuller *
8557112Smuller * This version is a superset of IEEE Std 1003.2b-d3
8657112Smuller *
8757112Smuller * Summary of Extensions to the IEEE Standard:
8857112Smuller *
8957543Smuller * 1 READ ENHANCEMENTS
9057112Smuller * 1.1 Operations which read archives will continue to operate even when
9157112Smuller * processing archives which may be damaged, truncated, or fail to meet
9257112Smuller * format specs in several different ways. Damaged sections of archives
9357112Smuller * are detected and avoided if possible. Attempts will be made to resync
9457112Smuller * archive read operations even with badly damaged media.
9557112Smuller * 1.2 Blocksize requirements are not strictly enforced on archive read.
9657112Smuller * Tapes which have variable sized records can be read without errors.
9757112Smuller * 1.3 The user can specify via the non-standard option flag -E if error
9857112Smuller * resync operation should stop on a media error, try a specified number
9957112Smuller * of times to correct, or try to correct forever.
10057112Smuller * 1.4 Sparse files (lseek holes) stored on the archive (but stored with blocks
10157112Smuller * of all zeros will be restored with holes appropriate for the target
10257112Smuller * filesystem
10357112Smuller * 1.5 The user is notified whenever something is found during archive
10457112Smuller * read operations which violates spec (but the read will continue).
10557112Smuller * 1.6 Multiple archive volumes can be read and may span over different
10657112Smuller * archive devices
10757112Smuller * 1.7 Rigidly restores all file attributes exactly as they are stored on the
10857112Smuller * archive.
10957543Smuller * 1.8 Modification change time ranges can be specified via multiple -T
11057543Smuller * options. These allow a user to select files whose modification time
11157543Smuller * lies within a specific time range.
11257112Smuller * 1.9 Files can be selected based on owner (user name or uid) via one or more
11357112Smuller * -U options.
11457112Smuller * 1.10 Files can be selected based on group (group name or gid) via one o
11557112Smuller * more -G options.
11657112Smuller * 1.11 File modification time can be checked against exisiting file after
11757112Smuller * name modification (-Z)
11857112Smuller *
11957543Smuller * 2 WRITE ENHANCEMENTS
12057112Smuller * 2.1 Write operation will stop instead of allowing a user to create a flawed
12157112Smuller * flawed archive (due to any problem).
12257112Smuller * 2.2 Archives writtens by pax are forced to strictly conform to both the
12357112Smuller * archive and pax the spceific format specifications.
12457112Smuller * 2.3 Blocking size and format is rigidly enforced on writes.
12557112Smuller * 2.4 Formats which may exhibit header overflow problems (they have fields
12657112Smuller * too small for large file systems, such as inode number storage), use
12757112Smuller * routines designed to repair this problem. These techniques still
12857112Smuller * conform to both pax and format specifications, but no longer truncate
12957112Smuller * these fields. This removes any restrictions on using these archive
13057112Smuller * formats on large file systems.
13157112Smuller * 2.5 Multiple archive volumes can be written and may span over different
13257112Smuller * archive devices
13357112Smuller * 2.6 A archive volume record limit allows the user to specify the number
13457112Smuller * of bytes stored on an archive volume. When reached the user is
13557112Smuller * prompted for the next archive volume. This is specified with the
13657112Smuller * non-standard -B flag. THe limit is rounded up to the next blocksize.
13757112Smuller * 2.7 All archive padding during write use zero filled sections. This makes
13857112Smuller * it much easier to pull data out of flawed archive during read
13957112Smuller * operations.
14057112Smuller * 2.8 Access time reset with the -t applies to all file nodes (including
14157112Smuller * directories).
14257112Smuller * 2.9 Symbolic links can be followed with -L (optional in the spec).
14357543Smuller * 2.10 Modification or inode change time ranges can be specified via
14457543Smuller * multiple -T options. These allow a user to select files whose
14557543Smuller * modification or inode change time lies within a specific time range.
14657112Smuller * 2.11 Files can be selected based on owner (user name or uid) via one or more
14757112Smuller * -U options.
14857112Smuller * 2.12 Files can be selected based on group (group name or gid) via one o
14957112Smuller * more -G options.
15057112Smuller * 2.13 Symlinks which appear on the command line can be followed (without
15157112Smuller * following other symlinks; -H flag)
15257112Smuller *
15357543Smuller * 3 COPY ENHANCEMENTS
15457112Smuller * 3.1 Sparse files (lseek holes) can be copied without expanding the holes
15557112Smuller * into zero filled blocks. The file copy is created with holes which are
15657112Smuller * appropriate for the target filesystem
15757112Smuller * 3.2 Access time as well as modification time on copied file trees can be
15857112Smuller * preserved with the appropriate -p options.
15957112Smuller * 3.3 Access time reset with the -t applies to all file nodes (including
16057112Smuller * directories).
16157112Smuller * 3.4 Symbolic links can be followed with -L (optional in the spec).
16257543Smuller * 3.5 Modification or inode change time ranges can be specified via
16357543Smuller * multiple -T options. These allow a user to select files whose
16457543Smuller * modification or inode change time lies within a specific time range.
16557112Smuller * 3.6 Files can be selected based on owner (user name or uid) via one or more
16657112Smuller * -U options.
16757112Smuller * 3.7 Files can be selected based on group (group name or gid) via one o
16857112Smuller * more -G options.
16957112Smuller * 3.8 Symlinks which appear on the command line can be followed (without
17057112Smuller * following other symlinks; -H flag)
17157543Smuller * 3.9 File inode change time can be checked against exisiting file before
17257543Smuller * name modification (-D)
17357543Smuller * 3.10 File inode change time can be checked against exisiting file after
17457543Smuller * name modification (-Y)
17557543Smuller * 3.11 File modification time can be checked against exisiting file after
17657112Smuller * name modification (-Z)
17757112Smuller *
17857543Smuller * 4 GENERAL ENHANCEMENTS
17957112Smuller * 4.1 Internal structure is designed to isolate format dependent and
18057112Smuller * independent functions. Formats are selected via a format driver table.
18157112Smuller * This encourages the addition of new archive formats by only having to
18257112Smuller * write those routines which id, read and write the archive header.
18357112Smuller */
18457112Smuller
18557543Smuller /*
18657543Smuller * main()
18757543Smuller * parse options, set up and operate as specified by the user.
18857543Smuller * any operational flaw will set exit_val to non-zero
18957543Smuller * Return: 0 if ok, 1 otherwise
19057543Smuller */
19157543Smuller
19257112Smuller #if __STDC__
19357112Smuller int
main(int argc,char ** argv)19457112Smuller main(int argc, char **argv)
19557112Smuller #else
19657112Smuller int
19757112Smuller main(argc, argv)
19857112Smuller int argc;
19957112Smuller char **argv;
20057112Smuller #endif
20157112Smuller {
20257112Smuller /*
20357543Smuller * parse options, determine operational mode, general init
20457112Smuller */
20557112Smuller options(argc, argv);
20657112Smuller if ((gen_init() < 0) || (tty_init() < 0))
20757112Smuller return(exit_val);
20857112Smuller
20957112Smuller /*
21057112Smuller * select a primary operation mode
21157112Smuller */
21257112Smuller switch(act) {
21357112Smuller case EXTRACT:
21457112Smuller extract();
21557112Smuller break;
21657112Smuller case ARCHIVE:
21757112Smuller archive();
21857112Smuller break;
21957112Smuller case APPND:
22057112Smuller append();
22157112Smuller break;
22257112Smuller case COPY:
22357112Smuller copy();
22457112Smuller break;
22557112Smuller default:
22657112Smuller case LIST:
22757112Smuller list();
22857112Smuller break;
22957112Smuller }
23057112Smuller return(exit_val);
23157112Smuller }
23257112Smuller
23357112Smuller /*
23457112Smuller * sig_cleanup()
23557112Smuller * when interrupted we try to do whatever delayed processing we can.
23657112Smuller * This is not critical, but we really ought to limit our damage when we
23757112Smuller * are aborted by the user.
23857112Smuller * Return:
23957112Smuller * never....
24057112Smuller */
24157112Smuller
24257112Smuller #if __STDC__
24357112Smuller void
sig_cleanup(int which_sig)24457112Smuller sig_cleanup(int which_sig)
24557112Smuller #else
24657112Smuller void
24757112Smuller sig_cleanup(which_sig)
24857112Smuller int which_sig;
24957112Smuller #endif
25057112Smuller {
25157112Smuller /*
25257112Smuller * restore modes and times for any dirs we may have created
25357543Smuller * or any dirs we may have read. Set vflag and vfpart so the user
25457543Smuller * will clearly see the message on a line by itself.
25557112Smuller */
25657543Smuller vflag = vfpart = 1;
25757112Smuller if (which_sig == SIGXCPU)
25857112Smuller warn(0, "Cpu time limit reached, cleaning up.");
25957112Smuller else
26057112Smuller warn(0, "Signal caught, cleaning up.");
26157543Smuller
26257112Smuller ar_close();
26357112Smuller proc_dir();
26457112Smuller if (tflag)
26557112Smuller atdir_end();
26657112Smuller exit(1);
26757112Smuller }
26857112Smuller
26957112Smuller /*
27057112Smuller * gen_init()
27157112Smuller * general setup routines. Not all are required, but they really help
27257112Smuller * when dealing with a medium to large sized archives.
27357112Smuller */
27457112Smuller
27557112Smuller #if __STDC__
27657112Smuller static int
gen_init(void)27757112Smuller gen_init(void)
27857112Smuller #else
27957112Smuller static int
28057112Smuller gen_init()
28157112Smuller #endif
28257112Smuller {
28357112Smuller struct rlimit reslimit;
28457112Smuller struct sigaction n_hand;
28557112Smuller struct sigaction o_hand;
28657112Smuller
28757112Smuller /*
28857112Smuller * Really needed to handle large archives. We can run out of memory for
28957112Smuller * internal tables really fast when we have a whole lot of files...
29057112Smuller */
29157112Smuller if (getrlimit(RLIMIT_DATA , &reslimit) == 0){
29257112Smuller reslimit.rlim_cur = reslimit.rlim_max;
29357112Smuller (void)setrlimit(RLIMIT_DATA , &reslimit);
29457112Smuller }
29557112Smuller
29657112Smuller /*
29757112Smuller * should file size limits be waived? if the os limits us, this is
29857112Smuller * needed if we want to write a large archive
29957112Smuller */
30057112Smuller if (getrlimit(RLIMIT_FSIZE , &reslimit) == 0){
30157112Smuller reslimit.rlim_cur = reslimit.rlim_max;
30257112Smuller (void)setrlimit(RLIMIT_FSIZE , &reslimit);
30357112Smuller }
30457112Smuller
30557112Smuller /*
30657112Smuller * increase the size the stack can grow to
30757112Smuller */
30857112Smuller if (getrlimit(RLIMIT_STACK , &reslimit) == 0){
30957112Smuller reslimit.rlim_cur = reslimit.rlim_max;
31057112Smuller (void)setrlimit(RLIMIT_STACK , &reslimit);
31157112Smuller }
31257112Smuller
31357112Smuller /*
31457112Smuller * not really needed, but doesn't hurt
31557112Smuller */
31657112Smuller if (getrlimit(RLIMIT_RSS , &reslimit) == 0){
31757112Smuller reslimit.rlim_cur = reslimit.rlim_max;
31857112Smuller (void)setrlimit(RLIMIT_RSS , &reslimit);
31957112Smuller }
32057112Smuller
32157112Smuller /*
32257112Smuller * Handle posix locale
32357112Smuller *
32457112Smuller * set user defines time printing format for -v option
32557112Smuller */
32657112Smuller ltmfrmt = getenv("LC_TIME");
32757112Smuller
32857112Smuller /*
32957112Smuller * signal handling to reset stored directory times and modes. Since
33057112Smuller * we deal with broken pipes via failed writes we ignore it. We also
33157543Smuller * deal with any file size limit thorugh failed writes. Cpu time
33257543Smuller * limits are caught and a cleanup is forced.
33357112Smuller */
33457112Smuller if ((sigemptyset(&s_mask) < 0) || (sigaddset(&s_mask, SIGTERM) < 0) ||
33557112Smuller (sigaddset(&s_mask,SIGINT) < 0)||(sigaddset(&s_mask,SIGHUP) < 0) ||
33657112Smuller (sigaddset(&s_mask,SIGPIPE) < 0)||(sigaddset(&s_mask,SIGQUIT)<0) ||
33757112Smuller (sigaddset(&s_mask,SIGXCPU) < 0)||(sigaddset(&s_mask,SIGXFSZ)<0)) {
33857112Smuller warn(1, "Unable to set up signal mask");
33957112Smuller return(-1);
34057112Smuller }
34157112Smuller n_hand.sa_mask = s_mask;
34257112Smuller n_hand.sa_flags = 0;
34357112Smuller n_hand.sa_handler = sig_cleanup;
34457112Smuller
34557112Smuller if ((sigaction(SIGHUP, &n_hand, &o_hand) < 0) &&
34657112Smuller (o_hand.sa_handler == SIG_IGN) &&
34757112Smuller (sigaction(SIGHUP, &o_hand, &o_hand) < 0))
34857112Smuller goto out;
34957112Smuller
35057112Smuller if ((sigaction(SIGTERM, &n_hand, &o_hand) < 0) &&
35157112Smuller (o_hand.sa_handler == SIG_IGN) &&
35257112Smuller (sigaction(SIGTERM, &o_hand, &o_hand) < 0))
35357112Smuller goto out;
35457112Smuller
35557112Smuller if ((sigaction(SIGINT, &n_hand, &o_hand) < 0) &&
35657112Smuller (o_hand.sa_handler == SIG_IGN) &&
35757112Smuller (sigaction(SIGINT, &o_hand, &o_hand) < 0))
35857112Smuller goto out;
35957112Smuller
36057112Smuller if ((sigaction(SIGQUIT, &n_hand, &o_hand) < 0) &&
36157112Smuller (o_hand.sa_handler == SIG_IGN) &&
36257112Smuller (sigaction(SIGQUIT, &o_hand, &o_hand) < 0))
36357112Smuller goto out;
36457112Smuller
36557112Smuller if ((sigaction(SIGXCPU, &n_hand, &o_hand) < 0) &&
36657112Smuller (o_hand.sa_handler == SIG_IGN) &&
36757112Smuller (sigaction(SIGXCPU, &o_hand, &o_hand) < 0))
36857112Smuller goto out;
36957112Smuller
37057112Smuller n_hand.sa_handler = SIG_IGN;
37157112Smuller if ((sigaction(SIGPIPE, &n_hand, &o_hand) < 0) ||
37257112Smuller (sigaction(SIGXFSZ, &n_hand, &o_hand) < 0))
37357112Smuller goto out;
37457112Smuller return(0);
37557112Smuller
37657112Smuller out:
37757112Smuller syswarn(1, errno, "Unable to set up signal handler");
37857112Smuller return(-1);
37957112Smuller }
380