source: trunk/libs/newlib/src/newlib/libc/posix/telldir.c @ 543

Last change on this file since 543 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 5.8 KB
Line 
1#ifndef HAVE_OPENDIR
2
3/*
4 * Copyright (c) 1983 Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *      This product includes software developed by the University of
18 *      California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37static char sccsid[] = "@(#)telldir.c   5.9 (Berkeley) 2/23/91";
38#endif /* LIBC_SCCS and not lint */
39
40#include <sys/param.h>
41#include <dirent.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <sys/lock.h>
45
46/*
47 * The option SINGLEUSE may be defined to say that a telldir
48 * cookie may be used only once before it is freed. This option
49 * is used to avoid having memory usage grow without bound.
50 */
51#define SINGLEUSE
52
53/*
54 * One of these structures is malloced to describe the current directory
55 * position each time telldir is called. It records the current magic
56 * cookie returned by getdirentries and the offset within the buffer
57 * associated with that return value.
58 */
59struct ddloc {
60        struct  ddloc *loc_next;/* next structure in list */
61        long    loc_index;      /* key associated with structure */
62        long    loc_seek;       /* magic cookie returned by getdirentries */
63        long    loc_loc;        /* offset of entry in buffer */
64        DIR    *loc_dirp;       /* DIR pointer */
65};
66
67#define NDIRHASH        32      /* Num of hash lists, must be a power of 2 */
68#define LOCHASH(i)      ((i)&(NDIRHASH-1))
69
70static long     dd_loccnt = 1;  /* Index of entry for sequential readdir's */
71static struct   ddloc *dd_hash[NDIRHASH];   /* Hash list heads for ddlocs */
72
73#if !defined(__SINGLE_THREAD__) && defined(HAVE_DD_LOCK)
74__LOCK_INIT(static, __dd_hash_mutex);
75#endif
76
77/*
78 * return a pointer into a directory
79 */
80
81#if !defined(_ELIX_LEVEL) || (_ELIX_LEVEL >= 2)
82
83long
84telldir (DIR *dirp)
85{
86        register int index;
87        register struct ddloc *lp;
88
89        if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
90                return (-1);
91
92#ifdef HAVE_DD_LOCK
93        __lock_acquire_recursive(dirp->dd_lock);
94#ifndef __SINGLE_THREAD__
95        __lock_acquire(__dd_hash_mutex);
96#endif
97#endif
98        index = dd_loccnt++;
99        lp->loc_index = index;
100        lp->loc_seek = dirp->dd_seek;
101        lp->loc_loc = dirp->dd_loc;
102        lp->loc_dirp = dirp;
103        lp->loc_next = dd_hash[LOCHASH(index)];
104        dd_hash[LOCHASH(index)] = lp;
105#ifdef HAVE_DD_LOCK
106#ifndef __SINGLE_THREAD__
107        __lock_release(__dd_hash_mutex);
108#endif
109        __lock_release_recursive(dirp->dd_lock);
110#endif
111        return (index);
112}
113
114#endif /* !_ELIX_LEVEL || _ELIX_LEVEL >= 2 */
115
116/*
117 * seek to an entry in a directory.
118 * Only values returned by "telldir" should be passed to seekdir.
119 */
120void
121_seekdir (register DIR *dirp,
122        long loc)
123{
124        register struct ddloc *lp;
125        register struct ddloc **prevlp;
126        struct dirent *dp;
127
128#if !defined(__SINGLE_THREAD__) && defined(HAVE_DD_LOCK)
129        __lock_acquire(__dd_hash_mutex);
130#endif
131        if (loc != 0) {
132                prevlp = &dd_hash[LOCHASH(loc)];
133                lp = *prevlp;
134                while (lp != NULL) {
135                        if (lp->loc_index == loc)
136                                break;
137                        prevlp = &lp->loc_next;
138                        lp = lp->loc_next;
139                }
140                if (lp == NULL) {
141#if !defined(__SINGLE_THREAD__) && defined(HAVE_DD_LOCK)
142                        __lock_release(__dd_hash_mutex);
143#endif
144                        return;
145                }
146                if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek)
147                        goto found;
148                (void) lseek(dirp->dd_fd, lp->loc_seek, 0);
149                dirp->dd_seek = lp->loc_seek;
150                dirp->dd_loc = 0;
151                while (dirp->dd_loc < lp->loc_loc) {
152                        dp = readdir(dirp);
153                        if (dp == NULL)
154                                break;
155                }
156found:
157#ifdef SINGLEUSE
158                *prevlp = lp->loc_next;
159                free((caddr_t)lp);
160#endif
161        } else {
162                // loc 0 means rewinding
163                (void) lseek(dirp->dd_fd, 0, 0);
164                dirp->dd_seek = 0;
165                dirp->dd_loc = 0;
166        }
167#if !defined(__SINGLE_THREAD__) && defined(HAVE_DD_LOCK)
168        __lock_release(__dd_hash_mutex);
169#endif
170}
171
172/* clean out any hash entries from a closed directory */
173void
174_cleanupdir (register DIR *dirp)
175{
176        int i;
177
178#if !defined(__SINGLE_THREAD__) && defined(HAVE_DD_LOCK)
179        __lock_acquire(__dd_hash_mutex);
180#endif
181        for (i = 0; i < NDIRHASH; ++i) {
182                struct ddloc head;
183                register struct ddloc *lp;
184                register struct ddloc *prevlp;
185
186                lp = dd_hash[i];
187                head.loc_next = lp;
188                prevlp = &head;
189                while (lp != NULL) {
190                        struct ddloc *nextlp;
191
192                        nextlp = lp->loc_next;
193                        if (lp->loc_dirp == dirp) {
194                                prevlp->loc_next = nextlp;
195                                free((caddr_t)lp);
196                        }
197                        else
198                                prevlp = lp;
199                        lp = nextlp;
200                }
201                dd_hash[i] = head.loc_next;
202        }
203#if !defined(__SINGLE_THREAD__) && defined(HAVE_DD_LOCK)
204        __lock_release(__dd_hash_mutex);
205#endif
206
207}
208#endif /* ! HAVE_OPENDIR */
Note: See TracBrowser for help on using the repository browser.