home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume12 / afio / part02 / afio.c.P1
Encoding:
Text File  |  1987-10-25  |  29.0 KB  |  1,279 lines

  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 86/12/15 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.  
  38. #ifndef    major
  39. #    include <sys/sysmacros.h>
  40. #endif    /* major */
  41.  
  42. #ifdef    SYSTIME
  43. #    include <sys/time.h>
  44. #else    /* SYSTIME */
  45. #    include <time.h>
  46. #endif    /* SYSTIME */
  47.  
  48. #ifdef    CTC3B2
  49. #    include <sys/vtoc.h>
  50. #    include <sys/ct.h>
  51. #endif    /* CTC3B2 */
  52.  
  53. /*
  54.  * Address link information base.
  55.  */
  56. #define    linkhash(ino)    \
  57.     (linkbase + (ino) % nel(linkbase))
  58.  
  59. /*
  60.  * Mininum value.
  61.  */
  62. #define    min(one, two)    \
  63.     (one < two ? one : two)
  64.  
  65. /*
  66.  * Number of array elements.
  67.  */
  68. #define    nel(a)        \
  69.     (sizeof(a) / sizeof(*(a)))
  70.  
  71. /*
  72.  * Remove a file or directory.
  73.  */
  74. #define    remove(name, asb) \
  75.     (((asb)->sb_mode & S_IFMT) == S_IFDIR ? rmdir(name) : unlink(name))
  76.  
  77. /*
  78.  * Swap bytes.
  79.  */
  80. #define    swab(n)        \
  81.     ((((ushort)(n) >> 8) & 0xff) | (((ushort)(n) << 8) & 0xff00))
  82.  
  83. /*
  84.  * Cast and reduce to unsigned short.
  85.  */
  86. #define    ush(n)        \
  87.     (((ushort) (n)) & 0177777)
  88.  
  89. /*
  90.  * Definitions.
  91.  */
  92. #define    reg    register    /* Convenience */
  93. #define    uint    unsigned int    /* Not always in types.h */
  94. #define    ushort    unsigned short    /* Not always in types.h */
  95. #define    BLOCK    5120        /* Default archive block size */
  96. #define    FSBUF    (8*1024)    /* Filesystem buffer size */
  97. #define    H_COUNT    10        /* Number of items in ASCII header */
  98. #define    H_PRINT    "%06o%06o%06o%06o%06o%06o%06o%011lo%06o%011lo"
  99. #define    H_SCAN    "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6o%11lo"
  100. #define    H_STRLEN 70        /* ASCII header string length */
  101. #define    M_ASCII "070707"    /* ASCII magic number */
  102. #define    M_BINARY 070707        /* Binary magic number */
  103. #define    M_STRLEN 6        /* ASCII magic number length */
  104. #define    NULLDEV    -1        /* Null device code */
  105. #define    NULLINO    0        /* Null inode number */
  106. #define    PATHELEM 256        /* Pathname element count limit */
  107. #define    PATHSIZE 1024        /* Pathname length limit */
  108. #define    S_IFSHF    12        /* File type shift (shb in stat.h) */
  109. #define    S_IPERM    07777        /* File permission bits (shb in stat.h) */
  110. #define    S_IPEXE    07000        /* Special execution bits (shb in stat.h) */
  111. #define    S_IPOPN    0777        /* Open access bits (shb in stat.h) */
  112. #define    STDIN    0        /* Standard input file descriptor */
  113. #define    STDOUT    1        /* Standard output file descriptor */
  114. #define    TTY    "/dev/tty"    /* For volume-change queries */
  115.  
  116. /*
  117.  * Some versions of the portable "C" compiler (PCC) can't handle
  118.  * pointers to functions returning void.
  119.  */
  120. #ifdef    VOIDFIX
  121. #    define    VOIDFN    void    /* Expect "void (*fnptr)()" to work */
  122. #else    /* VOIDFIX */
  123. #    define    VOIDFN    int    /* Avoid PCC "void (*fnptr)()" bug */
  124. #endif    /* VOIDFIX */
  125.  
  126. /*
  127.  * Trailer pathnames. All must be of the same length.
  128.  */
  129. #define    TRAILER    "TRAILER!!!"    /* Archive trailer (cpio compatible) */
  130. #define    TRAILZ    11        /* Trailer pathname length (including null) */
  131.  
  132. /*
  133.  * Open modes; there is no <fcntl.h> with v7 UNIX.
  134.  */
  135. #define    O_RDONLY 0        /* Read-only */
  136. #define    O_WRONLY 1        /* Write-only */
  137. #define    O_RDWR    2        /* Read/write */
  138.  
  139. /*
  140.  * V7 and BSD UNIX use old-fashioned names for a couple of
  141.  * string functions.
  142.  */
  143. #ifdef    INDEX
  144. #    define    strchr    index    /* Forward character search */
  145. #    define    strrchr    rindex    /* Reverse character search */
  146. #endif    /* INDEX */
  147.  
  148. /*
  149.  * Some compilers can't handle void casts.
  150.  */
  151. #ifdef    NOVOID
  152. #    define    VOID        /* Omit void casts */
  153. #else    /* NOVOID */
  154. #    define    VOID    (void)    /* Quiet lint about ignored return values */
  155. #endif    /* NOVOID */
  156.  
  157. /*
  158.  * Adb is more palatable when static functions and variables are
  159.  * declared as globals. Lint gives more useful information when
  160.  * statics are truly static.
  161.  */
  162. #ifdef    lint
  163. #    define    STATIC    static    /* Declare static variables for lint */
  164. #else    /* lint */
  165. #    define    STATIC        /* Make static variables global for adb */
  166. #endif    /* lint */
  167.  
  168. /*
  169.  * Simple types.
  170.  */
  171. typedef struct group    Group;    /* Structure for getgrgid(3) */
  172. typedef struct passwd    Passwd;    /* Structure for getpwuid(3) */
  173. typedef struct tm    Time;    /* Structure for localtime(3) */
  174.  
  175. #ifdef    S_IFLNK
  176.     /*
  177.      * File status with symbolic links. Kludged to hold symbolic
  178.      * link pathname within structure.
  179.      */
  180.     typedef struct {
  181.         struct stat    sb_stat;
  182.         char        sb_link[PATHSIZE];
  183.     } Stat;
  184. #    define    STAT(name, asb)        stat(name, &(asb)->sb_stat)
  185. #    define    FSTAT(fd, asb)        fstat(fd, &(asb)->sb_stat)
  186. #    define    LSTAT(name, asb)    lstat(name, &(asb)->sb_stat)
  187. #    define    sb_dev        sb_stat.st_dev
  188. #    define    sb_ino        sb_stat.st_ino
  189. #    define    sb_mode        sb_stat.st_mode
  190. #    define    sb_nlink    sb_stat.st_nlink
  191. #    define    sb_uid        sb_stat.st_uid
  192. #    define    sb_gid        sb_stat.st_gid
  193. #    define    sb_rdev        sb_stat.st_rdev
  194. #    define    sb_size        sb_stat.st_size
  195. #    define    sb_atime    sb_stat.st_atime
  196. #    define    sb_mtime    sb_stat.st_mtime
  197. #    define    sb_ctime    sb_stat.st_ctime
  198. #    define    sb_blksize    sb_stat.st_blksize
  199. #    define    sb_blocks    sb_stat.st_blocks
  200. #else    /* S_IFLNK */
  201.     /*
  202.      * File status without symbolic links.
  203.      */
  204.     typedef    struct stat    Stat;
  205. #    define    STAT(name, asb)        stat(name, asb)
  206. #    define    FSTAT(fd, asb)        fstat(fd, asb)
  207. #    define    LSTAT(name, asb)    stat(name, asb)
  208. #    define    sb_dev        st_dev
  209. #    define    sb_ino        st_ino
  210. #    define    sb_mode        st_mode
  211. #    define    sb_nlink    st_nlink
  212. #    define    sb_uid        st_uid
  213. #    define    sb_gid        st_gid
  214. #    define    sb_rdev        st_rdev
  215. #    define    sb_size        st_size
  216. #    define    sb_atime    st_atime
  217. #    define    sb_mtime    st_mtime
  218. #    define    sb_ctime    st_ctime
  219. #endif    /* S_IFLNK */
  220.  
  221. /*
  222.  * Binary archive header (obsolete).
  223.  */
  224. typedef struct {
  225.     short    b_dev;            /* Device code */
  226.     ushort    b_ino;            /* Inode number */
  227.     ushort    b_mode;            /* Type and permissions */
  228.     ushort    b_uid;            /* Owner */
  229.     ushort    b_gid;            /* Group */
  230.     short    b_nlink;        /* Number of links */
  231.     short    b_rdev;            /* Real device */
  232.     ushort    b_mtime[2];        /* Modification time (hi/lo) */
  233.     ushort    b_name;            /* Length of pathname (with null) */
  234.     ushort    b_size[2];        /* Length of data */
  235. } Binary;
  236.  
  237. /*
  238.  * Child process structure.
  239.  */
  240. typedef struct child {
  241.     struct child    *c_forw;    /* Forward link */
  242.     int        c_pid;        /* Process ID */
  243.     int        c_flags;    /* Flags (CF_) */
  244.     int        c_status;    /* Exit status */
  245. } Child;
  246.  
  247. /*
  248.  * Child process flags (c_flags).
  249.  */
  250. #define    CF_EXIT    (1<<0)            /* Exited */
  251.  
  252. /*
  253.  * Hard link sources. One or more are chained from each link
  254.  * structure.
  255.  */
  256. typedef struct name {
  257.     struct name    *p_forw;    /* Forward chain (terminated) */
  258.     struct name    *p_back;    /* Backward chain (circular) */
  259.     char        *p_name;    /* Pathname to link from */
  260. } Path;
  261.  
  262. /*
  263.  * File linking information. One entry exists for each unique
  264.  * file with with outstanding hard links.
  265.  */
  266. typedef struct link {
  267.     struct link    *l_forw;    /* Forward chain (terminated) */
  268.     struct link    *l_back;    /* Backward chain (terminated) */
  269.     dev_t        l_dev;        /* Device */
  270.     ino_t        l_ino;        /* Inode */
  271.     ushort        l_nlink;    /* Unresolved link count */
  272.     off_t        l_size;        /* Length */
  273.     Path        *l_path;    /* Pathname(s) to link from */
  274. } Link;
  275.  
  276. /*
  277.  * Pathnames to (or to not) be processed.
  278.  */
  279. typedef struct pattern {
  280.     struct pattern    *p_forw;    /* Forward chain */
  281.     char        *p_str;        /* String */
  282.     int        p_len;        /* Length of string */
  283.     int        p_not;        /* Reverse logic */
  284. } Pattern;
  285.  
  286. /*
  287.  * External functions.
  288.  */
  289. void    _exit();
  290. void    exit();
  291. void    free();
  292. char    *getenv();
  293. ushort    getgid();
  294. Group    *getgrgid();
  295. Passwd    *getpwuid();
  296. ushort    getuid();
  297. Time    *localtime();
  298. off_t    lseek();
  299. char    *malloc();
  300. VOIDFN    (*signal())();
  301. uint    sleep();
  302. char    *strcat();
  303. char    *strchr();
  304. char    *strcpy();
  305. char    *strncpy();
  306. char    *strrchr();
  307. time_t    time();
  308. ushort    umask();
  309.  
  310. /*
  311.  * Internal functions.
  312.  */
  313. VOIDFN    copyin();
  314. VOIDFN    copyout();
  315. int    dirchg();
  316. int    dirmake();
  317. int    dirneed();
  318. void    fatal();
  319. VOIDFN    in();
  320. void    inalloc();
  321. int    inascii();
  322. int    inavail();
  323. int    inbinary();
  324. int    indata();
  325. int    inentry();
  326. int    infill();
  327. int    inhead();
  328. int    inread();
  329. int    inskip();
  330. int    inswab();
  331. int    lineget();
  332. void    linkalso();
  333. Link    *linkfrom();
  334. void    linkleft();
  335. Link    *linkto();
  336. void    memcpy();
  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. extern char    *sys_errlist[];    /* System error messages */
  387. extern int    sys_nerr;    /* Number of sys_errlist entries */
  388.  
  389. /*
  390.  * Static variables.
  391.  */
  392. #ifdef    CTC3B2
  393. STATIC short    Cflag;        /* Enable 3B2 CTC streaming (kludge) */
  394. #endif    /* CTC3B2 */
  395. STATIC short    dflag;        /* Don't create missing directories */
  396. STATIC short    fflag;        /* Fork before writing to archive */
  397. STATIC short    gflag;        /* Change to input file directories */
  398. STATIC short    hflag;        /* Follow symbolic links */
  399. STATIC short    jflag;        /* Don't generate sparse filesystem blocks */
  400. STATIC short    kflag;        /* Skip initial junk to find a header */
  401. STATIC short    lflag;        /* Link rather than copying (when possible) */
  402. STATIC short    mflag;        /* Ignore archived timestamps */
  403. STATIC short    nflag;        /* Keep newer existing files */
  404. STATIC short    uflag;        /* Report files with unseen links */
  405. STATIC short    vflag;        /* Verbose */
  406. STATIC short    xflag;        /* Retain file ownership */
  407. STATIC short    zflag;        /* Print final statistics */
  408. STATIC uint    arbsize = BLOCK;/* Archive block size */
  409. STATIC short    areof;        /* End of input volume reached */
  410. STATIC int    arfd;        /* Archive file descriptor */
  411. STATIC off_t    arleft;        /* Space remaining within current volume */
  412. STATIC char    *arname;    /* Expanded archive name */
  413. STATIC uint    arpad;        /* Final archive block padding boundary */
  414. STATIC char    arspec[PATHSIZE];/* Specified archive name */
  415. STATIC off_t    aruntil;    /* Volume size limit */
  416. STATIC uint    arvolume;    /* Volume number */
  417. STATIC uint    buflen;        /* Archive buffer length */
  418. STATIC char    *buffer;    /* Archive buffer */
  419. STATIC char    *bufidx;    /* Archive buffer index */
  420. STATIC char    *bufend;    /* End of data within archive buffer */
  421. STATIC Child    *children;    /* Child processes */
  422. STATIC ushort    gid;        /* Group ID */
  423. STATIC Link    *linkbase[256];    /* Unresolved link information */
  424. STATIC ushort    mask;        /* File creation mask */
  425. STATIC char    *myname;    /* Arg0 */
  426. STATIC char    *optarg;    /* Option argument */
  427. STATIC int    optind;        /* Command line index */
  428. STATIC int    outpid;        /* Process ID of outstanding outflush() */
  429. STATIC Pattern    *pattern;    /* Pathname matching patterns */
  430. STATIC char    pwd[PATHSIZE];    /* Working directory (with "-g") */
  431. STATIC int    pipepid;    /* Pipeline process ID */
  432. STATIC time_t    timenow;    /* Current time */
  433. STATIC time_t    timewait;    /* Time spent awaiting new media */
  434. STATIC off_t    total;        /* Total number of bytes transferred */
  435. STATIC int    ttyf;        /* For interactive queries (yuk) */
  436. STATIC ushort    uid;        /* User ID */
  437.  
  438. main(ac, av)
  439. int        ac;
  440. reg char    **av;
  441. {
  442.     reg int        c;
  443.     reg uint    group = 1;
  444.     reg VOIDFN    (*fn)() = NULL;
  445.     reg time_t    timedone;
  446.     auto char    remote[PATHSIZE];
  447.  
  448.     if (myname = strrchr(*av, '/'))
  449.         ++myname;
  450.     else
  451.         myname = *av;
  452.     mask = umask(0);
  453.     ttyf = openq();
  454.     uid = getuid();
  455.     gid = getgid();
  456.     if (uid == 0)
  457.         ++xflag;
  458.     VOID signal(SIGPIPE, SIG_IGN);
  459.     while (c = options(ac, av, "ioptIOVCb:c:de:fghjklmns:uvxXy:Y:z")) {
  460.         switch (c) {
  461.         case 'i':
  462.             if (fn)
  463.                 usage();
  464.             fn = in;
  465.             break;
  466.         case 'o':
  467.             if (fn)
  468.                 usage();
  469.             fn = out;
  470.             break;
  471.         case 'p':
  472.             if (fn)
  473.                 usage();
  474.             fn = pass;
  475.             break;
  476.         case 't':
  477.             if (fn)
  478.                 usage();
  479.             fn = toc;
  480.             break;
  481.         case 'I':
  482.             if (fn)
  483.                 usage();
  484.             fn = copyin;
  485.             break;
  486.         case 'O':
  487.             if (fn)
  488.                 usage();
  489.             fn = copyout;
  490.             break;
  491.         case 'V':
  492.             VOID printf("%s\n", ident);
  493.             exit(0);
  494. #ifdef    CTC3B2
  495.         case 'C':
  496.             ++Cflag;
  497.             arbsize = 31 * 512;
  498.             group = 10;
  499.             aruntil = 1469 * 31 * 512;
  500.             break;
  501. #endif    /* CTC3B2 */
  502.         case 'b':
  503.             if ((arbsize = (uint) optsize(optarg)) == 0)
  504.                 fatal(optarg, "Bad block size");
  505.             break;
  506.         case 'c':
  507.             if ((group = (uint) optsize(optarg)) == 0)
  508.                 fatal(optarg, "Bad buffer count");
  509.             break;
  510.         case 'd':
  511.             ++dflag;
  512.             break;
  513.         case 'e':
  514.             arpad = (uint) optsize(optarg);
  515.             break;
  516.         case 'f':
  517.             ++fflag;
  518.             break;
  519.         case 'g':
  520.             ++gflag;
  521.             break;
  522.         case 'h':
  523.             ++hflag;
  524.             break;
  525.         case 'j':
  526.             ++jflag;
  527.             break;
  528.         case 'k':
  529.             ++kflag;
  530.             break;
  531.         case 'l':
  532.             ++lflag;
  533.             break;
  534.         case 'm':
  535.             ++mflag;
  536.             break;
  537.         case 'n':
  538.             ++nflag;
  539.             break;
  540.         case 's':
  541.             aruntil = optsize(optarg);
  542.             break;
  543.         case 'u':
  544.             ++uflag;
  545.             break;
  546.         case 'v':
  547.             ++vflag;
  548.             break;
  549.         case 'x':
  550.             ++xflag;
  551.             break;
  552.         case 'X':
  553.             xflag = 0;
  554.             break;
  555.         case 'y':
  556.             nameadd(optarg, 0);
  557.             break;
  558.         case 'Y':
  559.             nameadd(optarg, 1);
  560.             break;
  561.         case 'z':
  562.             ++zflag;
  563.             break;
  564.         default:
  565.             usage();
  566.         }
  567.     }
  568.     if (fn == NULL || av[optind] == NULL)
  569.         usage();
  570.     buflen = arbsize * group;
  571.     if (arpad == 0)
  572.         arpad = arbsize;
  573.     if (fn != pass) {
  574.         reg char    *colon;
  575.         reg char    *equal;
  576.         reg int        isoutput = (fn == out || fn == copyout);
  577.  
  578.         arname = strcpy(arspec, av[optind++]);
  579.         if (colon = strchr(arspec, ':')) {
  580.             *colon++ = '\0';
  581.             if (equal = strchr(arspec, '='))
  582.                 *equal++ = '\0';
  583.             VOID sprintf(arname = remote,
  584.                 "!rsh %s %s -%c -b %u -c %u %s",
  585.                 arspec, equal ? equal : myname,
  586.                 isoutput ? 'O' : 'I', arbsize,
  587.                 group, colon);
  588.             if (equal)
  589.                 *--equal = '=';
  590.             *--colon = ':';
  591.         }
  592.         if (gflag && *arname != '/' && *arname != '!')
  593.             fatal(arspec, "Relative pathname");
  594.         if ((buffer = bufidx = bufend = malloc(buflen)) == NULL)
  595.             fatal(arspec, "Cannot allocate I/O buffer");
  596.         if (nextopen(isoutput ? O_WRONLY : O_RDONLY) < 0)
  597.             exit(1);
  598.     }
  599.     timenow = time((time_t *) NULL);
  600.     (*fn)(av + optind);
  601.     timedone = time((time_t *) NULL);
  602.     if (uflag)
  603.         linkleft();
  604.     if (zflag) {
  605.         reg FILE    *stream;
  606.  
  607.         stream = fn == toc || arfd == STDOUT ? stderr : stdout;
  608.         VOID fprintf(stream, "%s: ", myname);
  609.         prsize(stream, total);
  610.         VOID fprintf(stream, " bytes %s in %lu seconds\n",
  611.           fn == pass
  612.             ? "transferred"
  613.             : fn == out || fn == copyout
  614.               ? "written"
  615.               : "read",
  616.           timedone - timenow - timewait);
  617.     }
  618.     nextclos();
  619.     exit(0);
  620.     /* NOTREACHED */
  621. }
  622.  
  623. /*
  624.  * copyin()
  625.  *
  626.  * Copy directly from the archive to the standard output.
  627.  */
  628. STATIC VOIDFN
  629. copyin(av)
  630. reg char    **av;
  631. {
  632.     reg int        got;
  633.     reg uint    have;
  634.  
  635.     if (*av)
  636.         fatal(*av, "Extraneous argument");
  637.     while (!areof) {
  638.         VOID infill();
  639.         while (have = bufend - bufidx)
  640.             if ((got = write(STDOUT, bufidx, have)) < 0)
  641.                 fatal("<stdout>", syserr());
  642.             else if (got > 0)
  643.                 bufidx += got;
  644.             else
  645.                 return;
  646.     }
  647. }
  648.  
  649. /*
  650.  * copyout()
  651.  *
  652.  * Copy directly from the standard input to the archive.
  653.  */
  654. STATIC VOIDFN
  655. copyout(av)
  656. reg char    **av;
  657. {
  658.     reg int        got;
  659.     reg uint    want;
  660.  
  661.     if (*av)
  662.         fatal(*av, "Extraneous argument");
  663.     for (;;) {
  664.         while ((want = bufend - bufidx) == 0)
  665.             outflush();
  666.         if ((got = read(STDIN, bufidx, want)) < 0)
  667.             fatal("<stdin>", syserr());
  668.         else if (got == 0)
  669.             break;
  670.         else
  671.             bufidx += got;
  672.     }
  673.     outflush();
  674.     if (fflag)
  675.         outwait();
  676. }
  677.  
  678. /*
  679.  * dirchg()
  680.  *
  681.  * Change to the directory containing a given file.
  682.  */
  683. STATIC int
  684. dirchg(name, local)
  685. reg char    *name;
  686. reg char    *local;
  687. {
  688.     reg char    *last;
  689.     reg int        len;
  690.     auto char    dir[PATHSIZE];
  691.  
  692.     if (*name != '/')
  693.         return (warn(name, "Relative pathname"));
  694.     for (last = name + strlen(name); last[-1] != '/'; --last)
  695.         ;
  696.     len = last - name;
  697.     strncpy(dir, name, len)[len] = '\0';
  698.     VOID strcpy(local, *last ? last : ".");
  699.     if (strcmp(dir, pwd) == 0)
  700.         return (0);
  701.     if (chdir(dir) < 0)
  702.         return (warn(name, syserr()));
  703.     VOID strcpy(pwd, dir);
  704.     return (0);
  705. }
  706.  
  707. /*
  708.  * dirmake()
  709.  *
  710.  * Make a directory. Returns zero if successful, -1 otherwise.
  711.  */
  712. STATIC int
  713. dirmake(name, asb)
  714. reg char    *name;
  715. reg Stat    *asb;
  716. {
  717.     if (mkdir(name, asb->sb_mode & S_IPOPN) < 0)
  718.         return (-1);
  719.     if (asb->sb_mode & S_IPEXE)
  720.         VOID chmod(name, asb->sb_mode & S_IPERM);
  721.     if (xflag)
  722.         VOID chown(name,
  723.             uid == 0 ? ush(asb->sb_uid) : uid,
  724.             ush(asb->sb_gid));
  725.     return (0);
  726. }
  727.  
  728. /*
  729.  * dirneed()
  730.  *
  731.  * Recursively create missing directories (with the same permissions
  732.  * as their first existing parent). Temporarily modifies the 'name'
  733.  * argument string. Returns zero if successful, -1 otherwise.
  734.  */
  735. STATIC int
  736. dirneed(name)
  737. char        *name;
  738. {
  739.     reg char    *cp;
  740.     reg char    *last;
  741.     reg int        ok;
  742.     static Stat    sb;
  743.  
  744.     last = NULL;
  745.     for (cp = name; *cp; )
  746.         if (*cp++ == '/')
  747.             last = cp;
  748.     if (last == NULL)
  749.         return (STAT(".", &sb));
  750.     *--last = '\0';
  751.     ok = STAT(*name ? name : "/", &sb) == 0
  752.         ? ((sb.sb_mode & S_IFMT) == S_IFDIR)
  753.         : (!dflag && dirneed(name) == 0 && dirmake(name, &sb) == 0);
  754.     *last = '/';
  755.     return (ok ? 0 : -1);
  756. }
  757.  
  758. /*
  759.  * fatal()
  760.  *
  761.  * Print fatal message and exit.
  762.  */
  763. STATIC void
  764. fatal(what, why)
  765. char        *what;
  766. char        *why;
  767. {
  768.     VOID fprintf(stderr,
  769.         "%s: \"%s\": %s\n",
  770.         myname, what, why);
  771.     exit(1);
  772. }
  773.  
  774. /*
  775.  * in()
  776.  *
  777.  * Read an archive.
  778.  */
  779. STATIC VOIDFN
  780. in(av)
  781. reg char    **av;
  782. {
  783.     auto Stat    sb;
  784.     auto char    name[PATHSIZE];
  785.  
  786.     if (*av)
  787.         fatal(*av, "Extraneous argument");
  788.     name[0] = '\0';
  789.     while (inhead(name, &sb) == 0) {
  790.         if (namecmp(name) < 0 || inentry(name, &sb) < 0)
  791.             if (inskip(sb.sb_size) < 0)
  792.                 VOID warn(name, "Skipped file data is corrupt");
  793.         if (vflag)
  794.             VOID fprintf(stderr, "%s\n", name);
  795.     }
  796. }
  797.  
  798. /*
  799.  * inalloc()
  800.  *
  801.  * Allocate input buffer space (which was previously indexed
  802.  * by inavail()).
  803.  */
  804. STATIC void
  805. inalloc(len)
  806. reg uint    len;
  807. {
  808.     bufidx += len;
  809.     total += len;
  810. }
  811.  
  812. /*
  813.  * inascii()
  814.  *
  815.  * Read an ASCII header. Returns zero if successful;
  816.  * -1 otherwise. Assumes that the entire magic number
  817.  * has been read.
  818.  */
  819. STATIC int
  820. inascii(magic, name, asb)
  821. reg char    *magic;
  822. reg char    *name;
  823. reg Stat    *asb;
  824. {
  825.     auto uint    namelen;
  826.     auto char    header[H_STRLEN + 1];
  827.  
  828.     if (strncmp(magic, M_ASCII, M_STRLEN) != 0)
  829.         return (-1);
  830.     if (inread(header, H_STRLEN) < 0)
  831.         return (warnarch("Corrupt ASCII header", (off_t) H_STRLEN));
  832.     header[H_STRLEN] = '\0';
  833.     if (sscanf(header, H_SCAN, &asb->sb_dev,
  834.         &asb->sb_ino, &asb->sb_mode, &asb->sb_uid,
  835.         &asb->sb_gid, &asb->sb_nlink, &asb->sb_rdev,
  836.         &asb->sb_mtime, &namelen, &asb->sb_size) != H_COUNT)
  837.         return (warnarch("Bad ASCII header", (off_t) H_STRLEN));
  838.     if (namelen == 0 || namelen >= PATHSIZE)
  839.         return (warnarch("Bad ASCII pathname length", (off_t) H_STRLEN));
  840.     if (inread(name, namelen) < 0)
  841.         return (warnarch("Corrupt ASCII pathname", (off_t) namelen));
  842.     if (name[namelen - 1] != '\0')
  843.         return (warnarch("Bad ASCII pathname", (off_t) namelen));
  844.     return (0);
  845. }
  846.  
  847. /*
  848.  * inavail()
  849.  *
  850.  * Index availible input data within the buffer. Stores a pointer
  851.  * to the data and its length in given locations. Returns zero with
  852.  * valid data, -1 if unreadable portions were replaced with nulls.
  853.  */
  854. STATIC int
  855. inavail(bufp, lenp)
  856. reg char    **bufp;
  857. uint        *lenp;
  858. {
  859.     reg uint    have;
  860.     reg int        corrupt = 0;
  861.  
  862.     while ((have = bufend - bufidx) == 0)
  863.         corrupt |= infill();
  864.     *bufp = bufidx;
  865.     *lenp = have;
  866.     return (corrupt);
  867. }
  868.  
  869. /*
  870.  * inbinary()
  871.  *
  872.  * Read a binary header. Returns the number of trailing alignment
  873.  * bytes to skip; -1 if unsuccessful.
  874.  */
  875. STATIC int
  876. inbinary(magic, name, asb)
  877. reg char    *magic;
  878. reg char    *name;
  879. reg Stat    *asb;
  880. {
  881.     reg uint    namefull;
  882.     auto Binary    binary;
  883.  
  884.     if (*((ushort *) magic) != M_BINARY)
  885.         return (-1);
  886.     memcpy((char *) &binary,
  887.         magic + sizeof(ushort),
  888.         M_STRLEN - sizeof(ushort));
  889.     if (inread((char *) &binary + M_STRLEN - sizeof(ushort),
  890.         sizeof(binary) - (M_STRLEN - sizeof(ushort))) < 0)
  891.         return (warnarch("Corrupt binary header",
  892.             (off_t) sizeof(binary) - (M_STRLEN - sizeof(ushort))));
  893.     asb->sb_dev = binary.b_dev;
  894.     asb->sb_ino = binary.b_ino;
  895.     asb->sb_mode = binary.b_mode;
  896.     asb->sb_uid = binary.b_uid;
  897.     asb->sb_gid = binary.b_gid;
  898.     asb->sb_nlink = binary.b_nlink;
  899.     asb->sb_rdev = binary.b_rdev;
  900.     asb->sb_mtime = binary.b_mtime[0] << 16 | binary.b_mtime[1];
  901.     asb->sb_size = binary.b_size[0] << 16 | binary.b_size[1];
  902.     if (binary.b_name == 0 || binary.b_name >= PATHSIZE)
  903.         return (warnarch("Bad binary pathname length",
  904.             (off_t) sizeof(binary) - (M_STRLEN - sizeof(ushort))));
  905.     if (inread(name, namefull = binary.b_name + binary.b_name % 2) < 0)
  906.         return (warnarch("Corrupt binary pathname", (off_t) namefull));
  907.     if (name[binary.b_name - 1] != '\0')
  908.         return (warnarch("Bad binary pathname", (off_t) namefull));
  909.     return (asb->sb_size % 2);
  910. }
  911.  
  912. /*
  913.  * indata()
  914.  *
  915.  * Install data from an archive. Returns given file descriptor.
  916.  */
  917. STATIC int
  918. indata(fd, size, name)
  919. int        fd;
  920. reg off_t    size;
  921. char        *name;
  922. {
  923.     reg uint    chunk;
  924.     reg char    *oops;
  925.     reg int        sparse;
  926.     reg int        corrupt;
  927.     auto char    *buf;
  928.     auto uint    avail;
  929.  
  930.     corrupt = sparse = 0;
  931.     oops = NULL;
  932.     while (size) {
  933.         corrupt |= inavail(&buf, &avail);
  934.         size -= (chunk = size < avail ? (uint) size : avail);
  935.         if (oops == NULL && (sparse = swrite(fd, buf, chunk)) < 0)
  936.             oops = syserr();
  937.         inalloc(chunk);
  938.     }
  939.     if (corrupt)
  940.         VOID warn(name, "Corrupt archive data");
  941.     if (oops)
  942.         VOID warn(name, oops);
  943.     else if (sparse > 0
  944.       && (lseek(fd, (off_t) -1, 1) < 0
  945.         || write(fd, "", 1) != 1))
  946.         VOID warn(name, syserr());
  947.     return (fd);
  948. }
  949.  
  950. /*
  951.  * inentry()
  952.  *
  953.  * Install a single archive entry. Returns zero if successful, -1 otherwise.
  954.  */
  955. STATIC int
  956. inentry(name, asb)
  957. char        *name;
  958. reg Stat    *asb;
  959. {
  960.     reg Link    *linkp;
  961.     reg int        ifd;
  962.     reg int        ofd;
  963.     auto time_t    tstamp[2];
  964.  
  965.     if ((ofd = openo(name, asb, linkp = linkfrom(asb), 0)) > 0)
  966.         if (asb->sb_size || linkp == NULL || linkp->l_size == 0)
  967.             VOID close(indata(ofd, asb->sb_size, name));
  968.         else if ((ifd = open(linkp->l_path->p_name, O_RDONLY)) < 0)
  969.             VOID warn(linkp->l_path->p_name, syserr());
  970.         else {
  971.             passdata(linkp->l_path->p_name, ifd, name, ofd);
  972.             VOID close(ifd);
  973.             VOID close(ofd);
  974.         }
  975.     else if (ofd < 0)
  976.         return (-1);
  977.     else if (inskip(asb->sb_size) < 0)
  978.         VOID warn(name, "Redundant file data is corrupt");
  979.     tstamp[0] = tstamp[1] = mflag ? timenow : asb->sb_mtime;
  980.     VOID utime(name, tstamp);
  981.     return (0);
  982. }
  983.  
  984. /*
  985.  * infill()
  986.  *
  987.  * Fill the archive buffer. Remembers mid-buffer read failures and
  988.  * reports them the next time through. Replaces unreadable data with
  989.  * null characters. Returns zero with valid data, -1 otherwise.
  990.  */
  991. STATIC int
  992. infill()
  993. {
  994.     reg int        got;
  995.     static int    failed;
  996.  
  997.     bufend = bufidx = buffer;
  998.     if (!failed) {
  999.         if (areof)
  1000.             if (total == 0)
  1001.                 fatal(arspec, "No input");
  1002.             else
  1003.                 next(O_RDONLY, "Input EOF");
  1004.         if (aruntil && arleft < arbsize)
  1005.             next(O_RDONLY, "Input limit reached");
  1006.         while (!failed
  1007.             && !areof
  1008.             && (aruntil == 0 || arleft >= arbsize)
  1009.             && buffer + buflen - bufend >= arbsize) {
  1010.             if ((got = read(arfd, bufend, arbsize)) > 0) {
  1011.                 bufend += got;
  1012.                 arleft -= got;
  1013.             } else if (got < 0)
  1014.                 failed = warnarch(syserr(),
  1015.                     (off_t) 0 - (bufend - bufidx));
  1016.             else
  1017.                 ++areof;
  1018.         }
  1019.     }
  1020.     if (failed && bufend == buffer) {
  1021.         failed = 0;
  1022.         for (got = 0; got < arbsize; ++got)
  1023.             *bufend++ = '\0';
  1024.         return (-1);
  1025.     }
  1026.     return (0);
  1027. }
  1028.  
  1029. /*
  1030.  * inhead()
  1031.  *
  1032.  * Read a header. Quietly translates old-fashioned binary cpio headers
  1033.  * (and arranges to skip the possible alignment byte). Returns zero if
  1034.  * successful, -1 upon archive trailer.
  1035.  */
  1036. STATIC int
  1037. inhead(name, asb)
  1038. reg char    *name;
  1039. reg Stat    *asb;
  1040. {
  1041.     reg off_t    skipped;
  1042.     auto char    magic[M_STRLEN];
  1043.     static int    align;
  1044.  
  1045.     if (align > 0)
  1046.         VOID inskip((off_t) align);
  1047.     align = 0;
  1048.     for (;;) {
  1049.         VOID inread(magic, M_STRLEN);
  1050.         skipped = 0;
  1051.         while ((align = inascii(magic, name, asb)) < 0
  1052.             && (align = inbinary(magic, name, asb)) < 0
  1053.             && (align = inswab(magic, name, asb)) < 0) {
  1054.             if (++skipped == 1) {
  1055.                 if (!kflag && total - sizeof(magic) == 0)
  1056.                     fatal(arspec, "Unrecognizable archive");
  1057.                 VOID warnarch("Bad magic number",
  1058.                     (off_t) sizeof(magic));
  1059.                 if (name[0])
  1060.                     VOID warn(name, "May be corrupt");
  1061.             }
  1062.             memcpy(magic, magic + 1, sizeof(magic) - 1);
  1063.             VOID inread(magic + sizeof(magic) - 1, 1);
  1064.         }
  1065.         if (skipped) {
  1066.             VOID warnarch("Apparently resynchronized",
  1067.                 (off_t) sizeof(magic));
  1068.             VOID warn(name, "Continuing");
  1069.         }
  1070.         if (strcmp(name, TRAILER) == 0)
  1071.             return (-1);
  1072.         if (nameopt(name) >= 0)
  1073.             break;
  1074.         VOID inskip(asb->sb_size + align);
  1075.     }
  1076. #ifdef    S_IFLNK
  1077.     if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  1078.         if (inread(asb->sb_link, (uint) asb->sb_size) < 0) {
  1079.             VOID warn(name, "Corrupt symbolic link");
  1080.             return (inhead(name, asb));
  1081.         }
  1082.         asb->sb_link[asb->sb_size] = '\0';
  1083.         asb->sb_size = 0;
  1084.     }
  1085. #endif    /* S_IFLNK */
  1086.     if (name[0] == '/')
  1087.         if (name[1])
  1088.             while (name[0] = name[1])
  1089.                 ++name;
  1090.         else
  1091.             name[0] = '.';
  1092.     asb->sb_atime = asb->sb_ctime = asb->sb_mtime;
  1093.     return (0);
  1094. }
  1095.  
  1096. /*
  1097.  * inread()
  1098.  *
  1099.  * Read a given number of characters from the input archive. Returns
  1100.  * zero with valid data, -1 if unreadable portions were replaced by
  1101.  * null characters.
  1102.  */
  1103. STATIC int
  1104. inread(dst, len)
  1105. reg char    *dst;
  1106. uint        len;
  1107. {
  1108.     reg uint    have;
  1109.     reg uint    want;
  1110.     reg int        corrupt = 0;
  1111.     char        *endx = dst + len;
  1112.  
  1113.     while (want = endx - dst) {
  1114.         while ((have = bufend - bufidx) == 0)
  1115.             corrupt |= infill();
  1116.         if (have > want)
  1117.             have = want;
  1118.         memcpy(dst, bufidx, have);
  1119.         bufidx += have;
  1120.         dst += have;
  1121.         total += have;
  1122.     }
  1123.     return (corrupt);
  1124. }
  1125.  
  1126. /*
  1127.  * inskip()
  1128.  *
  1129.  * Skip input archive data. Returns zero under normal circumstances,
  1130.  * -1 if unreadable data is encountered.
  1131.  */
  1132. STATIC int
  1133. inskip(len)
  1134. reg off_t    len;
  1135. {
  1136.     reg uint    chunk;
  1137.     reg int        corrupt = 0;
  1138.  
  1139.     while (len) {
  1140.         while ((chunk = bufend - bufidx) == 0)
  1141.             corrupt |= infill();
  1142.         if (chunk > len)
  1143.             chunk = len;
  1144.         bufidx += chunk;
  1145.         len -= chunk;
  1146.         total += chunk;
  1147.     }
  1148.     return (corrupt);
  1149. }
  1150.  
  1151. /*
  1152.  * inswab()
  1153.  *
  1154.  * Read a reversed byte order binary header. Returns the number
  1155.  * of trailing alignment bytes to skip; -1 if unsuccessful.
  1156.  */
  1157. STATIC int
  1158. inswab(magic, name, asb)
  1159. reg char    *magic;
  1160. reg char    *name;
  1161. reg Stat    *asb;
  1162. {
  1163.     reg ushort    namesize;
  1164.     reg uint    namefull;
  1165.     auto Binary    binary;
  1166.  
  1167.     if (*((ushort *) magic) != swab(M_BINARY))
  1168.         return (-1);
  1169.     memcpy((char *) &binary,
  1170.         magic + sizeof(ushort),
  1171.         M_STRLEN - sizeof(ushort));
  1172.     if (inread((char *) &binary + M_STRLEN - sizeof(ushort),
  1173.         sizeof(binary) - (M_STRLEN - sizeof(ushort))) < 0)
  1174.         return (warnarch("Corrupt swapped header",
  1175.             (off_t) sizeof(binary) - (M_STRLEN - sizeof(ushort))));
  1176.     asb->sb_dev = (dev_t) swab(binary.b_dev);
  1177.     asb->sb_ino = (ino_t) swab(binary.b_ino);
  1178.     asb->sb_mode = swab(binary.b_mode);
  1179.     asb->sb_uid = swab(binary.b_uid);
  1180.     asb->sb_gid = swab(binary.b_gid);
  1181.     asb->sb_nlink = swab(binary.b_nlink);
  1182.     asb->sb_rdev = (dev_t) swab(binary.b_rdev);
  1183.     asb->sb_mtime = swab(binary.b_mtime[0]) << 16 | swab(binary.b_mtime[1]);
  1184.     asb->sb_size = swab(binary.b_size[0]) << 16 | swab(binary.b_size[1]);
  1185.     if ((namesize = swab(binary.b_name)) == 0 || namesize >= PATHSIZE)
  1186.         return (warnarch("Bad swapped pathname length",
  1187.             (off_t) sizeof(binary) - (M_STRLEN - sizeof(ushort))));
  1188.     if (inread(name, namefull = namesize + namesize % 2) < 0)
  1189.         return (warnarch("Corrupt swapped pathname", (off_t) namefull));
  1190.     if (name[namesize - 1] != '\0')
  1191.         return (warnarch("Bad swapped pathname", (off_t) namefull));
  1192.     return (asb->sb_size % 2);
  1193. }
  1194.  
  1195. /*
  1196.  * lineget()
  1197.  *
  1198.  * Get a line from a given stream. Returns 0 if successful, -1 at EOF.
  1199.  */
  1200. STATIC int
  1201. lineget(stream, buf)
  1202. reg FILE    *stream;
  1203. reg char    *buf;
  1204. {
  1205.     reg int        c;
  1206.  
  1207.     for (;;) {
  1208.         if ((c = getc(stream)) == EOF)
  1209.             return (-1);
  1210.         if (c == '\n')
  1211.             break;
  1212.         *buf++ = c;
  1213.     }
  1214.     *buf = '\0';
  1215.     return (0);
  1216. }
  1217.  
  1218. /*
  1219.  * linkalso()
  1220.  *
  1221.  * Add a destination pathname to an existing chain. Assumes that
  1222.  * at least one element is present.
  1223.  */
  1224. STATIC void
  1225. linkalso(linkp, name)
  1226. reg Link    *linkp;
  1227. char        *name;
  1228. {
  1229.     reg Path    *path;
  1230.  
  1231.     if ((path = (Path *) memget(sizeof(Path))) == NULL
  1232.         || (path->p_name = memstr(name)) == NULL)
  1233.         return;
  1234.     path->p_forw = NULL;
  1235.     path->p_back = linkp->l_path->p_back;
  1236.     path->p_back->p_forw = path;
  1237.     linkp->l_path->p_back = path;
  1238. }
  1239.  
  1240. /*
  1241.  * linkfrom()
  1242.  *
  1243.  * Find a file to link from. Returns a pointer to a link
  1244.  * structure, or NULL if unsuccessful.
  1245.  */
  1246. STATIC Link *
  1247. linkfrom(asb)
  1248. reg Stat    *asb;
  1249. {
  1250.     reg Link    *linkp;
  1251.     reg Link    *linknext;
  1252.     reg Path    *path;
  1253.     reg Path    *pathnext;
  1254.     reg Link    **abase;
  1255.  
  1256.     for (linkp = *(abase = linkhash(asb->sb_ino)); linkp; linkp = linknext)
  1257.         if (linkp->l_nlink == 0) {
  1258.             for (path = linkp->l_path; path; path = pathnext) {
  1259.                 pathnext = path->p_forw;
  1260.                 free(path->p_name);
  1261.             }
  1262.             free((char *) linkp->l_path);
  1263.             if (linknext = linkp->l_forw)
  1264.                 linknext->l_back = linkp->l_back;
  1265.             if (linkp->l_back)
  1266.                 linkp->l_back->l_forw = linkp->l_forw;
  1267.             else
  1268.                 *abase = linkp->l_forw;
  1269.             free((char *) linkp);
  1270.         } else if (linkp->l_ino == asb->sb_ino
  1271.             && linkp->l_dev == asb->sb_dev) {
  1272.             --linkp->l_nlink;
  1273.             return (linkp);
  1274.         } else
  1275.             linknext = linkp->l_forw;
  1276.     return (NULL);
  1277. }
  1278.  
  1279.