|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.