summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2024-04-28 14:28:03 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2024-04-28 14:28:03 +0000
commit891358d20de03c388fb10d0148c4660261604dda (patch)
tree1ac0768f34c564815c7096278da22fcdbf9372fe /lib/libc
parentc2247d7ef89055fcaa31cc6422dbcfc00fd168f5 (diff)
__sfvwrite: allow writing buffers larger than BUFSIZ or st_blksize.
This can vastly improve write performance. For unbuffered writes, we now write up to INT_MAX instead of BUFSIZE. For buffered writes, write the largest multiple of the buffer size (which may be st_blksize). From Apple via enh at google. OK tb@
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/stdio/fvwrite.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/lib/libc/stdio/fvwrite.c b/lib/libc/stdio/fvwrite.c
index d83de884581..d615245abc2 100644
--- a/lib/libc/stdio/fvwrite.c
+++ b/lib/libc/stdio/fvwrite.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fvwrite.c,v 1.21 2023/10/06 16:41:02 millert Exp $ */
+/* $OpenBSD: fvwrite.c,v 1.22 2024/04/28 14:28:02 millert Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,6 +31,7 @@
* SUCH DAMAGE.
*/
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -76,11 +77,12 @@ __sfvwrite(FILE *fp, struct __suio *uio)
}
if (fp->_flags & __SNBF) {
/*
- * Unbuffered: write up to BUFSIZ bytes at a time.
+ * Unbuffered: write up to INT_MAX bytes at a time, to not
+ * truncate the value of len if it is greater than 2^31 bytes.
*/
do {
GETIOV(;);
- w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ));
+ w = (*fp->_write)(fp->_cookie, p, MIN(len, INT_MAX));
if (w <= 0)
goto err;
p += w;
@@ -90,7 +92,8 @@ __sfvwrite(FILE *fp, struct __suio *uio)
/*
* Fully buffered: fill partially full buffer, if any,
* and then flush. If there is no partial buffer, write
- * one _bf._size byte chunk directly (without copying).
+ * entire payload directly (without copying) up to a
+ * multiple of the buffer size.
*
* String output is a special case: write as many bytes
* as fit, but pretend we wrote everything. This makes
@@ -134,7 +137,15 @@ __sfvwrite(FILE *fp, struct __suio *uio)
if (__sflush(fp))
goto err;
} else if (len >= (w = fp->_bf._size)) {
- /* write directly */
+ /*
+ * Write directly up to INT_MAX or greatest
+ * multiple of buffer size (whichever is
+ * smaller), keeping in the memory buffer the
+ * remaining part of payload that is smaller
+ * than buffer size.
+ */
+ if (w != 0)
+ w = MIN(w * (len / w), INT_MAX);
w = (*fp->_write)(fp->_cookie, p, w);
if (w <= 0)
goto err;