pax.c revision 31666
11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1992 Keith Muller. 31556Srgrimes * Copyright (c) 1992, 1993 41556Srgrimes * The Regents of the University of California. All rights reserved. 51556Srgrimes * 61556Srgrimes * This code is derived from software contributed to Berkeley by 71556Srgrimes * Keith Muller of the University of California, San Diego. 81556Srgrimes * 91556Srgrimes * Redistribution and use in source and binary forms, with or without 101556Srgrimes * modification, are permitted provided that the following conditions 111556Srgrimes * are met: 121556Srgrimes * 1. Redistributions of source code must retain the above copyright 131556Srgrimes * notice, this list of conditions and the following disclaimer. 141556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151556Srgrimes * notice, this list of conditions and the following disclaimer in the 161556Srgrimes * documentation and/or other materials provided with the distribution. 171556Srgrimes * 3. All advertising materials mentioning features or use of this software 181556Srgrimes * must display the following acknowledgement: 191556Srgrimes * This product includes software developed by the University of 201556Srgrimes * California, Berkeley and its contributors. 211556Srgrimes * 4. Neither the name of the University nor the names of its contributors 221556Srgrimes * may be used to endorse or promote products derived from this software 231556Srgrimes * without specific prior written permission. 241556Srgrimes * 251556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351556Srgrimes * SUCH DAMAGE. 363044Sdg * 3731666Seivind * $Id: pax.c,v 1.9 1997/08/29 16:12:28 sos Exp $ 381556Srgrimes */ 391556Srgrimes 401556Srgrimes#ifndef lint 4120420Sstevestatic char const copyright[] = 421556Srgrimes"@(#) Copyright (c) 1992, 1993\n\ 431556Srgrimes The Regents of the University of California. All rights reserved.\n"; 441556Srgrimes#endif /* not lint */ 451556Srgrimes 461556Srgrimes#ifndef lint 4720420Sstevestatic char const sccsid[] = "@(#)pax.c 8.2 (Berkeley) 4/18/94"; 481556Srgrimes#endif /* not lint */ 491556Srgrimes 501556Srgrimes#include <sys/types.h> 511556Srgrimes#include <sys/stat.h> 521556Srgrimes#include <sys/time.h> 531556Srgrimes#include <sys/resource.h> 5431666Seivind#include <errno.h> 5531666Seivind#include <locale.h> 561556Srgrimes#include <signal.h> 5731666Seivind#include <stdio.h> 5831666Seivind#include <stdlib.h> 591556Srgrimes#include <unistd.h> 601556Srgrimes#include "pax.h" 611556Srgrimes#include "extern.h" 621556Srgrimesstatic int gen_init __P((void)); 631556Srgrimes 641556Srgrimes/* 651556Srgrimes * PAX main routines, general globals and some simple start up routines 661556Srgrimes */ 671556Srgrimes 681556Srgrimes/* 691556Srgrimes * Variables that can be accessed by any routine within pax 701556Srgrimes */ 711556Srgrimesint act = DEFOP; /* read/write/append/copy */ 721556SrgrimesFSUB *frmt = NULL; /* archive format type */ 731556Srgrimesint cflag; /* match all EXCEPT pattern/file */ 741556Srgrimesint dflag; /* directory member match only */ 751556Srgrimesint iflag; /* interactive file/archive rename */ 761556Srgrimesint kflag; /* do not overwrite existing files */ 771556Srgrimesint lflag; /* use hard links when possible */ 781556Srgrimesint nflag; /* select first archive member match */ 791556Srgrimesint tflag; /* restore access time after read */ 801556Srgrimesint uflag; /* ignore older modification time files */ 811556Srgrimesint vflag; /* produce verbose output */ 821556Srgrimesint Dflag; /* same as uflag except inode change time */ 831556Srgrimesint Hflag; /* follow command line symlinks (write only) */ 841556Srgrimesint Lflag; /* follow symlinks when writing */ 851556Srgrimesint Xflag; /* archive files with same device id only */ 861556Srgrimesint Yflag; /* same as Dflg except after name mode */ 871556Srgrimesint Zflag; /* same as uflg except after name mode */ 881556Srgrimesint vfpart; /* is partial verbose output in progress */ 891556Srgrimesint patime = 1; /* preserve file access time */ 901556Srgrimesint pmtime = 1; /* preserve file modification times */ 911556Srgrimesint pmode; /* preserve file mode bits */ 921556Srgrimesint pids; /* preserve file uid/gid */ 931556Srgrimesint exit_val; /* exit value */ 941556Srgrimesint docrc; /* check/create file crc */ 951556Srgrimeschar *dirptr; /* destination dir in a copy */ 961556Srgrimeschar *ltmfrmt; /* -v locale time format (if any) */ 971556Srgrimeschar *argv0; /* root of argv[0] */ 981556Srgrimessigset_t s_mask; /* signal mask for cleanup critical sect */ 991556Srgrimes 1001556Srgrimes/* 1011556Srgrimes * PAX - Portable Archive Interchange 1021556Srgrimes * 1031556Srgrimes * A utility to read, write, and write lists of the members of archive 1041556Srgrimes * files and copy directory hierarchies. A variety of archive formats 1051556Srgrimes * are supported (some are described in POSIX 1003.1 10.1): 1061556Srgrimes * 1071556Srgrimes * ustar - 10.1.1 extended tar interchange format 1081556Srgrimes * cpio - 10.1.2 extended cpio interchange format 1091556Srgrimes * tar - old BSD 4.3 tar format 1101556Srgrimes * binary cpio - old cpio with binary header format 1111556Srgrimes * sysVR4 cpio - with and without CRC 1121556Srgrimes * 1131556Srgrimes * This version is a superset of IEEE Std 1003.2b-d3 1141556Srgrimes * 1151556Srgrimes * Summary of Extensions to the IEEE Standard: 1161556Srgrimes * 1171556Srgrimes * 1 READ ENHANCEMENTS 1181556Srgrimes * 1.1 Operations which read archives will continue to operate even when 1198855Srgrimes * processing archives which may be damaged, truncated, or fail to meet 1201556Srgrimes * format specs in several different ways. Damaged sections of archives 1211556Srgrimes * are detected and avoided if possible. Attempts will be made to resync 1221556Srgrimes * archive read operations even with badly damaged media. 1231556Srgrimes * 1.2 Blocksize requirements are not strictly enforced on archive read. 1241556Srgrimes * Tapes which have variable sized records can be read without errors. 1251556Srgrimes * 1.3 The user can specify via the non-standard option flag -E if error 1261556Srgrimes * resync operation should stop on a media error, try a specified number 1271556Srgrimes * of times to correct, or try to correct forever. 1281556Srgrimes * 1.4 Sparse files (lseek holes) stored on the archive (but stored with blocks 1291556Srgrimes * of all zeros will be restored with holes appropriate for the target 1301556Srgrimes * filesystem 1311556Srgrimes * 1.5 The user is notified whenever something is found during archive 1321556Srgrimes * read operations which violates spec (but the read will continue). 1331556Srgrimes * 1.6 Multiple archive volumes can be read and may span over different 1348855Srgrimes * archive devices 1351556Srgrimes * 1.7 Rigidly restores all file attributes exactly as they are stored on the 1361556Srgrimes * archive. 1371556Srgrimes * 1.8 Modification change time ranges can be specified via multiple -T 1381556Srgrimes * options. These allow a user to select files whose modification time 1391556Srgrimes * lies within a specific time range. 1401556Srgrimes * 1.9 Files can be selected based on owner (user name or uid) via one or more 1411556Srgrimes * -U options. 1421556Srgrimes * 1.10 Files can be selected based on group (group name or gid) via one o 1431556Srgrimes * more -G options. 1441556Srgrimes * 1.11 File modification time can be checked against exisiting file after 1451556Srgrimes * name modification (-Z) 1461556Srgrimes * 1471556Srgrimes * 2 WRITE ENHANCEMENTS 1481556Srgrimes * 2.1 Write operation will stop instead of allowing a user to create a flawed 1491556Srgrimes * flawed archive (due to any problem). 1501556Srgrimes * 2.2 Archives writtens by pax are forced to strictly conform to both the 1511556Srgrimes * archive and pax the spceific format specifications. 1521556Srgrimes * 2.3 Blocking size and format is rigidly enforced on writes. 1531556Srgrimes * 2.4 Formats which may exhibit header overflow problems (they have fields 1541556Srgrimes * too small for large file systems, such as inode number storage), use 1551556Srgrimes * routines designed to repair this problem. These techniques still 1561556Srgrimes * conform to both pax and format specifications, but no longer truncate 1571556Srgrimes * these fields. This removes any restrictions on using these archive 1581556Srgrimes * formats on large file systems. 1591556Srgrimes * 2.5 Multiple archive volumes can be written and may span over different 1608855Srgrimes * archive devices 1611556Srgrimes * 2.6 A archive volume record limit allows the user to specify the number 1621556Srgrimes * of bytes stored on an archive volume. When reached the user is 1631556Srgrimes * prompted for the next archive volume. This is specified with the 1641556Srgrimes * non-standard -B flag. THe limit is rounded up to the next blocksize. 1651556Srgrimes * 2.7 All archive padding during write use zero filled sections. This makes 1661556Srgrimes * it much easier to pull data out of flawed archive during read 1671556Srgrimes * operations. 1681556Srgrimes * 2.8 Access time reset with the -t applies to all file nodes (including 1691556Srgrimes * directories). 1701556Srgrimes * 2.9 Symbolic links can be followed with -L (optional in the spec). 1711556Srgrimes * 2.10 Modification or inode change time ranges can be specified via 1721556Srgrimes * multiple -T options. These allow a user to select files whose 1731556Srgrimes * modification or inode change time lies within a specific time range. 1741556Srgrimes * 2.11 Files can be selected based on owner (user name or uid) via one or more 1751556Srgrimes * -U options. 1761556Srgrimes * 2.12 Files can be selected based on group (group name or gid) via one o 1771556Srgrimes * more -G options. 1781556Srgrimes * 2.13 Symlinks which appear on the command line can be followed (without 1791556Srgrimes * following other symlinks; -H flag) 1801556Srgrimes * 1811556Srgrimes * 3 COPY ENHANCEMENTS 1821556Srgrimes * 3.1 Sparse files (lseek holes) can be copied without expanding the holes 1831556Srgrimes * into zero filled blocks. The file copy is created with holes which are 1841556Srgrimes * appropriate for the target filesystem 1851556Srgrimes * 3.2 Access time as well as modification time on copied file trees can be 1861556Srgrimes * preserved with the appropriate -p options. 1871556Srgrimes * 3.3 Access time reset with the -t applies to all file nodes (including 1881556Srgrimes * directories). 1891556Srgrimes * 3.4 Symbolic links can be followed with -L (optional in the spec). 1901556Srgrimes * 3.5 Modification or inode change time ranges can be specified via 1911556Srgrimes * multiple -T options. These allow a user to select files whose 1921556Srgrimes * modification or inode change time lies within a specific time range. 1931556Srgrimes * 3.6 Files can be selected based on owner (user name or uid) via one or more 1941556Srgrimes * -U options. 1951556Srgrimes * 3.7 Files can be selected based on group (group name or gid) via one o 1961556Srgrimes * more -G options. 1971556Srgrimes * 3.8 Symlinks which appear on the command line can be followed (without 1981556Srgrimes * following other symlinks; -H flag) 1991556Srgrimes * 3.9 File inode change time can be checked against exisiting file before 2001556Srgrimes * name modification (-D) 2011556Srgrimes * 3.10 File inode change time can be checked against exisiting file after 2021556Srgrimes * name modification (-Y) 2031556Srgrimes * 3.11 File modification time can be checked against exisiting file after 2041556Srgrimes * name modification (-Z) 2051556Srgrimes * 2061556Srgrimes * 4 GENERAL ENHANCEMENTS 2078855Srgrimes * 4.1 Internal structure is designed to isolate format dependent and 2081556Srgrimes * independent functions. Formats are selected via a format driver table. 2091556Srgrimes * This encourages the addition of new archive formats by only having to 2101556Srgrimes * write those routines which id, read and write the archive header. 2111556Srgrimes */ 2121556Srgrimes 2131556Srgrimes/* 2141556Srgrimes * main() 2151556Srgrimes * parse options, set up and operate as specified by the user. 2161556Srgrimes * any operational flaw will set exit_val to non-zero 2171556Srgrimes * Return: 0 if ok, 1 otherwise 2181556Srgrimes */ 2191556Srgrimes 2201556Srgrimes#if __STDC__ 2211556Srgrimesint 2221556Srgrimesmain(int argc, char **argv) 2231556Srgrimes#else 2241556Srgrimesint 2251556Srgrimesmain(argc, argv) 2261556Srgrimes int argc; 2271556Srgrimes char **argv; 2281556Srgrimes#endif 2291556Srgrimes{ 23017517Sache (void) setlocale(LC_ALL, ""); 2311556Srgrimes /* 2321556Srgrimes * parse options, determine operational mode, general init 2331556Srgrimes */ 2341556Srgrimes options(argc, argv); 2351556Srgrimes if ((gen_init() < 0) || (tty_init() < 0)) 2361556Srgrimes return(exit_val); 2371556Srgrimes 2381556Srgrimes /* 2398855Srgrimes * select a primary operation mode 2401556Srgrimes */ 2411556Srgrimes switch(act) { 2421556Srgrimes case EXTRACT: 2431556Srgrimes extract(); 2441556Srgrimes break; 2451556Srgrimes case ARCHIVE: 2461556Srgrimes archive(); 2471556Srgrimes break; 2481556Srgrimes case APPND: 2491556Srgrimes append(); 2501556Srgrimes break; 2511556Srgrimes case COPY: 2521556Srgrimes copy(); 2531556Srgrimes break; 2541556Srgrimes default: 2551556Srgrimes case LIST: 2561556Srgrimes list(); 2571556Srgrimes break; 2581556Srgrimes } 2591556Srgrimes return(exit_val); 2601556Srgrimes} 2611556Srgrimes 2621556Srgrimes/* 2631556Srgrimes * sig_cleanup() 2641556Srgrimes * when interrupted we try to do whatever delayed processing we can. 2651556Srgrimes * This is not critical, but we really ought to limit our damage when we 2661556Srgrimes * are aborted by the user. 2671556Srgrimes * Return: 2681556Srgrimes * never.... 2691556Srgrimes */ 2701556Srgrimes 2711556Srgrimes#if __STDC__ 2721556Srgrimesvoid 2731556Srgrimessig_cleanup(int which_sig) 2741556Srgrimes#else 2751556Srgrimesvoid 2761556Srgrimessig_cleanup(which_sig) 2771556Srgrimes int which_sig; 2781556Srgrimes#endif 2791556Srgrimes{ 2801556Srgrimes /* 2811556Srgrimes * restore modes and times for any dirs we may have created 2821556Srgrimes * or any dirs we may have read. Set vflag and vfpart so the user 2831556Srgrimes * will clearly see the message on a line by itself. 2841556Srgrimes */ 2851556Srgrimes vflag = vfpart = 1; 2861556Srgrimes if (which_sig == SIGXCPU) 28728904Ssos pax_warn(0, "Cpu time limit reached, cleaning up."); 2881556Srgrimes else 28928904Ssos pax_warn(0, "Signal caught, cleaning up."); 2901556Srgrimes 2911556Srgrimes ar_close(); 2921556Srgrimes proc_dir(); 2931556Srgrimes if (tflag) 2941556Srgrimes atdir_end(); 2951556Srgrimes exit(1); 2961556Srgrimes} 2971556Srgrimes 2981556Srgrimes/* 2991556Srgrimes * gen_init() 3001556Srgrimes * general setup routines. Not all are required, but they really help 3011556Srgrimes * when dealing with a medium to large sized archives. 3021556Srgrimes */ 3031556Srgrimes 3041556Srgrimes#if __STDC__ 3051556Srgrimesstatic int 3061556Srgrimesgen_init(void) 3071556Srgrimes#else 3081556Srgrimesstatic int 3091556Srgrimesgen_init() 3101556Srgrimes#endif 3111556Srgrimes{ 3121556Srgrimes struct rlimit reslimit; 3131556Srgrimes struct sigaction n_hand; 3141556Srgrimes struct sigaction o_hand; 3151556Srgrimes 3161556Srgrimes /* 3171556Srgrimes * Really needed to handle large archives. We can run out of memory for 3181556Srgrimes * internal tables really fast when we have a whole lot of files... 3191556Srgrimes */ 3201556Srgrimes if (getrlimit(RLIMIT_DATA , &reslimit) == 0){ 3211556Srgrimes reslimit.rlim_cur = reslimit.rlim_max; 3221556Srgrimes (void)setrlimit(RLIMIT_DATA , &reslimit); 3231556Srgrimes } 3241556Srgrimes 3251556Srgrimes /* 3261556Srgrimes * should file size limits be waived? if the os limits us, this is 3271556Srgrimes * needed if we want to write a large archive 3281556Srgrimes */ 3291556Srgrimes if (getrlimit(RLIMIT_FSIZE , &reslimit) == 0){ 3301556Srgrimes reslimit.rlim_cur = reslimit.rlim_max; 3311556Srgrimes (void)setrlimit(RLIMIT_FSIZE , &reslimit); 3321556Srgrimes } 3331556Srgrimes 3341556Srgrimes /* 3351556Srgrimes * increase the size the stack can grow to 3361556Srgrimes */ 3371556Srgrimes if (getrlimit(RLIMIT_STACK , &reslimit) == 0){ 3381556Srgrimes reslimit.rlim_cur = reslimit.rlim_max; 3391556Srgrimes (void)setrlimit(RLIMIT_STACK , &reslimit); 3401556Srgrimes } 3411556Srgrimes 3421556Srgrimes /* 3431556Srgrimes * not really needed, but doesn't hurt 3441556Srgrimes */ 3451556Srgrimes if (getrlimit(RLIMIT_RSS , &reslimit) == 0){ 3461556Srgrimes reslimit.rlim_cur = reslimit.rlim_max; 3471556Srgrimes (void)setrlimit(RLIMIT_RSS , &reslimit); 3481556Srgrimes } 3491556Srgrimes 3501556Srgrimes /* 3511556Srgrimes * Handle posix locale 3521556Srgrimes * 3538855Srgrimes * set user defines time printing format for -v option 3541556Srgrimes */ 3551556Srgrimes ltmfrmt = getenv("LC_TIME"); 3561556Srgrimes 3571556Srgrimes /* 3581556Srgrimes * signal handling to reset stored directory times and modes. Since 3591556Srgrimes * we deal with broken pipes via failed writes we ignore it. We also 3601556Srgrimes * deal with any file size limit thorugh failed writes. Cpu time 3611556Srgrimes * limits are caught and a cleanup is forced. 3621556Srgrimes */ 3631556Srgrimes if ((sigemptyset(&s_mask) < 0) || (sigaddset(&s_mask, SIGTERM) < 0) || 3641556Srgrimes (sigaddset(&s_mask,SIGINT) < 0)||(sigaddset(&s_mask,SIGHUP) < 0) || 3651556Srgrimes (sigaddset(&s_mask,SIGPIPE) < 0)||(sigaddset(&s_mask,SIGQUIT)<0) || 3661556Srgrimes (sigaddset(&s_mask,SIGXCPU) < 0)||(sigaddset(&s_mask,SIGXFSZ)<0)) { 36728904Ssos pax_warn(1, "Unable to set up signal mask"); 3681556Srgrimes return(-1); 3691556Srgrimes } 3701556Srgrimes n_hand.sa_mask = s_mask; 3711556Srgrimes n_hand.sa_flags = 0; 3721556Srgrimes n_hand.sa_handler = sig_cleanup; 3731556Srgrimes 3741556Srgrimes if ((sigaction(SIGHUP, &n_hand, &o_hand) < 0) && 3758855Srgrimes (o_hand.sa_handler == SIG_IGN) && 3761556Srgrimes (sigaction(SIGHUP, &o_hand, &o_hand) < 0)) 3771556Srgrimes goto out; 3781556Srgrimes 3791556Srgrimes if ((sigaction(SIGTERM, &n_hand, &o_hand) < 0) && 3808855Srgrimes (o_hand.sa_handler == SIG_IGN) && 3811556Srgrimes (sigaction(SIGTERM, &o_hand, &o_hand) < 0)) 3821556Srgrimes goto out; 3831556Srgrimes 3841556Srgrimes if ((sigaction(SIGINT, &n_hand, &o_hand) < 0) && 3858855Srgrimes (o_hand.sa_handler == SIG_IGN) && 3861556Srgrimes (sigaction(SIGINT, &o_hand, &o_hand) < 0)) 3871556Srgrimes goto out; 3881556Srgrimes 3891556Srgrimes if ((sigaction(SIGQUIT, &n_hand, &o_hand) < 0) && 3908855Srgrimes (o_hand.sa_handler == SIG_IGN) && 3911556Srgrimes (sigaction(SIGQUIT, &o_hand, &o_hand) < 0)) 3921556Srgrimes goto out; 3931556Srgrimes 3941556Srgrimes if ((sigaction(SIGXCPU, &n_hand, &o_hand) < 0) && 3958855Srgrimes (o_hand.sa_handler == SIG_IGN) && 3961556Srgrimes (sigaction(SIGXCPU, &o_hand, &o_hand) < 0)) 3971556Srgrimes goto out; 3981556Srgrimes 3991556Srgrimes n_hand.sa_handler = SIG_IGN; 4001556Srgrimes if ((sigaction(SIGPIPE, &n_hand, &o_hand) < 0) || 4011556Srgrimes (sigaction(SIGXFSZ, &n_hand, &o_hand) < 0)) 4021556Srgrimes goto out; 4031556Srgrimes return(0); 4041556Srgrimes 4051556Srgrimes out: 40628904Ssos sys_warn(1, errno, "Unable to set up signal handler"); 4071556Srgrimes return(-1); 4081556Srgrimes} 409