|
|
1.1 ! root 1: # This is a shell archive. Remove anything before this line, then unpack ! 2: # it by saving it into a file and typing "sh file". To overwrite existing ! 3: # files, type "sh file -c". You can also feed this as standard input via ! 4: # unshar, or by typing "sh <file", e.g.. If this archive is complete, you ! 5: # will see the following message at the end: ! 6: # "End of archive 3 (of 6)." ! 7: # Contents: fileio.c namelist.c pax.c pax.h tar.c ! 8: # Wrapped by mark@jhereg on Tue Dec 27 19:37:45 1988 ! 9: PATH=/bin:/usr/bin:/usr/ucb ; export PATH ! 10: if test -f fileio.c -a "${1}" != "-c" ; then ! 11: echo shar: Will not over-write existing file \"fileio.c\" ! 12: else ! 13: echo shar: Extracting \"fileio.c\" \(10596 characters\) ! 14: sed "s/^X//" >fileio.c <<'END_OF_fileio.c' ! 15: X/* $Source: /u/mark/src/pax/RCS/fileio.c,v $ ! 16: X * ! 17: X * $Revision: 1.1 $ ! 18: X * ! 19: X * fileio.c - file I/O functions for all archive interfaces ! 20: X * ! 21: X * DESCRIPTION ! 22: X * ! 23: X * These function all do I/O of some form or another. They are ! 24: X * grouped here mainly for convienence. ! 25: X * ! 26: X * AUTHOR ! 27: X * ! 28: X * Mark H. Colburn, NAPS International ([email protected]) ! 29: X * ! 30: X * Sponsored by The USENIX Association for public distribution. ! 31: X * ! 32: X * Copyright (c) 1989 Mark H. Colburn. ! 33: X * All rights reserved. ! 34: X * ! 35: X * Redistribution and use in source and binary forms are permitted ! 36: X * provided that the above copyright notice is duplicated in all such ! 37: X * forms and that any documentation, advertising materials, and other ! 38: X * materials related to such distribution and use acknowledge that the ! 39: X * software was developed * by Mark H. Colburn and sponsored by The ! 40: X * USENIX Association. ! 41: X * ! 42: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 43: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 44: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 45: X * ! 46: X * $Log: fileio.c,v $ ! 47: X * Revision 1.1 88/12/23 18:02:09 mark ! 48: X * Initial revision ! 49: X * ! 50: X */ ! 51: X ! 52: X#ifndef lint ! 53: Xstatic char *ident = "$Id: fileio.c,v 1.1 88/12/23 18:02:09 mark Rel $"; ! 54: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n"; ! 55: X#endif /* ! lint */ ! 56: X ! 57: X ! 58: X/* Headers */ ! 59: X ! 60: X#include "pax.h" ! 61: X ! 62: X ! 63: X/* open_archive - open an archive file. ! 64: X * ! 65: X * DESCRIPTION ! 66: X * ! 67: X * Open_archive will open an archive file for reading or writing, ! 68: X * setting the proper file mode, depending on the "mode" passed to ! 69: X * it. All buffer pointers are reset according to the mode ! 70: X * specified. ! 71: X * ! 72: X * PARAMETERS ! 73: X * ! 74: X * int mode - specifies whether we are reading or writing. ! 75: X * ! 76: X * RETURNS ! 77: X * ! 78: X * Returns a zero if successfull, or -1 if an error occured during ! 79: X * the open. ! 80: X */ ! 81: X ! 82: X#ifdef __STDC__ ! 83: X ! 84: Xint open_archive(int mode) ! 85: X ! 86: X#else ! 87: X ! 88: Xint open_archive(mode) ! 89: Xint mode; ! 90: X ! 91: X#endif ! 92: X{ ! 93: X if (ar_file[0] == '-' && ar_file[1] == '\0') { ! 94: X if (mode == AR_READ) { ! 95: X archivefd = STDIN; ! 96: X bufend = bufidx = bufstart; ! 97: X } else { ! 98: X archivefd = STDOUT; ! 99: X } ! 100: X } else if (mode == AR_READ) { ! 101: X archivefd = open(ar_file, O_RDONLY | O_BINARY); ! 102: X bufend = bufidx = bufstart; /* set up for initial read */ ! 103: X } else if (mode == AR_WRITE) { ! 104: X archivefd = open(ar_file, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0666); ! 105: X } else if (mode == AR_APPEND) { ! 106: X archivefd = open(ar_file, O_RDWR | O_BINARY, 0666); ! 107: X bufend = bufidx = bufstart; /* set up for initial read */ ! 108: X } ! 109: X ! 110: X if (archivefd < 0) { ! 111: X warnarch(syserr(), (OFFSET) 0); ! 112: X return (-1); ! 113: X } ! 114: X ++arvolume; ! 115: X return (0); ! 116: X} ! 117: X ! 118: X ! 119: X/* close_archive - close the archive file ! 120: X * ! 121: X * DESCRIPTION ! 122: X * ! 123: X * Closes the current archive and resets the archive end of file ! 124: X * marker. ! 125: X */ ! 126: X ! 127: X#ifdef __STDC__ ! 128: X ! 129: Xvoid close_archive(void) ! 130: X ! 131: X#else ! 132: X ! 133: Xvoid close_archive() ! 134: X ! 135: X#endif ! 136: X{ ! 137: X if (archivefd != STDIN && archivefd != STDOUT) { ! 138: X close(archivefd); ! 139: X } ! 140: X areof = 0; ! 141: X} ! 142: X ! 143: X ! 144: X/* openo - open an output file ! 145: X * ! 146: X * DESCRIPTION ! 147: X * ! 148: X * Openo opens the named file for output. The file mode and type are ! 149: X * set based on the values stored in the stat structure for the file. ! 150: X * If the file is a special file, then no data will be written, the ! 151: X * file/directory/Fifo, etc., will just be created. Appropriate ! 152: X * permission may be required to create special files. ! 153: X * ! 154: X * PARAMETERS ! 155: X * ! 156: X * char *name - The name of the file to create ! 157: X * Stat *asb - Stat structure for the file ! 158: X * Link *linkp; - pointer to link chain for this file ! 159: X * int ispass - true if we are operating in "pass" mode ! 160: X * ! 161: X * RETURNS ! 162: X * ! 163: X * Returns the output file descriptor, 0 if no data is required or -1 ! 164: X * if unsuccessful. Note that UNIX open() will never return 0 because ! 165: X * the standard input is in use. ! 166: X */ ! 167: X ! 168: X#ifdef __STDC__ ! 169: X ! 170: Xint openo(char *name, Stat *asb, Link *linkp, int ispass) ! 171: X ! 172: X#else ! 173: X ! 174: Xint openo(name, asb, linkp, ispass) ! 175: Xchar *name; ! 176: XStat *asb; ! 177: XLink *linkp; ! 178: Xint ispass; ! 179: X ! 180: X#endif ! 181: X{ ! 182: X int exists; ! 183: X int fd; ! 184: X ushort perm; ! 185: X ushort operm = 0; ! 186: X Stat osb; ! 187: X#ifdef S_IFLNK ! 188: X int ssize; ! 189: X char sname[PATH_MAX + 1]; ! 190: X#endif /* S_IFLNK */ ! 191: X ! 192: X if (exists = (LSTAT(name, &osb) == 0)) { ! 193: X if (ispass && osb.sb_ino == asb->sb_ino && osb.sb_dev == asb->sb_dev) { ! 194: X warn(name, "Same file"); ! 195: X return (-1); ! 196: X } else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT)) { ! 197: X operm = osb.sb_mode & S_IPERM; ! 198: X } else if (REMOVE(name, &osb) < 0) { ! 199: X warn(name, syserr()); ! 200: X return (-1); ! 201: X } else { ! 202: X exists = 0; ! 203: X } ! 204: X } ! 205: X if (linkp) { ! 206: X if (exists) { ! 207: X if (asb->sb_ino == osb.sb_ino && asb->sb_dev == osb.sb_dev) { ! 208: X return (0); ! 209: X } else if (unlink(name) < 0) { ! 210: X warn(name, syserr()); ! 211: X return (-1); ! 212: X } else { ! 213: X exists = 0; ! 214: X } ! 215: X } ! 216: X if (link(linkp->l_name, name) != 0) { ! 217: X if (errno == ENOENT) { ! 218: X if (f_create_dirs) { ! 219: X if (dirneed(name) != 0 || ! 220: X link(linkp->l_name, name) != 0) { ! 221: X warn(name, syserr()); ! 222: X return (-1); ! 223: X } ! 224: X } else { ! 225: X warn(name, ! 226: X "Directories are not being created (-d option)"); ! 227: X } ! 228: X return(0); ! 229: X } else if (errno != EXDEV) { ! 230: X warn(name, syserr()); ! 231: X return (-1); ! 232: X } ! 233: X } else { ! 234: X return(0); ! 235: X } ! 236: X } ! 237: X perm = asb->sb_mode & S_IPERM; ! 238: X switch (asb->sb_mode & S_IFMT) { ! 239: X case S_IFBLK: ! 240: X case S_IFCHR: ! 241: X fd = 0; ! 242: X if (exists) { ! 243: X if (asb->sb_rdev == osb.sb_rdev) { ! 244: X if (perm != operm && chmod(name, (int) perm) < 0) { ! 245: X warn(name, syserr()); ! 246: X return (-1); ! 247: X } else { ! 248: X break; ! 249: X } ! 250: X } else if (REMOVE(name, &osb) < 0) { ! 251: X warn(name, syserr()); ! 252: X return (-1); ! 253: X } else { ! 254: X exists = 0; ! 255: X } ! 256: X } ! 257: X if (mknod(name, (int) asb->sb_mode, (int) asb->sb_rdev) < 0) { ! 258: X if (errno == ENOENT) { ! 259: X if (f_create_dirs) { ! 260: X if (dirneed(name) < 0 || mknod(name, (int) asb->sb_mode, ! 261: X (int) asb->sb_rdev) < 0) { ! 262: X warn(name, syserr()); ! 263: X return (-1); ! 264: X } ! 265: X } else { ! 266: X warn(name, "Directories are not being created (-d option)"); ! 267: X } ! 268: X } else { ! 269: X warn(name, syserr()); ! 270: X return (-1); ! 271: X } ! 272: X } ! 273: X return(0); ! 274: X break; ! 275: X case S_IFDIR: ! 276: X if (exists) { ! 277: X if (perm != operm && chmod(name, (int) perm) < 0) { ! 278: X warn(name, syserr()); ! 279: X return (-1); ! 280: X } ! 281: X } else if (f_create_dirs) { ! 282: X if (dirmake(name, asb) < 0 || dirneed(name) < 0) { ! 283: X warn(name, syserr()); ! 284: X return (-1); ! 285: X } ! 286: X } else { ! 287: X warn(name, "Directories are not being created (-d option)"); ! 288: X } ! 289: X return (0); ! 290: X#ifdef S_IFIFO ! 291: X case S_IFIFO: ! 292: X fd = 0; ! 293: X if (exists) { ! 294: X if (perm != operm && chmod(name, (int) perm) < 0) { ! 295: X warn(name, syserr()); ! 296: X return (-1); ! 297: X } ! 298: X } else if (mknod(name, (int) asb->sb_mode, 0) < 0) { ! 299: X if (errno == ENOENT) { ! 300: X if (f_create_dirs) { ! 301: X if (dirneed(name) < 0 ! 302: X || mknod(name, (int) asb->sb_mode, 0) < 0) { ! 303: X warn(name, syserr()); ! 304: X return (-1); ! 305: X } ! 306: X } else { ! 307: X warn(name, "Directories are not being created (-d option)"); ! 308: X } ! 309: X } else { ! 310: X warn(name, syserr()); ! 311: X return (-1); ! 312: X } ! 313: X } ! 314: X return(0); ! 315: X break; ! 316: X#endif /* S_IFIFO */ ! 317: X#ifdef S_IFLNK ! 318: X case S_IFLNK: ! 319: X if (exists) { ! 320: X if ((ssize = readlink(name, sname, sizeof(sname))) < 0) { ! 321: X warn(name, syserr()); ! 322: X return (-1); ! 323: X } else if (strncmp(sname, asb->sb_link, ssize) == 0) { ! 324: X return (0); ! 325: X } else if (REMOVE(name, &osb) < 0) { ! 326: X warn(name, syserr()); ! 327: X return (-1); ! 328: X } else { ! 329: X exists = 0; ! 330: X } ! 331: X } ! 332: X if (symlink(asb->sb_link, name) < 0) { ! 333: X if (errno == ENOENT) { ! 334: X if (f_create_dirs) { ! 335: X if (dirneed(name) < 0 || symlink(asb->sb_link, name) < 0) { ! 336: X warn(name, syserr()); ! 337: X return (-1); ! 338: X } ! 339: X } else { ! 340: X warn(name, "Directories are not being created (-d option)"); ! 341: X } ! 342: X } else { ! 343: X warn(name, syserr()); ! 344: X return (-1); ! 345: X } ! 346: X } ! 347: X return (0); /* Can't chown()/chmod() a symbolic link */ ! 348: X#endif /* S_IFLNK */ ! 349: X case S_IFREG: ! 350: X if (exists) { ! 351: X if (!f_unconditional && osb.sb_mtime > asb->sb_mtime) { ! 352: X warn(name, "Newer file exists"); ! 353: X return (-1); ! 354: X } else if (unlink(name) < 0) { ! 355: X warn(name, syserr()); ! 356: X return (-1); ! 357: X } else { ! 358: X exists = 0; ! 359: X } ! 360: X } ! 361: X if ((fd = creat(name, (int) perm)) < 0) { ! 362: X if (errno == ENOENT) { ! 363: X if (f_create_dirs) { ! 364: X if (dirneed(name) < 0 || ! 365: X (fd = creat(name, (int) perm)) < 0) { ! 366: X warn(name, syserr()); ! 367: X return (-1); ! 368: X } ! 369: X } else { ! 370: X /* ! 371: X * the file requires a directory which does not exist ! 372: X * and which the user does not want created, so skip ! 373: X * the file... ! 374: X */ ! 375: X warn(name, "Directories are not being created (-d option)"); ! 376: X return(0); ! 377: X } ! 378: X } else { ! 379: X warn(name, syserr()); ! 380: X return (-1); ! 381: X } ! 382: X } ! 383: X break; ! 384: X default: ! 385: X warn(name, "Unknown filetype"); ! 386: X return (-1); ! 387: X } ! 388: X if (f_owner) { ! 389: X if (!exists || asb->sb_uid != osb.sb_uid || asb->sb_gid != osb.sb_gid) { ! 390: X chown(name, (int) asb->sb_uid, (int) asb->sb_gid); ! 391: X } ! 392: X } ! 393: X return (fd); ! 394: X} ! 395: X ! 396: X ! 397: X/* openi - open the next input file ! 398: X * ! 399: X * DESCRIPTION ! 400: X * ! 401: X * Openi will attempt to open the next file for input. If the file is ! 402: X * a special file, such as a directory, FIFO, link, character- or ! 403: X * block-special file, then the file size field of the stat structure ! 404: X * is zeroed to make sure that no data is written out for the file. ! 405: X * If the file is a special file, then a file descriptor of 0 is ! 406: X * returned to the caller, which is handled specially. If the file ! 407: X * is a regular file, then the file is opened and a file descriptor ! 408: X * to the open file is returned to the caller. ! 409: X * ! 410: X * PARAMETERS ! 411: X * ! 412: X * char *name - pointer to the name of the file to open ! 413: X * Stat *asb - pointer to the stat block for the file to open ! 414: X * ! 415: X * RETURNS ! 416: X * ! 417: X * Returns a file descriptor, 0 if no data exists, or -1 at EOF. This ! 418: X * kludge works because standard input is in use, preventing open() from ! 419: X * returning zero. ! 420: X */ ! 421: X ! 422: X#ifdef __STDC__ ! 423: X ! 424: Xint openi(char *name, Stat *asb) ! 425: X ! 426: X#else ! 427: X ! 428: Xint openi(name, asb) ! 429: Xchar *name; /* name of file to open */ ! 430: XStat *asb; /* pointer to stat structure for file */ ! 431: X ! 432: X#endif ! 433: X{ ! 434: X int fd; ! 435: X ! 436: X switch (asb->sb_mode & S_IFMT) { ! 437: X case S_IFDIR: ! 438: X asb->sb_nlink = 1; ! 439: X asb->sb_size = 0; ! 440: X return (0); ! 441: X#ifdef S_IFLNK ! 442: X case S_IFLNK: ! 443: X if ((asb->sb_size = readlink(name, ! 444: X asb->sb_link, sizeof(asb->sb_link) - 1)) < 0) { ! 445: X warn(name, syserr()); ! 446: X return(0); ! 447: X } ! 448: X asb->sb_link[asb->sb_size] = '\0'; ! 449: X return (0); ! 450: X#endif /* S_IFLNK */ ! 451: X case S_IFREG: ! 452: X if (asb->sb_size == 0) { ! 453: X return (0); ! 454: X } ! 455: X if ((fd = open(name, O_RDONLY | O_BINARY)) < 0) { ! 456: X warn(name, syserr()); ! 457: X } ! 458: X return (fd); ! 459: X default: ! 460: X asb->sb_size = 0; ! 461: X return (0); ! 462: X } ! 463: X} ! 464: END_OF_fileio.c ! 465: if test 10596 -ne `wc -c <fileio.c`; then ! 466: echo shar: \"fileio.c\" unpacked with wrong size! ! 467: fi ! 468: # end of overwriting check ! 469: fi ! 470: if test -f namelist.c -a "${1}" != "-c" ; then ! 471: echo shar: Will not over-write existing file \"namelist.c\" ! 472: else ! 473: echo shar: Extracting \"namelist.c\" \(11056 characters\) ! 474: sed "s/^X//" >namelist.c <<'END_OF_namelist.c' ! 475: X/* $Source: /u/mark/src/pax/RCS/namelist.c,v $ ! 476: X * ! 477: X * $Revision: 1.1 $ ! 478: X * ! 479: X * namelist.c - track filenames given as arguments to tar/cpio/pax ! 480: X * ! 481: X * DESCRIPTION ! 482: X * ! 483: X * Arguments may be regular expressions, therefore all agurments will ! 484: X * be treated as if they were regular expressions, even if they are ! 485: X * not. ! 486: X * ! 487: X * AUTHOR ! 488: X * ! 489: X * Mark H. Colburn, NAPS International ([email protected]) ! 490: X * ! 491: X * Sponsored by The USENIX Association for public distribution. ! 492: X * ! 493: X * Copyright (c) 1989 Mark H. Colburn. ! 494: X * All rights reserved. ! 495: X * ! 496: X * Redistribution and use in source and binary forms are permitted ! 497: X * provided that the above copyright notice is duplicated in all such ! 498: X * forms and that any documentation, advertising materials, and other ! 499: X * materials related to such distribution and use acknowledge that the ! 500: X * software was developed * by Mark H. Colburn and sponsored by The ! 501: X * USENIX Association. ! 502: X * ! 503: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 504: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 505: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 506: X * ! 507: X * $Log: namelist.c,v $ ! 508: X * Revision 1.1 88/12/23 18:02:17 mark ! 509: X * Initial revision ! 510: X * ! 511: X */ ! 512: X ! 513: X#ifndef lint ! 514: Xstatic char *ident = "$Id: namelist.c,v 1.1 88/12/23 18:02:17 mark Rel $"; ! 515: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n"; ! 516: X#endif /* ! lint */ ! 517: X ! 518: X ! 519: X/* Headers */ ! 520: X ! 521: X#include "pax.h" ! 522: X ! 523: X ! 524: X/* Type Definitions */ ! 525: X ! 526: X/* ! 527: X * Structure for keeping track of filenames and lists thereof. ! 528: X */ ! 529: Xstruct nm_list { ! 530: X struct nm_list *next; ! 531: X short length; /* cached strlen(name) */ ! 532: X char found; /* A matching file has been found */ ! 533: X char firstch; /* First char is literally matched */ ! 534: X char regexp; /* regexp pattern for item */ ! 535: X char name[1]; /* name of file or rexexp */ ! 536: X}; ! 537: X ! 538: Xstruct dirinfo { ! 539: X char dirname[PATH_MAX + 1]; /* name of directory */ ! 540: X OFFSET where; /* current location in directory */ ! 541: X struct dirinfo *next; ! 542: X}; ! 543: X ! 544: X ! 545: X/* Function Prototypes */ ! 546: X ! 547: X#ifndef __STDC__ ! 548: X ! 549: Xstatic void pushdir(); ! 550: Xstatic struct dirinfo *popdir(); ! 551: X ! 552: X#else ! 553: X ! 554: Xstatic void pushdir(struct dirinfo *info); ! 555: Xstatic struct dirinfo *popdir(void); ! 556: X ! 557: X#endif ! 558: X ! 559: X ! 560: X/* Internal Identifiers */ ! 561: X ! 562: Xstatic struct nm_list *namelast; /* Points to last name in list */ ! 563: Xstatic struct nm_list *namelist; /* Points to first name in list */ ! 564: X ! 565: X ! 566: X/* addname - add a name to the namelist. ! 567: X * ! 568: X * DESCRIPTION ! 569: X * ! 570: X * Addname adds the name given to the name list. Memory for the ! 571: X * namelist structure is dynamically allocated. If the space for ! 572: X * the structure cannot be allocated, then the program will exit ! 573: X * the an out of memory error message and a non-zero return code ! 574: X * will be returned to the caller. ! 575: X * ! 576: X * PARAMETERS ! 577: X * ! 578: X * char *name - A pointer to the name to add to the list ! 579: X */ ! 580: X ! 581: X#ifdef __STDC__ ! 582: X ! 583: Xvoid add_name(char *name) ! 584: X ! 585: X#else ! 586: X ! 587: Xvoid add_name(name) ! 588: Xchar *name; /* pointer to name */ ! 589: X ! 590: X#endif ! 591: X{ ! 592: X int i; /* Length of string */ ! 593: X struct nm_list *p; /* Current struct pointer */ ! 594: X ! 595: X i = strlen(name); ! 596: X p = (struct nm_list *) malloc((unsigned) (i + sizeof(struct nm_list))); ! 597: X if (!p) { ! 598: X fatal("cannot allocate memory for namelist entry\n"); ! 599: X } ! 600: X p->next = (struct nm_list *) NULL; ! 601: X p->length = i; ! 602: X strncpy(p->name, name, i); ! 603: X p->name[i] = '\0'; /* Null term */ ! 604: X p->found = 0; ! 605: X p->firstch = isalpha(name[0]); ! 606: X if (strchr(name, '*') || strchr(name, '[') || strchr(name, '?')) { ! 607: X p->regexp = 1; ! 608: X } ! 609: X if (namelast) { ! 610: X namelast->next = p; ! 611: X } ! 612: X namelast = p; ! 613: X if (!namelist) { ! 614: X namelist = p; ! 615: X } ! 616: X} ! 617: X ! 618: X ! 619: X/* name_match - match a name from an archive with a name from the namelist ! 620: X * ! 621: X * DESCRIPTION ! 622: X * ! 623: X * Name_match attempts to find a name pointed at by p in the namelist. ! 624: X * If no namelist is available, then all filenames passed in are ! 625: X * assumed to match the filename criteria. Name_match knows how to ! 626: X * match names with regular expressions, etc. ! 627: X * ! 628: X * PARAMETERS ! 629: X * ! 630: X * char *p - the name to match ! 631: X * ! 632: X * RETURNS ! 633: X * ! 634: X * Returns 1 if the name is in the namelist, or no name list is ! 635: X * available, otherwise returns 0 ! 636: X * ! 637: X */ ! 638: X ! 639: X#ifdef __STDC__ ! 640: X ! 641: Xint name_match(char *p) ! 642: X ! 643: X#else ! 644: X ! 645: Xint name_match(p) ! 646: Xchar *p; ! 647: X ! 648: X#endif ! 649: X{ ! 650: X struct nm_list *nlp; ! 651: X int len; ! 652: X ! 653: X if ((nlp = namelist) == 0) {/* Empty namelist is easy */ ! 654: X return (1); ! 655: X } ! 656: X len = strlen(p); ! 657: X for (; nlp != 0; nlp = nlp->next) { ! 658: X /* If first chars don't match, quick skip */ ! 659: X if (nlp->firstch && nlp->name[0] != p[0]) { ! 660: X continue; ! 661: X } ! 662: X /* Regular expressions */ ! 663: X if (nlp->regexp) { ! 664: X if (wildmat(nlp->name, p)) { ! 665: X nlp->found = 1; /* Remember it matched */ ! 666: X return (1); /* We got a match */ ! 667: X } ! 668: X continue; ! 669: X } ! 670: X /* Plain Old Strings */ ! 671: X if (nlp->length <= len /* Archive len >= specified */ ! 672: X && (p[nlp->length] == '\0' || p[nlp->length] == '/') ! 673: X && strncmp(p, nlp->name, nlp->length) == 0) { ! 674: X /* Name compare */ ! 675: X nlp->found = 1; /* Remember it matched */ ! 676: X return (1); /* We got a match */ ! 677: X } ! 678: X } ! 679: X return (0); ! 680: X} ! 681: X ! 682: X ! 683: X/* names_notfound - print names of files in namelist that were not found ! 684: X * ! 685: X * DESCRIPTION ! 686: X * ! 687: X * Names_notfound scans through the namelist for any files which were ! 688: X * named, but for which a matching file was not processed by the ! 689: X * archive. Each of the files is listed on the standard error. ! 690: X * ! 691: X */ ! 692: X ! 693: X#ifdef __STDC__ ! 694: X ! 695: Xvoid names_notfound(void) ! 696: X ! 697: X#else ! 698: X ! 699: Xvoid names_notfound() ! 700: X ! 701: X#endif ! 702: X{ ! 703: X struct nm_list *nlp; ! 704: X ! 705: X for (nlp = namelist; nlp != 0; nlp = nlp->next) { ! 706: X if (!nlp->found) { ! 707: X fprintf(stderr, "%s: %s not found in archive\n", ! 708: X myname, nlp->name); ! 709: X } ! 710: X free(nlp); ! 711: X } ! 712: X namelist = (struct nm_list *) NULL; ! 713: X namelast = (struct nm_list *) NULL; ! 714: X} ! 715: X ! 716: X ! 717: X/* name_init - set up to gather file names ! 718: X * ! 719: X * DESCRIPTION ! 720: X * ! 721: X * Name_init sets up the namelist pointers so that we may access the ! 722: X * command line arguments. At least the first item of the command ! 723: X * line (argv[0]) is assumed to be stripped off, prior to the ! 724: X * name_init call. ! 725: X * ! 726: X * PARAMETERS ! 727: X * ! 728: X * int argc - number of items in argc ! 729: X * char **argv - pointer to the command line arguments ! 730: X */ ! 731: X ! 732: X#ifdef __STDC__ ! 733: X ! 734: Xvoid name_init(int argc, char **argv) ! 735: X ! 736: X#else ! 737: X ! 738: Xvoid name_init(argc, argv) ! 739: Xint argc; ! 740: Xchar **argv; ! 741: X ! 742: X#endif ! 743: X{ ! 744: X /* Get file names from argv, after options. */ ! 745: X n_argc = argc; ! 746: X n_argv = argv; ! 747: X} ! 748: X ! 749: X ! 750: X/* name_next - get the next name from argv or the name file. ! 751: X * ! 752: X * DESCRIPTION ! 753: X * ! 754: X * Name next finds the next name which is to be processed in the ! 755: X * archive. If the named file is a directory, then the directory ! 756: X * is recursively traversed for additional file names. Directory ! 757: X * names and locations within the directory are kept track of by ! 758: X * using a directory stack. See the pushdir/popdir function for ! 759: X * more details. ! 760: X * ! 761: X * The names come from argv, after options or from the standard input. ! 762: X * ! 763: X * PARAMETERS ! 764: X * ! 765: X * name - a pointer to a buffer of at least MAX_PATH + 1 bytes long; ! 766: X * statbuf - a pointer to a stat structure ! 767: X * ! 768: X * RETURNS ! 769: X * ! 770: X * Returns -1 if there are no names left, (e.g. EOF), otherwise returns ! 771: X * 0 ! 772: X */ ! 773: X ! 774: X#ifdef __STDC__ ! 775: X ! 776: Xint name_next(char *name, Stat *statbuf) ! 777: X ! 778: X#else ! 779: X ! 780: Xint name_next(name, statbuf) ! 781: Xchar *name; ! 782: XStat *statbuf; ! 783: X ! 784: X#endif ! 785: X{ ! 786: X int err = -1; ! 787: X static int in_subdir = 0; ! 788: X static DIR *dirp; ! 789: X struct dirent *d; ! 790: X static struct dirinfo *curr_dir; ! 791: X int len; ! 792: X ! 793: X do { ! 794: X if (names_from_stdin) { ! 795: X if (lineget(stdin, name) < 0) { ! 796: X return (-1); ! 797: X } ! 798: X if (nameopt(name) < 0) { ! 799: X continue; ! 800: X } ! 801: X } else { ! 802: X if (in_subdir) { ! 803: X if ((d = readdir(dirp)) != NULL) { ! 804: X /* Skip . and .. */ ! 805: X if (strcmp(d->d_name, ".") == 0 || ! 806: X strcmp(d->d_name, "..") == 0) { ! 807: X continue; ! 808: X } ! 809: X if (strlen(d->d_name) + ! 810: X strlen(curr_dir->dirname) >= PATH_MAX) { ! 811: X warn("name too long", d->d_name); ! 812: X continue; ! 813: X } ! 814: X strcpy(name, curr_dir->dirname); ! 815: X strcat(name, d->d_name); ! 816: X } else { ! 817: X closedir(dirp); ! 818: X in_subdir--; ! 819: X curr_dir = popdir(); ! 820: X if (in_subdir) { ! 821: X errno = 0; ! 822: X if ((dirp = opendir(curr_dir->dirname)) == NULL) { ! 823: X warn(curr_dir->dirname, "error opening directory (1)"); ! 824: X in_subdir--; ! 825: X } ! 826: X seekdir(dirp, curr_dir->where); ! 827: X } ! 828: X continue; ! 829: X } ! 830: X } else if (optind >= n_argc) { ! 831: X return (-1); ! 832: X } else { ! 833: X strcpy(name, n_argv[optind++]); ! 834: X } ! 835: X } ! 836: X if ((err = LSTAT(name, statbuf)) < 0) { ! 837: X warn(name, syserr()); ! 838: X continue; ! 839: X } ! 840: X if (!names_from_stdin && (statbuf->sb_mode & S_IFMT) == S_IFDIR) { ! 841: X if (in_subdir) { ! 842: X curr_dir->where = telldir(dirp); ! 843: X pushdir(curr_dir); ! 844: X close(dirp); ! 845: X } ! 846: X in_subdir++; ! 847: X ! 848: X /* Build new prototype name */ ! 849: X if ((curr_dir = (struct dirinfo *) ! 850: X mem_get(sizeof(struct dirinfo))) == NULL) { ! 851: X exit(2); ! 852: X } ! 853: X strcpy(curr_dir->dirname, name); ! 854: X len = strlen(curr_dir->dirname); ! 855: X while (len >= 1 && curr_dir->dirname[len - 1] == '/') { ! 856: X len--; /* Delete trailing slashes */ ! 857: X } ! 858: X curr_dir->dirname[len++] = '/'; /* Now add exactly one back */ ! 859: X curr_dir->dirname[len] = '\0';/* Make sure null-terminated */ ! 860: X ! 861: X errno = 0; ! 862: X if ((dirp = opendir(curr_dir->dirname)) == NULL) { ! 863: X warn(curr_dir->dirname, "error opening directory (2)"); ! 864: X } ! 865: X } ! 866: X } while (err < 0); ! 867: X return (0); ! 868: X} ! 869: X ! 870: X ! 871: X/* name_gather - gather names in a list for scanning. ! 872: X * ! 873: X * DESCRIPTION ! 874: X * ! 875: X * Name_gather takes names from the command line and adds them to ! 876: X * the name list. ! 877: X * ! 878: X * FIXME ! 879: X * ! 880: X * We could hash the names if we really care about speed here. ! 881: X */ ! 882: X ! 883: X#ifdef __STDC__ ! 884: X ! 885: Xvoid name_gather(void) ! 886: X ! 887: X#else ! 888: X ! 889: Xvoid name_gather() ! 890: X ! 891: X#endif ! 892: X{ ! 893: X while (optind < n_argc) { ! 894: X add_name(n_argv[optind++]); ! 895: X } ! 896: X} ! 897: X ! 898: X ! 899: Xstatic struct dirinfo *stack_head = NULL; ! 900: X ! 901: X ! 902: X/* pushdir - pushes a directory name on the directory stack ! 903: X * ! 904: X * DESCRIPTION ! 905: X * ! 906: X * The pushdir function puses the directory structure which is pointed ! 907: X * to by "info" onto a stack for later processing. The information ! 908: X * may be retrieved later with a call to popdir(). ! 909: X * ! 910: X * PARAMETERS ! 911: X * ! 912: X * dirinfo *info - pointer to directory structure to save ! 913: X */ ! 914: X ! 915: X#ifdef __STDC__ ! 916: X ! 917: Xstatic void pushdir(struct dirinfo *info) ! 918: X ! 919: X#else ! 920: X ! 921: Xstatic void pushdir(info) ! 922: Xstruct dirinfo *info; ! 923: X ! 924: X#endif ! 925: X{ ! 926: X if (stack_head == NULL) { ! 927: X stack_head = info; ! 928: X stack_head->next = NULL; ! 929: X } else { ! 930: X info->next = stack_head; ! 931: X stack_head = info; ! 932: X } ! 933: X} ! 934: X ! 935: X ! 936: X/* popdir - pop a directory structure off the directory stack. ! 937: X * ! 938: X * DESCRIPTION ! 939: X * ! 940: X * The popdir function pops the most recently pushed directory ! 941: X * structure off of the directory stack and returns it to the calling ! 942: X * function. ! 943: X * ! 944: X * RETURNS ! 945: X * ! 946: X * Returns a pointer to the most recently pushed directory structure ! 947: X * or NULL if the stack is empty. ! 948: X */ ! 949: X ! 950: X#ifdef __STDC__ ! 951: X ! 952: Xstatic struct dirinfo *popdir(void) ! 953: X ! 954: X#else ! 955: X ! 956: Xstatic struct dirinfo *popdir() ! 957: X ! 958: X#endif ! 959: X{ ! 960: X struct dirinfo *tmp; ! 961: X ! 962: X if (stack_head == NULL) { ! 963: X return(NULL); ! 964: X } else { ! 965: X tmp = stack_head; ! 966: X stack_head = stack_head->next; ! 967: X } ! 968: X return(tmp); ! 969: X} ! 970: END_OF_namelist.c ! 971: if test 11056 -ne `wc -c <namelist.c`; then ! 972: echo shar: \"namelist.c\" unpacked with wrong size! ! 973: fi ! 974: # end of overwriting check ! 975: fi ! 976: if test -f pax.c -a "${1}" != "-c" ; then ! 977: echo shar: Will not over-write existing file \"pax.c\" ! 978: else ! 979: echo shar: Extracting \"pax.c\" \(13026 characters\) ! 980: sed "s/^X//" >pax.c <<'END_OF_pax.c' ! 981: X/* $Source: /u/mark/src/pax/RCS/pax.c,v $ ! 982: X * ! 983: X * $Revision: 1.1 $ ! 984: X * ! 985: X * DESCRIPTION ! 986: X * ! 987: X * Pax is the archiver described in IEEE P1003.2. It is an archiver ! 988: X * which understands both tar and cpio archives and has a new interface. ! 989: X * ! 990: X * SYNOPSIS ! 991: X * ! 992: X * pax -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...] ! 993: X * pax -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...] ! 994: X * pax -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]...] ! 995: X * [-t device][-x format][pathname...] ! 996: X * pax -r -w [-ilmopuvy][-s replstr][pathname...] directory ! 997: X * ! 998: X * DESCRIPTION ! 999: X * ! 1000: X * PAX - POSIX conforming tar and cpio archive handler. This ! 1001: X * program implements POSIX conformant versions of tar, cpio and pax ! 1002: X * archive handlers for UNIX. These handlers have defined befined ! 1003: X * by the IEEE P1003.2 commitee. ! 1004: X * ! 1005: X * COMPILATION ! 1006: X * ! 1007: X * A number of different compile time configuration options are ! 1008: X * available, please see the Makefile and config.h for more details. ! 1009: X * ! 1010: X * AUTHOR ! 1011: X * ! 1012: X * Mark H. Colburn, NAPS International ([email protected]) ! 1013: X * ! 1014: X * ! 1015: X * Sponsored by The USENIX Association for public distribution. ! 1016: X * ! 1017: X * Copyright (c) 1989 Mark H. Colburn. ! 1018: X * All rights reserved. ! 1019: X * ! 1020: X * Redistribution and use in source and binary forms are permitted ! 1021: X * provided that the above copyright notice is duplicated in all such ! 1022: X * forms and that any documentation, advertising materials, and other ! 1023: X * materials related to such distribution and use acknowledge that the ! 1024: X * software was developed * by Mark H. Colburn and sponsored by The ! 1025: X * USENIX Association. ! 1026: X * ! 1027: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 1028: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 1029: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 1030: X * ! 1031: X * $Log: pax.c,v $ ! 1032: X * Revision 1.1 88/12/23 18:02:23 mark ! 1033: X * Initial revision ! 1034: X * ! 1035: X */ ! 1036: X ! 1037: X#ifndef lint ! 1038: Xstatic char *ident = "$Id: pax.c,v 1.1 88/12/23 18:02:23 mark Rel $"; ! 1039: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n"; ! 1040: X#endif /* ! lint */ ! 1041: X ! 1042: X ! 1043: X/* Headers */ ! 1044: X ! 1045: X#define NO_EXTERN ! 1046: X#include "pax.h" ! 1047: X ! 1048: X ! 1049: X/* Globally Available Identifiers */ ! 1050: X ! 1051: Xchar *ar_file; /* File containing name of archive */ ! 1052: Xchar *bufend; /* End of data within archive buffer */ ! 1053: Xchar *bufstart; /* Archive buffer */ ! 1054: Xchar *bufidx; /* Archive buffer index */ ! 1055: Xchar *myname; /* name of executable (argv[0]) */ ! 1056: Xchar **n_argv; /* Argv used by name routines */ ! 1057: Xint n_argc; /* Argc used by name routines */ ! 1058: Xint archivefd; /* Archive file descriptor */ ! 1059: Xint blocking; /* Size of each block, in records */ ! 1060: Xint gid; /* Group ID */ ! 1061: Xint head_standard; /* true if archive is POSIX format */ ! 1062: Xint ar_interface; /* defines interface we are using */ ! 1063: Xint ar_format; /* defines current archve format */ ! 1064: Xint mask; /* File creation mask */ ! 1065: Xint ttyf; /* For interactive queries */ ! 1066: Xint uid; /* User ID */ ! 1067: Xint names_from_stdin; /* names for files are from stdin */ ! 1068: XOFFSET total; /* Total number of bytes transferred */ ! 1069: Xshort f_access_time; /* Reset access times of input files */ ! 1070: Xshort areof; /* End of input volume reached */ ! 1071: Xshort f_create_dirs; /* Create missing directories */ ! 1072: Xshort f_append; /* Add named files to end of archive */ ! 1073: Xshort f_create; /* create a new archive */ ! 1074: Xshort f_extract; /* Extract named files from archive */ ! 1075: Xshort f_follow_links; /* follow symbolic links */ ! 1076: Xshort f_interactive; /* Interactivly extract files */ ! 1077: Xshort f_linksleft; /* Report on unresolved links */ ! 1078: Xshort f_list; /* List files on the archive */ ! 1079: Xshort f_modified; /* Don't restore modification times */ ! 1080: Xshort f_verbose; /* Turn on verbose mode */ ! 1081: Xshort f_link; /* link files where possible */ ! 1082: Xshort f_owner; /* extract files as the user */ ! 1083: Xshort f_pass; /* pass files between directories */ ! 1084: Xshort f_newer; /* append files to archive if newer */ ! 1085: Xshort f_disposition; /* ask for file disposition */ ! 1086: Xshort f_reverse_match; /* Reverse sense of pattern match */ ! 1087: Xshort f_modification_time; /* Retain file modification time */ ! 1088: Xshort f_unconditional; /* Copy unconditionally */ ! 1089: Xtime_t now = 0; /* Current time */ ! 1090: Xuint arvolume; /* Volume number */ ! 1091: Xuint blocksize = BLOCKSIZE; /* Archive block size */ ! 1092: XFILE *msgfile; /* message outpu file stdout/stderr */ ! 1093: XReplstr *rplhead = NULL; /* pointer to head of replstr list */ ! 1094: XReplstr *rpltail; /* pointer to tail of replstr list */ ! 1095: X ! 1096: X ! 1097: X/* Function Prototypes */ ! 1098: X ! 1099: X#ifdef __STDC__ ! 1100: X ! 1101: Xstatic void usage(void); ! 1102: Xstatic OFFSET pax_optsize(char *); ! 1103: X ! 1104: X#else /* !__STDC__ */ ! 1105: X ! 1106: Xstatic void usage(); ! 1107: Xstatic OFFSET pax_optsize(); ! 1108: X ! 1109: X#endif /* __STDC__ */ ! 1110: X ! 1111: X ! 1112: X/* main - main routine for handling all archive formats. ! 1113: X * ! 1114: X * DESCRIPTION ! 1115: X * ! 1116: X * Set up globals and call the proper interface as specified by the user. ! 1117: X * ! 1118: X * PARAMETERS ! 1119: X * ! 1120: X * int argc - count of user supplied arguments ! 1121: X * char **argv - user supplied arguments ! 1122: X * ! 1123: X * RETURNS ! 1124: X * ! 1125: X * Returns an exit code of 0 to the parent process. ! 1126: X */ ! 1127: X ! 1128: X#ifdef __STDC__ ! 1129: X ! 1130: Xint main(int argc, char **argv) ! 1131: X ! 1132: X#else ! 1133: X ! 1134: Xint main(argc, argv) ! 1135: Xint argc; ! 1136: Xchar **argv; ! 1137: X ! 1138: X#endif ! 1139: X{ ! 1140: X /* strip the pathname off of the name of the executable */ ! 1141: X if ((myname = strrchr(argv[0], '/')) != (char *)NULL) { ! 1142: X myname++; ! 1143: X } else { ! 1144: X myname = argv[0]; ! 1145: X } ! 1146: X ! 1147: X /* set upt for collecting other command line arguments */ ! 1148: X name_init(argc, argv); ! 1149: X ! 1150: X /* get all our necessary information */ ! 1151: X mask = umask(0); ! 1152: X uid = getuid(); ! 1153: X gid = getgid(); ! 1154: X now = time((time_t *) 0); ! 1155: X ! 1156: X /* open terminal for interactive queries */ ! 1157: X ttyf = open_tty(); ! 1158: X ! 1159: X if (strcmp(myname, "tar")==0) { ! 1160: X do_tar(argc, argv); ! 1161: X } else if (strcmp(myname, "cpio")==0) { ! 1162: X do_cpio(argc, argv); ! 1163: X } else { ! 1164: X do_pax(argc, argv); ! 1165: X } ! 1166: X exit(0); ! 1167: X /* NOTREACHED */ ! 1168: X} ! 1169: X ! 1170: X ! 1171: X/* do_pax - provide a PAX conformant user interface for archive handling ! 1172: X * ! 1173: X * DESCRIPTION ! 1174: X * ! 1175: X * Process the command line parameters given, doing some minimal sanity ! 1176: X * checking, and then launch the specified archiving functions. ! 1177: X * ! 1178: X * PARAMETERS ! 1179: X * ! 1180: X * int ac - A count of arguments in av. Should be passed argc ! 1181: X * from main ! 1182: X * char **av - A pointer to an argument list. Should be passed ! 1183: X * argv from main ! 1184: X * ! 1185: X * RETURNS ! 1186: X * ! 1187: X * Normally returns 0. If an error occurs, -1 is returned ! 1188: X * and state is set to reflect the error. ! 1189: X * ! 1190: X */ ! 1191: X ! 1192: X#ifdef __STDC__ ! 1193: X ! 1194: Xint do_pax(int ac, char **av) ! 1195: X ! 1196: X#else ! 1197: X ! 1198: Xint do_pax(ac, av) ! 1199: Xint ac; /* argument counter */ ! 1200: Xchar **av; /* arguments */ ! 1201: X ! 1202: X#endif ! 1203: X{ ! 1204: X int c; ! 1205: X char *dirname; ! 1206: X Stat st; ! 1207: X ! 1208: X /* default input/output file for PAX is STDIN/STDOUT */ ! 1209: X ar_file = "-"; ! 1210: X ! 1211: X /* ! 1212: X * set up the flags to reflect the default pax inteface. Unfortunately ! 1213: X * the pax interface has several options which are completely opposite ! 1214: X * of the tar and/or cpio interfaces... ! 1215: X */ ! 1216: X f_unconditional = 1; ! 1217: X f_modification_time = 1; ! 1218: X f_create_dirs = 1; ! 1219: X f_list = 1; ! 1220: X blocksize = 0; ! 1221: X blocking = 0; ! 1222: X ar_interface = PAX; ! 1223: X ar_format = TAR; /* default interface if none given for -w */ ! 1224: X msgfile=stdout; ! 1225: X ! 1226: X while ((c = getopt(ac, av, "ab:cdf:ilmoprs:t:uvwx:y")) != EOF) { ! 1227: X switch (c) { ! 1228: X case 'a': ! 1229: X f_append = 1; ! 1230: X f_list = 0; ! 1231: X break; ! 1232: X case 'b': ! 1233: X if ((blocksize = pax_optsize(optarg)) == 0) { ! 1234: X fatal("Bad block size"); ! 1235: X } ! 1236: X break; ! 1237: X case 'c': ! 1238: X f_reverse_match = 1; ! 1239: X break; ! 1240: X case 'd': ! 1241: X f_create_dirs = 0; ! 1242: X break; ! 1243: X case 'f': ! 1244: X if (blocksize == 0) { ! 1245: X blocking = 1; ! 1246: X blocksize = 1 * BLOCKSIZE; ! 1247: X } ! 1248: X ar_file = optarg; ! 1249: X break; ! 1250: X case 'i': ! 1251: X f_interactive = 1; ! 1252: X break; ! 1253: X case 'l': ! 1254: X f_link = 1; ! 1255: X break; ! 1256: X case 'm': ! 1257: X f_modification_time = 0; ! 1258: X break; ! 1259: X case 'o': ! 1260: X f_owner = 1; ! 1261: X break; ! 1262: X case 'p': ! 1263: X f_access_time = 1; ! 1264: X break; ! 1265: X case 'r': ! 1266: X if (f_create) { ! 1267: X f_create = 0; ! 1268: X f_pass = 1; ! 1269: X } else { ! 1270: X f_list = 0; ! 1271: X f_extract = 1; ! 1272: X } ! 1273: X msgfile=stderr; ! 1274: X break; ! 1275: X case 's': ! 1276: X add_replstr(optarg); ! 1277: X break; ! 1278: X case 't': ! 1279: X if (blocksize == 0) { ! 1280: X blocking = 1; ! 1281: X blocksize = 10 * BLOCKSIZE; ! 1282: X } ! 1283: X ar_file = optarg; ! 1284: X break; ! 1285: X case 'u': ! 1286: X f_unconditional = 1; ! 1287: X break; ! 1288: X case 'v': ! 1289: X f_verbose = 1; ! 1290: X break; ! 1291: X case 'w': ! 1292: X if (f_extract) { ! 1293: X f_extract = 0; ! 1294: X f_pass = 1; ! 1295: X } else { ! 1296: X f_list = 0; ! 1297: X f_create = 1; ! 1298: X } ! 1299: X msgfile=stderr; ! 1300: X break; ! 1301: X case 'x': ! 1302: X if (strcmp(optarg, "ustar") == 0) { ! 1303: X ar_format = TAR; ! 1304: X } else if (strcmp(optarg, "cpio") == 0) { ! 1305: X ar_format = CPIO; ! 1306: X } else { ! 1307: X usage(); ! 1308: X } ! 1309: X break; ! 1310: X case 'y': ! 1311: X f_disposition = 1; ! 1312: X break; ! 1313: X default: ! 1314: X usage(); ! 1315: X } ! 1316: X } ! 1317: X ! 1318: X if (blocksize == 0) { ! 1319: X blocking = 1; ! 1320: X blocksize = blocking * BLOCKSIZE; ! 1321: X } ! 1322: X buf_allocate((OFFSET) blocksize); ! 1323: X ! 1324: X if (f_extract || f_list) { ! 1325: X open_archive(AR_READ); ! 1326: X get_archive_type(); ! 1327: X read_archive(); ! 1328: X } else if (f_create) { ! 1329: X if (optind >= n_argc) { ! 1330: X names_from_stdin++; /* args from stdin */ ! 1331: X } ! 1332: X open_archive(AR_WRITE); ! 1333: X create_archive(); ! 1334: X } else if (f_append) { ! 1335: X open_archive(AR_APPEND); ! 1336: X get_archive_type(); ! 1337: X append_archive(); ! 1338: X } else if (f_pass && optind < n_argc) { ! 1339: X dirname = n_argv[--n_argc]; ! 1340: X if (LSTAT(dirname, &st) < 0) { ! 1341: X fatal(syserr()); ! 1342: X } ! 1343: X if ((st.sb_mode & S_IFMT) != S_IFDIR) { ! 1344: X fatal("Not a directory"); ! 1345: X } ! 1346: X if (optind >= n_argc) { ! 1347: X names_from_stdin++; /* args from stdin */ ! 1348: X } ! 1349: X pass(dirname); ! 1350: X } else { ! 1351: X usage(); ! 1352: X } ! 1353: X ! 1354: X return (0); ! 1355: X} ! 1356: X ! 1357: X ! 1358: X/* get_archive_type - determine input archive type from archive header ! 1359: X * ! 1360: X * DESCRIPTION ! 1361: X * ! 1362: X * reads the first block of the archive and determines the archive ! 1363: X * type from the data. If the archive type cannot be determined, ! 1364: X * processing stops, and a 1 is returned to the caller. If verbose ! 1365: X * mode is on, then the archive type will be printed on the standard ! 1366: X * error device as it is determined. ! 1367: X * ! 1368: X * FIXME ! 1369: X * ! 1370: X * be able to understand TAR and CPIO magic numbers ! 1371: X */ ! 1372: X ! 1373: X#ifdef __STDC__ ! 1374: X ! 1375: Xvoid get_archive_type(void) ! 1376: X ! 1377: X#else ! 1378: X ! 1379: Xvoid get_archive_type() ! 1380: X ! 1381: X#endif ! 1382: X{ ! 1383: X if (ar_read() != 0) { ! 1384: X fatal("Unable to determine archive type."); ! 1385: X } ! 1386: X if (strncmp(bufstart, "070707", 6) == 0) { ! 1387: X ar_format = CPIO; ! 1388: X if (f_verbose) { ! 1389: X fputs("CPIO format archive\n", stderr); ! 1390: X } ! 1391: X } else if (strncmp(&bufstart[257], "ustar", 5) == 0) { ! 1392: X ar_format = TAR; ! 1393: X if (f_verbose) { ! 1394: X fputs("USTAR format archive\n", stderr); ! 1395: X } ! 1396: X } else { ! 1397: X ar_format = TAR; ! 1398: X } ! 1399: X} ! 1400: X ! 1401: X ! 1402: X/* pax_optsize - interpret a size argument ! 1403: X * ! 1404: X * DESCRIPTION ! 1405: X * ! 1406: X * Recognizes suffixes for blocks (512-bytes), k-bytes and megabytes. ! 1407: X * Also handles simple expressions containing '+' for addition. ! 1408: X * ! 1409: X * PARAMETERS ! 1410: X * ! 1411: X * char *str - A pointer to the string to interpret ! 1412: X * ! 1413: X * RETURNS ! 1414: X * ! 1415: X * Normally returns the value represented by the expression in the ! 1416: X * the string. ! 1417: X * ! 1418: X * ERRORS ! 1419: X * ! 1420: X * If the string cannot be interpretted, the program will fail, since ! 1421: X * the buffering will be incorrect. ! 1422: X * ! 1423: X */ ! 1424: X ! 1425: X#ifdef __STDC__ ! 1426: X ! 1427: Xstatic OFFSET pax_optsize(char *str) ! 1428: X ! 1429: X#else ! 1430: X ! 1431: Xstatic OFFSET pax_optsize(str) ! 1432: Xchar *str; /* pointer to string to interpret */ ! 1433: X ! 1434: X#endif ! 1435: X{ ! 1436: X char *idx; ! 1437: X OFFSET number; /* temporary storage for current number */ ! 1438: X OFFSET result; /* cumulative total to be returned to caller */ ! 1439: X ! 1440: X result = 0; ! 1441: X idx = str; ! 1442: X for (;;) { ! 1443: X number = 0; ! 1444: X while (*idx >= '0' && *idx <= '9') ! 1445: X number = number * 10 + *idx++ - '0'; ! 1446: X switch (*idx++) { ! 1447: X case 'b': ! 1448: X result += number * 512; ! 1449: X continue; ! 1450: X case 'k': ! 1451: X result += number * 1024; ! 1452: X continue; ! 1453: X case 'm': ! 1454: X result += number * 1024 * 1024; ! 1455: X continue; ! 1456: X case '+': ! 1457: X result += number; ! 1458: X continue; ! 1459: X case '\0': ! 1460: X result += number; ! 1461: X break; ! 1462: X default: ! 1463: X break; ! 1464: X } ! 1465: X break; ! 1466: X } ! 1467: X if (*--idx) { ! 1468: X fatal("Unrecognizable value"); ! 1469: X } ! 1470: X return (result); ! 1471: X} ! 1472: X ! 1473: X ! 1474: X/* usage - print a helpful message and exit ! 1475: X * ! 1476: X * DESCRIPTION ! 1477: X * ! 1478: X * Usage prints out the usage message for the PAX interface and then ! 1479: X * exits with a non-zero termination status. This is used when a user ! 1480: X * has provided non-existant or incompatible command line arguments. ! 1481: X * ! 1482: X * RETURNS ! 1483: X * ! 1484: X * Returns an exit status of 1 to the parent process. ! 1485: X * ! 1486: X */ ! 1487: X ! 1488: X#ifdef __STDC__ ! 1489: X ! 1490: Xstatic void usage(void) ! 1491: X ! 1492: X#else ! 1493: X ! 1494: Xstatic void usage() ! 1495: X ! 1496: X#endif ! 1497: X{ ! 1498: X fprintf(stderr, "\ ! 1499: XUsage: %s -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n", ! 1500: X myname); ! 1501: X fprintf(stderr, "\ ! 1502: X %s -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n", ! 1503: X myname); ! 1504: X fprintf(stderr, "\ ! 1505: X %s -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]\n\ ! 1506: X [-t device] [-x format] [pathname...]\n", ! 1507: X myname); ! 1508: X fprintf(stderr, "\ ! 1509: X %s -r -w [-ilmopuvy] [-s replstr] [pathname...] directory\n", ! 1510: X myname); ! 1511: X exit(1); ! 1512: X} ! 1513: END_OF_pax.c ! 1514: if test 13026 -ne `wc -c <pax.c`; then ! 1515: echo shar: \"pax.c\" unpacked with wrong size! ! 1516: fi ! 1517: # end of overwriting check ! 1518: fi ! 1519: if test -f pax.h -a "${1}" != "-c" ; then ! 1520: echo shar: Will not over-write existing file \"pax.h\" ! 1521: else ! 1522: echo shar: Extracting \"pax.h\" \(9317 characters\) ! 1523: sed "s/^X//" >pax.h <<'END_OF_pax.h' ! 1524: X/* $Source: /u/mark/src/pax/RCS/pax.h,v $ ! 1525: X * ! 1526: X * $Revision: 1.1 $ ! 1527: X * ! 1528: X * pax.h - defnitions for entire program ! 1529: X * ! 1530: X * DESCRIPTION ! 1531: X * ! 1532: X * This file contains most all of the definitions required by the PAX ! 1533: X * software. This header is included in every source file. ! 1534: X * ! 1535: X * AUTHOR ! 1536: X * ! 1537: X * Mark H. Colburn, NAPS International ([email protected]) ! 1538: X * ! 1539: X * Sponsored by The USENIX Association for public distribution. ! 1540: X * ! 1541: X * Copyright (c) 1989 Mark H. Colburn. ! 1542: X * All rights reserved. ! 1543: X * ! 1544: X * Redistribution and use in source and binary forms are permitted ! 1545: X * provided that the above copyright notice and this paragraph are ! 1546: X * duplicated in all such forms and that any documentation, ! 1547: X * advertising materials, and other materials related to such ! 1548: X * distribution and use acknowledge that the software was developed ! 1549: X * by Mark H. Colburn and sponsored by The USENIX Association. ! 1550: X * ! 1551: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 1552: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 1553: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 1554: X */ ! 1555: X ! 1556: X#ifndef _PAX_H ! 1557: X#define _PAX_H ! 1558: X ! 1559: X/* Headers */ ! 1560: X ! 1561: X#include "config.h" ! 1562: X#include "limits.h" ! 1563: X#include <stdio.h> ! 1564: X#include <errno.h> ! 1565: X#include <signal.h> ! 1566: X#include <ctype.h> ! 1567: X#include <sys/types.h> ! 1568: X#include <sys/ioctl.h> ! 1569: X#include <sys/stat.h> ! 1570: X#include "regexp.h" ! 1571: X ! 1572: X#if defined(DIRENT) || defined(_POSIX_SOURCE) ! 1573: X# ifdef PAXDIR ! 1574: X# include "paxdir.h" ! 1575: X# else ! 1576: X# include <dirent.h> ! 1577: X# endif ! 1578: X#else ! 1579: X# include <sys/dir.h> ! 1580: X# define dirent direct ! 1581: X#endif ! 1582: X ! 1583: X#ifndef major ! 1584: X# include <sys/sysmacros.h> ! 1585: X#endif /* major */ ! 1586: X ! 1587: X#ifdef SYSTIME ! 1588: X# include <sys/time.h> ! 1589: X#else /* SYSTIME */ ! 1590: X# include <time.h> ! 1591: X#endif /* SYSTIME */ ! 1592: X ! 1593: X#ifndef V7 ! 1594: X# include <fcntl.h> ! 1595: X#endif ! 1596: X ! 1597: X#ifdef XENIX ! 1598: X# include <sys/inode.h> ! 1599: X#endif ! 1600: X ! 1601: X#include <pwd.h> ! 1602: X#include <grp.h> ! 1603: X#include <sys/file.h> ! 1604: X ! 1605: X/* Defines */ ! 1606: X ! 1607: X#define STDIN 0 /* Standard input file descriptor */ ! 1608: X#define STDOUT 1 /* Standard output file descriptor */ ! 1609: X ! 1610: X/* ! 1611: X * Open modes; there is no <fcntl.h> with v7 UNIX and other versions of ! 1612: X * UNIX may not have all of these defined... ! 1613: X */ ! 1614: X ! 1615: X#ifndef O_RDONLY ! 1616: X# define O_RDONLY 0 ! 1617: X#endif ! 1618: X ! 1619: X#ifndef O_WRONLY ! 1620: X# define O_WRONLY 1 ! 1621: X#endif ! 1622: X ! 1623: X#ifndef O_RDWR ! 1624: X# define O_WRONLY 2 ! 1625: X#endif ! 1626: X ! 1627: X#ifndef O_BINARY ! 1628: X# define O_BINARY 0 ! 1629: X#endif ! 1630: X ! 1631: X#ifndef NULL ! 1632: X# define NULL 0 ! 1633: X#endif ! 1634: X ! 1635: X#define TMAGIC "ustar" /* ustar and a null */ ! 1636: X#define TMAGLEN 6 ! 1637: X#define TVERSION "00" /* 00 and no null */ ! 1638: X#define TVERSLEN 2 ! 1639: X ! 1640: X/* Values used in typeflag field */ ! 1641: X#define REGTYPE '0' /* Regular File */ ! 1642: X#define AREGTYPE '\0' /* Regular File */ ! 1643: X#define LNKTYPE '1' /* Link */ ! 1644: X#define SYMTYPE '2' /* Reserved */ ! 1645: X#define CHRTYPE '3' /* Character Special File */ ! 1646: X#define BLKTYPE '4' /* Block Special File */ ! 1647: X#define DIRTYPE '5' /* Directory */ ! 1648: X#define FIFOTYPE '6' /* FIFO */ ! 1649: X#define CONTTYPE '7' /* Reserved */ ! 1650: X ! 1651: X#define BLOCKSIZE 512 /* all output is padded to 512 bytes */ ! 1652: X#define uint unsigned int /* Not always in types.h */ ! 1653: X#define ushort unsigned short /* Not always in types.h */ ! 1654: X#define BLOCK 5120 /* Default archive block size */ ! 1655: X#define H_COUNT 10 /* Number of items in ASCII header */ ! 1656: X#define H_PRINT "%06o%06o%06o%06o%06o%06o%06o%011lo%06o%011lo" ! 1657: X#define H_SCAN "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6o%11lo" ! 1658: X#define H_STRLEN 70 /* ASCII header string length */ ! 1659: X#define M_ASCII "070707" /* ASCII magic number */ ! 1660: X#define M_BINARY 070707 /* Binary magic number */ ! 1661: X#define M_STRLEN 6 /* ASCII magic number length */ ! 1662: X#define PATHELEM 256 /* Pathname element count limit */ ! 1663: X#define S_IFSHF 12 /* File type shift (shb in stat.h) */ ! 1664: X#define S_IPERM 07777 /* File permission bits (shb in stat.h) */ ! 1665: X#define S_IPEXE 07000 /* Special execution bits (shb in stat.h) */ ! 1666: X#define S_IPOPN 0777 /* Open access bits (shb in stat.h) */ ! 1667: X ! 1668: X/* ! 1669: X * Trailer pathnames. All must be of the same length. ! 1670: X */ ! 1671: X#define TRAILER "TRAILER!!!" /* Archive trailer (cpio compatible) */ ! 1672: X#define TRAILZ 11 /* Trailer pathname length (including null) */ ! 1673: X ! 1674: X#include "port.h" ! 1675: X ! 1676: X ! 1677: X#define TAR 1 ! 1678: X#define CPIO 2 ! 1679: X#define PAX 3 ! 1680: X ! 1681: X#define AR_READ 0 ! 1682: X#define AR_WRITE 1 ! 1683: X#define AR_EXTRACT 2 ! 1684: X#define AR_APPEND 4 ! 1685: X ! 1686: X/* ! 1687: X * Header block on tape. ! 1688: X */ ! 1689: X#define NAMSIZ 100 ! 1690: X#define PFIXSIZ 155 ! 1691: X#define TUNMLEN 32 ! 1692: X#define TGNMLEN 32 ! 1693: X ! 1694: X/* The checksum field is filled with this while the checksum is computed. */ ! 1695: X#define CHKBLANKS " " /* 8 blanks, no null */ ! 1696: X ! 1697: X/* ! 1698: X * Exit codes from the "tar" program ! 1699: X */ ! 1700: X#define EX_SUCCESS 0 /* success! */ ! 1701: X#define EX_ARGSBAD 1 /* invalid args */ ! 1702: X#define EX_BADFILE 2 /* invalid filename */ ! 1703: X#define EX_BADARCH 3 /* bad archive */ ! 1704: X#define EX_SYSTEM 4 /* system gave unexpected error */ ! 1705: X ! 1706: X#define ROUNDUP(a,b) (((a) % (b)) == 0 ? (a) : ((a) + ((b) - ((a) % (b))))) ! 1707: X ! 1708: X/* ! 1709: X * Mininum value. ! 1710: X */ ! 1711: X#define MIN(a, b) (((a) < (b)) ? (a) : (b)) ! 1712: X ! 1713: X/* ! 1714: X * Remove a file or directory. ! 1715: X */ ! 1716: X#define REMOVE(name, asb) \ ! 1717: X (((asb)->sb_mode & S_IFMT) == S_IFDIR ? rmdir(name) : unlink(name)) ! 1718: X ! 1719: X/* ! 1720: X * Cast and reduce to unsigned short. ! 1721: X */ ! 1722: X#define USH(n) (((ushort) (n)) & 0177777) ! 1723: X ! 1724: X ! 1725: X/* Type Definitions */ ! 1726: X ! 1727: X/* ! 1728: X * Binary archive header (obsolete). ! 1729: X */ ! 1730: Xtypedef struct { ! 1731: X short b_dev; /* Device code */ ! 1732: X ushort b_ino; /* Inode number */ ! 1733: X ushort b_mode; /* Type and permissions */ ! 1734: X ushort b_uid; /* Owner */ ! 1735: X ushort b_gid; /* Group */ ! 1736: X short b_nlink; /* Number of links */ ! 1737: X short b_rdev; /* Real device */ ! 1738: X ushort b_mtime[2]; /* Modification time (hi/lo) */ ! 1739: X ushort b_name; /* Length of pathname (with null) */ ! 1740: X ushort b_size[2]; /* Length of data */ ! 1741: X} Binary; ! 1742: X ! 1743: X/* ! 1744: X * File status with symbolic links. Kludged to hold symbolic link pathname ! 1745: X * within structure. ! 1746: X */ ! 1747: Xtypedef struct { ! 1748: X struct stat sb_stat; ! 1749: X char sb_link[PATH_MAX + 1]; ! 1750: X} Stat; ! 1751: X ! 1752: X#define STAT(name, asb) stat(name, &(asb)->sb_stat) ! 1753: X#define FSTAT(fd, asb) fstat(fd, &(asb)->sb_stat) ! 1754: X ! 1755: X#define sb_dev sb_stat.st_dev ! 1756: X#define sb_ino sb_stat.st_ino ! 1757: X#define sb_mode sb_stat.st_mode ! 1758: X#define sb_nlink sb_stat.st_nlink ! 1759: X#define sb_uid sb_stat.st_uid ! 1760: X#define sb_gid sb_stat.st_gid ! 1761: X#define sb_rdev sb_stat.st_rdev ! 1762: X#define sb_size sb_stat.st_size ! 1763: X#define sb_atime sb_stat.st_atime ! 1764: X#define sb_mtime sb_stat.st_mtime ! 1765: X#define sb_ctime sb_stat.st_ctime ! 1766: X ! 1767: X#ifdef S_IFLNK ! 1768: X# define LSTAT(name, asb) lstat(name, &(asb)->sb_stat) ! 1769: X# define sb_blksize sb_stat.st_blksize ! 1770: X# define sb_blocks sb_stat.st_blocks ! 1771: X#else /* S_IFLNK */ ! 1772: X/* ! 1773: X * File status without symbolic links. ! 1774: X */ ! 1775: X# define LSTAT(name, asb) stat(name, &(asb)->sb_stat) ! 1776: X#endif /* S_IFLNK */ ! 1777: X ! 1778: X/* ! 1779: X * Hard link sources. One or more are chained from each link structure. ! 1780: X */ ! 1781: Xtypedef struct name { ! 1782: X struct name *p_forw; /* Forward chain (terminated) */ ! 1783: X struct name *p_back; /* Backward chain (circular) */ ! 1784: X char *p_name; /* Pathname to link from */ ! 1785: X} Path; ! 1786: X ! 1787: X/* ! 1788: X * File linking information. One entry exists for each unique file with with ! 1789: X * outstanding hard links. ! 1790: X */ ! 1791: Xtypedef struct link { ! 1792: X struct link *l_forw; /* Forward chain (terminated) */ ! 1793: X struct link *l_back; /* Backward chain (terminated) */ ! 1794: X dev_t l_dev; /* Device */ ! 1795: X ino_t l_ino; /* Inode */ ! 1796: X ushort l_nlink; /* Unresolved link count */ ! 1797: X OFFSET l_size; /* Length */ ! 1798: X char *l_name; /* pathname to link from */ ! 1799: X Path *l_path; /* Pathname which link to l_name */ ! 1800: X} Link; ! 1801: X ! 1802: X/* ! 1803: X * Structure for ed-style replacement strings (-s option). ! 1804: X*/ ! 1805: Xtypedef struct replstr { ! 1806: X regexp *comp; /* compiled regular expression */ ! 1807: X char *replace; /* replacement string */ ! 1808: X char print; /* >0 if we are to print replacement */ ! 1809: X char global; /* >0 if we are to replace globally */ ! 1810: X struct replstr *next; /* pointer to next record */ ! 1811: X} Replstr; ! 1812: X ! 1813: X ! 1814: X/* ! 1815: X * This has to be included here to insure that all of the type ! 1816: X * delcarations are declared for the prototypes. ! 1817: X */ ! 1818: X#include "func.h" ! 1819: X ! 1820: X ! 1821: X#ifndef NO_EXTERN ! 1822: X/* Globally Available Identifiers */ ! 1823: X ! 1824: Xextern char *ar_file; ! 1825: Xextern char *bufend; ! 1826: Xextern char *bufstart; ! 1827: Xextern char *bufidx; ! 1828: Xextern char *myname; ! 1829: Xextern int archivefd; ! 1830: Xextern int blocking; ! 1831: Xextern uint blocksize; ! 1832: Xextern int gid; ! 1833: Xextern int head_standard; ! 1834: Xextern int ar_interface; ! 1835: Xextern int ar_format; ! 1836: Xextern int mask; ! 1837: Xextern int ttyf; ! 1838: Xextern int uid; ! 1839: Xextern OFFSET total; ! 1840: Xextern short areof; ! 1841: Xextern short f_append; ! 1842: Xextern short f_create; ! 1843: Xextern short f_extract; ! 1844: Xextern short f_follow_links; ! 1845: Xextern short f_interactive; ! 1846: Xextern short f_linksleft; ! 1847: Xextern short f_list; ! 1848: Xextern short f_modified; ! 1849: Xextern short f_verbose; ! 1850: Xextern short f_link; ! 1851: Xextern short f_owner; ! 1852: Xextern short f_access_time; ! 1853: Xextern short f_pass; ! 1854: Xextern short f_pass; ! 1855: Xextern short f_disposition; ! 1856: Xextern short f_reverse_match; ! 1857: Xextern short f_modification_time; ! 1858: Xextern short f_create_dirs; ! 1859: Xextern short f_unconditional; ! 1860: Xextern short f_newer; ! 1861: Xextern time_t now; ! 1862: Xextern uint arvolume; ! 1863: Xextern int names_from_stdin; ! 1864: Xextern Replstr *rplhead; ! 1865: Xextern Replstr *rpltail; ! 1866: Xextern char **n_argv; ! 1867: Xextern int n_argc; ! 1868: Xextern FILE *msgfile; ! 1869: X#endif /* NO_EXTERN */ ! 1870: X ! 1871: Xextern char *optarg; ! 1872: Xextern int optind; ! 1873: Xextern int sys_nerr; ! 1874: Xextern char *sys_errlist[]; ! 1875: Xextern int errno; ! 1876: X ! 1877: X#endif /* _PAX_H */ ! 1878: END_OF_pax.h ! 1879: if test 9317 -ne `wc -c <pax.h`; then ! 1880: echo shar: \"pax.h\" unpacked with wrong size! ! 1881: fi ! 1882: # end of overwriting check ! 1883: fi ! 1884: if test -f tar.c -a "${1}" != "-c" ; then ! 1885: echo shar: Will not over-write existing file \"tar.c\" ! 1886: else ! 1887: echo shar: Extracting \"tar.c\" \(7881 characters\) ! 1888: sed "s/^X//" >tar.c <<'END_OF_tar.c' ! 1889: X/* $Source: /u/mark/src/pax/RCS/tar.c,v $ ! 1890: X * ! 1891: X * $Revision: 1.1 $ ! 1892: X * ! 1893: X * tar.c - tar specific functions for archive handling ! 1894: X * ! 1895: X * DESCRIPTION ! 1896: X * ! 1897: X * These routines provide a tar conforming interface to the pax ! 1898: X * program. ! 1899: X * ! 1900: X * AUTHOR ! 1901: X * ! 1902: X * Mark H. Colburn, NAPS International ([email protected]) ! 1903: X * ! 1904: X * Sponsored by The USENIX Association for public distribution. ! 1905: X * ! 1906: X * Copyright (c) 1989 Mark H. Colburn. ! 1907: X * All rights reserved. ! 1908: X * ! 1909: X * Redistribution and use in source and binary forms are permitted ! 1910: X * provided that the above copyright notice is duplicated in all such ! 1911: X * forms and that any documentation, advertising materials, and other ! 1912: X * materials related to such distribution and use acknowledge that the ! 1913: X * software was developed by Mark H. Colburn and sponsored by The ! 1914: X * USENIX Association. ! 1915: X * ! 1916: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 1917: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 1918: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 1919: X * ! 1920: X * $Log: tar.c,v $ ! 1921: X * Revision 1.1 88/12/23 18:02:38 mark ! 1922: X * Initial revision ! 1923: X * ! 1924: X */ ! 1925: X ! 1926: X#ifndef lint ! 1927: Xstatic char *ident = "$Id: tar.c,v 1.1 88/12/23 18:02:38 mark Rel $"; ! 1928: Xstatic char *copyright ="Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved."; ! 1929: X#endif /* not lint */ ! 1930: X ! 1931: X/* Headers */ ! 1932: X ! 1933: X#include "pax.h" ! 1934: X ! 1935: X ! 1936: X/* Defines */ ! 1937: X ! 1938: X#define DEF_BLOCKING 20 /* default blocking factor for extract */ ! 1939: X ! 1940: X ! 1941: X/* Function Prototypes */ ! 1942: X ! 1943: X#ifdef __STDC__ ! 1944: X ! 1945: Xstatic int taropt(int , char **, char *); ! 1946: Xstatic void usage(void); ! 1947: X ! 1948: X#else /* !__STDC__ */ ! 1949: X ! 1950: Xstatic int taropt(); ! 1951: Xstatic void usage(); ! 1952: X ! 1953: X#endif /* __STDC__ */ ! 1954: X ! 1955: X ! 1956: X/* do_tar - main routine for tar. ! 1957: X * ! 1958: X * DESCRIPTION ! 1959: X * ! 1960: X * Provides a tar interface to the PAX program. All tar standard ! 1961: X * command line options are supported. ! 1962: X * ! 1963: X * PARAMETERS ! 1964: X * ! 1965: X * int argc - argument count (argc from main) ! 1966: X * char **argv - argument list (argv from main) ! 1967: X * ! 1968: X * RETURNS ! 1969: X * ! 1970: X * zero ! 1971: X */ ! 1972: X ! 1973: X#ifdef __STDC__ ! 1974: X ! 1975: Xint do_tar(int argc, char **argv) ! 1976: X ! 1977: X#else ! 1978: X ! 1979: Xint do_tar(argc, argv) ! 1980: Xint argc; /* argument count (argc from main) */ ! 1981: Xchar **argv; /* argument list (argv from main) */ ! 1982: X ! 1983: X#endif ! 1984: X{ ! 1985: X int c; /* Option letter */ ! 1986: X ! 1987: X /* Set default option values */ ! 1988: X names_from_stdin = 0; ! 1989: X ar_file = getenv("TAPE"); /* From environment, or */ ! 1990: X if (ar_file == 0) { ! 1991: X ar_file = DEF_AR_FILE; /* From Makefile */ ! 1992: X } ! 1993: X ! 1994: X /* ! 1995: X * set up the flags to reflect the default pax inteface. Unfortunately ! 1996: X * the pax interface has several options which are completely opposite ! 1997: X * of the tar and/or cpio interfaces... ! 1998: X */ ! 1999: X f_unconditional = 1; ! 2000: X f_modification_time = 1; ! 2001: X f_create_dirs = 1; ! 2002: X blocking = 0; ! 2003: X ar_interface = TAR; ! 2004: X ar_format = TAR; ! 2005: X msgfile=stdout; ! 2006: X ! 2007: X /* Parse options */ ! 2008: X while ((c = taropt(argc, argv, "b:cf:hlmortuvwx")) != EOF) { ! 2009: X switch (c) { ! 2010: X case 'b': /* specify blocking factor */ ! 2011: X /* ! 2012: X * FIXME - we should use a conversion routine that does ! 2013: X * some kind of reasonable error checking, but... ! 2014: X */ ! 2015: X blocking = atoi(optarg); ! 2016: X break; ! 2017: X case 'c': /* create a new archive */ ! 2018: X f_create = 1; ! 2019: X break; ! 2020: X case 'f': /* specify input/output file */ ! 2021: X ar_file = optarg; ! 2022: X break; ! 2023: X case 'h': ! 2024: X f_follow_links = 1; /* follow symbolic links */ ! 2025: X break; ! 2026: X case 'l': /* report unresolved links */ ! 2027: X f_linksleft = 1; ! 2028: X break; ! 2029: X case 'm': /* don't restore modification times */ ! 2030: X f_modified = 1; ! 2031: X break; ! 2032: X case 'o': /* take on user's group rather than ! 2033: X * archives */ ! 2034: X break; ! 2035: X case 'r': /* named files are appended to archive */ ! 2036: X f_append = 1; ! 2037: X break; ! 2038: X case 't': ! 2039: X f_list = 1; /* list files in archive */ ! 2040: X break; ! 2041: X case 'u': /* named files are added to archive */ ! 2042: X f_newer = 1; ! 2043: X break; ! 2044: X case 'v': /* verbose mode */ ! 2045: X f_verbose = 1; ! 2046: X break; ! 2047: X case 'w': /* user interactive mode */ ! 2048: X f_disposition = 1; ! 2049: X break; ! 2050: X case 'x': /* named files are extracted from archive */ ! 2051: X f_extract = 1; ! 2052: X break; ! 2053: X case '?': ! 2054: X usage(); ! 2055: X exit(EX_ARGSBAD); ! 2056: X } ! 2057: X } ! 2058: X ! 2059: X /* check command line argument sanity */ ! 2060: X if (f_create + f_extract + f_list + f_append + f_newer != 1) { ! 2061: X (void) fprintf(stderr, ! 2062: X "%s: you must specify exactly one of the c, t, r, u or x options\n", ! 2063: X myname); ! 2064: X usage(); ! 2065: X exit(EX_ARGSBAD); ! 2066: X } ! 2067: X ! 2068: X /* set the blocking factor, if not set by the user */ ! 2069: X if (blocking == 0) { ! 2070: X#ifdef USG ! 2071: X if (f_extract || f_list) { ! 2072: X blocking = DEF_BLOCKING; ! 2073: X fprintf(stderr, "Tar: blocksize = %d\n", blocking); ! 2074: X } else { ! 2075: X blocking = 1; ! 2076: X } ! 2077: X#else /* !USG */ ! 2078: X blocking = 20; ! 2079: X#endif /* USG */ ! 2080: X } ! 2081: X blocksize = blocking * BLOCKSIZE; ! 2082: X buf_allocate((OFFSET) blocksize); ! 2083: X ! 2084: X if (f_create) { ! 2085: X open_archive(AR_WRITE); ! 2086: X create_archive(); /* create the archive */ ! 2087: X } else if (f_extract) { ! 2088: X open_archive(AR_READ); ! 2089: X read_archive(); /* extract files from archive */ ! 2090: X } else if (f_list) { ! 2091: X open_archive(AR_READ); ! 2092: X read_archive(); /* read and list contents of archive */ ! 2093: X } else if (f_append) { ! 2094: X open_archive(AR_APPEND); ! 2095: X append_archive(); /* append files to archive */ ! 2096: X } ! 2097: X ! 2098: X if (f_linksleft) { ! 2099: X linkleft(); /* report any unresolved links */ ! 2100: X } ! 2101: X ! 2102: X return (0); ! 2103: X} ! 2104: X ! 2105: X ! 2106: X/* taropt - tar specific getopt ! 2107: X * ! 2108: X * DESCRIPTION ! 2109: X * ! 2110: X * Plug-compatible replacement for getopt() for parsing tar-like ! 2111: X * arguments. If the first argument begins with "-", it uses getopt; ! 2112: X * otherwise, it uses the old rules used by tar, dump, and ps. ! 2113: X * ! 2114: X * PARAMETERS ! 2115: X * ! 2116: X * int argc - argument count (argc from main) ! 2117: X * char **argv - argument list (argv from main) ! 2118: X * char *optstring - sring which describes allowable options ! 2119: X * ! 2120: X * RETURNS ! 2121: X * ! 2122: X * Returns the next option character in the option string(s). If the ! 2123: X * option requires an argument and an argument was given, the argument ! 2124: X * is pointed to by "optarg". If no option character was found, ! 2125: X * returns an EOF. ! 2126: X * ! 2127: X */ ! 2128: X ! 2129: X#ifdef __STDC__ ! 2130: X ! 2131: Xstatic int taropt(int argc, char **argv, char *optstring) ! 2132: X ! 2133: X#else ! 2134: X ! 2135: Xstatic int taropt(argc, argv, optstring) ! 2136: Xint argc; ! 2137: Xchar **argv; ! 2138: Xchar *optstring; ! 2139: X ! 2140: X#endif ! 2141: X{ ! 2142: X extern char *optarg; /* Points to next arg */ ! 2143: X extern int optind; /* Global argv index */ ! 2144: X static char *key; /* Points to next keyletter */ ! 2145: X static char use_getopt; /* !=0 if argv[1][0] was '-' */ ! 2146: X char c; ! 2147: X char *place; ! 2148: X ! 2149: X optarg = NULL; ! 2150: X ! 2151: X if (key == NULL) { /* First time */ ! 2152: X if (argc < 2) ! 2153: X return EOF; ! 2154: X key = argv[1]; ! 2155: X if (*key == '-') ! 2156: X use_getopt++; ! 2157: X else ! 2158: X optind = 2; ! 2159: X } ! 2160: X if (use_getopt) { ! 2161: X return getopt(argc, argv, optstring); ! 2162: X } ! 2163: X ! 2164: X c = *key++; ! 2165: X if (c == '\0') { ! 2166: X key--; ! 2167: X return EOF; ! 2168: X } ! 2169: X place = strchr(optstring, c); ! 2170: X ! 2171: X if (place == NULL || c == ':') { ! 2172: X fprintf(stderr, "%s: unknown option %c\n", argv[0], c); ! 2173: X return ('?'); ! 2174: X } ! 2175: X place++; ! 2176: X if (*place == ':') { ! 2177: X if (optind < argc) { ! 2178: X optarg = argv[optind]; ! 2179: X optind++; ! 2180: X } else { ! 2181: X fprintf(stderr, "%s: %c argument missing\n", ! 2182: X argv[0], c); ! 2183: X return ('?'); ! 2184: X } ! 2185: X } ! 2186: X return (c); ! 2187: X} ! 2188: X ! 2189: X ! 2190: X/* usage - print a helpful message and exit ! 2191: X * ! 2192: X * DESCRIPTION ! 2193: X * ! 2194: X * Usage prints out the usage message for the TAR interface and then ! 2195: X * exits with a non-zero termination status. This is used when a user ! 2196: X * has provided non-existant or incompatible command line arguments. ! 2197: X * ! 2198: X * RETURNS ! 2199: X * ! 2200: X * Returns an exit status of 1 to the parent process. ! 2201: X * ! 2202: X */ ! 2203: X ! 2204: X#ifdef __STDC__ ! 2205: X ! 2206: Xstatic void usage(void) ! 2207: X ! 2208: X#else ! 2209: X ! 2210: Xstatic void usage() ! 2211: X ! 2212: X#endif ! 2213: X{ ! 2214: X fprintf(stderr, "\ ! 2215: XUsage: %s -c[bfvw] device block filename..\n", myname); ! 2216: X fprintf(stderr, "\ ! 2217: X %s -r[bvw] device block [filename...]\n", myname); ! 2218: X fprintf(stderr, "\ ! 2219: X %s -t[vf] device\n", myname); ! 2220: X fprintf(stderr, "\ ! 2221: X %s -u[bvw] device block [filename...]\n", myname); ! 2222: X fprintf(stderr, "\ ! 2223: X %s -x[flmovw] device [filename...]\n", myname); ! 2224: X exit(1); ! 2225: X} ! 2226: END_OF_tar.c ! 2227: if test 7881 -ne `wc -c <tar.c`; then ! 2228: echo shar: \"tar.c\" unpacked with wrong size! ! 2229: fi ! 2230: # end of overwriting check ! 2231: fi ! 2232: echo shar: End of archive 3 \(of 6\). ! 2233: cp /dev/null ark3isdone ! 2234: MISSING="" ! 2235: for I in 1 2 3 4 5 6 ; do ! 2236: if test ! -f ark${I}isdone ; then ! 2237: MISSING="${MISSING} ${I}" ! 2238: fi ! 2239: done ! 2240: if test "${MISSING}" = "" ; then ! 2241: echo You have unpacked all 6 archives. ! 2242: rm -f ark[1-9]isdone ! 2243: else ! 2244: echo You still need to unpack the following archives: ! 2245: echo " " ${MISSING} ! 2246: fi ! 2247: ## End of shell archive. ! 2248: exit 0 ! 2249:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.