117721Speterecho 'directory.3': 217721Spetersed 's/^X//' >'directory.3' <<'!' 317721SpeterX.TH DIRECTORY 3 imported 417721SpeterX.DA 9 Oct 1985 517721SpeterX.SH NAME 617721SpeterXopendir, readdir, telldir, seekdir, rewinddir, closedir \- high-level directory operations 717721SpeterX.SH SYNOPSIS 817721SpeterX.B #include <sys/types.h> 917721SpeterX.br 1017721SpeterX.B #include <ndir.h> 1117721SpeterX.PP 1217721SpeterX.SM 1317721SpeterX.B DIR 1417721SpeterX.B *opendir(filename) 1517721SpeterX.br 1617721SpeterX.B char *filename; 1717721SpeterX.PP 1817721SpeterX.SM 1917721SpeterX.B struct direct 2017721SpeterX.B *readdir(dirp) 2117721SpeterX.br 2217721SpeterX.B DIR *dirp; 2317721SpeterX.PP 2417721SpeterX.SM 2517721SpeterX.B long 2617721SpeterX.B telldir(dirp) 2717721SpeterX.br 2817721SpeterX.B DIR *dirp; 2917721SpeterX.PP 3017721SpeterX.SM 3117721SpeterX.B seekdir(dirp, loc) 3217721SpeterX.br 3317721SpeterX.B DIR *dirp; 3417721SpeterX.br 3517721SpeterX.B long loc; 3617721SpeterX.PP 3717721SpeterX.SM 3817721SpeterX.B rewinddir(dirp) 3917721SpeterX.br 4017721SpeterX.B DIR *dirp; 4117721SpeterX.PP 4217721SpeterX.SM 4317721SpeterX.B closedir(dirp) 4417721SpeterX.br 4517721SpeterX.B DIR *dirp; 4617721SpeterX.SH DESCRIPTION 4717721SpeterXThis library provides high-level primitives for directory scanning, 4817721SpeterXsimilar to those available for 4.2BSD's (very different) directory system. 4917721SpeterX.\"The purpose of this library is to simulate 5017721SpeterX.\"the new flexible length directory names of 4.2bsd UNIX 5117721SpeterX.\"on top of the old directory structure of v7. 5217721SpeterXIt incidentally provides easy portability to and from 4.2BSD (insofar 5317721SpeterXas such portability is not compromised by other 4.2/VAX dependencies). 5417721SpeterX.\"It allows programs to be converted immediately 5517721SpeterX.\"to the new directory access interface, 5617721SpeterX.\"so that they need only be relinked 5717721SpeterX.\"when moved to 4.2bsd. 5817721SpeterX.\"It is obtained with the loader option 5917721SpeterX.\".BR \-lndir . 6017721SpeterX.PP 6117721SpeterX.I Opendir 6217721SpeterXopens the directory named by 6317721SpeterX.I filename 6417721SpeterXand associates a 6517721SpeterX.I directory stream 6617721SpeterXwith it. 6717721SpeterX.I Opendir 6817721SpeterXreturns a pointer to be used to identify the 6917721SpeterX.I directory stream 7017721SpeterXin subsequent operations. 7117721SpeterXThe pointer 7217721SpeterX.SM 7317721SpeterX.B NULL 7417721SpeterXis returned if 7517721SpeterX.I filename 7617721SpeterXcannot be accessed or is not a directory. 7717721SpeterX.PP 7817721SpeterX.I Readdir 7917721SpeterXreturns a pointer to the next directory entry. 8017721SpeterXIt returns 8117721SpeterX.B NULL 8217721SpeterXupon reaching the end of the directory or detecting 8317721SpeterXan invalid 8417721SpeterX.I seekdir 8517721SpeterXoperation. 8617721SpeterX.PP 8717721SpeterX.I Telldir 8817721SpeterXreturns the current location associated with the named 8917721SpeterX.I directory stream. 9017721SpeterX.PP 9117721SpeterX.I Seekdir 9217721SpeterXsets the position of the next 9317721SpeterX.I readdir 9417721SpeterXoperation on the 9517721SpeterX.I directory stream. 9617721SpeterXThe new position reverts to the one associated with the 9717721SpeterX.I directory stream 9817721SpeterXwhen the 9917721SpeterX.I telldir 10017721SpeterXoperation was performed. 10117721SpeterXValues returned by 10217721SpeterX.I telldir 10317721SpeterXare good only for the lifetime of the DIR pointer from 10417721SpeterXwhich they are derived. 10517721SpeterXIf the directory is closed and then reopened, 10617721SpeterXthe 10717721SpeterX.I telldir 10817721SpeterXvalue may be invalidated 10917721SpeterXdue to undetected directory compaction in 4.2BSD. 11017721SpeterXIt is safe to use a previous 11117721SpeterX.I telldir 11217721SpeterXvalue immediately after a call to 11317721SpeterX.I opendir 11417721SpeterXand before any calls to 11517721SpeterX.I readdir. 11617721SpeterX.PP 11717721SpeterX.I Rewinddir 11817721SpeterXresets the position of the named 11917721SpeterX.I directory stream 12017721SpeterXto the beginning of the directory. 12117721SpeterX.PP 12217721SpeterX.I Closedir 12317721SpeterXcauses the named 12417721SpeterX.I directory stream 12517721SpeterXto be closed, 12617721SpeterXand the structure associated with the DIR pointer to be freed. 12717721SpeterX.PP 12817721SpeterXA 12917721SpeterX.I direct 13017721SpeterXstructure is as follows: 13117721SpeterX.PP 13217721SpeterX.RS 13317721SpeterX.nf 13417721SpeterXstruct direct { 13517721SpeterX /* unsigned */ long d_ino; /* inode number of entry */ 13617721SpeterX unsigned short d_reclen; /* length of this record */ 13717721SpeterX unsigned short d_namlen; /* length of string in d_name */ 13817721SpeterX char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ 13917721SpeterX}; 14017721SpeterX.fi 14117721SpeterX.RE 14217721SpeterX.PP 14317721SpeterXThe 14417721SpeterX.I d_reclen 14517721SpeterXfield is meaningless in non-4.2BSD systems and should be ignored. 14617721SpeterXThe use of a 14717721SpeterX.I long 14817721SpeterXfor 14917721SpeterX.I d_ino 15017721SpeterXis also a 4.2BSDism; 15117721SpeterX.I ino_t 15217721SpeterX(see 15317721SpeterX.IR types (5)) 15417721SpeterXshould be used elsewhere. 15517721SpeterXThe macro 15617721SpeterX.I DIRSIZ(dp) 15717721SpeterXgives the minimum memory size needed to hold the 15817721SpeterX.I direct 15917721SpeterXvalue pointed to by 16017721SpeterX.IR dp , 16117721SpeterXwith the minimum necessary allocation for 16217721SpeterX.IR d_name . 16317721SpeterX.PP 16417721SpeterXThe preferred way to search the current directory for entry ``name'' is: 16517721SpeterX.PP 16617721SpeterX.RS 16717721SpeterX.nf 16817721SpeterX len = strlen(name); 16917721SpeterX dirp = opendir("."); 17017721SpeterX if (dirp == NULL) { 17117721SpeterX fprintf(stderr, "%s: can't read directory .\\n", argv[0]); 17217721SpeterX return NOT_FOUND; 17317721SpeterX } 17417721SpeterX while ((dp = readdir(dirp)) != NULL) 17517721SpeterX if (dp->d_namlen == len && strcmp(dp->d_name, name) == 0) { 17617721SpeterX closedir(dirp); 17717721SpeterX return FOUND; 17817721SpeterX } 17917721SpeterX closedir(dirp); 18017721SpeterX return NOT_FOUND; 18117721SpeterX.RE 18217721SpeterX.\".SH LINKING 18317721SpeterX.\"This library is accessed by specifying ``-lndir'' as the 18417721SpeterX.\"last argument to the compile line, e.g.: 18517721SpeterX.\".PP 18617721SpeterX.\" cc -I/usr/include/ndir -o prog prog.c -lndir 18717721SpeterX.SH "SEE ALSO" 18817721SpeterXopen(2), 18917721SpeterXclose(2), 19017721SpeterXread(2), 19117721SpeterXlseek(2) 19217721SpeterX.SH HISTORY 19317721SpeterXWritten by 19417721SpeterXKirk McKusick at Berkeley (ucbvax!mckusick). 19517721SpeterXMiscellaneous bug fixes from elsewhere. 19617721SpeterXThe size of the data structure has been decreased to avoid excessive 19717721SpeterXspace waste under V7 (where filenames are 14 characters at most). 19817721SpeterXFor obscure historical reasons, the include file is also available 19917721SpeterXas 20017721SpeterX.IR <ndir/sys/dir.h> . 20117721SpeterXThe Berkeley version lived in a separate library (\fI\-lndir\fR), 20217721SpeterXwhereas ours is 20317721SpeterXpart of the C library, although the separate library is retained to 20417721SpeterXmaximize compatibility. 20517721SpeterX.PP 20617721SpeterXThis manual page has been substantially rewritten to be informative in 20717721SpeterXthe absence of a 4.2BSD manual. 20817721SpeterX.SH BUGS 20917721SpeterXThe 21017721SpeterX.I DIRSIZ 21117721SpeterXmacro actually wastes a bit of space due to some padding requirements 21217721SpeterXthat are an artifact of 4.2BSD. 21317721SpeterX.PP 21417721SpeterXThe returned value of 21517721SpeterX.I readdir 21617721SpeterXpoints to a static area that will be overwritten by subsequent calls. 21717721SpeterX.PP 21817721SpeterXThere are some unfortunate name conflicts with the \fIreal\fR V7 21917721SpeterXdirectory structure definitions. 22017721Speter! 22117721Speterecho 'dir.h': 22217721Spetersed 's/^X//' >'dir.h' <<'!' 22317721SpeterX/* dir.h 4.4 82/07/25 */ 22417721SpeterX 22517721SpeterX/* 22617721SpeterX * A directory consists of some number of blocks of DIRBLKSIZ 22717721SpeterX * bytes, where DIRBLKSIZ is chosen such that it can be transferred 22817721SpeterX * to disk in a single atomic operation (e.g. 512 bytes on most machines). 22917721SpeterX * 23017721SpeterX * Each DIRBLKSIZ byte block contains some number of directory entry 23117721SpeterX * structures, which are of variable length. Each directory entry has 23217721SpeterX * a struct direct at the front of it, containing its inode number, 23317721SpeterX * the length of the entry, and the length of the name contained in 23417721SpeterX * the entry. These are followed by the name padded to a 4 byte boundary 23517721SpeterX * with null bytes. All names are guaranteed null terminated. 23617721SpeterX * The maximum length of a name in a directory is MAXNAMLEN. 23717721SpeterX * 23817721SpeterX * The macro DIRSIZ(dp) gives the amount of space required to represent 23917721SpeterX * a directory entry. Free space in a directory is represented by 24017721SpeterX * entries which have dp->d_reclen >= DIRSIZ(dp). All DIRBLKSIZ bytes 24117721SpeterX * in a directory block are claimed by the directory entries. This 24217721SpeterX * usually results in the last entry in a directory having a large 24317721SpeterX * dp->d_reclen. When entries are deleted from a directory, the 24417721SpeterX * space is returned to the previous entry in the same directory 24517721SpeterX * block by increasing its dp->d_reclen. If the first entry of 24617721SpeterX * a directory block is free, then its dp->d_ino is set to 0. 24717721SpeterX * Entries other than the first in a directory do not normally have 24817721SpeterX * dp->d_ino set to 0. 24917721SpeterX */ 25017721SpeterX#define DIRBLKSIZ 512 25117721SpeterX#ifdef VMUNIX 25217721SpeterX#define MAXNAMLEN 255 25317721SpeterX#else 25417721SpeterX#define MAXNAMLEN 14 25517721SpeterX#endif 25617721SpeterX 25717721SpeterXstruct direct { 25817721SpeterX /* unsigned */ long d_ino; /* inode number of entry */ 25917721SpeterX unsigned short d_reclen; /* length of this record */ 26017721SpeterX unsigned short d_namlen; /* length of string in d_name */ 26117721SpeterX char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ 26217721SpeterX}; 26317721SpeterX 26417721SpeterX/* 26517721SpeterX * The DIRSIZ macro gives the minimum record length which will hold 26617721SpeterX * the directory entry. This requires the amount of space in struct direct 26717721SpeterX * without the d_name field, plus enough space for the name with a terminating 26817721SpeterX * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. 26917721SpeterX */ 27017721SpeterX#undef DIRSIZ 27117721SpeterX#define DIRSIZ(dp) \ 27217721SpeterX ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) 27317721SpeterX 27417721SpeterX#ifndef KERNEL 27517721SpeterX/* 27617721SpeterX * Definitions for library routines operating on directories. 27717721SpeterX */ 27817721SpeterXtypedef struct _dirdesc { 27917721SpeterX int dd_fd; 28017721SpeterX long dd_loc; 28117721SpeterX long dd_size; 28217721SpeterX char dd_buf[DIRBLKSIZ]; 28317721SpeterX} DIR; 28417721SpeterX#ifndef NULL 28517721SpeterX#define NULL 0 28617721SpeterX#endif 28717721SpeterXextern DIR *opendir(); 28817721SpeterXextern struct direct *readdir(); 28917721SpeterXextern long telldir(); 29017721SpeterX#ifdef void 29117721SpeterXextern void seekdir(); 29217721SpeterXextern void closedir(); 29317721SpeterX#endif 29417721SpeterX#define rewinddir(dirp) seekdir((dirp), (long)0) 29517721SpeterX#endif KERNEL 29617721Speter! 29717721Speterecho 'makefile': 29817721Spetersed 's/^X//' >'makefile' <<'!' 29917721SpeterXDIR = closedir.o opendir.o readdir.o seekdir.o telldir.o 30017721SpeterXCFLAGS=-O -I. -Dvoid=int 30117721SpeterXDEST=.. 30217721SpeterX 30317721SpeterXall: $(DIR) 30417721SpeterX 30517721SpeterXmv: $(DIR) 30617721SpeterX mv $(DIR) $(DEST) 30717721SpeterX 30817721SpeterXcpif: dir.h 30917721SpeterX cp dir.h /usr/include/ndir.h 31017721SpeterX 31117721SpeterXclean: 31217721SpeterX rm -f *.o 31317721Speter! 31417721Speterecho 'closedir.c': 31517721Spetersed 's/^X//' >'closedir.c' <<'!' 31617721SpeterXstatic char sccsid[] = "@(#)closedir.c 4.2 3/10/82"; 31717721SpeterX 31817721SpeterX#include <sys/types.h> 31917721SpeterX#include <dir.h> 32017721SpeterX 32117721SpeterX/* 32217721SpeterX * close a directory. 32317721SpeterX */ 32417721SpeterXvoid 32517721SpeterXclosedir(dirp) 32617721SpeterX register DIR *dirp; 32717721SpeterX{ 32817721SpeterX close(dirp->dd_fd); 32917721SpeterX dirp->dd_fd = -1; 33017721SpeterX dirp->dd_loc = 0; 33117721SpeterX free((char *)dirp); 33217721SpeterX} 33317721Speter! 33417721Speterecho 'opendir.c': 33517721Spetersed 's/^X//' >'opendir.c' <<'!' 33617721SpeterX/* Copyright (c) 1982 Regents of the University of California */ 33717721SpeterX 33817721SpeterXstatic char sccsid[] = "@(#)opendir.c 4.4 11/12/82"; 33917721SpeterX 34017721SpeterX#include <sys/types.h> 34117721SpeterX#include <sys/stat.h> 34217721SpeterX#include <dir.h> 34317721SpeterX 34417721SpeterX/* 34517721SpeterX * open a directory. 34617721SpeterX */ 34717721SpeterXDIR * 34817721SpeterXopendir(name) 34917721SpeterX char *name; 35017721SpeterX{ 35117721SpeterX register DIR *dirp; 35217721SpeterX register int fd; 35317721SpeterX struct stat statbuf; 35417721SpeterX char *malloc(); 35517721SpeterX 35617721SpeterX if ((fd = open(name, 0)) == -1) 35717721SpeterX return NULL; 35817721SpeterX if (fstat(fd, &statbuf) == -1 || !(statbuf.st_mode & S_IFDIR)) { 35917721SpeterX close(fd); 36017721SpeterX return NULL; 36117721SpeterX } 36217721SpeterX if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) { 36317721SpeterX close (fd); 36417721SpeterX return NULL; 36517721SpeterX } 36617721SpeterX dirp->dd_fd = fd; 36717721SpeterX dirp->dd_loc = 0; 36817721SpeterX dirp->dd_size = 0; /* so that telldir will work before readdir */ 36917721SpeterX return dirp; 37017721SpeterX} 37117721Speter! 37217721Speterecho 'readdir.c': 37317721Spetersed 's/^X//' >'readdir.c' <<'!' 37417721SpeterX/* Copyright (c) 1982 Regents of the University of California */ 37517721SpeterX 37617721SpeterXstatic char sccsid[] = "@(#)readdir.c 4.3 8/8/82"; 37717721SpeterX 37817721SpeterX#include <sys/types.h> 37917721SpeterX#include <dir.h> 38017721SpeterX 38117721SpeterX/* 38217721SpeterX * read an old stlye directory entry and present it as a new one 38317721SpeterX */ 38417721SpeterX#define ODIRSIZ 14 38517721SpeterX 38617721SpeterXstruct olddirect { 38717721SpeterX ino_t od_ino; 38817721SpeterX char od_name[ODIRSIZ]; 38917721SpeterX}; 39017721SpeterX 39117721SpeterX/* 39217721SpeterX * get next entry in a directory. 39317721SpeterX */ 39417721SpeterXstruct direct * 39517721SpeterXreaddir(dirp) 39617721SpeterX register DIR *dirp; 39717721SpeterX{ 39817721SpeterX register struct olddirect *dp; 39917721SpeterX static struct direct dir; 40017721SpeterX 40117721SpeterX for (;;) { 40217721SpeterX if (dirp->dd_loc == 0) { 40317721SpeterX dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 40417721SpeterX DIRBLKSIZ); 40517721SpeterX if (dirp->dd_size <= 0) { 40617721SpeterX dirp->dd_size = 0; 40717721SpeterX return NULL; 40817721SpeterX } 40917721SpeterX } 41017721SpeterX if (dirp->dd_loc >= dirp->dd_size) { 41117721SpeterX dirp->dd_loc = 0; 41217721SpeterX continue; 41317721SpeterX } 41417721SpeterX dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc); 41517721SpeterX dirp->dd_loc += sizeof(struct olddirect); 41617721SpeterX if (dp->od_ino == 0) 41717721SpeterX continue; 41817721SpeterX dir.d_ino = dp->od_ino; 41917721SpeterX strncpy(dir.d_name, dp->od_name, ODIRSIZ); 42017721SpeterX dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */ 42117721SpeterX dir.d_namlen = strlen(dir.d_name); 42217721SpeterX dir.d_reclen = DIRBLKSIZ; 42317721SpeterX return (&dir); 42417721SpeterX } 42517721SpeterX} 42617721Speter! 42717721Speterecho 'seekdir.c': 42817721Spetersed 's/^X//' >'seekdir.c' <<'!' 42917721SpeterXstatic char sccsid[] = "@(#)seekdir.c 4.9 3/25/83"; 43017721SpeterX 43117721SpeterX#include <sys/param.h> 43217721SpeterX#include <dir.h> 43317721SpeterX 43417721SpeterX/* 43517721SpeterX * seek to an entry in a directory. 43617721SpeterX * Only values returned by "telldir" should be passed to seekdir. 43717721SpeterX */ 43817721SpeterXvoid 43917721SpeterXseekdir(dirp, loc) 44017721SpeterX register DIR *dirp; 44117721SpeterX long loc; 44217721SpeterX{ 44317721SpeterX long curloc, base, offset; 44417721SpeterX struct direct *dp; 44517721SpeterX extern long lseek(); 44617721SpeterX 44717721SpeterX curloc = telldir(dirp); 44817721SpeterX if (loc == curloc) 44917721SpeterX return; 45017721SpeterX base = loc & ~(DIRBLKSIZ - 1); 45117721SpeterX offset = loc & (DIRBLKSIZ - 1); 45217721SpeterX (void) lseek(dirp->dd_fd, base, 0); 45317721SpeterX dirp->dd_size = 0; 45417721SpeterX dirp->dd_loc = 0; 45517721SpeterX while (dirp->dd_loc < offset) { 45617721SpeterX dp = readdir(dirp); 45717721SpeterX if (dp == NULL) 45817721SpeterX return; 45917721SpeterX } 46017721SpeterX} 46117721Speter! 46217721Speterecho 'telldir.c': 46317721Spetersed 's/^X//' >'telldir.c' <<'!' 46417721SpeterXstatic char sccsid[] = "@(#)telldir.c 4.1 2/21/82"; 46517721SpeterX 46617721SpeterX#include <sys/types.h> 46717721SpeterX#include <dir.h> 46817721SpeterX 46917721SpeterX/* 47017721SpeterX * return a pointer into a directory 47117721SpeterX */ 47217721SpeterXlong 47317721SpeterXtelldir(dirp) 47417721SpeterX DIR *dirp; 47517721SpeterX{ 47617721SpeterX long lseek(); 47717721SpeterX 47817721SpeterX return (lseek(dirp->dd_fd, 0L, 1) - dirp->dd_size + dirp->dd_loc); 47917721SpeterX} 48017721Speter! 48117721Speterecho done 482