blob: c7b1ba4594cbe261261ece7f9caeecebd454ace8 [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 Hughes886370c2019-03-21 21:11:41 -070055#include "private/__bionic_get_shell_path.h"
Elliott Hughesfb3873d2016-08-10 11:07:54 -070056#include "private/bionic_fortify.h"
Elliott Hughes023c3072016-01-22 15:04:51 -080057#include "private/ErrnoRestorer.h"
Elliott Hughes6a03abc2014-11-03 12:32:17 -080058#include "private/thread_private.h"
59
Elliott Hughese1dc4f62021-01-11 11:51:29 -080060#include "private/bsd_sys_param.h" // For ALIGN/ALIGNBYTES.
Calin Juravlec20de902014-03-20 15:21:32 +000061
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080062#define NDYNAMIC 10 /* add ten more whenever necessary */
63
Elliott Hughes70715da2016-08-01 16:35:17 -070064#define PRINTF_IMPL(expr) \
65 va_list ap; \
66 va_start(ap, fmt); \
67 int result = (expr); \
68 va_end(ap); \
69 return result;
70
Elliott Hughes468efc82018-07-10 14:39:49 -070071#define MAKE_STD_STREAM(flags, fd) \
72 { \
73 ._flags = flags, ._file = fd, ._cookie = __sF + fd, ._close = __sclose, \
74 ._read = __sread, ._write = __swrite, ._ext = { \
75 ._base = reinterpret_cast<uint8_t*>(__sFext + fd) \
76 } \
77 }
Elliott Hughes29ee6392015-12-07 11:07:15 -080078
Elliott Hughesbb46afd2015-12-04 18:03:12 -080079static struct __sfileext __sFext[3] = {
Elliott Hughes468efc82018-07-10 14:39:49 -070080 {._lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
81 ._caller_handles_locking = false,
82 ._seek64 = __sseek64,
83 ._popen_pid = 0},
84 {._lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
85 ._caller_handles_locking = false,
86 ._seek64 = __sseek64,
87 ._popen_pid = 0},
88 {._lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
89 ._caller_handles_locking = false,
90 ._seek64 = __sseek64,
91 ._popen_pid = 0},
Elliott Hughesbb46afd2015-12-04 18:03:12 -080092};
Elliott Hughesf0141df2015-10-12 12:44:23 -070093
94// __sF is exported for backwards compatibility. Until M, we didn't have symbols
95// for stdin/stdout/stderr; they were macros accessing __sF.
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080096FILE __sF[3] = {
Elliott Hughes468efc82018-07-10 14:39:49 -070097 MAKE_STD_STREAM(__SRD, STDIN_FILENO),
98 MAKE_STD_STREAM(__SWR, STDOUT_FILENO),
99 MAKE_STD_STREAM(__SWR|__SNBF, STDERR_FILENO),
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800100};
Elliott Hughesf0141df2015-10-12 12:44:23 -0700101
Elliott Hughes168667c2014-11-14 14:42:59 -0800102FILE* stdin = &__sF[0];
103FILE* stdout = &__sF[1];
104FILE* stderr = &__sF[2];
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800105
Ryan Prichardc485cdb2019-04-30 14:47:34 -0700106static pthread_mutex_t __stdio_mutex = PTHREAD_MUTEX_INITIALIZER;
Josh Gaof6e5b582018-06-01 15:30:54 -0700107
108static uint64_t __get_file_tag(FILE* fp) {
109 // Don't use a tag for the standard streams.
110 // They don't really own their file descriptors, because the values are well-known, and you're
111 // allowed to do things like `close(STDIN_FILENO); open("foo", O_RDONLY)` when single-threaded.
112 if (fp == stdin || fp == stderr || fp == stdout) {
113 return 0;
114 }
115
116 return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_FILE,
117 reinterpret_cast<uint64_t>(fp));
118}
119
Elliott Hughes37ad9592017-10-30 17:47:12 -0700120struct glue __sglue = { nullptr, 3, __sF };
Elliott Hughesbb46afd2015-12-04 18:03:12 -0800121static struct glue* lastglue = &__sglue;
122
Elliott Hughes2704bd12016-01-20 17:14:53 -0800123class ScopedFileLock {
124 public:
Chih-Hung Hsieh62e3a072016-05-03 12:08:05 -0700125 explicit ScopedFileLock(FILE* fp) : fp_(fp) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800126 FLOCKFILE(fp_);
127 }
128 ~ScopedFileLock() {
129 FUNLOCKFILE(fp_);
130 }
131
132 private:
133 FILE* fp_;
134};
135
Elliott Hughes021335e2016-01-19 16:28:15 -0800136static glue* moreglue(int n) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800137 char* data = new char[sizeof(glue) + ALIGNBYTES + n * sizeof(FILE) + n * sizeof(__sfileext)];
138 if (data == nullptr) return nullptr;
Elliott Hughes021335e2016-01-19 16:28:15 -0800139
Elliott Hughes2704bd12016-01-20 17:14:53 -0800140 glue* g = reinterpret_cast<glue*>(data);
141 FILE* p = reinterpret_cast<FILE*>(ALIGN(data + sizeof(*g)));
142 __sfileext* pext = reinterpret_cast<__sfileext*>(ALIGN(data + sizeof(*g)) + n * sizeof(FILE));
Elliott Hughes37ad9592017-10-30 17:47:12 -0700143 g->next = nullptr;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800144 g->niobs = n;
145 g->iobs = p;
146 while (--n >= 0) {
Elliott Hughes468efc82018-07-10 14:39:49 -0700147 *p = {};
Elliott Hughes2704bd12016-01-20 17:14:53 -0800148 _FILEEXT_SETUP(p, pext);
149 p++;
150 pext++;
151 }
152 return g;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800153}
154
Elliott Hughes80e4c152017-07-21 13:57:55 -0700155static inline void free_fgetln_buffer(FILE* fp) {
156 if (__predict_false(fp->_lb._base != nullptr)) {
157 free(fp->_lb._base);
158 fp->_lb._base = nullptr;
159 }
160}
161
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800162/*
163 * Find a free FILE for fopen et al.
164 */
Elliott Hughes021335e2016-01-19 16:28:15 -0800165FILE* __sfp(void) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800166 FILE *fp;
167 int n;
168 struct glue *g;
169
Elliott Hughes468efc82018-07-10 14:39:49 -0700170 pthread_mutex_lock(&__stdio_mutex);
Elliott Hughes37ad9592017-10-30 17:47:12 -0700171 for (g = &__sglue; g != nullptr; g = g->next) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800172 for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
173 if (fp->_flags == 0)
174 goto found;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800175 }
Kenny Rootf5823402011-02-12 07:13:44 -0800176
177 /* release lock while mallocing */
Elliott Hughes468efc82018-07-10 14:39:49 -0700178 pthread_mutex_unlock(&__stdio_mutex);
Elliott Hughes37ad9592017-10-30 17:47:12 -0700179 if ((g = moreglue(NDYNAMIC)) == nullptr) return nullptr;
Elliott Hughes468efc82018-07-10 14:39:49 -0700180 pthread_mutex_lock(&__stdio_mutex);
Kenny Rootf5823402011-02-12 07:13:44 -0800181 lastglue->next = g;
182 lastglue = g;
183 fp = g->iobs;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800184found:
185 fp->_flags = 1; /* reserve this slot; caller sets real flags */
Elliott Hughes468efc82018-07-10 14:39:49 -0700186 pthread_mutex_unlock(&__stdio_mutex);
Elliott Hughes37ad9592017-10-30 17:47:12 -0700187 fp->_p = nullptr; /* no current pointer */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800188 fp->_w = 0; /* nothing to read or write */
189 fp->_r = 0;
Elliott Hughes37ad9592017-10-30 17:47:12 -0700190 fp->_bf._base = nullptr; /* no buffer */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800191 fp->_bf._size = 0;
192 fp->_lbfsize = 0; /* not line buffered */
193 fp->_file = -1; /* no file */
Elliott Hughes023c3072016-01-22 15:04:51 -0800194
Elliott Hughes37ad9592017-10-30 17:47:12 -0700195 fp->_lb._base = nullptr; /* no line buffer */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800196 fp->_lb._size = 0;
Elliott Hughes1a56a262017-12-20 08:53:49 -0800197
198 memset(_EXT(fp), 0, sizeof(struct __sfileext));
199 _FLOCK(fp) = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
200 _EXT(fp)->_caller_handles_locking = false;
Elliott Hughes023c3072016-01-22 15:04:51 -0800201
202 // Caller sets cookie, _read/_write etc.
203 // We explicitly clear _seek and _seek64 to prevent subtle bugs.
204 fp->_seek = nullptr;
205 _EXT(fp)->_seek64 = nullptr;
206
207 return fp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800208}
209
Elliott Hughes468efc82018-07-10 14:39:49 -0700210int _fwalk(int (*callback)(FILE*)) {
Elliott Hughes468efc82018-07-10 14:39:49 -0700211 int result = 0;
212 for (glue* g = &__sglue; g != nullptr; g = g->next) {
213 FILE* fp = g->iobs;
214 for (int n = g->niobs; --n >= 0; ++fp) {
Elliott Hughes468efc82018-07-10 14:39:49 -0700215 if (fp->_flags != 0 && (fp->_flags & __SIGN) == 0) {
216 result |= (*callback)(fp);
217 }
218 }
219 }
Elliott Hughes468efc82018-07-10 14:39:49 -0700220 return result;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800221}
Elliott Hughes923f1652016-01-19 15:46:05 -0800222
Ryan Prichardc485cdb2019-04-30 14:47:34 -0700223extern "C" __LIBC_HIDDEN__ void __libc_stdio_cleanup(void) {
224 // Equivalent to fflush(nullptr), but without all the locking since we're shutting down anyway.
225 _fwalk(__sflush);
226}
227
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
Dan Albertba1151c2019-03-26 13:01:22 -0700293 // Make sure O_CLOEXEC is set on the underlying fd if our mode has 'e'.
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700294 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
Ryan Prichardc485cdb2019-04-30 14:47:34 -0700522int __sflush_locked(FILE* fp) {
523 ScopedFileLock sfl(fp);
524 return __sflush(fp);
525}
526
Elliott Hughes021335e2016-01-19 16:28:15 -0800527int __sread(void* cookie, char* buf, int n) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800528 FILE* fp = reinterpret_cast<FILE*>(cookie);
529 return TEMP_FAILURE_RETRY(read(fp->_file, buf, n));
Elliott Hughes021335e2016-01-19 16:28:15 -0800530}
531
532int __swrite(void* cookie, const char* buf, int n) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800533 FILE* fp = reinterpret_cast<FILE*>(cookie);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800534 return TEMP_FAILURE_RETRY(write(fp->_file, buf, n));
Elliott Hughes021335e2016-01-19 16:28:15 -0800535}
536
Elliott Hughes021335e2016-01-19 16:28:15 -0800537fpos_t __sseek(void* cookie, fpos_t offset, int whence) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800538 FILE* fp = reinterpret_cast<FILE*>(cookie);
539 return TEMP_FAILURE_RETRY(lseek(fp->_file, offset, whence));
Elliott Hughes021335e2016-01-19 16:28:15 -0800540}
541
Elliott Hughes023c3072016-01-22 15:04:51 -0800542off64_t __sseek64(void* cookie, off64_t offset, int whence) {
543 FILE* fp = reinterpret_cast<FILE*>(cookie);
544 return TEMP_FAILURE_RETRY(lseek64(fp->_file, offset, whence));
545}
546
Elliott Hughes021335e2016-01-19 16:28:15 -0800547int __sclose(void* cookie) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800548 FILE* fp = reinterpret_cast<FILE*>(cookie);
Josh Gaof6e5b582018-06-01 15:30:54 -0700549 return android_fdsan_close_with_tag(fp->_file, __get_file_tag(fp));
Elliott Hughes2704bd12016-01-20 17:14:53 -0800550}
551
Elliott Hughes023c3072016-01-22 15:04:51 -0800552static off64_t __seek_unlocked(FILE* fp, off64_t offset, int whence) {
553 // Use `_seek64` if set, but fall back to `_seek`.
554 if (_EXT(fp)->_seek64 != nullptr) {
555 return (*_EXT(fp)->_seek64)(fp->_cookie, offset, whence);
556 } else if (fp->_seek != nullptr) {
Elliott Hughes955426e2016-01-26 18:25:52 -0800557 off64_t result = (*fp->_seek)(fp->_cookie, offset, whence);
558#if !defined(__LP64__)
559 // Avoid sign extension if off64_t is larger than off_t.
560 if (result != -1) result &= 0xffffffff;
561#endif
562 return result;
Elliott Hughes023c3072016-01-22 15:04:51 -0800563 } else {
564 errno = ESPIPE;
565 return -1;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800566 }
Elliott Hughes2704bd12016-01-20 17:14:53 -0800567}
568
Elliott Hughes9677fab2016-01-25 15:50:59 -0800569static off64_t __ftello64_unlocked(FILE* fp) {
Elliott Hughes023c3072016-01-22 15:04:51 -0800570 // Find offset of underlying I/O object, then adjust for buffered bytes.
Elliott Hughes2704bd12016-01-20 17:14:53 -0800571 __sflush(fp); // May adjust seek offset on append stream.
Elliott Hughes33a8cb12017-07-25 18:06:46 -0700572
Elliott Hughes9677fab2016-01-25 15:50:59 -0800573 off64_t result = __seek_unlocked(fp, 0, SEEK_CUR);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800574 if (result == -1) {
575 return -1;
576 }
577
578 if (fp->_flags & __SRD) {
579 // Reading. Any unread characters (including
580 // those from ungetc) cause the position to be
581 // smaller than that in the underlying object.
582 result -= fp->_r;
583 if (HASUB(fp)) result -= fp->_ur;
Elliott Hughes37ad9592017-10-30 17:47:12 -0700584 } else if (fp->_flags & __SWR && fp->_p != nullptr) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800585 // Writing. Any buffered characters cause the
586 // position to be greater than that in the
587 // underlying object.
588 result += fp->_p - fp->_bf._base;
589 }
590 return result;
591}
592
Elliott Hughes9677fab2016-01-25 15:50:59 -0800593int __fseeko64(FILE* fp, off64_t offset, int whence, int off_t_bits) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800594 ScopedFileLock sfl(fp);
595
Elliott Hughes023c3072016-01-22 15:04:51 -0800596 // Change any SEEK_CUR to SEEK_SET, and check `whence` argument.
Elliott Hughes2704bd12016-01-20 17:14:53 -0800597 // After this, whence is either SEEK_SET or SEEK_END.
598 if (whence == SEEK_CUR) {
Elliott Hughes9677fab2016-01-25 15:50:59 -0800599 fpos64_t current_offset = __ftello64_unlocked(fp);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800600 if (current_offset == -1) {
Elliott Hughes9677fab2016-01-25 15:50:59 -0800601 return -1;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800602 }
603 offset += current_offset;
604 whence = SEEK_SET;
605 } else if (whence != SEEK_SET && whence != SEEK_END) {
606 errno = EINVAL;
Elliott Hughes9677fab2016-01-25 15:50:59 -0800607 return -1;
608 }
609
610 // If our caller has a 32-bit interface, refuse to go past a 32-bit file offset.
611 if (off_t_bits == 32 && offset > LONG_MAX) {
612 errno = EOVERFLOW;
613 return -1;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800614 }
615
Elliott Hughes37ad9592017-10-30 17:47:12 -0700616 if (fp->_bf._base == nullptr) __smakebuf(fp);
Elliott Hughes2704bd12016-01-20 17:14:53 -0800617
618 // Flush unwritten data and attempt the seek.
Elliott Hughes023c3072016-01-22 15:04:51 -0800619 if (__sflush(fp) || __seek_unlocked(fp, offset, whence) == -1) {
Elliott Hughes9677fab2016-01-25 15:50:59 -0800620 return -1;
Elliott Hughes2704bd12016-01-20 17:14:53 -0800621 }
622
623 // Success: clear EOF indicator and discard ungetc() data.
624 if (HASUB(fp)) FREEUB(fp);
625 fp->_p = fp->_bf._base;
626 fp->_r = 0;
627 /* fp->_w = 0; */ /* unnecessary (I think...) */
628 fp->_flags &= ~__SEOF;
629 return 0;
630}
631
Elliott Hughes9677fab2016-01-25 15:50:59 -0800632int fseeko(FILE* fp, off_t offset, int whence) {
Josh Gaod1620602017-10-05 13:48:08 -0700633 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800634 static_assert(sizeof(off_t) == sizeof(long), "sizeof(off_t) != sizeof(long)");
635 return __fseeko64(fp, offset, whence, 8*sizeof(off_t));
636}
637__strong_alias(fseek, fseeko);
638
639int fseeko64(FILE* fp, off64_t offset, int whence) {
Josh Gaod1620602017-10-05 13:48:08 -0700640 CHECK_FP(fp);
Ryan Prichardbf549862017-11-07 15:30:32 -0800641 return __fseeko64(fp, offset, whence, 8*sizeof(off64_t));
Elliott Hughes2704bd12016-01-20 17:14:53 -0800642}
643
Elliott Hughes9677fab2016-01-25 15:50:59 -0800644int fsetpos(FILE* fp, const fpos_t* pos) {
Josh Gaod1620602017-10-05 13:48:08 -0700645 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800646 return fseeko(fp, *pos, SEEK_SET);
647}
648
649int fsetpos64(FILE* fp, const fpos64_t* pos) {
Josh Gaod1620602017-10-05 13:48:08 -0700650 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800651 return fseeko64(fp, *pos, SEEK_SET);
652}
653
Elliott Hughes2704bd12016-01-20 17:14:53 -0800654off_t ftello(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700655 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800656 static_assert(sizeof(off_t) == sizeof(long), "sizeof(off_t) != sizeof(long)");
657 off64_t result = ftello64(fp);
658 if (result > LONG_MAX) {
Elliott Hughes2704bd12016-01-20 17:14:53 -0800659 errno = EOVERFLOW;
660 return -1;
661 }
Elliott Hughes9677fab2016-01-25 15:50:59 -0800662 return result;
663}
664__strong_alias(ftell, ftello);
665
666off64_t ftello64(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700667 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800668 ScopedFileLock sfl(fp);
669 return __ftello64_unlocked(fp);
Elliott Hughes021335e2016-01-19 16:28:15 -0800670}
Elliott Hughes023c3072016-01-22 15:04:51 -0800671
Elliott Hughes023c3072016-01-22 15:04:51 -0800672int fgetpos(FILE* fp, fpos_t* pos) {
Josh Gaod1620602017-10-05 13:48:08 -0700673 CHECK_FP(fp);
Elliott Hughes023c3072016-01-22 15:04:51 -0800674 *pos = ftello(fp);
Elliott Hughes955426e2016-01-26 18:25:52 -0800675 return (*pos == -1) ? -1 : 0;
Elliott Hughes023c3072016-01-22 15:04:51 -0800676}
677
Elliott Hughes9677fab2016-01-25 15:50:59 -0800678int fgetpos64(FILE* fp, fpos64_t* pos) {
Josh Gaod1620602017-10-05 13:48:08 -0700679 CHECK_FP(fp);
Elliott Hughes9677fab2016-01-25 15:50:59 -0800680 *pos = ftello64(fp);
Elliott Hughes955426e2016-01-26 18:25:52 -0800681 return (*pos == -1) ? -1 : 0;
Elliott Hughes023c3072016-01-22 15:04:51 -0800682}
Elliott Hughes03e65eb2016-01-26 14:13:04 -0800683
684static FILE* __funopen(const void* cookie,
685 int (*read_fn)(void*, char*, int),
686 int (*write_fn)(void*, const char*, int),
687 int (*close_fn)(void*)) {
688 if (read_fn == nullptr && write_fn == nullptr) {
689 errno = EINVAL;
690 return nullptr;
691 }
692
693 FILE* fp = __sfp();
694 if (fp == nullptr) return nullptr;
695
696 if (read_fn != nullptr && write_fn != nullptr) {
697 fp->_flags = __SRW;
698 } else if (read_fn != nullptr) {
699 fp->_flags = __SRD;
700 } else if (write_fn != nullptr) {
701 fp->_flags = __SWR;
702 }
703
704 fp->_file = -1;
705 fp->_cookie = const_cast<void*>(cookie); // The funopen(3) API is incoherent.
706 fp->_read = read_fn;
707 fp->_write = write_fn;
708 fp->_close = close_fn;
709
710 return fp;
711}
712
713FILE* funopen(const void* cookie,
714 int (*read_fn)(void*, char*, int),
715 int (*write_fn)(void*, const char*, int),
716 fpos_t (*seek_fn)(void*, fpos_t, int),
717 int (*close_fn)(void*)) {
718 FILE* fp = __funopen(cookie, read_fn, write_fn, close_fn);
719 if (fp != nullptr) {
720 fp->_seek = seek_fn;
721 }
722 return fp;
723}
724
725FILE* funopen64(const void* cookie,
726 int (*read_fn)(void*, char*, int),
727 int (*write_fn)(void*, const char*, int),
728 fpos64_t (*seek_fn)(void*, fpos64_t, int),
729 int (*close_fn)(void*)) {
730 FILE* fp = __funopen(cookie, read_fn, write_fn, close_fn);
731 if (fp != nullptr) {
732 _EXT(fp)->_seek64 = seek_fn;
733 }
734 return fp;
735}
Elliott Hughes20788ae2016-06-09 15:16:32 -0700736
Elliott Hughes53cf3482016-08-09 13:06:41 -0700737int asprintf(char** s, const char* fmt, ...) {
738 PRINTF_IMPL(vasprintf(s, fmt, ap));
739}
740
Elliott Hughes20788ae2016-06-09 15:16:32 -0700741char* ctermid(char* s) {
742 return s ? strcpy(s, _PATH_TTY) : const_cast<char*>(_PATH_TTY);
743}
Elliott Hughescceaf062016-07-29 16:31:52 -0700744
Elliott Hughes70715da2016-08-01 16:35:17 -0700745int dprintf(int fd, const char* fmt, ...) {
746 PRINTF_IMPL(vdprintf(fd, fmt, ap));
747}
748
749int fprintf(FILE* fp, const char* fmt, ...) {
Josh Gaod1620602017-10-05 13:48:08 -0700750 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700751 PRINTF_IMPL(vfprintf(fp, fmt, ap));
752}
753
Elliott Hughescceaf062016-07-29 16:31:52 -0700754int fgetc(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700755 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700756 return getc(fp);
757}
758
Elliott Hughes37ad9592017-10-30 17:47:12 -0700759int fgetc_unlocked(FILE* fp) {
760 CHECK_FP(fp);
761 return getc_unlocked(fp);
762}
763
George Burgess IV90242352018-02-06 12:51:31 -0800764char* fgets(char* buf, int n, FILE* fp) {
Elliott Hughes37ad9592017-10-30 17:47:12 -0700765 CHECK_FP(fp);
766 ScopedFileLock sfl(fp);
767 return fgets_unlocked(buf, n, fp);
768}
769
Elliott Hughes468efc82018-07-10 14:39:49 -0700770// Reads at most n-1 characters from the given file.
771// Stops when a newline has been read, or the count runs out.
772// Returns first argument, or nullptr if no characters were read.
773// Does not return nullptr if n == 1.
Elliott Hughes37ad9592017-10-30 17:47:12 -0700774char* fgets_unlocked(char* buf, int n, FILE* fp) {
Elliott Hughes7cebf832020-08-12 14:25:41 -0700775 if (n <= 0) __fortify_fatal("fgets: buffer size %d <= 0", n);
Elliott Hughes37ad9592017-10-30 17:47:12 -0700776
777 _SET_ORIENTATION(fp, -1);
778
779 char* s = buf;
780 n--; // Leave space for NUL.
781 while (n != 0) {
782 // If the buffer is empty, refill it.
783 if (fp->_r <= 0) {
784 if (__srefill(fp)) {
785 // EOF/error: stop with partial or no line.
786 if (s == buf) return nullptr;
787 break;
788 }
789 }
790 size_t len = fp->_r;
791 unsigned char* p = fp->_p;
792
793 // Scan through at most n bytes of the current buffer,
794 // looking for '\n'. If found, copy up to and including
795 // newline, and stop. Otherwise, copy entire chunk and loop.
796 if (len > static_cast<size_t>(n)) len = n;
797 unsigned char* t = static_cast<unsigned char*>(memchr(p, '\n', len));
798 if (t != nullptr) {
799 len = ++t - p;
800 fp->_r -= len;
801 fp->_p = t;
802 memcpy(s, p, len);
803 s[len] = '\0';
804 return buf;
805 }
806 fp->_r -= len;
807 fp->_p += len;
808 memcpy(s, p, len);
809 s += len;
810 n -= len;
811 }
812 *s = '\0';
813 return buf;
814}
815
Elliott Hughescceaf062016-07-29 16:31:52 -0700816int fputc(int c, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700817 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700818 return putc(c, fp);
819}
820
Elliott Hughes37ad9592017-10-30 17:47:12 -0700821int fputc_unlocked(int c, FILE* fp) {
822 CHECK_FP(fp);
823 return putc_unlocked(c, fp);
824}
825
826int fputs(const char* s, FILE* fp) {
827 CHECK_FP(fp);
828 ScopedFileLock sfl(fp);
829 return fputs_unlocked(s, fp);
830}
831
832int fputs_unlocked(const char* s, FILE* fp) {
833 CHECK_FP(fp);
834 size_t length = strlen(s);
835 return (fwrite_unlocked(s, 1, length, fp) == length) ? 0 : EOF;
836}
837
Elliott Hughes70715da2016-08-01 16:35:17 -0700838int fscanf(FILE* fp, const char* fmt, ...) {
Josh Gaod1620602017-10-05 13:48:08 -0700839 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700840 PRINTF_IMPL(vfscanf(fp, fmt, ap));
841}
842
843int fwprintf(FILE* fp, const wchar_t* fmt, ...) {
Josh Gaod1620602017-10-05 13:48:08 -0700844 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700845 PRINTF_IMPL(vfwprintf(fp, fmt, ap));
846}
847
848int fwscanf(FILE* fp, const wchar_t* fmt, ...) {
Josh Gaod1620602017-10-05 13:48:08 -0700849 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700850 PRINTF_IMPL(vfwscanf(fp, fmt, ap));
851}
852
853int getc(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700854 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700855 ScopedFileLock sfl(fp);
856 return getc_unlocked(fp);
857}
858
859int getc_unlocked(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700860 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700861 return __sgetc(fp);
862}
863
864int getchar_unlocked() {
865 return getc_unlocked(stdin);
866}
867
868int getchar() {
869 return getc(stdin);
870}
871
Elliott Hughescceaf062016-07-29 16:31:52 -0700872ssize_t getline(char** buf, size_t* len, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700873 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700874 return getdelim(buf, len, '\n', fp);
875}
876
877wint_t getwc(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700878 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700879 return fgetwc(fp);
880}
881
882wint_t getwchar() {
883 return fgetwc(stdin);
884}
885
Elliott Hughes37ad9592017-10-30 17:47:12 -0700886void perror(const char* msg) {
887 if (msg == nullptr) msg = "";
888 fprintf(stderr, "%s%s%s\n", msg, (*msg == '\0') ? "" : ": ", strerror(errno));
889}
890
Elliott Hughes70715da2016-08-01 16:35:17 -0700891int printf(const char* fmt, ...) {
892 PRINTF_IMPL(vfprintf(stdout, fmt, ap));
893}
894
895int putc(int c, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700896 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700897 ScopedFileLock sfl(fp);
898 return putc_unlocked(c, fp);
899}
900
901int putc_unlocked(int c, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700902 CHECK_FP(fp);
Elliott Hughes70715da2016-08-01 16:35:17 -0700903 if (cantwrite(fp)) {
904 errno = EBADF;
905 return EOF;
906 }
907 _SET_ORIENTATION(fp, -1);
908 if (--fp->_w >= 0 || (fp->_w >= fp->_lbfsize && c != '\n')) {
909 return (*fp->_p++ = c);
910 }
911 return (__swbuf(c, fp));
912}
913
914int putchar(int c) {
915 return putc(c, stdout);
916}
917
918int putchar_unlocked(int c) {
919 return putc_unlocked(c, stdout);
920}
921
Elliott Hughes37ad9592017-10-30 17:47:12 -0700922int puts(const char* s) {
923 size_t length = strlen(s);
924 ScopedFileLock sfl(stdout);
925 return (fwrite_unlocked(s, 1, length, stdout) == length &&
926 putc_unlocked('\n', stdout) != EOF) ? 0 : EOF;
927}
928
Elliott Hughescceaf062016-07-29 16:31:52 -0700929wint_t putwc(wchar_t wc, FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700930 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700931 return fputwc(wc, fp);
932}
933
934wint_t putwchar(wchar_t wc) {
935 return fputwc(wc, stdout);
936}
937
Elliott Hughesd1f25a72016-08-05 15:53:03 -0700938int remove(const char* path) {
939 if (unlink(path) != -1) return 0;
940 if (errno != EISDIR) return -1;
941 return rmdir(path);
942}
943
Elliott Hughescceaf062016-07-29 16:31:52 -0700944void rewind(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700945 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700946 ScopedFileLock sfl(fp);
947 fseek(fp, 0, SEEK_SET);
948 clearerr_unlocked(fp);
949}
950
Elliott Hughes70715da2016-08-01 16:35:17 -0700951int scanf(const char* fmt, ...) {
952 PRINTF_IMPL(vfscanf(stdin, fmt, ap));
953}
954
Elliott Hughescceaf062016-07-29 16:31:52 -0700955void setbuf(FILE* fp, char* buf) {
Josh Gaod1620602017-10-05 13:48:08 -0700956 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700957 setbuffer(fp, buf, BUFSIZ);
958}
959
960void setbuffer(FILE* fp, char* buf, int size) {
Josh Gaod1620602017-10-05 13:48:08 -0700961 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700962 setvbuf(fp, buf, buf ? _IOFBF : _IONBF, size);
963}
964
965int setlinebuf(FILE* fp) {
Josh Gaod1620602017-10-05 13:48:08 -0700966 CHECK_FP(fp);
Elliott Hughescceaf062016-07-29 16:31:52 -0700967 return setvbuf(fp, nullptr, _IOLBF, 0);
968}
969
Elliott Hughes53cf3482016-08-09 13:06:41 -0700970int snprintf(char* s, size_t n, const char* fmt, ...) {
971 PRINTF_IMPL(vsnprintf(s, n, fmt, ap));
972}
973
974int sprintf(char* s, const char* fmt, ...) {
Elliott Hughesfb3873d2016-08-10 11:07:54 -0700975 PRINTF_IMPL(vsprintf(s, fmt, ap));
Elliott Hughes53cf3482016-08-09 13:06:41 -0700976}
977
978int sscanf(const char* s, const char* fmt, ...) {
979 PRINTF_IMPL(vsscanf(s, fmt, ap));
980}
981
Elliott Hughes70715da2016-08-01 16:35:17 -0700982int swprintf(wchar_t* s, size_t n, const wchar_t* fmt, ...) {
983 PRINTF_IMPL(vswprintf(s, n, fmt, ap));
984}
985
986int swscanf(const wchar_t* s, const wchar_t* fmt, ...) {
987 PRINTF_IMPL(vswscanf(s, fmt, ap));
988}
989
Elliott Hughes618303c2017-11-02 16:58:44 -0700990int vfprintf(FILE* fp, const char* fmt, va_list ap) {
991 ScopedFileLock sfl(fp);
992 return __vfprintf(fp, fmt, ap);
993}
994
Elliott Hughes345b7272017-11-10 16:20:43 -0800995int vfscanf(FILE* fp, const char* fmt, va_list ap) {
996 ScopedFileLock sfl(fp);
997 return __svfscanf(fp, fmt, ap);
998}
999
Elliott Hughes618303c2017-11-02 16:58:44 -07001000int vfwprintf(FILE* fp, const wchar_t* fmt, va_list ap) {
1001 ScopedFileLock sfl(fp);
1002 return __vfwprintf(fp, fmt, ap);
1003}
1004
Elliott Hughes345b7272017-11-10 16:20:43 -08001005int vfwscanf(FILE* fp, const wchar_t* fmt, va_list ap) {
1006 ScopedFileLock sfl(fp);
1007 return __vfwscanf(fp, fmt, ap);
1008}
1009
Elliott Hughescceaf062016-07-29 16:31:52 -07001010int vprintf(const char* fmt, va_list ap) {
1011 return vfprintf(stdout, fmt, ap);
1012}
1013
1014int vscanf(const char* fmt, va_list ap) {
1015 return vfscanf(stdin, fmt, ap);
1016}
1017
Elliott Hughesfb3873d2016-08-10 11:07:54 -07001018int vsnprintf(char* s, size_t n, const char* fmt, va_list ap) {
1019 // stdio internals use int rather than size_t.
1020 static_assert(INT_MAX <= SSIZE_MAX, "SSIZE_MAX too large to fit in int");
1021
1022 __check_count("vsnprintf", "size", n);
1023
1024 // Stdio internals do not deal correctly with zero length buffer.
Elliott Hughes68ae6ad2020-07-21 16:11:30 -07001025 char one_byte_buffer[1];
Elliott Hughesfb3873d2016-08-10 11:07:54 -07001026 if (n == 0) {
Elliott Hughes68ae6ad2020-07-21 16:11:30 -07001027 s = one_byte_buffer;
Elliott Hughesfb3873d2016-08-10 11:07:54 -07001028 n = 1;
1029 }
1030
1031 FILE f;
1032 __sfileext fext;
1033 _FILEEXT_SETUP(&f, &fext);
1034 f._file = -1;
1035 f._flags = __SWR | __SSTR;
1036 f._bf._base = f._p = reinterpret_cast<unsigned char*>(s);
1037 f._bf._size = f._w = n - 1;
1038
1039 int result = __vfprintf(&f, fmt, ap);
1040 *f._p = '\0';
1041 return result;
1042}
1043
Elliott Hughes53cf3482016-08-09 13:06:41 -07001044int vsprintf(char* s, const char* fmt, va_list ap) {
Elliott Hughesfb3873d2016-08-10 11:07:54 -07001045 return vsnprintf(s, SSIZE_MAX, fmt, ap);
Elliott Hughes53cf3482016-08-09 13:06:41 -07001046}
1047
Elliott Hughescceaf062016-07-29 16:31:52 -07001048int vwprintf(const wchar_t* fmt, va_list ap) {
1049 return vfwprintf(stdout, fmt, ap);
1050}
1051
1052int vwscanf(const wchar_t* fmt, va_list ap) {
1053 return vfwscanf(stdin, fmt, ap);
1054}
Elliott Hughes70715da2016-08-01 16:35:17 -07001055
1056int wprintf(const wchar_t* fmt, ...) {
1057 PRINTF_IMPL(vfwprintf(stdout, fmt, ap));
1058}
1059
1060int wscanf(const wchar_t* fmt, ...) {
1061 PRINTF_IMPL(vfwscanf(stdin, fmt, ap));
1062}
Dan Albert3037ea42016-10-06 15:46:45 -07001063
Elliott Hughes37ad9592017-10-30 17:47:12 -07001064static int fflush_all() {
Ryan Prichardc485cdb2019-04-30 14:47:34 -07001065 return _fwalk(__sflush_locked);
Elliott Hughes37ad9592017-10-30 17:47:12 -07001066}
1067
1068int fflush(FILE* fp) {
1069 if (fp == nullptr) return fflush_all();
1070 ScopedFileLock sfl(fp);
1071 return fflush_unlocked(fp);
1072}
1073
1074int fflush_unlocked(FILE* fp) {
1075 if (fp == nullptr) return fflush_all();
1076 if ((fp->_flags & (__SWR | __SRW)) == 0) {
1077 errno = EBADF;
1078 return EOF;
1079 }
1080 return __sflush(fp);
1081}
1082
George Burgess IV90242352018-02-06 12:51:31 -08001083size_t fread(void* buf, size_t size, size_t count, FILE* fp) {
Elliott Hughes37ad9592017-10-30 17:47:12 -07001084 CHECK_FP(fp);
1085 ScopedFileLock sfl(fp);
1086 return fread_unlocked(buf, size, count, fp);
1087}
1088
1089size_t fread_unlocked(void* buf, size_t size, size_t count, FILE* fp) {
1090 CHECK_FP(fp);
1091
1092 size_t desired_total;
1093 if (__builtin_mul_overflow(size, count, &desired_total)) {
1094 errno = EOVERFLOW;
1095 fp->_flags |= __SERR;
1096 return 0;
1097 }
1098
1099 size_t total = desired_total;
1100 if (total == 0) return 0;
1101
1102 _SET_ORIENTATION(fp, -1);
1103
1104 // TODO: how can this ever happen?!
1105 if (fp->_r < 0) fp->_r = 0;
1106
1107 // Ensure _bf._size is valid.
1108 if (fp->_bf._base == nullptr) __smakebuf(fp);
1109
1110 char* dst = static_cast<char*>(buf);
1111
1112 while (total > 0) {
1113 // Copy data out of the buffer.
1114 size_t buffered_bytes = MIN(static_cast<size_t>(fp->_r), total);
1115 memcpy(dst, fp->_p, buffered_bytes);
1116 fp->_p += buffered_bytes;
1117 fp->_r -= buffered_bytes;
1118 dst += buffered_bytes;
1119 total -= buffered_bytes;
1120
1121 // Are we done?
1122 if (total == 0) goto out;
1123
1124 // Do we have so much more to read that we should avoid copying it through the buffer?
1125 if (total > static_cast<size_t>(fp->_bf._size)) break;
1126
1127 // Less than a buffer to go, so refill the buffer and go around the loop again.
1128 if (__srefill(fp)) goto out;
1129 }
1130
1131 // Read directly into the caller's buffer.
1132 while (total > 0) {
1133 ssize_t bytes_read = (*fp->_read)(fp->_cookie, dst, total);
1134 if (bytes_read <= 0) {
1135 fp->_flags |= (bytes_read == 0) ? __SEOF : __SERR;
1136 break;
1137 }
1138 dst += bytes_read;
1139 total -= bytes_read;
1140 }
1141
1142out:
1143 return ((desired_total - total) / size);
1144}
1145
1146size_t fwrite(const void* buf, size_t size, size_t count, FILE* fp) {
1147 CHECK_FP(fp);
1148 ScopedFileLock sfl(fp);
1149 return fwrite_unlocked(buf, size, count, fp);
1150}
1151
1152size_t fwrite_unlocked(const void* buf, size_t size, size_t count, FILE* fp) {
1153 CHECK_FP(fp);
1154
1155 size_t n;
1156 if (__builtin_mul_overflow(size, count, &n)) {
1157 errno = EOVERFLOW;
1158 fp->_flags |= __SERR;
1159 return 0;
1160 }
1161
1162 if (n == 0) return 0;
1163
1164 __siov iov = { .iov_base = const_cast<void*>(buf), .iov_len = n };
1165 __suio uio = { .uio_iov = &iov, .uio_iovcnt = 1, .uio_resid = n };
1166
1167 _SET_ORIENTATION(fp, -1);
1168
1169 // The usual case is success (__sfvwrite returns 0); skip the divide if this happens,
1170 // since divides are generally slow.
1171 return (__sfvwrite(fp, &uio) == 0) ? count : ((n - uio.uio_resid) / size);
1172}
1173
Elliott Hughes468efc82018-07-10 14:39:49 -07001174static FILE* __popen_fail(int fds[2]) {
1175 ErrnoRestorer errno_restorer;
1176 close(fds[0]);
1177 close(fds[1]);
1178 return nullptr;
1179}
1180
1181FILE* popen(const char* cmd, const char* mode) {
Elliott Hughes468efc82018-07-10 14:39:49 -07001182 // Was the request for a socketpair or just a pipe?
1183 int fds[2];
1184 bool bidirectional = false;
1185 if (strchr(mode, '+') != nullptr) {
1186 if (socketpair(AF_LOCAL, SOCK_CLOEXEC | SOCK_STREAM, 0, fds) == -1) return nullptr;
1187 bidirectional = true;
1188 mode = "r+";
1189 } else {
1190 if (pipe2(fds, O_CLOEXEC) == -1) return nullptr;
1191 mode = strrchr(mode, 'r') ? "r" : "w";
1192 }
1193
1194 // If the parent wants to read, the child's fd needs to be stdout.
1195 int parent, child, desired_child_fd;
1196 if (*mode == 'r') {
1197 parent = 0;
1198 child = 1;
1199 desired_child_fd = STDOUT_FILENO;
1200 } else {
1201 parent = 1;
1202 child = 0;
1203 desired_child_fd = STDIN_FILENO;
1204 }
1205
1206 // Ensure that the child fd isn't the desired child fd.
1207 if (fds[child] == desired_child_fd) {
1208 int new_fd = fcntl(fds[child], F_DUPFD_CLOEXEC, 0);
1209 if (new_fd == -1) return __popen_fail(fds);
1210 close(fds[child]);
1211 fds[child] = new_fd;
1212 }
1213
1214 pid_t pid = vfork();
1215 if (pid == -1) return __popen_fail(fds);
1216
1217 if (pid == 0) {
1218 close(fds[parent]);
Elliott Hughes468efc82018-07-10 14:39:49 -07001219 // dup2 so that the child fd isn't closed on exec.
1220 if (dup2(fds[child], desired_child_fd) == -1) _exit(127);
1221 close(fds[child]);
1222 if (bidirectional) dup2(STDOUT_FILENO, STDIN_FILENO);
Elliott Hughes886370c2019-03-21 21:11:41 -07001223 execl(__bionic_get_shell_path(), "sh", "-c", cmd, nullptr);
Elliott Hughes468efc82018-07-10 14:39:49 -07001224 _exit(127);
1225 }
1226
1227 FILE* fp = fdopen(fds[parent], mode);
1228 if (fp == nullptr) return __popen_fail(fds);
1229
Elliott Hughes468efc82018-07-10 14:39:49 -07001230 close(fds[child]);
1231
1232 _EXT(fp)->_popen_pid = pid;
1233 return fp;
1234}
1235
Elliott Hughes22917f62018-10-01 14:21:07 -07001236int pclose(FILE* fp) {
1237 CHECK_FP(fp);
1238 return __FILE_close(fp);
1239}
1240
Dan Albert3037ea42016-10-06 15:46:45 -07001241namespace {
1242
1243namespace phony {
1244#include <bits/struct_file.h>
1245}
1246
1247static_assert(sizeof(::__sFILE) == sizeof(phony::__sFILE),
1248 "size mismatch between `struct __sFILE` implementation and public stub");
1249static_assert(alignof(::__sFILE) == alignof(phony::__sFILE),
1250 "alignment mismatch between `struct __sFILE` implementation and public stub");
1251
1252}