|
|
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.