merge latest bugfixes from MirBSD CVS
[alioth/cvs.git] / contrib / dirfns.shar
1 echo 'directory.3':
2 sed 's/^X//' >'directory.3' <<'!'
3 X.TH DIRECTORY 3 imported
4 X.DA 9 Oct 1985
5 X.SH NAME
6 Xopendir, readdir, telldir, seekdir, rewinddir, closedir \- high-level directory operations
7 X.SH SYNOPSIS
8 X.B #include <sys/types.h>
9 X.br
10 X.B #include <ndir.h>
11 X.PP
12 X.SM
13 X.B DIR
14 X.B *opendir(filename)
15 X.br
16 X.B char *filename;
17 X.PP
18 X.SM
19 X.B struct direct
20 X.B *readdir(dirp)
21 X.br
22 X.B DIR *dirp;
23 X.PP
24 X.SM
25 X.B long
26 X.B telldir(dirp)
27 X.br
28 X.B DIR *dirp;
29 X.PP
30 X.SM
31 X.B seekdir(dirp, loc)
32 X.br
33 X.B DIR *dirp;
34 X.br
35 X.B long loc;
36 X.PP
37 X.SM
38 X.B rewinddir(dirp)
39 X.br
40 X.B DIR *dirp;
41 X.PP
42 X.SM
43 X.B closedir(dirp)
44 X.br
45 X.B DIR *dirp;
46 X.SH DESCRIPTION
47 XThis library provides high-level primitives for directory scanning,
48 Xsimilar to those available for 4.2BSD's (very different) directory system.
49 X.\"The purpose of this library is to simulate
50 X.\"the new flexible length directory names of 4.2bsd UNIX
51 X.\"on top of the old directory structure of v7.
52 XIt incidentally provides easy portability to and from 4.2BSD (insofar
53 Xas such portability is not compromised by other 4.2/VAX dependencies).
54 X.\"It allows programs to be converted immediately
55 X.\"to the new directory access interface,
56 X.\"so that they need only be relinked
57 X.\"when moved to 4.2bsd.
58 X.\"It is obtained with the loader option
59 X.\".BR \-lndir .
60 X.PP
61 X.I Opendir
62 Xopens the directory named by
63 X.I filename
64 Xand associates a
65 X.I directory stream
66 Xwith it.
67 X.I Opendir
68 Xreturns a pointer to be used to identify the
69 X.I directory stream
70 Xin subsequent operations.
71 XThe pointer
72 X.SM
73 X.B NULL
74 Xis returned if
75 X.I filename
76 Xcannot be accessed or is not a directory.
77 X.PP
78 X.I Readdir
79 Xreturns a pointer to the next directory entry.
80 XIt returns
81 X.B NULL
82 Xupon reaching the end of the directory or detecting
83 Xan invalid
84 X.I seekdir
85 Xoperation.
86 X.PP
87 X.I Telldir
88 Xreturns the current location associated with the named
89 X.I directory stream.
90 X.PP
91 X.I Seekdir
92 Xsets the position of the next
93 X.I readdir
94 Xoperation on the
95 X.I directory stream.
96 XThe new position reverts to the one associated with the
97 X.I directory stream
98 Xwhen the
99 X.I telldir
100 Xoperation was performed.
101 XValues returned by
102 X.I telldir
103 Xare good only for the lifetime of the DIR pointer from 
104 Xwhich they are derived.
105 XIf the directory is closed and then reopened, 
106 Xthe 
107 X.I telldir
108 Xvalue may be invalidated
109 Xdue to undetected directory compaction in 4.2BSD.
110 XIt is safe to use a previous
111 X.I telldir
112 Xvalue immediately after a call to
113 X.I opendir
114 Xand before any calls to
115 X.I readdir.
116 X.PP
117 X.I Rewinddir
118 Xresets the position of the named
119 X.I directory stream
120 Xto the beginning of the directory.
121 X.PP
122 X.I Closedir
123 Xcauses the named
124 X.I directory stream
125 Xto be closed,
126 Xand the structure associated with the DIR pointer to be freed.
127 X.PP
128 XA
129 X.I direct
130 Xstructure is as follows:
131 X.PP
132 X.RS
133 X.nf
134 Xstruct direct {
135 X       /* unsigned */ long     d_ino;  /* inode number of entry */
136 X       unsigned short  d_reclen;       /* length of this record */
137 X       unsigned short  d_namlen;       /* length of string in d_name */
138 X       char    d_name[MAXNAMLEN + 1];  /* name must be no longer than this */
139 X};
140 X.fi
141 X.RE
142 X.PP
143 XThe
144 X.I d_reclen
145 Xfield is meaningless in non-4.2BSD systems and should be ignored.
146 XThe use of a
147 X.I long
148 Xfor
149 X.I d_ino
150 Xis also a 4.2BSDism;
151 X.I ino_t
152 X(see
153 X.IR types (5))
154 Xshould be used elsewhere.
155 XThe macro
156 X.I DIRSIZ(dp)
157 Xgives the minimum memory size needed to hold the
158 X.I direct
159 Xvalue pointed to by
160 X.IR dp ,
161 Xwith the minimum necessary allocation for
162 X.IR d_name .
163 X.PP
164 XThe preferred way to search the current directory for entry ``name'' is:
165 X.PP
166 X.RS
167 X.nf
168 X       len = strlen(name);
169 X       dirp = opendir(".");
170 X       if (dirp == NULL) {
171 X               fprintf(stderr, "%s: can't read directory .\\n", argv[0]);
172 X               return NOT_FOUND;
173 X       }
174 X       while ((dp = readdir(dirp)) != NULL)
175 X               if (dp->d_namlen == len && strcmp(dp->d_name, name) == 0) {
176 X                       closedir(dirp);
177 X                       return FOUND;
178 X               }
179 X       closedir(dirp);
180 X       return NOT_FOUND;
181 X.RE
182 X.\".SH LINKING
183 X.\"This library is accessed by specifying ``-lndir'' as the
184 X.\"last argument to the compile line, e.g.:
185 X.\".PP
186 X.\"    cc -I/usr/include/ndir -o prog prog.c -lndir
187 X.SH "SEE ALSO"
188 Xopen(2),
189 Xclose(2),
190 Xread(2),
191 Xlseek(2)
192 X.SH HISTORY
193 XWritten by
194 XKirk McKusick at Berkeley (ucbvax!mckusick).
195 XMiscellaneous bug fixes from elsewhere.
196 XThe size of the data structure has been decreased to avoid excessive
197 Xspace waste under V7 (where filenames are 14 characters at most).
198 XFor obscure historical reasons, the include file is also available
199 Xas
200 X.IR <ndir/sys/dir.h> .
201 XThe Berkeley version lived in a separate library (\fI\-lndir\fR),
202 Xwhereas ours is
203 Xpart of the C library, although the separate library is retained to
204 Xmaximize compatibility.
205 X.PP
206 XThis manual page has been substantially rewritten to be informative in
207 Xthe absence of a 4.2BSD manual.
208 X.SH BUGS
209 XThe
210 X.I DIRSIZ
211 Xmacro actually wastes a bit of space due to some padding requirements
212 Xthat are an artifact of 4.2BSD.
213 X.PP
214 XThe returned value of
215 X.I readdir
216 Xpoints to a static area that will be overwritten by subsequent calls.
217 X.PP
218 XThere are some unfortunate name conflicts with the \fIreal\fR V7
219 Xdirectory structure definitions.
220 !
221 echo 'dir.h':
222 sed 's/^X//' >'dir.h' <<'!'
223 X/*     dir.h   4.4     82/07/25        */
224 X
225 X/*
226 X * A directory consists of some number of blocks of DIRBLKSIZ
227 X * bytes, where DIRBLKSIZ is chosen such that it can be transferred
228 X * to disk in a single atomic operation (e.g. 512 bytes on most machines).
229 X *
230 X * Each DIRBLKSIZ byte block contains some number of directory entry
231 X * structures, which are of variable length.  Each directory entry has
232 X * a struct direct at the front of it, containing its inode number,
233 X * the length of the entry, and the length of the name contained in
234 X * the entry.  These are followed by the name padded to a 4 byte boundary
235 X * with null bytes.  All names are guaranteed null terminated.
236 X * The maximum length of a name in a directory is MAXNAMLEN.
237 X *
238 X * The macro DIRSIZ(dp) gives the amount of space required to represent
239 X * a directory entry.  Free space in a directory is represented by
240 X * entries which have dp->d_reclen >= DIRSIZ(dp).  All DIRBLKSIZ bytes
241 X * in a directory block are claimed by the directory entries.  This
242 X * usually results in the last entry in a directory having a large
243 X * dp->d_reclen.  When entries are deleted from a directory, the
244 X * space is returned to the previous entry in the same directory
245 X * block by increasing its dp->d_reclen.  If the first entry of
246 X * a directory block is free, then its dp->d_ino is set to 0.
247 X * Entries other than the first in a directory do not normally have
248 X * dp->d_ino set to 0.
249 X */
250 X#define DIRBLKSIZ      512
251 X#ifdef VMUNIX
252 X#define        MAXNAMLEN       255
253 X#else
254 X#define        MAXNAMLEN       14
255 X#endif
256 X
257 Xstruct direct {
258 X       /* unsigned */ long     d_ino;  /* inode number of entry */
259 X       unsigned short  d_reclen;       /* length of this record */
260 X       unsigned short  d_namlen;       /* length of string in d_name */
261 X       char    d_name[MAXNAMLEN + 1];  /* name must be no longer than this */
262 X};
263 X
264 X/*
265 X * The DIRSIZ macro gives the minimum record length which will hold
266 X * the directory entry.  This requires the amount of space in struct direct
267 X * without the d_name field, plus enough space for the name with a terminating
268 X * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
269 X */
270 X#undef DIRSIZ
271 X#define DIRSIZ(dp) \
272 X    ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
273 X
274 X#ifndef KERNEL
275 X/*
276 X * Definitions for library routines operating on directories.
277 X */
278 Xtypedef struct _dirdesc {
279 X       int     dd_fd;
280 X       long    dd_loc;
281 X       long    dd_size;
282 X       char    dd_buf[DIRBLKSIZ];
283 X} DIR;
284 X#ifndef NULL
285 X#define NULL 0
286 X#endif
287 Xextern DIR *opendir();
288 Xextern struct direct *readdir();
289 Xextern long telldir();
290 X#ifdef void
291 Xextern void seekdir();
292 Xextern void closedir();
293 X#endif
294 X#define rewinddir(dirp)        seekdir((dirp), (long)0)
295 X#endif KERNEL
296 !
297 echo 'makefile':
298 sed 's/^X//' >'makefile' <<'!'
299 XDIR = closedir.o opendir.o readdir.o seekdir.o telldir.o
300 XCFLAGS=-O -I. -Dvoid=int
301 XDEST=..
302 X
303 Xall:   $(DIR)
304 X
305 Xmv:    $(DIR)
306 X       mv $(DIR) $(DEST)
307 X
308 Xcpif:  dir.h
309 X       cp dir.h /usr/include/ndir.h
310 X
311 Xclean:
312 X       rm -f *.o
313 !
314 echo 'closedir.c':
315 sed 's/^X//' >'closedir.c' <<'!'
316 Xstatic char sccsid[] = "@(#)closedir.c 4.2 3/10/82";
317 X
318 X#include <sys/types.h>
319 X#include <dir.h>
320 X
321 X/*
322 X * close a directory.
323 X */
324 Xvoid
325 Xclosedir(dirp)
326 X       register DIR *dirp;
327 X{
328 X       close(dirp->dd_fd);
329 X       dirp->dd_fd = -1;
330 X       dirp->dd_loc = 0;
331 X       free((char *)dirp);
332 X}
333 !
334 echo 'opendir.c':
335 sed 's/^X//' >'opendir.c' <<'!'
336 X/* Copyright (c) 1982 Regents of the University of California */
337 X
338 Xstatic char sccsid[] = "@(#)opendir.c 4.4 11/12/82";
339 X
340 X#include <sys/types.h>
341 X#include <sys/stat.h>
342 X#include <dir.h>
343 X
344 X/*
345 X * open a directory.
346 X */
347 XDIR *
348 Xopendir(name)
349 X       char *name;
350 X{
351 X       register DIR *dirp;
352 X       register int fd;
353 X       struct stat statbuf;
354 X       char *malloc();
355 X
356 X       if ((fd = open(name, 0)) == -1)
357 X               return NULL;
358 X       if (fstat(fd, &statbuf) == -1 || !(statbuf.st_mode & S_IFDIR)) {
359 X               close(fd);
360 X               return NULL;
361 X       }
362 X       if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
363 X               close (fd);
364 X               return NULL;
365 X       }
366 X       dirp->dd_fd = fd;
367 X       dirp->dd_loc = 0;
368 X       dirp->dd_size = 0;      /* so that telldir will work before readdir */
369 X       return dirp;
370 X}
371 !
372 echo 'readdir.c':
373 sed 's/^X//' >'readdir.c' <<'!'
374 X/* Copyright (c) 1982 Regents of the University of California */
375 X
376 Xstatic char sccsid[] = "@(#)readdir.c 4.3 8/8/82";
377 X
378 X#include <sys/types.h>
379 X#include <dir.h>
380 X
381 X/*
382 X * read an old stlye directory entry and present it as a new one
383 X */
384 X#define        ODIRSIZ 14
385 X
386 Xstruct olddirect {
387 X       ino_t   od_ino;
388 X       char    od_name[ODIRSIZ];
389 X};
390 X
391 X/*
392 X * get next entry in a directory.
393 X */
394 Xstruct direct *
395 Xreaddir(dirp)
396 X       register DIR *dirp;
397 X{
398 X       register struct olddirect *dp;
399 X       static struct direct dir;
400 X
401 X       for (;;) {
402 X               if (dirp->dd_loc == 0) {
403 X                       dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 
404 X                           DIRBLKSIZ);
405 X                       if (dirp->dd_size <= 0) {
406 X                               dirp->dd_size = 0;
407 X                               return NULL;
408 X                       }
409 X               }
410 X               if (dirp->dd_loc >= dirp->dd_size) {
411 X                       dirp->dd_loc = 0;
412 X                       continue;
413 X               }
414 X               dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc);
415 X               dirp->dd_loc += sizeof(struct olddirect);
416 X               if (dp->od_ino == 0)
417 X                       continue;
418 X               dir.d_ino = dp->od_ino;
419 X               strncpy(dir.d_name, dp->od_name, ODIRSIZ);
420 X               dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */
421 X               dir.d_namlen = strlen(dir.d_name);
422 X               dir.d_reclen = DIRBLKSIZ;
423 X               return (&dir);
424 X       }
425 X}
426 !
427 echo 'seekdir.c':
428 sed 's/^X//' >'seekdir.c' <<'!'
429 Xstatic char sccsid[] = "@(#)seekdir.c 4.9 3/25/83";
430 X
431 X#include <sys/param.h>
432 X#include <dir.h>
433 X
434 X/*
435 X * seek to an entry in a directory.
436 X * Only values returned by "telldir" should be passed to seekdir.
437 X */
438 Xvoid
439 Xseekdir(dirp, loc)
440 X       register DIR *dirp;
441 X       long loc;
442 X{
443 X       long curloc, base, offset;
444 X       struct direct *dp;
445 X       extern long lseek();
446 X
447 X       curloc = telldir(dirp);
448 X       if (loc == curloc)
449 X               return;
450 X       base = loc & ~(DIRBLKSIZ - 1);
451 X       offset = loc & (DIRBLKSIZ - 1);
452 X       (void) lseek(dirp->dd_fd, base, 0);
453 X       dirp->dd_size = 0;
454 X       dirp->dd_loc = 0;
455 X       while (dirp->dd_loc < offset) {
456 X               dp = readdir(dirp);
457 X               if (dp == NULL)
458 X                       return;
459 X       }
460 X}
461 !
462 echo 'telldir.c':
463 sed 's/^X//' >'telldir.c' <<'!'
464 Xstatic char sccsid[] = "@(#)telldir.c 4.1 2/21/82";
465 X
466 X#include <sys/types.h>
467 X#include <dir.h>
468 X
469 X/*
470 X * return a pointer into a directory
471 X */
472 Xlong
473 Xtelldir(dirp)
474 X       DIR *dirp;
475 X{
476 X       long lseek();
477 X
478 X       return (lseek(dirp->dd_fd, 0L, 1) - dirp->dd_size + dirp->dd_loc);
479 X}
480 !
481 echo done