00001 /*- 00002 * Copyright (c) 1992 Keith Muller. 00003 * Copyright (c) 1992, 1993 00004 * The Regents of the University of California. All rights reserved. 00005 * 00006 * This code is derived from software contributed to Berkeley by 00007 * Keith Muller of the University of California, San Diego. 00008 * 00009 * Redistribution and use in source and binary forms, with or without 00010 * modification, are permitted provided that the following conditions 00011 * are met: 00012 * 1. Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * 2. Redistributions in binary form must reproduce the above copyright 00015 * notice, this list of conditions and the following disclaimer in the 00016 * documentation and/or other materials provided with the distribution. 00017 * 4. Neither the name of the University nor the names of its contributors 00018 * may be used to endorse or promote products derived from this software 00019 * without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00022 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00023 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00024 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00025 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00026 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00027 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00028 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00029 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00030 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00031 * SUCH DAMAGE. 00032 */ 00033 00034 #if 0 00035 #ifndef lint 00036 static char const copyright[] = 00037 "@(#) Copyright (c) 1992, 1993\n\ 00038 The Regents of the University of California. All rights reserved.\n"; 00039 #endif /* not lint */ 00040 00041 #ifndef lint 00042 static char sccsid[] = "@(#)pax.c 8.2 (Berkeley) 4/18/94"; 00043 #endif /* not lint */ 00044 #endif 00045 00046 #include <sys/types.h> 00047 #include <sys/stat.h> 00048 #include <sys/time.h> 00049 #include <sys/resource.h> 00050 #include <errno.h> 00051 #include <fcntl.h> 00052 #include <locale.h> 00053 #include <minix/paths.h> 00054 #include <signal.h> 00055 #include <stdio.h> 00056 #include <stdlib.h> 00057 #include <string.h> 00058 #include <unistd.h> 00059 #include "pax.h" 00060 #include "extern.h" 00061 static int gen_init(void); 00062 00063 /* 00064 * PAX main routines, general globals and some simple start up routines 00065 */ 00066 00067 /* 00068 * Variables that can be accessed by any routine within pax 00069 */ 00070 int act = DEFOP; /* read/write/append/copy */ 00071 FSUB *frmt = NULL; /* archive format type */ 00072 int cflag; /* match all EXCEPT pattern/file */ 00073 int cwdfd; /* starting cwd */ 00074 int dflag; /* directory member match only */ 00075 int iflag; /* interactive file/archive rename */ 00076 int kflag; /* do not overwrite existing files */ 00077 int lflag; /* use hard links when possible */ 00078 int nflag; /* select first archive member match */ 00079 int tflag; /* restore access time after read */ 00080 int uflag; /* ignore older modification time files */ 00081 int vflag; /* produce verbose output */ 00082 int Dflag; /* same as uflag except inode change time */ 00083 int Hflag; /* follow command line symlinks (write only) */ 00084 int Lflag; /* follow symlinks when writing */ 00085 int Xflag; /* archive files with same device id only */ 00086 int Yflag; /* same as Dflg except after name mode */ 00087 int Zflag; /* same as uflg except after name mode */ 00088 int vfpart; /* is partial verbose output in progress */ 00089 int patime = 1; /* preserve file access time */ 00090 int pmtime = 1; /* preserve file modification times */ 00091 int nodirs; /* do not create directories as needed */ 00092 int pmode; /* preserve file mode bits */ 00093 int pids; /* preserve file uid/gid */ 00094 int rmleadslash = 0; /* remove leading '/' from pathnames */ 00095 int exit_val; /* exit value */ 00096 int docrc; /* check/create file crc */ 00097 char *dirptr; /* destination dir in a copy */ 00098 const char *argv0; /* root of argv[0] */ 00099 sigset_t s_mask; /* signal mask for cleanup critical sect */ 00100 FILE *listf; /* file pointer to print file list to */ 00101 char *tempfile; /* tempfile to use for mkstemp(3) */ 00102 char *tempbase; /* basename of tempfile to use for mkstemp(3) */ 00103 00104 /* 00105 * PAX - Portable Archive Interchange 00106 * 00107 * A utility to read, write, and write lists of the members of archive 00108 * files and copy directory hierarchies. A variety of archive formats 00109 * are supported (some are described in POSIX 1003.1 10.1): 00110 * 00111 * ustar - 10.1.1 extended tar interchange format 00112 * cpio - 10.1.2 extended cpio interchange format 00113 * tar - old BSD 4.3 tar format 00114 * binary cpio - old cpio with binary header format 00115 * sysVR4 cpio - with and without CRC 00116 * 00117 * This version is a superset of IEEE Std 1003.2b-d3 00118 * 00119 * Summary of Extensions to the IEEE Standard: 00120 * 00121 * 1 READ ENHANCEMENTS 00122 * 1.1 Operations which read archives will continue to operate even when 00123 * processing archives which may be damaged, truncated, or fail to meet 00124 * format specs in several different ways. Damaged sections of archives 00125 * are detected and avoided if possible. Attempts will be made to resync 00126 * archive read operations even with badly damaged media. 00127 * 1.2 Blocksize requirements are not strictly enforced on archive read. 00128 * Tapes which have variable sized records can be read without errors. 00129 * 1.3 The user can specify via the non-standard option flag -E if error 00130 * resync operation should stop on a media error, try a specified number 00131 * of times to correct, or try to correct forever. 00132 * 1.4 Sparse files (lseek holes) stored on the archive (but stored with blocks 00133 * of all zeros will be restored with holes appropriate for the target 00134 * file system 00135 * 1.5 The user is notified whenever something is found during archive 00136 * read operations which violates spec (but the read will continue). 00137 * 1.6 Multiple archive volumes can be read and may span over different 00138 * archive devices 00139 * 1.7 Rigidly restores all file attributes exactly as they are stored on the 00140 * archive. 00141 * 1.8 Modification change time ranges can be specified via multiple -T 00142 * options. These allow a user to select files whose modification time 00143 * lies within a specific time range. 00144 * 1.9 Files can be selected based on owner (user name or uid) via one or more 00145 * -U options. 00146 * 1.10 Files can be selected based on group (group name or gid) via one o 00147 * more -G options. 00148 * 1.11 File modification time can be checked against existing file after 00149 * name modification (-Z) 00150 * 00151 * 2 WRITE ENHANCEMENTS 00152 * 2.1 Write operation will stop instead of allowing a user to create a flawed 00153 * flawed archive (due to any problem). 00154 * 2.2 Archives written by pax are forced to strictly conform to both the 00155 * archive and pax the specific format specifications. 00156 * 2.3 Blocking size and format is rigidly enforced on writes. 00157 * 2.4 Formats which may exhibit header overflow problems (they have fields 00158 * too small for large file systems, such as inode number storage), use 00159 * routines designed to repair this problem. These techniques still 00160 * conform to both pax and format specifications, but no longer truncate 00161 * these fields. This removes any restrictions on using these archive 00162 * formats on large file systems. 00163 * 2.5 Multiple archive volumes can be written and may span over different 00164 * archive devices 00165 * 2.6 A archive volume record limit allows the user to specify the number 00166 * of bytes stored on an archive volume. When reached the user is 00167 * prompted for the next archive volume. This is specified with the 00168 * non-standard -B flag. The limit is rounded up to the next blocksize. 00169 * 2.7 All archive padding during write use zero filled sections. This makes 00170 * it much easier to pull data out of flawed archive during read 00171 * operations. 00172 * 2.8 Access time reset with the -t applies to all file nodes (including 00173 * directories). 00174 * 2.9 Symbolic links can be followed with -L (optional in the spec). 00175 * 2.10 Modification or inode change time ranges can be specified via 00176 * multiple -T options. These allow a user to select files whose 00177 * modification or inode change time lies within a specific time range. 00178 * 2.11 Files can be selected based on owner (user name or uid) via one or more 00179 * -U options. 00180 * 2.12 Files can be selected based on group (group name or gid) via one o 00181 * more -G options. 00182 * 2.13 Symlinks which appear on the command line can be followed (without 00183 * following other symlinks; -H flag) 00184 * 00185 * 3 COPY ENHANCEMENTS 00186 * 3.1 Sparse files (lseek holes) can be copied without expanding the holes 00187 * into zero filled blocks. The file copy is created with holes which are 00188 * appropriate for the target file system 00189 * 3.2 Access time as well as modification time on copied file trees can be 00190 * preserved with the appropriate -p options. 00191 * 3.3 Access time reset with the -t applies to all file nodes (including 00192 * directories). 00193 * 3.4 Symbolic links can be followed with -L (optional in the spec). 00194 * 3.5 Modification or inode change time ranges can be specified via 00195 * multiple -T options. These allow a user to select files whose 00196 * modification or inode change time lies within a specific time range. 00197 * 3.6 Files can be selected based on owner (user name or uid) via one or more 00198 * -U options. 00199 * 3.7 Files can be selected based on group (group name or gid) via one o 00200 * more -G options. 00201 * 3.8 Symlinks which appear on the command line can be followed (without 00202 * following other symlinks; -H flag) 00203 * 3.9 File inode change time can be checked against existing file before 00204 * name modification (-D) 00205 * 3.10 File inode change time can be checked against existing file after 00206 * name modification (-Y) 00207 * 3.11 File modification time can be checked against existing file after 00208 * name modification (-Z) 00209 * 00210 * 4 GENERAL ENHANCEMENTS 00211 * 4.1 Internal structure is designed to isolate format dependent and 00212 * independent functions. Formats are selected via a format driver table. 00213 * This encourages the addition of new archive formats by only having to 00214 * write those routines which id, read and write the archive header. 00215 */ 00216 00217 /* 00218 * main() 00219 * parse options, set up and operate as specified by the user. 00220 * any operational flaw will set exit_val to non-zero 00221 * Return: 0 if ok, 1 otherwise 00222 */ 00223 00224 int 00225 main(int argc, char *argv[]) 00226 { 00227 const char *tmpdir; 00228 size_t tdlen; 00229 00230 (void) setlocale(LC_ALL, ""); 00231 listf = stderr; 00232 /* 00233 * Keep a reference to cwd, so we can always come back home. 00234 */ 00235 cwdfd = open(".", O_RDONLY); 00236 if (cwdfd < 0) { 00237 syswarn(0, errno, "Can't open current working directory."); 00238 return(exit_val); 00239 } 00240 00241 /* 00242 * Where should we put temporary files? 00243 */ 00244 if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0') 00245 tmpdir = _PATH_TMP; 00246 tdlen = strlen(tmpdir); 00247 while(tdlen > 0 && tmpdir[tdlen - 1] == '/') 00248 tdlen--; 00249 tempfile = malloc(tdlen + 1 + sizeof(_TFILE_BASE)); 00250 if (tempfile == NULL) { 00251 paxwarn(1, "Cannot allocate memory for temp file name."); 00252 return(exit_val); 00253 } 00254 if (tdlen) 00255 memcpy(tempfile, tmpdir, tdlen); 00256 tempbase = tempfile + tdlen; 00257 *tempbase++ = '/'; 00258 00259 /* 00260 * parse options, determine operational mode, general init 00261 */ 00262 options(argc, argv); 00263 if ((gen_init() < 0) || (tty_init() < 0)) 00264 return(exit_val); 00265 00266 /* 00267 * select a primary operation mode 00268 */ 00269 switch(act) { 00270 case EXTRACT: 00271 extract(); 00272 break; 00273 case ARCHIVE: 00274 archive(); 00275 break; 00276 case APPND: 00277 if (gzip_program != NULL) 00278 err(1, "can not gzip while appending"); 00279 append(); 00280 break; 00281 case COPY: 00282 copy(); 00283 break; 00284 default: 00285 case LIST: 00286 list(); 00287 break; 00288 } 00289 return(exit_val); 00290 } 00291 00292 /* 00293 * sig_cleanup() 00294 * when interrupted we try to do whatever delayed processing we can. 00295 * This is not critical, but we really ought to limit our damage when we 00296 * are aborted by the user. 00297 * Return: 00298 * never.... 00299 */ 00300 00301 void 00302 sig_cleanup(int which_sig) 00303 { 00304 /* 00305 * restore modes and times for any dirs we may have created 00306 * or any dirs we may have read. Set vflag and vfpart so the user 00307 * will clearly see the message on a line by itself. 00308 */ 00309 vflag = vfpart = 1; 00310 #if 0 00311 /* ignore this under minix */ 00312 if (which_sig == SIGXCPU) 00313 paxwarn(0, "Cpu time limit reached, cleaning up."); 00314 else 00315 #endif 00316 paxwarn(0, "Signal caught, cleaning up."); 00317 00318 ar_close(); 00319 proc_dir(); 00320 if (tflag) 00321 atdir_end(); 00322 exit(1); 00323 } 00324 00325 /* 00326 * gen_init() 00327 * general setup routines. Not all are required, but they really help 00328 * when dealing with a medium to large sized archives. 00329 */ 00330 00331 static int 00332 gen_init(void) 00333 { 00334 #if 0 00335 struct rlimit reslimit; 00336 #endif 00337 struct sigaction n_hand; 00338 struct sigaction o_hand; 00339 00340 #if 0 00341 /* 00342 * Really needed to handle large archives. We can run out of memory for 00343 * internal tables really fast when we have a whole lot of files... 00344 */ 00345 if (getrlimit(RLIMIT_DATA , &reslimit) == 0){ 00346 reslimit.rlim_cur = reslimit.rlim_max; 00347 (void)setrlimit(RLIMIT_DATA , &reslimit); 00348 } 00349 00350 /* 00351 * should file size limits be waived? if the os limits us, this is 00352 * needed if we want to write a large archive 00353 */ 00354 if (getrlimit(RLIMIT_FSIZE , &reslimit) == 0){ 00355 reslimit.rlim_cur = reslimit.rlim_max; 00356 (void)setrlimit(RLIMIT_FSIZE , &reslimit); 00357 } 00358 00359 /* 00360 * increase the size the stack can grow to 00361 */ 00362 if (getrlimit(RLIMIT_STACK , &reslimit) == 0){ 00363 reslimit.rlim_cur = reslimit.rlim_max; 00364 (void)setrlimit(RLIMIT_STACK , &reslimit); 00365 } 00366 00367 /* 00368 * not really needed, but doesn't hurt 00369 */ 00370 if (getrlimit(RLIMIT_RSS , &reslimit) == 0){ 00371 reslimit.rlim_cur = reslimit.rlim_max; 00372 (void)setrlimit(RLIMIT_RSS , &reslimit); 00373 } 00374 #endif 00375 00376 /* 00377 * signal handling to reset stored directory times and modes. Since 00378 * we deal with broken pipes via failed writes we ignore it. We also 00379 * deal with any file size limit thorugh failed writes. Cpu time 00380 * limits are caught and a cleanup is forced. 00381 */ 00382 00383 if ((sigemptyset(&s_mask) < 0) || (sigaddset(&s_mask, SIGTERM) < 0) || 00384 (sigaddset(&s_mask,SIGINT) < 0)||(sigaddset(&s_mask,SIGHUP) < 0) || 00385 (sigaddset(&s_mask,SIGPIPE) < 0)||(sigaddset(&s_mask,SIGQUIT)<0) 00386 #if 0 00387 || (sigaddset(&s_mask,SIGXCPU) < 0)||(sigaddset(&s_mask,SIGXFSZ)<0) 00388 #endif 00389 ) { 00390 paxwarn(1, "Unable to set up signal mask"); 00391 return(-1); 00392 } 00393 memset(&n_hand, 0, sizeof n_hand); 00394 n_hand.sa_mask = s_mask; 00395 n_hand.sa_flags = 0; 00396 n_hand.sa_handler = sig_cleanup; 00397 00398 if ((sigaction(SIGHUP, &n_hand, &o_hand) < 0) && 00399 (o_hand.sa_handler == SIG_IGN) && 00400 (sigaction(SIGHUP, &o_hand, &o_hand) < 0)) 00401 goto out; 00402 00403 if ((sigaction(SIGTERM, &n_hand, &o_hand) < 0) && 00404 (o_hand.sa_handler == SIG_IGN) && 00405 (sigaction(SIGTERM, &o_hand, &o_hand) < 0)) 00406 goto out; 00407 00408 if ((sigaction(SIGINT, &n_hand, &o_hand) < 0) && 00409 (o_hand.sa_handler == SIG_IGN) && 00410 (sigaction(SIGINT, &o_hand, &o_hand) < 0)) 00411 goto out; 00412 00413 if ((sigaction(SIGQUIT, &n_hand, &o_hand) < 0) && 00414 (o_hand.sa_handler == SIG_IGN) && 00415 (sigaction(SIGQUIT, &o_hand, &o_hand) < 0)) 00416 goto out; 00417 00418 #if 0 00419 if ((sigaction(SIGXCPU, &n_hand, &o_hand) < 0) && 00420 (o_hand.sa_handler == SIG_IGN) && 00421 (sigaction(SIGXCPU, &o_hand, &o_hand) < 0)) 00422 goto out; 00423 #endif 00424 00425 n_hand.sa_handler = SIG_IGN; 00426 if ((sigaction(SIGPIPE, &n_hand, &o_hand) < 0) 00427 #if 0 00428 || (sigaction(SIGXFSZ, &n_hand, &o_hand) < 0) 00429 #endif 00430 ) 00431 00432 00433 goto out; 00434 return(0); 00435 00436 out: 00437 syswarn(1, errno, "Unable to set up signal handler"); 00438 return(-1); 00439 }
1.4.6