mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-05-22 08:54:50 +03:00
libzigc: dup2 and dup3
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: #30978
This commit is contained in:
committed by
Andrew Kelley
parent
6e987a1d04
commit
ff612334fa
@@ -21,6 +21,8 @@ comptime {
|
|||||||
symbol(&chrootLinux, "chroot");
|
symbol(&chrootLinux, "chroot");
|
||||||
symbol(&ctermidLinux, "ctermid");
|
symbol(&ctermidLinux, "ctermid");
|
||||||
symbol(&dupLinux, "dup");
|
symbol(&dupLinux, "dup");
|
||||||
|
symbol(&dup2Linux, "dup2");
|
||||||
|
symbol(&dup3Linux, "dup3");
|
||||||
|
|
||||||
symbol(&getegidLinux, "getegid");
|
symbol(&getegidLinux, "getegid");
|
||||||
symbol(&geteuidLinux, "geteuid");
|
symbol(&geteuidLinux, "geteuid");
|
||||||
@@ -101,6 +103,31 @@ fn dupLinux(fd: c_int) callconv(.c) c_int {
|
|||||||
return errno(linux.dup(fd));
|
return errno(linux.dup(fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dup2Linux(old: c_int, new: c_int) callconv(.c) c_int {
|
||||||
|
const busy: usize = @bitCast(-@as(isize, @intFromEnum(linux.E.BUSY)));
|
||||||
|
var res = busy;
|
||||||
|
while (res == busy) res = linux.dup2(old, new);
|
||||||
|
return errno(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dup3Linux(old: c_int, new: c_int, flags: c_int) callconv(.c) c_int {
|
||||||
|
const busy: usize = @bitCast(-@as(isize, @intFromEnum(linux.E.BUSY)));
|
||||||
|
var res = busy;
|
||||||
|
|
||||||
|
if (@hasField(linux.SYS, "dup3")) {
|
||||||
|
while (res == busy) res = linux.dup3(old, new, @intCast(flags));
|
||||||
|
} else if (@hasField(linux.SYS, "dup2")) {
|
||||||
|
const cloexec: c_int = @bitCast(linux.O{ .CLOEXEC = true });
|
||||||
|
const inval: usize = @bitCast(-@as(isize, @intFromEnum(linux.E.INVAL)));
|
||||||
|
if (old == new or (flags & ~cloexec != 0)) return errno(inval);
|
||||||
|
while (res == busy) res = linux.dup2(old, new);
|
||||||
|
_ = if (res >= 0 and (flags & cloexec == cloexec)) linux.fcntl(new, linux.F.SETFD, linux.FD_CLOEXEC);
|
||||||
|
} else {
|
||||||
|
return errno(@bitCast(-@as(isize, @intFromEnum(linux.E.NOSYS))));
|
||||||
|
}
|
||||||
|
return errno(res);
|
||||||
|
}
|
||||||
|
|
||||||
fn getegidLinux() callconv(.c) linux.gid_t {
|
fn getegidLinux() callconv(.c) linux.gid_t {
|
||||||
return linux.getegid();
|
return linux.getegid();
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
-20
@@ -1,20 +0,0 @@
|
|||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include "syscall.h"
|
|
||||||
|
|
||||||
int dup2(int old, int new)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
#ifdef SYS_dup2
|
|
||||||
while ((r=__syscall(SYS_dup2, old, new))==-EBUSY);
|
|
||||||
#else
|
|
||||||
if (old==new) {
|
|
||||||
r = __syscall(SYS_fcntl, old, F_GETFD);
|
|
||||||
if (r >= 0) return old;
|
|
||||||
} else {
|
|
||||||
while ((r=__syscall(SYS_dup3, old, new, 0))==-EBUSY);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return __syscall_ret(r);
|
|
||||||
}
|
|
||||||
Vendored
-26
@@ -1,26 +0,0 @@
|
|||||||
#define _GNU_SOURCE
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include "syscall.h"
|
|
||||||
|
|
||||||
int __dup3(int old, int new, int flags)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
#ifdef SYS_dup2
|
|
||||||
if (old==new) return __syscall_ret(-EINVAL);
|
|
||||||
if (flags) {
|
|
||||||
while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY);
|
|
||||||
if (r!=-ENOSYS) return __syscall_ret(r);
|
|
||||||
if (flags & ~O_CLOEXEC) return __syscall_ret(-EINVAL);
|
|
||||||
}
|
|
||||||
while ((r=__syscall(SYS_dup2, old, new))==-EBUSY);
|
|
||||||
if (r >= 0 && (flags & O_CLOEXEC))
|
|
||||||
__syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC);
|
|
||||||
#else
|
|
||||||
while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY);
|
|
||||||
#endif
|
|
||||||
return __syscall_ret(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
weak_alias(__dup3, dup3);
|
|
||||||
@@ -1758,8 +1758,6 @@ const src_files = [_][]const u8{
|
|||||||
"musl/src/time/wcsftime.c",
|
"musl/src/time/wcsftime.c",
|
||||||
"musl/src/time/__year_to_secs.c",
|
"musl/src/time/__year_to_secs.c",
|
||||||
"musl/src/unistd/alarm.c",
|
"musl/src/unistd/alarm.c",
|
||||||
"musl/src/unistd/dup2.c",
|
|
||||||
"musl/src/unistd/dup3.c",
|
|
||||||
"musl/src/unistd/faccessat.c",
|
"musl/src/unistd/faccessat.c",
|
||||||
"musl/src/unistd/fchdir.c",
|
"musl/src/unistd/fchdir.c",
|
||||||
"musl/src/unistd/fchown.c",
|
"musl/src/unistd/fchown.c",
|
||||||
|
|||||||
Reference in New Issue
Block a user