This is the mail archive of the newlib@sourceware.org mailing list for the newlib 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]

Re: [PATCH/RFA] _fflush_r check seek result fix


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.


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);
 	    }


-- 
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat


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