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/13 20:51:04 $
27 /* FIXME: anything clever to put here? */
39 # define FILENAME_MAX (260)
42 #define WIN32_LEAN_AND_MEAN
43 #include <windows.h> /* for GetFileAttributes */
51 long d_ino; /* Always zero. */
52 unsigned short d_reclen; /* Always zero. */
53 unsigned short d_namlen; /* Length of name in d_name. */
54 char d_name[FILENAME_MAX]; /* File name. */
59 /* disk transfer area for this dir */
60 WIN32_FIND_DATA dd_dta;
62 /* dirent struct to return from dir (NOTE: this makes this thread
63 * safe as long as only one thread uses a particular DIR struct at
72 * 0 = not started yet (next entry to read is first entry)
74 * positive = 0 based index of next entry
78 /* given path for dir with search pattern (struct is extended) */
85 * Returns a pointer to a DIR structure appropriately filled in to begin
86 * searching a directory.
89 vlc_opendir (const CHAR *szPath)
93 CHAR szFullPath[MAX_PATH];
103 if (szPath[0] == '\0')
109 /* Attempt to determine if the given path really is a directory. */
112 wchar_t szPathTmp[MAX_PATH];
113 mbstowcs( szPathTmp, szPath, MAX_PATH );
114 szPathTmp[MAX_PATH-1] = 0;
115 rc = GetFileAttributes (szPathTmp);
118 rc = GetFileAttributes (szPath);
120 if (rc == (unsigned int)-1)
122 /* call GetLastError for more error info */
126 if (!(rc & FILE_ATTRIBUTE_DIRECTORY))
128 /* Error, entry exists but not a directory. */
133 /* Make an absolute pathname. */
134 #if defined( UNDER_CE )
135 if (szPath[0] == '\\' || szPath[0] == '/')
137 sprintf (szFullPath, "%s", szPath);
138 szFullPath[0] = '\\';
142 wchar_t szFullPathTmp[MAX_PATH];
143 if (GetModuleFileName( NULL, szFullPathTmp, MAX_PATH ) )
145 wcstombs( szFullPath, szFullPathTmp, MAX_PATH );
146 szFullPath[MAX_PATH-1] = 0;
150 /* FIXME: if I wasn't lazy, I'd check for overflows here. */
151 sprintf (szFullPath, "\\%s", szPath );
155 _fullpath (szFullPath, szPath, MAX_PATH);
158 /* Allocate enough space to store DIR structure and the complete
159 * directory path given. */
160 nd = (DIR *) malloc (sizeof (DIR) + strlen (szFullPath) + sizeof (SLASH) +
165 /* Error, out of memory. */
170 /* Create the search expression. */
171 strcpy (nd->dd_name, szFullPath);
173 /* Add on a slash if the path does not end with one. */
174 if (nd->dd_name[0] != '\0' &&
175 nd->dd_name[strlen (nd->dd_name) - 1] != '/' &&
176 nd->dd_name[strlen (nd->dd_name) - 1] != '\\')
178 strcat (nd->dd_name, SLASH);
181 /* Add on the search pattern */
182 strcat (nd->dd_name, SUFFIX);
184 /* Initialize handle so that a premature closedir doesn't try
185 * to call FindClose on it. */
186 nd->dd_handle = INVALID_HANDLE_VALUE;
188 /* Initialize the status. */
191 /* Initialize the dirent structure. ino and reclen are invalid under
192 * Win32, and name simply points at the appropriate part of the
193 * findfirst_t structure. */
194 nd->dd_dir.d_ino = 0;
195 nd->dd_dir.d_reclen = 0;
196 nd->dd_dir.d_namlen = 0;
197 memset (nd->dd_dir.d_name, 0, FILENAME_MAX);
206 * Return a pointer to a dirent structure filled with the information on the
207 * next entry in the directory.
210 vlc_readdir (DIR * dirp)
214 /* Check for valid DIR struct. */
218 return (struct dirent *) 0;
221 if (dirp->dd_stat < 0)
223 /* We have already returned all files in the directory
224 * (or the structure has an invalid dd_stat). */
225 return (struct dirent *) 0;
227 else if (dirp->dd_stat == 0)
230 wchar_t dd_name[MAX_PATH];
231 mbstowcs( dd_name, dirp->dd_name, MAX_PATH );
232 dd_name[MAX_PATH-1] = 0;
234 char *dd_name = dirp->dd_name;
236 /* We haven't started the search yet. */
237 /* Start the search */
238 dirp->dd_handle = FindFirstFile (dd_name, &(dirp->dd_dta));
240 if (dirp->dd_handle == INVALID_HANDLE_VALUE)
242 /* Whoops! Seems there are no files in that
253 /* Get the next search entry. */
254 if (!FindNextFile ((HANDLE)dirp->dd_handle, &(dirp->dd_dta)))
256 /* We are off the end or otherwise error. */
257 FindClose ((HANDLE)dirp->dd_handle);
258 dirp->dd_handle = INVALID_HANDLE_VALUE;
263 /* Update the status to indicate the correct
269 if (dirp->dd_stat > 0)
271 /* Successfully got an entry */
274 char d_name[MAX_PATH];
275 wcstombs( d_name, dirp->dd_dta.cFileName, MAX_PATH );
276 d_name[MAX_PATH-1] = 0;
278 char *d_name = dirp->dd_dta.cFileName;
281 strcpy (dirp->dd_dir.d_name, d_name);
282 dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name);
283 return &dirp->dd_dir;
286 return (struct dirent *) 0;
293 * Frees up resources allocated by opendir.
296 vlc_closedir (DIR * dirp)
309 if (dirp->dd_handle != INVALID_HANDLE_VALUE)
311 rc = FindClose ((HANDLE)dirp->dd_handle);
314 /* Delete the dir structure. */
323 * Return to the beginning of the directory "stream". We simply call findclose
324 * and then reset things like an opendir.
327 vlc_rewinddir (DIR * dirp)
337 if (dirp->dd_handle != INVALID_HANDLE_VALUE)
339 FindClose ((HANDLE)dirp->dd_handle);
342 dirp->dd_handle = INVALID_HANDLE_VALUE;
349 * Returns the "position" in the "directory stream" which can be used with
350 * seekdir to go back to an old entry. We simply return the value in stat.
353 vlc_telldir (DIR * dirp)
362 return dirp->dd_stat;
368 * Seek to an entry previously returned by telldir. We rewind the directory
369 * and call readdir repeatedly until either dd_stat is the position number
370 * or -1 (off the end). This is not perfect, in that the directory may
371 * have changed while we weren't looking. But that is probably the case with
375 vlc_seekdir (DIR * dirp, long lPos)
387 /* Seeking to an invalid position. */
394 if (dirp->dd_handle != INVALID_HANDLE_VALUE)
396 FindClose ((HANDLE)dirp->dd_handle);
398 dirp->dd_handle = INVALID_HANDLE_VALUE;
403 /* Rewind and read forward to the appropriate index. */
404 vlc_rewinddir (dirp);
406 while ((dirp->dd_stat < lPos) && vlc_readdir (dirp))