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