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