blob: 1f08ea13d66e401112e8409735520f357908a729 [file] [log] [blame]
Dmitriy Ivanov623b0d02014-05-14 23:11:05 -07001/* $OpenBSD: findfp.c,v 1.15 2013/12/17 16:33:27 deraadt Exp $ */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002/*-
3 * Copyright (c) 1990, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
Elliott Hughes53cf3482016-08-09 13:06:41 -070034#define __BIONIC_NO_STDIO_FORTIFY
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080035#include <stdio.h>
Elliott Hughes021335e2016-01-19 16:28:15 -080036
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080037#include <errno.h>
Elliott Hughes021335e2016-01-19 16:28:15 -080038#include <fcntl.h>
Elliott Hughes2704bd12016-01-20 17:14:53 -080039#include <limits.h>
Elliott Hughes20788ae2016-06-09 15:16:32 -070040#include <paths.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080041#include <stdlib.h>
42#include <string.h>
Elliott Hughes021335e2016-01-19 16:28:15 -080043#include <sys/param.h>
Elliott Hughes468efc82018-07-10 14:39:49 -070044#include <sys/socket.h>
Elliott Hughes023c3072016-01-22 15:04:51 -080045#include <sys/stat.h>
Elliott Hughes468efc82018-07-10 14:39:49 -070046#include <sys/wait.h>
Elliott Hughes021335e2016-01-19 16:28:15 -080047#include <unistd.h>
48
Josh Gaod1620602017-10-05 13:48:08 -070049#include <async_safe/log.h>
50
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080051#include "local.h"
52#include "glue.h"
Elliott Hughesfb3873d2016-08-10 11:07:54 -070053#include "private/bionic_fortify.h"
Elliott Hughes023c3072016-01-22 15:04:51 -080054#include "private/ErrnoRestorer.h"
Elliott Hughes6a03abc2014-11-03 12:32:17 -080055#include "private/thread_private.h"
56
57#define ALIGNBYTES (sizeof(uintptr_t) - 1)
58#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
Calin Juravlec20de902014-03-20 15:21:32 +000059
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080060#define NDYNAMIC 10 /* add ten more whenever necessary */
61
Elliott Hughes70715da2016-08-01 16:35:17 -070062#define PRINTF_IMPL(expr) \
63 va_list ap; \
64 va_start(ap, fmt); \
65 int result = (expr); \
66 va_end(ap); \
67 return result;
68
Elliott Hughes468efc82018-07-10 14:39:49 -070069#define MAKE_STD_STREAM(flags, fd) \
70 { \
71 ._flags = flags, ._file = fd, ._cookie = __sF + fd, ._close = __sclose, \
72 ._read = __sread, ._write = __swrite, ._ext = { \
73 ._base = reinterpret_cast<uint8_t*>(__sFext + fd) \
74 } \
75 }
Elliott Hughes29ee6392015-12-07 11:07:15 -080076
Elliott Hughesbb46afd2015-12-04 18:03:12 -080077static struct __sfileext __sFext[3] = {
Elliott Hughes468efc82018-07-10 14:39:49 -070078 {._lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
79 ._caller_handles_locking = false,
80 ._seek64 = __sseek64,
81 ._popen_pid = 0},
82 {._lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
83 ._caller_handles_locking = false,
84 ._seek64 = __sseek64,
85 ._popen_pid = 0},
86 {._lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
87 ._caller_handles_locking = false,
88 ._seek64 = __sseek64,
89 ._popen_pid = 0},
Elliott Hughesbb46afd2015-12-04 18:03:12 -080090};
Elliott Hughesf0141df2015-10-12 12:44:23 -070091
92// __sF is exported for backwards compatibility. Until M, we didn't have symbols
93// for stdin/stdout/stderr; they were macros accessing __sF.
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080094FILE __sF[3] = {
Elliott Hughes468efc82018-07-10 14:39:49 -070095 MAKE_STD_STREAM(__SRD, STDIN_FILENO),
96 MAKE_STD_STREAM(__SWR, STDOUT_FILENO),
97 MAKE_STD_STREAM(__SWR|__SNBF, STDERR_FILENO),
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080098};
Elliott Hughesf0141df2015-10-12 12:44:23 -070099
Elliott Hughes168667c2014-11-14 14:42:59 -0800100FILE* stdin = &__sF[0];
101FILE* stdout = &__sF[1];
102FILE* stderr = &__sF[2];
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800103
Elliott Hughes468efc82018-07-10 14:39:49 -0700104static pthread_mutex_t __stdio_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
Elliott Hughes37ad9592017-10-30 17:47:12 -0700105struct glue __sglue = { nullptr, 3, __sF };
Elliott Hughesbb46afd2015-12-04 18:03:12 -0800106static struct glue* lastglue = &__sglue;
107
Elliott Hughes2704bd12016-01-20 17:14:53 -0800108class ScopedFileLock {
109 public:
Chih-Hung Hsieh62e3a072016-05-03 12:08:05 -0700110 explicit ScopedFileLock(FILE* fp) : fp_(fp) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800111 FLOCKFILE(fp_);
112 }
113 ~ScopedFileLock() {
114 FUNLOCKFILE(fp_);
115 }
116
117 private:
118 FILE* fp_;
119};
120
Elliott Hughes021335e2016-01-19 16:28:15 -0800121static glue* moreglue(int n) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800122 char* data = new char[sizeof(glue) + ALIGNBYTES + n * sizeof(FILE) + n * sizeof(__sfileext)];
123 if (data == nullptr) return nullptr;
Elliott Hughes021335e2016-01-19 16:28:15 -0800124
Elliott Hughes2704bd12016-01-20 17:14:53 -0800125 glue* g = reinterpret_cast<glue*>(data);
126 FILE* p = reinterpret_cast<FILE*>(ALIGN(data + sizeof(*g)));
127 __sfileext* pext = reinterpret_cast<__sfileext*>(ALIGN(data + sizeof(*g)) + n * sizeof(FILE));
Elliott Hughes37ad9592017-10-30 17:47:12 -0700128 g->next = nullptr;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800129 g->niobs = n;
130 g->iobs = p;
131 while (--n >= 0) {
Elliott Hughes468efc82018-07-10 14:39:49 -0700132 *p = {};
Elliott Hughes2704bd12016-01-20 17:14:53 -0800133 _FILEEXT_SETUP(p, pext);
134 p++;
135 pext++;
136 }
137 return g;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800138}
139
Elliott Hughes80e4c152017-07-21 13:57:55 -0700140static inline void free_fgetln_buffer(FILE* fp) {
141 if (__predict_false(fp->_lb._base != nullptr)) {
142 free(fp->_lb._base);
143 fp->_lb._base = nullptr;
144 }
145}
146
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800147/*
148 * Find a free FILE for fopen et al.
149 */
Elliott Hughes021335e2016-01-19 16:28:15 -0800150FILE* __sfp(void) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800151 FILE *fp;
152 int n;
153 struct glue *g;
154
Elliott Hughes468efc82018-07-10 14:39:49 -0700155 pthread_mutex_lock(&__stdio_mutex);
Elliott Hughes37ad9592017-10-30 17:47:12 -0700156 for (g = &__sglue; g != nullptr; g = g->next) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800157 for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
158 if (fp->_flags == 0)
159 goto found;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800160 }
Kenny Rootf5823402011-02-12 07:13:44 -0800161
162 /* release lock while mallocing */
Elliott Hughes468efc82018-07-10 14:39:49 -0700163 pthread_mutex_unlock(&__stdio_mutex);
Elliott Hughes37ad9592017-10-30 17:47:12 -0700164 if ((g = moreglue(NDYNAMIC)) == nullptr) return nullptr;
Elliott Hughes468efc82018-07-10 14:39:49 -0700165 pthread_mutex_lock(&__stdio_mutex);
Kenny Rootf5823402011-02-12 07:13:44 -0800166 lastglue->next = g;
167 lastglue = g;
168 fp = g->iobs;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800169found:
170 fp->_flags = 1; /* reserve this slot; caller sets real flags */
Elliott Hughes468efc82018-07-10 14:39:49 -0700171 pthread_mutex_unlock(&__stdio_mutex);
Elliott Hughes37ad9592017-10-30 17:47:12 -0700172 fp->_p = nullptr; /* no current pointer */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800173 fp->_w = 0; /* nothing to read or write */
174 fp->_r = 0;
Elliott Hughes37ad9592017-10-30 17:47:12 -0700175 fp->_bf._base = nullptr; /* no buffer */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800176 fp->_bf._size = 0;
177 fp->_lbfsize = 0; /* not line buffered */
178 fp->_file = -1; /* no file */
Elliott Hughes023c3072016-01-22 15:04:51 -0800179
Elliott Hughes37ad9592017-10-30 17:47:12 -0700180 fp->_lb._base = nullptr; /* no line buffer */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800181 fp->_lb._size = 0;
Elliott Hughes1a56a262017-12-20 08:53:49 -0800182
183 memset(_EXT(fp), 0, sizeof(struct __sfileext));
184 _FLOCK(fp) = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
185 _EXT(fp)->_caller_handles_locking = false;
Elliott Hughes023c3072016-01-22 15:04:51 -0800186
187 // Caller sets cookie, _read/_write etc.
188 // We explicitly clear _seek and _seek64 to prevent subtle bugs.
189 fp->_seek = nullptr;
190 _EXT(fp)->_seek64 = nullptr;
191
192 return fp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800193}
194
Elliott Hughes468efc82018-07-10 14:39:49 -0700195int _fwalk(int (*callback)(FILE*)) {
196 pthread_mutex_lock(&__stdio_mutex);
197 int result = 0;
198 for (glue* g = &__sglue; g != nullptr; g = g->next) {
199 FILE* fp = g->iobs;
200 for (int n = g->niobs; --n >= 0; ++fp) {
201 ScopedFileLock sfl(fp);
202 if (fp->_flags != 0 && (fp->_flags & __SIGN) == 0) {
203 result |= (*callback)(fp);
204 }
205 }
206 }
207 pthread_mutex_unlock(&__stdio_mutex);
208 return result;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800209}
Elliott Hughes923f1652016-01-19 15:46:05 -0800210
Elliott Hughes023c3072016-01-22 15:04:51 -0800211static FILE* __fopen(int fd, int flags) {
212#if !defined(__LP64__)
213 if (fd > SHRT_MAX) {
214 errno = EMFILE;
215 return nullptr;
216 }
217#endif
218
219 FILE* fp = __sfp();
220 if (fp != nullptr) {
221 fp->_file = fd;
222 fp->_flags = flags;
223 fp->_cookie = fp;
224 fp->_read = __sread;
225 fp->_write = __swrite;
226 fp->_close = __sclose;
227 _EXT(fp)->_seek64 = __sseek64;
228 }
229 return fp;
230}
231
232FILE* fopen(const char* file, const char* mode) {
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700233 int mode_flags;
234 int flags = __sflags(mode, &mode_flags);
Elliott Hughes023c3072016-01-22 15:04:51 -0800235 if (flags == 0) return nullptr;
236
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700237 int fd = open(file, mode_flags, DEFFILEMODE);
Elliott Hughes023c3072016-01-22 15:04:51 -0800238 if (fd == -1) {
239 return nullptr;
240 }
241
242 FILE* fp = __fopen(fd, flags);
243 if (fp == nullptr) {
244 ErrnoRestorer errno_restorer;
245 close(fd);
246 return nullptr;
247 }
248
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700249 // For append mode, even though we use O_APPEND, we need to seek to the end now.
250 if ((mode_flags & O_APPEND) != 0) __sseek64(fp, 0, SEEK_END);
Elliott Hughes023c3072016-01-22 15:04:51 -0800251 return fp;
252}
Elliott Hughesf226ee52016-02-03 11:24:28 -0800253__strong_alias(fopen64, fopen);
Elliott Hughes023c3072016-01-22 15:04:51 -0800254
255FILE* fdopen(int fd, const char* mode) {
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700256 int mode_flags;
257 int flags = __sflags(mode, &mode_flags);
Elliott Hughes023c3072016-01-22 15:04:51 -0800258 if (flags == 0) return nullptr;
259
260 // Make sure the mode the user wants is a subset of the actual mode.
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700261 int fd_flags = fcntl(fd, F_GETFL, 0);
262 if (fd_flags == -1) return nullptr;
263 int tmp = fd_flags & O_ACCMODE;
264 if (tmp != O_RDWR && (tmp != (mode_flags & O_ACCMODE))) {
Elliott Hughes023c3072016-01-22 15:04:51 -0800265 errno = EINVAL;
266 return nullptr;
267 }
268
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700269 // Make sure O_APPEND is set on the underlying fd if our mode has 'a'.
270 // POSIX says we just take the current offset of the underlying fd.
271 if ((mode_flags & O_APPEND) && !(fd_flags & O_APPEND)) {
272 if (fcntl(fd, F_SETFL, fd_flags | O_APPEND) == -1) return nullptr;
273 }
Elliott Hughes023c3072016-01-22 15:04:51 -0800274
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700275 // Make sure O_CLOEXEC is set on the underlying fd if our mode has 'x'.
276 if ((mode_flags & O_CLOEXEC) && !((tmp = fcntl(fd, F_GETFD)) & FD_CLOEXEC)) {
Elliott Hughes023c3072016-01-22 15:04:51 -0800277 fcntl(fd, F_SETFD, tmp | FD_CLOEXEC);
278 }
279
280 return __fopen(fd, flags);
281}
282
283// Re-direct an existing, open (probably) file to some other file.
284// ANSI is written such that the original file gets closed if at
285// all possible, no matter what.
286// TODO: rewrite this mess completely.
287FILE* freopen(const char* file, const char* mode, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700288 CHECK_FP(fp);
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700289 int mode_flags;
290 int flags = __sflags(mode, &mode_flags);
Elliott Hughes023c3072016-01-22 15:04:51 -0800291 if (flags == 0) {
292 fclose(fp);
293 return nullptr;
294 }
295
296 ScopedFileLock sfl(fp);
297
298 // There are actually programs that depend on being able to "freopen"
299 // descriptors that weren't originally open. Keep this from breaking.
300 // Remember whether the stream was open to begin with, and which file
301 // descriptor (if any) was associated with it. If it was attached to
302 // a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
303 // should work. This is unnecessary if it was not a Unix file.
304 int isopen, wantfd;
305 if (fp->_flags == 0) {
306 fp->_flags = __SEOF; // Hold on to it.
307 isopen = 0;
308 wantfd = -1;
309 } else {
310 // Flush the stream; ANSI doesn't require this.
311 if (fp->_flags & __SWR) __sflush(fp);
312
Elliott Hughes37ad9592017-10-30 17:47:12 -0700313 // If close is null, closing is a no-op, hence pointless.
314 isopen = (fp->_close != nullptr);
Elliott Hughes023c3072016-01-22 15:04:51 -0800315 if ((wantfd = fp->_file) < 0 && isopen) {
316 (*fp->_close)(fp->_cookie);
317 isopen = 0;
318 }
319 }
320
321 // Get a new descriptor to refer to the new file.
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700322 int fd = open(file, mode_flags, DEFFILEMODE);
Elliott Hughes023c3072016-01-22 15:04:51 -0800323 if (fd < 0 && isopen) {
324 // If out of fd's close the old one and try again.
325 if (errno == ENFILE || errno == EMFILE) {
326 (*fp->_close)(fp->_cookie);
327 isopen = 0;
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700328 fd = open(file, mode_flags, DEFFILEMODE);
Elliott Hughes023c3072016-01-22 15:04:51 -0800329 }
330 }
331
332 int sverrno = errno;
333
334 // Finish closing fp. Even if the open succeeded above, we cannot
335 // keep fp->_base: it may be the wrong size. This loses the effect
336 // of any setbuffer calls, but stdio has always done this before.
337 if (isopen && fd != wantfd) (*fp->_close)(fp->_cookie);
338 if (fp->_flags & __SMBF) free(fp->_bf._base);
339 fp->_w = 0;
340 fp->_r = 0;
Elliott Hughes37ad9592017-10-30 17:47:12 -0700341 fp->_p = nullptr;
342 fp->_bf._base = nullptr;
Elliott Hughes023c3072016-01-22 15:04:51 -0800343 fp->_bf._size = 0;
344 fp->_lbfsize = 0;
345 if (HASUB(fp)) FREEUB(fp);
346 _UB(fp)._size = 0;
347 WCIO_FREE(fp);
Elliott Hughes80e4c152017-07-21 13:57:55 -0700348 free_fgetln_buffer(fp);
Elliott Hughes023c3072016-01-22 15:04:51 -0800349 fp->_lb._size = 0;
350
351 if (fd < 0) { // Did not get it after all.
352 fp->_flags = 0; // Release.
353 errno = sverrno; // Restore errno in case _close clobbered it.
354 return nullptr;
355 }
356
357 // If reopening something that was open before on a real file, try
358 // to maintain the descriptor. Various C library routines (perror)
359 // assume stderr is always fd STDERR_FILENO, even if being freopen'd.
360 if (wantfd >= 0 && fd != wantfd) {
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700361 if (dup3(fd, wantfd, mode_flags & O_CLOEXEC) >= 0) {
Elliott Hughes023c3072016-01-22 15:04:51 -0800362 close(fd);
363 fd = wantfd;
364 }
365 }
366
367 // _file is only a short.
368 if (fd > SHRT_MAX) {
369 fp->_flags = 0; // Release.
370 errno = EMFILE;
371 return nullptr;
372 }
373
374 fp->_flags = flags;
375 fp->_file = fd;
376 fp->_cookie = fp;
377 fp->_read = __sread;
378 fp->_write = __swrite;
379 fp->_close = __sclose;
380 _EXT(fp)->_seek64 = __sseek64;
381
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700382 // For append mode, even though we use O_APPEND, we need to seek to the end now.
383 if ((mode_flags & O_APPEND) != 0) __sseek64(fp, 0, SEEK_END);
Elliott Hughes023c3072016-01-22 15:04:51 -0800384 return fp;
385}
Elliott Hughesf226ee52016-02-03 11:24:28 -0800386__strong_alias(freopen64, freopen);
Elliott Hughes023c3072016-01-22 15:04:51 -0800387
Elliott Hughes923f1652016-01-19 15:46:05 -0800388int fclose(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700389 CHECK_FP(fp);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800390 if (fp->_flags == 0) {
391 // Already freed!
392 errno = EBADF;
393 return EOF;
394 }
Elliott Hughes923f1652016-01-19 15:46:05 -0800395
Elliott Hughes2704bd12016-01-20 17:14:53 -0800396 ScopedFileLock sfl(fp);
397 WCIO_FREE(fp);
398 int r = fp->_flags & __SWR ? __sflush(fp) : 0;
Elliott Hughes37ad9592017-10-30 17:47:12 -0700399 if (fp->_close != nullptr && (*fp->_close)(fp->_cookie) < 0) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800400 r = EOF;
401 }
402 if (fp->_flags & __SMBF) free(fp->_bf._base);
403 if (HASUB(fp)) FREEUB(fp);
Elliott Hughes80e4c152017-07-21 13:57:55 -0700404 free_fgetln_buffer(fp);
Elliott Hughes923f1652016-01-19 15:46:05 -0800405
Elliott Hughes468efc82018-07-10 14:39:49 -0700406 // If we were created by popen(3), wait for the child.
407 pid_t pid = _EXT(fp)->_popen_pid;
408 if (pid > 0) {
409 int status;
410 if (TEMP_FAILURE_RETRY(wait4(pid, &status, 0, nullptr)) != -1) {
411 r = status;
412 }
413 }
414 _EXT(fp)->_popen_pid = 0;
415
Elliott Hughes2704bd12016-01-20 17:14:53 -0800416 // Poison this FILE so accesses after fclose will be obvious.
417 fp->_file = -1;
418 fp->_r = fp->_w = 0;
Elliott Hughes923f1652016-01-19 15:46:05 -0800419
Elliott Hughes2704bd12016-01-20 17:14:53 -0800420 // Release this FILE for reuse.
421 fp->_flags = 0;
422 return r;
Elliott Hughes923f1652016-01-19 15:46:05 -0800423}
Elliott Hughes468efc82018-07-10 14:39:49 -0700424__strong_alias(pclose, fclose);
Elliott Hughes923f1652016-01-19 15:46:05 -0800425
Elliott Hughescceaf062016-07-29 16:31:52 -0700426int fileno_unlocked(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700427 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700428 int fd = fp->_file;
429 if (fd == -1) {
430 errno = EBADF;
431 return -1;
432 }
433 return fd;
434}
435
Elliott Hughes923f1652016-01-19 15:46:05 -0800436int fileno(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700437 CHECK_FP(fp);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800438 ScopedFileLock sfl(fp);
439 return fileno_unlocked(fp);
Elliott Hughes923f1652016-01-19 15:46:05 -0800440}
Elliott Hughes021335e2016-01-19 16:28:15 -0800441
Elliott Hughescceaf062016-07-29 16:31:52 -0700442void clearerr_unlocked(FILE* fp) {
443 return __sclearerr(fp);
444}
445
446void clearerr(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700447 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700448 ScopedFileLock sfl(fp);
449 clearerr_unlocked(fp);
450}
451
452int feof_unlocked(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700453 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700454 return ((fp->_flags & __SEOF) != 0);
Elliott Hughescceaf062016-07-29 16:31:52 -0700455}
456
457int feof(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700458 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700459 ScopedFileLock sfl(fp);
460 return feof_unlocked(fp);
461}
462
463int ferror_unlocked(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700464 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700465 return __sferror(fp);
466}
467
468int ferror(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700469 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700470 ScopedFileLock sfl(fp);
471 return ferror_unlocked(fp);
472}
473
Elliott Hughes37ad9592017-10-30 17:47:12 -0700474int __sflush(FILE* fp) {
475 // Flushing a read-only file is a no-op.
476 if ((fp->_flags & __SWR) == 0) return 0;
477
478 // Flushing a file without a buffer is a no-op.
479 unsigned char* p = fp->_bf._base;
480 if (p == nullptr) return 0;
481
482 // Set these immediately to avoid problems with longjmp and to allow
483 // exchange buffering (via setvbuf) in user write function.
484 int n = fp->_p - p;
485 fp->_p = p;
486 fp->_w = (fp->_flags & (__SLBF|__SNBF)) ? 0 : fp->_bf._size;
487
488 while (n > 0) {
489 int written = (*fp->_write)(fp->_cookie, reinterpret_cast<char*>(p), n);
490 if (written <= 0) {
491 fp->_flags |= __SERR;
492 return EOF;
493 }
494 n -= written, p += written;
495 }
496 return 0;
497}
498
Elliott Hughes021335e2016-01-19 16:28:15 -0800499int __sread(void* cookie, char* buf, int n) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800500 FILE* fp = reinterpret_cast<FILE*>(cookie);
501 return TEMP_FAILURE_RETRY(read(fp->_file, buf, n));
Elliott Hughes021335e2016-01-19 16:28:15 -0800502}
503
504int __swrite(void* cookie, const char* buf, int n) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800505 FILE* fp = reinterpret_cast<FILE*>(cookie);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800506 return TEMP_FAILURE_RETRY(write(fp->_file, buf, n));
Elliott Hughes021335e2016-01-19 16:28:15 -0800507}
508
Elliott Hughes021335e2016-01-19 16:28:15 -0800509fpos_t __sseek(void* cookie, fpos_t offset, int whence) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800510 FILE* fp = reinterpret_cast<FILE*>(cookie);
511 return TEMP_FAILURE_RETRY(lseek(fp->_file, offset, whence));
Elliott Hughes021335e2016-01-19 16:28:15 -0800512}
513
Elliott Hughes023c3072016-01-22 15:04:51 -0800514off64_t __sseek64(void* cookie, off64_t offset, int whence) {
515 FILE* fp = reinterpret_cast<FILE*>(cookie);
516 return TEMP_FAILURE_RETRY(lseek64(fp->_file, offset, whence));
517}
518
Elliott Hughes021335e2016-01-19 16:28:15 -0800519int __sclose(void* cookie) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800520 FILE* fp = reinterpret_cast<FILE*>(cookie);
521 return close(fp->_file);
522}
523
Elliott Hughes023c3072016-01-22 15:04:51 -0800524static off64_t __seek_unlocked(FILE* fp, off64_t offset, int whence) {
525 // Use `_seek64` if set, but fall back to `_seek`.
526 if (_EXT(fp)->_seek64 != nullptr) {
527 return (*_EXT(fp)->_seek64)(fp->_cookie, offset, whence);
528 } else if (fp->_seek != nullptr) {
Elliott Hughes955426e2016-01-26 18:25:52 -0800529 off64_t result = (*fp->_seek)(fp->_cookie, offset, whence);
530#if !defined(__LP64__)
531 // Avoid sign extension if off64_t is larger than off_t.
532 if (result != -1) result &= 0xffffffff;
533#endif
534 return result;
Elliott Hughes023c3072016-01-22 15:04:51 -0800535 } else {
536 errno = ESPIPE;
537 return -1;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800538 }
Elliott Hughes2704bd12016-01-20 17:14:53 -0800539}
540
Elliott Hughes9677fab2016-01-25 15:50:59 -0800541static off64_t __ftello64_unlocked(FILE* fp) {
Elliott Hughes023c3072016-01-22 15:04:51 -0800542 // Find offset of underlying I/O object, then adjust for buffered bytes.
Elliott Hughes2704bd12016-01-20 17:14:53 -0800543 __sflush(fp); // May adjust seek offset on append stream.
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700544
Elliott Hughes9677fab2016-01-25 15:50:59 -0800545 off64_t result = __seek_unlocked(fp, 0, SEEK_CUR);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800546 if (result == -1) {
547 return -1;
548 }
549
550 if (fp->_flags & __SRD) {
551 // Reading. Any unread characters (including
552 // those from ungetc) cause the position to be
553 // smaller than that in the underlying object.
554 result -= fp->_r;
555 if (HASUB(fp)) result -= fp->_ur;
Elliott Hughes37ad9592017-10-30 17:47:12 -0700556 } else if (fp->_flags & __SWR && fp->_p != nullptr) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800557 // Writing. Any buffered characters cause the
558 // position to be greater than that in the
559 // underlying object.
560 result += fp->_p - fp->_bf._base;
561 }
562 return result;
563}
564
Elliott Hughes9677fab2016-01-25 15:50:59 -0800565int __fseeko64(FILE* fp, off64_t offset, int whence, int off_t_bits) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800566 ScopedFileLock sfl(fp);
567
Elliott Hughes023c3072016-01-22 15:04:51 -0800568 // Change any SEEK_CUR to SEEK_SET, and check `whence` argument.
Elliott Hughes2704bd12016-01-20 17:14:53 -0800569 // After this, whence is either SEEK_SET or SEEK_END.
570 if (whence == SEEK_CUR) {
Elliott Hughes9677fab2016-01-25 15:50:59 -0800571 fpos64_t current_offset = __ftello64_unlocked(fp);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800572 if (current_offset == -1) {
Elliott Hughes9677fab2016-01-25 15:50:59 -0800573 return -1;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800574 }
575 offset += current_offset;
576 whence = SEEK_SET;
577 } else if (whence != SEEK_SET && whence != SEEK_END) {
578 errno = EINVAL;
Elliott Hughes9677fab2016-01-25 15:50:59 -0800579 return -1;
580 }
581
582 // If our caller has a 32-bit interface, refuse to go past a 32-bit file offset.
583 if (off_t_bits == 32 && offset > LONG_MAX) {
584 errno = EOVERFLOW;
585 return -1;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800586 }
587
Elliott Hughes37ad9592017-10-30 17:47:12 -0700588 if (fp->_bf._base == nullptr) __smakebuf(fp);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800589
590 // Flush unwritten data and attempt the seek.
Elliott Hughes023c3072016-01-22 15:04:51 -0800591 if (__sflush(fp) || __seek_unlocked(fp, offset, whence) == -1) {
Elliott Hughes9677fab2016-01-25 15:50:59 -0800592 return -1;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800593 }
594
595 // Success: clear EOF indicator and discard ungetc() data.
596 if (HASUB(fp)) FREEUB(fp);
597 fp->_p = fp->_bf._base;
598 fp->_r = 0;
599 /* fp->_w = 0; */ /* unnecessary (I think...) */
600 fp->_flags &= ~__SEOF;
601 return 0;
602}
603
Elliott Hughes9677fab2016-01-25 15:50:59 -0800604int fseeko(FILE* fp, off_t offset, int whence) {
Josh Gaod1620602017-10-05 13:48:08 -0700605 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800606 static_assert(sizeof(off_t) == sizeof(long), "sizeof(off_t) != sizeof(long)");
607 return __fseeko64(fp, offset, whence, 8*sizeof(off_t));
608}
609__strong_alias(fseek, fseeko);
610
611int fseeko64(FILE* fp, off64_t offset, int whence) {
Josh Gaod1620602017-10-05 13:48:08 -0700612 CHECK_FP(fp);
Ryan Prichardbf549862017-11-07 15:30:32 -0800613 return __fseeko64(fp, offset, whence, 8*sizeof(off64_t));
Elliott Hughes2704bd12016-01-20 17:14:53 -0800614}
615
Elliott Hughes9677fab2016-01-25 15:50:59 -0800616int fsetpos(FILE* fp, const fpos_t* pos) {
Josh Gaod1620602017-10-05 13:48:08 -0700617 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800618 return fseeko(fp, *pos, SEEK_SET);
619}
620
621int fsetpos64(FILE* fp, const fpos64_t* pos) {
Josh Gaod1620602017-10-05 13:48:08 -0700622 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800623 return fseeko64(fp, *pos, SEEK_SET);
624}
625
Elliott Hughes2704bd12016-01-20 17:14:53 -0800626off_t ftello(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700627 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800628 static_assert(sizeof(off_t) == sizeof(long), "sizeof(off_t) != sizeof(long)");
629 off64_t result = ftello64(fp);
630 if (result > LONG_MAX) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800631 errno = EOVERFLOW;
632 return -1;
633 }
Elliott Hughes9677fab2016-01-25 15:50:59 -0800634 return result;
635}
636__strong_alias(ftell, ftello);
637
638off64_t ftello64(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700639 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800640 ScopedFileLock sfl(fp);
641 return __ftello64_unlocked(fp);
Elliott Hughes021335e2016-01-19 16:28:15 -0800642}
Elliott Hughes023c3072016-01-22 15:04:51 -0800643
Elliott Hughes023c3072016-01-22 15:04:51 -0800644int fgetpos(FILE* fp, fpos_t* pos) {
Josh Gaod1620602017-10-05 13:48:08 -0700645 CHECK_FP(fp);
Elliott Hughes023c3072016-01-22 15:04:51 -0800646 *pos = ftello(fp);
Elliott Hughes955426e2016-01-26 18:25:52 -0800647 return (*pos == -1) ? -1 : 0;
Elliott Hughes023c3072016-01-22 15:04:51 -0800648}
649
Elliott Hughes9677fab2016-01-25 15:50:59 -0800650int fgetpos64(FILE* fp, fpos64_t* pos) {
Josh Gaod1620602017-10-05 13:48:08 -0700651 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800652 *pos = ftello64(fp);
Elliott Hughes955426e2016-01-26 18:25:52 -0800653 return (*pos == -1) ? -1 : 0;
Elliott Hughes023c3072016-01-22 15:04:51 -0800654}
Elliott Hughes03e65eb2016-01-26 14:13:04 -0800655
656static FILE* __funopen(const void* cookie,
657 int (*read_fn)(void*, char*, int),
658 int (*write_fn)(void*, const char*, int),
659 int (*close_fn)(void*)) {
660 if (read_fn == nullptr && write_fn == nullptr) {
661 errno = EINVAL;
662 return nullptr;
663 }
664
665 FILE* fp = __sfp();
666 if (fp == nullptr) return nullptr;
667
668 if (read_fn != nullptr && write_fn != nullptr) {
669 fp->_flags = __SRW;
670 } else if (read_fn != nullptr) {
671 fp->_flags = __SRD;
672 } else if (write_fn != nullptr) {
673 fp->_flags = __SWR;
674 }
675
676 fp->_file = -1;
677 fp->_cookie = const_cast<void*>(cookie); // The funopen(3) API is incoherent.
678 fp->_read = read_fn;
679 fp->_write = write_fn;
680 fp->_close = close_fn;
681
682 return fp;
683}
684
685FILE* funopen(const void* cookie,
686 int (*read_fn)(void*, char*, int),
687 int (*write_fn)(void*, const char*, int),
688 fpos_t (*seek_fn)(void*, fpos_t, int),
689 int (*close_fn)(void*)) {
690 FILE* fp = __funopen(cookie, read_fn, write_fn, close_fn);
691 if (fp != nullptr) {
692 fp->_seek = seek_fn;
693 }
694 return fp;
695}
696
697FILE* funopen64(const void* cookie,
698 int (*read_fn)(void*, char*, int),
699 int (*write_fn)(void*, const char*, int),
700 fpos64_t (*seek_fn)(void*, fpos64_t, int),
701 int (*close_fn)(void*)) {
702 FILE* fp = __funopen(cookie, read_fn, write_fn, close_fn);
703 if (fp != nullptr) {
704 _EXT(fp)->_seek64 = seek_fn;
705 }
706 return fp;
707}
Elliott Hughes20788ae2016-06-09 15:16:32 -0700708
Elliott Hughes53cf3482016-08-09 13:06:41 -0700709int asprintf(char** s, const char* fmt, ...) {
710 PRINTF_IMPL(vasprintf(s, fmt, ap));
711}
712
Elliott Hughes20788ae2016-06-09 15:16:32 -0700713char* ctermid(char* s) {
714 return s ? strcpy(s, _PATH_TTY) : const_cast<char*>(_PATH_TTY);
715}
Elliott Hughescceaf062016-07-29 16:31:52 -0700716
Elliott Hughes70715da2016-08-01 16:35:17 -0700717int dprintf(int fd, const char* fmt, ...) {
718 PRINTF_IMPL(vdprintf(fd, fmt, ap));
719}
720
721int fprintf(FILE* fp, const char* fmt, ...) {
Josh Gaod1620602017-10-05 13:48:08 -0700722 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700723 PRINTF_IMPL(vfprintf(fp, fmt, ap));
724}
725
Elliott Hughescceaf062016-07-29 16:31:52 -0700726int fgetc(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700727 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700728 return getc(fp);
729}
730
Elliott Hughes37ad9592017-10-30 17:47:12 -0700731int fgetc_unlocked(FILE* fp) {
732 CHECK_FP(fp);
733 return getc_unlocked(fp);
734}
735
George Burgess IV90242352018-02-06 12:51:31 -0800736char* fgets(char* buf, int n, FILE* fp) {
Elliott Hughes37ad9592017-10-30 17:47:12 -0700737 CHECK_FP(fp);
738 ScopedFileLock sfl(fp);
739 return fgets_unlocked(buf, n, fp);
740}
741
Elliott Hughes468efc82018-07-10 14:39:49 -0700742// Reads at most n-1 characters from the given file.
743// Stops when a newline has been read, or the count runs out.
744// Returns first argument, or nullptr if no characters were read.
745// Does not return nullptr if n == 1.
Elliott Hughes37ad9592017-10-30 17:47:12 -0700746char* fgets_unlocked(char* buf, int n, FILE* fp) {
747 if (n <= 0) {
748 errno = EINVAL;
749 return nullptr;
750 }
751
752 _SET_ORIENTATION(fp, -1);
753
754 char* s = buf;
755 n--; // Leave space for NUL.
756 while (n != 0) {
757 // If the buffer is empty, refill it.
758 if (fp->_r <= 0) {
759 if (__srefill(fp)) {
760 // EOF/error: stop with partial or no line.
761 if (s == buf) return nullptr;
762 break;
763 }
764 }
765 size_t len = fp->_r;
766 unsigned char* p = fp->_p;
767
768 // Scan through at most n bytes of the current buffer,
769 // looking for '\n'. If found, copy up to and including
770 // newline, and stop. Otherwise, copy entire chunk and loop.
771 if (len > static_cast<size_t>(n)) len = n;
772 unsigned char* t = static_cast<unsigned char*>(memchr(p, '\n', len));
773 if (t != nullptr) {
774 len = ++t - p;
775 fp->_r -= len;
776 fp->_p = t;
777 memcpy(s, p, len);
778 s[len] = '\0';
779 return buf;
780 }
781 fp->_r -= len;
782 fp->_p += len;
783 memcpy(s, p, len);
784 s += len;
785 n -= len;
786 }
787 *s = '\0';
788 return buf;
789}
790
Elliott Hughescceaf062016-07-29 16:31:52 -0700791int fputc(int c, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700792 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700793 return putc(c, fp);
794}
795
Elliott Hughes37ad9592017-10-30 17:47:12 -0700796int fputc_unlocked(int c, FILE* fp) {
797 CHECK_FP(fp);
798 return putc_unlocked(c, fp);
799}
800
801int fputs(const char* s, FILE* fp) {
802 CHECK_FP(fp);
803 ScopedFileLock sfl(fp);
804 return fputs_unlocked(s, fp);
805}
806
807int fputs_unlocked(const char* s, FILE* fp) {
808 CHECK_FP(fp);
809 size_t length = strlen(s);
810 return (fwrite_unlocked(s, 1, length, fp) == length) ? 0 : EOF;
811}
812
Elliott Hughes70715da2016-08-01 16:35:17 -0700813int fscanf(FILE* fp, const char* fmt, ...) {
Josh Gaod1620602017-10-05 13:48:08 -0700814 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700815 PRINTF_IMPL(vfscanf(fp, fmt, ap));
816}
817
818int fwprintf(FILE* fp, const wchar_t* fmt, ...) {
Josh Gaod1620602017-10-05 13:48:08 -0700819 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700820 PRINTF_IMPL(vfwprintf(fp, fmt, ap));
821}
822
823int fwscanf(FILE* fp, const wchar_t* fmt, ...) {
Josh Gaod1620602017-10-05 13:48:08 -0700824 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700825 PRINTF_IMPL(vfwscanf(fp, fmt, ap));
826}
827
828int getc(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700829 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700830 ScopedFileLock sfl(fp);
831 return getc_unlocked(fp);
832}
833
834int getc_unlocked(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700835 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700836 return __sgetc(fp);
837}
838
839int getchar_unlocked() {
840 return getc_unlocked(stdin);
841}
842
843int getchar() {
844 return getc(stdin);
845}
846
Elliott Hughescceaf062016-07-29 16:31:52 -0700847ssize_t getline(char** buf, size_t* len, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700848 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700849 return getdelim(buf, len, '\n', fp);
850}
851
852wint_t getwc(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700853 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700854 return fgetwc(fp);
855}
856
857wint_t getwchar() {
858 return fgetwc(stdin);
859}
860
Elliott Hughes37ad9592017-10-30 17:47:12 -0700861void perror(const char* msg) {
862 if (msg == nullptr) msg = "";
863 fprintf(stderr, "%s%s%s\n", msg, (*msg == '\0') ? "" : ": ", strerror(errno));
864}
865
Elliott Hughes70715da2016-08-01 16:35:17 -0700866int printf(const char* fmt, ...) {
867 PRINTF_IMPL(vfprintf(stdout, fmt, ap));
868}
869
870int putc(int c, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700871 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700872 ScopedFileLock sfl(fp);
873 return putc_unlocked(c, fp);
874}
875
876int putc_unlocked(int c, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700877 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700878 if (cantwrite(fp)) {
879 errno = EBADF;
880 return EOF;
881 }
882 _SET_ORIENTATION(fp, -1);
883 if (--fp->_w >= 0 || (fp->_w >= fp->_lbfsize && c != '\n')) {
884 return (*fp->_p++ = c);
885 }
886 return (__swbuf(c, fp));
887}
888
889int putchar(int c) {
890 return putc(c, stdout);
891}
892
893int putchar_unlocked(int c) {
894 return putc_unlocked(c, stdout);
895}
896
Elliott Hughes37ad9592017-10-30 17:47:12 -0700897int puts(const char* s) {
898 size_t length = strlen(s);
899 ScopedFileLock sfl(stdout);
900 return (fwrite_unlocked(s, 1, length, stdout) == length &&
901 putc_unlocked('\n', stdout) != EOF) ? 0 : EOF;
902}
903
Elliott Hughescceaf062016-07-29 16:31:52 -0700904wint_t putwc(wchar_t wc, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700905 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700906 return fputwc(wc, fp);
907}
908
909wint_t putwchar(wchar_t wc) {
910 return fputwc(wc, stdout);
911}
912
Elliott Hughesd1f25a72016-08-05 15:53:03 -0700913int remove(const char* path) {
914 if (unlink(path) != -1) return 0;
915 if (errno != EISDIR) return -1;
916 return rmdir(path);
917}
918
Elliott Hughescceaf062016-07-29 16:31:52 -0700919void rewind(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700920 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700921 ScopedFileLock sfl(fp);
922 fseek(fp, 0, SEEK_SET);
923 clearerr_unlocked(fp);
924}
925
Elliott Hughes70715da2016-08-01 16:35:17 -0700926int scanf(const char* fmt, ...) {
927 PRINTF_IMPL(vfscanf(stdin, fmt, ap));
928}
929
Elliott Hughescceaf062016-07-29 16:31:52 -0700930void setbuf(FILE* fp, char* buf) {
Josh Gaod1620602017-10-05 13:48:08 -0700931 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700932 setbuffer(fp, buf, BUFSIZ);
933}
934
935void setbuffer(FILE* fp, char* buf, int size) {
Josh Gaod1620602017-10-05 13:48:08 -0700936 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700937 setvbuf(fp, buf, buf ? _IOFBF : _IONBF, size);
938}
939
940int setlinebuf(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700941 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700942 return setvbuf(fp, nullptr, _IOLBF, 0);
943}
944
Elliott Hughes53cf3482016-08-09 13:06:41 -0700945int snprintf(char* s, size_t n, const char* fmt, ...) {
946 PRINTF_IMPL(vsnprintf(s, n, fmt, ap));
947}
948
949int sprintf(char* s, const char* fmt, ...) {
Elliott Hughesfb3873d2016-08-10 11:07:54 -0700950 PRINTF_IMPL(vsprintf(s, fmt, ap));
Elliott Hughes53cf3482016-08-09 13:06:41 -0700951}
952
953int sscanf(const char* s, const char* fmt, ...) {
954 PRINTF_IMPL(vsscanf(s, fmt, ap));
955}
956
Elliott Hughes70715da2016-08-01 16:35:17 -0700957int swprintf(wchar_t* s, size_t n, const wchar_t* fmt, ...) {
958 PRINTF_IMPL(vswprintf(s, n, fmt, ap));
959}
960
961int swscanf(const wchar_t* s, const wchar_t* fmt, ...) {
962 PRINTF_IMPL(vswscanf(s, fmt, ap));
963}
964
Elliott Hughes618303c2017-11-02 16:58:44 -0700965int vfprintf(FILE* fp, const char* fmt, va_list ap) {
966 ScopedFileLock sfl(fp);
967 return __vfprintf(fp, fmt, ap);
968}
969
Elliott Hughes345b7272017-11-10 16:20:43 -0800970int vfscanf(FILE* fp, const char* fmt, va_list ap) {
971 ScopedFileLock sfl(fp);
972 return __svfscanf(fp, fmt, ap);
973}
974
Elliott Hughes618303c2017-11-02 16:58:44 -0700975int vfwprintf(FILE* fp, const wchar_t* fmt, va_list ap) {
976 ScopedFileLock sfl(fp);
977 return __vfwprintf(fp, fmt, ap);
978}
979
Elliott Hughes345b7272017-11-10 16:20:43 -0800980int vfwscanf(FILE* fp, const wchar_t* fmt, va_list ap) {
981 ScopedFileLock sfl(fp);
982 return __vfwscanf(fp, fmt, ap);
983}
984
Elliott Hughescceaf062016-07-29 16:31:52 -0700985int vprintf(const char* fmt, va_list ap) {
986 return vfprintf(stdout, fmt, ap);
987}
988
989int vscanf(const char* fmt, va_list ap) {
990 return vfscanf(stdin, fmt, ap);
991}
992
Elliott Hughesfb3873d2016-08-10 11:07:54 -0700993int vsnprintf(char* s, size_t n, const char* fmt, va_list ap) {
994 // stdio internals use int rather than size_t.
995 static_assert(INT_MAX <= SSIZE_MAX, "SSIZE_MAX too large to fit in int");
996
997 __check_count("vsnprintf", "size", n);
998
999 // Stdio internals do not deal correctly with zero length buffer.
1000 char dummy;
1001 if (n == 0) {
1002 s = &dummy;
1003 n = 1;
1004 }
1005
1006 FILE f;
1007 __sfileext fext;
1008 _FILEEXT_SETUP(&f, &fext);
1009 f._file = -1;
1010 f._flags = __SWR | __SSTR;
1011 f._bf._base = f._p = reinterpret_cast<unsigned char*>(s);
1012 f._bf._size = f._w = n - 1;
1013
1014 int result = __vfprintf(&f, fmt, ap);
1015 *f._p = '\0';
1016 return result;
1017}
1018
Elliott Hughes53cf3482016-08-09 13:06:41 -07001019int vsprintf(char* s, const char* fmt, va_list ap) {
Elliott Hughesfb3873d2016-08-10 11:07:54 -07001020 return vsnprintf(s, SSIZE_MAX, fmt, ap);
Elliott Hughes53cf3482016-08-09 13:06:41 -07001021}
1022
Elliott Hughescceaf062016-07-29 16:31:52 -07001023int vwprintf(const wchar_t* fmt, va_list ap) {
1024 return vfwprintf(stdout, fmt, ap);
1025}
1026
1027int vwscanf(const wchar_t* fmt, va_list ap) {
1028 return vfwscanf(stdin, fmt, ap);
1029}
Elliott Hughes70715da2016-08-01 16:35:17 -07001030
1031int wprintf(const wchar_t* fmt, ...) {
1032 PRINTF_IMPL(vfwprintf(stdout, fmt, ap));
1033}
1034
1035int wscanf(const wchar_t* fmt, ...) {
1036 PRINTF_IMPL(vfwscanf(stdin, fmt, ap));
1037}
Dan Albert3037ea42016-10-06 15:46:45 -07001038
Elliott Hughes37ad9592017-10-30 17:47:12 -07001039static int fflush_all() {
Elliott Hughes468efc82018-07-10 14:39:49 -07001040 return _fwalk(__sflush);
Elliott Hughes37ad9592017-10-30 17:47:12 -07001041}
1042
1043int fflush(FILE* fp) {
1044 if (fp == nullptr) return fflush_all();
1045 ScopedFileLock sfl(fp);
1046 return fflush_unlocked(fp);
1047}
1048
1049int fflush_unlocked(FILE* fp) {
1050 if (fp == nullptr) return fflush_all();
1051 if ((fp->_flags & (__SWR | __SRW)) == 0) {
1052 errno = EBADF;
1053 return EOF;
1054 }
1055 return __sflush(fp);
1056}
1057
George Burgess IV90242352018-02-06 12:51:31 -08001058size_t fread(void* buf, size_t size, size_t count, FILE* fp) {
Elliott Hughes37ad9592017-10-30 17:47:12 -07001059 CHECK_FP(fp);
1060 ScopedFileLock sfl(fp);
1061 return fread_unlocked(buf, size, count, fp);
1062}
1063
1064size_t fread_unlocked(void* buf, size_t size, size_t count, FILE* fp) {
1065 CHECK_FP(fp);
1066
1067 size_t desired_total;
1068 if (__builtin_mul_overflow(size, count, &desired_total)) {
1069 errno = EOVERFLOW;
1070 fp->_flags |= __SERR;
1071 return 0;
1072 }
1073
1074 size_t total = desired_total;
1075 if (total == 0) return 0;
1076
1077 _SET_ORIENTATION(fp, -1);
1078
1079 // TODO: how can this ever happen?!
1080 if (fp->_r < 0) fp->_r = 0;
1081
1082 // Ensure _bf._size is valid.
1083 if (fp->_bf._base == nullptr) __smakebuf(fp);
1084
1085 char* dst = static_cast<char*>(buf);
1086
1087 while (total > 0) {
1088 // Copy data out of the buffer.
1089 size_t buffered_bytes = MIN(static_cast<size_t>(fp->_r), total);
1090 memcpy(dst, fp->_p, buffered_bytes);
1091 fp->_p += buffered_bytes;
1092 fp->_r -= buffered_bytes;
1093 dst += buffered_bytes;
1094 total -= buffered_bytes;
1095
1096 // Are we done?
1097 if (total == 0) goto out;
1098
1099 // Do we have so much more to read that we should avoid copying it through the buffer?
1100 if (total > static_cast<size_t>(fp->_bf._size)) break;
1101
1102 // Less than a buffer to go, so refill the buffer and go around the loop again.
1103 if (__srefill(fp)) goto out;
1104 }
1105
1106 // Read directly into the caller's buffer.
1107 while (total > 0) {
1108 ssize_t bytes_read = (*fp->_read)(fp->_cookie, dst, total);
1109 if (bytes_read <= 0) {
1110 fp->_flags |= (bytes_read == 0) ? __SEOF : __SERR;
1111 break;
1112 }
1113 dst += bytes_read;
1114 total -= bytes_read;
1115 }
1116
1117out:
1118 return ((desired_total - total) / size);
1119}
1120
1121size_t fwrite(const void* buf, size_t size, size_t count, FILE* fp) {
1122 CHECK_FP(fp);
1123 ScopedFileLock sfl(fp);
1124 return fwrite_unlocked(buf, size, count, fp);
1125}
1126
1127size_t fwrite_unlocked(const void* buf, size_t size, size_t count, FILE* fp) {
1128 CHECK_FP(fp);
1129
1130 size_t n;
1131 if (__builtin_mul_overflow(size, count, &n)) {
1132 errno = EOVERFLOW;
1133 fp->_flags |= __SERR;
1134 return 0;
1135 }
1136
1137 if (n == 0) return 0;
1138
1139 __siov iov = { .iov_base = const_cast<void*>(buf), .iov_len = n };
1140 __suio uio = { .uio_iov = &iov, .uio_iovcnt = 1, .uio_resid = n };
1141
1142 _SET_ORIENTATION(fp, -1);
1143
1144 // The usual case is success (__sfvwrite returns 0); skip the divide if this happens,
1145 // since divides are generally slow.
1146 return (__sfvwrite(fp, &uio) == 0) ? count : ((n - uio.uio_resid) / size);
1147}
1148
Elliott Hughes468efc82018-07-10 14:39:49 -07001149static int __close_if_popened(FILE* fp) {
1150 if (_EXT(fp)->_popen_pid > 0) close(fileno(fp));
1151 return 0;
1152}
1153
1154static FILE* __popen_fail(int fds[2]) {
1155 ErrnoRestorer errno_restorer;
1156 close(fds[0]);
1157 close(fds[1]);
1158 return nullptr;
1159}
1160
1161FILE* popen(const char* cmd, const char* mode) {
1162 bool close_on_exec = (strchr(mode, 'e') != nullptr);
1163
1164 // Was the request for a socketpair or just a pipe?
1165 int fds[2];
1166 bool bidirectional = false;
1167 if (strchr(mode, '+') != nullptr) {
1168 if (socketpair(AF_LOCAL, SOCK_CLOEXEC | SOCK_STREAM, 0, fds) == -1) return nullptr;
1169 bidirectional = true;
1170 mode = "r+";
1171 } else {
1172 if (pipe2(fds, O_CLOEXEC) == -1) return nullptr;
1173 mode = strrchr(mode, 'r') ? "r" : "w";
1174 }
1175
1176 // If the parent wants to read, the child's fd needs to be stdout.
1177 int parent, child, desired_child_fd;
1178 if (*mode == 'r') {
1179 parent = 0;
1180 child = 1;
1181 desired_child_fd = STDOUT_FILENO;
1182 } else {
1183 parent = 1;
1184 child = 0;
1185 desired_child_fd = STDIN_FILENO;
1186 }
1187
1188 // Ensure that the child fd isn't the desired child fd.
1189 if (fds[child] == desired_child_fd) {
1190 int new_fd = fcntl(fds[child], F_DUPFD_CLOEXEC, 0);
1191 if (new_fd == -1) return __popen_fail(fds);
1192 close(fds[child]);
1193 fds[child] = new_fd;
1194 }
1195
1196 pid_t pid = vfork();
1197 if (pid == -1) return __popen_fail(fds);
1198
1199 if (pid == 0) {
1200 close(fds[parent]);
1201 // POSIX says "The popen() function shall ensure that any streams from previous popen() calls
1202 // that remain open in the parent process are closed in the new child process."
1203 _fwalk(__close_if_popened);
1204 // dup2 so that the child fd isn't closed on exec.
1205 if (dup2(fds[child], desired_child_fd) == -1) _exit(127);
1206 close(fds[child]);
1207 if (bidirectional) dup2(STDOUT_FILENO, STDIN_FILENO);
1208 execl(_PATH_BSHELL, "sh", "-c", cmd, nullptr);
1209 _exit(127);
1210 }
1211
1212 FILE* fp = fdopen(fds[parent], mode);
1213 if (fp == nullptr) return __popen_fail(fds);
1214
1215 // The caller didn't ask for their pipe to be O_CLOEXEC, so flip it back now the child has forked.
1216 if (!close_on_exec) fcntl(fds[parent], F_SETFD, 0);
1217 close(fds[child]);
1218
1219 _EXT(fp)->_popen_pid = pid;
1220 return fp;
1221}
1222
Dan Albert3037ea42016-10-06 15:46:45 -07001223namespace {
1224
1225namespace phony {
1226#include <bits/struct_file.h>
1227}
1228
1229static_assert(sizeof(::__sFILE) == sizeof(phony::__sFILE),
1230 "size mismatch between `struct __sFILE` implementation and public stub");
1231static_assert(alignof(::__sFILE) == alignof(phony::__sFILE),
1232 "alignment mismatch between `struct __sFILE` implementation and public stub");
1233
1234}