|
|
1.1 root 1: # This is a shell archive. Remove anything before this line, then unpack
2: # it by saving it into a file and typing "sh file". To overwrite existing
3: # files, type "sh file -c". You can also feed this as standard input via
4: # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
5: # will see the following message at the end:
6: # "End of archive 5 (of 6)."
7: # Contents: buffer.c paxdir.c
8: # Wrapped by mark@jhereg on Tue Dec 27 19:37:59 1988
9: PATH=/bin:/usr/bin:/usr/ucb ; export PATH
10: if test -f buffer.c -a "${1}" != "-c" ; then
11: echo shar: Will not over-write existing file \"buffer.c\"
12: else
13: echo shar: Extracting \"buffer.c\" \(17360 characters\)
14: sed "s/^X//" >buffer.c <<'END_OF_buffer.c'
15: X/* $Source: /u/mark/src/pax/RCS/buffer.c,v $
16: X *
17: X * $Revision: 1.1 $
18: X *
19: X * buffer.c - Buffer management functions
20: X *
21: X * DESCRIPTION
22: X *
23: X * These functions handle buffer manipulations for the archiving
24: X * formats. Functions are provided to get memory for buffers,
25: X * flush buffers, read and write buffers and de-allocate buffers.
26: X * Several housekeeping functions are provided as well to get some
27: X * information about how full buffers are, etc.
28: X *
29: X * AUTHOR
30: X *
31: X * Mark H. Colburn, NAPS International ([email protected])
32: X *
33: X * Sponsored by The USENIX Association for public distribution.
34: X *
35: X * Copyright (c) 1989 Mark H. Colburn.
36: X * All rights reserved.
37: X *
38: X * Redistribution and use in source and binary forms are permitted
39: X * provided that the above copyright notice is duplicated in all such
40: X * forms and that any documentation, advertising materials, and other
41: X * materials related to such distribution and use acknowledge that the
42: X * software was developed * by Mark H. Colburn and sponsored by The
43: X * USENIX Association.
44: X *
45: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
46: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
47: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
48: X *
49: X * $Log: buffer.c,v $
50: X * Revision 1.1 88/12/23 18:02:01 mark
51: X * Initial revision
52: X *
53: X */
54: X
55: X#ifndef lint
56: Xstatic char *ident = "$Id: buffer.c,v 1.1 88/12/23 18:02:01 mark Rel $";
57: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
58: X#endif /* ! lint */
59: X
60: X
61: X/* Headers */
62: X
63: X#include "pax.h"
64: X
65: X
66: X/* Function Prototypes */
67: X
68: X#ifdef __STDC__
69: X
70: Xstatic int ar_write(int, char *, uint);
71: Xstatic void buf_pad(OFFSET);
72: Xstatic int indata(int, OFFSET, char *);
73: Xstatic void outflush(void);
74: Xstatic void buf_use(uint);
75: Xstatic int buf_in_avail(char **, uint *);
76: Xstatic uint buf_out_avail(char **);
77: X
78: X#else /* !__STDC__ */
79: X
80: Xstatic int ar_write();
81: Xstatic void buf_pad();
82: Xstatic int indata();
83: Xstatic void outflush();
84: Xstatic void buf_use();
85: Xstatic int buf_in_avail();
86: Xstatic uint buf_out_avail();
87: X
88: X#endif /* __STDC__ */
89: X
90: X
91: X/* inentry - install a single archive entry
92: X *
93: X * DESCRIPTION
94: X *
95: X * Inentry reads an archive entry from the archive file and writes it
96: X * out the the named file. If we are in PASS mode during archive
97: X * processing, the pass() function is called, otherwise we will
98: X * extract from the archive file.
99: X *
100: X * Inentry actaully calls indata to process the actual data to the
101: X * file.
102: X *
103: X * PARAMETERS
104: X *
105: X * char *name - name of the file to extract from the archive
106: X * Stat *asb - stat block of the file to be extracted from the
107: X * archive.
108: X *
109: X * RETURNS
110: X *
111: X * Returns zero if successful, -1 otherwise.
112: X */
113: X
114: X#ifdef __STDC__
115: X
116: Xint inentry(char *name, Stat *asb)
117: X
118: X#else
119: X
120: Xint inentry(name, asb)
121: Xchar *name;
122: XStat *asb;
123: X
124: X#endif
125: X{
126: X Link *linkp;
127: X int ifd;
128: X int ofd;
129: X time_t tstamp[2];
130: X
131: X if ((ofd = openo(name, asb, linkp = linkfrom(name, asb), 0)) > 0) {
132: X if (asb->sb_size || linkp == NULL || linkp->l_size == 0) {
133: X close(indata(ofd, asb->sb_size, name));
134: X } else if ((ifd = open(linkp->l_path->p_name, O_RDONLY)) < 0) {
135: X warn(linkp->l_path->p_name, syserr());
136: X } else {
137: X passdata(linkp->l_path->p_name, ifd, name, ofd);
138: X close(ifd);
139: X close(ofd);
140: X }
141: X } else {
142: X return(buf_skip((OFFSET) asb->sb_size) >= 0);
143: X }
144: X tstamp[0] = (!f_pass && f_access_time) ? asb->sb_atime : time((time_t *) 0);
145: X tstamp[1] = f_modification_time ? asb->sb_mtime : time((time_t *) 0);
146: X utime(name, tstamp);
147: X return (0);
148: X}
149: X
150: X
151: X/* outdata - write archive data
152: X *
153: X * DESCRIPTION
154: X *
155: X * Outdata transfers data from the named file to the archive buffer.
156: X * It knows about the file padding which is required by tar, but no
157: X * by cpio. Outdata continues after file read errors, padding with
158: X * null characters if neccessary. Closes the input file descriptor
159: X * when finished.
160: X *
161: X * PARAMETERS
162: X *
163: X * int fd - file descriptor of file to read data from
164: X * char *name - name of file
165: X * OFFSET size - size of the file
166: X *
167: X */
168: X
169: X#ifdef __STDC__
170: X
171: Xvoid outdata(int fd, char *name, OFFSET size)
172: X
173: X#else
174: X
175: Xvoid outdata(fd, name, size)
176: Xint fd;
177: Xchar *name;
178: XOFFSET size;
179: X
180: X#endif
181: X{
182: X uint chunk;
183: X int got;
184: X int oops;
185: X uint avail;
186: X int pad;
187: X char *buf;
188: X
189: X oops = got = 0;
190: X if (pad = (size % BLOCKSIZE)) {
191: X pad = (BLOCKSIZE - pad);
192: X }
193: X while (size) {
194: X avail = buf_out_avail(&buf);
195: X size -= (chunk = size < avail ? (uint) size : avail);
196: X if (oops == 0 && (got = read(fd, buf, (unsigned int) chunk)) < 0) {
197: X oops = -1;
198: X warn(name, syserr());
199: X got = 0;
200: X }
201: X if (got < chunk) {
202: X if (oops == NULL) {
203: X oops = -1;
204: X }
205: X warn(name, "Early EOF");
206: X while (got < chunk) {
207: X buf[got++] = '\0';
208: X }
209: X }
210: X buf_use(chunk);
211: X }
212: X close(fd);
213: X if (ar_format == TAR) {
214: X buf_pad((OFFSET) pad);
215: X }
216: X}
217: X
218: X
219: X/* write_eot - write the end of archive record(s)
220: X *
221: X * DESCRIPTION
222: X *
223: X * Write out an End-Of-Tape record. We actually zero at least one
224: X * record, through the end of the block. Old tar writes garbage after
225: X * two zeroed records -- and PDtar used to.
226: X */
227: X
228: X#ifdef __STDC__
229: X
230: Xvoid write_eot(void)
231: X
232: X#else
233: X
234: Xvoid write_eot()
235: X
236: X#endif
237: X{
238: X OFFSET pad;
239: X char header[M_STRLEN + H_STRLEN + 1];
240: X
241: X if (ar_format == TAR) {
242: X /* write out two zero blocks for trailer */
243: X pad = 2 * BLOCKSIZE;
244: X } else {
245: X if (pad = (total + M_STRLEN + H_STRLEN + TRAILZ) % BLOCKSIZE) {
246: X pad = BLOCKSIZE - pad;
247: X }
248: X strcpy(header, M_ASCII);
249: X sprintf(header + M_STRLEN, H_PRINT, 0, 0,
250: X 0, 0, 0, 1, 0, (time_t) 0, TRAILZ, pad);
251: X outwrite(header, M_STRLEN + H_STRLEN);
252: X outwrite(TRAILER, TRAILZ);
253: X }
254: X buf_pad((OFFSET) pad);
255: X outflush();
256: X}
257: X
258: X
259: X/* outwrite - write archive data
260: X *
261: X * DESCRIPTION
262: X *
263: X * Writes out data in the archive buffer to the archive file. The
264: X * buffer index and the total byte count are incremented by the number
265: X * of data bytes written.
266: X *
267: X * PARAMETERS
268: X *
269: X * char *idx - pointer to data to write
270: X * uint len - length of the data to write
271: X */
272: X
273: X#ifdef __STDC__
274: X
275: Xvoid outwrite(char *idx, uint len)
276: X
277: X#else
278: X
279: Xvoid outwrite(idx, len)
280: Xchar *idx; /* pointer to data to write */
281: Xuint len; /* length of data to write */
282: X
283: X#endif
284: X{
285: X uint have;
286: X uint want;
287: X char *endx;
288: X
289: X endx = idx + len;
290: X while (want = endx - idx) {
291: X if (bufend - bufidx < 0) {
292: X fatal("Buffer overlow in out_write\n");
293: X }
294: X if ((have = bufend - bufidx) == 0) {
295: X outflush();
296: X }
297: X if (have > want) {
298: X have = want;
299: X }
300: X memcpy(bufidx, idx, (int) have);
301: X bufidx += have;
302: X idx += have;
303: X total += have;
304: X }
305: X}
306: X
307: X
308: X/* passdata - copy data to one file
309: X *
310: X * DESCRIPTION
311: X *
312: X * Copies a file from one place to another. Doesn't believe in input
313: X * file descriptor zero (see description of kludge in openi() comments).
314: X * Closes the provided output file descriptor.
315: X *
316: X * PARAMETERS
317: X *
318: X * char *from - input file name (old file)
319: X * int ifd - input file descriptor
320: X * char *to - output file name (new file)
321: X * int ofd - output file descriptor
322: X */
323: X
324: X#ifdef __STDC__
325: X
326: Xvoid passdata(char *from, int ifd, char *to, int ofd)
327: X
328: X#else
329: X
330: Xvoid passdata(from, ifd, to, ofd)
331: Xchar *from;
332: Xint ifd;
333: Xchar *to;
334: Xint ofd;
335: X
336: X#endif
337: X{
338: X int got;
339: X int sparse;
340: X char block[BUFSIZ];
341: X
342: X if (ifd) {
343: X lseek(ifd, (OFFSET) 0, 0);
344: X sparse = 0;
345: X while ((got = read(ifd, block, sizeof(block))) > 0
346: X && (sparse = ar_write(ofd, block, (uint) got)) >= 0) {
347: X total += got;
348: X }
349: X if (got) {
350: X warn(got < 0 ? from : to, syserr());
351: X } else if (sparse > 0
352: X && (lseek(ofd, (OFFSET)(-sparse), 1) < 0
353: X || write(ofd, block, (uint) sparse) != sparse)) {
354: X warn(to, syserr());
355: X }
356: X }
357: X close(ofd);
358: X}
359: X
360: X
361: X/* buf_allocate - get space for the I/O buffer
362: X *
363: X * DESCRIPTION
364: X *
365: X * buf_allocate allocates an I/O buffer using malloc. The resulting
366: X * buffer is used for all data buffering throughout the program.
367: X * Buf_allocate must be called prior to any use of the buffer or any
368: X * of the buffering calls.
369: X *
370: X * PARAMETERS
371: X *
372: X * int size - size of the I/O buffer to request
373: X *
374: X * ERRORS
375: X *
376: X * If an invalid size is given for a buffer or if a buffer of the
377: X * required size cannot be allocated, then the function prints out an
378: X * error message and returns a non-zero exit status to the calling
379: X * process, terminating the program.
380: X *
381: X */
382: X
383: X#ifdef __STDC__
384: X
385: Xvoid buf_allocate(OFFSET size)
386: X
387: X#else
388: X
389: Xvoid buf_allocate(size)
390: XOFFSET size;
391: X
392: X#endif
393: X{
394: X extern char *malloc();
395: X
396: X if (size <= 0) {
397: X fatal("invalid value for blocksize");
398: X }
399: X if ((bufstart = malloc((unsigned) size)) == NULL) {
400: X fatal("Cannot allocate I/O buffer");
401: X }
402: X bufend = bufidx = bufstart;
403: X bufend += size;
404: X}
405: X
406: X
407: X/* buf_skip - skip input archive data
408: X *
409: X * DESCRIPTION
410: X *
411: X * Buf_skip skips past archive data. It is used when the length of
412: X * the archive data is known, and we do not wish to process the data.
413: X *
414: X * PARAMETERS
415: X *
416: X * OFFSET len - number of bytes to skip
417: X *
418: X * RETURNS
419: X *
420: X * Returns zero under normal circumstances, -1 if unreadable data is
421: X * encountered.
422: X */
423: X
424: X#ifdef __STDC__
425: X
426: Xint buf_skip(OFFSET len)
427: X
428: X#else
429: X
430: Xint buf_skip(len)
431: XOFFSET len;
432: X
433: X#endif
434: X{
435: X uint chunk;
436: X int corrupt = 0;
437: X
438: X while (len) {
439: X if (bufend - bufidx < 0) {
440: X fatal("Buffer overlow in buf_skip\n");
441: X }
442: X while ((chunk = bufend - bufidx) == 0) {
443: X corrupt |= ar_read();
444: X }
445: X if (chunk > len) {
446: X chunk = len;
447: X }
448: X bufidx += chunk;
449: X len -= chunk;
450: X total += chunk;
451: X }
452: X return (corrupt);
453: X}
454: X
455: X
456: X/* buf_read - read a given number of characters from the input archive
457: X *
458: X * DESCRIPTION
459: X *
460: X * Reads len number of characters from the input archive and
461: X * stores them in the buffer pointed at by dst.
462: X *
463: X * PARAMETERS
464: X *
465: X * char *dst - pointer to buffer to store data into
466: X * uint len - length of data to read
467: X *
468: X * RETURNS
469: X *
470: X * Returns zero with valid data, -1 if unreadable portions were
471: X * replaced by null characters.
472: X */
473: X
474: X#ifdef __STDC__
475: X
476: Xint buf_read(char *dst, uint len)
477: X
478: X#else
479: X
480: Xint buf_read(dst, len)
481: Xchar *dst;
482: Xuint len;
483: X
484: X#endif
485: X{
486: X int have;
487: X int want;
488: X int corrupt = 0;
489: X char *endx = dst + len;
490: X
491: X while (want = endx - dst) {
492: X if (bufend - bufidx < 0) {
493: X fatal("Buffer overlow in buf_read\n");
494: X }
495: X while ((have = bufend - bufidx) == 0) {
496: X have = 0;
497: X corrupt |= ar_read();
498: X }
499: X if (have > want) {
500: X have = want;
501: X }
502: X memcpy(dst, bufidx, have);
503: X bufidx += have;
504: X dst += have;
505: X total += have;
506: X }
507: X return (corrupt);
508: X}
509: X
510: X
511: X/* indata - install data from an archive
512: X *
513: X * DESCRIPTION
514: X *
515: X * Indata writes size bytes of data from the archive buffer to the output
516: X * file specified by fd. The filename which is being written, pointed
517: X * to by name is provided only for diagnostics.
518: X *
519: X * PARAMETERS
520: X *
521: X * int fd - output file descriptor
522: X * OFFSET size - number of bytes to write to output file
523: X * char *name - name of file which corresponds to fd
524: X *
525: X * RETURNS
526: X *
527: X * Returns given file descriptor.
528: X */
529: X
530: X#ifdef __STDC__
531: X
532: Xstatic int indata(int fd, OFFSET size, char *name)
533: X
534: X#else
535: X
536: Xstatic int indata(fd, size, name)
537: Xint fd;
538: XOFFSET size;
539: Xchar *name;
540: X
541: X#endif
542: X{
543: X uint chunk;
544: X char *oops;
545: X int sparse;
546: X int corrupt;
547: X char *buf;
548: X uint avail;
549: X
550: X corrupt = sparse = 0;
551: X oops = NULL;
552: X while (size) {
553: X corrupt |= buf_in_avail(&buf, &avail);
554: X size -= (chunk = size < avail ? (uint) size : avail);
555: X if (oops == NULL && (sparse = ar_write(fd, buf, chunk)) < 0) {
556: X oops = syserr();
557: X }
558: X buf_use(chunk);
559: X }
560: X if (corrupt) {
561: X warn(name, "Corrupt archive data");
562: X }
563: X if (oops) {
564: X warn(name, oops);
565: X } else if (sparse > 0 && (lseek(fd, (OFFSET) - 1, 1) < 0
566: X || write(fd, "", 1) != 1)) {
567: X warn(name, syserr());
568: X }
569: X return (fd);
570: X}
571: X
572: X
573: X/* outflush - flush the output buffer
574: X *
575: X * DESCRIPTION
576: X *
577: X * The output buffer is written, if there is anything in it, to the
578: X * archive file.
579: X */
580: X
581: X#ifdef __STDC__
582: X
583: Xstatic void outflush(void)
584: X
585: X#else
586: X
587: Xstatic void outflush()
588: X
589: X#endif
590: X{
591: X char *buf;
592: X int got;
593: X uint len;
594: X
595: X /* if (bufidx - buf > 0) */
596: X for (buf = bufstart; len = bufidx - buf;) {
597: X if ((got = write(archivefd, buf, MIN(len, blocksize))) > 0) {
598: X buf += got;
599: X } else if (got < 0) {
600: X next(AR_WRITE);
601: X }
602: X }
603: X bufend = (bufidx = bufstart) + blocksize;
604: X}
605: X
606: X
607: X/* ar_read - fill the archive buffer
608: X *
609: X * DESCRIPTION
610: X *
611: X * Remembers mid-buffer read failures and reports them the next time
612: X * through. Replaces unreadable data with null characters. Resets
613: X * the buffer pointers as appropriate.
614: X *
615: X * RETURNS
616: X *
617: X * Returns zero with valid data, -1 otherwise.
618: X */
619: X
620: X#ifdef __STDC__
621: X
622: Xint ar_read(void)
623: X
624: X#else
625: X
626: Xint ar_read()
627: X
628: X#endif
629: X{
630: X int got;
631: X static int failed;
632: X
633: X bufend = bufidx = bufstart;
634: X if (!failed) {
635: X if (areof) {
636: X if (total == 0) {
637: X fatal("No input");
638: X } else {
639: X next(AR_READ);
640: X }
641: X }
642: X while (!failed && !areof && bufstart + blocksize - bufend >= blocksize) {
643: X if ((got = read(archivefd, bufend, (unsigned int) blocksize)) > 0) {
644: X bufend += got;
645: X } else if (got < 0) {
646: X failed = -1;
647: X warnarch(syserr(), (OFFSET) 0 - (bufend - bufidx));
648: X } else {
649: X ++areof;
650: X }
651: X }
652: X }
653: X if (failed && bufend == bufstart) {
654: X failed = 0;
655: X for (got = 0; got < blocksize; ++got) {
656: X *bufend++ = '\0';
657: X }
658: X return (-1);
659: X }
660: X return (0);
661: X}
662: X
663: X
664: X/* ar_write - write a filesystem block
665: X *
666: X * DESCRIPTION
667: X *
668: X * Writes len bytes of data data from the specified buffer to the
669: X * specified file. Seeks past sparse blocks.
670: X *
671: X * PARAMETERS
672: X *
673: X * int fd - file to write to
674: X * char *buf - buffer to get data from
675: X * uint len - number of bytes to transfer
676: X *
677: X * RETURNS
678: X *
679: X * Returns 0 if the block was written, the given length for a sparse
680: X * block or -1 if unsuccessful.
681: X */
682: X
683: X#ifdef __STDC__
684: X
685: Xstatic int ar_write(int fd, char *buf, uint len)
686: X
687: X#else
688: X
689: Xstatic int ar_write(fd, buf, len)
690: Xint fd;
691: Xchar *buf;
692: Xuint len;
693: X
694: X#endif
695: X{
696: X char *bidx;
697: X char *bend;
698: X
699: X bend = (bidx = buf) + len;
700: X while (bidx < bend) {
701: X if (*bidx++) {
702: X return (write(fd, buf, len) == len ? 0 : -1);
703: X }
704: X }
705: X return (lseek(fd, (OFFSET) len, 1) < 0 ? -1 : len);
706: X}
707: X
708: X
709: X/* buf_pad - pad the archive buffer
710: X *
711: X * DESCRIPTION
712: X *
713: X * Buf_pad writes len zero bytes to the archive buffer in order to
714: X * pad it.
715: X *
716: X * PARAMETERS
717: X *
718: X * OFFSET pad - number of zero bytes to pad
719: X *
720: X */
721: X
722: X#ifdef __STDC__
723: X
724: Xstatic void buf_pad(OFFSET pad)
725: X
726: X#else
727: X
728: Xstatic void buf_pad(pad)
729: XOFFSET pad;
730: X
731: X#endif
732: X{
733: X int idx;
734: X int have;
735: X
736: X while (pad) {
737: X if ((have = bufend - bufidx) > pad) {
738: X have = pad;
739: X }
740: X for (idx = 0; idx < have; ++idx) {
741: X *bufidx++ = '\0';
742: X }
743: X total += have;
744: X pad -= have;
745: X if (bufend - bufidx == 0) {
746: X outflush();
747: X }
748: X }
749: X}
750: X
751: X
752: X/* buf_use - allocate buffer space
753: X *
754: X * DESCRIPTION
755: X *
756: X * Buf_use marks space in the buffer as being used; advancing both the
757: X * buffer index (bufidx) and the total byte count (total).
758: X *
759: X * PARAMETERS
760: X *
761: X * uint len - Amount of space to allocate in the buffer
762: X */
763: X
764: X#ifdef __STDC__
765: X
766: Xstatic void buf_use(uint len)
767: X
768: X#else
769: X
770: Xstatic void buf_use(len)
771: Xuint len;
772: X
773: X#endif
774: X{
775: X bufidx += len;
776: X total += len;
777: X}
778: X
779: X
780: X/* buf_in_avail - index available input data within the buffer
781: X *
782: X * DESCRIPTION
783: X *
784: X * Buf_in_avail fills the archive buffer, and points the bufp
785: X * parameter at the start of the data. The lenp parameter is
786: X * modified to contain the number of bytes which were read.
787: X *
788: X * PARAMETERS
789: X *
790: X * char **bufp - pointer to the buffer to read data into
791: X * uint *lenp - pointer to the number of bytes which were read
792: X * (returned to the caller)
793: X *
794: X * RETURNS
795: X *
796: X * Stores a pointer to the data and its length in given locations.
797: X * Returns zero with valid data, -1 if unreadable portions were
798: X * replaced with nulls.
799: X *
800: X * ERRORS
801: X *
802: X * If an error occurs in ar_read, the error code is returned to the
803: X * calling function.
804: X *
805: X */
806: X
807: X#ifdef __STDC__
808: X
809: Xstatic int buf_in_avail(char **bufp, uint *lenp)
810: X
811: X#else
812: X
813: Xstatic int buf_in_avail(bufp, lenp)
814: Xchar **bufp;
815: Xuint *lenp;
816: X
817: X#endif
818: X{
819: X uint have;
820: X int corrupt = 0;
821: X
822: X while ((have = bufend - bufidx) == 0) {
823: X corrupt |= ar_read();
824: X }
825: X *bufp = bufidx;
826: X *lenp = have;
827: X return (corrupt);
828: X}
829: X
830: X
831: X/* buf_out_avail - index buffer space for archive output
832: X *
833: X * DESCRIPTION
834: X *
835: X * Stores a buffer pointer at a given location. Returns the number
836: X * of bytes available.
837: X *
838: X * PARAMETERS
839: X *
840: X * char **bufp - pointer to the buffer which is to be stored
841: X *
842: X * RETURNS
843: X *
844: X * The number of bytes which are available in the buffer.
845: X *
846: X */
847: X
848: X#ifdef __STDC__
849: X
850: Xstatic uint buf_out_avail(char **bufp)
851: X
852: X#else
853: X
854: Xstatic uint buf_out_avail(bufp)
855: Xchar **bufp;
856: X
857: X#endif
858: X{
859: X int have;
860: X
861: X if (bufend - bufidx < 0) {
862: X fatal("Buffer overlow in buf_out_avail\n");
863: X }
864: X if ((have = bufend - bufidx) == 0) {
865: X outflush();
866: X }
867: X *bufp = bufidx;
868: X return (have);
869: X}
870: END_OF_buffer.c
871: if test 17360 -ne `wc -c <buffer.c`; then
872: echo shar: \"buffer.c\" unpacked with wrong size!
873: fi
874: # end of overwriting check
875: fi
876: if test -f paxdir.c -a "${1}" != "-c" ; then
877: echo shar: Will not over-write existing file \"paxdir.c\"
878: else
879: echo shar: Extracting \"paxdir.c\" \(16936 characters\)
880: sed "s/^X//" >paxdir.c <<'END_OF_paxdir.c'
881: X/*
882: X opendir -- open a directory stream
883: X
884: X last edit: 16-Jun-1987 D A Gwyn
885: X*/
886: X
887: X#include <sys/errno.h>
888: X#include <sys/types.h>
889: X#include <sys/stat.h>
890: X#include "paxdir.h"
891: X
892: X#ifdef BSD_SYSV
893: X/*
894: X <sys/_dir.h> -- definitions for 4.2,4.3BSD directories
895: X
896: X last edit: 25-Apr-1987 D A Gwyn
897: X
898: X A directory consists of some number of blocks of DIRBLKSIZ bytes each,
899: X where DIRBLKSIZ is chosen such that it can be transferred to disk in a
900: X single atomic operation (e.g., 512 bytes on most machines).
901: X
902: X Each DIRBLKSIZ-byte block contains some number of directory entry
903: X structures, which are of variable length. Each directory entry has the
904: X beginning of a (struct direct) at the front of it, containing its
905: X filesystem-unique ident number, the length of the entry, and the length
906: X of the name contained in the entry. These are followed by the NUL-
907: X terminated name padded to a (long) boundary with 0 bytes. The maximum
908: X length of a name in a directory is MAXNAMELEN.
909: X
910: X The macro DIRSIZ(dp) gives the amount of space required to represent a
911: X directory entry. Free space in a directory is represented by entries
912: X that have dp->d_reclen > DIRSIZ(dp). All DIRBLKSIZ bytes in a
913: X directory block are claimed by the directory entries; this usually
914: X results in the last entry in a directory having a large dp->d_reclen.
915: X When entries are deleted from a directory, the space is returned to the
916: X previous entry in the same directory block by increasing its
917: X dp->d_reclen. If the first entry of a directory block is free, then
918: X its dp->d_fileno is set to 0; entries other than the first in a
919: X directory do not normally have dp->d_fileno set to 0.
920: X
921: X prerequisite: <sys/types.h>
922: X*/
923: X
924: X#if defined(accel) || defined(sun) || defined(vax)
925: X#define DIRBLKSIZ 512 /* size of directory block */
926: X#else
927: X#ifdef alliant
928: X#define DIRBLKSIZ 4096 /* size of directory block */
929: X#else
930: X#ifdef gould
931: X#define DIRBLKSIZ 1024 /* size of directory block */
932: X#else
933: X#ifdef ns32000 /* Dynix System V */
934: X#define DIRBLKSIZ 2600 /* size of directory block */
935: X#else /* be conservative; multiple blocks are okay
936: X * but fractions are not */
937: X#define DIRBLKSIZ 4096 /* size of directory block */
938: X#endif
939: X#endif
940: X#endif
941: X#endif
942: X
943: X#define MAXNAMELEN 255 /* maximum filename length */
944: X/* NOTE: not MAXNAMLEN, which has been preempted by SVR3 <dirent.h> */
945: X
946: Xstruct direct { /* data from read()/_getdirentries() */
947: X unsigned long d_fileno; /* unique ident of entry */
948: X unsigned short d_reclen; /* length of this record */
949: X unsigned short d_namlen; /* length of string in d_name */
950: X char d_name[MAXNAMELEN + 1]; /* NUL-terminated filename */
951: X};
952: X
953: X/*
954: X The DIRSIZ macro gives the minimum record length which will hold the
955: X directory entry. This requires the amount of space in a (struct
956: X direct) without the d_name field, plus enough space for the name with a
957: X terminating NUL character, rounded up to a (long) boundary.
958: X
959: X (Note that Berkeley didn't properly compensate for struct padding,
960: X but we nevertheless have to use the same size as the actual system.)
961: X*/
962: X
963: X#define DIRSIZ( dp ) ((sizeof(struct direct) - (MAXNAMELEN+1) \
964: X + sizeof(long) + (dp)->d_namlen) \
965: X / sizeof(long) * sizeof(long))
966: X
967: X#else
968: X#include <sys/dir.h>
969: X#ifdef SYSV3
970: X#undef MAXNAMLEN /* avoid conflict with SVR3 */
971: X#endif
972: X /* Good thing we don't need to use the DIRSIZ() macro! */
973: X#ifdef d_ino /* 4.3BSD/NFS using d_fileno */
974: X#undef d_ino /* (not absolutely necessary) */
975: X#else
976: X#define d_fileno d_ino /* (struct direct) member */
977: X#endif
978: X#endif
979: X#ifdef UNK
980: X#ifndef UFS
981: X#include "***** ERROR ***** UNK applies only to UFS"
982: X/* One could do something similar for getdirentries(), but I didn't bother. */
983: X#endif
984: X#include <signal.h>
985: X#endif
986: X
987: X#if defined(UFS) + defined(BFS) + defined(NFS) != 1 /* sanity check */
988: X#include "***** ERROR ***** exactly one of UFS, BFS, or NFS must be defined"
989: X#endif
990: X
991: X#ifdef UFS
992: X#define RecLen( dp ) (sizeof(struct direct)) /* fixed-length entries */
993: X#else /* BFS || NFS */
994: X#define RecLen( dp ) ((dp)->d_reclen) /* variable-length entries */
995: X#endif
996: X
997: X#ifdef NFS
998: X#ifdef BSD_SYSV
999: X#define getdirentries _getdirentries /* package hides this system call */
1000: X#endif
1001: Xextern int getdirentries();
1002: Xstatic long dummy; /* getdirentries() needs basep */
1003: X#define GetBlock( fd, buf, n ) getdirentries( fd, buf, (unsigned)n, &dummy )
1004: X#else /* UFS || BFS */
1005: X#ifdef BSD_SYSV
1006: X#define read _read /* avoid emulation overhead */
1007: X#endif
1008: Xextern int read();
1009: X#define GetBlock( fd, buf, n ) read( fd, buf, (unsigned)n )
1010: X#endif
1011: X
1012: X#ifdef UNK
1013: Xextern int _getdents(); /* actual system call */
1014: X#endif
1015: X
1016: Xextern char *strncpy();
1017: Xextern int fstat();
1018: Xextern OFFSET lseek();
1019: X
1020: Xextern int errno;
1021: X
1022: X#ifndef DIRBLKSIZ
1023: X#define DIRBLKSIZ 4096 /* directory file read buffer size */
1024: X#endif
1025: X
1026: X#ifndef NULL
1027: X#define NULL 0
1028: X#endif
1029: X
1030: X#ifndef SEEK_CUR
1031: X#define SEEK_CUR 1
1032: X#endif
1033: X
1034: X#ifndef S_ISDIR /* macro to test for directory file */
1035: X#define S_ISDIR( mode ) (((mode) & S_IFMT) == S_IFDIR)
1036: X#endif
1037: X
1038: X
1039: X#ifndef SEEK_CUR
1040: X#define SEEK_CUR 1
1041: X#endif
1042: X
1043: X#ifdef BSD_SYSV
1044: X#define open _open /* avoid emulation overhead */
1045: X#endif
1046: X
1047: Xextern int getdents(); /* SVR3 system call, or emulation */
1048: X
1049: Xtypedef char *pointer; /* (void *) if you have it */
1050: X
1051: Xextern void free();
1052: Xextern pointer malloc();
1053: Xextern int
1054: Xopen(), close(), fstat();
1055: X
1056: Xextern int errno;
1057: Xextern OFFSET lseek();
1058: X
1059: X#ifndef SEEK_SET
1060: X#define SEEK_SET 0
1061: X#endif
1062: X
1063: Xtypedef int bool; /* Boolean data type */
1064: X#define false 0
1065: X#define true 1
1066: X
1067: X
1068: X#ifndef NULL
1069: X#define NULL 0
1070: X#endif
1071: X
1072: X#ifndef O_RDONLY
1073: X#define O_RDONLY 0
1074: X#endif
1075: X
1076: X#ifndef S_ISDIR /* macro to test for directory file */
1077: X#define S_ISDIR( mode ) (((mode) & S_IFMT) == S_IFDIR)
1078: X#endif
1079: X
1080: X#ifdef __STDC__
1081: X
1082: XDIR *opendir(char *dirname)
1083: X
1084: X#else
1085: X
1086: XDIR *opendir(dirname)
1087: Xchar *dirname; /* name of directory */
1088: X
1089: X#endif
1090: X{
1091: X register DIR *dirp; /* -> malloc'ed storage */
1092: X register int fd; /* file descriptor for read */
1093: X struct stat sbuf; /* result of fstat() */
1094: X
1095: X if ((fd = open(dirname, O_RDONLY)) < 0)
1096: X return NULL; /* errno set by open() */
1097: X
1098: X if (fstat(fd, &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) {
1099: X close(fd);
1100: X errno = ENOTDIR;
1101: X return NULL; /* not a directory */
1102: X }
1103: X if ((dirp = (DIR *) malloc(sizeof(DIR))) == NULL
1104: X || (dirp->dd_buf = (char *) malloc((unsigned) DIRBUF)) == NULL
1105: X ) {
1106: X register int serrno = errno;
1107: X /* errno set to ENOMEM by sbrk() */
1108: X
1109: X if (dirp != NULL)
1110: X free((pointer) dirp);
1111: X
1112: X close(fd);
1113: X errno = serrno;
1114: X return NULL; /* not enough memory */
1115: X }
1116: X dirp->dd_fd = fd;
1117: X dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
1118: X
1119: X return dirp;
1120: X}
1121: X
1122: X
1123: X/*
1124: X * closedir -- close a directory stream
1125: X *
1126: X * last edit: 11-Nov-1988 D A Gwyn
1127: X */
1128: X
1129: X#ifdef __STDC__
1130: X
1131: Xint closedir(register DIR *dirp)
1132: X
1133: X#else
1134: X
1135: Xint closedir(dirp)
1136: Xregister DIR *dirp; /* stream from opendir() */
1137: X
1138: X#endif
1139: X{
1140: X register int fd;
1141: X
1142: X if ( dirp == NULL || dirp->dd_buf == NULL ) {
1143: X errno = EFAULT;
1144: X return -1; /* invalid pointer */
1145: X }
1146: X
1147: X fd = dirp->dd_fd; /* bug fix thanks to R. Salz */
1148: X free( (pointer)dirp->dd_buf );
1149: X free( (pointer)dirp );
1150: X return close( fd );
1151: X}
1152: X
1153: X
1154: X/*
1155: X readdir -- read next entry from a directory stream
1156: X
1157: X last edit: 25-Apr-1987 D A Gwyn
1158: X*/
1159: X
1160: X#ifdef __STDC__
1161: X
1162: Xstruct dirent *readdir(register DIR *dirp)
1163: X
1164: X#else
1165: X
1166: Xstruct dirent *readdir(dirp)
1167: Xregister DIR *dirp; /* stream from opendir() */
1168: X
1169: X#endif
1170: X{
1171: X register struct dirent *dp; /* -> directory data */
1172: X
1173: X if (dirp == NULL || dirp->dd_buf == NULL) {
1174: X errno = EFAULT;
1175: X return NULL; /* invalid pointer */
1176: X }
1177: X do {
1178: X if (dirp->dd_loc >= dirp->dd_size) /* empty or obsolete */
1179: X dirp->dd_loc = dirp->dd_size = 0;
1180: X
1181: X if (dirp->dd_size == 0 /* need to refill buffer */
1182: X && (dirp->dd_size =
1183: X getdents(dirp->dd_fd, dirp->dd_buf, (unsigned) DIRBUF)
1184: X ) <= 0
1185: X )
1186: X return NULL; /* EOF or error */
1187: X
1188: X dp = (struct dirent *) & dirp->dd_buf[dirp->dd_loc];
1189: X dirp->dd_loc += dp->d_reclen;
1190: X }
1191: X while (dp->d_ino == 0L); /* don't rely on getdents() */
1192: X
1193: X return dp;
1194: X}
1195: X
1196: X
1197: X/*
1198: X seekdir -- reposition a directory stream
1199: X
1200: X last edit: 24-May-1987 D A Gwyn
1201: X
1202: X An unsuccessful seekdir() will in general alter the current
1203: X directory position; beware.
1204: X
1205: X NOTE: 4.nBSD directory compaction makes seekdir() & telldir()
1206: X practically impossible to do right. Avoid using them!
1207: X*/
1208: X
1209: X#ifdef __STDC__
1210: X
1211: Xvoid seekdir(register DIR *dirp, register OFFSET loc)
1212: X
1213: X#else
1214: X
1215: Xvoid seekdir(dirp, loc)
1216: Xregister DIR *dirp; /* stream from opendir() */
1217: Xregister OFFSET loc; /* position from telldir() */
1218: X
1219: X#endif
1220: X{
1221: X register bool rewind; /* "start over when stymied" flag */
1222: X
1223: X if (dirp == NULL || dirp->dd_buf == NULL) {
1224: X errno = EFAULT;
1225: X return; /* invalid pointer */
1226: X }
1227: X /*
1228: X * A (struct dirent)'s d_off is an invented quantity on 4.nBSD
1229: X * NFS-supporting systems, so it is not safe to lseek() to it.
1230: X */
1231: X
1232: X /* Monotonicity of d_off is heavily exploited in the following. */
1233: X
1234: X /*
1235: X * This algorithm is tuned for modest directory sizes. For huge
1236: X * directories, it might be more efficient to read blocks until the first
1237: X * d_off is too large, then back up one block, or even to use binary
1238: X * search on the directory blocks. I doubt that the extra code for that
1239: X * would be worthwhile.
1240: X */
1241: X
1242: X if (dirp->dd_loc >= dirp->dd_size /* invalid index */
1243: X || ((struct dirent *) & dirp->dd_buf[dirp->dd_loc])->d_off > loc
1244: X /* too far along in buffer */
1245: X )
1246: X dirp->dd_loc = 0; /* reset to beginning of buffer */
1247: X /* else save time by starting at current dirp->dd_loc */
1248: X
1249: X for (rewind = true;;) {
1250: X register struct dirent *dp;
1251: X
1252: X /* See whether the matching entry is in the current buffer. */
1253: X
1254: X if ((dirp->dd_loc < dirp->dd_size /* valid index */
1255: X || readdir(dirp) != NULL /* next buffer read */
1256: X && (dirp->dd_loc = 0, true) /* beginning of buffer set */
1257: X )
1258: X && (dp = (struct dirent *) & dirp->dd_buf[dirp->dd_loc])->d_off
1259: X <= loc /* match possible in this buffer */
1260: X ) {
1261: X for ( /* dp initialized above */ ;
1262: X (char *) dp < &dirp->dd_buf[dirp->dd_size];
1263: X dp = (struct dirent *) ((char *) dp + dp->d_reclen)
1264: X )
1265: X if (dp->d_off == loc) { /* found it! */
1266: X dirp->dd_loc =
1267: X (char *) dp - dirp->dd_buf;
1268: X return;
1269: X }
1270: X rewind = false; /* no point in backing up later */
1271: X dirp->dd_loc = dirp->dd_size; /* set end of buffer */
1272: X } else
1273: X /* whole buffer past matching entry */ if (!rewind) { /* no point in searching
1274: X * further */
1275: X errno = EINVAL;
1276: X return; /* no entry at specified loc */
1277: X } else { /* rewind directory and start over */
1278: X rewind = false; /* but only once! */
1279: X
1280: X dirp->dd_loc = dirp->dd_size = 0;
1281: X
1282: X if (lseek(dirp->dd_fd, (OFFSET) 0, SEEK_SET)
1283: X != 0
1284: X )
1285: X return; /* errno already set (EBADF) */
1286: X
1287: X if (loc == 0)
1288: X return; /* save time */
1289: X }
1290: X }
1291: X}
1292: X
1293: X
1294: X/* telldir - report directory stream position
1295: X *
1296: X * DESCRIPTION
1297: X *
1298: X * Returns the offset of the next directory entry in the
1299: X * directory associated with dirp.
1300: X *
1301: X * NOTE: 4.nBSD directory compaction makes seekdir() & telldir()
1302: X * practically impossible to do right. Avoid using them!
1303: X *
1304: X * PARAMETERS
1305: X *
1306: X * DIR *dirp - stream from opendir()
1307: X *
1308: X * RETURNS
1309: X *
1310: X * Return offset of next entry
1311: X */
1312: X
1313: X
1314: X#ifdef __STDC__
1315: X
1316: XOFFSET telldir(DIR *dirp)
1317: X
1318: X#else
1319: X
1320: XOFFSET telldir(dirp)
1321: XDIR *dirp; /* stream from opendir() */
1322: X
1323: X#endif
1324: X{
1325: X if (dirp == NULL || dirp->dd_buf == NULL) {
1326: X errno = EFAULT;
1327: X return -1; /* invalid pointer */
1328: X }
1329: X if (dirp->dd_loc < dirp->dd_size) /* valid index */
1330: X return ((struct dirent *) & dirp->dd_buf[dirp->dd_loc])->d_off;
1331: X else /* beginning of next directory block */
1332: X return lseek(dirp->dd_fd, (OFFSET) 0, SEEK_CUR);
1333: X}
1334: X
1335: X
1336: X#ifdef UFS
1337: X
1338: X/*
1339: X The following routine is necessary to handle DIRSIZ-long entry names.
1340: X Thanks to Richard Todd for pointing this out.
1341: X*/
1342: X
1343: X
1344: X/* return # chars in embedded name */
1345: X
1346: X#ifdef __STDC__
1347: X
1348: Xstatic int NameLen(char *name)
1349: X
1350: X#else
1351: X
1352: Xstatic int NameLen(name)
1353: Xchar *name; /* -> name embedded in struct direct */
1354: X
1355: X#endif
1356: X{
1357: X register char *s; /* -> name[.] */
1358: X register char *stop = &name[DIRSIZ]; /* -> past end of name field */
1359: X
1360: X for (s = &name[1]; /* (empty names are impossible) */
1361: X *s != '\0' /* not NUL terminator */
1362: X && ++s < stop; /* < DIRSIZ characters scanned */
1363: X );
1364: X
1365: X return s - name; /* # valid characters in name */
1366: X}
1367: X
1368: X#else /* BFS || NFS */
1369: X
1370: Xextern int strlen();
1371: X
1372: X#define NameLen( name ) strlen( name ) /* names are always NUL-terminated */
1373: X
1374: X#endif
1375: X
1376: X#ifdef UNK
1377: Xstatic enum {
1378: X maybe, no, yes
1379: X} state = maybe;
1380: X
1381: X
1382: X/* sig_catch - used to catch signals
1383: X *
1384: X * DESCRIPTION
1385: X *
1386: X * Used to catch signals.
1387: X */
1388: X
1389: X/*ARGSUSED*/
1390: X
1391: X#ifdef __STDC__
1392: X
1393: Xstatic void sig_catch(int sig)
1394: X
1395: X#else
1396: X
1397: Xstatic void sig_catch(sig)
1398: Xint sig; /* must be SIGSYS */
1399: X
1400: X#endif
1401: X{
1402: X state = no; /* attempted _getdents() faulted */
1403: X}
1404: X#endif
1405: X
1406: X
1407: X/* getdents - get directory entries
1408: X *
1409: X * DESCRIPTION
1410: X *
1411: X * Gets directory entries from the filesystem in an implemenation
1412: X * defined way.
1413: X *
1414: X * PARAMETERS
1415: X *
1416: X * int fildes - directory file descriptor
1417: X * char *buf - where to put the (struct dirent)s
1418: X * unsigned nbyte - size of buf[]
1419: X *
1420: X * RETURNS
1421: X *
1422: X * Returns number of bytes read; 0 on EOF, -1 on error
1423: X */
1424: X
1425: X#ifdef __STDC__
1426: X
1427: Xint getdents(int fildes, char *buf, unsigned nbyte)
1428: X
1429: X#else
1430: X
1431: Xint getdents(fildes, buf, nbyte)
1432: Xint fildes; /* directory file descriptor */
1433: Xchar *buf; /* where to put the (struct dirent)s */
1434: Xunsigned nbyte; /* size of buf[] */
1435: X
1436: X#endif
1437: X{
1438: X int serrno; /* entry errno */
1439: X OFFSET offset; /* initial directory file offset */
1440: X struct stat statb; /* fstat() info */
1441: X union {
1442: X /* directory file block buffer */
1443: X#ifdef UFS
1444: X char dblk[DIRBLKSIZ + 1];
1445: X#else
1446: X char dblk[DIRBLKSIZ];
1447: X#endif
1448: X struct direct dummy; /* just for alignment */
1449: X } u; /* (avoids having to malloc()) */
1450: X register struct direct *dp; /* -> u.dblk[.] */
1451: X register struct dirent *bp; /* -> buf[.] */
1452: X
1453: X#ifdef UNK
1454: X switch (state) {
1455: X SIG_T (*shdlr)(); /* entry SIGSYS handler */
1456: X register int retval; /* return from _getdents() if any */
1457: X
1458: X case yes: /* _getdents() is known to work */
1459: X return _getdents(fildes, buf, nbyte);
1460: X
1461: X case maybe: /* first time only */
1462: X shdlr = signal(SIGSYS, sig_catch);
1463: X retval = _getdents(fildes, buf, nbyte); /* try it */
1464: X signal(SIGSYS, shdlr);
1465: X
1466: X if (state == maybe) { /* SIGSYS did not occur */
1467: X state = yes; /* so _getdents() must have worked */
1468: X return retval;
1469: X }
1470: X /* else fall through into emulation */
1471: X
1472: X/* case no: /* fall through into emulation */
1473: X }
1474: X#endif
1475: X
1476: X if (buf == NULL
1477: X#ifdef ATT_SPEC
1478: X || (unsigned long) buf % sizeof(long) != 0 /* ugh */
1479: X#endif
1480: X ) {
1481: X errno = EFAULT; /* invalid pointer */
1482: X return -1;
1483: X }
1484: X if (fstat(fildes, &statb) != 0) {
1485: X return -1; /* errno set by fstat() */
1486: X }
1487: X
1488: X if (!S_ISDIR(statb.st_mode)) {
1489: X errno = ENOTDIR; /* not a directory */
1490: X return -1;
1491: X }
1492: X if ((offset = lseek(fildes, (OFFSET) 0, SEEK_CUR)) < 0) {
1493: X return -1; /* errno set by lseek() */
1494: X }
1495: X
1496: X#ifdef BFS /* no telling what remote hosts do */
1497: X if ((unsigned long) offset % DIRBLKSIZ != 0) {
1498: X errno = ENOENT; /* file pointer probably misaligned */
1499: X return -1;
1500: X }
1501: X#endif
1502: X
1503: X serrno = errno; /* save entry errno */
1504: X
1505: X for (bp = (struct dirent *) buf; bp == (struct dirent *) buf;) {
1506: X
1507: X /* convert next directory block */
1508: X int size;
1509: X
1510: X do {
1511: X size = GetBlock(fildes, u.dblk, DIRBLKSIZ);
1512: X } while (size == -1 && errno == EINTR);
1513: X
1514: X if (size <= 0) {
1515: X return size; /* EOF or error (EBADF) */
1516: X }
1517: X
1518: X for (dp = (struct direct *) u.dblk;
1519: X (char *) dp < &u.dblk[size];
1520: X dp = (struct direct *) ((char *) dp + RecLen(dp))
1521: X ) {
1522: X#ifndef UFS
1523: X if (dp->d_reclen <= 0) {
1524: X errno = EIO; /* corrupted directory */
1525: X return -1;
1526: X }
1527: X#endif
1528: X
1529: X if (dp->d_fileno != 0) { /* non-empty; copy to user buffer */
1530: X register int reclen =
1531: X DIRENTSIZ(NameLen(dp->d_name));
1532: X
1533: X if ((char *) bp + reclen > &buf[nbyte]) {
1534: X errno = EINVAL;
1535: X return -1; /* buf too small */
1536: X }
1537: X bp->d_ino = dp->d_fileno;
1538: X bp->d_off = offset + ((char *) dp - u.dblk);
1539: X bp->d_reclen = reclen;
1540: X
1541: X {
1542: X#ifdef UFS
1543: X /* Is the following kludge ugly? You bet. */
1544: X
1545: X register char save = dp->d_name[DIRSIZ];
1546: X /* save original data */
1547: X
1548: X dp->d_name[DIRSIZ] = '\0';
1549: X /* ensure NUL termination */
1550: X#endif
1551: X /* adds NUL padding */
1552: X strncpy(bp->d_name, dp->d_name, reclen - DIRENTBASESIZ);
1553: X#ifdef UFS
1554: X dp->d_name[DIRSIZ] = save;
1555: X /* restore original data */
1556: X#endif
1557: X }
1558: X
1559: X bp = (struct dirent *) ((char *) bp + reclen);
1560: X }
1561: X }
1562: X
1563: X#ifndef BFS /* 4.2BSD screwed up; fixed in 4.3BSD */
1564: X if ((char *) dp > &u.dblk[size]) {
1565: X errno = EIO; /* corrupted directory */
1566: X return -1;
1567: X }
1568: X#endif
1569: X }
1570: X
1571: X errno = serrno; /* restore entry errno */
1572: X return (char *) bp - buf; /* return # bytes read */
1573: X}
1574: END_OF_paxdir.c
1575: if test 16936 -ne `wc -c <paxdir.c`; then
1576: echo shar: \"paxdir.c\" unpacked with wrong size!
1577: fi
1578: # end of overwriting check
1579: fi
1580: echo shar: End of archive 5 \(of 6\).
1581: cp /dev/null ark5isdone
1582: MISSING=""
1583: for I in 1 2 3 4 5 6 ; do
1584: if test ! -f ark${I}isdone ; then
1585: MISSING="${MISSING} ${I}"
1586: fi
1587: done
1588: if test "${MISSING}" = "" ; then
1589: echo You have unpacked all 6 archives.
1590: rm -f ark[1-9]isdone
1591: else
1592: echo You still need to unpack the following archives:
1593: echo " " ${MISSING}
1594: fi
1595: ## End of shell archive.
1596: exit 0
1597:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.