mirror of
https://github.com/boostorg/filesystem.git
synced 2026-07-21 13:13:44 +00:00
Handle EINTR error code returned from opendir and readdir.
Although not documented, this error code, reportedly, may be returned on Apple operating systems and some BSD systems.
This commit is contained in:
@@ -45,6 +45,7 @@
|
||||
<li>Marked templated versions of <code>initial_path</code> as deprecated and removed from <b>v4</b>. Use the non-templated versions instead.</li>
|
||||
<li>Use <code>readdir</code> instead of <code>readdir_r</code> on more POSIX platforms, specifically on Mac OS and other Apple operating systems, FreeBSD, OpenBSD, DragonFly BSD, NetBSD, QNX 6.0 and later, Solaris 10 and later and Illumos-based systems. Solaris users with gcc are recommended to define <code>__SunOS_5_x</code> macros according to their target Solaris version (e.g. <code>__SunOS_5_11</code>) when building Boost. (<a href="https://github.com/boostorg/filesystem/issues/349">#349</a>)</li>
|
||||
<li>Support for platforms with non-thread-safe <code>readdir</code> is deprecated and will be removed in a future release. Although not required until <a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/readdir.html">POSIX.1-2024</a>, on modern systems <code>readdir</code> is thread-safe when used with separate <code>DIR</code> objects in different threads and on some systems <code>readdir_r</code> is marked as deprecated. POSIX.1-2024 has been updated accordingly and also marked <code>readdir_r</code> as obsolescent, with a planned removal in a future version of the specification.</li>
|
||||
<li>On POSIX platforms, handle <code>EINTR</code> error code returned from <code>opendir</code>, <code>readdir</code> and equivalents. Although not documented, this error code, reportedly, may be returned on Apple operating systems and some BSD systems.</li>
|
||||
</ul>
|
||||
|
||||
<h2>1.91.0</h2>
|
||||
|
||||
+66
-25
@@ -417,11 +417,21 @@ inline int invoke_readdir(dir_itr_imp& imp, struct dirent** result)
|
||||
system::error_code dir_itr_increment(dir_itr_imp& imp, fs::path& filename, fs::file_status& sf, fs::file_status& symlink_sf)
|
||||
{
|
||||
dirent* result = nullptr;
|
||||
int err = invoke_readdir(imp, &result);
|
||||
if (BOOST_UNLIKELY(err != 0))
|
||||
return system::error_code(err, system::system_category());
|
||||
if (result == nullptr)
|
||||
return dir_itr_close(imp);
|
||||
while (true)
|
||||
{
|
||||
int err = invoke_readdir(imp, &result);
|
||||
if (BOOST_UNLIKELY(err != 0))
|
||||
{
|
||||
if (err == EINTR)
|
||||
continue;
|
||||
return system::error_code(err, system::system_category());
|
||||
}
|
||||
|
||||
if (result == nullptr)
|
||||
return dir_itr_close(imp);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
filename = result->d_name;
|
||||
|
||||
@@ -511,21 +521,35 @@ system::error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& i
|
||||
return ec;
|
||||
}
|
||||
|
||||
pimpl->handle = ::fdopendir(fd.get());
|
||||
if (BOOST_UNLIKELY(!pimpl->handle))
|
||||
while (true)
|
||||
{
|
||||
const int err = errno;
|
||||
return system::error_code(err, system::system_category());
|
||||
pimpl->handle = ::fdopendir(fd.get());
|
||||
if (BOOST_UNLIKELY(!pimpl->handle))
|
||||
{
|
||||
const int err = errno;
|
||||
if (err == EINTR)
|
||||
continue;
|
||||
return system::error_code(err, system::system_category());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// At this point fd will be closed by closedir
|
||||
fd.release();
|
||||
#else // defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW)
|
||||
pimpl->handle = ::opendir(dir.c_str());
|
||||
if (BOOST_UNLIKELY(!pimpl->handle))
|
||||
while (true)
|
||||
{
|
||||
const int err = errno;
|
||||
return system::error_code(err, system::system_category());
|
||||
pimpl->handle = ::opendir(dir.c_str());
|
||||
if (BOOST_UNLIKELY(!pimpl->handle))
|
||||
{
|
||||
const int err = errno;
|
||||
if (err == EINTR)
|
||||
continue;
|
||||
return system::error_code(err, system::system_category());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif // defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW)
|
||||
|
||||
@@ -1118,29 +1142,44 @@ bool is_empty_directory(boost::scope::unique_fd&& fd, path const& p, error_code*
|
||||
::closedir(dir);
|
||||
}
|
||||
};
|
||||
std::unique_ptr< DIR, closedir_deleter > dir;
|
||||
|
||||
int err;
|
||||
|
||||
#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW)
|
||||
std::unique_ptr< DIR, closedir_deleter > dir(::fdopendir(fd.get()));
|
||||
if (BOOST_UNLIKELY(!dir))
|
||||
while (true)
|
||||
{
|
||||
err = errno;
|
||||
fail:
|
||||
emit_error(err, p, ec, "boost::filesystem::is_empty");
|
||||
return false;
|
||||
dir.reset(::fdopendir(fd.get()));
|
||||
if (BOOST_UNLIKELY(!dir))
|
||||
{
|
||||
err = errno;
|
||||
if (err == EINTR)
|
||||
continue;
|
||||
fail:
|
||||
emit_error(err, p, ec, "boost::filesystem::is_empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// At this point fd will be closed by closedir
|
||||
fd.release();
|
||||
#else // defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW)
|
||||
std::unique_ptr< DIR, closedir_deleter > dir(::opendir(p.c_str()));
|
||||
if (BOOST_UNLIKELY(!dir))
|
||||
while (true)
|
||||
{
|
||||
err = errno;
|
||||
fail:
|
||||
emit_error(err, p, ec, "boost::filesystem::is_empty");
|
||||
return false;
|
||||
dir.reset(::opendir(p.c_str()));
|
||||
if (BOOST_UNLIKELY(!dir))
|
||||
{
|
||||
err = errno;
|
||||
if (err == EINTR)
|
||||
continue;
|
||||
fail:
|
||||
emit_error(err, p, ec, "boost::filesystem::is_empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif // defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW)
|
||||
|
||||
@@ -1151,6 +1190,8 @@ bool is_empty_directory(boost::scope::unique_fd&& fd, path const& p, error_code*
|
||||
if (!ent)
|
||||
{
|
||||
err = errno;
|
||||
if (err == EINTR)
|
||||
continue;
|
||||
if (err != 0)
|
||||
goto fail;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user