From 83429c9bfd9c305fa35dbf15bbcd127d6f280c5f Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 29 Mar 2021 20:20:34 +0300 Subject: [PATCH] Check file status for status_error in create_directories. create_directories used to ignore errors returned by status() calls issued internally. The operation would likely fail anyway, but the error codes returned by create_directories would be incorrect. Also, it is better to terminate the operation as early as possible when an error is encountered. Reported in https://github.com/boostorg/filesystem/issues/182. --- doc/release_history.html | 1 + src/operations.cpp | 36 ++++++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/doc/release_history.html b/doc/release_history.html index 562bac7..cf56e20 100644 --- a/doc/release_history.html +++ b/doc/release_history.html @@ -42,6 +42,7 @@

1.75.0

diff --git a/src/operations.cpp b/src/operations.cpp index 2c1c96e..afebd16 100644 --- a/src/operations.cpp +++ b/src/operations.cpp @@ -1454,17 +1454,17 @@ void copy_symlink(const path& existing_symlink, const path& new_symlink, system: BOOST_FILESYSTEM_DECL bool create_directories(const path& p, system::error_code* ec) { - if (p.empty()) - { - if (!ec) - { - BOOST_FILESYSTEM_THROW(filesystem_error( - "boost::filesystem::create_directories", p, - system::errc::make_error_code(system::errc::invalid_argument))); - } - ec->assign(system::errc::invalid_argument, system::generic_category()); - return false; - } + if (p.empty()) + { + if (!ec) + { + BOOST_FILESYSTEM_THROW(filesystem_error( + "boost::filesystem::create_directories", p, + system::errc::make_error_code(system::errc::invalid_argument))); + } + ec->assign(system::errc::invalid_argument, system::generic_category()); + return false; + } if (p.filename_is_dot() || p.filename_is_dot_dot()) return create_directories(p.parent_path(), ec); @@ -1478,6 +1478,13 @@ bool create_directories(const path& p, system::error_code* ec) ec->clear(); return false; } + else if (BOOST_UNLIKELY(p_status.type() == status_error)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::create_directories", p, local_ec)); + *ec = local_ec; + return false; + } path parent = p.parent_path(); BOOST_ASSERT_MSG(parent != p, "internal error: p == p.parent_path()"); @@ -1490,14 +1497,19 @@ bool create_directories(const path& p, system::error_code* ec) if (parent_status.type() == file_not_found) { create_directories(parent, local_ec); - if (local_ec) + if (BOOST_UNLIKELY(!!local_ec)) { + parent_fail_local_ec: if (!ec) BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::create_directories", parent, local_ec)); *ec = local_ec; return false; } } + else if (BOOST_UNLIKELY(parent_status.type() == status_error)) + { + goto parent_fail_local_ec; + } } // create the directory