summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Niklas Hasse <jhasse@bixense.com>2020-12-07 18:46:10 (GMT)
committerJan Niklas Hasse <jhasse@bixense.com>2020-12-07 18:46:10 (GMT)
commit2d7f7e55c05a92033a1a62fbb6163e2e32aa81c3 (patch)
tree58b2a17a55409c4108aa54c5c71e542641f44d33
parent58f77f972bcece256c16ca1cc4a933270b1ea1c1 (diff)
downloadNinja-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.cc21
-rw-r--r--src/disk_interface_test.cc6
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,