dono@killer.DALLAS.TX.US (Don OConnell) (12/15/88)
This is from an old archive that I had at home - there is a more recent one in comp.sources.unix archives. These work fine for my uses. Compile closedir opendir seekdir readdir telldir and put them at the end of libca in the order listed above. These routines were originally done by D. A. Gwyn - if I am not mistaken. -----------------------------CUT HERE------------------------------------- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: READ_ME closedir.c dir.h directory.3c opendir.c readdir.c # seekdir.c telldir.c testdir.c # Wrapped by dono@killer on Wed Dec 14 12:33:20 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f READ_ME -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"READ_ME\" else echo shar: Extracting \"READ_ME\" \(3777 characters\) sed "s/^X//" >READ_ME <<'END_OF_READ_ME' X NOTES FOR C LIBRARY EXTENSIONS FOR DIRECTORY ACCESS X X XThe standard C library lacks support for reading UNIX directories, so Xhistorically programs had knowledge of UNIX directory structure hard- Xwired into them. When Berkeley changed the format of directories for X4.2BSD, it became necessary to change programs to work with the new Xstructure. Fortunately Berkeley designed a small set of directory Xaccess routines to encapsulate knowledge of the new directory format Xso that user programs could deal with directory entries as an abstract Xdata type. The interface to these routines is independent of the Xparticular implementation of directories on any given UNIX system. X XTherefore it becomes possible to write portable applications that Xsearch directories by restricting all directory access to these new Xinterface routines. The sources supplied here are a total rewrite of XBerkeley's code and are in the PUBLIC DOMAIN. They simulate the new X4.2BSD directory entries on systems having the original UNIX directory Xstructure. These routines should be added to the standard C library Xon ALL non-BSD UNIX systems and all existing and future code changed to Xuse this interface. Once this is done, there will be no portability Xproblems associated with the difference in underlying directory Xstructures between 4.2BSD and other UNIX systems. X XAn additional benefit of these routines is that they buffer directory Xinput, which provides improved access speed. X X X INSTALLATION INSTRUCTIONS X X XIf your system predates 7th Edition UNIX you have problems. Adapt the Xinstructions and source code as required, or better still upgrade your Xsystem (a modern compiler and library can be made to run on an older Xkernel with a modest amount of work). X X XFor systems (such as pre-System III UNIXes) that do not support C's X"void" data type: X X0) Edit the file ./include/dir.h to insert the following line before X the first occurrence of the word "void": X X typedef int void; X X XFor 7th Edition or later UNIXes (but NOT 4.2BSD): X X1) Copy the file ./include/dir.h to /usr/include (note that there is X NOT a conflict with /usr/include/sys/dir.h). X X2) Copy the file ./man/directory.3c to /usr/man/p_man/man3, X /usr/man/u_man/man3, or /usr/man/man3; then print the manual page X via the command X X man 3 directory X X to see what the new routines are like. (If you have a "catman" X type of on-line manual, adapt these instructions accordingly.) X X3) Copy the files ./src/* to the "gen" subdirectory of your C library X source directory, then remake the C library. Alternatively you X might just compile the new sources and insert their objects near X the front of the C library /lib/libc.a using the archiver (seekdir X must precede telldir and readdir). X X4) To verify installation, try compiling, linking, and running the X program test/testdir.c. This program searches the current X directory "." for each file named as a program argument and prints X `"FOO" found.' or `"FOO" not found.' where FOO is replaced by the X name being looked for in the directory. Try something like X X cd /usr/bin # a multi-block directory X WHEREVER/testdir FOO lint BAR f77 XYZZY X X which should produce the output X X "FOO" not found. X "lint" found. X "BAR" not found. X "f77" found. X "XYZZY" not found. X X5) Notify your users that all directory access must be through the X new routines, and that documentation is available via X X man 3 directory X X6) Change all system sources that were accessing directories to use X the new routines. Nearly all such sources contain the line X X #include <sys/dir.h> X X so they should be easy to find. X X7) After a suitable changeover period, remove /usr/include/sys/dir.h X to force use of the new routines for all directory access. END_OF_READ_ME if test 3777 -ne `wc -c <READ_ME`; then echo shar: \"READ_ME\" unpacked with wrong size! fi # end of overwriting check fi if test -f closedir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"closedir.c\" else echo shar: Extracting \"closedir.c\" \(271 characters\) sed "s/^X//" >closedir.c <<'END_OF_closedir.c' X/* X closedir -- C library extension routine X X last edit: 21-Jan-1984 D A Gwyn X*/ X X#include <dir.h> X Xextern void free(); Xextern int close(); X Xvoid Xclosedir( dirp ) X register DIR *dirp; /* stream from opendir() */ X { X (void)close( dirp->dd_fd ); X free( (char *)dirp ); X } END_OF_closedir.c if test 271 -ne `wc -c <closedir.c`; then echo shar: \"closedir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f dir.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"dir.h\" else echo shar: Extracting \"dir.h\" \(927 characters\) sed "s/^X//" >dir.h <<'END_OF_dir.h' X/* X <dir.h> -- definitions for 4.2BSD-compatible directory access X X last edit: 09-Jul-1983 D A Gwyn X*/ X X#define DIRBLKSIZ 512 /* size of directory block */ X#define MAXNAMLEN 15 /* maximum filename length */ X /* NOTE: MAXNAMLEN must be one less than a multiple of 4 */ X Xstruct direct /* data from readdir() */ X { X long d_ino; /* inode number of entry */ X unsigned short d_reclen; /* length of this record */ X unsigned short d_namlen; /* length of string in d_name */ X char d_name[MAXNAMLEN+1]; /* name of file */ X }; X Xtypedef struct X { X int dd_fd; /* file descriptor */ X int dd_loc; /* offset in block */ X int dd_size; /* amount of valid data */ X char dd_buf[DIRBLKSIZ]; /* directory block */ X } DIR; /* stream data from opendir() */ X Xextern DIR *opendir(); Xextern struct direct *readdir(); Xextern long telldir(); Xextern void seekdir(); Xextern void closedir(); X X#define rewinddir( dirp ) seekdir( dirp, 0L ) END_OF_dir.h if test 927 -ne `wc -c <dir.h`; then echo shar: \"dir.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f directory.3c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"directory.3c\" else echo shar: Extracting \"directory.3c\" \(2748 characters\) sed "s/^X//" >directory.3c <<'END_OF_directory.3c' X.TH DIRECTORY 3 "Standard Extension" X.SH NAME Xopendir, readdir, telldir, seekdir, rewinddir, closedir \- directory operations X.SH SYNOPSIS X.B #include <dir.h> X.PP X.B DIR \(**opendir (filename) X.br X.B char \(**filename; X.PP X.B struct direct \(**readdir (dirp) X.br X.B DIR \(**dirp; X.PP X.B long telldir (dirp) X.br X.B DIR \(**dirp; X.PP X.B void seekdir (dirp, loc) X.br X.B DIR \(**dirp; X.br X.B long loc; X.PP X.B void rewinddir (dirp) X.br X.B DIR X.B *dirp; X.PP X.B void X.B closedir(dirp) X.br X.B DIR X.B *dirp; X.SM X.SH DESCRIPTION X.I Opendir\^ Xopens the directory named by X.I filename\^ Xand associates a X.I directory stream\^ Xwith it. X.I Opendir\^ Xreturns a pointer to be used to identify the X.I directory stream\^ Xin subsequent operations. XThe pointer X.SM X.B NULL Xis returned if X.I filename\^ Xcannot be accessed or is not a directory, Xor if it cannot X.IR malloc (3) Xenough memory to hold a X.SM X.I DIR\^ Xstructure. X.PP X.I Readdir\^ Xreturns a pointer to the next directory entry. XIt returns X.SM X.B NULL Xupon reaching the end of the directory or Xupon detecting an invalid X.I seekdir\^ Xoperation. X.PP X.I Telldir\^ Xreturns the current location associated with the named X.I directory stream. X.PP X.I Seekdir\^ Xsets the position of the next X.I readdir\^ Xoperation on the X.I directory stream. XThe new position reverts to the one associated with the X.I directory stream\^ Xwhen the X.I telldir\^ Xoperation from which X.I loc\^ Xwas obtained was performed. XValues returned by X.I telldir\^ Xare good only for the lifetime of Xthe DIR pointer from which they are derived. XIf the directory is closed and then reopened, Xthe X.I telldir\^ Xvalue may be invalidated Xdue to undetected directory compaction. XIt is safe to use a previous X.I telldir\^ Xvalue immediately after a call to X.I opendir\^ Xand before any calls to X.I readdir. X.PP X.I Rewinddir\^ Xresets the position of the named X.I directory stream\^ Xto the beginning of the directory. X.PP X.I Closedir\^ Xcloses the named X.I directory stream\^ Xand frees the X.SM X.I DIR\^ Xstructure. X.SH EXAMPLE XSample code which searchs a directory for entry ``name'': X.PP X.br X dirp = opendir( "." ); X.br X while ( (dp = readdir( dirp )) != NULL ) X.br X if ( strcmp( dp->d_name, name ) == 0 ) X.br X { X.br X closedir( dirp ); X.br X return FOUND; X.br X } X.br X closedir( dirp ); X.br X return NOT_FOUND; X.SH "SEE ALSO" Xopen(2), close(2), read(2), lseek(2), Xscandir(3B) X.SH WARNINGS X.I Rewinddir\^ Xis implemented as a macro, Xso its function address cannot be taken. X.PP XAll UNIX programs which examine directories Xshould be converted to use this package, Xsince directory format is no longer the same on all UNIX systems. XUnfortunately, Xthis package is not yet Xsupplied with all UNIX systems, Xalthough public-domain source code is available Xfrom BRL. END_OF_directory.3c if test 2748 -ne `wc -c <directory.3c`; then echo shar: \"directory.3c\" unpacked with wrong size! fi # end of overwriting check fi if test -f opendir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"opendir.c\" else echo shar: Extracting \"opendir.c\" \(838 characters\) sed "s/^X//" >opendir.c <<'END_OF_opendir.c' X/* X opendir -- C library extension routine X X last edit: 09-Jul-1983 D A Gwyn X*/ X X#include <dir.h> X#include <sys/types.h> X#include <sys/stat.h> X X#ifdef BRL X#define open _open /* avoid emulation */ X#endif X Xextern char *malloc(); Xextern int open(), close(), fstat(); X X#define NULL 0 X XDIR * Xopendir( filename ) X char *filename; /* name of directory */ X { X register DIR *dirp; /* -> malloc'ed storage */ X register int fd; /* file descriptor for read */ X struct stat sbuf; /* result of fstat() */ X X if ( (fd = open( filename, 0 )) < 0 ) X return NULL; X X if ( fstat( fd, &sbuf ) < 0 X || (sbuf.st_mode & S_IFMT) != S_IFDIR X || (dirp = (DIR *)malloc( sizeof(DIR) )) == NULL X ) { X (void)close( fd ); X return NULL; /* bad luck today */ X } X X dirp->dd_fd = fd; X dirp->dd_loc = dirp->dd_size = 0; /* refill needed */ X X return dirp; X } END_OF_opendir.c if test 838 -ne `wc -c <opendir.c`; then echo shar: \"opendir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f readdir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"readdir.c\" else echo shar: Extracting \"readdir.c\" \(1259 characters\) sed "s/^X//" >readdir.c <<'END_OF_readdir.c' X/* X readdir -- C library extension routine for non-BSD UNIX X X last edit: 09-Jul-1983 D A Gwyn X*/ X X#include <dir.h> X#include <sys/types.h> X Xextern char *strncpy(); Xextern int read(), strlen(); X X#define NULL 0 X X#define DIRSIZ 14 Xstruct olddir X { X ino_t od_ino; /* inode */ X char od_name[DIRSIZ]; /* filename */ X }; X Xstruct direct * Xreaddir( dirp ) X register DIR *dirp; /* stream from opendir() */ X { X register struct olddir *dp; /* -> directory data */ X X for ( ; ; ) X { X if ( dirp->dd_loc >= dirp->dd_size ) X dirp->dd_loc = dirp->dd_size = 0; X X if ( dirp->dd_size == 0 /* refill buffer */ X && (dirp->dd_size = read( dirp->dd_fd, dirp->dd_buf, X DIRBLKSIZ X ) X ) <= 0 X ) X return NULL; /* error or EOF */ X X dp = (struct olddir *)&dirp->dd_buf[dirp->dd_loc]; X dirp->dd_loc += sizeof(struct olddir); X X if ( dp->od_ino != 0 ) /* not deleted entry */ X { X static struct direct dir; /* simulated */ X X dir.d_ino = dp->od_ino; X (void)strncpy( dir.d_name, dp->od_name, DIRSIZ X ); X dir.d_name[DIRSIZ] = '\0'; X dir.d_namlen = strlen( dir.d_name ); X dir.d_reclen = sizeof(struct direct) X - MAXNAMLEN + 3 X + dir.d_namlen - dir.d_namlen % 4; X return &dir; /* -> simulated structure */ X } X } X } END_OF_readdir.c if test 1259 -ne `wc -c <readdir.c`; then echo shar: \"readdir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f seekdir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"seekdir.c\" else echo shar: Extracting \"seekdir.c\" \(670 characters\) sed "s/^X//" >seekdir.c <<'END_OF_seekdir.c' X/* X seekdir -- C library extension routine X X last edit: 21-Jan-1984 D A Gwyn X*/ X X#include <dir.h> X Xextern long lseek(); X X#define NULL 0 X Xvoid Xseekdir( dirp, loc ) X register DIR *dirp; /* stream from opendir() */ X long loc; /* position from telldir() */ X { X long base; /* file location of block */ X long offset; /* offset within block */ X X if ( telldir( dirp ) == loc ) X return; /* save time */ X X offset = loc % DIRBLKSIZ; X base = loc - offset; X X (void)lseek( dirp->dd_fd, base, 0 ); /* change blocks */ X dirp->dd_loc = dirp->dd_size = 0; X X while ( dirp->dd_loc < offset ) /* skip entries */ X if ( readdir( dirp ) == NULL ) X return; /* "can't happen" */ X } END_OF_seekdir.c if test 670 -ne `wc -c <seekdir.c`; then echo shar: \"seekdir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f telldir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"telldir.c\" else echo shar: Extracting \"telldir.c\" \(276 characters\) sed "s/^X//" >telldir.c <<'END_OF_telldir.c' X/* X telldir -- C library extension routine X X last edit: 09-Jul-1983 D A Gwyn X*/ X X#include <dir.h> X Xextern long lseek(); X Xlong Xtelldir( dirp ) X DIR *dirp; /* stream from opendir() */ X { X return lseek( dirp->dd_fd, 0L, 1 ) - (long)dirp->dd_size X + (long)dirp->dd_loc; X } END_OF_telldir.c if test 276 -ne `wc -c <telldir.c`; then echo shar: \"telldir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f testdir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"testdir.c\" else echo shar: Extracting \"testdir.c\" \(889 characters\) sed "s/^X//" >testdir.c <<'END_OF_testdir.c' X/* X testdir -- test for C library directory access extensions X X last edit: 09-Jul-1983 D A Gwyn X*/ X X#include <dir.h> X#include <stdio.h> X Xextern void exit(); Xextern int strcmp(), strlen(); X Xmain( argc, argv ) X int argc; X char **argv; X { X register DIR *dirp; X register struct direct *dp; X int nerrs = 0; /* total not found */ X X if ( (dirp = opendir( "." )) == NULL ) X { X (void)fprintf( stderr, "Cannot open \".\" directory\n" X ); X exit( 1 ); X } X X while ( --argc > 0 ) X { X register int len = strlen( *++argv ); X X while ( (dp = readdir( dirp)) != NULL ) X if ( dp->d_namlen == len X && strcmp( dp->d_name, *argv ) == 0 X ) { X (void)printf( "\"%s\" found.\n", X *argv X ); X break; X } X if ( dp == NULL ) X { X (void)printf( "\"%s\" not found.\n", *argv ); X ++nerrs; X } X X rewinddir( dirp ); X } X X closedir( dirp ); X exit( nerrs ); X } END_OF_testdir.c if test 889 -ne `wc -c <testdir.c`; then echo shar: \"testdir.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of shell archive. exit 0