Annotation of 43BSDReno/contrib/isode-beta/dirent/getdents.c, revision 1.1.1.1

1.1       root        1: /*
                      2:        getdents -- get directory entries in a file system independent format
                      3:                        (SVR3 system call emulation)
                      4: 
                      5:        last edit:      06-Jul-1987     D A Gwyn
                      6: 
                      7:        This single source file supports several different methods of
                      8:        getting directory entries from the operating system.  Define
                      9:        whichever one of the following describes your system:
                     10: 
                     11:        GETDENTS getdents() system call native, this library is unnecessary
                     12: 
                     13:        UFS     original UNIX filesystem (14-character name limit)
                     14:        BFS     4.2BSD (also 4.3BSD) native filesystem (long names)
                     15:        NFS     getdirentries() system call
                     16: 
                     17:        Also define any of the following that are pertinent:
                     18: 
                     19:        ATT_SPEC        check user buffer address for longword alignment
                     20:        BSD_SYSV        BRL UNIX System V emulation environment on 4.nBSD
                     21:        UNK             have _getdents() system call, but kernel may not
                     22:                        support it
                     23: 
                     24:        If your C library has a getdents() system call interface, but you
                     25:        can't count on all kernels on which your application binaries may
                     26:        run to support it, change the system call interface name to
                     27:        _getdents() and define "UNK" to enable the system-call validity
                     28:        test in this "wrapper" around _getdents().
                     29: 
                     30:        If your system has a getdents() system call that is guaranteed 
                     31:        to always work, you shouldn't be using this source file at all.
                     32: */
                     33: 
                     34: #ifndef        lint                    /* for strings... */
                     35: static char *rcsid="$Header: /f/osi/dirent/RCS/getdents.c,v 7.0 89/11/23 21:30:58 mrose Rel $";
                     36: #endif
                     37: 
                     38: #include "config.h"
                     39: 
                     40: #if    !defined(SVR3) && !defined(apollo) && !defined(GETDENTS)
                     41: 
                     42: #include       <sys/errno.h>
                     43: #include       <sys/types.h>
                     44: #ifdef BSD_SYSV
                     45: #include       "sys._dir.h"            /* BSD flavor, not System V */
                     46: #else
                     47: #ifndef        AIX
                     48: #include       <sys/dir.h>
                     49: #else
                     50: #include       "/usr/include/sys/dir.h"
                     51: #endif
                     52: #undef MAXNAMLEN                       /* avoid conflict with SVR3 */
                     53:        /* Good thing we don't need to use the DIRSIZ() macro! */
                     54: #ifdef d_ino                           /* 4.3BSD/NFS using d_fileno */
                     55: #undef d_ino                           /* (not absolutely necessary) */
                     56: #else
                     57: #define        d_fileno        d_ino           /* (struct direct) member */
                     58: #endif
                     59: #endif
                     60: #include       "sys.dirent.h"
                     61: #include       <sys/stat.h>
                     62: 
                     63: #ifndef        NFS
                     64: #ifdef BSD42
                     65: #define        BFS
                     66: #else
                     67: #define        UFS
                     68: #endif
                     69: #endif
                     70: 
                     71: #ifdef UNK
                     72: #ifndef UFS
                     73: #include "***** ERROR ***** UNK applies only to UFS"
                     74: /* One could do something similar for getdirentries(), but I didn't bother. */
                     75: #endif
                     76: #include       <signal.h>
                     77: #endif
                     78: 
                     79: #if defined(UFS) + defined(BFS) + defined(NFS) != 1    /* sanity check */
                     80: #include "***** ERROR ***** exactly one of UFS, BFS, or NFS must be defined"
                     81: #endif
                     82: 
                     83: #ifdef UFS
                     84: #define        RecLen( dp )    (sizeof(struct direct)) /* fixed-length entries */
                     85: #else  /* BFS || NFS */
                     86: #define        RecLen( dp )    ((dp)->d_reclen)        /* variable-length entries */
                     87: #endif
                     88: 
                     89: #ifdef NFS
                     90: #ifdef BSD_SYSV
                     91: #define        getdirentries   _getdirentries  /* package hides this system call */
                     92: #endif
                     93: extern int     getdirentries();
                     94: static long    dummy;                  /* getdirentries() needs basep */
                     95: #define        GetBlock( fd, buf, n )  getdirentries( fd, buf, (int)n, &dummy )
                     96: #else  /* UFS || BFS */
                     97: #ifdef BSD_SYSV
                     98: #define read   _read                   /* avoid emulation overhead */
                     99: #endif
                    100: extern int     read();
                    101: #define        GetBlock( fd, buf, n )  read( fd, buf, (unsigned)n )
                    102: #endif
                    103: 
                    104: #ifdef UNK
                    105: extern int     _getdents();            /* actual system call */
                    106: #endif
                    107: 
                    108: extern char    *strncpy();
                    109: extern int     fstat();
                    110: extern off_t   lseek();
                    111: 
                    112: extern int     errno;
                    113: 
                    114: #ifndef DIRBLKSIZ
                    115: #define        DIRBLKSIZ       4096            /* directory file read buffer size */
                    116: #endif
                    117: 
                    118: #ifndef NULL
                    119: #define        NULL    0
                    120: #endif
                    121: 
                    122: #ifndef SEEK_CUR
                    123: #define        SEEK_CUR        1
                    124: #endif
                    125: 
                    126: #ifndef S_ISDIR                                /* macro to test for directory file */
                    127: #define        S_ISDIR( mode )         (((mode) & S_IFMT) == S_IFDIR)
                    128: #endif
                    129: 
                    130: #ifdef UFS
                    131: 
                    132: /*
                    133:        The following routine is necessary to handle DIRSIZ-long entry names.
                    134:        Thanks to Richard Todd for pointing this out.
                    135: */
                    136: 
                    137: static int
                    138: NameLen( name )                                /* return # chars in embedded name */
                    139:        char            name[];         /* -> name embedded in struct direct */
                    140:        {
                    141:        register char   *s;             /* -> name[.] */
                    142:        register char   *stop = &name[DIRSIZ];  /* -> past end of name field */
                    143: 
                    144:        for ( s = &name[1];             /* (empty names are impossible) */
                    145:              *s != '\0'                /* not NUL terminator */
                    146:           && ++s < stop;               /* < DIRSIZ characters scanned */
                    147:            )
                    148:                ;
                    149: 
                    150:        return s - name;                /* # valid characters in name */
                    151:        }
                    152: 
                    153: #else  /* BFS || NFS */
                    154: 
                    155: extern int     strlen();
                    156: 
                    157: #define        NameLen( name ) strlen( name )  /* names are always NUL-terminated */
                    158: 
                    159: #endif
                    160: 
                    161: #ifdef UNK
                    162: static enum    { maybe, no, yes }      state = maybe;
                    163:                                        /* does _getdents() work? */
                    164: 
                    165: /*ARGSUSED*/
                    166: static void
                    167: sig_catch( sig )
                    168:        int     sig;                    /* must be SIGSYS */
                    169:        {
                    170:        state = no;                     /* attempted _getdents() faulted */
                    171:        }
                    172: #endif
                    173: 
                    174: int
                    175: getdents( fildes, buf, nbyte )         /* returns # bytes read;
                    176:                                           0 on EOF, -1 on error */
                    177:        int                     fildes; /* directory file descriptor */
                    178:        char                    *buf;   /* where to put the (struct dirent)s */
                    179:        unsigned                nbyte;  /* size of buf[] */
                    180:        {
                    181:        int                     serrno; /* entry errno */
                    182:        off_t                   offset; /* initial directory file offset */
                    183:        struct stat             statb;  /* fstat() info */
                    184:        union   {
                    185:                char            dblk[DIRBLKSIZ];
                    186:                                        /* directory file block buffer */
                    187:                struct direct   dummy;  /* just for alignment */
                    188:                }       u;              /* (avoids having to malloc()) */
                    189:        register struct direct  *dp;    /* -> u.dblk[.] */
                    190:        register struct dirent  *bp;    /* -> buf[.] */
                    191: 
                    192: #ifdef UNK
                    193:        switch ( state )
                    194:                {
                    195:                void            (*shdlr)();     /* entry SIGSYS handler */
                    196:                register int    retval; /* return from _getdents() if any */
                    197: 
                    198:        case yes:                       /* _getdents() is known to work */
                    199:                return _getdents( fildes, buf, nbyte );
                    200: 
                    201:        case maybe:                     /* first time only */
                    202:                shdlr = signal( SIGSYS, sig_catch );
                    203:                retval = _getdents( fildes, buf, nbyte );       /* try it */
                    204:                (void)signal( SIGSYS, shdlr );
                    205: 
                    206:                if ( state == maybe )   /* SIGSYS did not occur */
                    207:                        {
                    208:                        state = yes;    /* so _getdents() must have worked */
                    209:                        return retval;
                    210:                        }
                    211:                /* else fall through into emulation */
                    212: 
                    213: /*     case no:        /* fall through into emulation */
                    214:                }
                    215: #endif
                    216: 
                    217:        if ( buf == NULL
                    218: #ifdef ATT_SPEC
                    219:          || (unsigned long)buf % sizeof(long) != 0     /* ugh */
                    220: #endif
                    221:           )    {
                    222:                errno = EFAULT;         /* invalid pointer */
                    223:                return -1;
                    224:                }
                    225: 
                    226:        if ( fstat( fildes, &statb ) != 0 )
                    227:                return -1;              /* errno set by fstat() */
                    228: 
                    229:        if ( !S_ISDIR( statb.st_mode ) )
                    230:                {
                    231:                errno = ENOTDIR;        /* not a directory */
                    232:                return -1;
                    233:                }
                    234: 
                    235:        if ( (offset = lseek( fildes, (off_t)0, SEEK_CUR )) < 0 )
                    236:                return -1;              /* errno set by lseek() */
                    237: 
                    238: #ifdef BFS                             /* no telling what remote hosts do */
                    239:        if ( (unsigned long)offset % DIRBLKSIZ != 0 )
                    240:                {
                    241:                errno = ENOENT;         /* file pointer probably misaligned */
                    242:                return -1;
                    243:                }
                    244: #endif
                    245: 
                    246:        serrno = errno;                 /* save entry errno */
                    247: 
                    248:        for ( bp = (struct dirent *)buf; bp == (struct dirent *)buf; )
                    249:                {                       /* convert next directory block */
                    250:                int     size;
                    251: 
                    252:                do      size = GetBlock( fildes, u.dblk, DIRBLKSIZ );
                    253:                while ( size == -1 && errno == EINTR );
                    254: 
                    255:                if ( size <= 0 )
                    256:                        return size;    /* EOF or error (EBADF) */
                    257: 
                    258:                for ( dp = (struct direct *)u.dblk;
                    259:                      (char *)dp < &u.dblk[size];
                    260:                      dp = (struct direct *)((char *)dp + RecLen( dp ))
                    261:                    )   {
                    262: #ifndef UFS
                    263:                        if ( dp->d_reclen <= 0 )
                    264:                                {
                    265:                                errno = EIO;    /* corrupted directory */
                    266:                                return -1;
                    267:                                }
                    268: #endif
                    269: 
                    270:                        if ( dp->d_fileno != 0 )
                    271:                                {       /* non-empty; copy to user buffer */
                    272:                                register int    reclen =
                    273:                                        DIRENTSIZ( NameLen( dp->d_name ) );
                    274: 
                    275:                                if ( (char *)bp + reclen > &buf[nbyte] )
                    276:                                        {
                    277:                                        errno = EINVAL;
                    278:                                        return -1;      /* buf too small */
                    279:                                        }
                    280: 
                    281:                                bp->d_ino = dp->d_fileno;
                    282:                                bp->d_off = offset + ((char *)dp - u.dblk);
                    283:                                bp->d_reclen = reclen;
                    284:                                (void)strncpy( bp->d_name, dp->d_name,
                    285: #ifdef UFS
                    286:                                        DIRSIZ );
                    287:                                /* be sure d_name is NULL-terminated */
                    288:                                bp->d_name[DIRSIZ] = NULL;
                    289: #else
                    290:                                        reclen - DIRENTBASESIZ );
                    291:                                        /* adds NUL padding */
                    292: #endif
                    293: 
                    294:                                bp = (struct dirent *)((char *)bp + reclen);
                    295:                                }
                    296:                        }
                    297: 
                    298: #ifndef BFS    /* 4.2BSD screwed up; fixed in 4.3BSD */
                    299:                if ( (char *)dp > &u.dblk[size] )
                    300:                        {
                    301:                        errno = EIO;    /* corrupted directory */
                    302:                        return -1;
                    303:                        }
                    304: #endif
                    305:                }
                    306: 
                    307:        errno = serrno;                 /* restore entry errno */
                    308:        return (char *)bp - buf;        /* return # bytes read */
                    309:        }
                    310: 
                    311: #endif         /* not SVR3 */

unix.superglobalmegacorp.com

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