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