summaryrefslogtreecommitdiffstats
path: root/src/disk_interface.cc
diff options
context:
space:
mode:
authorJan Niklas Hasse <jhasse@bixense.com>2022-05-15 15:05:27 (GMT)
committerJan Niklas Hasse <jhasse@bixense.com>2022-05-15 15:08:10 (GMT)
commit51edeeb063a82693573db43782d9e3733b2840e4 (patch)
tree8c10c9376892e93762136985265ff8c9f51299b0 /src/disk_interface.cc
parente72d1d581c945c158ed68d9bc48911063022a2c6 (diff)
parentbb471e235a83fd2b146299cd7d4d3a95163de10a (diff)
downloadNinja-51edeeb063a82693573db43782d9e3733b2840e4.zip
Ninja-51edeeb063a82693573db43782d9e3733b2840e4.tar.gz
Ninja-51edeeb063a82693573db43782d9e3733b2840e4.tar.bz2
v1.11.0v1.11.0
Diffstat (limited to 'src/disk_interface.cc')
-rw-r--r--src/disk_interface.cc52
1 files changed, 47 insertions, 5 deletions
diff --git a/src/disk_interface.cc b/src/disk_interface.cc
index 49af001..e73d901 100644
--- a/src/disk_interface.cc
+++ b/src/disk_interface.cc
@@ -180,12 +180,13 @@ TimeStamp RealDiskInterface::Stat(const string& path, string* err) const {
dir = path;
}
- transform(dir.begin(), dir.end(), dir.begin(), ::tolower);
+ string dir_lowercase = dir;
+ transform(dir.begin(), dir.end(), dir_lowercase.begin(), ::tolower);
transform(base.begin(), base.end(), base.begin(), ::tolower);
- Cache::iterator ci = cache_.find(dir);
+ Cache::iterator ci = cache_.find(dir_lowercase);
if (ci == cache_.end()) {
- ci = cache_.insert(make_pair(dir, DirCache())).first;
+ ci = cache_.insert(make_pair(dir_lowercase, DirCache())).first;
if (!StatAllFilesInDir(dir.empty() ? "." : dir, &ci->second, err)) {
cache_.erase(ci);
return -1;
@@ -265,6 +266,47 @@ 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) {
+ DWORD win_err = GetLastError();
+ if (win_err == ERROR_FILE_NOT_FOUND || win_err == ERROR_PATH_NOT_FOUND) {
+ return 1;
+ }
+ } else if (attributes & FILE_ATTRIBUTE_READONLY) {
+ // On non-Windows systems, remove() will happily delete read-only files.
+ // On Windows Ninja should behave the same:
+ // https://github.com/ninja-build/ninja/issues/1886
+ // Skip error checking. If this fails, accept whatever happens below.
+ SetFileAttributes(path.c_str(), attributes & ~FILE_ATTRIBUTE_READONLY);
+ }
+ if (attributes & FILE_ATTRIBUTE_DIRECTORY) {
+ // remove() deletes both files and directories. On Windows we have to
+ // select the correct function (DeleteFile will yield Permission Denied when
+ // used on a directory)
+ // This fixes the behavior of ninja -t clean in some cases
+ // https://github.com/ninja-build/ninja/issues/828
+ if (!RemoveDirectory(path.c_str())) {
+ DWORD win_err = GetLastError();
+ if (win_err == ERROR_FILE_NOT_FOUND || win_err == ERROR_PATH_NOT_FOUND) {
+ return 1;
+ }
+ // Report remove(), not RemoveDirectory(), for cross-platform consistency.
+ Error("remove(%s): %s", path.c_str(), GetLastErrorString().c_str());
+ return -1;
+ }
+ } else {
+ if (!DeleteFile(path.c_str())) {
+ DWORD win_err = GetLastError();
+ if (win_err == ERROR_FILE_NOT_FOUND || win_err == ERROR_PATH_NOT_FOUND) {
+ return 1;
+ }
+ // Report as remove(), not DeleteFile(), for cross-platform consistency.
+ 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 +315,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) {