This option directs the library to only use simple stdio APIs instead
of using fileno to get the file descriptor for use with POSIX APIs.

Signed-off-by: Keith Packard <kei...@keithp.com>
---
 libstdc++-v3/ChangeLog                     | 13 ++++++
 libstdc++-v3/acinclude.m4                  | 13 ++++++
 libstdc++-v3/config/io/basic_file_stdio.cc | 46 +++++++++++++++++++---
 libstdc++-v3/configure.ac                  |  1 +
 4 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index d3ee18ed7d1..7f6b0697534 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1147,6 +1147,19 @@
        * include/bits/uniform_int_dist.h (uniform_int_distribution::_S_nd):
        Use qualified-id to refer to static member functions.
 
+2020-11-04  Keith Packard  <kei...@keithp.com>
+
+       * acinclude.m4: Add GLIBCXX_ENABLE_PURE_STDIO for
+       --enable-libstdcxx-pure-stdio
+       * configure.ac: Use GLIBCXX_ENABLE_PURE_STDIO for
+       --enable-libstdcxx-pure-stdio
+       * configure: regenerate
+       * config.h.in: regenerate
+       * config/io/basic_file_stdio.cc: Add support for
+       _GLIBCXX_USE_PURE_STDIO. This makes libstdc++ use only defined
+       stdio entry points for all I/O operations, without direct calls to
+       underlying POSIX functions.
+
 2020-11-03  Jonathan Wakely  <jwak...@redhat.com>
 
        * include/std/syncstream: Include <bits/std_mutex.h>
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index fcd9ea3d23a..863695e68e7 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -2889,6 +2889,19 @@ AC_DEFUN([GLIBCXX_ENABLE_CSTDIO], [
 ])
 
 
+dnl
+dnl Check whether to use 'pure' stdio (no POSIX calls at all)
+dnl
+dnl Default is 'no'
+AC_DEFUN([GLIBCXX_ENABLE_PURE_STDIO], [
+  GLIBCXX_ENABLE(libstdcxx-pure-stdio,$1,,[use only stdio APIs])
+  if test $enable_libstdcxx_pure_stdio = yes; then
+    AC_DEFINE(_GLIBCXX_USE_PURE_STDIO, 1,
+              [Define to restrict code to stdio APIs.])
+  fi
+])
+
+
 dnl
 dnl Check for "unusual" flags to pass to the compiler while building.
 dnl
diff --git a/libstdc++-v3/config/io/basic_file_stdio.cc 
b/libstdc++-v3/config/io/basic_file_stdio.cc
index ba830fb9e97..d31da8497f4 100644
--- a/libstdc++-v3/config/io/basic_file_stdio.cc
+++ b/libstdc++-v3/config/io/basic_file_stdio.cc
@@ -111,13 +111,21 @@ namespace
 
   // Wrapper handling partial write.
   static std::streamsize
+#ifdef _GLIBCXX_USE_PURE_STDIO
+  xwrite(FILE *__file, const char* __s, std::streamsize __n)
+#else
   xwrite(int __fd, const char* __s, std::streamsize __n)
+#endif
   {
     std::streamsize __nleft = __n;
 
     for (;;)
       {
+#ifdef _GLIBCXX_USE_PURE_STDIO
+       const std::streamsize __ret = fwrite(__file, 1, __nleft, __file);
+#else
        const std::streamsize __ret = write(__fd, __s, __nleft);
+#endif
        if (__ret == -1L && errno == EINTR)
          continue;
        if (__ret == -1L)
@@ -133,7 +141,7 @@ namespace
     return __n - __nleft;
   }
 
-#ifdef _GLIBCXX_HAVE_WRITEV
+#if defined(_GLIBCXX_HAVE_WRITEV) && !defined(_GLIBCXX_USE_PURE_STDIO)
   // Wrapper handling partial writev.
   static std::streamsize
   xwritev(int __fd, const char* __s1, std::streamsize __n1,
@@ -286,9 +294,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __basic_file<char>::is_open() const throw ()
   { return _M_cfile != 0; }
 
+#ifndef _GLIBCCXX_USE_PURE_STDIO
   int
   __basic_file<char>::fd() throw ()
   { return fileno(_M_cfile); }
+#endif
 
   __c_file*
   __basic_file<char>::file() throw ()
@@ -315,28 +325,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
     streamsize __ret;
     do
+#ifdef _GLIBCXX_USE_PURE_STDIO
+      __ret = fread(__s, 1, __n, this->file());
+#else
       __ret = read(this->fd(), __s, __n);
+#endif
     while (__ret == -1L && errno == EINTR);
     return __ret;
   }
 
   streamsize
   __basic_file<char>::xsputn(const char* __s, streamsize __n)
-  { return xwrite(this->fd(), __s, __n); }
+  {
+#ifdef _GLIBCXX_USE_PURE_STDIO
+    return xwrite(this->file(), __s, __n);
+#else
+    return xwrite(this->fd(), __s, __n);
+#endif
+  }
 
   streamsize
   __basic_file<char>::xsputn_2(const char* __s1, streamsize __n1,
                               const char* __s2, streamsize __n2)
   {
     streamsize __ret = 0;
-#ifdef _GLIBCXX_HAVE_WRITEV
+#if defined(_GLIBCXX_HAVE_WRITEV) && !defined(_GLIBCXX_USE_PURE_STDIO)
     __ret = xwritev(this->fd(), __s1, __n1, __s2, __n2);
 #else
     if (__n1)
+#ifdef _GLIBCXX_USE_PURE_STDIO
+      __ret = xwrite(this->file(), __s1, __n1);
+#else
       __ret = xwrite(this->fd(), __s1, __n1);
+#endif
 
     if (__ret == __n1)
+#ifdef _GLIBCXX_USE_PURE_STDIO
+      __ret += xwrite(this->file(), __s2, __n2);
+#else
       __ret += xwrite(this->fd(), __s2, __n2);
+#endif
 #endif
     return __ret;
   }
@@ -350,7 +378,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     if (__off > numeric_limits<off_t>::max()
        || __off < numeric_limits<off_t>::min())
       return -1L;
+#ifdef _GLIBCXX_USE_PURE_STDIO
+    return fseek(this->file(), __off, __way);
+#else
     return lseek(this->fd(), __off, __way);
+#endif
 #endif
   }
 
@@ -361,7 +393,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   streamsize
   __basic_file<char>::showmanyc()
   {
-#ifndef _GLIBCXX_NO_IOCTL
+#if !defined(_GLIBCXX_NO_IOCTL) && !defined(_GLIBCXX_USE_PURE_STDIO)
 #ifdef FIONREAD
     // Pipes and sockets.
     int __num = 0;
@@ -371,7 +403,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 #endif
 
-#ifdef _GLIBCXX_HAVE_POLL
+#if defined(_GLIBCXX_HAVE_POLL) && !defined(_GLIBCXX_USE_PURE_STDIO)
     // Cheap test.
     struct pollfd __pfd[1];
     __pfd[0].fd = this->fd();
@@ -395,8 +427,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct stat __buffer;
     const int __err = fstat(this->fd(), &__buffer);
     if (!__err && _GLIBCXX_ISREG(__buffer.st_mode))
+#ifdef _GLIBCXX_USE_PURE_STDIO
+      return __buffer.st_size - fseek(this->file(), 0, ios_base::cur);
+#else
       return __buffer.st_size - lseek(this->fd(), 0, ios_base::cur);
 #endif
+#endif
 #endif
     return 0;
   }
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index cbfdf4c6bad..733154d070b 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -179,6 +179,7 @@ GLIBCXX_ENABLE_EXTERN_TEMPLATE([yes])
 GLIBCXX_ENABLE_PYTHON
 GLIBCXX_ENABLE_WERROR([no])
 GLIBCXX_ENABLE_VTABLE_VERIFY([no])
+GLIBCXX_ENABLE_PURE_STDIO
 
 # Checks for operating systems support that doesn't require linking.
 GLIBCXX_CHECK_STDIO_PROTO
-- 
2.29.2

Reply via email to