diff options
Diffstat (limited to 'base')
-rw-r--r-- | base/file_util_unittest.cc | 17 | ||||
-rw-r--r-- | base/file_util_win.cc | 41 |
2 files changed, 55 insertions, 3 deletions
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc index 6d57e2c..7296113 100644 --- a/base/file_util_unittest.cc +++ b/base/file_util_unittest.cc @@ -1137,6 +1137,23 @@ TEST_F(FileUtilTest, CreateDirectoryTest) { EXPECT_TRUE(file_util::Delete(test_root, true)); EXPECT_FALSE(file_util::PathExists(test_root)); EXPECT_FALSE(file_util::PathExists(test_path)); + + // Verify assumptions made by the Windows implementation: + // 1. The current directory always exists. + // 2. The root directory always exists. + ASSERT_TRUE(file_util::DirectoryExists( + FilePath(FilePath::kCurrentDirectory))); + FilePath top_level = test_root; + while (top_level != top_level.DirName()) { + top_level = top_level.DirName(); + } + ASSERT_TRUE(file_util::DirectoryExists(top_level)); + + // Given these assumptions hold, it should be safe to + // test that "creating" these directories succeeds. + EXPECT_TRUE(file_util::CreateDirectory( + FilePath(FilePath::kCurrentDirectory))); + EXPECT_TRUE(file_util::CreateDirectory(top_level)); } TEST_F(FileUtilTest, DetectDirectoryTest) { diff --git a/base/file_util_win.cc b/base/file_util_win.cc index 9722e31..812a706 100644 --- a/base/file_util_win.cc +++ b/base/file_util_win.cc @@ -509,10 +509,45 @@ bool CreateNewTempDirectory(const FilePath::StringType& prefix, } bool CreateDirectory(const FilePath& full_path) { - if (DirectoryExists(full_path)) + // If the path exists, we've succeeded if it's a directory, failed otherwise. + const wchar_t* full_path_str = full_path.value().c_str(); + DWORD fileattr = ::GetFileAttributes(full_path_str); + if (fileattr != INVALID_FILE_ATTRIBUTES) { + if ((fileattr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + DLOG(INFO) << "CreateDirectory(" << full_path_str << "), " << + "directory already exists."; + return true; + } else { + LOG(WARNING) << "CreateDirectory(" << full_path_str << "), " << + "conflicts with existing file."; + } + } + + // Invariant: Path does not exist as file or directory. + + // Attempt to create the parent recursively. This will immediately return + // true if it already exists, otherwise will create all required parent + // directories starting with the highest-level missing parent. + if (!CreateDirectory(full_path.DirName())) { + DLOG(WARNING) << "Failed to create one of the parent directories."; + return false; + } + + if (!::CreateDirectory(full_path_str, NULL)) { + DWORD error_code = ::GetLastError(); + if (error_code == ERROR_ALREADY_EXISTS && DirectoryExists(full_path)) { + // This error code doesn't indicate whether we were racing with someone + // creating the same directory, or a file with the same path, therefore + // we check. + return true; + } else { + LOG(WARNING) << "Failed to create directory " << full_path_str << + ", le=" << error_code; + return false; + } + } else { return true; - int err = SHCreateDirectoryEx(NULL, full_path.value().c_str(), NULL); - return err == ERROR_SUCCESS; + } } bool GetFileInfo(const FilePath& file_path, FileInfo* results) { |