]> git.sesse.net Git - vlc/blob - src/extras/dirent.c
Use var_Inherit* instead of var_CreateGet*.
[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 #include <stdio.h>
22
23 #include <errno.h>
24 #include <string.h>
25 #ifndef UNDER_CE
26 #   include <io.h>
27 #   include <direct.h>
28 #else
29 #   define FILENAME_MAX (260)
30 #endif
31
32 #define WIN32_LEAN_AND_MEAN
33 #include <windows.h> /* for GetFileAttributes */
34
35 #include <tchar.h>
36 #define SUFFIX  "*"
37 #define SLASH   "\\"
38
39 struct dirent
40 {
41     long        d_ino;        /* Always zero. */
42     unsigned short    d_reclen;    /* Always zero. */
43     unsigned short    d_namlen;    /* Length of name in d_name. */
44     char            d_name[FILENAME_MAX]; /* File name. */
45 };
46
47 typedef struct
48 {
49     /* disk transfer area for this dir */
50     WIN32_FIND_DATA        dd_dta;
51
52     /* dirent struct to return from dir (NOTE: this makes this thread
53      * safe as long as only one thread uses a particular DIR struct at
54      * a time) */
55     struct dirent        dd_dir;
56
57     /* findnext handle */
58     HANDLE            dd_handle;
59
60     /*
61          * Status of search:
62      *   0 = not started yet (next entry to read is first entry)
63      *  -1 = off the end
64      *   positive = 0 based index of next entry
65      */
66     int            dd_stat;
67
68     /* given path for dir with search pattern (struct is extended) */
69     char            dd_name[1];
70 } DIR;
71
72 /*
73  * opendir
74  *
75  * Returns a pointer to a DIR structure appropriately filled in to begin
76  * searching a directory.
77  */
78 DIR *
79 vlc_opendir (const CHAR *szPath)
80 {
81   DIR *nd;
82   unsigned int rc;
83   CHAR szFullPath[MAX_PATH];
84
85   errno = 0;
86
87   if (!szPath)
88     {
89       errno = EFAULT;
90       return (DIR *) 0;
91     }
92
93   if (szPath[0] == '\0')
94     {
95       errno = ENOTDIR;
96       return (DIR *) 0;
97     }
98
99   /* Attempt to determine if the given path really is a directory. */
100 #ifdef UNICODE
101   {
102     wchar_t szPathTmp[MAX_PATH];
103     mbstowcs( szPathTmp, szPath, MAX_PATH );
104     szPathTmp[MAX_PATH-1] = 0;
105     rc = GetFileAttributes (szPathTmp);
106   }
107 #else
108   rc = GetFileAttributes (szPath);
109 #endif
110   if (rc == (unsigned int)-1)
111     {
112       /* call GetLastError for more error info */
113       errno = ENOENT;
114       return (DIR *) 0;
115     }
116   if (!(rc & FILE_ATTRIBUTE_DIRECTORY))
117     {
118       /* Error, entry exists but not a directory. */
119       errno = ENOTDIR;
120       return (DIR *) 0;
121     }
122
123   /* Make an absolute pathname.  */
124 #if defined( UNDER_CE )
125   if (szPath[0] == '\\' || szPath[0] == '/')
126     {
127       sprintf (szFullPath, "%s", szPath);
128       szFullPath[0] = '\\';
129     }
130   else
131     {
132       wchar_t szFullPathTmp[MAX_PATH];
133       if (GetModuleFileName( NULL, szFullPathTmp, MAX_PATH ) )
134         {
135           wcstombs( szFullPath, szFullPathTmp, MAX_PATH );
136           szFullPath[MAX_PATH-1] = 0;
137         }
138       else
139         {
140           /* FIXME: if I wasn't lazy, I'd check for overflows here. */
141           sprintf (szFullPath, "\\%s", szPath );
142         }
143     }
144 #else
145   _fullpath (szFullPath, szPath, MAX_PATH);
146 #endif
147
148   /* Allocate enough space to store DIR structure and the complete
149    * directory path given. */
150   nd = (DIR *) malloc (sizeof (DIR) + strlen (szFullPath) + sizeof (SLASH) +
151                        sizeof (SUFFIX));
152
153   if (!nd)
154     {
155       /* Error, out of memory. */
156       errno = ENOMEM;
157       return (DIR *) 0;
158     }
159
160   /* Create the search expression. */
161   strcpy (nd->dd_name, szFullPath);
162
163   /* Add on a slash if the path does not end with one. */
164   if (nd->dd_name[0] != '\0' &&
165       nd->dd_name[strlen (nd->dd_name) - 1] != '/' &&
166       nd->dd_name[strlen (nd->dd_name) - 1] != '\\')
167     {
168       strcat (nd->dd_name, SLASH);
169     }
170
171   /* Add on the search pattern */
172   strcat (nd->dd_name, SUFFIX);
173
174   /* Initialize handle so that a premature closedir doesn't try
175    * to call FindClose on it. */
176   nd->dd_handle = INVALID_HANDLE_VALUE;
177
178   /* Initialize the status. */
179   nd->dd_stat = 0;
180
181   /* Initialize the dirent structure. ino and reclen are invalid under
182    * Win32, and name simply points at the appropriate part of the
183    * findfirst_t structure. */
184   nd->dd_dir.d_ino = 0;
185   nd->dd_dir.d_reclen = 0;
186   nd->dd_dir.d_namlen = 0;
187   memset (nd->dd_dir.d_name, 0, FILENAME_MAX);
188
189   return nd;
190 }
191
192
193 /*
194  * readdir
195  *
196  * Return a pointer to a dirent structure filled with the information on the
197  * next entry in the directory.
198  */
199 struct dirent *
200 vlc_readdir (DIR * dirp)
201 {
202   errno = 0;
203
204   /* Check for valid DIR struct. */
205   if (!dirp)
206     {
207       errno = EFAULT;
208       return (struct dirent *) 0;
209     }
210
211   if (dirp->dd_stat < 0)
212     {
213       /* We have already returned all files in the directory
214        * (or the structure has an invalid dd_stat). */
215       return (struct dirent *) 0;
216     }
217   else if (dirp->dd_stat == 0)
218     {
219 #ifdef UNICODE
220         wchar_t dd_name[MAX_PATH];
221         mbstowcs( dd_name, dirp->dd_name, MAX_PATH );
222         dd_name[MAX_PATH-1] = 0;
223 #else
224         char *dd_name = dirp->dd_name;
225 #endif
226       /* We haven't started the search yet. */
227       /* Start the search */
228       dirp->dd_handle = FindFirstFile (dd_name, &(dirp->dd_dta));
229
230           if (dirp->dd_handle == INVALID_HANDLE_VALUE)
231         {
232           /* Whoops! Seems there are no files in that
233            * directory. */
234           dirp->dd_stat = -1;
235         }
236       else
237         {
238           dirp->dd_stat = 1;
239         }
240     }
241   else
242     {
243       /* Get the next search entry. */
244       if (!FindNextFile ((HANDLE)dirp->dd_handle, &(dirp->dd_dta)))
245         {
246           /* We are off the end or otherwise error. */
247           FindClose ((HANDLE)dirp->dd_handle);
248           dirp->dd_handle = INVALID_HANDLE_VALUE;
249           dirp->dd_stat = -1;
250         }
251       else
252         {
253           /* Update the status to indicate the correct
254            * number. */
255           dirp->dd_stat++;
256         }
257     }
258
259   if (dirp->dd_stat > 0)
260     {
261       /* Successfully got an entry */
262
263 #ifdef UNICODE
264       char d_name[MAX_PATH];
265       wcstombs( d_name, dirp->dd_dta.cFileName, MAX_PATH );
266       d_name[MAX_PATH-1] = 0;
267 #else
268       char *d_name = dirp->dd_dta.cFileName;
269 #endif
270
271       strcpy (dirp->dd_dir.d_name, d_name);
272       dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name);
273       return &dirp->dd_dir;
274     }
275
276   return (struct dirent *) 0;
277 }
278
279
280 /*
281  * closedir
282  *
283  * Frees up resources allocated by opendir.
284  */
285 int
286 vlc_closedir (DIR * dirp)
287 {
288   int rc;
289
290   errno = 0;
291   rc = 0;
292
293   if (!dirp)
294     {
295       errno = EFAULT;
296       return -1;
297     }
298
299   if (dirp->dd_handle != INVALID_HANDLE_VALUE)
300     {
301       rc = FindClose ((HANDLE)dirp->dd_handle);
302     }
303
304   /* Delete the dir structure. */
305   free (dirp);
306
307   return rc;
308 }
309
310 /*
311  * rewinddir
312  *
313  * Return to the beginning of the directory "stream". We simply call findclose
314  * and then reset things like an opendir.
315  */
316 void
317 vlc_rewinddir (DIR * dirp)
318 {
319   errno = 0;
320
321   if (!dirp)
322     {
323       errno = EFAULT;
324       return;
325     }
326
327   if (dirp->dd_handle != INVALID_HANDLE_VALUE)
328     {
329       FindClose ((HANDLE)dirp->dd_handle);
330     }
331
332   dirp->dd_handle = INVALID_HANDLE_VALUE;
333   dirp->dd_stat = 0;
334 }