PR libstdc++/78870 support std::filesystem on Windows
PR libstdc++/78870 support std::filesystem on Windows * config.h.in: Regenerate. * configure: Regenerate. * configure.ac: Check for link, readlink and symlink. * include/bits/fs_path.h (path::operator/=(const path&)): Move definition out of class body. (path::is_absolute(), path::_M_append(path)): Likewise. (operator<<(basic_ostream, const path&)): Use std::quoted directly. (operator>>(basic_istream, path&)): Likewise. (u8path): Reorder definitions and fix Windows implementation. (path::is_absolute()): Define inline and fix for Windows. [!_GLIBCXX_FILESYSTEM_IS_WINDOWS] (path::operator/=(const path&)): Define POSIX version inline. (path::_M_append(path)): Define inline. * include/experimental/bits/fs_path.h (path::is_absolute()): Move definition out of class body. (operator<<(basic_ostream, const path&)): Fix type of delimiter and escape characters. (operator>>(basic_istream, path&)): Likewise. (path::is_absolute()): Define inline and fix for Windows. * src/filesystem/dir-common.h (__gnu_posix): New namespace. (__gnu_posix::char_type, __gnu_posix::DIR, __gnu_posix::dirent) (__gnu_posix::opendir, __gnu_posix::readdir, __gnu_posix::closedir): Define as adaptors for Windows functions/types or as using-declarations for POSIX functions/types. (_Dir_base, get_file_type): Qualify names to use declarations from __gnu_posix namespace. (_Dir_base::is_dor_or_dotdot): New helper functions. * src/filesystem/dir.cc (_Dir, recursive_directory_iterator): Qualify names to use declarations from __gnu_posix namespace. * src/filesystem/ops-common.h (__gnu_posix): New nested namespace. (__gnu_posix::open, __gnu_posix::close, __gnu_posix::stat_type) (__gnu_posix::stat, __gnu_posix::lstat, __gnu_posix::mode_t) (__gnu_posix::chmod, __gnu_posix::mkdir, __gnu_posix::getcwd) (__gnu_posix::chdir, __gnu_posix::utimbuf, __gnu_posix::utime) (__gnu_posix::rename, __gnu_posix::truncate, __gnu_posix::char_type): Define as adaptors for Windows functions/types or as using-declarations for POSIX functions/types. (stat_type, do_copy_file): Qualify names to use declarations from __gnu_posix namespace. (do_space): Declare new function. (make_file_type): Only use S_ISLNK if defined. * src/filesystem/ops.cc (char_ptr, filesystem::canonical): Use path::value_type not char. (filesystem::copy, create_dir, filesystem::create_directory): Qualify names to use declarations from __gnu_posix namespace. (filesystem::create_hard_link): Check HAVE_LINK autoconf macro and add implementation for Windows. (filesystem::create_symlink): Check HAVE_SYMLINK autoconf macro. (filesystem::current_path(error_code&)): Use __gnu_posix::getcwd. [!_PC_PATH_MAX]: Don't use pathconf. [PATH_MAX]: Use if defined. (filesystem::current_path(const path&, error_code&)) (filesystem::equivalent, do_stat, filesystem::hard_link_count) (filesystem::last_write_time, filesystem::permissions): Use names from __gnu_posix. (filesystem::read_symlink): Check HAVE_READLINK autoconf macro. (filesystem::remove) [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Add implementation for Windows. (filesystem::rename, filesystem::resize_file): Use names from __gnu_posix. (filesystem::space): Use do_space. [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Get absolute path to directory. (filesystem::status, filesystem::symlink_status): Use names from __gnu_posix. (filesystem::temp_directory_path): Add implementation for Windows. * src/filesystem/path.cc (dot): Define constant. (path::replace_extension): Use dot. (path::_M_find_extension): Likewise. Use path::string_type not std::string. (path::_M_split_cmpts): Use dot. (filesystem_error::_M_get_what): Use u8string() not native(). * src/filesystem/std-dir.cc (_Dir, recursive_directory_iterator): Qualify names to use declarations from __gnu_posix namespace. * src/filesystem/std-ops.cc (filesystem::absolute(const path&)): Use correct error_code. (filesystem::absolute(const path&, error_code&)): Add implementation for Windows. (char_ptr, filesystem::canonical): Use path::value_type not char. (do_copy_file): Use names from __gnu_posix. [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Do not use fchmod, fchmodat or sendfile. (filesystem::copy, create_dir, filesystem::create_directory): Qualify names to use declarations from __gnu_posix namespace. (filesystem::create_hard_link): Check HAVE_LINK autoconf macro and add implementation for Windows. (filesystem::create_symlink): Check HAVE_SYMLINK autoconf macro. (filesystem::current_path(error_code&)): Use __gnu_posix::getcwd. [!_PC_PATH_MAX]: Don't use pathconf. [PATH_MAX]: Use if defined. (filesystem::current_path(const path&, error_code&)) (filesystem::equivalent, do_stat, filesystem::hard_link_count) (filesystem::last_write_time, filesystem::permissions): Use names from __gnu_posix. (filesystem::read_symlink): Check HAVE_READLINK autoconf macro. (filesystem::remove) [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Add implementation for Windows. (filesystem::rename, filesystem::resize_file): Use names from __gnu_posix. (do_space): Define. (filesystem::space): Use do_space. (filesystem::status, filesystem::symlink_status): Use names from __gnu_posix. (filesystem::temp_directory_path): Add implementation for Windows. * src/filesystem/std-path.cc [_GLIBCXX_FILESYSTEM_IS_WINDOWS] (path::operator/=(const path&)): Define for Windows. (dot): Define constant. (path::replace_extension, is_dot): Use dot. (path::lexically_normal): Check _M_type instead of calling non-existent function. (path::_M_find_extension): Use dot. Use path::string_type not std::string. (path::_M_split_cmpts): Use dot. (filesystem_error::_M_get_what): Use u8string() not native(). * testsuite/27_io/filesystem/iterators/directory_iterator.cc: Do not use symlinks. * testsuite/27_io/filesystem/iterators/recursive_directory_iterator.cc: Likewise. * testsuite/27_io/filesystem/operations/absolute.cc: Use __gnu_test::root_path() instead of "/" and add Windows-specific tests. * testsuite/27_io/filesystem/operations/canonical.cc: Use path::string() to get narrow string, not path::native(). * testsuite/27_io/filesystem/operations/copy.cc: Construct fstreams with std::filesystem::path not std::basic_string. * testsuite/27_io/filesystem/operations/copy_file.cc: Likewise. * testsuite/27_io/filesystem/operations/exists.cc: Use __gnu_test::root_path() instead of "/". * testsuite/27_io/filesystem/operations/is_empty.cc: Construct fstreams with std::filesystem::path not std::basic_string. * testsuite/27_io/filesystem/operations/last_write_time.cc: Use path::string() to get narrow string. * testsuite/27_io/filesystem/operations/space.cc: Check results for errors, expect sensible values otherwise. * testsuite/27_io/filesystem/operations/temp_directory_path.cc: Add helpers for adjusting the environment on Windows. * testsuite/27_io/filesystem/path/append/path.cc: Test Windows-specific behaviour. * testsuite/27_io/filesystem/path/construct/format.cc: Fix creation of path::string_type objects. * testsuite/27_io/filesystem/path/construct/locale.cc: Compare native string to wide string on Windows. * testsuite/27_io/filesystem/path/decompose/root_directory.cc: Allow for backslash as root-directory. * testsuite/27_io/filesystem/path/decompose/stem.cc: Use path::string() to get narrow string. * testsuite/27_io/filesystem/path/itr/traversal.cc: Test Windows-style paths. * testsuite/27_io/filesystem/path/native/string.cc: Use string_type not std::string. * testsuite/27_io/filesystem/path/query/is_absolute.cc: Adjust for different definintion of absolute paths on Windows. * testsuite/experimental/filesystem/iterators/directory_iterator.cc: Do not use symlinks. * testsuite/experimental/filesystem/operations/absolute.cc: Test Windows behaviour. * testsuite/experimental/filesystem/operations/copy.cc: Construct fstreams with NTCTS not std::basic_string. * testsuite/experimental/filesystem/operations/copy_file.cc: Likewise. * testsuite/experimental/filesystem/operations/exists.cc: Use __gnu_test::root_path() instead of "/". * testsuite/experimental/filesystem/operations/is_empty.cc: Construct fstreams with NTCTS not std::basic_string. * testsuite/experimental/filesystem/operations/last_write_time.cc: Use path::string() to get narrow string. * testsuite/experimental/filesystem/operations/space.cc: Use __gnu_test::root_path() instead of "/". * testsuite/experimental/filesystem/operations/temp_directory_path.cc: Add helpers for adjusting the environment on Windows. * testsuite/experimental/filesystem/path/append/path.cc: Use path::string() to get narrow strings for comparisons. * testsuite/experimental/filesystem/path/concat/path.cc: Likewise. * testsuite/experimental/filesystem/path/decompose/root_directory.cc: Likewise. * testsuite/experimental/filesystem/path/decompose/stem.cc: Likewise. * testsuite/experimental/filesystem/path/native/string.cc: Use string_type not std::string. * testsuite/experimental/filesystem/path/query/is_absolute.cc: Adjust for different definintion of absolute paths on Windows. * testsuite/util/testsuite_fs.h (__gnu_test::root_path()): New function. (__gnu_test::scoped_file): Construct fstreams with NTCTS not std::basic_string. From-SVN: r261034
This commit is contained in:
parent
c931509704
commit
9534a5e62d
49 changed files with 1047 additions and 363 deletions
|
@ -1,3 +1,189 @@
|
|||
2018-05-24 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/78870 support std::filesystem on Windows
|
||||
* config.h.in: Regenerate.
|
||||
* configure: Regenerate.
|
||||
* configure.ac: Check for link, readlink and symlink.
|
||||
* include/bits/fs_path.h (path::operator/=(const path&)): Move
|
||||
definition out of class body.
|
||||
(path::is_absolute(), path::_M_append(path)): Likewise.
|
||||
(operator<<(basic_ostream, const path&)): Use std::quoted directly.
|
||||
(operator>>(basic_istream, path&)): Likewise.
|
||||
(u8path): Reorder definitions and fix Windows implementation.
|
||||
(path::is_absolute()): Define inline and fix for Windows.
|
||||
[!_GLIBCXX_FILESYSTEM_IS_WINDOWS] (path::operator/=(const path&)):
|
||||
Define POSIX version inline.
|
||||
(path::_M_append(path)): Define inline.
|
||||
* include/experimental/bits/fs_path.h (path::is_absolute()): Move
|
||||
definition out of class body.
|
||||
(operator<<(basic_ostream, const path&)): Fix type of delimiter and
|
||||
escape characters.
|
||||
(operator>>(basic_istream, path&)): Likewise.
|
||||
(path::is_absolute()): Define inline and fix for Windows.
|
||||
* src/filesystem/dir-common.h (__gnu_posix): New namespace.
|
||||
(__gnu_posix::char_type, __gnu_posix::DIR, __gnu_posix::dirent)
|
||||
(__gnu_posix::opendir, __gnu_posix::readdir, __gnu_posix::closedir):
|
||||
Define as adaptors for Windows functions/types or as
|
||||
using-declarations for POSIX functions/types.
|
||||
(_Dir_base, get_file_type): Qualify names to use declarations from
|
||||
__gnu_posix namespace.
|
||||
(_Dir_base::is_dor_or_dotdot): New helper functions.
|
||||
* src/filesystem/dir.cc (_Dir, recursive_directory_iterator): Qualify
|
||||
names to use declarations from __gnu_posix namespace.
|
||||
* src/filesystem/ops-common.h (__gnu_posix): New nested namespace.
|
||||
(__gnu_posix::open, __gnu_posix::close, __gnu_posix::stat_type)
|
||||
(__gnu_posix::stat, __gnu_posix::lstat, __gnu_posix::mode_t)
|
||||
(__gnu_posix::chmod, __gnu_posix::mkdir, __gnu_posix::getcwd)
|
||||
(__gnu_posix::chdir, __gnu_posix::utimbuf, __gnu_posix::utime)
|
||||
(__gnu_posix::rename, __gnu_posix::truncate, __gnu_posix::char_type):
|
||||
Define as adaptors for Windows functions/types or as
|
||||
using-declarations for POSIX functions/types.
|
||||
(stat_type, do_copy_file): Qualify names to use declarations from
|
||||
__gnu_posix namespace.
|
||||
(do_space): Declare new function.
|
||||
(make_file_type): Only use S_ISLNK if defined.
|
||||
* src/filesystem/ops.cc (char_ptr, filesystem::canonical): Use
|
||||
path::value_type not char.
|
||||
(filesystem::copy, create_dir, filesystem::create_directory): Qualify
|
||||
names to use declarations from __gnu_posix namespace.
|
||||
(filesystem::create_hard_link): Check HAVE_LINK autoconf macro and
|
||||
add implementation for Windows.
|
||||
(filesystem::create_symlink): Check HAVE_SYMLINK autoconf macro.
|
||||
(filesystem::current_path(error_code&)): Use __gnu_posix::getcwd.
|
||||
[!_PC_PATH_MAX]: Don't use pathconf.
|
||||
[PATH_MAX]: Use if defined.
|
||||
(filesystem::current_path(const path&, error_code&))
|
||||
(filesystem::equivalent, do_stat, filesystem::hard_link_count)
|
||||
(filesystem::last_write_time, filesystem::permissions): Use names
|
||||
from __gnu_posix.
|
||||
(filesystem::read_symlink): Check HAVE_READLINK autoconf macro.
|
||||
(filesystem::remove) [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Add
|
||||
implementation for Windows.
|
||||
(filesystem::rename, filesystem::resize_file): Use names from
|
||||
__gnu_posix.
|
||||
(filesystem::space): Use do_space.
|
||||
[_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Get absolute path to directory.
|
||||
(filesystem::status, filesystem::symlink_status): Use names from
|
||||
__gnu_posix.
|
||||
(filesystem::temp_directory_path): Add implementation for Windows.
|
||||
* src/filesystem/path.cc (dot): Define constant.
|
||||
(path::replace_extension): Use dot.
|
||||
(path::_M_find_extension): Likewise. Use path::string_type not
|
||||
std::string.
|
||||
(path::_M_split_cmpts): Use dot.
|
||||
(filesystem_error::_M_get_what): Use u8string() not native().
|
||||
* src/filesystem/std-dir.cc (_Dir, recursive_directory_iterator):
|
||||
Qualify names to use declarations from __gnu_posix namespace.
|
||||
* src/filesystem/std-ops.cc (filesystem::absolute(const path&)): Use
|
||||
correct error_code.
|
||||
(filesystem::absolute(const path&, error_code&)): Add implementation
|
||||
for Windows.
|
||||
(char_ptr, filesystem::canonical): Use path::value_type not char.
|
||||
(do_copy_file): Use names from __gnu_posix.
|
||||
[_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Do not use fchmod, fchmodat or
|
||||
sendfile.
|
||||
(filesystem::copy, create_dir, filesystem::create_directory): Qualify
|
||||
names to use declarations from __gnu_posix namespace.
|
||||
(filesystem::create_hard_link): Check HAVE_LINK autoconf macro and
|
||||
add implementation for Windows.
|
||||
(filesystem::create_symlink): Check HAVE_SYMLINK autoconf macro.
|
||||
(filesystem::current_path(error_code&)): Use __gnu_posix::getcwd.
|
||||
[!_PC_PATH_MAX]: Don't use pathconf.
|
||||
[PATH_MAX]: Use if defined.
|
||||
(filesystem::current_path(const path&, error_code&))
|
||||
(filesystem::equivalent, do_stat, filesystem::hard_link_count)
|
||||
(filesystem::last_write_time, filesystem::permissions): Use names
|
||||
from __gnu_posix.
|
||||
(filesystem::read_symlink): Check HAVE_READLINK autoconf macro.
|
||||
(filesystem::remove) [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Add
|
||||
implementation for Windows.
|
||||
(filesystem::rename, filesystem::resize_file): Use names from
|
||||
__gnu_posix.
|
||||
(do_space): Define.
|
||||
(filesystem::space): Use do_space.
|
||||
(filesystem::status, filesystem::symlink_status): Use names from
|
||||
__gnu_posix.
|
||||
(filesystem::temp_directory_path): Add implementation for Windows.
|
||||
* src/filesystem/std-path.cc
|
||||
[_GLIBCXX_FILESYSTEM_IS_WINDOWS] (path::operator/=(const path&)):
|
||||
Define for Windows.
|
||||
(dot): Define constant.
|
||||
(path::replace_extension, is_dot): Use dot.
|
||||
(path::lexically_normal): Check _M_type instead of calling
|
||||
non-existent function.
|
||||
(path::_M_find_extension): Use dot. Use path::string_type not
|
||||
std::string.
|
||||
(path::_M_split_cmpts): Use dot.
|
||||
(filesystem_error::_M_get_what): Use u8string() not native().
|
||||
* testsuite/27_io/filesystem/iterators/directory_iterator.cc: Do not
|
||||
use symlinks.
|
||||
* testsuite/27_io/filesystem/iterators/recursive_directory_iterator.cc:
|
||||
Likewise.
|
||||
* testsuite/27_io/filesystem/operations/absolute.cc: Use
|
||||
__gnu_test::root_path() instead of "/" and add Windows-specific tests.
|
||||
* testsuite/27_io/filesystem/operations/canonical.cc: Use
|
||||
path::string() to get narrow string, not path::native().
|
||||
* testsuite/27_io/filesystem/operations/copy.cc: Construct fstreams
|
||||
with std::filesystem::path not std::basic_string.
|
||||
* testsuite/27_io/filesystem/operations/copy_file.cc: Likewise.
|
||||
* testsuite/27_io/filesystem/operations/exists.cc: Use
|
||||
__gnu_test::root_path() instead of "/".
|
||||
* testsuite/27_io/filesystem/operations/is_empty.cc: Construct
|
||||
fstreams with std::filesystem::path not std::basic_string.
|
||||
* testsuite/27_io/filesystem/operations/last_write_time.cc: Use
|
||||
path::string() to get narrow string.
|
||||
* testsuite/27_io/filesystem/operations/space.cc: Check results for
|
||||
errors, expect sensible values otherwise.
|
||||
* testsuite/27_io/filesystem/operations/temp_directory_path.cc: Add
|
||||
helpers for adjusting the environment on Windows.
|
||||
* testsuite/27_io/filesystem/path/append/path.cc: Test
|
||||
Windows-specific behaviour.
|
||||
* testsuite/27_io/filesystem/path/construct/format.cc: Fix creation
|
||||
of path::string_type objects.
|
||||
* testsuite/27_io/filesystem/path/construct/locale.cc: Compare native
|
||||
string to wide string on Windows.
|
||||
* testsuite/27_io/filesystem/path/decompose/root_directory.cc: Allow
|
||||
for backslash as root-directory.
|
||||
* testsuite/27_io/filesystem/path/decompose/stem.cc: Use
|
||||
path::string() to get narrow string.
|
||||
* testsuite/27_io/filesystem/path/itr/traversal.cc: Test Windows-style
|
||||
paths.
|
||||
* testsuite/27_io/filesystem/path/native/string.cc: Use string_type
|
||||
not std::string.
|
||||
* testsuite/27_io/filesystem/path/query/is_absolute.cc: Adjust for
|
||||
different definintion of absolute paths on Windows.
|
||||
* testsuite/experimental/filesystem/iterators/directory_iterator.cc:
|
||||
Do not use symlinks.
|
||||
* testsuite/experimental/filesystem/operations/absolute.cc: Test
|
||||
Windows behaviour.
|
||||
* testsuite/experimental/filesystem/operations/copy.cc: Construct
|
||||
fstreams with NTCTS not std::basic_string.
|
||||
* testsuite/experimental/filesystem/operations/copy_file.cc: Likewise.
|
||||
* testsuite/experimental/filesystem/operations/exists.cc: Use
|
||||
__gnu_test::root_path() instead of "/".
|
||||
* testsuite/experimental/filesystem/operations/is_empty.cc: Construct
|
||||
fstreams with NTCTS not std::basic_string.
|
||||
* testsuite/experimental/filesystem/operations/last_write_time.cc:
|
||||
Use path::string() to get narrow string.
|
||||
* testsuite/experimental/filesystem/operations/space.cc: Use
|
||||
__gnu_test::root_path() instead of "/".
|
||||
* testsuite/experimental/filesystem/operations/temp_directory_path.cc:
|
||||
Add helpers for adjusting the environment on Windows.
|
||||
* testsuite/experimental/filesystem/path/append/path.cc: Use
|
||||
path::string() to get narrow strings for comparisons.
|
||||
* testsuite/experimental/filesystem/path/concat/path.cc: Likewise.
|
||||
* testsuite/experimental/filesystem/path/decompose/root_directory.cc:
|
||||
Likewise.
|
||||
* testsuite/experimental/filesystem/path/decompose/stem.cc: Likewise.
|
||||
* testsuite/experimental/filesystem/path/native/string.cc: Use
|
||||
string_type not std::string.
|
||||
* testsuite/experimental/filesystem/path/query/is_absolute.cc:
|
||||
Adjust for different definintion of absolute paths on Windows.
|
||||
* testsuite/util/testsuite_fs.h (__gnu_test::root_path()): New
|
||||
function.
|
||||
(__gnu_test::scoped_file): Construct fstreams with NTCTS not
|
||||
std::basic_string.
|
||||
|
||||
2018-05-31 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/85951
|
||||
|
|
|
@ -264,6 +264,9 @@
|
|||
/* Only used in build directory testsuite_hooks.h. */
|
||||
#undef HAVE_LIMIT_VMEM
|
||||
|
||||
/* Define to 1 if you have the `link' function. */
|
||||
#undef HAVE_LINK
|
||||
|
||||
/* Define if futex syscall is available. */
|
||||
#undef HAVE_LINUX_FUTEX
|
||||
|
||||
|
@ -339,6 +342,9 @@
|
|||
/* Define to 1 if you have the `quick_exit' function. */
|
||||
#undef HAVE_QUICK_EXIT
|
||||
|
||||
/* Define to 1 if you have the `readlink' function. */
|
||||
#undef HAVE_READLINK
|
||||
|
||||
/* Define to 1 if you have the `setenv' function. */
|
||||
#undef HAVE_SETENV
|
||||
|
||||
|
@ -408,6 +414,9 @@
|
|||
/* Define if strxfrm_l is available in <string.h>. */
|
||||
#undef HAVE_STRXFRM_L
|
||||
|
||||
/* Define to 1 if you have the `symlink' function. */
|
||||
#undef HAVE_SYMLINK
|
||||
|
||||
/* Define to 1 if the target runtime linker supports binding the same symbol
|
||||
to different versions. */
|
||||
#undef HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT
|
||||
|
|
13
libstdc++-v3/configure
vendored
13
libstdc++-v3/configure
vendored
|
@ -80047,6 +80047,19 @@ _ACEOF
|
|||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
for ac_func in link readlink symlink
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
eval as_val=\$$as_ac_var
|
||||
if test "x$as_val" = x""yes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
|
|
|
@ -420,6 +420,7 @@ GLIBCXX_CHECK_GTHREADS
|
|||
|
||||
# For Filesystem TS.
|
||||
AC_CHECK_HEADERS([fcntl.h dirent.h sys/statvfs.h utime.h])
|
||||
AC_CHECK_FUNCS(link readlink symlink)
|
||||
GLIBCXX_ENABLE_FILESYSTEM_TS
|
||||
GLIBCXX_CHECK_FILESYSTEM_DEPS
|
||||
|
||||
|
|
|
@ -37,11 +37,11 @@
|
|||
#include <vector>
|
||||
#include <locale>
|
||||
#include <iosfwd>
|
||||
#include <iomanip>
|
||||
#include <codecvt>
|
||||
#include <string_view>
|
||||
#include <system_error>
|
||||
#include <bits/stl_algobase.h>
|
||||
#include <bits/quoted_string.h>
|
||||
#include <bits/locale_conv.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
|
@ -232,37 +232,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
|
||||
// appends
|
||||
|
||||
path& operator/=(const path& __p)
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
if (__p.is_absolute()
|
||||
|| (__p.has_root_name() && __p.root_name() != root_name()))
|
||||
operator=(__p);
|
||||
else
|
||||
{
|
||||
string_type __pathname;
|
||||
if (__p.has_root_directory())
|
||||
__pathname = root_name().native();
|
||||
else if (has_filename() || (!has_root_directory() && is_absolute()))
|
||||
__pathname = _M_pathname + preferred_separator;
|
||||
__pathname += __p.relative_path().native(); // XXX is this right?
|
||||
_M_pathname.swap(__pathname);
|
||||
_M_split_cmpts();
|
||||
}
|
||||
#else
|
||||
// Much simpler, as any path with root-name or root-dir is absolute.
|
||||
if (__p.is_absolute())
|
||||
operator=(__p);
|
||||
else
|
||||
{
|
||||
if (has_filename() || (_M_type == _Type::_Root_name))
|
||||
_M_pathname += preferred_separator;
|
||||
_M_pathname += __p.native();
|
||||
_M_split_cmpts();
|
||||
}
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
path& operator/=(const path& __p);
|
||||
|
||||
template <class _Source>
|
||||
_Path<_Source>&
|
||||
|
@ -378,7 +348,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
bool has_filename() const;
|
||||
bool has_stem() const;
|
||||
bool has_extension() const;
|
||||
bool is_absolute() const { return has_root_directory(); }
|
||||
bool is_absolute() const;
|
||||
bool is_relative() const { return !is_absolute(); }
|
||||
|
||||
// generation
|
||||
|
@ -419,19 +389,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
|
||||
enum class _Split { _Stem, _Extension };
|
||||
|
||||
path&
|
||||
_M_append(path __p)
|
||||
{
|
||||
if (__p.is_absolute())
|
||||
operator=(std::move(__p));
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
else if (__p.has_root_name() && __p.root_name() != root_name())
|
||||
operator=(std::move(__p));
|
||||
#endif
|
||||
else
|
||||
operator/=(const_cast<const path&>(__p));
|
||||
return *this;
|
||||
}
|
||||
path& _M_append(path __p);
|
||||
|
||||
pair<const string_type*, size_t> _M_find_extension() const;
|
||||
|
||||
|
@ -552,10 +510,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p)
|
||||
{
|
||||
auto __tmp = __p.string<_CharT, _Traits>();
|
||||
using __quoted_string
|
||||
= std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>;
|
||||
__os << __quoted_string{__tmp, '"', '\\'};
|
||||
__os << std::quoted(__p.string<_CharT, _Traits>());
|
||||
return __os;
|
||||
}
|
||||
|
||||
|
@ -565,43 +520,58 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
operator>>(basic_istream<_CharT, _Traits>& __is, path& __p)
|
||||
{
|
||||
basic_string<_CharT, _Traits> __tmp;
|
||||
using __quoted_string
|
||||
= std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>;
|
||||
if (__is >> __quoted_string{ __tmp, '"', '\\' })
|
||||
if (__is >> std::quoted(__tmp))
|
||||
__p = std::move(__tmp);
|
||||
return __is;
|
||||
}
|
||||
|
||||
template<typename _Source>
|
||||
inline auto
|
||||
u8path(const _Source& __source)
|
||||
-> decltype(filesystem::path(__source, std::locale::classic()))
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
const std::string __u8str{__source};
|
||||
return std::filesystem::u8path(__u8str.begin(), __u8str.end());
|
||||
#else
|
||||
return path{ __source };
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename _InputIterator>
|
||||
inline auto
|
||||
u8path(_InputIterator __first, _InputIterator __last)
|
||||
-> decltype(filesystem::path(__first, __last, std::locale::classic()))
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
codecvt_utf8<value_type> __cvt;
|
||||
string_type __tmp;
|
||||
if (__str_codecvt_in(__first, __last, __tmp, __cvt))
|
||||
return path{ __tmp };
|
||||
codecvt_utf8<path::value_type> __cvt;
|
||||
path::string_type __tmp;
|
||||
if constexpr (is_pointer_v<_InputIterator>)
|
||||
{
|
||||
if (__str_codecvt_in(__first, __last, __tmp, __cvt))
|
||||
return path{ __tmp };
|
||||
}
|
||||
else
|
||||
return {};
|
||||
{
|
||||
const std::string __u8str{__first, __last};
|
||||
const char* const __ptr = __u8str.data();
|
||||
if (__str_codecvt_in(__ptr, __ptr + __u8str.size(), __tmp, __cvt))
|
||||
return path{ __tmp };
|
||||
}
|
||||
return {};
|
||||
#else
|
||||
return path{ __first, __last };
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename _Source>
|
||||
inline auto
|
||||
u8path(const _Source& __source)
|
||||
-> decltype(filesystem::path(__source, std::locale::classic()))
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
if constexpr (is_convertible_v<const _Source&, std::string_view>)
|
||||
{
|
||||
const std::string_view __s = __source;
|
||||
return filesystem::u8path(__s.data(), __s.data() + __s.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string __s = path::_S_string_from_iter(__source);
|
||||
return filesystem::u8path(__s.data(), __s.data() + __s.size());
|
||||
}
|
||||
#else
|
||||
return path{ __source };
|
||||
#endif
|
||||
}
|
||||
|
||||
class filesystem_error : public std::system_error
|
||||
{
|
||||
public:
|
||||
|
@ -1068,6 +1038,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
return ext.first && ext.second != string_type::npos;
|
||||
}
|
||||
|
||||
inline bool
|
||||
path::is_absolute() const
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
return has_root_name() && has_root_directory();
|
||||
#else
|
||||
return has_root_directory();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline path::iterator
|
||||
path::begin() const
|
||||
{
|
||||
|
@ -1084,6 +1064,38 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
return iterator(this, true);
|
||||
}
|
||||
|
||||
#ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
inline path& path::operator/=(const path& __p)
|
||||
{
|
||||
// Much simpler than the specification in the standard,
|
||||
// as any path with root-name or root-dir is absolute.
|
||||
if (__p.is_absolute())
|
||||
operator=(__p);
|
||||
else
|
||||
{
|
||||
if (has_filename() || (_M_type == _Type::_Root_name))
|
||||
_M_pathname += preferred_separator;
|
||||
_M_pathname += __p.native();
|
||||
_M_split_cmpts();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline path&
|
||||
path::_M_append(path __p)
|
||||
{
|
||||
if (__p.is_absolute())
|
||||
operator=(std::move(__p));
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
else if (__p.has_root_name() && __p.root_name() != root_name())
|
||||
operator=(std::move(__p));
|
||||
#endif
|
||||
else
|
||||
operator/=(const_cast<const path&>(__p));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline path::iterator&
|
||||
path::iterator::operator++()
|
||||
{
|
||||
|
|
|
@ -372,7 +372,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
bool has_filename() const;
|
||||
bool has_stem() const;
|
||||
bool has_extension() const;
|
||||
bool is_absolute() const { return has_root_directory(); }
|
||||
bool is_absolute() const;
|
||||
bool is_relative() const { return !is_absolute(); }
|
||||
|
||||
// iterators
|
||||
|
@ -537,7 +537,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
auto __tmp = __p.string<_CharT, _Traits>();
|
||||
using __quoted_string
|
||||
= std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>;
|
||||
__os << __quoted_string{__tmp, '"', '\\'};
|
||||
__os << __quoted_string{__tmp, _CharT('"'), _CharT('\\')};
|
||||
return __os;
|
||||
}
|
||||
|
||||
|
@ -549,7 +549,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
basic_string<_CharT, _Traits> __tmp;
|
||||
using __quoted_string
|
||||
= std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>;
|
||||
if (__is >> __quoted_string{ __tmp, '"', '\\' })
|
||||
if (__is >> __quoted_string{ __tmp, _CharT('"'), _CharT('\\') })
|
||||
__p = std::move(__tmp);
|
||||
return __is;
|
||||
}
|
||||
|
@ -993,6 +993,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
return ext.first && ext.second != string_type::npos;
|
||||
}
|
||||
|
||||
inline bool
|
||||
path::is_absolute() const
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
return has_root_name() && has_root_directory();
|
||||
#else
|
||||
return has_root_directory();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline path::iterator
|
||||
path::begin() const
|
||||
{
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#define _GLIBCXX_DIR_COMMON_H 1
|
||||
|
||||
#include <string.h> // strcmp
|
||||
#if _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
#include <wchar.h> // wcscmp
|
||||
#endif
|
||||
#ifdef _GLIBCXX_HAVE_DIRENT_H
|
||||
# ifdef _GLIBCXX_HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
|
@ -35,26 +38,42 @@
|
|||
# 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
|
||||
{
|
||||
namespace __gnu_posix
|
||||
{
|
||||
#if _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
// Adapt the Windows _wxxx functions to look like POSIX xxx, but for wchar_t*.
|
||||
using char_type = wchar_t;
|
||||
using DIR = ::_WDIR;
|
||||
using dirent = _wdirent;
|
||||
inline DIR* opendir(const wchar_t* path) { return ::_wopendir(path); }
|
||||
inline dirent* readdir(DIR* dir) { return ::_wreaddir(dir); }
|
||||
inline int closedir(DIR* dir) { return ::_wclosedir(dir); }
|
||||
#else
|
||||
using char_type = char;
|
||||
using DIR = ::DIR;
|
||||
typedef struct ::dirent dirent;
|
||||
using ::opendir;
|
||||
using ::readdir;
|
||||
using ::closedir;
|
||||
#endif
|
||||
} // namespace __gnu_posix
|
||||
|
||||
namespace posix = __gnu_posix;
|
||||
|
||||
struct _Dir_base
|
||||
{
|
||||
_Dir_base(DIR* dirp = nullptr) : dirp(dirp) { }
|
||||
_Dir_base(posix::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,
|
||||
_Dir_base(const posix::char_type* pathname, bool skip_permission_denied,
|
||||
error_code& ec) noexcept
|
||||
: dirp(::opendir(p))
|
||||
: dirp(posix::opendir(pathname))
|
||||
{
|
||||
if (dirp)
|
||||
ec.clear();
|
||||
|
@ -72,22 +91,22 @@ struct _Dir_base
|
|||
|
||||
_Dir_base& operator=(_Dir_base&&) = delete;
|
||||
|
||||
~_Dir_base() { if (dirp) ::closedir(dirp); }
|
||||
~_Dir_base() { if (dirp) posix::closedir(dirp); }
|
||||
|
||||
const struct ::dirent*
|
||||
const posix::dirent*
|
||||
advance(bool skip_permission_denied, error_code& ec) noexcept
|
||||
{
|
||||
ec.clear();
|
||||
|
||||
int err = std::exchange(errno, 0);
|
||||
const struct ::dirent* entp = readdir(dirp);
|
||||
const posix::dirent* entp = posix::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, ".."))
|
||||
if (is_dot_or_dotdot(entp->d_name))
|
||||
return advance(skip_permission_denied, ec);
|
||||
return entp;
|
||||
}
|
||||
|
@ -105,15 +124,24 @@ struct _Dir_base
|
|||
}
|
||||
}
|
||||
|
||||
DIR* dirp;
|
||||
static bool is_dot_or_dotdot(const char* s) noexcept
|
||||
{ return !strcmp(s, ".") || !strcmp(s, ".."); }
|
||||
|
||||
#if _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
static bool is_dot_or_dotdot(const wchar_t* s) noexcept
|
||||
{ return !wcscmp(s, L".") || !wcscmp(s, L".."); }
|
||||
#endif
|
||||
|
||||
posix::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__)))
|
||||
get_file_type(const std::filesystem::__gnu_posix::dirent& d [[gnu::unused]])
|
||||
{
|
||||
#ifdef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE
|
||||
switch (d.d_type)
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "dir-common.h"
|
||||
|
||||
namespace fs = std::experimental::filesystem;
|
||||
namespace posix = std::filesystem::__gnu_posix;
|
||||
|
||||
struct fs::_Dir : std::filesystem::_Dir_base
|
||||
{
|
||||
|
@ -47,7 +48,7 @@ struct fs::_Dir : std::filesystem::_Dir_base
|
|||
path = p;
|
||||
}
|
||||
|
||||
_Dir(DIR* dirp, const path& p) : _Dir_base(dirp), path(p) { }
|
||||
_Dir(posix::DIR* dirp, const path& p) : _Dir_base(dirp), path(p) { }
|
||||
|
||||
_Dir(_Dir&&) = default;
|
||||
|
||||
|
@ -185,7 +186,7 @@ recursive_directory_iterator(const path& p, directory_options options,
|
|||
{
|
||||
if (ec)
|
||||
ec->clear();
|
||||
if (DIR* dirp = ::opendir(p.c_str()))
|
||||
if (posix::DIR* dirp = posix::opendir(p.c_str()))
|
||||
{
|
||||
auto sp = std::make_shared<_Dir_stack>();
|
||||
sp->push(_Dir{ dirp, p });
|
||||
|
|
|
@ -34,12 +34,103 @@
|
|||
# include <sys/stat.h>
|
||||
# endif
|
||||
#endif
|
||||
#if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
|
||||
# include <utime.h> // utime
|
||||
#endif
|
||||
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
# include <wchar.h>
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
namespace filesystem
|
||||
{
|
||||
namespace __gnu_posix
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
// Adapt the Windows _wxxx functions to look like POSIX xxx, but for wchar_t*.
|
||||
inline int open(const wchar_t* path, int flags)
|
||||
{ return ::_wopen(path, flags); }
|
||||
|
||||
inline int open(const wchar_t* path, int flags, int mode)
|
||||
{ return ::_wopen(path, flags, mode); }
|
||||
|
||||
inline int close(int fd)
|
||||
{ return ::_close(fd); }
|
||||
|
||||
typedef struct ::_stat stat_type;
|
||||
|
||||
inline int stat(const wchar_t* path, stat_type* buffer)
|
||||
{ return ::_wstat(path, buffer); }
|
||||
|
||||
inline lstat(const wchar_t* path, stat_type* buffer)
|
||||
{
|
||||
// TODO symlinks not currently supported
|
||||
return stat(path, buffer);
|
||||
}
|
||||
|
||||
using ::mode_t;
|
||||
|
||||
inline int chmod(const wchar_t* path, mode_t mode)
|
||||
{ return ::_wchmod(path, mode); }
|
||||
|
||||
inline int mkdir(const wchar_t* path, mode_t)
|
||||
{ return ::_wmkdir(path); }
|
||||
|
||||
inline wchar_t* getcwd(wchar_t* buf, size_t size)
|
||||
{ return ::_wgetcwd(buf, size > (size_t)INT_MAX ? INT_MAX : (int)size); }
|
||||
|
||||
inline int chdir(const wchar_t* path)
|
||||
{ return ::_wchdir(path); }
|
||||
|
||||
#if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
|
||||
using utimbuf = _utimbuf;
|
||||
|
||||
inline int utime(const wchar_t* path, utimbuf* times)
|
||||
{ return ::_wutime(path, times); }
|
||||
#endif
|
||||
|
||||
inline int rename(const wchar_t* oldname, const wchar_t* newname)
|
||||
{ return _wrename(oldname, newname); }
|
||||
|
||||
inline int truncate(const wchar_t* path, _off64_t length)
|
||||
{
|
||||
const int fd = ::_wopen(path, _O_BINARY|_O_RDWR);
|
||||
if (fd == -1)
|
||||
return fd;
|
||||
const int ret = ::ftruncate64(fd, length);
|
||||
int err;
|
||||
::_get_errno(&err);
|
||||
::_close(fd);
|
||||
::_set_errno(err);
|
||||
return ret;
|
||||
}
|
||||
using char_type = wchar_t;
|
||||
#else // _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
using ::open;
|
||||
using ::close;
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
typedef struct ::stat stat_type;
|
||||
using ::stat;
|
||||
using ::lstat;
|
||||
#endif
|
||||
using ::mode_t;
|
||||
using ::chmod;
|
||||
using ::mkdir;
|
||||
using ::getcwd;
|
||||
using ::chdir;
|
||||
#if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
|
||||
using ::utimbuf;
|
||||
using ::utime;
|
||||
#endif
|
||||
using ::rename;
|
||||
using ::truncate;
|
||||
using char_type = char;
|
||||
#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
} // namespace __gnu_posix
|
||||
|
||||
template<typename Bitmask>
|
||||
inline bool is_set(Bitmask obj, Bitmask bits)
|
||||
{
|
||||
|
@ -53,7 +144,7 @@ namespace filesystem
|
|||
}
|
||||
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
typedef struct ::stat stat_type;
|
||||
using __gnu_posix::stat_type;
|
||||
|
||||
inline std::chrono::system_clock::time_point
|
||||
file_time(const stat_type& st, std::error_code& ec) noexcept
|
||||
|
@ -82,11 +173,17 @@ namespace filesystem
|
|||
};
|
||||
|
||||
bool
|
||||
do_copy_file(const char* from, const char* to,
|
||||
do_copy_file(const __gnu_posix::char_type* from,
|
||||
const __gnu_posix::char_type* to,
|
||||
copy_options_existing_file options,
|
||||
stat_type* from_st, stat_type* to_st,
|
||||
std::error_code& ec) noexcept;
|
||||
|
||||
void
|
||||
do_space(const __gnu_posix::char_type* pathname,
|
||||
uintmax_t& capacity, uintmax_t& free, uintmax_t& available,
|
||||
std::error_code&);
|
||||
|
||||
#endif // _GLIBCXX_HAVE_SYS_STAT_H
|
||||
|
||||
} // namespace filesystem
|
||||
|
@ -95,7 +192,7 @@ namespace filesystem
|
|||
_GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
|
||||
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
typedef struct ::stat stat_type;
|
||||
using std::filesystem::__gnu_posix::stat_type;
|
||||
|
||||
inline file_type
|
||||
make_file_type(const stat_type& st) noexcept
|
||||
|
@ -111,8 +208,10 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
|
|||
return file_type::block;
|
||||
else if (S_ISFIFO(st.st_mode))
|
||||
return file_type::fifo;
|
||||
#ifdef S_ISLNK // not present in mingw
|
||||
else if (S_ISLNK(st.st_mode))
|
||||
return file_type::symlink;
|
||||
#endif
|
||||
#ifdef S_ISSOCK // not present until POSIX:2001
|
||||
else if (S_ISSOCK(st.st_mode))
|
||||
return file_type::socket;
|
||||
|
|
|
@ -47,20 +47,17 @@
|
|||
#if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
|
||||
# include <utime.h> // utime
|
||||
#endif
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
# include <windows.h>
|
||||
#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
|
||||
# undef chmod
|
||||
# define chmod _wchmod
|
||||
#endif
|
||||
|
||||
namespace fs = std::experimental::filesystem;
|
||||
namespace posix = std::filesystem::__gnu_posix;
|
||||
|
||||
fs::path
|
||||
fs::absolute(const path& p, const path& base)
|
||||
|
@ -109,7 +106,7 @@ namespace
|
|||
void operator()(void* p) const { ::free(p); }
|
||||
};
|
||||
|
||||
using char_ptr = std::unique_ptr<char[], free_as_in_malloc>;
|
||||
using char_ptr = std::unique_ptr<fs::path::value_type[], free_as_in_malloc>;
|
||||
}
|
||||
|
||||
fs::path
|
||||
|
@ -122,7 +119,8 @@ fs::canonical(const path& p, const path& base, error_code& ec)
|
|||
char_ptr buf{ nullptr };
|
||||
# if _XOPEN_VERSION < 700
|
||||
// Not safe to call realpath(path, NULL)
|
||||
buf.reset( (char*)::malloc(PATH_MAX) );
|
||||
using char_type = fs::path::value_type;
|
||||
buf.reset( (char_type*)::malloc(PATH_MAX * sizeof(char_type)) );
|
||||
# endif
|
||||
if (char* rp = ::realpath(pa.c_str(), buf.get()))
|
||||
{
|
||||
|
@ -241,12 +239,13 @@ namespace
|
|||
using std::filesystem::is_set;
|
||||
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
typedef struct ::stat stat_type;
|
||||
using posix::stat_type;
|
||||
|
||||
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
|
||||
|
@ -263,15 +262,15 @@ fs::copy(const path& from, const path& to, copy_options options,
|
|||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2681. filesystem::copy() cannot copy symlinks
|
||||
if (use_lstat || copy_symlinks
|
||||
? ::lstat(from.c_str(), &from_st)
|
||||
: ::stat(from.c_str(), &from_st))
|
||||
? posix::lstat(from.c_str(), &from_st)
|
||||
: posix::stat(from.c_str(), &from_st))
|
||||
{
|
||||
ec.assign(errno, std::generic_category());
|
||||
return;
|
||||
}
|
||||
if (use_lstat
|
||||
? ::lstat(to.c_str(), &to_st)
|
||||
: ::stat(to.c_str(), &to_st))
|
||||
? posix::lstat(to.c_str(), &to_st)
|
||||
: posix::stat(to.c_str(), &to_st))
|
||||
{
|
||||
if (!is_not_found_errno(errno))
|
||||
{
|
||||
|
@ -459,8 +458,8 @@ namespace
|
|||
{
|
||||
bool created = false;
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
::mode_t mode = static_cast<std::underlying_type_t<fs::perms>>(perm);
|
||||
if (::mkdir(p.c_str(), mode))
|
||||
posix::mode_t mode = static_cast<std::underlying_type_t<fs::perms>>(perm);
|
||||
if (posix::mkdir(p.c_str(), mode))
|
||||
{
|
||||
const int err = errno;
|
||||
if (err != EEXIST || !is_directory(p, ec))
|
||||
|
@ -513,7 +512,7 @@ fs::create_directory(const path& p, const path& attributes,
|
|||
{
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
stat_type st;
|
||||
if (::stat(attributes.c_str(), &st))
|
||||
if (posix::stat(attributes.c_str(), &st))
|
||||
{
|
||||
ec.assign(errno, std::generic_category());
|
||||
return false;
|
||||
|
@ -562,11 +561,16 @@ void
|
|||
fs::create_hard_link(const path& to, const path& new_hard_link,
|
||||
error_code& ec) noexcept
|
||||
{
|
||||
#ifdef _GLIBCXX_HAVE_UNISTD_H
|
||||
#ifdef _GLIBCXX_HAVE_LINK
|
||||
if (::link(to.c_str(), new_hard_link.c_str()))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
ec.clear();
|
||||
#elif defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
if (CreateHardLinkW(new_hard_link.c_str(), to.c_str(), NULL))
|
||||
ec.clear();
|
||||
else
|
||||
ec.assign((int)GetLastError(), generic_category());
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
#endif
|
||||
|
@ -586,7 +590,7 @@ void
|
|||
fs::create_symlink(const path& to, const path& new_symlink,
|
||||
error_code& ec) noexcept
|
||||
{
|
||||
#ifdef _GLIBCXX_HAVE_UNISTD_H
|
||||
#ifdef _GLIBCXX_HAVE_SYMLINK
|
||||
if (::symlink(to.c_str(), new_symlink.c_str()))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
|
@ -596,7 +600,6 @@ fs::create_symlink(const path& to, const path& new_symlink,
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
fs::path
|
||||
fs::current_path()
|
||||
{
|
||||
|
@ -612,8 +615,8 @@ fs::current_path(error_code& ec)
|
|||
{
|
||||
path p;
|
||||
#ifdef _GLIBCXX_HAVE_UNISTD_H
|
||||
#ifdef __GLIBC__
|
||||
if (char_ptr cwd = char_ptr{::getcwd(nullptr, 0)})
|
||||
#if defined __GLIBC__ || defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
if (char_ptr cwd = char_ptr{posix::getcwd(nullptr, 0)})
|
||||
{
|
||||
p.assign(cwd.get());
|
||||
ec.clear();
|
||||
|
@ -621,6 +624,7 @@ fs::current_path(error_code& ec)
|
|||
else
|
||||
ec.assign(errno, std::generic_category());
|
||||
#else
|
||||
#ifdef _PC_PATH_MAX
|
||||
long path_max = pathconf(".", _PC_PATH_MAX);
|
||||
size_t size;
|
||||
if (path_max == -1)
|
||||
|
@ -629,9 +633,15 @@ fs::current_path(error_code& ec)
|
|||
size = 10240;
|
||||
else
|
||||
size = path_max;
|
||||
#elif defined(PATH_MAX)
|
||||
size_t size = PATH_MAX;
|
||||
#else
|
||||
size_t size = 1024;
|
||||
#endif
|
||||
for (char_ptr buf; p.empty(); size *= 2)
|
||||
{
|
||||
buf.reset((char*)malloc(size));
|
||||
using char_type = fs::path::value_type;
|
||||
buf.reset((char_type*)malloc(size * sizeof(char_type)));
|
||||
if (buf)
|
||||
{
|
||||
if (getcwd(buf.get(), size))
|
||||
|
@ -671,7 +681,7 @@ void
|
|||
fs::current_path(const path& p, error_code& ec) noexcept
|
||||
{
|
||||
#ifdef _GLIBCXX_HAVE_UNISTD_H
|
||||
if (::chdir(p.c_str()))
|
||||
if (posix::chdir(p.c_str()))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
ec.clear();
|
||||
|
@ -698,14 +708,14 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
|
|||
int err = 0;
|
||||
file_status s1, s2;
|
||||
stat_type st1, st2;
|
||||
if (::stat(p1.c_str(), &st1) == 0)
|
||||
if (posix::stat(p1.c_str(), &st1) == 0)
|
||||
s1 = make_file_status(st1);
|
||||
else if (is_not_found_errno(errno))
|
||||
s1.type(file_type::not_found);
|
||||
else
|
||||
err = errno;
|
||||
|
||||
if (::stat(p2.c_str(), &st2) == 0)
|
||||
if (posix::stat(p2.c_str(), &st2) == 0)
|
||||
s2 = make_file_status(st2);
|
||||
else if (is_not_found_errno(errno))
|
||||
s2.type(file_type::not_found);
|
||||
|
@ -755,7 +765,7 @@ namespace
|
|||
{
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
stat_type st;
|
||||
if (::stat(p.c_str(), &st))
|
||||
if (posix::stat(p.c_str(), &st))
|
||||
{
|
||||
ec.assign(errno, std::generic_category());
|
||||
return deflt;
|
||||
|
@ -805,7 +815,7 @@ fs::hard_link_count(const path& p)
|
|||
std::uintmax_t
|
||||
fs::hard_link_count(const path& p, error_code& ec) noexcept
|
||||
{
|
||||
return do_stat(p, ec, std::mem_fn(&stat::st_nlink),
|
||||
return do_stat(p, ec, std::mem_fn(&stat_type::st_nlink),
|
||||
static_cast<uintmax_t>(-1));
|
||||
}
|
||||
|
||||
|
@ -881,11 +891,11 @@ fs::last_write_time(const path& p __attribute__((__unused__)),
|
|||
else
|
||||
ec.clear();
|
||||
#elif _GLIBCXX_HAVE_UTIME_H
|
||||
::utimbuf times;
|
||||
posix::utimbuf times;
|
||||
times.modtime = s.count();
|
||||
times.actime = do_stat(p, ec, [](const auto& st) { return st.st_atime; },
|
||||
times.modtime);
|
||||
if (::utime(p.c_str(), ×))
|
||||
if (posix::utime(p.c_str(), ×))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
ec.clear();
|
||||
|
@ -938,7 +948,7 @@ fs::permissions(const path& p, perms prms, error_code& ec) noexcept
|
|||
#else
|
||||
if (nofollow && is_symlink(st))
|
||||
ec = std::make_error_code(std::errc::operation_not_supported);
|
||||
else if (::chmod(p.c_str(), static_cast<mode_t>(prms)))
|
||||
else if (posix::chmod(p.c_str(), static_cast<mode_t>(prms)))
|
||||
err = errno;
|
||||
#endif
|
||||
|
||||
|
@ -958,10 +968,10 @@ fs::read_symlink(const path& p)
|
|||
return tgt;
|
||||
}
|
||||
|
||||
fs::path fs::read_symlink(const path& p, error_code& ec)
|
||||
fs::path fs::read_symlink(const path& p [[gnu::unused]], error_code& ec)
|
||||
{
|
||||
path result;
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
#if defined(_GLIBCXX_HAVE_READLINK) && defined(_GLIBCXX_HAVE_SYS_STAT_H)
|
||||
stat_type st;
|
||||
if (::lstat(p.c_str(), &st))
|
||||
{
|
||||
|
@ -1015,6 +1025,19 @@ fs::remove(const path& p)
|
|||
bool
|
||||
fs::remove(const path& p, error_code& ec) noexcept
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
if (exists(symlink_status(p, ec)))
|
||||
{
|
||||
if ((is_directory(p, ec) && RemoveDirectoryW(p.c_str()))
|
||||
|| DeleteFileW(p.c_str()))
|
||||
{
|
||||
ec.clear();
|
||||
return true;
|
||||
}
|
||||
else if (!ec)
|
||||
ec.assign((int)GetLastError(), generic_category());
|
||||
}
|
||||
#else
|
||||
if (::remove(p.c_str()) == 0)
|
||||
{
|
||||
ec.clear();
|
||||
|
@ -1024,6 +1047,7 @@ fs::remove(const path& p, error_code& ec) noexcept
|
|||
ec.clear();
|
||||
else
|
||||
ec.assign(errno, std::generic_category());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1077,7 +1101,7 @@ fs::rename(const path& from, const path& to)
|
|||
void
|
||||
fs::rename(const path& from, const path& to, error_code& ec) noexcept
|
||||
{
|
||||
if (::rename(from.c_str(), to.c_str()))
|
||||
if (posix::rename(from.c_str(), to.c_str()))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
ec.clear();
|
||||
|
@ -1098,7 +1122,7 @@ fs::resize_file(const path& p, uintmax_t size, error_code& ec) noexcept
|
|||
#ifdef _GLIBCXX_HAVE_UNISTD_H
|
||||
if (size > static_cast<uintmax_t>(std::numeric_limits<off_t>::max()))
|
||||
ec.assign(EINVAL, std::generic_category());
|
||||
else if (::truncate(p.c_str(), size))
|
||||
else if (posix::truncate(p.c_str(), size))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
ec.clear();
|
||||
|
@ -1126,23 +1150,14 @@ fs::space(const path& p, error_code& ec) noexcept
|
|||
static_cast<uintmax_t>(-1),
|
||||
static_cast<uintmax_t>(-1)
|
||||
};
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
|
||||
struct ::statvfs f;
|
||||
if (::statvfs(p.c_str(), &f))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
{
|
||||
uintmax_t fragment_size = f.f_frsize;
|
||||
info = space_info{
|
||||
f.f_blocks * fragment_size,
|
||||
f.f_bfree * fragment_size,
|
||||
f.f_bavail * fragment_size
|
||||
};
|
||||
ec.clear();
|
||||
}
|
||||
#if _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
path dir = absolute(p);
|
||||
dir.remove_filename();
|
||||
auto str = dir.c_str();
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
auto str = p.c_str();
|
||||
#endif
|
||||
std::filesystem::do_space(str, info.capacity, info.free, info.available, ec);
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -1152,7 +1167,7 @@ fs::status(const fs::path& p, error_code& ec) noexcept
|
|||
{
|
||||
file_status status;
|
||||
stat_type st;
|
||||
if (::stat(p.c_str(), &st))
|
||||
if (posix::stat(p.c_str(), &st))
|
||||
{
|
||||
int err = errno;
|
||||
ec.assign(err, std::generic_category());
|
||||
|
@ -1176,7 +1191,7 @@ fs::symlink_status(const fs::path& p, std::error_code& ec) noexcept
|
|||
{
|
||||
file_status status;
|
||||
stat_type st;
|
||||
if (::lstat(p.c_str(), &st))
|
||||
if (posix::lstat(p.c_str(), &st))
|
||||
{
|
||||
int err = errno;
|
||||
ec.assign(err, std::generic_category());
|
||||
|
@ -1251,27 +1266,38 @@ fs::path fs::temp_directory_path()
|
|||
|
||||
fs::path fs::temp_directory_path(error_code& ec)
|
||||
{
|
||||
path p;
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
return {}; // TODO
|
||||
unsigned len = 1024;
|
||||
std::wstring buf;
|
||||
do
|
||||
{
|
||||
buf.resize(len);
|
||||
len = GetTempPathW(buf.size(), buf.data());
|
||||
} while (len > buf.size());
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
ec.assign((int)GetLastError(), std::system_category());
|
||||
return p;
|
||||
}
|
||||
buf.resize(len);
|
||||
p = std::move(buf);
|
||||
#else
|
||||
const char* tmpdir = nullptr;
|
||||
const char* env[] = { "TMPDIR", "TMP", "TEMP", "TEMPDIR", nullptr };
|
||||
for (auto e = env; tmpdir == nullptr && *e != nullptr; ++e)
|
||||
tmpdir = ::getenv(*e);
|
||||
path p = tmpdir ? tmpdir : "/tmp";
|
||||
p = tmpdir ? tmpdir : "/tmp";
|
||||
auto st = status(p, ec);
|
||||
if (!ec)
|
||||
if (ec)
|
||||
p.clear();
|
||||
else if (!is_directory(st))
|
||||
{
|
||||
if (is_directory(st))
|
||||
{
|
||||
ec.clear();
|
||||
return p;
|
||||
}
|
||||
else
|
||||
ec = std::make_error_code(std::errc::not_a_directory);
|
||||
p.clear();
|
||||
ec = std::make_error_code(std::errc::not_a_directory);
|
||||
}
|
||||
return {};
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,12 @@ path::replace_filename(const path& replacement)
|
|||
return *this;
|
||||
}
|
||||
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
const fs::path::value_type dot = L'.';
|
||||
#else
|
||||
const fs::path::value_type dot = '.';
|
||||
#endif
|
||||
|
||||
path&
|
||||
path::replace_extension(const path& replacement)
|
||||
{
|
||||
|
@ -78,8 +84,8 @@ path::replace_extension(const path& replacement)
|
|||
_M_pathname.erase(back._M_pos + ext.second);
|
||||
}
|
||||
}
|
||||
if (!replacement.empty() && replacement.native()[0] != '.')
|
||||
_M_pathname += '.';
|
||||
if (!replacement.empty() && replacement.native()[0] != dot)
|
||||
_M_pathname += dot;
|
||||
_M_pathname += replacement.native();
|
||||
_M_split_cmpts();
|
||||
return *this;
|
||||
|
@ -297,7 +303,7 @@ path::has_filename() const
|
|||
std::pair<const path::string_type*, std::size_t>
|
||||
path::_M_find_extension() const
|
||||
{
|
||||
const std::string* s = nullptr;
|
||||
const string_type* s = nullptr;
|
||||
|
||||
if (_M_type != _Type::_Multi)
|
||||
s = &_M_pathname;
|
||||
|
@ -312,14 +318,14 @@ path::_M_find_extension() const
|
|||
{
|
||||
if (auto sz = s->size())
|
||||
{
|
||||
if (sz <= 2 && (*s)[0] == '.')
|
||||
if (sz <= 2 && (*s)[0] == dot)
|
||||
{
|
||||
if (sz == 1 || (*s)[1] == '.') // filename is "." or ".."
|
||||
if (sz == 1 || (*s)[1] == dot) // filename is "." or ".."
|
||||
return { s, string_type::npos };
|
||||
else
|
||||
return { s, 0 }; // filename is like ".?"
|
||||
}
|
||||
return { s, s->rfind('.') };
|
||||
return { s, s->rfind(dot) };
|
||||
}
|
||||
}
|
||||
return {};
|
||||
|
@ -405,7 +411,7 @@ path::_M_split_cmpts()
|
|||
{
|
||||
const auto& last = _M_cmpts.back();
|
||||
pos = last._M_pos + last._M_pathname.size();
|
||||
_M_cmpts.emplace_back(string_type(1, '.'), _Type::_Filename, pos);
|
||||
_M_cmpts.emplace_back(string_type(1, dot), _Type::_Filename, pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,8 +501,8 @@ _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());
|
||||
return fs_err_concat(system_error::what(), _M_path1.u8string(),
|
||||
_M_path2.u8string());
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_CXX11
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "dir-common.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
namespace posix = std::filesystem::__gnu_posix;
|
||||
|
||||
struct fs::_Dir : _Dir_base
|
||||
{
|
||||
|
@ -47,7 +48,7 @@ struct fs::_Dir : _Dir_base
|
|||
path = p;
|
||||
}
|
||||
|
||||
_Dir(DIR* dirp, const path& p) : _Dir_base(dirp), path(p) { }
|
||||
_Dir(posix::DIR* dirp, const path& p) : _Dir_base(dirp), path(p) { }
|
||||
|
||||
_Dir(_Dir&&) = default;
|
||||
|
||||
|
@ -180,7 +181,7 @@ 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 (posix::DIR* dirp = posix::opendir(p.c_str()))
|
||||
{
|
||||
if (ecptr)
|
||||
ecptr->clear();
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#ifndef _GLIBCXX_USE_CXX11_ABI
|
||||
# define _GLIBCXX_USE_CXX11_ABI 1
|
||||
# define NEED_DO_COPY_FILE
|
||||
# define NEED_DO_SPACE
|
||||
#endif
|
||||
|
||||
#include <filesystem>
|
||||
|
@ -52,19 +53,16 @@
|
|||
#if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
|
||||
# include <utime.h> // utime
|
||||
#endif
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#define _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM namespace filesystem {
|
||||
#define _GLIBCXX_END_NAMESPACE_FILESYSTEM }
|
||||
#include "ops-common.h"
|
||||
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
# undef utime
|
||||
# define utime _wutime
|
||||
# undef chmod
|
||||
# define chmod _wchmod
|
||||
#endif
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
namespace posix = std::filesystem::__gnu_posix;
|
||||
|
||||
fs::path
|
||||
fs::absolute(const path& p)
|
||||
|
@ -74,7 +72,7 @@ fs::absolute(const path& p)
|
|||
path ret = absolute(p, ec);
|
||||
if (ec)
|
||||
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot make absolute path", p,
|
||||
std::make_error_code(errc::not_supported)));
|
||||
ec));
|
||||
return ret;
|
||||
#else
|
||||
return current_path() / p;
|
||||
|
@ -91,7 +89,24 @@ fs::absolute(const path& p, error_code& ec)
|
|||
return ret;
|
||||
}
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
ec = std::make_error_code(errc::not_supported);
|
||||
const wstring& s = p.native();
|
||||
uint32_t len = 1024;
|
||||
wstring buf;
|
||||
do
|
||||
{
|
||||
buf.resize(len);
|
||||
len = GetFullPathNameW(s.c_str(), len, buf.data(), nullptr);
|
||||
}
|
||||
while (len > buf.size());
|
||||
|
||||
if (len == 0)
|
||||
ec.assign((int)GetLastError(), std::system_category());
|
||||
else
|
||||
{
|
||||
ec.clear();
|
||||
buf.resize(len);
|
||||
ret = std::move(buf);
|
||||
}
|
||||
#else
|
||||
ec.clear();
|
||||
ret = current_path();
|
||||
|
@ -125,7 +140,7 @@ namespace
|
|||
void operator()(void* p) const { ::free(p); }
|
||||
};
|
||||
|
||||
using char_ptr = std::unique_ptr<char[], free_as_in_malloc>;
|
||||
using char_ptr = std::unique_ptr<fs::path::value_type[], free_as_in_malloc>;
|
||||
}
|
||||
|
||||
fs::path
|
||||
|
@ -140,7 +155,8 @@ fs::canonical(const path& p, error_code& ec)
|
|||
char_ptr buf{ nullptr };
|
||||
# if _XOPEN_VERSION < 700
|
||||
// Not safe to call realpath(path, NULL)
|
||||
buf.reset( (char*)::malloc(PATH_MAX) );
|
||||
using char_type = fs::path::value_type;
|
||||
buf.reset( (char_type*)::malloc(PATH_MAX * sizeof(char_type)) );
|
||||
# endif
|
||||
if (char* rp = ::realpath(pa.c_str(), buf.get()))
|
||||
{
|
||||
|
@ -261,7 +277,7 @@ namespace std::filesystem
|
|||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
#ifdef NEED_DO_COPY_FILE
|
||||
bool
|
||||
fs::do_copy_file(const char* from, const char* to,
|
||||
fs::do_copy_file(const path::value_type* from, const path::value_type* to,
|
||||
copy_options_existing_file options,
|
||||
stat_type* from_st, stat_type* to_st,
|
||||
std::error_code& ec) noexcept
|
||||
|
@ -271,7 +287,7 @@ fs::do_copy_file(const char* from, const char* to,
|
|||
|
||||
if (to_st == nullptr)
|
||||
{
|
||||
if (::stat(to, &st1))
|
||||
if (posix::stat(to, &st1))
|
||||
{
|
||||
const int err = errno;
|
||||
if (!is_not_found_errno(err))
|
||||
|
@ -293,7 +309,7 @@ fs::do_copy_file(const char* from, const char* to,
|
|||
|
||||
if (from_st == nullptr)
|
||||
{
|
||||
if (::stat(from, &st2))
|
||||
if (posix::stat(from, &st2))
|
||||
{
|
||||
ec.assign(errno, std::generic_category());
|
||||
return false;
|
||||
|
@ -351,12 +367,12 @@ fs::do_copy_file(const char* from, const char* to,
|
|||
}
|
||||
|
||||
struct CloseFD {
|
||||
~CloseFD() { if (fd != -1) ::close(fd); }
|
||||
bool close() { return ::close(std::exchange(fd, -1)) == 0; }
|
||||
~CloseFD() { if (fd != -1) posix::close(fd); }
|
||||
bool close() { return posix::close(std::exchange(fd, -1)) == 0; }
|
||||
int fd;
|
||||
};
|
||||
|
||||
CloseFD in = { ::open(from, O_RDONLY) };
|
||||
CloseFD in = { posix::open(from, O_RDONLY) };
|
||||
if (in.fd == -1)
|
||||
{
|
||||
ec.assign(errno, std::generic_category());
|
||||
|
@ -367,7 +383,7 @@ fs::do_copy_file(const char* from, const char* to,
|
|||
oflag |= O_TRUNC;
|
||||
else
|
||||
oflag |= O_EXCL;
|
||||
CloseFD out = { ::open(to, oflag, S_IWUSR) };
|
||||
CloseFD out = { posix::open(to, oflag, S_IWUSR) };
|
||||
if (out.fd == -1)
|
||||
{
|
||||
if (errno == EEXIST && options.skip)
|
||||
|
@ -377,12 +393,12 @@ fs::do_copy_file(const char* from, const char* to,
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef _GLIBCXX_USE_FCHMOD
|
||||
#if defined _GLIBCXX_USE_FCHMOD && ! defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
if (::fchmod(out.fd, from_st->st_mode))
|
||||
#elif defined _GLIBCXX_USE_FCHMODAT
|
||||
#elif defined _GLIBCXX_USE_FCHMODAT && ! defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
if (::fchmodat(AT_FDCWD, to, from_st->st_mode, 0))
|
||||
#else
|
||||
if (::chmod(to, from_st->st_mode))
|
||||
if (posix::chmod(to, from_st->st_mode))
|
||||
#endif
|
||||
{
|
||||
ec.assign(errno, std::generic_category());
|
||||
|
@ -390,7 +406,7 @@ fs::do_copy_file(const char* from, const char* to,
|
|||
}
|
||||
|
||||
size_t count = from_st->st_size;
|
||||
#ifdef _GLIBCXX_USE_SENDFILE
|
||||
#if defined _GLIBCXX_USE_SENDFILE && ! defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
off_t offset = 0;
|
||||
ssize_t n = ::sendfile(out.fd, in.fd, &offset, count);
|
||||
if (n < 0 && errno != ENOSYS && errno != EINVAL)
|
||||
|
@ -469,15 +485,15 @@ fs::copy(const path& from, const path& to, copy_options options,
|
|||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2681. filesystem::copy() cannot copy symlinks
|
||||
if (use_lstat || copy_symlinks
|
||||
? ::lstat(from.c_str(), &from_st)
|
||||
: ::stat(from.c_str(), &from_st))
|
||||
? posix::lstat(from.c_str(), &from_st)
|
||||
: posix::stat(from.c_str(), &from_st))
|
||||
{
|
||||
ec.assign(errno, std::generic_category());
|
||||
return;
|
||||
}
|
||||
if (use_lstat
|
||||
? ::lstat(to.c_str(), &to_st)
|
||||
: ::stat(to.c_str(), &to_st))
|
||||
? posix::lstat(to.c_str(), &to_st)
|
||||
: posix::stat(to.c_str(), &to_st))
|
||||
{
|
||||
if (!is_not_found_errno(errno))
|
||||
{
|
||||
|
@ -671,8 +687,9 @@ namespace
|
|||
{
|
||||
bool created = false;
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
::mode_t mode = static_cast<std::underlying_type_t<fs::perms>>(perm);
|
||||
if (::mkdir(p.c_str(), mode))
|
||||
posix::mode_t mode
|
||||
= static_cast<std::underlying_type_t<fs::perms>>(perm);
|
||||
if (posix::mkdir(p.c_str(), mode))
|
||||
{
|
||||
const int err = errno;
|
||||
if (err != EEXIST || !is_directory(p, ec))
|
||||
|
@ -725,7 +742,7 @@ fs::create_directory(const path& p, const path& attributes,
|
|||
{
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
stat_type st;
|
||||
if (::stat(attributes.c_str(), &st))
|
||||
if (posix::stat(attributes.c_str(), &st))
|
||||
{
|
||||
ec.assign(errno, std::generic_category());
|
||||
return false;
|
||||
|
@ -767,18 +784,23 @@ fs::create_hard_link(const path& to, const path& new_hard_link)
|
|||
create_hard_link(to, new_hard_link, ec);
|
||||
if (ec)
|
||||
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create hard link",
|
||||
to, new_hard_link, ec));
|
||||
to, new_hard_link, ec));
|
||||
}
|
||||
|
||||
void
|
||||
fs::create_hard_link(const path& to, const path& new_hard_link,
|
||||
error_code& ec) noexcept
|
||||
{
|
||||
#ifdef _GLIBCXX_HAVE_UNISTD_H
|
||||
#ifdef _GLIBCXX_HAVE_LINK
|
||||
if (::link(to.c_str(), new_hard_link.c_str()))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
ec.clear();
|
||||
#elif defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
if (CreateHardLinkW(new_hard_link.c_str(), to.c_str(), NULL))
|
||||
ec.clear();
|
||||
else
|
||||
ec.assign((int)GetLastError(), generic_category());
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
#endif
|
||||
|
@ -798,7 +820,7 @@ void
|
|||
fs::create_symlink(const path& to, const path& new_symlink,
|
||||
error_code& ec) noexcept
|
||||
{
|
||||
#ifdef _GLIBCXX_HAVE_UNISTD_H
|
||||
#ifdef _GLIBCXX_HAVE_SYMLINK
|
||||
if (::symlink(to.c_str(), new_symlink.c_str()))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
|
@ -824,8 +846,8 @@ fs::current_path(error_code& ec)
|
|||
{
|
||||
path p;
|
||||
#ifdef _GLIBCXX_HAVE_UNISTD_H
|
||||
#ifdef __GLIBC__
|
||||
if (char_ptr cwd = char_ptr{::getcwd(nullptr, 0)})
|
||||
#if defined __GLIBC__ || defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
if (char_ptr cwd = char_ptr{posix::getcwd(nullptr, 0)})
|
||||
{
|
||||
p.assign(cwd.get());
|
||||
ec.clear();
|
||||
|
@ -833,6 +855,7 @@ fs::current_path(error_code& ec)
|
|||
else
|
||||
ec.assign(errno, std::generic_category());
|
||||
#else
|
||||
#ifdef _PC_PATH_MAX
|
||||
long path_max = pathconf(".", _PC_PATH_MAX);
|
||||
size_t size;
|
||||
if (path_max == -1)
|
||||
|
@ -841,9 +864,15 @@ fs::current_path(error_code& ec)
|
|||
size = 10240;
|
||||
else
|
||||
size = path_max;
|
||||
#elif defined(PATH_MAX)
|
||||
size_t size = PATH_MAX;
|
||||
#else
|
||||
size_t size = 1024;
|
||||
#endif
|
||||
for (char_ptr buf; p.empty(); size *= 2)
|
||||
{
|
||||
buf.reset((char*)malloc(size));
|
||||
using char_type = fs::path::value_type;
|
||||
buf.reset((char_type*)malloc(size * sizeof(char_type)));
|
||||
if (buf)
|
||||
{
|
||||
if (getcwd(buf.get(), size))
|
||||
|
@ -883,7 +912,7 @@ void
|
|||
fs::current_path(const path& p, error_code& ec) noexcept
|
||||
{
|
||||
#ifdef _GLIBCXX_HAVE_UNISTD_H
|
||||
if (::chdir(p.c_str()))
|
||||
if (posix::chdir(p.c_str()))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
ec.clear();
|
||||
|
@ -910,14 +939,14 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
|
|||
int err = 0;
|
||||
file_status s1, s2;
|
||||
stat_type st1, st2;
|
||||
if (::stat(p1.c_str(), &st1) == 0)
|
||||
if (posix::stat(p1.c_str(), &st1) == 0)
|
||||
s1 = make_file_status(st1);
|
||||
else if (is_not_found_errno(errno))
|
||||
s1.type(file_type::not_found);
|
||||
else
|
||||
err = errno;
|
||||
|
||||
if (::stat(p2.c_str(), &st2) == 0)
|
||||
if (posix::stat(p2.c_str(), &st2) == 0)
|
||||
s2 = make_file_status(st2);
|
||||
else if (is_not_found_errno(errno))
|
||||
s2.type(file_type::not_found);
|
||||
|
@ -966,8 +995,8 @@ namespace
|
|||
do_stat(const fs::path& p, std::error_code& ec, Accessor f, T deflt)
|
||||
{
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
fs::stat_type st;
|
||||
if (::stat(p.c_str(), &st))
|
||||
posix::stat_type st;
|
||||
if (posix::stat(p.c_str(), &st))
|
||||
{
|
||||
ec.assign(errno, std::generic_category());
|
||||
return deflt;
|
||||
|
@ -1017,7 +1046,7 @@ fs::hard_link_count(const path& p)
|
|||
std::uintmax_t
|
||||
fs::hard_link_count(const path& p, error_code& ec) noexcept
|
||||
{
|
||||
return do_stat(p, ec, std::mem_fn(&stat::st_nlink),
|
||||
return do_stat(p, ec, std::mem_fn(&stat_type::st_nlink),
|
||||
static_cast<uintmax_t>(-1));
|
||||
}
|
||||
|
||||
|
@ -1093,11 +1122,11 @@ fs::last_write_time(const path& p __attribute__((__unused__)),
|
|||
else
|
||||
ec.clear();
|
||||
#elif _GLIBCXX_HAVE_UTIME_H
|
||||
::utimbuf times;
|
||||
posix::utimbuf times;
|
||||
times.modtime = s.count();
|
||||
times.actime = do_stat(p, ec, [](const auto& st) { return st.st_atime; },
|
||||
times.modtime);
|
||||
if (::utime(p.c_str(), ×))
|
||||
if (posix::utime(p.c_str(), ×))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
ec.clear();
|
||||
|
@ -1152,7 +1181,7 @@ fs::permissions(const path& p, perms prms, perm_options opts,
|
|||
#else
|
||||
if (nofollow && is_symlink(st))
|
||||
ec = std::make_error_code(std::errc::operation_not_supported);
|
||||
else if (::chmod(p.c_str(), static_cast<mode_t>(prms)))
|
||||
else if (posix::chmod(p.c_str(), static_cast<mode_t>(prms)))
|
||||
err = errno;
|
||||
#endif
|
||||
|
||||
|
@ -1192,10 +1221,10 @@ fs::read_symlink(const path& p)
|
|||
return tgt;
|
||||
}
|
||||
|
||||
fs::path fs::read_symlink(const path& p, error_code& ec)
|
||||
fs::path fs::read_symlink(const path& p [[gnu::unused]], error_code& ec)
|
||||
{
|
||||
path result;
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
|
||||
#if defined(_GLIBCXX_HAVE_READLINK) && defined(_GLIBCXX_HAVE_SYS_STAT_H)
|
||||
stat_type st;
|
||||
if (::lstat(p.c_str(), &st))
|
||||
{
|
||||
|
@ -1268,6 +1297,19 @@ fs::remove(const path& p)
|
|||
bool
|
||||
fs::remove(const path& p, error_code& ec) noexcept
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
if (exists(symlink_status(p, ec)))
|
||||
{
|
||||
if ((is_directory(p, ec) && RemoveDirectoryW(p.c_str()))
|
||||
|| DeleteFileW(p.c_str()))
|
||||
{
|
||||
ec.clear();
|
||||
return true;
|
||||
}
|
||||
else if (!ec)
|
||||
ec.assign((int)GetLastError(), generic_category());
|
||||
}
|
||||
#else
|
||||
if (::remove(p.c_str()) == 0)
|
||||
{
|
||||
ec.clear();
|
||||
|
@ -1277,6 +1319,7 @@ fs::remove(const path& p, error_code& ec) noexcept
|
|||
ec.clear();
|
||||
else
|
||||
ec.assign(errno, std::generic_category());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1330,7 +1373,7 @@ fs::rename(const path& from, const path& to)
|
|||
void
|
||||
fs::rename(const path& from, const path& to, error_code& ec) noexcept
|
||||
{
|
||||
if (::rename(from.c_str(), to.c_str()))
|
||||
if (posix::rename(from.c_str(), to.c_str()))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
ec.clear();
|
||||
|
@ -1351,7 +1394,7 @@ fs::resize_file(const path& p, uintmax_t size, error_code& ec) noexcept
|
|||
#ifdef _GLIBCXX_HAVE_UNISTD_H
|
||||
if (size > static_cast<uintmax_t>(std::numeric_limits<off_t>::max()))
|
||||
ec.assign(EINVAL, std::generic_category());
|
||||
else if (::truncate(p.c_str(), size))
|
||||
else if (posix::truncate(p.c_str(), size))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
ec.clear();
|
||||
|
@ -1371,6 +1414,51 @@ fs::space(const path& p)
|
|||
return s;
|
||||
}
|
||||
|
||||
#ifdef NEED_DO_SPACE
|
||||
void
|
||||
fs::do_space(const __gnu_posix::char_type* pathname,
|
||||
uintmax_t& capacity, uintmax_t& free, uintmax_t& available,
|
||||
std::error_code& ec)
|
||||
{
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
|
||||
struct ::statvfs f;
|
||||
if (::statvfs(pathname, &f))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
{
|
||||
if (f.f_frsize != (unsigned long)-1)
|
||||
{
|
||||
const uintmax_t fragment_size = f.f_frsize;
|
||||
const fsblkcnt_t unknown = -1;
|
||||
if (f.f_blocks != unknown)
|
||||
capacity = f.f_blocks * fragment_size;
|
||||
if (f.f_bfree != unknown)
|
||||
free = f.f_bfree * fragment_size;
|
||||
if (f.f_bavail != unknown)
|
||||
available = f.f_bavail * fragment_size;
|
||||
}
|
||||
ec.clear();
|
||||
}
|
||||
#elif _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
ULARGE_INTEGER bytes_avail = {}, bytes_total = {}, bytes_free = {};
|
||||
if (GetDiskFreeSpaceExW(pathname, &bytes_avail, &bytes_total, &bytes_free))
|
||||
{
|
||||
if (bytes_total.QuadPart != 0)
|
||||
capacity = bytes_total.QuadPart;
|
||||
if (bytes_free.QuadPart != 0)
|
||||
free = bytes_free.QuadPart;
|
||||
if (bytes_avail.QuadPart != 0)
|
||||
available = bytes_avail.QuadPart;
|
||||
ec.clear();
|
||||
}
|
||||
else
|
||||
ec.assign((int)GetLastError(), std::system_category());
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
#endif
|
||||
}
|
||||
#endif // NEED_DO_SPACE
|
||||
|
||||
fs::space_info
|
||||
fs::space(const path& p, error_code& ec) noexcept
|
||||
{
|
||||
|
@ -1379,23 +1467,14 @@ fs::space(const path& p, error_code& ec) noexcept
|
|||
static_cast<uintmax_t>(-1),
|
||||
static_cast<uintmax_t>(-1)
|
||||
};
|
||||
#ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
|
||||
struct ::statvfs f;
|
||||
if (::statvfs(p.c_str(), &f))
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
{
|
||||
uintmax_t fragment_size = f.f_frsize;
|
||||
info = space_info{
|
||||
f.f_blocks * fragment_size,
|
||||
f.f_bfree * fragment_size,
|
||||
f.f_bavail * fragment_size
|
||||
};
|
||||
ec.clear();
|
||||
}
|
||||
#if _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
path dir = absolute(p);
|
||||
dir.remove_filename();
|
||||
auto str = dir.c_str();
|
||||
#else
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
auto str = p.c_str();
|
||||
#endif
|
||||
do_space(str, info.capacity, info.free, info.available, ec);
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -1405,7 +1484,7 @@ fs::status(const fs::path& p, error_code& ec) noexcept
|
|||
{
|
||||
file_status status;
|
||||
stat_type st;
|
||||
if (::stat(p.c_str(), &st))
|
||||
if (posix::stat(p.c_str(), &st))
|
||||
{
|
||||
int err = errno;
|
||||
ec.assign(err, std::generic_category());
|
||||
|
@ -1429,7 +1508,7 @@ fs::symlink_status(const fs::path& p, std::error_code& ec) noexcept
|
|||
{
|
||||
file_status status;
|
||||
stat_type st;
|
||||
if (::lstat(p.c_str(), &st))
|
||||
if (posix::lstat(p.c_str(), &st))
|
||||
{
|
||||
int err = errno;
|
||||
ec.assign(err, std::generic_category());
|
||||
|
@ -1476,28 +1555,39 @@ fs::path fs::temp_directory_path()
|
|||
|
||||
fs::path fs::temp_directory_path(error_code& ec)
|
||||
{
|
||||
path p;
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
ec = std::make_error_code(std::errc::not_supported);
|
||||
return {}; // TODO
|
||||
unsigned len = 1024;
|
||||
std::wstring buf;
|
||||
do
|
||||
{
|
||||
buf.resize(len);
|
||||
len = GetTempPathW(buf.size(), buf.data());
|
||||
} while (len > buf.size());
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
ec.assign((int)GetLastError(), std::system_category());
|
||||
return p;
|
||||
}
|
||||
buf.resize(len);
|
||||
p = std::move(buf);
|
||||
#else
|
||||
const char* tmpdir = nullptr;
|
||||
const char* env[] = { "TMPDIR", "TMP", "TEMP", "TEMPDIR", nullptr };
|
||||
for (auto e = env; tmpdir == nullptr && *e != nullptr; ++e)
|
||||
tmpdir = ::getenv(*e);
|
||||
path p = tmpdir ? tmpdir : "/tmp";
|
||||
auto st = status(p, ec);
|
||||
if (!ec)
|
||||
{
|
||||
if (is_directory(st))
|
||||
{
|
||||
ec.clear();
|
||||
return p;
|
||||
}
|
||||
else
|
||||
ec = std::make_error_code(std::errc::not_a_directory);
|
||||
}
|
||||
return {};
|
||||
p = tmpdir ? tmpdir : "/tmp";
|
||||
#endif
|
||||
auto st = status(p, ec);
|
||||
if (ec)
|
||||
p.clear();
|
||||
else if (!is_directory(st))
|
||||
{
|
||||
p.clear();
|
||||
ec = std::make_error_code(std::errc::not_a_directory);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
fs::path
|
||||
|
|
|
@ -38,6 +38,66 @@ fs::filesystem_error::~filesystem_error() = default;
|
|||
|
||||
constexpr path::value_type path::preferred_separator;
|
||||
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
path&
|
||||
path::operator/=(const path& __p)
|
||||
{
|
||||
if (__p.is_absolute()
|
||||
|| (__p.has_root_name() && __p.root_name() != root_name()))
|
||||
return operator=(__p);
|
||||
|
||||
basic_string_view<value_type> __lhs = _M_pathname;
|
||||
bool __add_sep = false;
|
||||
|
||||
if (__p.has_root_directory())
|
||||
{
|
||||
// Remove any root directory and relative path
|
||||
if (_M_type != _Type::_Root_name)
|
||||
{
|
||||
if (!_M_cmpts.empty()
|
||||
&& _M_cmpts.front()._M_type == _Type::_Root_name)
|
||||
__lhs = _M_cmpts.front()._M_pathname;
|
||||
else
|
||||
__lhs = {};
|
||||
}
|
||||
}
|
||||
else if (has_filename() || (!has_root_directory() && is_absolute()))
|
||||
__add_sep = true;
|
||||
|
||||
basic_string_view<value_type> __rhs = __p._M_pathname;
|
||||
// Omit any root-name from the generic format pathname:
|
||||
if (__p._M_type == _Type::_Root_name)
|
||||
__rhs = {};
|
||||
else if (!__p._M_cmpts.empty()
|
||||
&& __p._M_cmpts.front()._M_type == _Type::_Root_name)
|
||||
__rhs.remove_prefix(__p._M_cmpts.front()._M_pathname.size());
|
||||
|
||||
const size_t __len = __lhs.size() + (int)__add_sep + __rhs.size();
|
||||
const size_t __maxcmpts = _M_cmpts.size() + __p._M_cmpts.size();
|
||||
if (_M_pathname.capacity() < __len || _M_cmpts.capacity() < __maxcmpts)
|
||||
{
|
||||
// Construct new path and swap (strong exception-safety guarantee).
|
||||
string_type __tmp;
|
||||
__tmp.reserve(__len);
|
||||
__tmp = __lhs;
|
||||
if (__add_sep)
|
||||
__tmp += preferred_separator;
|
||||
__tmp += __rhs;
|
||||
path __newp = std::move(__tmp);
|
||||
swap(__newp);
|
||||
}
|
||||
else
|
||||
{
|
||||
_M_pathname = __lhs;
|
||||
if (__add_sep)
|
||||
_M_pathname += preferred_separator;
|
||||
_M_pathname += __rhs;
|
||||
_M_split_cmpts();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
path&
|
||||
path::remove_filename()
|
||||
{
|
||||
|
@ -74,6 +134,12 @@ path::replace_filename(const path& replacement)
|
|||
return *this;
|
||||
}
|
||||
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
const fs::path::value_type dot = L'.';
|
||||
#else
|
||||
const fs::path::value_type dot = '.';
|
||||
#endif
|
||||
|
||||
path&
|
||||
path::replace_extension(const path& replacement)
|
||||
{
|
||||
|
@ -94,8 +160,8 @@ path::replace_extension(const path& replacement)
|
|||
}
|
||||
// If replacement is not empty and does not begin with a dot character,
|
||||
// a dot character is appended
|
||||
if (!replacement.empty() && replacement.native()[0] != '.')
|
||||
_M_pathname += '.';
|
||||
if (!replacement.empty() && replacement.native()[0] != dot)
|
||||
_M_pathname += dot;
|
||||
operator+=(replacement);
|
||||
return *this;
|
||||
}
|
||||
|
@ -332,11 +398,7 @@ path::has_filename() const
|
|||
|
||||
namespace
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
inline bool is_dot(wchar_t c) { return c == L'.'; }
|
||||
#else
|
||||
inline bool is_dot(char c) { return c == '.'; }
|
||||
#endif
|
||||
inline bool is_dot(fs::path::value_type c) { return c == dot; }
|
||||
|
||||
inline bool is_dot(const fs::path& path)
|
||||
{
|
||||
|
@ -376,7 +438,7 @@ path::lexically_normal() const
|
|||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
// Replace each slash character in the root-name
|
||||
if (p.is_root_name())
|
||||
if (p._M_type == _Type::_Root_name)
|
||||
{
|
||||
string_type s = p.native();
|
||||
std::replace(s.begin(), s.end(), L'/', L'\\');
|
||||
|
@ -485,7 +547,7 @@ path::lexically_proximate(const path& base) const
|
|||
std::pair<const path::string_type*, std::size_t>
|
||||
path::_M_find_extension() const
|
||||
{
|
||||
const std::string* s = nullptr;
|
||||
const string_type* s = nullptr;
|
||||
|
||||
if (_M_type == _Type::_Filename)
|
||||
s = &_M_pathname;
|
||||
|
@ -500,9 +562,9 @@ path::_M_find_extension() const
|
|||
{
|
||||
if (auto sz = s->size())
|
||||
{
|
||||
if (sz <= 2 && (*s)[0] == '.')
|
||||
if (sz <= 2 && (*s)[0] == dot)
|
||||
return { s, string_type::npos };
|
||||
const auto pos = s->rfind('.');
|
||||
const auto pos = s->rfind(dot);
|
||||
return { s, pos ? pos : string_type::npos };
|
||||
}
|
||||
}
|
||||
|
@ -703,8 +765,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
|
||||
std::string filesystem_error::_M_gen_what()
|
||||
{
|
||||
return fs_err_concat(system_error::what(), _M_path1.native(),
|
||||
_M_path2.native());
|
||||
return fs_err_concat(system_error::what(), _M_path1.u8string(),
|
||||
_M_path2.u8string());
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_CXX11
|
||||
|
|
|
@ -47,16 +47,17 @@ test01()
|
|||
|
||||
// Test non-empty directory.
|
||||
ec = bad_ec;
|
||||
create_directory_symlink(p, p / "l", ec);
|
||||
create_directory(p / "x", ec);
|
||||
VERIFY( !ec );
|
||||
ec = bad_ec;
|
||||
iter = fs::directory_iterator(p, ec);
|
||||
VERIFY( !ec );
|
||||
VERIFY( iter != fs::directory_iterator() );
|
||||
VERIFY( iter->path() == p/"l" );
|
||||
VERIFY( iter->path() == p/"x" );
|
||||
++iter;
|
||||
VERIFY( iter == end(iter) );
|
||||
|
||||
#if !(defined(__MINGW32__) || defined(__MINGW64__))
|
||||
// Test inaccessible directory.
|
||||
ec = bad_ec;
|
||||
permissions(p, fs::perms::none, ec);
|
||||
|
@ -71,6 +72,7 @@ test01()
|
|||
iter = fs::directory_iterator(p, opts, ec);
|
||||
VERIFY( !ec );
|
||||
VERIFY( iter == end(iter) );
|
||||
#endif
|
||||
|
||||
permissions(p, fs::perms::owner_all, ec);
|
||||
remove_all(p, ec);
|
||||
|
@ -84,7 +86,7 @@ test02()
|
|||
const auto p = __gnu_test::nonexistent_path();
|
||||
ec = bad_ec;
|
||||
create_directory(p, fs::current_path(), ec);
|
||||
create_directory_symlink(p, p / "l", ec);
|
||||
create_directory(p / "x", ec);
|
||||
VERIFY( !ec );
|
||||
|
||||
// Test post-increment (libstdc++/71005)
|
||||
|
@ -95,7 +97,7 @@ test02()
|
|||
const auto entry1 = *iter;
|
||||
const auto entry2 = *iter++;
|
||||
VERIFY( entry1 == entry2 );
|
||||
VERIFY( entry1.path() == p/"l" );
|
||||
VERIFY( entry1.path() == p/"x" );
|
||||
VERIFY( iter == end(iter) );
|
||||
|
||||
remove_all(p, ec);
|
||||
|
@ -130,7 +132,7 @@ test05()
|
|||
{
|
||||
auto p = __gnu_test::nonexistent_path();
|
||||
create_directory(p);
|
||||
create_directory_symlink(p, p / "l");
|
||||
create_directory(p / "x");
|
||||
fs::directory_iterator it(p), endit;
|
||||
VERIFY( begin(it) == it );
|
||||
static_assert( noexcept(begin(it)), "begin is noexcept" );
|
||||
|
|
|
@ -60,6 +60,7 @@ test01()
|
|||
++iter;
|
||||
VERIFY( iter == end(iter) );
|
||||
|
||||
#if ! (defined (__MINGW32__) || defined(__MINGW64__))
|
||||
// Test inaccessible directory.
|
||||
ec = bad_ec;
|
||||
permissions(p, fs::perms::none, ec);
|
||||
|
@ -106,6 +107,7 @@ test01()
|
|||
iter.increment(ec); // should fail to recurse into p/d1/d2, so skip it
|
||||
VERIFY( !ec );
|
||||
VERIFY( iter == end(iter) );
|
||||
#endif
|
||||
|
||||
permissions(p/"d1/d2", fs::perms::owner_all, ec);
|
||||
remove_all(p, ec);
|
||||
|
@ -171,7 +173,7 @@ test05()
|
|||
{
|
||||
auto p = __gnu_test::nonexistent_path();
|
||||
create_directory(p);
|
||||
create_directory_symlink(p, p / "l");
|
||||
create_directory(p / "x");
|
||||
fs::recursive_directory_iterator it(p), endit;
|
||||
VERIFY( begin(it) == it );
|
||||
static_assert( noexcept(begin(it)), "begin is noexcept" );
|
||||
|
|
|
@ -41,6 +41,22 @@ test01()
|
|||
void
|
||||
test02()
|
||||
{
|
||||
std::error_code ec = make_error_code(std::errc::invalid_argument);
|
||||
path root = __gnu_test::root_path();
|
||||
VERIFY( absolute(root) == root );
|
||||
VERIFY( absolute(root, ec) == root && !ec );
|
||||
VERIFY( absolute(path{}, ec).empty() && ec );
|
||||
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
path p1("/");
|
||||
VERIFY( absolute(p1) != p1 );
|
||||
path p2("/foo");
|
||||
VERIFY( absolute(p2) != p2 );
|
||||
path p3("foo");
|
||||
VERIFY( absolute(p3) != p3 );
|
||||
path p4("C:\\");
|
||||
VERIFY( absolute(p4) == p4 );
|
||||
#else
|
||||
path p1("/");
|
||||
VERIFY( absolute(p1) == p1 );
|
||||
path p2("/foo");
|
||||
|
@ -48,6 +64,7 @@ test02()
|
|||
path p3("foo");
|
||||
VERIFY( absolute(p3) != p3 );
|
||||
VERIFY( absolute(p3) == (std::filesystem::current_path()/p3) );
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -41,7 +41,7 @@ test01()
|
|||
VERIFY( !ec );
|
||||
|
||||
ec = bad_ec;
|
||||
p2 = canonical( fs::current_path() / "." / (p.native() + "////././."), ec );
|
||||
p2 = canonical( fs::current_path() / "." / (p.string() + "////././."), ec );
|
||||
compare_paths( p2, fs::current_path()/p );
|
||||
VERIFY( !ec );
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ test03()
|
|||
auto to = __gnu_test::nonexistent_path();
|
||||
|
||||
// test empty file
|
||||
std::ofstream{from.native()};
|
||||
std::ofstream{from};
|
||||
VERIFY( fs::exists(from) );
|
||||
VERIFY( fs::file_size(from) == 0 );
|
||||
fs::copy(from, to);
|
||||
|
@ -125,7 +125,7 @@ test03()
|
|||
|
||||
remove(to);
|
||||
VERIFY( !fs::exists(to) );
|
||||
std::ofstream{from.native()} << "Hello, filesystem!";
|
||||
std::ofstream{from} << "Hello, filesystem!";
|
||||
VERIFY( fs::file_size(from) != 0 );
|
||||
fs::copy(from, to);
|
||||
VERIFY( fs::exists(to) );
|
||||
|
|
|
@ -42,7 +42,7 @@ test01()
|
|||
VERIFY( !exists(to) );
|
||||
|
||||
// test empty file
|
||||
std::ofstream{from.native()};
|
||||
std::ofstream{from};
|
||||
VERIFY( exists(from) );
|
||||
VERIFY( file_size(from) == 0 );
|
||||
|
||||
|
@ -58,7 +58,7 @@ test01()
|
|||
VERIFY( exists(to) );
|
||||
VERIFY( file_size(to) == 0 );
|
||||
|
||||
std::ofstream{from.native()} << "Hello, filesystem!";
|
||||
std::ofstream{from} << "Hello, filesystem!";
|
||||
VERIFY( file_size(from) != 0 );
|
||||
remove(to);
|
||||
VERIFY( !exists(to) );
|
||||
|
|
|
@ -29,19 +29,20 @@ void
|
|||
test01()
|
||||
{
|
||||
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
|
||||
const path root = __gnu_test::root_path();
|
||||
|
||||
VERIFY( exists(path{"/"}) );
|
||||
VERIFY( exists(path{"/."}) );
|
||||
VERIFY( exists(root) );
|
||||
VERIFY( exists(root/".") );
|
||||
VERIFY( exists(path{"."}) );
|
||||
VERIFY( exists(path{".."}) );
|
||||
VERIFY( exists(std::filesystem::current_path()) );
|
||||
|
||||
std::error_code ec;
|
||||
ec = bad_ec;
|
||||
VERIFY( exists(path{"/"}, ec) );
|
||||
VERIFY( exists(root, ec) );
|
||||
VERIFY( !ec );
|
||||
ec = bad_ec;
|
||||
VERIFY( exists(path{"/."}, ec) );
|
||||
VERIFY( exists(root/".", ec) );
|
||||
VERIFY( !ec );
|
||||
ec = bad_ec;
|
||||
VERIFY( exists(path{"."}, ec) );
|
||||
|
|
|
@ -82,7 +82,7 @@ test02()
|
|||
empty = is_empty(f.path);
|
||||
VERIFY( empty );
|
||||
|
||||
std::ofstream{f.path.native()} << "data";
|
||||
std::ofstream{f.path} << "data";
|
||||
ec = bad_ec;
|
||||
empty = is_empty(p, ec);
|
||||
VERIFY( !ec );
|
||||
|
|
|
@ -81,7 +81,7 @@ test01()
|
|||
::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(), ×) );
|
||||
VERIFY( !::utime(p.string().c_str(), ×) );
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
|
|
@ -25,25 +25,35 @@
|
|||
#include <testsuite_fs.h>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
bool check(std::filesystem::space_info const& s)
|
||||
{
|
||||
const std::uintmax_t err = -1;
|
||||
return s.capacity != err || s.free != err || s.available != err;
|
||||
}
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
std::filesystem::space_info s = std::filesystem::space("/");
|
||||
const std::filesystem::path root = __gnu_test::root_path();
|
||||
std::filesystem::space_info s = std::filesystem::space(root);
|
||||
std::error_code ec = make_error_code(std::errc::invalid_argument);
|
||||
s = std::filesystem::space("/", ec);
|
||||
s = std::filesystem::space(root, ec);
|
||||
VERIFY( !ec );
|
||||
VERIFY( check(s) );
|
||||
VERIFY( s.capacity >= s.free );
|
||||
|
||||
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) );
|
||||
s = std::filesystem::space(__gnu_test::nonexistent_path()/".", ec);
|
||||
if (ec)
|
||||
VERIFY( ! check(s) );
|
||||
else
|
||||
VERIFY( check(s) );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
std::filesystem::space_info s = std::filesystem::space(".");
|
||||
VERIFY( check(s) );
|
||||
VERIFY( s.capacity >= s.free );
|
||||
}
|
||||
|
||||
|
|
|
@ -27,10 +27,28 @@
|
|||
void
|
||||
clean_env()
|
||||
{
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
::_putenv("TMP=");
|
||||
::_putenv("TEMP=");
|
||||
#else
|
||||
::unsetenv("TMPDIR");
|
||||
::unsetenv("TMP");
|
||||
::unsetenv("TEMPDIR");
|
||||
::unsetenv("TEMP");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
set_env(const char* name, std::string value)
|
||||
{
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
std::string s = name;
|
||||
s += '=';
|
||||
s += value;
|
||||
return !::_putenv(s.c_str());
|
||||
#else
|
||||
return !::setenv(name, value.c_str(), 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
@ -57,7 +75,7 @@ test02()
|
|||
{
|
||||
clean_env();
|
||||
|
||||
if (::setenv("TMPDIR", __gnu_test::nonexistent_path().string().c_str(), 1))
|
||||
if (!set_env("TMPDIR", __gnu_test::nonexistent_path().string()))
|
||||
return; // just give up
|
||||
|
||||
std::error_code ec;
|
||||
|
@ -80,7 +98,7 @@ test03()
|
|||
auto p = __gnu_test::nonexistent_path();
|
||||
create_directories(p/"tmp");
|
||||
permissions(p, fs::perms::none);
|
||||
setenv("TMPDIR", (p/"tmp").c_str(), 1);
|
||||
set_env("TMPDIR", (p/"tmp").string());
|
||||
std::error_code ec;
|
||||
auto r = fs::temp_directory_path(ec); // libstdc++/PR71337
|
||||
VERIFY( ec == std::make_error_code(std::errc::permission_denied) );
|
||||
|
@ -102,7 +120,7 @@ void
|
|||
test04()
|
||||
{
|
||||
__gnu_test::scoped_file f;
|
||||
setenv("TMPDIR", f.path.c_str(), 1);
|
||||
set_env("TMPDIR", f.path.string());
|
||||
std::error_code ec;
|
||||
auto r = fs::temp_directory_path(ec);
|
||||
VERIFY( ec == std::make_error_code(std::errc::not_a_directory) );
|
||||
|
|
|
@ -55,6 +55,10 @@ test01()
|
|||
|
||||
compare_paths( append("dir/", "/file"), "/file" );
|
||||
compare_paths( append("dir/", "file"), "dir/file" );
|
||||
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
compare_paths( append("c:/foo", "/bar"), "c:/bar" );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -30,7 +30,7 @@ void
|
|||
test01()
|
||||
{
|
||||
// path(string_type&&, format)
|
||||
auto s = [&]() -> path::string_type { return "foo/bar"; };
|
||||
auto s = [&]() -> path::string_type { return path("foo/bar").native(); };
|
||||
path p0(s());
|
||||
path p1(s(), path::auto_format);
|
||||
VERIFY( p1 == p0 );
|
||||
|
@ -44,7 +44,7 @@ void
|
|||
test02()
|
||||
{
|
||||
// path(const Source&, format)
|
||||
path::string_type s = "foo/bar";
|
||||
const path::string_type s = path("foo/bar").native();
|
||||
path p0(s);
|
||||
path p1(s, path::auto_format);
|
||||
VERIFY( p1 == p0 );
|
||||
|
@ -58,7 +58,7 @@ void
|
|||
test03()
|
||||
{
|
||||
// path(const Source&, format)
|
||||
std::string s = "foo/bar";
|
||||
const std::string s = "foo/bar";
|
||||
path p0(s);
|
||||
path p1(s, path::auto_format);
|
||||
VERIFY( p1 == p0 );
|
||||
|
@ -73,7 +73,7 @@ test04()
|
|||
{
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
// path(const Source&, format)
|
||||
std::wstring s = L"foo/bar";
|
||||
const std::wstring s = L"foo/bar";
|
||||
path p0(s);
|
||||
path p1(s, path::auto_format);
|
||||
VERIFY( p1 == p0 );
|
||||
|
|
|
@ -31,7 +31,11 @@ void
|
|||
test01()
|
||||
{
|
||||
path p("/foo/bar", std::locale::classic());
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
VERIFY( p.native() == L"/foo/bar" );
|
||||
#else
|
||||
VERIFY( p.native() == "/foo/bar" );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -47,7 +47,12 @@ test02()
|
|||
{
|
||||
path rootdir = p.root_directory();
|
||||
VERIFY( !rootdir.has_relative_path() );
|
||||
VERIFY( rootdir.empty() || rootdir.native() == "/");
|
||||
if (!rootdir.empty())
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
VERIFY( rootdir.string() == "/" || rootdir.string() == "\\" );
|
||||
#else
|
||||
VERIFY( rootdir.string() == "/" );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ test01()
|
|||
path p = "foo.bar.baz.tar";
|
||||
std::vector<std::string> v;
|
||||
for (; !p.extension().empty(); p = p.stem())
|
||||
v.push_back(p.extension().native());
|
||||
v.push_back(p.extension().string());
|
||||
VERIFY( v.at(0) == ".tar" );
|
||||
VERIFY( v.at(1) == ".baz" );
|
||||
VERIFY( v.at(2) == ".bar" );
|
||||
|
|
|
@ -81,6 +81,24 @@ test01()
|
|||
v2 = { "//rootname", "/", "dir", "filename" };
|
||||
#else
|
||||
v2 = { "/", "rootname", "dir", "filename" };
|
||||
#endif
|
||||
VERIFY( v == v2 );
|
||||
|
||||
p = "c:relative/path";
|
||||
v.assign(p.begin(), p.end());
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
v2 = { "c:", "relative", "path" };
|
||||
#else
|
||||
v2 = { "c:relative", "path" };
|
||||
#endif
|
||||
VERIFY( v == v2 );
|
||||
|
||||
p = "c:/absolute/path";
|
||||
v.assign(p.begin(), p.end());
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
v2 = { "c:", "/", "absolute", "path" };
|
||||
#else
|
||||
v2 = { "c:", "absolute", "path" };
|
||||
#endif
|
||||
VERIFY( v == v2 );
|
||||
}
|
||||
|
|
|
@ -27,14 +27,15 @@ void
|
|||
test01()
|
||||
{
|
||||
using namespace std::filesystem;
|
||||
const std::string s = "abc";
|
||||
using string_type = std::basic_string<path::value_type>;
|
||||
const string_type s{ 'a', 'b', 'c' };
|
||||
path p(s);
|
||||
|
||||
VERIFY( p.native() == s );
|
||||
VERIFY( p.c_str() == s );
|
||||
VERIFY( static_cast<std::string>(p) == s );
|
||||
VERIFY( static_cast<string_type>(p) == s );
|
||||
|
||||
std::string s2 = p; // implicit conversion
|
||||
string_type s2 = p; // implicit conversion
|
||||
VERIFY( s2 == p.native() );
|
||||
}
|
||||
|
||||
|
|
|
@ -29,11 +29,17 @@ using std::filesystem::path;
|
|||
void
|
||||
test01()
|
||||
{
|
||||
VERIFY( path("/").is_absolute() );
|
||||
VERIFY( path("/foo").is_absolute() );
|
||||
VERIFY( path("/foo/").is_absolute() );
|
||||
VERIFY( path("/foo/bar").is_absolute() );
|
||||
VERIFY( path("/foo/bar/").is_absolute() );
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
const bool is_posix = false;
|
||||
#else
|
||||
const bool is_posix = true;
|
||||
#endif
|
||||
|
||||
VERIFY( path("/").is_absolute() == is_posix );
|
||||
VERIFY( path("/foo").is_absolute() == is_posix );
|
||||
VERIFY( path("/foo/").is_absolute() == is_posix );
|
||||
VERIFY( path("/foo/bar").is_absolute() == is_posix );
|
||||
VERIFY( path("/foo/bar/").is_absolute() == is_posix );
|
||||
VERIFY( ! path("foo").is_absolute() );
|
||||
VERIFY( ! path("foo/").is_absolute() );
|
||||
VERIFY( ! path("foo/bar").is_absolute() );
|
||||
|
@ -43,16 +49,11 @@ test01()
|
|||
VERIFY( ! path("c:foo/").is_absolute() );
|
||||
VERIFY( ! path("c:foo/bar").is_absolute() );
|
||||
VERIFY( ! path("c:foo/bar/").is_absolute() );
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
const bool drive_letter_is_root_name = true;
|
||||
#else
|
||||
const bool drive_letter_is_root_name = false;
|
||||
#endif
|
||||
VERIFY( path("c:/").is_absolute() == drive_letter_is_root_name );
|
||||
VERIFY( path("c:/foo").is_absolute() == drive_letter_is_root_name );
|
||||
VERIFY( path("c:/foo/").is_absolute() == drive_letter_is_root_name );
|
||||
VERIFY( path("c:/foo/bar").is_absolute() == drive_letter_is_root_name );
|
||||
VERIFY( path("c:/foo/bar/").is_absolute() == drive_letter_is_root_name );
|
||||
VERIFY( path("c:/").is_absolute() == !is_posix );
|
||||
VERIFY( path("c:/foo").is_absolute() == !is_posix );
|
||||
VERIFY( path("c:/foo/").is_absolute() == !is_posix );
|
||||
VERIFY( path("c:/foo/bar").is_absolute() == !is_posix );
|
||||
VERIFY( path("c:/foo/bar/").is_absolute() == !is_posix );
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -44,15 +44,16 @@ test01()
|
|||
VERIFY( iter == end(iter) );
|
||||
|
||||
// Test non-empty directory.
|
||||
create_directory_symlink(p, p / "l", ec);
|
||||
create_directory(p / "x", ec);
|
||||
VERIFY( !ec );
|
||||
iter = fs::directory_iterator(p, ec);
|
||||
VERIFY( !ec );
|
||||
VERIFY( iter != fs::directory_iterator() );
|
||||
VERIFY( iter->path() == p/"l" );
|
||||
VERIFY( iter->path() == p/"x" );
|
||||
++iter;
|
||||
VERIFY( iter == end(iter) );
|
||||
|
||||
#if !(defined(__MINGW32__) || defined(__MINGW64__))
|
||||
// Test inaccessible directory.
|
||||
permissions(p, fs::perms::none, ec);
|
||||
VERIFY( !ec );
|
||||
|
@ -65,6 +66,7 @@ test01()
|
|||
iter = fs::directory_iterator(p, opts, ec);
|
||||
VERIFY( !ec );
|
||||
VERIFY( iter == end(iter) );
|
||||
#endif
|
||||
|
||||
permissions(p, fs::perms::owner_all, ec);
|
||||
remove_all(p, ec);
|
||||
|
@ -76,7 +78,7 @@ test02()
|
|||
std::error_code ec;
|
||||
const auto p = __gnu_test::nonexistent_path();
|
||||
create_directory(p, fs::current_path(), ec);
|
||||
create_directory_symlink(p, p / "l", ec);
|
||||
create_directory(p / "x", ec);
|
||||
VERIFY( !ec );
|
||||
|
||||
// Test post-increment (libstdc++/71005)
|
||||
|
@ -86,7 +88,7 @@ test02()
|
|||
const auto entry1 = *iter;
|
||||
const auto entry2 = *iter++;
|
||||
VERIFY( entry1 == entry2 );
|
||||
VERIFY( entry1.path() == p/"l" );
|
||||
VERIFY( entry1.path() == p/"x" );
|
||||
VERIFY( iter == end(iter) );
|
||||
|
||||
remove_all(p, ec);
|
||||
|
@ -121,7 +123,7 @@ test05()
|
|||
{
|
||||
auto p = __gnu_test::nonexistent_path();
|
||||
create_directory(p);
|
||||
create_directory_symlink(p, p / "l");
|
||||
create_directory(p / "x");
|
||||
fs::directory_iterator it(p), endit;
|
||||
VERIFY( begin(it) == it );
|
||||
static_assert( noexcept(begin(it)), "begin is noexcept" );
|
||||
|
|
|
@ -31,12 +31,29 @@ void
|
|||
test01()
|
||||
{
|
||||
for (const path& p : __gnu_test::test_paths)
|
||||
{
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
if (p.empty())
|
||||
continue;
|
||||
#endif
|
||||
VERIFY( absolute(p).is_absolute() );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
path p1("/");
|
||||
VERIFY( absolute(p1) != p1 );
|
||||
path p2("/foo");
|
||||
VERIFY( absolute(p2) != p2 );
|
||||
path p3("foo");
|
||||
VERIFY( absolute(p3) != p3 );
|
||||
path p4("C:\\");
|
||||
VERIFY( absolute(p3, p4) == "C:\\foo" );
|
||||
VERIFY( absolute(p4) == p4 );
|
||||
#else
|
||||
path p1("/");
|
||||
VERIFY( absolute(p1) == p1 );
|
||||
VERIFY( absolute(p1, "/bar") == p1 );
|
||||
|
@ -46,6 +63,7 @@ test02()
|
|||
path p3("foo");
|
||||
VERIFY( absolute(p3) != p3 );
|
||||
VERIFY( absolute(p3, "/bar") == "/bar/foo" );
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -114,7 +114,7 @@ test03()
|
|||
auto to = __gnu_test::nonexistent_path();
|
||||
|
||||
// test empty file
|
||||
std::ofstream{from.native()};
|
||||
std::ofstream{from.c_str()};
|
||||
VERIFY( fs::exists(from) );
|
||||
VERIFY( fs::file_size(from) == 0 );
|
||||
fs::copy(from, to);
|
||||
|
@ -123,7 +123,7 @@ test03()
|
|||
|
||||
remove(to);
|
||||
VERIFY( !fs::exists(to) );
|
||||
std::ofstream{from.native()} << "Hello, filesystem!";
|
||||
std::ofstream{from.c_str()} << "Hello, filesystem!";
|
||||
VERIFY( fs::file_size(from) != 0 );
|
||||
fs::copy(from, to);
|
||||
VERIFY( fs::exists(to) );
|
||||
|
@ -150,9 +150,9 @@ test04()
|
|||
}
|
||||
|
||||
__gnu_test::scoped_file f1(from/"a/f1");
|
||||
std::ofstream{f1.path} << "file one";
|
||||
std::ofstream{f1.path.c_str()} << "file one";
|
||||
__gnu_test::scoped_file f2(from/"a/b/f2");
|
||||
std::ofstream{f2.path} << "file two";
|
||||
std::ofstream{f2.path.c_str()} << "file two";
|
||||
|
||||
copy(from, to, ec);
|
||||
VERIFY( !ec );
|
||||
|
|
|
@ -42,7 +42,7 @@ test01()
|
|||
VERIFY( !exists(to) );
|
||||
|
||||
// test empty file
|
||||
std::ofstream{from.native()};
|
||||
std::ofstream{from.c_str()};
|
||||
VERIFY( exists(from) );
|
||||
VERIFY( file_size(from) == 0 );
|
||||
|
||||
|
@ -58,7 +58,7 @@ test01()
|
|||
VERIFY( exists(to) );
|
||||
VERIFY( file_size(to) == 0 );
|
||||
|
||||
std::ofstream{from.native()} << "Hello, filesystem!";
|
||||
std::ofstream{from.c_str()} << "Hello, filesystem!";
|
||||
VERIFY( file_size(from) != 0 );
|
||||
remove(to);
|
||||
VERIFY( !exists(to) );
|
||||
|
|
|
@ -28,16 +28,18 @@ using std::experimental::filesystem::path;
|
|||
void
|
||||
test01()
|
||||
{
|
||||
VERIFY( exists(path{"/"}) );
|
||||
VERIFY( exists(path{"/."}) );
|
||||
const path root = __gnu_test::root_path();
|
||||
|
||||
VERIFY( exists(root) );
|
||||
VERIFY( exists(root/".") );
|
||||
VERIFY( exists(path{"."}) );
|
||||
VERIFY( exists(path{".."}) );
|
||||
VERIFY( exists(std::experimental::filesystem::current_path()) );
|
||||
|
||||
std::error_code ec = std::make_error_code(std::errc::invalid_argument);
|
||||
VERIFY( exists(path{"/"}, ec) );
|
||||
VERIFY( exists(root, ec) );
|
||||
VERIFY( !ec );
|
||||
VERIFY( exists(path{"/."}, ec) );
|
||||
VERIFY( exists(root/".", ec) );
|
||||
VERIFY( !ec );
|
||||
VERIFY( exists(path{"."}, ec) );
|
||||
VERIFY( !ec );
|
||||
|
|
|
@ -82,7 +82,7 @@ test02()
|
|||
empty = is_empty(f.path);
|
||||
VERIFY( empty );
|
||||
|
||||
std::ofstream{f.path.native()} << "data";
|
||||
std::ofstream{f.path.c_str()} << "data";
|
||||
ec = bad_ec;
|
||||
empty = is_empty(p, ec);
|
||||
VERIFY( !ec );
|
||||
|
|
|
@ -81,7 +81,7 @@ test01()
|
|||
::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(), ×) );
|
||||
VERIFY( !::utime(p.string().c_str(), ×) );
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
|
|
@ -30,9 +30,10 @@ namespace fs = std::experimental::filesystem;
|
|||
void
|
||||
test01()
|
||||
{
|
||||
fs::space_info s = fs::space("/");
|
||||
const fs::path root = __gnu_test::root_path();
|
||||
fs::space_info s = fs::space(root);
|
||||
std::error_code ec = make_error_code(std::errc::invalid_argument);
|
||||
s = fs::space("/", ec);
|
||||
s = fs::space(root, ec);
|
||||
VERIFY( !ec );
|
||||
|
||||
s = fs::space(__gnu_test::nonexistent_path(), ec);
|
||||
|
|
|
@ -27,10 +27,28 @@
|
|||
void
|
||||
clean_env()
|
||||
{
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
::_putenv("TMP=");
|
||||
::_putenv("TEMP=");
|
||||
#else
|
||||
::unsetenv("TMPDIR");
|
||||
::unsetenv("TMP");
|
||||
::unsetenv("TEMPDIR");
|
||||
::unsetenv("TEMP");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
set_env(const char* name, std::string value)
|
||||
{
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
std::string s = name;
|
||||
s += '=';
|
||||
s += value;
|
||||
return !::_putenv(s.c_str());
|
||||
#else
|
||||
return !::setenv(name, value.c_str(), 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace fs = std::experimental::filesystem;
|
||||
|
@ -57,7 +75,7 @@ test02()
|
|||
{
|
||||
clean_env();
|
||||
|
||||
if (::setenv("TMPDIR", __gnu_test::nonexistent_path().string().c_str(), 1))
|
||||
if (set_env("TMPDIR", __gnu_test::nonexistent_path().string()))
|
||||
return; // just give up
|
||||
|
||||
std::error_code ec;
|
||||
|
@ -80,7 +98,7 @@ test03()
|
|||
auto p = __gnu_test::nonexistent_path();
|
||||
create_directories(p/"tmp");
|
||||
permissions(p, fs::perms::none);
|
||||
setenv("TMPDIR", (p/"tmp").c_str(), 1);
|
||||
set_env("TMPDIR", (p/"tmp").string());
|
||||
std::error_code ec;
|
||||
auto r = fs::temp_directory_path(ec); // libstdc++/PR71337
|
||||
VERIFY( ec == std::make_error_code(std::errc::permission_denied) );
|
||||
|
@ -102,7 +120,7 @@ void
|
|||
test04()
|
||||
{
|
||||
__gnu_test::scoped_file f;
|
||||
setenv("TMPDIR", f.path.c_str(), 1);
|
||||
set_env("TMPDIR", f.path.string());
|
||||
std::error_code ec;
|
||||
auto r = fs::temp_directory_path(ec);
|
||||
VERIFY( ec == std::make_error_code(std::errc::not_a_directory) );
|
||||
|
|
|
@ -34,16 +34,20 @@ test01()
|
|||
|
||||
path pp = p;
|
||||
pp /= p;
|
||||
VERIFY( pp.native() == "/foo/bar/foo/bar" );
|
||||
VERIFY( pp.string() == "/foo/bar/foo/bar" );
|
||||
|
||||
path q("baz");
|
||||
|
||||
path qq = q;
|
||||
qq /= q;
|
||||
VERIFY( qq.native() == "baz/baz" );
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
VERIFY( qq.string() == "baz\\baz" );
|
||||
#else
|
||||
VERIFY( qq.string() == "baz/baz" );
|
||||
#endif
|
||||
|
||||
q /= p;
|
||||
VERIFY( q.native() == "baz/foo/bar" );
|
||||
VERIFY( q.string() == "baz/foo/bar" );
|
||||
|
||||
path r = "";
|
||||
r /= path();
|
||||
|
@ -54,7 +58,7 @@ test01()
|
|||
|
||||
path s = "dir/";
|
||||
s /= path("/file");
|
||||
VERIFY( s.native() == "dir//file" );
|
||||
VERIFY( s.string() == "dir//file" );
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -34,18 +34,18 @@ test01()
|
|||
|
||||
path pp = p;
|
||||
pp += p;
|
||||
VERIFY( pp.native() == "/foo/bar/foo/bar" );
|
||||
VERIFY( pp.string() == "/foo/bar/foo/bar" );
|
||||
VERIFY( std::distance(pp.begin(), pp.end()) == 5 );
|
||||
|
||||
path q("foo/bar");
|
||||
|
||||
path qq = q;
|
||||
qq += q;
|
||||
VERIFY( qq.native() == "foo/barfoo/bar" );
|
||||
VERIFY( qq.string() == "foo/barfoo/bar" );
|
||||
VERIFY( std::distance(qq.begin(), qq.end()) == 3 );
|
||||
|
||||
q += p;
|
||||
VERIFY( q.native() == "foo/bar/foo/bar" );
|
||||
VERIFY( q.string() == "foo/bar/foo/bar" );
|
||||
VERIFY( std::distance(q.begin(), q.end()) == 4 );
|
||||
}
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ test02()
|
|||
path rootdir = p.root_directory();
|
||||
// If root-directory is composed of 'slash name',
|
||||
// 'slash' is excluded from the returned string.
|
||||
if (!rootdir.empty() && rootdir.native() != "/")
|
||||
VERIFY( rootdir.native()[0] != '/' );
|
||||
if (!rootdir.empty() && rootdir.string() != "/")
|
||||
VERIFY( rootdir.string()[0] != '/' );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ test01()
|
|||
path p = "foo.bar.baz.tar";
|
||||
std::vector<std::string> v;
|
||||
for (; !p.extension().empty(); p = p.stem())
|
||||
v.push_back(p.extension().native());
|
||||
v.push_back(p.extension().string());
|
||||
VERIFY( v.at(0) == ".tar" );
|
||||
VERIFY( v.at(1) == ".baz" );
|
||||
VERIFY( v.at(2) == ".bar" );
|
||||
|
|
|
@ -27,14 +27,15 @@ void
|
|||
test01()
|
||||
{
|
||||
using namespace std::experimental::filesystem;
|
||||
const std::string s = "abc";
|
||||
using string_type = std::basic_string<path::value_type>;
|
||||
const string_type s{ 'a', 'b', 'c' };
|
||||
path p(s);
|
||||
|
||||
VERIFY( p.native() == s );
|
||||
VERIFY( p.c_str() == s );
|
||||
VERIFY( static_cast<std::string>(p) == s );
|
||||
VERIFY( static_cast<string_type>(p) == s );
|
||||
|
||||
std::string s2 = p; // implicit conversion
|
||||
string_type s2 = p; // implicit conversion
|
||||
VERIFY( s2 == p.native() );
|
||||
}
|
||||
|
||||
|
|
|
@ -29,11 +29,17 @@ using std::filesystem::path;
|
|||
void
|
||||
test01()
|
||||
{
|
||||
VERIFY( path("/").is_absolute() );
|
||||
VERIFY( path("/foo").is_absolute() );
|
||||
VERIFY( path("/foo/").is_absolute() );
|
||||
VERIFY( path("/foo/bar").is_absolute() );
|
||||
VERIFY( path("/foo/bar/").is_absolute() );
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
const bool is_posix = false;
|
||||
#else
|
||||
const bool is_posix = true;
|
||||
#endif
|
||||
|
||||
VERIFY( path("/").is_absolute() == is_posix );
|
||||
VERIFY( path("/foo").is_absolute() == is_posix );
|
||||
VERIFY( path("/foo/").is_absolute() == is_posix );
|
||||
VERIFY( path("/foo/bar").is_absolute() == is_posix );
|
||||
VERIFY( path("/foo/bar/").is_absolute() == is_posix );
|
||||
VERIFY( ! path("foo").is_absolute() );
|
||||
VERIFY( ! path("foo/").is_absolute() );
|
||||
VERIFY( ! path("foo/bar").is_absolute() );
|
||||
|
@ -43,16 +49,11 @@ test01()
|
|||
VERIFY( ! path("c:foo/").is_absolute() );
|
||||
VERIFY( ! path("c:foo/bar").is_absolute() );
|
||||
VERIFY( ! path("c:foo/bar/").is_absolute() );
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
const bool drive_letter_is_root_name = true;
|
||||
#else
|
||||
const bool drive_letter_is_root_name = false;
|
||||
#endif
|
||||
VERIFY( path("c:/").is_absolute() == drive_letter_is_root_name );
|
||||
VERIFY( path("c:/foo").is_absolute() == drive_letter_is_root_name );
|
||||
VERIFY( path("c:/foo/").is_absolute() == drive_letter_is_root_name );
|
||||
VERIFY( path("c:/foo/bar").is_absolute() == drive_letter_is_root_name );
|
||||
VERIFY( path("c:/foo/bar/").is_absolute() == drive_letter_is_root_name );
|
||||
VERIFY( path("c:/").is_absolute() == !is_posix );
|
||||
VERIFY( path("c:/foo").is_absolute() == !is_posix );
|
||||
VERIFY( path("c:/foo/").is_absolute() == !is_posix );
|
||||
VERIFY( path("c:/foo/bar").is_absolute() == !is_posix );
|
||||
VERIFY( path("c:/foo/bar/").is_absolute() == !is_posix );
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -73,6 +73,16 @@ namespace __gnu_test
|
|||
"a", "a/b", "a/b/", "a/b/c", "a/b/c.d", "a/b/..", "a/b/c.", "a/b/.c"
|
||||
};
|
||||
|
||||
test_fs::path
|
||||
root_path()
|
||||
{
|
||||
#if defined(__MING32__) || defined(__MINGW64__)
|
||||
return L"c:/";
|
||||
#else
|
||||
return "/";
|
||||
#endif
|
||||
}
|
||||
|
||||
// This is NOT supposed to be a secure way to get a unique name!
|
||||
// We just need a path that doesn't exist for testing purposes.
|
||||
test_fs::path
|
||||
|
@ -111,7 +121,7 @@ namespace __gnu_test
|
|||
|
||||
explicit
|
||||
scoped_file(const path_type& p = nonexistent_path()) : path(p)
|
||||
{ std::ofstream{p.native()}; }
|
||||
{ std::ofstream{p.c_str()}; }
|
||||
|
||||
scoped_file(path_type p, adopt_file_t) : path(p) { }
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue