📄 buffer.c
字号:
/* $Source: /u/mark/src/pax/RCS/buffer.c,v $ * * $Revision: 1.2 $ * * buffer.c - Buffer management functions * * DESCRIPTION * * These functions handle buffer manipulations for the archiving * formats. Functions are provided to get memory for buffers, * flush buffers, read and write buffers and de-allocate buffers. * Several housekeeping functions are provided as well to get some * information about how full buffers are, etc. * * AUTHOR * * Mark H. Colburn, NAPS International (mark@jhereg.mn.org) * * Sponsored by The USENIX Association for public distribution. * * Copyright (c) 1989 Mark H. Colburn. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice is duplicated in all such * forms and that any documentation, advertising materials, and other * materials related to such distribution and use acknowledge that the * software was developed * by Mark H. Colburn and sponsored by The * USENIX Association. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * $Log: buffer.c,v $ * Revision 1.2 89/02/12 10:04:02 mark * 1.2 release fixes * * Revision 1.1 88/12/23 18:02:01 mark * Initial revision * */#ifndef lintstatic char *ident = "$Id: buffer.c,v 1.2 89/02/12 10:04:02 mark Exp $";static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";#endif /* ! lint *//* Headers */#include "pax.h"/* Function Prototypes */#ifdef __STDC__static int ar_write(int, char *, uint);static void buf_pad(OFFSET);static int indata(int, OFFSET, char *);static void outflush(void);static void buf_use(uint);static int buf_in_avail(char **, uint *);static uint buf_out_avail(char **);#else /* !__STDC__ */static int ar_write();static void buf_pad();static int indata();static void outflush();static void buf_use();static int buf_in_avail();static uint buf_out_avail();#endif /* __STDC__ *//* inentry - install a single archive entry * * DESCRIPTION * * Inentry reads an archive entry from the archive file and writes it * out the the named file. If we are in PASS mode during archive * processing, the pass() function is called, otherwise we will * extract from the archive file. * * Inentry actaully calls indata to process the actual data to the * file. * * PARAMETERS * * char *name - name of the file to extract from the archive * Stat *asb - stat block of the file to be extracted from the * archive. * * RETURNS * * Returns zero if successful, -1 otherwise. */#ifdef __STDC__int inentry(char *name, Stat *asb)#elseint inentry(name, asb)char *name;Stat *asb;#endif{ Link *linkp; int ifd; int ofd; time_t tstamp[2]; if ((ofd = openout(name, asb, linkp = linkfrom(name, asb), 0)) > 0) { if (asb->sb_size || linkp == (Link *)NULL || linkp->l_size == 0) { close(indata(ofd, asb->sb_size, name)); } else if ((ifd = open(linkp->l_path->p_name, O_RDONLY)) < 0) { warn(linkp->l_path->p_name, strerror()); } else { passdata(linkp->l_path->p_name, ifd, name, ofd); close(ifd); close(ofd); } } else { return(buf_skip((OFFSET) asb->sb_size) >= 0); } tstamp[0] = (!f_pass && f_access_time) ? asb->sb_atime : time((time_t *) 0); tstamp[1] = f_mtime ? asb->sb_mtime : time((time_t *) 0); utime(name, tstamp); return (0);}/* outdata - write archive data * * DESCRIPTION * * Outdata transfers data from the named file to the archive buffer. * It knows about the file padding which is required by tar, but no * by cpio. Outdata continues after file read errors, padding with * null characters if neccessary. Closes the input file descriptor * when finished. * * PARAMETERS * * int fd - file descriptor of file to read data from * char *name - name of file * OFFSET size - size of the file * */#ifdef __STDC__void outdata(int fd, char *name, OFFSET size)#elsevoid outdata(fd, name, size)int fd;char *name;OFFSET size;#endif{ uint chunk; int got; int oops; uint avail; int pad; char *buf; oops = got = 0; if (pad = (size % BLOCKSIZE)) { pad = (BLOCKSIZE - pad); } while (size) { avail = buf_out_avail(&buf); size -= (chunk = size < avail ? (uint) size : avail); if (oops == 0 && (got = read(fd, buf, (unsigned int) chunk)) < 0) { oops = -1; warn(name, strerror()); got = 0; } if (got < chunk) { if (oops == 0) { oops = -1; } warn(name, "Early EOF"); while (got < chunk) { buf[got++] = '\0'; } } buf_use(chunk); } close(fd); if (ar_format == TAR) { buf_pad((OFFSET) pad); }}/* write_eot - write the end of archive record(s) * * DESCRIPTION * * Write out an End-Of-Tape record. We actually zero at least one * record, through the end of the block. Old tar writes garbage after * two zeroed records -- and PDtar used to. */#ifdef __STDC__void write_eot(void)#elsevoid write_eot()#endif{ OFFSET pad; char header[M_STRLEN + H_STRLEN + 1]; if (ar_format == TAR) { /* write out two zero blocks for trailer */ pad = 2 * BLOCKSIZE; } else { if (pad = (total + M_STRLEN + H_STRLEN + TRAILZ) % BLOCKSIZE) { pad = BLOCKSIZE - pad; } strcpy(header, M_ASCII); sprintf(header + M_STRLEN, H_PRINT, 0, 0, 0, 0, 0, 1, 0, (time_t) 0, TRAILZ, pad); outwrite(header, M_STRLEN + H_STRLEN); outwrite(TRAILER, TRAILZ); } buf_pad((OFFSET) pad); outflush();} /* outwrite - write archive data * * DESCRIPTION * * Writes out data in the archive buffer to the archive file. The * buffer index and the total byte count are incremented by the number * of data bytes written. * * PARAMETERS * * char *idx - pointer to data to write * uint len - length of the data to write */#ifdef __STDC__void outwrite(char *idx, uint len)#elsevoid outwrite(idx, len)char *idx; /* pointer to data to write */uint len; /* length of data to write */#endif{ uint have; uint want; char *endx; endx = idx + len; while (want = endx - idx) { if (bufend - bufidx < 0) { fatal("Buffer overlow in out_write\n"); } if ((have = bufend - bufidx) == 0) { outflush(); } if (have > want) { have = want; } memcpy(bufidx, idx, (int) have); bufidx += have; idx += have; total += have; }}/* passdata - copy data to one file * * DESCRIPTION * * Copies a file from one place to another. Doesn't believe in input * file descriptor zero (see description of kludge in openin() comments). * Closes the provided output file descriptor. * * PARAMETERS * * char *from - input file name (old file) * int ifd - input file descriptor * char *to - output file name (new file) * int ofd - output file descriptor */#ifdef __STDC__void passdata(char *from, int ifd, char *to, int ofd)#elsevoid passdata(from, ifd, to, ofd)char *from;int ifd;char *to;int ofd;#endif{ int got; int sparse; char block[BUFSIZ]; if (ifd) { lseek(ifd, (OFFSET) 0, 0); sparse = 0; while ((got = read(ifd, block, sizeof(block))) > 0 && (sparse = ar_write(ofd, block, (uint) got)) >= 0) { total += got; } if (got) { warn(got < 0 ? from : to, strerror()); } else if (sparse > 0 && (lseek(ofd, (OFFSET)(-sparse), 1) < 0 || write(ofd, block, (uint) sparse) != sparse)) { warn(to, strerror()); } } close(ofd);}/* buf_allocate - get space for the I/O buffer * * DESCRIPTION * * buf_allocate allocates an I/O buffer using malloc. The resulting * buffer is used for all data buffering throughout the program. * Buf_allocate must be called prior to any use of the buffer or any * of the buffering calls. * * PARAMETERS * * int size - size of the I/O buffer to request * * ERRORS * * If an invalid size is given for a buffer or if a buffer of the * required size cannot be allocated, then the function prints out an * error message and returns a non-zero exit status to the calling * process, terminating the program. * */#ifdef __STDC__void buf_allocate(OFFSET size)#elsevoid buf_allocate(size)OFFSET size;#endif{ if (size <= 0) { fatal("invalid value for blocksize"); } if ((bufstart = malloc((unsigned) size)) == (char *)NULL) { fatal("Cannot allocate I/O buffer"); } bufend = bufidx = bufstart; bufend += size;}/* buf_skip - skip input archive data * * DESCRIPTION * * Buf_skip skips past archive data. It is used when the length of * the archive data is known, and we do not wish to process the data. * * PARAMETERS * * OFFSET len - number of bytes to skip * * RETURNS * * Returns zero under normal circumstances, -1 if unreadable data is * encountered. */#ifdef __STDC__int buf_skip(OFFSET len)#elseint buf_skip(len)OFFSET len;#endif{ uint chunk; int corrupt = 0; while (len) { if (bufend - bufidx < 0) { fatal("Buffer overlow in buf_skip\n"); } while ((chunk = bufend - bufidx) == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -