[PATCH] Do not break buffers in fvwrite for unbuffered files

Federico Terraneo fede.tft@hotmail.it
Fri Nov 1 09:39:00 GMT 2013

Hash: SHA1

On 10/31/2013 03:41 PM, Corinna Vinschen wrote:
> On Oct 31 12:55, Federico Terraneo wrote:
>> This can't happen, since there's an
>> else if (fp->_p > fp->_bf._base || len < fp->_bf._size)
>> that catches this case and fills the file buffer instead.
> Oh, hmm.  I didn't notice the || in the if clause.  Doesn't that
> mean that the last else branch is never used since there's always a
> buffer at _bf._base?  The fact that we use a FILE buffer is now
> sufficient to use it and never to write directly, AFAICS.

Not exactly. The

if (fp->_p > fp->_bf._base

isn't true if there's a buffer. It's true if there is at least a
character in the buffer, fp->_p is the 'put pointer'.

The rationale is this: when shall we pass through the buffer? When we
are asked to write less than fp->_bf._size (to write in large chunks and
optimize performance), or when there's at least one character in the
buffer (to preserve the order of written data we can't just forget about
eventual data lying in the buffer)

Consider the following case, assuming fp->_bf._size=1024:

FILE *f=...
char buf1[16];
char buf2[32768];

The first fwrite goes through the buffer beacuse of its small size (len
< fp->_bf._size is true). The buffer now holds 16 char.

The second fwrite does three iterations:
- - first, since fp->_p > fp->_bf._base is true the buffer is filled with
  the remaining 1024-16 char and flushed as the first 16 char have to
  be written first.
- - the size of the data to write is now 32768-(1024-16)=31760, but
  fp->_p > fp->_bf._base is now false due to the fflush. We now write
  31744 (31KBytes, 31760/1024*1024) directly without passing through
  the buffer.
- - lastly, we are left with another 16 char to write, the difference
  between 31760 and 31744, and those will be put in the buffer.

Attached is a patch with the requested changes in the previous mail.

Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

-------------- next part --------------
A non-text attachment was scrubbed...
Name: fvwrite.patch
Type: text/x-patch
Size: 1763 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/newlib/attachments/20131101/17ad39d0/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: fvwrite.patch.sig
Type: application/octet-stream
Size: 287 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/newlib/attachments/20131101/17ad39d0/attachment.obj>

More information about the Newlib mailing list