]> git.sesse.net Git - vlc/blob - src/extras/dirent.c
* ALL: WinCE compilation fixes (mostly nonexistent headers). A lot of
[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.3 $
13  * $Author: sam $
14  * $Date: 2002/11/10 18:04:23 $
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       snprintf (szFullPath, MAX_PATH, "%s", szPath);
93       szFullPath[0] = '\\';
94     }
95   else
96     {
97       snprintf (szFullPath, MAX_PATH, "\\%s", szPath );
98     }
99 #else
100   _fullpath (szFullPath, szPath, MAX_PATH);
101 #endif
102
103   /* Allocate enough space to store DIR structure and the complete
104    * directory path given. */
105   nd = (DIR *) malloc (sizeof (DIR) + strlen (szFullPath) + strlen (SLASH) +
106                        strlen (SUFFIX));
107
108   if (!nd)
109     {
110       /* Error, out of memory. */
111       errno = ENOMEM;
112       return (DIR *) 0;
113     }
114
115   /* Create the search expression. */
116   strcpy (nd->dd_name, szFullPath);
117
118   /* Add on a slash if the path does not end with one. */
119   if (nd->dd_name[0] != '\0' &&
120       nd->dd_name[strlen (nd->dd_name) - 1] != '/' &&
121       nd->dd_name[strlen (nd->dd_name) - 1] != '\\')
122     {
123       strcat (nd->dd_name, SLASH);
124     }
125
126   /* Add on the search pattern */
127   strcat (nd->dd_name, SUFFIX);
128
129   /* Initialize handle to -1 so that a premature closedir doesn't try
130    * to call FindClose on it. */
131   nd->dd_handle = -1;
132
133   /* Initialize the status. */
134   nd->dd_stat = 0;
135
136   /* Initialize the dirent structure. ino and reclen are invalid under
137    * Win32, and name simply points at the appropriate part of the
138    * findfirst_t structure. */
139   nd->dd_dir.d_ino = 0;
140   nd->dd_dir.d_reclen = 0;
141   nd->dd_dir.d_namlen = 0;
142   nd->dd_dir.d_name = nd->dd_dta.cFileName;
143
144   return nd;
145 }
146
147
148 /*
149  * readdir
150  *
151  * Return a pointer to a dirent structure filled with the information on the
152  * next entry in the directory.
153  */
154 struct dirent *
155 readdir (DIR * dirp)
156 {
157   errno = 0;
158
159   /* Check for valid DIR struct. */
160   if (!dirp)
161     {
162       errno = EFAULT;
163       return (struct dirent *) 0;
164     }
165
166   if (dirp->dd_dir.d_name != dirp->dd_dta.cFileName)
167     {
168       /* The structure does not seem to be set up correctly. */
169       errno = EINVAL;
170       return (struct dirent *) 0;
171     }
172
173   if (dirp->dd_stat < 0)
174     {
175       /* We have already returned all files in the directory
176        * (or the structure has an invalid dd_stat). */
177       return (struct dirent *) 0;
178     }
179   else if (dirp->dd_stat == 0)
180     {
181       /* We haven't started the search yet. */
182       /* Start the search */
183       dirp->dd_handle = FindFirstFile (dirp->dd_name, &(dirp->dd_dta));
184
185           if (dirp->dd_handle == -1)
186         {
187           /* Whoops! Seems there are no files in that
188            * directory. */
189           dirp->dd_stat = -1;
190         }
191       else
192         {
193           dirp->dd_stat = 1;
194         }
195     }
196   else
197     {
198       /* Get the next search entry. */
199       if (FindNextFile (dirp->dd_handle, &(dirp->dd_dta)))
200         {
201           /* We are off the end or otherwise error. */
202           FindClose (dirp->dd_handle);
203           dirp->dd_handle = -1;
204           dirp->dd_stat = -1;
205         }
206       else
207         {
208           /* Update the status to indicate the correct
209            * number. */
210           dirp->dd_stat++;
211         }
212     }
213
214   if (dirp->dd_stat > 0)
215     {
216       /* Successfully got an entry. Everything about the file is
217        * already appropriately filled in except the length of the
218        * file name. */
219       dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name);
220       return &dirp->dd_dir;
221     }
222
223   return (struct dirent *) 0;
224 }
225
226
227 /*
228  * closedir
229  *
230  * Frees up resources allocated by opendir.
231  */
232 int
233 closedir (DIR * dirp)
234 {
235   int rc;
236
237   errno = 0;
238   rc = 0;
239
240   if (!dirp)
241     {
242       errno = EFAULT;
243       return -1;
244     }
245
246   if (dirp->dd_handle != -1)
247     {
248       rc = FindClose (dirp->dd_handle);
249     }
250
251   /* Delete the dir structure. */
252   free (dirp);
253
254   return rc;
255 }
256
257 /*
258  * rewinddir
259  *
260  * Return to the beginning of the directory "stream". We simply call findclose
261  * and then reset things like an opendir.
262  */
263 void
264 rewinddir (DIR * dirp)
265 {
266   errno = 0;
267
268   if (!dirp)
269     {
270       errno = EFAULT;
271       return;
272     }
273
274   if (dirp->dd_handle != -1)
275     {
276       FindClose (dirp->dd_handle);
277     }
278
279   dirp->dd_handle = -1;
280   dirp->dd_stat = 0;
281 }
282
283 /*
284  * telldir
285  *
286  * Returns the "position" in the "directory stream" which can be used with
287  * seekdir to go back to an old entry. We simply return the value in stat.
288  */
289 long
290 telldir (DIR * dirp)
291 {
292   errno = 0;
293
294   if (!dirp)
295     {
296       errno = EFAULT;
297       return -1;
298     }
299   return dirp->dd_stat;
300 }
301
302 /*
303  * seekdir
304  *
305  * Seek to an entry previously returned by telldir. We rewind the directory
306  * and call readdir repeatedly until either dd_stat is the position number
307  * or -1 (off the end). This is not perfect, in that the directory may
308  * have changed while we weren't looking. But that is probably the case with
309  * any such system.
310  */
311 void
312 seekdir (DIR * dirp, long lPos)
313 {
314   errno = 0;
315
316   if (!dirp)
317     {
318       errno = EFAULT;
319       return;
320     }
321
322   if (lPos < -1)
323     {
324       /* Seeking to an invalid position. */
325       errno = EINVAL;
326       return;
327     }
328   else if (lPos == -1)
329     {
330       /* Seek past end. */
331       if (dirp->dd_handle != -1)
332         {
333           FindClose (dirp->dd_handle);
334         }
335       dirp->dd_handle = -1;
336       dirp->dd_stat = -1;
337     }
338   else
339     {
340       /* Rewind and read forward to the appropriate index. */
341       rewinddir (dirp);
342
343       while ((dirp->dd_stat < lPos) && readdir (dirp))
344         ;
345     }
346 }