namespace
{
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+ inline bool is_dot(wchar_t c) { return c == L'.'; }
+#else
+ inline bool is_dot(char c) { return c == '.'; }
+#endif
+
+ inline bool is_dot(const fs::path& path)
+ {
+ const auto& filename = path.native();
+ return filename.size() == 1 && is_dot(filename[0]);
+ }
+
+ inline bool is_dotdot(const fs::path& path)
+ {
+ const auto& filename = path.native();
+ return filename.size() == 2 && is_dot(filename[0]) && is_dot(filename[1]);
+ }
+
struct free_as_in_malloc
{
void operator()(void* p) const { ::free(p); }
bool
fs::create_directories(const path& p, error_code& ec) noexcept
{
+ if (p.empty())
+ {
+ ec = std::make_error_code(errc::invalid_argument);
+ return false;
+ }
std::stack<path> missing;
path pp = p;
- ec.clear();
- while (!p.empty() && !exists(pp, ec) && !ec.value())
+
+ while (!pp.empty() && status(pp, ec).type() == file_type::not_found)
{
- missing.push(pp);
- pp = pp.parent_path();
+ ec.clear();
+ const auto& filename = pp.filename();
+ if (!is_dot(filename) && !is_dotdot(filename))
+ missing.push(pp);
+ pp.remove_filename();
}
- while (!missing.empty() && !ec.value())
+
+ if (ec || missing.empty())
+ return false;
+
+ do
{
- create_directory(missing.top(), ec);
+ const path& top = missing.top();
+ create_directory(top, ec);
+ if (ec && is_directory(top))
+ ec.clear();
missing.pop();
}
+ while (!missing.empty() && !ec);
+
return missing.empty();
}
--- /dev/null
+// Copyright (C) 2015 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.
+ bool b = fs::create_directories( "", ec );
+ VERIFY( ec );
+ VERIFY( !b );
+
+ // Test existing path.
+ b = fs::create_directories( fs::current_path(), ec );
+ VERIFY( !ec );
+ VERIFY( !b );
+
+ // Test non-existent path.
+ const auto p = __gnu_test::nonexistent_path();
+ b = fs::create_directories( p, ec );
+ VERIFY( !ec );
+ VERIFY( b );
+ VERIFY( is_directory(p) );
+
+ b = fs::create_directories( p/".", ec );
+ VERIFY( !ec );
+ VERIFY( !b );
+
+ b = fs::create_directories( p/"..", ec );
+ VERIFY( !ec );
+ VERIFY( !b );
+
+ b = fs::create_directories( p/"d1/d2/d3", ec );
+ VERIFY( !ec );
+ VERIFY( b );
+ VERIFY( is_directory(p/"d1/d2/d3") );
+
+ b = fs::create_directories( p/"./d4/../d5", ec );
+ VERIFY( !ec );
+ VERIFY( b );
+ VERIFY( is_directory(p/"./d4/../d5") );
+
+ remove_all(p, ec);
+}
+
+int
+main()
+{
+ test01();
+}