remove last vestige of AT&T code; it was really gone long ago
[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 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
bb0cfa24
DF
16 */
17
2ce81398 18#if defined(LIBC_SCCS) && !defined(lint)
d109757d 19static char sccsid[] = "@(#)telldir.c 5.6 (Berkeley) %G%";
d99e6414 20#endif /* LIBC_SCCS and not lint */
d0ecd57b 21
c4a04593 22#include <sys/param.h>
8c6e64bc 23#include <dirent.h>
d0ecd57b 24
d109757d
KM
25/*
26 * The option SINGLEUSE may be defined to say that a telldir
27 * cookie may be used only once before it is freed. This option
28 * is used to avoid having memory usage grow without bound.
29 */
30#define SINGLEUSE
31
32/*
33 * One of these structures is malloced to describe the current directory
34 * position each time telldir is called. It records the current magic
35 * cookie returned by getdirentries and the offset within the buffer
36 * associated with that return value.
37 */
38struct ddloc {
39 struct ddloc *loc_next;/* next structure in list */
40 long loc_index; /* key associated with structure */
41 long loc_seek; /* magic cookie returned by getdirentries */
42 long loc_loc; /* offset of entry in buffer */
43};
44
45#define NDIRHASH 32 /* Num of hash lists, must be a power of 2 */
46#define LOCHASH(i) ((i)&(NDIRHASH-1))
47
48static long dd_loccnt; /* Index of entry for sequential readdir's */
49static struct ddloc *dd_hash[NDIRHASH]; /* Hash list heads for ddlocs */
50
d0ecd57b
KM
51/*
52 * return a pointer into a directory
53 */
54long
55telldir(dirp)
56 DIR *dirp;
57{
d46abbe3
KM
58 register int index;
59 register struct ddloc *lp;
55e81f97 60
d46abbe3
KM
61 if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
62 return (-1);
d109757d 63 index = dd_loccnt++;
d46abbe3
KM
64 lp->loc_index = index;
65 lp->loc_seek = dirp->dd_seek;
66 lp->loc_loc = dirp->dd_loc;
d109757d
KM
67 lp->loc_next = dd_hash[LOCHASH(index)];
68 dd_hash[LOCHASH(index)] = lp;
d46abbe3 69 return (index);
d0ecd57b 70}
d109757d
KM
71
72/*
73 * seek to an entry in a directory.
74 * Only values returned by "telldir" should be passed to seekdir.
75 */
76void
77_seekdir(dirp, loc)
78 register DIR *dirp;
79 long loc;
80{
81 register struct ddloc *lp;
82 register struct ddloc **prevlp;
83 struct dirent *dp;
84 extern long lseek();
85
86 prevlp = &dd_hash[LOCHASH(loc)];
87 lp = *prevlp;
88 while (lp != NULL) {
89 if (lp->loc_index == loc)
90 break;
91 prevlp = &lp->loc_next;
92 lp = lp->loc_next;
93 }
94 if (lp == NULL)
95 return;
96 if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek)
97 goto found;
98 (void) lseek(dirp->dd_fd, lp->loc_seek, 0);
99 dirp->dd_loc = 0;
100 while (dirp->dd_loc < lp->loc_loc) {
101 dp = readdir(dirp);
102 if (dp == NULL)
103 break;
104 }
105found:
106#ifdef SINGLEUSE
107 *prevlp = lp->loc_next;
108 free((caddr_t)lp);
109#endif
110}