libstdc++/71036 Handle EEXIST in filesystem::create_directory
authorJonathan Wakely <jwakely@redhat.com>
Tue, 10 May 2016 13:04:21 +0000 (14:04 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 10 May 2016 13:04:21 +0000 (14:04 +0100)
PR libstdc++/71036
* src/filesystem/ops.cc (create_dir): Handle EEXIST from mkdir.
* testsuite/experimental/filesystem/operations/create_directory.cc:
New test.

From-SVN: r236076

libstdc++-v3/ChangeLog
libstdc++-v3/src/filesystem/ops.cc
libstdc++-v3/testsuite/experimental/filesystem/operations/create_directory.cc [new file with mode: 0644]

index cf7ce6f5cd13210c9948a8d24e92752949966a50..20c55ff4d5e013e45d66af95ff5433da25101da5 100644 (file)
@@ -1,5 +1,10 @@
 2016-05-10  Jonathan Wakely  <jwakely@redhat.com>
 
+       PR libstdc++/71036
+       * src/filesystem/ops.cc (create_dir): Handle EEXIST from mkdir.
+       * testsuite/experimental/filesystem/operations/create_directory.cc:
+       New test.
+
        PR libstdc++/71037
        * src/filesystem/ops.cc (canonical(const path&, const path&)): Add
        base path to exception.
index e18c7510c4170b54c9e1a83c6abee105247f61c7..fab42355f9f4191fa1d00e8d8ff983d1b5fd4113 100644 (file)
@@ -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<std::underlying_type_t<fs::perms>>(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 (file)
index 0000000..66c2b3f
--- /dev/null
@@ -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 <experimental/filesystem>
+#include <testsuite_hooks.h>
+#include <testsuite_fs.h>
+
+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();
+}