home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / std_unix / pax / 5 / buffer.c next >
C/C++ Source or Header  |  1989-01-07  |  17KB  |  856 lines

  1. /* $Source: /u/mark/src/pax/RCS/buffer.c,v $
  2.  *
  3.  * $Revision: 1.1 $
  4.  *
  5.  * buffer.c - Buffer management functions
  6.  *
  7.  * DESCRIPTION
  8.  *
  9.  *    These functions handle buffer manipulations for the archiving
  10.  *    formats.  Functions are provided to get memory for buffers, 
  11.  *    flush buffers, read and write buffers and de-allocate buffers.  
  12.  *    Several housekeeping functions are provided as well to get some 
  13.  *    information about how full buffers are, etc.
  14.  *
  15.  * AUTHOR
  16.  *
  17.  *    Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  18.  *
  19.  * Sponsored by The USENIX Association for public distribution. 
  20.  *
  21.  * Copyright (c) 1989 Mark H. Colburn.
  22.  * All rights reserved.
  23.  *
  24.  * Redistribution and use in source and binary forms are permitted
  25.  * provided that the above copyright notice is duplicated in all such 
  26.  * forms and that any documentation, advertising materials, and other 
  27.  * materials related to such distribution and use acknowledge that the 
  28.  * software was developed * by Mark H. Colburn and sponsored by The 
  29.  * USENIX Association. 
  30.  *
  31.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  32.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  33.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  34.  *
  35.  * $Log:    buffer.c,v $
  36.  * Revision 1.1  88/12/23  18:02:01  mark
  37.  * Initial revision
  38.  * 
  39.  */
  40.  
  41. #ifndef lint
  42. static char *ident = "$Id: buffer.c,v 1.1 88/12/23 18:02:01 mark Rel $";
  43. static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  44. #endif /* ! lint */
  45.  
  46.  
  47. /* Headers */
  48.  
  49. #include "pax.h"
  50.  
  51.  
  52. /* Function Prototypes */
  53.  
  54. #ifdef __STDC__
  55.  
  56. static int ar_write(int, char *, uint);
  57. static void buf_pad(OFFSET);
  58. static int indata(int, OFFSET, char *);
  59. static void outflush(void);
  60. static void buf_use(uint);
  61. static int buf_in_avail(char **, uint *);
  62. static uint buf_out_avail(char **);
  63.  
  64. #else /* !__STDC__ */
  65.  
  66. static int ar_write();
  67. static void buf_pad();
  68. static int indata();
  69. static void outflush();
  70. static void buf_use();
  71. static int buf_in_avail();
  72. static uint buf_out_avail();
  73.  
  74. #endif /* __STDC__ */
  75.  
  76.  
  77. /* inentry - install a single archive entry
  78.  *
  79.  * DESCRIPTION
  80.  *
  81.  *    Inentry reads an archive entry from the archive file and writes it
  82.  *    out the the named file.  If we are in PASS mode during archive
  83.  *    processing, the pass() function is called, otherwise we will
  84.  *    extract from the archive file.
  85.  *
  86.  *    Inentry actaully calls indata to process the actual data to the
  87.  *    file.
  88.  *
  89.  * PARAMETERS
  90.  *
  91.  *    char    *name    - name of the file to extract from the archive
  92.  *    Stat    *asb    - stat block of the file to be extracted from the
  93.  *              archive.
  94.  *
  95.  * RETURNS
  96.  *
  97.  *     Returns zero if successful, -1 otherwise. 
  98.  */
  99.  
  100. #ifdef __STDC__
  101.  
  102. int inentry(char *name, Stat *asb)
  103.  
  104. #else
  105.  
  106. int inentry(name, asb)
  107. char           *name;
  108. Stat           *asb;
  109.  
  110. #endif
  111. {
  112.     Link           *linkp;
  113.     int             ifd;
  114.     int             ofd;
  115.     time_t          tstamp[2];
  116.  
  117.     if ((ofd = openo(name, asb, linkp = linkfrom(name, asb), 0)) > 0) {
  118.     if (asb->sb_size || linkp == NULL || linkp->l_size == 0) {
  119.         close(indata(ofd, asb->sb_size, name));
  120.     } else if ((ifd = open(linkp->l_path->p_name, O_RDONLY)) < 0) {
  121.         warn(linkp->l_path->p_name, syserr());
  122.     } else {
  123.         passdata(linkp->l_path->p_name, ifd, name, ofd);
  124.         close(ifd);
  125.         close(ofd);
  126.     }
  127.     } else {
  128.     return(buf_skip((OFFSET) asb->sb_size) >= 0);
  129.     }
  130.     tstamp[0] = (!f_pass && f_access_time) ? asb->sb_atime : time((time_t *) 0);
  131.     tstamp[1] = f_modification_time ? asb->sb_mtime : time((time_t *) 0);
  132.     utime(name, tstamp);
  133.     return (0);
  134. }
  135.  
  136.  
  137. /* outdata - write archive data
  138.  *
  139.  * DESCRIPTION
  140.  *
  141.  *    Outdata transfers data from the named file to the archive buffer.
  142.  *    It knows about the file padding which is required by tar, but no
  143.  *    by cpio.  Outdata continues after file read errors, padding with 
  144.  *    null characters if neccessary.   Closes the input file descriptor 
  145.  *    when finished.
  146.  *
  147.  * PARAMETERS
  148.  *
  149.  *    int    fd    - file descriptor of file to read data from
  150.  *    char   *name    - name of file
  151.  *    OFFSET    size    - size of the file
  152.  *
  153.  */
  154.  
  155. #ifdef __STDC__
  156.  
  157. void outdata(int fd, char *name, OFFSET size)
  158.  
  159. #else
  160.  
  161. void outdata(fd, name, size)
  162. int             fd;
  163. char           *name;
  164. OFFSET          size;
  165.  
  166. #endif
  167. {
  168.     uint            chunk;
  169.     int             got;
  170.     int             oops;
  171.     uint            avail;
  172.     int            pad;
  173.     char           *buf;
  174.  
  175.     oops = got = 0;
  176.     if (pad = (size % BLOCKSIZE)) {
  177.     pad = (BLOCKSIZE - pad);
  178.     }
  179.     while (size) {
  180.     avail = buf_out_avail(&buf);
  181.     size -= (chunk = size < avail ? (uint) size : avail);
  182.     if (oops == 0 && (got = read(fd, buf, (unsigned int) chunk)) < 0) {
  183.         oops = -1;
  184.         warn(name, syserr());
  185.         got = 0;
  186.     }
  187.     if (got < chunk) {
  188.         if (oops == NULL) {
  189.         oops = -1;
  190.         }
  191.         warn(name, "Early EOF");
  192.         while (got < chunk) {
  193.         buf[got++] = '\0';
  194.         }
  195.     }
  196.     buf_use(chunk);
  197.     }
  198.     close(fd);
  199.     if (ar_format == TAR) {
  200.     buf_pad((OFFSET) pad);
  201.     }
  202. }
  203.  
  204.  
  205. /* write_eot -  write the end of archive record(s)
  206.  *
  207.  * DESCRIPTION
  208.  *
  209.  *    Write out an End-Of-Tape record.  We actually zero at least one 
  210.  *    record, through the end of the block.  Old tar writes garbage after 
  211.  *    two zeroed records -- and PDtar used to.
  212.  */
  213.  
  214. #ifdef __STDC__
  215.  
  216. void write_eot(void)
  217.  
  218. #else
  219.  
  220. void write_eot()
  221.  
  222. #endif
  223. {
  224.     OFFSET           pad;
  225.     char            header[M_STRLEN + H_STRLEN + 1];
  226.  
  227.     if (ar_format == TAR) {
  228.     /* write out two zero blocks for trailer */
  229.     pad = 2 * BLOCKSIZE;
  230.     } else {
  231.     if (pad = (total + M_STRLEN + H_STRLEN + TRAILZ) % BLOCKSIZE) {
  232.         pad = BLOCKSIZE - pad;
  233.     }
  234.     strcpy(header, M_ASCII);
  235.     sprintf(header + M_STRLEN, H_PRINT, 0, 0,
  236.                0, 0, 0, 1, 0, (time_t) 0, TRAILZ, pad);
  237.     outwrite(header, M_STRLEN + H_STRLEN);
  238.     outwrite(TRAILER, TRAILZ);
  239.     }
  240.     buf_pad((OFFSET) pad);
  241.     outflush();
  242. }
  243.  
  244.  
  245. /* outwrite -  write archive data
  246.  *
  247.  * DESCRIPTION
  248.  *
  249.  *    Writes out data in the archive buffer to the archive file.  The
  250.  *    buffer index and the total byte count are incremented by the number
  251.  *    of data bytes written.
  252.  *
  253.  * PARAMETERS
  254.  *    
  255.  *    char   *idx    - pointer to data to write
  256.  *    uint    len    - length of the data to write
  257.  */
  258.  
  259. #ifdef __STDC__
  260.  
  261. void outwrite(char *idx, uint len)
  262.  
  263. #else
  264.  
  265. void outwrite(idx, len)
  266. char           *idx;    /* pointer to data to write */
  267. uint            len;    /* length of data to write */
  268.  
  269. #endif
  270. {
  271.     uint            have;
  272.     uint            want;
  273.     char           *endx;
  274.  
  275.     endx = idx + len;
  276.     while (want = endx - idx) {
  277.     if (bufend - bufidx < 0) {
  278.         fatal("Buffer overlow in out_write\n");
  279.     }
  280.     if ((have = bufend - bufidx) == 0) {
  281.         outflush();
  282.     }
  283.     if (have > want) {
  284.         have = want;
  285.     }
  286.     memcpy(bufidx, idx, (int) have);
  287.     bufidx += have;
  288.     idx += have;
  289.     total += have;
  290.     }
  291. }
  292.  
  293.  
  294. /* passdata - copy data to one file
  295.  *
  296.  * DESCRIPTION
  297.  *
  298.  *    Copies a file from one place to another.  Doesn't believe in input 
  299.  *    file descriptor zero (see description of kludge in openi() comments). 
  300.  *    Closes the provided output file descriptor. 
  301.  *
  302.  * PARAMETERS
  303.  *
  304.  *    char    *from    - input file name (old file)
  305.  *    int    ifd    - input file descriptor
  306.  *    char    *to    - output file name (new file)
  307.  *    int    ofd    - output file descriptor
  308.  */
  309.  
  310. #ifdef __STDC__
  311.  
  312. void passdata(char *from, int ifd, char *to, int ofd)
  313.  
  314. #else
  315.  
  316. void passdata(from, ifd, to, ofd)
  317. char           *from;
  318. int             ifd;
  319. char           *to;
  320. int             ofd;
  321.  
  322. #endif
  323. {
  324.     int             got;
  325.     int             sparse;
  326.     char            block[BUFSIZ];
  327.  
  328.     if (ifd) {
  329.     lseek(ifd, (OFFSET) 0, 0);
  330.     sparse = 0;
  331.     while ((got = read(ifd, block, sizeof(block))) > 0
  332.            && (sparse = ar_write(ofd, block, (uint) got)) >= 0) {
  333.         total += got;
  334.     }
  335.     if (got) {
  336.         warn(got < 0 ? from : to, syserr());
  337.     } else if (sparse > 0
  338.          && (lseek(ofd, (OFFSET)(-sparse), 1) < 0
  339.              || write(ofd, block, (uint) sparse) != sparse)) {
  340.         warn(to, syserr());
  341.     }
  342.     }
  343.     close(ofd);
  344. }
  345.  
  346.  
  347. /* buf_allocate - get space for the I/O buffer 
  348.  *
  349.  * DESCRIPTION
  350.  *
  351.  *    buf_allocate allocates an I/O buffer using malloc.  The resulting
  352.  *    buffer is used for all data buffering throughout the program.
  353.  *    Buf_allocate must be called prior to any use of the buffer or any
  354.  *    of the buffering calls.
  355.  *
  356.  * PARAMETERS
  357.  *
  358.  *    int    size    - size of the I/O buffer to request
  359.  *
  360.  * ERRORS
  361.  *
  362.  *    If an invalid size is given for a buffer or if a buffer of the 
  363.  *    required size cannot be allocated, then the function prints out an 
  364.  *    error message and returns a non-zero exit status to the calling 
  365.  *    process, terminating the program.
  366.  *
  367.  */
  368.  
  369. #ifdef __STDC__
  370.  
  371. void buf_allocate(OFFSET size)
  372.  
  373. #else
  374.  
  375. void buf_allocate(size)
  376. OFFSET            size;
  377.  
  378. #endif
  379. {
  380.     extern char *malloc();
  381.     
  382.     if (size <= 0) {
  383.     fatal("invalid value for blocksize");
  384.     }
  385.     if ((bufstart = malloc((unsigned) size)) == NULL) {
  386.     fatal("Cannot allocate I/O buffer");
  387.     }
  388.     bufend = bufidx = bufstart;
  389.     bufend += size;
  390. }
  391.  
  392.  
  393. /* buf_skip - skip input archive data
  394.  *
  395.  * DESCRIPTION
  396.  *
  397.  *    Buf_skip skips past archive data.  It is used when the length of
  398.  *    the archive data is known, and we do not wish to process the data.
  399.  *
  400.  * PARAMETERS
  401.  *
  402.  *    OFFSET    len    - number of bytes to skip
  403.  *
  404.  * RETURNS
  405.  *
  406.  *     Returns zero under normal circumstances, -1 if unreadable data is 
  407.  *     encountered. 
  408.  */
  409.  
  410. #ifdef __STDC__
  411.  
  412. int buf_skip(OFFSET len)
  413.  
  414. #else
  415.  
  416. int buf_skip(len)
  417. OFFSET           len;
  418.  
  419. #endif
  420. {
  421.     uint            chunk;
  422.     int             corrupt = 0;
  423.  
  424.     while (len) {
  425.     if (bufend - bufidx < 0) {
  426.         fatal("Buffer overlow in buf_skip\n");
  427.     }
  428.     while ((chunk = bufend - bufidx) == 0) {
  429.         corrupt |= ar_read();
  430.     }
  431.     if (chunk > len) {
  432.         chunk = len;
  433.     }
  434.     bufidx += chunk;
  435.     len -= chunk;
  436.     total += chunk;
  437.     }
  438.     return (corrupt);
  439. }
  440.  
  441.  
  442. /* buf_read - read a given number of characters from the input archive
  443.  *
  444.  * DESCRIPTION
  445.  *
  446.  *    Reads len number of characters from the input archive and
  447.  *    stores them in the buffer pointed at by dst.
  448.  *
  449.  * PARAMETERS
  450.  *
  451.  *    char   *dst    - pointer to buffer to store data into
  452.  *    uint    len    - length of data to read
  453.  *
  454.  * RETURNS
  455.  *
  456.  *     Returns zero with valid data, -1 if unreadable portions were 
  457.  *    replaced by null characters. 
  458.  */
  459.  
  460. #ifdef __STDC__
  461.  
  462. int buf_read(char *dst, uint len)
  463.  
  464. #else
  465.  
  466. int buf_read(dst, len)
  467. char           *dst;
  468. uint            len;
  469.  
  470. #endif
  471. {
  472.     int             have;
  473.     int             want;
  474.     int             corrupt = 0;
  475.     char           *endx = dst + len;
  476.  
  477.     while (want = endx - dst) {
  478.     if (bufend - bufidx < 0) {
  479.         fatal("Buffer overlow in buf_read\n");
  480.     }
  481.     while ((have = bufend - bufidx) == 0) {
  482.         have = 0;
  483.         corrupt |= ar_read();
  484.     }
  485.     if (have > want) {
  486.         have = want;
  487.     }
  488.     memcpy(dst, bufidx, have);
  489.     bufidx += have;
  490.     dst += have;
  491.     total += have;
  492.     }
  493.     return (corrupt);
  494. }
  495.  
  496.  
  497. /* indata - install data from an archive
  498.  *
  499.  * DESCRIPTION
  500.  *
  501.  *    Indata writes size bytes of data from the archive buffer to the output 
  502.  *    file specified by fd.  The filename which is being written, pointed
  503.  *    to by name is provided only for diagnostics.
  504.  *
  505.  * PARAMETERS
  506.  *
  507.  *    int    fd    - output file descriptor
  508.  *    OFFSET    size    - number of bytes to write to output file
  509.  *    char    *name    - name of file which corresponds to fd
  510.  *
  511.  * RETURNS
  512.  *
  513.  *     Returns given file descriptor. 
  514.  */
  515.  
  516. #ifdef __STDC__
  517.  
  518. static int indata(int fd, OFFSET size, char *name)
  519.  
  520. #else
  521.  
  522. static int indata(fd, size, name)
  523. int             fd;
  524. OFFSET          size;
  525. char           *name;
  526.  
  527. #endif
  528. {
  529.     uint            chunk;
  530.     char           *oops;
  531.     int             sparse;
  532.     int             corrupt;
  533.     char           *buf;
  534.     uint            avail;
  535.  
  536.     corrupt = sparse = 0;
  537.     oops = NULL;
  538.     while (size) {
  539.     corrupt |= buf_in_avail(&buf, &avail);
  540.     size -= (chunk = size < avail ? (uint) size : avail);
  541.     if (oops == NULL && (sparse = ar_write(fd, buf, chunk)) < 0) {
  542.         oops = syserr();
  543.     }
  544.     buf_use(chunk);
  545.     }
  546.     if (corrupt) {
  547.     warn(name, "Corrupt archive data");
  548.     }
  549.     if (oops) {
  550.     warn(name, oops);
  551.     } else if (sparse > 0 && (lseek(fd, (OFFSET) - 1, 1) < 0
  552.                   || write(fd, "", 1) != 1)) {
  553.     warn(name, syserr());
  554.     }
  555.     return (fd);
  556. }
  557.  
  558.  
  559. /* outflush - flush the output buffer
  560.  *
  561.  * DESCRIPTION
  562.  *
  563.  *    The output buffer is written, if there is anything in it, to the
  564.  *    archive file.
  565.  */
  566.  
  567. #ifdef __STDC__
  568.  
  569. static void outflush(void)
  570.  
  571. #else
  572.  
  573. static void outflush()
  574.  
  575. #endif
  576. {
  577.     char           *buf;
  578.     int             got;
  579.     uint            len;
  580.  
  581.     /* if (bufidx - buf > 0) */
  582.     for (buf = bufstart; len = bufidx - buf;) {
  583.         if ((got = write(archivefd, buf, MIN(len, blocksize))) > 0) {
  584.         buf += got;
  585.         } else if (got < 0) {
  586.         next(AR_WRITE);
  587.         }
  588.     }
  589.     bufend = (bufidx = bufstart) + blocksize;
  590. }
  591.  
  592.  
  593. /* ar_read - fill the archive buffer
  594.  *
  595.  * DESCRIPTION
  596.  *
  597.  *     Remembers mid-buffer read failures and reports them the next time 
  598.  *    through.  Replaces unreadable data with null characters.   Resets
  599.  *    the buffer pointers as appropriate.
  600.  *
  601.  * RETURNS
  602.  *
  603.  *    Returns zero with valid data, -1 otherwise. 
  604.  */
  605.  
  606. #ifdef __STDC__
  607.  
  608. int ar_read(void)
  609.  
  610. #else
  611.  
  612. int ar_read()
  613.  
  614. #endif
  615. {
  616.     int             got;
  617.     static int      failed;
  618.  
  619.     bufend = bufidx = bufstart;
  620.     if (!failed) {
  621.     if (areof) {
  622.         if (total == 0) {
  623.         fatal("No input");
  624.         } else {
  625.         next(AR_READ);
  626.         }
  627.     }
  628.     while (!failed && !areof && bufstart + blocksize - bufend >= blocksize) {
  629.         if ((got = read(archivefd, bufend, (unsigned int) blocksize)) > 0) {
  630.         bufend += got;
  631.         } else if (got < 0) {
  632.         failed = -1;
  633.         warnarch(syserr(), (OFFSET) 0 - (bufend - bufidx));
  634.         } else {
  635.         ++areof;
  636.         }
  637.     }
  638.     }
  639.     if (failed && bufend == bufstart) {
  640.     failed = 0;
  641.     for (got = 0; got < blocksize; ++got) {
  642.         *bufend++ = '\0';
  643.     }
  644.     return (-1);
  645.     }
  646.     return (0);
  647. }
  648.  
  649.  
  650. /* ar_write - write a filesystem block
  651.  *
  652.  * DESCRIPTION
  653.  *
  654.  *     Writes len bytes of data data from the specified buffer to the 
  655.  *    specified file.   Seeks past sparse blocks. 
  656.  *
  657.  * PARAMETERS
  658.  *
  659.  *    int     fd    - file to write to
  660.  *    char   *buf    - buffer to get data from
  661.  *    uint    len    - number of bytes to transfer
  662.  *
  663.  * RETURNS
  664.  *
  665.  *    Returns 0 if the block was written, the given length for a sparse 
  666.  *    block or -1 if unsuccessful. 
  667.  */
  668.  
  669. #ifdef __STDC__
  670.  
  671. static int ar_write(int fd, char *buf, uint len)
  672.  
  673. #else
  674.  
  675. static int ar_write(fd, buf, len)
  676. int             fd;
  677. char           *buf;
  678. uint            len;
  679.  
  680. #endif
  681. {
  682.     char           *bidx;
  683.     char           *bend;
  684.  
  685.     bend = (bidx = buf) + len;
  686.     while (bidx < bend) {
  687.     if (*bidx++) {
  688.         return (write(fd, buf, len) == len ? 0 : -1);
  689.     }
  690.     }
  691.     return (lseek(fd, (OFFSET) len, 1) < 0 ? -1 : len);
  692. }
  693.  
  694.  
  695. /* buf_pad - pad the archive buffer
  696.  *
  697.  * DESCRIPTION
  698.  *
  699.  *    Buf_pad writes len zero bytes to the archive buffer in order to 
  700.  *    pad it.
  701.  *
  702.  * PARAMETERS
  703.  *
  704.  *    OFFSET    pad    - number of zero bytes to pad
  705.  *
  706.  */
  707.  
  708. #ifdef __STDC__
  709.  
  710. static void buf_pad(OFFSET pad)
  711.  
  712. #else
  713.  
  714. static void buf_pad(pad)
  715. OFFSET           pad;
  716.  
  717. #endif
  718. {
  719.     int             idx;
  720.     int             have;
  721.  
  722.     while (pad) {
  723.     if ((have = bufend - bufidx) > pad) {
  724.         have = pad;
  725.     }
  726.     for (idx = 0; idx < have; ++idx) {
  727.         *bufidx++ = '\0';
  728.     }
  729.     total += have;
  730.     pad -= have;
  731.     if (bufend - bufidx == 0) {
  732.         outflush();
  733.     }
  734.     }
  735. }
  736.  
  737.  
  738. /* buf_use - allocate buffer space
  739.  *
  740.  * DESCRIPTION
  741.  *
  742.  *    Buf_use marks space in the buffer as being used; advancing both the
  743.  *    buffer index (bufidx) and the total byte count (total).
  744.  *
  745.  * PARAMETERS
  746.  *
  747.  *    uint    len    - Amount of space to allocate in the buffer
  748.  */
  749.  
  750. #ifdef __STDC__
  751.  
  752. static void buf_use(uint len)
  753.  
  754. #else
  755.  
  756. static void buf_use(len)
  757. uint            len;
  758.  
  759. #endif
  760. {
  761.     bufidx += len;
  762.     total += len;
  763. }
  764.  
  765.  
  766. /* buf_in_avail - index available input data within the buffer
  767.  *
  768.  * DESCRIPTION
  769.  *
  770.  *    Buf_in_avail fills the archive buffer, and points the bufp
  771.  *    parameter at the start of the data.  The lenp parameter is
  772.  *    modified to contain the number of bytes which were read.
  773.  *
  774.  * PARAMETERS
  775.  *
  776.  *    char   **bufp    - pointer to the buffer to read data into
  777.  *    uint    *lenp    - pointer to the number of bytes which were read
  778.  *              (returned to the caller)
  779.  *
  780.  * RETURNS
  781.  *
  782.  *     Stores a pointer to the data and its length in given locations. 
  783.  *    Returns zero with valid data, -1 if unreadable portions were 
  784.  *    replaced with nulls. 
  785.  *
  786.  * ERRORS
  787.  *
  788.  *    If an error occurs in ar_read, the error code is returned to the
  789.  *    calling function.
  790.  *
  791.  */
  792.  
  793. #ifdef __STDC__
  794.  
  795. static int buf_in_avail(char **bufp, uint *lenp)
  796.  
  797. #else
  798.  
  799. static int buf_in_avail(bufp, lenp)
  800. char          **bufp;
  801. uint           *lenp;
  802.  
  803. #endif
  804. {
  805.     uint            have;
  806.     int             corrupt = 0;
  807.  
  808.     while ((have = bufend - bufidx) == 0) {
  809.     corrupt |= ar_read();
  810.     }
  811.     *bufp = bufidx;
  812.     *lenp = have;
  813.     return (corrupt);
  814. }
  815.  
  816.  
  817. /* buf_out_avail  - index buffer space for archive output
  818.  *
  819.  * DESCRIPTION
  820.  *
  821.  *     Stores a buffer pointer at a given location. Returns the number 
  822.  *    of bytes available. 
  823.  *
  824.  * PARAMETERS
  825.  *
  826.  *    char    **bufp    - pointer to the buffer which is to be stored
  827.  *
  828.  * RETURNS
  829.  *
  830.  *     The number of bytes which are available in the buffer.
  831.  *
  832.  */
  833.  
  834. #ifdef __STDC__
  835.  
  836. static uint buf_out_avail(char **bufp)
  837.  
  838. #else
  839.  
  840. static uint buf_out_avail(bufp)
  841. char          **bufp;
  842.  
  843. #endif
  844. {
  845.     int             have;
  846.  
  847.     if (bufend - bufidx < 0) {
  848.     fatal("Buffer overlow in buf_out_avail\n");
  849.     }
  850.     if ((have = bufend - bufidx) == 0) {
  851.     outflush();
  852.     }
  853.     *bufp = bufidx;
  854.     return (have);
  855. }
  856.