1aaecdfd9Smuller /*-
2aaecdfd9Smuller * Copyright (c) 1992 Keith Muller.
33631e65bSbostic * Copyright (c) 1992, 1993
43631e65bSbostic * The Regents of the University of California. All rights reserved.
5aaecdfd9Smuller *
6aaecdfd9Smuller * This code is derived from software contributed to Berkeley by
7aaecdfd9Smuller * Keith Muller of the University of California, San Diego.
8aaecdfd9Smuller *
9aaecdfd9Smuller * %sccs.include.redist.c%
10aaecdfd9Smuller */
11aaecdfd9Smuller
12aaecdfd9Smuller #ifndef lint
13e2d715fdSmuller static char copyright[] =
143631e65bSbostic "@(#) Copyright (c) 1992, 1993\n\
153631e65bSbostic The Regents of the University of California. All rights reserved.\n";
16aaecdfd9Smuller #endif /* not lint */
17aaecdfd9Smuller
18aaecdfd9Smuller #ifndef lint
19*95bb8cdaSbostic static char sccsid[] = "@(#)pax.c 8.2 (Berkeley) 04/18/94";
20aaecdfd9Smuller #endif /* not lint */
21aaecdfd9Smuller
22aaecdfd9Smuller #include <stdio.h>
23aaecdfd9Smuller #include <sys/types.h>
24aaecdfd9Smuller #include <sys/param.h>
25aaecdfd9Smuller #include <sys/stat.h>
26aaecdfd9Smuller #include <sys/time.h>
27aaecdfd9Smuller #include <sys/resource.h>
28aaecdfd9Smuller #include <signal.h>
29aaecdfd9Smuller #include <unistd.h>
30aaecdfd9Smuller #include <stdlib.h>
31aaecdfd9Smuller #include <errno.h>
32aaecdfd9Smuller #include "pax.h"
33aaecdfd9Smuller #include "extern.h"
34aaecdfd9Smuller static int gen_init __P((void));
35aaecdfd9Smuller
36aaecdfd9Smuller /*
37700ad227Smuller * PAX main routines, general globals and some simple start up routines
38aaecdfd9Smuller */
39aaecdfd9Smuller
40aaecdfd9Smuller /*
41aaecdfd9Smuller * Variables that can be accessed by any routine within pax
42aaecdfd9Smuller */
43aaecdfd9Smuller int act = DEFOP; /* read/write/append/copy */
44aaecdfd9Smuller FSUB *frmt = NULL; /* archive format type */
45aaecdfd9Smuller int cflag; /* match all EXCEPT pattern/file */
46aaecdfd9Smuller int dflag; /* directory member match only */
47aaecdfd9Smuller int iflag; /* interactive file/archive rename */
48aaecdfd9Smuller int kflag; /* do not overwrite existing files */
49aaecdfd9Smuller int lflag; /* use hard links when possible */
50aaecdfd9Smuller int nflag; /* select first archive member match */
51aaecdfd9Smuller int tflag; /* restore access time after read */
52aaecdfd9Smuller int uflag; /* ignore older modification time files */
53aaecdfd9Smuller int vflag; /* produce verbose output */
54700ad227Smuller int Dflag; /* same as uflag except inode change time */
55aaecdfd9Smuller int Hflag; /* follow command line symlinks (write only) */
56*95bb8cdaSbostic int Lflag; /* follow symlinks when writing */
57aaecdfd9Smuller int Xflag; /* archive files with same device id only */
58700ad227Smuller int Yflag; /* same as Dflg except after name mode */
59700ad227Smuller int Zflag; /* same as uflg except after name mode */
60aaecdfd9Smuller int vfpart; /* is partial verbose output in progress */
61aaecdfd9Smuller int patime = 1; /* preserve file access time */
62aaecdfd9Smuller int pmtime = 1; /* preserve file modification times */
63aaecdfd9Smuller int pmode; /* preserve file mode bits */
64aaecdfd9Smuller int pids; /* preserve file uid/gid */
65aaecdfd9Smuller int exit_val; /* exit value */
66aaecdfd9Smuller int docrc; /* check/create file crc */
67aaecdfd9Smuller char *dirptr; /* destination dir in a copy */
68aaecdfd9Smuller char *ltmfrmt; /* -v locale time format (if any) */
69*95bb8cdaSbostic char *argv0; /* root of argv[0] */
70aaecdfd9Smuller sigset_t s_mask; /* signal mask for cleanup critical sect */
71aaecdfd9Smuller
72aaecdfd9Smuller /*
73aaecdfd9Smuller * PAX - Portable Archive Interchange
74aaecdfd9Smuller *
75aaecdfd9Smuller * A utility to read, write, and write lists of the members of archive
76aaecdfd9Smuller * files and copy directory hierarchies. A variety of archive formats
77aaecdfd9Smuller * are supported (some are described in POSIX 1003.1 10.1):
78aaecdfd9Smuller *
79aaecdfd9Smuller * ustar - 10.1.1 extended tar interchange format
80aaecdfd9Smuller * cpio - 10.1.2 extended cpio interchange format
81aaecdfd9Smuller * tar - old BSD 4.3 tar format
82aaecdfd9Smuller * binary cpio - old cpio with binary header format
83aaecdfd9Smuller * sysVR4 cpio - with and without CRC
84aaecdfd9Smuller *
85aaecdfd9Smuller * This version is a superset of IEEE Std 1003.2b-d3
86aaecdfd9Smuller *
87aaecdfd9Smuller * Summary of Extensions to the IEEE Standard:
88aaecdfd9Smuller *
89700ad227Smuller * 1 READ ENHANCEMENTS
90aaecdfd9Smuller * 1.1 Operations which read archives will continue to operate even when
91aaecdfd9Smuller * processing archives which may be damaged, truncated, or fail to meet
92aaecdfd9Smuller * format specs in several different ways. Damaged sections of archives
93aaecdfd9Smuller * are detected and avoided if possible. Attempts will be made to resync
94aaecdfd9Smuller * archive read operations even with badly damaged media.
95aaecdfd9Smuller * 1.2 Blocksize requirements are not strictly enforced on archive read.
96aaecdfd9Smuller * Tapes which have variable sized records can be read without errors.
97aaecdfd9Smuller * 1.3 The user can specify via the non-standard option flag -E if error
98aaecdfd9Smuller * resync operation should stop on a media error, try a specified number
99aaecdfd9Smuller * of times to correct, or try to correct forever.
100aaecdfd9Smuller * 1.4 Sparse files (lseek holes) stored on the archive (but stored with blocks
101aaecdfd9Smuller * of all zeros will be restored with holes appropriate for the target
102aaecdfd9Smuller * filesystem
103aaecdfd9Smuller * 1.5 The user is notified whenever something is found during archive
104aaecdfd9Smuller * read operations which violates spec (but the read will continue).
105aaecdfd9Smuller * 1.6 Multiple archive volumes can be read and may span over different
106aaecdfd9Smuller * archive devices
107aaecdfd9Smuller * 1.7 Rigidly restores all file attributes exactly as they are stored on the
108aaecdfd9Smuller * archive.
109700ad227Smuller * 1.8 Modification change time ranges can be specified via multiple -T
110700ad227Smuller * options. These allow a user to select files whose modification time
111700ad227Smuller * lies within a specific time range.
112aaecdfd9Smuller * 1.9 Files can be selected based on owner (user name or uid) via one or more
113aaecdfd9Smuller * -U options.
114aaecdfd9Smuller * 1.10 Files can be selected based on group (group name or gid) via one o
115aaecdfd9Smuller * more -G options.
116aaecdfd9Smuller * 1.11 File modification time can be checked against exisiting file after
117aaecdfd9Smuller * name modification (-Z)
118aaecdfd9Smuller *
119700ad227Smuller * 2 WRITE ENHANCEMENTS
120aaecdfd9Smuller * 2.1 Write operation will stop instead of allowing a user to create a flawed
121aaecdfd9Smuller * flawed archive (due to any problem).
122aaecdfd9Smuller * 2.2 Archives writtens by pax are forced to strictly conform to both the
123aaecdfd9Smuller * archive and pax the spceific format specifications.
124aaecdfd9Smuller * 2.3 Blocking size and format is rigidly enforced on writes.
125aaecdfd9Smuller * 2.4 Formats which may exhibit header overflow problems (they have fields
126aaecdfd9Smuller * too small for large file systems, such as inode number storage), use
127aaecdfd9Smuller * routines designed to repair this problem. These techniques still
128aaecdfd9Smuller * conform to both pax and format specifications, but no longer truncate
129aaecdfd9Smuller * these fields. This removes any restrictions on using these archive
130aaecdfd9Smuller * formats on large file systems.
131aaecdfd9Smuller * 2.5 Multiple archive volumes can be written and may span over different
132aaecdfd9Smuller * archive devices
133aaecdfd9Smuller * 2.6 A archive volume record limit allows the user to specify the number
134aaecdfd9Smuller * of bytes stored on an archive volume. When reached the user is
135aaecdfd9Smuller * prompted for the next archive volume. This is specified with the
136aaecdfd9Smuller * non-standard -B flag. THe limit is rounded up to the next blocksize.
137aaecdfd9Smuller * 2.7 All archive padding during write use zero filled sections. This makes
138aaecdfd9Smuller * it much easier to pull data out of flawed archive during read
139aaecdfd9Smuller * operations.
140aaecdfd9Smuller * 2.8 Access time reset with the -t applies to all file nodes (including
141aaecdfd9Smuller * directories).
142aaecdfd9Smuller * 2.9 Symbolic links can be followed with -L (optional in the spec).
143700ad227Smuller * 2.10 Modification or inode change time ranges can be specified via
144700ad227Smuller * multiple -T options. These allow a user to select files whose
145700ad227Smuller * modification or inode change time lies within a specific time range.
146aaecdfd9Smuller * 2.11 Files can be selected based on owner (user name or uid) via one or more
147aaecdfd9Smuller * -U options.
148aaecdfd9Smuller * 2.12 Files can be selected based on group (group name or gid) via one o
149aaecdfd9Smuller * more -G options.
150aaecdfd9Smuller * 2.13 Symlinks which appear on the command line can be followed (without
151aaecdfd9Smuller * following other symlinks; -H flag)
152aaecdfd9Smuller *
153700ad227Smuller * 3 COPY ENHANCEMENTS
154aaecdfd9Smuller * 3.1 Sparse files (lseek holes) can be copied without expanding the holes
155aaecdfd9Smuller * into zero filled blocks. The file copy is created with holes which are
156aaecdfd9Smuller * appropriate for the target filesystem
157aaecdfd9Smuller * 3.2 Access time as well as modification time on copied file trees can be
158aaecdfd9Smuller * preserved with the appropriate -p options.
159aaecdfd9Smuller * 3.3 Access time reset with the -t applies to all file nodes (including
160aaecdfd9Smuller * directories).
161aaecdfd9Smuller * 3.4 Symbolic links can be followed with -L (optional in the spec).
162700ad227Smuller * 3.5 Modification or inode change time ranges can be specified via
163700ad227Smuller * multiple -T options. These allow a user to select files whose
164700ad227Smuller * modification or inode change time lies within a specific time range.
165aaecdfd9Smuller * 3.6 Files can be selected based on owner (user name or uid) via one or more
166aaecdfd9Smuller * -U options.
167aaecdfd9Smuller * 3.7 Files can be selected based on group (group name or gid) via one o
168aaecdfd9Smuller * more -G options.
169aaecdfd9Smuller * 3.8 Symlinks which appear on the command line can be followed (without
170aaecdfd9Smuller * following other symlinks; -H flag)
171700ad227Smuller * 3.9 File inode change time can be checked against exisiting file before
172700ad227Smuller * name modification (-D)
173700ad227Smuller * 3.10 File inode change time can be checked against exisiting file after
174700ad227Smuller * name modification (-Y)
175700ad227Smuller * 3.11 File modification time can be checked against exisiting file after
176aaecdfd9Smuller * name modification (-Z)
177aaecdfd9Smuller *
178700ad227Smuller * 4 GENERAL ENHANCEMENTS
179aaecdfd9Smuller * 4.1 Internal structure is designed to isolate format dependent and
180aaecdfd9Smuller * independent functions. Formats are selected via a format driver table.
181aaecdfd9Smuller * This encourages the addition of new archive formats by only having to
182aaecdfd9Smuller * write those routines which id, read and write the archive header.
183aaecdfd9Smuller */
184aaecdfd9Smuller
185700ad227Smuller /*
186700ad227Smuller * main()
187700ad227Smuller * parse options, set up and operate as specified by the user.
188700ad227Smuller * any operational flaw will set exit_val to non-zero
189700ad227Smuller * Return: 0 if ok, 1 otherwise
190700ad227Smuller */
191700ad227Smuller
192aaecdfd9Smuller #if __STDC__
193aaecdfd9Smuller int
main(int argc,char ** argv)194aaecdfd9Smuller main(int argc, char **argv)
195aaecdfd9Smuller #else
196aaecdfd9Smuller int
197aaecdfd9Smuller main(argc, argv)
198aaecdfd9Smuller int argc;
199aaecdfd9Smuller char **argv;
200aaecdfd9Smuller #endif
201aaecdfd9Smuller {
202aaecdfd9Smuller /*
203700ad227Smuller * parse options, determine operational mode, general init
204aaecdfd9Smuller */
205aaecdfd9Smuller options(argc, argv);
206aaecdfd9Smuller if ((gen_init() < 0) || (tty_init() < 0))
207aaecdfd9Smuller return(exit_val);
208aaecdfd9Smuller
209aaecdfd9Smuller /*
210aaecdfd9Smuller * select a primary operation mode
211aaecdfd9Smuller */
212aaecdfd9Smuller switch(act) {
213aaecdfd9Smuller case EXTRACT:
214aaecdfd9Smuller extract();
215aaecdfd9Smuller break;
216aaecdfd9Smuller case ARCHIVE:
217aaecdfd9Smuller archive();
218aaecdfd9Smuller break;
219aaecdfd9Smuller case APPND:
220aaecdfd9Smuller append();
221aaecdfd9Smuller break;
222aaecdfd9Smuller case COPY:
223aaecdfd9Smuller copy();
224aaecdfd9Smuller break;
225aaecdfd9Smuller default:
226aaecdfd9Smuller case LIST:
227aaecdfd9Smuller list();
228aaecdfd9Smuller break;
229aaecdfd9Smuller }
230aaecdfd9Smuller return(exit_val);
231aaecdfd9Smuller }
232aaecdfd9Smuller
233aaecdfd9Smuller /*
234aaecdfd9Smuller * sig_cleanup()
235aaecdfd9Smuller * when interrupted we try to do whatever delayed processing we can.
236aaecdfd9Smuller * This is not critical, but we really ought to limit our damage when we
237aaecdfd9Smuller * are aborted by the user.
238aaecdfd9Smuller * Return:
239aaecdfd9Smuller * never....
240aaecdfd9Smuller */
241aaecdfd9Smuller
242aaecdfd9Smuller #if __STDC__
243aaecdfd9Smuller void
sig_cleanup(int which_sig)244aaecdfd9Smuller sig_cleanup(int which_sig)
245aaecdfd9Smuller #else
246aaecdfd9Smuller void
247aaecdfd9Smuller sig_cleanup(which_sig)
248aaecdfd9Smuller int which_sig;
249aaecdfd9Smuller #endif
250aaecdfd9Smuller {
251aaecdfd9Smuller /*
252aaecdfd9Smuller * restore modes and times for any dirs we may have created
253700ad227Smuller * or any dirs we may have read. Set vflag and vfpart so the user
254700ad227Smuller * will clearly see the message on a line by itself.
255aaecdfd9Smuller */
256700ad227Smuller vflag = vfpart = 1;
257aaecdfd9Smuller if (which_sig == SIGXCPU)
258aaecdfd9Smuller warn(0, "Cpu time limit reached, cleaning up.");
259aaecdfd9Smuller else
260aaecdfd9Smuller warn(0, "Signal caught, cleaning up.");
261700ad227Smuller
262aaecdfd9Smuller ar_close();
263aaecdfd9Smuller proc_dir();
264aaecdfd9Smuller if (tflag)
265aaecdfd9Smuller atdir_end();
266aaecdfd9Smuller exit(1);
267aaecdfd9Smuller }
268aaecdfd9Smuller
269aaecdfd9Smuller /*
270aaecdfd9Smuller * gen_init()
271aaecdfd9Smuller * general setup routines. Not all are required, but they really help
272aaecdfd9Smuller * when dealing with a medium to large sized archives.
273aaecdfd9Smuller */
274aaecdfd9Smuller
275aaecdfd9Smuller #if __STDC__
276aaecdfd9Smuller static int
gen_init(void)277aaecdfd9Smuller gen_init(void)
278aaecdfd9Smuller #else
279aaecdfd9Smuller static int
280aaecdfd9Smuller gen_init()
281aaecdfd9Smuller #endif
282aaecdfd9Smuller {
283aaecdfd9Smuller struct rlimit reslimit;
284aaecdfd9Smuller struct sigaction n_hand;
285aaecdfd9Smuller struct sigaction o_hand;
286aaecdfd9Smuller
287aaecdfd9Smuller /*
288aaecdfd9Smuller * Really needed to handle large archives. We can run out of memory for
289aaecdfd9Smuller * internal tables really fast when we have a whole lot of files...
290aaecdfd9Smuller */
291aaecdfd9Smuller if (getrlimit(RLIMIT_DATA , &reslimit) == 0){
292aaecdfd9Smuller reslimit.rlim_cur = reslimit.rlim_max;
293aaecdfd9Smuller (void)setrlimit(RLIMIT_DATA , &reslimit);
294aaecdfd9Smuller }
295aaecdfd9Smuller
296aaecdfd9Smuller /*
297aaecdfd9Smuller * should file size limits be waived? if the os limits us, this is
298aaecdfd9Smuller * needed if we want to write a large archive
299aaecdfd9Smuller */
300aaecdfd9Smuller if (getrlimit(RLIMIT_FSIZE , &reslimit) == 0){
301aaecdfd9Smuller reslimit.rlim_cur = reslimit.rlim_max;
302aaecdfd9Smuller (void)setrlimit(RLIMIT_FSIZE , &reslimit);
303aaecdfd9Smuller }
304aaecdfd9Smuller
305aaecdfd9Smuller /*
306aaecdfd9Smuller * increase the size the stack can grow to
307aaecdfd9Smuller */
308aaecdfd9Smuller if (getrlimit(RLIMIT_STACK , &reslimit) == 0){
309aaecdfd9Smuller reslimit.rlim_cur = reslimit.rlim_max;
310aaecdfd9Smuller (void)setrlimit(RLIMIT_STACK , &reslimit);
311aaecdfd9Smuller }
312aaecdfd9Smuller
313aaecdfd9Smuller /*
314aaecdfd9Smuller * not really needed, but doesn't hurt
315aaecdfd9Smuller */
316aaecdfd9Smuller if (getrlimit(RLIMIT_RSS , &reslimit) == 0){
317aaecdfd9Smuller reslimit.rlim_cur = reslimit.rlim_max;
318aaecdfd9Smuller (void)setrlimit(RLIMIT_RSS , &reslimit);
319aaecdfd9Smuller }
320aaecdfd9Smuller
321aaecdfd9Smuller /*
322aaecdfd9Smuller * Handle posix locale
323aaecdfd9Smuller *
324aaecdfd9Smuller * set user defines time printing format for -v option
325aaecdfd9Smuller */
326aaecdfd9Smuller ltmfrmt = getenv("LC_TIME");
327aaecdfd9Smuller
328aaecdfd9Smuller /*
329aaecdfd9Smuller * signal handling to reset stored directory times and modes. Since
330aaecdfd9Smuller * we deal with broken pipes via failed writes we ignore it. We also
331700ad227Smuller * deal with any file size limit thorugh failed writes. Cpu time
332700ad227Smuller * limits are caught and a cleanup is forced.
333aaecdfd9Smuller */
334aaecdfd9Smuller if ((sigemptyset(&s_mask) < 0) || (sigaddset(&s_mask, SIGTERM) < 0) ||
335aaecdfd9Smuller (sigaddset(&s_mask,SIGINT) < 0)||(sigaddset(&s_mask,SIGHUP) < 0) ||
336aaecdfd9Smuller (sigaddset(&s_mask,SIGPIPE) < 0)||(sigaddset(&s_mask,SIGQUIT)<0) ||
337aaecdfd9Smuller (sigaddset(&s_mask,SIGXCPU) < 0)||(sigaddset(&s_mask,SIGXFSZ)<0)) {
338aaecdfd9Smuller warn(1, "Unable to set up signal mask");
339aaecdfd9Smuller return(-1);
340aaecdfd9Smuller }
341aaecdfd9Smuller n_hand.sa_mask = s_mask;
342aaecdfd9Smuller n_hand.sa_flags = 0;
343aaecdfd9Smuller n_hand.sa_handler = sig_cleanup;
344aaecdfd9Smuller
345aaecdfd9Smuller if ((sigaction(SIGHUP, &n_hand, &o_hand) < 0) &&
346aaecdfd9Smuller (o_hand.sa_handler == SIG_IGN) &&
347aaecdfd9Smuller (sigaction(SIGHUP, &o_hand, &o_hand) < 0))
348aaecdfd9Smuller goto out;
349aaecdfd9Smuller
350aaecdfd9Smuller if ((sigaction(SIGTERM, &n_hand, &o_hand) < 0) &&
351aaecdfd9Smuller (o_hand.sa_handler == SIG_IGN) &&
352aaecdfd9Smuller (sigaction(SIGTERM, &o_hand, &o_hand) < 0))
353aaecdfd9Smuller goto out;
354aaecdfd9Smuller
355aaecdfd9Smuller if ((sigaction(SIGINT, &n_hand, &o_hand) < 0) &&
356aaecdfd9Smuller (o_hand.sa_handler == SIG_IGN) &&
357aaecdfd9Smuller (sigaction(SIGINT, &o_hand, &o_hand) < 0))
358aaecdfd9Smuller goto out;
359aaecdfd9Smuller
360aaecdfd9Smuller if ((sigaction(SIGQUIT, &n_hand, &o_hand) < 0) &&
361aaecdfd9Smuller (o_hand.sa_handler == SIG_IGN) &&
362aaecdfd9Smuller (sigaction(SIGQUIT, &o_hand, &o_hand) < 0))
363aaecdfd9Smuller goto out;
364aaecdfd9Smuller
365aaecdfd9Smuller if ((sigaction(SIGXCPU, &n_hand, &o_hand) < 0) &&
366aaecdfd9Smuller (o_hand.sa_handler == SIG_IGN) &&
367aaecdfd9Smuller (sigaction(SIGXCPU, &o_hand, &o_hand) < 0))
368aaecdfd9Smuller goto out;
369aaecdfd9Smuller
370aaecdfd9Smuller n_hand.sa_handler = SIG_IGN;
371aaecdfd9Smuller if ((sigaction(SIGPIPE, &n_hand, &o_hand) < 0) ||
372aaecdfd9Smuller (sigaction(SIGXFSZ, &n_hand, &o_hand) < 0))
373aaecdfd9Smuller goto out;
374aaecdfd9Smuller return(0);
375aaecdfd9Smuller
376aaecdfd9Smuller out:
377aaecdfd9Smuller syswarn(1, errno, "Unable to set up signal handler");
378aaecdfd9Smuller return(-1);
379aaecdfd9Smuller }
380