From 465529531ba3776329c490fb6afa8493151af138 Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Thu, 30 Jan 2020 15:43:02 -0800 Subject: [PATCH] Fix Windows file checks of unicode paths (#16105) --- fml/file_unittest.cc | 29 +++++++++++++++++++++++++++++ fml/platform/win/file_win.cc | 29 ++++++++++++++++++----------- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/fml/file_unittest.cc b/fml/file_unittest.cc index aed268b3f..bd27fb021 100644 --- a/fml/file_unittest.cc +++ b/fml/file_unittest.cc @@ -10,6 +10,7 @@ #include "flutter/fml/build_config.h" #include "flutter/fml/file.h" #include "flutter/fml/mapping.h" +#include "flutter/fml/paths.h" #include "flutter/fml/unique_fd.h" static bool WriteStringToFile(const fml::UniqueFD& fd, @@ -267,3 +268,31 @@ TEST(FileTest, EmptyMappingTest) { ASSERT_TRUE(fml::UnlinkFile(dir.fd(), "my_contents")); } + +TEST(FileTest, FileTestsWork) { + fml::ScopedTemporaryDirectory dir; + ASSERT_TRUE(dir.fd().is_valid()); + const char* filename = "some.txt"; + auto fd = + fml::OpenFile(dir.fd(), filename, true, fml::FilePermission::kWrite); + ASSERT_TRUE(fd.is_valid()); + fd.reset(); + ASSERT_TRUE(fml::FileExists(dir.fd(), filename)); + ASSERT_TRUE( + fml::IsFile(fml::paths::JoinPaths({dir.path(), filename}).c_str())); + ASSERT_TRUE(fml::UnlinkFile(dir.fd(), filename)); +} + +TEST(FileTest, FileTestsSupportsUnicode) { + fml::ScopedTemporaryDirectory dir; + ASSERT_TRUE(dir.fd().is_valid()); + const char* filename = u8"äëïöüテスト☃"; + auto fd = + fml::OpenFile(dir.fd(), filename, true, fml::FilePermission::kWrite); + ASSERT_TRUE(fd.is_valid()); + fd.reset(); + ASSERT_TRUE(fml::FileExists(dir.fd(), filename)); + ASSERT_TRUE( + fml::IsFile(fml::paths::JoinPaths({dir.path(), filename}).c_str())); + ASSERT_TRUE(fml::UnlinkFile(dir.fd(), filename)); +} diff --git a/fml/platform/win/file_win.cc b/fml/platform/win/file_win.cc index a4c74940c..e6319dfd5 100644 --- a/fml/platform/win/file_win.cc +++ b/fml/platform/win/file_win.cc @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -18,10 +17,6 @@ #include "flutter/fml/platform/win/errors_win.h" #include "flutter/fml/platform/win/wstring_conversion.h" -#if defined(OS_WIN) -#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG) -#endif - namespace fml { static std::string GetFullHandlePath(const fml::UniqueFD& handle) { @@ -80,6 +75,16 @@ static DWORD GetShareFlags(FilePermission permission) { return FILE_SHARE_READ; } +static DWORD GetFileAttributesForUtf8Path(const char* absolute_path) { + return ::GetFileAttributes(ConvertToWString(absolute_path).c_str()); +} + +static DWORD GetFileAttributesForUtf8Path(const fml::UniqueFD& base_directory, + const char* path) { + std::string full_path = GetFullHandlePath(base_directory) + "\\" + path; + return GetFileAttributesForUtf8Path(full_path.c_str()); +} + std::string CreateTemporaryDirectory() { // Get the system temporary directory. auto temp_dir_container = GetTemporaryDirectoryPath(); @@ -253,16 +258,17 @@ bool IsDirectory(const fml::UniqueFD& directory) { } bool IsDirectory(const fml::UniqueFD& base_directory, const char* path) { - std::string full_path = GetFullHandlePath(base_directory) + "\\" + path; - return ::GetFileAttributes(ConvertToWString(full_path.c_str()).c_str()) & + return GetFileAttributesForUtf8Path(base_directory, path) & FILE_ATTRIBUTE_DIRECTORY; } bool IsFile(const std::string& path) { - struct stat buf; - if (stat(path.c_str(), &buf) != 0) + DWORD attributes = GetFileAttributesForUtf8Path(path.c_str()); + if (attributes == INVALID_FILE_ATTRIBUTES) { return false; - return S_ISREG(buf.st_mode); + } + return !(attributes & + (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)); } bool UnlinkDirectory(const char* path) { @@ -323,7 +329,8 @@ bool TruncateFile(const fml::UniqueFD& file, size_t size) { } bool FileExists(const fml::UniqueFD& base_directory, const char* path) { - return IsFile(GetAbsolutePath(base_directory, path).c_str()); + return GetFileAttributesForUtf8Path(base_directory, path) != + INVALID_FILE_ATTRIBUTES; } bool WriteAtomically(const fml::UniqueFD& base_directory, -- GitLab