|
|
1.1 ! root 1: /* ! 2: Hatari - scandir.c ! 3: ! 4: This file is distributed under the GNU Public License, version 2 or at ! 5: your option any later version. Read the file gpl.txt for details. ! 6: ! 7: scandir function for BEOS, SunOS etc.. ! 8: */ ! 9: const char ScanDir_fileid[] = "Hatari scandir.c : " __DATE__ " " __TIME__; ! 10: ! 11: #include <string.h> ! 12: #include <stdio.h> ! 13: #include <stdlib.h> ! 14: #include <sys/types.h> ! 15: #include <sys/stat.h> ! 16: #include <fcntl.h> ! 17: #include <unistd.h> ! 18: ! 19: #include "scandir.h" ! 20: #include "log.h" ! 21: ! 22: /*----------------------------------------------------------------------- ! 23: * Here come alphasort and scandir for POSIX-like OSes ! 24: *-----------------------------------------------------------------------*/ ! 25: #if !defined(WIN32) && !defined(__CEGCC__) ! 26: ! 27: /** ! 28: * Alphabetic order comparison routine. ! 29: */ ! 30: #if !HAVE_ALPHASORT ! 31: int alphasort(const void *d1, const void *d2) ! 32: { ! 33: return strcmp((*(struct dirent * const *)d1)->d_name, ! 34: (*(struct dirent * const *)d2)->d_name); ! 35: } ! 36: #endif ! 37: ! 38: ! 39: #if !HAVE_SCANDIR ! 40: ! 41: #undef DIRSIZ ! 42: ! 43: #define DIRSIZ(dp) \ ! 44: ((sizeof(struct dirent) - sizeof(dp)->d_name) + \ ! 45: (((dp)->d_reclen + 1 + 3) &~ 3)) ! 46: ! 47: #if (defined(__sun) && defined(__SVR4)) || defined(__CEGCC__) ! 48: # define dirfd(d) ((d)->dd_fd) ! 49: #elif defined(__BEOS__) ! 50: # define dirfd(d) ((d)->fd) ! 51: #endif ! 52: ! 53: ! 54: /*-----------------------------------------------------------------------*/ ! 55: /** ! 56: * Scan a directory for all its entries ! 57: * Return -1 on error, number of entries on success ! 58: */ ! 59: int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(struct dirent *), int (*dcomp)(const void *, const void *)) ! 60: { ! 61: struct dirent *d, *p = NULL, **names = NULL; ! 62: struct stat stb; ! 63: size_t nitems = 0; ! 64: size_t arraysz; ! 65: DIR *dirp; ! 66: ! 67: if ((dirp = opendir(dirname)) == NULL) ! 68: goto error_out; ! 69: ! 70: if (fstat(dirfd(dirp), &stb) < 0) ! 71: goto error_out; ! 72: ! 73: /* ! 74: * estimate the array size by taking the size of the directory file ! 75: * and dividing it by a multiple of the minimum size entry. ! 76: */ ! 77: arraysz = (stb.st_size / 24); ! 78: ! 79: names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); ! 80: if (names == NULL) ! 81: goto error_out; ! 82: ! 83: while ((d = readdir(dirp)) != NULL) ! 84: { ! 85: ! 86: if (sdfilter != NULL && !(*sdfilter)(d)) ! 87: continue; /* just selected names */ ! 88: ! 89: /* ! 90: * Make a minimum size copy of the data ! 91: */ ! 92: ! 93: p = (struct dirent *)malloc(DIRSIZ(d)); ! 94: if (p == NULL) ! 95: goto error_out; ! 96: ! 97: p->d_ino = d->d_ino; ! 98: p->d_reclen = d->d_reclen; ! 99: /*p->d_namlen = d->d_namlen;*/ ! 100: memcpy(p->d_name, d->d_name, p->d_reclen + 1); ! 101: ! 102: /* ! 103: * Check to make sure the array has space left and ! 104: * realloc the maximum size. ! 105: */ ! 106: ! 107: if ((nitems+1) >= arraysz) ! 108: { ! 109: struct dirent **tmp; ! 110: ! 111: if (fstat(dirfd(dirp), &stb) < 0) ! 112: goto error_out; /* just might have grown */ ! 113: ! 114: arraysz = stb.st_size / 12; ! 115: ! 116: tmp = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *)); ! 117: if (tmp == NULL) ! 118: goto error_out; ! 119: names = tmp; ! 120: } ! 121: ! 122: names[nitems++] = p; ! 123: p = NULL; ! 124: } ! 125: ! 126: closedir(dirp); ! 127: ! 128: if (nitems && dcomp != NULL) ! 129: qsort(names, nitems, sizeof(struct dirent *), dcomp); ! 130: ! 131: *namelist = names; ! 132: ! 133: return nitems; ! 134: ! 135: error_out: ! 136: if (names) ! 137: { ! 138: int i; ! 139: for (i = 0; i < nitems; i++) ! 140: free(names[i]); ! 141: free(names); ! 142: } ! 143: if (dirp) ! 144: closedir(dirp); ! 145: return -1; ! 146: } ! 147: #endif /* !HAVE_SCANDIR */ ! 148: ! 149: #endif /* !WIN32 */ ! 150: ! 151: ! 152: /*----------------------------------------------------------------------- ! 153: * Here come alphasort and scandir for Windows ! 154: *-----------------------------------------------------------------------*/ ! 155: #if defined(WIN32) || defined(__CEGCC__) ! 156: ! 157: #include <windows.h> ! 158: #include <wchar.h> ! 159: ! 160: /*-----------------------------------------------------------------------*/ ! 161: /** ! 162: * Alphabetic order comparison routine. ! 163: */ ! 164: int alphasort(const void *d1, const void *d2) ! 165: { ! 166: return stricmp((*(struct dirent * const *)d1)->d_name, (*(struct dirent * const *)d2)->d_name); ! 167: } ! 168: ! 169: /*-----------------------------------------------------------------------*/ ! 170: /** ! 171: * Scan a directory for all its entries ! 172: */ ! 173: int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(struct dirent *), int (*dcomp)(const void *, const void *)) ! 174: { ! 175: int len; ! 176: char *findIn, *d; ! 177: WIN32_FIND_DATA find; ! 178: HANDLE h; ! 179: int nDir = 0, NDir = 0; ! 180: struct dirent **dir = 0, *selectDir; ! 181: unsigned long ret; ! 182: ! 183: len = strlen(dirname); ! 184: findIn = (char *)malloc(len+5); ! 185: if (!findIn) ! 186: return -1; ! 187: ! 188: strcpy(findIn, dirname); ! 189: Log_Printf(LOG_DEBUG, "scandir : findIn orign='%s'\n", findIn); ! 190: ! 191: for (d = findIn; *d; d++) ! 192: if (*d=='/') ! 193: *d='\\'; ! 194: if ((len==0)) ! 195: { ! 196: strcpy(findIn, ".\\*"); ! 197: } ! 198: if ((len==1)&& (d[-1]=='.')) ! 199: { ! 200: strcpy(findIn, ".\\*"); ! 201: } ! 202: if ((len>0) && (d[-1]=='\\')) ! 203: { ! 204: *d++ = '*'; ! 205: *d = 0; ! 206: } ! 207: if ((len>1) && (d[-1]=='.') && (d[-2]=='\\')) ! 208: { ! 209: d[-1] = '*'; ! 210: } ! 211: if ((len>1) && !(d[-2]=='\\' && d[-1]=='*') ) ! 212: { ! 213: *d++ = '\\'; ! 214: *d++ = '*'; ! 215: *d = 0; ! 216: } ! 217: ! 218: Log_Printf(LOG_DEBUG, "scandir : findIn processed='%s'\n", findIn); ! 219: ! 220: #if defined(__CEGCC__) ! 221: void *findInW = NULL; ! 222: findInW = malloc((len+6)*2); ! 223: if (!findInW) ! 224: return -1; ! 225: mbstowcs(findInW, findIn, len+6); ! 226: h = FindFirstFileW(findInW, &find); ! 227: #else ! 228: h = FindFirstFile(findIn, &find); ! 229: #endif ! 230: ! 231: if (h == INVALID_HANDLE_VALUE) ! 232: { ! 233: Log_Printf(LOG_DEBUG, "scandir : FindFirstFile error\n"); ! 234: ret = GetLastError(); ! 235: if (ret != ERROR_NO_MORE_FILES) ! 236: { ! 237: // TODO: return some error code ! 238: } ! 239: *namelist = dir; ! 240: return nDir; ! 241: } ! 242: ! 243: do ! 244: { ! 245: selectDir=(struct dirent*)malloc(sizeof(struct dirent)+lstrlen(find.cFileName)+1); ! 246: #if defined(__CEGCC__) ! 247: wcstombs(selectDir->d_name, find.cFileName, lstrlen(find.cFileName)+1); ! 248: #else ! 249: strcpy(selectDir->d_name, find.cFileName); ! 250: #endif ! 251: //Log_Printf(LOG_DEBUG, "scandir : findFile='%s'\n", selectDir->d_name); ! 252: if (!sdfilter || (*sdfilter)(selectDir)) ! 253: { ! 254: if (nDir==NDir) ! 255: { ! 256: struct dirent **tempDir = (struct dirent **)calloc(sizeof(struct dirent*), NDir+33); ! 257: if (NDir) ! 258: memcpy(tempDir, dir, sizeof(struct dirent*)*NDir); ! 259: if (dir) ! 260: free(dir); ! 261: dir = tempDir; ! 262: NDir += 32; ! 263: } ! 264: dir[nDir] = selectDir; ! 265: nDir++; ! 266: dir[nDir] = 0; ! 267: } ! 268: else ! 269: { ! 270: free(selectDir); ! 271: } ! 272: ! 273: #if defined(__CEGCC__) ! 274: ret = FindNextFileW(h, &find); ! 275: #else ! 276: ret = FindNextFile(h, &find); ! 277: #endif ! 278: } ! 279: while (ret); ! 280: ! 281: ret = GetLastError(); ! 282: if (ret != ERROR_NO_MORE_FILES) ! 283: { ! 284: // TODO: return some error code ! 285: Log_Printf(LOG_DEBUG, "scandir: last error = %ld\n", ret); ! 286: } ! 287: ! 288: FindClose(h); ! 289: ! 290: free(findIn); ! 291: ! 292: #if defined(__CEGCC__) ! 293: free(findInW); ! 294: #endif ! 295: ! 296: if (dcomp) ! 297: qsort (dir, nDir, sizeof(*dir),dcomp); ! 298: ! 299: *namelist = dir; ! 300: return nDir; ! 301: } ! 302: ! 303: #endif /* WIN32 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.