1*8d67ca89SAndroid Build Coastguard Worker /* $OpenBSD: findfp.c,v 1.15 2013/12/17 16:33:27 deraadt Exp $ */
2*8d67ca89SAndroid Build Coastguard Worker /*-
3*8d67ca89SAndroid Build Coastguard Worker * Copyright (c) 1990, 1993
4*8d67ca89SAndroid Build Coastguard Worker * The Regents of the University of California. All rights reserved.
5*8d67ca89SAndroid Build Coastguard Worker *
6*8d67ca89SAndroid Build Coastguard Worker * This code is derived from software contributed to Berkeley by
7*8d67ca89SAndroid Build Coastguard Worker * Chris Torek.
8*8d67ca89SAndroid Build Coastguard Worker *
9*8d67ca89SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
10*8d67ca89SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
11*8d67ca89SAndroid Build Coastguard Worker * are met:
12*8d67ca89SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
13*8d67ca89SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
14*8d67ca89SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
15*8d67ca89SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
16*8d67ca89SAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
17*8d67ca89SAndroid Build Coastguard Worker * 3. Neither the name of the University nor the names of its contributors
18*8d67ca89SAndroid Build Coastguard Worker * may be used to endorse or promote products derived from this software
19*8d67ca89SAndroid Build Coastguard Worker * without specific prior written permission.
20*8d67ca89SAndroid Build Coastguard Worker *
21*8d67ca89SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22*8d67ca89SAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*8d67ca89SAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*8d67ca89SAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25*8d67ca89SAndroid Build Coastguard Worker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*8d67ca89SAndroid Build Coastguard Worker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27*8d67ca89SAndroid Build Coastguard Worker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*8d67ca89SAndroid Build Coastguard Worker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29*8d67ca89SAndroid Build Coastguard Worker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30*8d67ca89SAndroid Build Coastguard Worker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*8d67ca89SAndroid Build Coastguard Worker * SUCH DAMAGE.
32*8d67ca89SAndroid Build Coastguard Worker */
33*8d67ca89SAndroid Build Coastguard Worker
34*8d67ca89SAndroid Build Coastguard Worker #define __BIONIC_NO_STDIO_FORTIFY
35*8d67ca89SAndroid Build Coastguard Worker #include <stdio.h>
36*8d67ca89SAndroid Build Coastguard Worker
37*8d67ca89SAndroid Build Coastguard Worker #include <errno.h>
38*8d67ca89SAndroid Build Coastguard Worker #include <fcntl.h>
39*8d67ca89SAndroid Build Coastguard Worker #include <limits.h>
40*8d67ca89SAndroid Build Coastguard Worker #include <paths.h>
41*8d67ca89SAndroid Build Coastguard Worker #include <stdlib.h>
42*8d67ca89SAndroid Build Coastguard Worker #include <string.h>
43*8d67ca89SAndroid Build Coastguard Worker #include <sys/param.h>
44*8d67ca89SAndroid Build Coastguard Worker #include <sys/socket.h>
45*8d67ca89SAndroid Build Coastguard Worker #include <sys/stat.h>
46*8d67ca89SAndroid Build Coastguard Worker #include <sys/wait.h>
47*8d67ca89SAndroid Build Coastguard Worker #include <unistd.h>
48*8d67ca89SAndroid Build Coastguard Worker
49*8d67ca89SAndroid Build Coastguard Worker #include <android/fdsan.h>
50*8d67ca89SAndroid Build Coastguard Worker
51*8d67ca89SAndroid Build Coastguard Worker #include <async_safe/log.h>
52*8d67ca89SAndroid Build Coastguard Worker
53*8d67ca89SAndroid Build Coastguard Worker #include "glue.h"
54*8d67ca89SAndroid Build Coastguard Worker #include "local.h"
55*8d67ca89SAndroid Build Coastguard Worker #include "private/ErrnoRestorer.h"
56*8d67ca89SAndroid Build Coastguard Worker #include "private/FdPath.h"
57*8d67ca89SAndroid Build Coastguard Worker #include "private/__bionic_get_shell_path.h"
58*8d67ca89SAndroid Build Coastguard Worker #include "private/bionic_fortify.h"
59*8d67ca89SAndroid Build Coastguard Worker #include "private/thread_private.h"
60*8d67ca89SAndroid Build Coastguard Worker
61*8d67ca89SAndroid Build Coastguard Worker #define NDYNAMIC 10 /* add ten more whenever necessary */
62*8d67ca89SAndroid Build Coastguard Worker
63*8d67ca89SAndroid Build Coastguard Worker #define PRINTF_IMPL(expr) \
64*8d67ca89SAndroid Build Coastguard Worker va_list ap; \
65*8d67ca89SAndroid Build Coastguard Worker va_start(ap, fmt); \
66*8d67ca89SAndroid Build Coastguard Worker int result = (expr); \
67*8d67ca89SAndroid Build Coastguard Worker va_end(ap); \
68*8d67ca89SAndroid Build Coastguard Worker return result;
69*8d67ca89SAndroid Build Coastguard Worker
70*8d67ca89SAndroid Build Coastguard Worker #define MAKE_STD_STREAM(flags, fd) \
71*8d67ca89SAndroid Build Coastguard Worker { \
72*8d67ca89SAndroid Build Coastguard Worker ._flags = flags, ._file = fd, ._cookie = __sF + fd, ._close = __sclose, \
73*8d67ca89SAndroid Build Coastguard Worker ._read = __sread, ._write = __swrite, ._ext = { \
74*8d67ca89SAndroid Build Coastguard Worker ._base = reinterpret_cast<uint8_t*>(__sFext + fd) \
75*8d67ca89SAndroid Build Coastguard Worker } \
76*8d67ca89SAndroid Build Coastguard Worker }
77*8d67ca89SAndroid Build Coastguard Worker
78*8d67ca89SAndroid Build Coastguard Worker static struct __sfileext __sFext[3] = {
79*8d67ca89SAndroid Build Coastguard Worker {._lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
80*8d67ca89SAndroid Build Coastguard Worker ._caller_handles_locking = false,
81*8d67ca89SAndroid Build Coastguard Worker ._seek64 = __sseek64,
82*8d67ca89SAndroid Build Coastguard Worker ._popen_pid = 0},
83*8d67ca89SAndroid Build Coastguard Worker {._lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
84*8d67ca89SAndroid Build Coastguard Worker ._caller_handles_locking = false,
85*8d67ca89SAndroid Build Coastguard Worker ._seek64 = __sseek64,
86*8d67ca89SAndroid Build Coastguard Worker ._popen_pid = 0},
87*8d67ca89SAndroid Build Coastguard Worker {._lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
88*8d67ca89SAndroid Build Coastguard Worker ._caller_handles_locking = false,
89*8d67ca89SAndroid Build Coastguard Worker ._seek64 = __sseek64,
90*8d67ca89SAndroid Build Coastguard Worker ._popen_pid = 0},
91*8d67ca89SAndroid Build Coastguard Worker };
92*8d67ca89SAndroid Build Coastguard Worker
93*8d67ca89SAndroid Build Coastguard Worker // __sF is exported for backwards compatibility. Until M, we didn't have symbols
94*8d67ca89SAndroid Build Coastguard Worker // for stdin/stdout/stderr; they were macros accessing __sF.
95*8d67ca89SAndroid Build Coastguard Worker FILE __sF[3] = {
96*8d67ca89SAndroid Build Coastguard Worker MAKE_STD_STREAM(__SRD, STDIN_FILENO),
97*8d67ca89SAndroid Build Coastguard Worker MAKE_STD_STREAM(__SWR, STDOUT_FILENO),
98*8d67ca89SAndroid Build Coastguard Worker MAKE_STD_STREAM(__SWR|__SNBF, STDERR_FILENO),
99*8d67ca89SAndroid Build Coastguard Worker };
100*8d67ca89SAndroid Build Coastguard Worker
101*8d67ca89SAndroid Build Coastguard Worker FILE* stdin = &__sF[0];
102*8d67ca89SAndroid Build Coastguard Worker FILE* stdout = &__sF[1];
103*8d67ca89SAndroid Build Coastguard Worker FILE* stderr = &__sF[2];
104*8d67ca89SAndroid Build Coastguard Worker
105*8d67ca89SAndroid Build Coastguard Worker static pthread_mutex_t __stdio_mutex = PTHREAD_MUTEX_INITIALIZER;
106*8d67ca89SAndroid Build Coastguard Worker
__get_file_tag(FILE * fp)107*8d67ca89SAndroid Build Coastguard Worker static uint64_t __get_file_tag(FILE* fp) {
108*8d67ca89SAndroid Build Coastguard Worker // Don't use a tag for the standard streams.
109*8d67ca89SAndroid Build Coastguard Worker // They don't really own their file descriptors, because the values are well-known, and you're
110*8d67ca89SAndroid Build Coastguard Worker // allowed to do things like `close(STDIN_FILENO); open("foo", O_RDONLY)` when single-threaded.
111*8d67ca89SAndroid Build Coastguard Worker if (fp == stdin || fp == stderr || fp == stdout) {
112*8d67ca89SAndroid Build Coastguard Worker return 0;
113*8d67ca89SAndroid Build Coastguard Worker }
114*8d67ca89SAndroid Build Coastguard Worker
115*8d67ca89SAndroid Build Coastguard Worker return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_FILE,
116*8d67ca89SAndroid Build Coastguard Worker reinterpret_cast<uint64_t>(fp));
117*8d67ca89SAndroid Build Coastguard Worker }
118*8d67ca89SAndroid Build Coastguard Worker
119*8d67ca89SAndroid Build Coastguard Worker struct glue __sglue = { nullptr, 3, __sF };
120*8d67ca89SAndroid Build Coastguard Worker static struct glue* lastglue = &__sglue;
121*8d67ca89SAndroid Build Coastguard Worker
122*8d67ca89SAndroid Build Coastguard Worker class ScopedFileLock {
123*8d67ca89SAndroid Build Coastguard Worker public:
ScopedFileLock(FILE * fp)124*8d67ca89SAndroid Build Coastguard Worker explicit ScopedFileLock(FILE* fp) : fp_(fp) {
125*8d67ca89SAndroid Build Coastguard Worker FLOCKFILE(fp_);
126*8d67ca89SAndroid Build Coastguard Worker }
~ScopedFileLock()127*8d67ca89SAndroid Build Coastguard Worker ~ScopedFileLock() {
128*8d67ca89SAndroid Build Coastguard Worker FUNLOCKFILE(fp_);
129*8d67ca89SAndroid Build Coastguard Worker }
130*8d67ca89SAndroid Build Coastguard Worker
131*8d67ca89SAndroid Build Coastguard Worker private:
132*8d67ca89SAndroid Build Coastguard Worker FILE* fp_;
133*8d67ca89SAndroid Build Coastguard Worker };
134*8d67ca89SAndroid Build Coastguard Worker
moreglue(int n)135*8d67ca89SAndroid Build Coastguard Worker static glue* moreglue(int n) {
136*8d67ca89SAndroid Build Coastguard Worker char* data = new char[sizeof(glue) +
137*8d67ca89SAndroid Build Coastguard Worker alignof(FILE) + n * sizeof(FILE) +
138*8d67ca89SAndroid Build Coastguard Worker alignof(__sfileext) + n * sizeof(__sfileext)];
139*8d67ca89SAndroid Build Coastguard Worker if (data == nullptr) return nullptr;
140*8d67ca89SAndroid Build Coastguard Worker
141*8d67ca89SAndroid Build Coastguard Worker glue* g = reinterpret_cast<glue*>(data);
142*8d67ca89SAndroid Build Coastguard Worker FILE* p = reinterpret_cast<FILE*>(__builtin_align_up(g + 1, alignof(FILE)));
143*8d67ca89SAndroid Build Coastguard Worker __sfileext* pext = reinterpret_cast<__sfileext*>(__builtin_align_up(p + n, alignof(__sfileext)));
144*8d67ca89SAndroid Build Coastguard Worker g->next = nullptr;
145*8d67ca89SAndroid Build Coastguard Worker g->niobs = n;
146*8d67ca89SAndroid Build Coastguard Worker g->iobs = p;
147*8d67ca89SAndroid Build Coastguard Worker while (--n >= 0) {
148*8d67ca89SAndroid Build Coastguard Worker *p = {};
149*8d67ca89SAndroid Build Coastguard Worker _FILEEXT_SETUP(p, pext);
150*8d67ca89SAndroid Build Coastguard Worker p++;
151*8d67ca89SAndroid Build Coastguard Worker pext++;
152*8d67ca89SAndroid Build Coastguard Worker }
153*8d67ca89SAndroid Build Coastguard Worker return g;
154*8d67ca89SAndroid Build Coastguard Worker }
155*8d67ca89SAndroid Build Coastguard Worker
free_fgetln_buffer(FILE * fp)156*8d67ca89SAndroid Build Coastguard Worker static inline void free_fgetln_buffer(FILE* fp) {
157*8d67ca89SAndroid Build Coastguard Worker if (__predict_false(fp->_lb._base != nullptr)) {
158*8d67ca89SAndroid Build Coastguard Worker free(fp->_lb._base);
159*8d67ca89SAndroid Build Coastguard Worker fp->_lb._base = nullptr;
160*8d67ca89SAndroid Build Coastguard Worker }
161*8d67ca89SAndroid Build Coastguard Worker }
162*8d67ca89SAndroid Build Coastguard Worker
163*8d67ca89SAndroid Build Coastguard Worker /*
164*8d67ca89SAndroid Build Coastguard Worker * Find a free FILE for fopen et al.
165*8d67ca89SAndroid Build Coastguard Worker */
__sfp(void)166*8d67ca89SAndroid Build Coastguard Worker FILE* __sfp(void) {
167*8d67ca89SAndroid Build Coastguard Worker FILE *fp;
168*8d67ca89SAndroid Build Coastguard Worker int n;
169*8d67ca89SAndroid Build Coastguard Worker struct glue *g;
170*8d67ca89SAndroid Build Coastguard Worker
171*8d67ca89SAndroid Build Coastguard Worker pthread_mutex_lock(&__stdio_mutex);
172*8d67ca89SAndroid Build Coastguard Worker for (g = &__sglue; g != nullptr; g = g->next) {
173*8d67ca89SAndroid Build Coastguard Worker for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
174*8d67ca89SAndroid Build Coastguard Worker if (fp->_flags == 0)
175*8d67ca89SAndroid Build Coastguard Worker goto found;
176*8d67ca89SAndroid Build Coastguard Worker }
177*8d67ca89SAndroid Build Coastguard Worker
178*8d67ca89SAndroid Build Coastguard Worker /* release lock while mallocing */
179*8d67ca89SAndroid Build Coastguard Worker pthread_mutex_unlock(&__stdio_mutex);
180*8d67ca89SAndroid Build Coastguard Worker if ((g = moreglue(NDYNAMIC)) == nullptr) return nullptr;
181*8d67ca89SAndroid Build Coastguard Worker pthread_mutex_lock(&__stdio_mutex);
182*8d67ca89SAndroid Build Coastguard Worker lastglue->next = g;
183*8d67ca89SAndroid Build Coastguard Worker lastglue = g;
184*8d67ca89SAndroid Build Coastguard Worker fp = g->iobs;
185*8d67ca89SAndroid Build Coastguard Worker found:
186*8d67ca89SAndroid Build Coastguard Worker fp->_flags = 1; /* reserve this slot; caller sets real flags */
187*8d67ca89SAndroid Build Coastguard Worker pthread_mutex_unlock(&__stdio_mutex);
188*8d67ca89SAndroid Build Coastguard Worker fp->_p = nullptr; /* no current pointer */
189*8d67ca89SAndroid Build Coastguard Worker fp->_w = 0; /* nothing to read or write */
190*8d67ca89SAndroid Build Coastguard Worker fp->_r = 0;
191*8d67ca89SAndroid Build Coastguard Worker fp->_bf._base = nullptr; /* no buffer */
192*8d67ca89SAndroid Build Coastguard Worker fp->_bf._size = 0;
193*8d67ca89SAndroid Build Coastguard Worker fp->_lbfsize = 0; /* not line buffered */
194*8d67ca89SAndroid Build Coastguard Worker fp->_file = -1; /* no file */
195*8d67ca89SAndroid Build Coastguard Worker
196*8d67ca89SAndroid Build Coastguard Worker fp->_lb._base = nullptr; /* no line buffer */
197*8d67ca89SAndroid Build Coastguard Worker fp->_lb._size = 0;
198*8d67ca89SAndroid Build Coastguard Worker
199*8d67ca89SAndroid Build Coastguard Worker memset(_EXT(fp), 0, sizeof(struct __sfileext));
200*8d67ca89SAndroid Build Coastguard Worker _EXT(fp)->_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
201*8d67ca89SAndroid Build Coastguard Worker _EXT(fp)->_caller_handles_locking = false;
202*8d67ca89SAndroid Build Coastguard Worker
203*8d67ca89SAndroid Build Coastguard Worker // Caller sets cookie, _read/_write etc.
204*8d67ca89SAndroid Build Coastguard Worker // We explicitly clear _seek and _seek64 to prevent subtle bugs.
205*8d67ca89SAndroid Build Coastguard Worker fp->_seek = nullptr;
206*8d67ca89SAndroid Build Coastguard Worker _EXT(fp)->_seek64 = nullptr;
207*8d67ca89SAndroid Build Coastguard Worker
208*8d67ca89SAndroid Build Coastguard Worker return fp;
209*8d67ca89SAndroid Build Coastguard Worker }
210*8d67ca89SAndroid Build Coastguard Worker
_fwalk(int (* callback)(FILE *))211*8d67ca89SAndroid Build Coastguard Worker int _fwalk(int (*callback)(FILE*)) {
212*8d67ca89SAndroid Build Coastguard Worker int result = 0;
213*8d67ca89SAndroid Build Coastguard Worker for (glue* g = &__sglue; g != nullptr; g = g->next) {
214*8d67ca89SAndroid Build Coastguard Worker FILE* fp = g->iobs;
215*8d67ca89SAndroid Build Coastguard Worker for (int n = g->niobs; --n >= 0; ++fp) {
216*8d67ca89SAndroid Build Coastguard Worker if (fp->_flags != 0 && (fp->_flags & __SIGN) == 0) {
217*8d67ca89SAndroid Build Coastguard Worker result |= (*callback)(fp);
218*8d67ca89SAndroid Build Coastguard Worker }
219*8d67ca89SAndroid Build Coastguard Worker }
220*8d67ca89SAndroid Build Coastguard Worker }
221*8d67ca89SAndroid Build Coastguard Worker return result;
222*8d67ca89SAndroid Build Coastguard Worker }
223*8d67ca89SAndroid Build Coastguard Worker
__libc_stdio_cleanup(void)224*8d67ca89SAndroid Build Coastguard Worker extern "C" __LIBC_HIDDEN__ void __libc_stdio_cleanup(void) {
225*8d67ca89SAndroid Build Coastguard Worker // Equivalent to fflush(nullptr), but without all the locking since we're shutting down anyway.
226*8d67ca89SAndroid Build Coastguard Worker _fwalk(__sflush);
227*8d67ca89SAndroid Build Coastguard Worker }
228*8d67ca89SAndroid Build Coastguard Worker
__FILE_init(FILE * fp,int fd,int flags)229*8d67ca89SAndroid Build Coastguard Worker static FILE* __FILE_init(FILE* fp, int fd, int flags) {
230*8d67ca89SAndroid Build Coastguard Worker if (fp == nullptr) return nullptr;
231*8d67ca89SAndroid Build Coastguard Worker
232*8d67ca89SAndroid Build Coastguard Worker #if !defined(__LP64__)
233*8d67ca89SAndroid Build Coastguard Worker if (fd > SHRT_MAX) __fortify_fatal("stdio: fd %d > SHRT_MAX", fd);
234*8d67ca89SAndroid Build Coastguard Worker #endif
235*8d67ca89SAndroid Build Coastguard Worker
236*8d67ca89SAndroid Build Coastguard Worker fp->_file = fd;
237*8d67ca89SAndroid Build Coastguard Worker android_fdsan_exchange_owner_tag(fd, 0, __get_file_tag(fp));
238*8d67ca89SAndroid Build Coastguard Worker fp->_flags = flags;
239*8d67ca89SAndroid Build Coastguard Worker fp->_cookie = fp;
240*8d67ca89SAndroid Build Coastguard Worker fp->_read = __sread;
241*8d67ca89SAndroid Build Coastguard Worker fp->_write = __swrite;
242*8d67ca89SAndroid Build Coastguard Worker fp->_close = __sclose;
243*8d67ca89SAndroid Build Coastguard Worker _EXT(fp)->_seek64 = __sseek64;
244*8d67ca89SAndroid Build Coastguard Worker return fp;
245*8d67ca89SAndroid Build Coastguard Worker }
246*8d67ca89SAndroid Build Coastguard Worker
fopen(const char * file,const char * mode)247*8d67ca89SAndroid Build Coastguard Worker FILE* fopen(const char* file, const char* mode) {
248*8d67ca89SAndroid Build Coastguard Worker int mode_flags;
249*8d67ca89SAndroid Build Coastguard Worker int flags = __sflags(mode, &mode_flags);
250*8d67ca89SAndroid Build Coastguard Worker if (flags == 0) return nullptr;
251*8d67ca89SAndroid Build Coastguard Worker
252*8d67ca89SAndroid Build Coastguard Worker int fd = open(file, mode_flags, DEFFILEMODE);
253*8d67ca89SAndroid Build Coastguard Worker if (fd == -1) {
254*8d67ca89SAndroid Build Coastguard Worker return nullptr;
255*8d67ca89SAndroid Build Coastguard Worker }
256*8d67ca89SAndroid Build Coastguard Worker
257*8d67ca89SAndroid Build Coastguard Worker FILE* fp = __FILE_init(__sfp(), fd, flags);
258*8d67ca89SAndroid Build Coastguard Worker if (fp == nullptr) {
259*8d67ca89SAndroid Build Coastguard Worker ErrnoRestorer errno_restorer;
260*8d67ca89SAndroid Build Coastguard Worker close(fd);
261*8d67ca89SAndroid Build Coastguard Worker return nullptr;
262*8d67ca89SAndroid Build Coastguard Worker }
263*8d67ca89SAndroid Build Coastguard Worker
264*8d67ca89SAndroid Build Coastguard Worker // For append mode, O_APPEND sets the write position for free, but we need to
265*8d67ca89SAndroid Build Coastguard Worker // set the read position manually.
266*8d67ca89SAndroid Build Coastguard Worker if ((mode_flags & O_APPEND) != 0) __sseek64(fp, 0, SEEK_END);
267*8d67ca89SAndroid Build Coastguard Worker return fp;
268*8d67ca89SAndroid Build Coastguard Worker }
269*8d67ca89SAndroid Build Coastguard Worker __strong_alias(fopen64, fopen);
270*8d67ca89SAndroid Build Coastguard Worker
fdopen(int fd,const char * mode)271*8d67ca89SAndroid Build Coastguard Worker FILE* fdopen(int fd, const char* mode) {
272*8d67ca89SAndroid Build Coastguard Worker int mode_flags;
273*8d67ca89SAndroid Build Coastguard Worker int flags = __sflags(mode, &mode_flags);
274*8d67ca89SAndroid Build Coastguard Worker if (flags == 0) return nullptr;
275*8d67ca89SAndroid Build Coastguard Worker
276*8d67ca89SAndroid Build Coastguard Worker // Make sure the mode the user wants is a subset of the actual mode.
277*8d67ca89SAndroid Build Coastguard Worker int fd_flags = fcntl(fd, F_GETFL, 0);
278*8d67ca89SAndroid Build Coastguard Worker if (fd_flags == -1) return nullptr;
279*8d67ca89SAndroid Build Coastguard Worker int tmp = fd_flags & O_ACCMODE;
280*8d67ca89SAndroid Build Coastguard Worker if (tmp != O_RDWR && (tmp != (mode_flags & O_ACCMODE))) {
281*8d67ca89SAndroid Build Coastguard Worker errno = EINVAL;
282*8d67ca89SAndroid Build Coastguard Worker return nullptr;
283*8d67ca89SAndroid Build Coastguard Worker }
284*8d67ca89SAndroid Build Coastguard Worker
285*8d67ca89SAndroid Build Coastguard Worker // Make sure O_APPEND is set on the underlying fd if our mode has 'a'.
286*8d67ca89SAndroid Build Coastguard Worker // POSIX says we just take the current offset of the underlying fd.
287*8d67ca89SAndroid Build Coastguard Worker if ((mode_flags & O_APPEND) && !(fd_flags & O_APPEND)) {
288*8d67ca89SAndroid Build Coastguard Worker if (fcntl(fd, F_SETFL, fd_flags | O_APPEND) == -1) return nullptr;
289*8d67ca89SAndroid Build Coastguard Worker }
290*8d67ca89SAndroid Build Coastguard Worker
291*8d67ca89SAndroid Build Coastguard Worker // Make sure O_CLOEXEC is set on the underlying fd if our mode has 'e'.
292*8d67ca89SAndroid Build Coastguard Worker if ((mode_flags & O_CLOEXEC) && !((tmp = fcntl(fd, F_GETFD)) & FD_CLOEXEC)) {
293*8d67ca89SAndroid Build Coastguard Worker fcntl(fd, F_SETFD, tmp | FD_CLOEXEC);
294*8d67ca89SAndroid Build Coastguard Worker }
295*8d67ca89SAndroid Build Coastguard Worker
296*8d67ca89SAndroid Build Coastguard Worker return __FILE_init(__sfp(), fd, flags);
297*8d67ca89SAndroid Build Coastguard Worker }
298*8d67ca89SAndroid Build Coastguard Worker
freopen(const char * file,const char * mode,FILE * fp)299*8d67ca89SAndroid Build Coastguard Worker FILE* freopen(const char* file, const char* mode, FILE* fp) {
300*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
301*8d67ca89SAndroid Build Coastguard Worker
302*8d67ca89SAndroid Build Coastguard Worker // POSIX says: "If pathname is a null pointer, the freopen() function shall
303*8d67ca89SAndroid Build Coastguard Worker // attempt to change the mode of the stream to that specified by mode, as if
304*8d67ca89SAndroid Build Coastguard Worker // the name of the file currently associated with the stream had been used. In
305*8d67ca89SAndroid Build Coastguard Worker // this case, the file descriptor associated with the stream need not be
306*8d67ca89SAndroid Build Coastguard Worker // closed if the call to freopen() succeeds. It is implementation-defined
307*8d67ca89SAndroid Build Coastguard Worker // which changes of mode are permitted (if any), and under what
308*8d67ca89SAndroid Build Coastguard Worker // circumstances."
309*8d67ca89SAndroid Build Coastguard Worker //
310*8d67ca89SAndroid Build Coastguard Worker // Linux is quite restrictive about what changes you can make with F_SETFL,
311*8d67ca89SAndroid Build Coastguard Worker // and in particular won't let you touch the access bits. It's easiest and
312*8d67ca89SAndroid Build Coastguard Worker // most effective to just rely on /proc/self/fd/...
313*8d67ca89SAndroid Build Coastguard Worker FdPath fd_path(fp->_file);
314*8d67ca89SAndroid Build Coastguard Worker if (file == nullptr) file = fd_path.c_str();
315*8d67ca89SAndroid Build Coastguard Worker
316*8d67ca89SAndroid Build Coastguard Worker int mode_flags;
317*8d67ca89SAndroid Build Coastguard Worker int flags = __sflags(mode, &mode_flags);
318*8d67ca89SAndroid Build Coastguard Worker if (flags == 0) {
319*8d67ca89SAndroid Build Coastguard Worker fclose(fp);
320*8d67ca89SAndroid Build Coastguard Worker return nullptr;
321*8d67ca89SAndroid Build Coastguard Worker }
322*8d67ca89SAndroid Build Coastguard Worker
323*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
324*8d67ca89SAndroid Build Coastguard Worker
325*8d67ca89SAndroid Build Coastguard Worker // TODO: rewrite this mess completely.
326*8d67ca89SAndroid Build Coastguard Worker
327*8d67ca89SAndroid Build Coastguard Worker // There are actually programs that depend on being able to "freopen"
328*8d67ca89SAndroid Build Coastguard Worker // descriptors that weren't originally open. Keep this from breaking.
329*8d67ca89SAndroid Build Coastguard Worker // Remember whether the stream was open to begin with, and which file
330*8d67ca89SAndroid Build Coastguard Worker // descriptor (if any) was associated with it. If it was attached to
331*8d67ca89SAndroid Build Coastguard Worker // a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
332*8d67ca89SAndroid Build Coastguard Worker // should work. This is unnecessary if it was not a Unix file.
333*8d67ca89SAndroid Build Coastguard Worker int isopen, wantfd;
334*8d67ca89SAndroid Build Coastguard Worker if (fp->_flags == 0) {
335*8d67ca89SAndroid Build Coastguard Worker fp->_flags = __SEOF; // Hold on to it.
336*8d67ca89SAndroid Build Coastguard Worker isopen = 0;
337*8d67ca89SAndroid Build Coastguard Worker wantfd = -1;
338*8d67ca89SAndroid Build Coastguard Worker } else {
339*8d67ca89SAndroid Build Coastguard Worker // Flush the stream; ANSI doesn't require this.
340*8d67ca89SAndroid Build Coastguard Worker if (fp->_flags & __SWR) __sflush(fp);
341*8d67ca89SAndroid Build Coastguard Worker
342*8d67ca89SAndroid Build Coastguard Worker // If close is null, closing is a no-op, hence pointless.
343*8d67ca89SAndroid Build Coastguard Worker isopen = (fp->_close != nullptr);
344*8d67ca89SAndroid Build Coastguard Worker if ((wantfd = fp->_file) < 0 && isopen) {
345*8d67ca89SAndroid Build Coastguard Worker (*fp->_close)(fp->_cookie);
346*8d67ca89SAndroid Build Coastguard Worker isopen = 0;
347*8d67ca89SAndroid Build Coastguard Worker }
348*8d67ca89SAndroid Build Coastguard Worker }
349*8d67ca89SAndroid Build Coastguard Worker
350*8d67ca89SAndroid Build Coastguard Worker // Get a new descriptor to refer to the new file.
351*8d67ca89SAndroid Build Coastguard Worker int fd = open(file, mode_flags, DEFFILEMODE);
352*8d67ca89SAndroid Build Coastguard Worker if (fd < 0 && isopen) {
353*8d67ca89SAndroid Build Coastguard Worker // If out of fd's close the old one and try again.
354*8d67ca89SAndroid Build Coastguard Worker if (errno == ENFILE || errno == EMFILE) {
355*8d67ca89SAndroid Build Coastguard Worker (*fp->_close)(fp->_cookie);
356*8d67ca89SAndroid Build Coastguard Worker isopen = 0;
357*8d67ca89SAndroid Build Coastguard Worker fd = open(file, mode_flags, DEFFILEMODE);
358*8d67ca89SAndroid Build Coastguard Worker }
359*8d67ca89SAndroid Build Coastguard Worker }
360*8d67ca89SAndroid Build Coastguard Worker
361*8d67ca89SAndroid Build Coastguard Worker int sverrno = errno;
362*8d67ca89SAndroid Build Coastguard Worker
363*8d67ca89SAndroid Build Coastguard Worker // Finish closing fp. Even if the open succeeded above, we cannot
364*8d67ca89SAndroid Build Coastguard Worker // keep fp->_base: it may be the wrong size. This loses the effect
365*8d67ca89SAndroid Build Coastguard Worker // of any setbuffer calls, but stdio has always done this before.
366*8d67ca89SAndroid Build Coastguard Worker if (isopen && fd != wantfd) (*fp->_close)(fp->_cookie);
367*8d67ca89SAndroid Build Coastguard Worker if (fp->_flags & __SMBF) free(fp->_bf._base);
368*8d67ca89SAndroid Build Coastguard Worker fp->_w = 0;
369*8d67ca89SAndroid Build Coastguard Worker fp->_r = 0;
370*8d67ca89SAndroid Build Coastguard Worker fp->_p = nullptr;
371*8d67ca89SAndroid Build Coastguard Worker fp->_bf._base = nullptr;
372*8d67ca89SAndroid Build Coastguard Worker fp->_bf._size = 0;
373*8d67ca89SAndroid Build Coastguard Worker fp->_lbfsize = 0;
374*8d67ca89SAndroid Build Coastguard Worker if (HASUB(fp)) FREEUB(fp);
375*8d67ca89SAndroid Build Coastguard Worker _UB(fp)._size = 0;
376*8d67ca89SAndroid Build Coastguard Worker WCIO_FREE(fp);
377*8d67ca89SAndroid Build Coastguard Worker free_fgetln_buffer(fp);
378*8d67ca89SAndroid Build Coastguard Worker fp->_lb._size = 0;
379*8d67ca89SAndroid Build Coastguard Worker
380*8d67ca89SAndroid Build Coastguard Worker if (fd < 0) { // Did not get it after all.
381*8d67ca89SAndroid Build Coastguard Worker fp->_flags = 0; // Release.
382*8d67ca89SAndroid Build Coastguard Worker errno = sverrno; // Restore errno in case _close clobbered it.
383*8d67ca89SAndroid Build Coastguard Worker return nullptr;
384*8d67ca89SAndroid Build Coastguard Worker }
385*8d67ca89SAndroid Build Coastguard Worker
386*8d67ca89SAndroid Build Coastguard Worker // If reopening something that was open before on a real file, try
387*8d67ca89SAndroid Build Coastguard Worker // to maintain the descriptor. Various C library routines (perror)
388*8d67ca89SAndroid Build Coastguard Worker // assume stderr is always fd STDERR_FILENO, even if being freopen'd.
389*8d67ca89SAndroid Build Coastguard Worker if (wantfd >= 0 && fd != wantfd) {
390*8d67ca89SAndroid Build Coastguard Worker if (dup3(fd, wantfd, mode_flags & O_CLOEXEC) >= 0) {
391*8d67ca89SAndroid Build Coastguard Worker close(fd);
392*8d67ca89SAndroid Build Coastguard Worker fd = wantfd;
393*8d67ca89SAndroid Build Coastguard Worker }
394*8d67ca89SAndroid Build Coastguard Worker }
395*8d67ca89SAndroid Build Coastguard Worker
396*8d67ca89SAndroid Build Coastguard Worker __FILE_init(fp, fd, flags);
397*8d67ca89SAndroid Build Coastguard Worker
398*8d67ca89SAndroid Build Coastguard Worker // For append mode, O_APPEND sets the write position for free, but we need to
399*8d67ca89SAndroid Build Coastguard Worker // set the read position manually.
400*8d67ca89SAndroid Build Coastguard Worker if ((mode_flags & O_APPEND) != 0) __sseek64(fp, 0, SEEK_END);
401*8d67ca89SAndroid Build Coastguard Worker
402*8d67ca89SAndroid Build Coastguard Worker return fp;
403*8d67ca89SAndroid Build Coastguard Worker }
404*8d67ca89SAndroid Build Coastguard Worker __strong_alias(freopen64, freopen);
405*8d67ca89SAndroid Build Coastguard Worker
__FILE_close(FILE * fp)406*8d67ca89SAndroid Build Coastguard Worker static int __FILE_close(FILE* fp) {
407*8d67ca89SAndroid Build Coastguard Worker if (fp->_flags == 0) {
408*8d67ca89SAndroid Build Coastguard Worker // Already freed!
409*8d67ca89SAndroid Build Coastguard Worker errno = EBADF;
410*8d67ca89SAndroid Build Coastguard Worker return EOF;
411*8d67ca89SAndroid Build Coastguard Worker }
412*8d67ca89SAndroid Build Coastguard Worker
413*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
414*8d67ca89SAndroid Build Coastguard Worker WCIO_FREE(fp);
415*8d67ca89SAndroid Build Coastguard Worker int r = fp->_flags & __SWR ? __sflush(fp) : 0;
416*8d67ca89SAndroid Build Coastguard Worker if (fp->_close != nullptr && (*fp->_close)(fp->_cookie) < 0) {
417*8d67ca89SAndroid Build Coastguard Worker r = EOF;
418*8d67ca89SAndroid Build Coastguard Worker }
419*8d67ca89SAndroid Build Coastguard Worker if (fp->_flags & __SMBF) free(fp->_bf._base);
420*8d67ca89SAndroid Build Coastguard Worker if (HASUB(fp)) FREEUB(fp);
421*8d67ca89SAndroid Build Coastguard Worker free_fgetln_buffer(fp);
422*8d67ca89SAndroid Build Coastguard Worker
423*8d67ca89SAndroid Build Coastguard Worker // If we were created by popen(3), wait for the child.
424*8d67ca89SAndroid Build Coastguard Worker pid_t pid = _EXT(fp)->_popen_pid;
425*8d67ca89SAndroid Build Coastguard Worker if (pid > 0) {
426*8d67ca89SAndroid Build Coastguard Worker int status;
427*8d67ca89SAndroid Build Coastguard Worker if (TEMP_FAILURE_RETRY(wait4(pid, &status, 0, nullptr)) != -1) {
428*8d67ca89SAndroid Build Coastguard Worker r = status;
429*8d67ca89SAndroid Build Coastguard Worker }
430*8d67ca89SAndroid Build Coastguard Worker }
431*8d67ca89SAndroid Build Coastguard Worker _EXT(fp)->_popen_pid = 0;
432*8d67ca89SAndroid Build Coastguard Worker
433*8d67ca89SAndroid Build Coastguard Worker // Poison this FILE so accesses after fclose will be obvious.
434*8d67ca89SAndroid Build Coastguard Worker fp->_file = -1;
435*8d67ca89SAndroid Build Coastguard Worker fp->_r = fp->_w = 0;
436*8d67ca89SAndroid Build Coastguard Worker
437*8d67ca89SAndroid Build Coastguard Worker // Release this FILE for reuse.
438*8d67ca89SAndroid Build Coastguard Worker fp->_flags = 0;
439*8d67ca89SAndroid Build Coastguard Worker return r;
440*8d67ca89SAndroid Build Coastguard Worker }
441*8d67ca89SAndroid Build Coastguard Worker
fclose(FILE * fp)442*8d67ca89SAndroid Build Coastguard Worker int fclose(FILE* fp) {
443*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
444*8d67ca89SAndroid Build Coastguard Worker return __FILE_close(fp);
445*8d67ca89SAndroid Build Coastguard Worker }
446*8d67ca89SAndroid Build Coastguard Worker
fileno_unlocked(FILE * fp)447*8d67ca89SAndroid Build Coastguard Worker int fileno_unlocked(FILE* fp) {
448*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
449*8d67ca89SAndroid Build Coastguard Worker int fd = fp->_file;
450*8d67ca89SAndroid Build Coastguard Worker if (fd == -1) {
451*8d67ca89SAndroid Build Coastguard Worker errno = EBADF;
452*8d67ca89SAndroid Build Coastguard Worker return -1;
453*8d67ca89SAndroid Build Coastguard Worker }
454*8d67ca89SAndroid Build Coastguard Worker return fd;
455*8d67ca89SAndroid Build Coastguard Worker }
456*8d67ca89SAndroid Build Coastguard Worker
fileno(FILE * fp)457*8d67ca89SAndroid Build Coastguard Worker int fileno(FILE* fp) {
458*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
459*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
460*8d67ca89SAndroid Build Coastguard Worker return fileno_unlocked(fp);
461*8d67ca89SAndroid Build Coastguard Worker }
462*8d67ca89SAndroid Build Coastguard Worker
clearerr_unlocked(FILE * fp)463*8d67ca89SAndroid Build Coastguard Worker void clearerr_unlocked(FILE* fp) {
464*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
465*8d67ca89SAndroid Build Coastguard Worker return __sclearerr(fp);
466*8d67ca89SAndroid Build Coastguard Worker }
467*8d67ca89SAndroid Build Coastguard Worker
clearerr(FILE * fp)468*8d67ca89SAndroid Build Coastguard Worker void clearerr(FILE* fp) {
469*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
470*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
471*8d67ca89SAndroid Build Coastguard Worker clearerr_unlocked(fp);
472*8d67ca89SAndroid Build Coastguard Worker }
473*8d67ca89SAndroid Build Coastguard Worker
feof_unlocked(FILE * fp)474*8d67ca89SAndroid Build Coastguard Worker int feof_unlocked(FILE* fp) {
475*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
476*8d67ca89SAndroid Build Coastguard Worker return ((fp->_flags & __SEOF) != 0);
477*8d67ca89SAndroid Build Coastguard Worker }
478*8d67ca89SAndroid Build Coastguard Worker
feof(FILE * fp)479*8d67ca89SAndroid Build Coastguard Worker int feof(FILE* fp) {
480*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
481*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
482*8d67ca89SAndroid Build Coastguard Worker return feof_unlocked(fp);
483*8d67ca89SAndroid Build Coastguard Worker }
484*8d67ca89SAndroid Build Coastguard Worker
ferror_unlocked(FILE * fp)485*8d67ca89SAndroid Build Coastguard Worker int ferror_unlocked(FILE* fp) {
486*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
487*8d67ca89SAndroid Build Coastguard Worker return __sferror(fp);
488*8d67ca89SAndroid Build Coastguard Worker }
489*8d67ca89SAndroid Build Coastguard Worker
ferror(FILE * fp)490*8d67ca89SAndroid Build Coastguard Worker int ferror(FILE* fp) {
491*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
492*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
493*8d67ca89SAndroid Build Coastguard Worker return ferror_unlocked(fp);
494*8d67ca89SAndroid Build Coastguard Worker }
495*8d67ca89SAndroid Build Coastguard Worker
__sflush(FILE * fp)496*8d67ca89SAndroid Build Coastguard Worker int __sflush(FILE* fp) {
497*8d67ca89SAndroid Build Coastguard Worker // Flushing a read-only file is a no-op.
498*8d67ca89SAndroid Build Coastguard Worker if ((fp->_flags & __SWR) == 0) return 0;
499*8d67ca89SAndroid Build Coastguard Worker
500*8d67ca89SAndroid Build Coastguard Worker // Flushing a file without a buffer is a no-op.
501*8d67ca89SAndroid Build Coastguard Worker unsigned char* p = fp->_bf._base;
502*8d67ca89SAndroid Build Coastguard Worker if (p == nullptr) return 0;
503*8d67ca89SAndroid Build Coastguard Worker
504*8d67ca89SAndroid Build Coastguard Worker // Set these immediately to avoid problems with longjmp and to allow
505*8d67ca89SAndroid Build Coastguard Worker // exchange buffering (via setvbuf) in user write function.
506*8d67ca89SAndroid Build Coastguard Worker int n = fp->_p - p;
507*8d67ca89SAndroid Build Coastguard Worker fp->_p = p;
508*8d67ca89SAndroid Build Coastguard Worker fp->_w = (fp->_flags & (__SLBF|__SNBF)) ? 0 : fp->_bf._size;
509*8d67ca89SAndroid Build Coastguard Worker
510*8d67ca89SAndroid Build Coastguard Worker while (n > 0) {
511*8d67ca89SAndroid Build Coastguard Worker int written = (*fp->_write)(fp->_cookie, reinterpret_cast<char*>(p), n);
512*8d67ca89SAndroid Build Coastguard Worker if (written <= 0) {
513*8d67ca89SAndroid Build Coastguard Worker fp->_flags |= __SERR;
514*8d67ca89SAndroid Build Coastguard Worker return EOF;
515*8d67ca89SAndroid Build Coastguard Worker }
516*8d67ca89SAndroid Build Coastguard Worker n -= written, p += written;
517*8d67ca89SAndroid Build Coastguard Worker }
518*8d67ca89SAndroid Build Coastguard Worker return 0;
519*8d67ca89SAndroid Build Coastguard Worker }
520*8d67ca89SAndroid Build Coastguard Worker
__sflush_locked(FILE * fp)521*8d67ca89SAndroid Build Coastguard Worker int __sflush_locked(FILE* fp) {
522*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
523*8d67ca89SAndroid Build Coastguard Worker return __sflush(fp);
524*8d67ca89SAndroid Build Coastguard Worker }
525*8d67ca89SAndroid Build Coastguard Worker
__sread(void * cookie,char * buf,int n)526*8d67ca89SAndroid Build Coastguard Worker int __sread(void* cookie, char* buf, int n) {
527*8d67ca89SAndroid Build Coastguard Worker FILE* fp = reinterpret_cast<FILE*>(cookie);
528*8d67ca89SAndroid Build Coastguard Worker return TEMP_FAILURE_RETRY(read(fp->_file, buf, n));
529*8d67ca89SAndroid Build Coastguard Worker }
530*8d67ca89SAndroid Build Coastguard Worker
__swrite(void * cookie,const char * buf,int n)531*8d67ca89SAndroid Build Coastguard Worker int __swrite(void* cookie, const char* buf, int n) {
532*8d67ca89SAndroid Build Coastguard Worker FILE* fp = reinterpret_cast<FILE*>(cookie);
533*8d67ca89SAndroid Build Coastguard Worker return TEMP_FAILURE_RETRY(write(fp->_file, buf, n));
534*8d67ca89SAndroid Build Coastguard Worker }
535*8d67ca89SAndroid Build Coastguard Worker
__sseek(void * cookie,fpos_t offset,int whence)536*8d67ca89SAndroid Build Coastguard Worker fpos_t __sseek(void* cookie, fpos_t offset, int whence) {
537*8d67ca89SAndroid Build Coastguard Worker FILE* fp = reinterpret_cast<FILE*>(cookie);
538*8d67ca89SAndroid Build Coastguard Worker return TEMP_FAILURE_RETRY(lseek(fp->_file, offset, whence));
539*8d67ca89SAndroid Build Coastguard Worker }
540*8d67ca89SAndroid Build Coastguard Worker
__sseek64(void * cookie,off64_t offset,int whence)541*8d67ca89SAndroid Build Coastguard Worker off64_t __sseek64(void* cookie, off64_t offset, int whence) {
542*8d67ca89SAndroid Build Coastguard Worker FILE* fp = reinterpret_cast<FILE*>(cookie);
543*8d67ca89SAndroid Build Coastguard Worker return TEMP_FAILURE_RETRY(lseek64(fp->_file, offset, whence));
544*8d67ca89SAndroid Build Coastguard Worker }
545*8d67ca89SAndroid Build Coastguard Worker
__sclose(void * cookie)546*8d67ca89SAndroid Build Coastguard Worker int __sclose(void* cookie) {
547*8d67ca89SAndroid Build Coastguard Worker FILE* fp = reinterpret_cast<FILE*>(cookie);
548*8d67ca89SAndroid Build Coastguard Worker return android_fdsan_close_with_tag(fp->_file, __get_file_tag(fp));
549*8d67ca89SAndroid Build Coastguard Worker }
550*8d67ca89SAndroid Build Coastguard Worker
__seek_unlocked(FILE * fp,off64_t offset,int whence)551*8d67ca89SAndroid Build Coastguard Worker static off64_t __seek_unlocked(FILE* fp, off64_t offset, int whence) {
552*8d67ca89SAndroid Build Coastguard Worker // Use `_seek64` if set, but fall back to `_seek`.
553*8d67ca89SAndroid Build Coastguard Worker if (_EXT(fp)->_seek64 != nullptr) {
554*8d67ca89SAndroid Build Coastguard Worker return (*_EXT(fp)->_seek64)(fp->_cookie, offset, whence);
555*8d67ca89SAndroid Build Coastguard Worker } else if (fp->_seek != nullptr) {
556*8d67ca89SAndroid Build Coastguard Worker off64_t result = (*fp->_seek)(fp->_cookie, offset, whence);
557*8d67ca89SAndroid Build Coastguard Worker #if !defined(__LP64__)
558*8d67ca89SAndroid Build Coastguard Worker // Avoid sign extension if off64_t is larger than off_t.
559*8d67ca89SAndroid Build Coastguard Worker if (result != -1) result &= 0xffffffff;
560*8d67ca89SAndroid Build Coastguard Worker #endif
561*8d67ca89SAndroid Build Coastguard Worker return result;
562*8d67ca89SAndroid Build Coastguard Worker } else {
563*8d67ca89SAndroid Build Coastguard Worker errno = ESPIPE;
564*8d67ca89SAndroid Build Coastguard Worker return -1;
565*8d67ca89SAndroid Build Coastguard Worker }
566*8d67ca89SAndroid Build Coastguard Worker }
567*8d67ca89SAndroid Build Coastguard Worker
__ftello64_unlocked(FILE * fp)568*8d67ca89SAndroid Build Coastguard Worker static off64_t __ftello64_unlocked(FILE* fp) {
569*8d67ca89SAndroid Build Coastguard Worker // Find offset of underlying I/O object, then adjust for buffered bytes.
570*8d67ca89SAndroid Build Coastguard Worker __sflush(fp); // May adjust seek offset on append stream.
571*8d67ca89SAndroid Build Coastguard Worker
572*8d67ca89SAndroid Build Coastguard Worker off64_t result = __seek_unlocked(fp, 0, SEEK_CUR);
573*8d67ca89SAndroid Build Coastguard Worker if (result == -1) {
574*8d67ca89SAndroid Build Coastguard Worker return -1;
575*8d67ca89SAndroid Build Coastguard Worker }
576*8d67ca89SAndroid Build Coastguard Worker
577*8d67ca89SAndroid Build Coastguard Worker if (fp->_flags & __SRD) {
578*8d67ca89SAndroid Build Coastguard Worker // Reading. Any unread characters (including
579*8d67ca89SAndroid Build Coastguard Worker // those from ungetc) cause the position to be
580*8d67ca89SAndroid Build Coastguard Worker // smaller than that in the underlying object.
581*8d67ca89SAndroid Build Coastguard Worker result -= fp->_r;
582*8d67ca89SAndroid Build Coastguard Worker if (HASUB(fp)) result -= fp->_ur;
583*8d67ca89SAndroid Build Coastguard Worker } else if (fp->_flags & __SWR && fp->_p != nullptr) {
584*8d67ca89SAndroid Build Coastguard Worker // Writing. Any buffered characters cause the
585*8d67ca89SAndroid Build Coastguard Worker // position to be greater than that in the
586*8d67ca89SAndroid Build Coastguard Worker // underlying object.
587*8d67ca89SAndroid Build Coastguard Worker result += fp->_p - fp->_bf._base;
588*8d67ca89SAndroid Build Coastguard Worker }
589*8d67ca89SAndroid Build Coastguard Worker return result;
590*8d67ca89SAndroid Build Coastguard Worker }
591*8d67ca89SAndroid Build Coastguard Worker
__fseeko64(FILE * fp,off64_t offset,int whence,int off_t_bits)592*8d67ca89SAndroid Build Coastguard Worker int __fseeko64(FILE* fp, off64_t offset, int whence, int off_t_bits) {
593*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
594*8d67ca89SAndroid Build Coastguard Worker
595*8d67ca89SAndroid Build Coastguard Worker // Change any SEEK_CUR to SEEK_SET, and check `whence` argument.
596*8d67ca89SAndroid Build Coastguard Worker // After this, whence is either SEEK_SET or SEEK_END.
597*8d67ca89SAndroid Build Coastguard Worker if (whence == SEEK_CUR) {
598*8d67ca89SAndroid Build Coastguard Worker fpos64_t current_offset = __ftello64_unlocked(fp);
599*8d67ca89SAndroid Build Coastguard Worker if (current_offset == -1) {
600*8d67ca89SAndroid Build Coastguard Worker return -1;
601*8d67ca89SAndroid Build Coastguard Worker }
602*8d67ca89SAndroid Build Coastguard Worker offset += current_offset;
603*8d67ca89SAndroid Build Coastguard Worker whence = SEEK_SET;
604*8d67ca89SAndroid Build Coastguard Worker } else if (whence != SEEK_SET && whence != SEEK_END) {
605*8d67ca89SAndroid Build Coastguard Worker errno = EINVAL;
606*8d67ca89SAndroid Build Coastguard Worker return -1;
607*8d67ca89SAndroid Build Coastguard Worker }
608*8d67ca89SAndroid Build Coastguard Worker
609*8d67ca89SAndroid Build Coastguard Worker // If our caller has a 32-bit interface, refuse to go past a 32-bit file offset.
610*8d67ca89SAndroid Build Coastguard Worker if (off_t_bits == 32 && offset > LONG_MAX) {
611*8d67ca89SAndroid Build Coastguard Worker errno = EOVERFLOW;
612*8d67ca89SAndroid Build Coastguard Worker return -1;
613*8d67ca89SAndroid Build Coastguard Worker }
614*8d67ca89SAndroid Build Coastguard Worker
615*8d67ca89SAndroid Build Coastguard Worker if (fp->_bf._base == nullptr) __smakebuf(fp);
616*8d67ca89SAndroid Build Coastguard Worker
617*8d67ca89SAndroid Build Coastguard Worker // Flush unwritten data and attempt the seek.
618*8d67ca89SAndroid Build Coastguard Worker if (__sflush(fp) || __seek_unlocked(fp, offset, whence) == -1) {
619*8d67ca89SAndroid Build Coastguard Worker return -1;
620*8d67ca89SAndroid Build Coastguard Worker }
621*8d67ca89SAndroid Build Coastguard Worker
622*8d67ca89SAndroid Build Coastguard Worker // Success: clear EOF indicator and discard ungetc() data.
623*8d67ca89SAndroid Build Coastguard Worker if (HASUB(fp)) FREEUB(fp);
624*8d67ca89SAndroid Build Coastguard Worker fp->_p = fp->_bf._base;
625*8d67ca89SAndroid Build Coastguard Worker fp->_r = 0;
626*8d67ca89SAndroid Build Coastguard Worker /* fp->_w = 0; */ /* unnecessary (I think...) */
627*8d67ca89SAndroid Build Coastguard Worker fp->_flags &= ~__SEOF;
628*8d67ca89SAndroid Build Coastguard Worker return 0;
629*8d67ca89SAndroid Build Coastguard Worker }
630*8d67ca89SAndroid Build Coastguard Worker
fseeko(FILE * fp,off_t offset,int whence)631*8d67ca89SAndroid Build Coastguard Worker int fseeko(FILE* fp, off_t offset, int whence) {
632*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
633*8d67ca89SAndroid Build Coastguard Worker static_assert(sizeof(off_t) == sizeof(long), "sizeof(off_t) != sizeof(long)");
634*8d67ca89SAndroid Build Coastguard Worker return __fseeko64(fp, offset, whence, 8*sizeof(off_t));
635*8d67ca89SAndroid Build Coastguard Worker }
636*8d67ca89SAndroid Build Coastguard Worker __strong_alias(fseek, fseeko);
637*8d67ca89SAndroid Build Coastguard Worker
fseeko64(FILE * fp,off64_t offset,int whence)638*8d67ca89SAndroid Build Coastguard Worker int fseeko64(FILE* fp, off64_t offset, int whence) {
639*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
640*8d67ca89SAndroid Build Coastguard Worker return __fseeko64(fp, offset, whence, 8*sizeof(off64_t));
641*8d67ca89SAndroid Build Coastguard Worker }
642*8d67ca89SAndroid Build Coastguard Worker
fsetpos(FILE * fp,const fpos_t * pos)643*8d67ca89SAndroid Build Coastguard Worker int fsetpos(FILE* fp, const fpos_t* pos) {
644*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
645*8d67ca89SAndroid Build Coastguard Worker return fseeko(fp, *pos, SEEK_SET);
646*8d67ca89SAndroid Build Coastguard Worker }
647*8d67ca89SAndroid Build Coastguard Worker
fsetpos64(FILE * fp,const fpos64_t * pos)648*8d67ca89SAndroid Build Coastguard Worker int fsetpos64(FILE* fp, const fpos64_t* pos) {
649*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
650*8d67ca89SAndroid Build Coastguard Worker return fseeko64(fp, *pos, SEEK_SET);
651*8d67ca89SAndroid Build Coastguard Worker }
652*8d67ca89SAndroid Build Coastguard Worker
ftello(FILE * fp)653*8d67ca89SAndroid Build Coastguard Worker off_t ftello(FILE* fp) {
654*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
655*8d67ca89SAndroid Build Coastguard Worker static_assert(sizeof(off_t) == sizeof(long), "sizeof(off_t) != sizeof(long)");
656*8d67ca89SAndroid Build Coastguard Worker off64_t result = ftello64(fp);
657*8d67ca89SAndroid Build Coastguard Worker if (result > LONG_MAX) {
658*8d67ca89SAndroid Build Coastguard Worker errno = EOVERFLOW;
659*8d67ca89SAndroid Build Coastguard Worker return -1;
660*8d67ca89SAndroid Build Coastguard Worker }
661*8d67ca89SAndroid Build Coastguard Worker return result;
662*8d67ca89SAndroid Build Coastguard Worker }
663*8d67ca89SAndroid Build Coastguard Worker __strong_alias(ftell, ftello);
664*8d67ca89SAndroid Build Coastguard Worker
ftello64(FILE * fp)665*8d67ca89SAndroid Build Coastguard Worker off64_t ftello64(FILE* fp) {
666*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
667*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
668*8d67ca89SAndroid Build Coastguard Worker return __ftello64_unlocked(fp);
669*8d67ca89SAndroid Build Coastguard Worker }
670*8d67ca89SAndroid Build Coastguard Worker
fgetpos(FILE * fp,fpos_t * pos)671*8d67ca89SAndroid Build Coastguard Worker int fgetpos(FILE* fp, fpos_t* pos) {
672*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
673*8d67ca89SAndroid Build Coastguard Worker *pos = ftello(fp);
674*8d67ca89SAndroid Build Coastguard Worker return (*pos == -1) ? -1 : 0;
675*8d67ca89SAndroid Build Coastguard Worker }
676*8d67ca89SAndroid Build Coastguard Worker
fgetpos64(FILE * fp,fpos64_t * pos)677*8d67ca89SAndroid Build Coastguard Worker int fgetpos64(FILE* fp, fpos64_t* pos) {
678*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
679*8d67ca89SAndroid Build Coastguard Worker *pos = ftello64(fp);
680*8d67ca89SAndroid Build Coastguard Worker return (*pos == -1) ? -1 : 0;
681*8d67ca89SAndroid Build Coastguard Worker }
682*8d67ca89SAndroid Build Coastguard Worker
__funopen(const void * cookie,int (* read_fn)(void *,char *,int),int (* write_fn)(void *,const char *,int),int (* close_fn)(void *))683*8d67ca89SAndroid Build Coastguard Worker static FILE* __funopen(const void* cookie,
684*8d67ca89SAndroid Build Coastguard Worker int (*read_fn)(void*, char*, int),
685*8d67ca89SAndroid Build Coastguard Worker int (*write_fn)(void*, const char*, int),
686*8d67ca89SAndroid Build Coastguard Worker int (*close_fn)(void*)) {
687*8d67ca89SAndroid Build Coastguard Worker if (read_fn == nullptr && write_fn == nullptr) {
688*8d67ca89SAndroid Build Coastguard Worker errno = EINVAL;
689*8d67ca89SAndroid Build Coastguard Worker return nullptr;
690*8d67ca89SAndroid Build Coastguard Worker }
691*8d67ca89SAndroid Build Coastguard Worker
692*8d67ca89SAndroid Build Coastguard Worker FILE* fp = __sfp();
693*8d67ca89SAndroid Build Coastguard Worker if (fp == nullptr) return nullptr;
694*8d67ca89SAndroid Build Coastguard Worker
695*8d67ca89SAndroid Build Coastguard Worker if (read_fn != nullptr && write_fn != nullptr) {
696*8d67ca89SAndroid Build Coastguard Worker fp->_flags = __SRW;
697*8d67ca89SAndroid Build Coastguard Worker } else if (read_fn != nullptr) {
698*8d67ca89SAndroid Build Coastguard Worker fp->_flags = __SRD;
699*8d67ca89SAndroid Build Coastguard Worker } else if (write_fn != nullptr) {
700*8d67ca89SAndroid Build Coastguard Worker fp->_flags = __SWR;
701*8d67ca89SAndroid Build Coastguard Worker }
702*8d67ca89SAndroid Build Coastguard Worker
703*8d67ca89SAndroid Build Coastguard Worker fp->_file = -1;
704*8d67ca89SAndroid Build Coastguard Worker fp->_cookie = const_cast<void*>(cookie); // The funopen(3) API is incoherent.
705*8d67ca89SAndroid Build Coastguard Worker fp->_read = read_fn;
706*8d67ca89SAndroid Build Coastguard Worker fp->_write = write_fn;
707*8d67ca89SAndroid Build Coastguard Worker fp->_close = close_fn;
708*8d67ca89SAndroid Build Coastguard Worker
709*8d67ca89SAndroid Build Coastguard Worker return fp;
710*8d67ca89SAndroid Build Coastguard Worker }
711*8d67ca89SAndroid Build Coastguard Worker
funopen(const void * cookie,int (* read_fn)(void *,char *,int),int (* write_fn)(void *,const char *,int),fpos_t (* seek_fn)(void *,fpos_t,int),int (* close_fn)(void *))712*8d67ca89SAndroid Build Coastguard Worker FILE* funopen(const void* cookie,
713*8d67ca89SAndroid Build Coastguard Worker int (*read_fn)(void*, char*, int),
714*8d67ca89SAndroid Build Coastguard Worker int (*write_fn)(void*, const char*, int),
715*8d67ca89SAndroid Build Coastguard Worker fpos_t (*seek_fn)(void*, fpos_t, int),
716*8d67ca89SAndroid Build Coastguard Worker int (*close_fn)(void*)) {
717*8d67ca89SAndroid Build Coastguard Worker FILE* fp = __funopen(cookie, read_fn, write_fn, close_fn);
718*8d67ca89SAndroid Build Coastguard Worker if (fp != nullptr) {
719*8d67ca89SAndroid Build Coastguard Worker fp->_seek = seek_fn;
720*8d67ca89SAndroid Build Coastguard Worker }
721*8d67ca89SAndroid Build Coastguard Worker return fp;
722*8d67ca89SAndroid Build Coastguard Worker }
723*8d67ca89SAndroid Build Coastguard Worker
funopen64(const void * cookie,int (* read_fn)(void *,char *,int),int (* write_fn)(void *,const char *,int),fpos64_t (* seek_fn)(void *,fpos64_t,int),int (* close_fn)(void *))724*8d67ca89SAndroid Build Coastguard Worker FILE* funopen64(const void* cookie,
725*8d67ca89SAndroid Build Coastguard Worker int (*read_fn)(void*, char*, int),
726*8d67ca89SAndroid Build Coastguard Worker int (*write_fn)(void*, const char*, int),
727*8d67ca89SAndroid Build Coastguard Worker fpos64_t (*seek_fn)(void*, fpos64_t, int),
728*8d67ca89SAndroid Build Coastguard Worker int (*close_fn)(void*)) {
729*8d67ca89SAndroid Build Coastguard Worker FILE* fp = __funopen(cookie, read_fn, write_fn, close_fn);
730*8d67ca89SAndroid Build Coastguard Worker if (fp != nullptr) {
731*8d67ca89SAndroid Build Coastguard Worker _EXT(fp)->_seek64 = seek_fn;
732*8d67ca89SAndroid Build Coastguard Worker }
733*8d67ca89SAndroid Build Coastguard Worker return fp;
734*8d67ca89SAndroid Build Coastguard Worker }
735*8d67ca89SAndroid Build Coastguard Worker
asprintf(char ** s,const char * fmt,...)736*8d67ca89SAndroid Build Coastguard Worker int asprintf(char** s, const char* fmt, ...) {
737*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vasprintf(s, fmt, ap));
738*8d67ca89SAndroid Build Coastguard Worker }
739*8d67ca89SAndroid Build Coastguard Worker
ctermid(char * s)740*8d67ca89SAndroid Build Coastguard Worker char* ctermid(char* s) {
741*8d67ca89SAndroid Build Coastguard Worker return s ? strcpy(s, _PATH_TTY) : const_cast<char*>(_PATH_TTY);
742*8d67ca89SAndroid Build Coastguard Worker }
743*8d67ca89SAndroid Build Coastguard Worker
dprintf(int fd,const char * fmt,...)744*8d67ca89SAndroid Build Coastguard Worker int dprintf(int fd, const char* fmt, ...) {
745*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vdprintf(fd, fmt, ap));
746*8d67ca89SAndroid Build Coastguard Worker }
747*8d67ca89SAndroid Build Coastguard Worker
fprintf(FILE * fp,const char * fmt,...)748*8d67ca89SAndroid Build Coastguard Worker int fprintf(FILE* fp, const char* fmt, ...) {
749*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
750*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vfprintf(fp, fmt, ap));
751*8d67ca89SAndroid Build Coastguard Worker }
752*8d67ca89SAndroid Build Coastguard Worker
fgetc(FILE * fp)753*8d67ca89SAndroid Build Coastguard Worker int fgetc(FILE* fp) {
754*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
755*8d67ca89SAndroid Build Coastguard Worker return getc(fp);
756*8d67ca89SAndroid Build Coastguard Worker }
757*8d67ca89SAndroid Build Coastguard Worker
fgetc_unlocked(FILE * fp)758*8d67ca89SAndroid Build Coastguard Worker int fgetc_unlocked(FILE* fp) {
759*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
760*8d67ca89SAndroid Build Coastguard Worker return getc_unlocked(fp);
761*8d67ca89SAndroid Build Coastguard Worker }
762*8d67ca89SAndroid Build Coastguard Worker
fgets(char * buf,int n,FILE * fp)763*8d67ca89SAndroid Build Coastguard Worker char* fgets(char* buf, int n, FILE* fp) {
764*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
765*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
766*8d67ca89SAndroid Build Coastguard Worker return fgets_unlocked(buf, n, fp);
767*8d67ca89SAndroid Build Coastguard Worker }
768*8d67ca89SAndroid Build Coastguard Worker
769*8d67ca89SAndroid Build Coastguard Worker // Reads at most n-1 characters from the given file.
770*8d67ca89SAndroid Build Coastguard Worker // Stops when a newline has been read, or the count runs out.
771*8d67ca89SAndroid Build Coastguard Worker // Returns first argument, or nullptr if no characters were read.
772*8d67ca89SAndroid Build Coastguard Worker // Does not return nullptr if n == 1.
fgets_unlocked(char * buf,int n,FILE * fp)773*8d67ca89SAndroid Build Coastguard Worker char* fgets_unlocked(char* buf, int n, FILE* fp) {
774*8d67ca89SAndroid Build Coastguard Worker if (n <= 0) __fortify_fatal("fgets: buffer size %d <= 0", n);
775*8d67ca89SAndroid Build Coastguard Worker
776*8d67ca89SAndroid Build Coastguard Worker _SET_ORIENTATION(fp, ORIENT_BYTES);
777*8d67ca89SAndroid Build Coastguard Worker
778*8d67ca89SAndroid Build Coastguard Worker char* s = buf;
779*8d67ca89SAndroid Build Coastguard Worker n--; // Leave space for NUL.
780*8d67ca89SAndroid Build Coastguard Worker while (n != 0) {
781*8d67ca89SAndroid Build Coastguard Worker // If the buffer is empty, refill it.
782*8d67ca89SAndroid Build Coastguard Worker if (fp->_r <= 0) {
783*8d67ca89SAndroid Build Coastguard Worker if (__srefill(fp)) {
784*8d67ca89SAndroid Build Coastguard Worker // EOF/error: stop with partial or no line.
785*8d67ca89SAndroid Build Coastguard Worker if (s == buf) return nullptr;
786*8d67ca89SAndroid Build Coastguard Worker break;
787*8d67ca89SAndroid Build Coastguard Worker }
788*8d67ca89SAndroid Build Coastguard Worker }
789*8d67ca89SAndroid Build Coastguard Worker size_t len = fp->_r;
790*8d67ca89SAndroid Build Coastguard Worker unsigned char* p = fp->_p;
791*8d67ca89SAndroid Build Coastguard Worker
792*8d67ca89SAndroid Build Coastguard Worker // Scan through at most n bytes of the current buffer,
793*8d67ca89SAndroid Build Coastguard Worker // looking for '\n'. If found, copy up to and including
794*8d67ca89SAndroid Build Coastguard Worker // newline, and stop. Otherwise, copy entire chunk and loop.
795*8d67ca89SAndroid Build Coastguard Worker if (len > static_cast<size_t>(n)) len = n;
796*8d67ca89SAndroid Build Coastguard Worker unsigned char* t = static_cast<unsigned char*>(memchr(p, '\n', len));
797*8d67ca89SAndroid Build Coastguard Worker if (t != nullptr) {
798*8d67ca89SAndroid Build Coastguard Worker len = ++t - p;
799*8d67ca89SAndroid Build Coastguard Worker fp->_r -= len;
800*8d67ca89SAndroid Build Coastguard Worker fp->_p = t;
801*8d67ca89SAndroid Build Coastguard Worker memcpy(s, p, len);
802*8d67ca89SAndroid Build Coastguard Worker s[len] = '\0';
803*8d67ca89SAndroid Build Coastguard Worker return buf;
804*8d67ca89SAndroid Build Coastguard Worker }
805*8d67ca89SAndroid Build Coastguard Worker fp->_r -= len;
806*8d67ca89SAndroid Build Coastguard Worker fp->_p += len;
807*8d67ca89SAndroid Build Coastguard Worker memcpy(s, p, len);
808*8d67ca89SAndroid Build Coastguard Worker s += len;
809*8d67ca89SAndroid Build Coastguard Worker n -= len;
810*8d67ca89SAndroid Build Coastguard Worker }
811*8d67ca89SAndroid Build Coastguard Worker *s = '\0';
812*8d67ca89SAndroid Build Coastguard Worker return buf;
813*8d67ca89SAndroid Build Coastguard Worker }
814*8d67ca89SAndroid Build Coastguard Worker
fputc(int c,FILE * fp)815*8d67ca89SAndroid Build Coastguard Worker int fputc(int c, FILE* fp) {
816*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
817*8d67ca89SAndroid Build Coastguard Worker return putc(c, fp);
818*8d67ca89SAndroid Build Coastguard Worker }
819*8d67ca89SAndroid Build Coastguard Worker
fputc_unlocked(int c,FILE * fp)820*8d67ca89SAndroid Build Coastguard Worker int fputc_unlocked(int c, FILE* fp) {
821*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
822*8d67ca89SAndroid Build Coastguard Worker return putc_unlocked(c, fp);
823*8d67ca89SAndroid Build Coastguard Worker }
824*8d67ca89SAndroid Build Coastguard Worker
fputs(const char * s,FILE * fp)825*8d67ca89SAndroid Build Coastguard Worker int fputs(const char* s, FILE* fp) {
826*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
827*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
828*8d67ca89SAndroid Build Coastguard Worker return fputs_unlocked(s, fp);
829*8d67ca89SAndroid Build Coastguard Worker }
830*8d67ca89SAndroid Build Coastguard Worker
fputs_unlocked(const char * s,FILE * fp)831*8d67ca89SAndroid Build Coastguard Worker int fputs_unlocked(const char* s, FILE* fp) {
832*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
833*8d67ca89SAndroid Build Coastguard Worker size_t length = strlen(s);
834*8d67ca89SAndroid Build Coastguard Worker return (fwrite_unlocked(s, 1, length, fp) == length) ? 0 : EOF;
835*8d67ca89SAndroid Build Coastguard Worker }
836*8d67ca89SAndroid Build Coastguard Worker
fscanf(FILE * fp,const char * fmt,...)837*8d67ca89SAndroid Build Coastguard Worker int fscanf(FILE* fp, const char* fmt, ...) {
838*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
839*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vfscanf(fp, fmt, ap));
840*8d67ca89SAndroid Build Coastguard Worker }
841*8d67ca89SAndroid Build Coastguard Worker
fwprintf(FILE * fp,const wchar_t * fmt,...)842*8d67ca89SAndroid Build Coastguard Worker int fwprintf(FILE* fp, const wchar_t* fmt, ...) {
843*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
844*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vfwprintf(fp, fmt, ap));
845*8d67ca89SAndroid Build Coastguard Worker }
846*8d67ca89SAndroid Build Coastguard Worker
fwscanf(FILE * fp,const wchar_t * fmt,...)847*8d67ca89SAndroid Build Coastguard Worker int fwscanf(FILE* fp, const wchar_t* fmt, ...) {
848*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
849*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vfwscanf(fp, fmt, ap));
850*8d67ca89SAndroid Build Coastguard Worker }
851*8d67ca89SAndroid Build Coastguard Worker
getc(FILE * fp)852*8d67ca89SAndroid Build Coastguard Worker int getc(FILE* fp) {
853*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
854*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
855*8d67ca89SAndroid Build Coastguard Worker return getc_unlocked(fp);
856*8d67ca89SAndroid Build Coastguard Worker }
857*8d67ca89SAndroid Build Coastguard Worker
getc_unlocked(FILE * fp)858*8d67ca89SAndroid Build Coastguard Worker int getc_unlocked(FILE* fp) {
859*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
860*8d67ca89SAndroid Build Coastguard Worker return __sgetc(fp);
861*8d67ca89SAndroid Build Coastguard Worker }
862*8d67ca89SAndroid Build Coastguard Worker
getchar_unlocked()863*8d67ca89SAndroid Build Coastguard Worker int getchar_unlocked() {
864*8d67ca89SAndroid Build Coastguard Worker return getc_unlocked(stdin);
865*8d67ca89SAndroid Build Coastguard Worker }
866*8d67ca89SAndroid Build Coastguard Worker
getchar()867*8d67ca89SAndroid Build Coastguard Worker int getchar() {
868*8d67ca89SAndroid Build Coastguard Worker return getc(stdin);
869*8d67ca89SAndroid Build Coastguard Worker }
870*8d67ca89SAndroid Build Coastguard Worker
getline(char ** buf,size_t * len,FILE * fp)871*8d67ca89SAndroid Build Coastguard Worker ssize_t getline(char** buf, size_t* len, FILE* fp) {
872*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
873*8d67ca89SAndroid Build Coastguard Worker return getdelim(buf, len, '\n', fp);
874*8d67ca89SAndroid Build Coastguard Worker }
875*8d67ca89SAndroid Build Coastguard Worker
getwc(FILE * fp)876*8d67ca89SAndroid Build Coastguard Worker wint_t getwc(FILE* fp) {
877*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
878*8d67ca89SAndroid Build Coastguard Worker return fgetwc(fp);
879*8d67ca89SAndroid Build Coastguard Worker }
880*8d67ca89SAndroid Build Coastguard Worker
getwchar()881*8d67ca89SAndroid Build Coastguard Worker wint_t getwchar() {
882*8d67ca89SAndroid Build Coastguard Worker return fgetwc(stdin);
883*8d67ca89SAndroid Build Coastguard Worker }
884*8d67ca89SAndroid Build Coastguard Worker
perror(const char * msg)885*8d67ca89SAndroid Build Coastguard Worker void perror(const char* msg) {
886*8d67ca89SAndroid Build Coastguard Worker if (msg == nullptr) msg = "";
887*8d67ca89SAndroid Build Coastguard Worker fprintf(stderr, "%s%s%m\n", msg, (*msg == '\0') ? "" : ": ");
888*8d67ca89SAndroid Build Coastguard Worker }
889*8d67ca89SAndroid Build Coastguard Worker
printf(const char * fmt,...)890*8d67ca89SAndroid Build Coastguard Worker int printf(const char* fmt, ...) {
891*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vfprintf(stdout, fmt, ap));
892*8d67ca89SAndroid Build Coastguard Worker }
893*8d67ca89SAndroid Build Coastguard Worker
putc(int c,FILE * fp)894*8d67ca89SAndroid Build Coastguard Worker int putc(int c, FILE* fp) {
895*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
896*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
897*8d67ca89SAndroid Build Coastguard Worker return putc_unlocked(c, fp);
898*8d67ca89SAndroid Build Coastguard Worker }
899*8d67ca89SAndroid Build Coastguard Worker
putc_unlocked(int c,FILE * fp)900*8d67ca89SAndroid Build Coastguard Worker int putc_unlocked(int c, FILE* fp) {
901*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
902*8d67ca89SAndroid Build Coastguard Worker if (cantwrite(fp)) {
903*8d67ca89SAndroid Build Coastguard Worker errno = EBADF;
904*8d67ca89SAndroid Build Coastguard Worker return EOF;
905*8d67ca89SAndroid Build Coastguard Worker }
906*8d67ca89SAndroid Build Coastguard Worker _SET_ORIENTATION(fp, ORIENT_BYTES);
907*8d67ca89SAndroid Build Coastguard Worker if (--fp->_w >= 0 || (fp->_w >= fp->_lbfsize && c != '\n')) {
908*8d67ca89SAndroid Build Coastguard Worker return (*fp->_p++ = c);
909*8d67ca89SAndroid Build Coastguard Worker }
910*8d67ca89SAndroid Build Coastguard Worker return (__swbuf(c, fp));
911*8d67ca89SAndroid Build Coastguard Worker }
912*8d67ca89SAndroid Build Coastguard Worker
putchar(int c)913*8d67ca89SAndroid Build Coastguard Worker int putchar(int c) {
914*8d67ca89SAndroid Build Coastguard Worker return putc(c, stdout);
915*8d67ca89SAndroid Build Coastguard Worker }
916*8d67ca89SAndroid Build Coastguard Worker
putchar_unlocked(int c)917*8d67ca89SAndroid Build Coastguard Worker int putchar_unlocked(int c) {
918*8d67ca89SAndroid Build Coastguard Worker return putc_unlocked(c, stdout);
919*8d67ca89SAndroid Build Coastguard Worker }
920*8d67ca89SAndroid Build Coastguard Worker
puts(const char * s)921*8d67ca89SAndroid Build Coastguard Worker int puts(const char* s) {
922*8d67ca89SAndroid Build Coastguard Worker size_t length = strlen(s);
923*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(stdout);
924*8d67ca89SAndroid Build Coastguard Worker return (fwrite_unlocked(s, 1, length, stdout) == length &&
925*8d67ca89SAndroid Build Coastguard Worker putc_unlocked('\n', stdout) != EOF) ? 0 : EOF;
926*8d67ca89SAndroid Build Coastguard Worker }
927*8d67ca89SAndroid Build Coastguard Worker
putwc(wchar_t wc,FILE * fp)928*8d67ca89SAndroid Build Coastguard Worker wint_t putwc(wchar_t wc, FILE* fp) {
929*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
930*8d67ca89SAndroid Build Coastguard Worker return fputwc(wc, fp);
931*8d67ca89SAndroid Build Coastguard Worker }
932*8d67ca89SAndroid Build Coastguard Worker
putwchar(wchar_t wc)933*8d67ca89SAndroid Build Coastguard Worker wint_t putwchar(wchar_t wc) {
934*8d67ca89SAndroid Build Coastguard Worker return fputwc(wc, stdout);
935*8d67ca89SAndroid Build Coastguard Worker }
936*8d67ca89SAndroid Build Coastguard Worker
remove(const char * path)937*8d67ca89SAndroid Build Coastguard Worker int remove(const char* path) {
938*8d67ca89SAndroid Build Coastguard Worker if (unlink(path) != -1) return 0;
939*8d67ca89SAndroid Build Coastguard Worker if (errno != EISDIR) return -1;
940*8d67ca89SAndroid Build Coastguard Worker return rmdir(path);
941*8d67ca89SAndroid Build Coastguard Worker }
942*8d67ca89SAndroid Build Coastguard Worker
rewind(FILE * fp)943*8d67ca89SAndroid Build Coastguard Worker void rewind(FILE* fp) {
944*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
945*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
946*8d67ca89SAndroid Build Coastguard Worker fseek(fp, 0, SEEK_SET);
947*8d67ca89SAndroid Build Coastguard Worker clearerr_unlocked(fp);
948*8d67ca89SAndroid Build Coastguard Worker }
949*8d67ca89SAndroid Build Coastguard Worker
scanf(const char * fmt,...)950*8d67ca89SAndroid Build Coastguard Worker int scanf(const char* fmt, ...) {
951*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vfscanf(stdin, fmt, ap));
952*8d67ca89SAndroid Build Coastguard Worker }
953*8d67ca89SAndroid Build Coastguard Worker
setbuf(FILE * fp,char * buf)954*8d67ca89SAndroid Build Coastguard Worker void setbuf(FILE* fp, char* buf) {
955*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
956*8d67ca89SAndroid Build Coastguard Worker setbuffer(fp, buf, BUFSIZ);
957*8d67ca89SAndroid Build Coastguard Worker }
958*8d67ca89SAndroid Build Coastguard Worker
setbuffer(FILE * fp,char * buf,int size)959*8d67ca89SAndroid Build Coastguard Worker void setbuffer(FILE* fp, char* buf, int size) {
960*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
961*8d67ca89SAndroid Build Coastguard Worker setvbuf(fp, buf, buf ? _IOFBF : _IONBF, size);
962*8d67ca89SAndroid Build Coastguard Worker }
963*8d67ca89SAndroid Build Coastguard Worker
setlinebuf(FILE * fp)964*8d67ca89SAndroid Build Coastguard Worker int setlinebuf(FILE* fp) {
965*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
966*8d67ca89SAndroid Build Coastguard Worker return setvbuf(fp, nullptr, _IOLBF, 0);
967*8d67ca89SAndroid Build Coastguard Worker }
968*8d67ca89SAndroid Build Coastguard Worker
snprintf(char * s,size_t n,const char * fmt,...)969*8d67ca89SAndroid Build Coastguard Worker int snprintf(char* s, size_t n, const char* fmt, ...) {
970*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vsnprintf(s, n, fmt, ap));
971*8d67ca89SAndroid Build Coastguard Worker }
972*8d67ca89SAndroid Build Coastguard Worker
sprintf(char * s,const char * fmt,...)973*8d67ca89SAndroid Build Coastguard Worker int sprintf(char* s, const char* fmt, ...) {
974*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vsprintf(s, fmt, ap));
975*8d67ca89SAndroid Build Coastguard Worker }
976*8d67ca89SAndroid Build Coastguard Worker
sscanf(const char * s,const char * fmt,...)977*8d67ca89SAndroid Build Coastguard Worker int sscanf(const char* s, const char* fmt, ...) {
978*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vsscanf(s, fmt, ap));
979*8d67ca89SAndroid Build Coastguard Worker }
980*8d67ca89SAndroid Build Coastguard Worker
swprintf(wchar_t * s,size_t n,const wchar_t * fmt,...)981*8d67ca89SAndroid Build Coastguard Worker int swprintf(wchar_t* s, size_t n, const wchar_t* fmt, ...) {
982*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vswprintf(s, n, fmt, ap));
983*8d67ca89SAndroid Build Coastguard Worker }
984*8d67ca89SAndroid Build Coastguard Worker
swscanf(const wchar_t * s,const wchar_t * fmt,...)985*8d67ca89SAndroid Build Coastguard Worker int swscanf(const wchar_t* s, const wchar_t* fmt, ...) {
986*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vswscanf(s, fmt, ap));
987*8d67ca89SAndroid Build Coastguard Worker }
988*8d67ca89SAndroid Build Coastguard Worker
vfprintf(FILE * fp,const char * fmt,va_list ap)989*8d67ca89SAndroid Build Coastguard Worker int vfprintf(FILE* fp, const char* fmt, va_list ap) {
990*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
991*8d67ca89SAndroid Build Coastguard Worker return __vfprintf(fp, fmt, ap);
992*8d67ca89SAndroid Build Coastguard Worker }
993*8d67ca89SAndroid Build Coastguard Worker
vfscanf(FILE * fp,const char * fmt,va_list ap)994*8d67ca89SAndroid Build Coastguard Worker int vfscanf(FILE* fp, const char* fmt, va_list ap) {
995*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
996*8d67ca89SAndroid Build Coastguard Worker return __svfscanf(fp, fmt, ap);
997*8d67ca89SAndroid Build Coastguard Worker }
998*8d67ca89SAndroid Build Coastguard Worker
vfwprintf(FILE * fp,const wchar_t * fmt,va_list ap)999*8d67ca89SAndroid Build Coastguard Worker int vfwprintf(FILE* fp, const wchar_t* fmt, va_list ap) {
1000*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
1001*8d67ca89SAndroid Build Coastguard Worker return __vfwprintf(fp, fmt, ap);
1002*8d67ca89SAndroid Build Coastguard Worker }
1003*8d67ca89SAndroid Build Coastguard Worker
vfwscanf(FILE * fp,const wchar_t * fmt,va_list ap)1004*8d67ca89SAndroid Build Coastguard Worker int vfwscanf(FILE* fp, const wchar_t* fmt, va_list ap) {
1005*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
1006*8d67ca89SAndroid Build Coastguard Worker return __vfwscanf(fp, fmt, ap);
1007*8d67ca89SAndroid Build Coastguard Worker }
1008*8d67ca89SAndroid Build Coastguard Worker
vprintf(const char * fmt,va_list ap)1009*8d67ca89SAndroid Build Coastguard Worker int vprintf(const char* fmt, va_list ap) {
1010*8d67ca89SAndroid Build Coastguard Worker return vfprintf(stdout, fmt, ap);
1011*8d67ca89SAndroid Build Coastguard Worker }
1012*8d67ca89SAndroid Build Coastguard Worker
vscanf(const char * fmt,va_list ap)1013*8d67ca89SAndroid Build Coastguard Worker int vscanf(const char* fmt, va_list ap) {
1014*8d67ca89SAndroid Build Coastguard Worker return vfscanf(stdin, fmt, ap);
1015*8d67ca89SAndroid Build Coastguard Worker }
1016*8d67ca89SAndroid Build Coastguard Worker
vsnprintf(char * s,size_t n,const char * fmt,va_list ap)1017*8d67ca89SAndroid Build Coastguard Worker int vsnprintf(char* s, size_t n, const char* fmt, va_list ap) {
1018*8d67ca89SAndroid Build Coastguard Worker // stdio internals use int rather than size_t.
1019*8d67ca89SAndroid Build Coastguard Worker static_assert(INT_MAX <= SSIZE_MAX, "SSIZE_MAX too large to fit in int");
1020*8d67ca89SAndroid Build Coastguard Worker
1021*8d67ca89SAndroid Build Coastguard Worker __check_count("vsnprintf", "size", n);
1022*8d67ca89SAndroid Build Coastguard Worker
1023*8d67ca89SAndroid Build Coastguard Worker // Stdio internals do not deal correctly with zero length buffer.
1024*8d67ca89SAndroid Build Coastguard Worker char one_byte_buffer[1];
1025*8d67ca89SAndroid Build Coastguard Worker if (n == 0) {
1026*8d67ca89SAndroid Build Coastguard Worker s = one_byte_buffer;
1027*8d67ca89SAndroid Build Coastguard Worker n = 1;
1028*8d67ca89SAndroid Build Coastguard Worker }
1029*8d67ca89SAndroid Build Coastguard Worker
1030*8d67ca89SAndroid Build Coastguard Worker FILE f;
1031*8d67ca89SAndroid Build Coastguard Worker __sfileext fext;
1032*8d67ca89SAndroid Build Coastguard Worker _FILEEXT_SETUP(&f, &fext);
1033*8d67ca89SAndroid Build Coastguard Worker f._file = -1;
1034*8d67ca89SAndroid Build Coastguard Worker f._flags = __SWR | __SSTR;
1035*8d67ca89SAndroid Build Coastguard Worker f._bf._base = f._p = reinterpret_cast<unsigned char*>(s);
1036*8d67ca89SAndroid Build Coastguard Worker f._bf._size = f._w = n - 1;
1037*8d67ca89SAndroid Build Coastguard Worker
1038*8d67ca89SAndroid Build Coastguard Worker int result = __vfprintf(&f, fmt, ap);
1039*8d67ca89SAndroid Build Coastguard Worker *f._p = '\0';
1040*8d67ca89SAndroid Build Coastguard Worker return result;
1041*8d67ca89SAndroid Build Coastguard Worker }
1042*8d67ca89SAndroid Build Coastguard Worker
vsprintf(char * s,const char * fmt,va_list ap)1043*8d67ca89SAndroid Build Coastguard Worker int vsprintf(char* s, const char* fmt, va_list ap) {
1044*8d67ca89SAndroid Build Coastguard Worker return vsnprintf(s, SSIZE_MAX, fmt, ap);
1045*8d67ca89SAndroid Build Coastguard Worker }
1046*8d67ca89SAndroid Build Coastguard Worker
vwprintf(const wchar_t * fmt,va_list ap)1047*8d67ca89SAndroid Build Coastguard Worker int vwprintf(const wchar_t* fmt, va_list ap) {
1048*8d67ca89SAndroid Build Coastguard Worker return vfwprintf(stdout, fmt, ap);
1049*8d67ca89SAndroid Build Coastguard Worker }
1050*8d67ca89SAndroid Build Coastguard Worker
vwscanf(const wchar_t * fmt,va_list ap)1051*8d67ca89SAndroid Build Coastguard Worker int vwscanf(const wchar_t* fmt, va_list ap) {
1052*8d67ca89SAndroid Build Coastguard Worker return vfwscanf(stdin, fmt, ap);
1053*8d67ca89SAndroid Build Coastguard Worker }
1054*8d67ca89SAndroid Build Coastguard Worker
wprintf(const wchar_t * fmt,...)1055*8d67ca89SAndroid Build Coastguard Worker int wprintf(const wchar_t* fmt, ...) {
1056*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vfwprintf(stdout, fmt, ap));
1057*8d67ca89SAndroid Build Coastguard Worker }
1058*8d67ca89SAndroid Build Coastguard Worker
wscanf(const wchar_t * fmt,...)1059*8d67ca89SAndroid Build Coastguard Worker int wscanf(const wchar_t* fmt, ...) {
1060*8d67ca89SAndroid Build Coastguard Worker PRINTF_IMPL(vfwscanf(stdin, fmt, ap));
1061*8d67ca89SAndroid Build Coastguard Worker }
1062*8d67ca89SAndroid Build Coastguard Worker
fflush_all()1063*8d67ca89SAndroid Build Coastguard Worker static int fflush_all() {
1064*8d67ca89SAndroid Build Coastguard Worker return _fwalk(__sflush_locked);
1065*8d67ca89SAndroid Build Coastguard Worker }
1066*8d67ca89SAndroid Build Coastguard Worker
fflush(FILE * fp)1067*8d67ca89SAndroid Build Coastguard Worker int fflush(FILE* fp) {
1068*8d67ca89SAndroid Build Coastguard Worker if (fp == nullptr) return fflush_all();
1069*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
1070*8d67ca89SAndroid Build Coastguard Worker return fflush_unlocked(fp);
1071*8d67ca89SAndroid Build Coastguard Worker }
1072*8d67ca89SAndroid Build Coastguard Worker
fflush_unlocked(FILE * fp)1073*8d67ca89SAndroid Build Coastguard Worker int fflush_unlocked(FILE* fp) {
1074*8d67ca89SAndroid Build Coastguard Worker if (fp == nullptr) return fflush_all();
1075*8d67ca89SAndroid Build Coastguard Worker if ((fp->_flags & (__SWR | __SRW)) == 0) {
1076*8d67ca89SAndroid Build Coastguard Worker errno = EBADF;
1077*8d67ca89SAndroid Build Coastguard Worker return EOF;
1078*8d67ca89SAndroid Build Coastguard Worker }
1079*8d67ca89SAndroid Build Coastguard Worker return __sflush(fp);
1080*8d67ca89SAndroid Build Coastguard Worker }
1081*8d67ca89SAndroid Build Coastguard Worker
fpurge(FILE * fp)1082*8d67ca89SAndroid Build Coastguard Worker int fpurge(FILE* fp) {
1083*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
1084*8d67ca89SAndroid Build Coastguard Worker
1085*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
1086*8d67ca89SAndroid Build Coastguard Worker
1087*8d67ca89SAndroid Build Coastguard Worker if (fp->_flags == 0) {
1088*8d67ca89SAndroid Build Coastguard Worker // Already freed!
1089*8d67ca89SAndroid Build Coastguard Worker errno = EBADF;
1090*8d67ca89SAndroid Build Coastguard Worker return EOF;
1091*8d67ca89SAndroid Build Coastguard Worker }
1092*8d67ca89SAndroid Build Coastguard Worker
1093*8d67ca89SAndroid Build Coastguard Worker if (HASUB(fp)) FREEUB(fp);
1094*8d67ca89SAndroid Build Coastguard Worker WCIO_FREE(fp);
1095*8d67ca89SAndroid Build Coastguard Worker fp->_p = fp->_bf._base;
1096*8d67ca89SAndroid Build Coastguard Worker fp->_r = 0;
1097*8d67ca89SAndroid Build Coastguard Worker fp->_w = fp->_flags & (__SLBF | __SNBF) ? 0 : fp->_bf._size;
1098*8d67ca89SAndroid Build Coastguard Worker return 0;
1099*8d67ca89SAndroid Build Coastguard Worker }
1100*8d67ca89SAndroid Build Coastguard Worker __strong_alias(__fpurge, fpurge);
1101*8d67ca89SAndroid Build Coastguard Worker
fread(void * buf,size_t size,size_t count,FILE * fp)1102*8d67ca89SAndroid Build Coastguard Worker size_t fread(void* buf, size_t size, size_t count, FILE* fp) {
1103*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
1104*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
1105*8d67ca89SAndroid Build Coastguard Worker return fread_unlocked(buf, size, count, fp);
1106*8d67ca89SAndroid Build Coastguard Worker }
1107*8d67ca89SAndroid Build Coastguard Worker
fread_unlocked(void * buf,size_t size,size_t count,FILE * fp)1108*8d67ca89SAndroid Build Coastguard Worker size_t fread_unlocked(void* buf, size_t size, size_t count, FILE* fp) {
1109*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
1110*8d67ca89SAndroid Build Coastguard Worker
1111*8d67ca89SAndroid Build Coastguard Worker size_t desired_total;
1112*8d67ca89SAndroid Build Coastguard Worker if (__builtin_mul_overflow(size, count, &desired_total)) {
1113*8d67ca89SAndroid Build Coastguard Worker errno = EOVERFLOW;
1114*8d67ca89SAndroid Build Coastguard Worker fp->_flags |= __SERR;
1115*8d67ca89SAndroid Build Coastguard Worker return 0;
1116*8d67ca89SAndroid Build Coastguard Worker }
1117*8d67ca89SAndroid Build Coastguard Worker
1118*8d67ca89SAndroid Build Coastguard Worker size_t total = desired_total;
1119*8d67ca89SAndroid Build Coastguard Worker if (total == 0) return 0;
1120*8d67ca89SAndroid Build Coastguard Worker
1121*8d67ca89SAndroid Build Coastguard Worker _SET_ORIENTATION(fp, ORIENT_BYTES);
1122*8d67ca89SAndroid Build Coastguard Worker
1123*8d67ca89SAndroid Build Coastguard Worker // TODO: how can this ever happen?!
1124*8d67ca89SAndroid Build Coastguard Worker if (fp->_r < 0) fp->_r = 0;
1125*8d67ca89SAndroid Build Coastguard Worker
1126*8d67ca89SAndroid Build Coastguard Worker // Ensure _bf._size is valid.
1127*8d67ca89SAndroid Build Coastguard Worker if (fp->_bf._base == nullptr) __smakebuf(fp);
1128*8d67ca89SAndroid Build Coastguard Worker
1129*8d67ca89SAndroid Build Coastguard Worker char* dst = static_cast<char*>(buf);
1130*8d67ca89SAndroid Build Coastguard Worker
1131*8d67ca89SAndroid Build Coastguard Worker while (total > 0) {
1132*8d67ca89SAndroid Build Coastguard Worker // Copy data out of the buffer.
1133*8d67ca89SAndroid Build Coastguard Worker size_t buffered_bytes = MIN(static_cast<size_t>(fp->_r), total);
1134*8d67ca89SAndroid Build Coastguard Worker memcpy(dst, fp->_p, buffered_bytes);
1135*8d67ca89SAndroid Build Coastguard Worker fp->_p += buffered_bytes;
1136*8d67ca89SAndroid Build Coastguard Worker fp->_r -= buffered_bytes;
1137*8d67ca89SAndroid Build Coastguard Worker dst += buffered_bytes;
1138*8d67ca89SAndroid Build Coastguard Worker total -= buffered_bytes;
1139*8d67ca89SAndroid Build Coastguard Worker
1140*8d67ca89SAndroid Build Coastguard Worker // Are we done?
1141*8d67ca89SAndroid Build Coastguard Worker if (total == 0) goto out;
1142*8d67ca89SAndroid Build Coastguard Worker
1143*8d67ca89SAndroid Build Coastguard Worker // Do we have so much more to read that we should avoid copying it through the buffer?
1144*8d67ca89SAndroid Build Coastguard Worker if (total > static_cast<size_t>(fp->_bf._size)) break;
1145*8d67ca89SAndroid Build Coastguard Worker
1146*8d67ca89SAndroid Build Coastguard Worker // Less than a buffer to go, so refill the buffer and go around the loop again.
1147*8d67ca89SAndroid Build Coastguard Worker if (__srefill(fp)) goto out;
1148*8d67ca89SAndroid Build Coastguard Worker }
1149*8d67ca89SAndroid Build Coastguard Worker
1150*8d67ca89SAndroid Build Coastguard Worker // Read directly into the caller's buffer.
1151*8d67ca89SAndroid Build Coastguard Worker while (total > 0) {
1152*8d67ca89SAndroid Build Coastguard Worker // The _read function pointer takes an int instead of a size_t.
1153*8d67ca89SAndroid Build Coastguard Worker int chunk_size = MIN(total, INT_MAX);
1154*8d67ca89SAndroid Build Coastguard Worker ssize_t bytes_read = (*fp->_read)(fp->_cookie, dst, chunk_size);
1155*8d67ca89SAndroid Build Coastguard Worker if (bytes_read <= 0) {
1156*8d67ca89SAndroid Build Coastguard Worker fp->_flags |= (bytes_read == 0) ? __SEOF : __SERR;
1157*8d67ca89SAndroid Build Coastguard Worker break;
1158*8d67ca89SAndroid Build Coastguard Worker }
1159*8d67ca89SAndroid Build Coastguard Worker dst += bytes_read;
1160*8d67ca89SAndroid Build Coastguard Worker total -= bytes_read;
1161*8d67ca89SAndroid Build Coastguard Worker }
1162*8d67ca89SAndroid Build Coastguard Worker
1163*8d67ca89SAndroid Build Coastguard Worker out:
1164*8d67ca89SAndroid Build Coastguard Worker return ((desired_total - total) / size);
1165*8d67ca89SAndroid Build Coastguard Worker }
1166*8d67ca89SAndroid Build Coastguard Worker
fwrite(const void * buf,size_t size,size_t count,FILE * fp)1167*8d67ca89SAndroid Build Coastguard Worker size_t fwrite(const void* buf, size_t size, size_t count, FILE* fp) {
1168*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
1169*8d67ca89SAndroid Build Coastguard Worker ScopedFileLock sfl(fp);
1170*8d67ca89SAndroid Build Coastguard Worker return fwrite_unlocked(buf, size, count, fp);
1171*8d67ca89SAndroid Build Coastguard Worker }
1172*8d67ca89SAndroid Build Coastguard Worker
fwrite_unlocked(const void * buf,size_t size,size_t count,FILE * fp)1173*8d67ca89SAndroid Build Coastguard Worker size_t fwrite_unlocked(const void* buf, size_t size, size_t count, FILE* fp) {
1174*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
1175*8d67ca89SAndroid Build Coastguard Worker
1176*8d67ca89SAndroid Build Coastguard Worker size_t n;
1177*8d67ca89SAndroid Build Coastguard Worker if (__builtin_mul_overflow(size, count, &n)) {
1178*8d67ca89SAndroid Build Coastguard Worker errno = EOVERFLOW;
1179*8d67ca89SAndroid Build Coastguard Worker fp->_flags |= __SERR;
1180*8d67ca89SAndroid Build Coastguard Worker return 0;
1181*8d67ca89SAndroid Build Coastguard Worker }
1182*8d67ca89SAndroid Build Coastguard Worker
1183*8d67ca89SAndroid Build Coastguard Worker if (n == 0) return 0;
1184*8d67ca89SAndroid Build Coastguard Worker
1185*8d67ca89SAndroid Build Coastguard Worker __siov iov = { .iov_base = const_cast<void*>(buf), .iov_len = n };
1186*8d67ca89SAndroid Build Coastguard Worker __suio uio = { .uio_iov = &iov, .uio_iovcnt = 1, .uio_resid = n };
1187*8d67ca89SAndroid Build Coastguard Worker
1188*8d67ca89SAndroid Build Coastguard Worker _SET_ORIENTATION(fp, ORIENT_BYTES);
1189*8d67ca89SAndroid Build Coastguard Worker
1190*8d67ca89SAndroid Build Coastguard Worker // The usual case is success (__sfvwrite returns 0); skip the divide if this happens,
1191*8d67ca89SAndroid Build Coastguard Worker // since divides are generally slow.
1192*8d67ca89SAndroid Build Coastguard Worker return (__sfvwrite(fp, &uio) == 0) ? count : ((n - uio.uio_resid) / size);
1193*8d67ca89SAndroid Build Coastguard Worker }
1194*8d67ca89SAndroid Build Coastguard Worker
__popen_fail(int fds[2])1195*8d67ca89SAndroid Build Coastguard Worker static FILE* __popen_fail(int fds[2]) {
1196*8d67ca89SAndroid Build Coastguard Worker ErrnoRestorer errno_restorer;
1197*8d67ca89SAndroid Build Coastguard Worker close(fds[0]);
1198*8d67ca89SAndroid Build Coastguard Worker close(fds[1]);
1199*8d67ca89SAndroid Build Coastguard Worker return nullptr;
1200*8d67ca89SAndroid Build Coastguard Worker }
1201*8d67ca89SAndroid Build Coastguard Worker
popen(const char * cmd,const char * mode)1202*8d67ca89SAndroid Build Coastguard Worker FILE* popen(const char* cmd, const char* mode) {
1203*8d67ca89SAndroid Build Coastguard Worker // Was the request for a socketpair or just a pipe?
1204*8d67ca89SAndroid Build Coastguard Worker int fds[2];
1205*8d67ca89SAndroid Build Coastguard Worker bool bidirectional = false;
1206*8d67ca89SAndroid Build Coastguard Worker if (strchr(mode, '+') != nullptr) {
1207*8d67ca89SAndroid Build Coastguard Worker if (socketpair(AF_LOCAL, SOCK_CLOEXEC | SOCK_STREAM, 0, fds) == -1) return nullptr;
1208*8d67ca89SAndroid Build Coastguard Worker bidirectional = true;
1209*8d67ca89SAndroid Build Coastguard Worker mode = "r+";
1210*8d67ca89SAndroid Build Coastguard Worker } else {
1211*8d67ca89SAndroid Build Coastguard Worker if (pipe2(fds, O_CLOEXEC) == -1) return nullptr;
1212*8d67ca89SAndroid Build Coastguard Worker mode = strrchr(mode, 'r') ? "r" : "w";
1213*8d67ca89SAndroid Build Coastguard Worker }
1214*8d67ca89SAndroid Build Coastguard Worker
1215*8d67ca89SAndroid Build Coastguard Worker // If the parent wants to read, the child's fd needs to be stdout.
1216*8d67ca89SAndroid Build Coastguard Worker int parent, child, desired_child_fd;
1217*8d67ca89SAndroid Build Coastguard Worker if (*mode == 'r') {
1218*8d67ca89SAndroid Build Coastguard Worker parent = 0;
1219*8d67ca89SAndroid Build Coastguard Worker child = 1;
1220*8d67ca89SAndroid Build Coastguard Worker desired_child_fd = STDOUT_FILENO;
1221*8d67ca89SAndroid Build Coastguard Worker } else {
1222*8d67ca89SAndroid Build Coastguard Worker parent = 1;
1223*8d67ca89SAndroid Build Coastguard Worker child = 0;
1224*8d67ca89SAndroid Build Coastguard Worker desired_child_fd = STDIN_FILENO;
1225*8d67ca89SAndroid Build Coastguard Worker }
1226*8d67ca89SAndroid Build Coastguard Worker
1227*8d67ca89SAndroid Build Coastguard Worker // Ensure that the child fd isn't the desired child fd.
1228*8d67ca89SAndroid Build Coastguard Worker if (fds[child] == desired_child_fd) {
1229*8d67ca89SAndroid Build Coastguard Worker int new_fd = fcntl(fds[child], F_DUPFD_CLOEXEC, 0);
1230*8d67ca89SAndroid Build Coastguard Worker if (new_fd == -1) return __popen_fail(fds);
1231*8d67ca89SAndroid Build Coastguard Worker close(fds[child]);
1232*8d67ca89SAndroid Build Coastguard Worker fds[child] = new_fd;
1233*8d67ca89SAndroid Build Coastguard Worker }
1234*8d67ca89SAndroid Build Coastguard Worker
1235*8d67ca89SAndroid Build Coastguard Worker pid_t pid = vfork();
1236*8d67ca89SAndroid Build Coastguard Worker if (pid == -1) return __popen_fail(fds);
1237*8d67ca89SAndroid Build Coastguard Worker
1238*8d67ca89SAndroid Build Coastguard Worker if (pid == 0) {
1239*8d67ca89SAndroid Build Coastguard Worker close(fds[parent]);
1240*8d67ca89SAndroid Build Coastguard Worker // dup2 so that the child fd isn't closed on exec.
1241*8d67ca89SAndroid Build Coastguard Worker if (dup2(fds[child], desired_child_fd) == -1) _exit(127);
1242*8d67ca89SAndroid Build Coastguard Worker close(fds[child]);
1243*8d67ca89SAndroid Build Coastguard Worker if (bidirectional) dup2(STDOUT_FILENO, STDIN_FILENO);
1244*8d67ca89SAndroid Build Coastguard Worker execl(__bionic_get_shell_path(), "sh", "-c", "--", cmd, nullptr);
1245*8d67ca89SAndroid Build Coastguard Worker _exit(127);
1246*8d67ca89SAndroid Build Coastguard Worker }
1247*8d67ca89SAndroid Build Coastguard Worker
1248*8d67ca89SAndroid Build Coastguard Worker FILE* fp = fdopen(fds[parent], mode);
1249*8d67ca89SAndroid Build Coastguard Worker if (fp == nullptr) return __popen_fail(fds);
1250*8d67ca89SAndroid Build Coastguard Worker
1251*8d67ca89SAndroid Build Coastguard Worker close(fds[child]);
1252*8d67ca89SAndroid Build Coastguard Worker
1253*8d67ca89SAndroid Build Coastguard Worker _EXT(fp)->_popen_pid = pid;
1254*8d67ca89SAndroid Build Coastguard Worker return fp;
1255*8d67ca89SAndroid Build Coastguard Worker }
1256*8d67ca89SAndroid Build Coastguard Worker
pclose(FILE * fp)1257*8d67ca89SAndroid Build Coastguard Worker int pclose(FILE* fp) {
1258*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
1259*8d67ca89SAndroid Build Coastguard Worker return __FILE_close(fp);
1260*8d67ca89SAndroid Build Coastguard Worker }
1261*8d67ca89SAndroid Build Coastguard Worker
flockfile(FILE * fp)1262*8d67ca89SAndroid Build Coastguard Worker void flockfile(FILE* fp) {
1263*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
1264*8d67ca89SAndroid Build Coastguard Worker pthread_mutex_lock(&_EXT(fp)->_lock);
1265*8d67ca89SAndroid Build Coastguard Worker }
1266*8d67ca89SAndroid Build Coastguard Worker
ftrylockfile(FILE * fp)1267*8d67ca89SAndroid Build Coastguard Worker int ftrylockfile(FILE* fp) {
1268*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
1269*8d67ca89SAndroid Build Coastguard Worker // The specification for ftrylockfile() says it returns 0 on success,
1270*8d67ca89SAndroid Build Coastguard Worker // or non-zero on error. We don't bother canonicalizing to 0/-1...
1271*8d67ca89SAndroid Build Coastguard Worker return pthread_mutex_trylock(&_EXT(fp)->_lock);
1272*8d67ca89SAndroid Build Coastguard Worker }
1273*8d67ca89SAndroid Build Coastguard Worker
funlockfile(FILE * fp)1274*8d67ca89SAndroid Build Coastguard Worker void funlockfile(FILE* fp) {
1275*8d67ca89SAndroid Build Coastguard Worker CHECK_FP(fp);
1276*8d67ca89SAndroid Build Coastguard Worker pthread_mutex_unlock(&_EXT(fp)->_lock);
1277*8d67ca89SAndroid Build Coastguard Worker }
1278*8d67ca89SAndroid Build Coastguard Worker
1279*8d67ca89SAndroid Build Coastguard Worker namespace {
1280*8d67ca89SAndroid Build Coastguard Worker
1281*8d67ca89SAndroid Build Coastguard Worker namespace phony {
1282*8d67ca89SAndroid Build Coastguard Worker #include <bits/struct_file.h>
1283*8d67ca89SAndroid Build Coastguard Worker }
1284*8d67ca89SAndroid Build Coastguard Worker
1285*8d67ca89SAndroid Build Coastguard Worker static_assert(sizeof(::__sFILE) == sizeof(phony::__sFILE),
1286*8d67ca89SAndroid Build Coastguard Worker "size mismatch between `struct __sFILE` implementation and public stub");
1287*8d67ca89SAndroid Build Coastguard Worker static_assert(alignof(::__sFILE) == alignof(phony::__sFILE),
1288*8d67ca89SAndroid Build Coastguard Worker "alignment mismatch between `struct __sFILE` implementation and public stub");
1289*8d67ca89SAndroid Build Coastguard Worker
1290*8d67ca89SAndroid Build Coastguard Worker }
1291