PR libstdc++/86756 Move rest of std::filesystem to libstdc++.so
authorJonathan Wakely <jwakely@redhat.com>
Sun, 6 Jan 2019 22:34:37 +0000 (22:34 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Sun, 6 Jan 2019 22:34:37 +0000 (22:34 +0000)
Move std::filesystem directory iterators and operations from
libstdc++fs.a to main libstdc++ library. These components have many
dependencies on OS support, which is not available on all targets. Some
additional autoconf checks and conditional compilation is needed to
ensure the files will build for all targets. Previously this code was
not compiled without --enable-libstdcxx-filesystem-ts but the C++17
components should be available for all hosted builds.

The tests for these components no longer need to link to libstdc++fs.a,
but are not expected to pass on all targets. To avoid numerous failures
on targets which are not expected to pass the tests (due to missing OS
functionality) leave the dg-require-filesystem-ts directives in place
for now. This will ensure the tests only run for builds where the
filesystem-ts library is built, which presumably means some level of OS
support is present.

PR libstdc++/86756
* acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for utime and
lstat and define _GLIBCXX_USE_UTIME and _GLIBCXX_USE_LSTAT.
* config.h.in: Regenerate.
* config/abi/pre/gnu.ver (GLIBCXX_3.4.26): Export symbols for
remaining std::filesystem types and functions.
* configure: Regenerate.
* src/c++17/Makefile.am: Add C++17 filesystem sources.
* src/c++17/Makefile.in: Regenerate.
* src/c++17/cow-fs_dir.cc: Move src/filesystem/cow-std-dir.cc to
here, and change name of included file.
* src/c++17/cow-fs_ops.cc: Move src/filesystem/cow-std-ops.cc to
here, and change name of included file.
* src/c++17/fs_dir.cc: Move src/filesystem/std-dir.cc to here. Change
path to dir-common.h.
* src/c++17/fs_ops.cc: Move src/filesystem/std-ops.cc to here. Change
path to ops-common.h. Disable -Wunused-parameter warnings.
(internal_file_clock): Define unconditionally.
[!_GLIBCXX_HAVE_SYS_STAT_H] (internal_file_clock::from_stat): Do not
define.
(do_copy_file, do_space): Move definitions to ops.common.h.
(copy, file_size, hard_link_count, last_write_time, space): Only
perform operation when _GLIBCXX_HAVE_SYS_STAT_H is defined, otherwise
report an error.
(last_write_time, read_symlink): Remove unused attributes from
parameters.
* src/filesystem/Makefile.am: Remove C++17 filesystem sources.
* src/filesystem/Makefile.in: Regenerate.
* src/filesystem/cow-std-dir.cc: Move to src/c++17/cow-fs_dir.cc.
* src/filesystem/cow-std-ops.cc: Move to src/c++17/cow-fs_ops.cc.
* src/filesystem/std-dir.cc: Move to src/c++17/fs_dir.cc.
* src/filesystem/std-ops.cc: Move to src/c++17/fs_ops.cc.
* src/filesystem/dir-common.h [!_GLIBCXX_HAVE_DIRENT_H]: Define
dummy types and functions instead of using #error.
* src/filesystem/dir.cc [!_GLIBCXX_HAVE_DIRENT_H]: Use #error.
* src/filesystem/ops-common.h [!_GLIBCXX_USE_LSTAT] (lstat): Define
in terms of stat.
[!_GLIBCXX_HAVE_UNISTD_H]: Define dummy types and functions.
(do_copy_file, do_space): Move definitions here from std-ops.cc.
* src/filesystem/ops.cc: Adjust calls to do_copy_file and do_space
to account for new namespace.
* testsuite/27_io/filesystem/directory_entry/86597.cc: Remove
-lstdc++fs from dg-options.
* testsuite/27_io/filesystem/directory_entry/lwg3171.cc: Likewise.
* testsuite/27_io/filesystem/file_status/1.cc: Likewise.
* testsuite/27_io/filesystem/filesystem_error/cons.cc: Likewise.
* testsuite/27_io/filesystem/filesystem_error/copy.cc: Likewise.
* testsuite/27_io/filesystem/iterators/directory_iterator.cc:
Likewise.
* testsuite/27_io/filesystem/iterators/pop.cc: Likewise.
* testsuite/27_io/filesystem/iterators/recursive_directory_iterator.cc:
Likewise.
* testsuite/27_io/filesystem/operations/absolute.cc: Likewise.
* testsuite/27_io/filesystem/operations/canonical.cc: Likewise.
* testsuite/27_io/filesystem/operations/copy.cc: Likewise.
* testsuite/27_io/filesystem/operations/copy_file.cc: Likewise.
* testsuite/27_io/filesystem/operations/create_directories.cc:
Likewise.
* testsuite/27_io/filesystem/operations/create_directory.cc: Likewise.
* testsuite/27_io/filesystem/operations/create_symlink.cc: Likewise.
* testsuite/27_io/filesystem/operations/current_path.cc: Likewise.
* testsuite/27_io/filesystem/operations/equivalent.cc: Likewise.
* testsuite/27_io/filesystem/operations/exists.cc: Likewise.
* testsuite/27_io/filesystem/operations/file_size.cc: Likewise.
* testsuite/27_io/filesystem/operations/is_empty.cc: Likewise.
* testsuite/27_io/filesystem/operations/last_write_time.cc: Likewise.
* testsuite/27_io/filesystem/operations/permissions.cc: Likewise.
* testsuite/27_io/filesystem/operations/proximate.cc: Likewise.
* testsuite/27_io/filesystem/operations/read_symlink.cc: Likewise.
* testsuite/27_io/filesystem/operations/relative.cc: Likewise.
* testsuite/27_io/filesystem/operations/remove.cc: Likewise.
* testsuite/27_io/filesystem/operations/remove_all.cc: Likewise.
* testsuite/27_io/filesystem/operations/space.cc: Likewise.
* testsuite/27_io/filesystem/operations/status.cc: Likewise.
* testsuite/27_io/filesystem/operations/symlink_status.cc: Likewise.
* testsuite/27_io/filesystem/operations/temp_directory_path.cc:
Likewise.
* testsuite/27_io/filesystem/operations/weakly_canonical.cc: Likewise.

From-SVN: r267616

53 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/acinclude.m4
libstdc++-v3/config.h.in
libstdc++-v3/config/abi/pre/gnu.ver
libstdc++-v3/configure
libstdc++-v3/src/c++17/Makefile.am
libstdc++-v3/src/c++17/Makefile.in
libstdc++-v3/src/c++17/cow-fs_dir.cc [new file with mode: 0644]
libstdc++-v3/src/c++17/cow-fs_ops.cc [new file with mode: 0644]
libstdc++-v3/src/c++17/fs_dir.cc [new file with mode: 0644]
libstdc++-v3/src/c++17/fs_ops.cc [new file with mode: 0644]
libstdc++-v3/src/filesystem/Makefile.am
libstdc++-v3/src/filesystem/Makefile.in
libstdc++-v3/src/filesystem/cow-std-dir.cc [deleted file]
libstdc++-v3/src/filesystem/cow-std-ops.cc [deleted file]
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/std-dir.cc [deleted file]
libstdc++-v3/src/filesystem/std-ops.cc [deleted file]
libstdc++-v3/testsuite/27_io/filesystem/directory_entry/86597.cc
libstdc++-v3/testsuite/27_io/filesystem/directory_entry/lwg3171.cc
libstdc++-v3/testsuite/27_io/filesystem/file_status/1.cc
libstdc++-v3/testsuite/27_io/filesystem/filesystem_error/cons.cc
libstdc++-v3/testsuite/27_io/filesystem/filesystem_error/copy.cc
libstdc++-v3/testsuite/27_io/filesystem/iterators/directory_iterator.cc
libstdc++-v3/testsuite/27_io/filesystem/iterators/pop.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/create_directories.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/create_directory.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/create_symlink.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/current_path.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/equivalent.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/exists.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/file_size.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/permissions.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/proximate.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/read_symlink.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/relative.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/remove.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/remove_all.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/space.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/status.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/symlink_status.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/temp_directory_path.cc
libstdc++-v3/testsuite/27_io/filesystem/operations/weakly_canonical.cc

index dd8939773401579f0ccf7200c42d00414aa13153..7d21d89ba9575b67129874c212dd5b00ae914c10 100644 (file)
@@ -1,5 +1,85 @@
 2019-01-06  Jonathan Wakely  <jwakely@redhat.com>
 
+       PR libstdc++/86756
+       * acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for utime and
+       lstat and define _GLIBCXX_USE_UTIME and _GLIBCXX_USE_LSTAT.
+       * config.h.in: Regenerate.
+       * config/abi/pre/gnu.ver (GLIBCXX_3.4.26): Export symbols for
+       remaining std::filesystem types and functions.
+       * configure: Regenerate.
+       * src/c++17/Makefile.am: Add C++17 filesystem sources.
+       * src/c++17/Makefile.in: Regenerate.
+       * src/c++17/cow-fs_dir.cc: Move src/filesystem/cow-std-dir.cc to
+       here, and change name of included file.
+       * src/c++17/cow-fs_ops.cc: Move src/filesystem/cow-std-ops.cc to
+       here, and change name of included file.
+       * src/c++17/fs_dir.cc: Move src/filesystem/std-dir.cc to here. Change
+       path to dir-common.h.
+       * src/c++17/fs_ops.cc: Move src/filesystem/std-ops.cc to here. Change
+       path to ops-common.h. Disable -Wunused-parameter warnings.
+       (internal_file_clock): Define unconditionally.
+       [!_GLIBCXX_HAVE_SYS_STAT_H] (internal_file_clock::from_stat): Do not
+       define.
+       (do_copy_file, do_space): Move definitions to ops.common.h.
+       (copy, file_size, hard_link_count, last_write_time, space): Only
+       perform operation when _GLIBCXX_HAVE_SYS_STAT_H is defined, otherwise
+       report an error.
+       (last_write_time, read_symlink): Remove unused attributes from
+       parameters.
+       * src/filesystem/Makefile.am: Remove C++17 filesystem sources.
+       * src/filesystem/Makefile.in: Regenerate.
+       * src/filesystem/cow-std-dir.cc: Move to src/c++17/cow-fs_dir.cc.
+       * src/filesystem/cow-std-ops.cc: Move to src/c++17/cow-fs_ops.cc.
+       * src/filesystem/std-dir.cc: Move to src/c++17/fs_dir.cc.
+       * src/filesystem/std-ops.cc: Move to src/c++17/fs_ops.cc.
+       * src/filesystem/dir-common.h [!_GLIBCXX_HAVE_DIRENT_H]: Define
+       dummy types and functions instead of using #error.
+       * src/filesystem/dir.cc [!_GLIBCXX_HAVE_DIRENT_H]: Use #error.
+       * src/filesystem/ops-common.h [!_GLIBCXX_USE_LSTAT] (lstat): Define
+       in terms of stat.
+       [!_GLIBCXX_HAVE_UNISTD_H]: Define dummy types and functions.
+       (do_copy_file, do_space): Move definitions here from std-ops.cc.
+       * src/filesystem/ops.cc: Adjust calls to do_copy_file and do_space
+       to account for new namespace.
+       * testsuite/27_io/filesystem/directory_entry/86597.cc: Remove
+       -lstdc++fs from dg-options.
+       * testsuite/27_io/filesystem/directory_entry/lwg3171.cc: Likewise.
+       * testsuite/27_io/filesystem/file_status/1.cc: Likewise.
+       * testsuite/27_io/filesystem/filesystem_error/cons.cc: Likewise.
+       * testsuite/27_io/filesystem/filesystem_error/copy.cc: Likewise.
+       * testsuite/27_io/filesystem/iterators/directory_iterator.cc:
+       Likewise.
+       * testsuite/27_io/filesystem/iterators/pop.cc: Likewise.
+       * testsuite/27_io/filesystem/iterators/recursive_directory_iterator.cc:
+       Likewise.
+       * testsuite/27_io/filesystem/operations/absolute.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/canonical.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/copy.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/copy_file.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/create_directories.cc:
+       Likewise.
+       * testsuite/27_io/filesystem/operations/create_directory.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/create_symlink.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/current_path.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/equivalent.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/exists.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/file_size.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/is_empty.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/last_write_time.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/permissions.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/proximate.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/read_symlink.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/relative.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/remove.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/remove_all.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/space.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/status.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/symlink_status.cc: Likewise.
+       * testsuite/27_io/filesystem/operations/temp_directory_path.cc:
+       Likewise.
+       * testsuite/27_io/filesystem/operations/weakly_canonical.cc: Likewise.
+
+
        PR libstdc++/86756
        * config/abi/pre/gnu.ver (GLIBCXX_3.4): Make various patterns for
        typeinfo and vtables less greedy.
index 6bcd29dc8c3f71b2df9da7e166c85bb571d0f9a5..ce91e495fabf40ccae5ca5d8acfb8cc854c4e046 100644 (file)
@@ -4451,6 +4451,40 @@ dnl
       AC_DEFINE(_GLIBCXX_USE_UTIMENSAT, 1, [Define if utimensat and UTIME_OMIT are available in <sys/stat.h> and AT_FDCWD in <fcntl.h>.])
     fi
     AC_MSG_RESULT($glibcxx_cv_utimensat)
+dnl
+    AC_MSG_CHECKING([for utime])
+    AC_CACHE_VAL(glibcxx_cv_utime, [dnl
+      GCC_TRY_COMPILE_OR_LINK(
+        [
+          #include <utime.h>
+        ],
+        [
+          struct utimbuf t = { 1, 1 };
+          int i = utime("path", &t);
+        ],
+        [glibcxx_cv_utime=yes],
+        [glibcxx_cv_utime=no])
+    ])
+    if test $glibcxx_cv_utime = yes; then
+      AC_DEFINE(_GLIBCXX_USE_UTIME, 1, [Define if utime is available in <utime.h>.])
+    fi
+    AC_MSG_RESULT($glibcxx_cv_utime)
+dnl
+    AC_MSG_CHECKING([for lstat])
+    AC_CACHE_VAL(glibcxx_cv_lstat, [dnl
+      GCC_TRY_COMPILE_OR_LINK(
+        [ #include <sys/stat.h> ],
+        [
+          struct stat st;
+          int i = lstat("path", &st);
+        ],
+        [glibcxx_cv_lstat=yes],
+        [glibcxx_cv_lstat=no])
+    ])
+    if test $glibcxx_cv_lstat = yes; then
+      AC_DEFINE(_GLIBCXX_USE_LSTAT, 1, [Define if lstat is available in <sys/stat.h>.])
+    fi
+    AC_MSG_RESULT($glibcxx_cv_lstat)
 dnl
     AC_MSG_CHECKING([for struct stat.st_mtim.tv_nsec])
     AC_CACHE_VAL(glibcxx_cv_st_mtim, [dnl
index 9c45c8c66284235ca92230498331aeb9375af3dc..97b5eed0a9a812a1420aa1e4062c15ca4434c973 100644 (file)
 /* Define if code specialized for long long should be used. */
 #undef _GLIBCXX_USE_LONG_LONG
 
+/* Define if lstat is available in <sys/stat.h>. */
+#undef _GLIBCXX_USE_LSTAT
+
 /* Defined if nanosleep is available. */
 #undef _GLIBCXX_USE_NANOSLEEP
 
 /* Define if obsolescent tmpnam is available in <stdio.h>. */
 #undef _GLIBCXX_USE_TMPNAM
 
+/* Define if utime is available in <utime.h>. */
+#undef _GLIBCXX_USE_UTIME
+
 /* Define if utimensat and UTIME_OMIT are available in <sys/stat.h> and
    AT_FDCWD in <fcntl.h>. */
 #undef _GLIBCXX_USE_UTIMENSAT
index f83d2b1cca9448f393028717436f49fdf80e241c..20325bf7a33ff994cdffcc5d110e2a71b3a3da69 100644 (file)
@@ -2167,6 +2167,58 @@ GLIBCXX_3.4.26 {
     _ZNSt10filesystem7__cxx114pathpLERKS1_;
     _ZT[IV]NSt10filesystem7__cxx1116filesystem_errorE;
 
+    _ZNSt10filesystem10equivalent*;
+    _ZNSt10filesystem10remove_all*;
+    _ZNSt10filesystem11permissions*;
+    _ZNSt10filesystem12current_path*;
+    _ZNSt10filesystem12read_symlink*;
+    _ZNSt10filesystem14create_symlink*;
+    _ZNSt10filesystem14symlink_status*;
+    _ZNSt10filesystem15last_write_time*;
+    _ZNSt10filesystem16create_directory*;
+    _ZNSt10filesystem16create_hard_link*;
+    _ZNSt10filesystem16weakly_canonical*;
+    _ZNSt10filesystem18create_directories*;
+    _ZNSt10filesystem19temp_directory_path*;
+    _ZNSt10filesystem24create_directory_symlink*;
+    _ZNSt10filesystem4copy*;
+    _ZNSt10filesystem5space*;
+    _ZNSt10filesystem6remove*;
+    _ZNSt10filesystem6status*;
+    _ZNSt10filesystem8absolute*;
+    _ZNSt10filesystem8is_empty*;
+    _ZNSt10filesystem8relative*;
+    _ZNSt10filesystem9canonical*;
+    _ZNSt10filesystem9copy_file*;
+    _ZNSt10filesystem9file_size*;
+    _ZNSt10filesystem9proximate*;
+
+    _ZNKSt10filesystem18directory_iteratordeEv;
+    _ZNKSt10filesystem28recursive_directory_iterator5depthEv;
+    _ZNKSt10filesystem28recursive_directory_iteratordeEv;
+    _ZNSt10filesystem18directory_iteratorC[12]ERKNS_4pathENS_17directory_optionsEPSt10error_code;
+    _ZNSt10filesystem18directory_iteratorppEv;
+    _ZNSt10filesystem28recursive_directory_iterator3popERSt10error_code;
+    _ZNSt10filesystem28recursive_directory_iterator3popEv;
+    _ZNSt10filesystem28recursive_directory_iterator9incrementERSt10error_code;
+    _ZNSt10filesystem28recursive_directory_iteratorC[12]ERKNS_4pathENS_17directory_optionsEPSt10error_code;
+    _ZNSt10filesystem28recursive_directory_iteratorD[12]Ev;
+    _ZNSt10filesystem28recursive_directory_iteratoraSEOS0_;
+    _ZNSt10filesystem28recursive_directory_iteratorppEv;
+
+    _ZNKSt10filesystem7__cxx1118directory_iteratordeEv;
+    _ZNKSt10filesystem7__cxx1128recursive_directory_iterator5depthEv;
+    _ZNKSt10filesystem7__cxx1128recursive_directory_iteratordeEv;
+    _ZNSt10filesystem7__cxx1118directory_iteratorC[12]ERKNS0_4pathENS_17directory_optionsEPSt10error_code;
+    _ZNSt10filesystem7__cxx1118directory_iteratorppEv;
+    _ZNSt10filesystem7__cxx1128recursive_directory_iterator3popERSt10error_code;
+    _ZNSt10filesystem7__cxx1128recursive_directory_iterator3popEv;
+    _ZNSt10filesystem7__cxx1128recursive_directory_iterator9incrementERSt10error_code;
+    _ZNSt10filesystem7__cxx1128recursive_directory_iteratorC[12]ERKNS0_4pathENS_17directory_optionsEPSt10error_code;
+    _ZNSt10filesystem7__cxx1128recursive_directory_iteratorD[12]Ev;
+    _ZNSt10filesystem7__cxx1128recursive_directory_iteratoraSEOS1_;
+    _ZNSt10filesystem7__cxx1128recursive_directory_iteratorppEv;
+
 } GLIBCXX_3.4.25;
 
 # Symbols in the support library (libsupc++) have their own tag.
index 77805e8680fe97417d91f4e89f6908a37b6db4b2..e01d900ad0b704314f0a3462315a270b8346684c 100755 (executable)
@@ -80499,6 +80499,134 @@ $as_echo "#define _GLIBCXX_USE_UTIMENSAT 1" >>confdefs.h
     fi
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_utimensat" >&5
 $as_echo "$glibcxx_cv_utimensat" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for utime" >&5
+$as_echo_n "checking for utime... " >&6; }
+    if ${glibcxx_cv_utime+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+        if test x$gcc_no_link = xyes; then
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <utime.h>
+
+int
+main ()
+{
+
+          struct utimbuf t = { 1, 1 };
+          int i = utime("path", &t);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  glibcxx_cv_utime=yes
+else
+  glibcxx_cv_utime=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  if test x$gcc_no_link = xyes; then
+  as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
+fi
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <utime.h>
+
+int
+main ()
+{
+
+          struct utimbuf t = { 1, 1 };
+          int i = utime("path", &t);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  glibcxx_cv_utime=yes
+else
+  glibcxx_cv_utime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+
+fi
+
+    if test $glibcxx_cv_utime = yes; then
+
+$as_echo "#define _GLIBCXX_USE_UTIME 1" >>confdefs.h
+
+    fi
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_utime" >&5
+$as_echo "$glibcxx_cv_utime" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lstat" >&5
+$as_echo_n "checking for lstat... " >&6; }
+    if ${glibcxx_cv_lstat+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+        if test x$gcc_no_link = xyes; then
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/stat.h>
+int
+main ()
+{
+
+          struct stat st;
+          int i = lstat("path", &st);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  glibcxx_cv_lstat=yes
+else
+  glibcxx_cv_lstat=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  if test x$gcc_no_link = xyes; then
+  as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
+fi
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/stat.h>
+int
+main ()
+{
+
+          struct stat st;
+          int i = lstat("path", &st);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  glibcxx_cv_lstat=yes
+else
+  glibcxx_cv_lstat=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+
+fi
+
+    if test $glibcxx_cv_lstat = yes; then
+
+$as_echo "#define _GLIBCXX_USE_LSTAT 1" >>confdefs.h
+
+    fi
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_lstat" >&5
+$as_echo "$glibcxx_cv_lstat" >&6; }
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat.st_mtim.tv_nsec" >&5
 $as_echo_n "checking for struct stat.st_mtim.tv_nsec... " >&6; }
     if ${glibcxx_cv_st_mtim+:} false; then :
index 85883c33f2d8b3d95e6d9a91ea23df458c843bf5..4200f7f8259a220d29c1e903dd2cb4affa1ae369 100644 (file)
@@ -29,7 +29,10 @@ headers =
 
 if ENABLE_DUAL_ABI
 extra_string_inst_sources = cow-string-inst.cc
-extra_fs_sources = cow-fs_path.cc
+extra_fs_sources = \
+       cow-fs_dir.cc \
+       cow-fs_ops.cc \
+       cow-fs_path.cc
 else
 extra_string_inst_sources =
 extra_fs_sources =
@@ -45,6 +48,8 @@ inst_sources =
 endif
 
 sources = \
+       fs_dir.cc \
+       fs_ops.cc \
        fs_path.cc \
        memory_resource.cc \
        string-inst.cc \
index d76580f08aae5347529cbe6bdf1972ecad2f1a1f..a402d13d5169deec6fea1c009bc37e75e177af08 100644 (file)
@@ -121,9 +121,10 @@ CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 libc__17convenience_la_LIBADD =
-@ENABLE_DUAL_ABI_TRUE@am__objects_1 = cow-fs_path.lo
-am__objects_2 = fs_path.lo memory_resource.lo string-inst.lo \
-       $(am__objects_1)
+@ENABLE_DUAL_ABI_TRUE@am__objects_1 = cow-fs_dir.lo cow-fs_ops.lo \
+@ENABLE_DUAL_ABI_TRUE@ cow-fs_path.lo
+am__objects_2 = fs_dir.lo fs_ops.lo fs_path.lo memory_resource.lo \
+       string-inst.lo $(am__objects_1)
 @ENABLE_DUAL_ABI_TRUE@am__objects_3 = cow-string-inst.lo
 @ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_4 = $(am__objects_3)
 am_libc__17convenience_la_OBJECTS = $(am__objects_2) $(am__objects_4)
@@ -415,7 +416,11 @@ headers =
 @ENABLE_DUAL_ABI_FALSE@extra_string_inst_sources = 
 @ENABLE_DUAL_ABI_TRUE@extra_string_inst_sources = cow-string-inst.cc
 @ENABLE_DUAL_ABI_FALSE@extra_fs_sources = 
-@ENABLE_DUAL_ABI_TRUE@extra_fs_sources = cow-fs_path.cc
+@ENABLE_DUAL_ABI_TRUE@extra_fs_sources = \
+@ENABLE_DUAL_ABI_TRUE@ cow-fs_dir.cc \
+@ENABLE_DUAL_ABI_TRUE@ cow-fs_ops.cc \
+@ENABLE_DUAL_ABI_TRUE@ cow-fs_path.cc
+
 # XTEMPLATE_FLAGS =
 @ENABLE_EXTERN_TEMPLATE_FALSE@inst_sources = 
 
@@ -424,6 +429,8 @@ headers =
 @ENABLE_EXTERN_TEMPLATE_TRUE@  $(extra_string_inst_sources)
 
 sources = \
+       fs_dir.cc \
+       fs_ops.cc \
        fs_path.cc \
        memory_resource.cc \
        string-inst.cc \
diff --git a/libstdc++-v3/src/c++17/cow-fs_dir.cc b/libstdc++-v3/src/c++17/cow-fs_dir.cc
new file mode 100644 (file)
index 0000000..126edab
--- /dev/null
@@ -0,0 +1,26 @@
+// Class filesystem::directory_entry etc. -*- C++ -*-
+
+// Copyright (C) 2015-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#define _GLIBCXX_USE_CXX11_ABI 0
+#include "fs_dir.cc"
diff --git a/libstdc++-v3/src/c++17/cow-fs_ops.cc b/libstdc++-v3/src/c++17/cow-fs_ops.cc
new file mode 100644 (file)
index 0000000..e519091
--- /dev/null
@@ -0,0 +1,26 @@
+// Filesystem operations -*- C++ -*-
+
+// Copyright (C) 2015-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#define _GLIBCXX_USE_CXX11_ABI 0
+#include "fs_ops.cc"
diff --git a/libstdc++-v3/src/c++17/fs_dir.cc b/libstdc++-v3/src/c++17/fs_dir.cc
new file mode 100644 (file)
index 0000000..8e6755e
--- /dev/null
@@ -0,0 +1,323 @@
+// Class filesystem::directory_entry etc. -*- C++ -*-
+
+// Copyright (C) 2014-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef _GLIBCXX_USE_CXX11_ABI
+# define _GLIBCXX_USE_CXX11_ABI 1
+#endif
+
+#include <filesystem>
+#include <utility>
+#include <stack>
+#include <string.h>
+#include <errno.h>
+#define _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM namespace filesystem {
+#define _GLIBCXX_END_NAMESPACE_FILESYSTEM }
+#include "../filesystem/dir-common.h"
+
+namespace fs = std::filesystem;
+namespace posix = std::filesystem::__gnu_posix;
+
+template class std::__shared_ptr<fs::_Dir>;
+template class std::__shared_ptr<fs::recursive_directory_iterator::_Dir_stack>;
+
+struct fs::_Dir : _Dir_base
+{
+  _Dir(const fs::path& p, bool skip_permission_denied, error_code& ec)
+  : _Dir_base(p.c_str(), skip_permission_denied, ec)
+  {
+    if (!ec)
+      path = p;
+  }
+
+  _Dir(posix::DIR* dirp, const path& p) : _Dir_base(dirp), path(p) { }
+
+  _Dir(_Dir&&) = default;
+
+  // Returns false when the end of the directory entries is reached.
+  // Reports errors by setting ec.
+  bool advance(bool skip_permission_denied, error_code& ec) noexcept
+  {
+    if (const auto entp = _Dir_base::advance(skip_permission_denied, ec))
+      {
+       auto name = path;
+       name /= entp->d_name;
+       entry = fs::directory_entry{std::move(name), get_file_type(*entp)};
+       return true;
+      }
+    else if (!ec)
+      {
+       // reached the end
+       entry = {};
+      }
+    return false;
+  }
+
+  bool advance(error_code& ec) noexcept { return advance(false, ec); }
+
+  // Returns false when the end of the directory entries is reached.
+  // Reports errors by throwing.
+  bool advance(bool skip_permission_denied = false)
+  {
+    error_code ec;
+    const bool ok = advance(skip_permission_denied, ec);
+    if (ec)
+      _GLIBCXX_THROW_OR_ABORT(filesystem_error(
+             "directory iterator cannot advance", ec));
+    return ok;
+  }
+
+  bool should_recurse(bool follow_symlink, error_code& ec) const
+  {
+    file_type type = entry._M_type;
+    if (type == file_type::none || type == file_type::unknown)
+    {
+      type = entry.symlink_status(ec).type();
+      if (ec)
+       return false;
+    }
+
+    if (type == file_type::directory)
+      return true;
+    if (type == file_type::symlink)
+      return follow_symlink && is_directory(entry.status(ec));
+    return false;
+  }
+
+  fs::path             path;
+  directory_entry      entry;
+};
+
+namespace
+{
+  template<typename Bitmask>
+    inline bool
+    is_set(Bitmask obj, Bitmask bits)
+    {
+      return (obj & bits) != Bitmask::none;
+    }
+}
+
+fs::directory_iterator::
+directory_iterator(const path& p, directory_options options, error_code* ecptr)
+{
+  const bool skip_permission_denied
+    = is_set(options, directory_options::skip_permission_denied);
+
+  error_code ec;
+  _Dir dir(p, skip_permission_denied, ec);
+
+  if (dir.dirp)
+    {
+      auto sp = std::__make_shared<fs::_Dir>(std::move(dir));
+      if (sp->advance(skip_permission_denied, ec))
+       _M_dir.swap(sp);
+    }
+  if (ecptr)
+    *ecptr = ec;
+  else if (ec)
+    _GLIBCXX_THROW_OR_ABORT(fs::filesystem_error(
+         "directory iterator cannot open directory", p, ec));
+}
+
+const fs::directory_entry&
+fs::directory_iterator::operator*() const
+{
+  if (!_M_dir)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error(
+         "non-dereferenceable directory iterator",
+         std::make_error_code(errc::invalid_argument)));
+  return _M_dir->entry;
+}
+
+fs::directory_iterator&
+fs::directory_iterator::operator++()
+{
+  if (!_M_dir)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error(
+         "cannot advance non-dereferenceable directory iterator",
+         std::make_error_code(errc::invalid_argument)));
+  if (!_M_dir->advance())
+    _M_dir.reset();
+  return *this;
+}
+
+fs::directory_iterator&
+fs::directory_iterator::increment(error_code& ec)
+{
+  if (!_M_dir)
+    {
+      ec = std::make_error_code(errc::invalid_argument);
+      return *this;
+    }
+  if (!_M_dir->advance(ec))
+    _M_dir.reset();
+  return *this;
+}
+
+struct fs::recursive_directory_iterator::_Dir_stack : std::stack<_Dir>
+{
+  void clear() { c.clear(); }
+};
+
+fs::recursive_directory_iterator::
+recursive_directory_iterator(const path& p, directory_options options,
+                             error_code* ecptr)
+: _M_options(options), _M_pending(true)
+{
+  if (posix::DIR* dirp = posix::opendir(p.c_str()))
+    {
+      if (ecptr)
+       ecptr->clear();
+      auto sp = std::__make_shared<_Dir_stack>();
+      sp->push(_Dir{ dirp, p });
+      if (ecptr ? sp->top().advance(*ecptr) : sp->top().advance())
+       _M_dirs.swap(sp);
+    }
+  else
+    {
+      const int err = errno;
+      if (err == EACCES
+         && is_set(options, fs::directory_options::skip_permission_denied))
+       {
+         if (ecptr)
+           ecptr->clear();
+         return;
+       }
+
+      if (!ecptr)
+       _GLIBCXX_THROW_OR_ABORT(filesystem_error(
+             "recursive directory iterator cannot open directory", p,
+             std::error_code(err, std::generic_category())));
+
+      ecptr->assign(err, std::generic_category());
+    }
+}
+
+fs::recursive_directory_iterator::~recursive_directory_iterator() = default;
+
+int
+fs::recursive_directory_iterator::depth() const
+{
+  return int(_M_dirs->size()) - 1;
+}
+
+const fs::directory_entry&
+fs::recursive_directory_iterator::operator*() const
+{
+  return _M_dirs->top().entry;
+}
+
+fs::recursive_directory_iterator&
+fs::recursive_directory_iterator::
+operator=(const recursive_directory_iterator& other) noexcept = default;
+
+fs::recursive_directory_iterator&
+fs::recursive_directory_iterator::
+operator=(recursive_directory_iterator&& other) noexcept = default;
+
+fs::recursive_directory_iterator&
+fs::recursive_directory_iterator::operator++()
+{
+  error_code ec;
+  increment(ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error(
+         "cannot increment recursive directory iterator", ec));
+  return *this;
+}
+
+fs::recursive_directory_iterator&
+fs::recursive_directory_iterator::increment(error_code& ec)
+{
+  if (!_M_dirs)
+    {
+      ec = std::make_error_code(errc::invalid_argument);
+      return *this;
+    }
+
+  const bool follow
+    = is_set(_M_options, directory_options::follow_directory_symlink);
+  const bool skip_permission_denied
+    = is_set(_M_options, directory_options::skip_permission_denied);
+
+  auto& top = _M_dirs->top();
+
+  if (std::exchange(_M_pending, true) && top.should_recurse(follow, ec))
+    {
+      _Dir dir(top.entry.path(), skip_permission_denied, ec);
+      if (ec)
+       {
+         _M_dirs.reset();
+         return *this;
+       }
+      if (dir.dirp)
+         _M_dirs->push(std::move(dir));
+    }
+
+  while (!_M_dirs->top().advance(skip_permission_denied, ec) && !ec)
+    {
+      _M_dirs->pop();
+      if (_M_dirs->empty())
+       {
+         _M_dirs.reset();
+         return *this;
+       }
+    }
+  return *this;
+}
+
+void
+fs::recursive_directory_iterator::pop(error_code& ec)
+{
+  if (!_M_dirs)
+    {
+      ec = std::make_error_code(errc::invalid_argument);
+      return;
+    }
+
+  const bool skip_permission_denied
+    = is_set(_M_options, directory_options::skip_permission_denied);
+
+  do {
+    _M_dirs->pop();
+    if (_M_dirs->empty())
+      {
+       _M_dirs.reset();
+       ec.clear();
+       return;
+      }
+  } while (!_M_dirs->top().advance(skip_permission_denied, ec));
+}
+
+void
+fs::recursive_directory_iterator::pop()
+{
+  error_code ec;
+  pop(ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error(_M_dirs
+         ? "recursive directory iterator cannot pop"
+         : "non-dereferenceable recursive directory iterator cannot pop",
+         ec));
+}
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
new file mode 100644 (file)
index 0000000..fd8cf35
--- /dev/null
@@ -0,0 +1,1501 @@
+// Filesystem operations -*- C++ -*-
+
+// Copyright (C) 2014-2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef _GLIBCXX_USE_CXX11_ABI
+# define _GLIBCXX_USE_CXX11_ABI 1
+# define NEED_DO_COPY_FILE
+# define NEED_DO_SPACE
+#endif
+
+#include <filesystem>
+#include <functional>
+#include <ostream>
+#include <stack>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>  // PATH_MAX
+#ifdef _GLIBCXX_HAVE_FCNTL_H
+# include <fcntl.h>  // AT_FDCWD, AT_SYMLINK_NOFOLLOW
+#endif
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+#  include <sys/stat.h>   // stat, utimensat, fchmodat
+#endif
+#ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
+# include <sys/statvfs.h> // statvfs
+#endif
+#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 "../filesystem/ops-common.h"
+
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+
+namespace fs = std::filesystem;
+namespace posix = std::filesystem::__gnu_posix;
+
+fs::path
+fs::absolute(const path& p)
+{
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+  error_code ec;
+  path ret = absolute(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot make absolute path", p,
+                                            ec));
+  return ret;
+#else
+  return current_path() / p;
+#endif
+}
+
+fs::path
+fs::absolute(const path& p, error_code& ec)
+{
+  path ret;
+  if (p.empty())
+    {
+      ec = make_error_code(std::errc::no_such_file_or_directory);
+      return ret;
+    }
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+  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();
+  ret /= p;
+#endif
+  return ret;
+}
+
+namespace
+{
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+  inline bool is_dot(wchar_t c) { return c == L'.'; }
+#else
+  inline bool is_dot(char c) { return c == '.'; }
+#endif
+
+  inline bool is_dot(const fs::path& path)
+  {
+    const auto& filename = path.native();
+    return filename.size() == 1 && is_dot(filename[0]);
+  }
+
+  inline bool is_dotdot(const fs::path& path)
+  {
+    const auto& filename = path.native();
+    return filename.size() == 2 && is_dot(filename[0]) && is_dot(filename[1]);
+  }
+
+  struct free_as_in_malloc
+  {
+    void operator()(void* p) const { ::free(p); }
+  };
+
+  using char_ptr = std::unique_ptr<fs::path::value_type[], free_as_in_malloc>;
+}
+
+fs::path
+fs::canonical(const path& p, error_code& ec)
+{
+  path result;
+  const path pa = absolute(p, ec);
+  if (ec)
+    return result;
+
+#ifdef _GLIBCXX_USE_REALPATH
+  char_ptr buf{ nullptr };
+# if _XOPEN_VERSION < 700
+  // Not safe to call realpath(path, NULL)
+  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()))
+    {
+      if (buf == nullptr)
+       buf.reset(rp);
+      result.assign(rp);
+      ec.clear();
+      return result;
+    }
+  if (errno != ENAMETOOLONG)
+    {
+      ec.assign(errno, std::generic_category());
+      return result;
+    }
+#endif
+
+  if (!exists(pa, ec))
+    {
+      if (!ec)
+       ec = make_error_code(std::errc::no_such_file_or_directory);
+      return result;
+    }
+  // else: we know there are (currently) no unresolvable symlink loops
+
+  result = pa.root_path();
+
+  deque<path> cmpts;
+  for (auto& f : pa.relative_path())
+    cmpts.push_back(f);
+
+  int max_allowed_symlinks = 40;
+
+  while (!cmpts.empty() && !ec)
+    {
+      path f = std::move(cmpts.front());
+      cmpts.pop_front();
+
+      if (f.empty())
+       {
+         // ignore empty element
+       }
+      else if (is_dot(f))
+       {
+         if (!is_directory(result, ec) && !ec)
+           ec.assign(ENOTDIR, std::generic_category());
+       }
+      else if (is_dotdot(f))
+       {
+         auto parent = result.parent_path();
+         if (parent.empty())
+           result = pa.root_path();
+         else
+           result.swap(parent);
+       }
+      else
+       {
+         result /= f;
+
+         if (is_symlink(result, ec))
+           {
+             path link = read_symlink(result, ec);
+             if (!ec)
+               {
+                 if (--max_allowed_symlinks == 0)
+                   ec.assign(ELOOP, std::generic_category());
+                 else
+                   {
+                     if (link.is_absolute())
+                       {
+                         result = link.root_path();
+                         link = link.relative_path();
+                       }
+                     else
+                       result = result.parent_path();
+
+                     cmpts.insert(cmpts.begin(), link.begin(), link.end());
+                   }
+               }
+           }
+       }
+    }
+
+  if (ec || !exists(result, ec))
+    result.clear();
+
+  return result;
+}
+
+fs::path
+fs::canonical(const path& p)
+{
+  error_code ec;
+  path res = canonical(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot make canonical path",
+                                            p, ec));
+  return res;
+}
+
+void
+fs::copy(const path& from, const path& to, copy_options options)
+{
+  error_code ec;
+  copy(from, to, options, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot copy", from, to, ec));
+}
+
+namespace std::filesystem
+{
+  // Need this as there's no 'perm_options::none' enumerator.
+  static inline bool is_set(fs::perm_options obj, fs::perm_options bits)
+  {
+    return (obj & bits) != fs::perm_options{};
+  }
+}
+
+namespace
+{
+  struct internal_file_clock : fs::__file_clock
+  {
+    using __file_clock::_S_to_sys;
+    using __file_clock::_S_from_sys;
+
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+    static fs::file_time_type
+    from_stat(const fs::stat_type& st, std::error_code& ec) noexcept
+    {
+      const auto sys_time = fs::file_time(st, ec);
+      if (sys_time == sys_time.min())
+       return fs::file_time_type::min();
+      return _S_from_sys(sys_time);
+    }
+#endif
+  };
+}
+
+void
+fs::copy(const path& from, const path& to, copy_options options,
+        error_code& ec)
+{
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+  const bool skip_symlinks = is_set(options, copy_options::skip_symlinks);
+  const bool create_symlinks = is_set(options, copy_options::create_symlinks);
+  const bool copy_symlinks = is_set(options, copy_options::copy_symlinks);
+  const bool use_lstat = create_symlinks || skip_symlinks;
+
+  file_status f, t;
+  stat_type from_st, to_st;
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2681. filesystem::copy() cannot copy symlinks
+  if (use_lstat || copy_symlinks
+      ? posix::lstat(from.c_str(), &from_st)
+      : posix::stat(from.c_str(), &from_st))
+    {
+      ec.assign(errno, std::generic_category());
+      return;
+    }
+  if (use_lstat
+      ? posix::lstat(to.c_str(), &to_st)
+      : posix::stat(to.c_str(), &to_st))
+    {
+      if (!is_not_found_errno(errno))
+       {
+         ec.assign(errno, std::generic_category());
+         return;
+       }
+      t = file_status{file_type::not_found};
+    }
+  else
+    t = make_file_status(to_st);
+  f = make_file_status(from_st);
+
+  if (exists(t) && !is_other(t) && !is_other(f)
+      && to_st.st_dev == from_st.st_dev && to_st.st_ino == from_st.st_ino)
+    {
+      ec = std::make_error_code(std::errc::file_exists);
+      return;
+    }
+  if (is_other(f) || is_other(t))
+    {
+      ec = std::make_error_code(std::errc::not_supported);
+      return;
+    }
+  if (is_directory(f) && is_regular_file(t))
+    {
+      ec = std::make_error_code(std::errc::is_a_directory);
+      return;
+    }
+
+  if (is_symlink(f))
+    {
+      if (skip_symlinks)
+       ec.clear();
+      else if (!exists(t) && copy_symlinks)
+       copy_symlink(from, to, ec);
+      else
+       // Not clear what should be done here.
+       // "Otherwise report an error as specified in Error reporting (7)."
+       ec = std::make_error_code(std::errc::invalid_argument);
+    }
+  else if (is_regular_file(f))
+    {
+      if (is_set(options, copy_options::directories_only))
+       ec.clear();
+      else if (create_symlinks)
+       create_symlink(from, to, ec);
+      else if (is_set(options, copy_options::create_hard_links))
+       create_hard_link(from, to, ec);
+      else if (is_directory(t))
+       do_copy_file(from.c_str(), (to / from.filename()).c_str(),
+                    copy_file_options(options), &from_st, nullptr, ec);
+      else
+       {
+         auto ptr = exists(t) ? &to_st : &from_st;
+         do_copy_file(from.c_str(), to.c_str(), copy_file_options(options),
+                      &from_st, ptr, ec);
+       }
+    }
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2682. filesystem::copy() won't create a symlink to a directory
+  else if (is_directory(f) && create_symlinks)
+    ec = std::make_error_code(errc::is_a_directory);
+  else if (is_directory(f) && (is_set(options, copy_options::recursive)
+                              || options == copy_options::none))
+    {
+      if (!exists(t))
+       if (!create_directory(to, from, ec))
+         return;
+      // set an unused bit in options to disable further recursion
+      if (!is_set(options, copy_options::recursive))
+       options |= static_cast<copy_options>(4096);
+      for (const directory_entry& x : directory_iterator(from))
+       copy(x.path(), to/x.path().filename(), options, ec);
+    }
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2683. filesystem::copy() says "no effects"
+  else
+    ec.clear();
+#else
+  ec = std::make_error_code(std::errc::not_supported);
+#endif
+}
+
+bool
+fs::copy_file(const path& from, const path& to, copy_options option)
+{
+  error_code ec;
+  bool result = copy_file(from, to, option, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot copy file", from, to,
+                                            ec));
+  return result;
+}
+
+bool
+fs::copy_file(const path& from, const path& to, copy_options options,
+             error_code& ec)
+{
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+  return do_copy_file(from.c_str(), to.c_str(), copy_file_options(options),
+                     nullptr, nullptr, ec);
+#else
+  ec = std::make_error_code(std::errc::not_supported);
+  return false;
+#endif
+}
+
+
+void
+fs::copy_symlink(const path& existing_symlink, const path& new_symlink)
+{
+  error_code ec;
+  copy_symlink(existing_symlink, new_symlink, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot copy symlink",
+         existing_symlink, new_symlink, ec));
+}
+
+void
+fs::copy_symlink(const path& existing_symlink, const path& new_symlink,
+                error_code& ec) noexcept
+{
+  auto p = read_symlink(existing_symlink, ec);
+  if (ec)
+    return;
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+  if (is_directory(p))
+    {
+      create_directory_symlink(p, new_symlink, ec);
+      return;
+    }
+#endif
+  create_symlink(p, new_symlink, ec);
+}
+
+
+bool
+fs::create_directories(const path& p)
+{
+  error_code ec;
+  bool result = create_directories(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directories", p,
+                                            ec));
+  return result;
+}
+
+bool
+fs::create_directories(const path& p, error_code& ec)
+{
+  if (p.empty())
+    {
+      ec = std::make_error_code(errc::invalid_argument);
+      return false;
+    }
+
+  file_status st = symlink_status(p, ec);
+  if (is_directory(st))
+    return false;
+  else if (ec && !status_known(st))
+    return false;
+  else if (exists(st))
+    {
+      if (!ec)
+       ec = std::make_error_code(std::errc::not_a_directory);
+      return false;
+    }
+
+  std::stack<path> missing;
+  path pp = p;
+
+  // Strip any trailing slash
+  if (pp.has_relative_path() && !pp.has_filename())
+    pp = pp.parent_path();
+
+  do
+    {
+      const auto& filename = pp.filename();
+      if (is_dot(filename) || is_dotdot(filename))
+       pp = pp.parent_path();
+      else
+       {
+         missing.push(std::move(pp));
+         if (missing.size() > 1000) // sanity check
+           {
+             ec = std::make_error_code(std::errc::filename_too_long);
+             return false;
+           }
+         pp = missing.top().parent_path();
+       }
+
+      if (pp.empty())
+       break;
+
+      st = status(pp, ec);
+      if (exists(st))
+       {
+         if (ec)
+           return false;
+         if (!is_directory(st))
+           {
+             ec = std::make_error_code(std::errc::not_a_directory);
+             return false;
+           }
+       }
+
+      if (ec && exists(st))
+       return false;
+    }
+  while (st.type() == file_type::not_found);
+
+  bool created;
+  do
+    {
+      const path& top = missing.top();
+      created = create_directory(top, ec);
+      if (ec)
+       return false;
+      missing.pop();
+    }
+  while (!missing.empty());
+
+  return created;
+}
+
+namespace
+{
+  bool
+  create_dir(const fs::path& p, fs::perms perm, std::error_code& ec)
+  {
+    bool created = false;
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+    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))
+         ec.assign(err, std::generic_category());
+      }
+    else
+      {
+       ec.clear();
+       created = true;
+      }
+#else
+    ec = std::make_error_code(std::errc::not_supported);
+#endif
+    return created;
+  }
+} // namespace
+
+bool
+fs::create_directory(const path& p)
+{
+  error_code ec;
+  bool result = create_directory(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directory", p,
+         ec));
+  return result;
+}
+
+bool
+fs::create_directory(const path& p, error_code& ec) noexcept
+{
+  return create_dir(p, perms::all, ec);
+}
+
+
+bool
+fs::create_directory(const path& p, const path& attributes)
+{
+  error_code ec;
+  bool result = create_directory(p, attributes, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directory", p,
+         ec));
+  return result;
+}
+
+bool
+fs::create_directory(const path& p, const path& attributes,
+                    error_code& ec) noexcept
+{
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+  stat_type st;
+  if (posix::stat(attributes.c_str(), &st))
+    {
+      ec.assign(errno, std::generic_category());
+      return false;
+    }
+  return create_dir(p, static_cast<perms>(st.st_mode), ec);
+#else
+  ec = std::make_error_code(std::errc::not_supported);
+  return false;
+#endif
+}
+
+
+void
+fs::create_directory_symlink(const path& to, const path& new_symlink)
+{
+  error_code ec;
+  create_directory_symlink(to, new_symlink, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directory symlink",
+         to, new_symlink, ec));
+}
+
+void
+fs::create_directory_symlink(const path& to, const path& new_symlink,
+                            error_code& ec) noexcept
+{
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+  ec = std::make_error_code(std::errc::not_supported);
+#else
+  create_symlink(to, new_symlink, ec);
+#endif
+}
+
+
+void
+fs::create_hard_link(const path& to, const path& new_hard_link)
+{
+  error_code ec;
+  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));
+}
+
+void
+fs::create_hard_link(const path& to, const path& new_hard_link,
+                    error_code& ec) noexcept
+{
+#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
+}
+
+void
+fs::create_symlink(const path& to, const path& new_symlink)
+{
+  error_code ec;
+  create_symlink(to, new_symlink, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create symlink",
+         to, new_symlink, ec));
+}
+
+void
+fs::create_symlink(const path& to, const path& new_symlink,
+                  error_code& ec) noexcept
+{
+#ifdef _GLIBCXX_HAVE_SYMLINK
+  if (::symlink(to.c_str(), new_symlink.c_str()))
+    ec.assign(errno, std::generic_category());
+  else
+    ec.clear();
+#else
+  ec = std::make_error_code(std::errc::not_supported);
+#endif
+}
+
+
+fs::path
+fs::current_path()
+{
+  error_code ec;
+  path p = current_path(ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get current path", ec));
+  return p;
+}
+
+fs::path
+fs::current_path(error_code& ec)
+{
+  path p;
+#ifdef _GLIBCXX_HAVE_UNISTD_H
+#if defined __GLIBC__ || defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
+  if (char_ptr cwd = char_ptr{posix::getcwd(nullptr, 0)})
+    {
+      p.assign(cwd.get());
+      ec.clear();
+    }
+  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)
+      size = 1024;
+  else if (path_max > 10240)
+      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)
+    {
+      using char_type = fs::path::value_type;
+      buf.reset((char_type*)malloc(size * sizeof(char_type)));
+      if (buf)
+       {
+         if (getcwd(buf.get(), size))
+           {
+             p.assign(buf.get());
+             ec.clear();
+           }
+         else if (errno != ERANGE)
+           {
+             ec.assign(errno, std::generic_category());
+             return {};
+           }
+       }
+      else
+       {
+         ec = std::make_error_code(std::errc::not_enough_memory);
+         return {};
+       }
+    }
+#endif  // __GLIBC__
+#else   // _GLIBCXX_HAVE_UNISTD_H
+  ec = std::make_error_code(std::errc::not_supported);
+#endif
+  return p;
+}
+
+void
+fs::current_path(const path& p)
+{
+  error_code ec;
+  current_path(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set current path", ec));
+}
+
+void
+fs::current_path(const path& p, error_code& ec) noexcept
+{
+#ifdef _GLIBCXX_HAVE_UNISTD_H
+  if (posix::chdir(p.c_str()))
+    ec.assign(errno, std::generic_category());
+  else
+    ec.clear();
+#else
+  ec = std::make_error_code(std::errc::not_supported);
+#endif
+}
+
+bool
+fs::equivalent(const path& p1, const path& p2)
+{
+  error_code ec;
+  auto result = equivalent(p1, p2, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot check file equivalence",
+         p1, p2, ec));
+  return result;
+}
+
+bool
+fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
+{
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+  int err = 0;
+  file_status s1, s2;
+  stat_type st1, st2;
+  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 (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);
+  else
+    err = errno;
+
+  if (exists(s1) && exists(s2))
+    {
+      if (is_other(s1) && is_other(s2))
+       {
+         ec = std::make_error_code(std::errc::not_supported);
+         return false;
+       }
+      ec.clear();
+      if (is_other(s1) || is_other(s2))
+       return false;
+      return st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino;
+    }
+  else if (!exists(s1) && !exists(s2))
+    ec = std::make_error_code(std::errc::no_such_file_or_directory);
+  else if (err)
+    ec.assign(err, std::generic_category());
+  else
+    ec.clear();
+  return false;
+#else
+  ec = std::make_error_code(std::errc::not_supported);
+#endif
+  return false;
+}
+
+std::uintmax_t
+fs::file_size(const path& p)
+{
+  error_code ec;
+  auto sz = file_size(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get file size", p, ec));
+  return sz;
+}
+
+namespace
+{
+  template<typename Accessor, typename T>
+    inline T
+    do_stat(const fs::path& p, std::error_code& ec, Accessor f, T deflt)
+    {
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+      posix::stat_type st;
+      if (posix::stat(p.c_str(), &st))
+       {
+         ec.assign(errno, std::generic_category());
+         return deflt;
+       }
+      ec.clear();
+      return f(st);
+#else
+      ec = std::make_error_code(std::errc::not_supported);
+      return deflt;
+#endif
+    }
+}
+
+std::uintmax_t
+fs::file_size(const path& p, error_code& ec) noexcept
+{
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+  struct S
+  {
+    S(const stat_type& st) : type(make_file_type(st)), size(st.st_size) { }
+    S() : type(file_type::not_found) { }
+    file_type type;
+    size_t size;
+  };
+  auto s = do_stat(p, ec, [](const auto& st) { return S{st}; }, S{});
+  if (s.type == file_type::regular)
+    return s.size;
+  if (!ec)
+    {
+      if (s.type == file_type::directory)
+       ec = std::make_error_code(std::errc::is_a_directory);
+      else
+       ec = std::make_error_code(std::errc::not_supported);
+    }
+#else
+  ec = std::make_error_code(std::errc::not_supported);
+#endif
+  return -1;
+}
+
+std::uintmax_t
+fs::hard_link_count(const path& p)
+{
+  error_code ec;
+  auto count = hard_link_count(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get link count", p, ec));
+  return count;
+}
+
+std::uintmax_t
+fs::hard_link_count(const path& p, error_code& ec) noexcept
+{
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+  return do_stat(p, ec, std::mem_fn(&stat_type::st_nlink),
+                static_cast<uintmax_t>(-1));
+#else
+  ec = std::make_error_code(std::errc::not_supported);
+  return static_cast<uintmax_t>(-1);
+#endif
+}
+
+bool
+fs::is_empty(const path& p)
+{
+  error_code ec;
+  bool e = is_empty(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot check if file is empty",
+                                            p, ec));
+  return e;
+}
+
+bool
+fs::is_empty(const path& p, error_code& ec)
+{
+  auto s = status(p, ec);
+  if (ec)
+    return false;
+  bool empty = fs::is_directory(s)
+    ? fs::directory_iterator(p, ec) == fs::directory_iterator()
+    : fs::file_size(p, ec) == 0;
+  return ec ? false : empty;
+}
+
+fs::file_time_type
+fs::last_write_time(const path& p)
+{
+  error_code ec;
+  auto t = last_write_time(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get file time", p, ec));
+  return t;
+}
+
+fs::file_time_type
+fs::last_write_time(const path& p, error_code& ec) noexcept
+{
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+  return do_stat(p, ec,
+                [&ec](const auto& st) {
+                    return internal_file_clock::from_stat(st, ec);
+                },
+                file_time_type::min());
+#else
+  ec = std::make_error_code(std::errc::not_supported);
+  return file_time_type::min();
+#endif
+}
+
+void
+fs::last_write_time(const path& p, file_time_type new_time)
+{
+  error_code ec;
+  last_write_time(p, new_time, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set file time", p, ec));
+}
+
+void
+fs::last_write_time(const path& p,
+                   file_time_type new_time, error_code& ec) noexcept
+{
+  auto d = internal_file_clock::_S_to_sys(new_time).time_since_epoch();
+  auto s = chrono::duration_cast<chrono::seconds>(d);
+#if _GLIBCXX_USE_UTIMENSAT
+  auto ns = chrono::duration_cast<chrono::nanoseconds>(d - s);
+  if (ns < ns.zero()) // tv_nsec must be non-negative and less than 10e9.
+    {
+      --s;
+      ns += chrono::seconds(1);
+    }
+  struct ::timespec ts[2];
+  ts[0].tv_sec = 0;
+  ts[0].tv_nsec = UTIME_OMIT;
+  ts[1].tv_sec = static_cast<std::time_t>(s.count());
+  ts[1].tv_nsec = static_cast<long>(ns.count());
+  if (::utimensat(AT_FDCWD, p.c_str(), ts, 0))
+    ec.assign(errno, std::generic_category());
+  else
+    ec.clear();
+#elif _GLIBCXX_USE_UTIME && _GLIBCXX_HAVE_SYS_STAT_H
+  posix::utimbuf times;
+  times.modtime = s.count();
+  times.actime = do_stat(p, ec, [](const auto& st) { return st.st_atime; },
+                        times.modtime);
+  if (posix::utime(p.c_str(), &times))
+    ec.assign(errno, std::generic_category());
+  else
+    ec.clear();
+#else
+  ec = std::make_error_code(std::errc::not_supported);
+#endif
+}
+
+void
+fs::permissions(const path& p, perms prms, perm_options opts)
+{
+  error_code ec;
+  permissions(p, prms, opts, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set permissions", p, ec));
+}
+
+void
+fs::permissions(const path& p, perms prms, perm_options opts,
+               error_code& ec) noexcept
+{
+  const bool replace = is_set(opts, perm_options::replace);
+  const bool add = is_set(opts, perm_options::add);
+  const bool remove = is_set(opts, perm_options::remove);
+  const bool nofollow = is_set(opts, perm_options::nofollow);
+  if (((int)replace + (int)add + (int)remove) != 1)
+    {
+      ec = std::make_error_code(std::errc::invalid_argument);
+      return;
+    }
+
+  prms &= perms::mask;
+
+  file_status st;
+  if (add || remove || nofollow)
+    {
+      st = nofollow ? symlink_status(p, ec) : status(p, ec);
+      if (ec)
+       return;
+      auto curr = st.permissions();
+      if (add)
+       prms |= curr;
+      else if (remove)
+       prms = curr & ~prms;
+    }
+
+  int err = 0;
+#if _GLIBCXX_USE_FCHMODAT
+  const int flag = (nofollow && is_symlink(st)) ? AT_SYMLINK_NOFOLLOW : 0;
+  if (::fchmodat(AT_FDCWD, p.c_str(), static_cast<mode_t>(prms), flag))
+    err = errno;
+#else
+  if (nofollow && is_symlink(st))
+    ec = std::make_error_code(std::errc::operation_not_supported);
+  else if (posix::chmod(p.c_str(), static_cast<mode_t>(prms)))
+    err = errno;
+#endif
+
+  if (err)
+    ec.assign(err, std::generic_category());
+  else
+    ec.clear();
+}
+
+fs::path
+fs::proximate(const path& p, const path& base)
+{
+  return weakly_canonical(p).lexically_proximate(weakly_canonical(base));
+}
+
+fs::path
+fs::proximate(const path& p, const path& base, error_code& ec)
+{
+  path result;
+  const auto p2 = weakly_canonical(p, ec);
+  if (!ec)
+    {
+      const auto base2 = weakly_canonical(base, ec);
+      if (!ec)
+       result = p2.lexically_proximate(base2);
+    }
+  return result;
+}
+
+fs::path
+fs::read_symlink(const path& p)
+{
+  error_code ec;
+  path tgt = read_symlink(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("read_symlink", p, ec));
+  return tgt;
+}
+
+fs::path fs::read_symlink(const path& p, error_code& ec)
+{
+  path result;
+#if defined(_GLIBCXX_HAVE_READLINK) && defined(_GLIBCXX_HAVE_SYS_STAT_H)
+  stat_type st;
+  if (::lstat(p.c_str(), &st))
+    {
+      ec.assign(errno, std::generic_category());
+      return result;
+    }
+  std::string buf(st.st_size ? st.st_size + 1 : 128, '\0');
+  do
+    {
+      ssize_t len = ::readlink(p.c_str(), buf.data(), buf.size());
+      if (len == -1)
+       {
+         ec.assign(errno, std::generic_category());
+         return result;
+       }
+      else if (len == (ssize_t)buf.size())
+       {
+         if (buf.size() > 4096)
+           {
+             ec.assign(ENAMETOOLONG, std::generic_category());
+             return result;
+           }
+         buf.resize(buf.size() * 2);
+       }
+      else
+       {
+         buf.resize(len);
+         result.assign(buf);
+         ec.clear();
+         break;
+       }
+    }
+  while (true);
+#else
+  ec = std::make_error_code(std::errc::not_supported);
+#endif
+  return result;
+}
+
+fs::path
+fs::relative(const path& p, const path& base)
+{
+  return weakly_canonical(p).lexically_relative(weakly_canonical(base));
+}
+
+fs::path
+fs::relative(const path& p, const path& base, error_code& ec)
+{
+  auto result = weakly_canonical(p, ec);
+  fs::path cbase;
+  if (!ec)
+    cbase = weakly_canonical(base, ec);
+  if (!ec)
+    result = result.lexically_relative(cbase);
+  if (ec)
+    result.clear();
+  return result;
+}
+
+bool
+fs::remove(const path& p)
+{
+  error_code ec;
+  const bool result = fs::remove(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove", p, ec));
+  return result;
+}
+
+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();
+      return true;
+    }
+  else if (errno == ENOENT)
+    ec.clear();
+  else
+    ec.assign(errno, std::generic_category());
+#endif
+  return false;
+}
+
+
+std::uintmax_t
+fs::remove_all(const path& p)
+{
+  error_code ec;
+  const auto result = remove_all(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
+  return result;
+}
+
+std::uintmax_t
+fs::remove_all(const path& p, error_code& ec)
+{
+  const auto s = symlink_status(p, ec);
+  if (!status_known(s))
+    return -1;
+
+  ec.clear();
+  if (s.type() == file_type::not_found)
+    return 0;
+
+  uintmax_t count = 0;
+  if (s.type() == file_type::directory)
+    {
+      for (directory_iterator d(p, ec), end; !ec && d != end; d.increment(ec))
+       count += fs::remove_all(d->path(), ec);
+      if (ec.value() == ENOENT)
+       ec.clear();
+      else if (ec)
+       return -1;
+    }
+
+  if (fs::remove(p, ec))
+    ++count;
+  return ec ? -1 : count;
+}
+
+void
+fs::rename(const path& from, const path& to)
+{
+  error_code ec;
+  rename(from, to, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot rename", from, to, ec));
+}
+
+void
+fs::rename(const path& from, const path& to, error_code& ec) noexcept
+{
+  if (posix::rename(from.c_str(), to.c_str()))
+    ec.assign(errno, std::generic_category());
+  else
+    ec.clear();
+}
+
+void
+fs::resize_file(const path& p, uintmax_t size)
+{
+  error_code ec;
+  resize_file(p, size, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot resize file", p, ec));
+}
+
+void
+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 (posix::truncate(p.c_str(), size))
+    ec.assign(errno, std::generic_category());
+  else
+    ec.clear();
+#else
+  ec = std::make_error_code(std::errc::not_supported);
+#endif
+}
+
+
+fs::space_info
+fs::space(const path& p)
+{
+  error_code ec;
+  space_info s = space(p, ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get free space", p, ec));
+  return s;
+}
+
+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)
+  };
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+#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);
+#endif // _GLIBCXX_HAVE_SYS_STAT_H
+
+  return info;
+}
+
+#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+fs::file_status
+fs::status(const fs::path& p, error_code& ec) noexcept
+{
+  file_status status;
+  stat_type st;
+  if (posix::stat(p.c_str(), &st))
+    {
+      int err = errno;
+      ec.assign(err, std::generic_category());
+      if (is_not_found_errno(err))
+       status.type(file_type::not_found);
+#ifdef EOVERFLOW
+      else if (err == EOVERFLOW)
+       status.type(file_type::unknown);
+#endif
+    }
+  else
+    {
+      status = make_file_status(st);
+      ec.clear();
+    }
+  return status;
+}
+
+fs::file_status
+fs::symlink_status(const fs::path& p, std::error_code& ec) noexcept
+{
+  file_status status;
+  stat_type st;
+  if (posix::lstat(p.c_str(), &st))
+    {
+      int err = errno;
+      ec.assign(err, std::generic_category());
+      if (is_not_found_errno(err))
+       status.type(file_type::not_found);
+    }
+  else
+    {
+      status = make_file_status(st);
+      ec.clear();
+    }
+  return status;
+}
+#endif
+
+fs::file_status
+fs::status(const fs::path& p)
+{
+  std::error_code ec;
+  auto result = status(p, ec);
+  if (result.type() == file_type::none)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("status", p, ec));
+  return result;
+}
+
+fs::file_status
+fs::symlink_status(const fs::path& p)
+{
+  std::error_code ec;
+  auto result = symlink_status(p, ec);
+  if (result.type() == file_type::none)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("symlink_status", p, ec));
+  return result;
+}
+
+fs::path fs::temp_directory_path()
+{
+  error_code ec;
+  path tmp = temp_directory_path(ec);
+  if (ec)
+    _GLIBCXX_THROW_OR_ABORT(filesystem_error("temp_directory_path", ec));
+  return tmp;
+}
+
+fs::path fs::temp_directory_path(error_code& ec)
+{
+  path p;
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+  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);
+  p = tmpdir ? tmpdir : "/tmp";
+#endif
+  auto st = status(p, ec);
+  if (ec)
+    p.clear();
+  else if (!is_directory(st))
+    {
+      p.clear();
+      ec = std::make_error_code(std::errc::not_a_directory);
+    }
+  return p;
+}
+
+fs::path
+fs::weakly_canonical(const path& p)
+{
+  path result;
+  if (exists(status(p)))
+    return canonical(p);
+
+  path tmp;
+  auto iter = p.begin(), end = p.end();
+  // find leading elements of p that exist:
+  while (iter != end)
+    {
+      tmp = result / *iter;
+      if (exists(status(tmp)))
+       swap(result, tmp);
+      else
+       break;
+      ++iter;
+    }
+  // canonicalize:
+  if (!result.empty())
+    result = canonical(result);
+  // append the non-existing elements:
+  while (iter != end)
+    result /= *iter++;
+  // normalize:
+  return result.lexically_normal();
+}
+
+fs::path
+fs::weakly_canonical(const path& p, error_code& ec)
+{
+  path result;
+  file_status st = status(p, ec);
+  if (exists(st))
+    return canonical(p, ec);
+  else if (status_known(st))
+    ec.clear();
+  else
+    return result;
+
+  path tmp;
+  auto iter = p.begin(), end = p.end();
+  // find leading elements of p that exist:
+  while (iter != end)
+    {
+      tmp = result / *iter;
+      st = status(tmp, ec);
+      if (exists(st))
+       swap(result, tmp);
+      else
+       {
+         if (status_known(st))
+           ec.clear();
+         break;
+       }
+      ++iter;
+    }
+  // canonicalize:
+  if (!ec && !result.empty())
+    result = canonical(result, ec);
+  if (ec)
+    result.clear();
+  else
+    {
+      // append the non-existing elements:
+      while (iter != end)
+       result /= *iter++;
+      // normalize:
+      result = result.lexically_normal();
+    }
+  return result;
+}
index 6f2a9f63b8aeb74834da5c09d5c8f2e10698f285..af9dcd25f8ea9a520db83baec595483f44e93c9a 100644 (file)
@@ -30,9 +30,7 @@ if ENABLE_DUAL_ABI
 cxx11_abi_sources = \
        cow-dir.cc \
        cow-ops.cc \
-       cow-path.cc \
-       cow-std-dir.cc \
-       cow-std-ops.cc
+       cow-path.cc
 else
 cxx11_abi_sources =
 endif
@@ -41,8 +39,6 @@ sources = \
        dir.cc \
        ops.cc \
        path.cc \
-       std-dir.cc \
-       std-ops.cc \
        ${cxx11_abi_sources}
 
 # vpath % $(top_srcdir)/src/filesystem
index 12524ff1cc694bd6b9fccf76ca0cf5c8d0996c6a..d3cb3683245f5da6b0f4cccd9be0873ca251a932 100644 (file)
@@ -150,10 +150,8 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)"
 LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
 libstdc__fs_la_LIBADD =
 @ENABLE_DUAL_ABI_TRUE@am__objects_1 = cow-dir.lo cow-ops.lo \
-@ENABLE_DUAL_ABI_TRUE@ cow-path.lo cow-std-dir.lo \
-@ENABLE_DUAL_ABI_TRUE@ cow-std-ops.lo
-am__objects_2 = dir.lo ops.lo path.lo std-dir.lo std-ops.lo \
-       $(am__objects_1)
+@ENABLE_DUAL_ABI_TRUE@ cow-path.lo
+am__objects_2 = dir.lo ops.lo path.lo $(am__objects_1)
 am_libstdc__fs_la_OBJECTS = $(am__objects_2)
 libstdc__fs_la_OBJECTS = $(am_libstdc__fs_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
@@ -442,16 +440,12 @@ headers =
 @ENABLE_DUAL_ABI_TRUE@cxx11_abi_sources = \
 @ENABLE_DUAL_ABI_TRUE@ cow-dir.cc \
 @ENABLE_DUAL_ABI_TRUE@ cow-ops.cc \
-@ENABLE_DUAL_ABI_TRUE@ cow-path.cc \
-@ENABLE_DUAL_ABI_TRUE@ cow-std-dir.cc \
-@ENABLE_DUAL_ABI_TRUE@ cow-std-ops.cc
+@ENABLE_DUAL_ABI_TRUE@ cow-path.cc
 
 sources = \
        dir.cc \
        ops.cc \
        path.cc \
-       std-dir.cc \
-       std-ops.cc \
        ${cxx11_abi_sources}
 
 
diff --git a/libstdc++-v3/src/filesystem/cow-std-dir.cc b/libstdc++-v3/src/filesystem/cow-std-dir.cc
deleted file mode 100644 (file)
index a48e99f..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Class filesystem::directory_entry etc. -*- C++ -*-
-
-// Copyright (C) 2015-2019 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library.  This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-// <http://www.gnu.org/licenses/>.
-
-#define _GLIBCXX_USE_CXX11_ABI 0
-#include "std-dir.cc"
diff --git a/libstdc++-v3/src/filesystem/cow-std-ops.cc b/libstdc++-v3/src/filesystem/cow-std-ops.cc
deleted file mode 100644 (file)
index 7e76208..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Filesystem operations -*- C++ -*-
-
-// Copyright (C) 2015-2019 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library.  This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-// <http://www.gnu.org/licenses/>.
-
-#define _GLIBCXX_USE_CXX11_ABI 0
-#include "std-ops.cc"
index bcfbfcd0beab241edf1f236b7b64ab0023af4eb5..6ec798c9aa0000c22d28d194e51185393b55ca99 100644 (file)
@@ -26,6 +26,7 @@
 #define _GLIBCXX_DIR_COMMON_H 1
 
 #include <string.h>  // strcmp
+#include <errno.h>
 #if _GLIBCXX_FILESYSTEM_IS_WINDOWS
 #include <wchar.h>  // wcscmp
 #endif
@@ -34,8 +35,6 @@
 #  include <sys/types.h>
 # endif
 # include <dirent.h>
-#else
-# error "the <dirent.h> header is needed to build the Filesystem TS"
 #endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
@@ -53,13 +52,20 @@ 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
+#elif defined _GLIBCXX_HAVE_DIRENT_H
 using char_type = char;
 using DIR = ::DIR;
 typedef struct ::dirent dirent;
 using ::opendir;
 using ::readdir;
 using ::closedir;
+#else
+using char_type = char;
+struct dirent { const char* d_name; };
+struct DIR { };
+inline DIR* opendir(const char*) { return nullptr; }
+inline dirent* readdir(DIR*) { return nullptr; }
+inline int closedir(DIR*) { return -1; }
 #endif
 } // namespace __gnu_posix
 
index 0738ea784f7ff7540aab3841d9b3c92a6a1af113..3e6e598fa6423b201dbf1e349752a1bfffe792b0 100644 (file)
 #endif
 
 #include <experimental/filesystem>
+
+#ifndef _GLIBCXX_HAVE_DIRENT_H
+# error "the <dirent.h> header is needed to build the Filesystem TS"
+#endif
+
 #include <utility>
 #include <stack>
 #include <string.h>
index 1c0d650f4440340bd1c06d634fa9f93b9c4045ce..f20867c217e441d2ea6365dd1e4bcef0a4428984 100644 (file)
 # include <wchar.h>
 #endif
 
+#ifdef NEED_DO_COPY_FILE
+# include <filesystem>
+# include <ext/stdio_filebuf.h>
+# ifdef _GLIBCXX_USE_SENDFILE
+#  include <sys/sendfile.h> // sendfile
+# endif
+#endif
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -108,26 +116,42 @@ namespace __gnu_posix
     return ret;
   }
   using char_type = wchar_t;
-#else // _GLIBCXX_FILESYSTEM_IS_WINDOWS
+#elif defined _GLIBCXX_HAVE_UNISTD_H
   using ::open;
   using ::close;
-#ifdef _GLIBCXX_HAVE_SYS_STAT_H
+# ifdef _GLIBCXX_HAVE_SYS_STAT_H
   typedef struct ::stat stat_type;
   using ::stat;
+#  ifdef _GLIBCXX_USE_LSTAT
   using ::lstat;
-#endif
+#  else
+  inline int lstat(const char* path, stat_type* buffer)
+  { return stat(path, buffer); }
+#  endif
+# endif
   using ::mode_t;
   using ::chmod;
   using ::mkdir;
   using ::getcwd;
   using ::chdir;
-#if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
+# if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_USE_UTIME
   using ::utimbuf;
   using ::utime;
-#endif
+# endif
   using ::rename;
   using ::truncate;
   using char_type = char;
+#else // ! _GLIBCXX_FILESYSTEM_IS_WINDOWS && ! _GLIBCXX_HAVE_UNISTD_H
+  inline int open(const char*, int, ...) { errno = ENOTSUP; return -1; }
+  inline int close(int) { errno = ENOTSUP; return -1; }
+  using mode_t = int;
+  inline int chmod(const char*, mode_t) { errno = ENOTSUP; return -1; }
+  inline int mkdir(const char*, mode_t) { errno = ENOTSUP; return -1; }
+  inline char* getcwd(char*, size_t) { errno = ENOTSUP; return nullptr; }
+  inline int chdir(const char*) { errno = ENOTSUP; return -1; }
+  inline int rename(const char*, const char*) { errno = ENOTSUP; return -1; }
+  inline int truncate(const char*, long) { errno = ENOTSUP; return -1; }
+  using char_type = char;
 #endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
 } // namespace __gnu_posix
 
@@ -190,18 +214,6 @@ namespace __gnu_posix
     bool skip, update, overwrite;
   };
 
-  bool
-  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
@@ -211,6 +223,19 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
 
 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
   using std::filesystem::__gnu_posix::stat_type;
+  using std::filesystem::__gnu_posix::char_type;
+
+  bool
+  do_copy_file(const char_type* from, const char_type* to,
+              std::filesystem::copy_options_existing_file options,
+              stat_type* from_st, stat_type* to_st,
+              std::error_code& ec) noexcept;
+
+  void
+  do_space(const char_type* pathname,
+          uintmax_t& capacity, uintmax_t& free, uintmax_t& available,
+          std::error_code&);
+
 
   inline file_type
   make_file_type(const stat_type& st) noexcept
@@ -257,6 +282,253 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
        is_set(opt, copy_options::overwrite_existing)
     };
   }
+
+#ifdef NEED_DO_COPY_FILE
+  bool
+  do_copy_file(const char_type* from, const char_type* to,
+              std::filesystem::copy_options_existing_file options,
+              stat_type* from_st, stat_type* to_st,
+              std::error_code& ec) noexcept
+  {
+    namespace fs = std::filesystem;
+    namespace posix = fs::__gnu_posix;
+
+    stat_type st1, st2;
+    file_status t, f;
+
+    if (to_st == nullptr)
+      {
+       if (posix::stat(to, &st1))
+         {
+           const int err = errno;
+           if (!fs::is_not_found_errno(err))
+             {
+               ec.assign(err, std::generic_category());
+               return false;
+             }
+         }
+       else
+         to_st = &st1;
+      }
+    else if (to_st == from_st)
+      to_st = nullptr;
+
+    if (to_st == nullptr)
+      t = file_status{file_type::not_found};
+    else
+      t = make_file_status(*to_st);
+
+    if (from_st == nullptr)
+      {
+       if (posix::stat(from, &st2))
+         {
+           ec.assign(errno, std::generic_category());
+           return false;
+         }
+       else
+         from_st = &st2;
+      }
+    f = make_file_status(*from_st);
+    // _GLIBCXX_RESOLVE_LIB_DEFECTS
+    // 2712. copy_file() has a number of unspecified error conditions
+    if (!is_regular_file(f))
+      {
+       ec = std::make_error_code(std::errc::not_supported);
+       return false;
+      }
+
+    if (exists(t))
+      {
+       if (!is_regular_file(t))
+         {
+           ec = std::make_error_code(std::errc::not_supported);
+           return false;
+         }
+
+       if (to_st->st_dev == from_st->st_dev
+           && to_st->st_ino == from_st->st_ino)
+         {
+           ec = std::make_error_code(std::errc::file_exists);
+           return false;
+         }
+
+       if (options.skip)
+         {
+           ec.clear();
+           return false;
+         }
+       else if (options.update)
+         {
+           const auto from_mtime = fs::file_time(*from_st, ec);
+           if (ec)
+             return false;
+           if ((from_mtime <= fs::file_time(*to_st, ec)) || ec)
+             return false;
+         }
+       else if (!options.overwrite)
+         {
+           ec = std::make_error_code(std::errc::file_exists);
+           return false;
+         }
+       else if (!is_regular_file(t))
+         {
+           ec = std::make_error_code(std::errc::not_supported);
+           return false;
+         }
+      }
+
+    struct CloseFD {
+      ~CloseFD() { if (fd != -1) posix::close(fd); }
+      bool close() { return posix::close(std::exchange(fd, -1)) == 0; }
+      int fd;
+    };
+
+    CloseFD in = { posix::open(from, O_RDONLY) };
+    if (in.fd == -1)
+      {
+       ec.assign(errno, std::generic_category());
+       return false;
+      }
+    int oflag = O_WRONLY|O_CREAT;
+    if (options.overwrite || options.update)
+      oflag |= O_TRUNC;
+    else
+      oflag |= O_EXCL;
+    CloseFD out = { posix::open(to, oflag, S_IWUSR) };
+    if (out.fd == -1)
+      {
+       if (errno == EEXIST && options.skip)
+         ec.clear();
+       else
+         ec.assign(errno, std::generic_category());
+       return false;
+      }
+
+#if defined _GLIBCXX_USE_FCHMOD && ! defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
+    if (::fchmod(out.fd, from_st->st_mode))
+#elif defined _GLIBCXX_USE_FCHMODAT && ! defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
+    if (::fchmodat(AT_FDCWD, to, from_st->st_mode, 0))
+#else
+    if (posix::chmod(to, from_st->st_mode))
+#endif
+      {
+       ec.assign(errno, std::generic_category());
+       return false;
+      }
+
+    size_t count = from_st->st_size;
+#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)
+      {
+       ec.assign(errno, std::generic_category());
+       return false;
+      }
+    if ((size_t)n == count)
+      {
+       if (!out.close() || !in.close())
+         {
+           ec.assign(errno, std::generic_category());
+           return false;
+         }
+       ec.clear();
+       return true;
+      }
+    else if (n > 0)
+      count -= n;
+#endif // _GLIBCXX_USE_SENDFILE
+
+    using std::ios;
+    __gnu_cxx::stdio_filebuf<char> sbin(in.fd, ios::in|ios::binary);
+    __gnu_cxx::stdio_filebuf<char> sbout(out.fd, ios::out|ios::binary);
+
+    if (sbin.is_open())
+      in.fd = -1;
+    if (sbout.is_open())
+      out.fd = -1;
+
+#ifdef _GLIBCXX_USE_SENDFILE
+    if (n != 0)
+      {
+       if (n < 0)
+         n = 0;
+
+       const auto p1 = sbin.pubseekoff(n, ios::beg, ios::in);
+       const auto p2 = sbout.pubseekoff(n, ios::beg, ios::out);
+
+       const std::streampos errpos(std::streamoff(-1));
+       if (p1 == errpos || p2 == errpos)
+         {
+           ec = std::make_error_code(std::errc::io_error);
+           return false;
+         }
+      }
+#endif
+
+    if (count && !(std::ostream(&sbout) << &sbin))
+      {
+       ec = std::make_error_code(std::errc::io_error);
+       return false;
+      }
+    if (!sbout.close() || !sbin.close())
+      {
+       ec.assign(errno, std::generic_category());
+       return false;
+      }
+    ec.clear();
+    return true;
+  }
+#endif // NEED_DO_COPY_FILE
+
+#ifdef NEED_DO_SPACE
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+  void
+  do_space(const char_type* pathname,
+          uintmax_t& capacity, uintmax_t& free, uintmax_t& available,
+          std::error_code& ec)
+  {
+#ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
+    struct ::statvfs f;
+    if (::statvfs(pathname, &f))
+       ec.assign(errno, std::generic_category());
+    else
+      {
+       if (f.f_frsize != (unsigned long)-1)
+         {
+           const uintmax_t fragment_size = f.f_frsize;
+           const fsblkcnt_t unknown = -1;
+           if (f.f_blocks != unknown)
+             capacity = f.f_blocks * fragment_size;
+           if (f.f_bfree != unknown)
+             free = f.f_bfree * fragment_size;
+           if (f.f_bavail != unknown)
+             available = f.f_bavail * fragment_size;
+         }
+       ec.clear();
+      }
+#elif _GLIBCXX_FILESYSTEM_IS_WINDOWS
+    ULARGE_INTEGER bytes_avail = {}, bytes_total = {}, bytes_free = {};
+    if (GetDiskFreeSpaceExW(pathname, &bytes_avail, &bytes_total, &bytes_free))
+      {
+       if (bytes_total.QuadPart != 0)
+         capacity = bytes_total.QuadPart;
+       if (bytes_free.QuadPart != 0)
+         free = bytes_free.QuadPart;
+       if (bytes_avail.QuadPart != 0)
+         available = bytes_avail.QuadPart;
+       ec.clear();
+      }
+    else
+      ec.assign((int)GetLastError(), std::system_category());
+#else
+    ec = std::make_error_code(std::errc::not_supported);
+#endif
+  }
+#pragma GCC diagnostic pop
+#endif // NEED_DO_SPACE
+
 #endif // _GLIBCXX_HAVE_SYS_STAT_H
 
 _GLIBCXX_END_NAMESPACE_FILESYSTEM
index 95bf23b5b5233aa8ae1d490b7e8ca751b4230833..369604da80f1ae1c89cb872227ac1785e63da4b0 100644 (file)
@@ -24,6 +24,8 @@
 
 #ifndef _GLIBCXX_USE_CXX11_ABI
 # define _GLIBCXX_USE_CXX11_ABI 1
+# define NEED_DO_COPY_FILE
+# define NEED_DO_SPACE
 #endif
 
 #include <experimental/filesystem>
@@ -243,7 +245,6 @@ namespace
 
   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
@@ -1175,7 +1176,7 @@ fs::space(const path& p, error_code& ec) noexcept
 #else
   auto str = p.c_str();
 #endif
-  std::filesystem::do_space(str, info.capacity, info.free, info.available, ec);
+  fs::do_space(str, info.capacity, info.free, info.available, ec);
   return info;
 }
 
diff --git a/libstdc++-v3/src/filesystem/std-dir.cc b/libstdc++-v3/src/filesystem/std-dir.cc
deleted file mode 100644 (file)
index a2936fc..0000000
+++ /dev/null
@@ -1,324 +0,0 @@
-// Class filesystem::directory_entry etc. -*- C++ -*-
-
-// Copyright (C) 2014-2019 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library.  This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef _GLIBCXX_USE_CXX11_ABI
-# define _GLIBCXX_USE_CXX11_ABI 1
-#endif
-
-#include <filesystem>
-#include <experimental/filesystem>
-#include <utility>
-#include <stack>
-#include <string.h>
-#include <errno.h>
-#define _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM namespace filesystem {
-#define _GLIBCXX_END_NAMESPACE_FILESYSTEM }
-#include "dir-common.h"
-
-namespace fs = std::filesystem;
-namespace posix = std::filesystem::__gnu_posix;
-
-template class std::__shared_ptr<fs::_Dir>;
-template class std::__shared_ptr<fs::recursive_directory_iterator::_Dir_stack>;
-
-struct fs::_Dir : _Dir_base
-{
-  _Dir(const fs::path& p, bool skip_permission_denied, error_code& ec)
-  : _Dir_base(p.c_str(), skip_permission_denied, ec)
-  {
-    if (!ec)
-      path = p;
-  }
-
-  _Dir(posix::DIR* dirp, const path& p) : _Dir_base(dirp), path(p) { }
-
-  _Dir(_Dir&&) = default;
-
-  // Returns false when the end of the directory entries is reached.
-  // Reports errors by setting ec.
-  bool advance(bool skip_permission_denied, error_code& ec) noexcept
-  {
-    if (const auto entp = _Dir_base::advance(skip_permission_denied, ec))
-      {
-       auto name = path;
-       name /= entp->d_name;
-       entry = fs::directory_entry{std::move(name), get_file_type(*entp)};
-       return true;
-      }
-    else if (!ec)
-      {
-       // reached the end
-       entry = {};
-      }
-    return false;
-  }
-
-  bool advance(error_code& ec) noexcept { return advance(false, ec); }
-
-  // Returns false when the end of the directory entries is reached.
-  // Reports errors by throwing.
-  bool advance(bool skip_permission_denied = false)
-  {
-    error_code ec;
-    const bool ok = advance(skip_permission_denied, ec);
-    if (ec)
-      _GLIBCXX_THROW_OR_ABORT(filesystem_error(
-             "directory iterator cannot advance", ec));
-    return ok;
-  }
-
-  bool should_recurse(bool follow_symlink, error_code& ec) const
-  {
-    file_type type = entry._M_type;
-    if (type == file_type::none || type == file_type::unknown)
-    {
-      type = entry.symlink_status(ec).type();
-      if (ec)
-       return false;
-    }
-
-    if (type == file_type::directory)
-      return true;
-    if (type == file_type::symlink)
-      return follow_symlink && is_directory(entry.status(ec));
-    return false;
-  }
-
-  fs::path             path;
-  directory_entry      entry;
-};
-
-namespace
-{
-  template<typename Bitmask>
-    inline bool
-    is_set(Bitmask obj, Bitmask bits)
-    {
-      return (obj & bits) != Bitmask::none;
-    }
-}
-
-fs::directory_iterator::
-directory_iterator(const path& p, directory_options options, error_code* ecptr)
-{
-  const bool skip_permission_denied
-    = is_set(options, directory_options::skip_permission_denied);
-
-  error_code ec;
-  _Dir dir(p, skip_permission_denied, ec);
-
-  if (dir.dirp)
-    {
-      auto sp = std::__make_shared<fs::_Dir>(std::move(dir));
-      if (sp->advance(skip_permission_denied, ec))
-       _M_dir.swap(sp);
-    }
-  if (ecptr)
-    *ecptr = ec;
-  else if (ec)
-    _GLIBCXX_THROW_OR_ABORT(fs::filesystem_error(
-         "directory iterator cannot open directory", p, ec));
-}
-
-const fs::directory_entry&
-fs::directory_iterator::operator*() const
-{
-  if (!_M_dir)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error(
-         "non-dereferenceable directory iterator",
-         std::make_error_code(errc::invalid_argument)));
-  return _M_dir->entry;
-}
-
-fs::directory_iterator&
-fs::directory_iterator::operator++()
-{
-  if (!_M_dir)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error(
-         "cannot advance non-dereferenceable directory iterator",
-         std::make_error_code(errc::invalid_argument)));
-  if (!_M_dir->advance())
-    _M_dir.reset();
-  return *this;
-}
-
-fs::directory_iterator&
-fs::directory_iterator::increment(error_code& ec)
-{
-  if (!_M_dir)
-    {
-      ec = std::make_error_code(errc::invalid_argument);
-      return *this;
-    }
-  if (!_M_dir->advance(ec))
-    _M_dir.reset();
-  return *this;
-}
-
-struct fs::recursive_directory_iterator::_Dir_stack : std::stack<_Dir>
-{
-  void clear() { c.clear(); }
-};
-
-fs::recursive_directory_iterator::
-recursive_directory_iterator(const path& p, directory_options options,
-                             error_code* ecptr)
-: _M_options(options), _M_pending(true)
-{
-  if (posix::DIR* dirp = posix::opendir(p.c_str()))
-    {
-      if (ecptr)
-       ecptr->clear();
-      auto sp = std::__make_shared<_Dir_stack>();
-      sp->push(_Dir{ dirp, p });
-      if (ecptr ? sp->top().advance(*ecptr) : sp->top().advance())
-       _M_dirs.swap(sp);
-    }
-  else
-    {
-      const int err = errno;
-      if (err == EACCES
-         && is_set(options, fs::directory_options::skip_permission_denied))
-       {
-         if (ecptr)
-           ecptr->clear();
-         return;
-       }
-
-      if (!ecptr)
-       _GLIBCXX_THROW_OR_ABORT(filesystem_error(
-             "recursive directory iterator cannot open directory", p,
-             std::error_code(err, std::generic_category())));
-
-      ecptr->assign(err, std::generic_category());
-    }
-}
-
-fs::recursive_directory_iterator::~recursive_directory_iterator() = default;
-
-int
-fs::recursive_directory_iterator::depth() const
-{
-  return int(_M_dirs->size()) - 1;
-}
-
-const fs::directory_entry&
-fs::recursive_directory_iterator::operator*() const
-{
-  return _M_dirs->top().entry;
-}
-
-fs::recursive_directory_iterator&
-fs::recursive_directory_iterator::
-operator=(const recursive_directory_iterator& other) noexcept = default;
-
-fs::recursive_directory_iterator&
-fs::recursive_directory_iterator::
-operator=(recursive_directory_iterator&& other) noexcept = default;
-
-fs::recursive_directory_iterator&
-fs::recursive_directory_iterator::operator++()
-{
-  error_code ec;
-  increment(ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error(
-         "cannot increment recursive directory iterator", ec));
-  return *this;
-}
-
-fs::recursive_directory_iterator&
-fs::recursive_directory_iterator::increment(error_code& ec)
-{
-  if (!_M_dirs)
-    {
-      ec = std::make_error_code(errc::invalid_argument);
-      return *this;
-    }
-
-  const bool follow
-    = is_set(_M_options, directory_options::follow_directory_symlink);
-  const bool skip_permission_denied
-    = is_set(_M_options, directory_options::skip_permission_denied);
-
-  auto& top = _M_dirs->top();
-
-  if (std::exchange(_M_pending, true) && top.should_recurse(follow, ec))
-    {
-      _Dir dir(top.entry.path(), skip_permission_denied, ec);
-      if (ec)
-       {
-         _M_dirs.reset();
-         return *this;
-       }
-      if (dir.dirp)
-         _M_dirs->push(std::move(dir));
-    }
-
-  while (!_M_dirs->top().advance(skip_permission_denied, ec) && !ec)
-    {
-      _M_dirs->pop();
-      if (_M_dirs->empty())
-       {
-         _M_dirs.reset();
-         return *this;
-       }
-    }
-  return *this;
-}
-
-void
-fs::recursive_directory_iterator::pop(error_code& ec)
-{
-  if (!_M_dirs)
-    {
-      ec = std::make_error_code(errc::invalid_argument);
-      return;
-    }
-
-  const bool skip_permission_denied
-    = is_set(_M_options, directory_options::skip_permission_denied);
-
-  do {
-    _M_dirs->pop();
-    if (_M_dirs->empty())
-      {
-       _M_dirs.reset();
-       ec.clear();
-       return;
-      }
-  } while (!_M_dirs->top().advance(skip_permission_denied, ec));
-}
-
-void
-fs::recursive_directory_iterator::pop()
-{
-  error_code ec;
-  pop(ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error(_M_dirs
-         ? "recursive directory iterator cannot pop"
-         : "non-dereferenceable recursive directory iterator cannot pop",
-         ec));
-}
diff --git a/libstdc++-v3/src/filesystem/std-ops.cc b/libstdc++-v3/src/filesystem/std-ops.cc
deleted file mode 100644 (file)
index 8c3ec1d..0000000
+++ /dev/null
@@ -1,1723 +0,0 @@
-// Filesystem operations -*- C++ -*-
-
-// Copyright (C) 2014-2019 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library.  This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef _GLIBCXX_USE_CXX11_ABI
-# define _GLIBCXX_USE_CXX11_ABI 1
-# define NEED_DO_COPY_FILE
-# define NEED_DO_SPACE
-#endif
-
-#include <filesystem>
-#include <experimental/filesystem>
-#include <functional>
-#include <ostream>
-#include <stack>
-#include <ext/stdio_filebuf.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <limits.h>  // PATH_MAX
-#ifdef _GLIBCXX_HAVE_FCNTL_H
-# include <fcntl.h>  // AT_FDCWD, AT_SYMLINK_NOFOLLOW
-#endif
-#ifdef _GLIBCXX_HAVE_SYS_STAT_H
-#  include <sys/stat.h>   // stat, utimensat, fchmodat
-#endif
-#ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
-# include <sys/statvfs.h> // statvfs
-#endif
-#ifdef _GLIBCXX_USE_SENDFILE
-# include <sys/sendfile.h> // sendfile
-#endif
-#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"
-
-namespace fs = std::filesystem;
-namespace posix = std::filesystem::__gnu_posix;
-
-fs::path
-fs::absolute(const path& p)
-{
-#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
-  error_code ec;
-  path ret = absolute(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot make absolute path", p,
-                                            ec));
-  return ret;
-#else
-  return current_path() / p;
-#endif
-}
-
-fs::path
-fs::absolute(const path& p, error_code& ec)
-{
-  path ret;
-  if (p.empty())
-    {
-      ec = make_error_code(std::errc::no_such_file_or_directory);
-      return ret;
-    }
-#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
-  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();
-  ret /= p;
-#endif
-  return ret;
-}
-
-namespace
-{
-#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
-  inline bool is_dot(wchar_t c) { return c == L'.'; }
-#else
-  inline bool is_dot(char c) { return c == '.'; }
-#endif
-
-  inline bool is_dot(const fs::path& path)
-  {
-    const auto& filename = path.native();
-    return filename.size() == 1 && is_dot(filename[0]);
-  }
-
-  inline bool is_dotdot(const fs::path& path)
-  {
-    const auto& filename = path.native();
-    return filename.size() == 2 && is_dot(filename[0]) && is_dot(filename[1]);
-  }
-
-  struct free_as_in_malloc
-  {
-    void operator()(void* p) const { ::free(p); }
-  };
-
-  using char_ptr = std::unique_ptr<fs::path::value_type[], free_as_in_malloc>;
-}
-
-fs::path
-fs::canonical(const path& p, error_code& ec)
-{
-  path result;
-  const path pa = absolute(p, ec);
-  if (ec)
-    return result;
-
-#ifdef _GLIBCXX_USE_REALPATH
-  char_ptr buf{ nullptr };
-# if _XOPEN_VERSION < 700
-  // Not safe to call realpath(path, NULL)
-  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()))
-    {
-      if (buf == nullptr)
-       buf.reset(rp);
-      result.assign(rp);
-      ec.clear();
-      return result;
-    }
-  if (errno != ENAMETOOLONG)
-    {
-      ec.assign(errno, std::generic_category());
-      return result;
-    }
-#endif
-
-  if (!exists(pa, ec))
-    {
-      if (!ec)
-       ec = make_error_code(std::errc::no_such_file_or_directory);
-      return result;
-    }
-  // else: we know there are (currently) no unresolvable symlink loops
-
-  result = pa.root_path();
-
-  deque<path> cmpts;
-  for (auto& f : pa.relative_path())
-    cmpts.push_back(f);
-
-  int max_allowed_symlinks = 40;
-
-  while (!cmpts.empty() && !ec)
-    {
-      path f = std::move(cmpts.front());
-      cmpts.pop_front();
-
-      if (f.empty())
-       {
-         // ignore empty element
-       }
-      else if (is_dot(f))
-       {
-         if (!is_directory(result, ec) && !ec)
-           ec.assign(ENOTDIR, std::generic_category());
-       }
-      else if (is_dotdot(f))
-       {
-         auto parent = result.parent_path();
-         if (parent.empty())
-           result = pa.root_path();
-         else
-           result.swap(parent);
-       }
-      else
-       {
-         result /= f;
-
-         if (is_symlink(result, ec))
-           {
-             path link = read_symlink(result, ec);
-             if (!ec)
-               {
-                 if (--max_allowed_symlinks == 0)
-                   ec.assign(ELOOP, std::generic_category());
-                 else
-                   {
-                     if (link.is_absolute())
-                       {
-                         result = link.root_path();
-                         link = link.relative_path();
-                       }
-                     else
-                       result = result.parent_path();
-
-                     cmpts.insert(cmpts.begin(), link.begin(), link.end());
-                   }
-               }
-           }
-       }
-    }
-
-  if (ec || !exists(result, ec))
-    result.clear();
-
-  return result;
-}
-
-fs::path
-fs::canonical(const path& p)
-{
-  error_code ec;
-  path res = canonical(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot make canonical path",
-                                            p, ec));
-  return res;
-}
-
-void
-fs::copy(const path& from, const path& to, copy_options options)
-{
-  error_code ec;
-  copy(from, to, options, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot copy", from, to, ec));
-}
-
-namespace std::filesystem
-{
-  // Need this as there's no 'perm_options::none' enumerator.
-  static inline bool is_set(fs::perm_options obj, fs::perm_options bits)
-  {
-    return (obj & bits) != fs::perm_options{};
-  }
-}
-
-#ifdef _GLIBCXX_HAVE_SYS_STAT_H
-
-namespace
-{
-  struct internal_file_clock : fs::__file_clock
-  {
-    using __file_clock::_S_to_sys;
-    using __file_clock::_S_from_sys;
-
-    static fs::file_time_type
-    from_stat(const fs::stat_type& st, std::error_code& ec) noexcept
-    {
-      const auto sys_time = fs::file_time(st, ec);
-      if (sys_time == sys_time.min())
-       return fs::file_time_type::min();
-      return _S_from_sys(sys_time);
-    }
-  };
-}
-
-#ifdef NEED_DO_COPY_FILE
-bool
-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
-{
-  stat_type st1, st2;
-  fs::file_status t, f;
-
-  if (to_st == nullptr)
-    {
-      if (posix::stat(to, &st1))
-       {
-         const int err = errno;
-         if (!is_not_found_errno(err))
-           {
-             ec.assign(err, std::generic_category());
-             return false;
-           }
-       }
-      else
-       to_st = &st1;
-    }
-  else if (to_st == from_st)
-    to_st = nullptr;
-
-  if (to_st == nullptr)
-    t = fs::file_status{fs::file_type::not_found};
-  else
-    t = make_file_status(*to_st);
-
-  if (from_st == nullptr)
-    {
-      if (posix::stat(from, &st2))
-       {
-         ec.assign(errno, std::generic_category());
-         return false;
-       }
-      else
-       from_st = &st2;
-    }
-  f = make_file_status(*from_st);
-  // _GLIBCXX_RESOLVE_LIB_DEFECTS
-  // 2712. copy_file() has a number of unspecified error conditions
-  if (!is_regular_file(f))
-    {
-      ec = std::make_error_code(std::errc::not_supported);
-      return false;
-    }
-
-  if (exists(t))
-    {
-      if (!is_regular_file(t))
-       {
-         ec = std::make_error_code(std::errc::not_supported);
-         return false;
-       }
-
-      if (to_st->st_dev == from_st->st_dev
-         && to_st->st_ino == from_st->st_ino)
-       {
-         ec = std::make_error_code(std::errc::file_exists);
-         return false;
-       }
-
-      if (options.skip)
-       {
-         ec.clear();
-         return false;
-       }
-      else if (options.update)
-       {
-         const auto from_mtime = internal_file_clock::from_stat(*from_st, ec);
-         if (ec)
-           return false;
-         if ((from_mtime <= internal_file_clock::from_stat(*to_st, ec)) || ec)
-           return false;
-       }
-      else if (!options.overwrite)
-       {
-         ec = std::make_error_code(std::errc::file_exists);
-         return false;
-       }
-      else if (!is_regular_file(t))
-       {
-         ec = std::make_error_code(std::errc::not_supported);
-         return false;
-       }
-    }
-
-  struct CloseFD {
-    ~CloseFD() { if (fd != -1) posix::close(fd); }
-    bool close() { return posix::close(std::exchange(fd, -1)) == 0; }
-    int fd;
-  };
-
-  CloseFD in = { posix::open(from, O_RDONLY) };
-  if (in.fd == -1)
-    {
-      ec.assign(errno, std::generic_category());
-      return false;
-    }
-  int oflag = O_WRONLY|O_CREAT;
-  if (options.overwrite || options.update)
-    oflag |= O_TRUNC;
-  else
-    oflag |= O_EXCL;
-  CloseFD out = { posix::open(to, oflag, S_IWUSR) };
-  if (out.fd == -1)
-    {
-      if (errno == EEXIST && options.skip)
-       ec.clear();
-      else
-       ec.assign(errno, std::generic_category());
-      return false;
-    }
-
-#if defined _GLIBCXX_USE_FCHMOD && ! defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
-  if (::fchmod(out.fd, from_st->st_mode))
-#elif defined _GLIBCXX_USE_FCHMODAT && ! defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
-  if (::fchmodat(AT_FDCWD, to, from_st->st_mode, 0))
-#else
-  if (posix::chmod(to, from_st->st_mode))
-#endif
-    {
-      ec.assign(errno, std::generic_category());
-      return false;
-    }
-
-  size_t count = from_st->st_size;
-#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)
-    {
-      ec.assign(errno, std::generic_category());
-      return false;
-    }
-  if ((size_t)n == count)
-    {
-      if (!out.close() || !in.close())
-       {
-         ec.assign(errno, std::generic_category());
-         return false;
-       }
-      ec.clear();
-      return true;
-    }
-  else if (n > 0)
-    count -= n;
-#endif // _GLIBCXX_USE_SENDFILE
-
-  using std::ios;
-  __gnu_cxx::stdio_filebuf<char> sbin(in.fd, ios::in|ios::binary);
-  __gnu_cxx::stdio_filebuf<char> sbout(out.fd, ios::out|ios::binary);
-
-  if (sbin.is_open())
-    in.fd = -1;
-  if (sbout.is_open())
-    out.fd = -1;
-
-#ifdef _GLIBCXX_USE_SENDFILE
-  if (n != 0)
-    {
-      if (n < 0)
-       n = 0;
-
-      const auto p1 = sbin.pubseekoff(n, ios::beg, ios::in);
-      const auto p2 = sbout.pubseekoff(n, ios::beg, ios::out);
-
-      const std::streampos errpos(std::streamoff(-1));
-      if (p1 == errpos || p2 == errpos)
-       {
-         ec = std::make_error_code(std::errc::io_error);
-         return false;
-       }
-    }
-#endif
-
-  if (count && !(std::ostream(&sbout) << &sbin))
-    {
-      ec = std::make_error_code(std::errc::io_error);
-      return false;
-    }
-  if (!sbout.close() || !sbin.close())
-    {
-      ec.assign(errno, std::generic_category());
-      return false;
-    }
-  ec.clear();
-  return true;
-}
-#endif // NEED_DO_COPY_FILE
-#endif // _GLIBCXX_HAVE_SYS_STAT_H
-
-void
-fs::copy(const path& from, const path& to, copy_options options,
-        error_code& ec)
-{
-  const bool skip_symlinks = is_set(options, copy_options::skip_symlinks);
-  const bool create_symlinks = is_set(options, copy_options::create_symlinks);
-  const bool copy_symlinks = is_set(options, copy_options::copy_symlinks);
-  const bool use_lstat = create_symlinks || skip_symlinks;
-
-  file_status f, t;
-  stat_type from_st, to_st;
-  // _GLIBCXX_RESOLVE_LIB_DEFECTS
-  // 2681. filesystem::copy() cannot copy symlinks
-  if (use_lstat || copy_symlinks
-      ? posix::lstat(from.c_str(), &from_st)
-      : posix::stat(from.c_str(), &from_st))
-    {
-      ec.assign(errno, std::generic_category());
-      return;
-    }
-  if (use_lstat
-      ? posix::lstat(to.c_str(), &to_st)
-      : posix::stat(to.c_str(), &to_st))
-    {
-      if (!is_not_found_errno(errno))
-       {
-         ec.assign(errno, std::generic_category());
-         return;
-       }
-      t = file_status{file_type::not_found};
-    }
-  else
-    t = make_file_status(to_st);
-  f = make_file_status(from_st);
-
-  if (exists(t) && !is_other(t) && !is_other(f)
-      && to_st.st_dev == from_st.st_dev && to_st.st_ino == from_st.st_ino)
-    {
-      ec = std::make_error_code(std::errc::file_exists);
-      return;
-    }
-  if (is_other(f) || is_other(t))
-    {
-      ec = std::make_error_code(std::errc::not_supported);
-      return;
-    }
-  if (is_directory(f) && is_regular_file(t))
-    {
-      ec = std::make_error_code(std::errc::is_a_directory);
-      return;
-    }
-
-  if (is_symlink(f))
-    {
-      if (skip_symlinks)
-       ec.clear();
-      else if (!exists(t) && copy_symlinks)
-       copy_symlink(from, to, ec);
-      else
-       // Not clear what should be done here.
-       // "Otherwise report an error as specified in Error reporting (7)."
-       ec = std::make_error_code(std::errc::invalid_argument);
-    }
-  else if (is_regular_file(f))
-    {
-      if (is_set(options, copy_options::directories_only))
-       ec.clear();
-      else if (create_symlinks)
-       create_symlink(from, to, ec);
-      else if (is_set(options, copy_options::create_hard_links))
-       create_hard_link(from, to, ec);
-      else if (is_directory(t))
-       do_copy_file(from.c_str(), (to / from.filename()).c_str(),
-                    copy_file_options(options), &from_st, nullptr, ec);
-      else
-       {
-         auto ptr = exists(t) ? &to_st : &from_st;
-         do_copy_file(from.c_str(), to.c_str(), copy_file_options(options),
-                      &from_st, ptr, ec);
-       }
-    }
-  // _GLIBCXX_RESOLVE_LIB_DEFECTS
-  // 2682. filesystem::copy() won't create a symlink to a directory
-  else if (is_directory(f) && create_symlinks)
-    ec = std::make_error_code(errc::is_a_directory);
-  else if (is_directory(f) && (is_set(options, copy_options::recursive)
-                              || options == copy_options::none))
-    {
-      if (!exists(t))
-       if (!create_directory(to, from, ec))
-         return;
-      // set an unused bit in options to disable further recursion
-      if (!is_set(options, copy_options::recursive))
-       options |= static_cast<copy_options>(4096);
-      for (const directory_entry& x : directory_iterator(from))
-       copy(x.path(), to/x.path().filename(), options, ec);
-    }
-  // _GLIBCXX_RESOLVE_LIB_DEFECTS
-  // 2683. filesystem::copy() says "no effects"
-  else
-    ec.clear();
-}
-
-bool
-fs::copy_file(const path& from, const path& to, copy_options option)
-{
-  error_code ec;
-  bool result = copy_file(from, to, option, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot copy file", from, to,
-                                            ec));
-  return result;
-}
-
-bool
-fs::copy_file(const path& from, const path& to, copy_options options,
-             error_code& ec)
-{
-#ifdef _GLIBCXX_HAVE_SYS_STAT_H
-  return do_copy_file(from.c_str(), to.c_str(), copy_file_options(options),
-                     nullptr, nullptr, ec);
-#else
-  ec = std::make_error_code(std::errc::not_supported);
-  return false;
-#endif
-}
-
-
-void
-fs::copy_symlink(const path& existing_symlink, const path& new_symlink)
-{
-  error_code ec;
-  copy_symlink(existing_symlink, new_symlink, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot copy symlink",
-         existing_symlink, new_symlink, ec));
-}
-
-void
-fs::copy_symlink(const path& existing_symlink, const path& new_symlink,
-                error_code& ec) noexcept
-{
-  auto p = read_symlink(existing_symlink, ec);
-  if (ec)
-    return;
-#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
-  if (is_directory(p))
-    {
-      create_directory_symlink(p, new_symlink, ec);
-      return;
-    }
-#endif
-  create_symlink(p, new_symlink, ec);
-}
-
-
-bool
-fs::create_directories(const path& p)
-{
-  error_code ec;
-  bool result = create_directories(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directories", p,
-                                            ec));
-  return result;
-}
-
-bool
-fs::create_directories(const path& p, error_code& ec)
-{
-  if (p.empty())
-    {
-      ec = std::make_error_code(errc::invalid_argument);
-      return false;
-    }
-
-  file_status st = symlink_status(p, ec);
-  if (is_directory(st))
-    return false;
-  else if (ec && !status_known(st))
-    return false;
-  else if (exists(st))
-    {
-      if (!ec)
-       ec = std::make_error_code(std::errc::not_a_directory);
-      return false;
-    }
-
-  std::stack<path> missing;
-  path pp = p;
-
-  // Strip any trailing slash
-  if (pp.has_relative_path() && !pp.has_filename())
-    pp = pp.parent_path();
-
-  do
-    {
-      const auto& filename = pp.filename();
-      if (is_dot(filename) || is_dotdot(filename))
-       pp = pp.parent_path();
-      else
-       {
-         missing.push(std::move(pp));
-         if (missing.size() > 1000) // sanity check
-           {
-             ec = std::make_error_code(std::errc::filename_too_long);
-             return false;
-           }
-         pp = missing.top().parent_path();
-       }
-
-      if (pp.empty())
-       break;
-
-      st = status(pp, ec);
-      if (exists(st))
-       {
-         if (ec)
-           return false;
-         if (!is_directory(st))
-           {
-             ec = std::make_error_code(std::errc::not_a_directory);
-             return false;
-           }
-       }
-
-      if (ec && exists(st))
-       return false;
-    }
-  while (st.type() == file_type::not_found);
-
-  bool created;
-  do
-    {
-      const path& top = missing.top();
-      created = create_directory(top, ec);
-      if (ec)
-       return false;
-      missing.pop();
-    }
-  while (!missing.empty());
-
-  return created;
-}
-
-namespace
-{
-  bool
-  create_dir(const fs::path& p, fs::perms perm, std::error_code& ec)
-  {
-    bool created = false;
-#ifdef _GLIBCXX_HAVE_SYS_STAT_H
-    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))
-         ec.assign(err, std::generic_category());
-      }
-    else
-      {
-       ec.clear();
-       created = true;
-      }
-#else
-    ec = std::make_error_code(std::errc::not_supported);
-#endif
-    return created;
-  }
-} // namespace
-
-bool
-fs::create_directory(const path& p)
-{
-  error_code ec;
-  bool result = create_directory(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directory", p,
-         ec));
-  return result;
-}
-
-bool
-fs::create_directory(const path& p, error_code& ec) noexcept
-{
-  return create_dir(p, perms::all, ec);
-}
-
-
-bool
-fs::create_directory(const path& p, const path& attributes)
-{
-  error_code ec;
-  bool result = create_directory(p, attributes, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directory", p,
-         ec));
-  return result;
-}
-
-bool
-fs::create_directory(const path& p, const path& attributes,
-                    error_code& ec) noexcept
-{
-#ifdef _GLIBCXX_HAVE_SYS_STAT_H
-  stat_type st;
-  if (posix::stat(attributes.c_str(), &st))
-    {
-      ec.assign(errno, std::generic_category());
-      return false;
-    }
-  return create_dir(p, static_cast<perms>(st.st_mode), ec);
-#else
-  ec = std::make_error_code(std::errc::not_supported);
-  return false;
-#endif
-}
-
-
-void
-fs::create_directory_symlink(const path& to, const path& new_symlink)
-{
-  error_code ec;
-  create_directory_symlink(to, new_symlink, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directory symlink",
-         to, new_symlink, ec));
-}
-
-void
-fs::create_directory_symlink(const path& to, const path& new_symlink,
-                            error_code& ec) noexcept
-{
-#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
-  ec = std::make_error_code(std::errc::not_supported);
-#else
-  create_symlink(to, new_symlink, ec);
-#endif
-}
-
-
-void
-fs::create_hard_link(const path& to, const path& new_hard_link)
-{
-  error_code ec;
-  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));
-}
-
-void
-fs::create_hard_link(const path& to, const path& new_hard_link,
-                    error_code& ec) noexcept
-{
-#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
-}
-
-void
-fs::create_symlink(const path& to, const path& new_symlink)
-{
-  error_code ec;
-  create_symlink(to, new_symlink, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create symlink",
-         to, new_symlink, ec));
-}
-
-void
-fs::create_symlink(const path& to, const path& new_symlink,
-                  error_code& ec) noexcept
-{
-#ifdef _GLIBCXX_HAVE_SYMLINK
-  if (::symlink(to.c_str(), new_symlink.c_str()))
-    ec.assign(errno, std::generic_category());
-  else
-    ec.clear();
-#else
-  ec = std::make_error_code(std::errc::not_supported);
-#endif
-}
-
-
-fs::path
-fs::current_path()
-{
-  error_code ec;
-  path p = current_path(ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get current path", ec));
-  return p;
-}
-
-fs::path
-fs::current_path(error_code& ec)
-{
-  path p;
-#ifdef _GLIBCXX_HAVE_UNISTD_H
-#if defined __GLIBC__ || defined _GLIBCXX_FILESYSTEM_IS_WINDOWS
-  if (char_ptr cwd = char_ptr{posix::getcwd(nullptr, 0)})
-    {
-      p.assign(cwd.get());
-      ec.clear();
-    }
-  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)
-      size = 1024;
-  else if (path_max > 10240)
-      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)
-    {
-      using char_type = fs::path::value_type;
-      buf.reset((char_type*)malloc(size * sizeof(char_type)));
-      if (buf)
-       {
-         if (getcwd(buf.get(), size))
-           {
-             p.assign(buf.get());
-             ec.clear();
-           }
-         else if (errno != ERANGE)
-           {
-             ec.assign(errno, std::generic_category());
-             return {};
-           }
-       }
-      else
-       {
-         ec = std::make_error_code(std::errc::not_enough_memory);
-         return {};
-       }
-    }
-#endif  // __GLIBC__
-#else   // _GLIBCXX_HAVE_UNISTD_H
-  ec = std::make_error_code(std::errc::not_supported);
-#endif
-  return p;
-}
-
-void
-fs::current_path(const path& p)
-{
-  error_code ec;
-  current_path(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set current path", ec));
-}
-
-void
-fs::current_path(const path& p, error_code& ec) noexcept
-{
-#ifdef _GLIBCXX_HAVE_UNISTD_H
-  if (posix::chdir(p.c_str()))
-    ec.assign(errno, std::generic_category());
-  else
-    ec.clear();
-#else
-  ec = std::make_error_code(std::errc::not_supported);
-#endif
-}
-
-bool
-fs::equivalent(const path& p1, const path& p2)
-{
-  error_code ec;
-  auto result = equivalent(p1, p2, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot check file equivalence",
-         p1, p2, ec));
-  return result;
-}
-
-bool
-fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept
-{
-#ifdef _GLIBCXX_HAVE_SYS_STAT_H
-  int err = 0;
-  file_status s1, s2;
-  stat_type st1, st2;
-  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 (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);
-  else
-    err = errno;
-
-  if (exists(s1) && exists(s2))
-    {
-      if (is_other(s1) && is_other(s2))
-       {
-         ec = std::make_error_code(std::errc::not_supported);
-         return false;
-       }
-      ec.clear();
-      if (is_other(s1) || is_other(s2))
-       return false;
-      return st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino;
-    }
-  else if (!exists(s1) && !exists(s2))
-    ec = std::make_error_code(std::errc::no_such_file_or_directory);
-  else if (err)
-    ec.assign(err, std::generic_category());
-  else
-    ec.clear();
-  return false;
-#else
-  ec = std::make_error_code(std::errc::not_supported);
-#endif
-  return false;
-}
-
-std::uintmax_t
-fs::file_size(const path& p)
-{
-  error_code ec;
-  auto sz = file_size(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get file size", p, ec));
-  return sz;
-}
-
-namespace
-{
-  template<typename Accessor, typename T>
-    inline T
-    do_stat(const fs::path& p, std::error_code& ec, Accessor f, T deflt)
-    {
-#ifdef _GLIBCXX_HAVE_SYS_STAT_H
-      posix::stat_type st;
-      if (posix::stat(p.c_str(), &st))
-       {
-         ec.assign(errno, std::generic_category());
-         return deflt;
-       }
-      ec.clear();
-      return f(st);
-#else
-      ec = std::make_error_code(std::errc::not_supported);
-      return deflt;
-#endif
-    }
-}
-
-std::uintmax_t
-fs::file_size(const path& p, error_code& ec) noexcept
-{
-  struct S
-  {
-    S(const stat_type& st) : type(make_file_type(st)), size(st.st_size) { }
-    S() : type(file_type::not_found) { }
-    file_type type;
-    size_t size;
-  };
-  auto s = do_stat(p, ec, [](const auto& st) { return S{st}; }, S{});
-  if (s.type == file_type::regular)
-    return s.size;
-  if (!ec)
-    {
-      if (s.type == file_type::directory)
-       ec = std::make_error_code(std::errc::is_a_directory);
-      else
-       ec = std::make_error_code(std::errc::not_supported);
-    }
-  return -1;
-}
-
-std::uintmax_t
-fs::hard_link_count(const path& p)
-{
-  error_code ec;
-  auto count = hard_link_count(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get link count", p, ec));
-  return count;
-}
-
-std::uintmax_t
-fs::hard_link_count(const path& p, error_code& ec) noexcept
-{
-  return do_stat(p, ec, std::mem_fn(&stat_type::st_nlink),
-                static_cast<uintmax_t>(-1));
-}
-
-bool
-fs::is_empty(const path& p)
-{
-  error_code ec;
-  bool e = is_empty(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot check if file is empty",
-                                            p, ec));
-  return e;
-}
-
-bool
-fs::is_empty(const path& p, error_code& ec)
-{
-  auto s = status(p, ec);
-  if (ec)
-    return false;
-  bool empty = fs::is_directory(s)
-    ? fs::directory_iterator(p, ec) == fs::directory_iterator()
-    : fs::file_size(p, ec) == 0;
-  return ec ? false : empty;
-}
-
-fs::file_time_type
-fs::last_write_time(const path& p)
-{
-  error_code ec;
-  auto t = last_write_time(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get file time", p, ec));
-  return t;
-}
-
-fs::file_time_type
-fs::last_write_time(const path& p, error_code& ec) noexcept
-{
-  return do_stat(p, ec,
-                [&ec](const auto& st) {
-                    return internal_file_clock::from_stat(st, ec);
-                },
-                file_time_type::min());
-}
-
-void
-fs::last_write_time(const path& p, file_time_type new_time)
-{
-  error_code ec;
-  last_write_time(p, new_time, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set file time", p, ec));
-}
-
-void
-fs::last_write_time(const path& p __attribute__((__unused__)),
-                   file_time_type new_time, error_code& ec) noexcept
-{
-  auto d = internal_file_clock::_S_to_sys(new_time).time_since_epoch();
-  auto s = chrono::duration_cast<chrono::seconds>(d);
-#if _GLIBCXX_USE_UTIMENSAT
-  auto ns = chrono::duration_cast<chrono::nanoseconds>(d - s);
-  if (ns < ns.zero()) // tv_nsec must be non-negative and less than 10e9.
-    {
-      --s;
-      ns += chrono::seconds(1);
-    }
-  struct ::timespec ts[2];
-  ts[0].tv_sec = 0;
-  ts[0].tv_nsec = UTIME_OMIT;
-  ts[1].tv_sec = static_cast<std::time_t>(s.count());
-  ts[1].tv_nsec = static_cast<long>(ns.count());
-  if (::utimensat(AT_FDCWD, p.c_str(), ts, 0))
-    ec.assign(errno, std::generic_category());
-  else
-    ec.clear();
-#elif _GLIBCXX_HAVE_UTIME_H
-  posix::utimbuf times;
-  times.modtime = s.count();
-  times.actime = do_stat(p, ec, [](const auto& st) { return st.st_atime; },
-                        times.modtime);
-  if (posix::utime(p.c_str(), &times))
-    ec.assign(errno, std::generic_category());
-  else
-    ec.clear();
-#else
-  ec = std::make_error_code(std::errc::not_supported);
-#endif
-}
-
-void
-fs::permissions(const path& p, perms prms, perm_options opts)
-{
-  error_code ec;
-  permissions(p, prms, opts, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set permissions", p, ec));
-}
-
-void
-fs::permissions(const path& p, perms prms, perm_options opts,
-               error_code& ec) noexcept
-{
-  const bool replace = is_set(opts, perm_options::replace);
-  const bool add = is_set(opts, perm_options::add);
-  const bool remove = is_set(opts, perm_options::remove);
-  const bool nofollow = is_set(opts, perm_options::nofollow);
-  if (((int)replace + (int)add + (int)remove) != 1)
-    {
-      ec = std::make_error_code(std::errc::invalid_argument);
-      return;
-    }
-
-  prms &= perms::mask;
-
-  file_status st;
-  if (add || remove || nofollow)
-    {
-      st = nofollow ? symlink_status(p, ec) : status(p, ec);
-      if (ec)
-       return;
-      auto curr = st.permissions();
-      if (add)
-       prms |= curr;
-      else if (remove)
-       prms = curr & ~prms;
-    }
-
-  int err = 0;
-#if _GLIBCXX_USE_FCHMODAT
-  const int flag = (nofollow && is_symlink(st)) ? AT_SYMLINK_NOFOLLOW : 0;
-  if (::fchmodat(AT_FDCWD, p.c_str(), static_cast<mode_t>(prms), flag))
-    err = errno;
-#else
-  if (nofollow && is_symlink(st))
-    ec = std::make_error_code(std::errc::operation_not_supported);
-  else if (posix::chmod(p.c_str(), static_cast<mode_t>(prms)))
-    err = errno;
-#endif
-
-  if (err)
-    ec.assign(err, std::generic_category());
-  else
-    ec.clear();
-}
-
-fs::path
-fs::proximate(const path& p, const path& base)
-{
-  return weakly_canonical(p).lexically_proximate(weakly_canonical(base));
-}
-
-fs::path
-fs::proximate(const path& p, const path& base, error_code& ec)
-{
-  path result;
-  const auto p2 = weakly_canonical(p, ec);
-  if (!ec)
-    {
-      const auto base2 = weakly_canonical(base, ec);
-      if (!ec)
-       result = p2.lexically_proximate(base2);
-    }
-  return result;
-}
-
-fs::path
-fs::read_symlink(const path& p)
-{
-  error_code ec;
-  path tgt = read_symlink(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("read_symlink", p, ec));
-  return tgt;
-}
-
-fs::path fs::read_symlink(const path& p [[gnu::unused]], error_code& ec)
-{
-  path result;
-#if defined(_GLIBCXX_HAVE_READLINK) && defined(_GLIBCXX_HAVE_SYS_STAT_H)
-  stat_type st;
-  if (::lstat(p.c_str(), &st))
-    {
-      ec.assign(errno, std::generic_category());
-      return result;
-    }
-  std::string buf(st.st_size ? st.st_size + 1 : 128, '\0');
-  do
-    {
-      ssize_t len = ::readlink(p.c_str(), buf.data(), buf.size());
-      if (len == -1)
-       {
-         ec.assign(errno, std::generic_category());
-         return result;
-       }
-      else if (len == (ssize_t)buf.size())
-       {
-         if (buf.size() > 4096)
-           {
-             ec.assign(ENAMETOOLONG, std::generic_category());
-             return result;
-           }
-         buf.resize(buf.size() * 2);
-       }
-      else
-       {
-         buf.resize(len);
-         result.assign(buf);
-         ec.clear();
-         break;
-       }
-    }
-  while (true);
-#else
-  ec = std::make_error_code(std::errc::not_supported);
-#endif
-  return result;
-}
-
-fs::path
-fs::relative(const path& p, const path& base)
-{
-  return weakly_canonical(p).lexically_relative(weakly_canonical(base));
-}
-
-fs::path
-fs::relative(const path& p, const path& base, error_code& ec)
-{
-  auto result = weakly_canonical(p, ec);
-  fs::path cbase;
-  if (!ec)
-    cbase = weakly_canonical(base, ec);
-  if (!ec)
-    result = result.lexically_relative(cbase);
-  if (ec)
-    result.clear();
-  return result;
-}
-
-bool
-fs::remove(const path& p)
-{
-  error_code ec;
-  const bool result = fs::remove(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove", p, ec));
-  return result;
-}
-
-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();
-      return true;
-    }
-  else if (errno == ENOENT)
-    ec.clear();
-  else
-    ec.assign(errno, std::generic_category());
-#endif
-  return false;
-}
-
-
-std::uintmax_t
-fs::remove_all(const path& p)
-{
-  error_code ec;
-  const auto result = remove_all(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
-  return result;
-}
-
-std::uintmax_t
-fs::remove_all(const path& p, error_code& ec)
-{
-  const auto s = symlink_status(p, ec);
-  if (!status_known(s))
-    return -1;
-
-  ec.clear();
-  if (s.type() == file_type::not_found)
-    return 0;
-
-  uintmax_t count = 0;
-  if (s.type() == file_type::directory)
-    {
-      for (directory_iterator d(p, ec), end; !ec && d != end; d.increment(ec))
-       count += fs::remove_all(d->path(), ec);
-      if (ec.value() == ENOENT)
-       ec.clear();
-      else if (ec)
-       return -1;
-    }
-
-  if (fs::remove(p, ec))
-    ++count;
-  return ec ? -1 : count;
-}
-
-void
-fs::rename(const path& from, const path& to)
-{
-  error_code ec;
-  rename(from, to, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot rename", from, to, ec));
-}
-
-void
-fs::rename(const path& from, const path& to, error_code& ec) noexcept
-{
-  if (posix::rename(from.c_str(), to.c_str()))
-    ec.assign(errno, std::generic_category());
-  else
-    ec.clear();
-}
-
-void
-fs::resize_file(const path& p, uintmax_t size)
-{
-  error_code ec;
-  resize_file(p, size, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot resize file", p, ec));
-}
-
-void
-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 (posix::truncate(p.c_str(), size))
-    ec.assign(errno, std::generic_category());
-  else
-    ec.clear();
-#else
-  ec = std::make_error_code(std::errc::not_supported);
-#endif
-}
-
-
-fs::space_info
-fs::space(const path& p)
-{
-  error_code ec;
-  space_info s = space(p, ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get free space", p, ec));
-  return s;
-}
-
-#ifdef NEED_DO_SPACE
-void
-fs::do_space(const __gnu_posix::char_type* pathname,
-        uintmax_t& capacity, uintmax_t& free, uintmax_t& available,
-        std::error_code& ec)
-{
-#ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
-  struct ::statvfs f;
-  if (::statvfs(pathname, &f))
-      ec.assign(errno, std::generic_category());
-  else
-    {
-      if (f.f_frsize != (unsigned long)-1)
-       {
-         const uintmax_t fragment_size = f.f_frsize;
-         const fsblkcnt_t unknown = -1;
-         if (f.f_blocks != unknown)
-           capacity = f.f_blocks * fragment_size;
-         if (f.f_bfree != unknown)
-           free = f.f_bfree * fragment_size;
-         if (f.f_bavail != unknown)
-           available = f.f_bavail * fragment_size;
-       }
-      ec.clear();
-    }
-#elif _GLIBCXX_FILESYSTEM_IS_WINDOWS
-  ULARGE_INTEGER bytes_avail = {}, bytes_total = {}, bytes_free = {};
-  if (GetDiskFreeSpaceExW(pathname, &bytes_avail, &bytes_total, &bytes_free))
-    {
-      if (bytes_total.QuadPart != 0)
-       capacity = bytes_total.QuadPart;
-      if (bytes_free.QuadPart != 0)
-       free = bytes_free.QuadPart;
-      if (bytes_avail.QuadPart != 0)
-       available = bytes_avail.QuadPart;
-      ec.clear();
-    }
-  else
-    ec.assign((int)GetLastError(), std::system_category());
-#else
-  ec = std::make_error_code(std::errc::not_supported);
-#endif
-}
-#endif // NEED_DO_SPACE
-
-fs::space_info
-fs::space(const path& p, error_code& ec) noexcept
-{
-  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;
-}
-
-#ifdef _GLIBCXX_HAVE_SYS_STAT_H
-fs::file_status
-fs::status(const fs::path& p, error_code& ec) noexcept
-{
-  file_status status;
-  stat_type st;
-  if (posix::stat(p.c_str(), &st))
-    {
-      int err = errno;
-      ec.assign(err, std::generic_category());
-      if (is_not_found_errno(err))
-       status.type(file_type::not_found);
-#ifdef EOVERFLOW
-      else if (err == EOVERFLOW)
-       status.type(file_type::unknown);
-#endif
-    }
-  else
-    {
-      status = make_file_status(st);
-      ec.clear();
-    }
-  return status;
-}
-
-fs::file_status
-fs::symlink_status(const fs::path& p, std::error_code& ec) noexcept
-{
-  file_status status;
-  stat_type st;
-  if (posix::lstat(p.c_str(), &st))
-    {
-      int err = errno;
-      ec.assign(err, std::generic_category());
-      if (is_not_found_errno(err))
-       status.type(file_type::not_found);
-    }
-  else
-    {
-      status = make_file_status(st);
-      ec.clear();
-    }
-  return status;
-}
-#endif
-
-fs::file_status
-fs::status(const fs::path& p)
-{
-  std::error_code ec;
-  auto result = status(p, ec);
-  if (result.type() == file_type::none)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("status", p, ec));
-  return result;
-}
-
-fs::file_status
-fs::symlink_status(const fs::path& p)
-{
-  std::error_code ec;
-  auto result = symlink_status(p, ec);
-  if (result.type() == file_type::none)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("symlink_status", p, ec));
-  return result;
-}
-
-fs::path fs::temp_directory_path()
-{
-  error_code ec;
-  path tmp = temp_directory_path(ec);
-  if (ec)
-    _GLIBCXX_THROW_OR_ABORT(filesystem_error("temp_directory_path", ec));
-  return tmp;
-}
-
-fs::path fs::temp_directory_path(error_code& ec)
-{
-  path p;
-#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
-  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);
-  p = tmpdir ? tmpdir : "/tmp";
-#endif
-  auto st = status(p, ec);
-  if (ec)
-    p.clear();
-  else if (!is_directory(st))
-    {
-      p.clear();
-      ec = std::make_error_code(std::errc::not_a_directory);
-    }
-  return p;
-}
-
-fs::path
-fs::weakly_canonical(const path& p)
-{
-  path result;
-  if (exists(status(p)))
-    return canonical(p);
-
-  path tmp;
-  auto iter = p.begin(), end = p.end();
-  // find leading elements of p that exist:
-  while (iter != end)
-    {
-      tmp = result / *iter;
-      if (exists(status(tmp)))
-       swap(result, tmp);
-      else
-       break;
-      ++iter;
-    }
-  // canonicalize:
-  if (!result.empty())
-    result = canonical(result);
-  // append the non-existing elements:
-  while (iter != end)
-    result /= *iter++;
-  // normalize:
-  return result.lexically_normal();
-}
-
-fs::path
-fs::weakly_canonical(const path& p, error_code& ec)
-{
-  path result;
-  file_status st = status(p, ec);
-  if (exists(st))
-    return canonical(p, ec);
-  else if (status_known(st))
-    ec.clear();
-  else
-    return result;
-
-  path tmp;
-  auto iter = p.begin(), end = p.end();
-  // find leading elements of p that exist:
-  while (iter != end)
-    {
-      tmp = result / *iter;
-      st = status(tmp, ec);
-      if (exists(st))
-       swap(result, tmp);
-      else
-       {
-         if (status_known(st))
-           ec.clear();
-         break;
-       }
-      ++iter;
-    }
-  // canonicalize:
-  if (!ec && !result.empty())
-    result = canonical(result, ec);
-  if (ec)
-    result.clear();
-  else
-    {
-      // append the non-existing elements:
-      while (iter != end)
-       result /= *iter++;
-      // normalize:
-      result = result.lexically_normal();
-    }
-  return result;
-}
index 10202f5be3e0dd293da8c03a8816c17322a232f7..67c70abf4a1d338389417d7a36559a4d8f425a9c 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 95158c63ca8c39f77b288258d49cc1573652db23..b688d69085efc33adb6e1407e6bc04a695596867 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 030a1d273f354b4e2685e5de53fbce8ed0e63236..0bda10d28e2edcd708edbacdc4be140118ffb701 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index cd40397c3461267abbf03c94f0da51489bf4a5b0..8b24541cbc643a41e6c9e790af01f05612460c8e 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 71eac38e0d3b711f164a24ecdb3ba3972fa33cfe..926f164f5fa4c60663153262f382981dee90e410 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 71ecd21ab40061d934f479dfba6082f39d2ce6cb..ddb424b4be0029595ec924a1fca267901621eb9d 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index fab7ac0f89619875540499912777206a0dc6516f..b092dee91e017a6a708109be5725d93d9a90322b 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index ca4899d058c8bb53835bc98ceaac8edc71533e74..bf67bfd215b274ea88c52b187134c21a1ac511d3 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 496f3f8d4fbf461fec1d9c4a74c87c6dc47dbdf4..45f66ac96c5f0bc0194487c0d841f9e066926871 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 9f511c51a9d528377e47d3751a7e82dbf9620995..8051a4bfb7ac86648d90bd9f240e3543acc57021 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 2fba1fba2d1c084b7bf1f7392d63be4d686c9929..7234e34831fed4de745a1e2e02639522c529a388 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 85e97c634d3fc885dbb547c5fa7c645060b79d71..dfad8541bfeec8084d9c7c23eeac5c133223d0f8 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 007c5cd55fcd45fa4e36ed61e51dfe5832abc269..d248676b82db04de955fcf2c2ae061c1e8427cc0 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index e196c57e799e946d3a8a14dd668d34f8c1c726b7..da78fb2de87f6e4f24311a3f04826de77718997e 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 55a103f89368feaccdad0afb9c5c9a0ae71ae496..4236f20f62d81c779f1455ccf28266d82ec2d6d2 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index b5a6c6384762e52e4b7e84eede3cd1aa6d3ee64a..c62ada9f1116bea81a7b3d3bc10529a7d18d12af 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index f371cdb0afec41d108c18f3f1fbe0aa89491abff..ca1d691bc7c2e88359708f1650d934e0a6e562cf 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 330ec542ce842ebc5184f88473eab6d0be5a300d..df8251e55c2372c34c3c363d75642077b140ec74 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index bb11653cae200adc2474e93b9ce68b49b06fc1bc..57c9e96e4dcb066f5d3b439517ba240c2723208e 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index e4e4c3e3bc7324f7fd5ecd6325064329975b8c30..c572a83457683b016d86abba1d95ff649d5fd59c 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 49822e166b11ef4541f5d41bf15343d39b5ce12c..7a693a1ddcb7af5de5c016d17b8edc0db4d33056 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 669b04903f17b3f851632277dd3493f67ffe9360..23d5817acadb0aadf1495972b904475d1141b042 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 093582506287bd668430f300f5382635730913fa..8a7e258628a08f7fb3f2222a162cbd4d5862081e 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index f04932fcc0f72c7b7b0b48f952d4ac183eb70093..038c0447a042e5badf7a30a43656319350378a92 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 // { dg-xfail-if "symlinks not supported" { *-*-mingw* } }
index c7521d132620958e71960bae31cd2313a200e6ee..e013faaaf6816583955d5537a85f33bd6de8db20 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 066bd2bad0ea120deeda239b2bc73b2fdfa9bdd6..afe9580fa33ba7c533fee2f8ba1edbad81d49565 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 255a6b1b9ff33e5b53ebd86f4069fd02a3f80532..2f2802ff859d5f18fd43aa9fceb31cf6c04f18ad 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 4070e7bdb92b44649f05f163991a89a66cefe558..e545e5e8f70ec661952be08a1e6a37d79e475b07 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 8a526db7cabb7a0165192dce04742099083d205f..b5ab1b5fd5eb888a7b64a71845a059224bde5ab2 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index 66125743001cd07378530038b736e5ce10065c0d..6f01419da3ea1f443617c4fae100f4ba85bfc9c8 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 // { dg-xfail-if "symlinks not supported" { *-*-mingw* } }
index 8f03b9dc324a2d99296e04822bf4761f158d64e0..b3ae66d7d640dbbcff91e946f5064e4ff3797e7b 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }
 
index ef6a8b563eab3a74c05596d1aaf84cf477f5ccac..e7f1a4ca782f06614eda0c25a338d4c52a985357 100644 (file)
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17 -lstdc++fs" }
+// { dg-options "-std=gnu++17" }
 // { dg-do run { target c++17 } }
 // { dg-require-filesystem-ts "" }