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