🛠️🐜 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.

232 lines
5.1 KiB

  1. /*
  2. * An example demonstrating wide-character functions
  3. *
  4. * Compile this file with Visual Studio and run the produced command in
  5. * console with a directory name argument. For example, command
  6. *
  7. * updatedb C:\
  8. *
  9. * will produce the file locate.db with one file name per line such as
  10. *
  11. * c:\Program Files/7-Zip/7-zip.chm
  12. * c:\Program Files/7-Zip/7-zip.dll
  13. * c:\Program Files/7-Zip/7z.dll
  14. * c:\Program Files/Adobe/Reader 10.0/Reader/logsession.dll
  15. * c:\Program Files/Adobe/Reader 10.0/Reader/LogTransport2.exe
  16. * c:\Program Files/Windows NT/Accessories/wordpad.exe
  17. * c:\Program Files/Windows NT/Accessories/write.wpc
  18. *
  19. * Be ware that this file uses wide-character API which is not compatible
  20. * with Linux or other major Unixes.
  21. *
  22. * Copyright (C) 1998-2019 Toni Ronkko
  23. * This file is part of dirent. Dirent may be freely distributed
  24. * under the MIT license. For all details and documentation, see
  25. * https://github.com/tronkko/dirent
  26. */
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <wchar.h>
  31. #ifdef WIN32
  32. # include <io.h>
  33. # include <fcntl.h>
  34. #endif
  35. #include <dirent.h>
  36. /* File name and location of database file */
  37. #define DB_LOCATION L"locate.db"
  38. /* Forward-decl */
  39. static int update_directory (const wchar_t *dirname);
  40. static void db_open (void);
  41. static void db_close (void);
  42. static void db_store (const wchar_t *dirname);
  43. /* Module local variables */
  44. static FILE *db = NULL;
  45. int
  46. main(
  47. int argc, char *argv[])
  48. {
  49. #ifdef WIN32
  50. int i;
  51. int ok;
  52. /* Prepare for unicode output */
  53. _setmode (_fileno (stdout), _O_U16TEXT);
  54. /* Open locate.db */
  55. db_open ();
  56. /* For each directory in command line */
  57. i = 1;
  58. while (i < argc) {
  59. wchar_t buffer[PATH_MAX + 1];
  60. errno_t error;
  61. size_t n;
  62. /* Convert ith argument to wide-character string */
  63. error = mbstowcs_s (&n, buffer, PATH_MAX, argv[i], _TRUNCATE);
  64. if (!error) {
  65. /* Scan directory for files */
  66. ok = update_directory (buffer);
  67. if (!ok) {
  68. wprintf (L"Cannot open directory %s\n", buffer);
  69. exit (EXIT_FAILURE);
  70. }
  71. }
  72. i++;
  73. }
  74. /* Use current working directory if no arguments on command line */
  75. if (argc == 1) {
  76. update_directory (L".");
  77. }
  78. db_close ();
  79. #else
  80. printf ("updatedb only works on Microsoft Windows\n");
  81. #endif
  82. return EXIT_SUCCESS;
  83. }
  84. /* Find files recursively */
  85. static int
  86. update_directory(
  87. const wchar_t *dirname)
  88. {
  89. int ok = 0;
  90. #ifdef WIN32
  91. _WDIR *dir;
  92. wchar_t buffer[PATH_MAX + 2];
  93. wchar_t *p = buffer;
  94. const wchar_t *src;
  95. wchar_t *end = &buffer[PATH_MAX];
  96. /* Copy directory name to buffer */
  97. src = dirname;
  98. while (p < end && *src != '\0') {
  99. *p++ = *src++;
  100. }
  101. *p = '\0';
  102. /* Open directory stream */
  103. dir = _wopendir (dirname);
  104. if (dir != NULL) {
  105. struct _wdirent *ent;
  106. /* Print all files and directories within the directory */
  107. while ((ent = _wreaddir (dir)) != NULL) {
  108. wchar_t *q = p;
  109. wchar_t c;
  110. /* Get final character of directory name */
  111. if (buffer < q) {
  112. c = q[-1];
  113. } else {
  114. c = ':';
  115. }
  116. /* Append directory separator if not already there */
  117. if (c != ':' && c != '/' && c != '\\') {
  118. *q++ = '/';
  119. }
  120. /* Append file name */
  121. src = ent->d_name;
  122. while (q < end && *src != '\0') {
  123. *q++ = *src++;
  124. }
  125. *q = '\0';
  126. /* Decide what to do with the directory entry */
  127. switch (ent->d_type) {
  128. case DT_REG:
  129. /* Store file name */
  130. db_store (buffer);
  131. break;
  132. case DT_DIR:
  133. /* Scan sub-directory recursively */
  134. if (wcscmp (ent->d_name, L".") != 0
  135. && wcscmp (ent->d_name, L"..") != 0) {
  136. update_directory (buffer);
  137. }
  138. break;
  139. default:
  140. /* Do not device entries */
  141. /*NOP*/;
  142. }
  143. }
  144. wclosedir (dir);
  145. ok = 1;
  146. } else {
  147. /* Cannot open directory */
  148. ok = 0;
  149. }
  150. #endif
  151. return ok;
  152. }
  153. /* Store file name to locate.db */
  154. static void
  155. db_store(
  156. const wchar_t *dirname)
  157. {
  158. #ifdef WIN32
  159. if (db) {
  160. /* Output line to file */
  161. fwprintf (db, L"%s\n", dirname);
  162. } else {
  163. wprintf (L"Database not open\n");
  164. exit (EXIT_FAILURE);
  165. }
  166. #endif
  167. }
  168. /* Open database file locate.db */
  169. static void
  170. db_open(
  171. void)
  172. {
  173. #ifdef WIN32
  174. if (db == NULL) {
  175. errno_t error;
  176. /* Open file for writing */
  177. error = _wfopen_s (&db, DB_LOCATION, L"wt, ccs=UNICODE");
  178. if (error) {
  179. wprintf (L"Cannot open %s\n", DB_LOCATION);
  180. exit (EXIT_FAILURE);
  181. }
  182. }
  183. #endif
  184. }
  185. /* Close database file */
  186. static void
  187. db_close(
  188. void)
  189. {
  190. if (db) {
  191. fclose (db);
  192. db = NULL;
  193. }
  194. }