Fix filesystem::create_directories() function
* src/filesystem/ops.cc (is_dot, is_dotdot): Define new helpers. (create_directories): Fix error handling. * testsuite/experimental/filesystem/operations/create_directories.cc: New. From-SVN: r228041
This commit is contained in:
parent
be6e26f995
commit
366703118c
@ -1,3 +1,10 @@
|
||||
2015-09-23 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* src/filesystem/ops.cc (is_dot, is_dotdot): Define new helpers.
|
||||
(create_directories): Fix error handling.
|
||||
* testsuite/experimental/filesystem/operations/create_directories.cc:
|
||||
New.
|
||||
|
||||
2015-09-21 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/67647
|
||||
|
@ -85,6 +85,24 @@ fs::absolute(const path& p, const path& base)
|
||||
|
||||
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); }
|
||||
@ -576,19 +594,36 @@ fs::create_directories(const path& 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();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,75 @@
|
||||
// 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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user