Source code of Windows XP (NT5)
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.

253 lines
8.2 KiB

  1. // recurse.c
  2. #include <ctype.h>
  3. #include <direct.h>
  4. #include <malloc.h>
  5. #include <string.h>
  6. #include <windows.h>
  7. #include <assert.h>
  8. #include <stdlib.h>
  9. typedef struct patarray_s {
  10. HANDLE hfind; // handle for FindFirstFile/FindNextFile
  11. BOOLEAN find_next_file; // TRUE if FindNextFile is to be called
  12. BOOLEAN IsDir; // TRUE if current found file is a dir
  13. char szfile[MAX_PATH];// Name of file/dir found
  14. } patarray_t;
  15. typedef struct dirstack_s {
  16. struct dirstack_s *next; // Next element in stack
  17. struct dirstack_s *prev; // Previous element in stack
  18. HANDLE hfind;
  19. patarray_t *ppatarray; // pointer to an array of pattern records
  20. char szdir[1]; // Directory name
  21. } dirstack_t; // Directory stack
  22. #define FA_ATTR(x) ((x).dwFileAttributes)
  23. #define FA_CCHNAME(x) MAX_PATH
  24. #define FA_NAME(x) ((x).cFileName)
  25. #define FA_ALL (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \
  26. FILE_ATTRIBUTE_SYSTEM)
  27. #define FA_DIR FILE_ATTRIBUTE_DIRECTORY
  28. static dirstack_t *pdircur = NULL; // Current directory pointer
  29. void
  30. makename(
  31. char *pszfile,
  32. char *pszname
  33. )
  34. {
  35. dirstack_t *pdir; // Directory stack pointer
  36. *pszfile = '\0'; // Start with null string
  37. pdir = pdircur; // Point at last entry
  38. if (pdir->next != pdircur) { // If not only entry
  39. do {
  40. pdir = pdir->next; // Advance to next subdirectory
  41. strcat(pszfile,pdir->szdir);// Add the subdirectory
  42. } while (pdir != pdircur); // Do until current directory
  43. } else
  44. strcpy(pszfile, pdircur->szdir);
  45. strcat(pszfile,pszname);
  46. }
  47. int
  48. filematch(
  49. char *pszfile,
  50. char **ppszpat,
  51. int cpat,
  52. int fsubdirs
  53. )
  54. {
  55. WIN32_FIND_DATA fi, fi2;
  56. BOOL b;
  57. int i;
  58. dirstack_t *pdir;
  59. patarray_t *pPatFind;
  60. char drive[_MAX_DRIVE];
  61. char dir[_MAX_DIR];
  62. char fname[_MAX_FNAME];
  63. char ext[_MAX_EXT];
  64. assert(INVALID_HANDLE_VALUE != NULL);
  65. if (pdircur == NULL) {
  66. // If stack empty
  67. if ((pdircur = (dirstack_t *) malloc(sizeof(dirstack_t)+MAX_PATH+1)) == NULL)
  68. return(-1); // Fail if allocation fails
  69. if ((pdircur->ppatarray =
  70. (patarray_t *) malloc(sizeof(patarray_t)*cpat)) == NULL) {
  71. free(pdircur);
  72. return(-1);
  73. }
  74. pdircur->szdir[0] = '\0'; // Root has no name
  75. pdircur->hfind = INVALID_HANDLE_VALUE; // No search handle yet
  76. pdircur->next = pdircur->prev = pdircur; // Entry points to self
  77. _splitpath(ppszpat[0], drive, dir, fname, ext);
  78. strcpy(pdircur->szdir, drive);
  79. strcat(pdircur->szdir, dir);
  80. strcpy(ppszpat[0], fname);
  81. strcat(ppszpat[0], ext);
  82. for (i=1; i<cpat; i++) {
  83. _splitpath(ppszpat[i], drive, dir, fname, ext);
  84. strcpy(ppszpat[i], fname);
  85. strcat(ppszpat[i], ext);
  86. }
  87. for (i=0; i<cpat; i++) {
  88. pdircur->ppatarray[i].hfind = INVALID_HANDLE_VALUE;
  89. pdircur->ppatarray[i].szfile[0] = '\0';
  90. }
  91. }
  92. while (pdircur != NULL) {
  93. // While directories remain
  94. b = TRUE;
  95. if (pdircur->hfind == INVALID_HANDLE_VALUE) {
  96. // If no handle yet
  97. makename(pszfile,"*.*"); // Make search name
  98. pdircur->hfind = FindFirstFile((LPSTR) pszfile,
  99. (LPWIN32_FIND_DATA) &fi); // Find first matching entry
  100. } else
  101. b = FindNextFile(pdircur->hfind,
  102. (LPWIN32_FIND_DATA) &fi); // Else find next matching entry
  103. if (b == FALSE || pdircur->hfind == INVALID_HANDLE_VALUE) {
  104. // If search fails
  105. if (pdircur->hfind != INVALID_HANDLE_VALUE)
  106. FindClose(pdircur->hfind);
  107. pdir = pdircur; // Point at record to delete
  108. if ((pdircur = pdir->prev) != pdir) {
  109. // If no parent directory
  110. pdircur->next = pdir->next; // Delete record from list
  111. pdir->next->prev = pdircur;
  112. } else
  113. pdircur = NULL; // Else cause search to stop
  114. pPatFind = pdir->ppatarray;
  115. for (i=0; i<cpat; i++) {
  116. if (pPatFind[i].hfind != NULL &&
  117. pPatFind[i].hfind != INVALID_HANDLE_VALUE)
  118. FindClose(pPatFind[i].hfind);
  119. }
  120. free(pdir->ppatarray);
  121. free(pdir); // Free the record
  122. continue; // Top of loop
  123. }
  124. if (FA_ATTR(fi) & FA_DIR) {
  125. // If subdirectory found
  126. if (fsubdirs &&
  127. strcmp(FA_NAME(fi),".") != 0 && strcmp(FA_NAME(fi),"..") != 0 &&
  128. (pdir = (dirstack_t *) malloc(sizeof(dirstack_t)+FA_CCHNAME(fi)+1)) != NULL)
  129. {
  130. if ((pdir->ppatarray =
  131. (patarray_t *) malloc(sizeof(patarray_t)*cpat)) == NULL) {
  132. free(pdir);
  133. continue;
  134. }
  135. // If not "." nor ".." and alloc okay
  136. strcpy(pdir->szdir,FA_NAME(fi)); // Copy name to buffer
  137. strcat(pdir->szdir,"\\"); // Add trailing backslash
  138. pdir->hfind = INVALID_HANDLE_VALUE; // No search handle yet
  139. pdir->next = pdircur->next; // Insert entry in linked list
  140. pdir->prev = pdircur;
  141. for (i=0; i<cpat; i++) {
  142. pdir->ppatarray[i].hfind = INVALID_HANDLE_VALUE;
  143. pdir->ppatarray[i].szfile[0] = '\0';
  144. }
  145. pdircur->next = pdir;
  146. pdir->next->prev = pdir;
  147. pdircur = pdir; // Make new entry current
  148. }
  149. continue; // Top of loop
  150. }
  151. pPatFind = pdircur->ppatarray;
  152. for (i = cpat; i-- > 0; ) {
  153. // Loop to see if we care
  154. b = (pPatFind[i].hfind != NULL);
  155. for (;;) {
  156. if (pPatFind[i].hfind == INVALID_HANDLE_VALUE) {
  157. makename(pszfile, ppszpat[i]);
  158. pPatFind[i].hfind = FindFirstFile(pszfile, &fi2);
  159. b = (pPatFind[i].hfind != INVALID_HANDLE_VALUE);
  160. pPatFind[i].find_next_file = FALSE;
  161. if (b) {
  162. strcpy(pPatFind[i].szfile, FA_NAME(fi2));
  163. pPatFind[i].IsDir = (BOOLEAN)(FA_ATTR(fi2) & FA_DIR);
  164. }
  165. } else if (pPatFind[i].find_next_file) {
  166. b = FindNextFile(pPatFind[i].hfind, &fi2);
  167. pPatFind[i].find_next_file = FALSE;
  168. if (b) {
  169. strcpy(pPatFind[i].szfile, FA_NAME(fi2));
  170. pPatFind[i].IsDir = (BOOLEAN)(FA_ATTR(fi2) & FA_DIR);
  171. }
  172. }
  173. if (b) {
  174. if (pPatFind[i].IsDir) {
  175. pPatFind[i].find_next_file = TRUE;
  176. } else
  177. break; // found a file to do matching
  178. } else {
  179. if (pPatFind[i].hfind != NULL &&
  180. pPatFind[i].hfind != INVALID_HANDLE_VALUE) {
  181. FindClose(pPatFind[i].hfind);
  182. pPatFind[i].hfind = NULL;
  183. }
  184. pPatFind[i].find_next_file = FALSE;
  185. break; // exhausted all entries
  186. }
  187. } // for
  188. if (b) {
  189. if (strcmp(FA_NAME(fi), pPatFind[i].szfile) == 0) {
  190. pPatFind[i].find_next_file = TRUE;
  191. makename(pszfile, FA_NAME(fi));
  192. return 1;
  193. }
  194. }
  195. }
  196. }
  197. return(-1); // No match found
  198. }
  199. #ifdef TEST
  200. #include <process.h>
  201. #include <stdio.h>
  202. void
  203. main(
  204. int carg,
  205. char **ppszarg
  206. )
  207. {
  208. char szfile[MAX_PATH]; // if OS2: CCHPATHMAX];
  209. while (filematch(szfile,ppszarg,carg) >= 0)
  210. printf("%s\n",szfile);
  211. exit(0);
  212. }
  213. #endif