From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id 99EB63857031; Tue, 18 Jul 2023 11:00:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 99EB63857031 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1689678054; bh=VwHBIOT8B5eTrRxh1yMTvm1F/lMAkDgENRHUSm/ik5Q=; h=From:To:Subject:Date:From; b=PWa+RBro1bRYh3TLY73M9OBIS+dFHKgPZ6SGq/sJnLackI5bH58vq7gqxNBffnk8F YBT/DBnkSYwuJQ9eAwUNsoW4DngbB04DcL/y6BrVAUO6JHVYMGTmCG86TKHdwrENIT 1GhDzTkmbU2q/pnYE71VQz+sdw2dn7m9hbTm8B4Q= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r13-7578] libstdc++: Fix --enable-cstdio=stdio_pure [PR110574] X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/releases/gcc-13 X-Git-Oldrev: c9da749155fef64777e186558cbdd5d5c7e7d474 X-Git-Newrev: 5342e3cc446d9ba0017c167aa3ff9d3c08c11f0f Message-Id: <20230718110054.99EB63857031@sourceware.org> Date: Tue, 18 Jul 2023 11:00:54 +0000 (GMT) List-Id: https://gcc.gnu.org/g:5342e3cc446d9ba0017c167aa3ff9d3c08c11f0f commit r13-7578-g5342e3cc446d9ba0017c167aa3ff9d3c08c11f0f Author: Jonathan Wakely Date: Thu Jul 6 17:10:41 2023 +0100 libstdc++: Fix --enable-cstdio=stdio_pure [PR110574] When configured with --enable-cstdio=stdio_pure we need to consistently use fseek and not mix seeks on the file descriptor with reads and writes on the FILE stream. There are also a number of bugs related to error handling and return values, because fread and fwrite return 0 on error, not -1, and fseek returns 0 on success, not the file offset. libstdc++-v3/ChangeLog: PR libstdc++/110574 * acinclude.m4 (GLIBCXX_CHECK_LFS): Check for fseeko and ftello and define _GLIBCXX_USE_FSEEKO_FTELLO. * config.h.in: Regenerate. * configure: Regenerate. * config/io/basic_file_stdio.cc (xwrite) [_GLIBCXX_USE_STDIO_PURE]: Check for fwrite error correctly. (__basic_file::xsgetn) [_GLIBCXX_USE_STDIO_PURE]: Check for fread error correctly. (get_file_offset): New function. (__basic_file::seekoff) [_GLIBCXX_USE_STDIO_PURE]: Use fseeko if available. Use get_file_offset instead of return value of fseek. (__basic_file::showmanyc): Use get_file_offset. (cherry picked from commit 2f6bbc9a7d9a62423c576e13dc46323fe16ba5aa) Diff: --- libstdc++-v3/acinclude.m4 | 16 ++++++++ libstdc++-v3/config.h.in | 3 ++ libstdc++-v3/config/io/basic_file_stdio.cc | 66 ++++++++++++++++++++++-------- libstdc++-v3/configure | 66 ++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 18 deletions(-) diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index 4adf23a771d..c2977e4c375 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -497,6 +497,22 @@ AC_DEFUN([GLIBCXX_CHECK_LFS], [ if test $glibcxx_cv_LFS = yes; then AC_DEFINE(_GLIBCXX_USE_LFS, 1, [Define if LFS support is available.]) fi + + AC_CACHE_CHECK([for fseeko and ftello], glibcxx_cv_posix_lfs, [ + GCC_TRY_COMPILE_OR_LINK( + [#include + ], + [FILE* fp; + fseeko(fp, 0, SEEK_CUR); + ftello(fp); + ], + [glibcxx_cv_posix_lfs=yes], + [glibcxx_cv_posix_lfs=no]) + ]) + if test $glibcxx_cv_posix_lfs = yes; then + AC_DEFINE(_GLIBCXX_USE_FSEEKO_FTELLO, 1, [Define if fseeko and ftello are available.]) + fi + CXXFLAGS="$ac_save_CXXFLAGS" AC_LANG_RESTORE ]) diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index 86c8eeef8ac..047dcc4f1dd 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -949,6 +949,9 @@ /* Define if fchmodat is available in . */ #undef _GLIBCXX_USE_FCHMODAT +/* Define if fseeko and ftello are available. */ +#undef _GLIBCXX_USE_FSEEKO_FTELLO + /* Defined if gettimeofday is available. */ #undef _GLIBCXX_USE_GETTIMEOFDAY diff --git a/libstdc++-v3/config/io/basic_file_stdio.cc b/libstdc++-v3/config/io/basic_file_stdio.cc index 7de9d98c3c7..27c2ad2afe3 100644 --- a/libstdc++-v3/config/io/basic_file_stdio.cc +++ b/libstdc++-v3/config/io/basic_file_stdio.cc @@ -129,14 +129,15 @@ namespace { #ifdef _GLIBCXX_USE_STDIO_PURE const std::streamsize __ret = fwrite(__s, 1, __nleft, __file); + if (__ret == 0 && ferror(__file)) + break; #else const std::streamsize __ret = write(__fd, __s, __nleft); -#endif if (__ret == -1L && errno == EINTR) continue; if (__ret == -1L) break; - +#endif __nleft -= __ret; if (__nleft == 0) break; @@ -330,13 +331,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __basic_file::xsgetn(char* __s, streamsize __n) { streamsize __ret; - do #ifdef _GLIBCXX_USE_STDIO_PURE - __ret = fread(__s, 1, __n, this->file()); + __ret = fread(__s, 1, __n, this->file()); + if (__ret == 0 && ferror(this->file())) + __ret = -1; #else + do __ret = read(this->fd(), __s, __n); -#endif while (__ret == -1L && errno == EINTR); +#endif return __ret; } @@ -375,20 +378,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __ret; } + namespace + { + inline streamoff + get_file_offset(__basic_file* __f) + { +#ifdef _GLIBCXX_USE_STDIO_PURE +# ifdef _GLIBCXX_USE_FSEEKO_FTELLO + return ftello(__f->file()); +# else + return ftell(__f->file()); +# endif +#elif defined(_GLIBCXX_USE_LFS) + return lseek64(__f->fd(), 0, (int)ios_base::cur); +#else + return lseek(__f->fd(), 0, (int)ios_base::cur); +#endif + } + } + streamoff __basic_file::seekoff(streamoff __off, ios_base::seekdir __way) throw () { -#ifdef _GLIBCXX_USE_LFS +#ifdef _GLIBCXX_USE_STDIO_PURE +#ifdef _GLIBCXX_USE_FSEEKO_FTELLO + if _GLIBCXX17_CONSTEXPR (sizeof(off_t) > sizeof(long)) + { + if (fseeko(this->file(), __off, __way)) + return -1; + } + else +#endif + { + if (__off > numeric_limits::max() + || __off < numeric_limits::min()) + return -1; + if (fseek(this->file(), __off, __way)) + return -1; + } + return __way == ios_base::beg ? __off : std::get_file_offset(this); +#elif defined(_GLIBCXX_USE_LFS) return lseek64(this->fd(), __off, __way); #else if (__off > numeric_limits::max() - || __off < numeric_limits::min()) + || __off < numeric_limits::min()) return -1L; -#ifdef _GLIBCXX_USE_STDIO_PURE - return fseek(this->file(), __off, __way); -#else return lseek(this->fd(), __off, __way); -#endif #endif } @@ -425,19 +460,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const int __err = fstat64(this->fd(), &__buffer); if (!__err && _GLIBCXX_ISREG(__buffer.st_mode)) { - const streamoff __off = __buffer.st_size - lseek64(this->fd(), 0, - ios_base::cur); + const streamoff __off = __buffer.st_size - std::get_file_offset(this); return std::min(__off, streamoff(numeric_limits::max())); } #else struct stat __buffer; const int __err = fstat(this->fd(), &__buffer); if (!__err && _GLIBCXX_ISREG(__buffer.st_mode)) -#ifdef _GLIBCXX_USE_STDIO_PURE - return __buffer.st_size - fseek(this->file(), 0, ios_base::cur); -#else - return __buffer.st_size - lseek(this->fd(), 0, ios_base::cur); -#endif + return __buffer.st_size - std::get_file_offset(this); #endif #endif return 0; diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 02a931cd096..5339834b875 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -19363,6 +19363,72 @@ $as_echo "$glibcxx_cv_LFS" >&6; } $as_echo "#define _GLIBCXX_USE_LFS 1" >>confdefs.h fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fseeko and ftello" >&5 +$as_echo_n "checking for fseeko and ftello... " >&6; } +if ${glibcxx_cv_posix_lfs+:} 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 + +int +main () +{ +FILE* fp; + fseeko(fp, 0, SEEK_CUR); + ftello(fp); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + glibcxx_cv_posix_lfs=yes +else + glibcxx_cv_posix_lfs=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 () +{ +FILE* fp; + fseeko(fp, 0, SEEK_CUR); + ftello(fp); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + glibcxx_cv_posix_lfs=yes +else + glibcxx_cv_posix_lfs=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_posix_lfs" >&5 +$as_echo "$glibcxx_cv_posix_lfs" >&6; } + if test $glibcxx_cv_posix_lfs = yes; then + +$as_echo "#define _GLIBCXX_USE_FSEEKO_FTELLO 1" >>confdefs.h + + fi + CXXFLAGS="$ac_save_CXXFLAGS" ac_ext=c ac_cpp='$CPP $CPPFLAGS'