X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/9385eb3d10ebe5eb398c52040ec3dbfba9b0cdcf..refs/heads/master:/stdio/FreeBSD/makebuf.c diff --git a/stdio/FreeBSD/makebuf.c b/stdio/FreeBSD/makebuf.c index a4c5c36..a472776 100644 --- a/stdio/FreeBSD/makebuf.c +++ b/stdio/FreeBSD/makebuf.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -38,7 +36,7 @@ static char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD: src/lib/libc/stdio/makebuf.c,v 1.4 2002/03/22 21:53:04 obrien Exp $"); +__FBSDID("$FreeBSD$"); #include "namespace.h" #include @@ -46,9 +44,120 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/makebuf.c,v 1.4 2002/03/22 21:53:04 obrie #include #include #include -#include "local.h" #include "un-namespace.h" +#include "libc_private.h" +#include "local.h" +#include +#include +#include + +#ifdef FEATURE_SMALL_STDIOBUF +# define MAXBUFSIZE (1 << 12) +#else +# define MAXBUFSIZE (1 << 16) +#endif + +#define TTYBUFSIZE 4096 +#define MAXEVPSIZE 16 + +static char __fallback_evp[MAXEVPSIZE]; +static char __stdout_evp[MAXEVPSIZE]; + +static void +__loadevp(const char* key, char destination[MAXEVPSIZE]) +{ + char* evp = getenv(key); + if (evp != NULL) { + strlcpy(destination, evp, MAXEVPSIZE); + } else { + destination[0] = '\0'; + } +} + +static void +__evpinit(void* __unused unused) +{ + __loadevp("STDBUF", __fallback_evp); + __loadevp("STDBUF1", __stdout_evp); +} + +static char* +__getevp(int fd) +{ + static os_once_t predicate; + os_once(&predicate, NULL, __evpinit); + + if (fd == STDOUT_FILENO && __stdout_evp[0] != '\0') { + return __stdout_evp; + } else if (__fallback_evp[0] != '\0') { + return __fallback_evp; + } else { + return NULL; + } + +} + +/* + * Internal routine to determine environment override buffering for a file. + * + * Sections of the below taken from NetBSD's version of this file under the same license. + */ +static int +__senvbuf(FILE *fp, size_t *bufsize, int *couldbetty) +{ + char* evp; + char* end; + int flags; + long size; + + flags = 0; // Default to fully buffered + + if ((evp = __getevp(fp->_file)) == NULL) { + return flags; + } + + // Look at the first character only to determine buffering mode + switch (*evp) { + case 'u': + case 'U': + flags |= __SNBF; + break; + case 'l': + case 'L': + flags |= __SLBF; + break; + case 'f': + case 'F': + // Default flags is fully buffered + break; + default: + // Unexpected buffering mode, use default fully buffered + return flags; + } + // User specified envrionment defaults have higher priority than tty defaults + *couldbetty = 0; + + // Advance the envrionment variable pointer, so we can attempt to parse the number + evp++; + if (!isdigit(*evp)) { + return flags; // No number found, this protects us from negative size values + } + + size = strtol_l(evp, &end, 10, LC_C_LOCALE); + if (*end != '\0') { + return flags; + } + + if (size <= 0) { + return __SNBF; // Override with unbuffered if the buffer size is 0 + } + + // We had a non zero buffer, cap it and return the flags; + *bufsize = size > MAXBUFSIZE ? MAXBUFSIZE : size; + return flags; +} + /* * Allocate a file buffer, or switch to unbuffered I/O. * Per the ANSI C standard, ALL tty devices default to line buffered. @@ -57,8 +166,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/makebuf.c,v 1.4 2002/03/22 21:53:04 obrie * optimisation) right after the _fstat() that finds the buffer size. */ void -__smakebuf(fp) - FILE *fp; +__smakebuf(FILE *fp) { void *p; int flags; @@ -71,6 +179,23 @@ __smakebuf(fp) return; } flags = __swhatbuf(fp, &size, &couldbetty); + if (fp->_file >= 0) { + flags |= __senvbuf(fp, &size, &couldbetty); + + if (flags & __SNBF) { + fp->_flags |= __SNBF; + fp->_bf._base = fp->_p = fp->_nbuf; + fp->_bf._size = 1; + return; + } + } + + if (couldbetty && isatty(fp->_file)) { + flags |= __SLBF; + /* st_blksize for ttys is 128K, so make it more reasonable */ + if (size > TTYBUFSIZE) + fp->_blksize = size = TTYBUFSIZE; + } if ((p = malloc(size)) == NULL) { fp->_flags |= __SNBF; fp->_bf._base = fp->_p = fp->_nbuf; @@ -81,8 +206,6 @@ __smakebuf(fp) flags |= __SMBF; fp->_bf._base = fp->_p = p; fp->_bf._size = size; - if (couldbetty && isatty(fp->_file)) - flags |= __SLBF; fp->_flags |= flags; } @@ -90,10 +213,7 @@ __smakebuf(fp) * Internal routine to determine `proper' buffering for a file. */ int -__swhatbuf(fp, bufsize, couldbetty) - FILE *fp; - size_t *bufsize; - int *couldbetty; +__swhatbuf(FILE *fp, size_t *bufsize, int *couldbetty) { struct stat st; @@ -115,8 +235,7 @@ __swhatbuf(fp, bufsize, couldbetty) * __sseek is mainly paranoia.) It is safe to set _blksize * unconditionally; it will only be used if __SOPT is also set. */ - *bufsize = st.st_blksize; - fp->_blksize = st.st_blksize; + fp->_blksize = *bufsize = st.st_blksize > MAXBUFSIZE ? MAXBUFSIZE : st.st_blksize; return ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek ? __SOPT : __SNPT); }