public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-2476] libstdc++: Fix --enable-cstdio=stdio_pure [PR110574]
@ 2023-07-12 20:04 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2023-07-12 20:04 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:2f6bbc9a7d9a62423c576e13dc46323fe16ba5aa

commit r14-2476-g2f6bbc9a7d9a62423c576e13dc46323fe16ba5aa
Author: Jonathan Wakely <jwakely@redhat.com>
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<char>::xsgetn) [_GLIBCXX_USE_STDIO_PURE]: Check for
            fread error correctly.
            (get_file_offset): New function.
            (__basic_file<char>::seekoff) [_GLIBCXX_USE_STDIO_PURE]: Use
            fseeko if available. Use get_file_offset instead of return value
            of fseek.
            (__basic_file<char>::showmanyc): Use get_file_offset.

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 823832f97d4..b25378eaace 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 <stdio.h>
+      ],
+      [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 91eca6ef608..1c2224c1919 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -988,6 +988,9 @@
 /* Define if fchmodat is available in <sys/stat.h>. */
 #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<char>::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<char>* __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<char>::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<long>::max()
+	      || __off < numeric_limits<long>::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<off_t>::max()
-	|| __off < numeric_limits<off_t>::min())
+	  || __off < numeric_limits<off_t>::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<streamsize>::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 c8d55083cd7..36f217c898c 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -19940,6 +19940,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 <stdio.h>
+
+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 <stdio.h>
+
+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'

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-07-12 20:04 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-12 20:04 [gcc r14-2476] libstdc++: Fix --enable-cstdio=stdio_pure [PR110574] Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).