]> git.ipfire.org Git - thirdparty/squid.git/blame - lib/dirent.c
SourceFormat Enforcement
[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
f7f3304a 51#include "squid.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
63b81f13
GS
69/*
70 * opendir
71 *
72 * Returns a pointer to a DIR structure appropriately filled in to begin
73 * searching a directory.
74 */
75DIR *
76opendir(const CHAR * szPath)
77{
78 DIR *nd;
79 unsigned int rc;
80 CHAR szFullPath[MAX_PATH];
81
82 errno = 0;
83
84 if (!szPath) {
26ac0430
AJ
85 errno = EFAULT;
86 return (DIR *) 0;
63b81f13
GS
87 }
88 if (szPath[0] == '\0') {
26ac0430
AJ
89 errno = ENOTDIR;
90 return (DIR *) 0;
63b81f13
GS
91 }
92 /* Attempt to determine if the given path really is a directory. */
93 rc = GetFileAttributes(szPath);
94 if (rc == (unsigned int) -1) {
26ac0430
AJ
95 /* call GetLastError for more error info */
96 errno = ENOENT;
97 return (DIR *) 0;
63b81f13
GS
98 }
99 if (!(rc & FILE_ATTRIBUTE_DIRECTORY)) {
26ac0430
AJ
100 /* Error, entry exists but not a directory. */
101 errno = ENOTDIR;
102 return (DIR *) 0;
63b81f13
GS
103 }
104 /* Make an absolute pathname. */
105 _fullpath(szFullPath, szPath, MAX_PATH);
106
107 /* Allocate enough space to store DIR structure and the complete
108 * directory path given. */
109 nd = (DIR *) malloc(sizeof(DIR) + (strlen(szFullPath)
26ac0430
AJ
110 + strlen(SLASH)
111 + strlen(SUFFIX) + 1)
112 * sizeof(CHAR));
63b81f13
GS
113
114 if (!nd) {
26ac0430
AJ
115 /* Error, out of memory. */
116 errno = ENOMEM;
117 return (DIR *) 0;
63b81f13
GS
118 }
119 /* Create the search expression. */
120 strcpy(nd->dd_name, szFullPath);
121
122 /* Add on a slash if the path does not end with one. */
123 if (nd->dd_name[0] != '\0'
26ac0430
AJ
124 && strchr(nd->dd_name, '/') != nd->dd_name
125 + strlen(nd->dd_name) - 1
126 && strchr(nd->dd_name, '\\') != nd->dd_name
127 + strlen(nd->dd_name) - 1) {
128 strcat(nd->dd_name, SLASH);
63b81f13
GS
129 }
130 /* Add on the search pattern */
131 strcat(nd->dd_name, SUFFIX);
132
133 /* Initialize handle to -1 so that a premature closedir doesn't try
134 * to call _findclose on it. */
135 nd->dd_handle = -1;
136
137 /* Initialize the status. */
138 nd->dd_stat = 0;
139
140 /* Initialize the dirent structure. ino and reclen are invalid under
141 * Win32, and name simply points at the appropriate part of the
142 * findfirst_t structure. */
143 nd->dd_dir.d_ino = 0;
144 nd->dd_dir.d_reclen = 0;
145 nd->dd_dir.d_namlen = 0;
146 memset(nd->dd_dir.d_name, 0, FILENAME_MAX);
147
148 return nd;
149}
150
63b81f13
GS
151/*
152 * readdir
153 *
154 * Return a pointer to a dirent structure filled with the information on the
155 * next entry in the directory.
156 */
157struct dirent *
e1381638 158readdir(DIR * dirp) {
63b81f13
GS
159 errno = 0;
160
161 /* Check for valid DIR struct. */
162 if (!dirp) {
26ac0430
AJ
163 errno = EFAULT;
164 return (struct dirent *) 0;
63b81f13
GS
165 }
166 if (dirp->dd_stat < 0) {
26ac0430
AJ
167 /* We have already returned all files in the directory
168 * (or the structure has an invalid dd_stat). */
169 return (struct dirent *) 0;
63b81f13 170 } else if (dirp->dd_stat == 0) {
26ac0430
AJ
171 /* We haven't started the search yet. */
172 /* Start the search */
173 dirp->dd_handle = _findfirst(dirp->dd_name, &(dirp->dd_dta));
174
175 if (dirp->dd_handle == -1) {
176 /* Whoops! Seems there are no files in that
177 * directory. */
178 dirp->dd_stat = -1;
179 } else {
180 dirp->dd_stat = 1;
181 }
63b81f13 182 } else {
26ac0430
AJ
183 /* Get the next search entry. */
184 if (_findnext(dirp->dd_handle, &(dirp->dd_dta))) {
185 /* We are off the end or otherwise error.
186 * _findnext sets errno to ENOENT if no more file
187 * Undo this. */
188 DWORD winerr = GetLastError();
189 if (winerr == ERROR_NO_MORE_FILES)
190 errno = 0;
191 _findclose(dirp->dd_handle);
192 dirp->dd_handle = -1;
193 dirp->dd_stat = -1;
194 } else {
195 /* Update the status to indicate the correct
196 * number. */
197 dirp->dd_stat++;
198 }
63b81f13
GS
199 }
200
201 if (dirp->dd_stat > 0) {
26ac0430
AJ
202 /* Successfully got an entry. Everything about the file is
203 * already appropriately filled in except the length of the
204 * file name. */
205 dirp->dd_dir.d_namlen = strlen(dirp->dd_dta.name);
206 strcpy(dirp->dd_dir.d_name, dirp->dd_dta.name);
207 return &dirp->dd_dir;
63b81f13
GS
208 }
209 return (struct dirent *) 0;
210}
211
63b81f13
GS
212/*
213 * closedir
214 *
215 * Frees up resources allocated by opendir.
216 */
217int
218closedir(DIR * dirp)
219{
220 int rc;
221
222 errno = 0;
223 rc = 0;
224
225 if (!dirp) {
26ac0430
AJ
226 errno = EFAULT;
227 return -1;
63b81f13
GS
228 }
229 if (dirp->dd_handle != -1) {
26ac0430 230 rc = _findclose(dirp->dd_handle);
63b81f13
GS
231 }
232 /* Delete the dir structure. */
233 free(dirp);
234
235 return rc;
236}
237
238/*
239 * rewinddir
240 *
241 * Return to the beginning of the directory "stream". We simply call findclose
242 * and then reset things like an opendir.
243 */
244void
245rewinddir(DIR * dirp)
246{
247 errno = 0;
248
249 if (!dirp) {
26ac0430
AJ
250 errno = EFAULT;
251 return;
63b81f13
GS
252 }
253 if (dirp->dd_handle != -1) {
26ac0430 254 _findclose(dirp->dd_handle);
63b81f13
GS
255 }
256 dirp->dd_handle = -1;
257 dirp->dd_stat = 0;
258}
259
260/*
261 * telldir
262 *
263 * Returns the "position" in the "directory stream" which can be used with
264 * seekdir to go back to an old entry. We simply return the value in stat.
265 */
266long
267telldir(DIR * dirp)
268{
269 errno = 0;
270
271 if (!dirp) {
26ac0430
AJ
272 errno = EFAULT;
273 return -1;
63b81f13
GS
274 }
275 return dirp->dd_stat;
276}
277
278/*
279 * seekdir
280 *
281 * Seek to an entry previously returned by telldir. We rewind the directory
282 * and call readdir repeatedly until either dd_stat is the position number
283 * or -1 (off the end). This is not perfect, in that the directory may
284 * have changed while we weren't looking. But that is probably the case with
285 * any such system.
286 */
287void
288seekdir(DIR * dirp, long lPos)
289{
290 errno = 0;
291
292 if (!dirp) {
26ac0430
AJ
293 errno = EFAULT;
294 return;
63b81f13
GS
295 }
296 if (lPos < -1) {
26ac0430
AJ
297 /* Seeking to an invalid position. */
298 errno = EINVAL;
299 return;
63b81f13 300 } else if (lPos == -1) {
26ac0430
AJ
301 /* Seek past end. */
302 if (dirp->dd_handle != -1) {
303 _findclose(dirp->dd_handle);
304 }
305 dirp->dd_handle = -1;
306 dirp->dd_stat = -1;
63b81f13 307 } else {
26ac0430
AJ
308 /* Rewind and read forward to the appropriate index. */
309 rewinddir(dirp);
63b81f13 310
26ac0430 311 while ((dirp->dd_stat < lPos) && readdir(dirp));
63b81f13
GS
312 }
313}
314#endif /* _SQUID_MSWIN_ */