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

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

Issue 13654002: Change how File/Directory/Link .delete works. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix windows error codes. Created 7 years, 8 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) 2012, 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 "platform/globals.h" 5 #include "platform/globals.h"
6 #if defined(TARGET_OS_WINDOWS) 6 #if defined(TARGET_OS_WINDOWS)
7 7
8 #include "bin/directory.h" 8 #include "bin/directory.h"
9 #include "bin/file.h"
9 10
10 #include <errno.h> // NOLINT 11 #include <errno.h> // NOLINT
11 #include <sys/stat.h> // NOLINT 12 #include <sys/stat.h> // NOLINT
12 13
13 #include "bin/log.h" 14 #include "bin/log.h"
14 15
15 class PathBuffer { 16 class PathBuffer {
16 public: 17 public:
17 PathBuffer() : length(0) { 18 PathBuffer() : length(0) {
18 data = new wchar_t[MAX_PATH + 1]; 19 data = new wchar_t[MAX_PATH + 1];
(...skipping 22 matching lines...) Expand all
41 return false; 42 return false;
42 } 43 }
43 } 44 }
44 45
45 void Reset(int new_length) { 46 void Reset(int new_length) {
46 length = new_length; 47 length = new_length;
47 data[length] = L'\0'; 48 data[length] = L'\0';
48 } 49 }
49 }; 50 };
50 51
52 // If link_name points to a link, IsBrokenLink will return true if link_name
53 // points to an invalid target.
54 static bool IsBrokenLink(const wchar_t* link_name) {
55 HANDLE handle = CreateFileW(
56 link_name,
57 0,
58 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
59 NULL,
60 OPEN_EXISTING,
61 FILE_FLAG_BACKUP_SEMANTICS,
62 NULL);
63 if (handle == INVALID_HANDLE_VALUE) {
64 return true;
65 } else {
66 CloseHandle(handle);
67 return false;
68 }
69 }
70
51 71
52 // Forward declarations. 72 // Forward declarations.
53 static bool ListRecursively(PathBuffer* path, 73 static bool ListRecursively(PathBuffer* path,
54 bool recursive, 74 bool recursive,
55 bool follow_links, 75 bool follow_links,
56 DirectoryListing* listing); 76 DirectoryListing* listing);
57 static bool DeleteRecursively(PathBuffer* path); 77 static bool DeleteRecursively(PathBuffer* path);
58 78
59 79
60 static void PostError(DirectoryListing* listing, 80 static void PostError(DirectoryListing* listing,
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 static bool HandleEntry(LPWIN32_FIND_DATAW find_file_data, 135 static bool HandleEntry(LPWIN32_FIND_DATAW find_file_data,
116 PathBuffer* path, 136 PathBuffer* path,
117 bool recursive, 137 bool recursive,
118 bool follow_links, 138 bool follow_links,
119 DirectoryListing* listing) { 139 DirectoryListing* listing) {
120 DWORD attributes = find_file_data->dwFileAttributes; 140 DWORD attributes = find_file_data->dwFileAttributes;
121 if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { 141 if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
122 if (!follow_links) { 142 if (!follow_links) {
123 return HandleLink(find_file_data->cFileName, path, listing); 143 return HandleLink(find_file_data->cFileName, path, listing);
124 } 144 }
125 // Attempt to list the directory, to see if it's a valid link or not.
126 int path_length = path->length; 145 int path_length = path->length;
127 if (!path->Add(find_file_data->cFileName)) return false; 146 if (!path->Add(find_file_data->cFileName)) return false;
128 if (!path->Add(L"\\*")) return false; 147 bool broken = IsBrokenLink(path->data);
129 WIN32_FIND_DATAW tmp_file_data;
130 HANDLE find_handle = FindFirstFileW(path->data, &tmp_file_data);
131 path->Reset(path_length); 148 path->Reset(path_length);
132 if (find_handle == INVALID_HANDLE_VALUE) { 149 if (broken) {
133 // Invalid handle, report as (broken) link. 150 // Report as (broken) link.
134 return HandleLink(find_file_data->cFileName, path, listing); 151 return HandleLink(find_file_data->cFileName, path, listing);
135 } else {
136 FindClose(find_handle);
137 } 152 }
138 } 153 }
139 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { 154 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
140 return HandleDir(find_file_data->cFileName, 155 return HandleDir(find_file_data->cFileName,
141 path, 156 path,
142 recursive, 157 recursive,
143 follow_links, 158 follow_links,
144 listing); 159 listing);
145 } else { 160 } else {
146 return HandleFile(find_file_data->cFileName, path, listing); 161 return HandleFile(find_file_data->cFileName, path, listing);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 } 261 }
247 } 262 }
248 263
249 264
250 static bool DeleteRecursively(PathBuffer* path) { 265 static bool DeleteRecursively(PathBuffer* path) {
251 // If the directory is a junction, it's pointing to some other place in the 266 // If the directory is a junction, it's pointing to some other place in the
252 // filesystem that we do not want to recurse into. 267 // filesystem that we do not want to recurse into.
253 DWORD attributes = GetFileAttributesW(path->data); 268 DWORD attributes = GetFileAttributesW(path->data);
254 if ((attributes != INVALID_FILE_ATTRIBUTES) && 269 if ((attributes != INVALID_FILE_ATTRIBUTES) &&
255 (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { 270 (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
256 // Just delete the junction itself. 271 if (IsBrokenLink(path->data)) {
257 return RemoveDirectoryW(path->data) != 0; 272 return false;
273 } else {
274 // Just delete the junction itself.
275 return RemoveDirectoryW(path->data) != 0;
276 }
258 } 277 }
259 278
260 if (!path->Add(L"\\*")) return false; 279 if (!path->Add(L"\\*")) return false;
261 280
262 WIN32_FIND_DATAW find_file_data; 281 WIN32_FIND_DATAW find_file_data;
263 HANDLE find_handle = FindFirstFileW(path->data, &find_file_data); 282 HANDLE find_handle = FindFirstFileW(path->data, &find_file_data);
264 283
265 // Adjust the path by removing the '*' used for the search. 284 // Adjust the path by removing the '*' used for the search.
266 int path_length = path->length - 1; 285 int path_length = path->length - 1;
267 path->Reset(path_length); 286 path->Reset(path_length);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 last_error == ERROR_PATH_NOT_FOUND) { 330 last_error == ERROR_PATH_NOT_FOUND) {
312 return Directory::DOES_NOT_EXIST; 331 return Directory::DOES_NOT_EXIST;
313 } else { 332 } else {
314 // We might not be able to get the file attributes for other 333 // We might not be able to get the file attributes for other
315 // reasons such as lack of permissions. In that case we do 334 // reasons such as lack of permissions. In that case we do
316 // not know if the directory exists. 335 // not know if the directory exists.
317 return Directory::UNKNOWN; 336 return Directory::UNKNOWN;
318 } 337 }
319 } 338 }
320 bool exists = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; 339 bool exists = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
340 exists = exists && !IsBrokenLink(dir_name);
321 return exists ? Directory::EXISTS : Directory::DOES_NOT_EXIST; 341 return exists ? Directory::EXISTS : Directory::DOES_NOT_EXIST;
322 } 342 }
323 343
324 344
325 Directory::ExistsResult Directory::Exists(const char* dir_name) { 345 Directory::ExistsResult Directory::Exists(const char* dir_name) {
326 const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name); 346 const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name);
327 Directory::ExistsResult result = ExistsHelper(system_name); 347 Directory::ExistsResult result = ExistsHelper(system_name);
328 free(const_cast<wchar_t*>(system_name)); 348 free(const_cast<wchar_t*>(system_name));
329 return result; 349 return result;
330 } 350 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 } 420 }
401 char* result = StringUtils::WideToUtf8(path.data); 421 char* result = StringUtils::WideToUtf8(path.data);
402 return result; 422 return result;
403 } 423 }
404 424
405 425
406 bool Directory::Delete(const char* dir_name, bool recursive) { 426 bool Directory::Delete(const char* dir_name, bool recursive) {
407 bool result = false; 427 bool result = false;
408 const wchar_t* system_dir_name = StringUtils::Utf8ToWide(dir_name); 428 const wchar_t* system_dir_name = StringUtils::Utf8ToWide(dir_name);
409 if (!recursive) { 429 if (!recursive) {
410 result = (RemoveDirectoryW(system_dir_name) != 0); 430 if (File::GetType(dir_name, true) == File::kIsDirectory) {
431 result = (RemoveDirectoryW(system_dir_name) != 0);
432 } else {
433 SetLastError(ERROR_DIRECTORY);
434 }
411 } else { 435 } else {
412 PathBuffer path; 436 PathBuffer path;
413 if (!path.Add(system_dir_name)) { 437 if (path.Add(system_dir_name)) {
414 return false; 438 result = DeleteRecursively(&path);
415 } 439 }
416 result = DeleteRecursively(&path);
417 } 440 }
418 free(const_cast<wchar_t*>(system_dir_name)); 441 free(const_cast<wchar_t*>(system_dir_name));
419 return result; 442 return result;
420 } 443 }
421 444
422 445
423 bool Directory::Rename(const char* path, const char* new_path) { 446 bool Directory::Rename(const char* path, const char* new_path) {
424 const wchar_t* system_path = StringUtils::Utf8ToWide(path); 447 const wchar_t* system_path = StringUtils::Utf8ToWide(path);
425 const wchar_t* system_new_path = StringUtils::Utf8ToWide(new_path); 448 const wchar_t* system_new_path = StringUtils::Utf8ToWide(new_path);
426 ExistsResult exists = ExistsHelper(system_path); 449 ExistsResult exists = ExistsHelper(system_path);
427 if (exists != EXISTS) return false; 450 if (exists != EXISTS) return false;
428 ExistsResult new_exists = ExistsHelper(system_new_path); 451 ExistsResult new_exists = ExistsHelper(system_new_path);
429 // MoveFile does not allow replacing exising directories. Therefore, 452 // MoveFile does not allow replacing exising directories. Therefore,
430 // if the new_path is currently a directory we need to delete it 453 // if the new_path is currently a directory we need to delete it
431 // first. 454 // first.
432 if (new_exists == EXISTS) { 455 if (new_exists == EXISTS) {
433 bool success = Delete(new_path, true); 456 bool success = Delete(new_path, true);
434 if (!success) return false; 457 if (!success) return false;
435 } 458 }
436 DWORD flags = MOVEFILE_WRITE_THROUGH; 459 DWORD flags = MOVEFILE_WRITE_THROUGH;
437 int move_status = 460 int move_status =
438 MoveFileExW(system_path, system_new_path, flags); 461 MoveFileExW(system_path, system_new_path, flags);
439 free(const_cast<wchar_t*>(system_path)); 462 free(const_cast<wchar_t*>(system_path));
440 free(const_cast<wchar_t*>(system_new_path)); 463 free(const_cast<wchar_t*>(system_new_path));
441 return (move_status != 0); 464 return (move_status != 0);
442 } 465 }
443 466
444 #endif // defined(TARGET_OS_WINDOWS) 467 #endif // defined(TARGET_OS_WINDOWS)
OLDNEW
« no previous file with comments | « runtime/bin/directory_macos.cc ('k') | runtime/bin/file.h » ('j') | runtime/bin/file_win.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698