Home | History | Annotate | Download | only in stdio
      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:
    103   explicit ScopedFileLock(FILE* fp) : fp_(fp) {
    104     FLOCKFILE(fp_);
    105   }
    106   ~ScopedFileLock() {
    107     FUNLOCKFILE(fp_);
    108   }
    109 
    110  private:
    111   FILE* fp_;
    112 };
    113 
    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  */
    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 
    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 
    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 
    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 
    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.
    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 
    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 
    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 
    409 int fileno(FILE* fp) {
    410   ScopedFileLock sfl(fp);
    411   return fileno_unlocked(fp);
    412 }
    413 
    414 void clearerr_unlocked(FILE* fp) {
    415   return __sclearerr(fp);
    416 }
    417 
    418 void clearerr(FILE* fp) {
    419   ScopedFileLock sfl(fp);
    420   clearerr_unlocked(fp);
    421 }
    422 
    423 int feof_unlocked(FILE* fp) {
    424   return ((fp->_flags & __SEOF) != 0);
    425 }
    426 
    427 int feof(FILE* fp) {
    428   ScopedFileLock sfl(fp);
    429   return feof_unlocked(fp);
    430 }
    431 
    432 int ferror_unlocked(FILE* fp) {
    433   return __sferror(fp);
    434 }
    435 
    436 int ferror(FILE* fp) {
    437   ScopedFileLock sfl(fp);
    438   return ferror_unlocked(fp);
    439 }
    440 
    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 
    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 
    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 
    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 
    467 int __sclose(void* cookie) {
    468   FILE* fp = reinterpret_cast<FILE*>(cookie);
    469   return close(fp->_file);
    470 }
    471 
    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 
    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 
    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 
    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 
    557 int fseeko64(FILE* fp, off64_t offset, int whence) {
    558   return __fseeko64(fp, offset, whence, 8*sizeof(off_t));
    559 }
    560 
    561 int fsetpos(FILE* fp, const fpos_t* pos) {
    562   return fseeko(fp, *pos, SEEK_SET);
    563 }
    564 
    565 int fsetpos64(FILE* fp, const fpos64_t* pos) {
    566   return fseeko64(fp, *pos, SEEK_SET);
    567 }
    568 
    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 
    580 off64_t ftello64(FILE* fp) {
    581   ScopedFileLock sfl(fp);
    582   return __ftello64_unlocked(fp);
    583 }
    584 
    585 int fgetpos(FILE* fp, fpos_t* pos) {
    586   *pos = ftello(fp);
    587   return (*pos == -1) ? -1 : 0;
    588 }
    589 
    590 int fgetpos64(FILE* fp, fpos64_t* pos) {
    591   *pos = ftello64(fp);
    592   return (*pos == -1) ? -1 : 0;
    593 }
    594 
    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 
    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 
    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 
    648 int asprintf(char** s, const char* fmt, ...) {
    649   PRINTF_IMPL(vasprintf(s, fmt, ap));
    650 }
    651 
    652 char* ctermid(char* s) {
    653   return s ? strcpy(s, _PATH_TTY) : const_cast<char*>(_PATH_TTY);
    654 }
    655 
    656 int dprintf(int fd, const char* fmt, ...) {
    657   PRINTF_IMPL(vdprintf(fd, fmt, ap));
    658 }
    659 
    660 int fprintf(FILE* fp, const char* fmt, ...) {
    661   PRINTF_IMPL(vfprintf(fp, fmt, ap));
    662 }
    663 
    664 int fgetc(FILE* fp) {
    665   return getc(fp);
    666 }
    667 
    668 int fputc(int c, FILE* fp) {
    669   return putc(c, fp);
    670 }
    671 
    672 int fscanf(FILE* fp, const char* fmt, ...) {
    673   PRINTF_IMPL(vfscanf(fp, fmt, ap));
    674 }
    675 
    676 int fwprintf(FILE* fp, const wchar_t* fmt, ...) {
    677   PRINTF_IMPL(vfwprintf(fp, fmt, ap));
    678 }
    679 
    680 int fwscanf(FILE* fp, const wchar_t* fmt, ...) {
    681   PRINTF_IMPL(vfwscanf(fp, fmt, ap));
    682 }
    683 
    684 int getc(FILE* fp) {
    685   ScopedFileLock sfl(fp);
    686   return getc_unlocked(fp);
    687 }
    688 
    689 int getc_unlocked(FILE* fp) {
    690   return __sgetc(fp);
    691 }
    692 
    693 int getchar_unlocked() {
    694   return getc_unlocked(stdin);
    695 }
    696 
    697 int getchar() {
    698   return getc(stdin);
    699 }
    700 
    701 ssize_t getline(char** buf, size_t* len, FILE* fp) {
    702   return getdelim(buf, len, '\n', fp);
    703 }
    704 
    705 wint_t getwc(FILE* fp) {
    706   return fgetwc(fp);
    707 }
    708 
    709 wint_t getwchar() {
    710   return fgetwc(stdin);
    711 }
    712 
    713 int printf(const char* fmt, ...) {
    714   PRINTF_IMPL(vfprintf(stdout, fmt, ap));
    715 }
    716 
    717 int putc(int c, FILE* fp) {
    718   ScopedFileLock sfl(fp);
    719   return putc_unlocked(c, fp);
    720 }
    721 
    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 
    734 int putchar(int c) {
    735   return putc(c, stdout);
    736 }
    737 
    738 int putchar_unlocked(int c) {
    739   return putc_unlocked(c, stdout);
    740 }
    741 
    742 wint_t putwc(wchar_t wc, FILE* fp) {
    743   return fputwc(wc, fp);
    744 }
    745 
    746 wint_t putwchar(wchar_t wc) {
    747   return fputwc(wc, stdout);
    748 }
    749 
    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 
    756 void rewind(FILE* fp) {
    757   ScopedFileLock sfl(fp);
    758   fseek(fp, 0, SEEK_SET);
    759   clearerr_unlocked(fp);
    760 }
    761 
    762 int scanf(const char* fmt, ...) {
    763   PRINTF_IMPL(vfscanf(stdin, fmt, ap));
    764 }
    765 
    766 void setbuf(FILE* fp, char* buf) {
    767   setbuffer(fp, buf, BUFSIZ);
    768 }
    769 
    770 void setbuffer(FILE* fp, char* buf, int size) {
    771   setvbuf(fp, buf, buf ? _IOFBF : _IONBF, size);
    772 }
    773 
    774 int setlinebuf(FILE* fp) {
    775   return setvbuf(fp, nullptr, _IOLBF, 0);
    776 }
    777 
    778 int snprintf(char* s, size_t n, const char* fmt, ...) {
    779   PRINTF_IMPL(vsnprintf(s, n, fmt, ap));
    780 }
    781 
    782 int sprintf(char* s, const char* fmt, ...) {
    783   PRINTF_IMPL(vsprintf(s, fmt, ap));
    784 }
    785 
    786 int sscanf(const char* s, const char* fmt, ...) {
    787   PRINTF_IMPL(vsscanf(s, fmt, ap));
    788 }
    789 
    790 int swprintf(wchar_t* s, size_t n, const wchar_t* fmt, ...) {
    791   PRINTF_IMPL(vswprintf(s, n, fmt, ap));
    792 }
    793 
    794 int swscanf(const wchar_t* s, const wchar_t* fmt, ...) {
    795   PRINTF_IMPL(vswscanf(s, fmt, ap));
    796 }
    797 
    798 int vprintf(const char* fmt, va_list ap) {
    799   return vfprintf(stdout, fmt, ap);
    800 }
    801 
    802 int vscanf(const char* fmt, va_list ap) {
    803   return vfscanf(stdin, fmt, ap);
    804 }
    805 
    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 
    832 int vsprintf(char* s, const char* fmt, va_list ap) {
    833   return vsnprintf(s, SSIZE_MAX, fmt, ap);
    834 }
    835 
    836 int vwprintf(const wchar_t* fmt, va_list ap) {
    837   return vfwprintf(stdout, fmt, ap);
    838 }
    839 
    840 int vwscanf(const wchar_t* fmt, va_list ap) {
    841   return vfwscanf(stdin, fmt, ap);
    842 }
    843 
    844 int wprintf(const wchar_t* fmt, ...) {
    845   PRINTF_IMPL(vfwprintf(stdout, fmt, ap));
    846 }
    847 
    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