]> git.proxmox.com Git - wasi-libc.git/blame - libc-top-half/musl/src/stdio/freopen.c
Add comments explaining changes to upstream source files.
[wasi-libc.git] / libc-top-half / musl / src / stdio / freopen.c
CommitLineData
e5f14be3 1#ifdef __wasilibc_unmodified_upstream // WASI has no syscall, dup
320054e8
DG
2#include "stdio_impl.h"
3#else
4#include <wasi/libc.h>
5#endif
6#include <fcntl.h>
7#include <unistd.h>
e5f14be3 8#ifdef __wasilibc_unmodified_upstream // WASI has no syscall, dup
320054e8
DG
9#else
10// Move this below fcntl.h and unistd.h so that the __syscall macro doesn't
11// cause trouble.
12#include "stdio_impl.h"
13#endif
14
15/* The basic idea of this implementation is to open a new FILE,
16 * hack the necessary parts of the new FILE into the old one, then
17 * close the new FILE. */
18
19/* Locking IS necessary because another thread may provably hold the
20 * lock, via flockfile or otherwise, when freopen is called, and in that
21 * case, freopen cannot act until the lock is released. */
22
23FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *restrict f)
24{
25 int fl = __fmodeflags(mode);
26 FILE *f2;
27
28 FLOCK(f);
29
30 fflush(f);
31
32 if (!filename) {
33 if (fl&O_CLOEXEC)
e5f14be3 34#ifdef __wasilibc_unmodified_upstream // WASI has no syscall
320054e8
DG
35 __syscall(SYS_fcntl, f->fd, F_SETFD, FD_CLOEXEC);
36#else
37 fcntl(f->fd, F_SETFD, FD_CLOEXEC);
38#endif
39 fl &= ~(O_CREAT|O_EXCL|O_CLOEXEC);
e5f14be3 40#ifdef __wasilibc_unmodified_upstream // WASI has no syscall
320054e8
DG
41 if (syscall(SYS_fcntl, f->fd, F_SETFL, fl) < 0)
42#else
43 if (fcntl(f->fd, F_SETFL, fl) < 0)
44#endif
45 goto fail;
46 } else {
47 f2 = fopen(filename, mode);
48 if (!f2) goto fail;
49 if (f2->fd == f->fd) f2->fd = -1; /* avoid closing in fclose */
e5f14be3 50#ifdef __wasilibc_unmodified_upstream // WASI has no dup
320054e8
DG
51 else if (__dup3(f2->fd, f->fd, fl&O_CLOEXEC)<0) goto fail2;
52#else
53 // WASI doesn't have dup3, but does have a way to renumber
54 // an existing file descriptor.
55 else {
56 if (__wasilibc_fd_renumber(f2->fd, f->fd)<0) goto fail2;
57 f2->fd = -1; /* avoid closing in fclose */
58 }
59#endif
60
61 f->flags = (f->flags & F_PERM) | f2->flags;
62 f->read = f2->read;
63 f->write = f2->write;
64 f->seek = f2->seek;
65 f->close = f2->close;
66
67 fclose(f2);
68 }
69
70 FUNLOCK(f);
71 return f;
72
73fail2:
74 fclose(f2);
75fail:
76 fclose(f);
77 return NULL;
78}
79
80weak_alias(freopen, freopen64);