diff options
Diffstat (limited to 'gcc/config/winnt/dirent.c')
-rwxr-xr-x | gcc/config/winnt/dirent.c | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/gcc/config/winnt/dirent.c b/gcc/config/winnt/dirent.c new file mode 100755 index 0000000..59f7dc1 --- /dev/null +++ b/gcc/config/winnt/dirent.c @@ -0,0 +1,360 @@ +/* + * @(#)msd_dir.c 1.4 87/11/06 Public Domain. + * + * A public domain implementation of BSD directory routines for + * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield), + * August 1897 + * + * Modified by Ian Stewartson, Data Logic (istewart@datlog.co.uk). + * + * Updates: 1. To support OS/2 1.x + * 2. To support HPFS long filenames + * 3. To support OS/2 2.x + * 4. To support TurboC + * 5. To support Windows NT + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> + +#include <malloc.h> + +#include <string.h> +#include <limits.h> +#include <ctype.h> +#include <errno.h> +#include <dirent.h> + + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#define FILE_NAME_E cFileName +#define OS_CloseFH(a) FindClose (a) +#define FIND_BUFFER WIN32_FIND_DATA +#define DISABLE_HARD_ERRORS SetErrorMode (0) +#define ENABLE_HARD_ERRORS SetErrorMode (SEM_FAILCRITICALERRORS | \ + SEM_NOOPENFILEERRORBOX); + +# define ERROR_EMPTY_DIR ERROR_FILE_NOT_FOUND + +# define ATTRIBUTES (_A_SUBDIR | _A_HIDDEN | _A_SYSTEM | \ + _A_NORMAL | _A_RDONLY | _A_ARCH) + +/* + * missing ?? + */ + +#ifndef ENOTDIR +# define ENOTDIR 120 /* Not a directory */ +#endif + +#ifndef S_IFMT +# define S_IFMT 0xf000 /* type of file */ +#endif + +#ifndef S_ISDIR +# define S_ISDIR(m) ((((m) & S_IFMT) == S_IFDIR)) +#endif + +/* + * Internals + */ + +typedef struct _dircontents DIRCONT; +static void free_dircontents (DIRCONT *); + +/* + * Open the directory stream + */ + +DIR * +opendir (name) + const char *name; +{ + struct stat statb; + DIR *dirp; + char *last; + DIRCONT *dp; + char *nbuf; + int len = strlen (name); + unsigned long rc; + FIND_BUFFER dtabuf; + HANDLE d_handle; + bool HPFS = FALSE; + + if (!len) + { + errno = ENOTDIR; + return (DIR *)NULL; + } + + if ((nbuf = malloc (len + 5)) == (char *)NULL) + return (DIR *) NULL; + + strcpy (nbuf, name); + last = &nbuf[len - 1]; + +/* Ok, DOS is very picky about its directory names. The following are + * valid. + * + * c:/ + * c:. + * c:name/name1 + * + * c:name/ is not valid + */ + + if (((*last == '\\') || (*last == '/')) && (len > 1) && + (!((len == 3) && (name[1] == ':')))) + *(last--) = 0; + +/* Check its a directory */ + + DISABLE_HARD_ERRORS; + rc = stat (nbuf, &statb); + ENABLE_HARD_ERRORS; + + if (rc) + { + free (nbuf); + return (DIR *) NULL; + } + + if (!S_ISDIR (statb.st_mode)) + { + free (nbuf); + errno = ENOTDIR; + return (DIR *)NULL; + } + + if ((dirp = (DIR *) malloc (sizeof (DIR))) == (DIR *) NULL) + { + free (nbuf); + return (DIR *) NULL; + } + +/* Set up to find everything */ + + if ((*last != '\\') && (*last != '/')) + strcat (last, "/"); + + strcat (last, "*.*"); + +/* Find the file system type */ + + HPFS = IsHPFSFileSystem (nbuf); + + dirp->dd_loc = 0; + dirp->dd_cp = (DIRCONT *) NULL; + dirp->dd_contents = (DIRCONT *) NULL; + + DISABLE_HARD_ERRORS; + + d_handle = FindFirstFile (nbuf, &dtabuf); + rc = (d_handle == INVALID_HANDLE_VALUE) ? GetLastError () : 0; + + ENABLE_HARD_ERRORS; + +/* Check for errors */ + + if (rc) + { + free (nbuf); + +/* Empty directory */ + +#if defined (ERROR_EMPTY_DIR) + if (rc == ERROR_EMPTY_DIR) + return dirp; +#endif + + free (dirp); + return (DIR *) NULL; + } + +/* Process the directory */ + + do + { + if (((dp = (DIRCONT *) malloc (sizeof (DIRCONT))) == (DIRCONT *)NULL) || + ((dp->_d_entry = strdup (dtabuf.FILE_NAME_E)) == (char *) NULL)) + { + if (dp->_d_entry != (char *)NULL) + free ((char *)dp); + + free (nbuf); + free_dircontents (dirp->dd_contents); + + OS_CloseFH (d_handle); + return (DIR *) NULL; + } + + if (!HPFS) + strlwr (dp->_d_entry); + + if (dirp->dd_contents != (DIRCONT *) NULL) + dirp->dd_cp = dirp->dd_cp->_d_next = dp; + + else + dirp->dd_contents = dirp->dd_cp = dp; + + dp->_d_next = (DIRCONT *) NULL; + + } while (FindNextFile (d_handle, &dtabuf)); + + dirp->dd_cp = dirp->dd_contents; + free (nbuf); + + OS_CloseFH (d_handle); + return dirp; +} + + +/* + * Close the directory stream + */ + +int +closedir (dirp) + DIR *dirp; +{ + if (dirp != (DIR *)NULL) + { + free_dircontents (dirp->dd_contents); + free ((char *)dirp); + } + + return 0; +} + +/* + * Read the next record from the stream + */ + +struct dirent * +readdir (dirp) + DIR *dirp; +{ + static struct dirent dp; + + if ((dirp == (DIR *)NULL) || (dirp->dd_cp == (DIRCONT *) NULL)) + return (struct dirent *) NULL; + + dp.d_reclen = strlen (strcpy (dp.d_name, dirp->dd_cp->_d_entry)); + dp.d_off = dirp->dd_loc * 32; + dp.d_ino = (ino_t)++dirp->dd_loc; + dirp->dd_cp = dirp->dd_cp->_d_next; + + return &dp; +} + +/* + * Restart the directory stream + */ + +void +rewinddir (dirp) + DIR *dirp; +{ + seekdir (dirp, (off_t)0); +} + +/* + * Move to a know position in the stream + */ + +void +seekdir (dirp, off) + DIR *dirp; + off_t off; +{ + long i = off; + DIRCONT *dp; + + if ((dirp == (DIR *)NULL) || (off < 0L)) + return; + + for (dp = dirp->dd_contents; (--i >= 0) && (dp != (DIRCONT *)NULL); + dp = dp->_d_next) + ; + + dirp->dd_loc = off - (i + 1); + dirp->dd_cp = dp; +} + +/* + * Get the current position + */ + +off_t +telldir(dirp) + DIR *dirp; +{ + return (dirp == (DIR *)NULL) ? (off_t) -1 : dirp->dd_loc; +} + +/* + * Release the internal structure + */ + +static void +free_dircontents (dp) + DIRCONT *dp; +{ + DIRCONT *odp; + + while ((odp = dp) != (DIRCONT *)NULL) + { + if (dp->_d_entry != (char *)NULL) + free (dp->_d_entry); + + dp = dp->_d_next; + free ((char *)odp); + } +} + + +/* + * Windows NT version + */ + +bool +IsHPFSFileSystem (directory) + char *directory; +{ + char bName[4]; + DWORD flags; + DWORD maxname; + BOOL rc; + unsigned int nDrive; + char szCurDir [MAX_PATH]; + + if (isalpha (directory[0]) && (directory[1] == ':')) + nDrive = toupper (directory[0]) - '@'; + + else + { + GetCurrentDirectory (MAX_PATH, szCurDir); + nDrive = szCurDir[0] - 'A' + 1; + } + +/* Set up the drive name */ + + strcpy (bName, "x:\\"); + bName[0] = (char) (nDrive + '@'); + +/* Read the volume info, if we fail - assume non-HPFS */ + + DISABLE_HARD_ERRORS; + + rc = GetVolumeInformation (bName, (LPTSTR)NULL, 0, (LPDWORD)NULL, + &maxname, &flags, (LPTSTR)NULL, 0); + ENABLE_HARD_ERRORS; + + return ((rc) && (flags & (FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED))) + ? TRUE : FALSE; +} + |