Implement C++17 Filesystem library

Based on Filesystem TS implementation, with the changes applied by:

- P0219R1 Relative Paths for Filesystem
- P0317R1 Directory Entry Caching for Filesystem
- P0492R2 Resolution of C++17 National Body Comments

Where appropriate code is shared between the TS and C++17
implementations.

	* include/Makefile.am: Add new headers for C++17 filesystem library.
	* include/Makefile.in: Regenerate.
	* include/bits/fs_dir.h: New header, based on Filesystem TS code in
	include/experimental/bits directory.
	* include/bits/fs_fwd.h: Likewise.
	* include/bits/fs_ops.h: Likewise.
	* include/bits/fs_path.h: Likewise.
	* include/experimental/bits/fs_dir.h: Rename Doxygen group.
	* include/experimental/bits/fs_fwd.h: Likewise.
	* include/experimental/bits/fs_ops.h: Likewise.
	* include/experimental/bits/fs_path.h: Likewise.
	* include/experimental/filesystem (filesystem_error::_M_gen_what):
	Remove inline definition.
	* include/precompiled/stdc++.h: Add <filesystem> to precompiled
	header.
	* include/std/filesystem: New header.
	* python/libstdcxx/v6/printers.py: Enable printer for std::filesystem
	paths.
	* src/filesystem/Makefile.am: Add new files. Compile as C++17.
	* src/filesystem/Makefile.in: Regenerate.
	* src/filesystem/cow-dir.cc: Update comment.
	* src/filesystem/cow-ops.cc: Likewise.
	* src/filesystem/cow-path.cc: Likewise.
	* src/filesystem/cow-std-dir.cc: New file.
	* src/filesystem/cow-std-ops.cc: New file.
	* src/filesystem/cow-std-path.cc: New file.
	* src/filesystem/dir-common.h (_Dir_base, get_file_type): New header
	for common code.
	* src/filesystem/dir.cc (_Dir): Derive from _Dir_base.
	(open_dir): Move to _Dir_base constructor.
	(get_file_type): Move to dir-common.h.
	(recurse): Move to _Dir_base::should_recurse.
	* src/filesystem/ops-common.h: New header for common code.
	* src/filesystem/ops.cc (is_set, make_file_type, make_file_status)
	(is_not_found_errno, file_time, do_copy_file): Move to ops-common.h.
	* src/filesystem/path.cc (filesystem_error::_M_gen_what): Define.
	* src/filesystem/std-dir.cc: New file, based on Filesystem TS code.
	* src/filesystem/std-ops.cc: Likewise.
	* src/filesystem/std-dir.cc: Likewise.
	* testsuite/27_io/filesystem/iterators/directory_iterator.cc: New
	test.
	* testsuite/27_io/filesystem/iterators/pop.cc: New test.
	* testsuite/27_io/filesystem/iterators/recursive_directory_iterator.cc:
	New test.
	* testsuite/27_io/filesystem/operations/absolute.cc: New test.
	* testsuite/27_io/filesystem/operations/canonical.cc: New test.
	* testsuite/27_io/filesystem/operations/copy.cc: New test.
	* testsuite/27_io/filesystem/operations/copy_file.cc: New test.
	* testsuite/27_io/filesystem/operations/create_directories.cc: New
	test.
	* testsuite/27_io/filesystem/operations/create_directory.cc: New test.
	* testsuite/27_io/filesystem/operations/create_symlink.cc: New test.
	* testsuite/27_io/filesystem/operations/current_path.cc: New test.
	* testsuite/27_io/filesystem/operations/equivalent.cc: New test.
	* testsuite/27_io/filesystem/operations/exists.cc: New test.
	* testsuite/27_io/filesystem/operations/file_size.cc: New test.
	* testsuite/27_io/filesystem/operations/is_empty.cc: New test.
	* testsuite/27_io/filesystem/operations/last_write_time.cc: New test.
	* testsuite/27_io/filesystem/operations/permissions.cc: New test.
	* testsuite/27_io/filesystem/operations/proximate.cc: New test.
	* testsuite/27_io/filesystem/operations/read_symlink.cc: New test.
	* testsuite/27_io/filesystem/operations/relative.cc: New test.
	* testsuite/27_io/filesystem/operations/remove_all.cc: New test.
	* testsuite/27_io/filesystem/operations/space.cc: New test.
	* testsuite/27_io/filesystem/operations/status.cc: New test.
	* testsuite/27_io/filesystem/operations/symlink_status.cc: New test.
	* testsuite/27_io/filesystem/operations/temp_directory_path.cc: New
	test.
	* testsuite/27_io/filesystem/operations/weakly_canonical.cc: New test.
	* testsuite/27_io/filesystem/path/append/path.cc: New test.
	* testsuite/27_io/filesystem/path/assign/assign.cc: New test.
	* testsuite/27_io/filesystem/path/assign/copy.cc: New test.
	* testsuite/27_io/filesystem/path/compare/compare.cc: New test.
	* testsuite/27_io/filesystem/path/compare/path.cc: New test.
	* testsuite/27_io/filesystem/path/compare/strings.cc: New test.
	* testsuite/27_io/filesystem/path/concat/path.cc: New test.
	* testsuite/27_io/filesystem/path/concat/strings.cc: New test.
	* testsuite/27_io/filesystem/path/construct/copy.cc: New test.
	* testsuite/27_io/filesystem/path/construct/default.cc: New test.
	* testsuite/27_io/filesystem/path/construct/locale.cc: New test.
	* testsuite/27_io/filesystem/path/construct/range.cc: New test.
	* testsuite/27_io/filesystem/path/construct/string_view.cc: New test.
	* testsuite/27_io/filesystem/path/decompose/extension.cc: New test.
	* testsuite/27_io/filesystem/path/decompose/filename.cc: New test.
	* testsuite/27_io/filesystem/path/decompose/parent_path.cc: New test.
	* testsuite/27_io/filesystem/path/decompose/relative_path.cc: New
	test.
	* testsuite/27_io/filesystem/path/decompose/root_directory.cc: New
	test.
	* testsuite/27_io/filesystem/path/decompose/root_name.cc: New test.
	* testsuite/27_io/filesystem/path/decompose/root_path.cc: New test.
	* testsuite/27_io/filesystem/path/decompose/stem.cc: New test.
	* testsuite/27_io/filesystem/path/generation/normal.cc: New test.
	* testsuite/27_io/filesystem/path/generation/proximate.cc: New test.
	* testsuite/27_io/filesystem/path/generation/relative.cc: New test.
	* testsuite/27_io/filesystem/path/generic/generic_string.cc: New test.
	* testsuite/27_io/filesystem/path/itr/traversal.cc: New test.
	* testsuite/27_io/filesystem/path/modifiers/clear.cc: New test.
	* testsuite/27_io/filesystem/path/modifiers/make_preferred.cc: New
	test.
	* testsuite/27_io/filesystem/path/modifiers/remove_filename.cc: New
	test.
	* testsuite/27_io/filesystem/path/modifiers/replace_extension.cc: New
	test.
	* testsuite/27_io/filesystem/path/modifiers/replace_filename.cc: New
	test.
	* testsuite/27_io/filesystem/path/modifiers/swap.cc: New test.
	* testsuite/27_io/filesystem/path/native/string.cc: New test.
	* testsuite/27_io/filesystem/path/nonmember/hash_value.cc: New test.
	* testsuite/27_io/filesystem/path/query/empty.cc: New test.
	* testsuite/27_io/filesystem/path/query/has_extension.cc: New test.
	* testsuite/27_io/filesystem/path/query/has_filename.cc: New test.
	* testsuite/27_io/filesystem/path/query/has_parent_path.cc: New test.
	* testsuite/27_io/filesystem/path/query/has_relative_path.cc: New
	test.
	* testsuite/27_io/filesystem/path/query/has_root_directory.cc: New
	test.
	* testsuite/27_io/filesystem/path/query/has_root_name.cc: New test.
	* testsuite/27_io/filesystem/path/query/has_root_path.cc: New test.
	* testsuite/27_io/filesystem/path/query/has_stem.cc: New test.
	* testsuite/27_io/filesystem/path/query/is_relative.cc: New test.
	* testsuite/experimental/filesystem/path/construct/string_view.cc:
	Define USE_FILESYSTEM_TS.
	* testsuite/util/testsuite_fs.h: Allow use with C++17 paths as well
	as Filesystem TS.

From-SVN: r254008
This commit is contained in:
Jonathan Wakely 2017-10-23 13:11:22 +01:00 committed by Jonathan Wakely
parent 9c71c00f17
commit 641cb5a675
103 changed files with 10854 additions and 494 deletions

View File

@ -1,5 +1,131 @@
2017-10-23 Jonathan Wakely <jwakely@redhat.com>
* include/Makefile.am: Add new headers for C++17 filesystem library.
* include/Makefile.in: Regenerate.
* include/bits/fs_dir.h: New header, based on Filesystem TS code in
include/experimental/bits directory.
* include/bits/fs_fwd.h: Likewise.
* include/bits/fs_ops.h: Likewise.
* include/bits/fs_path.h: Likewise.
* include/experimental/bits/fs_dir.h: Rename Doxygen group.
* include/experimental/bits/fs_fwd.h: Likewise.
* include/experimental/bits/fs_ops.h: Likewise.
* include/experimental/bits/fs_path.h: Likewise.
* include/experimental/filesystem (filesystem_error::_M_gen_what):
Remove inline definition.
* include/precompiled/stdc++.h: Add <filesystem> to precompiled
header.
* include/std/filesystem: New header.
* python/libstdcxx/v6/printers.py: Enable printer for std::filesystem
paths.
* src/filesystem/Makefile.am: Add new files. Compile as C++17.
* src/filesystem/Makefile.in: Regenerate.
* src/filesystem/cow-dir.cc: Update comment.
* src/filesystem/cow-ops.cc: Likewise.
* src/filesystem/cow-path.cc: Likewise.
* src/filesystem/cow-std-dir.cc: New file.
* src/filesystem/cow-std-ops.cc: New file.
* src/filesystem/cow-std-path.cc: New file.
* src/filesystem/dir-common.h (_Dir_base, get_file_type): New header
for common code.
* src/filesystem/dir.cc (_Dir): Derive from _Dir_base.
(open_dir): Move to _Dir_base constructor.
(get_file_type): Move to dir-common.h.
(recurse): Move to _Dir_base::should_recurse.
* src/filesystem/ops-common.h: New header for common code.
* src/filesystem/ops.cc (is_set, make_file_type, make_file_status)
(is_not_found_errno, file_time, do_copy_file): Move to ops-common.h.
* src/filesystem/path.cc (filesystem_error::_M_gen_what): Define.
* src/filesystem/std-dir.cc: New file, based on Filesystem TS code.
* src/filesystem/std-ops.cc: Likewise.
* src/filesystem/std-dir.cc: Likewise.
* testsuite/27_io/filesystem/iterators/directory_iterator.cc: New
test.
* testsuite/27_io/filesystem/iterators/pop.cc: New test.
* testsuite/27_io/filesystem/iterators/recursive_directory_iterator.cc:
New test.
* testsuite/27_io/filesystem/operations/absolute.cc: New test.
* testsuite/27_io/filesystem/operations/canonical.cc: New test.
* testsuite/27_io/filesystem/operations/copy.cc: New test.
* testsuite/27_io/filesystem/operations/copy_file.cc: New test.
* testsuite/27_io/filesystem/operations/create_directories.cc: New
test.
* testsuite/27_io/filesystem/operations/create_directory.cc: New test.
* testsuite/27_io/filesystem/operations/create_symlink.cc: New test.
* testsuite/27_io/filesystem/operations/current_path.cc: New test.
* testsuite/27_io/filesystem/operations/equivalent.cc: New test.
* testsuite/27_io/filesystem/operations/exists.cc: New test.
* testsuite/27_io/filesystem/operations/file_size.cc: New test.
* testsuite/27_io/filesystem/operations/is_empty.cc: New test.
* testsuite/27_io/filesystem/operations/last_write_time.cc: New test.
* testsuite/27_io/filesystem/operations/permissions.cc: New test.
* testsuite/27_io/filesystem/operations/proximate.cc: New test.
* testsuite/27_io/filesystem/operations/read_symlink.cc: New test.
* testsuite/27_io/filesystem/operations/relative.cc: New test.
* testsuite/27_io/filesystem/operations/remove_all.cc: New test.
* testsuite/27_io/filesystem/operations/space.cc: New test.
* testsuite/27_io/filesystem/operations/status.cc: New test.
* testsuite/27_io/filesystem/operations/symlink_status.cc: New test.
* testsuite/27_io/filesystem/operations/temp_directory_path.cc: New
test.
* testsuite/27_io/filesystem/operations/weakly_canonical.cc: New test.
* testsuite/27_io/filesystem/path/append/path.cc: New test.
* testsuite/27_io/filesystem/path/assign/assign.cc: New test.
* testsuite/27_io/filesystem/path/assign/copy.cc: New test.
* testsuite/27_io/filesystem/path/compare/compare.cc: New test.
* testsuite/27_io/filesystem/path/compare/path.cc: New test.
* testsuite/27_io/filesystem/path/compare/strings.cc: New test.
* testsuite/27_io/filesystem/path/concat/path.cc: New test.
* testsuite/27_io/filesystem/path/concat/strings.cc: New test.
* testsuite/27_io/filesystem/path/construct/copy.cc: New test.
* testsuite/27_io/filesystem/path/construct/default.cc: New test.
* testsuite/27_io/filesystem/path/construct/locale.cc: New test.
* testsuite/27_io/filesystem/path/construct/range.cc: New test.
* testsuite/27_io/filesystem/path/construct/string_view.cc: New test.
* testsuite/27_io/filesystem/path/decompose/extension.cc: New test.
* testsuite/27_io/filesystem/path/decompose/filename.cc: New test.
* testsuite/27_io/filesystem/path/decompose/parent_path.cc: New test.
* testsuite/27_io/filesystem/path/decompose/relative_path.cc: New
test.
* testsuite/27_io/filesystem/path/decompose/root_directory.cc: New
test.
* testsuite/27_io/filesystem/path/decompose/root_name.cc: New test.
* testsuite/27_io/filesystem/path/decompose/root_path.cc: New test.
* testsuite/27_io/filesystem/path/decompose/stem.cc: New test.
* testsuite/27_io/filesystem/path/generation/normal.cc: New test.
* testsuite/27_io/filesystem/path/generation/proximate.cc: New test.
* testsuite/27_io/filesystem/path/generation/relative.cc: New test.
* testsuite/27_io/filesystem/path/generic/generic_string.cc: New test.
* testsuite/27_io/filesystem/path/itr/traversal.cc: New test.
* testsuite/27_io/filesystem/path/modifiers/clear.cc: New test.
* testsuite/27_io/filesystem/path/modifiers/make_preferred.cc: New
test.
* testsuite/27_io/filesystem/path/modifiers/remove_filename.cc: New
test.
* testsuite/27_io/filesystem/path/modifiers/replace_extension.cc: New
test.
* testsuite/27_io/filesystem/path/modifiers/replace_filename.cc: New
test.
* testsuite/27_io/filesystem/path/modifiers/swap.cc: New test.
* testsuite/27_io/filesystem/path/native/string.cc: New test.
* testsuite/27_io/filesystem/path/nonmember/hash_value.cc: New test.
* testsuite/27_io/filesystem/path/query/empty.cc: New test.
* testsuite/27_io/filesystem/path/query/has_extension.cc: New test.
* testsuite/27_io/filesystem/path/query/has_filename.cc: New test.
* testsuite/27_io/filesystem/path/query/has_parent_path.cc: New test.
* testsuite/27_io/filesystem/path/query/has_relative_path.cc: New
test.
* testsuite/27_io/filesystem/path/query/has_root_directory.cc: New
test.
* testsuite/27_io/filesystem/path/query/has_root_name.cc: New test.
* testsuite/27_io/filesystem/path/query/has_root_path.cc: New test.
* testsuite/27_io/filesystem/path/query/has_stem.cc: New test.
* testsuite/27_io/filesystem/path/query/is_relative.cc: New test.
* testsuite/experimental/filesystem/path/construct/string_view.cc:
Define USE_FILESYSTEM_TS.
* testsuite/util/testsuite_fs.h: Allow use with C++17 paths as well
as Filesystem TS.
PR libstdc++/82644
* doc/xml/manual/intro.xml: Include new section.
* doc/xml/manual/status_cxxis29124.xml: New section on IS 29124

View File

@ -37,6 +37,7 @@ std_headers = \
${std_srcdir}/complex \
${std_srcdir}/condition_variable \
${std_srcdir}/deque \
${std_srcdir}/filesystem \
${std_srcdir}/forward_list \
${std_srcdir}/fstream \
${std_srcdir}/functional \
@ -104,6 +105,10 @@ bits_headers = \
${bits_srcdir}/enable_special_members.h \
${bits_srcdir}/forward_list.h \
${bits_srcdir}/forward_list.tcc \
${bits_srcdir}/fs_dir.h \
${bits_srcdir}/fs_fwd.h \
${bits_srcdir}/fs_ops.h \
${bits_srcdir}/fs_path.h \
${bits_srcdir}/fstream.tcc \
${bits_srcdir}/functexcept.h \
${bits_srcdir}/functional_hash.h \

View File

@ -330,6 +330,7 @@ std_headers = \
${std_srcdir}/complex \
${std_srcdir}/condition_variable \
${std_srcdir}/deque \
${std_srcdir}/filesystem \
${std_srcdir}/forward_list \
${std_srcdir}/fstream \
${std_srcdir}/functional \
@ -397,6 +398,10 @@ bits_headers = \
${bits_srcdir}/enable_special_members.h \
${bits_srcdir}/forward_list.h \
${bits_srcdir}/forward_list.tcc \
${bits_srcdir}/fs_dir.h \
${bits_srcdir}/fs_fwd.h \
${bits_srcdir}/fs_ops.h \
${bits_srcdir}/fs_path.h \
${bits_srcdir}/fstream.tcc \
${bits_srcdir}/functexcept.h \
${bits_srcdir}/functional_hash.h \

View File

@ -0,0 +1,526 @@
// Filesystem directory utilities -*- C++ -*-
// Copyright (C) 2014-2017 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file include/bits/fs_dir.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{filesystem}
*/
#ifndef _GLIBCXX_FS_DIR_H
#define _GLIBCXX_FS_DIR_H 1
#if __cplusplus >= 201703L
# include <typeinfo>
# include <ext/concurrence.h>
# include <bits/unique_ptr.h>
# include <bits/shared_ptr.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace filesystem
{
/**
* @ingroup filesystem
* @{
*/
class file_status
{
public:
// constructors
explicit
file_status(file_type __ft = file_type::none,
perms __prms = perms::unknown) noexcept
: _M_type(__ft), _M_perms(__prms) { }
file_status(const file_status&) noexcept = default;
file_status(file_status&&) noexcept = default;
~file_status() = default;
file_status& operator=(const file_status&) noexcept = default;
file_status& operator=(file_status&&) noexcept = default;
// observers
file_type type() const noexcept { return _M_type; }
perms permissions() const noexcept { return _M_perms; }
// modifiers
void type(file_type __ft) noexcept { _M_type = __ft; }
void permissions(perms __prms) noexcept { _M_perms = __prms; }
private:
file_type _M_type;
perms _M_perms;
};
_GLIBCXX_BEGIN_NAMESPACE_CXX11
struct _Dir;
class directory_iterator;
class recursive_directory_iterator;
class directory_entry
{
public:
// constructors and destructor
directory_entry() noexcept = default;
directory_entry(const directory_entry&) = default;
directory_entry(directory_entry&&) noexcept = default;
explicit
directory_entry(const filesystem::path& __p)
: _M_path(__p)
{ refresh(); }
directory_entry(const filesystem::path& __p, error_code& __ec)
: _M_path(__p)
{
refresh(__ec);
if (__ec)
_M_path.clear();
}
~directory_entry() = default;
// modifiers
directory_entry& operator=(const directory_entry&) = default;
directory_entry& operator=(directory_entry&&) noexcept = default;
void
assign(const filesystem::path& __p)
{
_M_path = __p;
refresh();
}
void
assign(const filesystem::path& __p, error_code& __ec)
{
_M_path = __p;
refresh(__ec);
}
void
replace_filename(const filesystem::path& __p)
{
_M_path.replace_filename(__p);
refresh();
}
void
replace_filename(const filesystem::path& __p, error_code& __ec)
{
_M_path.replace_filename(__p);
refresh(__ec);
}
void refresh() { _M_type = symlink_status().type(); }
void refresh(error_code& __ec) { _M_type = symlink_status(__ec).type(); }
// observers
const filesystem::path& path() const noexcept { return _M_path; }
operator const filesystem::path& () const noexcept { return _M_path; }
bool
exists() const
{ return filesystem::exists(file_status{_M_file_type()}); }
bool
exists(error_code& __ec) const noexcept
{ return filesystem::exists(file_status{_M_file_type(__ec)}); }
bool
is_block_file() const
{ return _M_file_type() == file_type::block; }
bool
is_block_file(error_code& __ec) const noexcept
{ return _M_file_type(__ec) == file_type::block; }
bool
is_character_file() const
{ return _M_file_type() == file_type::character; }
bool
is_character_file(error_code& __ec) const noexcept
{ return _M_file_type(__ec) == file_type::character; }
bool
is_directory() const
{ return _M_file_type() == file_type::directory; }
bool
is_directory(error_code& __ec) const noexcept
{ return _M_file_type(__ec) == file_type::directory; }
bool
is_fifo() const
{ return _M_file_type() == file_type::fifo; }
bool
is_fifo(error_code& __ec) const noexcept
{ return _M_file_type(__ec) == file_type::fifo; }
bool
is_other() const
{ return filesystem::is_other(file_status{_M_file_type()}); }
bool
is_other(error_code& __ec) const noexcept
{ return filesystem::is_other(file_status{_M_file_type(__ec)}); }
bool
is_regular_file() const
{ return _M_file_type() == file_type::regular; }
bool
is_regular_file(error_code& __ec) const noexcept
{ return _M_file_type(__ec) == file_type::regular; }
bool
is_socket() const
{ return _M_file_type() == file_type::socket; }
bool
is_socket(error_code& __ec) const noexcept
{ return _M_file_type(__ec) == file_type::socket; }
bool
is_symlink() const
{
if (_M_type != file_type::none)
return _M_type == file_type::symlink;
return symlink_status().type() == file_type::symlink;
}
bool
is_symlink(error_code& __ec) const noexcept
{
if (_M_type != file_type::none)
return _M_type == file_type::symlink;
return symlink_status(__ec).type() == file_type::symlink;
}
uintmax_t
file_size() const
{ return filesystem::file_size(_M_path); }
uintmax_t
file_size(error_code& __ec) const noexcept
{ return filesystem::file_size(_M_path, __ec); }
uintmax_t
hard_link_count() const
{ return filesystem::hard_link_count(_M_path); }
uintmax_t
hard_link_count(error_code& __ec) const noexcept
{ return filesystem::hard_link_count(_M_path, __ec); }
file_time_type
last_write_time() const
{ return filesystem::last_write_time(_M_path); }
file_time_type
last_write_time(error_code& __ec) const noexcept
{ return filesystem::last_write_time(_M_path, __ec); }
file_status
status() const
{ return filesystem::status(_M_path); }
file_status
status(error_code& __ec) const noexcept
{ return filesystem::status(_M_path, __ec); }
file_status
symlink_status() const
{ return filesystem::symlink_status(_M_path); }
file_status
symlink_status(error_code& __ec) const noexcept
{ return filesystem::symlink_status(_M_path, __ec); }
bool
operator< (const directory_entry& __rhs) const noexcept
{ return _M_path < __rhs._M_path; }
bool
operator==(const directory_entry& __rhs) const noexcept
{ return _M_path == __rhs._M_path; }
bool
operator!=(const directory_entry& __rhs) const noexcept
{ return _M_path != __rhs._M_path; }
bool
operator<=(const directory_entry& __rhs) const noexcept
{ return _M_path <= __rhs._M_path; }
bool
operator> (const directory_entry& __rhs) const noexcept
{ return _M_path > __rhs._M_path; }
bool
operator>=(const directory_entry& __rhs) const noexcept
{ return _M_path >= __rhs._M_path; }
private:
friend class _Dir;
friend class directory_iterator;
friend class recursive_directory_iterator;
directory_entry(const filesystem::path& __p, file_type __t)
: _M_path(__p), _M_type(__t)
{ }
// Equivalent to status().type() but uses cached value, if any.
file_type
_M_file_type() const
{
if (_M_type != file_type::none && _M_type != file_type::symlink)
return _M_type;
return status().type();
}
// Equivalent to status(__ec).type() but uses cached value, if any.
file_type
_M_file_type(error_code& __ec) const noexcept
{
if (_M_type != file_type::none && _M_type != file_type::symlink)
return _M_type;
return status(__ec).type();
}
filesystem::path _M_path;
file_type _M_type = file_type::none;
};
struct __directory_iterator_proxy
{
const directory_entry& operator*() const& noexcept { return _M_entry; }
directory_entry operator*() && noexcept { return std::move(_M_entry); }
private:
friend class directory_iterator;
friend class recursive_directory_iterator;
explicit
__directory_iterator_proxy(const directory_entry& __e) : _M_entry(__e) { }
directory_entry _M_entry;
};
class directory_iterator
{
public:
typedef directory_entry value_type;
typedef ptrdiff_t difference_type;
typedef const directory_entry* pointer;
typedef const directory_entry& reference;
typedef input_iterator_tag iterator_category;
directory_iterator() = default;
explicit
directory_iterator(const path& __p)
: directory_iterator(__p, directory_options::none, nullptr) { }
directory_iterator(const path& __p, directory_options __options)
: directory_iterator(__p, __options, nullptr) { }
directory_iterator(const path& __p, error_code& __ec) noexcept
: directory_iterator(__p, directory_options::none, __ec) { }
directory_iterator(const path& __p,
directory_options __options,
error_code& __ec) noexcept
: directory_iterator(__p, __options, &__ec) { }
directory_iterator(const directory_iterator& __rhs) = default;
directory_iterator(directory_iterator&& __rhs) noexcept = default;
~directory_iterator() = default;
directory_iterator&
operator=(const directory_iterator& __rhs) = default;
directory_iterator&
operator=(directory_iterator&& __rhs) noexcept = default;
const directory_entry& operator*() const;
const directory_entry* operator->() const { return &**this; }
directory_iterator& operator++();
directory_iterator& increment(error_code& __ec) noexcept;
__directory_iterator_proxy operator++(int)
{
__directory_iterator_proxy __pr{**this};
++*this;
return __pr;
}
private:
directory_iterator(const path&, directory_options, error_code*);
friend bool
operator==(const directory_iterator& __lhs,
const directory_iterator& __rhs);
friend class recursive_directory_iterator;
std::shared_ptr<_Dir> _M_dir;
};
inline directory_iterator
begin(directory_iterator __iter) noexcept
{ return __iter; }
inline directory_iterator
end(directory_iterator) noexcept
{ return directory_iterator(); }
inline bool
operator==(const directory_iterator& __lhs, const directory_iterator& __rhs)
{
return !__rhs._M_dir.owner_before(__lhs._M_dir)
&& !__lhs._M_dir.owner_before(__rhs._M_dir);
}
inline bool
operator!=(const directory_iterator& __lhs, const directory_iterator& __rhs)
{ return !(__lhs == __rhs); }
class recursive_directory_iterator
{
public:
typedef directory_entry value_type;
typedef ptrdiff_t difference_type;
typedef const directory_entry* pointer;
typedef const directory_entry& reference;
typedef input_iterator_tag iterator_category;
recursive_directory_iterator() = default;
explicit
recursive_directory_iterator(const path& __p)
: recursive_directory_iterator(__p, directory_options::none, nullptr) { }
recursive_directory_iterator(const path& __p, directory_options __options)
: recursive_directory_iterator(__p, __options, nullptr) { }
recursive_directory_iterator(const path& __p,
directory_options __options,
error_code& __ec) noexcept
: recursive_directory_iterator(__p, __options, &__ec) { }
recursive_directory_iterator(const path& __p, error_code& __ec) noexcept
: recursive_directory_iterator(__p, directory_options::none, &__ec) { }
recursive_directory_iterator(
const recursive_directory_iterator&) = default;
recursive_directory_iterator(recursive_directory_iterator&&) = default;
~recursive_directory_iterator();
// observers
directory_options options() const { return _M_options; }
int depth() const;
bool recursion_pending() const { return _M_pending; }
const directory_entry& operator*() const;
const directory_entry* operator->() const { return &**this; }
// modifiers
recursive_directory_iterator&
operator=(const recursive_directory_iterator& __rhs) noexcept;
recursive_directory_iterator&
operator=(recursive_directory_iterator&& __rhs) noexcept;
recursive_directory_iterator& operator++();
recursive_directory_iterator& increment(error_code& __ec) noexcept;
__directory_iterator_proxy operator++(int)
{
__directory_iterator_proxy __pr{**this};
++*this;
return __pr;
}
void pop();
void pop(error_code&);
void disable_recursion_pending() { _M_pending = false; }
private:
recursive_directory_iterator(const path&, directory_options, error_code*);
friend bool
operator==(const recursive_directory_iterator& __lhs,
const recursive_directory_iterator& __rhs);
struct _Dir_stack;
std::shared_ptr<_Dir_stack> _M_dirs;
directory_options _M_options = {};
bool _M_pending = false;
};
inline recursive_directory_iterator
begin(recursive_directory_iterator __iter) noexcept
{ return __iter; }
inline recursive_directory_iterator
end(recursive_directory_iterator) noexcept
{ return recursive_directory_iterator(); }
inline bool
operator==(const recursive_directory_iterator& __lhs,
const recursive_directory_iterator& __rhs)
{
return !__rhs._M_dirs.owner_before(__lhs._M_dirs)
&& !__lhs._M_dirs.owner_before(__rhs._M_dirs);
}
inline bool
operator!=(const recursive_directory_iterator& __lhs,
const recursive_directory_iterator& __rhs)
{ return !(__lhs == __rhs); }
_GLIBCXX_END_NAMESPACE_CXX11
// @} group filesystem
} // namespace filesystem
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++17
#endif // _GLIBCXX_FS_DIR_H

View File

@ -0,0 +1,348 @@
// Filesystem declarations -*- C++ -*-
// Copyright (C) 2014-2017 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file include/bits/fs_fwd.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{filesystem}
*/
#ifndef _GLIBCXX_FS_FWD_H
#define _GLIBCXX_FS_FWD_H 1
#if __cplusplus >= 201703L
#include <system_error>
#include <cstdint>
#include <chrono>
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace filesystem
{
#if _GLIBCXX_USE_CXX11_ABI
inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { }
#endif
/**
* @defgroup filesystem Filesystem
*
* Utilities for performing operations on file systems and their components,
* such as paths, regular files, and directories.
*
* @{
*/
class file_status;
_GLIBCXX_BEGIN_NAMESPACE_CXX11
class path;
class filesystem_error;
class directory_entry;
class directory_iterator;
class recursive_directory_iterator;
_GLIBCXX_END_NAMESPACE_CXX11
struct space_info
{
uintmax_t capacity;
uintmax_t free;
uintmax_t available;
};
enum class file_type : signed char {
none = 0, not_found = -1, regular = 1, directory = 2, symlink = 3,
block = 4, character = 5, fifo = 6, socket = 7, unknown = 8
};
/// Bitmask type
enum class copy_options : unsigned short {
none = 0,
skip_existing = 1, overwrite_existing = 2, update_existing = 4,
recursive = 8,
copy_symlinks = 16, skip_symlinks = 32,
directories_only = 64, create_symlinks = 128, create_hard_links = 256
};
constexpr copy_options
operator&(copy_options __x, copy_options __y) noexcept
{
using __utype = typename std::underlying_type<copy_options>::type;
return static_cast<copy_options>(
static_cast<__utype>(__x) & static_cast<__utype>(__y));
}
constexpr copy_options
operator|(copy_options __x, copy_options __y) noexcept
{
using __utype = typename std::underlying_type<copy_options>::type;
return static_cast<copy_options>(
static_cast<__utype>(__x) | static_cast<__utype>(__y));
}
constexpr copy_options
operator^(copy_options __x, copy_options __y) noexcept
{
using __utype = typename std::underlying_type<copy_options>::type;
return static_cast<copy_options>(
static_cast<__utype>(__x) ^ static_cast<__utype>(__y));
}
constexpr copy_options
operator~(copy_options __x) noexcept
{
using __utype = typename std::underlying_type<copy_options>::type;
return static_cast<copy_options>(~static_cast<__utype>(__x));
}
inline copy_options&
operator&=(copy_options& __x, copy_options __y) noexcept
{ return __x = __x & __y; }
inline copy_options&
operator|=(copy_options& __x, copy_options __y) noexcept
{ return __x = __x | __y; }
inline copy_options&
operator^=(copy_options& __x, copy_options __y) noexcept
{ return __x = __x ^ __y; }
/// Bitmask type
enum class perms : unsigned {
none = 0,
owner_read = 0400,
owner_write = 0200,
owner_exec = 0100,
owner_all = 0700,
group_read = 040,
group_write = 020,
group_exec = 010,
group_all = 070,
others_read = 04,
others_write = 02,
others_exec = 01,
others_all = 07,
all = 0777,
set_uid = 04000,
set_gid = 02000,
sticky_bit = 01000,
mask = 07777,
unknown = 0xFFFF,
};
constexpr perms
operator&(perms __x, perms __y) noexcept
{
using __utype = typename std::underlying_type<perms>::type;
return static_cast<perms>(
static_cast<__utype>(__x) & static_cast<__utype>(__y));
}
constexpr perms
operator|(perms __x, perms __y) noexcept
{
using __utype = typename std::underlying_type<perms>::type;
return static_cast<perms>(
static_cast<__utype>(__x) | static_cast<__utype>(__y));
}
constexpr perms
operator^(perms __x, perms __y) noexcept
{
using __utype = typename std::underlying_type<perms>::type;
return static_cast<perms>(
static_cast<__utype>(__x) ^ static_cast<__utype>(__y));
}
constexpr perms
operator~(perms __x) noexcept
{
using __utype = typename std::underlying_type<perms>::type;
return static_cast<perms>(~static_cast<__utype>(__x));
}
inline perms&
operator&=(perms& __x, perms __y) noexcept
{ return __x = __x & __y; }
inline perms&
operator|=(perms& __x, perms __y) noexcept
{ return __x = __x | __y; }
inline perms&
operator^=(perms& __x, perms __y) noexcept
{ return __x = __x ^ __y; }
/// Bitmask type
enum class perm_options : unsigned {
replace = 0x1,
add = 0x2,
remove = 0x4,
nofollow = 0x8
};
constexpr perm_options
operator&(perm_options __x, perm_options __y) noexcept
{
using __utype = typename std::underlying_type<perm_options>::type;
return static_cast<perm_options>(
static_cast<__utype>(__x) & static_cast<__utype>(__y));
}
constexpr perm_options
operator|(perm_options __x, perm_options __y) noexcept
{
using __utype = typename std::underlying_type<perm_options>::type;
return static_cast<perm_options>(
static_cast<__utype>(__x) | static_cast<__utype>(__y));
}
constexpr perm_options
operator^(perm_options __x, perm_options __y) noexcept
{
using __utype = typename std::underlying_type<perm_options>::type;
return static_cast<perm_options>(
static_cast<__utype>(__x) ^ static_cast<__utype>(__y));
}
constexpr perm_options
operator~(perm_options __x) noexcept
{
using __utype = typename std::underlying_type<perm_options>::type;
return static_cast<perm_options>(~static_cast<__utype>(__x));
}
inline perm_options&
operator&=(perm_options& __x, perm_options __y) noexcept
{ return __x = __x & __y; }
inline perm_options&
operator|=(perm_options& __x, perm_options __y) noexcept
{ return __x = __x | __y; }
inline perm_options&
operator^=(perm_options& __x, perm_options __y) noexcept
{ return __x = __x ^ __y; }
// Bitmask type
enum class directory_options : unsigned char {
none = 0, follow_directory_symlink = 1, skip_permission_denied = 2
};
constexpr directory_options
operator&(directory_options __x, directory_options __y) noexcept
{
using __utype = typename std::underlying_type<directory_options>::type;
return static_cast<directory_options>(
static_cast<__utype>(__x) & static_cast<__utype>(__y));
}
constexpr directory_options
operator|(directory_options __x, directory_options __y) noexcept
{
using __utype = typename std::underlying_type<directory_options>::type;
return static_cast<directory_options>(
static_cast<__utype>(__x) | static_cast<__utype>(__y));
}
constexpr directory_options
operator^(directory_options __x, directory_options __y) noexcept
{
using __utype = typename std::underlying_type<directory_options>::type;
return static_cast<directory_options>(
static_cast<__utype>(__x) ^ static_cast<__utype>(__y));
}
constexpr directory_options
operator~(directory_options __x) noexcept
{
using __utype = typename std::underlying_type<directory_options>::type;
return static_cast<directory_options>(~static_cast<__utype>(__x));
}
inline directory_options&
operator&=(directory_options& __x, directory_options __y) noexcept
{ return __x = __x & __y; }
inline directory_options&
operator|=(directory_options& __x, directory_options __y) noexcept
{ return __x = __x | __y; }
inline directory_options&
operator^=(directory_options& __x, directory_options __y) noexcept
{ return __x = __x ^ __y; }
using file_time_type = std::chrono::system_clock::time_point;
// operational functions
void copy(const path& __from, const path& __to, copy_options __options);
void copy(const path& __from, const path& __to, copy_options __options,
error_code&) noexcept;
bool copy_file(const path& __from, const path& __to, copy_options __option);
bool copy_file(const path& __from, const path& __to, copy_options __option,
error_code&) noexcept;
path current_path();
bool exists(file_status) noexcept;
bool is_other(file_status) noexcept;
uintmax_t file_size(const path&);
uintmax_t file_size(const path&, error_code&) noexcept;
uintmax_t hard_link_count(const path&);
uintmax_t hard_link_count(const path&, error_code&) noexcept;
file_time_type last_write_time(const path&);
file_time_type last_write_time(const path&, error_code&) noexcept;
void permissions(const path&, perms, perm_options, error_code&);
path proximate(const path& __p, const path& __base, error_code& __ec);
path proximate(const path& __p, const path& __base, error_code& __ec);
path relative(const path& __p, const path& __base, error_code& __ec);
file_status status(const path&);
file_status status(const path&, error_code&) noexcept;
bool status_known(file_status) noexcept;
file_status symlink_status(const path&);
file_status symlink_status(const path&, error_code&) noexcept;
bool is_regular_file(file_status) noexcept;
bool is_symlink(file_status) noexcept;
// @} group filesystem
} // namespace filesystem
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++17
#endif // _GLIBCXX_FS_FWD_H

View File

@ -0,0 +1,311 @@
// Filesystem operational functions -*- C++ -*-
// Copyright (C) 2014-2017 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file include/bits/fs_fwd.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{filesystem}
*/
#ifndef _GLIBCXX_FS_OPS_H
#define _GLIBCXX_FS_OPS_H 1
#if __cplusplus >= 201703L
#include <cstdint>
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace filesystem
{
/**
* @ingroup filesystem
* @{
*/
path absolute(const path& __p);
path absolute(const path& __p, error_code& __ec);
path canonical(const path& __p);
path canonical(const path& __p, error_code& __ec);
inline void
copy(const path& __from, const path& __to)
{ copy(__from, __to, copy_options::none); }
inline void
copy(const path& __from, const path& __to, error_code& __ec) noexcept
{ copy(__from, __to, copy_options::none, __ec); }
void copy(const path& __from, const path& __to, copy_options __options);
void copy(const path& __from, const path& __to, copy_options __options,
error_code& __ec) noexcept;
inline bool
copy_file(const path& __from, const path& __to)
{ return copy_file(__from, __to, copy_options::none); }
inline bool
copy_file(const path& __from, const path& __to, error_code& __ec) noexcept
{ return copy_file(__from, __to, copy_options::none, __ec); }
bool copy_file(const path& __from, const path& __to, copy_options __option);
bool copy_file(const path& __from, const path& __to, copy_options __option,
error_code& __ec) noexcept;
void copy_symlink(const path& __existing_symlink, const path& __new_symlink);
void copy_symlink(const path& __existing_symlink, const path& __new_symlink,
error_code& __ec) noexcept;
bool create_directories(const path& __p);
bool create_directories(const path& __p, error_code& __ec) noexcept;
bool create_directory(const path& __p);
bool create_directory(const path& __p, error_code& __ec) noexcept;
bool create_directory(const path& __p, const path& attributes);
bool create_directory(const path& __p, const path& attributes,
error_code& __ec) noexcept;
void create_directory_symlink(const path& __to, const path& __new_symlink);
void create_directory_symlink(const path& __to, const path& __new_symlink,
error_code& __ec) noexcept;
void create_hard_link(const path& __to, const path& __new_hard_link);
void create_hard_link(const path& __to, const path& __new_hard_link,
error_code& __ec) noexcept;
void create_symlink(const path& __to, const path& __new_symlink);
void create_symlink(const path& __to, const path& __new_symlink,
error_code& __ec) noexcept;
path current_path();
path current_path(error_code& __ec);
void current_path(const path& __p);
void current_path(const path& __p, error_code& __ec) noexcept;
bool
equivalent(const path& __p1, const path& __p2);
bool
equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept;
inline bool
exists(file_status __s) noexcept
{ return status_known(__s) && __s.type() != file_type::not_found; }
inline bool
exists(const path& __p)
{ return exists(status(__p)); }
inline bool
exists(const path& __p, error_code& __ec) noexcept
{
auto __s = status(__p, __ec);
if (status_known(__s))
__ec.clear();
return exists(__s);
}
uintmax_t file_size(const path& __p);
uintmax_t file_size(const path& __p, error_code& __ec) noexcept;
uintmax_t hard_link_count(const path& __p);
uintmax_t hard_link_count(const path& __p, error_code& __ec) noexcept;
inline bool
is_block_file(file_status __s) noexcept
{ return __s.type() == file_type::block; }
inline bool
is_block_file(const path& __p)
{ return is_block_file(status(__p)); }
inline bool
is_block_file(const path& __p, error_code& __ec) noexcept
{ return is_block_file(status(__p, __ec)); }
inline bool
is_character_file(file_status __s) noexcept
{ return __s.type() == file_type::character; }
inline bool
is_character_file(const path& __p)
{ return is_character_file(status(__p)); }
inline bool
is_character_file(const path& __p, error_code& __ec) noexcept
{ return is_character_file(status(__p, __ec)); }
inline bool
is_directory(file_status __s) noexcept
{ return __s.type() == file_type::directory; }
inline bool
is_directory(const path& __p)
{ return is_directory(status(__p)); }
inline bool
is_directory(const path& __p, error_code& __ec) noexcept
{ return is_directory(status(__p, __ec)); }
bool is_empty(const path& __p);
bool is_empty(const path& __p, error_code& __ec) noexcept;
inline bool
is_fifo(file_status __s) noexcept
{ return __s.type() == file_type::fifo; }
inline bool
is_fifo(const path& __p)
{ return is_fifo(status(__p)); }
inline bool
is_fifo(const path& __p, error_code& __ec) noexcept
{ return is_fifo(status(__p, __ec)); }
inline bool
is_other(file_status __s) noexcept
{
return exists(__s) && !is_regular_file(__s) && !is_directory(__s)
&& !is_symlink(__s);
}
inline bool
is_other(const path& __p)
{ return is_other(status(__p)); }
inline bool
is_other(const path& __p, error_code& __ec) noexcept
{ return is_other(status(__p, __ec)); }
inline bool
is_regular_file(file_status __s) noexcept
{ return __s.type() == file_type::regular; }
inline bool
is_regular_file(const path& __p)
{ return is_regular_file(status(__p)); }
inline bool
is_regular_file(const path& __p, error_code& __ec) noexcept
{ return is_regular_file(status(__p, __ec)); }
inline bool
is_socket(file_status __s) noexcept
{ return __s.type() == file_type::socket; }
inline bool
is_socket(const path& __p)
{ return is_socket(status(__p)); }
inline bool
is_socket(const path& __p, error_code& __ec) noexcept
{ return is_socket(status(__p, __ec)); }
inline bool
is_symlink(file_status __s) noexcept
{ return __s.type() == file_type::symlink; }
inline bool
is_symlink(const path& __p)
{ return is_symlink(symlink_status(__p)); }
inline bool
is_symlink(const path& __p, error_code& __ec) noexcept
{ return is_symlink(symlink_status(__p, __ec)); }
file_time_type last_write_time(const path& __p);
file_time_type last_write_time(const path& __p, error_code& __ec) noexcept;
void last_write_time(const path& __p, file_time_type __new_time);
void last_write_time(const path& __p, file_time_type __new_time,
error_code& __ec) noexcept;
void
permissions(const path& __p, perms __prms,
perm_options __opts = perm_options::replace);
inline void
permissions(const path& __p, perms __prms, error_code& __ec) noexcept
{ permissions(__p, __prms, perm_options::replace, __ec); }
void
permissions(const path& __p, perms __prms, perm_options __opts,
error_code& __ec);
inline path proximate(const path& __p, error_code& __ec)
{ return proximate(__p, current_path(), __ec); }
path proximate(const path& __p, const path& __base = current_path());
path proximate(const path& __p, const path& __base, error_code& __ec);
path read_symlink(const path& __p);
path read_symlink(const path& __p, error_code& __ec);
inline path relative(const path& __p, error_code& __ec)
{ return relative(__p, current_path(), __ec); }
path relative(const path& __p, const path& __base = current_path());
path relative(const path& __p, const path& __base, error_code& __ec);
bool remove(const path& __p);
bool remove(const path& __p, error_code& __ec) noexcept;
uintmax_t remove_all(const path& __p);
uintmax_t remove_all(const path& __p, error_code& __ec) noexcept;
void rename(const path& __from, const path& __to);
void rename(const path& __from, const path& __to, error_code& __ec) noexcept;
void resize_file(const path& __p, uintmax_t __size);
void resize_file(const path& __p, uintmax_t __size, error_code& __ec) noexcept;
space_info space(const path& __p);
space_info space(const path& __p, error_code& __ec) noexcept;
file_status status(const path& __p);
file_status status(const path& __p, error_code& __ec) noexcept;
inline bool status_known(file_status __s) noexcept
{ return __s.type() != file_type::none; }
file_status symlink_status(const path& __p);
file_status symlink_status(const path& __p, error_code& __ec) noexcept;
path temp_directory_path();
path temp_directory_path(error_code& __ec);
path weakly_canonical(const path& __p);
path weakly_canonical(const path& __p, error_code& __ec);
// @} group filesystem
} // namespace filesystem
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++17
#endif // _GLIBCXX_FS_OPS_H

File diff suppressed because it is too large Load Diff

View File

@ -49,7 +49,7 @@ namespace filesystem
inline namespace v1
{
/**
* @ingroup filesystem
* @ingroup filesystem-ts
* @{
*/
@ -351,7 +351,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_GLIBCXX_END_NAMESPACE_CXX11
// @} group filesystem
// @} group filesystem-ts
} // namespace v1
} // namespace filesystem
} // namespace experimental

View File

@ -53,7 +53,7 @@ inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { }
#endif
/**
* @defgroup filesystem Filesystem
* @defgroup filesystem-ts Filesystem TS
* @ingroup experimental
*
* Utilities for performing operations on file systems and their components,
@ -278,7 +278,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
bool is_regular_file(file_status) noexcept;
bool is_symlink(file_status) noexcept;
// @} group filesystem
// @} group filesystem-ts
} // namespace v1
} // namespace filesystem
} // namespace experimental

View File

@ -47,7 +47,7 @@ namespace filesystem
inline namespace v1
{
/**
* @ingroup filesystem
* @ingroup filesystem-ts
* @{
*/
@ -285,7 +285,7 @@ inline namespace v1
path temp_directory_path();
path temp_directory_path(error_code& __ec);
// @} group filesystem
// @} group filesystem-ts
} // namespace v1
} // namespace filesystem
} // namespace experimental

View File

@ -72,7 +72,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#endif
/**
* @ingroup filesystem
* @ingroup filesystem-ts
* @{
*/
@ -1079,7 +1079,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
return _M_at_end == __rhs._M_at_end;
}
// @} group filesystem
// @} group filesystem-ts
_GLIBCXX_END_NAMESPACE_CXX11
} // namespace v1
} // namespace filesystem

View File

@ -40,36 +40,6 @@
#define __cpp_lib_experimental_filesystem 201406
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace experimental
{
namespace filesystem
{
inline namespace v1
{
/**
* @ingroup filesystem
*/
inline std::string filesystem_error::_M_gen_what()
{
std::string __what = "filesystem error: ";
__what += system_error::what();
if (!_M_path1.empty())
__what += " [" + _M_path1.string() + ']';
if (!_M_path2.empty())
__what += " [" + _M_path2.string() + ']';
return __what;
}
} // namespace v1
} // namespace filesystem
} // namespace experimental
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++11
#endif // _GLIBCXX_EXPERIMENTAL_FILESYSTEM

View File

@ -122,6 +122,7 @@
#include <shared_mutex>
#endif
#if __cplusplus > 201402L
#if __cplusplus >= 201703L
#include <charconv>
#include <filesystem>
#endif

View File

@ -0,0 +1,45 @@
// <filesystem> -*- C++ -*-
// Copyright (C) 2014-2017 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file filesystem
* This is a Standard C++ Library header.
*/
#ifndef _GLIBCXX_FILESYSTEM
#define _GLIBCXX_FILESYSTEM 1
#pragma GCC system_header
#if __cplusplus >= 201703L
#include <bits/fs_fwd.h>
#include <bits/fs_path.h>
#include <bits/fs_dir.h>
#include <bits/fs_ops.h>
#define __cpp_lib_filesystem 201703
#endif // C++17
#endif // _GLIBCXX_FILESYSTEM

View File

@ -1592,6 +1592,10 @@ def build_libstdcxx_dictionary ():
'path', StdExpPathPrinter)
libstdcxx_printer.add_version('std::experimental::filesystem::v1::__cxx11::',
'path', StdExpPathPrinter)
libstdcxx_printer.add_version('std::filesystem::',
'path', StdExpPathPrinter)
libstdcxx_printer.add_version('std::filesystem::__cxx11::',
'path', StdExpPathPrinter)
# C++17 components
libstdcxx_printer.add_version('std::',

View File

@ -30,7 +30,10 @@ if ENABLE_DUAL_ABI
cxx11_abi_sources = \
cow-dir.cc \
cow-ops.cc \
cow-path.cc
cow-path.cc \
cow-std-dir.cc \
cow-std-ops.cc \
cow-std-path.cc
else
cxx11_abi_sources =
endif
@ -39,6 +42,9 @@ sources = \
dir.cc \
ops.cc \
path.cc \
std-dir.cc \
std-ops.cc \
std-path.cc \
${cxx11_abi_sources}
# vpath % $(top_srcdir)/src/filesystem
@ -52,7 +58,7 @@ libstdc__fs_la_SOURCES = $(sources)
# as the occasion call for it.
AM_CXXFLAGS = \
$(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
-std=gnu++14 \
-std=gnu++17 \
$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
AM_MAKEFLAGS = \

View File

@ -114,8 +114,10 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)"
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
libstdc__fs_la_LIBADD =
@ENABLE_DUAL_ABI_TRUE@am__objects_1 = cow-dir.lo cow-ops.lo \
@ENABLE_DUAL_ABI_TRUE@ cow-path.lo
am__objects_2 = dir.lo ops.lo path.lo $(am__objects_1)
@ENABLE_DUAL_ABI_TRUE@ cow-path.lo cow-std-dir.lo \
@ENABLE_DUAL_ABI_TRUE@ cow-std-ops.lo cow-std-path.lo
am__objects_2 = dir.lo ops.lo path.lo std-dir.lo std-ops.lo \
std-path.lo $(am__objects_1)
am_libstdc__fs_la_OBJECTS = $(am__objects_2)
libstdc__fs_la_OBJECTS = $(am_libstdc__fs_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
@ -362,12 +364,18 @@ headers =
@ENABLE_DUAL_ABI_TRUE@cxx11_abi_sources = \
@ENABLE_DUAL_ABI_TRUE@ cow-dir.cc \
@ENABLE_DUAL_ABI_TRUE@ cow-ops.cc \
@ENABLE_DUAL_ABI_TRUE@ cow-path.cc
@ENABLE_DUAL_ABI_TRUE@ cow-path.cc \
@ENABLE_DUAL_ABI_TRUE@ cow-std-dir.cc \
@ENABLE_DUAL_ABI_TRUE@ cow-std-ops.cc \
@ENABLE_DUAL_ABI_TRUE@ cow-std-path.cc
sources = \
dir.cc \
ops.cc \
path.cc \
std-dir.cc \
std-ops.cc \
std-path.cc \
${cxx11_abi_sources}
@ -381,7 +389,7 @@ libstdc__fs_la_SOURCES = $(sources)
# as the occasion call for it.
AM_CXXFLAGS = \
$(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
-std=gnu++14 \
-std=gnu++17 \
$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
AM_MAKEFLAGS = \

View File

@ -1,4 +1,4 @@
// Class filesystem::directory_entry etc. -*- C++ -*-
// Class experimental::filesystem::directory_entry etc. -*- C++ -*-
// Copyright (C) 2015-2017 Free Software Foundation, Inc.
//

View File

@ -1,4 +1,4 @@
// Filesystem operations -*- C++ -*-
// Filesystem TS operations -*- C++ -*-
// Copyright (C) 2015-2017 Free Software Foundation, Inc.
//

View File

@ -1,4 +1,4 @@
// Class filesystem::path -*- C++ -*-
// Class experimental::filesystem::path -*- C++ -*-
// Copyright (C) 2015-2017 Free Software Foundation, Inc.
//

View File

@ -0,0 +1,26 @@
// Class filesystem::directory_entry etc. -*- C++ -*-
// Copyright (C) 2015-2017 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
#define _GLIBCXX_USE_CXX11_ABI 0
#include "std-dir.cc"

View File

@ -0,0 +1,26 @@
// Filesystem operations -*- C++ -*-
// Copyright (C) 2015-2017 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
#define _GLIBCXX_USE_CXX11_ABI 0
#include "std-ops.cc"

View File

@ -0,0 +1,26 @@
// Class filesystem::path -*- C++ -*-
// Copyright (C) 2015-2017 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
#define _GLIBCXX_USE_CXX11_ABI 0
#include "std-path.cc"

View File

@ -0,0 +1,149 @@
// Filesystem directory iterator utilities -*- C++ -*-
// Copyright (C) 2014-2017 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
#ifndef _GLIBCXX_DIR_COMMON_H
#define _GLIBCXX_DIR_COMMON_H 1
#include <string.h> // strcmp
#ifdef _GLIBCXX_HAVE_DIRENT_H
# ifdef _GLIBCXX_HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
# include <dirent.h>
#else
# error "the <dirent.h> header is needed to build the Filesystem TS"
#endif
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
# undef opendir
# define opendir _wopendir
#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace filesystem
{
struct _Dir_base
{
_Dir_base(DIR* dirp = nullptr) : dirp(dirp) { }
// If no error occurs then dirp is non-null,
// otherwise null (whether error ignored or not).
_Dir_base(const char* p, bool skip_permission_denied,
error_code& ec) noexcept
: dirp(::opendir(p))
{
if (dirp)
ec.clear();
else
{
const int err = errno;
if (err == EACCES && skip_permission_denied)
ec.clear();
else
ec.assign(err, std::generic_category());
}
}
_Dir_base(_Dir_base&& d) : dirp(std::exchange(d.dirp, nullptr)) { }
_Dir_base& operator=(_Dir_base&&) = delete;
~_Dir_base() { if (dirp) ::closedir(dirp); }
const struct ::dirent*
advance(bool skip_permission_denied, error_code& ec) noexcept
{
ec.clear();
int err = std::exchange(errno, 0);
const struct ::dirent* entp = readdir(dirp);
// std::swap cannot be used with Bionic's errno
err = std::exchange(errno, err);
if (entp)
{
// skip past dot and dot-dot
if (!strcmp(entp->d_name, ".") || !strcmp(entp->d_name, ".."))
return advance(skip_permission_denied, ec);
return entp;
}
else if (err)
{
if (err == EACCES && skip_permission_denied)
return nullptr;
ec.assign(err, std::generic_category());
return nullptr;
}
else
{
// reached the end
return nullptr;
}
}
DIR* dirp;
};
} // namespace filesystem
// BEGIN/END macros must be defined before including this file.
_GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
inline file_type
get_file_type(const ::dirent& d __attribute__((__unused__)))
{
#ifdef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE
switch (d.d_type)
{
case DT_BLK:
return file_type::block;
case DT_CHR:
return file_type::character;
case DT_DIR:
return file_type::directory;
case DT_FIFO:
return file_type::fifo;
case DT_LNK:
return file_type::symlink;
case DT_REG:
return file_type::regular;
case DT_SOCK:
return file_type::socket;
case DT_UNKNOWN:
return file_type::unknown;
default:
return file_type::none;
}
#else
return file_type::none;
#endif
}
_GLIBCXX_END_NAMESPACE_FILESYSTEM
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // _GLIBCXX_DIR_COMMON_H

View File

@ -31,40 +31,76 @@
#include <stack>
#include <string.h>
#include <errno.h>
#ifdef _GLIBCXX_HAVE_DIRENT_H
# ifdef _GLIBCXX_HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
# include <dirent.h>
#else
# error "the <dirent.h> header is needed to build the Filesystem TS"
#endif
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
# undef opendir
# define opendir _wopendir
#endif
#define _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM \
namespace experimental { namespace filesystem {
#define _GLIBCXX_END_NAMESPACE_FILESYSTEM } }
#include "dir-common.h"
namespace fs = std::experimental::filesystem;
struct fs::_Dir
struct fs::_Dir : std::filesystem::_Dir_base
{
_Dir() : dirp(nullptr) { }
_Dir(const fs::path& p, bool skip_permission_denied, error_code& ec)
: _Dir_base(p.c_str(), skip_permission_denied, ec)
{
if (!ec)
path = p;
}
_Dir(DIR* dirp, const fs::path& path) : dirp(dirp), path(path) { }
_Dir(DIR* dirp, const path& p) : _Dir_base(dirp), path(p) { }
_Dir(_Dir&& d)
: dirp(std::exchange(d.dirp, nullptr)), path(std::move(d.path)),
entry(std::move(d.entry)), type(d.type)
{ }
_Dir(_Dir&&) = default;
_Dir& operator=(_Dir&&) = delete;
// Returns false when the end of the directory entries is reached.
// Reports errors by setting ec.
bool advance(bool skip_permission_denied, error_code& ec) noexcept
{
if (const auto entp = _Dir_base::advance(skip_permission_denied, ec))
{
entry = fs::directory_entry{path / entp->d_name};
type = get_file_type(*entp);
return true;
}
else if (!ec)
{
// reached the end
entry = {};
type = file_type::none;
}
return false;
}
~_Dir() { if (dirp) ::closedir(dirp); }
bool advance(error_code& ec) noexcept { return advance(false, ec); }
bool advance(std::error_code*, directory_options = directory_options::none);
// Returns false when the end of the directory entries is reached.
// Reports errors by throwing.
bool advance(bool skip_permission_denied = false)
{
error_code ec;
const bool ok = advance(skip_permission_denied, ec);
if (ec)
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"directory iterator cannot advance", ec));
return ok;
}
bool should_recurse(bool follow_symlink, error_code& ec) const
{
file_type type = this->type;
if (type == file_type::none || type == file_type::unknown)
{
type = entry.symlink_status(ec).type();
if (ec)
return false;
}
if (type == file_type::directory)
return true;
if (type == file_type::symlink)
return follow_symlink && is_directory(entry.status(ec));
return false;
}
DIR* dirp;
fs::path path;
directory_entry entry;
file_type type = file_type::none;
@ -78,119 +114,28 @@ namespace
{
return (obj & bits) != Bitmask::none;
}
// Returns {dirp, p} on success, {} on error (whether ignored or not).
inline fs::_Dir
open_dir(const fs::path& p, fs::directory_options options,
std::error_code* ec)
{
if (ec)
ec->clear();
if (DIR* dirp = ::opendir(p.c_str()))
return {dirp, p};
const int err = errno;
if (err == EACCES
&& is_set(options, fs::directory_options::skip_permission_denied))
return {};
if (!ec)
_GLIBCXX_THROW_OR_ABORT(fs::filesystem_error(
"directory iterator cannot open directory", p,
std::error_code(err, std::generic_category())));
ec->assign(err, std::generic_category());
return {};
}
inline fs::file_type
get_file_type(const ::dirent& d __attribute__((__unused__)))
{
#ifdef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE
switch (d.d_type)
{
case DT_BLK:
return fs::file_type::block;
case DT_CHR:
return fs::file_type::character;
case DT_DIR:
return fs::file_type::directory;
case DT_FIFO:
return fs::file_type::fifo;
case DT_LNK:
return fs::file_type::symlink;
case DT_REG:
return fs::file_type::regular;
case DT_SOCK:
return fs::file_type::socket;
case DT_UNKNOWN:
return fs::file_type::unknown;
default:
return fs::file_type::none;
}
#else
return fs::file_type::none;
#endif
}
}
// Returns false when the end of the directory entries is reached.
// Reports errors by setting ec or throwing.
bool
fs::_Dir::advance(error_code* ec, directory_options options)
{
if (ec)
ec->clear();
int err = std::exchange(errno, 0);
const auto entp = readdir(dirp);
// std::swap cannot be used with Bionic's errno
err = std::exchange(errno, err);
if (entp)
{
// skip past dot and dot-dot
if (!strcmp(entp->d_name, ".") || !strcmp(entp->d_name, ".."))
return advance(ec, options);
entry = fs::directory_entry{path / entp->d_name};
type = get_file_type(*entp);
return true;
}
else if (err)
{
if (err == EACCES
&& is_set(options, directory_options::skip_permission_denied))
return false;
if (!ec)
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"directory iterator cannot advance",
std::error_code(err, std::generic_category())));
ec->assign(err, std::generic_category());
return false;
}
else
{
// reached the end
entry = {};
type = fs::file_type::none;
return false;
}
}
fs::directory_iterator::
directory_iterator(const path& p, directory_options options, error_code* ec)
directory_iterator(const path& p, directory_options options, error_code* ecptr)
{
_Dir dir = open_dir(p, options, ec);
const bool skip_permission_denied
= is_set(options, directory_options::skip_permission_denied);
error_code ec;
_Dir dir(p, skip_permission_denied, ec);
if (dir.dirp)
{
auto sp = std::make_shared<fs::_Dir>(std::move(dir));
if (sp->advance(ec, options))
if (sp->advance(skip_permission_denied, ec))
_M_dir.swap(sp);
}
if (ecptr)
*ecptr = ec;
else if (ec)
_GLIBCXX_THROW_OR_ABORT(fs::filesystem_error(
"directory iterator cannot open directory", p, ec));
}
const fs::directory_entry&
@ -210,7 +155,7 @@ fs::directory_iterator::operator++()
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"cannot advance non-dereferenceable directory iterator",
std::make_error_code(errc::invalid_argument)));
if (!_M_dir->advance(nullptr))
if (!_M_dir->advance())
_M_dir.reset();
return *this;
}
@ -223,13 +168,11 @@ fs::directory_iterator::increment(error_code& ec) noexcept
ec = std::make_error_code(errc::invalid_argument);
return *this;
}
if (!_M_dir->advance(&ec))
if (!_M_dir->advance(ec))
_M_dir.reset();
return *this;
}
using Dir_iter_pair = std::pair<fs::_Dir, fs::directory_iterator>;
struct fs::recursive_directory_iterator::_Dir_stack : std::stack<_Dir>
{
void clear() { c.clear(); }
@ -240,6 +183,8 @@ recursive_directory_iterator(const path& p, directory_options options,
error_code* ec)
: _M_options(options), _M_pending(true)
{
if (ec)
ec->clear();
if (DIR* dirp = ::opendir(p.c_str()))
{
auto sp = std::make_shared<_Dir_stack>();
@ -252,11 +197,7 @@ recursive_directory_iterator(const path& p, directory_options options,
const int err = errno;
if (err == EACCES
&& is_set(options, fs::directory_options::skip_permission_denied))
{
if (ec)
ec->clear();
return;
}
return;
if (!ec)
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
@ -300,35 +241,6 @@ fs::recursive_directory_iterator::operator++()
return *this;
}
namespace
{
bool
recurse(const fs::_Dir& d, fs::directory_options options, std::error_code& ec)
{
bool follow_symlink
= is_set(options, fs::directory_options::follow_directory_symlink);
#ifdef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE
if (d.type == fs::file_type::directory)
return true;
if (d.type == fs::file_type::symlink && follow_symlink)
return d.entry.status().type() == fs::file_type::directory;
if (d.type != fs::file_type::none && d.type != fs::file_type::unknown)
return false;
#endif
const fs::path& path = d.entry.path();
auto type = fs::symlink_status(path, ec).type();
if (ec.value())
return false;
if (type == fs::file_type::symlink)
{
if (!follow_symlink)
return false;
type = fs::status(path, ec).type();
}
return type == fs::file_type::directory;
}
}
fs::recursive_directory_iterator&
fs::recursive_directory_iterator::increment(error_code& ec) noexcept
{
@ -338,11 +250,16 @@ fs::recursive_directory_iterator::increment(error_code& ec) noexcept
return *this;
}
const bool follow
= is_set(_M_options, directory_options::follow_directory_symlink);
const bool skip_permission_denied
= is_set(_M_options, directory_options::skip_permission_denied);
auto& top = _M_dirs->top();
if (std::exchange(_M_pending, true) && recurse(top, _M_options, ec))
if (std::exchange(_M_pending, true) && top.should_recurse(follow, ec))
{
_Dir dir = open_dir(top.entry.path(), _M_options, &ec);
_Dir dir(top.entry.path(), skip_permission_denied, ec);
if (ec)
{
_M_dirs.reset();
@ -352,7 +269,7 @@ fs::recursive_directory_iterator::increment(error_code& ec) noexcept
_M_dirs->push(std::move(dir));
}
while (!_M_dirs->top().advance(&ec, _M_options) && !ec)
while (!_M_dirs->top().advance(skip_permission_denied, ec) && !ec)
{
_M_dirs->pop();
if (_M_dirs->empty())
@ -373,6 +290,9 @@ fs::recursive_directory_iterator::pop(error_code& ec)
return;
}
const bool skip_permission_denied
= is_set(_M_options, directory_options::skip_permission_denied);
do {
_M_dirs->pop();
if (_M_dirs->empty())
@ -381,7 +301,7 @@ fs::recursive_directory_iterator::pop(error_code& ec)
ec.clear();
return;
}
} while (!_M_dirs->top().advance(&ec, _M_options));
} while (!_M_dirs->top().advance(skip_permission_denied, ec));
}
void

View File

@ -0,0 +1,148 @@
// Filesystem operation utilities -*- C++ -*-
// Copyright (C) 2014-2017 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
#ifndef _GLIBCXX_OPS_COMMON_H
#define _GLIBCXX_OPS_COMMON_H 1
#include <chrono>
#ifdef _GLIBCXX_HAVE_UNISTD_H
# include <unistd.h>
# if defined(_GLIBCXX_HAVE_SYS_STAT_H) && defined(_GLIBCXX_HAVE_SYS_TYPES_H)
# include <sys/types.h>
# include <sys/stat.h>
# endif
#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace filesystem
{
template<typename Bitmask>
inline bool is_set(Bitmask obj, Bitmask bits)
{
return (obj & bits) != Bitmask::none;
}
inline bool
is_not_found_errno(int err) noexcept
{
return err == ENOENT || err == ENOTDIR;
}
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
typedef struct ::stat stat_type;
inline std::chrono::system_clock::time_point
file_time(const stat_type& st, std::error_code& ec) noexcept
{
using namespace std::chrono;
#ifdef _GLIBCXX_USE_ST_MTIM
time_t s = st.st_mtim.tv_sec;
nanoseconds ns{st.st_mtim.tv_nsec};
#else
time_t s = st.st_mtime;
nanoseconds ns{};
#endif
if (s >= (nanoseconds::max().count() / 1e9))
{
ec = std::make_error_code(std::errc::value_too_large); // EOVERFLOW
return system_clock::time_point::min();
}
ec.clear();
return system_clock::time_point{seconds{s} + ns};
}
struct copy_options_existing_file
{
bool skip, update, overwrite;
};
bool
do_copy_file(const char* from, const char* to,
copy_options_existing_file options,
stat_type* from_st, stat_type* to_st,
std::error_code& ec) noexcept;
#endif // _GLIBCXX_HAVE_SYS_STAT_H
} // namespace filesystem
// BEGIN/END macros must be defined before including this file.
_GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
typedef struct ::stat stat_type;
inline file_type
make_file_type(const stat_type& st) noexcept
{
#ifdef _GLIBCXX_HAVE_S_ISREG
if (S_ISREG(st.st_mode))
return file_type::regular;
else if (S_ISDIR(st.st_mode))
return file_type::directory;
else if (S_ISCHR(st.st_mode))
return file_type::character;
else if (S_ISBLK(st.st_mode))
return file_type::block;
else if (S_ISFIFO(st.st_mode))
return file_type::fifo;
else if (S_ISLNK(st.st_mode))
return file_type::symlink;
else if (S_ISSOCK(st.st_mode))
return file_type::socket;
#endif
return file_type::unknown;
}
inline file_status
make_file_status(const stat_type& st) noexcept
{
return file_status{
make_file_type(st),
static_cast<perms>(st.st_mode) & perms::mask
};
}
inline std::filesystem::copy_options_existing_file
copy_file_options(copy_options opt)
{
using std::filesystem::is_set;
return {
is_set(opt, copy_options::skip_existing),
is_set(opt, copy_options::update_existing),
is_set(opt, copy_options::overwrite_existing)
};
}
#endif // _GLIBCXX_HAVE_SYS_STAT_H
_GLIBCXX_END_NAMESPACE_FILESYSTEM
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // _GLIBCXX_OPS_COMMON_H

View File

@ -1,4 +1,4 @@
// Filesystem operations -*- C++ -*-
// Filesystem TS operations -*- C++ -*-
// Copyright (C) 2014-2017 Free Software Foundation, Inc.
//
@ -35,26 +35,24 @@
#include <stdio.h>
#include <errno.h>
#include <limits.h> // PATH_MAX
#ifdef _GLIBCXX_HAVE_UNISTD_H
# include <unistd.h>
# if defined(_GLIBCXX_HAVE_SYS_STAT_H) && defined(_GLIBCXX_HAVE_SYS_TYPES_H)
# include <sys/types.h>
# include <sys/stat.h>
# endif
#endif
#ifdef _GLIBCXX_HAVE_FCNTL_H
# include <fcntl.h>
# include <fcntl.h> // AT_FDCWD, AT_SYMLINK_NOFOLLOW
#endif
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
# include <sys/stat.h> // stat, utimensat, fchmodat
#endif
#ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
# include <sys/statvfs.h>
# include <sys/statvfs.h> // statvfs
#endif
#ifdef _GLIBCXX_USE_SENDFILE
# include <sys/sendfile.h>
#endif
#if _GLIBCXX_HAVE_UTIME_H
# include <utime.h>
#if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
# include <utime.h> // utime
#endif
#define _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM \
namespace experimental { namespace filesystem {
#define _GLIBCXX_END_NAMESPACE_FILESYSTEM } }
#include "ops-common.h"
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
# undef utime
# define utime _wutime
@ -240,254 +238,16 @@ fs::copy(const path& from, const path& to, copy_options options)
namespace
{
template<typename Bitmask>
inline bool is_set(Bitmask obj, Bitmask bits)
{
return (obj & bits) != Bitmask::none;
}
}
using std::filesystem::is_set;
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
namespace
{
typedef struct ::stat stat_type;
inline fs::file_type
make_file_type(const stat_type& st) noexcept
{
using fs::file_type;
#ifdef _GLIBCXX_HAVE_S_ISREG
if (S_ISREG(st.st_mode))
return file_type::regular;
else if (S_ISDIR(st.st_mode))
return file_type::directory;
else if (S_ISCHR(st.st_mode))
return file_type::character;
else if (S_ISBLK(st.st_mode))
return file_type::block;
else if (S_ISFIFO(st.st_mode))
return file_type::fifo;
else if (S_ISLNK(st.st_mode))
return file_type::symlink;
else if (S_ISSOCK(st.st_mode))
return file_type::socket;
#endif
return file_type::unknown;
}
inline fs::file_status
make_file_status(const stat_type& st) noexcept
{
return fs::file_status{
make_file_type(st),
static_cast<fs::perms>(st.st_mode) & fs::perms::mask
};
}
inline bool
is_not_found_errno(int err) noexcept
{
return err == ENOENT || err == ENOTDIR;
}
inline fs::file_time_type
file_time(const stat_type& st, std::error_code& ec) noexcept
{
using namespace std::chrono;
#ifdef _GLIBCXX_USE_ST_MTIM
time_t s = st.st_mtim.tv_sec;
nanoseconds ns{st.st_mtim.tv_nsec};
#else
time_t s = st.st_mtime;
nanoseconds ns{};
#endif
if (s >= (nanoseconds::max().count() / 1e9))
{
ec = std::make_error_code(std::errc::value_too_large); // EOVERFLOW
return fs::file_time_type::min();
}
ec.clear();
return fs::file_time_type{seconds{s} + ns};
}
bool
do_copy_file(const fs::path& from, const fs::path& to,
fs::copy_options option,
stat_type* from_st, stat_type* to_st,
std::error_code& ec) noexcept
{
stat_type st1, st2;
fs::file_status t, f;
if (to_st == nullptr)
{
if (::stat(to.c_str(), &st1))
{
int err = errno;
if (!is_not_found_errno(err))
{
ec.assign(err, std::generic_category());
return false;
}
}
else
to_st = &st1;
}
else if (to_st == from_st)
to_st = nullptr;
if (to_st == nullptr)
t = fs::file_status{fs::file_type::not_found};
else
t = make_file_status(*to_st);
if (from_st == nullptr)
{
if (::stat(from.c_str(), &st2))
{
ec.assign(errno, std::generic_category());
return false;
}
else
from_st = &st2;
}
f = make_file_status(*from_st);
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2712. copy_file() has a number of unspecified error conditions
if (!is_regular_file(f))
{
ec = std::make_error_code(std::errc::not_supported);
return false;
}
using opts = fs::copy_options;
if (exists(t))
{
if (!is_regular_file(t))
{
ec = std::make_error_code(std::errc::not_supported);
return false;
}
if (to_st->st_dev == from_st->st_dev
&& to_st->st_ino == from_st->st_ino)
{
ec = std::make_error_code(std::errc::file_exists);
return false;
}
if (is_set(option, opts::skip_existing))
{
ec.clear();
return false;
}
else if (is_set(option, opts::update_existing))
{
const auto from_mtime = file_time(*from_st, ec);
if (ec)
return false;
if ((from_mtime <= file_time(*to_st, ec)) || ec)
return false;
}
else if (!is_set(option, opts::overwrite_existing))
{
ec = std::make_error_code(std::errc::file_exists);
return false;
}
else if (!is_regular_file(t))
{
ec = std::make_error_code(std::errc::not_supported);
return false;
}
}
struct CloseFD {
~CloseFD() { if (fd != -1) ::close(fd); }
bool close() { return ::close(std::exchange(fd, -1)) == 0; }
int fd;
};
CloseFD in = { ::open(from.c_str(), O_RDONLY) };
if (in.fd == -1)
{
ec.assign(errno, std::generic_category());
return false;
}
int oflag = O_WRONLY|O_CREAT;
if (is_set(option, opts::overwrite_existing|opts::update_existing))
oflag |= O_TRUNC;
else
oflag |= O_EXCL;
CloseFD out = { ::open(to.c_str(), oflag, S_IWUSR) };
if (out.fd == -1)
{
if (errno == EEXIST && is_set(option, opts::skip_existing))
ec.clear();
else
ec.assign(errno, std::generic_category());
return false;
}
#ifdef _GLIBCXX_USE_FCHMOD
if (::fchmod(out.fd, from_st->st_mode))
#elif defined _GLIBCXX_USE_FCHMODAT
if (::fchmodat(AT_FDCWD, to.c_str(), from_st->st_mode, 0))
#else
if (::chmod(to.c_str(), from_st->st_mode))
#endif
{
ec.assign(errno, std::generic_category());
return false;
}
#ifdef _GLIBCXX_USE_SENDFILE
off_t offset = 0;
const auto n = ::sendfile(out.fd, in.fd, &offset, from_st->st_size);
if (n < 0 && (errno == ENOSYS || errno == EINVAL))
{
#endif
__gnu_cxx::stdio_filebuf<char> sbin(in.fd, std::ios::in);
__gnu_cxx::stdio_filebuf<char> sbout(out.fd, std::ios::out);
if (sbin.is_open())
in.fd = -1;
if (sbout.is_open())
out.fd = -1;
if (from_st->st_size && !(std::ostream(&sbout) << &sbin))
{
ec = std::make_error_code(std::errc::io_error);
return false;
}
if (!sbout.close() || !sbin.close())
{
ec.assign(errno, std::generic_category());
return false;
}
ec.clear();
return true;
#ifdef _GLIBCXX_USE_SENDFILE
}
if (n != from_st->st_size)
{
ec.assign(errno, std::generic_category());
return false;
}
if (!out.close() || !in.close())
{
ec.assign(errno, std::generic_category());
return false;
}
ec.clear();
return true;
#endif
}
}
#endif
using std::filesystem::is_not_found_errno;
using std::filesystem::file_time;
using std::filesystem::do_copy_file;
#endif // _GLIBCXX_HAVE_SYS_STAT_H
} // namespace
void
fs::copy(const path& from, const path& to, copy_options options,
@ -561,11 +321,13 @@ fs::copy(const path& from, const path& to, copy_options options,
else if (is_set(options, copy_options::create_hard_links))
create_hard_link(from, to, ec);
else if (is_directory(t))
do_copy_file(from, to / from.filename(), options, &from_st, 0, ec);
do_copy_file(from.c_str(), (to / from.filename()).c_str(),
copy_file_options(options), &from_st, nullptr, ec);
else
{
auto ptr = exists(t) ? &to_st : &from_st;
do_copy_file(from, to, options, &from_st, ptr, ec);
do_copy_file(from.c_str(), to.c_str(), copy_file_options(options),
&from_st, ptr, ec);
}
}
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@ -602,11 +364,12 @@ fs::copy_file(const path& from, const path& to, copy_options option)
}
bool
fs::copy_file(const path& from, const path& to, copy_options option,
fs::copy_file(const path& from, const path& to, copy_options options,
error_code& ec) noexcept
{
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
return do_copy_file(from, to, option, nullptr, nullptr, ec);
return do_copy_file(from.c_str(), to.c_str(), copy_file_options(options),
nullptr, nullptr, ec);
#else
ec = std::make_error_code(std::errc::not_supported);
return false;

View File

@ -1,4 +1,4 @@
// Class filesystem::path -*- C++ -*-
// Class experimental::filesystem::path -*- C++ -*-
// Copyright (C) 2014-2017 Free Software Foundation, Inc.
//
@ -28,9 +28,10 @@
#include <experimental/filesystem>
using std::experimental::filesystem::path;
namespace fs = std::experimental::filesystem;
using fs::path;
std::experimental::filesystem::filesystem_error::~filesystem_error() = default;
fs::filesystem_error::~filesystem_error() = default;
constexpr path::value_type path::preferred_separator;
@ -461,7 +462,7 @@ path::_S_convert_loc(const char* __first, const char* __last,
}
std::size_t
std::experimental::filesystem::hash_value(const path& p) noexcept
fs::hash_value(const path& p) noexcept
{
// [path.non-member]
// "If for two paths, p1 == p2 then hash_value(p1) == hash_value(p2)."
@ -477,3 +478,29 @@ std::experimental::filesystem::hash_value(const path& p) noexcept
}
return seed;
}
namespace std
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace filesystem
{
extern string
fs_err_concat(const string& __what, const string& __path1,
const string& __path2);
} // namespace filesystem
namespace experimental::filesystem::v1 {
_GLIBCXX_BEGIN_NAMESPACE_CXX11
std::string filesystem_error::_M_gen_what()
{
using std::filesystem::fs_err_concat;
return fs_err_concat(system_error::what(), _M_path1.native(),
_M_path2.native());
}
_GLIBCXX_END_NAMESPACE_CXX11
} // namespace experimental::filesystem::v1
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std

View File

@ -0,0 +1,318 @@
// Class filesystem::directory_entry etc. -*- C++ -*-
// Copyright (C) 2014-2017 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
#ifndef _GLIBCXX_USE_CXX11_ABI
# define _GLIBCXX_USE_CXX11_ABI 1
#endif
#include <filesystem>
#include <experimental/filesystem>
#include <utility>
#include <stack>
#include <string.h>
#include <errno.h>
#define _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM namespace filesystem {
#define _GLIBCXX_END_NAMESPACE_FILESYSTEM }
#include "dir-common.h"
namespace fs = std::filesystem;
struct fs::_Dir : _Dir_base
{
_Dir(const fs::path& p, bool skip_permission_denied, error_code& ec)
: _Dir_base(p.c_str(), skip_permission_denied, ec)
{
if (!ec)
path = p;
}
_Dir(DIR* dirp, const path& p) : _Dir_base(dirp), path(p) { }
_Dir(_Dir&&) = default;
// Returns false when the end of the directory entries is reached.
// Reports errors by setting ec.
bool advance(bool skip_permission_denied, error_code& ec) noexcept
{
if (const auto entp = _Dir_base::advance(skip_permission_denied, ec))
{
entry = fs::directory_entry{path / entp->d_name, get_file_type(*entp)};
return true;
}
else if (!ec)
{
// reached the end
entry = {};
}
return false;
}
bool advance(error_code& ec) noexcept { return advance(false, ec); }
// Returns false when the end of the directory entries is reached.
// Reports errors by throwing.
bool advance(bool skip_permission_denied = false)
{
error_code ec;
const bool ok = advance(skip_permission_denied, ec);
if (ec)
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"directory iterator cannot advance", ec));
return ok;
}
bool should_recurse(bool follow_symlink, error_code& ec) const
{
file_type type = entry._M_type;
if (type == file_type::none || type == file_type::unknown)
{
type = entry.symlink_status(ec).type();
if (ec)
return false;
}
if (type == file_type::directory)
return true;
if (type == file_type::symlink)
return follow_symlink && is_directory(entry.status(ec));
return false;
}
fs::path path;
directory_entry entry;
};
namespace
{
template<typename Bitmask>
inline bool
is_set(Bitmask obj, Bitmask bits)
{
return (obj & bits) != Bitmask::none;
}
}
fs::directory_iterator::
directory_iterator(const path& p, directory_options options, error_code* ecptr)
{
const bool skip_permission_denied
= is_set(options, directory_options::skip_permission_denied);
error_code ec;
_Dir dir(p, skip_permission_denied, ec);
if (dir.dirp)
{
auto sp = std::make_shared<fs::_Dir>(std::move(dir));
if (sp->advance(skip_permission_denied, ec))
_M_dir.swap(sp);
}
if (ecptr)
*ecptr = ec;
else if (ec)
_GLIBCXX_THROW_OR_ABORT(fs::filesystem_error(
"directory iterator cannot open directory", p, ec));
}
const fs::directory_entry&
fs::directory_iterator::operator*() const
{
if (!_M_dir)
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"non-dereferenceable directory iterator",
std::make_error_code(errc::invalid_argument)));
return _M_dir->entry;
}
fs::directory_iterator&
fs::directory_iterator::operator++()
{
if (!_M_dir)
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"cannot advance non-dereferenceable directory iterator",
std::make_error_code(errc::invalid_argument)));
if (!_M_dir->advance())
_M_dir.reset();
return *this;
}
fs::directory_iterator&
fs::directory_iterator::increment(error_code& ec) noexcept
{
if (!_M_dir)
{
ec = std::make_error_code(errc::invalid_argument);
return *this;
}
if (!_M_dir->advance(ec))
_M_dir.reset();
return *this;
}
struct fs::recursive_directory_iterator::_Dir_stack : std::stack<_Dir>
{
void clear() { c.clear(); }
};
fs::recursive_directory_iterator::
recursive_directory_iterator(const path& p, directory_options options,
error_code* ecptr)
: _M_options(options), _M_pending(true)
{
if (DIR* dirp = ::opendir(p.c_str()))
{
if (ecptr)
ecptr->clear();
auto sp = std::make_shared<_Dir_stack>();
sp->push(_Dir{ dirp, p });
if (ecptr ? sp->top().advance(*ecptr) : sp->top().advance())
_M_dirs.swap(sp);
}
else
{
const int err = errno;
if (err == EACCES
&& is_set(options, fs::directory_options::skip_permission_denied))
{
if (ecptr)
ecptr->clear();
return;
}
if (!ecptr)
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"recursive directory iterator cannot open directory", p,
std::error_code(err, std::generic_category())));
ecptr->assign(err, std::generic_category());
}
}
fs::recursive_directory_iterator::~recursive_directory_iterator() = default;
int
fs::recursive_directory_iterator::depth() const
{
return int(_M_dirs->size()) - 1;
}
const fs::directory_entry&
fs::recursive_directory_iterator::operator*() const
{
return _M_dirs->top().entry;
}
fs::recursive_directory_iterator&
fs::recursive_directory_iterator::
operator=(const recursive_directory_iterator& other) noexcept = default;
fs::recursive_directory_iterator&
fs::recursive_directory_iterator::
operator=(recursive_directory_iterator&& other) noexcept = default;
fs::recursive_directory_iterator&
fs::recursive_directory_iterator::operator++()
{
error_code ec;
increment(ec);
if (ec)
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"cannot increment recursive directory iterator", ec));
return *this;
}
fs::recursive_directory_iterator&
fs::recursive_directory_iterator::increment(error_code& ec) noexcept
{
if (!_M_dirs)
{
ec = std::make_error_code(errc::invalid_argument);
return *this;
}
const bool follow
= is_set(_M_options, directory_options::follow_directory_symlink);
const bool skip_permission_denied
= is_set(_M_options, directory_options::skip_permission_denied);
auto& top = _M_dirs->top();
if (std::exchange(_M_pending, true) && top.should_recurse(follow, ec))
{
_Dir dir(top.entry.path(), skip_permission_denied, ec);
if (ec)
{
_M_dirs.reset();
return *this;
}
if (dir.dirp)
_M_dirs->push(std::move(dir));
}
while (!_M_dirs->top().advance(skip_permission_denied, ec) && !ec)
{
_M_dirs->pop();
if (_M_dirs->empty())
{
_M_dirs.reset();
return *this;
}
}
return *this;
}
void
fs::recursive_directory_iterator::pop(error_code& ec)
{
if (!_M_dirs)
{
ec = std::make_error_code(errc::invalid_argument);
return;
}
const bool skip_permission_denied
= is_set(_M_options, directory_options::skip_permission_denied);
do {
_M_dirs->pop();
if (_M_dirs->empty())
{
_M_dirs.reset();
ec.clear();
return;
}
} while (!_M_dirs->top().advance(skip_permission_denied, ec));
}
void
fs::recursive_directory_iterator::pop()
{
error_code ec;
pop(ec);
if (ec)
_GLIBCXX_THROW_OR_ABORT(filesystem_error(_M_dirs
? "recursive directory iterator cannot pop"
: "non-dereferenceable recursive directory iterator cannot pop",
ec));
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,688 @@
// Class filesystem::path -*- C++ -*-
// Copyright (C) 2014-2017 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
#ifndef _GLIBCXX_USE_CXX11_ABI
# define _GLIBCXX_USE_CXX11_ABI 1
#endif
#include <filesystem>
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
# include <algorithm>
#endif
namespace fs = std::filesystem;
using fs::path;
fs::filesystem_error::~filesystem_error() = default;
constexpr path::value_type path::preferred_separator;
path&
path::remove_filename()
{
if (_M_type == _Type::_Multi)
{
if (!_M_cmpts.empty())
{
auto cmpt = std::prev(_M_cmpts.end());
if (cmpt->_M_type == _Type::_Filename && !cmpt->empty())
{
_M_pathname.erase(cmpt->_M_pos);
auto prev = std::prev(cmpt);
if (prev->_M_type == _Type::_Root_dir
|| prev->_M_type == _Type::_Root_name)
{
_M_cmpts.erase(cmpt);
_M_trim();
}
else
cmpt->clear();
}
}
}
else if (_M_type == _Type::_Filename)
clear();
if (!empty() && _M_pathname.back() != '/')
throw 1;
return *this;
}
path&
path::replace_filename(const path& replacement)
{
remove_filename();
operator/=(replacement);
return *this;
}
path&
path::replace_extension(const path& replacement)
{
auto ext = _M_find_extension();
// Any existing extension() is removed
if (ext.first && ext.second != string_type::npos)
{
if (ext.first == &_M_pathname)
_M_pathname.erase(ext.second);
else
{
const auto& back = _M_cmpts.back();
if (ext.first != &back._M_pathname)
_GLIBCXX_THROW_OR_ABORT(
std::logic_error("path::replace_extension failed"));
_M_pathname.erase(back._M_pos + ext.second);
}
}
// If replacement is not empty and does not begin with a dot character,
// a dot character is appended
if (!replacement.empty() && replacement.native()[0] != '.')
_M_pathname += '.';
operator+=(replacement);
return *this;
}
namespace
{
template<typename Iter1, typename Iter2>
int do_compare(Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2)
{
int cmpt = 1;
while (begin1 != end1 && begin2 != end2)
{
if (begin1->native() < begin2->native())
return -cmpt;
if (begin1->native() > begin2->native())
return +cmpt;
++begin1;
++begin2;
++cmpt;
}
if (begin1 == end1)
{
if (begin2 == end2)
return 0;
return -cmpt;
}
return +cmpt;
}
}
int
path::compare(const path& p) const noexcept
{
struct CmptRef
{
const path* ptr;
const string_type& native() const noexcept { return ptr->native(); }
};
if (empty() && p.empty())
return 0;
else if (_M_type == _Type::_Multi && p._M_type == _Type::_Multi)
return do_compare(_M_cmpts.begin(), _M_cmpts.end(),
p._M_cmpts.begin(), p._M_cmpts.end());
else if (_M_type == _Type::_Multi)
{
CmptRef c[1] = { { &p } };
return do_compare(_M_cmpts.begin(), _M_cmpts.end(), c, c+1);
}
else if (p._M_type == _Type::_Multi)
{
CmptRef c[1] = { { this } };
return do_compare(c, c+1, p._M_cmpts.begin(), p._M_cmpts.end());
}
else
return _M_pathname.compare(p._M_pathname);
}
path
path::root_name() const
{
path __ret;
if (_M_type == _Type::_Root_name)
__ret = *this;
else if (_M_cmpts.size() && _M_cmpts.begin()->_M_type == _Type::_Root_name)
__ret = *_M_cmpts.begin();
return __ret;
}
path
path::root_directory() const
{
path __ret;
if (_M_type == _Type::_Root_dir)
{
__ret._M_type = _Type::_Root_dir;
__ret._M_pathname.assign(1, preferred_separator);
}
else if (!_M_cmpts.empty())
{
auto __it = _M_cmpts.begin();
if (__it->_M_type == _Type::_Root_name)
++__it;
if (__it != _M_cmpts.end() && __it->_M_type == _Type::_Root_dir)
__ret = *__it;
}
return __ret;
}
path
path::root_path() const
{
path __ret;
if (_M_type == _Type::_Root_name)
__ret = *this;
else if (_M_type == _Type::_Root_dir)
{
__ret._M_pathname.assign(1, preferred_separator);
__ret._M_type = _Type::_Root_dir;
}
else if (!_M_cmpts.empty())
{
auto __it = _M_cmpts.begin();
if (__it->_M_type == _Type::_Root_name)
{
__ret = *__it++;
if (__it != _M_cmpts.end() && __it->_M_type == _Type::_Root_dir)
__ret /= *__it;
}
else if (__it->_M_type == _Type::_Root_dir)
__ret = *__it;
}
return __ret;
}
path
path::relative_path() const
{
path __ret;
if (_M_type == _Type::_Filename)
__ret = *this;
else if (!_M_cmpts.empty())
{
auto __it = _M_cmpts.begin();
if (__it->_M_type == _Type::_Root_name)
++__it;
if (__it != _M_cmpts.end() && __it->_M_type == _Type::_Root_dir)
++__it;
if (__it != _M_cmpts.end())
__ret.assign(_M_pathname.substr(__it->_M_pos));
}
return __ret;
}
path
path::parent_path() const
{
path __ret;
if (!has_relative_path())
__ret = *this;
else if (_M_cmpts.size() >= 2)
{
for (auto __it = _M_cmpts.begin(), __end = std::prev(_M_cmpts.end());
__it != __end; ++__it)
{
__ret /= *__it;
}
}
return __ret;
}
bool
path::has_root_name() const
{
if (_M_type == _Type::_Root_name)
return true;
if (!_M_cmpts.empty() && _M_cmpts.begin()->_M_type == _Type::_Root_name)
return true;
return false;
}
bool
path::has_root_directory() const
{
if (_M_type == _Type::_Root_dir)
return true;
if (!_M_cmpts.empty())
{
auto __it = _M_cmpts.begin();
if (__it->_M_type == _Type::_Root_name)
++__it;
if (__it != _M_cmpts.end() && __it->_M_type == _Type::_Root_dir)
return true;
}
return false;
}
bool
path::has_root_path() const
{
if (_M_type == _Type::_Root_name || _M_type == _Type::_Root_dir)
return true;
if (!_M_cmpts.empty())
{
auto __type = _M_cmpts.front()._M_type;
if (__type == _Type::_Root_name || __type == _Type::_Root_dir)
return true;
}
return false;
}
bool
path::has_relative_path() const
{
if (_M_type == _Type::_Filename)
return true;
if (!_M_cmpts.empty())
{
auto __it = _M_cmpts.begin();
if (__it->_M_type == _Type::_Root_name)
++__it;
if (__it != _M_cmpts.end() && __it->_M_type == _Type::_Root_dir)
++__it;
if (__it != _M_cmpts.end())
return true;
}
return false;
}
bool
path::has_parent_path() const
{
if (!has_relative_path())
return !empty();
return _M_cmpts.size() >= 2;
}
bool
path::has_filename() const
{
if (empty())
return false;
if (_M_type == _Type::_Filename)
return !_M_pathname.empty();
if (_M_type == _Type::_Multi)
{
if (_M_pathname.back() == preferred_separator)
return false;
return _M_cmpts.back().has_filename();
}
return false;
}
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]);
}
} // namespace
path
path::lexically_normal() const
{
/*
C++17 [fs.path.generic] p6
- If the path is empty, stop.
- Replace each slash character in the root-name with a preferred-separator.
- Replace each directory-separator with a preferred-separator.
- Remove each dot filename and any immediately following directory-separator.
- As long as any appear, remove a non-dot-dot filename immediately followed
by a directory-separator and a dot-dot filename, along with any immediately
following directory-separator.
- If the last filename is dot-dot, remove any trailing directory-separator.
- If the path is empty, add a dot.
*/
path ret;
// If the path is empty, stop.
if (empty())
return ret;
for (auto& p : *this)
{
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
// Replace each slash character in the root-name
if (p.is_root_name())
{
string_type s = p.native();
std::replace(s.begin(), s.end(), L'/', L'\\');
ret /= s;
continue;
}
#endif
if (is_dotdot(p))
{
if (ret.has_filename() && !is_dotdot(ret.filename()))
ret.remove_filename();
else
ret /= p;
}
else if (is_dot(p))
ret /= path();
else
ret /= p;
}
if (ret._M_cmpts.size() >= 2)
{
auto back = std::prev(ret.end());
// If the last filename is dot-dot, ...
if (back->empty() && is_dotdot(*std::prev(back)))
// ... remove any trailing directory-separator.
ret = ret.parent_path();
}
// If the path is empty, add a dot.
else if (ret.empty())
ret = ".";
return ret;
}
path
path::lexically_relative(const path& base) const
{
path ret;
if (root_name() != base.root_name())
return ret;
if (is_absolute() != base.is_absolute())
return ret;
if (!has_root_directory() && base.has_root_directory())
return ret;
auto [a, b] = std::mismatch(begin(), end(), base.begin(), base.end());
if (a == end() && b == base.end())
ret = ".";
else
{
int n = 0;
for (; b != base.end(); ++b)
{
const path& p = *b;
if (is_dotdot(p))
--n;
else if (!is_dot(p))
++n;
}
if (n >= 0)
{
const path dotdot("..");
while (n--)
ret /= dotdot;
for (; a != end(); ++a)
ret /= *a;
}
}
return ret;
}
path
path::lexically_proximate(const path& base) const
{
path rel = lexically_relative(base);
if (rel.empty())
rel = *this;
return rel;
}
std::pair<const path::string_type*, std::size_t>
path::_M_find_extension() const
{
const std::string* s = nullptr;
if (_M_type == _Type::_Filename)
s = &_M_pathname;
else if (_M_type == _Type::_Multi && !_M_cmpts.empty())
{
const auto& c = _M_cmpts.back();
if (c._M_type == _Type::_Filename)
s = &c._M_pathname;
}
if (s)
{
if (auto sz = s->size())
{
if (sz <= 2 && (*s)[0] == '.')
return { s, string_type::npos };
const auto pos = s->rfind('.');
return { s, pos ? pos : string_type::npos };
}
}
return {};
}
void
path::_M_split_cmpts()
{
_M_type = _Type::_Multi;
_M_cmpts.clear();
if (_M_pathname.empty())
return;
size_t pos = 0;
const size_t len = _M_pathname.size();
// look for root name or root directory
if (_S_is_dir_sep(_M_pathname[0]))
{
#ifdef __CYGWIN__
// look for root name, such as "//foo"
if (len > 2 && _M_pathname[1] == _M_pathname[0])
{
if (!_S_is_dir_sep(_M_pathname[2]))
{
// got root name, find its end
pos = 3;
while (pos < len && !_S_is_dir_sep(_M_pathname[pos]))
++pos;
_M_add_root_name(pos);
if (pos < len) // also got root directory
_M_add_root_dir(pos);
}
else
{
// got something like "///foo" which is just a root directory
// composed of multiple redundant directory separators
_M_add_root_dir(0);
}
}
else
#endif
{
// got root directory
if (_M_pathname.find_first_not_of('/') == string_type::npos)
{
// entire path is just slashes
_M_type = _Type::_Root_dir;
return;
}
_M_add_root_dir(0);
++pos;
}
}
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
else if (len > 1 && _M_pathname[1] == L':')
{
// got disk designator
_M_add_root_name(2);
if (len > 2 && _S_is_dir_sep(_M_pathname[2]))
_M_add_root_dir(2);
pos = 2;
}
#endif
size_t back = pos;
while (pos < len)
{
if (_S_is_dir_sep(_M_pathname[pos]))
{
if (back != pos)
_M_add_filename(back, pos - back);
back = ++pos;
}
else
++pos;
}
if (back != pos)
_M_add_filename(back, pos - back);
else if (_S_is_dir_sep(_M_pathname.back()))
{
// [fs.path.itr]/4
// An empty element, if trailing non-root directory-separator present.
if (_M_cmpts.back()._M_type == _Type::_Filename)
{
const auto& last = _M_cmpts.back();
pos = last._M_pos + last._M_pathname.size();
_M_cmpts.emplace_back(string_type(), _Type::_Filename, pos);
}
}
_M_trim();
}
void
path::_M_add_root_name(size_t n)
{
_M_cmpts.emplace_back(_M_pathname.substr(0, n), _Type::_Root_name, 0);
}
void
path::_M_add_root_dir(size_t pos)
{
_M_cmpts.emplace_back(_M_pathname.substr(pos, 1), _Type::_Root_dir, pos);
}
void
path::_M_add_filename(size_t pos, size_t n)
{
_M_cmpts.emplace_back(_M_pathname.substr(pos, n), _Type::_Filename, pos);
}
void
path::_M_trim()
{
if (_M_cmpts.size() == 1)
{
_M_type = _M_cmpts.front()._M_type;
_M_cmpts.clear();
}
}
path::string_type
path::_S_convert_loc(const char* __first, const char* __last,
const std::locale& __loc)
{
#if _GLIBCXX_USE_WCHAR_T
auto& __cvt = std::use_facet<codecvt<wchar_t, char, mbstate_t>>(__loc);
basic_string<wchar_t> __ws;
if (!__str_codecvt_in(__first, __last, __ws, __cvt))
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"Cannot convert character sequence",
std::make_error_code(errc::illegal_byte_sequence)));
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
return __ws;
#else
return _Cvt<wchar_t>::_S_convert(__ws.data(), __ws.data() + __ws.size());
#endif
#else
return {__first, __last};
#endif
}
std::size_t
fs::hash_value(const path& p) noexcept
{
// [path.non-member]
// "If for two paths, p1 == p2 then hash_value(p1) == hash_value(p2)."
// Equality works as if by traversing the range [begin(), end()), meaning
// e.g. path("a//b") == path("a/b"), so we cannot simply hash _M_pathname
// but need to iterate over individual elements. Use the hash_combine from
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3876.pdf
size_t seed = 0;
for (const auto& x : p)
{
seed ^= std::hash<path::string_type>()(x.native()) + 0x9e3779b9
+ (seed<<6) + (seed>>2);
}
return seed;
}
namespace std
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace filesystem
{
string
fs_err_concat(const string& __what, const string& __path1,
const string& __path2)
{
const size_t __len = 18 + __what.length()
+ (__path1.length() ? __path1.length() + 3 : 0)
+ (__path2.length() ? __path2.length() + 3 : 0);
string __ret;
__ret.reserve(__len);
__ret = "filesystem error: ";
__ret += __what;
if (!__path1.empty())
{
__ret += " [";
__ret += __path1;
__ret += ']';
}
if (!__path2.empty())
{
__ret += " [";
__ret += __path2;
__ret += ']';
}
return __ret;
}
_GLIBCXX_BEGIN_NAMESPACE_CXX11
std::string filesystem_error::_M_gen_what()
{
return fs_err_concat(system_error::what(), _M_path1.native(),
_M_path2.native());
}
_GLIBCXX_END_NAMESPACE_CXX11
} // filesystem
_GLIBCXX_END_NAMESPACE_VERSION
} // std

View File

@ -0,0 +1,150 @@
// Copyright (C) 2015-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec;
// Test non-existent path.
const auto p = __gnu_test::nonexistent_path();
fs::directory_iterator iter(p, ec);
VERIFY( ec );
VERIFY( iter == end(iter) );
// Test empty directory.
create_directory(p, fs::current_path(), ec);
VERIFY( !ec );
ec = bad_ec;
iter = fs::directory_iterator(p, ec);
VERIFY( !ec );
VERIFY( iter == end(iter) );
// Test non-empty directory.
ec = bad_ec;
create_directory_symlink(p, p / "l", ec);
VERIFY( !ec );
ec = bad_ec;
iter = fs::directory_iterator(p, ec);
VERIFY( !ec );
VERIFY( iter != fs::directory_iterator() );
VERIFY( iter->path() == p/"l" );
++iter;
VERIFY( iter == end(iter) );
// Test inaccessible directory.
ec = bad_ec;
permissions(p, fs::perms::none, ec);
VERIFY( !ec );
ec = bad_ec;
iter = fs::directory_iterator(p, ec);
VERIFY( ec );
VERIFY( iter == end(iter) );
// Test inaccessible directory, skipping permission denied.
const auto opts = fs::directory_options::skip_permission_denied;
ec = bad_ec;
iter = fs::directory_iterator(p, opts, ec);
VERIFY( !ec );
VERIFY( iter == end(iter) );
permissions(p, fs::perms::owner_all, ec);
remove_all(p, ec);
}
void
test02()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec;
const auto p = __gnu_test::nonexistent_path();
ec = bad_ec;
create_directory(p, fs::current_path(), ec);
create_directory_symlink(p, p / "l", ec);
VERIFY( !ec );
// Test post-increment (libstdc++/71005)
ec = bad_ec;
auto iter = fs::directory_iterator(p, ec);
VERIFY( !ec );
VERIFY( iter != end(iter) );
const auto entry1 = *iter;
const auto entry2 = *iter++;
VERIFY( entry1 == entry2 );
VERIFY( entry1.path() == p/"l" );
VERIFY( iter == end(iter) );
remove_all(p, ec);
}
void
test03()
{
std::error_code ec = make_error_code(std::errc::invalid_argument);
const auto p = __gnu_test::nonexistent_path();
create_directories(p / "longer_than_small_string_buffer", ec);
VERIFY( !ec );
// Test for no reallocation on each dereference (this is a GNU extension)
auto iter = fs::directory_iterator(p, ec);
const auto* s1 = iter->path().c_str();
const auto* s2 = iter->path().c_str();
VERIFY( s1 == s2 );
remove_all(p, ec);
}
void
test04()
{
const fs::directory_iterator it;
VERIFY( it == fs::directory_iterator() );
}
void
test05()
{
auto p = __gnu_test::nonexistent_path();
create_directory(p);
create_directory_symlink(p, p / "l");
fs::directory_iterator it(p), endit;
VERIFY( begin(it) == it );
static_assert( noexcept(begin(it)), "begin is noexcept" );
VERIFY( end(it) == endit );
static_assert( noexcept(end(it)), "end is noexcept" );
}
int
main()
{
test01();
test02();
test03();
test04();
test05();
}

View File

@ -0,0 +1,117 @@
// Copyright (C) 2016-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
std::error_code ec;
fs::recursive_directory_iterator dir;
dir.pop(ec); // This is undefined, but our implementation
VERIFY( ec ); // checks and returns an error.
VERIFY( dir == end(dir) );
std::error_code ec2;
try
{
dir.pop();
}
catch (const fs::filesystem_error& ex)
{
ec2 = ex.code();
}
VERIFY( ec2 == ec );
}
void
test02()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec;
const auto p = __gnu_test::nonexistent_path();
create_directories(p / "d1/d2/d3");
for (int i = 0; i < 3; ++i)
{
fs::recursive_directory_iterator dir(p);
VERIFY( dir != end(dir) );
std::advance(dir, i);
VERIFY( dir != end(dir) );
VERIFY( dir.depth() == i );
ec = bad_ec;
dir.pop(ec);
VERIFY( !ec );
VERIFY( dir == end(dir) );
dir = fs::recursive_directory_iterator(p);
std::advance(dir, i);
VERIFY( dir != end(dir) );
VERIFY( dir.depth() == i );
dir.pop();
VERIFY( dir == end(dir) );
}
remove_all(p, ec);
}
void
test03()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec;
const auto p = __gnu_test::nonexistent_path();
create_directories(p / "d1/d2/d3");
create_directories(p / "d1/d2/e3");
create_directories(p / "d1/e2/d3");
for (int i = 0; i < 3; ++i)
{
fs::recursive_directory_iterator dir(p);
std::advance(dir, i);
VERIFY( dir != end(dir) );
int expected_depth = i;
VERIFY( dir.depth() == expected_depth );
ec = bad_ec;
dir.pop(ec);
VERIFY( !ec );
if (dir != end(dir))
VERIFY( dir.depth() == (expected_depth - 1) );
dir = fs::recursive_directory_iterator(p);
std::advance(dir, i);
VERIFY( dir != end(dir) );
VERIFY( dir.depth() == i );
dir.pop();
if (dir != end(dir))
VERIFY( dir.depth() == (i -1) );
}
remove_all(p, ec);
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,188 @@
// Copyright (C) 2015-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec;
// Test non-existent path.
const auto p = __gnu_test::nonexistent_path();
fs::recursive_directory_iterator iter(p, ec);
VERIFY( ec );
VERIFY( iter == end(iter) );
// Test empty directory.
ec = bad_ec;
create_directory(p, fs::current_path(), ec);
VERIFY( !ec );
ec = bad_ec;
iter = fs::recursive_directory_iterator(p, ec);
VERIFY( !ec );
VERIFY( iter == end(iter) );
// Test non-empty directory.
ec = bad_ec;
create_directories(p / "d1/d2", ec);
VERIFY( !ec );
ec = bad_ec;
iter = fs::recursive_directory_iterator(p, ec);
VERIFY( !ec );
VERIFY( iter != end(iter) );
VERIFY( iter->path() == p/"d1" );
++iter;
VERIFY( iter->path() == p/"d1/d2" );
++iter;
VERIFY( iter == end(iter) );
// Test inaccessible directory.
ec = bad_ec;
permissions(p, fs::perms::none, ec);
VERIFY( !ec );
iter = fs::recursive_directory_iterator(p, ec);
VERIFY( ec );
VERIFY( iter == end(iter) );
// Test inaccessible directory, skipping permission denied.
const auto opts = fs::directory_options::skip_permission_denied;
iter = fs::recursive_directory_iterator(p, opts, ec);
VERIFY( !ec );
VERIFY( iter == end(iter) );
// Test inaccessible sub-directory.
ec = bad_ec;
permissions(p, fs::perms::owner_all, ec);
VERIFY( !ec );
ec = bad_ec;
permissions(p/"d1/d2", fs::perms::none, ec);
VERIFY( !ec );
ec = bad_ec;
iter = fs::recursive_directory_iterator(p, ec);
VERIFY( !ec );
VERIFY( iter != end(iter) );
VERIFY( iter->path() == p/"d1" );
++iter; // should recurse into d1
VERIFY( iter->path() == p/"d1/d2" );
iter.increment(ec); // should fail to recurse into p/d1/d2
VERIFY( ec );
VERIFY( iter == end(iter) );
// Test inaccessible sub-directory, skipping permission denied.
ec = bad_ec;
iter = fs::recursive_directory_iterator(p, opts, ec);
VERIFY( !ec );
VERIFY( iter != end(iter) );
VERIFY( iter->path() == p/"d1" );
++iter; // should recurse into d1
VERIFY( iter->path() == p/"d1/d2" );
ec = bad_ec;
iter.increment(ec); // should fail to recurse into p/d1/d2, so skip it
VERIFY( !ec );
VERIFY( iter == end(iter) );
permissions(p/"d1/d2", fs::perms::owner_all, ec);
remove_all(p, ec);
}
void
test02()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec;
const auto p = __gnu_test::nonexistent_path();
ec = bad_ec;
create_directories(p / "d1/d2", ec);
VERIFY( !ec );
// Test post-increment (libstdc++/71005)
ec = bad_ec;
auto iter = fs::recursive_directory_iterator(p, ec);
VERIFY( !ec );
VERIFY( iter != end(iter) );
const auto entry1 = *iter;
const auto entry2 = *iter++;
VERIFY( entry1 == entry2 );
VERIFY( entry1.path() == p/"d1" );
const auto entry3 = *iter;
const auto entry4 = *iter++;
VERIFY( entry3 == entry4 );
VERIFY( entry3.path() == p/"d1/d2" );
VERIFY( iter == end(iter) );
remove_all(p, ec);
}
void
test03()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec;
const auto p = __gnu_test::nonexistent_path();
ec = bad_ec;
create_directories(p / "longer_than_small_string_buffer", ec);
VERIFY( !ec );
// Test for no reallocation on each dereference (this is a GNU extension)
auto iter = fs::recursive_directory_iterator(p, ec);
const auto* s1 = iter->path().c_str();
const auto* s2 = iter->path().c_str();
VERIFY( s1 == s2 );
remove_all(p, ec);
}
void
test04()
{
// libstdc++/71004
const fs::recursive_directory_iterator it;
VERIFY( it == end(it) );
}
void
test05()
{
auto p = __gnu_test::nonexistent_path();
create_directory(p);
create_directory_symlink(p, p / "l");
fs::recursive_directory_iterator it(p), endit;
VERIFY( begin(it) == it );
static_assert( noexcept(begin(it)), "begin is noexcept" );
VERIFY( end(it) == endit );
static_assert( noexcept(end(it)), "end is noexcept" );
}
int
main()
{
test01();
test02();
test03();
test04();
test05();
}

View File

@ -0,0 +1,54 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// C++17 30.10.14.1 Absolute [fs.op.absolute]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
for (const path& p : __gnu_test::test_paths)
VERIFY( absolute(p).is_absolute() );
}
void
test02()
{
path p1("/");
VERIFY( absolute(p1) == p1 );
path p2("/foo");
VERIFY( absolute(p2) == p2 );
path p3("foo");
VERIFY( absolute(p3) != p3 );
VERIFY( absolute(p3) == (std::filesystem::current_path()/p3) );
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,139 @@
// Copyright (C) 2015-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec;
auto p = __gnu_test::nonexistent_path();
canonical( p, ec );
VERIFY( ec );
create_directory(p);
auto p2 = canonical( p, ec );
VERIFY( p2 == fs::current_path()/p );
VERIFY( !ec );
ec = bad_ec;
p2 = canonical( fs::current_path() / "." / (p.native() + "////././."), ec );
VERIFY( p2 == fs::current_path()/p );
VERIFY( !ec );
ec = bad_ec;
p = fs::current_path();
p2 = canonical( p, ec );
VERIFY( p2 == p );
VERIFY( !ec );
ec = bad_ec;
p = "/";
p = canonical( p, ec );
VERIFY( p == "/" );
VERIFY( !ec );
ec = bad_ec;
p = "/.";
p = canonical( p, ec );
VERIFY( p == "/" );
VERIFY( !ec );
ec = bad_ec;
p = "/..";
p = canonical( p, ec );
VERIFY( p == "/" );
VERIFY( !ec );
ec = bad_ec;
p = "/../.././.";
p = canonical( p, ec );
VERIFY( p == "/" );
VERIFY( !ec );
}
void
test02()
{
const fs::path p = __gnu_test::nonexistent_path();
std::error_code ec, ec2;
const fs::path res = canonical(p, ec);
VERIFY( ec );
VERIFY( res.empty() );
#if __cpp_exceptions
fs::path e1, e2;
try {
canonical(p);
} catch (const fs::filesystem_error& e) {
e1 = e.path1();
e2 = e.path2();
ec2 = e.code();
}
VERIFY( e1 == p );
VERIFY( e2.empty() );
VERIFY( ec == ec2 );
#endif
}
void
test03()
{
std::error_code ec;
auto dir = __gnu_test::nonexistent_path();
fs::create_directory(dir);
fs::path foo = dir/"foo", bar = dir/"bar";
fs::create_directory(foo);
fs::create_directory(bar);
fs::create_symlink("../bar", foo/"baz");
auto dirc = canonical(dir);
auto barc = canonical(bar);
auto p1 = fs::canonical(dir/"foo//.///..//./");
VERIFY( p1 == dirc );
auto p2 = fs::canonical(dir/"foo//./baz///..//./");
VERIFY( p2 == dirc );
auto p3 = fs::canonical(dir/"foo//./baz////./");
VERIFY( p3 == barc );
auto p4 = fs::canonical(dir/"foo//./baz///..//./bar");
VERIFY( p4 == barc );
auto p5 = fs::canonical(dir/"foo//./baz///..//./bar/");
VERIFY( p5 == p4 );
auto p6 = fs::canonical(dir/"foo//./baz///..//./bar/.");
VERIFY( p6 == p4 );
remove_all(dir);
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,200 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 15.3 Copy [fs.op.copy]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
namespace fs = std::filesystem;
// Test error conditions.
void
test01()
{
auto p = __gnu_test::nonexistent_path();
std::error_code ec;
VERIFY( !fs::exists(p) );
fs::copy(p, ".", fs::copy_options::none, ec);
VERIFY( ec );
ec.clear();
fs::copy(".", ".", fs::copy_options::none, ec);
VERIFY( ec );
__gnu_test::scoped_file f(p);
VERIFY( fs::is_directory(".") );
VERIFY( fs::is_regular_file(p) );
ec.clear();
fs::copy(".", p, fs::copy_options::none, ec);
VERIFY( ec );
auto to = __gnu_test::nonexistent_path();
ec.clear();
auto opts = fs::copy_options::create_symlinks;
fs::copy("/", to, opts, ec);
VERIFY( ec == std::make_error_code(std::errc::is_a_directory) );
VERIFY( !exists(to) );
ec.clear();
opts != fs::copy_options::recursive;
fs::copy("/", to, opts, ec);
VERIFY( ec == std::make_error_code(std::errc::is_a_directory) );
VERIFY( !exists(to) );
}
// Test is_symlink(f) case.
void
test02()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
auto from = __gnu_test::nonexistent_path();
auto to = __gnu_test::nonexistent_path();
std::error_code ec;
ec = bad_ec;
fs::create_symlink(".", from, ec);
VERIFY( !ec );
VERIFY( fs::exists(from) );
ec = bad_ec;
fs::copy(from, to, fs::copy_options::skip_symlinks, ec);
VERIFY( !ec );
VERIFY( !fs::exists(to) );
ec = bad_ec;
fs::copy(from, to, fs::copy_options::skip_symlinks, ec);
VERIFY( !ec );
VERIFY( !fs::exists(to) );
ec = bad_ec;
fs::copy(from, to,
fs::copy_options::skip_symlinks|fs::copy_options::copy_symlinks,
ec);
VERIFY( !ec );
VERIFY( !fs::exists(to) );
ec = bad_ec;
fs::copy(from, to, fs::copy_options::copy_symlinks, ec);
VERIFY( !ec );
VERIFY( fs::exists(to) );
VERIFY( is_symlink(to) );
ec.clear();
fs::copy(from, to, fs::copy_options::copy_symlinks, ec);
VERIFY( ec );
remove(from, ec);
remove(to, ec);
}
// Test is_regular_file(f) case.
void
test03()
{
auto from = __gnu_test::nonexistent_path();
auto to = __gnu_test::nonexistent_path();
// test empty file
std::ofstream{from.native()};
VERIFY( fs::exists(from) );
VERIFY( fs::file_size(from) == 0 );
fs::copy(from, to);
VERIFY( fs::exists(to) );
VERIFY( fs::file_size(to) == 0 );
remove(to);
VERIFY( !fs::exists(to) );
std::ofstream{from.native()} << "Hello, filesystem!";
VERIFY( fs::file_size(from) != 0 );
fs::copy(from, to);
VERIFY( fs::exists(to) );
VERIFY( fs::file_size(to) == fs::file_size(from) );
remove(from);
remove(to);
}
// Test is_directory(f) case.
void
test04()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
auto from = __gnu_test::nonexistent_path();
auto to = __gnu_test::nonexistent_path();
std::error_code ec;
create_directories(from/"a/b/c");
{
__gnu_test::scoped_file f(to);
copy(from, to, ec);
VERIFY( ec );
}
__gnu_test::scoped_file f1(from/"a/f1");
std::ofstream{f1.path} << "file one";
__gnu_test::scoped_file f2(from/"a/b/f2");
std::ofstream{f2.path} << "file two";
copy(from, to, ec);
VERIFY( !ec );
VERIFY( exists(to) && is_empty(to) );
remove(to);
ec = bad_ec;
copy(from, to, fs::copy_options::recursive, ec);
VERIFY( !ec );
VERIFY( exists(to) && !is_empty(to) );
VERIFY( is_regular_file(to/"a/f1") && !is_empty(to/"a/f1") );
VERIFY( file_size(from/"a/f1") == file_size(to/"a/f1") );
VERIFY( is_regular_file(to/"a/b/f2") && !is_empty(to/"a/b/f2") );
VERIFY( file_size(from/"a/b/f2") == file_size(to/"a/b/f2") );
VERIFY( is_directory(to/"a/b/c") && is_empty(to/"a/b/c") );
f1.path.clear();
f2.path.clear();
remove_all(from, ec);
remove_all(to, ec);
}
// Test no-op cases.
void
test05()
{
auto to = __gnu_test::nonexistent_path();
std::error_code ec = std::make_error_code(std::errc::invalid_argument);
fs::copy("/", to, fs::copy_options::copy_symlinks, ec);
VERIFY( !ec ); // Previous value should be cleared (LWG 2683)
}
int
main()
{
test01();
test02();
test03();
test04();
test05();
}

View File

@ -0,0 +1,84 @@
// Copyright (C) 2016-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// 15.4 Copy [fs.op.copy_file]
#include <filesystem>
#include <fstream>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
void
test01()
{
using std::filesystem::copy_options;
std::error_code ec;
auto from = __gnu_test::nonexistent_path();
auto to = __gnu_test::nonexistent_path();
// test non-existent file
bool b = copy_file(from, to, ec);
VERIFY( !b );
VERIFY( ec );
VERIFY( !exists(to) );
// test empty file
std::ofstream{from.native()};
VERIFY( exists(from) );
VERIFY( file_size(from) == 0 );
b = copy_file(from, to);
VERIFY( b );
VERIFY( exists(to) );
VERIFY( file_size(to) == 0 );
remove(to);
VERIFY( !exists(to) );
b = copy_file(from, to, copy_options::none, ec);
VERIFY( b );
VERIFY( !ec );
VERIFY( exists(to) );
VERIFY( file_size(to) == 0 );
std::ofstream{from.native()} << "Hello, filesystem!";
VERIFY( file_size(from) != 0 );
remove(to);
VERIFY( !exists(to) );
b = copy_file(from, to);
VERIFY( b );
VERIFY( exists(to) );
VERIFY( file_size(to) == file_size(from) );
remove(to);
VERIFY( !exists(to) );
b = copy_file(from, to);
VERIFY( b );
VERIFY( exists(to) );
VERIFY( file_size(to) == file_size(from) );
remove(from);
remove(to);
}
int
main()
{
test01();
}

View File

@ -0,0 +1,83 @@
// Copyright (C) 2015-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec;
// Test empty path.
bool b = fs::create_directories( "", ec );
VERIFY( ec );
VERIFY( !b );
// Test existing path.
ec = bad_ec;
b = fs::create_directories( fs::current_path(), ec );
VERIFY( !ec );
VERIFY( !b );
// Test non-existent path.
const auto p = __gnu_test::nonexistent_path();
ec = bad_ec;
b = fs::create_directories( p, ec );
VERIFY( !ec );
VERIFY( b );
VERIFY( is_directory(p) );
ec = bad_ec;
b = fs::create_directories( p/".", ec );
VERIFY( !ec );
VERIFY( !b );
ec = bad_ec;
b = fs::create_directories( p/"..", ec );
VERIFY( !ec );
VERIFY( !b );
ec = bad_ec;
b = fs::create_directories( p/"d1/d2/d3", ec );
VERIFY( !ec );
VERIFY( b );
VERIFY( is_directory(p/"d1/d2/d3") );
ec = bad_ec;
b = fs::create_directories( p/"./d4/../d5", ec );
VERIFY( !ec );
VERIFY( b );
VERIFY( is_directory(p/"./d4/../d5") );
std::uintmax_t count = remove_all(p, ec);
VERIFY( count == 6 );
}
int
main()
{
test01();
}

View File

@ -0,0 +1,65 @@
// Copyright (C) 2016-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
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) );
ec = bad_ec;
b = create_directory(p, ec); // create the directory once
VERIFY( !ec );
VERIFY( b );
VERIFY( exists(p) );
// Test existing path (libstdc++/71036).
ec = bad_ec;
b = create_directory(p, ec);
VERIFY( !ec );
VERIFY( !b );
b = create_directory(p);
VERIFY( !b );
remove_all(p, ec);
}
int
main()
{
test01();
}

View File

@ -0,0 +1,96 @@
// Copyright (C) 2016-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
std::error_code ec, ec2;
__gnu_test::scoped_file f;
auto tgt = f.path;
// Test empty path.
fs::path p;
create_symlink(tgt, p, ec );
VERIFY( ec );
try
{
create_symlink(tgt, p);
}
catch (const std::filesystem::filesystem_error& ex)
{
ec2 = ex.code();
VERIFY( ex.path1() == tgt );
VERIFY( ex.path2() == p );
}
VERIFY( ec2 == ec );
}
void
test02()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec, ec2;
__gnu_test::scoped_file f;
auto tgt = f.path;
// Test non-existent path
auto p = __gnu_test::nonexistent_path();
VERIFY( !exists(p) );
ec = bad_ec;
create_symlink(tgt, p, ec); // create the symlink once
VERIFY( !ec );
VERIFY( exists(p) );
VERIFY( is_symlink(p) );
remove(p);
create_symlink(tgt, p); // create the symlink again
VERIFY( exists(p) );
VERIFY( is_symlink(p) );
ec.clear();
create_symlink(tgt, p, ec); // Try to create existing symlink
VERIFY( ec );
try
{
create_symlink(tgt, p);
}
catch (const std::filesystem::filesystem_error& ex)
{
ec2 = ex.code();
VERIFY( ex.path1() == tgt );
VERIFY( ex.path2() == p );
}
VERIFY( ec2 == ec );
remove(p);
}
int
main()
{
test01();
}

View File

@ -0,0 +1,58 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 15.11 Current path [fs.op.current_path]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
namespace fs = std::filesystem;
void
test01()
{
fs::path dot(".");
fs::path cwd = fs::current_path();
std::error_code ec;
fs::path cwd2 = fs::current_path(ec);
VERIFY( cwd == cwd2 );
}
void
test02()
{
auto oldwd = fs::current_path();
auto tmpdir = fs::temp_directory_path();
current_path(tmpdir);
VERIFY( canonical(fs::current_path()) == canonical(tmpdir) );
std::error_code ec;
current_path(oldwd, ec);
VERIFY( canonical(fs::current_path()) == canonical(oldwd) );
VERIFY( canonical(fs::current_path(ec)) == canonical(oldwd) );
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,74 @@
// Copyright (C) 2016-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
namespace fs = std::filesystem;
void
test01()
{
auto p1 = __gnu_test::nonexistent_path();
auto p2 = __gnu_test::nonexistent_path();
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec;
bool result;
result = equivalent(p1, p2, ec);
VERIFY( ec );
VERIFY( !result );
__gnu_test::scoped_file f1(p1);
ec = bad_ec;
result = equivalent(p1, p2, ec);
VERIFY( !ec );
VERIFY( !result );
__gnu_test::scoped_file f2(p2);
ec = bad_ec;
result = equivalent(p1, p2, ec);
VERIFY( !ec );
VERIFY( !result );
auto p3 = __gnu_test::nonexistent_path();
create_hard_link(p1, p3, ec);
if (ec)
return; // hard links not supported
__gnu_test::scoped_file f3(p3, __gnu_test::scoped_file::adopt_file);
ec = bad_ec;
result = equivalent(p1, p3, ec);
VERIFY( !ec );
VERIFY( result );
ec = bad_ec;
result = equivalent(p2, p3, ec);
VERIFY( !ec );
VERIFY( !result );
}
int
main()
{
test01();
}

View File

@ -0,0 +1,115 @@
// Copyright (C) 2015-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
VERIFY( exists(path{"/"}) );
VERIFY( exists(path{"/."}) );
VERIFY( exists(path{"."}) );
VERIFY( exists(path{".."}) );
VERIFY( exists(std::filesystem::current_path()) );
std::error_code ec;
ec = bad_ec;
VERIFY( exists(path{"/"}, ec) );
VERIFY( !ec );
ec = bad_ec;
VERIFY( exists(path{"/."}, ec) );
VERIFY( !ec );
ec = bad_ec;
VERIFY( exists(path{"."}, ec) );
VERIFY( !ec );
ec = bad_ec;
VERIFY( exists(path{".."}, ec) );
VERIFY( !ec );
ec = bad_ec;
VERIFY( exists(std::filesystem::current_path(), ec) );
VERIFY( !ec );
}
void
test02()
{
path rel = __gnu_test::nonexistent_path();
VERIFY( !exists(rel) );
std::error_code ec = std::make_error_code(std::errc::invalid_argument);
VERIFY( !exists(rel, ec) );
VERIFY( !ec ); // DR 2725
}
void
test03()
{
path abs = absolute(__gnu_test::nonexistent_path());
VERIFY( !exists(abs) );
std::error_code ec = std::make_error_code(std::errc::invalid_argument);
VERIFY( !exists(abs, ec) );
VERIFY( !ec ); // DR 2725
}
void
test04()
{
using std::filesystem::perms;
using std::filesystem::perm_options;
path p = __gnu_test::nonexistent_path();
create_directory(p);
permissions(p, perms::all, perm_options::remove);
auto unr = p / "unreachable";
std::error_code ec;
VERIFY( !exists(unr, ec) );
VERIFY( ec == std::errc::permission_denied );
ec.clear();
try
{
exists(unr);
}
catch(const std::filesystem::filesystem_error& ex)
{
ec = ex.code();
VERIFY( ex.path1() == unr );
}
VERIFY( ec == std::errc::permission_denied );
permissions(p, perms::owner_all);
remove(p);
}
int
main()
{
test01();
test02();
test03();
test04();
}

View File

@ -0,0 +1,71 @@
// Copyright (C) 2015-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
std::error_code ec;
size_t size = fs::file_size(".", ec);
VERIFY( ec == std::errc::is_a_directory );
VERIFY( size == -1 );
try {
size = fs::file_size(".");
ec.clear();
} catch (const fs::filesystem_error& e) {
ec = e.code();
}
VERIFY( ec == std::errc::is_a_directory );
VERIFY( size == -1 );
}
void
test02()
{
fs::path p = __gnu_test::nonexistent_path();
std::error_code ec;
size_t size = fs::file_size(p, ec);
VERIFY( ec );
VERIFY( size == -1 );
try {
size = fs::file_size(p);
ec.clear();
} catch (const fs::filesystem_error& e) {
ec = e.code();
}
VERIFY( ec );
VERIFY( size == -1 );
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,109 @@
// Copyright (C) 2016-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
auto p = __gnu_test::nonexistent_path();
create_directory(p);
permissions(p, fs::perms::none);
std::error_code ec, ec2;
bool result = fs::is_empty(p, ec);
VERIFY( ec == std::make_error_code(std::errc::permission_denied) );
VERIFY( !result );
try {
fs::is_empty(p);
} catch (const fs::filesystem_error& e) {
ec2 = e.code();
}
VERIFY( ec2 == ec );
result = fs::is_empty(p/"f", ec);
VERIFY( ec == std::make_error_code(std::errc::permission_denied) );
VERIFY( !result );
try {
fs::is_empty(p/"f");
} catch (const fs::filesystem_error& e) {
ec2 = e.code();
}
VERIFY( ec2 == ec );
permissions(p, fs::perms::owner_all, ec);
remove_all(p, ec);
}
void
test02()
{
auto p = __gnu_test::nonexistent_path();
create_directory(p);
std::error_code ec, bad_ec = make_error_code(std::errc::invalid_argument);
bool empty;
ec = bad_ec;
empty = is_empty(p, ec);
VERIFY( !ec );
VERIFY( empty );
empty = is_empty(p);
VERIFY( empty );
__gnu_test::scoped_file f(p/"f");
ec = bad_ec;
empty = is_empty(f.path, ec);
VERIFY( !ec );
VERIFY( empty );
empty = is_empty(f.path);
VERIFY( empty );
std::ofstream{f.path.native()} << "data";
ec = bad_ec;
empty = is_empty(p, ec);
VERIFY( !ec );
VERIFY( !empty );
empty = is_empty(p);
VERIFY( !empty );
ec = bad_ec;
empty = is_empty(p, ec);
VERIFY( !ec );
VERIFY( !empty );
empty = is_empty(p);
VERIFY( !empty );
f.path.clear();
remove_all(p, ec);
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,162 @@
// Copyright (C) 2016-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// 15.25 Permissions [fs.op.last_write_time]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
#ifdef _GLIBCXX_HAVE_FCNTL_H
# include <fcntl.h>
#endif
#if _GLIBCXX_HAVE_UTIME_H
# include <utime.h>
#endif
using time_type = std::filesystem::file_time_type;
void
test01()
{
// read times
auto p = __gnu_test::nonexistent_path();
std::error_code ec;
time_type mtime = last_write_time(p, ec);
VERIFY( ec );
VERIFY( ec == std::make_error_code(std::errc::no_such_file_or_directory) );
#if __cpp_exceptions
bool caught = false;
try {
mtime = last_write_time(p);
} catch (std::system_error const& e) {
caught = true;
ec = e.code();
}
VERIFY( caught );
VERIFY( ec );
VERIFY( ec == std::make_error_code(std::errc::no_such_file_or_directory) );
#endif
__gnu_test::scoped_file file(p);
VERIFY( exists(p) );
mtime = last_write_time(p, ec);
VERIFY( !ec );
VERIFY( mtime <= time_type::clock::now() );
VERIFY( mtime == last_write_time(p) );
auto end_of_time = time_type::duration::max();
auto last_second
= std::chrono::duration_cast<std::chrono::seconds>(end_of_time).count();
if (last_second > std::numeric_limits<std::time_t>::max())
return; // can't test overflow
#if _GLIBCXX_USE_UTIMENSAT
struct ::timespec ts[2];
ts[0].tv_sec = 0;
ts[0].tv_nsec = UTIME_NOW;
ts[1].tv_sec = std::numeric_limits<std::time_t>::max() - 1;
ts[1].tv_nsec = 0;
VERIFY( !::utimensat(AT_FDCWD, p.c_str(), ts, 0) );
#elif _GLIBCXX_HAVE_UTIME_H
::utimbuf times;
times.modtime = std::numeric_limits<std::time_t>::max() - 1;
times.actime = std::numeric_limits<std::time_t>::max() - 1;
VERIFY( !::utime(p.c_str(), &times) );
#else
return;
#endif
mtime = last_write_time(p, ec);
VERIFY( ec );
VERIFY( ec == std::make_error_code(std::errc::value_too_large) );
VERIFY( mtime == time_type::min() );
#if __cpp_exceptions
caught = false;
try {
mtime = last_write_time(p);
} catch (std::system_error const& e) {
caught = true;
ec = e.code();
}
VERIFY( caught );
VERIFY( ec );
VERIFY( ec == std::make_error_code(std::errc::value_too_large) );
#endif
}
bool approx_equal(time_type file_time, time_type expected)
{
auto delta = expected - file_time;
if (delta < delta.zero())
delta = -delta;
return delta < std::chrono::seconds(1);
}
void
test02()
{
// write times
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
__gnu_test::scoped_file f;
std::error_code ec;
time_type time;
time = last_write_time(f.path);
ec = bad_ec;
last_write_time(f.path, time, ec);
VERIFY( !ec );
VERIFY( approx_equal(last_write_time(f.path), time) );
ec = bad_ec;
time -= std::chrono::milliseconds(1000 * 60 * 10 + 15);
last_write_time(f.path, time, ec);
VERIFY( !ec );
VERIFY( approx_equal(last_write_time(f.path), time) );
ec = bad_ec;
time += std::chrono::milliseconds(1000 * 60 * 20 + 15);
last_write_time(f.path, time, ec);
VERIFY( !ec );
VERIFY( approx_equal(last_write_time(f.path), time) );
ec = bad_ec;
time = time_type();
last_write_time(f.path, time, ec);
VERIFY( !ec );
VERIFY( approx_equal(last_write_time(f.path), time) );
ec = bad_ec;
time -= std::chrono::milliseconds(1000 * 60 * 10 + 15);
last_write_time(f.path, time, ec);
VERIFY( !ec );
VERIFY( approx_equal(last_write_time(f.path), time) );
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,167 @@
// Copyright (C) 2016-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// C++17 30.10.14.26 Permissions [fs.op.permissions]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
void
test01()
{
using std::filesystem::perms;
using std::filesystem::perm_options;
auto p = __gnu_test::nonexistent_path();
__gnu_test::scoped_file f(p);
VERIFY( exists(p) );
permissions(p, perms::owner_all);
VERIFY( status(p).permissions() == perms::owner_all );
permissions(p, perms::group_read, perm_options::add);
VERIFY( status(p).permissions() == (perms::owner_all | perms::group_read) );
permissions(p, perms::group_read, perm_options::remove);
VERIFY( status(p).permissions() == perms::owner_all );
}
void
test02()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
using std::filesystem::perms;
using std::filesystem::perm_options;
auto p = __gnu_test::nonexistent_path();
std::error_code ec;
permissions(p, perms::owner_all, ec);
VERIFY( ec );
__gnu_test::scoped_file f(p);
VERIFY( exists(p) );
ec = bad_ec;
permissions(p, perms::owner_all, ec);
VERIFY( !ec );
VERIFY( status(p).permissions() == perms::owner_all );
ec = bad_ec;
permissions(p, perms::group_read, perm_options::add, ec);
VERIFY( !ec );
VERIFY( status(p).permissions() == (perms::owner_all | perms::group_read) );
ec = bad_ec;
permissions(p, perms::group_read, perm_options::remove, ec);
VERIFY( !ec );
VERIFY( status(p).permissions() == perms::owner_all );
}
void
test03()
{
using std::filesystem::perms;
using std::filesystem::perm_options;
__gnu_test::scoped_file f;
VERIFY( exists(f.path) );
auto p = __gnu_test::nonexistent_path();
create_symlink(f.path, p);
std::error_code ec = make_error_code(std::errc::no_such_file_or_directory);
std::error_code ec2 = make_error_code(std::errc::invalid_argument);
permissions(p, perms::owner_all,
perm_options::replace|perm_options::nofollow, ec);
try
{
permissions(p, perms::owner_all,
perm_options::replace|perm_options::nofollow);
}
catch (const std::filesystem::filesystem_error& ex)
{
ec2 = ex.code();
VERIFY( ex.path1() == p );
}
// Both calls should succeed, or both should fail with same error:
VERIFY( ec == ec2 );
remove(p);
}
void
test04()
{
using perms = std::filesystem::perms;
auto p = __gnu_test::nonexistent_path();
create_symlink(__gnu_test::nonexistent_path(), p);
std::error_code ec = make_error_code(std::errc::no_such_file_or_directory);
std::error_code ec2 = make_error_code(std::errc::invalid_argument);
permissions(p, perms::owner_all, ec);
VERIFY( ec );
try
{
permissions(p, perms::owner_all);
}
catch (const std::filesystem::filesystem_error& ex)
{
ec2 = ex.code();
VERIFY( ex.path1() == p );
}
VERIFY( ec == ec2 );
remove(p);
}
void
test05()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
using std::filesystem::perms;
using std::filesystem::perm_options;
std::error_code ec;
__gnu_test::scoped_file f;
auto p = perms::owner_write;
// symlink_nofollow should not give an error for non-symlinks
ec = bad_ec;
permissions(f.path, p, perm_options::replace|perm_options::nofollow, ec);
VERIFY( !ec );
auto st = status(f.path);
VERIFY( st.permissions() == p );
p |= perms::owner_read;
ec = bad_ec;
permissions(f.path, p, perm_options::replace|perm_options::nofollow, ec);
VERIFY( !ec );
st = status(f.path);
VERIFY( st.permissions() == p );
}
int
main()
{
test01();
test02();
test03();
test04();
test05();
}

View File

@ -0,0 +1,67 @@
// Copyright (C) 2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
using std::filesystem::proximate;
void
test01()
{
VERIFY( proximate("/a/d", "/a/b/c") == "../../d" );
VERIFY( proximate("/a/b/c", "/a/d") == "../b/c" );
VERIFY( proximate("a/b/c", "a") == "b/c" );
VERIFY( proximate("a/b/c", "a/b/c/x/y") == "../.." );
VERIFY( proximate("a/b/c", "a/b/c") == "." );
VERIFY( proximate("a/b", "c/d") == "../../a/b" );
}
void
test02()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec = bad_ec;
VERIFY( proximate("/a/d", "/a/b/c", ec) == "../../d" );
VERIFY( !ec );
ec = bad_ec;
VERIFY( proximate("/a/b/c", "/a/d", ec) == "../b/c" );
VERIFY( !ec );
ec = bad_ec;
VERIFY( proximate("a/b/c", "a", ec) == "b/c" );
VERIFY( !ec );
ec = bad_ec;
VERIFY( proximate("a/b/c", "a/b/c/x/y", ec) == "../.." );
VERIFY( !ec );
ec = bad_ec;
VERIFY( proximate("a/b/c", "a/b/c", ec) == "." );
VERIFY( !ec );
ec = bad_ec;
VERIFY( proximate("a/b", "c/d", ec) == "../../a/b" );
VERIFY( !ec );
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,51 @@
// Copyright (C) 2016-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
auto p = __gnu_test::nonexistent_path();
std::error_code ec;
read_symlink(p, ec);
VERIFY( ec );
fs::path tgt = ".";
create_symlink(tgt, p);
auto result = read_symlink(p, ec);
VERIFY( !ec );
VERIFY( result == tgt );
remove(p);
}
int
main()
{
test01();
}

View File

@ -0,0 +1,64 @@
// Copyright (C) 2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
void
test01()
{
auto p = __gnu_test::nonexistent_path();
auto q = __gnu_test::nonexistent_path();
auto r = relative(p, q);
VERIFY( r == ".."/p );
r = relative(p, p/q);
VERIFY( r == ".." );
r = relative(p/q, p);
VERIFY( r == q );
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec;
ec = bad_ec;
r = relative(p, q, ec);
VERIFY( !ec );
VERIFY( r == ".."/p );
ec = bad_ec;
r = relative(p, p/q, ec);
VERIFY( !ec );
VERIFY( r == ".." );
ec = bad_ec;
r = relative(p/q, p, ec);
VERIFY( !ec );
VERIFY( r == q );
}
int
main()
{
test01();
}

View File

@ -0,0 +1,92 @@
// Copyright (C) 2016-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
std::error_code ec;
std::uintmax_t n;
n = fs::remove_all("", ec);
VERIFY( ec );
VERIFY( n == std::uintmax_t(-1) );
auto p = __gnu_test::nonexistent_path();
ec.clear();
n = remove_all(p, ec);
VERIFY( ec );
VERIFY( n == std::uintmax_t(-1) );
const auto bad_ec = ec;
auto link = __gnu_test::nonexistent_path();
create_symlink(p, link); // dangling symlink
ec = bad_ec;
n = remove_all(link, ec);
VERIFY( !ec );
VERIFY( n == 1 );
VERIFY( !exists(symlink_status(link)) ); // DR 2721
__gnu_test::scoped_file f(p);
create_symlink(p, link);
ec = bad_ec;
n = remove_all(link, ec);
VERIFY( !ec );
VERIFY( n == 1 );
VERIFY( !exists(symlink_status(link)) ); // The symlink is removed, but
VERIFY( exists(p) ); // its target is not.
auto dir = __gnu_test::nonexistent_path();
create_directories(dir/"a/b/c");
ec = bad_ec;
n = remove_all(dir/"a", ec);
VERIFY( !ec );
VERIFY( n == 3 );
VERIFY( exists(dir) );
VERIFY( !exists(dir/"a") );
create_directories(dir/"a/b/c");
__gnu_test::scoped_file a1(dir/"a/1");
__gnu_test::scoped_file a2(dir/"a/2");
__gnu_test::scoped_file b1(dir/"a/b/1");
__gnu_test::scoped_file b2(dir/"a/b/2");
ec = bad_ec;
n = remove_all(dir, ec);
VERIFY( !ec );
VERIFY( n == 8 );
VERIFY( !exists(dir) );
a1.path.clear();
a2.path.clear();
b1.path.clear();
b2.path.clear();
}
int
main()
{
test01();
}

View File

@ -0,0 +1,46 @@
// Copyright (C) 2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// 30.10.14.3 Permissions [fs.op.space]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
void
test01()
{
std::filesystem::space_info s = std::filesystem::space("/");
std::error_code ec = make_error_code(std::errc::invalid_argument);
s = std::filesystem::space("/", ec);
VERIFY( !ec );
s = std::filesystem::space(__gnu_test::nonexistent_path(), ec);
VERIFY( ec );
VERIFY( s.capacity == static_cast<uintmax_t>(-1) );
VERIFY( s.free == static_cast<uintmax_t>(-1) );
VERIFY( s.available == static_cast<uintmax_t>(-1) );
}
int
main()
{
test01();
}

View File

@ -0,0 +1,97 @@
// Copyright (C) 2015-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
std::error_code ec = make_error_code(std::errc::invalid_argument);
fs::path dot = ".";
fs::file_status st1 = fs::status(dot, ec);
VERIFY( !ec );
VERIFY( st1.type() == fs::file_type::directory );
fs::file_status st2 = fs::status(dot);
VERIFY( st2.type() == fs::file_type::directory );
}
void
test02()
{
fs::path p = __gnu_test::nonexistent_path();
std::error_code ec;
fs::file_status st1 = fs::status(p, ec);
VERIFY( ec );
VERIFY( st1.type() == fs::file_type::not_found );
fs::file_status st2 = fs::status(p);
VERIFY( st2.type() == fs::file_type::not_found );
}
void
test03()
{
fs::path dir = __gnu_test::nonexistent_path();
fs::create_directory(dir);
__gnu_test::scoped_file d(dir, __gnu_test::scoped_file::adopt_file);
__gnu_test::scoped_file f(dir / "file");
fs::permissions(dir, fs::perms::none);
std::error_code ec;
fs::file_status st = fs::status(f.path, ec);
VERIFY( ec.value() == (int)std::errc::permission_denied );
VERIFY( st.type() == fs::file_type::none );
#if __cpp_exceptions
bool caught = false;
std::error_code ec2;
fs::path p, p2;
try {
fs::symlink_status(f.path);
} catch (const fs::filesystem_error& e) {
caught = true;
p = e.path1();
p2 = e.path2();
ec2 = e.code();
}
VERIFY( caught );
VERIFY( ec2 == ec );
VERIFY( p == f.path );
VERIFY( p2.empty() );
#endif
fs::permissions(dir, fs::perms::owner_all, ec);
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,118 @@
// Copyright (C) 2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
namespace fs = std::filesystem;
void
test01()
{
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec = bad_ec;
fs::path dot = ".";
fs::file_status st1 = fs::symlink_status(dot, ec);
VERIFY( !ec );
VERIFY( st1.type() == fs::file_type::directory );
fs::file_status st2 = fs::symlink_status(dot);
VERIFY( st2.type() == fs::file_type::directory );
fs::path link = __gnu_test::nonexistent_path();
create_directory_symlink(dot, link);
st1 = fs::symlink_status(link);
VERIFY( st1.type() == fs::file_type::symlink );
ec = bad_ec;
st2 = fs::symlink_status(link, ec);
VERIFY( !ec );
VERIFY( st2.type() == fs::file_type::symlink );
}
void
test02()
{
fs::path p = __gnu_test::nonexistent_path();
std::error_code ec;
fs::file_status st1 = fs::symlink_status(p, ec);
VERIFY( ec );
VERIFY( st1.type() == fs::file_type::not_found );
fs::file_status st2 = fs::symlink_status(p);
VERIFY( st2.type() == fs::file_type::not_found );
}
void
test03()
{
fs::path dir = __gnu_test::nonexistent_path();
fs::create_directory(dir);
__gnu_test::scoped_file d(dir, __gnu_test::scoped_file::adopt_file);
__gnu_test::scoped_file f(dir / "file");
fs::permissions(dir, fs::perms::none);
auto link = __gnu_test::nonexistent_path();
fs::create_symlink(f.path, link);
__gnu_test::scoped_file l(link, __gnu_test::scoped_file::adopt_file);
std::error_code ec;
fs::file_status st = fs::symlink_status(f.path, ec);
VERIFY( ec.value() == (int)std::errc::permission_denied );
VERIFY( st.type() == fs::file_type::none );
st = fs::symlink_status(link, ec);
VERIFY( !ec );
VERIFY( st.type() == fs::file_type::symlink );
#if __cpp_exceptions
bool caught = false;
std::error_code ec2;
fs::path p, p2;
try {
fs::symlink_status(f.path);
} catch (const fs::filesystem_error& e) {
caught = true;
p = e.path1();
p2 = e.path2();
ec2 = e.code();
}
VERIFY( caught );
VERIFY( ec2.value() == (int)std::errc::permission_denied );
VERIFY( p == f.path );
VERIFY( p2.empty() );
#endif
fs::file_status st2 = symlink_status(link);
VERIFY( st2.type() == fs::file_type::symlink );
fs::permissions(dir, fs::perms::owner_all, ec);
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,127 @@
// Copyright (C) 2015-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <stdlib.h>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
void
clean_env()
{
::unsetenv("TMPDIR");
::unsetenv("TMP");
::unsetenv("TEMPDIR");
::unsetenv("TEMP");
}
namespace fs = std::filesystem;
void
test01()
{
clean_env();
if (!fs::exists("/tmp"))
return; // just give up
std::error_code ec = make_error_code(std::errc::invalid_argument);
fs::path p1 = fs::temp_directory_path(ec);
VERIFY( !ec );
VERIFY( exists(p1) );
fs::path p2 = fs::temp_directory_path();
VERIFY( p1 == p2 );
}
void
test02()
{
clean_env();
if (::setenv("TMPDIR", __gnu_test::nonexistent_path().string().c_str(), 1))
return; // just give up
std::error_code ec;
fs::path p = fs::temp_directory_path(ec);
VERIFY( ec );
VERIFY( p == fs::path() );
std::error_code ec2;
try {
p = fs::temp_directory_path();
} catch (const fs::filesystem_error& e) {
ec2 = e.code();
}
VERIFY( ec2 == ec );
}
void
test03()
{
auto p = __gnu_test::nonexistent_path();
create_directories(p/"tmp");
permissions(p, fs::perms::none);
setenv("TMPDIR", (p/"tmp").c_str(), 1);
std::error_code ec;
auto r = fs::temp_directory_path(ec); // libstdc++/PR71337
VERIFY( ec == std::make_error_code(std::errc::permission_denied) );
VERIFY( r == fs::path() );
std::error_code ec2;
try {
fs::temp_directory_path();
} catch (const fs::filesystem_error& e) {
ec2 = e.code();
}
VERIFY( ec2 == ec );
permissions(p, fs::perms::owner_all, ec);
remove_all(p, ec);
}
void
test04()
{
__gnu_test::scoped_file f;
setenv("TMPDIR", f.path.c_str(), 1);
std::error_code ec;
auto r = fs::temp_directory_path(ec);
VERIFY( ec == std::make_error_code(std::errc::not_a_directory) );
VERIFY( r == fs::path() );
std::error_code ec2;
try {
fs::temp_directory_path();
} catch (const fs::filesystem_error& e) {
ec2 = e.code();
}
VERIFY( ec2 == ec );
}
int
main()
{
test01();
test02();
test03();
test04();
}

View File

@ -0,0 +1,70 @@
// Copyright (C) 2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
namespace fs = std::filesystem;
void
test01()
{
auto dir = __gnu_test::nonexistent_path();
fs::create_directory(dir);
const auto dirc = canonical(dir);
fs::path foo = dir/"foo", bar = dir/"bar";
fs::create_directory(foo);
fs::create_directory(bar);
fs::create_directory(bar/"baz");
fs::create_symlink("../bar", foo/"bar");
auto p = fs::weakly_canonical(dir/"foo//./bar///../biz/.");
VERIFY( p == dirc/"biz/" );
p = fs::weakly_canonical(dir/"foo/.//bar/././baz/.");
VERIFY( p == dirc/"bar/baz" );
p = fs::weakly_canonical(fs::current_path()/dir/"bar//../foo/bar/baz");
VERIFY( p == dirc/"bar/baz" );
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
std::error_code ec;
ec = bad_ec;
p = fs::weakly_canonical(dir/"foo//./bar///../biz/.", ec);
VERIFY( !ec );
VERIFY( p == dirc/"biz/" );
ec = bad_ec;
p = fs::weakly_canonical(dir/"foo/.//bar/././baz/.", ec);
VERIFY( !ec );
VERIFY( p == dirc/"bar/baz" );
ec = bad_ec;
p = fs::weakly_canonical(fs::current_path()/dir/"bar//../foo/bar/baz", ec);
VERIFY( !ec );
VERIFY( p == dirc/"bar/baz" );
fs::remove_all(dir, ec);
}
int
main()
{
test01();
}

View File

@ -0,0 +1,87 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.3 path appends [path.append]
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
const path p("/foo/bar");
path pp = p;
pp /= p;
VERIFY( pp.native() == p.native() );
path q("baz");
path qq = q;
qq /= q;
VERIFY( qq.native() == "baz/baz" );
q /= p;
VERIFY( q.native() == p.native() );
path r = "";
r /= path();
VERIFY( r.empty() );
r /= path("rel");
VERIFY( !r.is_absolute() );
path s = "dir/";
s /= path("/file");
VERIFY( s.native() == "/file" );
s = "dir/";
s /= path("file");
VERIFY( s.native() == "dir/file" );
}
void
test02()
{
// C++17 [fs.path.append] p4
path p = path("//host") / "foo";
VERIFY( p == "//host/foo" );
path pp = path("//host/") / "foo";
VERIFY( pp == "//host/foo" );
path q = path("foo") / "";
VERIFY( q == "foo/" );
path qq = path("foo") / "/bar";
VERIFY( qq == "/bar" );
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,94 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
#include <testsuite_fs.h>
using std::filesystem::path;
using __gnu_test::compare_paths;
void
test01()
{
for (std::string s : __gnu_test::test_paths)
{
path p0 = s, p1, p2, p3, p4;
p1 = s;
compare_paths(p0, p1);
p2 = s.c_str();
compare_paths(p0, p2);
#if _GLIBCXX_USE_WCHAR_T
std::wstring ws(s.begin(), s.end());
p3 = ws;
compare_paths(p0, p3);
p4 = ws.c_str();
compare_paths(p0, p4);
#endif
}
}
void
test02()
{
for (std::string s : __gnu_test::test_paths)
{
path p0 = s, p1, p2, p3, p4, p5, p6, p7, p8;
p1.assign(s);
compare_paths(p0, p1);
p2.assign( s.begin(), s.end() );
compare_paths(p0, p2);
p3.assign( s.c_str() );
compare_paths(p0, p3);
p4.assign( s.c_str(), s.c_str() + s.size() );
compare_paths(p0, p4);
#if _GLIBCXX_USE_WCHAR_T
std::wstring ws(s.begin(), s.end());
p5.assign(ws);
compare_paths(p0, p5);
p6.assign( ws.begin(), ws.end() );
compare_paths(p0, p6);
p7.assign( ws.c_str() );
compare_paths(p0, p7);
p8.assign( ws.c_str(), ws.c_str() + ws.size() );
compare_paths(p0, p8);
#endif
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,56 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
#include <filesystem>
#include <testsuite_fs.h>
using std::filesystem::path;
using __gnu_test::compare_paths;
void
test01()
{
for (const path& p : __gnu_test::test_paths)
{
path copy;
copy = p;
__gnu_test::compare_paths(p, copy);
}
}
void
test02()
{
for (const path& p : __gnu_test::test_paths)
{
path copy = p;
path move;
move = std::move(copy);
__gnu_test::compare_paths(p, move);
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,51 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.8 path compare [path.compare]
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
path p("/foo/bar");
VERIFY( p.compare(p) == 0 );
VERIFY( p.compare("/foo//bar") == 0 );
path q("/foo/baz");
VERIFY( p.compare(q) < 0 );
VERIFY( q.compare(p) > 0 );
path r("/foo/bar/.");
VERIFY( p.compare(r) < 0 );
VERIFY( path("a/b/").compare("a/b//") == 0 );
}
int
main()
{
test01();
}

View File

@ -0,0 +1,51 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.8 path compare [path.compare]
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
const path p0 = "/a/a/b/b";
for (const path& p : __gnu_test::test_paths)
{
VERIFY( p.compare(p) == 0 );
int cmp = p.compare(p0);
if (cmp == 0)
VERIFY( p0.compare(p) == 0 );
else if (cmp < 0)
VERIFY( p0.compare(p) > 0 );
else if (cmp > 0)
VERIFY( p0.compare(p) < 0 );
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,49 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.8 path compare [path.compare]
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
const std::string s0 = "/a/a/b/b";
const path p0 = s0;
for (const std::string& s : __gnu_test::test_paths)
{
path p(s);
VERIFY( p.compare(s) == 0 );
VERIFY( p.compare(s.c_str()) == 0 );
VERIFY( p.compare(p0) == p.compare(s0) );
VERIFY( p.compare(p0) == p.compare(s0.c_str()) );
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,69 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.4 path concatenation [path.concat]
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
const path p("/foo/bar");
path pp = p;
pp += p;
VERIFY( pp.native() == "/foo/bar/foo/bar" );
VERIFY( std::distance(pp.begin(), pp.end()) == 5 );
path q("foo/bar");
path qq = q;
qq += q;
VERIFY( qq.native() == "foo/barfoo/bar" );
VERIFY( std::distance(qq.begin(), qq.end()) == 3 );
q += p;
VERIFY( q.native() == "foo/bar/foo/bar" );
VERIFY( std::distance(q.begin(), q.end()) == 4 );
}
void
test02()
{
for (path p : __gnu_test::test_paths)
{
auto prior_native = p.native();
path x("//blah/di/blah");
p += x;
VERIFY( p.native() == prior_native + x.native() );
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,56 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.4 path concatenation [path.concat]
#include <filesystem>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
path p("/");
p += path::string_type("foo");
VERIFY( p.filename() == "foo" );
p += "bar";
VERIFY( p.filename() == "foobar" );
p += '/';
VERIFY( p.parent_path() == "/foobar" && p.filename() == "" );
#if _GLIBCXX_USE_WCHAR_T
p += L"baz.txt";
#else
p += "baz.txt";
#endif
VERIFY( p.filename() == "baz.txt" );
p.concat("/dir/");
VERIFY( p.parent_path() == "/foobar/baz.txt/dir" && p.filename() == "" );
std::string file = "file";
p.concat(file.begin(), file.end());
VERIFY( p.filename() == "file" );
}
int
main()
{
test01();
}

View File

@ -0,0 +1,55 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.1 path constructors [path.construct]
#include <filesystem>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
for (const path& p : __gnu_test::test_paths)
{
path copy = p;
__gnu_test::compare_paths(p, copy);
}
}
void
test02()
{
for (const path& p : __gnu_test::test_paths)
{
path copy = p;
path move = std::move(copy);
__gnu_test::compare_paths(p, move);
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,51 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.1 path constructors [path.construct]
#include <filesystem>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
path p;
VERIFY( p.empty() );
VERIFY( !p.has_root_path() );
VERIFY( !p.has_root_name() );
VERIFY( !p.has_root_directory() );
VERIFY( !p.has_relative_path() );
VERIFY( !p.has_parent_path() );
VERIFY( !p.has_filename() );
VERIFY( !p.has_stem() );
VERIFY( !p.has_extension() );
VERIFY( !p.is_absolute() );
VERIFY( p.is_relative() );
VERIFY( std::distance(p.begin(), p.end()) == 0 );
}
int
main()
{
test01();
}

View File

@ -0,0 +1,40 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.1 path constructors [path.construct]
#include <filesystem>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
path p("/foo/bar", std::locale::classic());
VERIFY( p.string() == "/foo/bar" );
}
int
main()
{
test01();
}

View File

@ -0,0 +1,112 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.1 path constructors [path.construct]
#include <filesystem>
#include <string>
#include <testsuite_fs.h>
#include <testsuite_iterators.h>
using std::filesystem::path;
using __gnu_test::compare_paths;
void
test01()
{
for (std::string s : __gnu_test::test_paths)
{
path p1 = s;
path p2( s.begin(), s.end() );
path p3( s.c_str() );
path p4( s.c_str(), s.c_str() + s.size() );
compare_paths(p1, p2);
compare_paths(p1, p3);
compare_paths(p1, p4);
#if _GLIBCXX_USE_WCHAR_T
std::wstring ws(s.begin(), s.end());
path p5 = ws;
path p6( ws.begin(), ws.end() );
path p7( ws.c_str() );
path p8( ws.c_str(), ws.c_str() + ws.size() );
compare_paths(p1, p5);
compare_paths(p1, p6);
compare_paths(p1, p7);
compare_paths(p1, p8);
#endif
using __gnu_test::test_container;
using __gnu_test::input_iterator_wrapper;
// Test with input iterators and const value_types
test_container<char, input_iterator_wrapper>
r1((char*)s.c_str(), (char*)s.c_str() + s.size());
path p9(r1.begin(), r1.end());
compare_paths(p1, p9);
test_container<char, input_iterator_wrapper>
r2((char*)s.c_str(), (char*)s.c_str() + s.size() + 1); // includes null-terminator
path p10(r2.begin());
compare_paths(p1, p10);
test_container<const char, input_iterator_wrapper>
r3(s.c_str(), s.c_str() + s.size());
path p11(r3.begin(), r3.end());
compare_paths(p1, p11);
test_container<const char, input_iterator_wrapper>
r4(s.c_str(), s.c_str() + s.size() + 1); // includes null-terminator
path p12(r4.begin());
compare_paths(p1, p12);
#if _GLIBCXX_USE_WCHAR_T
// Test with input iterators and const value_types
test_container<wchar_t, input_iterator_wrapper>
r5((wchar_t*)ws.c_str(), (wchar_t*)ws.c_str() + ws.size());
path p13(r5.begin(), r5.end());
compare_paths(p1, p13);
test_container<wchar_t, input_iterator_wrapper>
r6((wchar_t*)ws.c_str(), (wchar_t*)ws.c_str() + ws.size() + 1); // includes null-terminator
path p14(r6.begin());
compare_paths(p1, p14);
test_container<const wchar_t, input_iterator_wrapper>
r7(ws.c_str(), ws.c_str() + ws.size());
path p15(r7.begin(), r7.end());
compare_paths(p1, p15);
test_container<const wchar_t, input_iterator_wrapper>
r8(ws.c_str(), ws.c_str() + ws.size() + 1); // includes null-terminator
path p16(r8.begin());
compare_paths(p1, p16);
#endif
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,56 @@
// { dg-options "-lstdc++fs -std=gnu++17" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2016-2017 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/>.
// 8.4.1 path constructors [path.construct]
#include <filesystem>
#include <string_view>
#include <string>
#include <testsuite_fs.h>
using std::filesystem::path;
using __gnu_test::compare_paths;
void
test01()
{
for (std::string s : __gnu_test::test_paths)
{
path p1 = s;
std::string_view sv(s);
path p2 = sv;
compare_paths(p1, p2);
#if _GLIBCXX_USE_WCHAR_T
std::wstring ws(s.begin(), s.end());
path p3 = ws;
std::wstring_view wsv(ws);
path p4 = wsv;
compare_paths(p1, p4);
#endif
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,70 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
VERIFY( path("/foo/bar.txt").extension() == path(".txt") );
VERIFY( path("/foo/bar.baz.txt").extension() == path(".txt") );
VERIFY( path(".bar.baz.txt").extension() == path(".txt") );
VERIFY( path(".profile").extension() == path("") );
VERIFY( path(".profile.old").extension() == path(".old") );
VERIFY( path("..abc").extension() == path(".abc") );
VERIFY( path("...abc").extension() == path(".abc") );
VERIFY( path("abc..def").extension() == path(".def") );
VERIFY( path("abc...def").extension() == path(".def") );
VERIFY( path("abc.").extension() == path(".") );
VERIFY( path("abc..").extension() == path(".") );
VERIFY( path("abc.d.").extension() == path(".") );
VERIFY( path("..").extension() == path("") );
VERIFY( path(".").extension() == path("") );
VERIFY( path().extension() == path() );
}
void
test02()
{
for (const path& p : __gnu_test::test_paths)
{
auto stem = p.stem();
auto ext = p.extension();
auto file = p.filename();
VERIFY( stem.native() + ext.native() == file.native() );
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,70 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// C++17 30.10.7.4.9 path decomposition [fs.path.decompose]
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
VERIFY( path("/foo/bar.txt").filename() == "bar.txt" );
VERIFY( path("/foo/bar").filename() == "bar" );
VERIFY( path("/foo/bar/").filename() == "" );
VERIFY( path("/").filename() == "" );
#ifdef __CYGWIN__
VERIFY( path("//host").filename() == "" );
#else
VERIFY( path("//host").filename() == "host" );
#endif
VERIFY( path(".").filename() == "." );
VERIFY( path("..").filename() == ".." );
}
void
test02()
{
for (const path& p : __gnu_test::test_paths)
{
path f = p.filename();
if (p.empty())
VERIFY( f.empty() );
else
{
const path back = *--p.end();
if (back.has_root_path())
VERIFY( f.empty() );
else
VERIFY( f == back );
}
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,73 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
path p0;
VERIFY( p0.parent_path() == p0 );
path p1 = "foo";
VERIFY( p1.parent_path() == p0 );
path p2 = "foo/bar";
VERIFY( p2.parent_path() == p1 );
path p3 = "/foo/bar";
VERIFY( p3.parent_path() == path("/foo") );
VERIFY( p3.parent_path().parent_path() == path("/") );
VERIFY( p3.parent_path().parent_path().parent_path() == path("/") );
path p4 = "/";
VERIFY( p4.parent_path() == p4 );
}
void
test02()
{
for (const path& p : __gnu_test::test_paths)
{
if (p.begin() == p.end())
continue;
if (p.has_relative_path())
{
path pp;
for (auto i = p.begin(), end = --p.end(); i != end; ++i)
{
pp /= *i;
}
VERIFY( p.parent_path() == pp );
}
else
VERIFY( p.parent_path() == p );
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,70 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
path p1 = "foo";
VERIFY( p1.relative_path() == p1 );
path p2 = "foo/bar";
VERIFY( p2.relative_path() == p2 );
path p3 = "/foo/bar";
VERIFY( p3.relative_path() == p2 );
}
#include <iostream> // XXX
void
test02()
{
for (const path& p : __gnu_test::test_paths)
{
bool after_root = false;
const path prel = p.relative_path();
VERIFY( !prel.has_root_name() );
path rel;
for (const auto& cmpt : p)
{
if (!cmpt.has_root_path())
after_root = true;
if (after_root)
rel /= cmpt;
}
if (prel != rel)
std::cout << prel << ' ' << rel << '\n';
VERIFY( prel == rel );
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,59 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
path p1 = "foo/bar";
VERIFY( p1.root_directory() == path() );
path p2 = "/foo/bar";
VERIFY( p2.root_directory() == path("/") );
path p3 = "//foo";
VERIFY( p3.root_directory() == path("/") );
path p4 = "///foo";
VERIFY( p4.root_directory() == path("/") );
}
void
test02()
{
for (const path& p : __gnu_test::test_paths)
{
path rootdir = p.root_directory();
VERIFY( !rootdir.has_relative_path() );
VERIFY( rootdir.empty() || rootdir.native() == "/");
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,43 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
VERIFY( path("/foo/bar.txt").extension() == ".txt" );
VERIFY( path("/foo/bar.baz.txt").extension() == ".txt" );
VERIFY( path(".").extension().empty() );
VERIFY( path("..").extension().empty() );
}
int
main()
{
test01();
}

View File

@ -0,0 +1,61 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// C++17 30.10.7.4.9 path decomposition [fs.path.decompose]
#include <filesystem>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
path p1 = "foo/bar";
VERIFY( p1.root_path() == path() );
path p2 = "/foo/bar";
VERIFY( p2.root_path() == path("/") );
}
#undef VERIFY
#define VERIFY(X) do { if (!(X)) { __builtin_puts("FAIL: " #X); } } while(false)
#define DUMP(X, Y, Z) do { if (!(Y == Z)) { __builtin_printf("%s %s %s\n", X.c_str(), Y.c_str(), Z.c_str()); } } while(false)
void
test02()
{
for (const path& p : __gnu_test::test_paths)
{
path rootp = p.root_path();
path rootn = p.root_name();
path rootd = p.root_directory();
VERIFY( rootp == (rootn / rootd) );
DUMP(p, rootp , (rootn / rootd) );
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,62 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
VERIFY( path("/foo/bar.txt").stem() == path("bar") );
path p = "foo.bar.baz.tar";
std::vector<std::string> v;
for (; !p.extension().empty(); p = p.stem())
v.push_back(p.extension().native());
VERIFY( v.at(0) == ".tar" );
VERIFY( v.at(1) == ".baz" );
VERIFY( v.at(2) == ".bar" );
VERIFY( path(".profile").stem() == path(".profile") );
VERIFY( path(".profile.old").stem() == path(".profile") );
VERIFY( path("..abc").stem() == path(".") );
VERIFY( path("...abc").stem() == path("..") );
VERIFY( path("abc..def").stem() == path("abc.") );
VERIFY( path("abc...def").stem() == path("abc..") );
VERIFY( path("abc.").stem() == path("abc") );
VERIFY( path("abc..").stem() == path("abc.") );
VERIFY( path("abc.d.").stem() == path("abc.d") );
VERIFY( path("..").stem() == path("..") );
VERIFY( path(".").stem() == path(".") );
VERIFY( path().stem() == path() );
}
int
main()
{
test01();
}

View File

@ -0,0 +1,52 @@
// Copyright (C) 2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
// C++17 [fs.path.gen] p2
VERIFY( path("foo/./bar/..").lexically_normal() == "foo/" );
VERIFY( path("foo/.///bar/../").lexically_normal() == "foo/" );
}
void
test02()
{
VERIFY( path("foo/../bar").lexically_normal() == "bar" );
VERIFY( path("../foo/../bar").lexically_normal() == "../bar" );
VERIFY( path("foo/../").lexically_normal() == "." );
VERIFY( path("../../").lexically_normal() == "../.." );
VERIFY( path("../").lexically_normal() == ".." );
VERIFY( path("./").lexically_normal() == "." );
VERIFY( path().lexically_normal() == "" );
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,53 @@
// Copyright (C) 2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
// C++17 [fs.path.gen] p5
VERIFY( path("/a/d").lexically_proximate("/a/b/c") == "../../d" );
VERIFY( path("/a/b/c").lexically_proximate("/a/d") == "../b/c" );
VERIFY( path("a/b/c").lexically_proximate("a") == "b/c" );
VERIFY( path("a/b/c").lexically_proximate("a/b/c/x/y") == "../.." );
VERIFY( path("a/b/c").lexically_proximate("a/b/c") == "." );
VERIFY( path("a/b").lexically_proximate("c/d") == "../../a/b" );
}
void
test02()
{
path p = "a/b/c";
VERIFY( p.lexically_proximate(p) == "." );
VERIFY( p.lexically_proximate("a/../a/b/../b/c/../c/.") == "../../b/c" );
VERIFY( p.lexically_proximate("../../../") == p );
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,53 @@
// Copyright (C) 2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
// C++17 [fs.path.gen] p5
VERIFY( path("/a/d").lexically_relative("/a/b/c") == "../../d" );
VERIFY( path("/a/b/c").lexically_relative("/a/d") == "../b/c" );
VERIFY( path("a/b/c").lexically_relative("a") == "b/c" );
VERIFY( path("a/b/c").lexically_relative("a/b/c/x/y") == "../.." );
VERIFY( path("a/b/c").lexically_relative("a/b/c") == "." );
VERIFY( path("a/b").lexically_relative("c/d") == "../../a/b" );
}
void
test02()
{
path p = "a/b/c";
VERIFY( p.lexically_relative(p) == "." );
VERIFY( p.lexically_relative("a/../a/b/../b/c/../c/.") == "../../b/c" );
VERIFY( p.lexically_relative("../../../") == "" );
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,55 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2017 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/>.
// C++17 30.10.7.4.7 path generic format observers [fs.path.generic.obs]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
VERIFY( path().generic_string() == "" );
VERIFY( path("/").generic_string() == "/" );
VERIFY( path("////").generic_string() == "/" );
#ifdef __CYGWIN__
VERIFY( path("//a").generic_string() == "//a" );
VERIFY( path("//a/").generic_string() == "//a/" );
VERIFY( path("//a/b").generic_string() == "//a/b" );
#else
VERIFY( path("//a").generic_string() == "/a" );
VERIFY( path("//a/").generic_string() == "/a/" );
VERIFY( path("//a/b").generic_string() == "/a/b" );
#endif
VERIFY( path("/a//b").generic_string() == "/a/b" );
VERIFY( path("/a//b/").generic_string() == "/a/b/" );
VERIFY( path("/a//b//").generic_string() == "/a/b/" );
VERIFY( path("/a//b//.").generic_string() == "/a/b/." );
}
int
main()
{
test01();
}

View File

@ -0,0 +1,127 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// C++17 30.10.7.5 path iterators [fs.path.itr]
#include <filesystem>
#include <vector>
#include <algorithm>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
path p;
VERIFY( p.begin() == p.end() );
std::vector<path> v, v2;
p = "/";
v.assign(p.begin(), p.end());
v2 = { "/" };
VERIFY( v == v2 );
p = "filename";
v.assign(p.begin(), p.end());
v2 = { "filename" };
VERIFY( v == v2 );
p = "dir/.";
v.assign(p.begin(), p.end());
v2 = { "dir", "." };
VERIFY( v == v2 );
p = "dir/";
v.assign(p.begin(), p.end());
v2 = { "dir", "" };
VERIFY( v == v2 );
p = "//rootname/dir/.";
v.assign(p.begin(), p.end());
#ifdef __CYGWIN__
v2 = { "//rootname", "/", "dir", "." };
#else
v2 = { "/", "rootname", "dir", "." };
#endif
VERIFY( v == v2 );
p = "//rootname/dir/";
v.assign(p.begin(), p.end());
#ifdef __CYGWIN__
v2 = { "//rootname", "/", "dir", "" };
#else
v2 = { "/", "rootname", "dir", "" };
#endif
VERIFY( v == v2 );
p = "//rootname/dir/filename";
v.assign(p.begin(), p.end());
#ifdef __CYGWIN__
v2 = { "//rootname", "/", "dir", "filename" };
#else
v2 = { "/", "rootname", "dir", "filename" };
#endif
VERIFY( v == v2 );
}
void
test02()
{
using reverse_iterator = std::reverse_iterator<path::iterator>;
std::vector<path> fwd, rev;
for (const path& p : __gnu_test::test_paths)
{
const auto begin = p.begin(), end = p.end();
fwd.assign(begin, end);
rev.assign(reverse_iterator(end), reverse_iterator(begin));
VERIFY( fwd.size() == rev.size() );
VERIFY( std::equal(fwd.begin(), fwd.end(), rev.rbegin()) );
}
}
void
test03()
{
path paths[] = { "single", "multiple/elements" };
for (const path& p : paths)
for (auto iter = p.begin(); iter != p.end(); ++iter)
{
auto iter2 = iter;
++iter;
iter2++;
VERIFY( iter2 == iter );
--iter;
iter2--;
VERIFY( iter2 == iter );
}
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,46 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.5 path modifiers [path.modifiers]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
for (path p : __gnu_test::test_paths)
{
path empty;
p.clear();
VERIFY( p.empty() );
__gnu_test::compare_paths(p, empty);
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,64 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.5 path modifiers [path.modifiers]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
using std::filesystem::path;
template<typename T, T sep>
struct checker
{
static void check(const char* s) { }
};
template<>
struct checker<char, '/'>
{
static void check()
{
VERIFY( path("foo/bar").make_preferred() == "foo/bar" );
}
};
template<>
struct checker<wchar_t, L'\\'>
{
static void check()
{
VERIFY( path("foo/bar").make_preferred() == L"foo\\bar" );
}
};
void
test01()
{
checker<path::value_type, path::preferred_separator>::check();
}
int
main()
{
test01();
}

View File

@ -0,0 +1,62 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// C++17 30.10.7.4.5 path modifiers [fs.path.modifiers]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
// C++17 [fs.path.modifiers] p8
VERIFY( path("foo/bar").remove_filename() == "foo/" );
VERIFY( path("foo/").remove_filename() == "foo/" );
VERIFY( path("/foo").remove_filename() == "/" );
VERIFY( path("/").remove_filename() == "/" );
}
#undef VERIFY
#define VERIFY(X) do { if (!(X)) { __builtin_puts("FAIL: " #X); } } while(false)
#define DUMP(X, Y) do { if (!(X == Y)) { __builtin_printf("%s %s\n", X.c_str(), Y.c_str()); } } while(false)
void
test02()
{
for (const path& p : __gnu_test::test_paths)
{
path p2(p);
p2.remove_filename();
p2 /= p.filename();
VERIFY( p2 == p );
DUMP( p2 , p );
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,53 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.5 path modifiers [path.modifiers]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
VERIFY( path("/foo.txt").replace_extension("cpp") == "/foo.cpp" );
VERIFY( path("/foo.txt").replace_extension(".cpp") == "/foo.cpp" );
VERIFY( path("/").replace_extension("bar") == "/.bar" );
}
void
test02()
{
for (const path& p : __gnu_test::test_paths)
{
path p2 = p;
VERIFY(p2.replace_extension(p2.extension()) == p);
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,59 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// C++17 30.10.7.4.5 path modifiers [fs.path.modifiers]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
// C++17 [fs.path.modifiers] p11
VERIFY( path("/foo").replace_filename("bar") == "/bar" );
VERIFY( path("/").replace_filename("bar") == "/bar" );
}
#undef VERIFY
#define VERIFY(X) do { if (!(X)) { __builtin_puts("FAIL: " #X); } } while(false)
#define DUMP(X, Y) do { if (!(X == Y)) { __builtin_printf("%s %s\n", X.c_str(), Y.c_str()); } } while(false)
void
test02()
{
for (const path& p : __gnu_test::test_paths)
{
path p2(p);
p2.replace_filename(p.filename());
VERIFY( p2 == p );
DUMP( p2 , p );
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,45 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.5 path modifiers [path.modifiers]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
const path p("/foo/bar");
path p1;
path p2 = p;
p1.swap(p2);
VERIFY( p2.empty() );
__gnu_test::compare_paths(p1, p);
}
int
main()
{
test01();
}

View File

@ -0,0 +1,70 @@
// Copyright (C) 2016-2017 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++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <string>
#include <testsuite_hooks.h>
void
test01()
{
using namespace std::filesystem;
const std::string s = "abc";
path p(s);
VERIFY( p.native() == s );
VERIFY( p.c_str() == s );
VERIFY( static_cast<std::string>(p) == s );
std::string s2 = p; // implicit conversion
VERIFY( s2 == p.native() );
}
void
test02()
{
using namespace std::filesystem;
const char* s = "abc";
path p(s);
auto str = p.string<char>();
VERIFY( str == u"abc" );
VERIFY( str == p.string() );
auto strw = p.string<wchar_t>();
VERIFY( strw == L"abc" );
VERIFY( strw == p.wstring() );
auto str16 = p.string<char16_t>();
VERIFY( str16 == u"abc" );
VERIFY( str16 == p.u16string() );
auto str32 = p.string<char32_t>();
VERIFY( str32 == U"abc" );
VERIFY( str32 == p.u32string() );
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,52 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.6 path non-member functions [path.non-member]
#include <filesystem>
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
using std::filesystem::path;
void
test01()
{
VERIFY( hash_value(path("a//b")) == hash_value(path("a/b")) );
VERIFY( hash_value(path("a/")) == hash_value(path("a//")) );
}
void
test02()
{
for (const path& p : __gnu_test::test_paths)
{
path pp = p.native();
VERIFY( hash_value(p) == hash_value(pp) );
}
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,44 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
for (const std::string& s : __gnu_test::test_paths)
{
VERIFY( s.empty() == path(s).empty() );
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,44 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
for (const path& p : __gnu_test::test_paths)
{
VERIFY( p.has_extension() == !p.extension().empty() );
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,44 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
for (const path& p : __gnu_test::test_paths)
{
VERIFY( p.has_filename() == !p.filename().empty() );
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,44 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
for (const path& p : __gnu_test::test_paths)
{
VERIFY( p.has_parent_path() == !p.parent_path().empty() );
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,44 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
for (const path& p : __gnu_test::test_paths)
{
VERIFY( p.has_relative_path() == !p.relative_path().empty() );
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,44 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
for (const path& p : __gnu_test::test_paths)
{
VERIFY( p.has_root_directory() == !p.root_directory().empty() );
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,44 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
for (const path& p : __gnu_test::test_paths)
{
VERIFY( p.has_root_name() == !p.root_name().empty() );
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,44 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
for (const path& p : __gnu_test::test_paths)
{
VERIFY( p.has_root_path() == !p.root_path().empty() );
}
}
int
main()
{
test01();
}

View File

@ -0,0 +1,44 @@
// { dg-options "-std=gnu++17 -lstdc++fs" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
// Copyright (C) 2014-2017 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/>.
// 8.4.9 path decomposition [path.decompose]
#include <filesystem>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
using std::filesystem::path;
void
test01()
{
for (const path& p : __gnu_test::test_paths)
{
VERIFY( p.has_stem() == !p.stem().empty() );
}
}
int
main()
{
test01();
}

Some files were not shown because too many files have changed in this diff Show More