root/branches/maintenance/2.2.1/Modelica/C-Sources/win32_dirent.c

Revision 463, 6.9 kB (checked in by hubertus, 22 months ago)

Created maintenance version from Dynasims version with minimal changes (no checksum, 1 graphics, a few improved documentation places, structurallyIncomplete annotations in Visualizers)

Line 
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 * Martin Otter, 2001/01/06:
13 *   - Call to "GetFileAttributes" and "#include <windows.h>"
14 *     replaced by call to "_stat" because this is part of libc.a
15 *   - If no more file found, _findnext sets errno.
16 *     Since this is not an error, errno is reset to zero.
17 *     (otherwise the calling routine cannot check, whether an error
18 *     occured within this function)
19 *   - Initializing the search with findfirst is moved from "readdir"
20 *     to "opendir", in order that in the calling function the
21 *     current directory can be changed after "opendir".
22 */
23
24#include <stdlib.h>
25#include <errno.h>
26#include <string.h>
27#include <io.h>
28#include <direct.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31
32#include "win32_dirent.h"
33#define SUFFIX "*"
34#define  SLASH "\\"
35
36/*
37 * opendir
38 *
39 * Returns a pointer to a DIR structure appropriately filled in to begin
40 * searching a directory.
41 */
42DIR *
43opendir (const char *szPath)
44{
45  DIR *nd;
46
47  errno = 0;
48
49  if (!szPath)
50    {
51      errno = EFAULT;
52      return (DIR *) 0;
53    }
54
55  if (szPath[0] == '\0')
56    {
57      errno = ENOTDIR;
58      return (DIR *) 0;
59    }
60
61  /* Attempt to determine if the given path really is a directory. */
62  {
63#if defined(_MSC_VER)
64      struct _stat fileInfo;
65    if ( _stat(szPath, &fileInfo) != 0 ) {
66#else
67      struct stat fileInfo;
68    if ( stat(szPath, &fileInfo) != 0 ) {
69#endif
70      /* call GetLastError for more error info */
71      errno = ENOENT;
72      return (DIR *) 0;
73    }
74
75    if ( !(fileInfo.st_mode & S_IFDIR) ) {
76      /* Error, entry exists but not a directory. */
77      errno = ENOTDIR;
78      return (DIR *) 0;
79    }
80  }
81
82  /* Allocate enough space to store DIR structure and the complete
83   * directory path given. */
84  nd = (DIR *) malloc (sizeof (DIR) + strlen (szPath) + strlen (SLASH) +
85             strlen (SUFFIX));
86
87  if (!nd)
88    {
89      /* Error, out of memory. */
90      errno = ENOMEM;
91      return (DIR *) 0;
92    }
93
94  /* Create the search expression. */
95  strcpy (nd->dd_name, szPath);
96
97  /* Add on a slash if the path does not end with one. */
98  if (nd->dd_name[0] != '\0' &&
99      nd->dd_name[strlen (nd->dd_name) - 1] != '/' &&
100      nd->dd_name[strlen (nd->dd_name) - 1] != '\\')
101    {
102      strcat (nd->dd_name, SLASH);
103    }
104
105  /* Add on the search pattern */
106  strcat (nd->dd_name, SUFFIX);
107
108  /* Initialize handle to -1 so that a premature closedir doesn't try
109   * to call _findclose on it. */
110  nd->dd_handle = -1;
111
112  /* Initialize the status. */
113  nd->dd_stat = 0;
114
115  /* Initialize the dirent structure. ino and reclen are invalid under
116   * Win32, and name simply points at the appropriate part of the
117   * findfirst_t structure. */
118  nd->dd_dir.d_ino = 0;
119  nd->dd_dir.d_reclen = 0;
120  nd->dd_dir.d_namlen = 0;
121  nd->dd_dir.d_name = nd->dd_dta.name;
122
123
124  /* Start the search, in order that the user may still
125     change the current directory afterwards
126  */
127  nd->dd_handle = _findfirst (nd->dd_name, &(nd->dd_dta));
128  if (nd->dd_handle == -1) {
129     /* Whoops! Seems there are no files in that
130      * directory. */
131     nd->dd_stat = -1;
132  } else {
133     nd->dd_stat = 1;
134  }
135
136  return nd;
137}
138
139
140/*
141 * readdir
142 *
143 * Return a pointer to a dirent structure filled with the information on the
144 * next entry in the directory.
145 */
146struct dirent *
147readdir (DIR * dirp)
148{
149  errno = 0;
150
151  /* Check for valid DIR struct. */
152  if (!dirp)
153    {
154      errno = EFAULT;
155      return (struct dirent *) 0;
156    }
157
158  if (dirp->dd_dir.d_name != dirp->dd_dta.name)
159    {
160      /* The structure does not seem to be set up correctly. */
161      errno = EINVAL;
162      return (struct dirent *) 0;
163    }
164
165  if (dirp->dd_stat < 0)
166    {
167      /* We have already returned all files in the directory
168       * (or the structure has an invalid dd_stat). */
169      return (struct dirent *) 0;
170    }
171  else
172    {
173      /* Get the next search entry. */
174      if (_findnext (dirp->dd_handle, &(dirp->dd_dta)))
175   {
176     /* We are off the end */
177     errno = 0;
178     _findclose (dirp->dd_handle);
179     dirp->dd_handle = -1;
180     dirp->dd_stat = -1;
181   }
182      else
183   {
184     /* Update the status to indicate the correct
185      * number. */
186     dirp->dd_stat++;
187   }
188    }
189
190  if (dirp->dd_stat > 0)
191    {
192      /* Successfully got an entry. Everything about the file is
193       * already appropriately filled in except the length of the
194       * file name. */
195      dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name);
196      return &dirp->dd_dir;
197    }
198
199  return (struct dirent *) 0;
200}
201
202
203/*
204 * closedir
205 *
206 * Frees up resources allocated by opendir.
207 */
208int
209closedir (DIR * dirp)
210{
211  int rc;
212
213  errno = 0;
214  rc = 0;
215
216  if (!dirp)
217    {
218      errno = EFAULT;
219      return -1;
220    }
221
222  if (dirp->dd_handle != -1)
223    {
224      rc = _findclose (dirp->dd_handle);
225    }
226
227  /* Delete the dir structure. */
228  free (dirp);
229
230  return rc;
231}
232
233/*
234 * rewinddir
235 *
236 * Return to the beginning of the directory "stream". We simply call findclose
237 * and then reset things like an opendir.
238 */
239void
240rewinddir (DIR * dirp)
241{
242  errno = 0;
243
244  if (!dirp)
245    {
246      errno = EFAULT;
247      return;
248    }
249
250  if (dirp->dd_handle != -1)
251    {
252      _findclose (dirp->dd_handle);
253    }
254
255  dirp->dd_handle = -1;
256  dirp->dd_stat = 0;
257}
258
259/*
260 * telldir
261 *
262 * Returns the "position" in the "directory stream" which can be used with
263 * seekdir to go back to an old entry. We simply return the value in stat.
264 */
265long
266telldir (DIR * dirp)
267{
268  errno = 0;
269
270  if (!dirp)
271    {
272      errno = EFAULT;
273      return -1;
274    }
275  return dirp->dd_stat;
276}
277
278/*
279 * seekdir
280 *
281 * Seek to an entry previously returned by telldir. We rewind the directory
282 * and call readdir repeatedly until either dd_stat is the position number
283 * or -1 (off the end). This is not perfect, in that the directory may
284 * have changed while we weren't looking. But that is probably the case with
285 * any such system.
286 */
287void
288seekdir (DIR * dirp, long lPos)
289{
290  errno = 0;
291
292  if (!dirp)
293    {
294      errno = EFAULT;
295      return;
296    }
297
298  if (lPos < -1)
299    {
300      /* Seeking to an invalid position. */
301      errno = EINVAL;
302      return;
303    }
304  else if (lPos == -1)
305    {
306      /* Seek past end. */
307      if (dirp->dd_handle != -1)
308   {
309     _findclose (dirp->dd_handle);
310   }
311      dirp->dd_handle = -1;
312      dirp->dd_stat = -1;
313    }
314  else
315    {
316      /* Rewind and read forward to the appropriate index. */
317      rewinddir (dirp);
318
319      while ((dirp->dd_stat < lPos) && readdir (dirp))
320   ;
321    }
322}
Note: See TracBrowser for help on using the browser.