PR libstdc++/67747 use readdir instead of readdir_r
authorJonathan Wakely <jwakely@redhat.com>
Fri, 2 Oct 2015 16:34:34 +0000 (17:34 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 2 Oct 2015 16:34:34 +0000 (17:34 +0100)
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

libstdc++-v3/ChangeLog
libstdc++-v3/src/filesystem/dir.cc

index 8dcf1bdd2ea9db75655287180a992f588b0ccb58..239cd4467de82c04b7111693f60a1fd59e6d8d73 100644 (file)
@@ -1,3 +1,11 @@
+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>
 
        * doc/html/manual/errno.html: Add new file.
index bce751c3fb1d843e6eb474dc93278c3e7fb49065..33280ecdb07165e9c7ac295eb6e74fb704524657 100644 (file)
@@ -69,15 +69,17 @@ struct fs::_Dir
 namespace
 {
   template<typename Bitmask>
-    inline bool is_set(Bitmask obj, Bitmask bits)
+    inline bool
+    is_set(Bitmask obj, Bitmask bits)
     {
       return (obj & bits) != Bitmask::none;
     }
 
   // Returns {dirp, p} on success, {nullptr, p} on error.
   // If an ignored EACCES error occurs returns {}.
-  fs::_Dir
-  open_dir(const fs::path& p, fs::directory_options options, std::error_code* ec)
+  inline fs::_Dir
+  open_dir(const fs::path& p, fs::directory_options options,
+          std::error_code* ec)
   {
     if (ec)
       ec->clear();
@@ -100,7 +102,7 @@ namespace
   }
 
   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
     switch (d.d_type)
@@ -126,22 +128,11 @@ namespace
     }
 #else
     return fs::file_type::none;
-#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.
 // Reports errors by setting ec or throwing.
 bool
@@ -150,9 +141,20 @@ fs::_Dir::advance(error_code* ec, directory_options options)
   if (ec)
     ec->clear();
 
-  ::dirent ent;
-  ::dirent* result = &ent;
-  if (int err = native_readdir(dirp, result))
+  int err = std::exchange(errno, 0);
+  const auto entp = readdir(dirp);
+  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
         && is_set(options, directory_options::skip_permission_denied))
@@ -165,15 +167,6 @@ fs::_Dir::advance(error_code* ec, directory_options options)
       ec->assign(err, std::generic_category());
       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
     {
       // reached the end
@@ -251,10 +244,10 @@ recursive_directory_iterator(const path& p, directory_options options,
 {
   if (DIR* dirp = ::opendir(p.c_str()))
     {
-      _M_dirs = std::make_shared<_Dir_stack>();
-      _M_dirs->push(_Dir{ dirp, p });
-      if (!_M_dirs->top().advance(ec))
-       _M_dirs.reset();
+      auto sp = std::make_shared<_Dir_stack>();
+      sp->push(_Dir{ dirp, p });
+      if (sp->top().advance(ec))
+       _M_dirs.swap(sp);
     }
   else
     {