diff mbox

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

Message ID 20160510130600.GA21211@redhat.com
State New
Headers show

Commit Message

redi May 10, 2016, 1:06 p.m. UTC
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 <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Tue May 10 13:04:21 2016 +0000

    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 mbox

Patch

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<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
index 0000000..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 <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();
+}