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