Annotation of coherent/e/bin/pax/buffer.c, revision 1.1

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

unix.superglobalmegacorp.com

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