libc.c 8.2 KB

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