-
Notifications
You must be signed in to change notification settings - Fork 37.7k
util: use stronger-guarantee rename method #24308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Use std::filesystem::rename() instead of std::rename(). We rely on the destination to be overwritten if it exists, but std::rename()'s behavior is implementation-defined in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approach ACK ee822d8.
We rely on the destination to be overwritten if it exists
Add a test for this assumption?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK ee822d8
Add a test for this assumption?
Unit test for RenameOver()
commit 23074edf054845b1b74c43618cf7a8cc58aa5518 (HEAD -> pull/24308_1644480965_ee822d85d6__20435_rebased)
Parent: ee822d85d6de7db85416190cf843ad74147519cf
Author: Vasil Dimov <vd@FreeBSD.org>
AuthorDate: Thu Feb 10 14:11:35 2022 +0100
Commit: Vasil Dimov <vd@FreeBSD.org>
CommitDate: Thu Feb 10 14:14:58 2022 +0100
test: add a unit test for RenameOver()
diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp
index 1256395849..8a5f025e5f 100644
--- a/src/test/fs_tests.cpp
+++ b/src/test/fs_tests.cpp
@@ -115,7 +115,40 @@ BOOST_AUTO_TEST_CASE(fsbridge_fstream)
BOOST_CHECK(p1 != p2);
BOOST_CHECK(p2 != p3);
BOOST_CHECK(p1 != p3);
}
}
-BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file
+BOOST_AUTO_TEST_CASE(rename)
+{
+ const fs::path tmpfolder{m_args.GetDataDirBase()};
+
+ const fs::path path1{GetUniquePath(tmpfolder)};
+ const fs::path path2{GetUniquePath(tmpfolder)};
+
+ const std::string path1_contents{"1111"};
+ const std::string path2_contents{"2222"};
+
+ {
+ std::ofstream file{path1};
+ file << path1_contents;
+ }
+
+ {
+ std::ofstream file{path2};
+ file << path2_contents;
+ }
+
+ // Rename path1 -> path2.
+ BOOST_CHECK(RenameOver(path1, path2));
+
+ BOOST_CHECK(!fs::exists(path1));
+
+ {
+ std::ifstream file{path2};
+ std::string contents;
+ file >> contents;
+ BOOST_CHECK_EQUAL(contents, path1_contents);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
Concept ACK. Checked the relevant documentation that the behavior is what we want for
- https://en.cppreference.com/w/cpp/filesystem/rename
- https://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html Also, it is a nice cleanup, no more win32-specific code here. |
review ACK ee822d8 |
(Also reviewed the unit test in #24308 (review) but didn't run it) |
ee822d8 util: use stronger-guarantee rename method (Vasil Dimov) Pull request description: Use std::filesystem::rename() instead of std::rename(). We rely on the destination to be overwritten if it exists, but std::rename()'s behavior is implementation-defined in this case. This is a rebase of bitcoin#20435 by vasild. ACKs for top commit: MarcoFalke: review ACK ee822d8 hebasto: Approach ACK ee822d8. vasild: ACK ee822d8 Tree-SHA512: 8f65f154d235c2704f18008d9d40ced3c5d84e4d55653aa70bde345066b6083c84667b5a2f4d69eeaad0bec6c607645e21ddd2bf85617bdec4a2e33752e2059a
Btw, it fails for mingw build: https://cirrus-ci.com/task/6670169794674688 |
… MinGW-w64 dc01cbc test: Add fs_tests/rename unit test (Hennadii Stepanov) d4999d4 util: Revert back MoveFileExW call for MinGW-w64 (Hennadii Stepanov) Pull request description: Unfortunately, bitcoin/bitcoin#24308 introduced a [regression](bitcoin/bitcoin#24308 (comment)) for mingw builds. The root of the problem is a broken implementation of [`std::filesystem::rename`](https://en.cppreference.com/w/cpp/filesystem/rename). In particular, the expected behavior > If `old_p` is a non-directory file, then `new_p` must be ... existing non-directory file: `new_p` _is first deleted_... fails with the "File exists" error. This PR reverts back the `MoveFileExW` call, and adds the [suggested](bitcoin/bitcoin#24308 (review)) unit test. ACKs for top commit: vasild: ACK dc01cbc Tree-SHA512: c8e5a98844cfa32bec0ad67a1aaa58fe2efd0c5474d3e83490211985b110f83245758a742dcaa0a933a192ab66a7f11807e0c53ae69260b7dd02fc99f6d03849
dc01cbc test: Add fs_tests/rename unit test (Hennadii Stepanov) d4999d4 util: Revert back MoveFileExW call for MinGW-w64 (Hennadii Stepanov) Pull request description: Unfortunately, bitcoin#24308 introduced a [regression](bitcoin#24308 (comment)) for mingw builds. The root of the problem is a broken implementation of [`std::filesystem::rename`](https://en.cppreference.com/w/cpp/filesystem/rename). In particular, the expected behavior > If `old_p` is a non-directory file, then `new_p` must be ... existing non-directory file: `new_p` _is first deleted_... fails with the "File exists" error. This PR reverts back the `MoveFileExW` call, and adds the [suggested](bitcoin#24308 (review)) unit test. ACKs for top commit: vasild: ACK dc01cbc Tree-SHA512: c8e5a98844cfa32bec0ad67a1aaa58fe2efd0c5474d3e83490211985b110f83245758a742dcaa0a933a192ab66a7f11807e0c53ae69260b7dd02fc99f6d03849
Use std::filesystem::rename() instead of std::rename(). We rely on the
destination to be overwritten if it exists, but std::rename()'s behavior
is implementation-defined in this case.
This is a rebase of #20435 by vasild.