diff options
Diffstat (limited to 'libstdc++-v3/src')
-rw-r--r-- | libstdc++-v3/src/c++17/fs_ops.cc | 30 | ||||
-rw-r--r-- | libstdc++-v3/src/filesystem/ops-common.h | 11 |
2 files changed, 40 insertions, 1 deletions
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc index 3817655..3e1671e 100644 --- a/libstdc++-v3/src/c++17/fs_ops.cc +++ b/libstdc++-v3/src/c++17/fs_ops.cc @@ -1394,6 +1394,36 @@ fs::rename(const path& from, const path& to) void fs::rename(const path& from, const path& to, error_code& ec) noexcept { +#if _GLIBCXX_FILESYSTEM_IS_WINDOWS + const auto to_status = fs::status(to, ec); + if (to_status.type() == file_type::not_found) + ec.clear(); + else if (ec) + return; + + if (fs::exists(to_status)) + { + const auto from_status = fs::status(from, ec); + if (ec) + return; + + if (fs::is_directory(to_status)) + { + if (!fs::is_directory(from_status)) + { + // Cannot rename a non-directory over an existing directory. + ec = std::make_error_code(std::errc::is_a_directory); + return; + } + } + else if (fs::is_directory(from_status)) + { + // Cannot rename a directory over an existing non-directory. + ec = std::make_error_code(std::errc::not_a_directory); + return; + } + } +#endif if (posix::rename(from.c_str(), to.c_str())) ec.assign(errno, std::generic_category()); else diff --git a/libstdc++-v3/src/filesystem/ops-common.h b/libstdc++-v3/src/filesystem/ops-common.h index 118256a..529d4e0 100644 --- a/libstdc++-v3/src/filesystem/ops-common.h +++ b/libstdc++-v3/src/filesystem/ops-common.h @@ -104,7 +104,16 @@ namespace __gnu_posix #endif inline int rename(const wchar_t* oldname, const wchar_t* newname) - { return _wrename(oldname, newname); } + { + if (MoveFileExW(oldname, newname, + MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED)) + return 0; + if (GetLastError() == ERROR_ACCESS_DENIED) + errno = EACCES; + else + errno = EIO; + return -1; + } inline int truncate(const wchar_t* path, _off64_t length) { |