482 lines
11 KiB
Plaintext
482 lines
11 KiB
Plaintext
echo 'directory.3':
|
|
sed 's/^X//' >'directory.3' <<'!'
|
|
X.TH DIRECTORY 3 imported
|
|
X.DA 9 Oct 1985
|
|
X.SH NAME
|
|
Xopendir, readdir, telldir, seekdir, rewinddir, closedir \- high-level directory operations
|
|
X.SH SYNOPSIS
|
|
X.B #include <sys/types.h>
|
|
X.br
|
|
X.B #include <ndir.h>
|
|
X.PP
|
|
X.SM
|
|
X.B DIR
|
|
X.B *opendir(filename)
|
|
X.br
|
|
X.B char *filename;
|
|
X.PP
|
|
X.SM
|
|
X.B struct direct
|
|
X.B *readdir(dirp)
|
|
X.br
|
|
X.B DIR *dirp;
|
|
X.PP
|
|
X.SM
|
|
X.B long
|
|
X.B telldir(dirp)
|
|
X.br
|
|
X.B DIR *dirp;
|
|
X.PP
|
|
X.SM
|
|
X.B seekdir(dirp, loc)
|
|
X.br
|
|
X.B DIR *dirp;
|
|
X.br
|
|
X.B long loc;
|
|
X.PP
|
|
X.SM
|
|
X.B rewinddir(dirp)
|
|
X.br
|
|
X.B DIR *dirp;
|
|
X.PP
|
|
X.SM
|
|
X.B closedir(dirp)
|
|
X.br
|
|
X.B DIR *dirp;
|
|
X.SH DESCRIPTION
|
|
XThis library provides high-level primitives for directory scanning,
|
|
Xsimilar to those available for 4.2BSD's (very different) directory system.
|
|
X.\"The purpose of this library is to simulate
|
|
X.\"the new flexible length directory names of 4.2bsd UNIX
|
|
X.\"on top of the old directory structure of v7.
|
|
XIt incidentally provides easy portability to and from 4.2BSD (insofar
|
|
Xas such portability is not compromised by other 4.2/VAX dependencies).
|
|
X.\"It allows programs to be converted immediately
|
|
X.\"to the new directory access interface,
|
|
X.\"so that they need only be relinked
|
|
X.\"when moved to 4.2bsd.
|
|
X.\"It is obtained with the loader option
|
|
X.\".BR \-lndir .
|
|
X.PP
|
|
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.
|
|
X.PP
|
|
X.I Readdir
|
|
Xreturns a pointer to the next directory entry.
|
|
XIt returns
|
|
X.B NULL
|
|
Xupon reaching the end of the directory or detecting
|
|
Xan 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 was performed.
|
|
XValues returned by
|
|
X.I telldir
|
|
Xare good only for the lifetime of the DIR pointer from
|
|
Xwhich they are derived.
|
|
XIf the directory is closed and then reopened,
|
|
Xthe
|
|
X.I telldir
|
|
Xvalue may be invalidated
|
|
Xdue to undetected directory compaction in 4.2BSD.
|
|
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
|
|
Xcauses the named
|
|
X.I directory stream
|
|
Xto be closed,
|
|
Xand the structure associated with the DIR pointer to be freed.
|
|
X.PP
|
|
XA
|
|
X.I direct
|
|
Xstructure is as follows:
|
|
X.PP
|
|
X.RS
|
|
X.nf
|
|
Xstruct direct {
|
|
X /* unsigned */ 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 must be no longer than this */
|
|
X};
|
|
X.fi
|
|
X.RE
|
|
X.PP
|
|
XThe
|
|
X.I d_reclen
|
|
Xfield is meaningless in non-4.2BSD systems and should be ignored.
|
|
XThe use of a
|
|
X.I long
|
|
Xfor
|
|
X.I d_ino
|
|
Xis also a 4.2BSDism;
|
|
X.I ino_t
|
|
X(see
|
|
X.IR types (5))
|
|
Xshould be used elsewhere.
|
|
XThe macro
|
|
X.I DIRSIZ(dp)
|
|
Xgives the minimum memory size needed to hold the
|
|
X.I direct
|
|
Xvalue pointed to by
|
|
X.IR dp ,
|
|
Xwith the minimum necessary allocation for
|
|
X.IR d_name .
|
|
X.PP
|
|
XThe preferred way to search the current directory for entry ``name'' is:
|
|
X.PP
|
|
X.RS
|
|
X.nf
|
|
X len = strlen(name);
|
|
X dirp = opendir(".");
|
|
X if (dirp == NULL) {
|
|
X fprintf(stderr, "%s: can't read directory .\\n", argv[0]);
|
|
X return NOT_FOUND;
|
|
X }
|
|
X while ((dp = readdir(dirp)) != NULL)
|
|
X if (dp->d_namlen == len && strcmp(dp->d_name, name) == 0) {
|
|
X closedir(dirp);
|
|
X return FOUND;
|
|
X }
|
|
X closedir(dirp);
|
|
X return NOT_FOUND;
|
|
X.RE
|
|
X.\".SH LINKING
|
|
X.\"This library is accessed by specifying ``-lndir'' as the
|
|
X.\"last argument to the compile line, e.g.:
|
|
X.\".PP
|
|
X.\" cc -I/usr/include/ndir -o prog prog.c -lndir
|
|
X.SH "SEE ALSO"
|
|
Xopen(2),
|
|
Xclose(2),
|
|
Xread(2),
|
|
Xlseek(2)
|
|
X.SH HISTORY
|
|
XWritten by
|
|
XKirk McKusick at Berkeley (ucbvax!mckusick).
|
|
XMiscellaneous bug fixes from elsewhere.
|
|
XThe size of the data structure has been decreased to avoid excessive
|
|
Xspace waste under V7 (where filenames are 14 characters at most).
|
|
XFor obscure historical reasons, the include file is also available
|
|
Xas
|
|
X.IR <ndir/sys/dir.h> .
|
|
XThe Berkeley version lived in a separate library (\fI\-lndir\fR),
|
|
Xwhereas ours is
|
|
Xpart of the C library, although the separate library is retained to
|
|
Xmaximize compatibility.
|
|
X.PP
|
|
XThis manual page has been substantially rewritten to be informative in
|
|
Xthe absence of a 4.2BSD manual.
|
|
X.SH BUGS
|
|
XThe
|
|
X.I DIRSIZ
|
|
Xmacro actually wastes a bit of space due to some padding requirements
|
|
Xthat are an artifact of 4.2BSD.
|
|
X.PP
|
|
XThe returned value of
|
|
X.I readdir
|
|
Xpoints to a static area that will be overwritten by subsequent calls.
|
|
X.PP
|
|
XThere are some unfortunate name conflicts with the \fIreal\fR V7
|
|
Xdirectory structure definitions.
|
|
!
|
|
echo 'dir.h':
|
|
sed 's/^X//' >'dir.h' <<'!'
|
|
X/* dir.h 4.4 82/07/25 */
|
|
X
|
|
X/*
|
|
X * A directory consists of some number of blocks of DIRBLKSIZ
|
|
X * bytes, where DIRBLKSIZ is chosen such that it can be transferred
|
|
X * to disk in a single atomic operation (e.g. 512 bytes on most machines).
|
|
X *
|
|
X * Each DIRBLKSIZ byte block contains some number of directory entry
|
|
X * structures, which are of variable length. Each directory entry has
|
|
X * a struct direct at the front of it, containing its inode number,
|
|
X * the length of the entry, and the length of the name contained in
|
|
X * the entry. These are followed by the name padded to a 4 byte boundary
|
|
X * with null bytes. All names are guaranteed null terminated.
|
|
X * The maximum length of a name in a directory is MAXNAMLEN.
|
|
X *
|
|
X * The macro DIRSIZ(dp) gives the amount of space required to represent
|
|
X * a directory entry. Free space in a directory is represented by
|
|
X * entries which have dp->d_reclen >= DIRSIZ(dp). All DIRBLKSIZ bytes
|
|
X * in a directory block are claimed by the directory entries. This
|
|
X * usually results in the last entry in a directory having a large
|
|
X * dp->d_reclen. When entries are deleted from a directory, the
|
|
X * space is returned to the previous entry in the same directory
|
|
X * block by increasing its dp->d_reclen. If the first entry of
|
|
X * a directory block is free, then its dp->d_ino is set to 0.
|
|
X * Entries other than the first in a directory do not normally have
|
|
X * dp->d_ino set to 0.
|
|
X */
|
|
X#define DIRBLKSIZ 512
|
|
X#ifdef VMUNIX
|
|
X#define MAXNAMLEN 255
|
|
X#else
|
|
X#define MAXNAMLEN 14
|
|
X#endif
|
|
X
|
|
Xstruct direct {
|
|
X /* unsigned */ 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 must be no longer than this */
|
|
X};
|
|
X
|
|
X/*
|
|
X * The DIRSIZ macro gives the minimum record length which will hold
|
|
X * the directory entry. This requires the amount of space in struct direct
|
|
X * without the d_name field, plus enough space for the name with a terminating
|
|
X * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
|
|
X */
|
|
X#undef DIRSIZ
|
|
X#define DIRSIZ(dp) \
|
|
X ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
|
|
X
|
|
X#ifndef KERNEL
|
|
X/*
|
|
X * Definitions for library routines operating on directories.
|
|
X */
|
|
Xtypedef struct _dirdesc {
|
|
X int dd_fd;
|
|
X long dd_loc;
|
|
X long dd_size;
|
|
X char dd_buf[DIRBLKSIZ];
|
|
X} DIR;
|
|
X#ifndef NULL
|
|
X#define NULL 0
|
|
X#endif
|
|
Xextern DIR *opendir();
|
|
Xextern struct direct *readdir();
|
|
Xextern long telldir();
|
|
X#ifdef void
|
|
Xextern void seekdir();
|
|
Xextern void closedir();
|
|
X#endif
|
|
X#define rewinddir(dirp) seekdir((dirp), (long)0)
|
|
X#endif KERNEL
|
|
!
|
|
echo 'makefile':
|
|
sed 's/^X//' >'makefile' <<'!'
|
|
XDIR = closedir.o opendir.o readdir.o seekdir.o telldir.o
|
|
XCFLAGS=-O -I. -Dvoid=int
|
|
XDEST=..
|
|
X
|
|
Xall: $(DIR)
|
|
X
|
|
Xmv: $(DIR)
|
|
X mv $(DIR) $(DEST)
|
|
X
|
|
Xcpif: dir.h
|
|
X cp dir.h /usr/include/ndir.h
|
|
X
|
|
Xclean:
|
|
X rm -f *.o
|
|
!
|
|
echo 'closedir.c':
|
|
sed 's/^X//' >'closedir.c' <<'!'
|
|
Xstatic char sccsid[] = "@(#)closedir.c 4.2 3/10/82";
|
|
X
|
|
X#include <sys/types.h>
|
|
X#include <dir.h>
|
|
X
|
|
X/*
|
|
X * close a directory.
|
|
X */
|
|
Xvoid
|
|
Xclosedir(dirp)
|
|
X register DIR *dirp;
|
|
X{
|
|
X close(dirp->dd_fd);
|
|
X dirp->dd_fd = -1;
|
|
X dirp->dd_loc = 0;
|
|
X free((char *)dirp);
|
|
X}
|
|
!
|
|
echo 'opendir.c':
|
|
sed 's/^X//' >'opendir.c' <<'!'
|
|
X/* Copyright (c) 1982 Regents of the University of California */
|
|
X
|
|
Xstatic char sccsid[] = "@(#)opendir.c 4.4 11/12/82";
|
|
X
|
|
X#include <sys/types.h>
|
|
X#include <sys/stat.h>
|
|
X#include <dir.h>
|
|
X
|
|
X/*
|
|
X * open a directory.
|
|
X */
|
|
XDIR *
|
|
Xopendir(name)
|
|
X char *name;
|
|
X{
|
|
X register DIR *dirp;
|
|
X register int fd;
|
|
X struct stat statbuf;
|
|
X char *malloc();
|
|
X
|
|
X if ((fd = open(name, 0)) == -1)
|
|
X return NULL;
|
|
X if (fstat(fd, &statbuf) == -1 || !(statbuf.st_mode & S_IFDIR)) {
|
|
X close(fd);
|
|
X return NULL;
|
|
X }
|
|
X if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
|
|
X close (fd);
|
|
X return NULL;
|
|
X }
|
|
X dirp->dd_fd = fd;
|
|
X dirp->dd_loc = 0;
|
|
X dirp->dd_size = 0; /* so that telldir will work before readdir */
|
|
X return dirp;
|
|
X}
|
|
!
|
|
echo 'readdir.c':
|
|
sed 's/^X//' >'readdir.c' <<'!'
|
|
X/* Copyright (c) 1982 Regents of the University of California */
|
|
X
|
|
Xstatic char sccsid[] = "@(#)readdir.c 4.3 8/8/82";
|
|
X
|
|
X#include <sys/types.h>
|
|
X#include <dir.h>
|
|
X
|
|
X/*
|
|
X * read an old stlye directory entry and present it as a new one
|
|
X */
|
|
X#define ODIRSIZ 14
|
|
X
|
|
Xstruct olddirect {
|
|
X ino_t od_ino;
|
|
X char od_name[ODIRSIZ];
|
|
X};
|
|
X
|
|
X/*
|
|
X * get next entry in a directory.
|
|
X */
|
|
Xstruct direct *
|
|
Xreaddir(dirp)
|
|
X register DIR *dirp;
|
|
X{
|
|
X register struct olddirect *dp;
|
|
X static struct direct dir;
|
|
X
|
|
X for (;;) {
|
|
X if (dirp->dd_loc == 0) {
|
|
X dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
|
|
X DIRBLKSIZ);
|
|
X if (dirp->dd_size <= 0) {
|
|
X dirp->dd_size = 0;
|
|
X return NULL;
|
|
X }
|
|
X }
|
|
X if (dirp->dd_loc >= dirp->dd_size) {
|
|
X dirp->dd_loc = 0;
|
|
X continue;
|
|
X }
|
|
X dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc);
|
|
X dirp->dd_loc += sizeof(struct olddirect);
|
|
X if (dp->od_ino == 0)
|
|
X continue;
|
|
X dir.d_ino = dp->od_ino;
|
|
X strncpy(dir.d_name, dp->od_name, ODIRSIZ);
|
|
X dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */
|
|
X dir.d_namlen = strlen(dir.d_name);
|
|
X dir.d_reclen = DIRBLKSIZ;
|
|
X return (&dir);
|
|
X }
|
|
X}
|
|
!
|
|
echo 'seekdir.c':
|
|
sed 's/^X//' >'seekdir.c' <<'!'
|
|
Xstatic char sccsid[] = "@(#)seekdir.c 4.9 3/25/83";
|
|
X
|
|
X#include <sys/param.h>
|
|
X#include <dir.h>
|
|
X
|
|
X/*
|
|
X * seek to an entry in a directory.
|
|
X * Only values returned by "telldir" should be passed to seekdir.
|
|
X */
|
|
Xvoid
|
|
Xseekdir(dirp, loc)
|
|
X register DIR *dirp;
|
|
X long loc;
|
|
X{
|
|
X long curloc, base, offset;
|
|
X struct direct *dp;
|
|
X extern long lseek();
|
|
X
|
|
X curloc = telldir(dirp);
|
|
X if (loc == curloc)
|
|
X return;
|
|
X base = loc & ~(DIRBLKSIZ - 1);
|
|
X offset = loc & (DIRBLKSIZ - 1);
|
|
X (void) lseek(dirp->dd_fd, base, 0);
|
|
X dirp->dd_size = 0;
|
|
X dirp->dd_loc = 0;
|
|
X while (dirp->dd_loc < offset) {
|
|
X dp = readdir(dirp);
|
|
X if (dp == NULL)
|
|
X return;
|
|
X }
|
|
X}
|
|
!
|
|
echo 'telldir.c':
|
|
sed 's/^X//' >'telldir.c' <<'!'
|
|
Xstatic char sccsid[] = "@(#)telldir.c 4.1 2/21/82";
|
|
X
|
|
X#include <sys/types.h>
|
|
X#include <dir.h>
|
|
X
|
|
X/*
|
|
X * return a pointer into a directory
|
|
X */
|
|
Xlong
|
|
Xtelldir(dirp)
|
|
X DIR *dirp;
|
|
X{
|
|
X long lseek();
|
|
X
|
|
X return (lseek(dirp->dd_fd, 0L, 1) - dirp->dd_size + dirp->dd_loc);
|
|
X}
|
|
!
|
|
echo done
|