* libc/stdio/fflush.c (_fflush_r): Store old errno to check for

low-level seek error condition.  Restore old errno in case of
	success.  Don't use new position after seek as error condition,
	rather check for return value of -1 and errno.  Handle EINVAL
	just like ESPIPE.  Only set fp->_offset if errno is 0.
This commit is contained in:
Corinna Vinschen 2009-10-30 08:26:41 +00:00
parent c16cd85665
commit dc3d6d9093
2 changed files with 29 additions and 10 deletions

View File

@ -1,3 +1,11 @@
2009-10-30 Corinna Vinschen <corinna@vinschen.de>
* libc/stdio/fflush.c (_fflush_r): Store old errno to check for
low-level seek error condition. Restore old errno in case of
success. Don't use new position after seek as error condition,
rather check for return value of -1 and errno. Handle EINVAL
just like ESPIPE. Only set fp->_offset if errno is 0.
2009-10-27 Nick Clifton <nickc@redhat.com> 2009-10-27 Nick Clifton <nickc@redhat.com>
* MAINTAINERS (ARM): Add myself as an ARM maintainer. * MAINTAINERS (ARM): Add myself as an ARM maintainer.

View File

@ -115,31 +115,39 @@ _DEFUN(_fflush_r, (ptr, fp),
to miss a code scenario. */ to miss a code scenario. */
if ((fp->_r > 0 || fp->_ur > 0) && fp->_seek != NULL) if ((fp->_r > 0 || fp->_ur > 0) && fp->_seek != NULL)
{ {
int tmp; int tmp_errno;
#ifdef __LARGE64_FILES #ifdef __LARGE64_FILES
_fpos64_t curoff; _fpos64_t curoff;
#else #else
_fpos_t curoff; _fpos_t curoff;
#endif #endif
/* Save last errno and set errno to 0, so we can check if a device
returns with a valid position -1. We restore the last errno if
no other error condition has been encountered. */
tmp_errno = ptr->_errno;
ptr->_errno = 0;
/* Get the physical position we are at in the file. */ /* Get the physical position we are at in the file. */
if (fp->_flags & __SOFF) if (fp->_flags & __SOFF)
curoff = fp->_offset; curoff = fp->_offset;
else else
{ {
/* We don't know current physical offset, so ask for it. /* We don't know current physical offset, so ask for it.
Only ESPIPE is ignorable. */ Only ESPIPE and EINVAL are ignorable. */
#ifdef __LARGE64_FILES #ifdef __LARGE64_FILES
if (fp->_flags & __SL64) if (fp->_flags & __SL64)
curoff = fp->_seek64 (ptr, fp->_cookie, 0, SEEK_CUR); curoff = fp->_seek64 (ptr, fp->_cookie, 0, SEEK_CUR);
else else
#endif #endif
curoff = fp->_seek (ptr, fp->_cookie, 0, SEEK_CUR); curoff = fp->_seek (ptr, fp->_cookie, 0, SEEK_CUR);
if (curoff == -1L) if (curoff == -1L && ptr->_errno != 0)
{ {
int result = EOF; int result = EOF;
if (ptr->_errno == ESPIPE) if (ptr->_errno == ESPIPE || ptr->_errno == EINVAL)
result = 0; {
result = 0;
ptr->_errno = tmp_errno;
}
else else
fp->_flags |= __SERR; fp->_flags |= __SERR;
_funlockfile (fp); _funlockfile (fp);
@ -157,18 +165,21 @@ _DEFUN(_fflush_r, (ptr, fp),
/* Now physically seek to after byte last read. */ /* Now physically seek to after byte last read. */
#ifdef __LARGE64_FILES #ifdef __LARGE64_FILES
if (fp->_flags & __SL64) if (fp->_flags & __SL64)
tmp = (fp->_seek64 (ptr, fp->_cookie, curoff, SEEK_SET) == curoff); curoff = fp->_seek64 (ptr, fp->_cookie, curoff, SEEK_SET);
else else
#endif #endif
tmp = (fp->_seek (ptr, fp->_cookie, curoff, SEEK_SET) == curoff); curoff = fp->_seek (ptr, fp->_cookie, curoff, SEEK_SET);
if (tmp) if (curoff != -1 || ptr->_errno == 0
|| ptr->_errno == ESPIPE || ptr->_errno == EINVAL)
{ {
/* Seek successful. We can clear read buffer now. */ /* Seek successful or ignorable error condition.
We can clear read buffer now. */
fp->_flags &= ~__SNPT; fp->_flags &= ~__SNPT;
fp->_r = 0; fp->_r = 0;
fp->_p = fp->_bf._base; fp->_p = fp->_bf._base;
if (fp->_flags & __SOFF) if ((fp->_flags & __SOFF) && (curoff != -1 || ptr->_errno == 0))
fp->_offset = curoff; fp->_offset = curoff;
ptr->_errno = tmp_errno;
if (HASUB (fp)) if (HASUB (fp))
FREEUB (ptr, fp); FREEUB (ptr, fp);
} }