PR libstdc++/78870 support std::filesystem on Windows
authorJonathan Wakely <jwakely@redhat.com>
Thu, 31 May 2018 19:20:24 +0000 (20:20 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 31 May 2018 19:20:24 +0000 (20:20 +0100)
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

49 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/config.h.in
libstdc++-v3/configure
libstdc++-v3/configure.ac
libstdc++-v3/include/bits/fs_path.h
libstdc++-v3/include/experimental/bits/fs_path.h
libstdc++-v3/src/filesystem/dir-common.h
libstdc++-v3/src/filesystem/dir.cc
libstdc++-v3/src/filesystem/ops-common.h
libstdc++-v3/src/filesystem/ops.cc
libstdc++-v3/src/filesystem/path.cc
libstdc++-v3/src/filesystem/std-dir.cc
libstdc++-v3/src/filesystem/std-ops.cc
libstdc++-v3/src/filesystem/std-path.cc
libstdc++-v3/testsuite/27_io/filesystem/iterators/directory_iterator.cc
libstdc++-v3/testsuite/27_io/filesystem/iterators/recursive_directory_iterator.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/absolute.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/canonical.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/copy.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/copy_file.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/exists.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/is_empty.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/last_write_time.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/space.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/temp_directory_path.cc
libstdc++-v3/testsuite/27_io/filesystem/path/append/path.cc
libstdc++-v3/testsuite/27_io/filesystem/path/construct/format.cc
libstdc++-v3/testsuite/27_io/filesystem/path/construct/locale.cc
libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc
libstdc++-v3/testsuite/27_io/filesystem/path/decompose/stem.cc
libstdc++-v3/testsuite/27_io/filesystem/path/itr/traversal.cc
libstdc++-v3/testsuite/27_io/filesystem/path/native/string.cc
libstdc++-v3/testsuite/27_io/filesystem/path/query/is_absolute.cc
libstdc++-v3/testsuite/experimental/filesystem/iterators/directory_iterator.cc
libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc
libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc
libstdc++-v3/testsuite/experimental/filesystem/operations/copy_file.cc
libstdc++-v3/testsuite/experimental/filesystem/operations/exists.cc
libstdc++-v3/testsuite/experimental/filesystem/operations/is_empty.cc
libstdc++-v3/testsuite/experimental/filesystem/operations/last_write_time.cc
libstdc++-v3/testsuite/experimental/filesystem/operations/space.cc
libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc
libstdc++-v3/testsuite/experimental/filesystem/path/append/path.cc
libstdc++-v3/testsuite/experimental/filesystem/path/concat/path.cc
libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_directory.cc
libstdc++-v3/testsuite/experimental/filesystem/path/decompose/stem.cc
libstdc++-v3/testsuite/experimental/filesystem/path/native/string.cc
libstdc++-v3/testsuite/experimental/filesystem/path/query/is_absolute.cc
libstdc++-v3/testsuite/util/testsuite_fs.h

index 8735cacf94105e418f23dc9eb1859001f5eb02be..88e7c6dce515eba1caf32404bc8841beb33aef16 100644 (file)
@@ -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
index 751857800b84a7299704d51acec1674218db9f0d..3fb685ce9aa4f0f97d90eae11b9090d2a8ed7fb6 100644 (file)
 /* 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
 
 /* 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
 
 /* 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
index 79eb18727eaf757a8379d54455f199b8d825a0e4..b9883d413f624e9442461fccee68168b6643b40a 100755 (executable)
@@ -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
 
 
index 7e1fd84606a6ee25c195408379a97acf9fa728c2..dde1c4da9447674ec64448794cbefa5effd427de 100644 (file)
@@ -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
 
index 2dbde74e0d4c22448d055a40078fdbbfa0d7c853..6eab800ac5697cfcbcda556bf80f202da7cfefc9 100644 (file)
 #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,40 +520,55 @@ _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>
+  template<typename _InputIterator>
     inline auto
-    u8path(const _Source& __source)
-    -> decltype(filesystem::path(__source, std::locale::classic()))
+    u8path(_InputIterator __first, _InputIterator __last)
+    -> decltype(filesystem::path(__first, __last, std::locale::classic()))
     {
 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
-      const std::string __u8str{__source};
-      return std::filesystem::u8path(__u8str.begin(), __u8str.end());
+      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
+       {
+         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{ __source };
+      return path{ __first, __last };
 #endif
     }
 
-  template<typename _InputIterator>
+  template<typename _Source>
     inline auto
-    u8path(_InputIterator __first, _InputIterator __last)
-    -> decltype(filesystem::path(__first, __last, std::locale::classic()))
+    u8path(const _Source& __source)
+    -> decltype(filesystem::path(__source, 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 };
+      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
-       return {};
+       {
+         std::string __s = path::_S_string_from_iter(__source);
+         return filesystem::u8path(__s.data(), __s.data() + __s.size());
+       }
 #else
-      return path{ __first, __last };
+      return path{ __source };
 #endif
     }
 
@@ -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++()
   {
index 3ce2cd95b733bb417e229e34cf22baf6ea4b2cc8..653b4a3fe857363653240ed8fa202805422ee82b 100644 (file)
@@ -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
   {
index 21ba01ca9708d3bd5a90e003abcf70f9d65a4656..03875819d04fb205e0057a366439cadfc9cefd09 100644 (file)
@@ -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>
 # 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)
index 7e712c553c39d8e6818dd165687ce8d57466b298..01c3decaba61652cda9fb341d2cfcc679acce74c 100644 (file)
@@ -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 });
index bc186836bd45c5d538cc7016a3b378e13936a654..c1b817189a9591457091ae135b99b017a9ad26bb 100644 (file)
 #  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;
index 4a9e265d1d641baefbf614356e3338846f322ae1..40cadbf627014a9a42adfb1dbdec7bd263496394 100644 (file)
 #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(), &times))
+  if (posix::utime(p.c_str(), &times))
     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;
 }
 
index 899d94e0067cd6e2488a56581a7d41708d8a5235..fb70d30fdca28a50f6707aa335aa32232f0619f8 100644 (file)
@@ -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
index 98eb22ab92009b929f47da434ca7e792487007ec..4c9a287ad806d5319b2f623378acc385748b071a 100644 (file)
@@ -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();
index 00e4f987fc3a7c659671fa650dd3c43a3476725a..e266fa6d3f8701a68219053da4827cd53f58cf8d 100644 (file)
@@ -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>
 #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(), &times))
+  if (posix::utime(p.c_str(), &times))
     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,31 +1414,67 @@ fs::space(const path& p)
   return s;
 }
 
-fs::space_info
-fs::space(const path& p, error_code& ec) noexcept
+#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)
 {
-  space_info info = {
-    static_cast<uintmax_t>(-1),
-    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))
+  if (::statvfs(pathname, &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
-      };
+      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
+{
+  space_info info = {
+    static_cast<uintmax_t>(-1),
+    static_cast<uintmax_t>(-1),
+    static_cast<uintmax_t>(-1)
+  };
+#if _GLIBCXX_FILESYSTEM_IS_WINDOWS
+  path dir = absolute(p);
+  dir.remove_filename();
+  auto str = dir.c_str();
+#else
+  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";
+  p = tmpdir ? tmpdir : "/tmp";
+#endif
   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;
 }
 
 fs::path
index 755cb7c883aa22ee6f135e4596490af8e185b409..f6c0b8bb0f63da037105cd5eab89521ac4b2681b 100644 (file)
@@ -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
index 428a799013f8624264588ec16128b93cbb2b3fe2..b2445f72b5c75c36be7c90c98a59117de7ca228c 100644 (file)
@@ -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" );
index c391cd91113dc3785523d53fa9cf27eef5a8f228..8a5b8c3a0e241de8fcdb6a21cc4bdbf477b1622e 100644 (file)
@@ -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" );
index 413a86758f083eada786a9462bb53b333bcc681c..596ddd33f9d311c34748e211ce8dd366c2c9e0c0 100644 (file)
@@ -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
index 89cec15e7dfa2552cab315ce28dd1f019ba2d311..f7b6649adfe30d9f39580b96c6afb11961337828 100644 (file)
@@ -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 );
 
index 5fd2407e9e1787ac95e91dc8ba01875686e7d007..f9962ad350b264bace70340256f85b67b43ad643 100644 (file)
@@ -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) );
index 819dc08b734836d5558e78a5480dcfe454e42593..495e8d6ad040f0466477e1e914e4a2e1f113e152 100644 (file)
@@ -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) );
index d73ff35a539fc070b67b3a81fa2b9dd0d443a363..f8a4a280537ccf8a0e0c153c6a17d060c66dc88e 100644 (file)
@@ -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) );
index d57529b65f22dac1f631bc7c52a11227686c3381..ef0e01de4a2f607cfa407d737518c7c1bd6285e5 100644 (file)
@@ -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 );
index 1fdf39c7e0d0d0f6f8035e8ab8d93e744b6fbf2d..ff19afc12a0ac0d048f83f18ceee8e23c103ceb6 100644 (file)
@@ -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(), &times) );
+  VERIFY( !::utime(p.string().c_str(), &times) );
 #else
   return;
 #endif
index 3d64342fb8f3a5a3eb10b3e1c3ebcfe65f179019..79e3c7d9b73fd70151d50b53a4af08f8fcdc36b8 100644 (file)
 #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 );
 }
 
index f1fe32c8e5ee7544a9758208a5b4e83660b158c9..f9197ac70da24945784a2d26813e548ca3612080 100644 (file)
 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) );
index 0330bcf6c88ccb40e50ff2bc151dd996613a34c3..2295e1b0e2f8bd4cbae5afba35af069ded630bba 100644 (file)
@@ -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
index a793451aadac06fa68c77d7b23df636443913763..bd36e2842b6734e3b8f6a3d52e20ef5fed20595b 100644 (file)
@@ -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 );
index c32c647e16792f212ff9250db75dab2be6b32b13..dd696dea57ada6755bfd10659f284244fc2f4718 100644 (file)
@@ -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
index 8e6db4f67e2749feb1e67665e1a70ade79d2ddea..da5f377de9409897ce877312801d4f956f073ceb 100644 (file)
@@ -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
   }
 }
 
index 756085c932efcc388f4872bb946228efd53b1460..29eab0ad56c06a4a2b0feda376798c59cc971803 100644 (file)
@@ -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" );
index c23cb14fd735410a51291f1127b7dc73a6f363d5..4852c03c78eb0c79be1e10f7a46c8cc8cda844c2 100644 (file)
@@ -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 );
 }
index dc4c8b8454890e7d7ff49393d5acbcf1e91d40eb..6ae49bb606089deff645dc64185614429db72deb 100644 (file)
@@ -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() );
 }
 
index 6b5c098489a626e4017302c2842cb691b62978c4..16fb1910feb7875990f53cad1cb61de264d30695 100644 (file)
@@ -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
index 6199620c4dbe2959918eb71006b51503dc07ec9d..fe3d981d295b592bc6124fede1ee6069bfdfc2b3 100644 (file)
@@ -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" );
index 753e54d33ef1e0efc588465a4896cea5517b8efb..e493c5be009c1db6aedfcb21df75b3207584fb01 100644 (file)
@@ -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
index 6568a6d9c7679fed741e908ed503a97ad40b556c..1daf908438b11261136ef9a9ac39a723a573e40c 100644 (file)
@@ -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 );
index d529d0654bc619482a33b0701a740a85209faf52..cf4cd4b02a85f60060fd6e6f15dbd8349ab6a42a 100644 (file)
@@ -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) );
index c4b6ebf06627bc114aaea90d0908b0832e09ce48..c21a87124d07c49eaf66766533511a60d5ba3c23 100644 (file)
@@ -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 );
index 14b2bcea071517ab886d98eacb2187dac5dfc82d..17a174f6af68a5103336e89de561ec86fca80438 100644 (file)
@@ -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 );
index 9d1752fd4fcc6f91dd6046f329681882fc8b3527..d0be9028b04efef08a298c759cab861b1bfe5c6b 100644 (file)
@@ -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(), &times) );
+  VERIFY( !::utime(p.string().c_str(), &times) );
 #else
   return;
 #endif
index aa6a6aeaa602a2ab7836cda6ddd399f71fbd59a3..2ccf5014c3ac6dd797a2bb498a28f6e5cb78b638 100644 (file)
@@ -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);
index 7e60b3fa442ef6611039dd7eb05f3721c34b3ea9..1e98049d0436c5a959a61f723f9ccfeef9c8f710 100644 (file)
 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) );
index 52c83cf92d349e62cc204a6dc6eea7b28852ca81..5e8b330e18d6387eaf91754abd4cf1fe74231a56 100644 (file)
@@ -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
index 31bdcb9f1dc8e657afa91f9ac971e7e5f59b07d1..8f11254b7e24723692fc4a57843f01af0da7799e 100644 (file)
@@ -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 );
 }
 
index 535610f4e8f3d45edc27e1e7ae2ee13cb624a503..fc38be6adf1fa08c0ad27c47cafae3a3c4879bae 100644 (file)
@@ -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] != '/' );
   }
 }
 
index 088c4ec4b35e70b9a5691af38d96b7498ffa6e0c..0f67e02a11203b0a238f5c39e78389f42705ed73 100644 (file)
@@ -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" );
index bd353ae5e1988e3d93fef332a0ce2b3381f7faaf..8e40cdb0e1ef4645e2e80f6891925b1a51178d7c 100644 (file)
@@ -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() );
 }
 
index 1b99eaceef4308945e206ea39fec07cd271b94d9..974dec4381d55e8bb268614a27410c1c16344b10 100644 (file)
@@ -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
index 5a9cdac2f837dd6ed560a1f37d7380299fe01f16..eccb8929d7d55c0edc9620daa24e9e9cf68788e2 100644 (file)
@@ -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) { }