Skip to content

Conversation

fanquake
Copy link
Member

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.

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.
Copy link
Member

@hebasto hebasto left a 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?

Copy link
Contributor

@vasild vasild left a 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()

@laanwj
Copy link
Member

laanwj commented Feb 10, 2022

Concept ACK. Checked the relevant documentation that the behavior is what we want for RenameOver:

Moves or renames the filesystem object identified by old_p to new_p as if by the POSIX rename

- https://en.cppreference.com/w/cpp/filesystem/rename

If the link named by the new argument exists, it shall be removed and old renamed to new.

- https://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html

Also, it is a nice cleanup, no more win32-specific code here.

@maflcko
Copy link
Member

maflcko commented Feb 11, 2022

review ACK ee822d8

@maflcko maflcko merged commit b79c40b into bitcoin:master Feb 11, 2022
@maflcko
Copy link
Member

maflcko commented Feb 11, 2022

(Also reviewed the unit test in #24308 (review) but didn't run it)

sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Feb 11, 2022
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
@hebasto
Copy link
Member

hebasto commented Feb 12, 2022

It seems to break Windows builds:

Screenshot from 2022-02-12 17-19-40

@hebasto
Copy link
Member

hebasto commented Feb 13, 2022

Add a test for this assumption?

Unit test for RenameOver()

Btw, it fails for mingw build: https://cirrus-ci.com/task/6670169794674688

@fanquake fanquake deleted the 20435_rebased branch February 13, 2022 16:01
laanwj added a commit to bitcoin-core/gui that referenced this pull request Feb 17, 2022
… 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
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Feb 18, 2022
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
@bitcoin bitcoin locked and limited conversation to collaborators Feb 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants