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

[PATCH v1.1][BZ #15362] Correctly return bytes written out in _IO_new_file_write


On Fri, Apr 12, 2013 at 01:35:39PM +0530, Siddhesh Poyarekar wrote:
> Hi,
> 
> In my fix to pr#11741 I was overzealous about forwarding a failed
> write syscall and ignored an important case.
>     
> I overlooked the possibility of there having been a previous
> successful partial write and hence returned a failure when it
> shouldn't.  Attached patch causes _IO_new_file_write to return a short
> write if such a situation occurs and return a complete failure only if
> nothing was written to file in this function.
> 
> I also made an additional change in _IO_new_file_xsputn to explicitly
> return failure if new_do_write returns a failure.  I had relied on an
> ugly hack (n == to_do and adding 1 to to_do as a result of an error
> results in n - to_do == -1, hence returning error), which is wrong.
> 
> Tested on x86_64 to verify that the fix works for the reproducer
> mentioned in the bug report.  I have also verified that this patch
> does not cause regressions in the testsuite.
> 

I missed a subtle detail - count is _IO_size_t and it should be
_IO_ssize_t to make the (count < 0) work.  Also, we return EOF and not
-1.  Updated patch.

Siddhesh

	[BZ #15362]
	* libio/fileops.c (_IO_new_file_write): Correctly return short
	write.
	(_IO_new_file_xsputn): Explicitly return EOF on write error.


diff --git a/libio/fileops.c b/libio/fileops.c
index 61b61b3..96a62e0 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -1263,7 +1263,17 @@ _IO_new_file_write (f, data, n)
   n -= to_do;
   if (f->_offset >= 0)
     f->_offset += n;
-  return count < 0 ? count : n;
+
+  /* The last syscall resulted in an error, but we did succeed in writing some
+     bits.  Send back a short write and let them try again if needed.  */
+  if (count < 0 && n > 0)
+    return n;
+
+  /* We didn't succeed in writing anything.  */
+  if (count < 0)
+    return count;
+
+  return n;
 }
 
 _IO_size_t
@@ -1275,7 +1285,7 @@ _IO_new_file_xsputn (f, data, n)
   register const char *s = (const char *) data;
   _IO_size_t to_do = n;
   int must_flush = 0;
-  _IO_size_t count = 0;
+  _IO_ssize_t count = 0;
 
   if (n <= 0)
     return 0;
@@ -1336,6 +1346,10 @@ _IO_new_file_xsputn (f, data, n)
       if (do_write)
 	{
 	  count = new_do_write (f, s, do_write);
+
+	  if (count < 0)
+	    return EOF;
+
 	  to_do -= count;
 	  if (count < do_write)
 	    return n - to_do;


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