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.
This commit is contained in:
parent
519b29c9e5
commit
2f6bbc9a7d
4 changed files with 133 additions and 18 deletions
|
@ -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
|
||||
])
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
66
libstdc++-v3/configure
vendored
66
libstdc++-v3/configure
vendored
|
@ -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'
|
||||
|
|
Loading…
Add table
Reference in a new issue