Annotation of coherent/d/usr/bin/pax/public/part05.sh, revision 1.1.1.1

1.1       root        1: # This is a shell archive.  Remove anything before this line, then unpack
                      2: # it by saving it into a file and typing "sh file".  To overwrite existing
                      3: # files, type "sh file -c".  You can also feed this as standard input via
                      4: # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
                      5: # will see the following message at the end:
                      6: #              "End of archive 5 (of 6)."
                      7: # Contents:  buffer.c paxdir.c
                      8: # Wrapped by mark@jhereg on Tue Dec 27 19:37:59 1988
                      9: PATH=/bin:/usr/bin:/usr/ucb ; export PATH
                     10: if test -f buffer.c -a "${1}" != "-c" ; then 
                     11:   echo shar: Will not over-write existing file \"buffer.c\"
                     12: else
                     13: echo shar: Extracting \"buffer.c\" \(17360 characters\)
                     14: sed "s/^X//" >buffer.c <<'END_OF_buffer.c'
                     15: X/* $Source: /u/mark/src/pax/RCS/buffer.c,v $
                     16: X *
                     17: X * $Revision: 1.1 $
                     18: X *
                     19: X * buffer.c - Buffer management functions
                     20: X *
                     21: X * DESCRIPTION
                     22: X *
                     23: X *    These functions handle buffer manipulations for the archiving
                     24: X *    formats.  Functions are provided to get memory for buffers, 
                     25: X *    flush buffers, read and write buffers and de-allocate buffers.  
                     26: X *    Several housekeeping functions are provided as well to get some 
                     27: X *    information about how full buffers are, etc.
                     28: X *
                     29: X * AUTHOR
                     30: X *
                     31: X *    Mark H. Colburn, NAPS International ([email protected])
                     32: X *
                     33: X * Sponsored by The USENIX Association for public distribution. 
                     34: X *
                     35: X * Copyright (c) 1989 Mark H. Colburn.
                     36: X * All rights reserved.
                     37: X *
                     38: X * Redistribution and use in source and binary forms are permitted
                     39: X * provided that the above copyright notice is duplicated in all such 
                     40: X * forms and that any documentation, advertising materials, and other 
                     41: X * materials related to such distribution and use acknowledge that the 
                     42: X * software was developed * by Mark H. Colburn and sponsored by The 
                     43: X * USENIX Association. 
                     44: X *
                     45: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     46: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     47: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     48: X *
                     49: X * $Log:      buffer.c,v $
                     50: X * Revision 1.1  88/12/23  18:02:01  mark
                     51: X * Initial revision
                     52: X * 
                     53: X */
                     54: X
                     55: X#ifndef lint
                     56: Xstatic char *ident = "$Id: buffer.c,v 1.1 88/12/23 18:02:01 mark Rel $";
                     57: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
                     58: X#endif /* ! lint */
                     59: X
                     60: X
                     61: X/* Headers */
                     62: X
                     63: X#include "pax.h"
                     64: X
                     65: X
                     66: X/* Function Prototypes */
                     67: X
                     68: X#ifdef __STDC__
                     69: X
                     70: Xstatic int ar_write(int, char *, uint);
                     71: Xstatic void buf_pad(OFFSET);
                     72: Xstatic int indata(int, OFFSET, char *);
                     73: Xstatic void outflush(void);
                     74: Xstatic void buf_use(uint);
                     75: Xstatic int buf_in_avail(char **, uint *);
                     76: Xstatic uint buf_out_avail(char **);
                     77: X
                     78: X#else /* !__STDC__ */
                     79: X
                     80: Xstatic int ar_write();
                     81: Xstatic void buf_pad();
                     82: Xstatic int indata();
                     83: Xstatic void outflush();
                     84: Xstatic void buf_use();
                     85: Xstatic int buf_in_avail();
                     86: Xstatic uint buf_out_avail();
                     87: X
                     88: X#endif /* __STDC__ */
                     89: X
                     90: X
                     91: X/* inentry - install a single archive entry
                     92: X *
                     93: X * DESCRIPTION
                     94: X *
                     95: X *    Inentry reads an archive entry from the archive file and writes it
                     96: X *    out the the named file.  If we are in PASS mode during archive
                     97: X *    processing, the pass() function is called, otherwise we will
                     98: X *    extract from the archive file.
                     99: X *
                    100: X *    Inentry actaully calls indata to process the actual data to the
                    101: X *    file.
                    102: X *
                    103: X * PARAMETERS
                    104: X *
                    105: X *    char    *name   - name of the file to extract from the archive
                    106: X *    Stat    *asb    - stat block of the file to be extracted from the
                    107: X *                      archive.
                    108: X *
                    109: X * RETURNS
                    110: X *
                    111: X *    Returns zero if successful, -1 otherwise. 
                    112: X */
                    113: X
                    114: X#ifdef __STDC__
                    115: X
                    116: Xint inentry(char *name, Stat *asb)
                    117: X
                    118: X#else
                    119: X
                    120: Xint inentry(name, asb)
                    121: Xchar           *name;
                    122: XStat           *asb;
                    123: X
                    124: X#endif
                    125: X{
                    126: X    Link           *linkp;
                    127: X    int             ifd;
                    128: X    int             ofd;
                    129: X    time_t          tstamp[2];
                    130: X
                    131: X    if ((ofd = openo(name, asb, linkp = linkfrom(name, asb), 0)) > 0) {
                    132: X      if (asb->sb_size || linkp == NULL || linkp->l_size == 0) {
                    133: X          close(indata(ofd, asb->sb_size, name));
                    134: X      } else if ((ifd = open(linkp->l_path->p_name, O_RDONLY)) < 0) {
                    135: X          warn(linkp->l_path->p_name, syserr());
                    136: X      } else {
                    137: X          passdata(linkp->l_path->p_name, ifd, name, ofd);
                    138: X          close(ifd);
                    139: X          close(ofd);
                    140: X      }
                    141: X    } else {
                    142: X      return(buf_skip((OFFSET) asb->sb_size) >= 0);
                    143: X    }
                    144: X    tstamp[0] = (!f_pass && f_access_time) ? asb->sb_atime : time((time_t *) 0);
                    145: X    tstamp[1] = f_modification_time ? asb->sb_mtime : time((time_t *) 0);
                    146: X    utime(name, tstamp);
                    147: X    return (0);
                    148: X}
                    149: X
                    150: X
                    151: X/* outdata - write archive data
                    152: X *
                    153: X * DESCRIPTION
                    154: X *
                    155: X *    Outdata transfers data from the named file to the archive buffer.
                    156: X *    It knows about the file padding which is required by tar, but no
                    157: X *    by cpio.  Outdata continues after file read errors, padding with 
                    158: X *    null characters if neccessary.   Closes the input file descriptor 
                    159: X *    when finished.
                    160: X *
                    161: X * PARAMETERS
                    162: X *
                    163: X *    int     fd      - file descriptor of file to read data from
                    164: X *    char   *name    - name of file
                    165: X *    OFFSET  size    - size of the file
                    166: X *
                    167: X */
                    168: X
                    169: X#ifdef __STDC__
                    170: X
                    171: Xvoid outdata(int fd, char *name, OFFSET size)
                    172: X
                    173: X#else
                    174: X
                    175: Xvoid outdata(fd, name, size)
                    176: Xint             fd;
                    177: Xchar           *name;
                    178: XOFFSET          size;
                    179: X
                    180: X#endif
                    181: X{
                    182: X    uint            chunk;
                    183: X    int             got;
                    184: X    int             oops;
                    185: X    uint            avail;
                    186: X    int                   pad;
                    187: X    char           *buf;
                    188: X
                    189: X    oops = got = 0;
                    190: X    if (pad = (size % BLOCKSIZE)) {
                    191: X      pad = (BLOCKSIZE - pad);
                    192: X    }
                    193: X    while (size) {
                    194: X      avail = buf_out_avail(&buf);
                    195: X      size -= (chunk = size < avail ? (uint) size : avail);
                    196: X      if (oops == 0 && (got = read(fd, buf, (unsigned int) chunk)) < 0) {
                    197: X          oops = -1;
                    198: X          warn(name, syserr());
                    199: X          got = 0;
                    200: X      }
                    201: X      if (got < chunk) {
                    202: X          if (oops == NULL) {
                    203: X              oops = -1;
                    204: X          }
                    205: X          warn(name, "Early EOF");
                    206: X          while (got < chunk) {
                    207: X              buf[got++] = '\0';
                    208: X          }
                    209: X      }
                    210: X      buf_use(chunk);
                    211: X    }
                    212: X    close(fd);
                    213: X    if (ar_format == TAR) {
                    214: X      buf_pad((OFFSET) pad);
                    215: X    }
                    216: X}
                    217: X
                    218: X
                    219: X/* write_eot -  write the end of archive record(s)
                    220: X *
                    221: X * DESCRIPTION
                    222: X *
                    223: X *    Write out an End-Of-Tape record.  We actually zero at least one 
                    224: X *    record, through the end of the block.  Old tar writes garbage after 
                    225: X *    two zeroed records -- and PDtar used to.
                    226: X */
                    227: X
                    228: X#ifdef __STDC__
                    229: X
                    230: Xvoid write_eot(void)
                    231: X
                    232: X#else
                    233: X
                    234: Xvoid write_eot()
                    235: X
                    236: X#endif
                    237: X{
                    238: X    OFFSET           pad;
                    239: X    char            header[M_STRLEN + H_STRLEN + 1];
                    240: X
                    241: X    if (ar_format == TAR) {
                    242: X      /* write out two zero blocks for trailer */
                    243: X      pad = 2 * BLOCKSIZE;
                    244: X    } else {
                    245: X      if (pad = (total + M_STRLEN + H_STRLEN + TRAILZ) % BLOCKSIZE) {
                    246: X          pad = BLOCKSIZE - pad;
                    247: X      }
                    248: X      strcpy(header, M_ASCII);
                    249: X      sprintf(header + M_STRLEN, H_PRINT, 0, 0,
                    250: X                     0, 0, 0, 1, 0, (time_t) 0, TRAILZ, pad);
                    251: X      outwrite(header, M_STRLEN + H_STRLEN);
                    252: X      outwrite(TRAILER, TRAILZ);
                    253: X    }
                    254: X    buf_pad((OFFSET) pad);
                    255: X    outflush();
                    256: X}
                    257: X
                    258: X 
                    259: X/* outwrite -  write archive data
                    260: X *
                    261: X * DESCRIPTION
                    262: X *
                    263: X *    Writes out data in the archive buffer to the archive file.  The
                    264: X *    buffer index and the total byte count are incremented by the number
                    265: X *    of data bytes written.
                    266: X *
                    267: X * PARAMETERS
                    268: X *    
                    269: X *    char   *idx     - pointer to data to write
                    270: X *    uint    len     - length of the data to write
                    271: X */
                    272: X
                    273: X#ifdef __STDC__
                    274: X
                    275: Xvoid outwrite(char *idx, uint len)
                    276: X
                    277: X#else
                    278: X
                    279: Xvoid outwrite(idx, len)
                    280: Xchar           *idx;  /* pointer to data to write */
                    281: Xuint            len;  /* length of data to write */
                    282: X
                    283: X#endif
                    284: X{
                    285: X    uint            have;
                    286: X    uint            want;
                    287: X    char           *endx;
                    288: X
                    289: X    endx = idx + len;
                    290: X    while (want = endx - idx) {
                    291: X      if (bufend - bufidx < 0) {
                    292: X          fatal("Buffer overlow in out_write\n");
                    293: X      }
                    294: X      if ((have = bufend - bufidx) == 0) {
                    295: X          outflush();
                    296: X      }
                    297: X      if (have > want) {
                    298: X          have = want;
                    299: X      }
                    300: X      memcpy(bufidx, idx, (int) have);
                    301: X      bufidx += have;
                    302: X      idx += have;
                    303: X      total += have;
                    304: X    }
                    305: X}
                    306: X
                    307: X
                    308: X/* passdata - copy data to one file
                    309: X *
                    310: X * DESCRIPTION
                    311: X *
                    312: X *    Copies a file from one place to another.  Doesn't believe in input 
                    313: X *    file descriptor zero (see description of kludge in openi() comments). 
                    314: X *    Closes the provided output file descriptor. 
                    315: X *
                    316: X * PARAMETERS
                    317: X *
                    318: X *    char    *from   - input file name (old file)
                    319: X *    int     ifd     - input file descriptor
                    320: X *    char    *to     - output file name (new file)
                    321: X *    int     ofd     - output file descriptor
                    322: X */
                    323: X
                    324: X#ifdef __STDC__
                    325: X
                    326: Xvoid passdata(char *from, int ifd, char *to, int ofd)
                    327: X
                    328: X#else
                    329: X
                    330: Xvoid passdata(from, ifd, to, ofd)
                    331: Xchar           *from;
                    332: Xint             ifd;
                    333: Xchar           *to;
                    334: Xint             ofd;
                    335: X
                    336: X#endif
                    337: X{
                    338: X    int             got;
                    339: X    int             sparse;
                    340: X    char            block[BUFSIZ];
                    341: X
                    342: X    if (ifd) {
                    343: X      lseek(ifd, (OFFSET) 0, 0);
                    344: X      sparse = 0;
                    345: X      while ((got = read(ifd, block, sizeof(block))) > 0
                    346: X             && (sparse = ar_write(ofd, block, (uint) got)) >= 0) {
                    347: X          total += got;
                    348: X      }
                    349: X      if (got) {
                    350: X          warn(got < 0 ? from : to, syserr());
                    351: X      } else if (sparse > 0
                    352: X               && (lseek(ofd, (OFFSET)(-sparse), 1) < 0
                    353: X                   || write(ofd, block, (uint) sparse) != sparse)) {
                    354: X          warn(to, syserr());
                    355: X      }
                    356: X    }
                    357: X    close(ofd);
                    358: X}
                    359: X
                    360: X
                    361: X/* buf_allocate - get space for the I/O buffer 
                    362: X *
                    363: X * DESCRIPTION
                    364: X *
                    365: X *    buf_allocate allocates an I/O buffer using malloc.  The resulting
                    366: X *    buffer is used for all data buffering throughout the program.
                    367: X *    Buf_allocate must be called prior to any use of the buffer or any
                    368: X *    of the buffering calls.
                    369: X *
                    370: X * PARAMETERS
                    371: X *
                    372: X *    int     size    - size of the I/O buffer to request
                    373: X *
                    374: X * ERRORS
                    375: X *
                    376: X *    If an invalid size is given for a buffer or if a buffer of the 
                    377: X *    required size cannot be allocated, then the function prints out an 
                    378: X *    error message and returns a non-zero exit status to the calling 
                    379: X *    process, terminating the program.
                    380: X *
                    381: X */
                    382: X
                    383: X#ifdef __STDC__
                    384: X
                    385: Xvoid buf_allocate(OFFSET size)
                    386: X
                    387: X#else
                    388: X
                    389: Xvoid buf_allocate(size)
                    390: XOFFSET            size;
                    391: X
                    392: X#endif
                    393: X{
                    394: X    extern char *malloc();
                    395: X    
                    396: X    if (size <= 0) {
                    397: X      fatal("invalid value for blocksize");
                    398: X    }
                    399: X    if ((bufstart = malloc((unsigned) size)) == NULL) {
                    400: X      fatal("Cannot allocate I/O buffer");
                    401: X    }
                    402: X    bufend = bufidx = bufstart;
                    403: X    bufend += size;
                    404: X}
                    405: X
                    406: X
                    407: X/* buf_skip - skip input archive data
                    408: X *
                    409: X * DESCRIPTION
                    410: X *
                    411: X *    Buf_skip skips past archive data.  It is used when the length of
                    412: X *    the archive data is known, and we do not wish to process the data.
                    413: X *
                    414: X * PARAMETERS
                    415: X *
                    416: X *    OFFSET  len     - number of bytes to skip
                    417: X *
                    418: X * RETURNS
                    419: X *
                    420: X *    Returns zero under normal circumstances, -1 if unreadable data is 
                    421: X *    encountered. 
                    422: X */
                    423: X
                    424: X#ifdef __STDC__
                    425: X
                    426: Xint buf_skip(OFFSET len)
                    427: X
                    428: X#else
                    429: X
                    430: Xint buf_skip(len)
                    431: XOFFSET           len;
                    432: X
                    433: X#endif
                    434: X{
                    435: X    uint            chunk;
                    436: X    int             corrupt = 0;
                    437: X
                    438: X    while (len) {
                    439: X      if (bufend - bufidx < 0) {
                    440: X          fatal("Buffer overlow in buf_skip\n");
                    441: X      }
                    442: X      while ((chunk = bufend - bufidx) == 0) {
                    443: X          corrupt |= ar_read();
                    444: X      }
                    445: X      if (chunk > len) {
                    446: X          chunk = len;
                    447: X      }
                    448: X      bufidx += chunk;
                    449: X      len -= chunk;
                    450: X      total += chunk;
                    451: X    }
                    452: X    return (corrupt);
                    453: X}
                    454: X
                    455: X
                    456: X/* buf_read - read a given number of characters from the input archive
                    457: X *
                    458: X * DESCRIPTION
                    459: X *
                    460: X *    Reads len number of characters from the input archive and
                    461: X *    stores them in the buffer pointed at by dst.
                    462: X *
                    463: X * PARAMETERS
                    464: X *
                    465: X *    char   *dst     - pointer to buffer to store data into
                    466: X *    uint    len     - length of data to read
                    467: X *
                    468: X * RETURNS
                    469: X *
                    470: X *    Returns zero with valid data, -1 if unreadable portions were 
                    471: X *    replaced by null characters. 
                    472: X */
                    473: X
                    474: X#ifdef __STDC__
                    475: X
                    476: Xint buf_read(char *dst, uint len)
                    477: X
                    478: X#else
                    479: X
                    480: Xint buf_read(dst, len)
                    481: Xchar           *dst;
                    482: Xuint            len;
                    483: X
                    484: X#endif
                    485: X{
                    486: X    int             have;
                    487: X    int             want;
                    488: X    int             corrupt = 0;
                    489: X    char           *endx = dst + len;
                    490: X
                    491: X    while (want = endx - dst) {
                    492: X      if (bufend - bufidx < 0) {
                    493: X          fatal("Buffer overlow in buf_read\n");
                    494: X      }
                    495: X      while ((have = bufend - bufidx) == 0) {
                    496: X          have = 0;
                    497: X          corrupt |= ar_read();
                    498: X      }
                    499: X      if (have > want) {
                    500: X          have = want;
                    501: X      }
                    502: X      memcpy(dst, bufidx, have);
                    503: X      bufidx += have;
                    504: X      dst += have;
                    505: X      total += have;
                    506: X    }
                    507: X    return (corrupt);
                    508: X}
                    509: X
                    510: X
                    511: X/* indata - install data from an archive
                    512: X *
                    513: X * DESCRIPTION
                    514: X *
                    515: X *    Indata writes size bytes of data from the archive buffer to the output 
                    516: X *    file specified by fd.  The filename which is being written, pointed
                    517: X *    to by name is provided only for diagnostics.
                    518: X *
                    519: X * PARAMETERS
                    520: X *
                    521: X *    int     fd      - output file descriptor
                    522: X *    OFFSET  size    - number of bytes to write to output file
                    523: X *    char    *name   - name of file which corresponds to fd
                    524: X *
                    525: X * RETURNS
                    526: X *
                    527: X *    Returns given file descriptor. 
                    528: X */
                    529: X
                    530: X#ifdef __STDC__
                    531: X
                    532: Xstatic int indata(int fd, OFFSET size, char *name)
                    533: X
                    534: X#else
                    535: X
                    536: Xstatic int indata(fd, size, name)
                    537: Xint             fd;
                    538: XOFFSET          size;
                    539: Xchar           *name;
                    540: X
                    541: X#endif
                    542: X{
                    543: X    uint            chunk;
                    544: X    char           *oops;
                    545: X    int             sparse;
                    546: X    int             corrupt;
                    547: X    char           *buf;
                    548: X    uint            avail;
                    549: X
                    550: X    corrupt = sparse = 0;
                    551: X    oops = NULL;
                    552: X    while (size) {
                    553: X      corrupt |= buf_in_avail(&buf, &avail);
                    554: X      size -= (chunk = size < avail ? (uint) size : avail);
                    555: X      if (oops == NULL && (sparse = ar_write(fd, buf, chunk)) < 0) {
                    556: X          oops = syserr();
                    557: X      }
                    558: X      buf_use(chunk);
                    559: X    }
                    560: X    if (corrupt) {
                    561: X      warn(name, "Corrupt archive data");
                    562: X    }
                    563: X    if (oops) {
                    564: X      warn(name, oops);
                    565: X    } else if (sparse > 0 && (lseek(fd, (OFFSET) - 1, 1) < 0
                    566: X                            || write(fd, "", 1) != 1)) {
                    567: X      warn(name, syserr());
                    568: X    }
                    569: X    return (fd);
                    570: X}
                    571: X
                    572: X
                    573: X/* outflush - flush the output buffer
                    574: X *
                    575: X * DESCRIPTION
                    576: X *
                    577: X *    The output buffer is written, if there is anything in it, to the
                    578: X *    archive file.
                    579: X */
                    580: X
                    581: X#ifdef __STDC__
                    582: X
                    583: Xstatic void outflush(void)
                    584: X
                    585: X#else
                    586: X
                    587: Xstatic void outflush()
                    588: X
                    589: X#endif
                    590: X{
                    591: X    char           *buf;
                    592: X    int             got;
                    593: X    uint            len;
                    594: X
                    595: X    /* if (bufidx - buf > 0) */
                    596: X      for (buf = bufstart; len = bufidx - buf;) {
                    597: X          if ((got = write(archivefd, buf, MIN(len, blocksize))) > 0) {
                    598: X              buf += got;
                    599: X          } else if (got < 0) {
                    600: X              next(AR_WRITE);
                    601: X          }
                    602: X      }
                    603: X    bufend = (bufidx = bufstart) + blocksize;
                    604: X}
                    605: X
                    606: X
                    607: X/* ar_read - fill the archive buffer
                    608: X *
                    609: X * DESCRIPTION
                    610: X *
                    611: X *    Remembers mid-buffer read failures and reports them the next time 
                    612: X *    through.  Replaces unreadable data with null characters.   Resets
                    613: X *    the buffer pointers as appropriate.
                    614: X *
                    615: X * RETURNS
                    616: X *
                    617: X *    Returns zero with valid data, -1 otherwise. 
                    618: X */
                    619: X
                    620: X#ifdef __STDC__
                    621: X
                    622: Xint ar_read(void)
                    623: X
                    624: X#else
                    625: X
                    626: Xint ar_read()
                    627: X
                    628: X#endif
                    629: X{
                    630: X    int             got;
                    631: X    static int      failed;
                    632: X
                    633: X    bufend = bufidx = bufstart;
                    634: X    if (!failed) {
                    635: X      if (areof) {
                    636: X          if (total == 0) {
                    637: X              fatal("No input");
                    638: X          } else {
                    639: X              next(AR_READ);
                    640: X          }
                    641: X      }
                    642: X      while (!failed && !areof && bufstart + blocksize - bufend >= blocksize) {
                    643: X          if ((got = read(archivefd, bufend, (unsigned int) blocksize)) > 0) {
                    644: X              bufend += got;
                    645: X          } else if (got < 0) {
                    646: X              failed = -1;
                    647: X              warnarch(syserr(), (OFFSET) 0 - (bufend - bufidx));
                    648: X          } else {
                    649: X              ++areof;
                    650: X          }
                    651: X      }
                    652: X    }
                    653: X    if (failed && bufend == bufstart) {
                    654: X      failed = 0;
                    655: X      for (got = 0; got < blocksize; ++got) {
                    656: X          *bufend++ = '\0';
                    657: X      }
                    658: X      return (-1);
                    659: X    }
                    660: X    return (0);
                    661: X}
                    662: X
                    663: X
                    664: X/* ar_write - write a filesystem block
                    665: X *
                    666: X * DESCRIPTION
                    667: X *
                    668: X *    Writes len bytes of data data from the specified buffer to the 
                    669: X *    specified file.   Seeks past sparse blocks. 
                    670: X *
                    671: X * PARAMETERS
                    672: X *
                    673: X *    int     fd      - file to write to
                    674: X *    char   *buf     - buffer to get data from
                    675: X *    uint    len     - number of bytes to transfer
                    676: X *
                    677: X * RETURNS
                    678: X *
                    679: X *    Returns 0 if the block was written, the given length for a sparse 
                    680: X *    block or -1 if unsuccessful. 
                    681: X */
                    682: X
                    683: X#ifdef __STDC__
                    684: X
                    685: Xstatic int ar_write(int fd, char *buf, uint len)
                    686: X
                    687: X#else
                    688: X
                    689: Xstatic int ar_write(fd, buf, len)
                    690: Xint             fd;
                    691: Xchar           *buf;
                    692: Xuint            len;
                    693: X
                    694: X#endif
                    695: X{
                    696: X    char           *bidx;
                    697: X    char           *bend;
                    698: X
                    699: X    bend = (bidx = buf) + len;
                    700: X    while (bidx < bend) {
                    701: X      if (*bidx++) {
                    702: X          return (write(fd, buf, len) == len ? 0 : -1);
                    703: X      }
                    704: X    }
                    705: X    return (lseek(fd, (OFFSET) len, 1) < 0 ? -1 : len);
                    706: X}
                    707: X
                    708: X
                    709: X/* buf_pad - pad the archive buffer
                    710: X *
                    711: X * DESCRIPTION
                    712: X *
                    713: X *    Buf_pad writes len zero bytes to the archive buffer in order to 
                    714: X *    pad it.
                    715: X *
                    716: X * PARAMETERS
                    717: X *
                    718: X *    OFFSET  pad     - number of zero bytes to pad
                    719: X *
                    720: X */
                    721: X
                    722: X#ifdef __STDC__
                    723: X
                    724: Xstatic void buf_pad(OFFSET pad)
                    725: X
                    726: X#else
                    727: X
                    728: Xstatic void buf_pad(pad)
                    729: XOFFSET           pad;
                    730: X
                    731: X#endif
                    732: X{
                    733: X    int             idx;
                    734: X    int             have;
                    735: X
                    736: X    while (pad) {
                    737: X      if ((have = bufend - bufidx) > pad) {
                    738: X          have = pad;
                    739: X      }
                    740: X      for (idx = 0; idx < have; ++idx) {
                    741: X          *bufidx++ = '\0';
                    742: X      }
                    743: X      total += have;
                    744: X      pad -= have;
                    745: X      if (bufend - bufidx == 0) {
                    746: X          outflush();
                    747: X      }
                    748: X    }
                    749: X}
                    750: X
                    751: X
                    752: X/* buf_use - allocate buffer space
                    753: X *
                    754: X * DESCRIPTION
                    755: X *
                    756: X *    Buf_use marks space in the buffer as being used; advancing both the
                    757: X *    buffer index (bufidx) and the total byte count (total).
                    758: X *
                    759: X * PARAMETERS
                    760: X *
                    761: X *    uint    len     - Amount of space to allocate in the buffer
                    762: X */
                    763: X
                    764: X#ifdef __STDC__
                    765: X
                    766: Xstatic void buf_use(uint len)
                    767: X
                    768: X#else
                    769: X
                    770: Xstatic void buf_use(len)
                    771: Xuint            len;
                    772: X
                    773: X#endif
                    774: X{
                    775: X    bufidx += len;
                    776: X    total += len;
                    777: X}
                    778: X
                    779: X
                    780: X/* buf_in_avail - index available input data within the buffer
                    781: X *
                    782: X * DESCRIPTION
                    783: X *
                    784: X *    Buf_in_avail fills the archive buffer, and points the bufp
                    785: X *    parameter at the start of the data.  The lenp parameter is
                    786: X *    modified to contain the number of bytes which were read.
                    787: X *
                    788: X * PARAMETERS
                    789: X *
                    790: X *    char   **bufp   - pointer to the buffer to read data into
                    791: X *    uint    *lenp   - pointer to the number of bytes which were read
                    792: X *                      (returned to the caller)
                    793: X *
                    794: X * RETURNS
                    795: X *
                    796: X *    Stores a pointer to the data and its length in given locations. 
                    797: X *    Returns zero with valid data, -1 if unreadable portions were 
                    798: X *    replaced with nulls. 
                    799: X *
                    800: X * ERRORS
                    801: X *
                    802: X *    If an error occurs in ar_read, the error code is returned to the
                    803: X *    calling function.
                    804: X *
                    805: X */
                    806: X
                    807: X#ifdef __STDC__
                    808: X
                    809: Xstatic int buf_in_avail(char **bufp, uint *lenp)
                    810: X
                    811: X#else
                    812: X
                    813: Xstatic int buf_in_avail(bufp, lenp)
                    814: Xchar          **bufp;
                    815: Xuint           *lenp;
                    816: X
                    817: X#endif
                    818: X{
                    819: X    uint            have;
                    820: X    int             corrupt = 0;
                    821: X
                    822: X    while ((have = bufend - bufidx) == 0) {
                    823: X      corrupt |= ar_read();
                    824: X    }
                    825: X    *bufp = bufidx;
                    826: X    *lenp = have;
                    827: X    return (corrupt);
                    828: X}
                    829: X
                    830: X
                    831: X/* buf_out_avail  - index buffer space for archive output
                    832: X *
                    833: X * DESCRIPTION
                    834: X *
                    835: X *    Stores a buffer pointer at a given location. Returns the number 
                    836: X *    of bytes available. 
                    837: X *
                    838: X * PARAMETERS
                    839: X *
                    840: X *    char    **bufp  - pointer to the buffer which is to be stored
                    841: X *
                    842: X * RETURNS
                    843: X *
                    844: X *    The number of bytes which are available in the buffer.
                    845: X *
                    846: X */
                    847: X
                    848: X#ifdef __STDC__
                    849: X
                    850: Xstatic uint buf_out_avail(char **bufp)
                    851: X
                    852: X#else
                    853: X
                    854: Xstatic uint buf_out_avail(bufp)
                    855: Xchar          **bufp;
                    856: X
                    857: X#endif
                    858: X{
                    859: X    int             have;
                    860: X
                    861: X    if (bufend - bufidx < 0) {
                    862: X      fatal("Buffer overlow in buf_out_avail\n");
                    863: X    }
                    864: X    if ((have = bufend - bufidx) == 0) {
                    865: X      outflush();
                    866: X    }
                    867: X    *bufp = bufidx;
                    868: X    return (have);
                    869: X}
                    870: END_OF_buffer.c
                    871: if test 17360 -ne `wc -c <buffer.c`; then
                    872:     echo shar: \"buffer.c\" unpacked with wrong size!
                    873: fi
                    874: # end of overwriting check
                    875: fi
                    876: if test -f paxdir.c -a "${1}" != "-c" ; then 
                    877:   echo shar: Will not over-write existing file \"paxdir.c\"
                    878: else
                    879: echo shar: Extracting \"paxdir.c\" \(16936 characters\)
                    880: sed "s/^X//" >paxdir.c <<'END_OF_paxdir.c'
                    881: X/*
                    882: X      opendir -- open a directory stream
                    883: X  
                    884: X      last edit:      16-Jun-1987     D A Gwyn
                    885: X*/
                    886: X
                    887: X#include      <sys/errno.h>
                    888: X#include      <sys/types.h>
                    889: X#include      <sys/stat.h>
                    890: X#include      "paxdir.h"
                    891: X
                    892: X#ifdef BSD_SYSV
                    893: X/*
                    894: X      <sys/_dir.h> -- definitions for 4.2,4.3BSD directories
                    895: X  
                    896: X      last edit:      25-Apr-1987     D A Gwyn
                    897: X  
                    898: X      A directory consists of some number of blocks of DIRBLKSIZ bytes each,
                    899: X      where DIRBLKSIZ is chosen such that it can be transferred to disk in a
                    900: X      single atomic operation (e.g., 512 bytes on most machines).
                    901: X  
                    902: X      Each DIRBLKSIZ-byte block contains some number of directory entry
                    903: X      structures, which are of variable length.  Each directory entry has the
                    904: X      beginning of a (struct direct) at the front of it, containing its
                    905: X      filesystem-unique ident number, the length of the entry, and the length
                    906: X      of the name contained in the entry.  These are followed by the NUL-
                    907: X      terminated name padded to a (long) boundary with 0 bytes.  The maximum
                    908: X      length of a name in a directory is MAXNAMELEN.
                    909: X  
                    910: X      The macro DIRSIZ(dp) gives the amount of space required to represent a
                    911: X      directory entry.  Free space in a directory is represented by entries
                    912: X      that have dp->d_reclen > DIRSIZ(dp).  All DIRBLKSIZ bytes in a
                    913: X      directory block are claimed by the directory entries; this usually
                    914: X      results in the last entry in a directory having a large dp->d_reclen.
                    915: X      When entries are deleted from a directory, the space is returned to the
                    916: X      previous entry in the same directory block by increasing its
                    917: X      dp->d_reclen.  If the first entry of a directory block is free, then
                    918: X      its dp->d_fileno is set to 0; entries other than the first in a
                    919: X      directory do not normally have  dp->d_fileno set to 0.
                    920: X  
                    921: X      prerequisite:   <sys/types.h>
                    922: X*/
                    923: X
                    924: X#if defined(accel) || defined(sun) || defined(vax)
                    925: X#define       DIRBLKSIZ       512     /* size of directory block */
                    926: X#else
                    927: X#ifdef alliant
                    928: X#define       DIRBLKSIZ       4096    /* size of directory block */
                    929: X#else
                    930: X#ifdef gould
                    931: X#define       DIRBLKSIZ       1024    /* size of directory block */
                    932: X#else
                    933: X#ifdef ns32000                        /* Dynix System V */
                    934: X#define       DIRBLKSIZ       2600    /* size of directory block */
                    935: X#else                         /* be conservative; multiple blocks are okay
                    936: X                               * but fractions are not */
                    937: X#define       DIRBLKSIZ       4096    /* size of directory block */
                    938: X#endif
                    939: X#endif
                    940: X#endif
                    941: X#endif
                    942: X
                    943: X#define       MAXNAMELEN      255     /* maximum filename length */
                    944: X/* NOTE:  not MAXNAMLEN, which has been preempted by SVR3 <dirent.h> */
                    945: X
                    946: Xstruct direct {                       /* data from read()/_getdirentries() */
                    947: X    unsigned long   d_fileno; /* unique ident of entry */
                    948: X    unsigned short  d_reclen; /* length of this record */
                    949: X    unsigned short  d_namlen; /* length of string in d_name */
                    950: X    char            d_name[MAXNAMELEN + 1];   /* NUL-terminated filename */
                    951: X};
                    952: X
                    953: X/*
                    954: X      The DIRSIZ macro gives the minimum record length which will hold the
                    955: X      directory entry.  This requires the amount of space in a (struct
                    956: X      direct) without the d_name field, plus enough space for the name with a
                    957: X      terminating NUL character, rounded up to a (long) boundary.
                    958: X  
                    959: X      (Note that Berkeley didn't properly compensate for struct padding,
                    960: X      but we nevertheless have to use the same size as the actual system.)
                    961: X*/
                    962: X
                    963: X#define       DIRSIZ( dp )    ((sizeof(struct direct) - (MAXNAMELEN+1) \
                    964: X                      + sizeof(long) + (dp)->d_namlen) \
                    965: X                      / sizeof(long) * sizeof(long))
                    966: X
                    967: X#else
                    968: X#include      <sys/dir.h>
                    969: X#ifdef SYSV3
                    970: X#undef        MAXNAMLEN               /* avoid conflict with SVR3 */
                    971: X#endif
                    972: X /* Good thing we don't need to use the DIRSIZ() macro! */
                    973: X#ifdef d_ino                  /* 4.3BSD/NFS using d_fileno */
                    974: X#undef        d_ino                   /* (not absolutely necessary) */
                    975: X#else
                    976: X#define       d_fileno        d_ino   /* (struct direct) member */
                    977: X#endif
                    978: X#endif
                    979: X#ifdef UNK
                    980: X#ifndef UFS
                    981: X#include "***** ERROR ***** UNK applies only to UFS"
                    982: X/* One could do something similar for getdirentries(), but I didn't bother. */
                    983: X#endif
                    984: X#include      <signal.h>
                    985: X#endif
                    986: X
                    987: X#if defined(UFS) + defined(BFS) + defined(NFS) != 1   /* sanity check */
                    988: X#include "***** ERROR ***** exactly one of UFS, BFS, or NFS must be defined"
                    989: X#endif
                    990: X
                    991: X#ifdef UFS
                    992: X#define       RecLen( dp )    (sizeof(struct direct)) /* fixed-length entries */
                    993: X#else                         /* BFS || NFS */
                    994: X#define       RecLen( dp )    ((dp)->d_reclen)        /* variable-length entries */
                    995: X#endif
                    996: X
                    997: X#ifdef NFS
                    998: X#ifdef BSD_SYSV
                    999: X#define       getdirentries   _getdirentries  /* package hides this system call */
                   1000: X#endif
                   1001: Xextern int      getdirentries();
                   1002: Xstatic long     dummy;                /* getdirentries() needs basep */
                   1003: X#define       GetBlock( fd, buf, n )  getdirentries( fd, buf, (unsigned)n, &dummy )
                   1004: X#else                         /* UFS || BFS */
                   1005: X#ifdef BSD_SYSV
                   1006: X#define read  _read           /* avoid emulation overhead */
                   1007: X#endif
                   1008: Xextern int      read();
                   1009: X#define       GetBlock( fd, buf, n )  read( fd, buf, (unsigned)n )
                   1010: X#endif
                   1011: X
                   1012: X#ifdef UNK
                   1013: Xextern int      _getdents();  /* actual system call */
                   1014: X#endif
                   1015: X
                   1016: Xextern char    *strncpy();
                   1017: Xextern int      fstat();
                   1018: Xextern OFFSET   lseek();
                   1019: X
                   1020: Xextern int      errno;
                   1021: X
                   1022: X#ifndef DIRBLKSIZ
                   1023: X#define       DIRBLKSIZ       4096    /* directory file read buffer size */
                   1024: X#endif
                   1025: X
                   1026: X#ifndef NULL
                   1027: X#define       NULL    0
                   1028: X#endif
                   1029: X
                   1030: X#ifndef SEEK_CUR
                   1031: X#define       SEEK_CUR        1
                   1032: X#endif
                   1033: X
                   1034: X#ifndef S_ISDIR                       /* macro to test for directory file */
                   1035: X#define       S_ISDIR( mode )         (((mode) & S_IFMT) == S_IFDIR)
                   1036: X#endif
                   1037: X
                   1038: X
                   1039: X#ifndef SEEK_CUR
                   1040: X#define       SEEK_CUR        1
                   1041: X#endif
                   1042: X
                   1043: X#ifdef BSD_SYSV
                   1044: X#define open  _open           /* avoid emulation overhead */
                   1045: X#endif
                   1046: X
                   1047: Xextern int      getdents();   /* SVR3 system call, or emulation */
                   1048: X
                   1049: Xtypedef char   *pointer;      /* (void *) if you have it */
                   1050: X
                   1051: Xextern void     free();
                   1052: Xextern pointer  malloc();
                   1053: Xextern int
                   1054: Xopen(), close(), fstat();
                   1055: X
                   1056: Xextern int      errno;
                   1057: Xextern OFFSET   lseek();
                   1058: X
                   1059: X#ifndef SEEK_SET
                   1060: X#define       SEEK_SET        0
                   1061: X#endif
                   1062: X
                   1063: Xtypedef int     bool;         /* Boolean data type */
                   1064: X#define       false   0
                   1065: X#define       true    1
                   1066: X
                   1067: X
                   1068: X#ifndef NULL
                   1069: X#define       NULL    0
                   1070: X#endif
                   1071: X
                   1072: X#ifndef O_RDONLY
                   1073: X#define       O_RDONLY        0
                   1074: X#endif
                   1075: X
                   1076: X#ifndef S_ISDIR                       /* macro to test for directory file */
                   1077: X#define       S_ISDIR( mode )         (((mode) & S_IFMT) == S_IFDIR)
                   1078: X#endif
                   1079: X
                   1080: X#ifdef __STDC__
                   1081: X
                   1082: XDIR *opendir(char *dirname)
                   1083: X
                   1084: X#else
                   1085: X    
                   1086: XDIR *opendir(dirname)
                   1087: Xchar           *dirname;      /* name of directory */
                   1088: X
                   1089: X#endif
                   1090: X{
                   1091: X    register DIR   *dirp;     /* -> malloc'ed storage */
                   1092: X    register int    fd;               /* file descriptor for read */
                   1093: X    struct stat     sbuf;     /* result of fstat() */
                   1094: X
                   1095: X    if ((fd = open(dirname, O_RDONLY)) < 0)
                   1096: X      return NULL;            /* errno set by open() */
                   1097: X
                   1098: X    if (fstat(fd, &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) {
                   1099: X      close(fd);
                   1100: X      errno = ENOTDIR;
                   1101: X      return NULL;            /* not a directory */
                   1102: X    }
                   1103: X    if ((dirp = (DIR *) malloc(sizeof(DIR))) == NULL
                   1104: X      || (dirp->dd_buf = (char *) malloc((unsigned) DIRBUF)) == NULL
                   1105: X      ) {
                   1106: X      register int    serrno = errno;
                   1107: X      /* errno set to ENOMEM by sbrk() */
                   1108: X
                   1109: X      if (dirp != NULL)
                   1110: X          free((pointer) dirp);
                   1111: X
                   1112: X      close(fd);
                   1113: X      errno = serrno;
                   1114: X      return NULL;            /* not enough memory */
                   1115: X    }
                   1116: X    dirp->dd_fd = fd;
                   1117: X    dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
                   1118: X
                   1119: X    return dirp;
                   1120: X}
                   1121: X
                   1122: X
                   1123: X/*
                   1124: X *    closedir -- close a directory stream
                   1125: X *
                   1126: X *    last edit:      11-Nov-1988     D A Gwyn
                   1127: X */
                   1128: X
                   1129: X#ifdef __STDC__
                   1130: X
                   1131: Xint closedir(register DIR *dirp)
                   1132: X
                   1133: X#else
                   1134: X    
                   1135: Xint closedir(dirp)
                   1136: Xregister DIR  *dirp;          /* stream from opendir() */
                   1137: X
                   1138: X#endif
                   1139: X{
                   1140: X    register int      fd;
                   1141: X
                   1142: X    if ( dirp == NULL || dirp->dd_buf == NULL ) {
                   1143: X      errno = EFAULT;
                   1144: X      return -1;                      /* invalid pointer */
                   1145: X    }
                   1146: X
                   1147: X    fd = dirp->dd_fd;                 /* bug fix thanks to R. Salz */
                   1148: X    free( (pointer)dirp->dd_buf );
                   1149: X    free( (pointer)dirp );
                   1150: X    return close( fd );
                   1151: X}
                   1152: X
                   1153: X
                   1154: X/*
                   1155: X      readdir -- read next entry from a directory stream
                   1156: X  
                   1157: X      last edit:      25-Apr-1987     D A Gwyn
                   1158: X*/
                   1159: X
                   1160: X#ifdef __STDC__
                   1161: X
                   1162: Xstruct dirent  *readdir(register DIR *dirp)
                   1163: X
                   1164: X#else
                   1165: X    
                   1166: Xstruct dirent  *readdir(dirp)
                   1167: Xregister DIR   *dirp;         /* stream from opendir() */
                   1168: X
                   1169: X#endif
                   1170: X{
                   1171: X    register struct dirent *dp;       /* -> directory data */
                   1172: X
                   1173: X    if (dirp == NULL || dirp->dd_buf == NULL) {
                   1174: X      errno = EFAULT;
                   1175: X      return NULL;            /* invalid pointer */
                   1176: X    }
                   1177: X    do {
                   1178: X      if (dirp->dd_loc >= dirp->dd_size)      /* empty or obsolete */
                   1179: X          dirp->dd_loc = dirp->dd_size = 0;
                   1180: X
                   1181: X      if (dirp->dd_size == 0  /* need to refill buffer */
                   1182: X          && (dirp->dd_size =
                   1183: X              getdents(dirp->dd_fd, dirp->dd_buf, (unsigned) DIRBUF)
                   1184: X              ) <= 0
                   1185: X          )
                   1186: X          return NULL;        /* EOF or error */
                   1187: X
                   1188: X      dp = (struct dirent *) & dirp->dd_buf[dirp->dd_loc];
                   1189: X      dirp->dd_loc += dp->d_reclen;
                   1190: X    }
                   1191: X    while (dp->d_ino == 0L);  /* don't rely on getdents() */
                   1192: X
                   1193: X    return dp;
                   1194: X}
                   1195: X
                   1196: X
                   1197: X/*
                   1198: X      seekdir -- reposition a directory stream
                   1199: X  
                   1200: X      last edit:      24-May-1987     D A Gwyn
                   1201: X  
                   1202: X      An unsuccessful seekdir() will in general alter the current
                   1203: X      directory position; beware.
                   1204: X  
                   1205: X      NOTE:   4.nBSD directory compaction makes seekdir() & telldir()
                   1206: X              practically impossible to do right.  Avoid using them!
                   1207: X*/
                   1208: X
                   1209: X#ifdef __STDC__
                   1210: X
                   1211: Xvoid seekdir(register DIR *dirp, register OFFSET loc)
                   1212: X
                   1213: X#else
                   1214: X    
                   1215: Xvoid seekdir(dirp, loc)
                   1216: Xregister DIR   *dirp;         /* stream from opendir() */
                   1217: Xregister OFFSET  loc;         /* position from telldir() */
                   1218: X
                   1219: X#endif
                   1220: X{
                   1221: X    register bool   rewind;   /* "start over when stymied" flag */
                   1222: X
                   1223: X    if (dirp == NULL || dirp->dd_buf == NULL) {
                   1224: X      errno = EFAULT;
                   1225: X      return;                 /* invalid pointer */
                   1226: X    }
                   1227: X    /*
                   1228: X     * A (struct dirent)'s d_off is an invented quantity on 4.nBSD
                   1229: X     * NFS-supporting systems, so it is not safe to lseek() to it. 
                   1230: X     */
                   1231: X
                   1232: X    /* Monotonicity of d_off is heavily exploited in the following. */
                   1233: X
                   1234: X    /*
                   1235: X     * This algorithm is tuned for modest directory sizes.  For huge
                   1236: X     * directories, it might be more efficient to read blocks until the first
                   1237: X     * d_off is too large, then back up one block, or even to use binary
                   1238: X     * search on the directory blocks.  I doubt that the extra code for that
                   1239: X     * would be worthwhile. 
                   1240: X     */
                   1241: X
                   1242: X    if (dirp->dd_loc >= dirp->dd_size /* invalid index */
                   1243: X      || ((struct dirent *) & dirp->dd_buf[dirp->dd_loc])->d_off > loc
                   1244: X    /* too far along in buffer */
                   1245: X      )
                   1246: X      dirp->dd_loc = 0;       /* reset to beginning of buffer */
                   1247: X    /* else save time by starting at current dirp->dd_loc */
                   1248: X
                   1249: X    for (rewind = true;;) {
                   1250: X      register struct dirent *dp;
                   1251: X
                   1252: X      /* See whether the matching entry is in the current buffer. */
                   1253: X
                   1254: X      if ((dirp->dd_loc < dirp->dd_size       /* valid index */
                   1255: X           || readdir(dirp) != NULL   /* next buffer read */
                   1256: X           && (dirp->dd_loc = 0, true)        /* beginning of buffer set */
                   1257: X           )
                   1258: X          && (dp = (struct dirent *) & dirp->dd_buf[dirp->dd_loc])->d_off
                   1259: X          <= loc              /* match possible in this buffer */
                   1260: X          ) {
                   1261: X          for ( /* dp initialized above */ ;
                   1262: X               (char *) dp < &dirp->dd_buf[dirp->dd_size];
                   1263: X               dp = (struct dirent *) ((char *) dp + dp->d_reclen)
                   1264: X              )
                   1265: X              if (dp->d_off == loc) { /* found it! */
                   1266: X                  dirp->dd_loc =
                   1267: X                      (char *) dp - dirp->dd_buf;
                   1268: X                  return;
                   1269: X              }
                   1270: X          rewind = false;     /* no point in backing up later */
                   1271: X          dirp->dd_loc = dirp->dd_size;       /* set end of buffer */
                   1272: X      } else
                   1273: X       /* whole buffer past matching entry */ if (!rewind) {  /* no point in searching
                   1274: X                                                               * further */
                   1275: X          errno = EINVAL;
                   1276: X          return;             /* no entry at specified loc */
                   1277: X      } else {                /* rewind directory and start over */
                   1278: X          rewind = false;     /* but only once! */
                   1279: X
                   1280: X          dirp->dd_loc = dirp->dd_size = 0;
                   1281: X
                   1282: X          if (lseek(dirp->dd_fd, (OFFSET) 0, SEEK_SET)
                   1283: X              != 0
                   1284: X              )
                   1285: X              return;         /* errno already set (EBADF) */
                   1286: X
                   1287: X          if (loc == 0)
                   1288: X              return;         /* save time */
                   1289: X      }
                   1290: X    }
                   1291: X}
                   1292: X
                   1293: X
                   1294: X/* telldir - report directory stream position
                   1295: X *
                   1296: X * DESCRIPTION
                   1297: X *
                   1298: X *    Returns the offset of the next directory entry in the
                   1299: X *    directory associated with dirp.
                   1300: X *
                   1301: X *    NOTE:   4.nBSD directory compaction makes seekdir() & telldir()
                   1302: X *            practically impossible to do right.  Avoid using them!
                   1303: X *
                   1304: X * PARAMETERS
                   1305: X *
                   1306: X *    DIR     *dirp   - stream from opendir()
                   1307: X *
                   1308: X * RETURNS
                   1309: X *
                   1310: X *    Return offset of next entry 
                   1311: X */
                   1312: X
                   1313: X
                   1314: X#ifdef __STDC__
                   1315: X
                   1316: XOFFSET telldir(DIR *dirp)
                   1317: X
                   1318: X#else
                   1319: X    
                   1320: XOFFSET telldir(dirp)                  
                   1321: XDIR            *dirp;         /* stream from opendir() */
                   1322: X
                   1323: X#endif
                   1324: X{
                   1325: X    if (dirp == NULL || dirp->dd_buf == NULL) {
                   1326: X      errno = EFAULT;
                   1327: X      return -1;              /* invalid pointer */
                   1328: X    }
                   1329: X    if (dirp->dd_loc < dirp->dd_size) /* valid index */
                   1330: X      return ((struct dirent *) & dirp->dd_buf[dirp->dd_loc])->d_off;
                   1331: X    else                      /* beginning of next directory block */
                   1332: X      return lseek(dirp->dd_fd, (OFFSET) 0, SEEK_CUR);
                   1333: X}
                   1334: X
                   1335: X
                   1336: X#ifdef UFS
                   1337: X
                   1338: X/*
                   1339: X      The following routine is necessary to handle DIRSIZ-long entry names.
                   1340: X      Thanks to Richard Todd for pointing this out.
                   1341: X*/
                   1342: X
                   1343: X
                   1344: X/* return # chars in embedded name */
                   1345: X
                   1346: X#ifdef __STDC__
                   1347: X
                   1348: Xstatic int NameLen(char *name)
                   1349: X
                   1350: X#else
                   1351: X    
                   1352: Xstatic int NameLen(name)
                   1353: Xchar            *name;                /* -> name embedded in struct direct */
                   1354: X
                   1355: X#endif
                   1356: X{
                   1357: X    register char  *s;                /* -> name[.] */
                   1358: X    register char  *stop = &name[DIRSIZ];     /* -> past end of name field */
                   1359: X
                   1360: X    for (s = &name[1];                /* (empty names are impossible) */
                   1361: X       *s != '\0'             /* not NUL terminator */
                   1362: X       && ++s < stop;         /* < DIRSIZ characters scanned */
                   1363: X      );
                   1364: X
                   1365: X    return s - name;          /* # valid characters in name */
                   1366: X}
                   1367: X
                   1368: X#else                         /* BFS || NFS */
                   1369: X
                   1370: Xextern int      strlen();
                   1371: X
                   1372: X#define       NameLen( name ) strlen( name )  /* names are always NUL-terminated */
                   1373: X
                   1374: X#endif
                   1375: X
                   1376: X#ifdef UNK
                   1377: Xstatic enum {
                   1378: X    maybe, no, yes
                   1379: X} state = maybe;
                   1380: X
                   1381: X
                   1382: X/* sig_catch - used to catch signals
                   1383: X *
                   1384: X * DESCRIPTION
                   1385: X *
                   1386: X *    Used to catch signals.
                   1387: X */
                   1388: X
                   1389: X/*ARGSUSED*/
                   1390: X
                   1391: X#ifdef __STDC__
                   1392: X
                   1393: Xstatic void sig_catch(int sig)
                   1394: X
                   1395: X#else
                   1396: X    
                   1397: Xstatic void sig_catch(sig)
                   1398: Xint             sig;          /* must be SIGSYS */
                   1399: X
                   1400: X#endif
                   1401: X{
                   1402: X    state = no;                       /* attempted _getdents() faulted */
                   1403: X}
                   1404: X#endif
                   1405: X
                   1406: X
                   1407: X/* getdents - get directory entries
                   1408: X *
                   1409: X * DESCRIPTION
                   1410: X *
                   1411: X *    Gets directory entries from the filesystem in an implemenation
                   1412: X *    defined way.
                   1413: X *
                   1414: X * PARAMETERS
                   1415: X *
                   1416: X *    int             fildes  - directory file descriptor 
                   1417: X *    char           *buf     - where to put the (struct dirent)s 
                   1418: X *    unsigned        nbyte   - size of buf[] 
                   1419: X *
                   1420: X * RETURNS
                   1421: X * 
                   1422: X *    Returns number of bytes read; 0 on EOF, -1 on error 
                   1423: X */
                   1424: X
                   1425: X#ifdef __STDC__
                   1426: X
                   1427: Xint getdents(int fildes, char *buf, unsigned nbyte)
                   1428: X
                   1429: X#else
                   1430: X    
                   1431: Xint getdents(fildes, buf, nbyte)      
                   1432: Xint             fildes;               /* directory file descriptor */
                   1433: Xchar           *buf;          /* where to put the (struct dirent)s */
                   1434: Xunsigned        nbyte;                /* size of buf[] */
                   1435: X
                   1436: X#endif
                   1437: X{
                   1438: X    int             serrno;   /* entry errno */
                   1439: X    OFFSET          offset;   /* initial directory file offset */
                   1440: X    struct stat     statb;    /* fstat() info */
                   1441: X    union {
                   1442: X      /* directory file block buffer */
                   1443: X#ifdef UFS
                   1444: X      char            dblk[DIRBLKSIZ + 1];
                   1445: X#else
                   1446: X      char            dblk[DIRBLKSIZ];
                   1447: X#endif
                   1448: X      struct direct   dummy;  /* just for alignment */
                   1449: X    } u;              /* (avoids having to malloc()) */
                   1450: X    register struct direct *dp;       /* -> u.dblk[.] */
                   1451: X    register struct dirent *bp;       /* -> buf[.] */
                   1452: X
                   1453: X#ifdef UNK
                   1454: X    switch (state) {
                   1455: X      SIG_T         (*shdlr)();       /* entry SIGSYS handler */
                   1456: X      register int    retval;         /* return from _getdents() if any */
                   1457: X
                   1458: X    case yes:                 /* _getdents() is known to work */
                   1459: X      return _getdents(fildes, buf, nbyte);
                   1460: X
                   1461: X    case maybe:               /* first time only */
                   1462: X      shdlr = signal(SIGSYS, sig_catch);
                   1463: X      retval = _getdents(fildes, buf, nbyte); /* try it */
                   1464: X      signal(SIGSYS, shdlr);
                   1465: X
                   1466: X      if (state == maybe) {   /* SIGSYS did not occur */
                   1467: X          state = yes;        /* so _getdents() must have worked */
                   1468: X          return retval;
                   1469: X      }
                   1470: X      /* else fall through into emulation */
                   1471: X
                   1472: X/*    case no:        /* fall through into emulation */
                   1473: X    }
                   1474: X#endif
                   1475: X
                   1476: X    if (buf == NULL
                   1477: X#ifdef ATT_SPEC
                   1478: X      || (unsigned long) buf % sizeof(long) != 0      /* ugh */
                   1479: X#endif
                   1480: X      ) {
                   1481: X      errno = EFAULT;         /* invalid pointer */
                   1482: X      return -1;
                   1483: X    }
                   1484: X    if (fstat(fildes, &statb) != 0) {
                   1485: X      return -1;              /* errno set by fstat() */
                   1486: X    }
                   1487: X
                   1488: X    if (!S_ISDIR(statb.st_mode)) {
                   1489: X      errno = ENOTDIR;        /* not a directory */
                   1490: X      return -1;
                   1491: X    }
                   1492: X    if ((offset = lseek(fildes, (OFFSET) 0, SEEK_CUR)) < 0) {
                   1493: X      return -1;              /* errno set by lseek() */
                   1494: X    }
                   1495: X
                   1496: X#ifdef BFS                    /* no telling what remote hosts do */
                   1497: X    if ((unsigned long) offset % DIRBLKSIZ != 0) {
                   1498: X      errno = ENOENT;         /* file pointer probably misaligned */
                   1499: X      return -1;
                   1500: X    }
                   1501: X#endif
                   1502: X
                   1503: X    serrno = errno;           /* save entry errno */
                   1504: X
                   1505: X    for (bp = (struct dirent *) buf; bp == (struct dirent *) buf;) {  
                   1506: X
                   1507: X      /* convert next directory block */
                   1508: X      int             size;
                   1509: X
                   1510: X      do {
                   1511: X          size = GetBlock(fildes, u.dblk, DIRBLKSIZ);
                   1512: X      } while (size == -1 && errno == EINTR);
                   1513: X
                   1514: X      if (size <= 0) {
                   1515: X          return size;        /* EOF or error (EBADF) */
                   1516: X      }
                   1517: X
                   1518: X      for (dp = (struct direct *) u.dblk;
                   1519: X           (char *) dp < &u.dblk[size];
                   1520: X           dp = (struct direct *) ((char *) dp + RecLen(dp))
                   1521: X          ) {
                   1522: X#ifndef UFS
                   1523: X          if (dp->d_reclen <= 0) {
                   1524: X              errno = EIO;    /* corrupted directory */
                   1525: X              return -1;
                   1526: X          }
                   1527: X#endif
                   1528: X
                   1529: X          if (dp->d_fileno != 0) {    /* non-empty; copy to user buffer */
                   1530: X              register int    reclen =
                   1531: X              DIRENTSIZ(NameLen(dp->d_name));
                   1532: X
                   1533: X              if ((char *) bp + reclen > &buf[nbyte]) {
                   1534: X                  errno = EINVAL;
                   1535: X                  return -1;  /* buf too small */
                   1536: X              }
                   1537: X              bp->d_ino = dp->d_fileno;
                   1538: X              bp->d_off = offset + ((char *) dp - u.dblk);
                   1539: X              bp->d_reclen = reclen;
                   1540: X
                   1541: X              {
                   1542: X#ifdef UFS
                   1543: X                  /* Is the following kludge ugly?  You bet. */
                   1544: X
                   1545: X                  register char   save = dp->d_name[DIRSIZ];
                   1546: X                  /* save original data */
                   1547: X
                   1548: X                  dp->d_name[DIRSIZ] = '\0';
                   1549: X                  /* ensure NUL termination */
                   1550: X#endif
                   1551: X                  /* adds NUL padding */
                   1552: X                  strncpy(bp->d_name, dp->d_name, reclen - DIRENTBASESIZ);
                   1553: X#ifdef UFS
                   1554: X                  dp->d_name[DIRSIZ] = save;
                   1555: X                  /* restore original data */
                   1556: X#endif
                   1557: X              }
                   1558: X
                   1559: X              bp = (struct dirent *) ((char *) bp + reclen);
                   1560: X          }
                   1561: X      }
                   1562: X
                   1563: X#ifndef BFS                   /* 4.2BSD screwed up; fixed in 4.3BSD */
                   1564: X      if ((char *) dp > &u.dblk[size]) {
                   1565: X          errno = EIO;        /* corrupted directory */
                   1566: X          return -1;
                   1567: X      }
                   1568: X#endif
                   1569: X    }
                   1570: X
                   1571: X    errno = serrno;           /* restore entry errno */
                   1572: X    return (char *) bp - buf; /* return # bytes read */
                   1573: X}
                   1574: END_OF_paxdir.c
                   1575: if test 16936 -ne `wc -c <paxdir.c`; then
                   1576:     echo shar: \"paxdir.c\" unpacked with wrong size!
                   1577: fi
                   1578: # end of overwriting check
                   1579: fi
                   1580: echo shar: End of archive 5 \(of 6\).
                   1581: cp /dev/null ark5isdone
                   1582: MISSING=""
                   1583: for I in 1 2 3 4 5 6 ; do
                   1584:     if test ! -f ark${I}isdone ; then
                   1585:        MISSING="${MISSING} ${I}"
                   1586:     fi
                   1587: done
                   1588: if test "${MISSING}" = "" ; then
                   1589:     echo You have unpacked all 6 archives.
                   1590:     rm -f ark[1-9]isdone
                   1591: else
                   1592:     echo You still need to unpack the following archives:
                   1593:     echo "        " ${MISSING}
                   1594: fi
                   1595: ##  End of shell archive.
                   1596: exit 0
                   1597: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.