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.
This commit is contained in:
Andrey Semashev 2021-03-29 20:20:34 +03:00
parent 62515b937c
commit 83429c9bfd
2 changed files with 25 additions and 12 deletions

View File

@ -42,6 +42,7 @@
<ul> <ul>
<li>Updated compatibility with <a href="https://wasi.dev/">WASI</a> platform. (<a href="https://github.com/boostorg/filesystem/pull/169">PR#169</a>)</li> <li>Updated compatibility with <a href="https://wasi.dev/">WASI</a> platform. (<a href="https://github.com/boostorg/filesystem/pull/169">PR#169</a>)</li>
<li>Fixed an exception being thrown by <code>path::remove_filename</code> if the path is "////". (<a href="https://github.com/boostorg/filesystem/issues/176">#176</a>)</li> <li>Fixed an exception being thrown by <code>path::remove_filename</code> if the path is "////". (<a href="https://github.com/boostorg/filesystem/issues/176">#176</a>)</li>
<li>Fixed <code>create_directories</code> disregarding errors from file status query operations issued internally. This could result in incorrect error codes returned by <code>create_directories</code>. (<a href="https://github.com/boostorg/filesystem/issues/182">#182</a>)</li>
</ul> </ul>
<h2>1.75.0</h2> <h2>1.75.0</h2>

View File

@ -1454,17 +1454,17 @@ void copy_symlink(const path& existing_symlink, const path& new_symlink, system:
BOOST_FILESYSTEM_DECL BOOST_FILESYSTEM_DECL
bool create_directories(const path& p, system::error_code* ec) bool create_directories(const path& p, system::error_code* ec)
{ {
if (p.empty()) if (p.empty())
{ {
if (!ec) if (!ec)
{ {
BOOST_FILESYSTEM_THROW(filesystem_error( BOOST_FILESYSTEM_THROW(filesystem_error(
"boost::filesystem::create_directories", p, "boost::filesystem::create_directories", p,
system::errc::make_error_code(system::errc::invalid_argument))); system::errc::make_error_code(system::errc::invalid_argument)));
} }
ec->assign(system::errc::invalid_argument, system::generic_category()); ec->assign(system::errc::invalid_argument, system::generic_category());
return false; return false;
} }
if (p.filename_is_dot() || p.filename_is_dot_dot()) if (p.filename_is_dot() || p.filename_is_dot_dot())
return create_directories(p.parent_path(), ec); return create_directories(p.parent_path(), ec);
@ -1478,6 +1478,13 @@ bool create_directories(const path& p, system::error_code* ec)
ec->clear(); ec->clear();
return false; 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(); path parent = p.parent_path();
BOOST_ASSERT_MSG(parent != p, "internal error: p == 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) if (parent_status.type() == file_not_found)
{ {
create_directories(parent, local_ec); create_directories(parent, local_ec);
if (local_ec) if (BOOST_UNLIKELY(!!local_ec))
{ {
parent_fail_local_ec:
if (!ec) if (!ec)
BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::create_directories", parent, local_ec)); BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::create_directories", parent, local_ec));
*ec = local_ec; *ec = local_ec;
return false; return false;
} }
} }
else if (BOOST_UNLIKELY(parent_status.type() == status_error))
{
goto parent_fail_local_ec;
}
} }
// create the directory // create the directory