Annotation of coherent/e/bin/pax/paxdir.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.