acinclude.m4 (GLIBCXX_ENABLE_FILESYSTEM_TS): Disable when <dirent.h> is not available.
authorJonathan Wakely <jwakely@redhat.com>
Fri, 1 May 2015 19:48:00 +0000 (20:48 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 1 May 2015 19:48:00 +0000 (20:48 +0100)
* acinclude.m4 (GLIBCXX_ENABLE_FILESYSTEM_TS): Disable when <dirent.h>
is not available.
(GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for fchmodat.
* configure: Regenerate.
* config.h.in: Regenerate.
* configure.ac: Check for utime.h
* include/experimental/fs_path.h (path::string<>)
[_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Remove stray typename keyword.
* src/filesystem/dir.cc [!_GLIBCXX_HAVE_DIRENT_H] (DIR, opendir,
closedir, dirent, readdir_r): Replace dummy functions with #error.
(native_readdir, _Dir::advance): Use readdir when readdir_r is missing.
* src/filesystem/ops.cc (do_stat, is_set): Make inline.
(last_write_time) [!_GLIBCXX_USE_UTIMENSAT]: Use utime.
(permissions) [!_GLIBCXX_USE_FCHMODAT]: Use chmod.
(space, temp_directory_path) [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Set
error_code.

From-SVN: r222703

libstdc++-v3/ChangeLog
libstdc++-v3/acinclude.m4
libstdc++-v3/config.h.in
libstdc++-v3/configure
libstdc++-v3/configure.ac
libstdc++-v3/include/experimental/fs_path.h
libstdc++-v3/src/filesystem/dir.cc
libstdc++-v3/src/filesystem/ops.cc

index 8d559eb..7e07005 100644 (file)
@@ -1,5 +1,22 @@
 2015-05-01  Jonathan Wakely  <jwakely@redhat.com>
 
+       * acinclude.m4 (GLIBCXX_ENABLE_FILESYSTEM_TS): Disable when <dirent.h>
+       is not available.
+       (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for fchmodat.
+       * configure: Regenerate.
+       * config.h.in: Regenerate.
+       * configure.ac: Check for utime.h
+       * include/experimental/fs_path.h (path::string<>)
+       [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Remove stray typename keyword.
+       * src/filesystem/dir.cc [!_GLIBCXX_HAVE_DIRENT_H] (DIR, opendir,
+       closedir, dirent, readdir_r): Replace dummy functions with #error.
+       (native_readdir, _Dir::advance): Use readdir when readdir_r is missing.
+       * src/filesystem/ops.cc (do_stat, is_set): Make inline.
+       (last_write_time) [!_GLIBCXX_USE_UTIMENSAT]: Use utime.
+       (permissions) [!_GLIBCXX_USE_FCHMODAT]: Use chmod.
+       (space, temp_directory_path) [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Set
+       error_code.
+
        * include/experimental/fs_path.h (path::_List): Use vector instead of
        list.
        * python/libstdcxx/v6/printers.py (StdExpPathPrinter): Adapt.
index 9d8d96d..07b5bd7 100644 (file)
@@ -3914,6 +3914,9 @@ AC_DEFUN([GLIBCXX_ENABLE_FILESYSTEM_TS], [
     [permit yes|no|auto])
 
   AC_MSG_CHECKING([whether to build Filesystem TS support])
+  if test x"$ac_cv_header_dirent_h" != x"yes"; then
+    enable_libstdcxx_filesystem_ts=no
+  fi
   if test x"$enable_libstdcxx_filesystem_ts" = x"auto"; then
     case "${target_os}" in
       freebsd*|netbsd*|openbsd*|dragonfly*|darwin*)
@@ -3993,6 +3996,22 @@ dnl
   fi
   AC_MSG_RESULT($glibcxx_cv_st_mtim)
 dnl
+  AC_MSG_CHECKING([for fchmodat])
+  AC_CACHE_VAL(glibcxx_cv_fchmodat, [dnl
+    GCC_TRY_COMPILE_OR_LINK(
+      [
+        #include <fcntl.h>
+        #include <sys/stat.h>
+      ],
+      [fchmodat(AT_FDCWD, "", 0, AT_SYMLINK_NOFOLLOW);],
+      [glibcxx_cv_fchmodat=yes],
+      [glibcxx_cv_fchmodat=no])
+  ])
+  if test $glibcxx_cv_fchmodat = yes; then
+    AC_DEFINE(_GLIBCXX_USE_FCHMODAT, 1, [Define if fchmodat is available in <sys/stat.h>.])
+  fi
+  AC_MSG_RESULT($glibcxx_cv_fchmodat)
+dnl
   CXXFLAGS="$ac_save_CXXFLAGS"
   AC_LANG_RESTORE
 ])
index d763d1b..88d56b5 100644 (file)
 /* Defined if usleep exists. */
 #undef HAVE_USLEEP
 
+/* Define to 1 if you have the <utime.h> header file. */
+#undef HAVE_UTIME_H
+
 /* Defined if vfwscanf exists. */
 #undef HAVE_VFWSCANF
 
    this host. */
 #undef _GLIBCXX_USE_DECIMAL_FLOAT
 
+/* Define if fchmodat is available in <sys/stat.h>. */
+#undef _GLIBCXX_USE_FCHMODAT
+
 /* Define if __float128 is supported on this host. */
 #undef _GLIBCXX_USE_FLOAT128
 
index 5ecfdeb..90a5192 100755 (executable)
@@ -78928,7 +78928,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 # For Filesystem TS.
-for ac_header in fcntl.h dirent.h sys/statvfs.h
+for ac_header in fcntl.h dirent.h sys/statvfs.h utime.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -79154,6 +79154,9 @@ fi
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build Filesystem TS support" >&5
 $as_echo_n "checking whether to build Filesystem TS support... " >&6; }
+  if test x"$ac_cv_header_dirent_h" != x"yes"; then
+    enable_libstdcxx_filesystem_ts=no
+  fi
   if test x"$enable_libstdcxx_filesystem_ts" = x"auto"; then
     case "${target_os}" in
       freebsd*|netbsd*|openbsd*|dragonfly*|darwin*)
@@ -79369,6 +79372,68 @@ $as_echo "#define _GLIBCXX_USE_ST_MTIM 1" >>confdefs.h
   fi
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_st_mtim" >&5
 $as_echo "$glibcxx_cv_st_mtim" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fchmodat" >&5
+$as_echo_n "checking for fchmodat... " >&6; }
+  if test "${glibcxx_cv_fchmodat+set}" = set; 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 <fcntl.h>
+        #include <sys/stat.h>
+
+int
+main ()
+{
+fchmodat(AT_FDCWD, "", 0, AT_SYMLINK_NOFOLLOW);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  glibcxx_cv_fchmodat=yes
+else
+  glibcxx_cv_fchmodat=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 <fcntl.h>
+        #include <sys/stat.h>
+
+int
+main ()
+{
+fchmodat(AT_FDCWD, "", 0, AT_SYMLINK_NOFOLLOW);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  glibcxx_cv_fchmodat=yes
+else
+  glibcxx_cv_fchmodat=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+
+fi
+
+  if test $glibcxx_cv_fchmodat = yes; then
+
+$as_echo "#define _GLIBCXX_USE_FCHMODAT 1" >>confdefs.h
+
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_fchmodat" >&5
+$as_echo "$glibcxx_cv_fchmodat" >&6; }
   CXXFLAGS="$ac_save_CXXFLAGS"
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
index 4b39bfa..311baa5 100644 (file)
@@ -403,7 +403,7 @@ GLIBCXX_CONFIGURE_TESTSUITE
 GLIBCXX_CHECK_GTHREADS
 
 # For Filesystem TS.
-AC_CHECK_HEADERS([fcntl.h dirent.h sys/statvfs.h])
+AC_CHECK_HEADERS([fcntl.h dirent.h sys/statvfs.h utime.h])
 AC_STRUCT_DIRENT_D_TYPE
 GLIBCXX_ENABLE_FILESYSTEM_TS
 GLIBCXX_CHECK_FILESYSTEM_DEPS
index e57a08b..33a16db 100644 (file)
@@ -781,7 +781,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       const value_type* __last = __first + _M_pathname.size();
 
 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
-      using _CharAlloc = typename __alloc_rebind<_Allocator, char>;
+      using _CharAlloc = __alloc_rebind<_Allocator, char>;
       using _String = basic_string<char, char_traits<char>, _CharAlloc>;
       using _WString = basic_string<_CharT, _Traits, _Allocator>;
 
index 4ed869e..016a78d 100644 (file)
@@ -25,7 +25,6 @@
 #include <experimental/filesystem>
 #include <utility>
 #include <stack>
-#include <tuple>
 #include <string.h>
 #include <errno.h>
 #ifdef _GLIBCXX_HAVE_DIRENT_H
 # endif
 # include <dirent.h>
 #else
-// TODO: replace dummy definitions with suitable Win32 code
-#ifndef EACCES
-# define EACCES static_cast<int>(std::errc::permission_denied)
+# error "the <dirent.h> header is needed to build the Filesystem TS"
 #endif
-using DIR = void;
-using P = std::experimental::filesystem::path;
-static DIR* opendir(const P::value_type*) { return nullptr; }
-static void closedir(DIR*) { }
-struct dirent { const char* d_name; };
-static inline int readdir_r(DIR*, dirent*, dirent**)
-{ return static_cast<int>(std::errc::not_supported); }
+
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+# undef opendir
+# define opendir _wopendir
 #endif
 
 namespace fs = std::experimental::filesystem;
@@ -97,7 +91,7 @@ struct fs::_Dir
 namespace
 {
   template<typename Bitmask>
-    bool is_set(Bitmask obj, Bitmask bits)
+    inline bool is_set(Bitmask obj, Bitmask bits)
     {
       return (obj & bits) != Bitmask::none;
     }
@@ -159,14 +153,27 @@ namespace
     return fs::file_type::none;
 #endif
   }
+
+  int
+  native_readdir(DIR* dirp, ::dirent*& entryp)
+  {
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+    errno = 0;
+    if ((entryp = ::readdir(dirp)))
+      return 0;
+    return errno;
+#else
+    return ::readdir_r(dirp, entryp, &entryp);
+#endif
+  }
 }
 
 bool
 fs::_Dir::advance(ErrorCode ec)
 {
   ::dirent ent;
-  ::dirent* result;
-  if (int err = readdir_r(dirp, &ent, &result))
+  ::dirent* result = &ent;
+  if (int err = native_readdir(dirp, result))
     {
       if (!ec)
        _GLIBCXX_THROW_OR_ABORT(filesystem_error(
index 091ca72..c7e3960 100644 (file)
 # include <ext/stdio_filebuf.h>
 # include <ostream>
 #endif
+#if _GLIBCXX_HAVE_UTIME_H
+# include <utime.h>
+#endif
+
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+# undef utime
+# define utime _wutime
+# undef chmod
+# define chmod _wchmod
+#endif
 
 namespace fs = std::experimental::filesystem;
 
@@ -131,7 +141,7 @@ fs::copy(const path& from, const path& to, copy_options options)
 namespace
 {
   template<typename Bitmask>
-    bool is_set(Bitmask obj, Bitmask bits)
+    inline bool is_set(Bitmask obj, Bitmask bits)
     {
       return (obj & bits) != Bitmask::none;
     }
@@ -767,7 +777,7 @@ fs::file_size(const path& p)
 namespace
 {
   template<typename Accessor, typename T>
-    T
+    inline T
     do_stat(const fs::path& p, std::error_code& ec, Accessor f, T deflt)
     {
 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
@@ -871,6 +881,14 @@ fs::last_write_time(const path& p __attribute__((__unused__)),
     ec.assign(errno, std::generic_category());
   else
     ec.clear();
+#elif _GLIBCXX_HAVE_UTIME_H
+  ::utimbuf times;
+  times.modtime = s.count();
+  times.actime = do_stat(p, ec, std::mem_fn(&stat::st_atime), times.modtime);
+  if (::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
@@ -887,7 +905,11 @@ fs::permissions(const path& p, perms prms)
 
 void fs::permissions(const path& p, perms prms, error_code& ec) noexcept
 {
+#if _GLIBCXX_USE_FCHMODAT
   if (int err = ::fchmodat(AT_FDCWD, p.c_str(), static_cast<mode_t>(prms), 0))
+#else
+  if (int err = ::chmod(p.c_str(), static_cast<mode_t>(prms)))
+#endif
     ec.assign(err, std::generic_category());
   else
     ec.clear();
@@ -1051,6 +1073,8 @@ fs::space(const path& p, error_code& ec) noexcept
       };
       ec.clear();
     }
+#else
+  ec = std::make_error_code(std::errc::not_supported);
 #endif
   return info;
 }
@@ -1157,6 +1181,7 @@ fs::path fs::temp_directory_path()
 fs::path fs::temp_directory_path(error_code& ec)
 {
 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+  ec = std::make_error_code(std::errc::not_supported);
   return {}; // TODO
 #else
   const char* tmpdir = ::getenv("TMPDIR");