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