From a0c4531ccf06e9381083421e9e7c2bdf89aa7f13 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 14 May 2015 14:23:14 +0100 Subject: [PATCH] re PR libstdc++/66011 (call to '__open_missing_mode' declared with attribute error) 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 | 10 +++ libstdc++-v3/acinclude.m4 | 33 ++++++++ libstdc++-v3/config.h.in | 6 ++ libstdc++-v3/configure | 119 +++++++++++++++++++++++++++++ libstdc++-v3/src/filesystem/ops.cc | 50 +++++++----- 5 files changed, 197 insertions(+), 21 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 000bcd56bca..4e38fbfe93f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,15 @@ 2015-05-14 Jonathan Wakely + 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. diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index b2b48cc2944..8340572984d 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -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 ], + [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 .]) + 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 .]) 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 ], + [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 .]) + fi + AC_MSG_RESULT($glibcxx_cv_sendfile) dnl CXXFLAGS="$ac_save_CXXFLAGS" AC_LANG_RESTORE diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index b833c811c51..337f61440a9 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -836,6 +836,9 @@ this host. */ #undef _GLIBCXX_USE_DECIMAL_FLOAT +/* Define if fchmod is available in . */ +#undef _GLIBCXX_USE_FCHMOD + /* Define if fchmodat is available in . */ #undef _GLIBCXX_USE_FCHMODAT @@ -885,6 +888,9 @@ /* Define if _SC_NPROC_ONLN is available in . */ #undef _GLIBCXX_USE_SC_NPROC_ONLN +/* Define if sendfile is available in . */ +#undef _GLIBCXX_USE_SENDFILE + /* Define if struct stat has timespec members. */ #undef _GLIBCXX_USE_ST_MTIM diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index d30cd188b4e..3654b68f281 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -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 +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 +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 +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 +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' diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc index aa1ab048c70..f24cc19f1ef 100644 --- a/libstdc++-v3/src/filesystem/ops.cc +++ b/libstdc++-v3/src/filesystem/ops.cc @@ -41,7 +41,7 @@ #ifdef _GLIBCXX_HAVE_SYS_STATVFS_H # include #endif -#ifdef _GLIBCXX_HAVE_GNU_SENDFILE +#ifdef _GLIBCXX_USE_SENDFILE # include #else # include @@ -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 sbin(in.fd, std::ios::in); __gnu_cxx::stdio_filebuf 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(prms), 0)) + if (::fchmodat(AT_FDCWD, p.c_str(), static_cast(prms), 0)) #else - if (int err = ::chmod(p.c_str(), static_cast(prms))) + if (::chmod(p.c_str(), static_cast(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{ -- 2.30.2