]> git.ipfire.org Git - thirdparty/squid.git/blame - lib/dirent.c
Remove unnecessary stub_tools dependency on String
[thirdparty/squid.git] / lib / dirent.c
CommitLineData
63b81f13
GS
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.
26ac0430 24 *
63b81f13
GS
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.
26ac0430 29 *
63b81f13
GS
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 *
26ac0430 41 * Derived from DIRLIB.C by Matt J. Weinstein
63b81f13
GS
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>
26ac0430 48 *
63b81f13
GS
49 */
50
75072239 51#include "config.h"
63b81f13
GS
52
53/* The following code section is part of the native Windows Squid port */
8a09e810 54#if _SQUID_MSWIN_
75072239
AJ
55
56#include "util.h"
63b81f13
GS
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 */
76DIR *
77opendir(const CHAR * szPath)
78{
79 DIR *nd;
80 unsigned int rc;
81 CHAR szFullPath[MAX_PATH];
82
83 errno = 0;
84
85 if (!szPath) {
26ac0430
AJ
86 errno = EFAULT;
87 return (DIR *) 0;
63b81f13
GS
88 }
89 if (szPath[0] == '\0') {
26ac0430
AJ
90 errno = ENOTDIR;
91 return (DIR *) 0;
63b81f13
GS
92 }
93 /* Attempt to determine if the given path really is a directory. */
94 rc = GetFileAttributes(szPath);
95 if (rc == (unsigned int) -1) {
26ac0430
AJ
96 /* call GetLastError for more error info */
97 errno = ENOENT;
98 return (DIR *) 0;
63b81f13
GS
99 }
100 if (!(rc & FILE_ATTRIBUTE_DIRECTORY)) {
26ac0430
AJ
101 /* Error, entry exists but not a directory. */
102 errno = ENOTDIR;
103 return (DIR *) 0;
63b81f13
GS
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)
26ac0430
AJ
111 + strlen(SLASH)
112 + strlen(SUFFIX) + 1)
113 * sizeof(CHAR));
63b81f13
GS
114
115 if (!nd) {
26ac0430
AJ
116 /* Error, out of memory. */
117 errno = ENOMEM;
118 return (DIR *) 0;
63b81f13
GS
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'
26ac0430
AJ
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);
63b81f13
GS
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 */
159struct dirent *
e1381638 160readdir(DIR * dirp) {
63b81f13
GS
161 errno = 0;
162
163 /* Check for valid DIR struct. */
164 if (!dirp) {
26ac0430
AJ
165 errno = EFAULT;
166 return (struct dirent *) 0;
63b81f13
GS
167 }
168 if (dirp->dd_stat < 0) {
26ac0430
AJ
169 /* We have already returned all files in the directory
170 * (or the structure has an invalid dd_stat). */
171 return (struct dirent *) 0;
63b81f13 172 } else if (dirp->dd_stat == 0) {
26ac0430
AJ
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 }
63b81f13 184 } else {
26ac0430
AJ
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 }
63b81f13
GS
201 }
202
203 if (dirp->dd_stat > 0) {
26ac0430
AJ
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;
63b81f13
GS
210 }
211 return (struct dirent *) 0;
212}
213
214
215/*
216 * closedir
217 *
218 * Frees up resources allocated by opendir.
219 */
220int
221closedir(DIR * dirp)
222{
223 int rc;
224
225 errno = 0;
226 rc = 0;
227
228 if (!dirp) {
26ac0430
AJ
229 errno = EFAULT;
230 return -1;
63b81f13
GS
231 }
232 if (dirp->dd_handle != -1) {
26ac0430 233 rc = _findclose(dirp->dd_handle);
63b81f13
GS
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 */
247void
248rewinddir(DIR * dirp)
249{
250 errno = 0;
251
252 if (!dirp) {
26ac0430
AJ
253 errno = EFAULT;
254 return;
63b81f13
GS
255 }
256 if (dirp->dd_handle != -1) {
26ac0430 257 _findclose(dirp->dd_handle);
63b81f13
GS
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 */
269long
270telldir(DIR * dirp)
271{
272 errno = 0;
273
274 if (!dirp) {
26ac0430
AJ
275 errno = EFAULT;
276 return -1;
63b81f13
GS
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 */
290void
291seekdir(DIR * dirp, long lPos)
292{
293 errno = 0;
294
295 if (!dirp) {
26ac0430
AJ
296 errno = EFAULT;
297 return;
63b81f13
GS
298 }
299 if (lPos < -1) {
26ac0430
AJ
300 /* Seeking to an invalid position. */
301 errno = EINVAL;
302 return;
63b81f13 303 } else if (lPos == -1) {
26ac0430
AJ
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;
63b81f13 310 } else {
26ac0430
AJ
311 /* Rewind and read forward to the appropriate index. */
312 rewinddir(dirp);
63b81f13 313
26ac0430 314 while ((dirp->dd_stat < lPos) && readdir(dirp));
63b81f13
GS
315 }
316}
317#endif /* _SQUID_MSWIN_ */