]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/dirent.c
2 * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
10 * Implement dirent-style opendir(), readdir(), closedir(), rewinddir(),
11 * seekdir() and telldir on Windows - Based on mingw-runtime package sources.
15 * Original file info follow:
18 * This file has no copyright assigned and is placed in the Public Domain.
19 * This file is a part of the mingw-runtime package.
20 * No warranty is given; refer to the file DISCLAIMER within the package.
22 * Derived from DIRLIB.C by Matt J. Weinstein
23 * This note appears in the DIRLIB.H
24 * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89
26 * Updated by Jeremy Bettis <jeremy@hksys.com>
27 * Significantly revised and rewinddir, seekdir and telldir added by Colin
28 * Peters <colin@fu.is.saga-u.ac.jp>
34 /* The following code section is part of the native Windows Squid port */
44 #define WIN32_LEAN_AND_MEAN
45 #include <windows.h> /* for GetFileAttributes */
53 * Returns a pointer to a DIR structure appropriately filled in to begin
54 * searching a directory.
57 opendir(const CHAR
* szPath
)
61 CHAR szFullPath
[MAX_PATH
];
69 if (szPath
[0] == '\0') {
73 /* Attempt to determine if the given path really is a directory. */
74 rc
= GetFileAttributes(szPath
);
75 if (rc
== (unsigned int) -1) {
76 /* call GetLastError for more error info */
80 if (!(rc
& FILE_ATTRIBUTE_DIRECTORY
)) {
81 /* Error, entry exists but not a directory. */
85 /* Make an absolute pathname. */
86 _fullpath(szFullPath
, szPath
, MAX_PATH
);
88 /* Allocate enough space to store DIR structure and the complete
89 * directory path given. */
90 nd
= (DIR *) malloc(sizeof(DIR) + (strlen(szFullPath
)
96 /* Error, out of memory. */
100 /* Create the search expression. */
101 strcpy(nd
->dd_name
, szFullPath
);
103 /* Add on a slash if the path does not end with one. */
104 if (nd
->dd_name
[0] != '\0'
105 && strchr(nd
->dd_name
, '/') != nd
->dd_name
106 + strlen(nd
->dd_name
) - 1
107 && strchr(nd
->dd_name
, '\\') != nd
->dd_name
108 + strlen(nd
->dd_name
) - 1) {
109 strcat(nd
->dd_name
, SLASH
);
111 /* Add on the search pattern */
112 strcat(nd
->dd_name
, SUFFIX
);
114 /* Initialize handle to -1 so that a premature closedir doesn't try
115 * to call _findclose on it. */
118 /* Initialize the status. */
121 /* Initialize the dirent structure. ino and reclen are invalid under
122 * Win32, and name simply points at the appropriate part of the
123 * findfirst_t structure. */
124 nd
->dd_dir
.d_ino
= 0;
125 nd
->dd_dir
.d_reclen
= 0;
126 nd
->dd_dir
.d_namlen
= 0;
127 memset(nd
->dd_dir
.d_name
, 0, FILENAME_MAX
);
135 * Return a pointer to a dirent structure filled with the information on the
136 * next entry in the directory.
139 readdir(DIR * dirp
) {
142 /* Check for valid DIR struct. */
145 return (struct dirent
*) 0;
147 if (dirp
->dd_stat
< 0) {
148 /* We have already returned all files in the directory
149 * (or the structure has an invalid dd_stat). */
150 return (struct dirent
*) 0;
151 } else if (dirp
->dd_stat
== 0) {
152 /* We haven't started the search yet. */
153 /* Start the search */
154 dirp
->dd_handle
= _findfirst(dirp
->dd_name
, &(dirp
->dd_dta
));
156 if (dirp
->dd_handle
== -1) {
157 /* Whoops! Seems there are no files in that
164 /* Get the next search entry. */
165 if (_findnext(dirp
->dd_handle
, &(dirp
->dd_dta
))) {
166 /* We are off the end or otherwise error.
167 * _findnext sets errno to ENOENT if no more file
169 DWORD winerr
= GetLastError();
170 if (winerr
== ERROR_NO_MORE_FILES
)
172 _findclose(dirp
->dd_handle
);
173 dirp
->dd_handle
= -1;
176 /* Update the status to indicate the correct
182 if (dirp
->dd_stat
> 0) {
183 /* Successfully got an entry. Everything about the file is
184 * already appropriately filled in except the length of the
186 dirp
->dd_dir
.d_namlen
= strlen(dirp
->dd_dta
.name
);
187 strcpy(dirp
->dd_dir
.d_name
, dirp
->dd_dta
.name
);
188 return &dirp
->dd_dir
;
190 return (struct dirent
*) 0;
196 * Frees up resources allocated by opendir.
210 if (dirp
->dd_handle
!= -1) {
211 rc
= _findclose(dirp
->dd_handle
);
213 /* Delete the dir structure. */
222 * Return to the beginning of the directory "stream". We simply call findclose
223 * and then reset things like an opendir.
226 rewinddir(DIR * dirp
)
234 if (dirp
->dd_handle
!= -1) {
235 _findclose(dirp
->dd_handle
);
237 dirp
->dd_handle
= -1;
244 * Returns the "position" in the "directory stream" which can be used with
245 * seekdir to go back to an old entry. We simply return the value in stat.
256 return dirp
->dd_stat
;
262 * Seek to an entry previously returned by telldir. We rewind the directory
263 * and call readdir repeatedly until either dd_stat is the position number
264 * or -1 (off the end). This is not perfect, in that the directory may
265 * have changed while we weren't looking. But that is probably the case with
269 seekdir(DIR * dirp
, long lPos
)
278 /* Seeking to an invalid position. */
281 } else if (lPos
== -1) {
283 if (dirp
->dd_handle
!= -1) {
284 _findclose(dirp
->dd_handle
);
286 dirp
->dd_handle
= -1;
289 /* Rewind and read forward to the appropriate index. */
292 while ((dirp
->dd_stat
< lPos
) && readdir(dirp
));
295 #endif /* _SQUID_WINDOWS_ */