update copyrights in config dir.
[official-gcc.git] / gcc / config / winnt / dirent.c
blob59f7dc1c6effb2a05bec3fd4a5f7092a69b16e09
1 /*
2 * @(#)msd_dir.c 1.4 87/11/06 Public Domain.
4 * A public domain implementation of BSD directory routines for
5 * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
6 * August 1897
8 * Modified by Ian Stewartson, Data Logic (istewart@datlog.co.uk).
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
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <stdio.h>
20 #include <stdlib.h>
22 #include <malloc.h>
24 #include <string.h>
25 #include <limits.h>
26 #include <ctype.h>
27 #include <errno.h>
28 #include <dirent.h>
31 #define WIN32_LEAN_AND_MEAN
32 #include <windows.h>
34 #define FILE_NAME_E cFileName
35 #define OS_CloseFH(a) FindClose (a)
36 #define FIND_BUFFER WIN32_FIND_DATA
37 #define DISABLE_HARD_ERRORS SetErrorMode (0)
38 #define ENABLE_HARD_ERRORS SetErrorMode (SEM_FAILCRITICALERRORS | \
39 SEM_NOOPENFILEERRORBOX);
41 # define ERROR_EMPTY_DIR ERROR_FILE_NOT_FOUND
43 # define ATTRIBUTES (_A_SUBDIR | _A_HIDDEN | _A_SYSTEM | \
44 _A_NORMAL | _A_RDONLY | _A_ARCH)
47 * missing ??
50 #ifndef ENOTDIR
51 # define ENOTDIR 120 /* Not a directory */
52 #endif
54 #ifndef S_IFMT
55 # define S_IFMT 0xf000 /* type of file */
56 #endif
58 #ifndef S_ISDIR
59 # define S_ISDIR(m) ((((m) & S_IFMT) == S_IFDIR))
60 #endif
63 * Internals
66 typedef struct _dircontents DIRCONT;
67 static void free_dircontents (DIRCONT *);
70 * Open the directory stream
73 DIR *
74 opendir (name)
75 const char *name;
77 struct stat statb;
78 DIR *dirp;
79 char *last;
80 DIRCONT *dp;
81 char *nbuf;
82 int len = strlen (name);
83 unsigned long rc;
84 FIND_BUFFER dtabuf;
85 HANDLE d_handle;
86 bool HPFS = FALSE;
88 if (!len)
90 errno = ENOTDIR;
91 return (DIR *)NULL;
94 if ((nbuf = malloc (len + 5)) == (char *)NULL)
95 return (DIR *) NULL;
97 strcpy (nbuf, name);
98 last = &nbuf[len - 1];
100 /* Ok, DOS is very picky about its directory names. The following are
101 * valid.
103 * c:/
104 * c:.
105 * c:name/name1
107 * c:name/ is not valid
110 if (((*last == '\\') || (*last == '/')) && (len > 1) &&
111 (!((len == 3) && (name[1] == ':'))))
112 *(last--) = 0;
114 /* Check its a directory */
116 DISABLE_HARD_ERRORS;
117 rc = stat (nbuf, &statb);
118 ENABLE_HARD_ERRORS;
120 if (rc)
122 free (nbuf);
123 return (DIR *) NULL;
126 if (!S_ISDIR (statb.st_mode))
128 free (nbuf);
129 errno = ENOTDIR;
130 return (DIR *)NULL;
133 if ((dirp = (DIR *) malloc (sizeof (DIR))) == (DIR *) NULL)
135 free (nbuf);
136 return (DIR *) NULL;
139 /* Set up to find everything */
141 if ((*last != '\\') && (*last != '/'))
142 strcat (last, "/");
144 strcat (last, "*.*");
146 /* Find the file system type */
148 HPFS = IsHPFSFileSystem (nbuf);
150 dirp->dd_loc = 0;
151 dirp->dd_cp = (DIRCONT *) NULL;
152 dirp->dd_contents = (DIRCONT *) NULL;
154 DISABLE_HARD_ERRORS;
156 d_handle = FindFirstFile (nbuf, &dtabuf);
157 rc = (d_handle == INVALID_HANDLE_VALUE) ? GetLastError () : 0;
159 ENABLE_HARD_ERRORS;
161 /* Check for errors */
163 if (rc)
165 free (nbuf);
167 /* Empty directory */
169 #if defined (ERROR_EMPTY_DIR)
170 if (rc == ERROR_EMPTY_DIR)
171 return dirp;
172 #endif
174 free (dirp);
175 return (DIR *) NULL;
178 /* Process the directory */
182 if (((dp = (DIRCONT *) malloc (sizeof (DIRCONT))) == (DIRCONT *)NULL) ||
183 ((dp->_d_entry = strdup (dtabuf.FILE_NAME_E)) == (char *) NULL))
185 if (dp->_d_entry != (char *)NULL)
186 free ((char *)dp);
188 free (nbuf);
189 free_dircontents (dirp->dd_contents);
191 OS_CloseFH (d_handle);
192 return (DIR *) NULL;
195 if (!HPFS)
196 strlwr (dp->_d_entry);
198 if (dirp->dd_contents != (DIRCONT *) NULL)
199 dirp->dd_cp = dirp->dd_cp->_d_next = dp;
201 else
202 dirp->dd_contents = dirp->dd_cp = dp;
204 dp->_d_next = (DIRCONT *) NULL;
206 } while (FindNextFile (d_handle, &dtabuf));
208 dirp->dd_cp = dirp->dd_contents;
209 free (nbuf);
211 OS_CloseFH (d_handle);
212 return dirp;
217 * Close the directory stream
221 closedir (dirp)
222 DIR *dirp;
224 if (dirp != (DIR *)NULL)
226 free_dircontents (dirp->dd_contents);
227 free ((char *)dirp);
230 return 0;
234 * Read the next record from the stream
237 struct dirent *
238 readdir (dirp)
239 DIR *dirp;
241 static struct dirent dp;
243 if ((dirp == (DIR *)NULL) || (dirp->dd_cp == (DIRCONT *) NULL))
244 return (struct dirent *) NULL;
246 dp.d_reclen = strlen (strcpy (dp.d_name, dirp->dd_cp->_d_entry));
247 dp.d_off = dirp->dd_loc * 32;
248 dp.d_ino = (ino_t)++dirp->dd_loc;
249 dirp->dd_cp = dirp->dd_cp->_d_next;
251 return &dp;
255 * Restart the directory stream
258 void
259 rewinddir (dirp)
260 DIR *dirp;
262 seekdir (dirp, (off_t)0);
266 * Move to a know position in the stream
269 void
270 seekdir (dirp, off)
271 DIR *dirp;
272 off_t off;
274 long i = off;
275 DIRCONT *dp;
277 if ((dirp == (DIR *)NULL) || (off < 0L))
278 return;
280 for (dp = dirp->dd_contents; (--i >= 0) && (dp != (DIRCONT *)NULL);
281 dp = dp->_d_next)
284 dirp->dd_loc = off - (i + 1);
285 dirp->dd_cp = dp;
289 * Get the current position
292 off_t
293 telldir(dirp)
294 DIR *dirp;
296 return (dirp == (DIR *)NULL) ? (off_t) -1 : dirp->dd_loc;
300 * Release the internal structure
303 static void
304 free_dircontents (dp)
305 DIRCONT *dp;
307 DIRCONT *odp;
309 while ((odp = dp) != (DIRCONT *)NULL)
311 if (dp->_d_entry != (char *)NULL)
312 free (dp->_d_entry);
314 dp = dp->_d_next;
315 free ((char *)odp);
321 * Windows NT version
324 bool
325 IsHPFSFileSystem (directory)
326 char *directory;
328 char bName[4];
329 DWORD flags;
330 DWORD maxname;
331 BOOL rc;
332 unsigned int nDrive;
333 char szCurDir [MAX_PATH];
335 if (isalpha (directory[0]) && (directory[1] == ':'))
336 nDrive = toupper (directory[0]) - '@';
338 else
340 GetCurrentDirectory (MAX_PATH, szCurDir);
341 nDrive = szCurDir[0] - 'A' + 1;
344 /* Set up the drive name */
346 strcpy (bName, "x:\\");
347 bName[0] = (char) (nDrive + '@');
349 /* Read the volume info, if we fail - assume non-HPFS */
351 DISABLE_HARD_ERRORS;
353 rc = GetVolumeInformation (bName, (LPTSTR)NULL, 0, (LPDWORD)NULL,
354 &maxname, &flags, (LPTSTR)NULL, 0);
355 ENABLE_HARD_ERRORS;
357 return ((rc) && (flags & (FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED)))
358 ? TRUE : FALSE;