diff options
author | Jan Niklas Hasse <jhasse@bixense.com> | 2022-05-15 15:05:27 (GMT) |
---|---|---|
committer | Jan Niklas Hasse <jhasse@bixense.com> | 2022-05-15 15:08:10 (GMT) |
commit | 51edeeb063a82693573db43782d9e3733b2840e4 (patch) | |
tree | 8c10c9376892e93762136985265ff8c9f51299b0 /src/disk_interface.cc | |
parent | e72d1d581c945c158ed68d9bc48911063022a2c6 (diff) | |
parent | bb471e235a83fd2b146299cd7d4d3a95163de10a (diff) | |
download | Ninja-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.cc | 52 |
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) { |