1 /*	$OpenBSD: findfp.c,v 1.15 2013/12/17 16:33:27 deraadt Exp $ */
2 /*-
3  * Copyright (c) 1990, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Chris Torek.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #define __BIONIC_NO_STDIO_FORTIFY
35 #include <stdio.h>
36 
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <limits.h>
40 #include <paths.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/param.h>
44 #include <sys/stat.h>
45 #include <unistd.h>
46 
47 #include "local.h"
48 #include "glue.h"
49 #include "private/bionic_fortify.h"
50 #include "private/ErrnoRestorer.h"
51 #include "private/thread_private.h"
52 
53 #define ALIGNBYTES (sizeof(uintptr_t) - 1)
54 #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
55 
56 #define	NDYNAMIC 10		/* add ten more whenever necessary */
57 
58 #define PRINTF_IMPL(expr) \
59     va_list ap; \
60     va_start(ap, fmt); \
61     int result = (expr); \
62     va_end(ap); \
63     return result;
64 
65 #define std(flags, file) \
66     {0,0,0,flags,file,{0,0},0,__sF+file,__sclose,__sread,nullptr,__swrite, \
67     {(unsigned char *)(__sFext+file), 0},nullptr,0,{0},{0},{0,0},0,0}
68 
69 _THREAD_PRIVATE_MUTEX(__sfp_mutex);
70 
71 // TODO: when we no longer have to support both clang and GCC, we can simplify all this.
72 #define SBUF_INIT {0,0}
73 #if defined(__LP64__)
74 #define MBSTATE_T_INIT {{0},{0}}
75 #else
76 #define MBSTATE_T_INIT {{0}}
77 #endif
78 #define WCHAR_IO_DATA_INIT {MBSTATE_T_INIT,MBSTATE_T_INIT,{0},0,0}
79 
80 static struct __sfileext __sFext[3] = {
81   { SBUF_INIT, WCHAR_IO_DATA_INIT, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, false, __sseek64 },
82   { SBUF_INIT, WCHAR_IO_DATA_INIT, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, false, __sseek64 },
83   { SBUF_INIT, WCHAR_IO_DATA_INIT, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, false, __sseek64 },
84 };
85 
86 // __sF is exported for backwards compatibility. Until M, we didn't have symbols
87 // for stdin/stdout/stderr; they were macros accessing __sF.
88 FILE __sF[3] = {
89   std(__SRD, STDIN_FILENO),
90   std(__SWR, STDOUT_FILENO),
91   std(__SWR|__SNBF, STDERR_FILENO),
92 };
93 
94 FILE* stdin = &__sF[0];
95 FILE* stdout = &__sF[1];
96 FILE* stderr = &__sF[2];
97 
98 struct glue __sglue = { NULL, 3, __sF };
99 static struct glue* lastglue = &__sglue;
100 
101 class ScopedFileLock {
102  public:
ScopedFileLock(FILE * fp)103   explicit ScopedFileLock(FILE* fp) : fp_(fp) {
104     FLOCKFILE(fp_);
105   }
~ScopedFileLock()106   ~ScopedFileLock() {
107     FUNLOCKFILE(fp_);
108   }
109 
110  private:
111   FILE* fp_;
112 };
113 
moreglue(int n)114 static glue* moreglue(int n) {
115   static FILE empty;
116 
117   char* data = new char[sizeof(glue) + ALIGNBYTES + n * sizeof(FILE) + n * sizeof(__sfileext)];
118   if (data == nullptr) return nullptr;
119 
120   glue* g = reinterpret_cast<glue*>(data);
121   FILE* p = reinterpret_cast<FILE*>(ALIGN(data + sizeof(*g)));
122   __sfileext* pext = reinterpret_cast<__sfileext*>(ALIGN(data + sizeof(*g)) + n * sizeof(FILE));
123   g->next = NULL;
124   g->niobs = n;
125   g->iobs = p;
126   while (--n >= 0) {
127     *p = empty;
128     _FILEEXT_SETUP(p, pext);
129     p++;
130     pext++;
131   }
132   return g;
133 }
134 
135 /*
136  * Find a free FILE for fopen et al.
137  */
__sfp(void)138 FILE* __sfp(void) {
139 	FILE *fp;
140 	int n;
141 	struct glue *g;
142 
143 	_THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
144 	for (g = &__sglue; g != NULL; g = g->next) {
145 		for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
146 			if (fp->_flags == 0)
147 				goto found;
148 	}
149 
150 	/* release lock while mallocing */
151 	_THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex);
152 	if ((g = moreglue(NDYNAMIC)) == NULL)
153 		return (NULL);
154 	_THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
155 	lastglue->next = g;
156 	lastglue = g;
157 	fp = g->iobs;
158 found:
159 	fp->_flags = 1;		/* reserve this slot; caller sets real flags */
160 	_THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex);
161 	fp->_p = NULL;		/* no current pointer */
162 	fp->_w = 0;		/* nothing to read or write */
163 	fp->_r = 0;
164 	fp->_bf._base = NULL;	/* no buffer */
165 	fp->_bf._size = 0;
166 	fp->_lbfsize = 0;	/* not line buffered */
167 	fp->_file = -1;		/* no file */
168 
169 	fp->_lb._base = NULL;	/* no line buffer */
170 	fp->_lb._size = 0;
171 	_FILEEXT_INIT(fp);
172 
173 	// Caller sets cookie, _read/_write etc.
174 	// We explicitly clear _seek and _seek64 to prevent subtle bugs.
175 	fp->_seek = nullptr;
176 	_EXT(fp)->_seek64 = nullptr;
177 
178 	return fp;
179 }
180 
__libc_stdio_cleanup(void)181 extern "C" __LIBC_HIDDEN__ void __libc_stdio_cleanup(void) {
182   // Equivalent to fflush(nullptr), but without all the locking since we're shutting down anyway.
183   _fwalk(__sflush);
184 }
185 
__fopen(int fd,int flags)186 static FILE* __fopen(int fd, int flags) {
187 #if !defined(__LP64__)
188   if (fd > SHRT_MAX) {
189     errno = EMFILE;
190     return nullptr;
191   }
192 #endif
193 
194   FILE* fp = __sfp();
195   if (fp != nullptr) {
196     fp->_file = fd;
197     fp->_flags = flags;
198     fp->_cookie = fp;
199     fp->_read = __sread;
200     fp->_write = __swrite;
201     fp->_close = __sclose;
202     _EXT(fp)->_seek64 = __sseek64;
203   }
204   return fp;
205 }
206 
fopen(const char * file,const char * mode)207 FILE* fopen(const char* file, const char* mode) {
208   int oflags;
209   int flags = __sflags(mode, &oflags);
210   if (flags == 0) return nullptr;
211 
212   int fd = open(file, oflags, DEFFILEMODE);
213   if (fd == -1) {
214     return nullptr;
215   }
216 
217   FILE* fp = __fopen(fd, flags);
218   if (fp == nullptr) {
219     ErrnoRestorer errno_restorer;
220     close(fd);
221     return nullptr;
222   }
223 
224   // When opening in append mode, even though we use O_APPEND,
225   // we need to seek to the end so that ftell() gets the right
226   // answer.  If the user then alters the seek pointer, or
227   // the file extends, this will fail, but there is not much
228   // we can do about this.  (We could set __SAPP and check in
229   // fseek and ftell.)
230   // TODO: check in __sseek instead.
231   if (oflags & O_APPEND) __sseek64(fp, 0, SEEK_END);
232 
233   return fp;
234 }
235 __strong_alias(fopen64, fopen);
236 
fdopen(int fd,const char * mode)237 FILE* fdopen(int fd, const char* mode) {
238   int oflags;
239   int flags = __sflags(mode, &oflags);
240   if (flags == 0) return nullptr;
241 
242   // Make sure the mode the user wants is a subset of the actual mode.
243   int fdflags = fcntl(fd, F_GETFL, 0);
244   if (fdflags < 0) return nullptr;
245   int tmp = fdflags & O_ACCMODE;
246   if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) {
247     errno = EINVAL;
248     return nullptr;
249   }
250 
251   // If opened for appending, but underlying descriptor does not have
252   // O_APPEND bit set, assert __SAPP so that __swrite() will lseek to
253   // end before each write.
254   // TODO: use fcntl(2) to set O_APPEND instead.
255   if ((oflags & O_APPEND) && !(fdflags & O_APPEND)) flags |= __SAPP;
256 
257   // If close-on-exec was requested, then turn it on if not already.
258   if ((oflags & O_CLOEXEC) && !((tmp = fcntl(fd, F_GETFD)) & FD_CLOEXEC)) {
259     fcntl(fd, F_SETFD, tmp | FD_CLOEXEC);
260   }
261 
262   return __fopen(fd, flags);
263 }
264 
265 // Re-direct an existing, open (probably) file to some other file.
266 // ANSI is written such that the original file gets closed if at
267 // all possible, no matter what.
268 // TODO: rewrite this mess completely.
freopen(const char * file,const char * mode,FILE * fp)269 FILE* freopen(const char* file, const char* mode, FILE* fp) {
270   int oflags;
271   int flags = __sflags(mode, &oflags);
272   if (flags == 0) {
273     fclose(fp);
274     return nullptr;
275   }
276 
277   ScopedFileLock sfl(fp);
278 
279   // There are actually programs that depend on being able to "freopen"
280   // descriptors that weren't originally open.  Keep this from breaking.
281   // Remember whether the stream was open to begin with, and which file
282   // descriptor (if any) was associated with it.  If it was attached to
283   // a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
284   // should work.  This is unnecessary if it was not a Unix file.
285   int isopen, wantfd;
286   if (fp->_flags == 0) {
287     fp->_flags = __SEOF; // Hold on to it.
288     isopen = 0;
289     wantfd = -1;
290   } else {
291     // Flush the stream; ANSI doesn't require this.
292     if (fp->_flags & __SWR) __sflush(fp);
293 
294     // If close is NULL, closing is a no-op, hence pointless.
295     isopen = fp->_close != NULL;
296     if ((wantfd = fp->_file) < 0 && isopen) {
297         (*fp->_close)(fp->_cookie);
298         isopen = 0;
299     }
300   }
301 
302   // Get a new descriptor to refer to the new file.
303   int fd = open(file, oflags, DEFFILEMODE);
304   if (fd < 0 && isopen) {
305     // If out of fd's close the old one and try again.
306     if (errno == ENFILE || errno == EMFILE) {
307       (*fp->_close)(fp->_cookie);
308       isopen = 0;
309       fd = open(file, oflags, DEFFILEMODE);
310     }
311   }
312 
313   int sverrno = errno;
314 
315   // Finish closing fp.  Even if the open succeeded above, we cannot
316   // keep fp->_base: it may be the wrong size.  This loses the effect
317   // of any setbuffer calls, but stdio has always done this before.
318   if (isopen && fd != wantfd) (*fp->_close)(fp->_cookie);
319   if (fp->_flags & __SMBF) free(fp->_bf._base);
320   fp->_w = 0;
321   fp->_r = 0;
322   fp->_p = NULL;
323   fp->_bf._base = NULL;
324   fp->_bf._size = 0;
325   fp->_lbfsize = 0;
326   if (HASUB(fp)) FREEUB(fp);
327   _UB(fp)._size = 0;
328   WCIO_FREE(fp);
329   if (HASLB(fp)) FREELB(fp);
330   fp->_lb._size = 0;
331 
332   if (fd < 0) { // Did not get it after all.
333     fp->_flags = 0; // Release.
334     errno = sverrno; // Restore errno in case _close clobbered it.
335     return nullptr;
336   }
337 
338   // If reopening something that was open before on a real file, try
339   // to maintain the descriptor.  Various C library routines (perror)
340   // assume stderr is always fd STDERR_FILENO, even if being freopen'd.
341   if (wantfd >= 0 && fd != wantfd) {
342     if (dup3(fd, wantfd, oflags & O_CLOEXEC) >= 0) {
343       close(fd);
344       fd = wantfd;
345     }
346   }
347 
348   // _file is only a short.
349   if (fd > SHRT_MAX) {
350       fp->_flags = 0; // Release.
351       errno = EMFILE;
352       return nullptr;
353   }
354 
355   fp->_flags = flags;
356   fp->_file = fd;
357   fp->_cookie = fp;
358   fp->_read = __sread;
359   fp->_write = __swrite;
360   fp->_close = __sclose;
361   _EXT(fp)->_seek64 = __sseek64;
362 
363   // When opening in append mode, even though we use O_APPEND,
364   // we need to seek to the end so that ftell() gets the right
365   // answer.  If the user then alters the seek pointer, or
366   // the file extends, this will fail, but there is not much
367   // we can do about this.  (We could set __SAPP and check in
368   // fseek and ftell.)
369   if (oflags & O_APPEND) __sseek64(fp, 0, SEEK_END);
370   return fp;
371 }
372 __strong_alias(freopen64, freopen);
373 
fclose(FILE * fp)374 int fclose(FILE* fp) {
375   if (fp->_flags == 0) {
376     // Already freed!
377     errno = EBADF;
378     return EOF;
379   }
380 
381   ScopedFileLock sfl(fp);
382   WCIO_FREE(fp);
383   int r = fp->_flags & __SWR ? __sflush(fp) : 0;
384   if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0) {
385     r = EOF;
386   }
387   if (fp->_flags & __SMBF) free(fp->_bf._base);
388   if (HASUB(fp)) FREEUB(fp);
389   if (HASLB(fp)) FREELB(fp);
390 
391   // Poison this FILE so accesses after fclose will be obvious.
392   fp->_file = -1;
393   fp->_r = fp->_w = 0;
394 
395   // Release this FILE for reuse.
396   fp->_flags = 0;
397   return r;
398 }
399 
fileno_unlocked(FILE * fp)400 int fileno_unlocked(FILE* fp) {
401   int fd = fp->_file;
402   if (fd == -1) {
403     errno = EBADF;
404     return -1;
405   }
406   return fd;
407 }
408 
fileno(FILE * fp)409 int fileno(FILE* fp) {
410   ScopedFileLock sfl(fp);
411   return fileno_unlocked(fp);
412 }
413 
clearerr_unlocked(FILE * fp)414 void clearerr_unlocked(FILE* fp) {
415   return __sclearerr(fp);
416 }
417 
clearerr(FILE * fp)418 void clearerr(FILE* fp) {
419   ScopedFileLock sfl(fp);
420   clearerr_unlocked(fp);
421 }
422 
feof_unlocked(FILE * fp)423 int feof_unlocked(FILE* fp) {
424   return ((fp->_flags & __SEOF) != 0);
425 }
426 
feof(FILE * fp)427 int feof(FILE* fp) {
428   ScopedFileLock sfl(fp);
429   return feof_unlocked(fp);
430 }
431 
ferror_unlocked(FILE * fp)432 int ferror_unlocked(FILE* fp) {
433   return __sferror(fp);
434 }
435 
ferror(FILE * fp)436 int ferror(FILE* fp) {
437   ScopedFileLock sfl(fp);
438   return ferror_unlocked(fp);
439 }
440 
__sread(void * cookie,char * buf,int n)441 int __sread(void* cookie, char* buf, int n) {
442   FILE* fp = reinterpret_cast<FILE*>(cookie);
443   return TEMP_FAILURE_RETRY(read(fp->_file, buf, n));
444 }
445 
__swrite(void * cookie,const char * buf,int n)446 int __swrite(void* cookie, const char* buf, int n) {
447   FILE* fp = reinterpret_cast<FILE*>(cookie);
448   if (fp->_flags & __SAPP) {
449     // The FILE* is in append mode, but the underlying fd doesn't have O_APPEND set.
450     // We need to seek manually.
451     // TODO: use fcntl(2) to set O_APPEND in fdopen(3) instead?
452     TEMP_FAILURE_RETRY(lseek64(fp->_file, 0, SEEK_END));
453   }
454   return TEMP_FAILURE_RETRY(write(fp->_file, buf, n));
455 }
456 
__sseek(void * cookie,fpos_t offset,int whence)457 fpos_t __sseek(void* cookie, fpos_t offset, int whence) {
458   FILE* fp = reinterpret_cast<FILE*>(cookie);
459   return TEMP_FAILURE_RETRY(lseek(fp->_file, offset, whence));
460 }
461 
__sseek64(void * cookie,off64_t offset,int whence)462 off64_t __sseek64(void* cookie, off64_t offset, int whence) {
463   FILE* fp = reinterpret_cast<FILE*>(cookie);
464   return TEMP_FAILURE_RETRY(lseek64(fp->_file, offset, whence));
465 }
466 
__sclose(void * cookie)467 int __sclose(void* cookie) {
468   FILE* fp = reinterpret_cast<FILE*>(cookie);
469   return close(fp->_file);
470 }
471 
__seek_unlocked(FILE * fp,off64_t offset,int whence)472 static off64_t __seek_unlocked(FILE* fp, off64_t offset, int whence) {
473   // Use `_seek64` if set, but fall back to `_seek`.
474   if (_EXT(fp)->_seek64 != nullptr) {
475     return (*_EXT(fp)->_seek64)(fp->_cookie, offset, whence);
476   } else if (fp->_seek != nullptr) {
477     off64_t result = (*fp->_seek)(fp->_cookie, offset, whence);
478 #if !defined(__LP64__)
479     // Avoid sign extension if off64_t is larger than off_t.
480     if (result != -1) result &= 0xffffffff;
481 #endif
482     return result;
483   } else {
484     errno = ESPIPE;
485     return -1;
486   }
487 }
488 
__ftello64_unlocked(FILE * fp)489 static off64_t __ftello64_unlocked(FILE* fp) {
490   // Find offset of underlying I/O object, then adjust for buffered bytes.
491   __sflush(fp);  // May adjust seek offset on append stream.
492   off64_t result = __seek_unlocked(fp, 0, SEEK_CUR);
493   if (result == -1) {
494     return -1;
495   }
496 
497   if (fp->_flags & __SRD) {
498     // Reading.  Any unread characters (including
499     // those from ungetc) cause the position to be
500     // smaller than that in the underlying object.
501     result -= fp->_r;
502     if (HASUB(fp)) result -= fp->_ur;
503   } else if (fp->_flags & __SWR && fp->_p != NULL) {
504     // Writing.  Any buffered characters cause the
505     // position to be greater than that in the
506     // underlying object.
507     result += fp->_p - fp->_bf._base;
508   }
509   return result;
510 }
511 
__fseeko64(FILE * fp,off64_t offset,int whence,int off_t_bits)512 int __fseeko64(FILE* fp, off64_t offset, int whence, int off_t_bits) {
513   ScopedFileLock sfl(fp);
514 
515   // Change any SEEK_CUR to SEEK_SET, and check `whence` argument.
516   // After this, whence is either SEEK_SET or SEEK_END.
517   if (whence == SEEK_CUR) {
518     fpos64_t current_offset = __ftello64_unlocked(fp);
519     if (current_offset == -1) {
520       return -1;
521     }
522     offset += current_offset;
523     whence = SEEK_SET;
524   } else if (whence != SEEK_SET && whence != SEEK_END) {
525     errno = EINVAL;
526     return -1;
527   }
528 
529   // If our caller has a 32-bit interface, refuse to go past a 32-bit file offset.
530   if (off_t_bits == 32 && offset > LONG_MAX) {
531     errno = EOVERFLOW;
532     return -1;
533   }
534 
535   if (fp->_bf._base == NULL) __smakebuf(fp);
536 
537   // Flush unwritten data and attempt the seek.
538   if (__sflush(fp) || __seek_unlocked(fp, offset, whence) == -1) {
539     return -1;
540   }
541 
542   // Success: clear EOF indicator and discard ungetc() data.
543   if (HASUB(fp)) FREEUB(fp);
544   fp->_p = fp->_bf._base;
545   fp->_r = 0;
546   /* fp->_w = 0; */	/* unnecessary (I think...) */
547   fp->_flags &= ~__SEOF;
548   return 0;
549 }
550 
fseeko(FILE * fp,off_t offset,int whence)551 int fseeko(FILE* fp, off_t offset, int whence) {
552   static_assert(sizeof(off_t) == sizeof(long), "sizeof(off_t) != sizeof(long)");
553   return __fseeko64(fp, offset, whence, 8*sizeof(off_t));
554 }
555 __strong_alias(fseek, fseeko);
556 
fseeko64(FILE * fp,off64_t offset,int whence)557 int fseeko64(FILE* fp, off64_t offset, int whence) {
558   return __fseeko64(fp, offset, whence, 8*sizeof(off_t));
559 }
560 
fsetpos(FILE * fp,const fpos_t * pos)561 int fsetpos(FILE* fp, const fpos_t* pos) {
562   return fseeko(fp, *pos, SEEK_SET);
563 }
564 
fsetpos64(FILE * fp,const fpos64_t * pos)565 int fsetpos64(FILE* fp, const fpos64_t* pos) {
566   return fseeko64(fp, *pos, SEEK_SET);
567 }
568 
ftello(FILE * fp)569 off_t ftello(FILE* fp) {
570   static_assert(sizeof(off_t) == sizeof(long), "sizeof(off_t) != sizeof(long)");
571   off64_t result = ftello64(fp);
572   if (result > LONG_MAX) {
573     errno = EOVERFLOW;
574     return -1;
575   }
576   return result;
577 }
578 __strong_alias(ftell, ftello);
579 
ftello64(FILE * fp)580 off64_t ftello64(FILE* fp) {
581   ScopedFileLock sfl(fp);
582   return __ftello64_unlocked(fp);
583 }
584 
fgetpos(FILE * fp,fpos_t * pos)585 int fgetpos(FILE* fp, fpos_t* pos) {
586   *pos = ftello(fp);
587   return (*pos == -1) ? -1 : 0;
588 }
589 
fgetpos64(FILE * fp,fpos64_t * pos)590 int fgetpos64(FILE* fp, fpos64_t* pos) {
591   *pos = ftello64(fp);
592   return (*pos == -1) ? -1 : 0;
593 }
594 
__funopen(const void * cookie,int (* read_fn)(void *,char *,int),int (* write_fn)(void *,const char *,int),int (* close_fn)(void *))595 static FILE* __funopen(const void* cookie,
596                        int (*read_fn)(void*, char*, int),
597                        int (*write_fn)(void*, const char*, int),
598                        int (*close_fn)(void*)) {
599   if (read_fn == nullptr && write_fn == nullptr) {
600     errno = EINVAL;
601     return nullptr;
602   }
603 
604   FILE* fp = __sfp();
605   if (fp == nullptr) return nullptr;
606 
607   if (read_fn != nullptr && write_fn != nullptr) {
608     fp->_flags = __SRW;
609   } else if (read_fn != nullptr) {
610     fp->_flags = __SRD;
611   } else if (write_fn != nullptr) {
612     fp->_flags = __SWR;
613   }
614 
615   fp->_file = -1;
616   fp->_cookie = const_cast<void*>(cookie); // The funopen(3) API is incoherent.
617   fp->_read = read_fn;
618   fp->_write = write_fn;
619   fp->_close = close_fn;
620 
621   return fp;
622 }
623 
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 *))624 FILE* funopen(const void* cookie,
625               int (*read_fn)(void*, char*, int),
626               int (*write_fn)(void*, const char*, int),
627               fpos_t (*seek_fn)(void*, fpos_t, int),
628               int (*close_fn)(void*)) {
629   FILE* fp = __funopen(cookie, read_fn, write_fn, close_fn);
630   if (fp != nullptr) {
631     fp->_seek = seek_fn;
632   }
633   return fp;
634 }
635 
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 *))636 FILE* funopen64(const void* cookie,
637                 int (*read_fn)(void*, char*, int),
638                 int (*write_fn)(void*, const char*, int),
639                 fpos64_t (*seek_fn)(void*, fpos64_t, int),
640                 int (*close_fn)(void*)) {
641   FILE* fp = __funopen(cookie, read_fn, write_fn, close_fn);
642   if (fp != nullptr) {
643     _EXT(fp)->_seek64 = seek_fn;
644   }
645   return fp;
646 }
647 
asprintf(char ** s,const char * fmt,...)648 int asprintf(char** s, const char* fmt, ...) {
649   PRINTF_IMPL(vasprintf(s, fmt, ap));
650 }
651 
ctermid(char * s)652 char* ctermid(char* s) {
653   return s ? strcpy(s, _PATH_TTY) : const_cast<char*>(_PATH_TTY);
654 }
655 
dprintf(int fd,const char * fmt,...)656 int dprintf(int fd, const char* fmt, ...) {
657   PRINTF_IMPL(vdprintf(fd, fmt, ap));
658 }
659 
fprintf(FILE * fp,const char * fmt,...)660 int fprintf(FILE* fp, const char* fmt, ...) {
661   PRINTF_IMPL(vfprintf(fp, fmt, ap));
662 }
663 
fgetc(FILE * fp)664 int fgetc(FILE* fp) {
665   return getc(fp);
666 }
667 
fputc(int c,FILE * fp)668 int fputc(int c, FILE* fp) {
669   return putc(c, fp);
670 }
671 
fscanf(FILE * fp,const char * fmt,...)672 int fscanf(FILE* fp, const char* fmt, ...) {
673   PRINTF_IMPL(vfscanf(fp, fmt, ap));
674 }
675 
fwprintf(FILE * fp,const wchar_t * fmt,...)676 int fwprintf(FILE* fp, const wchar_t* fmt, ...) {
677   PRINTF_IMPL(vfwprintf(fp, fmt, ap));
678 }
679 
fwscanf(FILE * fp,const wchar_t * fmt,...)680 int fwscanf(FILE* fp, const wchar_t* fmt, ...) {
681   PRINTF_IMPL(vfwscanf(fp, fmt, ap));
682 }
683 
getc(FILE * fp)684 int getc(FILE* fp) {
685   ScopedFileLock sfl(fp);
686   return getc_unlocked(fp);
687 }
688 
getc_unlocked(FILE * fp)689 int getc_unlocked(FILE* fp) {
690   return __sgetc(fp);
691 }
692 
getchar_unlocked()693 int getchar_unlocked() {
694   return getc_unlocked(stdin);
695 }
696 
getchar()697 int getchar() {
698   return getc(stdin);
699 }
700 
getline(char ** buf,size_t * len,FILE * fp)701 ssize_t getline(char** buf, size_t* len, FILE* fp) {
702   return getdelim(buf, len, '\n', fp);
703 }
704 
getwc(FILE * fp)705 wint_t getwc(FILE* fp) {
706   return fgetwc(fp);
707 }
708 
getwchar()709 wint_t getwchar() {
710   return fgetwc(stdin);
711 }
712 
printf(const char * fmt,...)713 int printf(const char* fmt, ...) {
714   PRINTF_IMPL(vfprintf(stdout, fmt, ap));
715 }
716 
putc(int c,FILE * fp)717 int putc(int c, FILE* fp) {
718   ScopedFileLock sfl(fp);
719   return putc_unlocked(c, fp);
720 }
721 
putc_unlocked(int c,FILE * fp)722 int putc_unlocked(int c, FILE* fp) {
723   if (cantwrite(fp)) {
724     errno = EBADF;
725     return EOF;
726   }
727   _SET_ORIENTATION(fp, -1);
728   if (--fp->_w >= 0 || (fp->_w >= fp->_lbfsize && c != '\n')) {
729     return (*fp->_p++ = c);
730   }
731   return (__swbuf(c, fp));
732 }
733 
putchar(int c)734 int putchar(int c) {
735   return putc(c, stdout);
736 }
737 
putchar_unlocked(int c)738 int putchar_unlocked(int c) {
739   return putc_unlocked(c, stdout);
740 }
741 
putwc(wchar_t wc,FILE * fp)742 wint_t putwc(wchar_t wc, FILE* fp) {
743   return fputwc(wc, fp);
744 }
745 
putwchar(wchar_t wc)746 wint_t putwchar(wchar_t wc) {
747   return fputwc(wc, stdout);
748 }
749 
remove(const char * path)750 int remove(const char* path) {
751   if (unlink(path) != -1) return 0;
752   if (errno != EISDIR) return -1;
753   return rmdir(path);
754 }
755 
rewind(FILE * fp)756 void rewind(FILE* fp) {
757   ScopedFileLock sfl(fp);
758   fseek(fp, 0, SEEK_SET);
759   clearerr_unlocked(fp);
760 }
761 
scanf(const char * fmt,...)762 int scanf(const char* fmt, ...) {
763   PRINTF_IMPL(vfscanf(stdin, fmt, ap));
764 }
765 
setbuf(FILE * fp,char * buf)766 void setbuf(FILE* fp, char* buf) {
767   setbuffer(fp, buf, BUFSIZ);
768 }
769 
setbuffer(FILE * fp,char * buf,int size)770 void setbuffer(FILE* fp, char* buf, int size) {
771   setvbuf(fp, buf, buf ? _IOFBF : _IONBF, size);
772 }
773 
setlinebuf(FILE * fp)774 int setlinebuf(FILE* fp) {
775   return setvbuf(fp, nullptr, _IOLBF, 0);
776 }
777 
snprintf(char * s,size_t n,const char * fmt,...)778 int snprintf(char* s, size_t n, const char* fmt, ...) {
779   PRINTF_IMPL(vsnprintf(s, n, fmt, ap));
780 }
781 
sprintf(char * s,const char * fmt,...)782 int sprintf(char* s, const char* fmt, ...) {
783   PRINTF_IMPL(vsprintf(s, fmt, ap));
784 }
785 
sscanf(const char * s,const char * fmt,...)786 int sscanf(const char* s, const char* fmt, ...) {
787   PRINTF_IMPL(vsscanf(s, fmt, ap));
788 }
789 
swprintf(wchar_t * s,size_t n,const wchar_t * fmt,...)790 int swprintf(wchar_t* s, size_t n, const wchar_t* fmt, ...) {
791   PRINTF_IMPL(vswprintf(s, n, fmt, ap));
792 }
793 
swscanf(const wchar_t * s,const wchar_t * fmt,...)794 int swscanf(const wchar_t* s, const wchar_t* fmt, ...) {
795   PRINTF_IMPL(vswscanf(s, fmt, ap));
796 }
797 
vprintf(const char * fmt,va_list ap)798 int vprintf(const char* fmt, va_list ap) {
799   return vfprintf(stdout, fmt, ap);
800 }
801 
vscanf(const char * fmt,va_list ap)802 int vscanf(const char* fmt, va_list ap) {
803   return vfscanf(stdin, fmt, ap);
804 }
805 
vsnprintf(char * s,size_t n,const char * fmt,va_list ap)806 int vsnprintf(char* s, size_t n, const char* fmt, va_list ap) {
807   // stdio internals use int rather than size_t.
808   static_assert(INT_MAX <= SSIZE_MAX, "SSIZE_MAX too large to fit in int");
809 
810   __check_count("vsnprintf", "size", n);
811 
812   // Stdio internals do not deal correctly with zero length buffer.
813   char dummy;
814   if (n == 0) {
815     s = &dummy;
816     n = 1;
817   }
818 
819   FILE f;
820   __sfileext fext;
821   _FILEEXT_SETUP(&f, &fext);
822   f._file = -1;
823   f._flags = __SWR | __SSTR;
824   f._bf._base = f._p = reinterpret_cast<unsigned char*>(s);
825   f._bf._size = f._w = n - 1;
826 
827   int result = __vfprintf(&f, fmt, ap);
828   *f._p = '\0';
829   return result;
830 }
831 
vsprintf(char * s,const char * fmt,va_list ap)832 int vsprintf(char* s, const char* fmt, va_list ap) {
833   return vsnprintf(s, SSIZE_MAX, fmt, ap);
834 }
835 
vwprintf(const wchar_t * fmt,va_list ap)836 int vwprintf(const wchar_t* fmt, va_list ap) {
837   return vfwprintf(stdout, fmt, ap);
838 }
839 
vwscanf(const wchar_t * fmt,va_list ap)840 int vwscanf(const wchar_t* fmt, va_list ap) {
841   return vfwscanf(stdin, fmt, ap);
842 }
843 
wprintf(const wchar_t * fmt,...)844 int wprintf(const wchar_t* fmt, ...) {
845   PRINTF_IMPL(vfwprintf(stdout, fmt, ap));
846 }
847 
wscanf(const wchar_t * fmt,...)848 int wscanf(const wchar_t* fmt, ...) {
849   PRINTF_IMPL(vfwscanf(stdin, fmt, ap));
850 }
851 
852 namespace {
853 
854 namespace phony {
855 #include <bits/struct_file.h>
856 }
857 
858 static_assert(sizeof(::__sFILE) == sizeof(phony::__sFILE),
859               "size mismatch between `struct __sFILE` implementation and public stub");
860 static_assert(alignof(::__sFILE) == alignof(phony::__sFILE),
861               "alignment mismatch between `struct __sFILE` implementation and public stub");
862 
863 }
864