Commit | Line | Data |
---|---|---|
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 | 19 | static 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 | */ | |
38 | struct 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 | ||
48 | static long dd_loccnt; /* Index of entry for sequential readdir's */ | |
49 | static struct ddloc *dd_hash[NDIRHASH]; /* Hash list heads for ddlocs */ | |
50 | ||
d0ecd57b KM |
51 | /* |
52 | * return a pointer into a directory | |
53 | */ | |
54 | long | |
55 | telldir(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 | */ | |
76 | void | |
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 | } | |
105 | found: | |
106 | #ifdef SINGLEUSE | |
107 | *prevlp = lp->loc_next; | |
108 | free((caddr_t)lp); | |
109 | #endif | |
110 | } |