3 * This file has no copyright assigned and is placed in the Public Domain.
4 * This file is a part of the mingw-runtime package.
5 * No warranty is given; refer to the file DISCLAIMER within the package.
7 * Derived from DIRLIB.C by Matt J. Weinstein
8 * This note appears in the DIRLIB.H
9 * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89
11 * Updated by Jeremy Bettis <jeremy@hksys.com>
12 * Significantly revised and rewinddir, seekdir and telldir added by Colin
13 * Peters <colin@fu.is.saga-u.ac.jp>
23 #include "w32_dirent.h"
25 #define WIN32_LEAN_AND_MEAN
26 #include <windows.h> /* for GetFileAttributes */
34 * Returns a pointer to a DIR structure appropriately filled in to begin
35 * searching a directory.
37 DIR * opendir (const char *szPath)
41 char szFullPath[MAX_PATH];
51 if (szPath[0] == ('\0'))
57 /* Attempt to determine if the given path really is a directory. */
58 rc = GetFileAttributes (szPath);
59 if (rc == (unsigned int)-1)
61 /* call GetLastError for more error info */
65 if (!(rc & FILE_ATTRIBUTE_DIRECTORY))
67 /* Error, entry exists but not a directory. */
72 /* Make an absolute pathname. */
73 _fullpath (szFullPath, szPath, MAX_PATH);
75 /* Allocate enough space to store DIR structure and the complete
76 * directory path given. */
77 nd = (DIR *) malloc (sizeof (DIR) + (strlen (szFullPath)
79 + strlen (SUFFIX) + 1)
84 /* Error, out of memory. */
89 /* Create the search expression. */
90 strcpy (nd->dd_name, szFullPath);
92 /* Add on a slash if the path does not end with one. */
93 if (nd->dd_name[0] != ('\0')
94 && strrchr (nd->dd_name, ('/')) != nd->dd_name
95 + strlen (nd->dd_name) - 1
96 && strrchr (nd->dd_name, ('\\')) != nd->dd_name
97 + strlen (nd->dd_name) - 1)
99 strcat (nd->dd_name, SLASH);
102 /* Add on the search pattern */
103 strcat (nd->dd_name, SUFFIX);
105 /* Initialize handle to -1 so that a premature closedir doesn't try
106 * to call _findclose on it. */
109 /* Initialize the status. */
112 /* Initialize the dirent structure. ino and reclen are invalid under
113 * Win32, and name simply points at the appropriate part of the
114 * findfirst structure. */
115 nd->dd_dir.d_ino = 0;
116 nd->dd_dir.d_reclen = 0;
117 nd->dd_dir.d_namlen = 0;
118 memset (nd->dd_dir.d_name, 0, FILENAME_MAX);
127 * Return a pointer to a dirent structure filled with the information on the
128 * next entry in the directory.
135 /* Check for valid DIR struct. */
139 return (struct dirent *) 0;
142 if (dirp->dd_stat < 0)
144 /* We have already returned all files in the directory
145 * (or the structure has an invalid dd_stat). */
146 return (struct dirent *) 0;
148 else if (dirp->dd_stat == 0)
150 /* We haven't started the search yet. */
151 /* Start the search */
152 dirp->dd_handle = (long)_findfirst (dirp->dd_name, &(dirp->dd_dta));
154 if (dirp->dd_handle == -1)
156 /* Whoops! Seems there are no files in that
167 /* Get the next search entry. */
168 if (_findnext (dirp->dd_handle, &(dirp->dd_dta)))
170 /* We are off the end or otherwise error.
171 _findnext sets errno to ENOENT if no more file
173 DWORD winerr = GetLastError ();
174 if (winerr == ERROR_NO_MORE_FILES)
176 _findclose (dirp->dd_handle);
177 dirp->dd_handle = -1;
182 /* Update the status to indicate the correct
188 if (dirp->dd_stat > 0)
190 /* Successfully got an entry. Everything about the file is
191 * already appropriately filled in except the length of the
193 dirp->dd_dir.d_namlen = (unsigned short)strlen (dirp->dd_dta.name);
194 strcpy (dirp->dd_dir.d_name, dirp->dd_dta.name);
195 return &dirp->dd_dir;
198 return (struct dirent *) 0;
205 * Frees up resources allocated by opendir.
208 closedir (DIR * dirp)
221 if (dirp->dd_handle != -1)
223 rc = _findclose (dirp->dd_handle);
226 /* Delete the dir structure. */
235 * Return to the beginning of the directory "stream". We simply call findclose
236 * and then reset things like an opendir.
239 rewinddir (DIR * dirp)
249 if (dirp->dd_handle != -1)
251 _findclose (dirp->dd_handle);
254 dirp->dd_handle = -1;
261 * Returns the "position" in the "directory stream" which can be used with
262 * seekdir to go back to an old entry. We simply return the value in stat.
274 return dirp->dd_stat;
280 * Seek to an entry previously returned by telldir. We rewind the directory
281 * and call readdir repeatedly until either dd_stat is the position number
282 * or -1 (off the end). This is not perfect, in that the directory may
283 * have changed while we weren't looking. But that is probably the case with
287 seekdir (DIR * dirp, long lPos)
299 /* Seeking to an invalid position. */
306 if (dirp->dd_handle != -1)
308 _findclose (dirp->dd_handle);
310 dirp->dd_handle = -1;
315 /* Rewind and read forward to the appropriate index. */
318 while ((dirp->dd_stat < lPos) && readdir (dirp))
325 int _utk_w32_dirent_c_shut_up_stupid_compiler_warning;