[PATCH/RFA] _fflush_r check seek result fix
Jeff Johnston
jjohnstn@redhat.com
Thu Nov 5 17:10:00 GMT 2009
On 29/10/09 06:24 AM, Corinna Vinschen wrote:
> On Oct 28 11:56, Jeff Johnston wrote:
>> On 28/10/09 06:47 AM, Corinna Vinschen wrote:
>>> On Oct 28 11:06, Corinna Vinschen wrote:
>>>> * 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. Only seek to
>>>> positive offsets, explain why. Only set fp->_offset if errno
>>>> is not ESPIPE.
>>>
>>> There's a still a problem with this patch. Assuming the offset returned
>>> by the first seek on a regular file would result in a negative offset
>>> after fp->_r and fp->_ur have been subtracted, then the new position
>>> stored in fp->_offset will be incorrect. Therefore, the code must check
>>> for this condition before changing curoff. The below patch does this,
>>> so fp->_offset will not be set to an incorrect value.
>>>
>>> Alternatively, I'm wondering if it isn't easier to ignore the EINVAL
>>> condition in the second invocation of seek just like ESPIPE.
>>>
>>
>> I think you need to ignore the EINVAL regardless as it doesn't
>> indicate the seek had a failure as much as ESPIPE doesn't.
>
> Ok, no worries, but in that case it doesn't make sense to avoid offsets
> < 0. This case is sufficiently covered by checking for EINVAL. Patch
> below.
>
Looks fine. Feel free to commit.
-- Jeff J.
>
> Corinna
>
> * 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.
>
>
> Index: libc/stdio/fflush.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/fflush.c,v
> retrieving revision 1.14
> diff -u -p -r1.14 fflush.c
> --- libc/stdio/fflush.c 22 Jul 2009 02:17:12 -0000 1.14
> +++ libc/stdio/fflush.c 29 Oct 2009 10:23:28 -0000
> @@ -115,31 +115,39 @@ _DEFUN(_fflush_r, (ptr, fp),
> to miss a code scenario. */
> if ((fp->_r> 0 || fp->_ur> 0)&& fp->_seek != NULL)
> {
> - int tmp;
> + int tmp_errno;
> #ifdef __LARGE64_FILES
> _fpos64_t curoff;
> #else
> _fpos_t curoff;
> #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. */
> if (fp->_flags& __SOFF)
> curoff = fp->_offset;
> else
> {
> /* We don't know current physical offset, so ask for it.
> - Only ESPIPE is ignorable. */
> + Only ESPIPE and EINVAL are ignorable. */
> #ifdef __LARGE64_FILES
> if (fp->_flags& __SL64)
> curoff = fp->_seek64 (ptr, fp->_cookie, 0, SEEK_CUR);
> else
> #endif
> curoff = fp->_seek (ptr, fp->_cookie, 0, SEEK_CUR);
> - if (curoff == -1L)
> + if (curoff == -1L&& ptr->_errno != 0)
> {
> int result = EOF;
> - if (ptr->_errno == ESPIPE)
> - result = 0;
> + if (ptr->_errno == ESPIPE || ptr->_errno == EINVAL)
> + {
> + result = 0;
> + ptr->_errno = tmp_errno;
> + }
> else
> fp->_flags |= __SERR;
> _funlockfile (fp);
> @@ -157,18 +165,20 @@ _DEFUN(_fflush_r, (ptr, fp),
> /* Now physically seek to after byte last read. */
> #ifdef __LARGE64_FILES
> if (fp->_flags& __SL64)
> - tmp = (fp->_seek64 (ptr, fp->_cookie, curoff, SEEK_SET) == curoff);
> + curoff = fp->_seek64 (ptr, fp->_cookie, curoff, SEEK_SET);
> else
> #endif
> - tmp = (fp->_seek (ptr, fp->_cookie, curoff, SEEK_SET) == curoff);
> - if (tmp)
> + curoff = fp->_seek (ptr, fp->_cookie, curoff, SEEK_SET);
> + if (curoff != -1 || ptr->_errno == 0
> + || ptr->_errno == ESPIPE || ptr->_errno == EINVAL)
> {
> /* Seek successful. We can clear read buffer now. */
> fp->_flags&= ~__SNPT;
> fp->_r = 0;
> fp->_p = fp->_bf._base;
> - if (fp->_flags& __SOFF)
> + if ((fp->_flags& __SOFF)&& (curoff != -1 || ptr->_errno == 0))
> fp->_offset = curoff;
> + ptr->_errno = tmp_errno;
> if (HASUB (fp))
> FREEUB (ptr, fp);
> }
>
>
More information about the Newlib
mailing list