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