1#include "stdio_impl.h" 2#include <fcntl.h> 3#include <unistd.h> 4 5/* The basic idea of this implementation is to open a new FILE, 6 * hack the necessary parts of the new FILE into the old one, then 7 * close the new FILE. */ 8 9/* Locking IS necessary because another thread may provably hold the 10 * lock, via flockfile or otherwise, when freopen is called, and in that 11 * case, freopen cannot act until the lock is released. */ 12 13FILE* freopen(const char* restrict filename, const char* restrict mode, FILE* restrict f) { 14 int fl = __fmodeflags(mode); 15 FILE* f2; 16 17 FLOCK(f); 18 19 fflush(f); 20 21 if (!filename) { 22 if (fl & O_CLOEXEC) 23 fcntl(f->fd, F_SETFD, FD_CLOEXEC); 24 fl &= ~(O_CREAT | O_EXCL | O_CLOEXEC); 25 if (fcntl(f->fd, F_SETFL, fl) < 0) 26 goto fail; 27 } else { 28 f2 = fopen(filename, mode); 29 if (!f2) 30 goto fail; 31 if (f2->fd == f->fd) 32 f2->fd = -1; /* avoid closing in fclose */ 33 else if (dup3(f2->fd, f->fd, fl & O_CLOEXEC) < 0) 34 goto fail2; 35 36 f->flags = (f->flags & F_PERM) | f2->flags; 37 f->read = f2->read; 38 f->write = f2->write; 39 f->seek = f2->seek; 40 f->close = f2->close; 41 42 fclose(f2); 43 } 44 45 FUNLOCK(f); 46 return f; 47 48fail2: 49 fclose(f2); 50fail: 51 fclose(f); 52 return NULL; 53} 54