re PR libstdc++/66011 (call to '__open_missing_mode' declared with attribute error)
authorJonathan Wakely <jwakely@redhat.com>
Thu, 14 May 2015 13:23:14 +0000 (14:23 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 14 May 2015 13:23:14 +0000 (14:23 +0100)
PR libstdc++/66011
* acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for fchmod and
sendfile.
* config.h.in: Regenerate.
* configure: Regenerate.
* src/filesystem/ops.cc (do_copy_file): Fix arguments to open(). Do
not return after copying contents. Use fchmod, fchmodat, and sendfile
when available.
(current_path, permissions, space): Use errno not return value.

From-SVN: r223196

libstdc++-v3/ChangeLog
libstdc++-v3/acinclude.m4
libstdc++-v3/config.h.in
libstdc++-v3/configure
libstdc++-v3/src/filesystem/ops.cc

index 000bcd56bca18dd87a07bc119a88594a7c62f364..4e38fbfe93f1a9af01ce2a614d6b8aad8188a300 100644 (file)
@@ -1,5 +1,15 @@
 2015-05-14  Jonathan Wakely  <jwakely@redhat.com>
 
+       PR libstdc++/66011
+       * acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for fchmod and
+       sendfile.
+       * config.h.in: Regenerate.
+       * configure: Regenerate.
+       * src/filesystem/ops.cc (do_copy_file): Fix arguments to open(). Do
+       not return after copying contents. Use fchmod, fchmodat, and sendfile
+       when available.
+       (current_path, permissions, space): Use errno not return value.
+
        PR libstdc++/66018
        * acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for struct
        dirent.d_type.
index b2b48cc2944e36646c61b9a868e2254d42bf6b6b..8340572984daf8b2afb016539cf4950da05ffe43 100644 (file)
@@ -3938,6 +3938,19 @@ dnl
     AC_DEFINE(_GLIBCXX_USE_ST_MTIM, 1, [Define if struct stat has timespec members.])
   fi
   AC_MSG_RESULT($glibcxx_cv_st_mtim)
+dnl
+  AC_MSG_CHECKING([for fchmod])
+  AC_CACHE_VAL(glibcxx_cv_fchmod, [dnl
+    GCC_TRY_COMPILE_OR_LINK(
+      [#include <sys/stat.h>],
+      [fchmod(1, S_IWUSR);],
+      [glibcxx_cv_fchmod=yes],
+      [glibcxx_cv_fchmod=no])
+  ])
+  if test $glibcxx_cv_fchmod = yes; then
+    AC_DEFINE(_GLIBCXX_USE_FCHMOD, 1, [Define if fchmod is available in <sys/stat.h>.])
+  fi
+  AC_MSG_RESULT($glibcxx_cv_fchmod)
 dnl
   AC_MSG_CHECKING([for fchmodat])
   AC_CACHE_VAL(glibcxx_cv_fchmodat, [dnl
@@ -3954,6 +3967,26 @@ dnl
     AC_DEFINE(_GLIBCXX_USE_FCHMODAT, 1, [Define if fchmodat is available in <sys/stat.h>.])
   fi
   AC_MSG_RESULT($glibcxx_cv_fchmodat)
+dnl
+  AC_MSG_CHECKING([for sendfile that can copy files])
+  AC_CACHE_VAL(glibcxx_cv_sendfile, [dnl
+    case "${target_os}" in
+      gnu* | linux* | solaris*)
+        GCC_TRY_COMPILE_OR_LINK(
+          [#include <sys/sendfile.h>],
+          [sendfile(1, 2, (off_t*)NULL, sizeof 1);],
+          [glibcxx_cv_sendfile=yes],
+          [glibcxx_cv_sendfile=no])
+        ;;
+      *)
+        glibcxx_cv_sendfile=no
+        ;;
+    esac
+  ])
+  if test $glibcxx_cv_sendfile = yes; then
+    AC_DEFINE(_GLIBCXX_USE_SENDFILE, 1, [Define if sendfile is available in <sys/stat.h>.])
+  fi
+  AC_MSG_RESULT($glibcxx_cv_sendfile)
 dnl
   CXXFLAGS="$ac_save_CXXFLAGS"
   AC_LANG_RESTORE
index b833c811c519c4d9a6e006bfff5de265ae3c62e2..337f61440a9d72af1c519d8d4fa1cee593e97801 100644 (file)
    this host. */
 #undef _GLIBCXX_USE_DECIMAL_FLOAT
 
+/* Define if fchmod is available in <sys/stat.h>. */
+#undef _GLIBCXX_USE_FCHMOD
+
 /* Define if fchmodat is available in <sys/stat.h>. */
 #undef _GLIBCXX_USE_FCHMODAT
 
 /* Define if _SC_NPROC_ONLN is available in <unistd.h>. */
 #undef _GLIBCXX_USE_SC_NPROC_ONLN
 
+/* Define if sendfile is available in <sys/stat.h>. */
+#undef _GLIBCXX_USE_SENDFILE
+
 /* Define if struct stat has timespec members. */
 #undef _GLIBCXX_USE_ST_MTIM
 
index d30cd188b4e05fe1084783ebbe7a57291cc37bd5..3654b68f281022cf6e7997f4e3716647aa785736 100755 (executable)
@@ -79092,6 +79092,62 @@ $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 fchmod" >&5
+$as_echo_n "checking for fchmod... " >&6; }
+  if test "${glibcxx_cv_fchmod+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 <sys/stat.h>
+int
+main ()
+{
+fchmod(1, S_IWUSR);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  glibcxx_cv_fchmod=yes
+else
+  glibcxx_cv_fchmod=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 ()
+{
+fchmod(1, S_IWUSR);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  glibcxx_cv_fchmod=yes
+else
+  glibcxx_cv_fchmod=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+
+fi
+
+  if test $glibcxx_cv_fchmod = yes; then
+
+$as_echo "#define _GLIBCXX_USE_FCHMOD 1" >>confdefs.h
+
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_fchmod" >&5
+$as_echo "$glibcxx_cv_fchmod" >&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 :
@@ -79154,6 +79210,69 @@ $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; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sendfile that can copy files" >&5
+$as_echo_n "checking for sendfile that can copy files... " >&6; }
+  if test "${glibcxx_cv_sendfile+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+      case "${target_os}" in
+      gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu | solaris*)
+        if test x$gcc_no_link = xyes; then
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/sendfile.h>
+int
+main ()
+{
+sendfile(1, 2, (off_t*)NULL, sizeof 1);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  glibcxx_cv_sendfile=yes
+else
+  glibcxx_cv_sendfile=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/sendfile.h>
+int
+main ()
+{
+sendfile(1, 2, (off_t*)NULL, sizeof 1);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  glibcxx_cv_sendfile=yes
+else
+  glibcxx_cv_sendfile=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+        ;;
+      *)
+        glibcxx_cv_sendfile=no
+        ;;
+    esac
+
+fi
+
+  if test $glibcxx_cv_sendfile = yes; then
+
+$as_echo "#define _GLIBCXX_USE_SENDFILE 1" >>confdefs.h
+
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_sendfile" >&5
+$as_echo "$glibcxx_cv_sendfile" >&6; }
   CXXFLAGS="$ac_save_CXXFLAGS"
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
index aa1ab048c70b0620141b57b64655d5fed1464af1..f24cc19f1efddd4f519676bd3c78bf8f9d526919 100644 (file)
@@ -41,7 +41,7 @@
 #ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
 # include <sys/statvfs.h>
 #endif
-#ifdef _GLIBCXX_HAVE_GNU_SENDFILE
+#ifdef _GLIBCXX_USE_SENDFILE
 # include <sys/sendfile.h>
 #else
 # include <ext/stdio_filebuf.h>
@@ -241,6 +241,8 @@ namespace
       }
     f = make_file_status(*from_st);
 
+    using opts = fs::copy_options;
+
     if (exists(t))
       {
        if (!is_other(t) && !is_other(f)
@@ -251,12 +253,12 @@ namespace
            return false;
          }
 
-       if (is_set(option, fs::copy_options::skip_existing))
+       if (is_set(option, opts::skip_existing))
          {
            ec.clear();
            return false;
          }
-       else if (is_set(option, fs::copy_options::update_existing))
+       else if (is_set(option, opts::update_existing))
          {
            if (file_time(*from_st) <= file_time(*to_st))
              {
@@ -264,7 +266,7 @@ namespace
                return false;
              }
          }
-       else if (!is_set(option, fs::copy_options::overwrite_existing))
+       else if (!is_set(option, opts::overwrite_existing))
          {
            ec = std::make_error_code(std::errc::file_exists);
            return false;
@@ -282,14 +284,22 @@ namespace
        ec.assign(errno, std::generic_category());
        return false;
       }
-    CloseFD out = { ::open(to.c_str(), O_WRONLY|O_CREAT) };
+    int oflag = O_WRONLY|O_CREAT;
+    if (is_set(option, opts::overwrite_existing|opts::update_existing))
+      oflag |= O_TRUNC;
+    else
+      oflag |= O_EXCL;
+    CloseFD out = { ::open(to.c_str(), oflag, S_IWUSR) };
     if (out.fd == -1)
       {
-       ec.assign(errno, std::generic_category());
+       if (errno == EEXIST && is_set(option, opts::skip_existing))
+         ec.clear();
+       else
+         ec.assign(errno, std::generic_category());
        return false;
       }
 
-#ifdef _GLIBCXX_HAVE_GNU_SENDFILE
+#ifdef _GLIBCXX_USE_SENDFILE
     auto n = ::sendfile(out.fd, in.fd, nullptr, from_st->st_size);
     if (n != from_st->st_size)
       {
@@ -299,20 +309,17 @@ namespace
 #else
     __gnu_cxx::stdio_filebuf<char> sbin(in.fd, std::ios::in);
     __gnu_cxx::stdio_filebuf<char> sbout(out.fd, std::ios::out);
-    if (std::ostream(&sbout) << &sbin)
-      {
-       ec.clear();
-       return true;
-      }
-    else
+    if ( !(std::ostream(&sbout) << &sbin) )
       {
        ec = std::make_error_code(std::errc::io_error);
        return false;
       }
 #endif
 
-#ifdef _GLIBCXX_HAVE_FCHMOD
+#ifdef _GLIBCXX_USE_FCHMOD
     if (::fchmod(out.fd, from_st->st_mode))
+#elif _GLIBCXX_USE_FCHMODAT
+    if (::fchmodat(AT_FDCWD, to.c_str(), from_st->st_mode, 0))
 #else
     if (::chmod(to.c_str(), from_st->st_mode))
 #endif
@@ -320,6 +327,7 @@ namespace
        ec.assign(errno, std::generic_category());
        return false;
       }
+    ec.clear();
     return true;
   }
 }
@@ -715,8 +723,8 @@ void
 fs::current_path(const path& p, error_code& ec) noexcept
 {
 #ifdef _GLIBCXX_HAVE_UNISTD_H
-  if (int err = ::chdir(p.c_str()))
-    ec.assign(err, std::generic_category());
+  if (::chdir(p.c_str()))
+    ec.assign(errno, std::generic_category());
   else
     ec.clear();
 #else
@@ -908,11 +916,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))
+  if (::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)))
+  if (::chmod(p.c_str(), static_cast<mode_t>(prms)))
 #endif
-    ec.assign(err, std::generic_category());
+    ec.assign(errno, std::generic_category());
   else
     ec.clear();
 }
@@ -1064,8 +1072,8 @@ fs::space(const path& p, error_code& ec) noexcept
   };
 #ifdef _GLIBCXX_HAVE_SYS_STATVFS_H
   struct ::statvfs f;
-  if (int err = ::statvfs(p.c_str(), &f))
-      ec.assign(err, std::generic_category());
+  if (::statvfs(p.c_str(), &f))
+      ec.assign(errno, std::generic_category());
   else
     {
       info = space_info{