|
|
1.1 ! root 1: /* $Source: /newbits/usr/bin/pax/shipping/RCS/pax.c,v $ ! 2: * ! 3: * $Revision: 1.2 $ ! 4: * ! 5: * DESCRIPTION ! 6: * ! 7: * Pax is the archiver described in IEEE P1003.2. It is an archiver ! 8: * which understands both tar and cpio archives and has a new interface. ! 9: * ! 10: * SYNOPSIS ! 11: * ! 12: * pax -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...] ! 13: * pax -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...] ! 14: * pax -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]...] ! 15: * [-t device][-x format][pathname...] ! 16: * pax -r -w [-ilmopuvy][-s replstr][pathname...] directory ! 17: * ! 18: * DESCRIPTION ! 19: * ! 20: * PAX - POSIX conforming tar and cpio archive handler. This ! 21: * program implements POSIX conformant versions of tar, cpio and pax ! 22: * archive handlers for UNIX. These handlers have defined befined ! 23: * by the IEEE P1003.2 commitee. ! 24: * ! 25: * COMPILATION ! 26: * ! 27: * A number of different compile time configuration options are ! 28: * available, please see the Makefile and config.h for more details. ! 29: * ! 30: * AUTHOR ! 31: * ! 32: * Mark H. Colburn, NAPS International ([email protected]) ! 33: * ! 34: * ! 35: * Sponsored by The USENIX Association for public distribution. ! 36: * ! 37: * Copyright (c) 1989 Mark H. Colburn. ! 38: * All rights reserved. ! 39: * ! 40: * Redistribution and use in source and binary forms are permitted ! 41: * provided that the above copyright notice is duplicated in all such ! 42: * forms and that any documentation, advertising materials, and other ! 43: * materials related to such distribution and use acknowledge that the ! 44: * software was developed * by Mark H. Colburn and sponsored by The ! 45: * USENIX Association. ! 46: * ! 47: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 48: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 49: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 50: * ! 51: * $Log: pax.c,v $ ! 52: * Revision 1.2 92/06/11 07:51:11 bin ! 53: * vlad: added recognition of ustar AND tar ! 54: * ! 55: * Revision 1.1 91/02/05 11:58:29 bin ! 56: * Initial revision ! 57: * ! 58: * Revision 1.2 89/02/12 10:05:17 mark ! 59: * 1.2 release fixes ! 60: * ! 61: * Revision 1.1 88/12/23 18:02:23 mark ! 62: * Initial revision ! 63: * ! 64: */ ! 65: ! 66: #ifndef lint ! 67: static char *ident = "$Id: pax.c,v 1.2 92/06/11 07:51:11 bin Exp Locker: bin $"; ! 68: static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n"; ! 69: #endif /* ! lint */ ! 70: ! 71: ! 72: /* Headers */ ! 73: ! 74: #define NO_EXTERN ! 75: #include "pax.h" ! 76: ! 77: ! 78: /* Globally Available Identifiers */ ! 79: ! 80: char *ar_file; /* File containing name of archive */ ! 81: char *bufend; /* End of data within archive buffer */ ! 82: char *bufstart; /* Archive buffer */ ! 83: char *bufidx; /* Archive buffer index */ ! 84: char *myname; /* name of executable (argv[0]) */ ! 85: char **n_argv; /* Argv used by name routines */ ! 86: int n_argc; /* Argc used by name routines */ ! 87: int archivefd; /* Archive file descriptor */ ! 88: int blocking; /* Size of each block, in records */ ! 89: int gid; /* Group ID */ ! 90: int head_standard; /* true if archive is POSIX format */ ! 91: int ar_interface; /* defines interface we are using */ ! 92: int ar_format; /* defines current archve format */ ! 93: int mask; /* File creation mask */ ! 94: int ttyf; /* For interactive queries */ ! 95: int uid; /* User ID */ ! 96: int names_from_stdin; /* names for files are from stdin */ ! 97: OFFSET total; /* Total number of bytes transferred */ ! 98: short f_access_time; /* Reset access times of input files */ ! 99: short areof; /* End of input volume reached */ ! 100: short f_dir_create; /* Create missing directories */ ! 101: short f_append; /* Add named files to end of archive */ ! 102: short f_create; /* create a new archive */ ! 103: short f_extract; /* Extract named files from archive */ ! 104: short f_follow_links; /* follow symbolic links */ ! 105: short f_interactive; /* Interactivly extract files */ ! 106: short f_linksleft; /* Report on unresolved links */ ! 107: short f_list; /* List files on the archive */ ! 108: short f_modified; /* Don't restore modification times */ ! 109: short f_verbose; /* Turn on verbose mode */ ! 110: short f_link; /* link files where possible */ ! 111: short f_owner; /* extract files as the user */ ! 112: short f_pass; /* pass files between directories */ ! 113: short f_disposition; /* ask for file disposition */ ! 114: short f_reverse_match; /* Reverse sense of pattern match */ ! 115: short f_mtime; /* Retain file modification time */ ! 116: short f_unconditional; /* Copy unconditionally */ ! 117: time_t now = 0; /* Current time */ ! 118: uint arvolume; /* Volume number */ ! 119: uint blocksize = BLOCKSIZE; /* Archive block size */ ! 120: FILE *msgfile; /* message outpu file stdout/stderr */ ! 121: Replstr *rplhead = (Replstr *)NULL; /* head of replstr list */ ! 122: Replstr *rpltail; /* pointer to tail of replstr list */ ! 123: ! 124: ! 125: /* Function Prototypes */ ! 126: ! 127: #if __STDC__ ! 128: ! 129: static void usage(void); ! 130: static OFFSET pax_optsize(char *); ! 131: ! 132: #else /* !__STDC__ */ ! 133: ! 134: static void usage(); ! 135: static OFFSET pax_optsize(); ! 136: ! 137: #endif /* __STDC__ */ ! 138: ! 139: ! 140: /* main - main routine for handling all archive formats. ! 141: * ! 142: * DESCRIPTION ! 143: * ! 144: * Set up globals and call the proper interface as specified by the user. ! 145: * ! 146: * PARAMETERS ! 147: * ! 148: * int argc - count of user supplied arguments ! 149: * char **argv - user supplied arguments ! 150: * ! 151: * RETURNS ! 152: * ! 153: * Returns an exit code of 0 to the parent process. ! 154: */ ! 155: ! 156: #if __STDC__ ! 157: ! 158: int main(int argc, char **argv) ! 159: ! 160: #else ! 161: ! 162: int main(argc, argv) ! 163: int argc; ! 164: char **argv; ! 165: ! 166: #endif ! 167: { ! 168: /* strip the pathname off of the name of the executable */ ! 169: if ((myname = strrchr(argv[0], '/')) != (char *)NULL) { ! 170: myname++; ! 171: } else { ! 172: myname = argv[0]; ! 173: } ! 174: ! 175: /* set upt for collecting other command line arguments */ ! 176: name_init(argc, argv); ! 177: ! 178: /* get all our necessary information */ ! 179: mask = umask(0); ! 180: uid = getuid(); ! 181: gid = getgid(); ! 182: now = time((time_t *) 0); ! 183: ! 184: /* open terminal for interactive queries */ ! 185: ttyf = open_tty(); ! 186: ! 187: if (strcmp(myname, "ustar")==0 || strcmp(myname, "tar")==0) { ! 188: do_tar(argc, argv); ! 189: } else if (strcmp(myname, "cpio")==0) { ! 190: do_cpio(argc, argv); ! 191: } else { ! 192: do_pax(argc, argv); ! 193: } ! 194: exit(0); ! 195: /* NOTREACHED */ ! 196: } ! 197: ! 198: ! 199: /* do_pax - provide a PAX conformant user interface for archive handling ! 200: * ! 201: * DESCRIPTION ! 202: * ! 203: * Process the command line parameters given, doing some minimal sanity ! 204: * checking, and then launch the specified archiving functions. ! 205: * ! 206: * PARAMETERS ! 207: * ! 208: * int ac - A count of arguments in av. Should be passed argc ! 209: * from main ! 210: * char **av - A pointer to an argument list. Should be passed ! 211: * argv from main ! 212: * ! 213: * RETURNS ! 214: * ! 215: * Normally returns 0. If an error occurs, -1 is returned ! 216: * and state is set to reflect the error. ! 217: * ! 218: */ ! 219: ! 220: #if __STDC__ ! 221: ! 222: int do_pax(int ac, char **av) ! 223: ! 224: #else ! 225: ! 226: int do_pax(ac, av) ! 227: int ac; /* argument counter */ ! 228: char **av; /* arguments */ ! 229: ! 230: #endif ! 231: { ! 232: int c; ! 233: char *dirname; ! 234: Stat st; ! 235: ! 236: /* default input/output file for PAX is STDIN/STDOUT */ ! 237: ar_file = "-"; ! 238: ! 239: /* ! 240: * set up the flags to reflect the default pax inteface. Unfortunately ! 241: * the pax interface has several options which are completely opposite ! 242: * of the ustar and/or cpio interfaces... ! 243: */ ! 244: f_unconditional = 1; ! 245: f_mtime = 1; ! 246: f_dir_create = 1; ! 247: f_list = 1; ! 248: blocksize = 0; ! 249: blocking = 0; ! 250: ar_interface = PAX; ! 251: ar_format = TAR; /* default interface if none given for -w */ ! 252: msgfile=stdout; ! 253: ! 254: while ((c = getopt(ac, av, "ab:cdf:ilmoprs:t:uvwx:y")) != EOF) { ! 255: switch (c) { ! 256: case 'a': ! 257: f_append = 1; ! 258: f_list = 0; ! 259: break; ! 260: case 'b': ! 261: if ((blocksize = pax_optsize(optarg)) == 0) { ! 262: fatal("Bad block size"); ! 263: } ! 264: break; ! 265: case 'c': ! 266: f_reverse_match = 1; ! 267: break; ! 268: case 'd': ! 269: f_dir_create = 0; ! 270: break; ! 271: case 'f': ! 272: if (blocksize == 0) { ! 273: blocking = 1; ! 274: blocksize = 1 * BLOCKSIZE; ! 275: } ! 276: ar_file = optarg; ! 277: break; ! 278: case 'i': ! 279: f_interactive = 1; ! 280: break; ! 281: case 'l': ! 282: f_link = 1; ! 283: break; ! 284: case 'm': ! 285: f_mtime = 0; ! 286: break; ! 287: case 'o': ! 288: f_owner = 1; ! 289: break; ! 290: case 'p': ! 291: f_access_time = 1; ! 292: break; ! 293: case 'r': ! 294: if (f_create) { ! 295: f_create = 0; ! 296: f_pass = 1; ! 297: } else { ! 298: f_list = 0; ! 299: f_extract = 1; ! 300: } ! 301: msgfile=stderr; ! 302: break; ! 303: case 's': ! 304: add_replstr(optarg); ! 305: break; ! 306: case 't': ! 307: if (blocksize == 0) { ! 308: blocking = 1; ! 309: blocksize = 10 * BLOCKSIZE; ! 310: } ! 311: ar_file = optarg; ! 312: break; ! 313: case 'u': ! 314: f_unconditional = 1; ! 315: break; ! 316: case 'v': ! 317: f_verbose = 1; ! 318: break; ! 319: case 'w': ! 320: if (f_extract) { ! 321: f_extract = 0; ! 322: f_pass = 1; ! 323: } else { ! 324: f_list = 0; ! 325: f_create = 1; ! 326: } ! 327: msgfile=stderr; ! 328: break; ! 329: case 'x': ! 330: if (strcmp(optarg, "ustar") == 0) { ! 331: ar_format = TAR; ! 332: } else if (strcmp(optarg, "cpio") == 0) { ! 333: ar_format = CPIO; ! 334: } else { ! 335: usage(); ! 336: } ! 337: break; ! 338: case 'y': ! 339: f_disposition = 1; ! 340: break; ! 341: default: ! 342: usage(); ! 343: } ! 344: } ! 345: ! 346: if (blocksize == 0) { ! 347: blocking = 1; ! 348: blocksize = blocking * BLOCKSIZE; ! 349: } ! 350: buf_allocate((OFFSET) blocksize); ! 351: ! 352: if (f_extract || f_list) { ! 353: open_archive(AR_READ); ! 354: get_archive_type(); ! 355: read_archive(); ! 356: } else if (f_create) { ! 357: if (optind >= n_argc) { ! 358: names_from_stdin++; /* args from stdin */ ! 359: } ! 360: open_archive(AR_WRITE); ! 361: create_archive(); ! 362: } else if (f_append) { ! 363: open_archive(AR_APPEND); ! 364: get_archive_type(); ! 365: append_archive(); ! 366: } else if (f_pass && optind < n_argc) { ! 367: dirname = n_argv[--n_argc]; ! 368: if (LSTAT(dirname, &st) < 0) { ! 369: fatal(strerror()); ! 370: } ! 371: if ((st.sb_mode & S_IFMT) != S_IFDIR) { ! 372: fatal("Not a directory"); ! 373: } ! 374: if (optind >= n_argc) { ! 375: names_from_stdin++; /* args from stdin */ ! 376: } ! 377: pass(dirname); ! 378: } else { ! 379: usage(); ! 380: } ! 381: ! 382: return (0); ! 383: } ! 384: ! 385: ! 386: /* get_archive_type - determine input archive type from archive header ! 387: * ! 388: * DESCRIPTION ! 389: * ! 390: * reads the first block of the archive and determines the archive ! 391: * type from the data. If the archive type cannot be determined, ! 392: * processing stops, and a 1 is returned to the caller. If verbose ! 393: * mode is on, then the archive type will be printed on the standard ! 394: * error device as it is determined. ! 395: * ! 396: * FIXME ! 397: * ! 398: * be able to understand TAR and CPIO magic numbers ! 399: */ ! 400: ! 401: #if __STDC__ ! 402: ! 403: void get_archive_type(void) ! 404: ! 405: #else ! 406: ! 407: void get_archive_type() ! 408: ! 409: #endif ! 410: { ! 411: if (ar_read() != 0) { ! 412: fatal("Unable to determine archive type."); ! 413: } ! 414: if (strncmp(bufstart, "070707", 6) == 0) { ! 415: ar_format = CPIO; ! 416: if (f_verbose) { ! 417: fputs("CPIO format archive\n", stderr); ! 418: } ! 419: } else if (strncmp(&bufstart[257], "ustar", 5) == 0) { ! 420: ar_format = TAR; ! 421: if (f_verbose) { ! 422: fputs("USTAR format archive\n", stderr); ! 423: } ! 424: } else { ! 425: ar_format = TAR; ! 426: if (f_verbose) { ! 427: fputs("TAR(v7) format archive\n", stderr); ! 428: } ! 429: } ! 430: } ! 431: ! 432: ! 433: /* pax_optsize - interpret a size argument ! 434: * ! 435: * DESCRIPTION ! 436: * ! 437: * Recognizes suffixes for blocks (512-bytes), k-bytes and megabytes. ! 438: * Also handles simple expressions containing '+' for addition. ! 439: * ! 440: * PARAMETERS ! 441: * ! 442: * char *str - A pointer to the string to interpret ! 443: * ! 444: * RETURNS ! 445: * ! 446: * Normally returns the value represented by the expression in the ! 447: * the string. ! 448: * ! 449: * ERRORS ! 450: * ! 451: * If the string cannot be interpretted, the program will fail, since ! 452: * the buffering will be incorrect. ! 453: * ! 454: */ ! 455: ! 456: #if __STDC__ ! 457: ! 458: static OFFSET pax_optsize(char *str) ! 459: ! 460: #else ! 461: ! 462: static OFFSET pax_optsize(str) ! 463: char *str; /* pointer to string to interpret */ ! 464: ! 465: #endif ! 466: { ! 467: char *idx; ! 468: OFFSET number; /* temporary storage for current number */ ! 469: OFFSET result; /* cumulative total to be returned to caller */ ! 470: ! 471: result = 0; ! 472: idx = str; ! 473: for (;;) { ! 474: number = 0; ! 475: while (*idx >= '0' && *idx <= '9') ! 476: number = number * 10 + *idx++ - '0'; ! 477: switch (*idx++) { ! 478: case 'b': ! 479: result += number * 512L; ! 480: continue; ! 481: case 'k': ! 482: result += number * 1024L; ! 483: continue; ! 484: case 'm': ! 485: result += number * 1024L * 1024L; ! 486: continue; ! 487: case '+': ! 488: result += number; ! 489: continue; ! 490: case '\0': ! 491: result += number; ! 492: break; ! 493: default: ! 494: break; ! 495: } ! 496: break; ! 497: } ! 498: if (*--idx) { ! 499: fatal("Unrecognizable value"); ! 500: } ! 501: return (result); ! 502: } ! 503: ! 504: ! 505: /* usage - print a helpful message and exit ! 506: * ! 507: * DESCRIPTION ! 508: * ! 509: * Usage prints out the usage message for the PAX interface and then ! 510: * exits with a non-zero termination status. This is used when a user ! 511: * has provided non-existant or incompatible command line arguments. ! 512: * ! 513: * RETURNS ! 514: * ! 515: * Returns an exit status of 1 to the parent process. ! 516: * ! 517: */ ! 518: ! 519: #if __STDC__ ! 520: ! 521: static void usage(void) ! 522: ! 523: #else ! 524: ! 525: static void usage() ! 526: ! 527: #endif ! 528: { ! 529: fprintf(stderr, "Usage: %s -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n", ! 530: myname); ! 531: fprintf(stderr, " %s -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n", ! 532: myname); ! 533: fprintf(stderr, " %s -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]\n [-t device] [-x format] [pathname...]\n", ! 534: myname); ! 535: fprintf(stderr, " %s -r -w [-ilmopuvy] [-s replstr] [pathname...] directory\n", ! 536: myname); ! 537: exit(1); ! 538: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.