| author | |
| committer | |
| log | ff612334fa8af05c42b71f784dff521899026f97 |
| tree | cc89f0c97619c35f704842d5913a4b435fd23d24 |
| parent | 6e987a1d04e5d9eb41a10110a5343384f0a9a57b |
This commit adds `dup2` and `dup3` based on musl. Zig already has
wrappers for the syscalls, but musl's implementation checks for a rare,
temporary race condition with dup2/3 and `open`. Like musl, this
implementation adds a fallback for dup3 if the syscall isn't available.
Contributes to: #309784 files changed, 27 insertions(+), 48 deletions(-)
lib/c/unistd.zig+27| ... | ... | @@ -21,6 +21,8 @@ comptime { |
| 21 | 21 | symbol(&chrootLinux, "chroot"); |
| 22 | 22 | symbol(&ctermidLinux, "ctermid"); |
| 23 | 23 | symbol(&dupLinux, "dup"); |
| 24 | symbol(&dup2Linux, "dup2"); | |
| 25 | symbol(&dup3Linux, "dup3"); | |
| 24 | 26 | |
| 25 | 27 | symbol(&getegidLinux, "getegid"); |
| 26 | 28 | symbol(&geteuidLinux, "geteuid"); |
| ... | ... | @@ -101,6 +103,31 @@ fn dupLinux(fd: c_int) callconv(.c) c_int { |
| 101 | 103 | return errno(linux.dup(fd)); |
| 102 | 104 | } |
| 103 | 105 | |
| 106 | fn dup2Linux(old: c_int, new: c_int) callconv(.c) c_int { | |
| 107 | const busy: usize = @bitCast(-@as(isize, @intFromEnum(linux.E.BUSY))); | |
| 108 | var res = busy; | |
| 109 | while (res == busy) res = linux.dup2(old, new); | |
| 110 | return errno(res); | |
| 111 | } | |
| 112 | ||
| 113 | fn dup3Linux(old: c_int, new: c_int, flags: c_int) callconv(.c) c_int { | |
| 114 | const busy: usize = @bitCast(-@as(isize, @intFromEnum(linux.E.BUSY))); | |
| 115 | var res = busy; | |
| 116 | ||
| 117 | if (@hasField(linux.SYS, "dup3")) { | |
| 118 | while (res == busy) res = linux.dup3(old, new, @intCast(flags)); | |
| 119 | } else if (@hasField(linux.SYS, "dup2")) { | |
| 120 | const cloexec: c_int = @bitCast(linux.O{ .CLOEXEC = true }); | |
| 121 | const inval: usize = @bitCast(-@as(isize, @intFromEnum(linux.E.INVAL))); | |
| 122 | if (old == new or (flags & ~cloexec != 0)) return errno(inval); | |
| 123 | while (res == busy) res = linux.dup2(old, new); | |
| 124 | _ = if (res >= 0 and (flags & cloexec == cloexec)) linux.fcntl(new, linux.F.SETFD, linux.FD_CLOEXEC); | |
| 125 | } else { | |
| 126 | return errno(@bitCast(-@as(isize, @intFromEnum(linux.E.NOSYS)))); | |
| 127 | } | |
| 128 | return errno(res); | |
| 129 | } | |
| 130 | ||
| 104 | 131 | fn getegidLinux() callconv(.c) linux.gid_t { |
| 105 | 132 | return linux.getegid(); |
| 106 | 133 | } |
lib/libc/musl/src/unistd/dup2.c deleted-20| ... | ... | @@ -1,20 +0,0 @@ |
| 1 | #include <unistd.h> | |
| 2 | #include <errno.h> | |
| 3 | #include <fcntl.h> | |
| 4 | #include "syscall.h" | |
| 5 | ||
| 6 | int dup2(int old, int new) | |
| 7 | { | |
| 8 | 	int r; | |
| 9 | #ifdef SYS_dup2 | |
| 10 | 	while ((r=__syscall(SYS_dup2, old, new))==-EBUSY); | |
| 11 | #else | |
| 12 | 	if (old==new) { | |
| 13 | 		r = __syscall(SYS_fcntl, old, F_GETFD); | |
| 14 | 		if (r >= 0) return old; | |
| 15 | 	} else { | |
| 16 | 		while ((r=__syscall(SYS_dup3, old, new, 0))==-EBUSY); | |
| 17 | 	} | |
| 18 | #endif | |
| 19 | 	return __syscall_ret(r); | |
| 20 | } |
lib/libc/musl/src/unistd/dup3.c deleted-26| ... | ... | @@ -1,26 +0,0 @@ |
| 1 | #define _GNU_SOURCE | |
| 2 | #include <unistd.h> | |
| 3 | #include <errno.h> | |
| 4 | #include <fcntl.h> | |
| 5 | #include "syscall.h" | |
| 6 | ||
| 7 | int __dup3(int old, int new, int flags) | |
| 8 | { | |
| 9 | 	int r; | |
| 10 | #ifdef SYS_dup2 | |
| 11 | 	if (old==new) return __syscall_ret(-EINVAL); | |
| 12 | 	if (flags) { | |
| 13 | 		while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY); | |
| 14 | 		if (r!=-ENOSYS) return __syscall_ret(r); | |
| 15 | 		if (flags & ~O_CLOEXEC) return __syscall_ret(-EINVAL); | |
| 16 | 	} | |
| 17 | 	while ((r=__syscall(SYS_dup2, old, new))==-EBUSY); | |
| 18 | 	if (r >= 0 && (flags & O_CLOEXEC)) | |
| 19 | 		__syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC); | |
| 20 | #else | |
| 21 | 	while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY); | |
| 22 | #endif | |
| 23 | 	return __syscall_ret(r); | |
| 24 | } | |
| 25 | ||
| 26 | weak_alias(__dup3, dup3); |
src/libs/musl.zig-2| ... | ... | @@ -1758,8 +1758,6 @@ const src_files = [_][]const u8{ |
| 1758 | 1758 | "musl/src/time/wcsftime.c", |
| 1759 | 1759 | "musl/src/time/__year_to_secs.c", |
| 1760 | 1760 | "musl/src/unistd/alarm.c", |
| 1761 | "musl/src/unistd/dup2.c", | |
| 1762 | "musl/src/unistd/dup3.c", | |
| 1763 | 1761 | "musl/src/unistd/faccessat.c", |
| 1764 | 1762 | "musl/src/unistd/fchdir.c", |
| 1765 | 1763 | "musl/src/unistd/fchown.c", |