🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

264 lines
7.1 KiB

  1. /*
  2. * Make sure that scandir function works OK.
  3. *
  4. * Copyright (C) 1998-2019 Toni Ronkko
  5. * This file is part of dirent. Dirent may be freely distributed
  6. * under the MIT license. For all details and documentation, see
  7. * https://github.com/tronkko/dirent
  8. */
  9. /* Silence warning about fopen being insecure */
  10. #define _CRT_SECURE_NO_WARNINGS
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <sys/stat.h>
  15. #include <dirent.h>
  16. #include <errno.h>
  17. #include <time.h>
  18. #include <limits.h>
  19. #undef NDEBUG
  20. #include <assert.h>
  21. /* Filter and sort functions */
  22. static int only_readme (const struct dirent *entry);
  23. static int no_directories (const struct dirent *entry);
  24. static int reverse_alpha (const struct dirent **a, const struct dirent **b);
  25. int
  26. main(
  27. int argc, char *argv[])
  28. {
  29. struct dirent **files;
  30. int i;
  31. int n;
  32. (void) argc;
  33. (void) argv;
  34. /* Initialize random number generator */
  35. srand ((unsigned) time (NULL));
  36. /* Basic scan with simple filter function */
  37. {
  38. /* Read directory entries */
  39. n = scandir ("tests/3", &files, only_readme, alphasort);
  40. assert (n == 1);
  41. /* Make sure that the filter works */
  42. assert (strcmp (files[0]->d_name, "README.txt") == 0);
  43. /* Release file names */
  44. for (i = 0; i < n; i++) {
  45. free (files[i]);
  46. }
  47. free (files);
  48. }
  49. /* Basic scan with default sorting function */
  50. {
  51. /* Read directory entries in alphabetic order */
  52. n = scandir ("tests/3", &files, NULL, alphasort);
  53. assert (n == 13);
  54. /* Make sure that we got all the file names in the proper order */
  55. assert (strcmp (files[0]->d_name, ".") == 0);
  56. assert (strcmp (files[1]->d_name, "..") == 0);
  57. assert (strcmp (files[2]->d_name, "3zero.dat") == 0);
  58. assert (strcmp (files[3]->d_name, "666.dat") == 0);
  59. assert (strcmp (files[4]->d_name, "Qwerty-my-aunt.dat") == 0);
  60. assert (strcmp (files[5]->d_name, "README.txt") == 0);
  61. assert (strcmp (files[6]->d_name, "aaa.dat") == 0);
  62. assert (strcmp (files[7]->d_name, "dirent.dat") == 0);
  63. assert (strcmp (files[8]->d_name, "empty.dat") == 0);
  64. assert (strcmp (files[9]->d_name, "sane-1.12.0.dat") == 0);
  65. assert (strcmp (files[10]->d_name, "sane-1.2.3.dat") == 0);
  66. assert (strcmp (files[11]->d_name, "sane-1.2.4.dat") == 0);
  67. assert (strcmp (files[12]->d_name, "zebra.dat") == 0);
  68. /* Release file names */
  69. for (i = 0; i < n; i++) {
  70. free (files[i]);
  71. }
  72. free (files);
  73. }
  74. /* Custom filter AND sort function */
  75. {
  76. /* Read directory entries in alphabetic order */
  77. n = scandir ("tests/3", &files, no_directories, reverse_alpha);
  78. assert (n == 11);
  79. /* Make sure that we got all the FILE names in the REVERSE order */
  80. assert (strcmp (files[0]->d_name, "zebra.dat") == 0);
  81. assert (strcmp (files[1]->d_name, "sane-1.2.4.dat") == 0);
  82. assert (strcmp (files[2]->d_name, "sane-1.2.3.dat") == 0);
  83. assert (strcmp (files[3]->d_name, "sane-1.12.0.dat") == 0);
  84. assert (strcmp (files[4]->d_name, "empty.dat") == 0);
  85. assert (strcmp (files[5]->d_name, "dirent.dat") == 0);
  86. assert (strcmp (files[6]->d_name, "aaa.dat") == 0);
  87. assert (strcmp (files[7]->d_name, "README.txt") == 0);
  88. assert (strcmp (files[8]->d_name, "Qwerty-my-aunt.dat") == 0);
  89. assert (strcmp (files[9]->d_name, "666.dat") == 0);
  90. assert (strcmp (files[10]->d_name, "3zero.dat") == 0);
  91. /* Release file names */
  92. for (i = 0; i < n; i++) {
  93. free (files[i]);
  94. }
  95. free (files);
  96. }
  97. /* Trying to read from non-existent directory leads to an error */
  98. {
  99. files = NULL;
  100. n = scandir ("tests/invalid", &files, NULL, alphasort);
  101. assert (n == -1);
  102. assert (files == NULL);
  103. assert (errno == ENOENT);
  104. }
  105. /* Trying to open file as a directory produces ENOTDIR error */
  106. {
  107. files = NULL;
  108. n = scandir ("tests/3/666.dat", &files, NULL, alphasort);
  109. assert (n == -1);
  110. assert (files == NULL);
  111. assert (errno == ENOTDIR);
  112. }
  113. /* Scan large directory */
  114. {
  115. char dirname[PATH_MAX+1];
  116. int i, j;
  117. int ok;
  118. /* Copy name of temporary directory to variable dirname */
  119. #ifdef WIN32
  120. i = GetTempPathA (PATH_MAX, dirname);
  121. assert (i > 0);
  122. #else
  123. strcpy (dirname, "/tmp/");
  124. i = strlen (dirname);
  125. #endif
  126. /* Append random characters to dirname */
  127. for (j = 0; j < 10; j++) {
  128. char c;
  129. /* Generate random character */
  130. c = "abcdefghijklmnopqrstuvwxyz"[rand() % 26];
  131. /* Append character to dirname */
  132. assert (i < PATH_MAX);
  133. dirname[i++] = c;
  134. }
  135. /* Terminate directory name */
  136. assert (i < PATH_MAX);
  137. dirname[i] = '\0';
  138. /* Create directory */
  139. #ifdef WIN32
  140. ok = CreateDirectoryA (dirname, NULL);
  141. assert (ok);
  142. #else
  143. ok = mkdir (dirname, 0700);
  144. assert (ok == /*success*/0);
  145. #endif
  146. /* Create one thousand files */
  147. assert (i + 5 < PATH_MAX);
  148. for (j = 0; j < 1000; j++) {
  149. FILE *fp;
  150. /* Construct file name */
  151. dirname[i] = '/';
  152. dirname[i+1] = 'z';
  153. dirname[i+2] = '0' + ((j / 100) % 10);
  154. dirname[i+3] = '0' + ((j / 10) % 10);
  155. dirname[i+4] = '0' + (j % 10);
  156. dirname[i+5] = '\0';
  157. /* Create file */
  158. fp = fopen (dirname, "w");
  159. assert (fp != NULL);
  160. fclose (fp);
  161. }
  162. /* Cut out the file name part */
  163. dirname[i] = '\0';
  164. /* Scan directory */
  165. n = scandir (dirname, &files, no_directories, alphasort);
  166. assert (n == 1000);
  167. /* Make sure that all 1000 files are read back */
  168. for (j = 0; j < n; j++) {
  169. char match[100];
  170. /* Construct file name */
  171. match[0] = 'z';
  172. match[1] = '0' + ((j / 100) % 10);
  173. match[2] = '0' + ((j / 10) % 10);
  174. match[3] = '0' + (j % 10);
  175. match[4] = '\0';
  176. /* Make sure that file name matches that on the disk */
  177. assert (strcmp (files[j]->d_name, match) == 0);
  178. }
  179. /* Release file names */
  180. for (j = 0; j < n; j++) {
  181. free (files[j]);
  182. }
  183. free (files);
  184. }
  185. printf ("OK\n");
  186. return EXIT_SUCCESS;
  187. }
  188. /* Only pass README.txt file */
  189. static int
  190. only_readme (const struct dirent *entry)
  191. {
  192. int pass;
  193. if (strcmp (entry->d_name, "README.txt") == 0) {
  194. pass = 1;
  195. } else {
  196. pass = 0;
  197. }
  198. return pass;
  199. }
  200. /* Filter out directories */
  201. static int
  202. no_directories (const struct dirent *entry)
  203. {
  204. int pass;
  205. if (entry->d_type != DT_DIR) {
  206. pass = 1;
  207. } else {
  208. pass = 0;
  209. }
  210. return pass;
  211. }
  212. /* Sort in reverse direction */
  213. static int
  214. reverse_alpha(
  215. const struct dirent **a, const struct dirent **b)
  216. {
  217. return strcoll ((*b)->d_name, (*a)->d_name);
  218. }