Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Side by Side Diff: runtime/bin/directory_win.cc

Issue 9316066: Implement recursive directory deletion. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698