diff options
-rw-r--r-- | src/main/cpp/util/file_posix.cc | 8 | ||||
-rw-r--r-- | src/main/cpp/util/file_windows.cc | 6 | ||||
-rw-r--r-- | src/test/cpp/util/file_windows_test.cc | 31 |
3 files changed, 41 insertions, 4 deletions
diff --git a/src/main/cpp/util/file_posix.cc b/src/main/cpp/util/file_posix.cc index 466bae499d..9d7f772d2d 100644 --- a/src/main/cpp/util/file_posix.cc +++ b/src/main/cpp/util/file_posix.cc @@ -209,15 +209,15 @@ bool WriteFile(const void *data, size_t size, const string &filename) { return result; } -bool UnlinkPath(const string &file_path) { - return unlink(file_path.c_str()) == 0; -} - // TODO(bazel-team): implement all functions in file_windows.cc, use them from // MSYS, remove file_posix.cc from the `srcs` of // //src/main/cpp/util:file when building for MSYS, and remove all // #ifndef __CYGWIN__ directives. #ifndef __CYGWIN__ +bool UnlinkPath(const string &file_path) { + return unlink(file_path.c_str()) == 0; +} + bool PathExists(const string& path) { return access(path.c_str(), F_OK) == 0; } diff --git a/src/main/cpp/util/file_windows.cc b/src/main/cpp/util/file_windows.cc index 3a5b5ac8e4..ba3e777d2b 100644 --- a/src/main/cpp/util/file_windows.cc +++ b/src/main/cpp/util/file_windows.cc @@ -43,6 +43,12 @@ static unique_ptr<WCHAR[]> GetCwdW(); // necessary. static bool IsDirectoryW(const wstring& path); +// Returns true the file or junction at `path` is successfully deleted. +// Returns false otherwise, or if `path` doesn't exist or is a directory. +// `path` must be a normalized Windows path, with UNC prefix (and absolute) if +// necessary. +static bool UnlinkPathW(const wstring& path); + // Like `AsWindowsPath` but the result is absolute and has UNC prefix if needed. static bool AsWindowsPathWithUncPrefix(const string& path, wstring* wpath); diff --git a/src/test/cpp/util/file_windows_test.cc b/src/test/cpp/util/file_windows_test.cc index 5c2f68ee27..1d73d65e53 100644 --- a/src/test/cpp/util/file_windows_test.cc +++ b/src/test/cpp/util/file_windows_test.cc @@ -290,6 +290,37 @@ TEST(FileTest, TestPathExistsWindows) { ASSERT_FALSE(PathExists(JoinPath(tmpdir, "junc2"))); } +TEST(FileTest, TestUnlinkPath) { + string tmpdir(GetTestTmpDir()); + ASSERT_LT(0, tmpdir.size()); + ASSERT_TRUE(PathExists(tmpdir)); + + // Create a directory under `tempdir`, a file inside it, and a junction + // pointing to it. + string dir1(JoinPath(tmpdir, "dir1")); + ASSERT_EQ(0, mkdir(dir1.c_str())); + FILE* fh = fopen(JoinPath(dir1, "foo.txt").c_str(), "wt"); + ASSERT_NE(nullptr, fh); + ASSERT_LT(0, fprintf(fh, "hello\n")); + fclose(fh); + string junc1(JoinPath(tmpdir, "junc1")); + RunCommand(string("cmd.exe /C mklink /J \"") + junc1 + "\" \"" + dir1 + + "\" >NUL 2>NUL"); + ASSERT_TRUE(PathExists(junc1)); + ASSERT_TRUE(PathExists(JoinPath(junc1, "foo.txt"))); + + // Non-existent files cannot be unlinked. + ASSERT_FALSE(UnlinkPath("does.not.exist")); + // Directories cannot be unlinked. + ASSERT_FALSE(UnlinkPath(dir1)); + // Junctions can be unlinked, even if the pointed directory is not empty. + ASSERT_TRUE(UnlinkPath(JoinPath(junc1, "foo.txt"))); + // Files can be unlinked. + ASSERT_TRUE(UnlinkPath(junc1)); + // Clean up the now empty directory. + ASSERT_EQ(0, rmdir(dir1.c_str())); +} + TEST(FileTest, TestIsDirectory) { ASSERT_FALSE(IsDirectory("")); |