home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / PAX20.ZIP / BUFFER.C < prev    next >
C/C++ Source or Header  |  1990-11-12  |  20KB  |  918 lines

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