diff options
author | Jan Niklas Hasse <jhasse@bixense.com> | 2020-12-07 18:46:10 (GMT) |
---|---|---|
committer | Jan Niklas Hasse <jhasse@bixense.com> | 2020-12-07 18:46:10 (GMT) |
commit | 2d7f7e55c05a92033a1a62fbb6163e2e32aa81c3 (patch) | |
tree | 58b2a17a55409c4108aa54c5c71e542641f44d33 | |
parent | 58f77f972bcece256c16ca1cc4a933270b1ea1c1 (diff) | |
download | Ninja-2d7f7e55c05a92033a1a62fbb6163e2e32aa81c3.zip Ninja-2d7f7e55c05a92033a1a62fbb6163e2e32aa81c3.tar.gz Ninja-2d7f7e55c05a92033a1a62fbb6163e2e32aa81c3.tar.bz2 |
Delete read-only files on Windows, too
Fixes main complaint of #1886.
-rw-r--r-- | src/disk_interface.cc | 21 | ||||
-rw-r--r-- | src/disk_interface_test.cc | 6 |
2 files changed, 25 insertions, 2 deletions
diff --git a/src/disk_interface.cc b/src/disk_interface.cc index 49af001..8d4cc7f 100644 --- a/src/disk_interface.cc +++ b/src/disk_interface.cc @@ -265,6 +265,23 @@ FileReader::Status RealDiskInterface::ReadFile(const string& path, } int RealDiskInterface::RemoveFile(const string& path) { +#ifdef _WIN32 + DWORD attributes = GetFileAttributes(path.c_str()); + if (attributes == INVALID_FILE_ATTRIBUTES && + GetLastError() == ERROR_FILE_NOT_FOUND) { + return 1; + } + if (attributes & FILE_ATTRIBUTE_READONLY) { + // On non-Windows systems remove will happily delete read-only files. On + // Windows Ninja should behave the same. See + // https://github.com/ninja-build/ninja/issues/1886 + SetFileAttributes(path.c_str(), attributes & ~FILE_ATTRIBUTE_READONLY); + } + if (!DeleteFile(path.c_str())) { + Error("remove(%s): %s", path.c_str(), GetLastErrorString().c_str()); + return -1; + } +#else if (remove(path.c_str()) < 0) { switch (errno) { case ENOENT: @@ -273,9 +290,9 @@ int RealDiskInterface::RemoveFile(const string& path) { Error("remove(%s): %s", path.c_str(), strerror(errno)); return -1; } - } else { - return 0; } +#endif + return 0; } void RealDiskInterface::AllowStatCache(bool allow) { diff --git a/src/disk_interface_test.cc b/src/disk_interface_test.cc index 066c770..b424243 100644 --- a/src/disk_interface_test.cc +++ b/src/disk_interface_test.cc @@ -211,6 +211,12 @@ TEST_F(DiskInterfaceTest, RemoveFile) { EXPECT_EQ(0, disk_.RemoveFile(kFileName)); EXPECT_EQ(1, disk_.RemoveFile(kFileName)); EXPECT_EQ(1, disk_.RemoveFile("does not exist")); +#ifdef _WIN32 + ASSERT_TRUE(Touch(kFileName)); + EXPECT_EQ(0, system((std::string("attrib +R ") + kFileName).c_str())); + EXPECT_EQ(0, disk_.RemoveFile(kFileName)); + EXPECT_EQ(1, disk_.RemoveFile(kFileName)); +#endif } struct StatTest : public StateTestWithBuiltinRules, |