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

unix.superglobalmegacorp.com

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