4 * Derived from DIRLIB.C by Matt J. Weinstein
5 * This note appears in the DIRLIB.H
6 * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89
8 * Updated by Jeremy Bettis <jeremy@hksys.com>
9 * Significantly revised and rewinddir, seekdir and telldir added by Colin
10 * Peters <colin@fu.is.saga-u.ac.jp>
14 * $Date: 2002/11/10 23:41:53 $
25 /* FIXME: anything clever to put here? */
38 #define WIN32_LEAN_AND_MEAN
39 #include <windows.h> /* for GetFileAttributes */
49 * Returns a pointer to a DIR structure appropriately filled in to begin
50 * searching a directory.
53 opendir (const CHAR *szPath)
57 CHAR szFullPath[MAX_PATH];
67 if (szPath[0] == '\0')
73 /* Attempt to determine if the given path really is a directory. */
74 rc = GetFileAttributes (szPath);
77 /* call GetLastError for more error info */
81 if (!(rc & FILE_ATTRIBUTE_DIRECTORY))
83 /* Error, entry exists but not a directory. */
88 /* Make an absolute pathname. */
89 #if defined( UNDER_CE )
90 if (szPath[0] == '\\' || szPath[0] == '/')
92 sprintf (szFullPath, MAX_PATH, "%s", szPath);
97 /* FIXME: if I wasn't lazy, I'dcheck for overflows here. */
98 sprintf (szFullPath, MAX_PATH, "\\%s", szPath );
101 _fullpath (szFullPath, szPath, MAX_PATH);
104 /* Allocate enough space to store DIR structure and the complete
105 * directory path given. */
106 nd = (DIR *) malloc (sizeof (DIR) + strlen (szFullPath) + strlen (SLASH) +
111 /* Error, out of memory. */
116 /* Create the search expression. */
117 strcpy (nd->dd_name, szFullPath);
119 /* Add on a slash if the path does not end with one. */
120 if (nd->dd_name[0] != '\0' &&
121 nd->dd_name[strlen (nd->dd_name) - 1] != '/' &&
122 nd->dd_name[strlen (nd->dd_name) - 1] != '\\')
124 strcat (nd->dd_name, SLASH);
127 /* Add on the search pattern */
128 strcat (nd->dd_name, SUFFIX);
130 /* Initialize handle to -1 so that a premature closedir doesn't try
131 * to call FindClose on it. */
134 /* Initialize the status. */
137 /* Initialize the dirent structure. ino and reclen are invalid under
138 * Win32, and name simply points at the appropriate part of the
139 * findfirst_t structure. */
140 nd->dd_dir.d_ino = 0;
141 nd->dd_dir.d_reclen = 0;
142 nd->dd_dir.d_namlen = 0;
143 nd->dd_dir.d_name = nd->dd_dta.cFileName;
152 * Return a pointer to a dirent structure filled with the information on the
153 * next entry in the directory.
160 /* Check for valid DIR struct. */
164 return (struct dirent *) 0;
167 if (dirp->dd_dir.d_name != dirp->dd_dta.cFileName)
169 /* The structure does not seem to be set up correctly. */
171 return (struct dirent *) 0;
174 if (dirp->dd_stat < 0)
176 /* We have already returned all files in the directory
177 * (or the structure has an invalid dd_stat). */
178 return (struct dirent *) 0;
180 else if (dirp->dd_stat == 0)
182 /* We haven't started the search yet. */
183 /* Start the search */
184 dirp->dd_handle = FindFirstFile (dirp->dd_name, &(dirp->dd_dta));
186 if (dirp->dd_handle == -1)
188 /* Whoops! Seems there are no files in that
199 /* Get the next search entry. */
200 if (FindNextFile (dirp->dd_handle, &(dirp->dd_dta)))
202 /* We are off the end or otherwise error. */
203 FindClose (dirp->dd_handle);
204 dirp->dd_handle = -1;
209 /* Update the status to indicate the correct
215 if (dirp->dd_stat > 0)
217 /* Successfully got an entry. Everything about the file is
218 * already appropriately filled in except the length of the
220 dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name);
221 return &dirp->dd_dir;
224 return (struct dirent *) 0;
231 * Frees up resources allocated by opendir.
234 closedir (DIR * dirp)
247 if (dirp->dd_handle != -1)
249 rc = FindClose (dirp->dd_handle);
252 /* Delete the dir structure. */
261 * Return to the beginning of the directory "stream". We simply call findclose
262 * and then reset things like an opendir.
265 rewinddir (DIR * dirp)
275 if (dirp->dd_handle != -1)
277 FindClose (dirp->dd_handle);
280 dirp->dd_handle = -1;
287 * Returns the "position" in the "directory stream" which can be used with
288 * seekdir to go back to an old entry. We simply return the value in stat.
300 return dirp->dd_stat;
306 * Seek to an entry previously returned by telldir. We rewind the directory
307 * and call readdir repeatedly until either dd_stat is the position number
308 * or -1 (off the end). This is not perfect, in that the directory may
309 * have changed while we weren't looking. But that is probably the case with
313 seekdir (DIR * dirp, long lPos)
325 /* Seeking to an invalid position. */
332 if (dirp->dd_handle != -1)
334 FindClose (dirp->dd_handle);
336 dirp->dd_handle = -1;
341 /* Rewind and read forward to the appropriate index. */
344 while ((dirp->dd_stat < lPos) && readdir (dirp))