1: /* 2: * afio.c 3: * 4: * Manipulate archives and files. 5: * 6: * Copyright (c) 1985 Lachman Associates, Inc.. 7: * 8: * This software was written by Mark Brukhartz at Lachman Associates, 9: * Inc.. It may be distributed within the following restrictions: 10: * (1) It may not be sold at a profit. 11: * (2) This credit and notice must remain intact. 12: * This software may be distributed with other software by a commercial 13: * vendor, provided that it is included at no additional charge. 14: * 15: * Please report bugs to "..!ihnp4!laidbak!mdb". 16: * 17: * Options: 18: * o Define INDEX to use index() in place of strchr() (v7, BSD). 19: * o Define MEMCPY when an efficient memcpy() exists (SysV). 20: * o Define MKDIR when a mkdir() system call is present (4.2BSD, SysVr3). 21: * o Define NOVOID if your compiler doesn't like void casts. 22: * o Define SYSTIME to use <sys/time.h> rather than <time.h> (4.2BSD). 23: * o Define VOIDFIX to allow pointers to functions returning void (non-PCC). 24: * o Define CTC3B2 to support AT&T 3B2 streaming cartridge tape. 25: */ 26: 27: static char *ident = "$Header: afio.c,v 1.68.1 96/3/21 13:07:11 mdb Exp $"; 28: 29: #include <stdio.h> 30: #include <errno.h> 31: #include <sys/signal.h> 32: #include <sys/types.h> 33: #include <sys/ioctl.h> 34: #include <sys/stat.h> 35: #include <pwd.h> 36: #include <grp.h> 37: #include <string.h> 38: 39: #ifndef major 40: # include <sys/sysmacros.h> 41: #endif /* major */ 42: 43: #ifdef SYSTIME 44: # include <sys/time.h> 45: #else /* SYSTIME */ 46: # include <time.h> 47: #endif /* SYSTIME */ 48: 49: #ifdef CTC3B2 50: # include <sys/vtoc.h> 51: # include <sys/ct.h> 52: #endif /* CTC3B2 */ 53: 54: /* 55: * Address link information base. 56: */ 57: #define linkhash(ino) \ 58: (linkbase + (ino) % nel(linkbase)) 59: 60: /* 61: * Mininum value. 62: */ 63: #define min(one, two) \ 64: (one < two ? one : two) 65: 66: /* 67: * Number of array elements. 68: */ 69: #define nel(a) \ 70: (sizeof(a) / sizeof(*(a))) 71: 72: /* 73: * Remove a file or directory. 74: */ 75: #define remove(name, asb) \ 76: (((asb)->sb_mode & S_IFMT) == S_IFDIR ? rmdir(name) : unlink(name)) 77: 78: /* 79: * Swap bytes. 80: */ 81: #define swab(n) \ 82: ((((ushort)(n) >> 8) & 0xff) | (((ushort)(n) << 8) & 0xff00)) 83: 84: /* 85: * Cast and reduce to unsigned short. 86: */ 87: #define ush(n) \ 88: (((ushort) (n)) & 0177777) 89: 90: /* 91: * Definitions. 92: */ 93: #define reg register /* Convenience */ 94: #define uint unsigned int /* Not always in types.h */ 95: #define ushort unsigned short /* Not always in types.h */ 96: #define BLOCK 5120 /* Default archive block size */ 97: #define FSBUF (8*1024) /* Filesystem buffer size */ 98: #define H_COUNT 10 /* Number of items in ASCII header */ 99: #define H_PRINT "%06o%06o%06o%06o%06o%06o%06o%011lo%06o%011lo" 100: #define H_SCAN "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6o%11lo" 101: #define H_STRLEN 70 /* ASCII header string length */ 102: #define M_ASCII "070707" /* ASCII magic number */ 103: #define M_BINARY 070707 /* Binary magic number */ 104: #define M_STRLEN 6 /* ASCII magic number length */ 105: #define NULLDEV -1 /* Null device code */ 106: #define NULLINO 0 /* Null inode number */ 107: #define PATHELEM 256 /* Pathname element count limit */ 108: #define PATHSIZE 1024 /* Pathname length limit */ 109: #define S_IFSHF 12 /* File type shift (shb in stat.h) */ 110: #define S_IPERM 07777 /* File permission bits (shb in stat.h) */ 111: #define S_IPEXE 07000 /* Special execution bits (shb in stat.h) */ 112: #define S_IPOPN 0777 /* Open access bits (shb in stat.h) */ 113: #define STDIN 0 /* Standard input file descriptor */ 114: #define STDOUT 1 /* Standard output file descriptor */ 115: #define TTY "/dev/tty" /* For volume-change queries */ 116: 117: /* 118: * Some versions of the portable "C" compiler (PCC) can't handle 119: * pointers to functions returning void. 120: */ 121: #ifdef VOIDFIX 122: # define VOIDFN void /* Expect "void (*fnptr)()" to work */ 123: #else /* VOIDFIX */ 124: # define VOIDFN int /* Avoid PCC "void (*fnptr)()" bug */ 125: #endif /* VOIDFIX */ 126: 127: /* 128: * Trailer pathnames. All must be of the same length. 129: */ 130: #define TRAILER "TRAILER!!!" /* Archive trailer (cpio compatible) */ 131: #define TRAILZ 11 /* Trailer pathname length (including null) */ 132: 133: /* 134: * Open modes; there is no <fcntl.h> with v7 UNIX. 135: */ 136: #define O_RDONLY 0 /* Read-only */ 137: #define O_WRONLY 1 /* Write-only */ 138: #define O_RDWR 2 /* Read/write */ 139: 140: /* 141: * V7 and BSD UNIX use old-fashioned names for a couple of 142: * string functions. 143: */ 144: #ifdef INDEX 145: # define strchr index /* Forward character search */ 146: # define strrchr rindex /* Reverse character search */ 147: #endif /* INDEX */ 148: 149: /* 150: * Some compilers can't handle void casts. 151: */ 152: #ifdef NOVOID 153: # define VOID /* Omit void casts */ 154: #else /* NOVOID */ 155: # define VOID (void) /* Quiet lint about ignored return values */ 156: #endif /* NOVOID */ 157: 158: /* 159: * Adb is more palatable when static functions and variables are 160: * declared as globals. Lint gives more useful information when 161: * statics are truly static. 162: */ 163: #ifdef lint 164: # define STATIC static /* Declare static variables for lint */ 165: #else /* lint */ 166: # define STATIC /* Make static variables global for adb */ 167: #endif /* lint */ 168: 169: /* 170: * Simple types. 171: */ 172: typedef struct group Group; /* Structure for getgrgid(3) */ 173: typedef struct passwd Passwd; /* Structure for getpwuid(3) */ 174: typedef struct tm Time; /* Structure for localtime(3) */ 175: 176: #ifdef S_IFLNK 177: /* 178: * File status with symbolic links. Kludged to hold symbolic 179: * link pathname within structure. 180: */ 181: typedef struct { 182: struct stat sb_stat; 183: char sb_link[PATHSIZE]; 184: } Stat; 185: # define STAT(name, asb) stat(name, &(asb)->sb_stat) 186: # define FSTAT(fd, asb) fstat(fd, &(asb)->sb_stat) 187: # define LSTAT(name, asb) lstat(name, &(asb)->sb_stat) 188: # define sb_dev sb_stat.st_dev 189: # define sb_ino sb_stat.st_ino 190: # define sb_mode sb_stat.st_mode 191: # define sb_nlink sb_stat.st_nlink 192: # define sb_uid sb_stat.st_uid 193: # define sb_gid sb_stat.st_gid 194: # define sb_rdev sb_stat.st_rdev 195: # define sb_size sb_stat.st_size 196: # define sb_atime sb_stat.st_atime 197: # define sb_mtime sb_stat.st_mtime 198: # define sb_ctime sb_stat.st_ctime 199: # define sb_blksize sb_stat.st_blksize 200: # define sb_blocks sb_stat.st_blocks 201: #else /* S_IFLNK */ 202: /* 203: * File status without symbolic links. 204: */ 205: typedef struct stat Stat; 206: # define STAT(name, asb) stat(name, asb) 207: # define FSTAT(fd, asb) fstat(fd, asb) 208: # define LSTAT(name, asb) stat(name, asb) 209: # define sb_dev st_dev 210: # define sb_ino st_ino 211: # define sb_mode st_mode 212: # define sb_nlink st_nlink 213: # define sb_uid st_uid 214: # define sb_gid st_gid 215: # define sb_rdev st_rdev 216: # define sb_size st_size 217: # define sb_atime st_atime 218: # define sb_mtime st_mtime 219: # define sb_ctime st_ctime 220: #endif /* S_IFLNK */ 221: 222: /* 223: * Binary archive header (obsolete). 224: */ 225: typedef struct { 226: short b_dev; /* Device code */ 227: ushort b_ino; /* Inode number */ 228: ushort b_mode; /* Type and permissions */ 229: ushort b_uid; /* Owner */ 230: ushort b_gid; /* Group */ 231: short b_nlink; /* Number of links */ 232: short b_rdev; /* Real device */ 233: ushort b_mtime[2]; /* Modification time (hi/lo) */ 234: ushort b_name; /* Length of pathname (with null) */ 235: ushort b_size[2]; /* Length of data */ 236: } Binary; 237: 238: /* 239: * Child process structure. 240: */ 241: typedef struct child { 242: struct child *c_forw; /* Forward link */ 243: int c_pid; /* Process ID */ 244: int c_flags; /* Flags (CF_) */ 245: int c_status; /* Exit status */ 246: } Child; 247: 248: /* 249: * Child process flags (c_flags). 250: */ 251: #define CF_EXIT (1<<0) /* Exited */ 252: 253: /* 254: * Hard link sources. One or more are chained from each link 255: * structure. 256: */ 257: typedef struct name { 258: struct name *p_forw; /* Forward chain (terminated) */ 259: struct name *p_back; /* Backward chain (circular) */ 260: char *p_name; /* Pathname to link from */ 261: } Path; 262: 263: /* 264: * File linking information. One entry exists for each unique 265: * file with with outstanding hard links. 266: */ 267: typedef struct link { 268: struct link *l_forw; /* Forward chain (terminated) */ 269: struct link *l_back; /* Backward chain (terminated) */ 270: dev_t l_dev; /* Device */ 271: ino_t l_ino; /* Inode */ 272: ushort l_nlink; /* Unresolved link count */ 273: off_t l_size; /* Length */ 274: Path *l_path; /* Pathname(s) to link from */ 275: } Link; 276: 277: /* 278: * Pathnames to (or to not) be processed. 279: */ 280: typedef struct pattern { 281: struct pattern *p_forw; /* Forward chain */ 282: char *p_str; /* String */ 283: int p_len; /* Length of string */ 284: int p_not; /* Reverse logic */ 285: } Pattern; 286: 287: /* 288: * External functions. 289: */ 290: void _exit(); 291: void exit(); 292: void free(); 293: char *getenv(); 294: ushort getgid(); 295: Group *getgrgid(); 296: Passwd *getpwuid(); 297: ushort getuid(); 298: Time *localtime(); 299: off_t lseek(); 300: char *malloc(); 301: VOIDFN (*signal())(); 302: uint sleep(); 303: char *strcat(); 304: char *strchr(); 305: char *strcpy(); 306: char *strncpy(); 307: char *strrchr(); 308: time_t time(); 309: ushort umask(); 310: 311: /* 312: * Internal functions. 313: */ 314: VOIDFN copyin(); 315: VOIDFN copyout(); 316: int dirchg(); 317: int dirmake(); 318: int dirneed(); 319: void fatal(); 320: VOIDFN in(); 321: void inalloc(); 322: int inascii(); 323: int inavail(); 324: int inbinary(); 325: int indata(); 326: int inentry(); 327: int infill(); 328: int inhead(); 329: int inread(); 330: int inskip(); 331: int inswab(); 332: int lineget(); 333: void linkalso(); 334: Link *linkfrom(); 335: void linkleft(); 336: Link *linkto(); 337: char *memget(); 338: char *memstr(); 339: int mkdir(); 340: void nameadd(); 341: int namecmp(); 342: int nameopt(); 343: void next(); 344: void nextask(); 345: void nextclos(); 346: int nextopen(); 347: int openi(); 348: int openo(); 349: int openq(); 350: int options(); 351: off_t optsize(); 352: VOIDFN out(); 353: void outalloc(); 354: uint outavail(); 355: int outdata(); 356: void outeof(); 357: void outflush(); 358: void outhead(); 359: void outpad(); 360: void outwait(); 361: void outwrite(); 362: VOIDFN pass(); 363: void passdata(); 364: int passitem(); 365: int pipechld(); 366: int pipeopen(); 367: void pipewait(); 368: void prsize(); 369: int rmdir(); 370: int swrite(); 371: char *syserr(); 372: VOIDFN toc(); 373: void tocentry(); 374: void tocmode(); 375: void usage(); 376: int warn(); 377: int warnarch(); 378: int xfork(); 379: void xpause(); 380: int xwait(); 381: 382: /* 383: * External variables. 384: */ 385: extern int errno; /* System error code */ 386: 387: /* 388: * Static variables. 389: */ 390: #ifdef CTC3B2 391: STATIC short Cflag; /* Enable 3B2 CTC streaming (kludge) */ 392: #endif /* CTC3B2 */ 393: STATIC short dflag; /* Don't create missing directories */ 394: STATIC short fflag; /* Fork before writing to archive */ 395: STATIC short gflag; /* Change to input file directories */ 396: STATIC short hflag; /* Follow symbolic links */ 397: STATIC short jflag; /* Don't generate sparse filesystem blocks */ 398: STATIC short kflag; /* Skip initial junk to find a header */ 399: STATIC short lflag; /* Link rather than copying (when possible) */ 400: STATIC short mflag; /* Ignore archived timestamps */ 401: STATIC short nflag; /* Keep newer existing files */ 402: STATIC short uflag; /* Report files with unseen links */ 403: STATIC short vflag; /* Verbose */ 404: STATIC short xflag; /* Retain file ownership */ 405: STATIC short zflag; /* Print final statistics */ 406: STATIC uint arbsize = BLOCK;/* Archive block size */ 407: STATIC short areof; /* End of input volume reached */ 408: STATIC int arfd; /* Archive file descriptor */ 409: STATIC off_t arleft; /* Space remaining within current volume */ 410: STATIC char *arname; /* Expanded archive name */ 411: STATIC uint arpad; /* Final archive block padding boundary */ 412: STATIC char arspec[PATHSIZE];/* Specified archive name */ 413: STATIC off_t aruntil; /* Volume size limit */ 414: STATIC uint arvolume; /* Volume number */ 415: STATIC uint buflen; /* Archive buffer length */ 416: STATIC char *buffer; /* Archive buffer */ 417: STATIC char *bufidx; /* Archive buffer index */ 418: STATIC char *bufend; /* End of data within archive buffer */ 419: STATIC Child *children; /* Child processes */ 420: STATIC ushort gid; /* Group ID */ 421: STATIC Link *linkbase[256]; /* Unresolved link information */ 422: STATIC ushort mask; /* File creation mask */ 423: STATIC char *myname; /* Arg0 */ 424: STATIC char *optarg; /* Option argument */ 425: STATIC int optind; /* Command line index */ 426: STATIC int outpid; /* Process ID of outstanding outflush() */ 427: STATIC Pattern *pattern; /* Pathname matching patterns */ 428: STATIC char pwd[PATHSIZE]; /* Working directory (with "-g") */ 429: STATIC int pipepid; /* Pipeline process ID */ 430: STATIC time_t timenow; /* Current time */ 431: STATIC time_t timewait; /* Time spent awaiting new media */ 432: STATIC off_t total; /* Total number of bytes transferred */ 433: STATIC int ttyf; /* For interactive queries (yuk) */ 434: STATIC ushort uid; /* User ID */ 435: 436: main(ac, av) 437: int ac; 438: reg char **av; 439: { 440: reg int c; 441: reg uint group = 1; 442: reg VOIDFN (*fn)() = NULL; 443: reg time_t timedone; 444: auto char remote[PATHSIZE]; 445: 446: if (myname = strrchr(*av, '/')) 447: ++myname; 448: else 449: myname = *av; 450: mask = umask(0); 451: ttyf = openq(); 452: uid = getuid(); 453: gid = getgid(); 454: if (uid == 0) 455: ++xflag; 456: VOID signal(SIGPIPE, SIG_IGN); 457: while (c = options(ac, av, "ioptIOVCb:c:de:fghjklmns:uvxXy:Y:z")) { 458: switch (c) { 459: case 'i': 460: if (fn) 461: usage(); 462: fn = in; 463: break; 464: case 'o': 465: if (fn) 466: usage(); 467: fn = out; 468: break; 469: case 'p': 470: if (fn) 471: usage(); 472: fn = pass; 473: break; 474: case 't': 475: if (fn) 476: usage(); 477: fn = toc; 478: break; 479: case 'I': 480: if (fn) 481: usage(); 482: fn = copyin; 483: break; 484: case 'O': 485: if (fn) 486: usage(); 487: fn = copyout; 488: break; 489: case 'V': 490: VOID printf("%s\n", ident); 491: exit(0); 492: #ifdef CTC3B2 493: case 'C': 494: ++Cflag; 495: arbsize = 31 * 512; 496: group = 10; 497: aruntil = 1469 * 31 * 512; 498: break; 499: #endif /* CTC3B2 */ 500: case 'b': 501: if ((arbsize = (uint) optsize(optarg)) == 0) 502: fatal(optarg, "Bad block size"); 503: break; 504: case 'c': 505: if ((group = (uint) optsize(optarg)) == 0) 506: fatal(optarg, "Bad buffer count"); 507: break; 508: case 'd': 509: ++dflag; 510: break; 511: case 'e': 512: arpad = (uint) optsize(optarg); 513: break; 514: case 'f': 515: ++fflag; 516: break; 517: case 'g': 518: ++gflag; 519: break; 520: case 'h': 521: ++hflag; 522: break; 523: case 'j': 524: ++jflag; 525: break; 526: case 'k': 527: ++kflag; 528: break; 529: case 'l': 530: ++lflag; 531: break; 532: case 'm': 533: ++mflag; 534: break; 535: case 'n': 536: ++nflag; 537: break; 538: case 's': 539: aruntil = optsize(optarg); 540: break; 541: case 'u': 542: ++uflag; 543: break; 544: case 'v': 545: ++vflag; 546: break; 547: case 'x': 548: ++xflag; 549: break; 550: case 'X': 551: xflag = 0; 552: break; 553: case 'y': 554: nameadd(optarg, 0); 555: break; 556: case 'Y': 557: nameadd(optarg, 1); 558: break; 559: case 'z': 560: ++zflag; 561: break; 562: default: 563: usage(); 564: } 565: } 566: if (fn == NULL || av[optind] == NULL) 567: usage(); 568: buflen = arbsize * group; 569: if (arpad == 0) 570: arpad = arbsize; 571: if (fn != pass) { 572: reg char *colon; 573: reg char *equal; 574: reg int isoutput = (fn == out || fn == copyout); 575: 576: arname = strcpy(arspec, av[optind++]); 577: if (colon = strchr(arspec, ':')) { 578: *colon++ = '\0'; 579: if (equal = strchr(arspec, '=')) 580: *equal++ = '\0'; 581: VOID sprintf(arname = remote, 582: "!rsh %s %s -%c -b %u -c %u %s", 583: arspec, equal ? equal : myname, 584: isoutput ? 'O' : 'I', arbsize, 585: group, colon); 586: if (equal) 587: *--equal = '='; 588: *--colon = ':'; 589: } 590: if (gflag && *arname != '/' && *arname != '!') 591: fatal(arspec, "Relative pathname"); 592: if ((buffer = bufidx = bufend = malloc(buflen)) == NULL) 593: fatal(arspec, "Cannot allocate I/O buffer"); 594: if (nextopen(isoutput ? O_WRONLY : O_RDONLY) < 0) 595: exit(1); 596: } 597: timenow = time((time_t *) NULL); 598: (*fn)(av + optind); 599: timedone = time((time_t *) NULL); 600: if (uflag) 601: linkleft(); 602: if (zflag) { 603: reg FILE *stream; 604: 605: stream = fn == toc || arfd == STDOUT ? stderr : stdout; 606: VOID fprintf(stream, "%s: ", myname); 607: prsize(stream, total); 608: VOID fprintf(stream, " bytes %s in %lu seconds\n", 609: fn == pass 610: ? "transferred" 611: : fn == out || fn == copyout 612: ? "written" 613: : "read", 614: timedone - timenow - timewait); 615: } 616: nextclos(); 617: exit(0); 618: /* NOTREACHED */ 619: } 620: 621: /* 622: * copyin() 623: * 624: * Copy directly from the archive to the standard output. 625: */ 626: STATIC VOIDFN 627: copyin(av) 628: reg char **av; 629: { 630: reg int got; 631: reg uint have; 632: 633: if (*av) 634: fatal(*av, "Extraneous argument"); 635: while (!areof) { 636: VOID infill(); 637: while (have = bufend - bufidx) 638: if ((got = write(STDOUT, bufidx, have)) < 0) 639: fatal("<stdout>", syserr()); 640: else if (got > 0) 641: bufidx += got; 642: else 643: return; 644: } 645: } 646: 647: /* 648: * copyout() 649: * 650: * Copy directly from the standard input to the archive. 651: */ 652: STATIC VOIDFN 653: copyout(av) 654: reg char **av; 655: { 656: reg int got; 657: reg uint want; 658: 659: if (*av) 660: fatal(*av, "Extraneous argument"); 661: for (;;) { 662: while ((want = bufend - bufidx) == 0) 663: outflush(); 664: if ((got = read(STDIN, bufidx, want)) < 0) 665: fatal("<stdin>", syserr()); 666: else if (got == 0) 667: break; 668: else 669: bufidx += got; 670: } 671: outflush(); 672: if (fflag) 673: outwait(); 674: } 675: 676: /* 677: * dirchg() 678: * 679: * Change to the directory containing a given file. 680: */ 681: STATIC int 682: dirchg(name, local) 683: reg char *name; 684: reg char *local; 685: { 686: reg char *last; 687: reg int len; 688: auto char dir[PATHSIZE]; 689: 690: if (*name != '/') 691: return (warn(name, "Relative pathname")); 692: for (last = name + strlen(name); last[-1] != '/'; --last) 693: ; 694: len = last - name; 695: strncpy(dir, name, len)[len] = '\0'; 696: VOID strcpy(local, *last ? last : "."); 697: if (strcmp(dir, pwd) == 0) 698: return (0); 699: if (chdir(dir) < 0) 700: return (warn(name, syserr())); 701: VOID strcpy(pwd, dir); 702: return (0); 703: } 704: 705: /* 706: * dirmake() 707: * 708: * Make a directory. Returns zero if successful, -1 otherwise. 709: */ 710: STATIC int 711: dirmake(name, asb) 712: reg char *name; 713: reg Stat *asb; 714: { 715: if (mkdir(name, asb->sb_mode & S_IPOPN) < 0) 716: return (-1); 717: if (asb->sb_mode & S_IPEXE) 718: VOID chmod(name, asb->sb_mode & S_IPERM); 719: if (xflag) 720: VOID chown(name, 721: uid == 0 ? ush(asb->sb_uid) : uid, 722: ush(asb->sb_gid)); 723: return (0); 724: } 725: 726: /* 727: * dirneed() 728: * 729: * Recursively create missing directories (with the same permissions 730: * as their first existing parent). Temporarily modifies the 'name' 731: * argument string. Returns zero if successful, -1 otherwise. 732: */ 733: STATIC int 734: dirneed(name) 735: char *name; 736: { 737: reg char *cp; 738: reg char *last; 739: reg int ok; 740: static Stat sb; 741: 742: last = NULL; 743: for (cp = name; *cp; ) 744: if (*cp++ == '/') 745: last = cp; 746: if (last == NULL) 747: return (STAT(".", &sb)); 748: *--last = '\0'; 749: ok = STAT(*name ? name : "/", &sb) == 0 750: ? ((sb.sb_mode & S_IFMT) == S_IFDIR) 751: : (!dflag && dirneed(name) == 0 && dirmake(name, &sb) == 0); 752: *last = '/'; 753: return (ok ? 0 : -1); 754: } 755: 756: /* 757: * fatal() 758: * 759: * Print fatal message and exit. 760: */ 761: STATIC void 762: fatal(what, why) 763: char *what; 764: char *why; 765: { 766: VOID fprintf(stderr, 767: "%s: \"%s\": %s\n", 768: myname, what, why); 769: exit(1); 770: } 771: 772: /* 773: * in() 774: * 775: * Read an archive. 776: */ 777: STATIC VOIDFN 778: in(av) 779: reg char **av; 780: { 781: auto Stat sb; 782: auto char name[PATHSIZE]; 783: 784: if (*av) 785: fatal(*av, "Extraneous argument"); 786: name[0] = '\0'; 787: while (inhead(name, &sb) == 0) { 788: if (namecmp(name) < 0 || inentry(name, &sb) < 0) 789: if (inskip(sb.sb_size) < 0) 790: VOID warn(name, "Skipped file data is corrupt"); 791: if (vflag) 792: VOID fprintf(stderr, "%s\n", name); 793: } 794: } 795: 796: /* 797: * inalloc() 798: * 799: * Allocate input buffer space (which was previously indexed 800: * by inavail()). 801: */ 802: STATIC void 803: inalloc(len) 804: reg uint len; 805: { 806: bufidx += len; 807: total += len; 808: } 809: 810: /* 811: * inascii() 812: * 813: * Read an ASCII header. Returns zero if successful; 814: * -1 otherwise. Assumes that the entire magic number 815: * has been read. 816: */ 817: STATIC int 818: inascii(magic, name, asb) 819: reg char *magic; 820: reg char *name; 821: reg Stat *asb; 822: { 823: auto uint namelen; 824: auto char header[H_STRLEN + 1]; 825: 826: if (strncmp(magic, M_ASCII, M_STRLEN) != 0) 827: return (-1); 828: if (inread(header, H_STRLEN) < 0) 829: return (warnarch("Corrupt ASCII header", (off_t) H_STRLEN)); 830: header[H_STRLEN] = '\0'; 831: if (sscanf(header, H_SCAN, &asb->sb_dev, 832: &asb->sb_ino, &asb->sb_mode, &asb->sb_uid, 833: &asb->sb_gid, &asb->sb_nlink, &asb->sb_rdev, 834: &asb->sb_mtime, &namelen, &asb->sb_size) != H_COUNT) 835: return (warnarch("Bad ASCII header", (off_t) H_STRLEN)); 836: if (namelen == 0 || namelen >= PATHSIZE) 837: return (warnarch("Bad ASCII pathname length", (off_t) H_STRLEN)); 838: if (inread(name, namelen) < 0) 839: return (warnarch("Corrupt ASCII pathname", (off_t) namelen)); 840: if (name[namelen - 1] != '\0') 841: return (warnarch("Bad ASCII pathname", (off_t) namelen)); 842: return (0); 843: } 844: 845: /* 846: * inavail() 847: * 848: * Index availible input data within the buffer. Stores a pointer 849: * to the data and its length in given locations. Returns zero with 850: * valid data, -1 if unreadable portions were replaced with nulls. 851: */ 852: STATIC int 853: inavail(bufp, lenp) 854: reg char **bufp; 855: uint *lenp; 856: { 857: reg uint have; 858: reg int corrupt = 0; 859: 860: while ((have = bufend - bufidx) == 0) 861: corrupt |= infill(); 862: *bufp = bufidx; 863: *lenp = have; 864: return (corrupt); 865: } 866: 867: /* 868: * inbinary() 869: * 870: * Read a binary header. Returns the number of trailing alignment 871: * bytes to skip; -1 if unsuccessful. 872: */ 873: STATIC int 874: inbinary(magic, name, asb) 875: reg char *magic; 876: reg char *name; 877: reg Stat *asb; 878: { 879: reg uint namefull; 880: auto Binary binary; 881: 882: if (*((ushort *) magic) != M_BINARY) 883: return (-1); 884: memcpy((char *) &binary, 885: magic + sizeof(ushort), 886: M_STRLEN - sizeof(ushort)); 887: if (inread((char *) &binary + M_STRLEN - sizeof(ushort), 888: sizeof(binary) - (M_STRLEN - sizeof(ushort))) < 0) 889: return (warnarch("Corrupt binary header", 890: (off_t) sizeof(binary) - (M_STRLEN - sizeof(ushort)))); 891: asb->sb_dev = binary.b_dev; 892: asb->sb_ino = binary.b_ino; 893: asb->sb_mode = binary.b_mode; 894: asb->sb_uid = binary.b_uid; 895: asb->sb_gid = binary.b_gid; 896: asb->sb_nlink = binary.b_nlink; 897: asb->sb_rdev = binary.b_rdev; 898: asb->sb_mtime = binary.b_mtime[0] << 16 | binary.b_mtime[1]; 899: asb->sb_size = binary.b_size[0] << 16 | binary.b_size[1]; 900: if (binary.b_name == 0 || binary.b_name >= PATHSIZE) 901: return (warnarch("Bad binary pathname length", 902: (off_t) sizeof(binary) - (M_STRLEN - sizeof(ushort)))); 903: if (inread(name, namefull = binary.b_name + binary.b_name % 2) < 0) 904: return (warnarch("Corrupt binary pathname", (off_t) namefull)); 905: if (name[binary.b_name - 1] != '\0') 906: return (warnarch("Bad binary pathname", (off_t) namefull)); 907: return (asb->sb_size % 2); 908: } 909: 910: /* 911: * indata() 912: * 913: * Install data from an archive. Returns given file descriptor. 914: */ 915: STATIC int 916: indata(fd, size, name) 917: int fd; 918: reg off_t size; 919: char *name; 920: { 921: reg uint chunk; 922: reg char *oops; 923: reg int sparse; 924: reg int corrupt; 925: auto char *buf; 926: auto uint avail; 927: 928: corrupt = sparse = 0; 929: oops = NULL; 930: while (size) { 931: corrupt |= inavail(&buf, &avail); 932: size -= (chunk = size < avail ? (uint) size : avail); 933: if (oops == NULL && (sparse = swrite(fd, buf, chunk)) < 0) 934: oops = syserr(); 935: inalloc(chunk); 936: } 937: if (corrupt) 938: VOID warn(name, "Corrupt archive data"); 939: if (oops) 940: VOID warn(name, oops); 941: else if (sparse > 0 942: && (lseek(fd, (off_t) -1, 1) < 0 943: || write(fd, "", 1) != 1)) 944: VOID warn(name, syserr()); 945: return (fd); 946: } 947: 948: /* 949: * inentry() 950: * 951: * Install a single archive entry. Returns zero if successful, -1 otherwise. 952: */ 953: STATIC int 954: inentry(name, asb) 955: char *name; 956: reg Stat *asb; 957: { 958: reg Link *linkp; 959: reg int ifd; 960: reg int ofd; 961: auto time_t tstamp[2]; 962: 963: if ((ofd = openo(name, asb, linkp = linkfrom(asb), 0)) > 0) 964: if (asb->sb_size || linkp == NULL || linkp->l_size == 0) 965: VOID close(indata(ofd, asb->sb_size, name)); 966: else if ((ifd = open(linkp->l_path->p_name, O_RDONLY)) < 0) 967: VOID warn(linkp->l_path->p_name, syserr()); 968: else { 969: passdata(linkp->l_path->p_name, ifd, name, ofd); 970: VOID close(ifd); 971: VOID close(ofd); 972: } 973: else if (ofd < 0) 974: return (-1); 975: else if (inskip(asb->sb_size) < 0) 976: VOID warn(name, "Redundant file data is corrupt"); 977: tstamp[0] = tstamp[1] = mflag ? timenow : asb->sb_mtime; 978: VOID utime(name, tstamp); 979: return (0); 980: } 981: 982: /* 983: * infill() 984: * 985: * Fill the archive buffer. Remembers mid-buffer read failures and 986: * reports them the next time through. Replaces unreadable data with 987: * null characters. Returns zero with valid data, -1 otherwise. 988: */ 989: STATIC int 990: infill() 991: { 992: reg int got; 993: static int failed; 994: 995: bufend = bufidx = buffer; 996: if (!failed) { 997: if (areof) 998: if (total == 0) 999: fatal(arspec, "No input"); 1000: else 1001: next(O_RDONLY, "Input EOF"); 1002: if (aruntil && arleft < arbsize) 1003: next(O_RDONLY, "Input limit reached"); 1004: while (!failed 1005: && !areof 1006: && (aruntil == 0 || arleft >= arbsize) 1007: && buffer + buflen - bufend >= arbsize) { 1008: if ((got = read(arfd, bufend, arbsize)) > 0) { 1009: bufend += got; 1010: arleft -= got; 1011: } else if (got < 0) 1012: failed = warnarch(syserr(), 1013: (off_t) 0 - (bufend - bufidx)); 1014: else 1015: ++areof; 1016: } 1017: } 1018: if (failed && bufend == buffer) { 1019: failed = 0; 1020: for (got = 0; got < arbsize; ++got) 1021: *bufend++ = '\0'; 1022: return (-1); 1023: } 1024: return (0); 1025: } 1026: 1027: /* 1028: * inhead() 1029: * 1030: * Read a header. Quietly translates old-fashioned binary cpio headers 1031: * (and arranges to skip the possible alignment byte). Returns zero if 1032: * successful, -1 upon archive trailer. 1033: */ 1034: STATIC int 1035: inhead(name, asb) 1036: reg char *name; 1037: reg Stat *asb; 1038: { 1039: reg off_t skipped; 1040: auto char magic[M_STRLEN]; 1041: static int align; 1042: 1043: if (align > 0) 1044: VOID inskip((off_t) align); 1045: align = 0; 1046: for (;;) { 1047: VOID inread(magic, M_STRLEN); 1048: skipped = 0; 1049: while ((align = inascii(magic, name, asb)) < 0 1050: && (align = inbinary(magic, name, asb)) < 0 1051: && (align = inswab(magic, name, asb)) < 0) { 1052: if (++skipped == 1) { 1053: if (!kflag && total - sizeof(magic) == 0) 1054: fatal(arspec, "Unrecognizable archive"); 1055: VOID warnarch("Bad magic number", 1056: (off_t) sizeof(magic)); 1057: if (name[0]) 1058: VOID warn(name, "May be corrupt"); 1059: } 1060: memcpy(magic, magic + 1, sizeof(magic) - 1); 1061: VOID inread(magic + sizeof(magic) - 1, 1); 1062: } 1063: if (skipped) { 1064: VOID warnarch("Apparently resynchronized", 1065: (off_t) sizeof(magic)); 1066: VOID warn(name, "Continuing"); 1067: } 1068: if (strcmp(name, TRAILER) == 0) 1069: return (-1); 1070: if (nameopt(name) >= 0) 1071: break; 1072: VOID inskip(asb->sb_size + align); 1073: } 1074: #ifdef S_IFLNK 1075: if ((asb->sb_mode & S_IFMT) == S_IFLNK) { 1076: if (inread(asb->sb_link, (uint) asb->sb_size) < 0) { 1077: VOID warn(name, "Corrupt symbolic link"); 1078: return (inhead(name, asb)); 1079: } 1080: asb->sb_link[asb->sb_size] = '\0'; 1081: asb->sb_size = 0; 1082: } 1083: #endif /* S_IFLNK */ 1084: if (name[0] == '/') 1085: if (name[1]) 1086: while (name[0] = name[1]) 1087: ++name; 1088: else 1089: name[0] = '.'; 1090: asb->sb_atime = asb->sb_ctime = asb->sb_mtime; 1091: return (0); 1092: } 1093: 1094: /* 1095: * inread() 1096: * 1097: * Read a given number of characters from the input archive. Returns 1098: * zero with valid data, -1 if unreadable portions were replaced by 1099: * null characters. 1100: */ 1101: STATIC int 1102: inread(dst, len) 1103: reg char *dst; 1104: uint len; 1105: { 1106: reg uint have; 1107: reg uint want; 1108: reg int corrupt = 0; 1109: char *endx = dst + len; 1110: 1111: while (want = endx - dst) { 1112: while ((have = bufend - bufidx) == 0) 1113: corrupt |= infill(); 1114: if (have > want) 1115: have = want; 1116: memcpy(dst, bufidx, have); 1117: bufidx += have; 1118: dst += have; 1119: total += have; 1120: } 1121: return (corrupt); 1122: } 1123: 1124: /* 1125: * inskip() 1126: * 1127: * Skip input archive data. Returns zero under normal circumstances, 1128: * -1 if unreadable data is encountered. 1129: */ 1130: STATIC int 1131: inskip(len) 1132: reg off_t len; 1133: { 1134: reg uint chunk; 1135: reg int corrupt = 0; 1136: 1137: while (len) { 1138: while ((chunk = bufend - bufidx) == 0) 1139: corrupt |= infill(); 1140: if (chunk > len) 1141: chunk = len; 1142: bufidx += chunk; 1143: len -= chunk; 1144: total += chunk; 1145: } 1146: return (corrupt); 1147: } 1148: 1149: /* 1150: * inswab() 1151: * 1152: * Read a reversed byte order binary header. Returns the number 1153: * of trailing alignment bytes to skip; -1 if unsuccessful. 1154: */ 1155: STATIC int 1156: inswab(magic, name, asb) 1157: reg char *magic; 1158: reg char *name; 1159: reg Stat *asb; 1160: { 1161: reg ushort namesize; 1162: reg uint namefull; 1163: auto Binary binary; 1164: 1165: if (*((ushort *) magic) != swab(M_BINARY)) 1166: return (-1); 1167: memcpy((char *) &binary, 1168: magic + sizeof(ushort), 1169: M_STRLEN - sizeof(ushort)); 1170: if (inread((char *) &binary + M_STRLEN - sizeof(ushort), 1171: sizeof(binary) - (M_STRLEN - sizeof(ushort))) < 0) 1172: return (warnarch("Corrupt swapped header", 1173: (off_t) sizeof(binary) - (M_STRLEN - sizeof(ushort)))); 1174: asb->sb_dev = (dev_t) swab(binary.b_dev); 1175: asb->sb_ino = (ino_t) swab(binary.b_ino); 1176: asb->sb_mode = swab(binary.b_mode); 1177: asb->sb_uid = swab(binary.b_uid); 1178: asb->sb_gid = swab(binary.b_gid); 1179: asb->sb_nlink = swab(binary.b_nlink); 1180: asb->sb_rdev = (dev_t) swab(binary.b_rdev); 1181: asb->sb_mtime = swab(binary.b_mtime[0]) << 16 | swab(binary.b_mtime[1]); 1182: asb->sb_size = swab(binary.b_size[0]) << 16 | swab(binary.b_size[1]); 1183: if ((namesize = swab(binary.b_name)) == 0 || namesize >= PATHSIZE) 1184: return (warnarch("Bad swapped pathname length", 1185: (off_t) sizeof(binary) - (M_STRLEN - sizeof(ushort)))); 1186: if (inread(name, namefull = namesize + namesize % 2) < 0) 1187: return (warnarch("Corrupt swapped pathname", (off_t) namefull)); 1188: if (name[namesize - 1] != '\0') 1189: return (warnarch("Bad swapped pathname", (off_t) namefull)); 1190: return (asb->sb_size % 2); 1191: } 1192: 1193: /* 1194: * lineget() 1195: * 1196: * Get a line from a given stream. Returns 0 if successful, -1 at EOF. 1197: */ 1198: STATIC int 1199: lineget(stream, buf) 1200: reg FILE *stream; 1201: reg char *buf; 1202: { 1203: reg int c; 1204: 1205: for (;;) { 1206: if ((c = getc(stream)) == EOF) 1207: return (-1); 1208: if (c == '\n') 1209: break; 1210: *buf++ = c; 1211: } 1212: *buf = '\0'; 1213: return (0); 1214: } 1215: 1216: /* 1217: * linkalso() 1218: * 1219: * Add a destination pathname to an existing chain. Assumes that 1220: * at least one element is present. 1221: */ 1222: STATIC void 1223: linkalso(linkp, name) 1224: reg Link *linkp; 1225: char *name; 1226: { 1227: reg Path *path; 1228: 1229: if ((path = (Path *) memget(sizeof(Path))) == NULL 1230: || (path->p_name = memstr(name)) == NULL) 1231: return; 1232: path->p_forw = NULL; 1233: path->p_back = linkp->l_path->p_back; 1234: path->p_back->p_forw = path; 1235: linkp->l_path->p_back = path; 1236: } 1237: 1238: /* 1239: * linkfrom() 1240: * 1241: * Find a file to link from. Returns a pointer to a link 1242: * structure, or NULL if unsuccessful. 1243: */ 1244: STATIC Link * 1245: linkfrom(asb) 1246: reg Stat *asb; 1247: { 1248: reg Link *linkp; 1249: reg Link *linknext; 1250: reg Path *path; 1251: reg Path *pathnext; 1252: reg Link **abase; 1253: 1254: for (linkp = *(abase = linkhash(asb->sb_ino)); linkp; linkp = linknext) 1255: if (linkp->l_nlink == 0) { 1256: for (path = linkp->l_path; path; path = pathnext) { 1257: pathnext = path->p_forw; 1258: free(path->p_name); 1259: } 1260: free((char *) linkp->l_path); 1261: if (linknext = linkp->l_forw) 1262: linknext->l_back = linkp->l_back; 1263: if (linkp->l_back) 1264: linkp->l_back->l_forw = linkp->l_forw; 1265: else 1266: *abase = linkp->l_forw; 1267: free((char *) linkp); 1268: } else if (linkp->l_ino == asb->sb_ino 1269: && linkp->l_dev == asb->sb_dev) { 1270: --linkp->l_nlink; 1271: return (linkp); 1272: } else 1273: linknext = linkp->l_forw; 1274: return (NULL); 1275: } 1276: 1277: /* 1278: * linkleft() 1279: * 1280: * Complain about files with unseen links. 1281: */ 1282: STATIC void 1283: linkleft() 1284: { 1285: reg Link *lp; 1286: reg Link **base; 1287: 1288: for (base = linkbase; base < linkbase + nel(linkbase); ++base) 1289: for (lp = *base; lp; lp = lp->l_forw) 1290: if (lp->l_nlink) 1291: VOID warn(lp->l_path->p_name, "Unseen link(s)"); 1292: } 1293: 1294: /* 1295: * linkto() 1296: * 1297: * Remember a file with outstanding links. Returns a 1298: * pointer to the associated link structure, or NULL 1299: * when linking is not possible. 1300: */ 1301: STATIC Link * 1302: linkto(name, asb) 1303: char *name; 1304: reg Stat *asb; 1305: { 1306: reg Link *linkp; 1307: reg Path *path; 1308: reg Link **abase; 1309: 1310: if ((asb->sb_mode & S_IFMT) == S_IFDIR 1311: || (linkp = (Link *) memget(sizeof(Link))) == NULL 1312: || (path = (Path *) memget(sizeof(Path))) == NULL 1313: || (path->p_name = memstr(name)) == NULL) 1314: return (NULL); 1315: linkp->l_dev = asb->sb_dev; 1316: linkp->l_ino = asb->sb_ino; 1317: linkp->l_nlink = asb->sb_nlink - 1; 1318: linkp->l_size = asb->sb_size; 1319: linkp->l_path = path; 1320: path->p_forw = NULL; 1321: path->p_back = path; 1322: if (linkp->l_forw = *(abase = linkhash(asb->sb_ino))) 1323: linkp->l_forw->l_back = linkp; 1324: linkp->l_back = NULL; 1325: return (*abase = linkp); 1326: } 1327: 1328: #ifndef MEMCPY 1329: 1330: /* 1331: * memcpy() 1332: * 1333: * A simple block move. 1334: */ 1335: STATIC void 1336: memcpy(to, from, len) 1337: reg char *to; 1338: reg char *from; 1339: uint len; 1340: { 1341: reg char *toend; 1342: 1343: for (toend = to + len; to < toend; *to++ = *from++) 1344: ; 1345: } 1346: 1347: #endif /* MEMCPY */ 1348: 1349: /* 1350: * memget() 1351: * 1352: * Allocate memory. 1353: */ 1354: STATIC char * 1355: memget(len) 1356: uint len; 1357: { 1358: reg char *mem; 1359: static short outofmem; 1360: 1361: if ((mem = malloc(len)) == NULL && !outofmem) 1362: outofmem = warn("memget()", "Out of memory"); 1363: return (mem); 1364: } 1365: 1366: /* 1367: * memstr() 1368: * 1369: * Duplicate a string into dynamic memory. 1370: */ 1371: STATIC char * 1372: memstr(str) 1373: reg char *str; 1374: { 1375: reg char *mem; 1376: 1377: if (mem = memget((uint) strlen(str) + 1)) 1378: VOID strcpy(mem, str); 1379: return (mem); 1380: } 1381: 1382: #ifndef MKDIR 1383: 1384: /* 1385: * mkdir() 1386: * 1387: * Make a directory via "/bin/mkdir". Sets errno to a 1388: * questionably sane value upon failure. 1389: */ 1390: STATIC int 1391: mkdir(name, mode) 1392: reg char *name; 1393: reg ushort mode; 1394: { 1395: reg int pid; 1396: 1397: if ((pid = xfork("mkdir()")) == 0) { 1398: VOID close(fileno(stdin)); 1399: VOID close(fileno(stdout)); 1400: VOID close(fileno(stderr)); 1401: VOID open("/dev/null", O_RDWR); 1402: VOID dup(fileno(stdin)); 1403: VOID dup(fileno(stdin)); 1404: VOID umask(~mode); 1405: VOID execl("/bin/mkdir", "mkdir", name, (char *) NULL); 1406: exit(1); 1407: } 1408: if (xwait(pid, "mkdir()") == 0) 1409: return (0); 1410: errno = EACCES; 1411: return (-1); 1412: } 1413: 1414: #endif /* MKDIR */ 1415: 1416: /* 1417: * nameadd() 1418: * 1419: * Add a name to the pattern list. 1420: */ 1421: STATIC void 1422: nameadd(name, not) 1423: reg char *name; 1424: int not; 1425: { 1426: reg Pattern *px; 1427: 1428: px = (Pattern *) memget(sizeof(Pattern)); 1429: px->p_forw = pattern; 1430: px->p_str = name; 1431: px->p_len = strlen(name); 1432: px->p_not = not; 1433: pattern = px; 1434: } 1435: 1436: /* 1437: * namecmp() 1438: * 1439: * Compare a pathname with the pattern list. Returns 0 for 1440: * a match, -1 otherwise. 1441: */ 1442: STATIC int 1443: namecmp(name) 1444: reg char *name; 1445: { 1446: reg Pattern *px; 1447: reg int positive; 1448: reg int match; 1449: 1450: positive = match = 0; 1451: for (px = pattern; px; px = px->p_forw) { 1452: if (!px->p_not) 1453: ++positive; 1454: if (strncmp(name, px->p_str, px->p_len) == 0 1455: && (name[px->p_len] == '/' || name[px->p_len] == '\0')) { 1456: if (px->p_not) 1457: return (-1); 1458: ++match; 1459: } 1460: } 1461: return (match || !positive ? 0 : -1); 1462: } 1463: 1464: /* 1465: * nameopt() 1466: * 1467: * Optimize a pathname. Confused by "<symlink>/.." twistiness. 1468: * Returns the number of final pathname elements (zero for "/" 1469: * or ".") or -1 if unsuccessful. 1470: */ 1471: STATIC int 1472: nameopt(begin) 1473: char *begin; 1474: { 1475: reg char *name; 1476: reg char *item; 1477: reg int idx; 1478: int absolute; 1479: auto char *element[PATHELEM]; 1480: 1481: absolute = (*(name = begin) == '/'); 1482: idx = 0; 1483: for (;;) { 1484: if (idx == PATHELEM) 1485: return (warn(begin, "Too many elements")); 1486: while (*name == '/') 1487: ++name; 1488: if (*name == '\0') 1489: break; 1490: element[idx] = item = name; 1491: while (*name && *name != '/') 1492: ++name; 1493: if (*name) 1494: *name++ = '\0'; 1495: if (strcmp(item, "..") == 0) 1496: if (idx == 0) 1497: if (absolute) 1498: ; 1499: else 1500: ++idx; 1501: else if (strcmp(element[idx - 1], "..") == 0) 1502: ++idx; 1503: else 1504: --idx; 1505: else if (strcmp(item, ".") != 0) 1506: ++idx; 1507: } 1508: if (idx == 0) 1509: element[idx++] = absolute ? "" : "."; 1510: element[idx] = NULL; 1511: name = begin; 1512: if (absolute) 1513: *name++ = '/'; 1514: for (idx = 0; item = element[idx]; ++idx, *name++ = '/') 1515: while (*item) 1516: *name++ = *item++; 1517: *--name = '\0'; 1518: return (idx); 1519: } 1520: 1521: /* 1522: * next() 1523: * 1524: * Advance to the next archive volume. 1525: */ 1526: STATIC void 1527: next(mode, why) 1528: reg int mode; 1529: reg char *why; 1530: { 1531: reg time_t began; 1532: auto char msg[200]; 1533: auto char answer[20]; 1534: 1535: began = time((time_t *) NULL); 1536: nextclos(); 1537: VOID warnarch(why, (off_t) 0); 1538: if (arfd == STDIN || arfd == STDOUT) 1539: exit(1); 1540: VOID sprintf(msg, "\ 1541: %s: Ready for volume %u on \"%s\"\n\ 1542: %s: Type \"go\" when ready to proceed (or \"quit\" to abort): \07", 1543: myname, arvolume + 1, arspec, myname); 1544: for (;;) { 1545: nextask(msg, answer, sizeof(answer)); 1546: if (strcmp(answer, "quit") == 0) 1547: fatal(arspec, "Aborted"); 1548: if (strcmp(answer, "go") == 0 && nextopen(mode) == 0) 1549: break; 1550: } 1551: VOID warnarch("Continuing", (off_t) 0); 1552: timewait += time((time_t *) NULL) - began; 1553: } 1554: 1555: /* 1556: * nextask() 1557: * 1558: * Ask a question and get a response. Ignores spaces and tabs. 1559: */ 1560: STATIC void 1561: nextask(msg, answer, limit) 1562: reg char *msg; 1563: reg char *answer; 1564: reg int limit; 1565: { 1566: reg int idx; 1567: reg int got; 1568: auto char c; 1569: 1570: if (ttyf < 0) 1571: fatal(TTY, "Unavailable"); 1572: VOID write(ttyf, msg, (uint) strlen(msg)); 1573: idx = 0; 1574: while ((got = read(ttyf, &c, 1)) == 1) 1575: if (c == '\04' || c == '\n') 1576: break; 1577: else if (c == ' ' || c == '\t') 1578: continue; 1579: else if (idx < limit - 1) 1580: answer[idx++] = c; 1581: if (got < 0) 1582: fatal(TTY, syserr()); 1583: answer[idx] = '\0'; 1584: } 1585: 1586: /* 1587: * nextclos() 1588: * 1589: * Close an archive. 1590: */ 1591: STATIC void 1592: nextclos() 1593: { 1594: if (arfd != STDIN && arfd != STDOUT) 1595: VOID close(arfd); 1596: areof = 0; 1597: if (arname && *arname == '!') 1598: pipewait(); 1599: } 1600: 1601: /* 1602: * nextopen() 1603: * 1604: * Open an archive. Returns 0 if successful, -1 otherwise. 1605: */ 1606: STATIC int 1607: nextopen(mode) 1608: int mode; 1609: { 1610: if (*arname == '!') 1611: arfd = pipeopen(mode); 1612: else if (strcmp(arname, "-") == 0) 1613: arfd = mode ? STDOUT : STDIN; 1614: else { 1615: #ifdef CTC3B2 1616: if (Cflag) { 1617: reg int oops; 1618: reg int fd; 1619: 1620: oops = ((fd = open(arname, O_RDWR | O_CTSPECIAL)) < 0 1621: || ioctl(fd, STREAMON) < 0); 1622: VOID close(fd); 1623: if (oops) 1624: return (warnarch(syserr(), (off_t) 0)); 1625: } 1626: #endif /* CTC3B2 */ 1627: arfd = mode ? creat(arname, 0666 & ~mask) : open(arname, mode); 1628: } 1629: if (arfd < 0) 1630: return (warnarch(syserr(), (off_t) 0)); 1631: arleft = aruntil; 1632: ++arvolume; 1633: return (0); 1634: } 1635: 1636: /* 1637: * openi() 1638: * 1639: * Open the next input file. Returns a file descriptor, 0 if no data 1640: * exists, or -1 at EOF. This kludge works because standard input is 1641: * in use, preventing open() from returning zero. 1642: */ 1643: STATIC int 1644: openi(name, asb) 1645: char *name; 1646: reg Stat *asb; 1647: { 1648: reg int fd; 1649: auto char local[PATHSIZE]; 1650: 1651: for (;;) { 1652: if (lineget(stdin, name) < 0) 1653: return (-1); 1654: if (nameopt(name) < 0) 1655: continue; 1656: if (!gflag) 1657: VOID strcpy(local, name); 1658: else if (dirchg(name, local) < 0) 1659: continue; 1660: if ((hflag ? STAT(local, asb) : LSTAT(local, asb)) < 0) { 1661: VOID warn(name, syserr()); 1662: continue; 1663: } 1664: switch (asb->sb_mode & S_IFMT) { 1665: case S_IFDIR: 1666: asb->sb_nlink = 1; 1667: asb->sb_size = 0; 1668: return (0); 1669: #ifdef S_IFLNK 1670: case S_IFLNK: 1671: if ((asb->sb_size = readlink(local, 1672: asb->sb_link, sizeof(asb->sb_link) - 1)) < 0) { 1673: VOID warn(name, syserr()); 1674: continue; 1675: } 1676: asb->sb_link[asb->sb_size] = '\0'; 1677: return (0); 1678: #endif /* S_IFLNK */ 1679: case S_IFREG: 1680: if (asb->sb_size == 0) 1681: return (0); 1682: if ((fd = open(local, O_RDONLY)) >= 0) 1683: return (fd); 1684: VOID warn(name, syserr()); 1685: break; 1686: default: 1687: asb->sb_size = 0; 1688: return (0); 1689: } 1690: } 1691: } 1692: 1693: /* 1694: * openo() 1695: * 1696: * Open an output file. Returns the output file descriptor, 1697: * 0 if no data is required or -1 if unsuccessful. Note that 1698: * UNIX open() will never return 0 because the standard input 1699: * is in use. 1700: */ 1701: STATIC int 1702: openo(name, asb, linkp, ispass) 1703: char *name; 1704: reg Stat *asb; 1705: Link *linkp; 1706: reg int ispass; 1707: { 1708: reg int exists; 1709: reg int fd; 1710: reg ushort perm; 1711: ushort operm; 1712: Path *path; 1713: auto Stat osb; 1714: #ifdef S_IFLNK 1715: reg int ssize; 1716: auto char sname[PATHSIZE]; 1717: #endif /* S_IFLNK */ 1718: 1719: if (exists = (LSTAT(name, &osb) == 0)) 1720: if (ispass 1721: && osb.sb_ino == asb->sb_ino 1722: && osb.sb_dev == asb->sb_dev) 1723: return (warn(name, "Same file")); 1724: else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT)) 1725: operm = osb.sb_mode & (xflag ? S_IPERM : S_IPOPN); 1726: else if (remove(name, &osb) < 0) 1727: return (warn(name, syserr())); 1728: else 1729: exists = 0; 1730: if (linkp) { 1731: if (exists) 1732: if (asb->sb_ino == osb.sb_ino 1733: && asb->sb_dev == osb.sb_dev) 1734: return (0); 1735: else if (unlink(name) < 0) 1736: return (warn(name, syserr())); 1737: else 1738: exists = 0; 1739: for (path = linkp->l_path; path; path = path->p_forw) 1740: if (link(path->p_name, name) == 0 1741: || (errno == ENOENT 1742: && dirneed(name) == 0 1743: && link(path->p_name, name) == 0)) 1744: return (0); 1745: else if (errno != EXDEV) 1746: return (warn(name, syserr())); 1747: VOID warn(name, "Link broken"); 1748: linkalso(linkp, name); 1749: } 1750: perm = asb->sb_mode & (xflag ? S_IPERM : S_IPOPN); 1751: switch (asb->sb_mode & S_IFMT) { 1752: case S_IFBLK: 1753: case S_IFCHR: 1754: fd = 0; 1755: if (exists) 1756: if (asb->sb_rdev == osb.sb_rdev) 1757: if (perm != operm && chmod(name, perm) < 0) 1758: return (warn(name, syserr())); 1759: else 1760: break; 1761: else if (remove(name, &osb) < 0) 1762: return (warn(name, syserr())); 1763: else 1764: exists = 0; 1765: if (mknod(name, asb->sb_mode, asb->sb_rdev) < 0 1766: && (errno != ENOENT 1767: || dirneed(name) < 0 1768: || mknod(name, asb->sb_mode, asb->sb_rdev) < 0)) 1769: return (warn(name, syserr())); 1770: break; 1771: case S_IFDIR: 1772: if (exists) 1773: if (perm != operm && chmod(name, perm) < 0) 1774: return (warn(name, syserr())); 1775: else 1776: ; 1777: else if (dirneed(name) < 0 || dirmake(name, asb) < 0) 1778: return (warn(name, syserr())); 1779: return (0); 1780: #ifdef S_IFIFO 1781: case S_IFIFO: 1782: fd = 0; 1783: if (exists) 1784: if (perm != operm && chmod(name, perm) < 0) 1785: return (warn(name, syserr())); 1786: else 1787: ; 1788: else if (mknod(name, asb->sb_mode, (dev_t) 0) < 0 1789: && (errno != ENOENT 1790: || dirneed(name) < 0 1791: || mknod(name, asb->sb_mode, (dev_t) 0) < 0)) 1792: return (warn(name, syserr())); 1793: break; 1794: #endif /* S_IFIFO */ 1795: #ifdef S_IFLNK 1796: case S_IFLNK: 1797: if (exists) 1798: if ((ssize = readlink(name, sname, sizeof(sname))) < 0) 1799: return (warn(name, syserr())); 1800: else if (strncmp(sname, asb->sb_link, ssize) == 0) 1801: return (0); 1802: else if (remove(name, &osb) < 0) 1803: return (warn(name, syserr())); 1804: else 1805: exists = 0; 1806: if (symlink(asb->sb_link, name) < 0 1807: && (errno != ENOENT 1808: || dirneed(name) < 0 1809: || symlink(asb->sb_link, name) < 0)) 1810: return (warn(name, syserr())); 1811: return (0); /* Can't chown()/chmod() a symbolic link */ 1812: #endif /* S_IFLNK */ 1813: case S_IFREG: 1814: if (exists) 1815: if (nflag && osb.sb_mtime > asb->sb_mtime) 1816: return (warn(name, "Newer file exists")); 1817: else if (unlink(name) < 0) 1818: return (warn(name, syserr())); 1819: else 1820: exists = 0; 1821: if ((fd = creat(name, perm)) < 0 1822: && (errno != ENOENT 1823: || dirneed(name) < 0 1824: || (fd = creat(name, perm)) < 0)) 1825: return (warn(name, syserr())); 1826: break; 1827: default: 1828: return (warn(name, "Unknown filetype")); 1829: } 1830: if (xflag 1831: && (!exists 1832: || asb->sb_uid != osb.sb_uid 1833: || asb->sb_gid != osb.sb_gid)) 1834: VOID chown(name, 1835: uid == 0 ? ush(asb->sb_uid) : uid, 1836: ush(asb->sb_gid)); 1837: if (linkp == NULL && asb->sb_nlink > 1) 1838: VOID linkto(name, asb); 1839: return (fd); 1840: } 1841: 1842: /* 1843: * openq() 1844: * 1845: * Open the terminal for interactive queries (sigh). Assumes that 1846: * background processes ignore interrupts and that the open() or 1847: * the isatty() will fail for processes which are not attached to 1848: * terminals. Returns a file descriptor (-1 if unsuccessful). 1849: */ 1850: STATIC int 1851: openq() 1852: { 1853: reg int fd; 1854: reg VOIDFN (*intr)(); 1855: 1856: if ((intr = signal(SIGINT, SIG_IGN)) == SIG_IGN) 1857: return (-1); 1858: VOID signal(SIGINT, intr); 1859: if ((fd = open(TTY, O_RDWR)) < 0) 1860: return (-1); 1861: if (isatty(fd)) 1862: return (fd); 1863: VOID close(fd); 1864: return (-1); 1865: } 1866: 1867: /* 1868: * options() 1869: * 1870: * Decode most reasonable forms of UNIX option syntax. Takes main()- 1871: * style argument indices (argc/argv) and a string of valid option 1872: * letters. Letters denoting options with arguments must be followed 1873: * by colons. With valid options, returns the option letter and points 1874: * "optarg" at the associated argument (if any). Returns '?' for bad 1875: * options and missing arguments. Returns zero when no options remain, 1876: * leaving "optind" indexing the first remaining argument. 1877: */ 1878: STATIC int 1879: options(ac, av, proto) 1880: int ac; 1881: register char **av; 1882: char *proto; 1883: { 1884: register int c; 1885: register char *idx; 1886: static int optsub; 1887: 1888: if (optind == 0) { 1889: optind = 1; 1890: optsub = 0; 1891: } 1892: optarg = NULL; 1893: if (optind >= ac) 1894: return (0); 1895: if (optsub == 0 && (av[optind][0] != '-' || av[optind][1] == '\0')) 1896: return (0); 1897: switch (c = av[optind][++optsub]) { 1898: case '\0': 1899: ++optind; 1900: optsub = 0; 1901: return (options(ac, av, proto)); 1902: case '-': 1903: ++optind; 1904: optsub = 0; 1905: return (0); 1906: case ':': 1907: return ('?'); 1908: } 1909: if ((idx = strchr(proto, c)) == NULL) 1910: return ('?'); 1911: if (idx[1] != ':') 1912: return (c); 1913: optarg = &av[optind][++optsub]; 1914: ++optind; 1915: optsub = 0; 1916: if (*optarg) 1917: return (c); 1918: if (optind >= ac) 1919: return ('?'); 1920: optarg = av[optind++]; 1921: return (c); 1922: } 1923: 1924: /* 1925: * optsize() 1926: * 1927: * Interpret a "size" argument. Recognizes suffices for blocks 1928: * (512-byte), kilobytes and megabytes and blocksize. Returns 1929: * the size in bytes. 1930: */ 1931: STATIC off_t 1932: optsize(str) 1933: char *str; 1934: { 1935: reg char *idx; 1936: reg off_t number; 1937: reg off_t result; 1938: 1939: result = 0; 1940: idx = str; 1941: for (;;) { 1942: number = 0; 1943: while (*idx >= '0' && *idx <= '9') 1944: number = number * 10 + *idx++ - '0'; 1945: switch (*idx++) { 1946: case 'b': 1947: result += number * 512; 1948: continue; 1949: case 'k': 1950: result += number * 1024; 1951: continue; 1952: case 'm': 1953: result += number * 1024 * 1024; 1954: continue; 1955: case 'x': 1956: result += number * arbsize; 1957: continue; 1958: case '+': 1959: result += number; 1960: continue; 1961: case '\0': 1962: result += number; 1963: break; 1964: default: 1965: break; 1966: } 1967: break; 1968: } 1969: if (*--idx) 1970: fatal(str, "Unrecognizable value"); 1971: return (result); 1972: } 1973: 1974: /* 1975: * out() 1976: * 1977: * Write an archive. 1978: */ 1979: STATIC VOIDFN 1980: out(av) 1981: char **av; 1982: { 1983: reg int fd; 1984: auto Stat sb; 1985: auto char name[PATHSIZE]; 1986: 1987: if (*av) 1988: fatal(*av, "Extraneous argument"); 1989: while ((fd = openi(name, &sb)) >= 0) { 1990: if (!lflag && sb.sb_nlink > 1) 1991: if (linkfrom(&sb)) 1992: sb.sb_size = 0; 1993: else 1994: VOID linkto(name, &sb); 1995: outhead(name, &sb); 1996: if (fd) 1997: VOID close(outdata(fd, name, sb.sb_size)); 1998: if (vflag) 1999: VOID fprintf(stderr, "%s\n", name); 2000: } 2001: outeof(TRAILER, TRAILZ); 2002: } 2003: 2004: /* 2005: * outalloc() 2006: * 2007: * Allocate buffer space previously referenced by outavail(). 2008: */ 2009: STATIC void 2010: outalloc(len) 2011: reg uint len; 2012: { 2013: bufidx += len; 2014: total += len; 2015: } 2016: 2017: /* 2018: * outavail() 2019: * 2020: * Index buffer space for archive output. Stores a buffer pointer 2021: * at a given location. Returns the number of bytes available. 2022: */ 2023: STATIC uint 2024: outavail(bufp) 2025: reg char **bufp; 2026: { 2027: reg uint have; 2028: 2029: while ((have = bufend - bufidx) == 0) 2030: outflush(); 2031: *bufp = bufidx; 2032: return (have); 2033: } 2034: 2035: /* 2036: * outdata() 2037: * 2038: * Write archive data. Continues after file read errors, padding with 2039: * null characters if neccessary. Always returns the given input file 2040: * descriptor. 2041: */ 2042: STATIC int 2043: outdata(fd, name, size) 2044: int fd; 2045: char *name; 2046: reg off_t size; 2047: { 2048: reg uint chunk; 2049: reg int got; 2050: reg int oops; 2051: reg uint avail; 2052: auto char *buf; 2053: 2054: oops = got = 0; 2055: while (size) { 2056: avail = outavail(&buf); 2057: size -= (chunk = size < avail ? (uint) size : avail); 2058: if (oops == 0 && (got = read(fd, buf, chunk)) < 0) { 2059: oops = warn(name, syserr()); 2060: got = 0; 2061: } 2062: if (got < chunk) { 2063: if (oops == NULL) 2064: oops = warn(name, "Early EOF"); 2065: while (got < chunk) 2066: buf[got++] = '\0'; 2067: } 2068: outalloc(chunk); 2069: } 2070: return (fd); 2071: } 2072: 2073: /* 2074: * outeof() 2075: * 2076: * Write an archive trailer. 2077: */ 2078: STATIC void 2079: outeof(name, namelen) 2080: char *name; 2081: reg uint namelen; 2082: { 2083: reg off_t pad; 2084: auto char header[M_STRLEN + H_STRLEN + 1]; 2085: 2086: if (pad = (total + M_STRLEN + H_STRLEN + namelen) % arpad) 2087: pad = arpad - pad; 2088: VOID strcpy(header, M_ASCII); 2089: VOID sprintf(header + M_STRLEN, H_PRINT, 0, 0, 2090: 0, 0, 0, 1, 0, (time_t) 0, namelen, pad); 2091: outwrite(header, M_STRLEN + H_STRLEN); 2092: outwrite(name, namelen); 2093: outpad(pad); 2094: outflush(); 2095: if (fflag) 2096: outwait(); 2097: } 2098: 2099: /* 2100: * outflush() 2101: * 2102: * Flush the output buffer. Optionally fork()s to allow the 2103: * parent to refill the buffer while the child waits for the 2104: * write() to complete. 2105: */ 2106: STATIC void 2107: outflush() 2108: { 2109: reg char *buf; 2110: reg int got; 2111: reg uint len; 2112: 2113: if (aruntil && arleft == 0) 2114: next(O_WRONLY, "Output limit reached"); 2115: if (fflag) { 2116: outwait(); 2117: if ((outpid = xfork("outflush()")) == 0) 2118: VOID nice(-40); 2119: } 2120: if (!fflag || outpid == 0) { 2121: for (buf = buffer; len = bufidx - buf; ) { 2122: if ((got = write(arfd, buf, 2123: *arname == '!' ? len : min(len, arbsize))) > 0) { 2124: buf += got; 2125: arleft -= got; 2126: } else if (fflag) { 2127: VOID warn(arspec, got < 0 2128: ? syserr() 2129: : "Apparently full"); 2130: _exit(1); 2131: } else if (got < 0) 2132: fatal(arspec, syserr()); 2133: else 2134: next(O_WRONLY, "Apparently full"); 2135: } 2136: } 2137: if (fflag) { 2138: if (outpid == 0) 2139: _exit(0); 2140: else 2141: arleft -= bufidx - buffer; 2142: } 2143: bufend = (bufidx = buffer) + (aruntil ? min(buflen, arleft) : buflen); 2144: } 2145: 2146: /* 2147: * outhead() 2148: * 2149: * Write an archive header. 2150: */ 2151: STATIC void 2152: outhead(name, asb) 2153: reg char *name; 2154: reg Stat *asb; 2155: { 2156: reg uint namelen; 2157: auto char header[M_STRLEN + H_STRLEN + 1]; 2158: 2159: if (name[0] == '/') 2160: if (name[1]) 2161: ++name; 2162: else 2163: name = "."; 2164: namelen = (uint) strlen(name) + 1; 2165: VOID strcpy(header, M_ASCII); 2166: VOID sprintf(header + M_STRLEN, H_PRINT, ush(asb->sb_dev), 2167: ush(asb->sb_ino), ush(asb->sb_mode), ush(asb->sb_uid), 2168: ush(asb->sb_gid), ush(asb->sb_nlink), ush(asb->sb_rdev), 2169: mflag ? timenow : asb->sb_mtime, namelen, asb->sb_size); 2170: outwrite(header, M_STRLEN + H_STRLEN); 2171: outwrite(name, namelen); 2172: #ifdef S_IFLNK 2173: if ((asb->sb_mode & S_IFMT) == S_IFLNK) 2174: outwrite(asb->sb_link, (uint) asb->sb_size); 2175: #endif /* S_IFLNK */ 2176: } 2177: 2178: /* 2179: * outpad() 2180: * 2181: * Pad the archive. 2182: */ 2183: STATIC void 2184: outpad(pad) 2185: reg off_t pad; 2186: { 2187: reg int idx; 2188: reg int len; 2189: 2190: while (pad) { 2191: if ((len = bufend - bufidx) > pad) 2192: len = pad; 2193: for (idx = 0; idx < len; ++idx) 2194: *bufidx++ = '\0'; 2195: total += len; 2196: outflush(); 2197: pad -= len; 2198: } 2199: } 2200: 2201: /* 2202: * outwait() 2203: * 2204: * Wait for the last background outflush() process (if any). The child 2205: * exit value is zero if successful, 255 if a write() returned zero or 2206: * the value of errno if a write() was unsuccessful. 2207: */ 2208: STATIC void 2209: outwait() 2210: { 2211: auto int status; 2212: 2213: if (outpid == 0) 2214: return; 2215: status = xwait(outpid, "outwait()"); 2216: outpid = 0; 2217: if (status) 2218: fatal(arspec, "Child error"); 2219: } 2220: 2221: /* 2222: * outwrite() 2223: * 2224: * Write archive data. 2225: */ 2226: STATIC void 2227: outwrite(idx, len) 2228: reg char *idx; 2229: uint len; 2230: { 2231: reg uint have; 2232: reg uint want; 2233: reg char *endx = idx + len; 2234: 2235: while (want = endx - idx) { 2236: while ((have = bufend - bufidx) == 0) 2237: outflush(); 2238: if (have > want) 2239: have = want; 2240: memcpy(bufidx, idx, have); 2241: bufidx += have; 2242: idx += have; 2243: total += have; 2244: } 2245: } 2246: 2247: /* 2248: * pass() 2249: * 2250: * Copy within the filesystem. 2251: */ 2252: STATIC VOIDFN 2253: pass(av) 2254: reg char **av; 2255: { 2256: reg int fd; 2257: reg char **avx; 2258: auto Stat sb; 2259: auto char name[PATHSIZE]; 2260: 2261: for (avx = av; *avx; ++avx) { 2262: if (gflag && **avx != '/') 2263: fatal(*avx, "Relative pathname"); 2264: if (STAT(*avx, &sb) < 0) 2265: fatal(*avx, syserr()); 2266: if ((sb.sb_mode & S_IFMT) != S_IFDIR) 2267: fatal(*avx, "Not a directory"); 2268: } 2269: while ((fd = openi(name, &sb)) >= 0) { 2270: if (passitem(name, &sb, fd, av)) 2271: VOID close(fd); 2272: if (vflag) 2273: VOID fprintf(stderr, "%s\n", name); 2274: } 2275: } 2276: 2277: /* 2278: * passdata() 2279: * 2280: * Copy data to one file. Doesn't believe in input file 2281: * descriptor zero (see description of kludge in openi() 2282: * comments). Closes the provided output file descriptor. 2283: */ 2284: STATIC void 2285: passdata(from, ifd, to, ofd) 2286: char *from; 2287: reg int ifd; 2288: char *to; 2289: reg int ofd; 2290: { 2291: reg int got; 2292: reg int sparse; 2293: auto char block[FSBUF]; 2294: 2295: if (ifd) { 2296: VOID lseek(ifd, (off_t) 0, 0); 2297: sparse = 0; 2298: while ((got = read(ifd, block, sizeof(block))) > 0 2299: && (sparse = swrite(ofd, block, (uint) got)) >= 0) 2300: total += got; 2301: if (got) 2302: VOID warn(got < 0 ? from : to, syserr()); 2303: else if (sparse > 0 2304: && (lseek(ofd, (off_t) -sparse, 1) < 0 2305: || write(ofd, block, (uint) sparse) != sparse)) 2306: VOID warn(to, syserr()); 2307: } 2308: VOID close(ofd); 2309: } 2310: 2311: /* 2312: * passitem() 2313: * 2314: * Copy one file. Returns given input file descriptor. 2315: */ 2316: STATIC int 2317: passitem(from, asb, ifd, dir) 2318: char *from; 2319: Stat *asb; 2320: reg int ifd; 2321: reg char **dir; 2322: { 2323: reg int ofd; 2324: auto time_t tstamp[2]; 2325: auto char to[PATHSIZE]; 2326: 2327: while (*dir) { 2328: if (nameopt(strcat(strcat(strcpy(to, *dir++), "/"), from)) < 0) 2329: continue; 2330: if ((ofd = openo(to, asb, 2331: lflag ? linkto(from, asb) : linkfrom(asb), 1)) < 0) 2332: continue; 2333: if (ofd > 0) 2334: passdata(from, ifd, to, ofd); 2335: tstamp[0] = tstamp[1] = mflag ? timenow : asb->sb_mtime; 2336: VOID utime(to, tstamp); 2337: } 2338: return (ifd); 2339: } 2340: 2341: /* 2342: * pipechld() 2343: * 2344: * Child portion of pipeline fork. 2345: */ 2346: STATIC int 2347: pipechld(mode, pfd) 2348: int mode; 2349: reg int *pfd; 2350: { 2351: reg char **av; 2352: auto char *arg[32]; 2353: 2354: av = arg; 2355: if ((*av = getenv("SHELL")) && **av) 2356: ++av; 2357: else 2358: *av++ = "/bin/sh"; 2359: *av++ = "-c"; 2360: *av++ = arname + 1; 2361: *av = NULL; 2362: if (mode) { 2363: VOID close(pfd[1]); 2364: VOID close(STDIN); 2365: VOID dup(pfd[0]); 2366: VOID close(pfd[0]); 2367: VOID close(STDOUT); 2368: VOID open("/dev/null", O_WRONLY); 2369: } else { 2370: VOID close(STDIN); 2371: VOID open("/dev/null", O_RDONLY); 2372: VOID close(pfd[0]); 2373: VOID close(STDOUT); 2374: VOID dup(pfd[1]); 2375: VOID close(pfd[1]); 2376: } 2377: if (ttyf >= 0) 2378: VOID close(ttyf); 2379: VOID execvp(arg[0], arg); 2380: VOID warn(arg[0], syserr()); 2381: _exit(1); 2382: } 2383: 2384: /* 2385: * pipeopen() 2386: * 2387: * Open an archive via a pipeline. Returns a file 2388: * descriptor, or -1 if unsuccessful. 2389: */ 2390: STATIC int 2391: pipeopen(mode) 2392: reg int mode; 2393: { 2394: auto int pfd[2]; 2395: 2396: if (pipe(pfd) < 0) 2397: return (-1); 2398: if ((pipepid = xfork("pipeopen()")) == 0) 2399: pipechld(mode, pfd); 2400: if (mode) { 2401: VOID close(pfd[0]); 2402: return (pfd[1]); 2403: } else { 2404: VOID close(pfd[1]); 2405: return (pfd[0]); 2406: } 2407: } 2408: 2409: /* 2410: * pipewait() 2411: * 2412: * Await a pipeline. 2413: */ 2414: STATIC void 2415: pipewait() 2416: { 2417: reg int status; 2418: 2419: if (pipepid == 0) 2420: return; 2421: status = xwait(pipepid, "pipewait()"); 2422: pipepid = 0; 2423: if (status) 2424: fatal(arspec, "Pipeline error"); 2425: } 2426: 2427: /* 2428: * prsize() 2429: * 2430: * Print a file offset. 2431: */ 2432: STATIC void 2433: prsize(stream, size) 2434: FILE *stream; 2435: reg off_t size; 2436: { 2437: reg off_t n; 2438: 2439: if (n = (size / (1024 * 1024))) { 2440: VOID fprintf(stream, "%ldm+", n); 2441: size -= n * 1024 * 1024; 2442: } 2443: if (n = (size / 1024)) { 2444: VOID fprintf(stream, "%ldk+", n); 2445: size -= n * 1024; 2446: } 2447: VOID fprintf(stream, "%ld", size); 2448: } 2449: 2450: #ifndef MKDIR 2451: 2452: /* 2453: * rmdir() 2454: * 2455: * Remove a directory via "/bin/rmdir". Sets errno to a 2456: * questionably sane value upon failure. 2457: */ 2458: STATIC int 2459: rmdir(name) 2460: reg char *name; 2461: { 2462: reg int pid; 2463: 2464: if ((pid = xfork("rmdir()")) == 0) { 2465: VOID close(fileno(stdin)); 2466: VOID close(fileno(stdout)); 2467: VOID close(fileno(stderr)); 2468: VOID open("/dev/null", O_RDWR); 2469: VOID dup(fileno(stdin)); 2470: VOID dup(fileno(stdin)); 2471: VOID execl("/bin/rmdir", "rmdir", name, (char *) NULL); 2472: exit(1); 2473: } 2474: if (xwait(pid, "rmdir()") == 0) 2475: return (0); 2476: errno = EACCES; 2477: return (-1); 2478: } 2479: 2480: #endif /* MKDIR */ 2481: 2482: /* 2483: * swrite() 2484: * 2485: * Write a filesystem block. Seeks past sparse blocks. Returns 2486: * 0 if the block was written, the given length for a sparse 2487: * block or -1 if unsuccessful. 2488: */ 2489: STATIC int 2490: swrite(fd, buf, len) 2491: int fd; 2492: char *buf; 2493: uint len; 2494: { 2495: reg char *bidx; 2496: reg char *bend; 2497: 2498: if (jflag) 2499: return (write(fd, buf, len) == len ? 0 : -1); 2500: bend = (bidx = buf) + len; 2501: while (bidx < bend) 2502: if (*bidx++) 2503: return (write(fd, buf, len) == len ? 0 : -1); 2504: return (lseek(fd, (off_t) len, 1) < 0 ? -1 : len); 2505: } 2506: 2507: /* 2508: * syserr() 2509: * 2510: * Return pointer to appropriate system error message. 2511: */ 2512: char * 2513: syserr() 2514: { 2515: 2516: return (strerror(errno)); 2517: } 2518: 2519: /* 2520: * toc() 2521: * 2522: * Print archive table of contents. 2523: */ 2524: STATIC VOIDFN 2525: toc(av) 2526: reg char **av; 2527: { 2528: auto Stat sb; 2529: auto char name[PATHSIZE]; 2530: 2531: if (*av) 2532: fatal(*av, "Extraneous argument"); 2533: name[0] = '\0'; 2534: while (inhead(name, &sb) == 0) { 2535: if (namecmp(name) == 0) 2536: tocentry(name, &sb); 2537: if (inskip(sb.sb_size) < 0) 2538: VOID warn(name, "File data is corrupt"); 2539: } 2540: } 2541: 2542: /* 2543: * tocentry() 2544: * 2545: * Print a single table-of-contents entry. 2546: */ 2547: STATIC void 2548: tocentry(name, asb) 2549: char *name; 2550: reg Stat *asb; 2551: { 2552: reg Time *atm; 2553: reg Link *from; 2554: reg Passwd *pwp; 2555: reg Group *grp; 2556: static char *month[] = { 2557: "Jan", "Feb", "Mar", "Apr", "May", "Jun", 2558: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 2559: }; 2560: 2561: if (vflag) { 2562: tocmode(asb->sb_mode); 2563: VOID printf(" %2d", asb->sb_nlink); 2564: atm = localtime(&asb->sb_mtime); 2565: if (pwp = getpwuid(ush(asb->sb_uid))) 2566: VOID printf(" %-8s", pwp->pw_name); 2567: else 2568: VOID printf(" %-8u", ush(asb->sb_uid)); 2569: if (grp = getgrgid(ush(asb->sb_gid))) 2570: VOID printf(" %-8s", grp->gr_name); 2571: else 2572: VOID printf(" %-8u", ush(asb->sb_gid)); 2573: switch (asb->sb_mode & S_IFMT) { 2574: case S_IFBLK: 2575: case S_IFCHR: 2576: VOID printf(" %3d, %3d", 2577: major(asb->sb_rdev), minor(asb->sb_rdev)); 2578: break; 2579: case S_IFREG: 2580: VOID printf(" %8ld", asb->sb_size); 2581: break; 2582: default: 2583: VOID printf(" "); 2584: } 2585: VOID printf(" %3s %2d %02d:%02d:%02d %4d ", 2586: month[atm->tm_mon], atm->tm_mday, atm->tm_hour, 2587: atm->tm_min, atm->tm_sec, atm->tm_year + 1900); 2588: } 2589: VOID printf("%s", name); 2590: if (vflag || lflag) { 2591: if (asb->sb_nlink > 1) 2592: if (from = linkfrom(asb)) 2593: VOID printf(" -> %s", 2594: from->l_path->p_name); 2595: else 2596: VOID linkto(name, asb); 2597: #ifdef S_IFLNK 2598: if ((asb->sb_mode & S_IFMT) == S_IFLNK) 2599: VOID printf(" S-> %s", asb->sb_link); 2600: #endif /* S_IFLNK */ 2601: } 2602: putchar('\n'); 2603: } 2604: 2605: /* 2606: * tocmode() 2607: * 2608: * Fancy file mode display. 2609: */ 2610: STATIC void 2611: tocmode(mode) 2612: reg ushort mode; 2613: { 2614: switch (mode & S_IFMT) { 2615: case S_IFREG: putchar('-'); break; 2616: case S_IFDIR: putchar('d'); break; 2617: #ifdef S_IFLNK 2618: case S_IFLNK: putchar('l'); break; 2619: #endif /* S_IFLNK */ 2620: case S_IFBLK: putchar('b'); break; 2621: case S_IFCHR: putchar('c'); break; 2622: #ifdef S_IFIFO 2623: case S_IFIFO: putchar('p'); break; 2624: #endif /* S_IFIFO */ 2625: default: 2626: VOID printf("[%o]", mode >> S_IFSHF); 2627: } 2628: putchar(mode & 0400 ? 'r' : '-'); 2629: putchar(mode & 0200 ? 'w' : '-'); 2630: putchar(mode & 0100 2631: ? mode & 04000 ? 's' : 'x' 2632: : mode & 04000 ? 'S' : '-'); 2633: putchar(mode & 0040 ? 'r' : '-'); 2634: putchar(mode & 0020 ? 'w' : '-'); 2635: putchar(mode & 0010 2636: ? mode & 02000 ? 's' : 'x' 2637: : mode & 02000 ? 'S' : '-'); 2638: putchar(mode & 0004 ? 'r' : '-'); 2639: putchar(mode & 0002 ? 'w' : '-'); 2640: putchar(mode & 0001 2641: ? mode & 01000 ? 't' : 'x' 2642: : mode & 01000 ? 'T' : '-'); 2643: } 2644: 2645: /* 2646: * usage() 2647: * 2648: * Print a helpful message and exit. 2649: */ 2650: STATIC void 2651: usage() 2652: { 2653: VOID fprintf(stderr, "\ 2654: Usage: %s -o [ -fghlmuvz ] [ -(bces) n ] archive\n\ 2655: %s -i [ -djkmnuvxz ] [ -(bcs) n ] [ -y prefix ] archive\n\ 2656: %s -t [ -kuvz ] [ -(bcs) n ] [ -y prefix ] archive\n\ 2657: %s -p [ -dghjlmnuvxz ] dir [ ... ]\n", 2658: myname, myname, myname, myname); 2659: exit(1); 2660: } 2661: 2662: /* 2663: * warn() 2664: * 2665: * Print a warning message. Always returns -1. 2666: */ 2667: STATIC int 2668: warn(what, why) 2669: char *what; 2670: char *why; 2671: { 2672: VOID fprintf(stderr, 2673: "%s: \"%s\": %s\n", 2674: myname, what, why); 2675: return (-1); 2676: } 2677: 2678: /* 2679: * warnarch() 2680: * 2681: * Print an archive-related warning message, including 2682: * an adjusted file offset. Always returns -1. 2683: */ 2684: STATIC int 2685: warnarch(msg, adjust) 2686: char *msg; 2687: off_t adjust; 2688: { 2689: VOID fprintf(stderr, "%s: \"%s\" [offset ", myname, arspec); 2690: prsize(stderr, total - adjust); 2691: VOID fprintf(stderr, "]: %s\n", msg); 2692: return (-1); 2693: } 2694: 2695: /* 2696: * xfork() 2697: * 2698: * Create a child. 2699: */ 2700: STATIC int 2701: xfork(what) 2702: reg char *what; 2703: { 2704: reg int pid; 2705: reg Child *cp; 2706: reg int idx; 2707: static uint delay[] = { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144 }; 2708: 2709: for (idx = 0; (pid = fork()) < 0; ++idx) { 2710: if (idx == sizeof(delay)) 2711: fatal(arspec, syserr()); 2712: VOID warn(what, "Trouble forking..."); 2713: sleep(delay[idx]); 2714: } 2715: if (idx) 2716: VOID warn(what, "...successful fork"); 2717: cp = (Child *) memget(sizeof(*cp)); 2718: cp->c_pid = pid; 2719: cp->c_flags = 0; 2720: cp->c_status = 0; 2721: cp->c_forw = children; 2722: children = cp; 2723: return (pid); 2724: } 2725: 2726: /* 2727: * xpause() 2728: * 2729: * Await a child. 2730: */ 2731: STATIC void 2732: xpause() 2733: { 2734: reg Child *cp; 2735: reg int pid; 2736: auto int status; 2737: 2738: do { 2739: while ((pid = wait(&status)) < 0) 2740: ; 2741: for (cp = children; cp && cp->c_pid != pid; cp = cp->c_forw) 2742: ; 2743: } while (cp == NULL); 2744: cp->c_flags |= CF_EXIT; 2745: cp->c_status = status; 2746: } 2747: 2748: /* 2749: * xwait() 2750: * 2751: * Find the status of a child. 2752: */ 2753: STATIC int 2754: xwait(pid, what) 2755: reg int pid; 2756: char *what; 2757: { 2758: reg int status; 2759: reg Child *cp; 2760: reg Child **acp; 2761: auto char why[100]; 2762: 2763: for (acp = &children; cp = *acp; acp = &cp->c_forw) 2764: if (cp->c_pid == pid) 2765: break; 2766: if (cp == NULL) 2767: fatal(what, "Lost child"); 2768: while ((cp->c_flags & CF_EXIT) == 0) 2769: xpause(); 2770: status = cp->c_status; 2771: *acp = cp->c_forw; 2772: free((char *) cp); 2773: if (status == 0) 2774: return (0); 2775: if (status & 0377) 2776: VOID sprintf(why, "Killed by signal %d%s", 2777: status & 0177, status & 0200 ? " -- core dumped" : ""); 2778: else 2779: VOID sprintf(why, "Exit %d", (status >> 8) & 0377); 2780: return (warn(what, why)); 2781: }