Index: runtime/bin/directory_win.cc |
diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc |
index 40bfb9bf158ddf36b53217204bf56c9589a373c1..efaaaf90a6e7ee6f08e5e94b2f5e6a0157d08900 100644 |
--- a/runtime/bin/directory_win.cc |
+++ b/runtime/bin/directory_win.cc |
@@ -13,6 +13,7 @@ |
#include <errno.h> // NOLINT |
#include <sys/stat.h> // NOLINT |
+#include "bin/dartutils.h" |
#include "bin/log.h" |
#undef DeleteFile |
@@ -23,24 +24,37 @@ namespace dart { |
namespace bin { |
PathBuffer::PathBuffer() : length_(0) { |
- data_ = calloc(MAX_LONG_PATH + 1, sizeof(wchar_t)); // NOLINT |
+ data_ = calloc(MAX_LONG_PATH + 1, sizeof(wchar_t)); // NOLINT |
} |
+ |
+PathBuffer::~PathBuffer() { |
+ free(data_); |
+} |
+ |
+ |
char* PathBuffer::AsString() const { |
- return StringUtilsWin::WideToUtf8(AsStringW()); |
+ UNREACHABLE(); |
+ return NULL; |
} |
+ |
wchar_t* PathBuffer::AsStringW() const { |
return reinterpret_cast<wchar_t*>(data_); |
} |
+ |
+const char* PathBuffer::AsScopedString() const { |
+ return StringUtilsWin::WideToUtf8(AsStringW()); |
+} |
+ |
+ |
bool PathBuffer::Add(const char* name) { |
const wchar_t* wide_name = StringUtilsWin::Utf8ToWide(name); |
- bool success = AddW(wide_name); |
- free(const_cast<wchar_t*>(wide_name)); |
- return success; |
+ return AddW(wide_name); |
} |
+ |
bool PathBuffer::AddW(const wchar_t* name) { |
wchar_t* data = AsStringW(); |
int written = _snwprintf(data + length_, |
@@ -48,9 +62,9 @@ bool PathBuffer::AddW(const wchar_t* name) { |
L"%s", |
name); |
data[MAX_LONG_PATH] = L'\0'; |
- if (written <= MAX_LONG_PATH - length_ && |
- written >= 0 && |
- static_cast<size_t>(written) == wcsnlen(name, MAX_LONG_PATH + 1)) { |
+ if ((written <= MAX_LONG_PATH - length_) && |
+ (written >= 0) && |
+ (static_cast<size_t>(written) == wcsnlen(name, MAX_LONG_PATH + 1))) { |
length_ += written; |
return true; |
} else { |
@@ -59,11 +73,13 @@ bool PathBuffer::AddW(const wchar_t* name) { |
} |
} |
-void PathBuffer::Reset(int new_length) { |
+ |
+void PathBuffer::Reset(intptr_t new_length) { |
length_ = new_length; |
AsStringW()[length_] = L'\0'; |
} |
+ |
// If link_name points to a link, IsBrokenLink will return true if link_name |
// points to an invalid target. |
static bool IsBrokenLink(const wchar_t* link_name) { |
@@ -83,6 +99,7 @@ static bool IsBrokenLink(const wchar_t* link_name) { |
} |
} |
+ |
// A linked list structure holding a link target's unique file system ID. |
// Used to detect loops in the file system when listing recursively. |
struct LinkList { |
@@ -98,7 +115,7 @@ static bool DeleteRecursively(PathBuffer* path); |
static ListType HandleFindFile(DirectoryListing* listing, |
DirectoryListingEntry* entry, |
- WIN32_FIND_DATAW& find_file_data) { |
+ const WIN32_FIND_DATAW& find_file_data) { |
if (!listing->path_buffer().AddW(find_file_data.cFileName)) { |
return kListError; |
} |
@@ -137,17 +154,17 @@ static ListType HandleFindFile(DirectoryListing* listing, |
current_link.next = entry->link(); |
LinkList* previous = entry->link(); |
while (previous != NULL) { |
- if (previous->volume == current_link.volume && |
- previous->id_low == current_link.id_low && |
- previous->id_high == current_link.id_high) { |
+ if ((previous->volume == current_link.volume) && |
+ (previous->id_low == current_link.id_low) && |
+ (previous->id_high == current_link.id_high)) { |
// Report the looping link as a link, rather than following it. |
return kListLink; |
} |
previous = previous->next; |
} |
// Recurse into the directory, adding current link to the seen links list. |
- if (wcscmp(find_file_data.cFileName, L".") == 0 || |
- wcscmp(find_file_data.cFileName, L"..") == 0) { |
+ if ((wcscmp(find_file_data.cFileName, L".") == 0) || |
+ (wcscmp(find_file_data.cFileName, L"..") == 0)) { |
return entry->Next(listing); |
} |
entry->set_link(new LinkList(current_link)); |
@@ -155,8 +172,8 @@ static ListType HandleFindFile(DirectoryListing* listing, |
} |
} |
if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
- if (wcscmp(find_file_data.cFileName, L".") == 0 || |
- wcscmp(find_file_data.cFileName, L"..") == 0) { |
+ if ((wcscmp(find_file_data.cFileName, L".") == 0) || |
+ (wcscmp(find_file_data.cFileName, L"..") == 0)) { |
return entry->Next(listing); |
} |
return kListDirectory; |
@@ -165,6 +182,7 @@ static ListType HandleFindFile(DirectoryListing* listing, |
} |
} |
+ |
ListType DirectoryListingEntry::Next(DirectoryListing* listing) { |
if (done_) { |
return kListDone; |
@@ -223,7 +241,7 @@ DirectoryListingEntry::~DirectoryListingEntry() { |
void DirectoryListingEntry::ResetLink() { |
- if (link_ != NULL && (parent_ == NULL || parent_->link_ != link_)) { |
+ if ((link_ != NULL) && ((parent_ == NULL) || (parent_->link_ != link_))) { |
delete link_; |
link_ = NULL; |
} |
@@ -234,7 +252,9 @@ void DirectoryListingEntry::ResetLink() { |
static bool DeleteFile(wchar_t* file_name, PathBuffer* path) { |
- if (!path->AddW(file_name)) return false; |
+ if (!path->AddW(file_name)) { |
+ return false; |
+ } |
if (DeleteFileW(path->AsStringW()) != 0) { |
return true; |
@@ -265,8 +285,10 @@ static bool DeleteFile(wchar_t* file_name, PathBuffer* path) { |
static bool DeleteDir(wchar_t* dir_name, PathBuffer* path) { |
- if (wcscmp(dir_name, L".") == 0) return true; |
- if (wcscmp(dir_name, L"..") == 0) return true; |
+ if ((wcscmp(dir_name, L".") == 0) || |
+ (wcscmp(dir_name, L"..") == 0)) { |
+ return true; |
+ } |
return path->AddW(dir_name) && DeleteRecursively(path); |
} |
@@ -284,7 +306,7 @@ static bool DeleteEntry(LPWIN32_FIND_DATAW find_file_data, PathBuffer* path) { |
static bool DeleteRecursively(PathBuffer* path) { |
DWORD attributes = GetFileAttributesW(path->AsStringW()); |
- if ((attributes == INVALID_FILE_ATTRIBUTES)) { |
+ if (attributes == INVALID_FILE_ATTRIBUTES) { |
return false; |
} |
// If the directory is a junction, it's pointing to some other place in the |
@@ -298,7 +320,9 @@ static bool DeleteRecursively(PathBuffer* path) { |
return DeleteFile(L"", path); |
} |
- if (!path->AddW(L"\\*")) return false; |
+ if (!path->AddW(L"\\*")) { |
+ return false; |
+ } |
WIN32_FIND_DATAW find_file_data; |
HANDLE find_handle = FindFirstFileW(path->AsStringW(), &find_file_data); |
@@ -336,8 +360,8 @@ static Directory::ExistsResult ExistsHelper(const wchar_t* dir_name) { |
DWORD attributes = GetFileAttributesW(dir_name); |
if (attributes == INVALID_FILE_ATTRIBUTES) { |
DWORD last_error = GetLastError(); |
- if (last_error == ERROR_FILE_NOT_FOUND || |
- last_error == ERROR_PATH_NOT_FOUND) { |
+ if ((last_error == ERROR_FILE_NOT_FOUND) || |
+ (last_error == ERROR_PATH_NOT_FOUND)) { |
return Directory::DOES_NOT_EXIST; |
} else { |
// We might not be able to get the file attributes for other |
@@ -354,27 +378,42 @@ static Directory::ExistsResult ExistsHelper(const wchar_t* dir_name) { |
Directory::ExistsResult Directory::Exists(const char* dir_name) { |
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(dir_name); |
- Directory::ExistsResult result = ExistsHelper(system_name); |
- free(const_cast<wchar_t*>(system_name)); |
- return result; |
+ return ExistsHelper(system_name); |
} |
-char* Directory::Current() { |
+char* Directory::CurrentNoScope() { |
int length = GetCurrentDirectoryW(0, NULL); |
- if (length == 0) return NULL; |
+ if (length == 0) { |
+ return NULL; |
+ } |
wchar_t* current = new wchar_t[length + 1]; |
GetCurrentDirectoryW(length + 1, current); |
- char* result = StringUtilsWin::WideToUtf8(current); |
+ int utf8_len = WideCharToMultiByte( |
+ CP_UTF8, 0, current, -1, NULL, 0, NULL, NULL); |
+ char* result = reinterpret_cast<char*>(malloc(utf8_len)); |
+ WideCharToMultiByte(CP_UTF8, 0, current, -1, result, utf8_len, NULL, NULL); |
delete[] current; |
return result; |
} |
+const char* Directory::Current() { |
+ int length = GetCurrentDirectoryW(0, NULL); |
+ if (length == 0) { |
+ return NULL; |
+ } |
+ wchar_t* current; |
+ current = reinterpret_cast<wchar_t*>( |
+ Dart_ScopeAllocate((length + 1) * sizeof(*current))); |
+ GetCurrentDirectoryW(length + 1, current); |
+ return StringUtilsWin::WideToUtf8(current); |
+} |
+ |
+ |
bool Directory::SetCurrent(const char* path) { |
const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path); |
bool result = SetCurrentDirectoryW(system_path) != 0; |
- free(const_cast<wchar_t*>(system_path)); |
return result; |
} |
@@ -383,35 +422,34 @@ bool Directory::Create(const char* dir_name) { |
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(dir_name); |
int create_status = CreateDirectoryW(system_name, NULL); |
// If the directory already existed, treat it as a success. |
- if (create_status == 0 && |
- GetLastError() == ERROR_ALREADY_EXISTS && |
- ExistsHelper(system_name) == EXISTS) { |
- free(const_cast<wchar_t*>(system_name)); |
+ if ((create_status == 0) && |
+ (GetLastError() == ERROR_ALREADY_EXISTS) && |
+ (ExistsHelper(system_name) == EXISTS)) { |
return true; |
} |
- free(const_cast<wchar_t*>(system_name)); |
return (create_status != 0); |
} |
-char* Directory::SystemTemp() { |
+const char* Directory::SystemTemp() { |
PathBuffer path; |
// Remove \ at end. |
path.Reset(GetTempPathW(MAX_LONG_PATH, path.AsStringW()) - 1); |
- return path.AsString(); |
+ return path.AsScopedString(); |
} |
-char* Directory::CreateTemp(const char* prefix) { |
+const char* Directory::CreateTemp(const char* prefix) { |
// Returns a new, unused directory name, adding characters to the |
// end of prefix. |
// Creates this directory, with a default security |
// descriptor inherited from its parent directory. |
- // The return value must be freed by the caller. |
+ // The return value is Dart_ScopeAllocated. |
PathBuffer path; |
const wchar_t* system_prefix = StringUtilsWin::Utf8ToWide(prefix); |
- path.AddW(system_prefix); |
- free(const_cast<wchar_t*>(system_prefix)); |
+ if (!path.AddW(system_prefix)) { |
+ return NULL; |
+ } |
// Length of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 36. |
if (path.length() > MAX_LONG_PATH - 36) { |
@@ -420,7 +458,7 @@ char* Directory::CreateTemp(const char* prefix) { |
UUID uuid; |
RPC_STATUS status = UuidCreateSequential(&uuid); |
- if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { |
+ if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) { |
return NULL; |
} |
RPC_WSTR uuid_string; |
@@ -430,13 +468,14 @@ char* Directory::CreateTemp(const char* prefix) { |
} |
// RPC_WSTR is an unsigned short*, so we cast to wchar_t*. |
- path.AddW(reinterpret_cast<wchar_t*>(uuid_string)); |
+ if (!path.AddW(reinterpret_cast<wchar_t*>(uuid_string))) { |
+ return NULL; |
+ } |
RpcStringFreeW(&uuid_string); |
if (!CreateDirectoryW(path.AsStringW(), NULL)) { |
return NULL; |
} |
- char* result = path.AsString(); |
- return result; |
+ return path.AsScopedString(); |
} |
@@ -455,7 +494,6 @@ bool Directory::Delete(const char* dir_name, bool recursive) { |
result = DeleteRecursively(&path); |
} |
} |
- free(const_cast<wchar_t*>(system_dir_name)); |
return result; |
} |
@@ -464,20 +502,22 @@ bool Directory::Rename(const char* path, const char* new_path) { |
const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path); |
const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path); |
ExistsResult exists = ExistsHelper(system_path); |
- if (exists != EXISTS) return false; |
+ if (exists != EXISTS) { |
+ return false; |
+ } |
ExistsResult new_exists = ExistsHelper(system_new_path); |
// MoveFile does not allow replacing exising directories. Therefore, |
// if the new_path is currently a directory we need to delete it |
// first. |
if (new_exists == EXISTS) { |
bool success = Delete(new_path, true); |
- if (!success) return false; |
+ if (!success) { |
+ return false; |
+ } |
} |
DWORD flags = MOVEFILE_WRITE_THROUGH; |
int move_status = |
MoveFileExW(system_path, system_new_path, flags); |
- free(const_cast<wchar_t*>(system_path)); |
- free(const_cast<wchar_t*>(system_new_path)); |
return (move_status != 0); |
} |