blob: d7b69dcb5231b7f61e7c28a3272ed4884cadba8d [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 Gaof6e5b582018-06-01 15:30:54 -070049#include <android/fdsan.h>
50
Josh Gaod1620602017-10-05 13:48:08 -070051#include <async_safe/log.h>
52
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080053#include "local.h"
54#include "glue.h"
Elliott Hughesfb3873d2016-08-10 11:07:54 -070055#include "private/bionic_fortify.h"
Elliott Hughes023c3072016-01-22 15:04:51 -080056#include "private/ErrnoRestorer.h"
Elliott Hughes6a03abc2014-11-03 12:32:17 -080057#include "private/thread_private.h"
58
Josh Gaof6e5b582018-06-01 15:30:54 -070059extern "C" int ___close(int fd);
60
Elliott Hughes6a03abc2014-11-03 12:32:17 -080061#define ALIGNBYTES (sizeof(uintptr_t) - 1)
62#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
Calin Juravlec20de902014-03-20 15:21:32 +000063
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080064#define NDYNAMIC 10 /* add ten more whenever necessary */
65
Elliott Hughes70715da2016-08-01 16:35:17 -070066#define PRINTF_IMPL(expr) \
67 va_list ap; \
68 va_start(ap, fmt); \
69 int result = (expr); \
70 va_end(ap); \
71 return result;
72
Elliott Hughes468efc82018-07-10 14:39:49 -070073#define MAKE_STD_STREAM(flags, fd) \
74 { \
75 ._flags = flags, ._file = fd, ._cookie = __sF + fd, ._close = __sclose, \
76 ._read = __sread, ._write = __swrite, ._ext = { \
77 ._base = reinterpret_cast<uint8_t*>(__sFext + fd) \
78 } \
79 }
Elliott Hughes29ee6392015-12-07 11:07:15 -080080
Elliott Hughesbb46afd2015-12-04 18:03:12 -080081static struct __sfileext __sFext[3] = {
Elliott Hughes468efc82018-07-10 14:39:49 -070082 {._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},
90 {._lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
91 ._caller_handles_locking = false,
92 ._seek64 = __sseek64,
93 ._popen_pid = 0},
Elliott Hughesbb46afd2015-12-04 18:03:12 -080094};
Elliott Hughesf0141df2015-10-12 12:44:23 -070095
96// __sF is exported for backwards compatibility. Until M, we didn't have symbols
97// for stdin/stdout/stderr; they were macros accessing __sF.
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080098FILE __sF[3] = {
Elliott Hughes468efc82018-07-10 14:39:49 -070099 MAKE_STD_STREAM(__SRD, STDIN_FILENO),
100 MAKE_STD_STREAM(__SWR, STDOUT_FILENO),
101 MAKE_STD_STREAM(__SWR|__SNBF, STDERR_FILENO),
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800102};
Elliott Hughesf0141df2015-10-12 12:44:23 -0700103
Elliott Hughes168667c2014-11-14 14:42:59 -0800104FILE* stdin = &__sF[0];
105FILE* stdout = &__sF[1];
106FILE* stderr = &__sF[2];
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800107
Elliott Hughes468efc82018-07-10 14:39:49 -0700108static pthread_mutex_t __stdio_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
Josh Gaof6e5b582018-06-01 15:30:54 -0700109
110static uint64_t __get_file_tag(FILE* fp) {
111 // Don't use a tag for the standard streams.
112 // They don't really own their file descriptors, because the values are well-known, and you're
113 // allowed to do things like `close(STDIN_FILENO); open("foo", O_RDONLY)` when single-threaded.
114 if (fp == stdin || fp == stderr || fp == stdout) {
115 return 0;
116 }
117
118 return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_FILE,
119 reinterpret_cast<uint64_t>(fp));
120}
121
Elliott Hughes37ad9592017-10-30 17:47:12 -0700122struct glue __sglue = { nullptr, 3, __sF };
Elliott Hughesbb46afd2015-12-04 18:03:12 -0800123static struct glue* lastglue = &__sglue;
124
Elliott Hughes2704bd12016-01-20 17:14:53 -0800125class ScopedFileLock {
126 public:
Chih-Hung Hsieh62e3a072016-05-03 12:08:05 -0700127 explicit ScopedFileLock(FILE* fp) : fp_(fp) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800128 FLOCKFILE(fp_);
129 }
130 ~ScopedFileLock() {
131 FUNLOCKFILE(fp_);
132 }
133
134 private:
135 FILE* fp_;
136};
137
Elliott Hughes021335e2016-01-19 16:28:15 -0800138static glue* moreglue(int n) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800139 char* data = new char[sizeof(glue) + ALIGNBYTES + n * sizeof(FILE) + n * sizeof(__sfileext)];
140 if (data == nullptr) return nullptr;
Elliott Hughes021335e2016-01-19 16:28:15 -0800141
Elliott Hughes2704bd12016-01-20 17:14:53 -0800142 glue* g = reinterpret_cast<glue*>(data);
143 FILE* p = reinterpret_cast<FILE*>(ALIGN(data + sizeof(*g)));
144 __sfileext* pext = reinterpret_cast<__sfileext*>(ALIGN(data + sizeof(*g)) + n * sizeof(FILE));
Elliott Hughes37ad9592017-10-30 17:47:12 -0700145 g->next = nullptr;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800146 g->niobs = n;
147 g->iobs = p;
148 while (--n >= 0) {
Elliott Hughes468efc82018-07-10 14:39:49 -0700149 *p = {};
Elliott Hughes2704bd12016-01-20 17:14:53 -0800150 _FILEEXT_SETUP(p, pext);
151 p++;
152 pext++;
153 }
154 return g;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800155}
156
Elliott Hughes80e4c152017-07-21 13:57:55 -0700157static inline void free_fgetln_buffer(FILE* fp) {
158 if (__predict_false(fp->_lb._base != nullptr)) {
159 free(fp->_lb._base);
160 fp->_lb._base = nullptr;
161 }
162}
163
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800164/*
165 * Find a free FILE for fopen et al.
166 */
Elliott Hughes021335e2016-01-19 16:28:15 -0800167FILE* __sfp(void) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800168 FILE *fp;
169 int n;
170 struct glue *g;
171
Elliott Hughes468efc82018-07-10 14:39:49 -0700172 pthread_mutex_lock(&__stdio_mutex);
Elliott Hughes37ad9592017-10-30 17:47:12 -0700173 for (g = &__sglue; g != nullptr; g = g->next) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800174 for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
175 if (fp->_flags == 0)
176 goto found;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800177 }
Kenny Rootf5823402011-02-12 07:13:44 -0800178
179 /* release lock while mallocing */
Elliott Hughes468efc82018-07-10 14:39:49 -0700180 pthread_mutex_unlock(&__stdio_mutex);
Elliott Hughes37ad9592017-10-30 17:47:12 -0700181 if ((g = moreglue(NDYNAMIC)) == nullptr) return nullptr;
Elliott Hughes468efc82018-07-10 14:39:49 -0700182 pthread_mutex_lock(&__stdio_mutex);
Kenny Rootf5823402011-02-12 07:13:44 -0800183 lastglue->next = g;
184 lastglue = g;
185 fp = g->iobs;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800186found:
187 fp->_flags = 1; /* reserve this slot; caller sets real flags */
Elliott Hughes468efc82018-07-10 14:39:49 -0700188 pthread_mutex_unlock(&__stdio_mutex);
Elliott Hughes37ad9592017-10-30 17:47:12 -0700189 fp->_p = nullptr; /* no current pointer */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800190 fp->_w = 0; /* nothing to read or write */
191 fp->_r = 0;
Elliott Hughes37ad9592017-10-30 17:47:12 -0700192 fp->_bf._base = nullptr; /* no buffer */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800193 fp->_bf._size = 0;
194 fp->_lbfsize = 0; /* not line buffered */
195 fp->_file = -1; /* no file */
Elliott Hughes023c3072016-01-22 15:04:51 -0800196
Elliott Hughes37ad9592017-10-30 17:47:12 -0700197 fp->_lb._base = nullptr; /* no line buffer */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800198 fp->_lb._size = 0;
Elliott Hughes1a56a262017-12-20 08:53:49 -0800199
200 memset(_EXT(fp), 0, sizeof(struct __sfileext));
201 _FLOCK(fp) = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
202 _EXT(fp)->_caller_handles_locking = false;
Elliott Hughes023c3072016-01-22 15:04:51 -0800203
204 // Caller sets cookie, _read/_write etc.
205 // We explicitly clear _seek and _seek64 to prevent subtle bugs.
206 fp->_seek = nullptr;
207 _EXT(fp)->_seek64 = nullptr;
208
209 return fp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800210}
211
Elliott Hughes468efc82018-07-10 14:39:49 -0700212int _fwalk(int (*callback)(FILE*)) {
213 pthread_mutex_lock(&__stdio_mutex);
214 int result = 0;
215 for (glue* g = &__sglue; g != nullptr; g = g->next) {
216 FILE* fp = g->iobs;
217 for (int n = g->niobs; --n >= 0; ++fp) {
218 ScopedFileLock sfl(fp);
219 if (fp->_flags != 0 && (fp->_flags & __SIGN) == 0) {
220 result |= (*callback)(fp);
221 }
222 }
223 }
224 pthread_mutex_unlock(&__stdio_mutex);
225 return result;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800226}
Elliott Hughes923f1652016-01-19 15:46:05 -0800227
Elliott Hughes023c3072016-01-22 15:04:51 -0800228static FILE* __fopen(int fd, int flags) {
229#if !defined(__LP64__)
230 if (fd > SHRT_MAX) {
231 errno = EMFILE;
232 return nullptr;
233 }
234#endif
235
236 FILE* fp = __sfp();
237 if (fp != nullptr) {
238 fp->_file = fd;
Josh Gaof6e5b582018-06-01 15:30:54 -0700239 android_fdsan_exchange_owner_tag(fd, 0, __get_file_tag(fp));
Elliott Hughes023c3072016-01-22 15:04:51 -0800240 fp->_flags = flags;
241 fp->_cookie = fp;
242 fp->_read = __sread;
243 fp->_write = __swrite;
244 fp->_close = __sclose;
245 _EXT(fp)->_seek64 = __sseek64;
246 }
247 return fp;
248}
249
250FILE* fopen(const char* file, const char* mode) {
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700251 int mode_flags;
252 int flags = __sflags(mode, &mode_flags);
Elliott Hughes023c3072016-01-22 15:04:51 -0800253 if (flags == 0) return nullptr;
254
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700255 int fd = open(file, mode_flags, DEFFILEMODE);
Elliott Hughes023c3072016-01-22 15:04:51 -0800256 if (fd == -1) {
257 return nullptr;
258 }
259
260 FILE* fp = __fopen(fd, flags);
261 if (fp == nullptr) {
262 ErrnoRestorer errno_restorer;
263 close(fd);
264 return nullptr;
265 }
266
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700267 // For append mode, even though we use O_APPEND, we need to seek to the end now.
268 if ((mode_flags & O_APPEND) != 0) __sseek64(fp, 0, SEEK_END);
Elliott Hughes023c3072016-01-22 15:04:51 -0800269 return fp;
270}
Elliott Hughesf226ee52016-02-03 11:24:28 -0800271__strong_alias(fopen64, fopen);
Elliott Hughes023c3072016-01-22 15:04:51 -0800272
273FILE* fdopen(int fd, const char* mode) {
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700274 int mode_flags;
275 int flags = __sflags(mode, &mode_flags);
Elliott Hughes023c3072016-01-22 15:04:51 -0800276 if (flags == 0) return nullptr;
277
278 // Make sure the mode the user wants is a subset of the actual mode.
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700279 int fd_flags = fcntl(fd, F_GETFL, 0);
280 if (fd_flags == -1) return nullptr;
281 int tmp = fd_flags & O_ACCMODE;
282 if (tmp != O_RDWR && (tmp != (mode_flags & O_ACCMODE))) {
Elliott Hughes023c3072016-01-22 15:04:51 -0800283 errno = EINVAL;
284 return nullptr;
285 }
286
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700287 // Make sure O_APPEND is set on the underlying fd if our mode has 'a'.
288 // POSIX says we just take the current offset of the underlying fd.
289 if ((mode_flags & O_APPEND) && !(fd_flags & O_APPEND)) {
290 if (fcntl(fd, F_SETFL, fd_flags | O_APPEND) == -1) return nullptr;
291 }
Elliott Hughes023c3072016-01-22 15:04:51 -0800292
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700293 // Make sure O_CLOEXEC is set on the underlying fd if our mode has 'x'.
294 if ((mode_flags & O_CLOEXEC) && !((tmp = fcntl(fd, F_GETFD)) & FD_CLOEXEC)) {
Elliott Hughes023c3072016-01-22 15:04:51 -0800295 fcntl(fd, F_SETFD, tmp | FD_CLOEXEC);
296 }
297
298 return __fopen(fd, flags);
299}
300
301// Re-direct an existing, open (probably) file to some other file.
302// ANSI is written such that the original file gets closed if at
303// all possible, no matter what.
304// TODO: rewrite this mess completely.
305FILE* freopen(const char* file, const char* mode, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700306 CHECK_FP(fp);
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700307 int mode_flags;
308 int flags = __sflags(mode, &mode_flags);
Elliott Hughes023c3072016-01-22 15:04:51 -0800309 if (flags == 0) {
310 fclose(fp);
311 return nullptr;
312 }
313
314 ScopedFileLock sfl(fp);
315
316 // There are actually programs that depend on being able to "freopen"
317 // descriptors that weren't originally open. Keep this from breaking.
318 // Remember whether the stream was open to begin with, and which file
319 // descriptor (if any) was associated with it. If it was attached to
320 // a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
321 // should work. This is unnecessary if it was not a Unix file.
322 int isopen, wantfd;
323 if (fp->_flags == 0) {
324 fp->_flags = __SEOF; // Hold on to it.
325 isopen = 0;
326 wantfd = -1;
327 } else {
328 // Flush the stream; ANSI doesn't require this.
329 if (fp->_flags & __SWR) __sflush(fp);
330
Elliott Hughes37ad9592017-10-30 17:47:12 -0700331 // If close is null, closing is a no-op, hence pointless.
332 isopen = (fp->_close != nullptr);
Elliott Hughes023c3072016-01-22 15:04:51 -0800333 if ((wantfd = fp->_file) < 0 && isopen) {
334 (*fp->_close)(fp->_cookie);
335 isopen = 0;
336 }
337 }
338
339 // Get a new descriptor to refer to the new file.
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700340 int fd = open(file, mode_flags, DEFFILEMODE);
Elliott Hughes023c3072016-01-22 15:04:51 -0800341 if (fd < 0 && isopen) {
342 // If out of fd's close the old one and try again.
343 if (errno == ENFILE || errno == EMFILE) {
344 (*fp->_close)(fp->_cookie);
345 isopen = 0;
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700346 fd = open(file, mode_flags, DEFFILEMODE);
Elliott Hughes023c3072016-01-22 15:04:51 -0800347 }
348 }
349
350 int sverrno = errno;
351
352 // Finish closing fp. Even if the open succeeded above, we cannot
353 // keep fp->_base: it may be the wrong size. This loses the effect
354 // of any setbuffer calls, but stdio has always done this before.
355 if (isopen && fd != wantfd) (*fp->_close)(fp->_cookie);
356 if (fp->_flags & __SMBF) free(fp->_bf._base);
357 fp->_w = 0;
358 fp->_r = 0;
Elliott Hughes37ad9592017-10-30 17:47:12 -0700359 fp->_p = nullptr;
360 fp->_bf._base = nullptr;
Elliott Hughes023c3072016-01-22 15:04:51 -0800361 fp->_bf._size = 0;
362 fp->_lbfsize = 0;
363 if (HASUB(fp)) FREEUB(fp);
364 _UB(fp)._size = 0;
365 WCIO_FREE(fp);
Elliott Hughes80e4c152017-07-21 13:57:55 -0700366 free_fgetln_buffer(fp);
Elliott Hughes023c3072016-01-22 15:04:51 -0800367 fp->_lb._size = 0;
368
369 if (fd < 0) { // Did not get it after all.
370 fp->_flags = 0; // Release.
371 errno = sverrno; // Restore errno in case _close clobbered it.
372 return nullptr;
373 }
374
375 // If reopening something that was open before on a real file, try
376 // to maintain the descriptor. Various C library routines (perror)
377 // assume stderr is always fd STDERR_FILENO, even if being freopen'd.
378 if (wantfd >= 0 && fd != wantfd) {
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700379 if (dup3(fd, wantfd, mode_flags & O_CLOEXEC) >= 0) {
Elliott Hughes023c3072016-01-22 15:04:51 -0800380 close(fd);
381 fd = wantfd;
382 }
383 }
384
385 // _file is only a short.
386 if (fd > SHRT_MAX) {
387 fp->_flags = 0; // Release.
388 errno = EMFILE;
389 return nullptr;
390 }
391
392 fp->_flags = flags;
393 fp->_file = fd;
Josh Gaof6e5b582018-06-01 15:30:54 -0700394 android_fdsan_exchange_owner_tag(fd, 0, __get_file_tag(fp));
Elliott Hughes023c3072016-01-22 15:04:51 -0800395 fp->_cookie = fp;
396 fp->_read = __sread;
397 fp->_write = __swrite;
398 fp->_close = __sclose;
399 _EXT(fp)->_seek64 = __sseek64;
400
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700401 // For append mode, even though we use O_APPEND, we need to seek to the end now.
402 if ((mode_flags & O_APPEND) != 0) __sseek64(fp, 0, SEEK_END);
Elliott Hughes023c3072016-01-22 15:04:51 -0800403 return fp;
404}
Elliott Hughesf226ee52016-02-03 11:24:28 -0800405__strong_alias(freopen64, freopen);
Elliott Hughes023c3072016-01-22 15:04:51 -0800406
Elliott Hughes22917f62018-10-01 14:21:07 -0700407static int __FILE_close(FILE* fp) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800408 if (fp->_flags == 0) {
409 // Already freed!
410 errno = EBADF;
411 return EOF;
412 }
Elliott Hughes923f1652016-01-19 15:46:05 -0800413
Elliott Hughes2704bd12016-01-20 17:14:53 -0800414 ScopedFileLock sfl(fp);
415 WCIO_FREE(fp);
416 int r = fp->_flags & __SWR ? __sflush(fp) : 0;
Elliott Hughes37ad9592017-10-30 17:47:12 -0700417 if (fp->_close != nullptr && (*fp->_close)(fp->_cookie) < 0) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800418 r = EOF;
419 }
420 if (fp->_flags & __SMBF) free(fp->_bf._base);
421 if (HASUB(fp)) FREEUB(fp);
Elliott Hughes80e4c152017-07-21 13:57:55 -0700422 free_fgetln_buffer(fp);
Elliott Hughes923f1652016-01-19 15:46:05 -0800423
Elliott Hughes468efc82018-07-10 14:39:49 -0700424 // If we were created by popen(3), wait for the child.
425 pid_t pid = _EXT(fp)->_popen_pid;
426 if (pid > 0) {
427 int status;
428 if (TEMP_FAILURE_RETRY(wait4(pid, &status, 0, nullptr)) != -1) {
429 r = status;
430 }
431 }
432 _EXT(fp)->_popen_pid = 0;
433
Elliott Hughes2704bd12016-01-20 17:14:53 -0800434 // Poison this FILE so accesses after fclose will be obvious.
435 fp->_file = -1;
436 fp->_r = fp->_w = 0;
Elliott Hughes923f1652016-01-19 15:46:05 -0800437
Elliott Hughes2704bd12016-01-20 17:14:53 -0800438 // Release this FILE for reuse.
439 fp->_flags = 0;
440 return r;
Elliott Hughes923f1652016-01-19 15:46:05 -0800441}
Elliott Hughes22917f62018-10-01 14:21:07 -0700442
443int fclose(FILE* fp) {
444 CHECK_FP(fp);
445 return __FILE_close(fp);
446}
Elliott Hughes923f1652016-01-19 15:46:05 -0800447
Elliott Hughescceaf062016-07-29 16:31:52 -0700448int fileno_unlocked(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700449 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700450 int fd = fp->_file;
451 if (fd == -1) {
452 errno = EBADF;
453 return -1;
454 }
455 return fd;
456}
457
Elliott Hughes923f1652016-01-19 15:46:05 -0800458int fileno(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700459 CHECK_FP(fp);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800460 ScopedFileLock sfl(fp);
461 return fileno_unlocked(fp);
Elliott Hughes923f1652016-01-19 15:46:05 -0800462}
Elliott Hughes021335e2016-01-19 16:28:15 -0800463
Elliott Hughescceaf062016-07-29 16:31:52 -0700464void clearerr_unlocked(FILE* fp) {
Elliott Hughes22917f62018-10-01 14:21:07 -0700465 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700466 return __sclearerr(fp);
467}
468
469void clearerr(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700470 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700471 ScopedFileLock sfl(fp);
472 clearerr_unlocked(fp);
473}
474
475int feof_unlocked(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700476 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700477 return ((fp->_flags & __SEOF) != 0);
Elliott Hughescceaf062016-07-29 16:31:52 -0700478}
479
480int feof(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700481 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700482 ScopedFileLock sfl(fp);
483 return feof_unlocked(fp);
484}
485
486int ferror_unlocked(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700487 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700488 return __sferror(fp);
489}
490
491int ferror(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700492 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700493 ScopedFileLock sfl(fp);
494 return ferror_unlocked(fp);
495}
496
Elliott Hughes37ad9592017-10-30 17:47:12 -0700497int __sflush(FILE* fp) {
498 // Flushing a read-only file is a no-op.
499 if ((fp->_flags & __SWR) == 0) return 0;
500
501 // Flushing a file without a buffer is a no-op.
502 unsigned char* p = fp->_bf._base;
503 if (p == nullptr) return 0;
504
505 // Set these immediately to avoid problems with longjmp and to allow
506 // exchange buffering (via setvbuf) in user write function.
507 int n = fp->_p - p;
508 fp->_p = p;
509 fp->_w = (fp->_flags & (__SLBF|__SNBF)) ? 0 : fp->_bf._size;
510
511 while (n > 0) {
512 int written = (*fp->_write)(fp->_cookie, reinterpret_cast<char*>(p), n);
513 if (written <= 0) {
514 fp->_flags |= __SERR;
515 return EOF;
516 }
517 n -= written, p += written;
518 }
519 return 0;
520}
521
Elliott Hughes021335e2016-01-19 16:28:15 -0800522int __sread(void* cookie, char* buf, int n) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800523 FILE* fp = reinterpret_cast<FILE*>(cookie);
524 return TEMP_FAILURE_RETRY(read(fp->_file, buf, n));
Elliott Hughes021335e2016-01-19 16:28:15 -0800525}
526
527int __swrite(void* cookie, const char* buf, int n) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800528 FILE* fp = reinterpret_cast<FILE*>(cookie);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800529 return TEMP_FAILURE_RETRY(write(fp->_file, buf, n));
Elliott Hughes021335e2016-01-19 16:28:15 -0800530}
531
Elliott Hughes021335e2016-01-19 16:28:15 -0800532fpos_t __sseek(void* cookie, fpos_t offset, int whence) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800533 FILE* fp = reinterpret_cast<FILE*>(cookie);
534 return TEMP_FAILURE_RETRY(lseek(fp->_file, offset, whence));
Elliott Hughes021335e2016-01-19 16:28:15 -0800535}
536
Elliott Hughes023c3072016-01-22 15:04:51 -0800537off64_t __sseek64(void* cookie, off64_t offset, int whence) {
538 FILE* fp = reinterpret_cast<FILE*>(cookie);
539 return TEMP_FAILURE_RETRY(lseek64(fp->_file, offset, whence));
540}
541
Elliott Hughes021335e2016-01-19 16:28:15 -0800542int __sclose(void* cookie) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800543 FILE* fp = reinterpret_cast<FILE*>(cookie);
Josh Gaof6e5b582018-06-01 15:30:54 -0700544 return android_fdsan_close_with_tag(fp->_file, __get_file_tag(fp));
Elliott Hughes2704bd12016-01-20 17:14:53 -0800545}
546
Elliott Hughes023c3072016-01-22 15:04:51 -0800547static off64_t __seek_unlocked(FILE* fp, off64_t offset, int whence) {
548 // Use `_seek64` if set, but fall back to `_seek`.
549 if (_EXT(fp)->_seek64 != nullptr) {
550 return (*_EXT(fp)->_seek64)(fp->_cookie, offset, whence);
551 } else if (fp->_seek != nullptr) {
Elliott Hughes955426e2016-01-26 18:25:52 -0800552 off64_t result = (*fp->_seek)(fp->_cookie, offset, whence);
553#if !defined(__LP64__)
554 // Avoid sign extension if off64_t is larger than off_t.
555 if (result != -1) result &= 0xffffffff;
556#endif
557 return result;
Elliott Hughes023c3072016-01-22 15:04:51 -0800558 } else {
559 errno = ESPIPE;
560 return -1;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800561 }
Elliott Hughes2704bd12016-01-20 17:14:53 -0800562}
563
Elliott Hughes9677fab2016-01-25 15:50:59 -0800564static off64_t __ftello64_unlocked(FILE* fp) {
Elliott Hughes023c3072016-01-22 15:04:51 -0800565 // Find offset of underlying I/O object, then adjust for buffered bytes.
Elliott Hughes2704bd12016-01-20 17:14:53 -0800566 __sflush(fp); // May adjust seek offset on append stream.
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700567
Elliott Hughes9677fab2016-01-25 15:50:59 -0800568 off64_t result = __seek_unlocked(fp, 0, SEEK_CUR);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800569 if (result == -1) {
570 return -1;
571 }
572
573 if (fp->_flags & __SRD) {
574 // Reading. Any unread characters (including
575 // those from ungetc) cause the position to be
576 // smaller than that in the underlying object.
577 result -= fp->_r;
578 if (HASUB(fp)) result -= fp->_ur;
Elliott Hughes37ad9592017-10-30 17:47:12 -0700579 } else if (fp->_flags & __SWR && fp->_p != nullptr) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800580 // Writing. Any buffered characters cause the
581 // position to be greater than that in the
582 // underlying object.
583 result += fp->_p - fp->_bf._base;
584 }
585 return result;
586}
587
Elliott Hughes9677fab2016-01-25 15:50:59 -0800588int __fseeko64(FILE* fp, off64_t offset, int whence, int off_t_bits) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800589 ScopedFileLock sfl(fp);
590
Elliott Hughes023c3072016-01-22 15:04:51 -0800591 // Change any SEEK_CUR to SEEK_SET, and check `whence` argument.
Elliott Hughes2704bd12016-01-20 17:14:53 -0800592 // After this, whence is either SEEK_SET or SEEK_END.
593 if (whence == SEEK_CUR) {
Elliott Hughes9677fab2016-01-25 15:50:59 -0800594 fpos64_t current_offset = __ftello64_unlocked(fp);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800595 if (current_offset == -1) {
Elliott Hughes9677fab2016-01-25 15:50:59 -0800596 return -1;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800597 }
598 offset += current_offset;
599 whence = SEEK_SET;
600 } else if (whence != SEEK_SET && whence != SEEK_END) {
601 errno = EINVAL;
Elliott Hughes9677fab2016-01-25 15:50:59 -0800602 return -1;
603 }
604
605 // If our caller has a 32-bit interface, refuse to go past a 32-bit file offset.
606 if (off_t_bits == 32 && offset > LONG_MAX) {
607 errno = EOVERFLOW;
608 return -1;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800609 }
610
Elliott Hughes37ad9592017-10-30 17:47:12 -0700611 if (fp->_bf._base == nullptr) __smakebuf(fp);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800612
613 // Flush unwritten data and attempt the seek.
Elliott Hughes023c3072016-01-22 15:04:51 -0800614 if (__sflush(fp) || __seek_unlocked(fp, offset, whence) == -1) {
Elliott Hughes9677fab2016-01-25 15:50:59 -0800615 return -1;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800616 }
617
618 // Success: clear EOF indicator and discard ungetc() data.
619 if (HASUB(fp)) FREEUB(fp);
620 fp->_p = fp->_bf._base;
621 fp->_r = 0;
622 /* fp->_w = 0; */ /* unnecessary (I think...) */
623 fp->_flags &= ~__SEOF;
624 return 0;
625}
626
Elliott Hughes9677fab2016-01-25 15:50:59 -0800627int fseeko(FILE* fp, off_t offset, int whence) {
Josh Gaod1620602017-10-05 13:48:08 -0700628 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800629 static_assert(sizeof(off_t) == sizeof(long), "sizeof(off_t) != sizeof(long)");
630 return __fseeko64(fp, offset, whence, 8*sizeof(off_t));
631}
632__strong_alias(fseek, fseeko);
633
634int fseeko64(FILE* fp, off64_t offset, int whence) {
Josh Gaod1620602017-10-05 13:48:08 -0700635 CHECK_FP(fp);
Ryan Prichardbf549862017-11-07 15:30:32 -0800636 return __fseeko64(fp, offset, whence, 8*sizeof(off64_t));
Elliott Hughes2704bd12016-01-20 17:14:53 -0800637}
638
Elliott Hughes9677fab2016-01-25 15:50:59 -0800639int fsetpos(FILE* fp, const fpos_t* pos) {
Josh Gaod1620602017-10-05 13:48:08 -0700640 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800641 return fseeko(fp, *pos, SEEK_SET);
642}
643
644int fsetpos64(FILE* fp, const fpos64_t* pos) {
Josh Gaod1620602017-10-05 13:48:08 -0700645 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800646 return fseeko64(fp, *pos, SEEK_SET);
647}
648
Elliott Hughes2704bd12016-01-20 17:14:53 -0800649off_t ftello(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700650 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800651 static_assert(sizeof(off_t) == sizeof(long), "sizeof(off_t) != sizeof(long)");
652 off64_t result = ftello64(fp);
653 if (result > LONG_MAX) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800654 errno = EOVERFLOW;
655 return -1;
656 }
Elliott Hughes9677fab2016-01-25 15:50:59 -0800657 return result;
658}
659__strong_alias(ftell, ftello);
660
661off64_t ftello64(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700662 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800663 ScopedFileLock sfl(fp);
664 return __ftello64_unlocked(fp);
Elliott Hughes021335e2016-01-19 16:28:15 -0800665}
Elliott Hughes023c3072016-01-22 15:04:51 -0800666
Elliott Hughes023c3072016-01-22 15:04:51 -0800667int fgetpos(FILE* fp, fpos_t* pos) {
Josh Gaod1620602017-10-05 13:48:08 -0700668 CHECK_FP(fp);
Elliott Hughes023c3072016-01-22 15:04:51 -0800669 *pos = ftello(fp);
Elliott Hughes955426e2016-01-26 18:25:52 -0800670 return (*pos == -1) ? -1 : 0;
Elliott Hughes023c3072016-01-22 15:04:51 -0800671}
672
Elliott Hughes9677fab2016-01-25 15:50:59 -0800673int fgetpos64(FILE* fp, fpos64_t* pos) {
Josh Gaod1620602017-10-05 13:48:08 -0700674 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800675 *pos = ftello64(fp);
Elliott Hughes955426e2016-01-26 18:25:52 -0800676 return (*pos == -1) ? -1 : 0;
Elliott Hughes023c3072016-01-22 15:04:51 -0800677}
Elliott Hughes03e65eb2016-01-26 14:13:04 -0800678
679static FILE* __funopen(const void* cookie,
680 int (*read_fn)(void*, char*, int),
681 int (*write_fn)(void*, const char*, int),
682 int (*close_fn)(void*)) {
683 if (read_fn == nullptr && write_fn == nullptr) {
684 errno = EINVAL;
685 return nullptr;
686 }
687
688 FILE* fp = __sfp();
689 if (fp == nullptr) return nullptr;
690
691 if (read_fn != nullptr && write_fn != nullptr) {
692 fp->_flags = __SRW;
693 } else if (read_fn != nullptr) {
694 fp->_flags = __SRD;
695 } else if (write_fn != nullptr) {
696 fp->_flags = __SWR;
697 }
698
699 fp->_file = -1;
700 fp->_cookie = const_cast<void*>(cookie); // The funopen(3) API is incoherent.
701 fp->_read = read_fn;
702 fp->_write = write_fn;
703 fp->_close = close_fn;
704
705 return fp;
706}
707
708FILE* funopen(const void* cookie,
709 int (*read_fn)(void*, char*, int),
710 int (*write_fn)(void*, const char*, int),
711 fpos_t (*seek_fn)(void*, fpos_t, int),
712 int (*close_fn)(void*)) {
713 FILE* fp = __funopen(cookie, read_fn, write_fn, close_fn);
714 if (fp != nullptr) {
715 fp->_seek = seek_fn;
716 }
717 return fp;
718}
719
720FILE* funopen64(const void* cookie,
721 int (*read_fn)(void*, char*, int),
722 int (*write_fn)(void*, const char*, int),
723 fpos64_t (*seek_fn)(void*, fpos64_t, int),
724 int (*close_fn)(void*)) {
725 FILE* fp = __funopen(cookie, read_fn, write_fn, close_fn);
726 if (fp != nullptr) {
727 _EXT(fp)->_seek64 = seek_fn;
728 }
729 return fp;
730}
Elliott Hughes20788ae2016-06-09 15:16:32 -0700731
Elliott Hughes53cf3482016-08-09 13:06:41 -0700732int asprintf(char** s, const char* fmt, ...) {
733 PRINTF_IMPL(vasprintf(s, fmt, ap));
734}
735
Elliott Hughes20788ae2016-06-09 15:16:32 -0700736char* ctermid(char* s) {
737 return s ? strcpy(s, _PATH_TTY) : const_cast<char*>(_PATH_TTY);
738}
Elliott Hughescceaf062016-07-29 16:31:52 -0700739
Elliott Hughes70715da2016-08-01 16:35:17 -0700740int dprintf(int fd, const char* fmt, ...) {
741 PRINTF_IMPL(vdprintf(fd, fmt, ap));
742}
743
744int fprintf(FILE* fp, const char* fmt, ...) {
Josh Gaod1620602017-10-05 13:48:08 -0700745 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700746 PRINTF_IMPL(vfprintf(fp, fmt, ap));
747}
748
Elliott Hughescceaf062016-07-29 16:31:52 -0700749int fgetc(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700750 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700751 return getc(fp);
752}
753
Elliott Hughes37ad9592017-10-30 17:47:12 -0700754int fgetc_unlocked(FILE* fp) {
755 CHECK_FP(fp);
756 return getc_unlocked(fp);
757}
758
George Burgess IV90242352018-02-06 12:51:31 -0800759char* fgets(char* buf, int n, FILE* fp) {
Elliott Hughes37ad9592017-10-30 17:47:12 -0700760 CHECK_FP(fp);
761 ScopedFileLock sfl(fp);
762 return fgets_unlocked(buf, n, fp);
763}
764
Elliott Hughes468efc82018-07-10 14:39:49 -0700765// Reads at most n-1 characters from the given file.
766// Stops when a newline has been read, or the count runs out.
767// Returns first argument, or nullptr if no characters were read.
768// Does not return nullptr if n == 1.
Elliott Hughes37ad9592017-10-30 17:47:12 -0700769char* fgets_unlocked(char* buf, int n, FILE* fp) {
770 if (n <= 0) {
771 errno = EINVAL;
772 return nullptr;
773 }
774
775 _SET_ORIENTATION(fp, -1);
776
777 char* s = buf;
778 n--; // Leave space for NUL.
779 while (n != 0) {
780 // If the buffer is empty, refill it.
781 if (fp->_r <= 0) {
782 if (__srefill(fp)) {
783 // EOF/error: stop with partial or no line.
784 if (s == buf) return nullptr;
785 break;
786 }
787 }
788 size_t len = fp->_r;
789 unsigned char* p = fp->_p;
790
791 // Scan through at most n bytes of the current buffer,
792 // looking for '\n'. If found, copy up to and including
793 // newline, and stop. Otherwise, copy entire chunk and loop.
794 if (len > static_cast<size_t>(n)) len = n;
795 unsigned char* t = static_cast<unsigned char*>(memchr(p, '\n', len));
796 if (t != nullptr) {
797 len = ++t - p;
798 fp->_r -= len;
799 fp->_p = t;
800 memcpy(s, p, len);
801 s[len] = '\0';
802 return buf;
803 }
804 fp->_r -= len;
805 fp->_p += len;
806 memcpy(s, p, len);
807 s += len;
808 n -= len;
809 }
810 *s = '\0';
811 return buf;
812}
813
Elliott Hughescceaf062016-07-29 16:31:52 -0700814int fputc(int c, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700815 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700816 return putc(c, fp);
817}
818
Elliott Hughes37ad9592017-10-30 17:47:12 -0700819int fputc_unlocked(int c, FILE* fp) {
820 CHECK_FP(fp);
821 return putc_unlocked(c, fp);
822}
823
824int fputs(const char* s, FILE* fp) {
825 CHECK_FP(fp);
826 ScopedFileLock sfl(fp);
827 return fputs_unlocked(s, fp);
828}
829
830int fputs_unlocked(const char* s, FILE* fp) {
831 CHECK_FP(fp);
832 size_t length = strlen(s);
833 return (fwrite_unlocked(s, 1, length, fp) == length) ? 0 : EOF;
834}
835
Elliott Hughes70715da2016-08-01 16:35:17 -0700836int fscanf(FILE* fp, const char* fmt, ...) {
Josh Gaod1620602017-10-05 13:48:08 -0700837 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700838 PRINTF_IMPL(vfscanf(fp, fmt, ap));
839}
840
841int fwprintf(FILE* fp, const wchar_t* fmt, ...) {
Josh Gaod1620602017-10-05 13:48:08 -0700842 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700843 PRINTF_IMPL(vfwprintf(fp, fmt, ap));
844}
845
846int fwscanf(FILE* fp, const wchar_t* fmt, ...) {
Josh Gaod1620602017-10-05 13:48:08 -0700847 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700848 PRINTF_IMPL(vfwscanf(fp, fmt, ap));
849}
850
851int getc(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700852 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700853 ScopedFileLock sfl(fp);
854 return getc_unlocked(fp);
855}
856
857int getc_unlocked(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700858 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700859 return __sgetc(fp);
860}
861
862int getchar_unlocked() {
863 return getc_unlocked(stdin);
864}
865
866int getchar() {
867 return getc(stdin);
868}
869
Elliott Hughescceaf062016-07-29 16:31:52 -0700870ssize_t getline(char** buf, size_t* len, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700871 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700872 return getdelim(buf, len, '\n', fp);
873}
874
875wint_t getwc(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700876 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700877 return fgetwc(fp);
878}
879
880wint_t getwchar() {
881 return fgetwc(stdin);
882}
883
Elliott Hughes37ad9592017-10-30 17:47:12 -0700884void perror(const char* msg) {
885 if (msg == nullptr) msg = "";
886 fprintf(stderr, "%s%s%s\n", msg, (*msg == '\0') ? "" : ": ", strerror(errno));
887}
888
Elliott Hughes70715da2016-08-01 16:35:17 -0700889int printf(const char* fmt, ...) {
890 PRINTF_IMPL(vfprintf(stdout, fmt, ap));
891}
892
893int putc(int c, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700894 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700895 ScopedFileLock sfl(fp);
896 return putc_unlocked(c, fp);
897}
898
899int putc_unlocked(int c, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700900 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700901 if (cantwrite(fp)) {
902 errno = EBADF;
903 return EOF;
904 }
905 _SET_ORIENTATION(fp, -1);
906 if (--fp->_w >= 0 || (fp->_w >= fp->_lbfsize && c != '\n')) {
907 return (*fp->_p++ = c);
908 }
909 return (__swbuf(c, fp));
910}
911
912int putchar(int c) {
913 return putc(c, stdout);
914}
915
916int putchar_unlocked(int c) {
917 return putc_unlocked(c, stdout);
918}
919
Elliott Hughes37ad9592017-10-30 17:47:12 -0700920int puts(const char* s) {
921 size_t length = strlen(s);
922 ScopedFileLock sfl(stdout);
923 return (fwrite_unlocked(s, 1, length, stdout) == length &&
924 putc_unlocked('\n', stdout) != EOF) ? 0 : EOF;
925}
926
Elliott Hughescceaf062016-07-29 16:31:52 -0700927wint_t putwc(wchar_t wc, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700928 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700929 return fputwc(wc, fp);
930}
931
932wint_t putwchar(wchar_t wc) {
933 return fputwc(wc, stdout);
934}
935
Elliott Hughesd1f25a72016-08-05 15:53:03 -0700936int remove(const char* path) {
937 if (unlink(path) != -1) return 0;
938 if (errno != EISDIR) return -1;
939 return rmdir(path);
940}
941
Elliott Hughescceaf062016-07-29 16:31:52 -0700942void rewind(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700943 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700944 ScopedFileLock sfl(fp);
945 fseek(fp, 0, SEEK_SET);
946 clearerr_unlocked(fp);
947}
948
Elliott Hughes70715da2016-08-01 16:35:17 -0700949int scanf(const char* fmt, ...) {
950 PRINTF_IMPL(vfscanf(stdin, fmt, ap));
951}
952
Elliott Hughescceaf062016-07-29 16:31:52 -0700953void setbuf(FILE* fp, char* buf) {
Josh Gaod1620602017-10-05 13:48:08 -0700954 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700955 setbuffer(fp, buf, BUFSIZ);
956}
957
958void setbuffer(FILE* fp, char* buf, int size) {
Josh Gaod1620602017-10-05 13:48:08 -0700959 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700960 setvbuf(fp, buf, buf ? _IOFBF : _IONBF, size);
961}
962
963int setlinebuf(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700964 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700965 return setvbuf(fp, nullptr, _IOLBF, 0);
966}
967
Elliott Hughes53cf3482016-08-09 13:06:41 -0700968int snprintf(char* s, size_t n, const char* fmt, ...) {
969 PRINTF_IMPL(vsnprintf(s, n, fmt, ap));
970}
971
972int sprintf(char* s, const char* fmt, ...) {
Elliott Hughesfb3873d2016-08-10 11:07:54 -0700973 PRINTF_IMPL(vsprintf(s, fmt, ap));
Elliott Hughes53cf3482016-08-09 13:06:41 -0700974}
975
976int sscanf(const char* s, const char* fmt, ...) {
977 PRINTF_IMPL(vsscanf(s, fmt, ap));
978}
979
Elliott Hughes70715da2016-08-01 16:35:17 -0700980int swprintf(wchar_t* s, size_t n, const wchar_t* fmt, ...) {
981 PRINTF_IMPL(vswprintf(s, n, fmt, ap));
982}
983
984int swscanf(const wchar_t* s, const wchar_t* fmt, ...) {
985 PRINTF_IMPL(vswscanf(s, fmt, ap));
986}
987
Elliott Hughes618303c2017-11-02 16:58:44 -0700988int vfprintf(FILE* fp, const char* fmt, va_list ap) {
989 ScopedFileLock sfl(fp);
990 return __vfprintf(fp, fmt, ap);
991}
992
Elliott Hughes345b7272017-11-10 16:20:43 -0800993int vfscanf(FILE* fp, const char* fmt, va_list ap) {
994 ScopedFileLock sfl(fp);
995 return __svfscanf(fp, fmt, ap);
996}
997
Elliott Hughes618303c2017-11-02 16:58:44 -0700998int vfwprintf(FILE* fp, const wchar_t* fmt, va_list ap) {
999 ScopedFileLock sfl(fp);
1000 return __vfwprintf(fp, fmt, ap);
1001}
1002
Elliott Hughes345b7272017-11-10 16:20:43 -08001003int vfwscanf(FILE* fp, const wchar_t* fmt, va_list ap) {
1004 ScopedFileLock sfl(fp);
1005 return __vfwscanf(fp, fmt, ap);
1006}
1007
Elliott Hughescceaf062016-07-29 16:31:52 -07001008int vprintf(const char* fmt, va_list ap) {
1009 return vfprintf(stdout, fmt, ap);
1010}
1011
1012int vscanf(const char* fmt, va_list ap) {
1013 return vfscanf(stdin, fmt, ap);
1014}
1015
Elliott Hughesfb3873d2016-08-10 11:07:54 -07001016int vsnprintf(char* s, size_t n, const char* fmt, va_list ap) {
1017 // stdio internals use int rather than size_t.
1018 static_assert(INT_MAX <= SSIZE_MAX, "SSIZE_MAX too large to fit in int");
1019
1020 __check_count("vsnprintf", "size", n);
1021
1022 // Stdio internals do not deal correctly with zero length buffer.
1023 char dummy;
1024 if (n == 0) {
1025 s = &dummy;
1026 n = 1;
1027 }
1028
1029 FILE f;
1030 __sfileext fext;
1031 _FILEEXT_SETUP(&f, &fext);
1032 f._file = -1;
1033 f._flags = __SWR | __SSTR;
1034 f._bf._base = f._p = reinterpret_cast<unsigned char*>(s);
1035 f._bf._size = f._w = n - 1;
1036
1037 int result = __vfprintf(&f, fmt, ap);
1038 *f._p = '\0';
1039 return result;
1040}
1041
Elliott Hughes53cf3482016-08-09 13:06:41 -07001042int vsprintf(char* s, const char* fmt, va_list ap) {
Elliott Hughesfb3873d2016-08-10 11:07:54 -07001043 return vsnprintf(s, SSIZE_MAX, fmt, ap);
Elliott Hughes53cf3482016-08-09 13:06:41 -07001044}
1045
Elliott Hughescceaf062016-07-29 16:31:52 -07001046int vwprintf(const wchar_t* fmt, va_list ap) {
1047 return vfwprintf(stdout, fmt, ap);
1048}
1049
1050int vwscanf(const wchar_t* fmt, va_list ap) {
1051 return vfwscanf(stdin, fmt, ap);
1052}
Elliott Hughes70715da2016-08-01 16:35:17 -07001053
1054int wprintf(const wchar_t* fmt, ...) {
1055 PRINTF_IMPL(vfwprintf(stdout, fmt, ap));
1056}
1057
1058int wscanf(const wchar_t* fmt, ...) {
1059 PRINTF_IMPL(vfwscanf(stdin, fmt, ap));
1060}
Dan Albert3037ea42016-10-06 15:46:45 -07001061
Elliott Hughes37ad9592017-10-30 17:47:12 -07001062static int fflush_all() {
Elliott Hughes468efc82018-07-10 14:39:49 -07001063 return _fwalk(__sflush);
Elliott Hughes37ad9592017-10-30 17:47:12 -07001064}
1065
1066int fflush(FILE* fp) {
1067 if (fp == nullptr) return fflush_all();
1068 ScopedFileLock sfl(fp);
1069 return fflush_unlocked(fp);
1070}
1071
1072int fflush_unlocked(FILE* fp) {
1073 if (fp == nullptr) return fflush_all();
1074 if ((fp->_flags & (__SWR | __SRW)) == 0) {
1075 errno = EBADF;
1076 return EOF;
1077 }
1078 return __sflush(fp);
1079}
1080
George Burgess IV90242352018-02-06 12:51:31 -08001081size_t fread(void* buf, size_t size, size_t count, FILE* fp) {
Elliott Hughes37ad9592017-10-30 17:47:12 -07001082 CHECK_FP(fp);
1083 ScopedFileLock sfl(fp);
1084 return fread_unlocked(buf, size, count, fp);
1085}
1086
1087size_t fread_unlocked(void* buf, size_t size, size_t count, FILE* fp) {
1088 CHECK_FP(fp);
1089
1090 size_t desired_total;
1091 if (__builtin_mul_overflow(size, count, &desired_total)) {
1092 errno = EOVERFLOW;
1093 fp->_flags |= __SERR;
1094 return 0;
1095 }
1096
1097 size_t total = desired_total;
1098 if (total == 0) return 0;
1099
1100 _SET_ORIENTATION(fp, -1);
1101
1102 // TODO: how can this ever happen?!
1103 if (fp->_r < 0) fp->_r = 0;
1104
1105 // Ensure _bf._size is valid.
1106 if (fp->_bf._base == nullptr) __smakebuf(fp);
1107
1108 char* dst = static_cast<char*>(buf);
1109
1110 while (total > 0) {
1111 // Copy data out of the buffer.
1112 size_t buffered_bytes = MIN(static_cast<size_t>(fp->_r), total);
1113 memcpy(dst, fp->_p, buffered_bytes);
1114 fp->_p += buffered_bytes;
1115 fp->_r -= buffered_bytes;
1116 dst += buffered_bytes;
1117 total -= buffered_bytes;
1118
1119 // Are we done?
1120 if (total == 0) goto out;
1121
1122 // Do we have so much more to read that we should avoid copying it through the buffer?
1123 if (total > static_cast<size_t>(fp->_bf._size)) break;
1124
1125 // Less than a buffer to go, so refill the buffer and go around the loop again.
1126 if (__srefill(fp)) goto out;
1127 }
1128
1129 // Read directly into the caller's buffer.
1130 while (total > 0) {
1131 ssize_t bytes_read = (*fp->_read)(fp->_cookie, dst, total);
1132 if (bytes_read <= 0) {
1133 fp->_flags |= (bytes_read == 0) ? __SEOF : __SERR;
1134 break;
1135 }
1136 dst += bytes_read;
1137 total -= bytes_read;
1138 }
1139
1140out:
1141 return ((desired_total - total) / size);
1142}
1143
1144size_t fwrite(const void* buf, size_t size, size_t count, FILE* fp) {
1145 CHECK_FP(fp);
1146 ScopedFileLock sfl(fp);
1147 return fwrite_unlocked(buf, size, count, fp);
1148}
1149
1150size_t fwrite_unlocked(const void* buf, size_t size, size_t count, FILE* fp) {
1151 CHECK_FP(fp);
1152
1153 size_t n;
1154 if (__builtin_mul_overflow(size, count, &n)) {
1155 errno = EOVERFLOW;
1156 fp->_flags |= __SERR;
1157 return 0;
1158 }
1159
1160 if (n == 0) return 0;
1161
1162 __siov iov = { .iov_base = const_cast<void*>(buf), .iov_len = n };
1163 __suio uio = { .uio_iov = &iov, .uio_iovcnt = 1, .uio_resid = n };
1164
1165 _SET_ORIENTATION(fp, -1);
1166
1167 // The usual case is success (__sfvwrite returns 0); skip the divide if this happens,
1168 // since divides are generally slow.
1169 return (__sfvwrite(fp, &uio) == 0) ? count : ((n - uio.uio_resid) / size);
1170}
1171
Elliott Hughes468efc82018-07-10 14:39:49 -07001172static int __close_if_popened(FILE* fp) {
1173 if (_EXT(fp)->_popen_pid > 0) close(fileno(fp));
1174 return 0;
1175}
1176
1177static FILE* __popen_fail(int fds[2]) {
1178 ErrnoRestorer errno_restorer;
1179 close(fds[0]);
1180 close(fds[1]);
1181 return nullptr;
1182}
1183
1184FILE* popen(const char* cmd, const char* mode) {
Elliott Hughes468efc82018-07-10 14:39:49 -07001185 // Was the request for a socketpair or just a pipe?
1186 int fds[2];
1187 bool bidirectional = false;
1188 if (strchr(mode, '+') != nullptr) {
1189 if (socketpair(AF_LOCAL, SOCK_CLOEXEC | SOCK_STREAM, 0, fds) == -1) return nullptr;
1190 bidirectional = true;
1191 mode = "r+";
1192 } else {
1193 if (pipe2(fds, O_CLOEXEC) == -1) return nullptr;
1194 mode = strrchr(mode, 'r') ? "r" : "w";
1195 }
1196
1197 // If the parent wants to read, the child's fd needs to be stdout.
1198 int parent, child, desired_child_fd;
1199 if (*mode == 'r') {
1200 parent = 0;
1201 child = 1;
1202 desired_child_fd = STDOUT_FILENO;
1203 } else {
1204 parent = 1;
1205 child = 0;
1206 desired_child_fd = STDIN_FILENO;
1207 }
1208
1209 // Ensure that the child fd isn't the desired child fd.
1210 if (fds[child] == desired_child_fd) {
1211 int new_fd = fcntl(fds[child], F_DUPFD_CLOEXEC, 0);
1212 if (new_fd == -1) return __popen_fail(fds);
1213 close(fds[child]);
1214 fds[child] = new_fd;
1215 }
1216
1217 pid_t pid = vfork();
1218 if (pid == -1) return __popen_fail(fds);
1219
1220 if (pid == 0) {
1221 close(fds[parent]);
1222 // POSIX says "The popen() function shall ensure that any streams from previous popen() calls
1223 // that remain open in the parent process are closed in the new child process."
1224 _fwalk(__close_if_popened);
1225 // dup2 so that the child fd isn't closed on exec.
1226 if (dup2(fds[child], desired_child_fd) == -1) _exit(127);
1227 close(fds[child]);
1228 if (bidirectional) dup2(STDOUT_FILENO, STDIN_FILENO);
1229 execl(_PATH_BSHELL, "sh", "-c", cmd, nullptr);
1230 _exit(127);
1231 }
1232
1233 FILE* fp = fdopen(fds[parent], mode);
1234 if (fp == nullptr) return __popen_fail(fds);
1235
Elliott Hughes468efc82018-07-10 14:39:49 -07001236 close(fds[child]);
1237
1238 _EXT(fp)->_popen_pid = pid;
1239 return fp;
1240}
1241
Elliott Hughes22917f62018-10-01 14:21:07 -07001242int pclose(FILE* fp) {
1243 CHECK_FP(fp);
1244 return __FILE_close(fp);
1245}
1246
Dan Albert3037ea42016-10-06 15:46:45 -07001247namespace {
1248
1249namespace phony {
1250#include <bits/struct_file.h>
1251}
1252
1253static_assert(sizeof(::__sFILE) == sizeof(phony::__sFILE),
1254 "size mismatch between `struct __sFILE` implementation and public stub");
1255static_assert(alignof(::__sFILE) == alignof(phony::__sFILE),
1256 "alignment mismatch between `struct __sFILE` implementation and public stub");
1257
1258}