]> git.sesse.net Git - vlc/blob - src/extras/dirent.c
* ./bootstrap: bootstrap now requires the --config flag. With no arguments
[vlc] / src / extras / dirent.c
1 /*
2  * dirent.c
3  *
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
7  *
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>
11  *      
12  * $Revision: 1.6 $
13  * $Author: sam $
14  * $Date: 2002/11/13 20:51:04 $
15  *
16  */
17
18 #include "config.h"
19
20 #include <stdlib.h>
21 #ifdef HAVE_ERRNO_H
22 #   include <errno.h>
23 #else
24     static int errno;
25     /* FIXME: anything clever to put here? */
26 #   define EFAULT 12
27 #   define ENOTDIR 12
28 #   define ENOENT 12
29 #   define ENOMEM 12
30 #   define EINVAL 12
31 #endif
32 #include <string.h>
33 #ifndef UNDER_CE
34 #   include <io.h>
35 #   include <direct.h>
36 #endif
37
38 #define WIN32_LEAN_AND_MEAN
39 #include <windows.h> /* for GetFileAttributes */
40
41 #include "dirent.h"
42
43 #define SUFFIX  "*"
44 #define SLASH   "\\"
45
46 /*
47  * opendir
48  *
49  * Returns a pointer to a DIR structure appropriately filled in to begin
50  * searching a directory.
51  */
52 DIR * 
53 opendir (const CHAR *szPath)
54 {
55   DIR *nd;
56   unsigned int rc;
57   CHAR szFullPath[MAX_PATH];
58         
59   errno = 0;
60
61   if (!szPath)
62     {
63       errno = EFAULT;
64       return (DIR *) 0;
65     }
66
67   if (szPath[0] == '\0')
68     {
69       errno = ENOTDIR;
70       return (DIR *) 0;
71     }
72
73   /* Attempt to determine if the given path really is a directory. */
74   rc = GetFileAttributes (szPath);
75   if (rc == -1)
76     {
77       /* call GetLastError for more error info */
78       errno = ENOENT;
79       return (DIR *) 0;
80     }
81   if (!(rc & FILE_ATTRIBUTE_DIRECTORY))
82     {
83       /* Error, entry exists but not a directory. */
84       errno = ENOTDIR;
85       return (DIR *) 0;
86     }
87
88   /* Make an absolute pathname.  */
89 #if defined( UNDER_CE )
90   if (szPath[0] == '\\' || szPath[0] == '/')
91     {
92       sprintf (szFullPath, MAX_PATH, "%s", szPath);
93       szFullPath[0] = '\\';
94     }
95   else
96     {
97       /* FIXME: if I wasn't lazy, I'd check for overflows here. */
98       sprintf (szFullPath, MAX_PATH, "\\%s", szPath );
99     }
100 #else
101   _fullpath (szFullPath, szPath, MAX_PATH);
102 #endif
103
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) +
107                        strlen (SUFFIX));
108
109   if (!nd)
110     {
111       /* Error, out of memory. */
112       errno = ENOMEM;
113       return (DIR *) 0;
114     }
115
116   /* Create the search expression. */
117   strcpy (nd->dd_name, szFullPath);
118
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] != '\\')
123     {
124       strcat (nd->dd_name, SLASH);
125     }
126
127   /* Add on the search pattern */
128   strcat (nd->dd_name, SUFFIX);
129
130   /* Initialize handle to -1 so that a premature closedir doesn't try
131    * to call FindClose on it. */
132   nd->dd_handle = -1;
133
134   /* Initialize the status. */
135   nd->dd_stat = 0;
136
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;
144
145   return nd;
146 }
147
148
149 /*
150  * readdir
151  *
152  * Return a pointer to a dirent structure filled with the information on the
153  * next entry in the directory.
154  */
155 struct dirent *
156 readdir (DIR * dirp)
157 {
158   errno = 0;
159
160   /* Check for valid DIR struct. */
161   if (!dirp)
162     {
163       errno = EFAULT;
164       return (struct dirent *) 0;
165     }
166
167   if (dirp->dd_dir.d_name != dirp->dd_dta.cFileName)
168     {
169       /* The structure does not seem to be set up correctly. */
170       errno = EINVAL;
171       return (struct dirent *) 0;
172     }
173
174   if (dirp->dd_stat < 0)
175     {
176       /* We have already returned all files in the directory
177        * (or the structure has an invalid dd_stat). */
178       return (struct dirent *) 0;
179     }
180   else if (dirp->dd_stat == 0)
181     {
182       /* We haven't started the search yet. */
183       /* Start the search */
184       dirp->dd_handle = (long)FindFirstFile (dirp->dd_name, &(dirp->dd_dta));
185
186           if (dirp->dd_handle == -1)
187         {
188           /* Whoops! Seems there are no files in that
189            * directory. */
190           dirp->dd_stat = -1;
191         }
192       else
193         {
194           dirp->dd_stat = 1;
195         }
196     }
197   else
198     {
199       /* Get the next search entry. */
200       if (FindNextFile ((HANDLE)dirp->dd_handle, &(dirp->dd_dta)))
201         {
202           /* We are off the end or otherwise error. */
203           FindClose ((HANDLE)dirp->dd_handle);
204           dirp->dd_handle = -1;
205           dirp->dd_stat = -1;
206         }
207       else
208         {
209           /* Update the status to indicate the correct
210            * number. */
211           dirp->dd_stat++;
212         }
213     }
214
215   if (dirp->dd_stat > 0)
216     {
217       /* Successfully got an entry. Everything about the file is
218        * already appropriately filled in except the length of the
219        * file name. */
220       dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name);
221       return &dirp->dd_dir;
222     }
223
224   return (struct dirent *) 0;
225 }
226
227
228 /*
229  * closedir
230  *
231  * Frees up resources allocated by opendir.
232  */
233 int
234 closedir (DIR * dirp)
235 {
236   int rc;
237
238   errno = 0;
239   rc = 0;
240
241   if (!dirp)
242     {
243       errno = EFAULT;
244       return -1;
245     }
246
247   if (dirp->dd_handle != -1)
248     {
249       rc = FindClose ((HANDLE)dirp->dd_handle);
250     }
251
252   /* Delete the dir structure. */
253   free (dirp);
254
255   return rc;
256 }
257
258 /*
259  * rewinddir
260  *
261  * Return to the beginning of the directory "stream". We simply call findclose
262  * and then reset things like an opendir.
263  */
264 void
265 rewinddir (DIR * dirp)
266 {
267   errno = 0;
268
269   if (!dirp)
270     {
271       errno = EFAULT;
272       return;
273     }
274
275   if (dirp->dd_handle != -1)
276     {
277       FindClose ((HANDLE)dirp->dd_handle);
278     }
279
280   dirp->dd_handle = -1;
281   dirp->dd_stat = 0;
282 }
283
284 /*
285  * telldir
286  *
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.
289  */
290 long
291 telldir (DIR * dirp)
292 {
293   errno = 0;
294
295   if (!dirp)
296     {
297       errno = EFAULT;
298       return -1;
299     }
300   return dirp->dd_stat;
301 }
302
303 /*
304  * seekdir
305  *
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
310  * any such system.
311  */
312 void
313 seekdir (DIR * dirp, long lPos)
314 {
315   errno = 0;
316
317   if (!dirp)
318     {
319       errno = EFAULT;
320       return;
321     }
322
323   if (lPos < -1)
324     {
325       /* Seeking to an invalid position. */
326       errno = EINVAL;
327       return;
328     }
329   else if (lPos == -1)
330     {
331       /* Seek past end. */
332       if (dirp->dd_handle != -1)
333         {
334           FindClose ((HANDLE)dirp->dd_handle);
335         }
336       dirp->dd_handle = -1;
337       dirp->dd_stat = -1;
338     }
339   else
340     {
341       /* Rewind and read forward to the appropriate index. */
342       rewinddir (dirp);
343
344       while ((dirp->dd_stat < lPos) && readdir (dirp))
345         ;
346     }
347 }