157112Smuller /*- 257112Smuller * Copyright (c) 1992 Keith Muller. 3*60676Sbostic * Copyright (c) 1992, 1993 4*60676Sbostic * 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[] = 14*60676Sbostic "@(#) Copyright (c) 1992, 1993\n\ 15*60676Sbostic The Regents of the University of California. All rights reserved.\n"; 1657112Smuller #endif /* not lint */ 1757112Smuller 1857112Smuller #ifndef lint 19*60676Sbostic static char sccsid[] = "@(#)pax.c 8.1 (Berkeley) 05/31/93"; 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) */ 5657112Smuller int Lflag; /* follow symlinks when writing archive */ 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) */ 6957112Smuller sigset_t s_mask; /* signal mask for cleanup critical sect */ 7057112Smuller 7157112Smuller /* 7257112Smuller * PAX - Portable Archive Interchange 7357112Smuller * 7457112Smuller * A utility to read, write, and write lists of the members of archive 7557112Smuller * files and copy directory hierarchies. A variety of archive formats 7657112Smuller * are supported (some are described in POSIX 1003.1 10.1): 7757112Smuller * 7857112Smuller * ustar - 10.1.1 extended tar interchange format 7957112Smuller * cpio - 10.1.2 extended cpio interchange format 8057112Smuller * tar - old BSD 4.3 tar format 8157112Smuller * binary cpio - old cpio with binary header format 8257112Smuller * sysVR4 cpio - with and without CRC 8357112Smuller * 8457112Smuller * This version is a superset of IEEE Std 1003.2b-d3 8557112Smuller * 8657112Smuller * Summary of Extensions to the IEEE Standard: 8757112Smuller * 8857543Smuller * 1 READ ENHANCEMENTS 8957112Smuller * 1.1 Operations which read archives will continue to operate even when 9057112Smuller * processing archives which may be damaged, truncated, or fail to meet 9157112Smuller * format specs in several different ways. Damaged sections of archives 9257112Smuller * are detected and avoided if possible. Attempts will be made to resync 9357112Smuller * archive read operations even with badly damaged media. 9457112Smuller * 1.2 Blocksize requirements are not strictly enforced on archive read. 9557112Smuller * Tapes which have variable sized records can be read without errors. 9657112Smuller * 1.3 The user can specify via the non-standard option flag -E if error 9757112Smuller * resync operation should stop on a media error, try a specified number 9857112Smuller * of times to correct, or try to correct forever. 9957112Smuller * 1.4 Sparse files (lseek holes) stored on the archive (but stored with blocks 10057112Smuller * of all zeros will be restored with holes appropriate for the target 10157112Smuller * filesystem 10257112Smuller * 1.5 The user is notified whenever something is found during archive 10357112Smuller * read operations which violates spec (but the read will continue). 10457112Smuller * 1.6 Multiple archive volumes can be read and may span over different 10557112Smuller * archive devices 10657112Smuller * 1.7 Rigidly restores all file attributes exactly as they are stored on the 10757112Smuller * archive. 10857543Smuller * 1.8 Modification change time ranges can be specified via multiple -T 10957543Smuller * options. These allow a user to select files whose modification time 11057543Smuller * lies within a specific time range. 11157112Smuller * 1.9 Files can be selected based on owner (user name or uid) via one or more 11257112Smuller * -U options. 11357112Smuller * 1.10 Files can be selected based on group (group name or gid) via one o 11457112Smuller * more -G options. 11557112Smuller * 1.11 File modification time can be checked against exisiting file after 11657112Smuller * name modification (-Z) 11757112Smuller * 11857543Smuller * 2 WRITE ENHANCEMENTS 11957112Smuller * 2.1 Write operation will stop instead of allowing a user to create a flawed 12057112Smuller * flawed archive (due to any problem). 12157112Smuller * 2.2 Archives writtens by pax are forced to strictly conform to both the 12257112Smuller * archive and pax the spceific format specifications. 12357112Smuller * 2.3 Blocking size and format is rigidly enforced on writes. 12457112Smuller * 2.4 Formats which may exhibit header overflow problems (they have fields 12557112Smuller * too small for large file systems, such as inode number storage), use 12657112Smuller * routines designed to repair this problem. These techniques still 12757112Smuller * conform to both pax and format specifications, but no longer truncate 12857112Smuller * these fields. This removes any restrictions on using these archive 12957112Smuller * formats on large file systems. 13057112Smuller * 2.5 Multiple archive volumes can be written and may span over different 13157112Smuller * archive devices 13257112Smuller * 2.6 A archive volume record limit allows the user to specify the number 13357112Smuller * of bytes stored on an archive volume. When reached the user is 13457112Smuller * prompted for the next archive volume. This is specified with the 13557112Smuller * non-standard -B flag. THe limit is rounded up to the next blocksize. 13657112Smuller * 2.7 All archive padding during write use zero filled sections. This makes 13757112Smuller * it much easier to pull data out of flawed archive during read 13857112Smuller * operations. 13957112Smuller * 2.8 Access time reset with the -t applies to all file nodes (including 14057112Smuller * directories). 14157112Smuller * 2.9 Symbolic links can be followed with -L (optional in the spec). 14257543Smuller * 2.10 Modification or inode change time ranges can be specified via 14357543Smuller * multiple -T options. These allow a user to select files whose 14457543Smuller * modification or inode change time lies within a specific time range. 14557112Smuller * 2.11 Files can be selected based on owner (user name or uid) via one or more 14657112Smuller * -U options. 14757112Smuller * 2.12 Files can be selected based on group (group name or gid) via one o 14857112Smuller * more -G options. 14957112Smuller * 2.13 Symlinks which appear on the command line can be followed (without 15057112Smuller * following other symlinks; -H flag) 15157112Smuller * 15257543Smuller * 3 COPY ENHANCEMENTS 15357112Smuller * 3.1 Sparse files (lseek holes) can be copied without expanding the holes 15457112Smuller * into zero filled blocks. The file copy is created with holes which are 15557112Smuller * appropriate for the target filesystem 15657112Smuller * 3.2 Access time as well as modification time on copied file trees can be 15757112Smuller * preserved with the appropriate -p options. 15857112Smuller * 3.3 Access time reset with the -t applies to all file nodes (including 15957112Smuller * directories). 16057112Smuller * 3.4 Symbolic links can be followed with -L (optional in the spec). 16157543Smuller * 3.5 Modification or inode change time ranges can be specified via 16257543Smuller * multiple -T options. These allow a user to select files whose 16357543Smuller * modification or inode change time lies within a specific time range. 16457112Smuller * 3.6 Files can be selected based on owner (user name or uid) via one or more 16557112Smuller * -U options. 16657112Smuller * 3.7 Files can be selected based on group (group name or gid) via one o 16757112Smuller * more -G options. 16857112Smuller * 3.8 Symlinks which appear on the command line can be followed (without 16957112Smuller * following other symlinks; -H flag) 17057543Smuller * 3.9 File inode change time can be checked against exisiting file before 17157543Smuller * name modification (-D) 17257543Smuller * 3.10 File inode change time can be checked against exisiting file after 17357543Smuller * name modification (-Y) 17457543Smuller * 3.11 File modification time can be checked against exisiting file after 17557112Smuller * name modification (-Z) 17657112Smuller * 17757543Smuller * 4 GENERAL ENHANCEMENTS 17857112Smuller * 4.1 Internal structure is designed to isolate format dependent and 17957112Smuller * independent functions. Formats are selected via a format driver table. 18057112Smuller * This encourages the addition of new archive formats by only having to 18157112Smuller * write those routines which id, read and write the archive header. 18257112Smuller */ 18357112Smuller 18457543Smuller /* 18557543Smuller * main() 18657543Smuller * parse options, set up and operate as specified by the user. 18757543Smuller * any operational flaw will set exit_val to non-zero 18857543Smuller * Return: 0 if ok, 1 otherwise 18957543Smuller */ 19057543Smuller 19157112Smuller #if __STDC__ 19257112Smuller int 19357112Smuller main(int argc, char **argv) 19457112Smuller #else 19557112Smuller int 19657112Smuller main(argc, argv) 19757112Smuller int argc; 19857112Smuller char **argv; 19957112Smuller #endif 20057112Smuller { 20157112Smuller /* 20257543Smuller * parse options, determine operational mode, general init 20357112Smuller */ 20457112Smuller options(argc, argv); 20557112Smuller if ((gen_init() < 0) || (tty_init() < 0)) 20657112Smuller return(exit_val); 20757112Smuller 20857112Smuller /* 20957112Smuller * select a primary operation mode 21057112Smuller */ 21157112Smuller switch(act) { 21257112Smuller case EXTRACT: 21357112Smuller extract(); 21457112Smuller break; 21557112Smuller case ARCHIVE: 21657112Smuller archive(); 21757112Smuller break; 21857112Smuller case APPND: 21957112Smuller append(); 22057112Smuller break; 22157112Smuller case COPY: 22257112Smuller copy(); 22357112Smuller break; 22457112Smuller default: 22557112Smuller case LIST: 22657112Smuller list(); 22757112Smuller break; 22857112Smuller } 22957112Smuller return(exit_val); 23057112Smuller } 23157112Smuller 23257112Smuller /* 23357112Smuller * sig_cleanup() 23457112Smuller * when interrupted we try to do whatever delayed processing we can. 23557112Smuller * This is not critical, but we really ought to limit our damage when we 23657112Smuller * are aborted by the user. 23757112Smuller * Return: 23857112Smuller * never.... 23957112Smuller */ 24057112Smuller 24157112Smuller #if __STDC__ 24257112Smuller void 24357112Smuller sig_cleanup(int which_sig) 24457112Smuller #else 24557112Smuller void 24657112Smuller sig_cleanup(which_sig) 24757112Smuller int which_sig; 24857112Smuller #endif 24957112Smuller { 25057112Smuller /* 25157112Smuller * restore modes and times for any dirs we may have created 25257543Smuller * or any dirs we may have read. Set vflag and vfpart so the user 25357543Smuller * will clearly see the message on a line by itself. 25457112Smuller */ 25557543Smuller vflag = vfpart = 1; 25657112Smuller if (which_sig == SIGXCPU) 25757112Smuller warn(0, "Cpu time limit reached, cleaning up."); 25857112Smuller else 25957112Smuller warn(0, "Signal caught, cleaning up."); 26057543Smuller 26157112Smuller ar_close(); 26257112Smuller proc_dir(); 26357112Smuller if (tflag) 26457112Smuller atdir_end(); 26557112Smuller exit(1); 26657112Smuller } 26757112Smuller 26857112Smuller /* 26957112Smuller * gen_init() 27057112Smuller * general setup routines. Not all are required, but they really help 27157112Smuller * when dealing with a medium to large sized archives. 27257112Smuller */ 27357112Smuller 27457112Smuller #if __STDC__ 27557112Smuller static int 27657112Smuller gen_init(void) 27757112Smuller #else 27857112Smuller static int 27957112Smuller gen_init() 28057112Smuller #endif 28157112Smuller { 28257112Smuller struct rlimit reslimit; 28357112Smuller struct sigaction n_hand; 28457112Smuller struct sigaction o_hand; 28557112Smuller 28657112Smuller /* 28757112Smuller * Really needed to handle large archives. We can run out of memory for 28857112Smuller * internal tables really fast when we have a whole lot of files... 28957112Smuller */ 29057112Smuller if (getrlimit(RLIMIT_DATA , &reslimit) == 0){ 29157112Smuller reslimit.rlim_cur = reslimit.rlim_max; 29257112Smuller (void)setrlimit(RLIMIT_DATA , &reslimit); 29357112Smuller } 29457112Smuller 29557112Smuller /* 29657112Smuller * should file size limits be waived? if the os limits us, this is 29757112Smuller * needed if we want to write a large archive 29857112Smuller */ 29957112Smuller if (getrlimit(RLIMIT_FSIZE , &reslimit) == 0){ 30057112Smuller reslimit.rlim_cur = reslimit.rlim_max; 30157112Smuller (void)setrlimit(RLIMIT_FSIZE , &reslimit); 30257112Smuller } 30357112Smuller 30457112Smuller /* 30557112Smuller * increase the size the stack can grow to 30657112Smuller */ 30757112Smuller if (getrlimit(RLIMIT_STACK , &reslimit) == 0){ 30857112Smuller reslimit.rlim_cur = reslimit.rlim_max; 30957112Smuller (void)setrlimit(RLIMIT_STACK , &reslimit); 31057112Smuller } 31157112Smuller 31257112Smuller /* 31357112Smuller * not really needed, but doesn't hurt 31457112Smuller */ 31557112Smuller if (getrlimit(RLIMIT_RSS , &reslimit) == 0){ 31657112Smuller reslimit.rlim_cur = reslimit.rlim_max; 31757112Smuller (void)setrlimit(RLIMIT_RSS , &reslimit); 31857112Smuller } 31957112Smuller 32057112Smuller /* 32157112Smuller * Handle posix locale 32257112Smuller * 32357112Smuller * set user defines time printing format for -v option 32457112Smuller */ 32557112Smuller ltmfrmt = getenv("LC_TIME"); 32657112Smuller 32757112Smuller /* 32857112Smuller * signal handling to reset stored directory times and modes. Since 32957112Smuller * we deal with broken pipes via failed writes we ignore it. We also 33057543Smuller * deal with any file size limit thorugh failed writes. Cpu time 33157543Smuller * limits are caught and a cleanup is forced. 33257112Smuller */ 33357112Smuller if ((sigemptyset(&s_mask) < 0) || (sigaddset(&s_mask, SIGTERM) < 0) || 33457112Smuller (sigaddset(&s_mask,SIGINT) < 0)||(sigaddset(&s_mask,SIGHUP) < 0) || 33557112Smuller (sigaddset(&s_mask,SIGPIPE) < 0)||(sigaddset(&s_mask,SIGQUIT)<0) || 33657112Smuller (sigaddset(&s_mask,SIGXCPU) < 0)||(sigaddset(&s_mask,SIGXFSZ)<0)) { 33757112Smuller warn(1, "Unable to set up signal mask"); 33857112Smuller return(-1); 33957112Smuller } 34057112Smuller n_hand.sa_mask = s_mask; 34157112Smuller n_hand.sa_flags = 0; 34257112Smuller n_hand.sa_handler = sig_cleanup; 34357112Smuller 34457112Smuller if ((sigaction(SIGHUP, &n_hand, &o_hand) < 0) && 34557112Smuller (o_hand.sa_handler == SIG_IGN) && 34657112Smuller (sigaction(SIGHUP, &o_hand, &o_hand) < 0)) 34757112Smuller goto out; 34857112Smuller 34957112Smuller if ((sigaction(SIGTERM, &n_hand, &o_hand) < 0) && 35057112Smuller (o_hand.sa_handler == SIG_IGN) && 35157112Smuller (sigaction(SIGTERM, &o_hand, &o_hand) < 0)) 35257112Smuller goto out; 35357112Smuller 35457112Smuller if ((sigaction(SIGINT, &n_hand, &o_hand) < 0) && 35557112Smuller (o_hand.sa_handler == SIG_IGN) && 35657112Smuller (sigaction(SIGINT, &o_hand, &o_hand) < 0)) 35757112Smuller goto out; 35857112Smuller 35957112Smuller if ((sigaction(SIGQUIT, &n_hand, &o_hand) < 0) && 36057112Smuller (o_hand.sa_handler == SIG_IGN) && 36157112Smuller (sigaction(SIGQUIT, &o_hand, &o_hand) < 0)) 36257112Smuller goto out; 36357112Smuller 36457112Smuller if ((sigaction(SIGXCPU, &n_hand, &o_hand) < 0) && 36557112Smuller (o_hand.sa_handler == SIG_IGN) && 36657112Smuller (sigaction(SIGXCPU, &o_hand, &o_hand) < 0)) 36757112Smuller goto out; 36857112Smuller 36957112Smuller n_hand.sa_handler = SIG_IGN; 37057112Smuller if ((sigaction(SIGPIPE, &n_hand, &o_hand) < 0) || 37157112Smuller (sigaction(SIGXFSZ, &n_hand, &o_hand) < 0)) 37257112Smuller goto out; 37357112Smuller return(0); 37457112Smuller 37557112Smuller out: 37657112Smuller syswarn(1, errno, "Unable to set up signal handler"); 37757112Smuller return(-1); 37857112Smuller } 37957543Smuller 38057543Smuller /* 38157543Smuller * usage() 38257543Smuller * print the usage summary to the user 38357543Smuller */ 38457543Smuller 38557543Smuller #if __STDC__ 38657543Smuller void 38757543Smuller usage(void) 38857543Smuller #else 38957543Smuller void 39057543Smuller usage() 39157543Smuller #endif 39257543Smuller { 39357543Smuller (void)fputs("usage: pax [-cdnv] [-E limit] [-f archive] ", stderr); 39457543Smuller (void)fputs("[-s replstr] ... [-U user] ...", stderr); 39557543Smuller (void)fputs("\n [-G group] ... ", stderr); 39657543Smuller (void)fputs("[-T [from_date][,to_date]] ... ", stderr); 39757543Smuller (void)fputs("[pattern ...]\n", stderr); 39857543Smuller (void)fputs(" pax -r [-cdiknuvDYZ] [-E limit] ", stderr); 39957543Smuller (void)fputs("[-f archive] [-o options] ... \n", stderr); 40057543Smuller (void)fputs(" [-p string] ... [-s replstr] ... ", stderr); 40157543Smuller (void)fputs("[-U user] ... [-G group] ...\n ", stderr); 40257543Smuller (void)fputs("[-T [from_date][,to_date]] ... ", stderr); 40357543Smuller (void)fputs(" [pattern ...]\n", stderr); 40457543Smuller (void)fputs(" pax -w [-dituvHLX] [-b blocksize] ", stderr); 40557543Smuller (void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr); 40657543Smuller (void)fputs(" [-B bytes] [-s replstr] ... ", stderr); 40757543Smuller (void)fputs("[-o options] ... [-U user] ...", stderr); 40857543Smuller (void)fputs("\n [-G group] ... ", stderr); 40957543Smuller (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr); 41057543Smuller (void)fputs("[file ...]\n", stderr); 41157543Smuller (void)fputs(" pax -r -w [-diklntuvDHLXYZ]", stderr); 41257543Smuller (void)fputs("[-p string] ... [-s replstr] ... [-U user] ...", stderr); 41357543Smuller (void)fputs("\n [-G group] ... ", stderr); 41457543Smuller (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr); 41557543Smuller (void)fputs("[file ...]\n directory\n", stderr); 41657543Smuller exit(1); 41757543Smuller } 418