]> git.ipfire.org Git - thirdparty/squid.git/blob - lib/dirent.c
Renamed squid.h to squid-old.h and config.h to squid.h
[thirdparty/squid.git] / lib / dirent.c
1 /*
2 * $Id$
3 *
4 * Implement dirent-style opendir(), readdir(), closedir(), rewinddir(),
5 * seekdir() and telldir on Windows - Based on mingw-runtime package sources.
6 * AUTHOR: Guido Serassio <serassio@squid-cache.org>
7 *
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 * Original file info follow:
35 *
36 * dirent.c
37 * This file has no copyright assigned and is placed in the Public Domain.
38 * This file is a part of the mingw-runtime package.
39 * No warranty is given; refer to the file DISCLAIMER within the package.
40 *
41 * Derived from DIRLIB.C by Matt J. Weinstein
42 * This note appears in the DIRLIB.H
43 * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89
44 *
45 * Updated by Jeremy Bettis <jeremy@hksys.com>
46 * Significantly revised and rewinddir, seekdir and telldir added by Colin
47 * Peters <colin@fu.is.saga-u.ac.jp>
48 *
49 */
50
51 #include "squid.h"
52
53 /* The following code section is part of the native Windows Squid port */
54 #if _SQUID_MSWIN_
55
56 #include "util.h"
57 #include <stdlib.h>
58 #include <errno.h>
59 #include <string.h>
60 #include <io.h>
61 #include <dirent.h>
62
63 #define WIN32_LEAN_AND_MEAN
64 #include <windows.h> /* for GetFileAttributes */
65
66 #define SUFFIX ("*")
67 #define SLASH ("\\")
68
69
70 /*
71 * opendir
72 *
73 * Returns a pointer to a DIR structure appropriately filled in to begin
74 * searching a directory.
75 */
76 DIR *
77 opendir(const CHAR * szPath)
78 {
79 DIR *nd;
80 unsigned int rc;
81 CHAR szFullPath[MAX_PATH];
82
83 errno = 0;
84
85 if (!szPath) {
86 errno = EFAULT;
87 return (DIR *) 0;
88 }
89 if (szPath[0] == '\0') {
90 errno = ENOTDIR;
91 return (DIR *) 0;
92 }
93 /* Attempt to determine if the given path really is a directory. */
94 rc = GetFileAttributes(szPath);
95 if (rc == (unsigned int) -1) {
96 /* call GetLastError for more error info */
97 errno = ENOENT;
98 return (DIR *) 0;
99 }
100 if (!(rc & FILE_ATTRIBUTE_DIRECTORY)) {
101 /* Error, entry exists but not a directory. */
102 errno = ENOTDIR;
103 return (DIR *) 0;
104 }
105 /* Make an absolute pathname. */
106 _fullpath(szFullPath, szPath, MAX_PATH);
107
108 /* Allocate enough space to store DIR structure and the complete
109 * directory path given. */
110 nd = (DIR *) malloc(sizeof(DIR) + (strlen(szFullPath)
111 + strlen(SLASH)
112 + strlen(SUFFIX) + 1)
113 * sizeof(CHAR));
114
115 if (!nd) {
116 /* Error, out of memory. */
117 errno = ENOMEM;
118 return (DIR *) 0;
119 }
120 /* Create the search expression. */
121 strcpy(nd->dd_name, szFullPath);
122
123 /* Add on a slash if the path does not end with one. */
124 if (nd->dd_name[0] != '\0'
125 && strchr(nd->dd_name, '/') != nd->dd_name
126 + strlen(nd->dd_name) - 1
127 && strchr(nd->dd_name, '\\') != nd->dd_name
128 + strlen(nd->dd_name) - 1) {
129 strcat(nd->dd_name, SLASH);
130 }
131 /* Add on the search pattern */
132 strcat(nd->dd_name, SUFFIX);
133
134 /* Initialize handle to -1 so that a premature closedir doesn't try
135 * to call _findclose on it. */
136 nd->dd_handle = -1;
137
138 /* Initialize the status. */
139 nd->dd_stat = 0;
140
141 /* Initialize the dirent structure. ino and reclen are invalid under
142 * Win32, and name simply points at the appropriate part of the
143 * findfirst_t structure. */
144 nd->dd_dir.d_ino = 0;
145 nd->dd_dir.d_reclen = 0;
146 nd->dd_dir.d_namlen = 0;
147 memset(nd->dd_dir.d_name, 0, FILENAME_MAX);
148
149 return nd;
150 }
151
152
153 /*
154 * readdir
155 *
156 * Return a pointer to a dirent structure filled with the information on the
157 * next entry in the directory.
158 */
159 struct dirent *
160 readdir(DIR * dirp) {
161 errno = 0;
162
163 /* Check for valid DIR struct. */
164 if (!dirp) {
165 errno = EFAULT;
166 return (struct dirent *) 0;
167 }
168 if (dirp->dd_stat < 0) {
169 /* We have already returned all files in the directory
170 * (or the structure has an invalid dd_stat). */
171 return (struct dirent *) 0;
172 } else if (dirp->dd_stat == 0) {
173 /* We haven't started the search yet. */
174 /* Start the search */
175 dirp->dd_handle = _findfirst(dirp->dd_name, &(dirp->dd_dta));
176
177 if (dirp->dd_handle == -1) {
178 /* Whoops! Seems there are no files in that
179 * directory. */
180 dirp->dd_stat = -1;
181 } else {
182 dirp->dd_stat = 1;
183 }
184 } else {
185 /* Get the next search entry. */
186 if (_findnext(dirp->dd_handle, &(dirp->dd_dta))) {
187 /* We are off the end or otherwise error.
188 * _findnext sets errno to ENOENT if no more file
189 * Undo this. */
190 DWORD winerr = GetLastError();
191 if (winerr == ERROR_NO_MORE_FILES)
192 errno = 0;
193 _findclose(dirp->dd_handle);
194 dirp->dd_handle = -1;
195 dirp->dd_stat = -1;
196 } else {
197 /* Update the status to indicate the correct
198 * number. */
199 dirp->dd_stat++;
200 }
201 }
202
203 if (dirp->dd_stat > 0) {
204 /* Successfully got an entry. Everything about the file is
205 * already appropriately filled in except the length of the
206 * file name. */
207 dirp->dd_dir.d_namlen = strlen(dirp->dd_dta.name);
208 strcpy(dirp->dd_dir.d_name, dirp->dd_dta.name);
209 return &dirp->dd_dir;
210 }
211 return (struct dirent *) 0;
212 }
213
214
215 /*
216 * closedir
217 *
218 * Frees up resources allocated by opendir.
219 */
220 int
221 closedir(DIR * dirp)
222 {
223 int rc;
224
225 errno = 0;
226 rc = 0;
227
228 if (!dirp) {
229 errno = EFAULT;
230 return -1;
231 }
232 if (dirp->dd_handle != -1) {
233 rc = _findclose(dirp->dd_handle);
234 }
235 /* Delete the dir structure. */
236 free(dirp);
237
238 return rc;
239 }
240
241 /*
242 * rewinddir
243 *
244 * Return to the beginning of the directory "stream". We simply call findclose
245 * and then reset things like an opendir.
246 */
247 void
248 rewinddir(DIR * dirp)
249 {
250 errno = 0;
251
252 if (!dirp) {
253 errno = EFAULT;
254 return;
255 }
256 if (dirp->dd_handle != -1) {
257 _findclose(dirp->dd_handle);
258 }
259 dirp->dd_handle = -1;
260 dirp->dd_stat = 0;
261 }
262
263 /*
264 * telldir
265 *
266 * Returns the "position" in the "directory stream" which can be used with
267 * seekdir to go back to an old entry. We simply return the value in stat.
268 */
269 long
270 telldir(DIR * dirp)
271 {
272 errno = 0;
273
274 if (!dirp) {
275 errno = EFAULT;
276 return -1;
277 }
278 return dirp->dd_stat;
279 }
280
281 /*
282 * seekdir
283 *
284 * Seek to an entry previously returned by telldir. We rewind the directory
285 * and call readdir repeatedly until either dd_stat is the position number
286 * or -1 (off the end). This is not perfect, in that the directory may
287 * have changed while we weren't looking. But that is probably the case with
288 * any such system.
289 */
290 void
291 seekdir(DIR * dirp, long lPos)
292 {
293 errno = 0;
294
295 if (!dirp) {
296 errno = EFAULT;
297 return;
298 }
299 if (lPos < -1) {
300 /* Seeking to an invalid position. */
301 errno = EINVAL;
302 return;
303 } else if (lPos == -1) {
304 /* Seek past end. */
305 if (dirp->dd_handle != -1) {
306 _findclose(dirp->dd_handle);
307 }
308 dirp->dd_handle = -1;
309 dirp->dd_stat = -1;
310 } else {
311 /* Rewind and read forward to the appropriate index. */
312 rewinddir(dirp);
313
314 while ((dirp->dd_stat < lPos) && readdir(dirp));
315 }
316 }
317 #endif /* _SQUID_MSWIN_ */