new copyright notice
[unix-history] / usr / src / lib / libc / gen / telldir.c
CommitLineData
bb0cfa24
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
d99e6414
KB
3 * All rights reserved.
4 *
269a7923 5 * %sccs.include.redist.c%
bb0cfa24
DF
6 */
7
2ce81398 8#if defined(LIBC_SCCS) && !defined(lint)
269a7923 9static char sccsid[] = "@(#)telldir.c 5.8 (Berkeley) %G%";
d99e6414 10#endif /* LIBC_SCCS and not lint */
d0ecd57b 11
c4a04593 12#include <sys/param.h>
8c6e64bc 13#include <dirent.h>
d0ecd57b 14
d109757d
KM
15/*
16 * The option SINGLEUSE may be defined to say that a telldir
17 * cookie may be used only once before it is freed. This option
18 * is used to avoid having memory usage grow without bound.
19 */
20#define SINGLEUSE
21
22/*
23 * One of these structures is malloced to describe the current directory
24 * position each time telldir is called. It records the current magic
25 * cookie returned by getdirentries and the offset within the buffer
26 * associated with that return value.
27 */
28struct ddloc {
29 struct ddloc *loc_next;/* next structure in list */
30 long loc_index; /* key associated with structure */
31 long loc_seek; /* magic cookie returned by getdirentries */
32 long loc_loc; /* offset of entry in buffer */
33};
34
35#define NDIRHASH 32 /* Num of hash lists, must be a power of 2 */
36#define LOCHASH(i) ((i)&(NDIRHASH-1))
37
38static long dd_loccnt; /* Index of entry for sequential readdir's */
39static struct ddloc *dd_hash[NDIRHASH]; /* Hash list heads for ddlocs */
40
d0ecd57b
KM
41/*
42 * return a pointer into a directory
43 */
44long
45telldir(dirp)
46 DIR *dirp;
47{
d46abbe3
KM
48 register int index;
49 register struct ddloc *lp;
55e81f97 50
d46abbe3
KM
51 if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
52 return (-1);
d109757d 53 index = dd_loccnt++;
d46abbe3
KM
54 lp->loc_index = index;
55 lp->loc_seek = dirp->dd_seek;
56 lp->loc_loc = dirp->dd_loc;
d109757d
KM
57 lp->loc_next = dd_hash[LOCHASH(index)];
58 dd_hash[LOCHASH(index)] = lp;
d46abbe3 59 return (index);
d0ecd57b 60}
d109757d
KM
61
62/*
63 * seek to an entry in a directory.
64 * Only values returned by "telldir" should be passed to seekdir.
65 */
66void
67_seekdir(dirp, loc)
68 register DIR *dirp;
69 long loc;
70{
71 register struct ddloc *lp;
72 register struct ddloc **prevlp;
73 struct dirent *dp;
74 extern long lseek();
75
76 prevlp = &dd_hash[LOCHASH(loc)];
77 lp = *prevlp;
78 while (lp != NULL) {
79 if (lp->loc_index == loc)
80 break;
81 prevlp = &lp->loc_next;
82 lp = lp->loc_next;
83 }
84 if (lp == NULL)
85 return;
86 if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek)
87 goto found;
88 (void) lseek(dirp->dd_fd, lp->loc_seek, 0);
b3594ef4 89 dirp->dd_seek = lp->loc_seek;
d109757d
KM
90 dirp->dd_loc = 0;
91 while (dirp->dd_loc < lp->loc_loc) {
92 dp = readdir(dirp);
93 if (dp == NULL)
94 break;
95 }
96found:
97#ifdef SINGLEUSE
98 *prevlp = lp->loc_next;
99 free((caddr_t)lp);
100#endif
101}