Skip to content

Commit

Permalink
Don't throw in directory_entry::refresh if the file doesn't exist.
Browse files Browse the repository at this point in the history
This makes directory_entry::status, directory_entry::symlink_status, as well
as related methods behave similarly to the equivalent standalone operations.

std::filesystem specification for directory_entry::refresh doesn't explicitly
say that the file not existing is not an error, but it does say that
directory_entry::status and directory_entry::symlink_status should behave
the same way as the standalone operations. Currently, libstdc++, libc++
and MSVC standard library all avoid throwing the exception from
directory_entry::refresh if the file doesn't exist.

Closes #314.
  • Loading branch information
Lastique committed Jun 29, 2024
1 parent 7ff9487 commit 9f8dea7
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 14 deletions.
1 change: 1 addition & 0 deletions doc/release_history.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ <h2>1.86.0</h2>
<li><code>is_empty</code> operation is now better protected against concurrent filesystem modifications.</li>
<li>On POSIX systems, <code>is_empty</code> now indicates error if invoked on a file other than a regular file or a directory.</li>
<li>On Windows, fixed <code>file_size</code> and <code>is_empty</code> operating on symlinks rather than the files the symlinks refer to. (<a href="https://github.com/boostorg/filesystem/issues/313">#313</a>)</li>
<li><code>directory_entry::refresh</code> no longer throws an exception if the file referenced by the entry doesn't exist. This makes <code>directory_entry::status</code> and <code>directory_entry::symlink_status</code>, as well as methods based on them, behave similarly to the equivalent standalone operations. The fact that the file does not exist is still indicated via the <code>error_code</code> returned by the corresponding <code>directory_entry::refresh</code> overload, or can be seen by testing if the file type returned by <code>directory_entry::status</code> or <code>directory_entry::symlink_status</code> calls is <code>file_type::file_not_found</code>. (<a href="https://github.com/boostorg/filesystem/issues/314">#314</a>)</li>
</ul>

<h2>1.85.0</h2>
Expand Down
18 changes: 4 additions & 14 deletions src/directory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,25 +91,15 @@ namespace filesystem {

BOOST_FILESYSTEM_DECL void directory_entry::refresh_impl(system::error_code* ec) const
{
system::error_code local_ec;
m_symlink_status = detail::symlink_status(m_path, &local_ec);
m_status = filesystem::file_status();
m_symlink_status = filesystem::file_status();

m_symlink_status = detail::symlink_status(m_path, ec);

if (!filesystem::is_symlink(m_symlink_status))
{
// Also works if symlink_status fails - set m_status to status_error as well
m_status = m_symlink_status;

if (BOOST_UNLIKELY(!!local_ec))
{
if (!ec)
BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::directory_entry::refresh", m_path, local_ec));

*ec = local_ec;
return;
}

if (ec)
ec->clear();
}
else
{
Expand Down
17 changes: 17 additions & 0 deletions test/operations_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,23 @@ void directory_iterator_tests()
BOOST_TEST_EQ(vec[3].path().filename().string(), std::string("f1"));
}

// Test that querying a file status for a removed file referenced by the iterator
// doesn't cause an error (i.e. the behavior is similar to standalone status/symlink_status).
// https://github.com/boostorg/filesystem/issues/314
{
BOOST_TEST(fs::is_empty(d2));
create_file(d2 / "file");
fs::directory_iterator it(d2);
fs::remove(d2 / "file");

for (; it != fs::directory_iterator(); ++it)
{
it->symlink_status();
it->status();
it->refresh();
}
}

{ // *i++ must meet the standard's InputIterator requirements
fs::directory_iterator dir_itr(dir);
BOOST_TEST(dir_itr != fs::directory_iterator());
Expand Down

0 comments on commit 9f8dea7

Please sign in to comment.