This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch draft] Fix libstdc++/8610
- From: Paolo Carlini <pcarlini at suse dot de>
- To: libstdc++ at gcc dot gnu dot org
- Cc: Benjamin Kosnik <bkoz at redhat dot com>
- Date: Tue, 21 Oct 2003 00:02:35 +0200
- Subject: [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();
}