Annotation of coherent/d/usr/bin/pax/public/part05.sh, revision 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.