whitespace fixes
[platform/upstream/gstreamer.git] / win32 / 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  * Resource leaks fixed by <steve.lhomme@free.fr>
13  *
14  *
15  * $Revision$
16  * $Author$
17  * $Date$
18  *
19  */
20
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <io.h>
25 #include <direct.h>
26 #include <dirent.h>
27 #include <gtchar.h>
28 #define SUFFIX  _T("*")
29 #define SLASH   _T("\\")
30
31 #include <stdio.h>
32
33 #define WIN32_LEAN_AND_MEAN
34 #include <windows.h>            /* for GetFileAttributes */
35
36 /*
37  * opendir
38  *
39  * Returns a pointer to a DIR structure appropriately filled in to begin
40  * searching a directory.
41  */
42 _TDIR *
43 _topendir (const _TCHAR * szPath)
44 {
45   _TDIR *nd;
46   unsigned int rc;
47   _TCHAR szFullPath[MAX_PATH];
48
49   errno = 0;
50
51   if (!szPath) {
52     errno = EFAULT;
53     return (_TDIR *) 0;
54   }
55
56   if (szPath[0] == _T ('\0')) {
57     errno = ENOTDIR;
58     return (_TDIR *) 0;
59   }
60
61   /* Attempt to determine if the given path really is a directory. */
62   rc = GetFileAttributes (szPath);
63   if (rc == (unsigned int) -1) {
64     /* call GetLastError for more error info */
65     errno = ENOENT;
66     return (_TDIR *) 0;
67   }
68   if (!(rc & FILE_ATTRIBUTE_DIRECTORY)) {
69     /* Error, entry exists but not a directory. */
70     errno = ENOTDIR;
71     return (_TDIR *) 0;
72   }
73
74   /* Make an absolute pathname.  */
75   _tfullpath (szFullPath, szPath, MAX_PATH);
76
77   /* Allocate enough space to store DIR structure and the complete
78    * directory path given. */
79   nd = (_TDIR *) malloc (sizeof (_TDIR) + (_tcslen (szFullPath) +
80           _tcslen (SLASH) + _tcslen (SUFFIX) + 1) * sizeof (_TCHAR));
81
82   if (!nd) {
83     /* Error, out of memory. */
84     errno = ENOMEM;
85     return (_TDIR *) 0;
86   }
87
88   /* Create the search expression. */
89   _tcscpy (nd->dd_name, szFullPath);
90
91   /* Add on a slash if the path does not end with one. */
92   if (nd->dd_name[0] != _T ('\0') &&
93       nd->dd_name[_tcslen (nd->dd_name) - 1] != _T ('/') &&
94       nd->dd_name[_tcslen (nd->dd_name) - 1] != _T ('\\')) {
95     _tcscat (nd->dd_name, SLASH);
96   }
97
98   /* Add on the search pattern */
99   _tcscat (nd->dd_name, SUFFIX);
100
101   /* Initialize handle to -1 so that a premature closedir doesn't try
102    * to call _findclose on it. */
103   nd->dd_handle = -1;
104
105   /* Initialize the status. */
106   nd->dd_stat = 0;
107
108   /* Initialize the dirent structure. ino and reclen are invalid under
109    * Win32, and name simply points at the appropriate part of the
110    * findfirst_t structure. */
111   nd->dd_dir.d_ino = 0;
112   nd->dd_dir.d_reclen = 0;
113   nd->dd_dir.d_namlen = 0;
114   // Added by jcsston 02/04/2004, memset was writing to a bad pointer
115   nd->dd_dir.d_name = malloc (FILENAME_MAX);
116   // End add
117   memset (nd->dd_dir.d_name, 0, FILENAME_MAX);
118
119   return nd;
120 }
121
122
123 /*
124  * readdir
125  *
126  * Return a pointer to a dirent structure filled with the information on the
127  * next entry in the directory.
128  */
129 struct _tdirent *
130 _treaddir (_TDIR * dirp)
131 {
132   errno = 0;
133
134   /* Check for valid DIR struct. */
135   if (!dirp) {
136     errno = EFAULT;
137     return (struct _tdirent *) 0;
138   }
139
140   if (dirp->dd_stat < 0) {
141     /* We have already returned all files in the directory
142      * (or the structure has an invalid dd_stat). */
143     return (struct _tdirent *) 0;
144   } else if (dirp->dd_stat == 0) {
145     /* We haven't started the search yet. */
146     /* Start the search */
147     dirp->dd_handle = _tfindfirst (dirp->dd_name, &(dirp->dd_dta));
148
149     if (dirp->dd_handle == -1) {
150       /* Whoops! Seems there are no files in that
151        * directory. */
152       dirp->dd_stat = -1;
153     } else {
154       dirp->dd_stat = 1;
155     }
156   } else {
157     /* Get the next search entry. */
158     if (_tfindnext (dirp->dd_handle, &(dirp->dd_dta))) {
159       /* We are off the end or otherwise error.
160          _findnext sets errno to ENOENT if no more file
161          Undo this. */
162       DWORD winerr = GetLastError ();
163
164       if (winerr == ERROR_NO_MORE_FILES)
165         errno = 0;
166       _findclose (dirp->dd_handle);
167       dirp->dd_handle = -1;
168       dirp->dd_stat = -1;
169     } else {
170       /* Update the status to indicate the correct
171        * number. */
172       dirp->dd_stat++;
173     }
174   }
175
176   if (dirp->dd_stat > 0) {
177     /* Successfully got an entry. Everything about the file is
178      * already appropriately filled in except the length of the
179      * file name. */
180     dirp->dd_dir.d_namlen = _tcslen (dirp->dd_dta.name);
181     _tcscpy (dirp->dd_dir.d_name, dirp->dd_dta.name);
182     return &dirp->dd_dir;
183   }
184
185   return (struct _tdirent *) 0;
186 }
187
188
189 /*
190  * closedir
191  *
192  * Frees up resources allocated by opendir.
193  */
194 int
195 _tclosedir (_TDIR * dirp)
196 {
197   int rc;
198
199   errno = 0;
200   rc = 0;
201
202   if (!dirp) {
203     errno = EFAULT;
204     return -1;
205   }
206
207   if (dirp->dd_handle != -1) {
208     rc = _findclose (dirp->dd_handle);
209   }
210
211   if (dirp->dd_dir.d_name)
212     free (dirp->dd_dir.d_name);
213
214   /* Delete the dir structure. */
215   free (dirp);
216
217   return rc;
218 }
219
220 /*
221  * rewinddir
222  *
223  * Return to the beginning of the directory "stream". We simply call findclose
224  * and then reset things like an opendir.
225  */
226 void
227 _trewinddir (_TDIR * dirp)
228 {
229   errno = 0;
230
231   if (!dirp) {
232     errno = EFAULT;
233     return;
234   }
235
236   if (dirp->dd_handle != -1) {
237     _findclose (dirp->dd_handle);
238   }
239
240   dirp->dd_handle = -1;
241   dirp->dd_stat = 0;
242 }
243
244 /*
245  * telldir
246  *
247  * Returns the "position" in the "directory stream" which can be used with
248  * seekdir to go back to an old entry. We simply return the value in stat.
249  */
250 long
251 _ttelldir (_TDIR * dirp)
252 {
253   errno = 0;
254
255   if (!dirp) {
256     errno = EFAULT;
257     return -1;
258   }
259   return dirp->dd_stat;
260 }
261
262 /*
263  * seekdir
264  *
265  * Seek to an entry previously returned by telldir. We rewind the directory
266  * and call readdir repeatedly until either dd_stat is the position number
267  * or -1 (off the end). This is not perfect, in that the directory may
268  * have changed while we weren't looking. But that is probably the case with
269  * any such system.
270  */
271 void
272 _tseekdir (_TDIR * dirp, long lPos)
273 {
274   errno = 0;
275
276   if (!dirp) {
277     errno = EFAULT;
278     return;
279   }
280
281   if (lPos < -1) {
282     /* Seeking to an invalid position. */
283     errno = EINVAL;
284     return;
285   } else if (lPos == -1) {
286     /* Seek past end. */
287     if (dirp->dd_handle != -1) {
288       _findclose (dirp->dd_handle);
289     }
290     dirp->dd_handle = -1;
291     dirp->dd_stat = -1;
292   } else {
293     /* Rewind and read forward to the appropriate index. */
294     _trewinddir (dirp);
295
296     while ((dirp->dd_stat < lPos) && _treaddir (dirp));
297   }
298 }