| 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);
|
| }
|
|
|
|
|