Leaked source code of windows server 2003
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.

255 lines
8.5 KiB

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