| 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 | 	f->mode = 0; |
| 71 | 	f->locale = 0; |
| 72 | 	FUNLOCK(f); |
| 73 | 	return f; |
| 74 | |
| 75 | fail2: |
| 76 | 	fclose(f2); |
| 77 | fail: |
| 78 | 	fclose(f); |
| 79 | 	return NULL; |
| 80 | } |
| 81 | |
| 82 | weak_alias(freopen, freopen64); |