]>
git.saurik.com Git - apple/libc.git/blob - stdio/FreeBSD/makebuf.c
2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #if defined(LIBC_SCCS) && !defined(lint)
36 static char sccsid
[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93";
37 #endif /* LIBC_SCCS and not lint */
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
41 #include "namespace.h"
42 #include <sys/types.h>
47 #include "un-namespace.h"
49 #include "libc_private.h"
51 #include <xlocale/_stdio.h>
52 #include <xlocale/_stdlib.h>
53 #include <os/once_private.h>
55 #ifdef FEATURE_SMALL_STDIOBUF
56 # define MAXBUFSIZE (1 << 12)
58 # define MAXBUFSIZE (1 << 16)
61 #define TTYBUFSIZE 4096
64 static char __fallback_evp
[MAXEVPSIZE
];
65 static char __stdout_evp
[MAXEVPSIZE
];
68 __loadevp(const char* key
, char destination
[MAXEVPSIZE
])
70 char* evp
= getenv(key
);
72 strlcpy(destination
, evp
, MAXEVPSIZE
);
74 destination
[0] = '\0';
79 __evpinit(void* __unused unused
)
81 __loadevp("STDBUF", __fallback_evp
);
82 __loadevp("STDBUF1", __stdout_evp
);
88 static os_once_t predicate
;
89 os_once(&predicate
, NULL
, __evpinit
);
91 if (fd
== STDOUT_FILENO
&& __stdout_evp
[0] != '\0') {
93 } else if (__fallback_evp
[0] != '\0') {
94 return __fallback_evp
;
102 * Internal routine to determine environment override buffering for a file.
104 * Sections of the below taken from NetBSD's version of this file under the same license.
107 __senvbuf(FILE *fp
, size_t *bufsize
, int *couldbetty
)
114 flags
= 0; // Default to fully buffered
116 if ((evp
= __getevp(fp
->_file
)) == NULL
) {
120 // Look at the first character only to determine buffering mode
132 // Default flags is fully buffered
135 // Unexpected buffering mode, use default fully buffered
138 // User specified envrionment defaults have higher priority than tty defaults
141 // Advance the envrionment variable pointer, so we can attempt to parse the number
143 if (!isdigit(*evp
)) {
144 return flags
; // No number found, this protects us from negative size values
147 size
= strtol_l(evp
, &end
, 10, LC_C_LOCALE
);
153 return __SNBF
; // Override with unbuffered if the buffer size is 0
156 // We had a non zero buffer, cap it and return the flags;
157 *bufsize
= size
> MAXBUFSIZE
? MAXBUFSIZE
: size
;
162 * Allocate a file buffer, or switch to unbuffered I/O.
163 * Per the ANSI C standard, ALL tty devices default to line buffered.
165 * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek
166 * optimisation) right after the _fstat() that finds the buffer size.
176 if (fp
->_flags
& __SNBF
) {
177 fp
->_bf
._base
= fp
->_p
= fp
->_nbuf
;
181 flags
= __swhatbuf(fp
, &size
, &couldbetty
);
182 if (fp
->_file
>= 0) {
183 flags
|= __senvbuf(fp
, &size
, &couldbetty
);
185 if (flags
& __SNBF
) {
186 fp
->_flags
|= __SNBF
;
187 fp
->_bf
._base
= fp
->_p
= fp
->_nbuf
;
193 if (couldbetty
&& isatty(fp
->_file
)) {
195 /* st_blksize for ttys is 128K, so make it more reasonable */
196 if (size
> TTYBUFSIZE
)
197 fp
->_blksize
= size
= TTYBUFSIZE
;
199 if ((p
= malloc(size
)) == NULL
) {
200 fp
->_flags
|= __SNBF
;
201 fp
->_bf
._base
= fp
->_p
= fp
->_nbuf
;
205 __cleanup
= _cleanup
;
207 fp
->_bf
._base
= fp
->_p
= p
;
208 fp
->_bf
._size
= size
;
213 * Internal routine to determine `proper' buffering for a file.
216 __swhatbuf(FILE *fp
, size_t *bufsize
, int *couldbetty
)
220 if (fp
->_file
< 0 || _fstat(fp
->_file
, &st
) < 0) {
226 /* could be a tty iff it is a character device */
227 *couldbetty
= (st
.st_mode
& S_IFMT
) == S_IFCHR
;
228 if (st
.st_blksize
<= 0) {
234 * Optimise fseek() only if it is a regular file. (The test for
235 * __sseek is mainly paranoia.) It is safe to set _blksize
236 * unconditionally; it will only be used if __SOPT is also set.
238 fp
->_blksize
= *bufsize
= st
.st_blksize
> MAXBUFSIZE
? MAXBUFSIZE
: st
.st_blksize
;
239 return ((st
.st_mode
& S_IFMT
) == S_IFREG
&& fp
->_seek
== __sseek
?