Skip to content

Commit

Permalink
util: Work around libstdc++ create_directories issue
Browse files Browse the repository at this point in the history
Work around libstdc++ issue [PR101510] with create_directories where the
leaf already exists as a symlink. Fixes bitcoin#24257, introduced by the switch
to `std::filesystem`. It is meant to be more thorough than bitcoin#24266, which
only worked around one instance of the problem.

The issue was fixed upstream in
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=124eaa50e0a34f5f89572c1aa812c50979da58fc,
but unfortunately we'll have to carry a fix for it for a while.

This introduces a function `fs::create_directories` which wraps
`std::filesystem::create_directories`. This allows easiliy reverting the
workaround when it is no longer necessary.
  • Loading branch information
laanwj committed Feb 17, 2022
1 parent df08250 commit 1f46b6e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 2 deletions.
22 changes: 22 additions & 0 deletions src/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,28 @@ static inline path PathFromString(const std::string& string)
return std::filesystem::path(string);
#endif
}

/**
* Create directory (and if necessary its parents), unless the leaf directory
* already exists or is a symlink to an existing directory.
* This is a temporary workaround for an issue in libstdc++ that has been fixed
* upstream [PR101510].
*/
static inline bool create_directories(const std::filesystem::path& p)
{
if (std::filesystem::is_symlink(p) && std::filesystem::is_directory(p)) {
return false;
}
return std::filesystem::create_directories(p);
}

/**
* This variant is not used. Delete it to prevent it from accidentally working
* around the workaround. If it is needed, add a workaround in the same pattern
* as above.
*/
bool create_directories(const std::filesystem::path& p, std::error_code& ec) = delete;

} // namespace fs

/** Bridge operations to C stdio */
Expand Down
4 changes: 2 additions & 2 deletions src/test/dbwrapper_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
{
// We're going to share this fs::path between two wrappers
fs::path ph = m_args.GetDataDirBase() / "existing_data_no_obfuscate";
create_directories(ph);
fs::create_directories(ph);

// Set up a non-obfuscated wrapper to write some initial data.
std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(ph, (1 << 10), false, false, false);
Expand Down Expand Up @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex)
{
// We're going to share this fs::path between two wrappers
fs::path ph = m_args.GetDataDirBase() / "existing_data_reindex";
create_directories(ph);
fs::create_directories(ph);

// Set up a non-obfuscated wrapper to write some initial data.
std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(ph, (1 << 10), false, false, false);
Expand Down

0 comments on commit 1f46b6e

Please sign in to comment.