Annotation of 43BSDReno/contrib/isode-beta/dirent/getdents.c, revision 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.