[PATCH] libstdc++/71036 Handle EEXIST in filesystem::create_directory

2016-05-10 Thread redi

Another bug Eric noticed. I had tests for create_directories() but not
create_directory(), and the former was already checking whether it
existed or not, so I didn't notice this bug.

PR libstdc++/71036
* src/filesystem/ops.cc (create_dir): Handle EEXIST from mkdir.
* testsuite/experimental/filesystem/operations/create_directory.cc:
New test.

Tested x86_64-linux, committed to trunk. Backports to follow.
commit 50e15efafef5fd7893ff186546e755a6530c348a
Author: redi 
Date:   Tue May 10 13:04:21 2016 +

libstdc++/71036 Handle EEXIST in filesystem::create_directory

PR libstdc++/71036
* src/filesystem/ops.cc (create_dir): Handle EEXIST from mkdir.
* testsuite/experimental/filesystem/operations/create_directory.cc:
New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@236076 
138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/libstdc++-v3/src/filesystem/ops.cc 
b/libstdc++-v3/src/filesystem/ops.cc
index e18c751..fab4235 100644
--- a/libstdc++-v3/src/filesystem/ops.cc
+++ b/libstdc++-v3/src/filesystem/ops.cc
@@ -660,22 +660,26 @@ namespace
   bool
   create_dir(const fs::path& p, fs::perms perm, std::error_code& ec)
   {
+bool created = false;
 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
 ::mode_t mode = static_cast>(perm);
 if (::mkdir(p.c_str(), mode))
   {
-   ec.assign(errno, std::generic_category());
-   return false;
+   const int err = errno;
+   if (err != EEXIST || !is_directory(p))
+ ec.assign(err, std::generic_category());
+   else
+ ec.clear();
   }
 else
   {
ec.clear();
-   return true;
+   created = true;
   }
 #else
 ec = std::make_error_code(std::errc::not_supported);
-return false;
 #endif
+return created;
   }
 } // namespace
 
diff --git 
a/libstdc++-v3/testsuite/experimental/filesystem/operations/create_directory.cc 
b/libstdc++-v3/testsuite/experimental/filesystem/operations/create_directory.cc
new file mode 100644
index 000..66c2b3f
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/experimental/filesystem/operations/create_directory.cc
@@ -0,0 +1,63 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11 -lstdc++fs" }
+// { dg-require-filesystem-ts "" }
+
+#include 
+#include 
+#include 
+
+namespace fs = std::experimental::filesystem;
+
+void
+test01()
+{
+  bool test __attribute__((unused)) = false;
+  std::error_code ec;
+
+  // Test empty path.
+  fs::path p;
+  bool b = create_directory( p, ec );
+  VERIFY( ec );
+  VERIFY( !b );
+
+  // Test non-existent path
+  p = __gnu_test::nonexistent_path();
+  VERIFY( !exists(p) );
+
+  b = create_directory(p, ec); // create the directory once
+  VERIFY( !ec );
+  VERIFY( b );
+  VERIFY( exists(p) );
+
+  // Test existing path (libstdc++/71036).
+  b = create_directory(p, ec);
+  VERIFY( !ec );
+  VERIFY( !b );
+  b = create_directory(p);
+  VERIFY( !ec );
+  VERIFY( !b );
+
+  remove_all(p, ec);
+}
+
+int
+main()
+{
+  test01();
+}


[PATCH] Test begin and end functions for directory iterators

2016-05-10 Thread redi

A minor fix for missing noexcept qualifiers, pointed out by Eric
again.

* include/experimental/bits/fs_dir.h (begin, end): Add noexcept.
* testsuite/experimental/filesystem/iterators/directory_iterator.cc:
Test begin and end functions.
* testsuite/experimental/filesystem/iterators/
recursive_directory_iterator.cc: Likewise.

Tested x86_64-linux and x86_64-freebsd10, committed to trunk.
Backports to follow.

commit 2f45dbbd2c3f01a1dcdee4c265dc394561f42606
Author: redi 
Date:   Tue May 10 15:39:20 2016 +

Test begin and end functions for directory iterators

* include/experimental/bits/fs_dir.h (begin, end): Add noexcept.
* testsuite/experimental/filesystem/iterators/directory_iterator.cc:
Test begin and end functions.
* testsuite/experimental/filesystem/iterators/
recursive_directory_iterator.cc: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@236085 
138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/libstdc++-v3/include/experimental/bits/fs_dir.h 
b/libstdc++-v3/include/experimental/bits/fs_dir.h
index 011d398..70a95eb 100644
--- a/libstdc++-v3/include/experimental/bits/fs_dir.h
+++ b/libstdc++-v3/include/experimental/bits/fs_dir.h
@@ -235,10 +235,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   };
 
   inline directory_iterator
-  begin(directory_iterator __iter) { return __iter; }
+  begin(directory_iterator __iter) noexcept
+  { return __iter; }
 
   inline directory_iterator
-  end(directory_iterator) { return directory_iterator(); }
+  end(directory_iterator) noexcept
+  { return directory_iterator(); }
 
   inline bool
   operator==(const directory_iterator& __lhs, const directory_iterator& __rhs)
@@ -327,10 +329,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   };
 
   inline recursive_directory_iterator
-  begin(recursive_directory_iterator __iter) { return __iter; }
+  begin(recursive_directory_iterator __iter) noexcept
+  { return __iter; }
 
   inline recursive_directory_iterator
-  end(recursive_directory_iterator) { return recursive_directory_iterator(); }
+  end(recursive_directory_iterator) noexcept
+  { return recursive_directory_iterator(); }
 
   inline bool
   operator==(const recursive_directory_iterator& __lhs,
diff --git 
a/libstdc++-v3/testsuite/experimental/filesystem/iterators/directory_iterator.cc
 
b/libstdc++-v3/testsuite/experimental/filesystem/iterators/directory_iterator.cc
index ce9f437..ffd97ce 100644
--- 
a/libstdc++-v3/testsuite/experimental/filesystem/iterators/directory_iterator.cc
+++ 
b/libstdc++-v3/testsuite/experimental/filesystem/iterators/directory_iterator.cc
@@ -113,10 +113,36 @@ test03()
   remove_all(p, ec);
 }
 
+void
+test04()
+{
+  bool test __attribute__((unused)) = false;
+
+  const fs::directory_iterator it;
+  VERIFY( it == fs::directory_iterator() );
+}
+
+void
+test05()
+{
+  bool test __attribute__((unused)) = false;
+
+  auto p = __gnu_test::nonexistent_path();
+  create_directory(p);
+  create_directory_symlink(p, p / "l");
+  fs::directory_iterator it(p), endit;
+  VERIFY( begin(it) == it );
+  static_assert( noexcept(begin(it)), "begin is noexcept" );
+  VERIFY( end(it) == endit );
+  static_assert( noexcept(end(it)), "end is noexcept" );
+}
+
 int
 main()
 {
   test01();
   test02();
   test03();
+  test04();
+  test05();
 }
diff --git 
a/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc
 
b/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc
index fb4c31e..b44ff3f 100644
--- 
a/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc
+++ 
b/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc
@@ -153,6 +153,21 @@ test04()
   VERIFY( it == fs::recursive_directory_iterator() );
 }
 
+void
+test05()
+{
+  bool test __attribute__((unused)) = false;
+
+  auto p = __gnu_test::nonexistent_path();
+  create_directory(p);
+  create_directory_symlink(p, p / "l");
+  fs::recursive_directory_iterator it(p), endit;
+  VERIFY( begin(it) == it );
+  static_assert( noexcept(begin(it)), "begin is noexcept" );
+  VERIFY( end(it) == endit );
+  static_assert( noexcept(end(it)), "end is noexcept" );
+}
+
 int
 main()
 {
@@ -160,4 +175,5 @@ main()
   test02();
   test03();
   test04();
+  test05();
 }