2011-02-12 00:22:29 -05:00
|
|
|
#include "stdio_impl.h"
|
2012-11-08 16:39:41 -05:00
|
|
|
#include <fcntl.h>
|
2011-02-12 00:22:29 -05:00
|
|
|
|
|
|
|
/* The basic idea of this implementation is to open a new FILE,
|
|
|
|
* hack the necessary parts of the new FILE into the old one, then
|
|
|
|
* close the new FILE. */
|
|
|
|
|
2012-10-24 23:16:41 -04:00
|
|
|
/* Locking IS necessary because another thread may provably hold the
|
|
|
|
* lock, via flockfile or otherwise, when freopen is called, and in that
|
|
|
|
* case, freopen cannot act until the lock is released. */
|
2011-02-12 00:22:29 -05:00
|
|
|
|
2012-10-24 21:16:06 -04:00
|
|
|
int __dup3(int, int, int);
|
|
|
|
|
2012-09-06 22:44:55 -04:00
|
|
|
FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *restrict f)
|
2011-02-12 00:22:29 -05:00
|
|
|
{
|
2012-10-24 21:16:06 -04:00
|
|
|
int fl = __fmodeflags(mode);
|
2011-02-12 00:22:29 -05:00
|
|
|
FILE *f2;
|
|
|
|
|
2012-10-24 23:16:41 -04:00
|
|
|
FLOCK(f);
|
|
|
|
|
2011-02-12 00:22:29 -05:00
|
|
|
fflush(f);
|
|
|
|
|
|
|
|
if (!filename) {
|
2012-10-24 21:16:06 -04:00
|
|
|
if (fl&O_CLOEXEC)
|
|
|
|
__syscall(SYS_fcntl, f->fd, F_SETFD, FD_CLOEXEC);
|
|
|
|
fl &= ~(O_CREAT|O_EXCL|O_CLOEXEC);
|
2012-10-24 20:03:43 -04:00
|
|
|
if (syscall(SYS_fcntl, f->fd, F_SETFL, fl) < 0)
|
2012-10-24 21:16:06 -04:00
|
|
|
goto fail;
|
2011-02-12 00:22:29 -05:00
|
|
|
} else {
|
|
|
|
f2 = fopen(filename, mode);
|
|
|
|
if (!f2) goto fail;
|
2012-10-24 21:16:06 -04:00
|
|
|
if (f2->fd == f->fd) f2->fd = -1; /* avoid closing in fclose */
|
|
|
|
else if (__dup3(f2->fd, f->fd, fl&O_CLOEXEC)<0) goto fail2;
|
2011-02-12 00:22:29 -05:00
|
|
|
|
2012-10-24 23:16:41 -04:00
|
|
|
f->flags = (f->flags & F_PERM) | f2->flags;
|
|
|
|
f->read = f2->read;
|
|
|
|
f->write = f2->write;
|
|
|
|
f->seek = f2->seek;
|
|
|
|
f->close = f2->close;
|
2011-02-12 00:22:29 -05:00
|
|
|
|
2012-10-24 23:16:41 -04:00
|
|
|
fclose(f2);
|
|
|
|
}
|
|
|
|
|
|
|
|
FUNLOCK(f);
|
2011-02-12 00:22:29 -05:00
|
|
|
return f;
|
|
|
|
|
|
|
|
fail2:
|
|
|
|
fclose(f2);
|
|
|
|
fail:
|
|
|
|
fclose(f);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LFS64(freopen);
|