Commit 7b65155f by Jonathan Wakely Committed by Jonathan Wakely

PR libstdc++/67747 use readdir instead of readdir_r

	PR libstdc++/67747
	* src/filesystem/dir.cc (native_readdir): Remove.
	(_Dir::advance): Use readdir instead of native_readdir.
	(recursive_directory_iterator(const path&, directory_options,
	error_code*)): Use swap instead of reset.

From-SVN: r228404
parent 000051e1
2015-10-02 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/67747
* src/filesystem/dir.cc (native_readdir): Remove.
(_Dir::advance): Use readdir instead of native_readdir.
(recursive_directory_iterator(const path&, directory_options,
error_code*)): Use swap instead of reset.
2015-10-01 Jonathan Wakely <jwakely@redhat.com> 2015-10-01 Jonathan Wakely <jwakely@redhat.com>
* doc/html/manual/errno.html: Add new file. * doc/html/manual/errno.html: Add new file.
......
...@@ -69,15 +69,17 @@ struct fs::_Dir ...@@ -69,15 +69,17 @@ struct fs::_Dir
namespace namespace
{ {
template<typename Bitmask> template<typename Bitmask>
inline bool is_set(Bitmask obj, Bitmask bits) inline bool
is_set(Bitmask obj, Bitmask bits)
{ {
return (obj & bits) != Bitmask::none; return (obj & bits) != Bitmask::none;
} }
// Returns {dirp, p} on success, {nullptr, p} on error. // Returns {dirp, p} on success, {nullptr, p} on error.
// If an ignored EACCES error occurs returns {}. // If an ignored EACCES error occurs returns {}.
fs::_Dir inline fs::_Dir
open_dir(const fs::path& p, fs::directory_options options, std::error_code* ec) open_dir(const fs::path& p, fs::directory_options options,
std::error_code* ec)
{ {
if (ec) if (ec)
ec->clear(); ec->clear();
...@@ -100,7 +102,7 @@ namespace ...@@ -100,7 +102,7 @@ namespace
} }
inline fs::file_type inline fs::file_type
get_file_type(const dirent& d __attribute__((__unused__))) get_file_type(const ::dirent& d __attribute__((__unused__)))
{ {
#ifdef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE #ifdef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE
switch (d.d_type) switch (d.d_type)
...@@ -128,20 +130,9 @@ namespace ...@@ -128,20 +130,9 @@ namespace
return fs::file_type::none; return fs::file_type::none;
#endif #endif
} }
int
native_readdir(DIR* dirp, ::dirent*& entryp)
{
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
if ((entryp = ::readdir(dirp)))
return 0;
return errno;
#else
return ::readdir_r(dirp, entryp, &entryp);
#endif
}
} }
// Returns false when the end of the directory entries is reached. // Returns false when the end of the directory entries is reached.
// Reports errors by setting ec or throwing. // Reports errors by setting ec or throwing.
bool bool
...@@ -150,9 +141,20 @@ fs::_Dir::advance(error_code* ec, directory_options options) ...@@ -150,9 +141,20 @@ fs::_Dir::advance(error_code* ec, directory_options options)
if (ec) if (ec)
ec->clear(); ec->clear();
::dirent ent; int err = std::exchange(errno, 0);
::dirent* result = &ent; const auto entp = readdir(dirp);
if (int err = native_readdir(dirp, result)) std::swap(errno, err);
if (entp)
{
// skip past dot and dot-dot
if (!strcmp(entp->d_name, ".") || !strcmp(entp->d_name, ".."))
return advance(ec, options);
entry = fs::directory_entry{path / entp->d_name};
type = get_file_type(*entp);
return true;
}
else if (err)
{ {
if (err == EACCES if (err == EACCES
&& is_set(options, directory_options::skip_permission_denied)) && is_set(options, directory_options::skip_permission_denied))
...@@ -165,15 +167,6 @@ fs::_Dir::advance(error_code* ec, directory_options options) ...@@ -165,15 +167,6 @@ fs::_Dir::advance(error_code* ec, directory_options options)
ec->assign(err, std::generic_category()); ec->assign(err, std::generic_category());
return true; return true;
} }
else if (result != nullptr)
{
// skip past dot and dot-dot
if (!strcmp(ent.d_name, ".") || !strcmp(ent.d_name, ".."))
return advance(ec, options);
entry = fs::directory_entry{path / ent.d_name};
type = get_file_type(ent);
return true;
}
else else
{ {
// reached the end // reached the end
...@@ -251,10 +244,10 @@ recursive_directory_iterator(const path& p, directory_options options, ...@@ -251,10 +244,10 @@ recursive_directory_iterator(const path& p, directory_options options,
{ {
if (DIR* dirp = ::opendir(p.c_str())) if (DIR* dirp = ::opendir(p.c_str()))
{ {
_M_dirs = std::make_shared<_Dir_stack>(); auto sp = std::make_shared<_Dir_stack>();
_M_dirs->push(_Dir{ dirp, p }); sp->push(_Dir{ dirp, p });
if (!_M_dirs->top().advance(ec)) if (sp->top().advance(ec))
_M_dirs.reset(); _M_dirs.swap(sp);
} }
else else
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment