Annotation of coherent/g/usr/bin/pax/paxdir.c, revision 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.