1 /*++
2
3 Copyright (c) 2004 - 2006, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 FileSearch.c
15
16 Abstract:
17
18 Module used to support file searches on the system.
19
20 --*/
21
22 #include <stdio.h>
23
24 #include "CommonUtils.h"
25 #include "FileSearch.h"
26 #include "UtilsMsgs.h"
27
28 //
29 // Internal file search flag for sanity checks
30 //
31 #define FILE_SEARCH_STARTED 0x8000
32 #define FILE_SEARCH_INITED 0x4000
33
34 static
35 BOOLEAN
36 FileSearchMeetsCriteria (
37 FILE_SEARCH_DATA *FSData
38 );
39
40 /*****************************************************************************/
41 STATUS
FileSearchInit(FILE_SEARCH_DATA * FSData)42 FileSearchInit (
43 FILE_SEARCH_DATA *FSData
44 )
45 {
46 memset ((char *) FSData, 0, sizeof (FILE_SEARCH_DATA));
47 FSData->Handle = INVALID_HANDLE_VALUE;
48 FSData->FileSearchFlags = FILE_SEARCH_INITED;
49 FSData->FileName[0] = 0;
50 return STATUS_SUCCESS;
51 }
52
53 STATUS
FileSearchStart(FILE_SEARCH_DATA * FSData,char * FileMask,UINT32 SearchFlags)54 FileSearchStart (
55 FILE_SEARCH_DATA *FSData,
56 char *FileMask,
57 UINT32 SearchFlags
58 )
59 {
60 BOOLEAN Done;
61
62 //
63 // Save their flags, and set a flag to indicate that they called this
64 // start function so we can perform extended checking in the other
65 // routines we have in this module.
66 //
67 FSData->FileSearchFlags |= (SearchFlags | FILE_SEARCH_STARTED);
68 FSData->FileName[0] = 0;
69
70 //
71 // Begin the search
72 //
73 FSData->Handle = FindFirstFile (FileMask, &(FSData->FindData));
74 if (FSData->Handle == INVALID_HANDLE_VALUE) {
75 return STATUS_ERROR;
76 }
77 //
78 // Keep looping through until we find a file meeting the caller's
79 // criteria per the search flags
80 //
81 Done = FALSE;
82 while (!Done) {
83 //
84 // If we're done (we found a match) copy the file name found and return
85 //
86 Done = FileSearchMeetsCriteria (FSData);
87 if (Done) {
88 return STATUS_SUCCESS;
89 }
90 //
91 // Go on to next file
92 //
93 if (!FindNextFile (FSData->Handle, &(FSData->FindData))) {
94 return STATUS_NOT_FOUND;
95 }
96 }
97 //
98 // Not reached
99 //
100 return STATUS_NOT_FOUND;
101 }
102
103 //
104 // Find the next file meeting their criteria and return it.
105 //
106 STATUS
FileSearchFindNext(FILE_SEARCH_DATA * FSData)107 FileSearchFindNext (
108 FILE_SEARCH_DATA *FSData
109 )
110 {
111 BOOLEAN Done;
112
113 Done = FALSE;
114 while (!Done) {
115 if (!FindNextFile (FSData->Handle, &(FSData->FindData))) {
116 return STATUS_NOT_FOUND;
117 }
118 //
119 // See if it matches their criteria
120 //
121 Done = FileSearchMeetsCriteria (FSData);
122 if (Done) {
123 return STATUS_SUCCESS;
124 }
125 }
126 //
127 // Not reached
128 //
129 return STATUS_NOT_FOUND;
130 }
131 //
132 // Perform any cleanup necessary to close down a search
133 //
134 STATUS
FileSearchDestroy(FILE_SEARCH_DATA * FSData)135 FileSearchDestroy (
136 FILE_SEARCH_DATA *FSData
137 )
138 {
139 if (FSData->Handle != INVALID_HANDLE_VALUE) {
140 FindClose (FSData->Handle);
141 FSData->Handle = INVALID_HANDLE_VALUE;
142 }
143
144 FSData->FileName[0] = 0;
145 FSData->FileSearchFlags = 0;
146 return STATUS_SUCCESS;
147 }
148
149 static
150 BOOLEAN
FileSearchMeetsCriteria(FILE_SEARCH_DATA * FSData)151 FileSearchMeetsCriteria (
152 FILE_SEARCH_DATA *FSData
153 )
154 {
155 BOOLEAN Status;
156 STRING_LIST *StrList;
157 UINT32 ExtLen;
158 UINT32 FileNameLen;
159
160 Status = FALSE;
161
162 //
163 // First clear the flag indicating this is neither a file or a
164 // directory.
165 //
166 FSData->FileFlags &= ~(FILE_SEARCH_DIR | FILE_SEARCH_FILE);
167
168 //
169 // We found a file. See if it matches the user's search criteria. First
170 // check for this being a directory, and they want directories, and
171 // it's not "." and it's not ".."
172 //
173 if ((FSData->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
174 (FSData->FileSearchFlags & FILE_SEARCH_DIR) &&
175 (strcmp (FSData->FindData.cFileName, ".")) &&
176 (strcmp (FSData->FindData.cFileName, ".."))
177 ) {
178 //
179 // Assume we'll make it past this check
180 //
181 Status = TRUE;
182 //
183 // If they have a list of exclude directories, then check for those
184 //
185 StrList = FSData->ExcludeDirs;
186 while (StrList != NULL) {
187 if (_stricmp (FSData->FindData.cFileName, StrList->Str) == 0) {
188 Status = FALSE;
189 break;
190 }
191
192 StrList = StrList->Next;
193 }
194 //
195 // If we didn't fail due to excluded directories, then set the dir flag
196 //
197 if (Status) {
198 FSData->FileFlags |= FILE_SEARCH_DIR;
199 }
200 //
201 // Else check for a file, and they want files....
202 //
203 } else if (((FSData->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) &&
204 (FSData->FileSearchFlags & FILE_SEARCH_FILE)
205 ) {
206 //
207 // See if it's in our list of excluded files
208 //
209 Status = TRUE;
210 StrList = FSData->ExcludeFiles;
211 while (StrList != NULL) {
212 if (_stricmp (FSData->FindData.cFileName, StrList->Str) == 0) {
213 Status = FALSE;
214 break;
215 }
216
217 StrList = StrList->Next;
218 }
219
220 if (Status) {
221 //
222 // See if it's in our list of excluded file extensions
223 //
224 FileNameLen = strlen (FSData->FindData.cFileName);
225 StrList = FSData->ExcludeExtensions;
226 while (StrList != NULL) {
227 ExtLen = strlen (StrList->Str);
228 if (_stricmp (
229 FSData->FindData.cFileName + FileNameLen - ExtLen,
230 StrList->Str
231 ) == 0) {
232 Status = FALSE;
233 break;
234 }
235
236 StrList = StrList->Next;
237 }
238 }
239
240 if (Status) {
241 FSData->FileFlags |= FILE_SEARCH_FILE;
242 }
243 }
244 //
245 // If it's a match, copy the filename into another field of the structure
246 // for portability.
247 //
248 if (Status) {
249 strcpy (FSData->FileName, FSData->FindData.cFileName);
250 }
251
252 return Status;
253 }
254 //
255 // Exclude a list of subdirectories.
256 //
257 STATUS
FileSearchExcludeDirs(FILE_SEARCH_DATA * FSData,STRING_LIST * StrList)258 FileSearchExcludeDirs (
259 FILE_SEARCH_DATA *FSData,
260 STRING_LIST *StrList
261 )
262 {
263 FSData->ExcludeDirs = StrList;
264 return STATUS_SUCCESS;
265 }
266
267 STATUS
FileSearchExcludeFiles(FILE_SEARCH_DATA * FSData,STRING_LIST * StrList)268 FileSearchExcludeFiles (
269 FILE_SEARCH_DATA *FSData,
270 STRING_LIST *StrList
271 )
272 {
273 FSData->ExcludeFiles = StrList;
274 return STATUS_SUCCESS;
275 }
276
277 STATUS
FileSearchExcludeExtensions(FILE_SEARCH_DATA * FSData,STRING_LIST * StrList)278 FileSearchExcludeExtensions (
279 FILE_SEARCH_DATA *FSData,
280 STRING_LIST *StrList
281 )
282 {
283 FSData->ExcludeExtensions = StrList;
284 return STATUS_SUCCESS;
285 }
286