xref: /csrg-svn/bin/pax/pax.c (revision 66890)
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