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

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

Powered by Google App Engine
This is Rietveld 408576698