|
|
1.1 ! root 1: /* ! 2: opendir -- open a directory stream ! 3: ! 4: last edit: 16-Jun-1987 D A Gwyn ! 5: */ ! 6: ! 7: #include <sys/errno.h> ! 8: #include <sys/types.h> ! 9: #include <sys/stat.h> ! 10: #include "paxdir.h" ! 11: ! 12: #ifdef BSD_SYSV ! 13: /* ! 14: <sys/_dir.h> -- definitions for 4.2,4.3BSD directories ! 15: ! 16: last edit: 25-Apr-1987 D A Gwyn ! 17: ! 18: A directory consists of some number of blocks of DIRBLKSIZ bytes each, ! 19: where DIRBLKSIZ is chosen such that it can be transferred to disk in a ! 20: single atomic operation (e.g., 512 bytes on most machines). ! 21: ! 22: Each DIRBLKSIZ-byte block contains some number of directory entry ! 23: structures, which are of variable length. Each directory entry has the ! 24: beginning of a (struct direct) at the front of it, containing its ! 25: filesystem-unique ident number, the length of the entry, and the length ! 26: of the name contained in the entry. These are followed by the NUL- ! 27: terminated name padded to a (long) boundary with 0 bytes. The maximum ! 28: length of a name in a directory is MAXNAMELEN. ! 29: ! 30: The macro DIRSIZ(dp) gives the amount of space required to represent a ! 31: directory entry. Free space in a directory is represented by entries ! 32: that have dp->d_reclen > DIRSIZ(dp). All DIRBLKSIZ bytes in a ! 33: directory block are claimed by the directory entries; this usually ! 34: results in the last entry in a directory having a large dp->d_reclen. ! 35: When entries are deleted from a directory, the space is returned to the ! 36: previous entry in the same directory block by increasing its ! 37: dp->d_reclen. If the first entry of a directory block is free, then ! 38: its dp->d_fileno is set to 0; entries other than the first in a ! 39: directory do not normally have dp->d_fileno set to 0. ! 40: ! 41: prerequisite: <sys/types.h> ! 42: */ ! 43: ! 44: #if defined(accel) || defined(sun) || defined(vax) ! 45: #define DIRBLKSIZ 512 /* size of directory block */ ! 46: #else ! 47: #ifdef alliant ! 48: #define DIRBLKSIZ 4096 /* size of directory block */ ! 49: #else ! 50: #ifdef gould ! 51: #define DIRBLKSIZ 1024 /* size of directory block */ ! 52: #else ! 53: #ifdef ns32000 /* Dynix System V */ ! 54: #define DIRBLKSIZ 2600 /* size of directory block */ ! 55: #else /* be conservative; multiple blocks are okay ! 56: * but fractions are not */ ! 57: #define DIRBLKSIZ 4096 /* size of directory block */ ! 58: #endif ! 59: #endif ! 60: #endif ! 61: #endif ! 62: ! 63: #define MAXNAMELEN 255 /* maximum filename length */ ! 64: /* NOTE: not MAXNAMLEN, which has been preempted by SVR3 <dirent.h> */ ! 65: ! 66: struct direct { /* data from read()/_getdirentries() */ ! 67: unsigned long d_fileno; /* unique ident of entry */ ! 68: unsigned short d_reclen; /* length of this record */ ! 69: unsigned short d_namlen; /* length of string in d_name */ ! 70: char d_name[MAXNAMELEN + 1]; /* NUL-terminated filename */ ! 71: }; ! 72: ! 73: /* ! 74: The DIRSIZ macro gives the minimum record length which will hold the ! 75: directory entry. This requires the amount of space in a (struct ! 76: direct) without the d_name field, plus enough space for the name with a ! 77: terminating NUL character, rounded up to a (long) boundary. ! 78: ! 79: (Note that Berkeley didn't properly compensate for struct padding, ! 80: but we nevertheless have to use the same size as the actual system.) ! 81: */ ! 82: ! 83: #define DIRSIZ( dp ) ((sizeof(struct direct) - (MAXNAMELEN+1) \ ! 84: + sizeof(long) + (dp)->d_namlen) \ ! 85: / sizeof(long) * sizeof(long)) ! 86: ! 87: #else ! 88: #include <sys/dir.h> ! 89: #ifdef SYSV3 ! 90: #undef MAXNAMLEN /* avoid conflict with SVR3 */ ! 91: #endif ! 92: /* Good thing we don't need to use the DIRSIZ() macro! */ ! 93: #ifdef d_ino /* 4.3BSD/NFS using d_fileno */ ! 94: #undef d_ino /* (not absolutely necessary) */ ! 95: #else ! 96: #define d_fileno d_ino /* (struct direct) member */ ! 97: #endif ! 98: #endif ! 99: #ifdef UNK ! 100: #ifndef UFS ! 101: #include "***** ERROR ***** UNK applies only to UFS" ! 102: /* One could do something similar for getdirentries(), but I didn't bother. */ ! 103: #endif ! 104: #include <signal.h> ! 105: #endif ! 106: ! 107: #if defined(UFS) + defined(BFS) + defined(NFS) != 1 /* sanity check */ ! 108: #include "***** ERROR ***** exactly one of UFS, BFS, or NFS must be defined" ! 109: #endif ! 110: ! 111: #ifdef UFS ! 112: #define RecLen( dp ) (sizeof(struct direct)) /* fixed-length entries */ ! 113: #else /* BFS || NFS */ ! 114: #define RecLen( dp ) ((dp)->d_reclen) /* variable-length entries */ ! 115: #endif ! 116: ! 117: #ifdef NFS ! 118: #ifdef BSD_SYSV ! 119: #define getdirentries _getdirentries /* package hides this system call */ ! 120: #endif ! 121: extern int getdirentries(); ! 122: static long dummy; /* getdirentries() needs basep */ ! 123: #define GetBlock( fd, buf, n ) getdirentries( fd, buf, (unsigned)n, &dummy ) ! 124: #else /* UFS || BFS */ ! 125: #ifdef BSD_SYSV ! 126: #define read _read /* avoid emulation overhead */ ! 127: #endif ! 128: extern int read(); ! 129: #define GetBlock( fd, buf, n ) read( fd, buf, (unsigned)n ) ! 130: #endif ! 131: ! 132: #ifdef UNK ! 133: extern int _getdents(); /* actual system call */ ! 134: #endif ! 135: ! 136: extern char *strncpy(); ! 137: extern int fstat(); ! 138: extern OFFSET lseek(); ! 139: ! 140: extern int errno; ! 141: ! 142: #ifndef DIRBLKSIZ ! 143: #define DIRBLKSIZ 4096 /* directory file read buffer size */ ! 144: #endif ! 145: ! 146: #ifndef NULL ! 147: #define NULL 0 ! 148: #endif ! 149: ! 150: #ifndef SEEK_CUR ! 151: #define SEEK_CUR 1 ! 152: #endif ! 153: ! 154: #ifndef S_ISDIR /* macro to test for directory file */ ! 155: #define S_ISDIR( mode ) (((mode) & S_IFMT) == S_IFDIR) ! 156: #endif ! 157: ! 158: ! 159: #ifndef SEEK_CUR ! 160: #define SEEK_CUR 1 ! 161: #endif ! 162: ! 163: #ifdef BSD_SYSV ! 164: #define open _open /* avoid emulation overhead */ ! 165: #endif ! 166: ! 167: extern int getdents(); /* SVR3 system call, or emulation */ ! 168: ! 169: typedef char *pointer; /* (void *) if you have it */ ! 170: ! 171: extern void free(); ! 172: extern pointer malloc(); ! 173: extern int ! 174: open(), close(), fstat(); ! 175: ! 176: extern int errno; ! 177: extern OFFSET lseek(); ! 178: ! 179: #ifndef SEEK_SET ! 180: #define SEEK_SET 0 ! 181: #endif ! 182: ! 183: typedef int bool; /* Boolean data type */ ! 184: #define false 0 ! 185: #define true 1 ! 186: ! 187: ! 188: #ifndef NULL ! 189: #define NULL 0 ! 190: #endif ! 191: ! 192: #ifndef O_RDONLY ! 193: #define O_RDONLY 0 ! 194: #endif ! 195: ! 196: #ifndef S_ISDIR /* macro to test for directory file */ ! 197: #define S_ISDIR( mode ) (((mode) & S_IFMT) == S_IFDIR) ! 198: #endif ! 199: ! 200: #if __STDC__ ! 201: ! 202: DIR *opendir(char *dirname) ! 203: ! 204: #else ! 205: ! 206: DIR *opendir(dirname) ! 207: char *dirname; /* name of directory */ ! 208: ! 209: #endif ! 210: { ! 211: register DIR *dirp; /* -> malloc'ed storage */ ! 212: register int fd; /* file descriptor for read */ ! 213: struct stat sbuf; /* result of fstat() */ ! 214: ! 215: if ((fd = open(dirname, O_RDONLY)) < 0) ! 216: return NULL; /* errno set by open() */ ! 217: ! 218: if (fstat(fd, &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) { ! 219: close(fd); ! 220: errno = ENOTDIR; ! 221: return NULL; /* not a directory */ ! 222: } ! 223: if ((dirp = (DIR *) malloc(sizeof(DIR))) == NULL ! 224: || (dirp->dd_buf = (char *) malloc((unsigned) DIRBUF)) == NULL ! 225: ) { ! 226: register int serrno = errno; ! 227: /* errno set to ENOMEM by sbrk() */ ! 228: ! 229: if (dirp != NULL) ! 230: free((pointer) dirp); ! 231: ! 232: close(fd); ! 233: errno = serrno; ! 234: return NULL; /* not enough memory */ ! 235: } ! 236: dirp->dd_fd = fd; ! 237: dirp->dd_loc = dirp->dd_size = 0; /* refill needed */ ! 238: ! 239: return dirp; ! 240: } ! 241: ! 242: ! 243: /* ! 244: * closedir -- close a directory stream ! 245: * ! 246: * last edit: 11-Nov-1988 D A Gwyn ! 247: */ ! 248: ! 249: #if __STDC__ ! 250: ! 251: int closedir(register DIR *dirp) ! 252: ! 253: #else ! 254: ! 255: int closedir(dirp) ! 256: register DIR *dirp; /* stream from opendir() */ ! 257: ! 258: #endif ! 259: { ! 260: register int fd; ! 261: ! 262: if ( dirp == NULL || dirp->dd_buf == NULL ) { ! 263: errno = EFAULT; ! 264: return -1; /* invalid pointer */ ! 265: } ! 266: ! 267: fd = dirp->dd_fd; /* bug fix thanks to R. Salz */ ! 268: free( (pointer)dirp->dd_buf ); ! 269: free( (pointer)dirp ); ! 270: return close( fd ); ! 271: } ! 272: ! 273: ! 274: /* ! 275: readdir -- read next entry from a directory stream ! 276: ! 277: last edit: 25-Apr-1987 D A Gwyn ! 278: */ ! 279: ! 280: #if __STDC__ ! 281: ! 282: struct dirent *readdir(register DIR *dirp) ! 283: ! 284: #else ! 285: ! 286: struct dirent *readdir(dirp) ! 287: register DIR *dirp; /* stream from opendir() */ ! 288: ! 289: #endif ! 290: { ! 291: register struct dirent *dp; /* -> directory data */ ! 292: ! 293: if (dirp == NULL || dirp->dd_buf == NULL) { ! 294: errno = EFAULT; ! 295: return NULL; /* invalid pointer */ ! 296: } ! 297: do { ! 298: if (dirp->dd_loc >= dirp->dd_size) /* empty or obsolete */ ! 299: dirp->dd_loc = dirp->dd_size = 0; ! 300: ! 301: if (dirp->dd_size == 0 /* need to refill buffer */ ! 302: && (dirp->dd_size = ! 303: getdents(dirp->dd_fd, dirp->dd_buf, (unsigned) DIRBUF) ! 304: ) <= 0 ! 305: ) ! 306: return NULL; /* EOF or error */ ! 307: ! 308: dp = (struct dirent *) & dirp->dd_buf[dirp->dd_loc]; ! 309: dirp->dd_loc += dp->d_reclen; ! 310: } ! 311: while (dp->d_ino == 0L); /* don't rely on getdents() */ ! 312: ! 313: return dp; ! 314: } ! 315: ! 316: ! 317: /* ! 318: seekdir -- reposition a directory stream ! 319: ! 320: last edit: 24-May-1987 D A Gwyn ! 321: ! 322: An unsuccessful seekdir() will in general alter the current ! 323: directory position; beware. ! 324: ! 325: NOTE: 4.nBSD directory compaction makes seekdir() & telldir() ! 326: practically impossible to do right. Avoid using them! ! 327: */ ! 328: ! 329: #if __STDC__ ! 330: ! 331: void seekdir(register DIR *dirp, register OFFSET loc) ! 332: ! 333: #else ! 334: ! 335: void seekdir(dirp, loc) ! 336: register DIR *dirp; /* stream from opendir() */ ! 337: register OFFSET loc; /* position from telldir() */ ! 338: ! 339: #endif ! 340: { ! 341: register bool rewind; /* "start over when stymied" flag */ ! 342: ! 343: if (dirp == NULL || dirp->dd_buf == NULL) { ! 344: errno = EFAULT; ! 345: return; /* invalid pointer */ ! 346: } ! 347: /* ! 348: * A (struct dirent)'s d_off is an invented quantity on 4.nBSD ! 349: * NFS-supporting systems, so it is not safe to lseek() to it. ! 350: */ ! 351: ! 352: /* Monotonicity of d_off is heavily exploited in the following. */ ! 353: ! 354: /* ! 355: * This algorithm is tuned for modest directory sizes. For huge ! 356: * directories, it might be more efficient to read blocks until the first ! 357: * d_off is too large, then back up one block, or even to use binary ! 358: * search on the directory blocks. I doubt that the extra code for that ! 359: * would be worthwhile. ! 360: */ ! 361: ! 362: if (dirp->dd_loc >= dirp->dd_size /* invalid index */ ! 363: || ((struct dirent *) & dirp->dd_buf[dirp->dd_loc])->d_off > loc ! 364: /* too far along in buffer */ ! 365: ) ! 366: dirp->dd_loc = 0; /* reset to beginning of buffer */ ! 367: /* else save time by starting at current dirp->dd_loc */ ! 368: ! 369: for (rewind = true;;) { ! 370: register struct dirent *dp; ! 371: ! 372: /* See whether the matching entry is in the current buffer. */ ! 373: ! 374: if ((dirp->dd_loc < dirp->dd_size /* valid index */ ! 375: || readdir(dirp) != NULL /* next buffer read */ ! 376: && (dirp->dd_loc = 0, true) /* beginning of buffer set */ ! 377: ) ! 378: && (dp = (struct dirent *) & dirp->dd_buf[dirp->dd_loc])->d_off ! 379: <= loc /* match possible in this buffer */ ! 380: ) { ! 381: for ( /* dp initialized above */ ; ! 382: (char *) dp < &dirp->dd_buf[dirp->dd_size]; ! 383: dp = (struct dirent *) ((char *) dp + dp->d_reclen) ! 384: ) ! 385: if (dp->d_off == loc) { /* found it! */ ! 386: dirp->dd_loc = ! 387: (char *) dp - dirp->dd_buf; ! 388: return; ! 389: } ! 390: rewind = false; /* no point in backing up later */ ! 391: dirp->dd_loc = dirp->dd_size; /* set end of buffer */ ! 392: } else ! 393: /* whole buffer past matching entry */ if (!rewind) { /* no point in searching ! 394: * further */ ! 395: errno = EINVAL; ! 396: return; /* no entry at specified loc */ ! 397: } else { /* rewind directory and start over */ ! 398: rewind = false; /* but only once! */ ! 399: ! 400: dirp->dd_loc = dirp->dd_size = 0; ! 401: ! 402: if (lseek(dirp->dd_fd, (OFFSET) 0, SEEK_SET) ! 403: != 0 ! 404: ) ! 405: return; /* errno already set (EBADF) */ ! 406: ! 407: if (loc == 0) ! 408: return; /* save time */ ! 409: } ! 410: } ! 411: } ! 412: ! 413: ! 414: /* telldir - report directory stream position ! 415: * ! 416: * DESCRIPTION ! 417: * ! 418: * Returns the offset of the next directory entry in the ! 419: * directory associated with dirp. ! 420: * ! 421: * NOTE: 4.nBSD directory compaction makes seekdir() & telldir() ! 422: * practically impossible to do right. Avoid using them! ! 423: * ! 424: * PARAMETERS ! 425: * ! 426: * DIR *dirp - stream from opendir() ! 427: * ! 428: * RETURNS ! 429: * ! 430: * Return offset of next entry ! 431: */ ! 432: ! 433: ! 434: #if __STDC__ ! 435: ! 436: OFFSET telldir(DIR *dirp) ! 437: ! 438: #else ! 439: ! 440: OFFSET telldir(dirp) ! 441: DIR *dirp; /* stream from opendir() */ ! 442: ! 443: #endif ! 444: { ! 445: if (dirp == NULL || dirp->dd_buf == NULL) { ! 446: errno = EFAULT; ! 447: return -1; /* invalid pointer */ ! 448: } ! 449: if (dirp->dd_loc < dirp->dd_size) /* valid index */ ! 450: return ((struct dirent *) & dirp->dd_buf[dirp->dd_loc])->d_off; ! 451: else /* beginning of next directory block */ ! 452: return lseek(dirp->dd_fd, (OFFSET) 0, SEEK_CUR); ! 453: } ! 454: ! 455: ! 456: #ifdef UFS ! 457: ! 458: /* ! 459: The following routine is necessary to handle DIRSIZ-long entry names. ! 460: Thanks to Richard Todd for pointing this out. ! 461: */ ! 462: ! 463: ! 464: /* return # chars in embedded name */ ! 465: ! 466: #if __STDC__ ! 467: ! 468: static int NameLen(char *name) ! 469: ! 470: #else ! 471: ! 472: static int NameLen(name) ! 473: char *name; /* -> name embedded in struct direct */ ! 474: ! 475: #endif ! 476: { ! 477: register char *s; /* -> name[.] */ ! 478: register char *stop = &name[DIRSIZ]; /* -> past end of name field */ ! 479: ! 480: for (s = &name[1]; /* (empty names are impossible) */ ! 481: *s != '\0' /* not NUL terminator */ ! 482: && ++s < stop; /* < DIRSIZ characters scanned */ ! 483: ); ! 484: ! 485: return s - name; /* # valid characters in name */ ! 486: } ! 487: ! 488: #else /* BFS || NFS */ ! 489: ! 490: extern int strlen(); ! 491: ! 492: #define NameLen( name ) strlen( name ) /* names are always NUL-terminated */ ! 493: ! 494: #endif ! 495: ! 496: #ifdef UNK ! 497: static enum { ! 498: maybe, no, yes ! 499: } state = maybe; ! 500: ! 501: ! 502: /* sig_catch - used to catch signals ! 503: * ! 504: * DESCRIPTION ! 505: * ! 506: * Used to catch signals. ! 507: */ ! 508: ! 509: /*ARGSUSED*/ ! 510: ! 511: #if __STDC__ ! 512: ! 513: static void sig_catch(int sig) ! 514: ! 515: #else ! 516: ! 517: static void sig_catch(sig) ! 518: int sig; /* must be SIGSYS */ ! 519: ! 520: #endif ! 521: { ! 522: state = no; /* attempted _getdents() faulted */ ! 523: } ! 524: #endif ! 525: ! 526: ! 527: /* getdents - get directory entries ! 528: * ! 529: * DESCRIPTION ! 530: * ! 531: * Gets directory entries from the filesystem in an implemenation ! 532: * defined way. ! 533: * ! 534: * PARAMETERS ! 535: * ! 536: * int fildes - directory file descriptor ! 537: * char *buf - where to put the (struct dirent)s ! 538: * unsigned nbyte - size of buf[] ! 539: * ! 540: * RETURNS ! 541: * ! 542: * Returns number of bytes read; 0 on EOF, -1 on error ! 543: */ ! 544: ! 545: #if __STDC__ ! 546: ! 547: int getdents(int fildes, char *buf, unsigned nbyte) ! 548: ! 549: #else ! 550: ! 551: int getdents(fildes, buf, nbyte) ! 552: int fildes; /* directory file descriptor */ ! 553: char *buf; /* where to put the (struct dirent)s */ ! 554: unsigned nbyte; /* size of buf[] */ ! 555: ! 556: #endif ! 557: { ! 558: int serrno; /* entry errno */ ! 559: OFFSET offset; /* initial directory file offset */ ! 560: struct stat statb; /* fstat() info */ ! 561: union { ! 562: /* directory file block buffer */ ! 563: #ifdef UFS ! 564: char dblk[DIRBLKSIZ + 1]; ! 565: #else ! 566: char dblk[DIRBLKSIZ]; ! 567: #endif ! 568: struct direct dummy; /* just for alignment */ ! 569: } u; /* (avoids having to malloc()) */ ! 570: register struct direct *dp; /* -> u.dblk[.] */ ! 571: register struct dirent *bp; /* -> buf[.] */ ! 572: ! 573: #ifdef UNK ! 574: switch (state) { ! 575: SIG_T (*shdlr)(); /* entry SIGSYS handler */ ! 576: register int retval; /* return from _getdents() if any */ ! 577: ! 578: case yes: /* _getdents() is known to work */ ! 579: return _getdents(fildes, buf, nbyte); ! 580: ! 581: case maybe: /* first time only */ ! 582: shdlr = signal(SIGSYS, sig_catch); ! 583: retval = _getdents(fildes, buf, nbyte); /* try it */ ! 584: signal(SIGSYS, shdlr); ! 585: ! 586: if (state == maybe) { /* SIGSYS did not occur */ ! 587: state = yes; /* so _getdents() must have worked */ ! 588: return retval; ! 589: } ! 590: /* else fall through into emulation */ ! 591: ! 592: /* case no: /* fall through into emulation */ ! 593: } ! 594: #endif ! 595: ! 596: if (buf == NULL ! 597: #ifdef ATT_SPEC ! 598: || (unsigned long) buf % sizeof(long) != 0 /* ugh */ ! 599: #endif ! 600: ) { ! 601: errno = EFAULT; /* invalid pointer */ ! 602: return -1; ! 603: } ! 604: if (fstat(fildes, &statb) != 0) { ! 605: return -1; /* errno set by fstat() */ ! 606: } ! 607: ! 608: if (!S_ISDIR(statb.st_mode)) { ! 609: errno = ENOTDIR; /* not a directory */ ! 610: return -1; ! 611: } ! 612: if ((offset = lseek(fildes, (OFFSET) 0, SEEK_CUR)) < 0) { ! 613: return -1; /* errno set by lseek() */ ! 614: } ! 615: ! 616: #ifdef BFS /* no telling what remote hosts do */ ! 617: if ((unsigned long) offset % DIRBLKSIZ != 0) { ! 618: errno = ENOENT; /* file pointer probably misaligned */ ! 619: return -1; ! 620: } ! 621: #endif ! 622: ! 623: serrno = errno; /* save entry errno */ ! 624: ! 625: for (bp = (struct dirent *) buf; bp == (struct dirent *) buf;) { ! 626: ! 627: /* convert next directory block */ ! 628: int size; ! 629: ! 630: do { ! 631: size = GetBlock(fildes, u.dblk, DIRBLKSIZ); ! 632: } while (size == -1 && errno == EINTR); ! 633: ! 634: if (size <= 0) { ! 635: return size; /* EOF or error (EBADF) */ ! 636: } ! 637: ! 638: for (dp = (struct direct *) u.dblk; ! 639: (char *) dp < &u.dblk[size]; ! 640: dp = (struct direct *) ((char *) dp + RecLen(dp)) ! 641: ) { ! 642: #ifndef UFS ! 643: if (dp->d_reclen <= 0) { ! 644: errno = EIO; /* corrupted directory */ ! 645: return -1; ! 646: } ! 647: #endif ! 648: ! 649: if (dp->d_fileno != 0) { /* non-empty; copy to user buffer */ ! 650: register int reclen = ! 651: DIRENTSIZ(NameLen(dp->d_name)); ! 652: ! 653: if ((char *) bp + reclen > &buf[nbyte]) { ! 654: errno = EINVAL; ! 655: return -1; /* buf too small */ ! 656: } ! 657: bp->d_ino = dp->d_fileno; ! 658: bp->d_off = offset + ((char *) dp - u.dblk); ! 659: bp->d_reclen = reclen; ! 660: ! 661: { ! 662: #ifdef UFS ! 663: /* Is the following kludge ugly? You bet. */ ! 664: ! 665: register char save = dp->d_name[DIRSIZ]; ! 666: /* save original data */ ! 667: ! 668: dp->d_name[DIRSIZ] = '\0'; ! 669: /* ensure NUL termination */ ! 670: #endif ! 671: /* adds NUL padding */ ! 672: strncpy(bp->d_name, dp->d_name, reclen - DIRENTBASESIZ); ! 673: #ifdef UFS ! 674: dp->d_name[DIRSIZ] = save; ! 675: /* restore original data */ ! 676: #endif ! 677: } ! 678: ! 679: bp = (struct dirent *) ((char *) bp + reclen); ! 680: } ! 681: } ! 682: ! 683: #ifndef BFS /* 4.2BSD screwed up; fixed in 4.3BSD */ ! 684: if ((char *) dp > &u.dblk[size]) { ! 685: errno = EIO; /* corrupted directory */ ! 686: return -1; ! 687: } ! 688: #endif ! 689: } ! 690: ! 691: errno = serrno; /* restore entry errno */ ! 692: return (char *) bp - buf; /* return # bytes read */ ! 693: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.