]> git.proxmox.com Git - wasi-libc.git/blob - libc-top-half/musl/src/stdio/freopen.c
Format changes to musl code to fit musl's style.
[wasi-libc.git] / libc-top-half / musl / src / stdio / freopen.c
1 #ifdef __wasilibc_unmodified_upstream // WASI has no syscall, dup
2 #include "stdio_impl.h"
3 #else
4 #include <wasi/libc.h>
5 #endif
6 #include <fcntl.h>
7 #include <unistd.h>
8 #ifdef __wasilibc_unmodified_upstream // WASI has no syscall, dup
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
23 FILE *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)
34 #ifdef __wasilibc_unmodified_upstream // WASI has no syscall
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);
40 #ifdef __wasilibc_unmodified_upstream // WASI has no syscall
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 */
50 #ifdef __wasilibc_unmodified_upstream // WASI has no dup
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
73 fail2:
74 fclose(f2);
75 fail:
76 fclose(f);
77 return NULL;
78 }
79
80 weak_alias(freopen, freopen64);