diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 09d82b8a6181..467d3e3565f1 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -589,6 +589,80 @@ pub fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*: return syscall3(.execve, @intFromPtr(path), @intFromPtr(argv), @intFromPtr(envp)); } +pub const clone_args = extern struct { + /// Flag bit mask + flags: packed struct(u64) { + __reserverd0: u8 = 0, + VM: bool = false, + FS: bool = false, + FILES: bool = false, + SIGHAND: bool = false, + PIDFD: bool = false, + PTRACE: bool = false, + VFORK: bool = false, + PARENT: bool = false, + THREAD: bool = false, + NEWNS: bool = false, + SYSVSEM: bool = false, + SETTLS: bool = false, + PARENT_SETTID: bool = false, + CHILD_CLEARTID: bool = false, + DETACHED: bool = false, + UNTRACED: bool = false, + CHILD_SETTID: bool = false, + NEWCGROUP: bool = false, + NEWUTS: bool = false, + NEWIPC: bool = false, + NEWUSER: bool = false, + NEWPID: bool = false, + NEWNET: bool = false, + IO: bool = false, + CLEAR_SIGHAND: bool = false, + INTO_CGROUP: bool = false, + __reseved1: u30 = 0, + } = .{}, + + /// Where to store PID file descriptor + /// (int *) + pidfd: u64 = 0, + + /// Where to store child TID in child's memory + /// (pid_t *) + child_tid: u64 = 0, + + /// Where to store child TID in parent's memory + /// (pid_t *) + parent_tid: u64 = 0, + + /// Signal to deliver to parent on child termination + exit_signal: u64 = SIG.CHLD, + + /// Pointer to lowest byte of stack + stack: u64 = 0, + + /// Size of stack + stack_size: u64 = 0, + + /// Location of new TLS + tls: u64 = 0, + + /// Pointer to a pid_t array + /// (since linux 5.5) + set_tid: u64 = 0, + + /// Number of elements in set_tid + /// (since linux 5.5) + set_tid_size: u64 = 0, + + /// File descriptor for target cgroup of child + /// (since linux 5.7) + cgroup: u64 = 0, +}; + +pub fn clone3(cl_args: clone_args) usize { + return syscall2(.clone3, @intFromPtr(&cl_args), @sizeOf(@TypeOf(cl_args))); +} + pub fn fork() usize { if (comptime native_arch.isSPARC()) { return syscall_fork(); diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 94d63cf9ef85..f5ee99f60f63 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -77,6 +77,7 @@ pub const IOV_MAX = system.IOV_MAX; pub const IPPROTO = system.IPPROTO; pub const KERN = system.KERN; pub const Kevent = system.Kevent; +pub const clone_args = system.clone_args; pub const MADV = system.MADV; pub const MAP = system.MAP; pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN; @@ -4691,6 +4692,34 @@ pub fn mprotect(memory: []align(mem.page_size) u8, protection: u32) MProtectErro } } +pub const Clone3Error = error{ + AccessDenied, + SystemResources, + Invalid, + PidAlreadyExists, + OutOfMemory, + OperationNotSupported, + OutOfUserNamespaces, +} || UnexpectedError; + +pub fn clone3(cl_args: system.clone_args) Clone3Error!pid_t { + const rc = system.clone3(cl_args); + return switch (errno(rc)) { + .SUCCESS => @intCast(rc), + .ACCES => error.AccessDenied, + .AGAIN => error.SystemResources, + .BUSY => error.Invalid, + .EXIST => error.PidAlreadyExists, + .INVAL => error.Invalid, + .NOMEM => error.OutOfMemory, + .NOSPC => error.SystemResources, + .OPNOTSUPP => error.OperationNotSupported, + .PERM => error.AccessDenied, + .USERS => error.OutOfUserNamespaces, + else => |err| unexpectedErrno(err), + }; +} + pub const ForkError = error{SystemResources} || UnexpectedError; pub fn fork() ForkError!pid_t {