home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 May / W2KPRK.iso / apps / posix / source / PAX / BUFFER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-17  |  21.9 KB  |  979 lines

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