MISR Toolkit  1.5.1
dirent.c
Go to the documentation of this file.
1 /*
2  * @(#)msd_dir.c 1.4 87/11/06 Public Domain.
3  *
4  * A public domain implementation of BSD directory routines for
5  * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
6  * August 1897
7  *
8  * Modified by Ian Stewartson, Data Logic (istewart@datlog.co.uk).
9  *
10  * Updates: 1. To support OS/2 1.x
11  * 2. To support HPFS long filenames
12  * 3. To support OS/2 2.x
13  * 4. To support TurboC
14  * 5. To support Windows NT
15  */
16 #ifdef _MSC_VER
17 #define strdup _strdup
18 #define strlwr _strlwr
19 #endif
20 
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 
26 #include <malloc.h>
27 
28 #include <string.h>
29 #include <limits.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <dirent_win32.h>
33 
34 
35 #define WIN32_LEAN_AND_MEAN
36 #include <windows.h>
37 
38 #define FILE_NAME_E cFileName
39 #define OS_CloseFH(a) FindClose (a)
40 #define FIND_BUFFER WIN32_FIND_DATA
41 #define DISABLE_HARD_ERRORS SetErrorMode (0)
42 #define ENABLE_HARD_ERRORS SetErrorMode (SEM_FAILCRITICALERRORS | \
43  SEM_NOOPENFILEERRORBOX);
44 
45 # define ERROR_EMPTY_DIR ERROR_FILE_NOT_FOUND
46 
47 # define ATTRIBUTES (_A_SUBDIR | _A_HIDDEN | _A_SYSTEM | \
48  _A_NORMAL | _A_RDONLY | _A_ARCH)
49 
50 /*
51  * missing ??
52  */
53 
54 #ifndef ENOTDIR
55 # define ENOTDIR 120 /* Not a directory */
56 #endif
57 
58 #ifndef S_IFMT
59 # define S_IFMT 0xf000 /* type of file */
60 #endif
61 
62 #ifndef S_ISDIR
63 # define S_ISDIR(m) ((((m) & S_IFMT) == S_IFDIR))
64 #endif
65 
66 /*
67  * Internals
68  */
69 
70 typedef struct _dircontents DIRCONT;
71 static void free_dircontents (DIRCONT *);
72 
73 /*
74  * Open the directory stream
75  */
76 
77 DIR *
79  const char *name;
80 {
81  struct stat statb;
82  DIR *dirp;
83  char *last;
84  DIRCONT *dp;
85  char *nbuf;
86  int len = strlen (name);
87  unsigned long rc;
88  FIND_BUFFER dtabuf;
89  HANDLE d_handle;
90  bool HPFS = FALSE;
91 
92  if (!len)
93  {
94  errno = ENOTDIR;
95  return (DIR *)NULL;
96  }
97 
98  if ((nbuf = malloc (len + 5)) == (char *)NULL)
99  return (DIR *) NULL;
100 
101  strcpy (nbuf, name);
102  last = &nbuf[len - 1];
103 
104 /* Ok, DOS is very picky about its directory names. The following are
105  * valid.
106  *
107  * c:/
108  * c:.
109  * c:name/name1
110  *
111  * c:name/ is not valid
112  */
113 
114  if (((*last == '\\') || (*last == '/')) && (len > 1) &&
115  (!((len == 3) && (name[1] == ':'))))
116  *(last--) = 0;
117 
118 /* Check its a directory */
119 
121  rc = stat (nbuf, &statb);
123 
124  if (rc)
125  {
126  free (nbuf);
127  return (DIR *) NULL;
128  }
129 
130  if (!S_ISDIR (statb.st_mode))
131  {
132  free (nbuf);
133  errno = ENOTDIR;
134  return (DIR *)NULL;
135  }
136 
137  if ((dirp = (DIR *) malloc (sizeof (DIR))) == (DIR *) NULL)
138  {
139  free (nbuf);
140  return (DIR *) NULL;
141  }
142 
143 /* Set up to find everything */
144 
145  if ((*last != '\\') && (*last != '/'))
146  strcat (last, "/");
147 
148  strcat (last, "*.*");
149 
150 /* Find the file system type */
151 
152  HPFS = IsHPFSFileSystem (nbuf);
153 
154  dirp->dd_loc = 0;
155  dirp->dd_cp = (DIRCONT *) NULL;
156  dirp->dd_contents = (DIRCONT *) NULL;
157 
159 
160  d_handle = FindFirstFile (nbuf, &dtabuf);
161  rc = (d_handle == INVALID_HANDLE_VALUE) ? GetLastError () : 0;
162 
164 
165 /* Check for errors */
166 
167  if (rc)
168  {
169  free (nbuf);
170 
171 /* Empty directory */
172 
173 #if defined (ERROR_EMPTY_DIR)
174  if (rc == ERROR_EMPTY_DIR)
175  return dirp;
176 #endif
177 
178  free (dirp);
179  return (DIR *) NULL;
180  }
181 
182 /* Process the directory */
183 
184  do
185  {
186  if (((dp = (DIRCONT *) malloc (sizeof (DIRCONT))) == (DIRCONT *)NULL) ||
187  ((dp->_d_entry = strdup (dtabuf.FILE_NAME_E)) == (char *) NULL))
188  {
189  if (dp->_d_entry != (char *)NULL)
190  free ((char *)dp);
191 
192  free (nbuf);
193  free_dircontents (dirp->dd_contents);
194 
195  OS_CloseFH (d_handle);
196  return (DIR *) NULL;
197  }
198 
199  if (!HPFS)
200  strlwr (dp->_d_entry);
201 
202  if (dirp->dd_contents != (DIRCONT *) NULL)
203  dirp->dd_cp = dirp->dd_cp->_d_next = dp;
204 
205  else
206  dirp->dd_contents = dirp->dd_cp = dp;
207 
208  dp->_d_next = (DIRCONT *) NULL;
209 
210  } while (FindNextFile (d_handle, &dtabuf));
211 
212  dirp->dd_cp = dirp->dd_contents;
213  free (nbuf);
214 
215  OS_CloseFH (d_handle);
216  return dirp;
217 }
218 
219 
220 /*
221  * Close the directory stream
222  */
223 
224 int
225 closedir (dirp)
226  DIR *dirp;
227 {
228  if (dirp != (DIR *)NULL)
229  {
231  free ((char *)dirp);
232  }
233 
234  return 0;
235 }
236 
237 /*
238  * Read the next record from the stream
239  */
240 
241 struct dirent *
242 readdir (dirp)
243  DIR *dirp;
244 {
245  static struct dirent dp;
246 
247  if ((dirp == (DIR *)NULL) || (dirp->dd_cp == (DIRCONT *) NULL))
248  return (struct dirent *) NULL;
249 
250  dp.d_reclen = strlen (strcpy (dp.d_name, dirp->dd_cp->_d_entry));
251  dp.d_off = dirp->dd_loc * 32;
252  dp.d_ino = (ino_t)++dirp->dd_loc;
253  dirp->dd_cp = dirp->dd_cp->_d_next;
254 
255  return &dp;
256 }
257 
258 /*
259  * Restart the directory stream
260  */
261 
262 void
263 rewinddir (dirp)
264  DIR *dirp;
265 {
266  seekdir (dirp, (off_t)0);
267 }
268 
269 /*
270  * Move to a know position in the stream
271  */
272 
273 void
274 seekdir (dirp, off)
275  DIR *dirp;
276  off_t off;
277 {
278  long i = off;
279  DIRCONT *dp;
280 
281  if ((dirp == (DIR *)NULL) || (off < 0L))
282  return;
283 
284  for (dp = dirp->dd_contents; (--i >= 0) && (dp != (DIRCONT *)NULL);
285  dp = dp->_d_next)
286  ;
287 
288  dirp->dd_loc = off - (i + 1);
289  dirp->dd_cp = dp;
290 }
291 
292 /*
293  * Get the current position
294  */
295 
296 off_t
297 telldir(dirp)
298  DIR *dirp;
299 {
300  return (dirp == (DIR *)NULL) ? (off_t) -1 : dirp->dd_loc;
301 }
302 
303 /*
304  * Release the internal structure
305  */
306 
307 static void
309  DIRCONT *dp;
310 {
311  DIRCONT *odp;
312 
313  while ((odp = dp) != (DIRCONT *)NULL)
314  {
315  if (dp->_d_entry != (char *)NULL)
316  free (dp->_d_entry);
317 
318  dp = dp->_d_next;
319  free ((char *)odp);
320  }
321 }
322 
323 
324 /*
325  * Windows NT version
326  */
327 
328 bool
329 IsHPFSFileSystem (directory)
330  char *directory;
331 {
332  char bName[4];
333  DWORD flags;
334  DWORD maxname;
335  BOOL rc;
336  unsigned int nDrive;
337  char szCurDir [MAX_PATH];
338 
339  if (isalpha (directory[0]) && (directory[1] == ':'))
340  nDrive = toupper (directory[0]) - '@';
341 
342  else
343  {
344  GetCurrentDirectory (MAX_PATH, szCurDir);
345  nDrive = szCurDir[0] - 'A' + 1;
346  }
347 
348 /* Set up the drive name */
349 
350  strcpy (bName, "x:\\");
351  bName[0] = (char) (nDrive + '@');
352 
353 /* Read the volume info, if we fail - assume non-HPFS */
354 
356 
357  rc = GetVolumeInformation (bName, (LPTSTR)NULL, 0, (LPDWORD)NULL,
358  &maxname, &flags, (LPTSTR)NULL, 0);
360 
361  return ((rc) && (flags & (FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED)))
362  ? TRUE : FALSE;
363 }
364 
HDFFCLIBAPI intf * len
#define FALSE
Definition: odldef.h:53
#define ENOTDIR
Definition: dirent.c:55
struct _dircontents * _d_next
Definition: dirent_win32.h:50
#define ENABLE_HARD_ERRORS
Definition: dirent.c:42
int closedir(DIR *dirp)
Definition: dirent.c:225
#define OS_CloseFH(a)
Definition: dirent.c:39
#define FIND_BUFFER
Definition: dirent.c:40
off_t telldir(DIR *dirp)
Definition: dirent.c:297
HDFFCLIBAPI _fcd name
struct _dircontents * dd_contents
Definition: dirent_win32.h:56
void rewinddir(DIR *dirp)
Definition: dirent.c:263
#define TRUE
Definition: odldef.h:49
bool IsHPFSFileSystem(char *directory)
Definition: dirent.c:329
void seekdir(DIR *dirp, off_t off)
Definition: dirent.c:274
wchar_t d_reclen
Definition: dirent_win32.h:21
struct dirent * readdir(DIR *dirp)
Definition: dirent.c:242
ino_t d_ino
Definition: dirent_win32.h:19
#define ERROR_EMPTY_DIR
Definition: dirent.c:45
char * _d_entry
Definition: dirent_win32.h:49
HDFFCLIBAPI intf intf * flags
struct _dircontents * dd_cp
Definition: dirent_win32.h:57
#define S_ISDIR(m)
Definition: dirent.c:63
char d_name[MAXNAMLEN+1]
Definition: dirent_win32.h:22
off_t d_off
Definition: dirent_win32.h:20
#define DISABLE_HARD_ERRORS
Definition: dirent.c:41
DIR * opendir(char *name) const
Definition: dirent.c:78
long dd_loc
Definition: dirent_win32.h:55
static void free_dircontents(DIRCONT *)
Definition: dirent.c:308

MISR Toolkit - Copyright © 2005 - 2020 Jet Propulsion Laboratory
Generated on Fri Jun 19 2020 22:49:51