Commit 641cb5a6 by Jonathan Wakely Committed by Jonathan Wakely

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
parent 9c71c00f
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
......
......@@ -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 \
......
......@@ -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 \
......
// 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
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......@@ -122,6 +122,7 @@
#include <shared_mutex>
#endif
#if __cplusplus > 201402L
#if __cplusplus >= 201703L
#include <charconv>
#include <filesystem>
#endif
// <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
......@@ -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::',
......
......@@ -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 = \
......
......@@ -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 = \
......
// Class filesystem::directory_entry etc. -*- C++ -*-
// Class experimental::filesystem::directory_entry etc. -*- C++ -*-
// Copyright (C) 2015-2017 Free Software Foundation, Inc.
//
......
// Filesystem operations -*- C++ -*-
// Filesystem TS operations -*- C++ -*-
// Copyright (C) 2015-2017 Free Software Foundation, Inc.
//
......
// Class filesystem::path -*- C++ -*-
// Class experimental::filesystem::path -*- C++ -*-
// Copyright (C) 2015-2017 Free Software Foundation, Inc.
//
......
// 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"
// 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"
// 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"
// 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
// 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
// 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_STATVFS_H
# include <sys/statvfs.h>
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
# include <sys/stat.h> // stat, utimensat, fchmodat
#endif
#ifdef _GLIBCXX_USE_SENDFILE
# include <sys/sendfile.h>
#ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
# include <sys/statvfs.h> // statvfs
#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;
......
// 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
// 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));
}
// 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();
}
// 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();
}
// 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();
}
// { 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();
}
// 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();
}
// { 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// { 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// { 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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment