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

unix.superglobalmegacorp.com

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