mirror of git://gcc.gnu.org/git/gcc.git
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>
|
2015-09-21 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
PR libstdc++/67647
|
PR libstdc++/67647
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,24 @@ fs::absolute(const path& p, const path& base)
|
||||||
|
|
||||||
namespace
|
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
|
struct free_as_in_malloc
|
||||||
{
|
{
|
||||||
void operator()(void* p) const { ::free(p); }
|
void operator()(void* p) const { ::free(p); }
|
||||||
|
|
@ -576,19 +594,36 @@ fs::create_directories(const path& p)
|
||||||
bool
|
bool
|
||||||
fs::create_directories(const path& p, error_code& ec) noexcept
|
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;
|
std::stack<path> missing;
|
||||||
path pp = p;
|
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);
|
ec.clear();
|
||||||
pp = pp.parent_path();
|
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();
|
missing.pop();
|
||||||
}
|
}
|
||||||
|
while (!missing.empty() && !ec);
|
||||||
|
|
||||||
return missing.empty();
|
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