This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch draft] Fix libstdc++/8610


Hi!

So, here comes my first draft. Everything seems to work :), but I
encourage your feedback for refining it. For instance, perhaps I'm
being naive in checking if a value passed to 'lseek' doesn't
overflow off_t like this:

if (__off != static_cast<off_t>(__off))

???
It works, but probably we can do better...

Also, is it safe to assume that a libc making available lseek64
does also provide fopen64?

IMPORTANT: don't do my same error: if you want to try the patch on
the attached testcase or whatelse of your like, remember to set
appropriate 'ulimit -f' in the shell! For instance, my bash 2.0.5b
has only 1 Gigabyte, by default!

Paolo.

//////////
	* acinclude.m4 (GLIBCXX_CHECK_INT64_T): New macro,
	checking for the availability of int64_t.
	(GLIBCXX_CHECK_LSEEK64): New macro, checking for the
	availability of lseek64.
	* configure.ac: Call here.
	* acconfig.h: Add undef for the corresponding symbols.
	* config/io/basic_file_stdio.cc	(__basic_file<char>::open):
	Depending on GLIBCXX_CHECK_LSEEK64, call fopen64 or fopen.
	(__basic_file<char>::seekoff): Likewise, call lseek64 when
	available, otherwise lseek, checking the __off parameter.
	* include/bits/postypes.h: Typedef __streamoff_base_type
	to int64_t if available, otherwise long long.
	* aclocal.m4: Regenerate.
	* config.h.in: Likewise.
	* configure: Likewise.
diff -urN libstdc++-v3-orig/acconfig.h libstdc++-v3/acconfig.h
--- libstdc++-v3-orig/acconfig.h	2003-10-16 23:33:53.000000000 +0200
+++ libstdc++-v3/acconfig.h	2003-10-20 18:37:07.000000000 +0200
@@ -153,6 +153,12 @@
 // Define if writev is available in <sys/uio.h>.
 #undef HAVE_WRITEV
 
+// Define if int64_t is available in <stdint.h>.
+#undef HAVE_INT64_T
+
+// Define if lseek64 is available in <unistd.h>.
+#undef HAVE_LSEEK64
+
 // Define if LC_MESSAGES is available in <locale.h>.
 #undef HAVE_LC_MESSAGES
 
diff -urN libstdc++-v3-orig/acinclude.m4 libstdc++-v3/acinclude.m4
--- libstdc++-v3-orig/acinclude.m4	2003-10-17 00:51:36.000000000 +0200
+++ libstdc++-v3/acinclude.m4	2003-10-20 19:11:43.000000000 +0200
@@ -573,6 +573,40 @@
 
 
 dnl
+dnl Check whether int64_t is available in <stdint.h>, and define HAVE_INT64_T.
+dnl
+AC_DEFUN(GLIBCXX_CHECK_INT64_T, [
+  AC_CACHE_VAL(glibcxx_cv_INT64_T, [
+    AC_TRY_COMPILE(
+      [#include <stdint.h>],
+      [int64_t var;],
+      [glibcxx_cv_INT64_T=yes],
+      [glibcxx_cv_INT64_T=no])
+  ])
+  if test $glibcxx_cv_INT64_T = yes; then
+    AC_DEFINE(HAVE_INT64_T)
+  fi
+])
+
+
+dnl
+dnl Check whether lseek64 is available in <unistd.h>, and define HAVE_LSEEK64.
+dnl
+AC_DEFUN(GLIBCXX_CHECK_LSEEK64, [
+  AC_CACHE_VAL(glibcxx_cv_LSEEK64, [
+    AC_TRY_COMPILE(
+      [#include <unistd.h>],
+      [lseek64(1, 0, SEEK_CUR);],	
+      [glibcxx_cv_LSEEK64=yes],
+      [glibcxx_cv_LSEEK64=no])
+  ])
+  if test $glibcxx_cv_LSEEK64 = yes; then
+    AC_DEFINE(HAVE_LSEEK64)
+  fi
+])
+
+
+dnl
 dnl Does any necessary configuration of the testsuite directory.  Generates
 dnl the testsuite_hooks.h header.
 dnl
diff -urN libstdc++-v3-orig/config/io/basic_file_stdio.cc libstdc++-v3/config/io/basic_file_stdio.cc
--- libstdc++-v3-orig/config/io/basic_file_stdio.cc	2003-10-17 00:51:36.000000000 +0200
+++ libstdc++-v3/config/io/basic_file_stdio.cc	2003-10-20 23:37:03.000000000 +0200
@@ -173,7 +173,11 @@
 
     if (!this->is_open())
       {
+#ifdef _GLIBCXX_HAVE_LSEEK64
+	if ((_M_cfile = fopen64(__name, __c_mode)))
+#else
 	if ((_M_cfile = fopen(__name, __c_mode)))
+#endif
 	  {
 	    _M_cfile_created = true;
 	    __ret = this;
@@ -262,7 +266,15 @@
 
   streamoff
   __basic_file<char>::seekoff(streamoff __off, ios_base::seekdir __way)
-  { return lseek(this->fd(), __off, __way); }
+  {
+#ifdef _GLIBCXX_HAVE_LSEEK64
+    return lseek64(this->fd(), __off, __way);
+#else
+    if (__off != static_cast<off_t>(__off))
+      return -1L;
+    return lseek(this->fd(), __off, __way);
+#endif
+  }
 
   int 
   __basic_file<char>::sync() 
diff -urN libstdc++-v3-orig/configure.ac libstdc++-v3/configure.ac
--- libstdc++-v3-orig/configure.ac	2003-10-17 00:51:36.000000000 +0200
+++ libstdc++-v3/configure.ac	2003-10-20 18:51:21.000000000 +0200
@@ -134,6 +134,12 @@
   AC_CHECK_HEADERS(sys/uio.h)
   GLIBCXX_CHECK_WRITEV
 
+  # For the __streamoff_base_type typedef.
+  GLIBCXX_CHECK_INT64_T
+
+  # For lseek64 (aka, LFS support).
+  GLIBCXX_CHECK_LSEEK64
+
   AC_LC_MESSAGES
 
   AC_TRY_COMPILE(
diff -urN libstdc++-v3-orig/include/bits/postypes.h libstdc++-v3/include/bits/postypes.h
--- libstdc++-v3-orig/include/bits/postypes.h	2003-10-17 00:37:50.000000000 +0200
+++ libstdc++-v3/include/bits/postypes.h	2003-10-20 17:08:55.000000000 +0200
@@ -45,6 +45,10 @@
 
 #include <cwchar> // For mbstate_t
 
+#ifdef _GLIBCXX_HAVE_STDINT_H
+#include <stdint.h> // For int64_t
+#endif
+
 namespace std
 {
   // The types streamoff, streampos and wstreampos and the class
@@ -52,8 +56,14 @@
   // 27.2, 27.4.1, 27.4.3 and D.6. Despite all this verbage, the
   // behaviour of these types is mostly implementation defined or
   // unspecified. The behaviour in this implementation is as noted
-  // below.  
-  typedef long  	__streamoff_base_type;
+  // below.
+
+#ifdef _GLIBCXX_HAVE_INT64_T
+  typedef int64_t       __streamoff_base_type;
+#else
+  typedef long long     __streamoff_base_type;
+#endif
+
   typedef ptrdiff_t	streamsize; // Signed integral type
 
   template<typename _StateT>
#include <fstream>
#include <iostream>
#include <cassert>
#include <cstring>

#define TWO_GB 2147483648LL

int main()
{
  using namespace std;
  typedef filebuf::int_type 	int_type;
  typedef filebuf::pos_type 	pos_type;
  typedef filebuf::off_type 	off_type;

  basic_filebuf<char> fb;
  fb.open("test64.txt", ios_base::out | ios_base::in | ios_base::trunc);

  pos_type ret = fb.pubseekoff(TWO_GB+100, ios_base::beg);
  assert(ret != pos_type(off_type(-1)));

  fb.sputn("Strivi", 6);

  ret = fb.pubseekoff(0, ios_base::beg);
  ret = fb.pubseekoff(TWO_GB+100, ios_base::beg);
  assert(ret != pos_type(off_type(-1)));

  char arr[7] = "xxxxxx";
  streamsize size = fb.sgetn(arr, 6);
  assert(size == 6);
  assert(memcmp("Strivi", arr, 6) == 0);

  fb.close();
}
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]