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

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

Issue 1781883002: Fixes some memory leaks in //runtime/bin (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fix tests on Windows Created 4 years, 9 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
« no previous file with comments | « runtime/bin/directory_macos.cc ('k') | runtime/bin/fdutils_android.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include "bin/file.h"
10 #include "bin/utils.h" 10 #include "bin/utils.h"
11 #include "bin/utils_win.h" 11 #include "bin/utils_win.h"
12 12
13 #include <errno.h> // NOLINT 13 #include <errno.h> // NOLINT
14 #include <sys/stat.h> // NOLINT 14 #include <sys/stat.h> // NOLINT
15 15
16 #include "bin/dartutils.h"
16 #include "bin/log.h" 17 #include "bin/log.h"
17 18
18 #undef DeleteFile 19 #undef DeleteFile
19 20
20 #define MAX_LONG_PATH 32767 21 #define MAX_LONG_PATH 32767
21 22
22 namespace dart { 23 namespace dart {
23 namespace bin { 24 namespace bin {
24 25
25 PathBuffer::PathBuffer() : length_(0) { 26 PathBuffer::PathBuffer() : length_(0) {
26 data_ = calloc(MAX_LONG_PATH + 1, sizeof(wchar_t)); // NOLINT 27 data_ = calloc(MAX_LONG_PATH + 1, sizeof(wchar_t)); // NOLINT
27 } 28 }
28 29
30
31 PathBuffer::~PathBuffer() {
32 free(data_);
33 }
34
35
29 char* PathBuffer::AsString() const { 36 char* PathBuffer::AsString() const {
30 return StringUtilsWin::WideToUtf8(AsStringW()); 37 UNREACHABLE();
38 return NULL;
31 } 39 }
32 40
41
33 wchar_t* PathBuffer::AsStringW() const { 42 wchar_t* PathBuffer::AsStringW() const {
34 return reinterpret_cast<wchar_t*>(data_); 43 return reinterpret_cast<wchar_t*>(data_);
35 } 44 }
36 45
46
47 const char* PathBuffer::AsScopedString() const {
48 return StringUtilsWin::WideToUtf8(AsStringW());
49 }
50
51
37 bool PathBuffer::Add(const char* name) { 52 bool PathBuffer::Add(const char* name) {
38 const wchar_t* wide_name = StringUtilsWin::Utf8ToWide(name); 53 const wchar_t* wide_name = StringUtilsWin::Utf8ToWide(name);
39 bool success = AddW(wide_name); 54 return AddW(wide_name);
40 free(const_cast<wchar_t*>(wide_name));
41 return success;
42 } 55 }
43 56
57
44 bool PathBuffer::AddW(const wchar_t* name) { 58 bool PathBuffer::AddW(const wchar_t* name) {
45 wchar_t* data = AsStringW(); 59 wchar_t* data = AsStringW();
46 int written = _snwprintf(data + length_, 60 int written = _snwprintf(data + length_,
47 MAX_LONG_PATH - length_, 61 MAX_LONG_PATH - length_,
48 L"%s", 62 L"%s",
49 name); 63 name);
50 data[MAX_LONG_PATH] = L'\0'; 64 data[MAX_LONG_PATH] = L'\0';
51 if (written <= MAX_LONG_PATH - length_ && 65 if ((written <= MAX_LONG_PATH - length_) &&
52 written >= 0 && 66 (written >= 0) &&
53 static_cast<size_t>(written) == wcsnlen(name, MAX_LONG_PATH + 1)) { 67 (static_cast<size_t>(written) == wcsnlen(name, MAX_LONG_PATH + 1))) {
54 length_ += written; 68 length_ += written;
55 return true; 69 return true;
56 } else { 70 } else {
57 SetLastError(ERROR_BUFFER_OVERFLOW); 71 SetLastError(ERROR_BUFFER_OVERFLOW);
58 return false; 72 return false;
59 } 73 }
60 } 74 }
61 75
62 void PathBuffer::Reset(int new_length) { 76
77 void PathBuffer::Reset(intptr_t new_length) {
63 length_ = new_length; 78 length_ = new_length;
64 AsStringW()[length_] = L'\0'; 79 AsStringW()[length_] = L'\0';
65 } 80 }
66 81
82
67 // If link_name points to a link, IsBrokenLink will return true if link_name 83 // If link_name points to a link, IsBrokenLink will return true if link_name
68 // points to an invalid target. 84 // points to an invalid target.
69 static bool IsBrokenLink(const wchar_t* link_name) { 85 static bool IsBrokenLink(const wchar_t* link_name) {
70 HANDLE handle = CreateFileW( 86 HANDLE handle = CreateFileW(
71 link_name, 87 link_name,
72 0, 88 0,
73 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 89 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
74 NULL, 90 NULL,
75 OPEN_EXISTING, 91 OPEN_EXISTING,
76 FILE_FLAG_BACKUP_SEMANTICS, 92 FILE_FLAG_BACKUP_SEMANTICS,
77 NULL); 93 NULL);
78 if (handle == INVALID_HANDLE_VALUE) { 94 if (handle == INVALID_HANDLE_VALUE) {
79 return true; 95 return true;
80 } else { 96 } else {
81 CloseHandle(handle); 97 CloseHandle(handle);
82 return false; 98 return false;
83 } 99 }
84 } 100 }
85 101
102
86 // A linked list structure holding a link target's unique file system ID. 103 // A linked list structure holding a link target's unique file system ID.
87 // Used to detect loops in the file system when listing recursively. 104 // Used to detect loops in the file system when listing recursively.
88 struct LinkList { 105 struct LinkList {
89 DWORD volume; 106 DWORD volume;
90 DWORD id_low; 107 DWORD id_low;
91 DWORD id_high; 108 DWORD id_high;
92 LinkList* next; 109 LinkList* next;
93 }; 110 };
94 111
95 // Forward declarations. 112 // Forward declarations.
96 static bool DeleteRecursively(PathBuffer* path); 113 static bool DeleteRecursively(PathBuffer* path);
97 114
98 115
99 static ListType HandleFindFile(DirectoryListing* listing, 116 static ListType HandleFindFile(DirectoryListing* listing,
100 DirectoryListingEntry* entry, 117 DirectoryListingEntry* entry,
101 WIN32_FIND_DATAW& find_file_data) { 118 const WIN32_FIND_DATAW& find_file_data) {
102 if (!listing->path_buffer().AddW(find_file_data.cFileName)) { 119 if (!listing->path_buffer().AddW(find_file_data.cFileName)) {
103 return kListError; 120 return kListError;
104 } 121 }
105 DWORD attributes = find_file_data.dwFileAttributes; 122 DWORD attributes = find_file_data.dwFileAttributes;
106 if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { 123 if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
107 if (!listing->follow_links()) { 124 if (!listing->follow_links()) {
108 return kListLink; 125 return kListLink;
109 } 126 }
110 HANDLE handle = CreateFileW( 127 HANDLE handle = CreateFileW(
111 listing->path_buffer().AsStringW(), 128 listing->path_buffer().AsStringW(),
(...skipping 18 matching lines...) Expand all
130 SetLastError(error); 147 SetLastError(error);
131 return kListError; 148 return kListError;
132 } 149 }
133 CloseHandle(handle); 150 CloseHandle(handle);
134 current_link.volume = info.dwVolumeSerialNumber; 151 current_link.volume = info.dwVolumeSerialNumber;
135 current_link.id_low = info.nFileIndexLow; 152 current_link.id_low = info.nFileIndexLow;
136 current_link.id_high = info.nFileIndexHigh; 153 current_link.id_high = info.nFileIndexHigh;
137 current_link.next = entry->link(); 154 current_link.next = entry->link();
138 LinkList* previous = entry->link(); 155 LinkList* previous = entry->link();
139 while (previous != NULL) { 156 while (previous != NULL) {
140 if (previous->volume == current_link.volume && 157 if ((previous->volume == current_link.volume) &&
141 previous->id_low == current_link.id_low && 158 (previous->id_low == current_link.id_low) &&
142 previous->id_high == current_link.id_high) { 159 (previous->id_high == current_link.id_high)) {
143 // Report the looping link as a link, rather than following it. 160 // Report the looping link as a link, rather than following it.
144 return kListLink; 161 return kListLink;
145 } 162 }
146 previous = previous->next; 163 previous = previous->next;
147 } 164 }
148 // Recurse into the directory, adding current link to the seen links list. 165 // Recurse into the directory, adding current link to the seen links list.
149 if (wcscmp(find_file_data.cFileName, L".") == 0 || 166 if ((wcscmp(find_file_data.cFileName, L".") == 0) ||
150 wcscmp(find_file_data.cFileName, L"..") == 0) { 167 (wcscmp(find_file_data.cFileName, L"..") == 0)) {
151 return entry->Next(listing); 168 return entry->Next(listing);
152 } 169 }
153 entry->set_link(new LinkList(current_link)); 170 entry->set_link(new LinkList(current_link));
154 return kListDirectory; 171 return kListDirectory;
155 } 172 }
156 } 173 }
157 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { 174 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
158 if (wcscmp(find_file_data.cFileName, L".") == 0 || 175 if ((wcscmp(find_file_data.cFileName, L".") == 0) ||
159 wcscmp(find_file_data.cFileName, L"..") == 0) { 176 (wcscmp(find_file_data.cFileName, L"..") == 0)) {
160 return entry->Next(listing); 177 return entry->Next(listing);
161 } 178 }
162 return kListDirectory; 179 return kListDirectory;
163 } else { 180 } else {
164 return kListFile; 181 return kListFile;
165 } 182 }
166 } 183 }
167 184
185
168 ListType DirectoryListingEntry::Next(DirectoryListing* listing) { 186 ListType DirectoryListingEntry::Next(DirectoryListing* listing) {
169 if (done_) { 187 if (done_) {
170 return kListDone; 188 return kListDone;
171 } 189 }
172 190
173 WIN32_FIND_DATAW find_file_data; 191 WIN32_FIND_DATAW find_file_data;
174 192
175 if (lister_ == 0) { 193 if (lister_ == 0) {
176 const wchar_t* tail = parent_ == NULL ? L"*" : L"\\*"; 194 const wchar_t* tail = parent_ == NULL ? L"*" : L"\\*";
177 if (!listing->path_buffer().AddW(tail)) { 195 if (!listing->path_buffer().AddW(tail)) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 234
217 DirectoryListingEntry::~DirectoryListingEntry() { 235 DirectoryListingEntry::~DirectoryListingEntry() {
218 ResetLink(); 236 ResetLink();
219 if (lister_ != 0) { 237 if (lister_ != 0) {
220 FindClose(reinterpret_cast<HANDLE>(lister_)); 238 FindClose(reinterpret_cast<HANDLE>(lister_));
221 } 239 }
222 } 240 }
223 241
224 242
225 void DirectoryListingEntry::ResetLink() { 243 void DirectoryListingEntry::ResetLink() {
226 if (link_ != NULL && (parent_ == NULL || parent_->link_ != link_)) { 244 if ((link_ != NULL) && ((parent_ == NULL) || (parent_->link_ != link_))) {
227 delete link_; 245 delete link_;
228 link_ = NULL; 246 link_ = NULL;
229 } 247 }
230 if (parent_ != NULL) { 248 if (parent_ != NULL) {
231 link_ = parent_->link_; 249 link_ = parent_->link_;
232 } 250 }
233 } 251 }
234 252
235 253
236 static bool DeleteFile(wchar_t* file_name, PathBuffer* path) { 254 static bool DeleteFile(wchar_t* file_name, PathBuffer* path) {
237 if (!path->AddW(file_name)) return false; 255 if (!path->AddW(file_name)) {
256 return false;
257 }
238 258
239 if (DeleteFileW(path->AsStringW()) != 0) { 259 if (DeleteFileW(path->AsStringW()) != 0) {
240 return true; 260 return true;
241 } 261 }
242 262
243 // If we failed because the file is read-only, make it writeable and try 263 // If we failed because the file is read-only, make it writeable and try
244 // again. This mirrors Linux/Mac where a directory containing read-only files 264 // again. This mirrors Linux/Mac where a directory containing read-only files
245 // can still be recursively deleted. 265 // can still be recursively deleted.
246 if (GetLastError() == ERROR_ACCESS_DENIED) { 266 if (GetLastError() == ERROR_ACCESS_DENIED) {
247 DWORD attributes = GetFileAttributesW(path->AsStringW()); 267 DWORD attributes = GetFileAttributesW(path->AsStringW());
(...skipping 10 matching lines...) Expand all
258 278
259 return DeleteFileW(path->AsStringW()) != 0; 279 return DeleteFileW(path->AsStringW()) != 0;
260 } 280 }
261 } 281 }
262 282
263 return false; 283 return false;
264 } 284 }
265 285
266 286
267 static bool DeleteDir(wchar_t* dir_name, PathBuffer* path) { 287 static bool DeleteDir(wchar_t* dir_name, PathBuffer* path) {
268 if (wcscmp(dir_name, L".") == 0) return true; 288 if ((wcscmp(dir_name, L".") == 0) ||
269 if (wcscmp(dir_name, L"..") == 0) return true; 289 (wcscmp(dir_name, L"..") == 0)) {
290 return true;
291 }
270 return path->AddW(dir_name) && DeleteRecursively(path); 292 return path->AddW(dir_name) && DeleteRecursively(path);
271 } 293 }
272 294
273 295
274 static bool DeleteEntry(LPWIN32_FIND_DATAW find_file_data, PathBuffer* path) { 296 static bool DeleteEntry(LPWIN32_FIND_DATAW find_file_data, PathBuffer* path) {
275 DWORD attributes = find_file_data->dwFileAttributes; 297 DWORD attributes = find_file_data->dwFileAttributes;
276 298
277 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { 299 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
278 return DeleteDir(find_file_data->cFileName, path); 300 return DeleteDir(find_file_data->cFileName, path);
279 } else { 301 } else {
280 return DeleteFile(find_file_data->cFileName, path); 302 return DeleteFile(find_file_data->cFileName, path);
281 } 303 }
282 } 304 }
283 305
284 306
285 static bool DeleteRecursively(PathBuffer* path) { 307 static bool DeleteRecursively(PathBuffer* path) {
286 DWORD attributes = GetFileAttributesW(path->AsStringW()); 308 DWORD attributes = GetFileAttributesW(path->AsStringW());
287 if ((attributes == INVALID_FILE_ATTRIBUTES)) { 309 if (attributes == INVALID_FILE_ATTRIBUTES) {
288 return false; 310 return false;
289 } 311 }
290 // If the directory is a junction, it's pointing to some other place in the 312 // If the directory is a junction, it's pointing to some other place in the
291 // filesystem that we do not want to recurse into. 313 // filesystem that we do not want to recurse into.
292 if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { 314 if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
293 // Just delete the junction itself. 315 // Just delete the junction itself.
294 return RemoveDirectoryW(path->AsStringW()) != 0; 316 return RemoveDirectoryW(path->AsStringW()) != 0;
295 } 317 }
296 // If it's a file, remove it directly. 318 // If it's a file, remove it directly.
297 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { 319 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
298 return DeleteFile(L"", path); 320 return DeleteFile(L"", path);
299 } 321 }
300 322
301 if (!path->AddW(L"\\*")) return false; 323 if (!path->AddW(L"\\*")) {
324 return false;
325 }
302 326
303 WIN32_FIND_DATAW find_file_data; 327 WIN32_FIND_DATAW find_file_data;
304 HANDLE find_handle = FindFirstFileW(path->AsStringW(), &find_file_data); 328 HANDLE find_handle = FindFirstFileW(path->AsStringW(), &find_file_data);
305 329
306 if (find_handle == INVALID_HANDLE_VALUE) { 330 if (find_handle == INVALID_HANDLE_VALUE) {
307 return false; 331 return false;
308 } 332 }
309 333
310 // Adjust the path by removing the '*' used for the search. 334 // Adjust the path by removing the '*' used for the search.
311 int path_length = path->length() - 1; 335 int path_length = path->length() - 1;
(...skipping 17 matching lines...) Expand all
329 // All content deleted succesfully, try to delete directory. 353 // All content deleted succesfully, try to delete directory.
330 path->Reset(path_length - 1); // Drop the "\" from the end of the path. 354 path->Reset(path_length - 1); // Drop the "\" from the end of the path.
331 return RemoveDirectoryW(path->AsStringW()) != 0; 355 return RemoveDirectoryW(path->AsStringW()) != 0;
332 } 356 }
333 357
334 358
335 static Directory::ExistsResult ExistsHelper(const wchar_t* dir_name) { 359 static Directory::ExistsResult ExistsHelper(const wchar_t* dir_name) {
336 DWORD attributes = GetFileAttributesW(dir_name); 360 DWORD attributes = GetFileAttributesW(dir_name);
337 if (attributes == INVALID_FILE_ATTRIBUTES) { 361 if (attributes == INVALID_FILE_ATTRIBUTES) {
338 DWORD last_error = GetLastError(); 362 DWORD last_error = GetLastError();
339 if (last_error == ERROR_FILE_NOT_FOUND || 363 if ((last_error == ERROR_FILE_NOT_FOUND) ||
340 last_error == ERROR_PATH_NOT_FOUND) { 364 (last_error == ERROR_PATH_NOT_FOUND)) {
341 return Directory::DOES_NOT_EXIST; 365 return Directory::DOES_NOT_EXIST;
342 } else { 366 } else {
343 // We might not be able to get the file attributes for other 367 // We might not be able to get the file attributes for other
344 // reasons such as lack of permissions. In that case we do 368 // reasons such as lack of permissions. In that case we do
345 // not know if the directory exists. 369 // not know if the directory exists.
346 return Directory::UNKNOWN; 370 return Directory::UNKNOWN;
347 } 371 }
348 } 372 }
349 bool exists = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; 373 bool exists = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
350 exists = exists && !IsBrokenLink(dir_name); 374 exists = exists && !IsBrokenLink(dir_name);
351 return exists ? Directory::EXISTS : Directory::DOES_NOT_EXIST; 375 return exists ? Directory::EXISTS : Directory::DOES_NOT_EXIST;
352 } 376 }
353 377
354 378
355 Directory::ExistsResult Directory::Exists(const char* dir_name) { 379 Directory::ExistsResult Directory::Exists(const char* dir_name) {
356 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(dir_name); 380 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(dir_name);
357 Directory::ExistsResult result = ExistsHelper(system_name); 381 return ExistsHelper(system_name);
358 free(const_cast<wchar_t*>(system_name)); 382 }
383
384
385 char* Directory::CurrentNoScope() {
386 int length = GetCurrentDirectoryW(0, NULL);
387 if (length == 0) {
388 return NULL;
389 }
390 wchar_t* current = new wchar_t[length + 1];
391 GetCurrentDirectoryW(length + 1, current);
392 int utf8_len = WideCharToMultiByte(
393 CP_UTF8, 0, current, -1, NULL, 0, NULL, NULL);
394 char* result = reinterpret_cast<char*>(malloc(utf8_len));
395 WideCharToMultiByte(CP_UTF8, 0, current, -1, result, utf8_len, NULL, NULL);
396 delete[] current;
359 return result; 397 return result;
360 } 398 }
361 399
362 400
363 char* Directory::Current() { 401 const char* Directory::Current() {
364 int length = GetCurrentDirectoryW(0, NULL); 402 int length = GetCurrentDirectoryW(0, NULL);
365 if (length == 0) return NULL; 403 if (length == 0) {
366 wchar_t* current = new wchar_t[length + 1]; 404 return NULL;
405 }
406 wchar_t* current;
407 current = reinterpret_cast<wchar_t*>(
408 Dart_ScopeAllocate((length + 1) * sizeof(*current)));
367 GetCurrentDirectoryW(length + 1, current); 409 GetCurrentDirectoryW(length + 1, current);
368 char* result = StringUtilsWin::WideToUtf8(current); 410 return StringUtilsWin::WideToUtf8(current);
369 delete[] current;
370 return result;
371 } 411 }
372 412
373 413
374 bool Directory::SetCurrent(const char* path) { 414 bool Directory::SetCurrent(const char* path) {
375 const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path); 415 const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path);
376 bool result = SetCurrentDirectoryW(system_path) != 0; 416 bool result = SetCurrentDirectoryW(system_path) != 0;
377 free(const_cast<wchar_t*>(system_path));
378 return result; 417 return result;
379 } 418 }
380 419
381 420
382 bool Directory::Create(const char* dir_name) { 421 bool Directory::Create(const char* dir_name) {
383 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(dir_name); 422 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(dir_name);
384 int create_status = CreateDirectoryW(system_name, NULL); 423 int create_status = CreateDirectoryW(system_name, NULL);
385 // If the directory already existed, treat it as a success. 424 // If the directory already existed, treat it as a success.
386 if (create_status == 0 && 425 if ((create_status == 0) &&
387 GetLastError() == ERROR_ALREADY_EXISTS && 426 (GetLastError() == ERROR_ALREADY_EXISTS) &&
388 ExistsHelper(system_name) == EXISTS) { 427 (ExistsHelper(system_name) == EXISTS)) {
389 free(const_cast<wchar_t*>(system_name));
390 return true; 428 return true;
391 } 429 }
392 free(const_cast<wchar_t*>(system_name));
393 return (create_status != 0); 430 return (create_status != 0);
394 } 431 }
395 432
396 433
397 char* Directory::SystemTemp() { 434 const char* Directory::SystemTemp() {
398 PathBuffer path; 435 PathBuffer path;
399 // Remove \ at end. 436 // Remove \ at end.
400 path.Reset(GetTempPathW(MAX_LONG_PATH, path.AsStringW()) - 1); 437 path.Reset(GetTempPathW(MAX_LONG_PATH, path.AsStringW()) - 1);
401 return path.AsString(); 438 return path.AsScopedString();
402 } 439 }
403 440
404 441
405 char* Directory::CreateTemp(const char* prefix) { 442 const char* Directory::CreateTemp(const char* prefix) {
406 // Returns a new, unused directory name, adding characters to the 443 // Returns a new, unused directory name, adding characters to the
407 // end of prefix. 444 // end of prefix.
408 // Creates this directory, with a default security 445 // Creates this directory, with a default security
409 // descriptor inherited from its parent directory. 446 // descriptor inherited from its parent directory.
410 // The return value must be freed by the caller. 447 // The return value is Dart_ScopeAllocated.
411 PathBuffer path; 448 PathBuffer path;
412 const wchar_t* system_prefix = StringUtilsWin::Utf8ToWide(prefix); 449 const wchar_t* system_prefix = StringUtilsWin::Utf8ToWide(prefix);
413 path.AddW(system_prefix); 450 if (!path.AddW(system_prefix)) {
414 free(const_cast<wchar_t*>(system_prefix)); 451 return NULL;
452 }
415 453
416 // Length of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 36. 454 // Length of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 36.
417 if (path.length() > MAX_LONG_PATH - 36) { 455 if (path.length() > MAX_LONG_PATH - 36) {
418 return NULL; 456 return NULL;
419 } 457 }
420 458
421 UUID uuid; 459 UUID uuid;
422 RPC_STATUS status = UuidCreateSequential(&uuid); 460 RPC_STATUS status = UuidCreateSequential(&uuid);
423 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { 461 if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) {
424 return NULL; 462 return NULL;
425 } 463 }
426 RPC_WSTR uuid_string; 464 RPC_WSTR uuid_string;
427 status = UuidToStringW(&uuid, &uuid_string); 465 status = UuidToStringW(&uuid, &uuid_string);
428 if (status != RPC_S_OK) { 466 if (status != RPC_S_OK) {
429 return NULL; 467 return NULL;
430 } 468 }
431 469
432 // RPC_WSTR is an unsigned short*, so we cast to wchar_t*. 470 // RPC_WSTR is an unsigned short*, so we cast to wchar_t*.
433 path.AddW(reinterpret_cast<wchar_t*>(uuid_string)); 471 if (!path.AddW(reinterpret_cast<wchar_t*>(uuid_string))) {
472 return NULL;
473 }
434 RpcStringFreeW(&uuid_string); 474 RpcStringFreeW(&uuid_string);
435 if (!CreateDirectoryW(path.AsStringW(), NULL)) { 475 if (!CreateDirectoryW(path.AsStringW(), NULL)) {
436 return NULL; 476 return NULL;
437 } 477 }
438 char* result = path.AsString(); 478 return path.AsScopedString();
439 return result;
440 } 479 }
441 480
442 481
443 bool Directory::Delete(const char* dir_name, bool recursive) { 482 bool Directory::Delete(const char* dir_name, bool recursive) {
444 bool result = false; 483 bool result = false;
445 const wchar_t* system_dir_name = StringUtilsWin::Utf8ToWide(dir_name); 484 const wchar_t* system_dir_name = StringUtilsWin::Utf8ToWide(dir_name);
446 if (!recursive) { 485 if (!recursive) {
447 if (File::GetType(dir_name, true) == File::kIsDirectory) { 486 if (File::GetType(dir_name, true) == File::kIsDirectory) {
448 result = (RemoveDirectoryW(system_dir_name) != 0); 487 result = (RemoveDirectoryW(system_dir_name) != 0);
449 } else { 488 } else {
450 SetLastError(ERROR_FILE_NOT_FOUND); 489 SetLastError(ERROR_FILE_NOT_FOUND);
451 } 490 }
452 } else { 491 } else {
453 PathBuffer path; 492 PathBuffer path;
454 if (path.AddW(system_dir_name)) { 493 if (path.AddW(system_dir_name)) {
455 result = DeleteRecursively(&path); 494 result = DeleteRecursively(&path);
456 } 495 }
457 } 496 }
458 free(const_cast<wchar_t*>(system_dir_name));
459 return result; 497 return result;
460 } 498 }
461 499
462 500
463 bool Directory::Rename(const char* path, const char* new_path) { 501 bool Directory::Rename(const char* path, const char* new_path) {
464 const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path); 502 const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path);
465 const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path); 503 const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path);
466 ExistsResult exists = ExistsHelper(system_path); 504 ExistsResult exists = ExistsHelper(system_path);
467 if (exists != EXISTS) return false; 505 if (exists != EXISTS) {
506 return false;
507 }
468 ExistsResult new_exists = ExistsHelper(system_new_path); 508 ExistsResult new_exists = ExistsHelper(system_new_path);
469 // MoveFile does not allow replacing exising directories. Therefore, 509 // MoveFile does not allow replacing exising directories. Therefore,
470 // if the new_path is currently a directory we need to delete it 510 // if the new_path is currently a directory we need to delete it
471 // first. 511 // first.
472 if (new_exists == EXISTS) { 512 if (new_exists == EXISTS) {
473 bool success = Delete(new_path, true); 513 bool success = Delete(new_path, true);
474 if (!success) return false; 514 if (!success) {
515 return false;
516 }
475 } 517 }
476 DWORD flags = MOVEFILE_WRITE_THROUGH; 518 DWORD flags = MOVEFILE_WRITE_THROUGH;
477 int move_status = 519 int move_status =
478 MoveFileExW(system_path, system_new_path, flags); 520 MoveFileExW(system_path, system_new_path, flags);
479 free(const_cast<wchar_t*>(system_path));
480 free(const_cast<wchar_t*>(system_new_path));
481 return (move_status != 0); 521 return (move_status != 0);
482 } 522 }
483 523
484 } // namespace bin 524 } // namespace bin
485 } // namespace dart 525 } // namespace dart
486 526
487 #endif // defined(TARGET_OS_WINDOWS) 527 #endif // defined(TARGET_OS_WINDOWS)
OLDNEW
« no previous file with comments | « runtime/bin/directory_macos.cc ('k') | runtime/bin/fdutils_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698