diff options
Diffstat (limited to 'newlib/libc')
-rw-r--r-- | newlib/libc/stdio/fvwrite.c | 27 |
1 files changed, 12 insertions, 15 deletions
diff --git a/newlib/libc/stdio/fvwrite.c b/newlib/libc/stdio/fvwrite.c index 36a467845..455666006 100644 --- a/newlib/libc/stdio/fvwrite.c +++ b/newlib/libc/stdio/fvwrite.c @@ -21,6 +21,7 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#include <limits.h> #include "local.h" #include "fvwrite.h" @@ -89,12 +90,14 @@ _DEFUN(__sfvwrite_r, (ptr, fp, uio), if (fp->_flags & __SNBF) { /* - * Unbuffered: write up to BUFSIZ bytes at a time. + * Unbuffered: Split buffer in the largest multiple of BUFSIZ < INT_MAX + * as some legacy code may expect int instead of size_t. */ do { GETIOV (;); - w = fp->_write (ptr, fp->_cookie, p, MIN (len, BUFSIZ)); + w = fp->_write (ptr, fp->_cookie, p, + MIN (len, INT_MAX - INT_MAX % BUFSIZ)); if (w <= 0) goto err; p += w; @@ -177,30 +180,24 @@ _DEFUN(__sfvwrite_r, (ptr, fp, uio), fp->_p += w; w = len; /* but pretend copied all */ } - else if (fp->_p > fp->_bf._base && len > w) + else if (fp->_p > fp->_bf._base || len < fp->_bf._size) { - /* fill and flush */ + /* pass through the buffer */ + w = MIN (len, w); COPY (w); - /* fp->_w -= w; *//* unneeded */ + fp->_w -= w; fp->_p += w; - if (_fflush_r (ptr, fp)) + if (fp->_w == 0 && _fflush_r (ptr, fp)) goto err; } - else if (len >= (w = fp->_bf._size)) + else { /* write directly */ + w = ((int)MIN (len, INT_MAX)) / fp->_bf._size * fp->_bf._size; w = fp->_write (ptr, fp->_cookie, p, w); if (w <= 0) goto err; } - else - { - /* fill and done */ - w = len; - COPY (w); - fp->_w -= w; - fp->_p += w; - } p += w; len -= w; } |