OLD | NEW |
---|---|
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "bin/directory.h" | 5 #include "bin/directory.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <sys/stat.h> | 8 #include <sys/stat.h> |
9 | 9 |
10 #include "bin/platform.h" | 10 #include "bin/platform.h" |
11 | 11 |
(...skipping 20 matching lines...) Expand all Loading... | |
32 } | 32 } |
33 | 33 |
34 | 34 |
35 // Forward declaration. | 35 // Forward declaration. |
36 static bool ListRecursively(const char* dir_name, | 36 static bool ListRecursively(const char* dir_name, |
37 bool recursive, | 37 bool recursive, |
38 Dart_Port dir_port, | 38 Dart_Port dir_port, |
39 Dart_Port file_port, | 39 Dart_Port file_port, |
40 Dart_Port done_port, | 40 Dart_Port done_port, |
41 Dart_Port error_port); | 41 Dart_Port error_port); |
42 static bool DeleteRecursively(const char* dir_name); | |
42 | 43 |
43 | 44 |
44 static bool HandleDir(char* dir_name, | 45 static bool HandleDir(char* dir_name, |
45 char* path, | 46 char* path, |
46 int path_length, | 47 int path_length, |
47 bool recursive, | 48 bool recursive, |
48 Dart_Port dir_port, | 49 Dart_Port dir_port, |
49 Dart_Port file_port, | 50 Dart_Port file_port, |
50 Dart_Port done_port, | 51 Dart_Port done_port, |
51 Dart_Port error_port) { | 52 Dart_Port error_port) { |
52 if (strcmp(dir_name, ".") != 0 && | 53 if (strcmp(dir_name, ".") != 0 && |
53 strcmp(dir_name, "..") != 0) { | 54 strcmp(dir_name, "..") != 0) { |
54 size_t written = snprintf(path + path_length, | 55 size_t written = snprintf(path + path_length, |
55 MAX_PATH - path_length, | 56 MAX_PATH - path_length, |
56 "%s", | 57 "%s", |
57 dir_name); | 58 dir_name); |
58 ASSERT(written == strlen(dir_name)); | 59 if (written != strlen(dir_name)) { |
60 return false; | |
61 } | |
59 if (dir_port != 0) { | 62 if (dir_port != 0) { |
60 Dart_Handle name = Dart_NewString(path); | 63 Dart_Handle name = Dart_NewString(path); |
61 Dart_Post(dir_port, name); | 64 Dart_Post(dir_port, name); |
62 } | 65 } |
63 if (recursive) { | 66 if (recursive) { |
64 return ListRecursively(path, | 67 return ListRecursively(path, |
65 recursive, | 68 recursive, |
66 dir_port, | 69 dir_port, |
67 file_port, | 70 file_port, |
68 done_port, | 71 done_port, |
69 error_port); | 72 error_port); |
70 } | 73 } |
71 } | 74 } |
72 return true; | 75 return true; |
73 } | 76 } |
74 | 77 |
75 | 78 |
76 static void HandleFile(char* file_name, | 79 static bool HandleFile(char* file_name, |
77 char* path, | 80 char* path, |
78 int path_length, | 81 int path_length, |
79 Dart_Port file_port) { | 82 Dart_Port file_port) { |
80 if (file_port != 0) { | 83 if (file_port != 0) { |
81 size_t written = snprintf(path + path_length, | 84 size_t written = snprintf(path + path_length, |
82 MAX_PATH - path_length, | 85 MAX_PATH - path_length, |
83 "%s", | 86 "%s", |
84 file_name); | 87 file_name); |
85 ASSERT(written == strlen(file_name)); | 88 if (written != strlen(file_name)) { |
89 return false; | |
90 }; | |
86 Dart_Handle name = Dart_NewString(path); | 91 Dart_Handle name = Dart_NewString(path); |
87 Dart_Post(file_port, name); | 92 Dart_Post(file_port, name); |
88 } | 93 } |
94 return true; | |
89 } | 95 } |
90 | 96 |
91 | 97 |
92 static bool HandleEntry(LPWIN32_FIND_DATA find_file_data, | 98 static bool HandleEntry(LPWIN32_FIND_DATA find_file_data, |
93 char* path, | 99 char* path, |
94 int path_length, | 100 int path_length, |
95 bool recursive, | 101 bool recursive, |
96 Dart_Port dir_port, | 102 Dart_Port dir_port, |
97 Dart_Port file_port, | 103 Dart_Port file_port, |
98 Dart_Port done_port, | 104 Dart_Port done_port, |
99 Dart_Port error_port) { | 105 Dart_Port error_port) { |
100 DWORD attributes = find_file_data->dwFileAttributes; | 106 DWORD attributes = find_file_data->dwFileAttributes; |
101 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { | 107 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
102 return HandleDir(find_file_data->cFileName, | 108 return HandleDir(find_file_data->cFileName, |
103 path, | 109 path, |
104 path_length, | 110 path_length, |
105 recursive, | 111 recursive, |
106 dir_port, | 112 dir_port, |
107 file_port, | 113 file_port, |
108 done_port, | 114 done_port, |
109 error_port); | 115 error_port); |
110 } else { | 116 } else { |
111 HandleFile(find_file_data->cFileName, path, path_length, file_port); | 117 return HandleFile(find_file_data->cFileName, path, path_length, file_port); |
112 return true; | |
113 } | 118 } |
114 } | 119 } |
115 | 120 |
116 | 121 |
117 static void ComputeFullSearchPath(const char* dir_name, | 122 // ComputeFullSearchPath must be called with a path array of size at |
123 // least MAX_PATH. | |
Bill Hesse
2012/02/03 12:17:51
On Windows, ComputeFullSearchPath does do somethin
| |
124 static bool ComputeFullSearchPath(const char* dir_name, | |
118 char* path, | 125 char* path, |
119 int* path_length) { | 126 int* path_length) { |
120 // GetFullPathName only works in a multi-threaded environment if | 127 // GetFullPathName only works in a multi-threaded environment if |
121 // SetCurrentDirectory is not used. We currently have no plan for | 128 // SetCurrentDirectory is not used. We currently have no plan for |
122 // exposing SetCurrentDirectory. | 129 // exposing SetCurrentDirectory. |
123 size_t written = | 130 size_t written = GetFullPathName(dir_name, MAX_PATH, path, NULL); |
124 GetFullPathName(dir_name, MAX_PATH - *path_length, path, NULL); | 131 // GetFullPathName only accepts input strings of size less than |
125 *path_length += written; | 132 // MAX_PATH and returns 0 to indicate failure for paths longer than |
133 // that. Therefore the path buffer is always big enough. | |
134 if (written == 0) { | |
135 return false; | |
136 } | |
137 *path_length = written; | |
126 written = snprintf(path + *path_length, | 138 written = snprintf(path + *path_length, |
127 MAX_PATH - *path_length, | 139 MAX_PATH - *path_length, |
128 "%s", | 140 "%s", |
129 "\\*"); | 141 "\\*"); |
130 ASSERT(written == 2); | 142 if (written != 2) { |
143 return false; | |
144 } | |
131 *path_length += written; | 145 *path_length += written; |
146 return true; | |
132 } | 147 } |
133 | 148 |
134 static void PostError(Dart_Port error_port, | 149 static void PostError(Dart_Port error_port, |
135 const char* prefix, | 150 const char* prefix, |
136 const char* suffix) { | 151 const char* suffix) { |
137 if (error_port != 0) { | 152 if (error_port != 0) { |
138 char* error_str = Platform::StrError(GetLastError()); | 153 char* error_str = Platform::StrError(GetLastError()); |
139 int error_message_size = | 154 int error_message_size = |
140 strlen(prefix) + strlen(suffix) + strlen(error_str) + 3; | 155 strlen(prefix) + strlen(suffix) + strlen(error_str) + 3; |
141 char* message = static_cast<char*>(malloc(error_message_size + 1)); | 156 char* message = static_cast<char*>(malloc(error_message_size + 1)); |
142 size_t written = snprintf(message, | 157 size_t written = snprintf(message, |
143 error_message_size + 1, | 158 error_message_size + 1, |
144 "%s%s (%s)", | 159 "%s%s (%s)", |
145 prefix, | 160 prefix, |
146 suffix, | 161 suffix, |
147 error_str); | 162 error_str); |
148 ASSERT(written == error_message_size); | 163 ASSERT(written == error_message_size); |
149 free(error_str); | 164 free(error_str); |
150 Dart_Post(error_port, Dart_NewString(message)); | 165 Dart_Post(error_port, Dart_NewString(message)); |
151 free(message); | 166 free(message); |
152 } | 167 } |
153 } | 168 } |
154 | 169 |
155 | 170 |
156 static bool ListRecursively(const char* dir_name, | 171 static bool ListRecursively(const char* dir_name, |
157 bool recursive, | 172 bool recursive, |
158 Dart_Port dir_port, | 173 Dart_Port dir_port, |
159 Dart_Port file_port, | 174 Dart_Port file_port, |
160 Dart_Port done_port, | 175 Dart_Port done_port, |
161 Dart_Port error_port) { | 176 Dart_Port error_port) { |
177 // Compute full path for the directory currently being listed. The | |
178 // path buffer will be used to construct the current path in the | |
179 // recursive traversal. path_length does not always equal | |
180 // strlen(path) but indicates the current prefix of path that is the | |
181 // path of the current directory in the traversal. | |
162 char* path = static_cast<char*>(malloc(MAX_PATH)); | 182 char* path = static_cast<char*>(malloc(MAX_PATH)); |
163 int path_length = 0; | 183 int path_length = 0; |
164 ComputeFullSearchPath(dir_name, path, &path_length); | 184 bool valid = ComputeFullSearchPath(dir_name, path, &path_length); |
185 if (!valid) { | |
186 PostError(error_port, "Directory listing failed for: ", dir_name); | |
187 free(path); | |
188 return false; | |
189 } | |
165 | 190 |
166 WIN32_FIND_DATA find_file_data; | 191 WIN32_FIND_DATA find_file_data; |
167 HANDLE find_handle = FindFirstFile(path, &find_file_data); | 192 HANDLE find_handle = FindFirstFile(path, &find_file_data); |
168 | 193 |
169 // Adjust the path by removing the '*' used for the search. | 194 // Adjust the path by removing the '*' used for the search. |
170 path_length -= 1; | 195 path_length -= 1; |
171 path[path_length] = '\0'; | 196 path[path_length] = '\0'; |
172 | 197 |
173 if (find_handle == INVALID_HANDLE_VALUE) { | 198 if (find_handle == INVALID_HANDLE_VALUE) { |
174 PostError(error_port, "Directory listing failed for: ", path); | 199 PostError(error_port, "Directory listing failed for: ", path); |
175 free(path); | 200 free(path); |
176 return false; | 201 return false; |
177 } | 202 } |
178 | 203 |
179 bool listing_error = !HandleEntry(&find_file_data, | 204 bool success = HandleEntry(&find_file_data, |
180 path, | 205 path, |
181 path_length, | 206 path_length, |
182 recursive, | 207 recursive, |
183 dir_port, | 208 dir_port, |
184 file_port, | 209 file_port, |
185 done_port, | 210 done_port, |
186 error_port); | 211 error_port); |
187 | 212 |
188 while ((FindNextFile(find_handle, &find_file_data) != 0) && !listing_error) { | 213 while ((FindNextFile(find_handle, &find_file_data) != 0) && success) { |
189 listing_error = listing_error || !HandleEntry(&find_file_data, | 214 success = success && HandleEntry(&find_file_data, |
190 path, | 215 path, |
191 path_length, | 216 path_length, |
192 recursive, | 217 recursive, |
193 dir_port, | 218 dir_port, |
194 file_port, | 219 file_port, |
195 done_port, | 220 done_port, |
196 error_port); | 221 error_port); |
197 } | 222 } |
198 | 223 |
199 if (GetLastError() != ERROR_NO_MORE_FILES) { | 224 if (GetLastError() != ERROR_NO_MORE_FILES) { |
200 listing_error = true; | 225 success = false; |
201 PostError(error_port, "Directory listing failed", ""); | 226 PostError(error_port, "Directory listing failed", ""); |
202 } | 227 } |
203 | 228 |
204 if (FindClose(find_handle) == 0) { | 229 if (FindClose(find_handle) == 0) { |
205 PostError(error_port, "Failed to close directory", ""); | 230 PostError(error_port, "Failed to close directory", ""); |
206 } | 231 } |
207 free(path); | 232 free(path); |
208 | 233 |
209 return !listing_error; | 234 return success; |
210 } | 235 } |
211 | 236 |
212 | 237 |
238 static bool DeleteFile(char* file_name, | |
239 char* path, | |
240 int path_length) { | |
241 size_t written = snprintf(path + path_length, | |
242 MAX_PATH - path_length, | |
243 "%s", | |
244 file_name); | |
245 if (written != strlen(file_name)) { | |
246 return false; | |
247 } | |
248 return (DeleteFile(path) != 0); | |
249 } | |
250 | |
251 | |
252 static bool DeleteDir(char* dir_name, | |
253 char* path, | |
254 int path_length) { | |
255 if (strcmp(dir_name, ".") != 0 && | |
256 strcmp(dir_name, "..") != 0) { | |
257 size_t written = snprintf(path + path_length, | |
258 MAX_PATH - path_length, | |
259 "%s", | |
260 dir_name); | |
261 if (written != strlen(dir_name)) { | |
262 return false; | |
263 } | |
264 return DeleteRecursively(path); | |
265 } | |
266 return true; | |
267 } | |
268 | |
269 | |
270 static bool DeleteEntry(LPWIN32_FIND_DATA find_file_data, | |
271 char* path, | |
272 int path_length) { | |
273 DWORD attributes = find_file_data->dwFileAttributes; | |
274 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { | |
275 return DeleteDir(find_file_data->cFileName, path, path_length); | |
276 } else { | |
277 return DeleteFile(find_file_data->cFileName, path, path_length); | |
278 } | |
279 } | |
280 | |
281 | |
282 static bool DeleteRecursively(const char* dir_name) { | |
283 // Compute full path for the directory currently being deleted. The | |
284 // path buffer will be used to construct the current path in the | |
285 // recursive traversal. path_length does not always equal | |
286 // strlen(path) but indicates the current prefix of path that is the | |
287 // path of the current directory in the traversal. | |
288 char* path = static_cast<char*>(malloc(MAX_PATH)); | |
289 int path_length = 0; | |
290 bool valid = ComputeFullSearchPath(dir_name, path, &path_length); | |
291 if (!valid) { | |
292 free(path); | |
293 return false; | |
294 } | |
295 | |
296 WIN32_FIND_DATA find_file_data; | |
297 HANDLE find_handle = FindFirstFile(path, &find_file_data); | |
298 | |
299 // Adjust the path by removing the '*' used for the search. | |
300 path_length -= 1; | |
301 path[path_length] = '\0'; | |
302 | |
303 if (find_handle == INVALID_HANDLE_VALUE) { | |
304 free(path); | |
305 return false; | |
306 } | |
307 | |
308 bool success = DeleteEntry(&find_file_data, path, path_length); | |
309 | |
310 while ((FindNextFile(find_handle, &find_file_data) != 0) && success) { | |
311 success = success && DeleteEntry(&find_file_data, path, path_length); | |
312 } | |
313 | |
314 free(path); | |
315 | |
316 if ((GetLastError() != ERROR_NO_MORE_FILES) || | |
317 (FindClose(find_handle) == 0) || | |
318 (RemoveDirectory(dir_name) == 0)) { | |
319 return false; | |
320 } | |
321 | |
322 return success; | |
323 } | |
324 | |
325 | |
213 void Directory::List(const char* dir_name, | 326 void Directory::List(const char* dir_name, |
214 bool recursive, | 327 bool recursive, |
215 Dart_Port dir_port, | 328 Dart_Port dir_port, |
216 Dart_Port file_port, | 329 Dart_Port file_port, |
217 Dart_Port done_port, | 330 Dart_Port done_port, |
218 Dart_Port error_port) { | 331 Dart_Port error_port) { |
219 bool result = ListRecursively(dir_name, | 332 bool result = ListRecursively(dir_name, |
220 recursive, | 333 recursive, |
221 dir_port, | 334 dir_port, |
222 file_port, | 335 file_port, |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
320 free(*path); | 433 free(*path); |
321 *path = NULL; | 434 *path = NULL; |
322 int error_code = | 435 int error_code = |
323 SetOsErrorMessage(os_error_message, os_error_message_len); | 436 SetOsErrorMessage(os_error_message, os_error_message_len); |
324 return error_code; | 437 return error_code; |
325 } | 438 } |
326 return 0; | 439 return 0; |
327 } | 440 } |
328 | 441 |
329 | 442 |
330 bool Directory::Delete(const char* dir_name) { | 443 bool Directory::Delete(const char* dir_name, bool recursive) { |
331 return (RemoveDirectory(dir_name) != 0); | 444 if (!recursive) { |
445 return (RemoveDirectory(dir_name) != 0); | |
446 } else { | |
447 return DeleteRecursively(dir_name); | |
448 } | |
332 } | 449 } |
OLD | NEW |