|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.