diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-16 18:48:16 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-18 21:53:15 +0100 |
| commit | 266c81322e4e7b6c0b7f0a7fe9873b092aef7f54 (patch) | |
| tree | 5f55c05f4f426e86a3aaca4f467df1438ca1c580 /lib | |
| parent | e35c8a2fd6bb0eb16b45e76a39f4602f1161f357 (diff) | |
| download | zig-266c81322e4e7b6c0b7f0a7fe9873b092aef7f54.tar.gz zig-266c81322e4e7b6c0b7f0a7fe9873b092aef7f54.zip | |
darwin: resurrect posix_spawn wrappers
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/c/darwin.zig | 369 |
1 files changed, 298 insertions, 71 deletions
diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig index 75267cc171..ef31bc6d53 100644 --- a/lib/std/c/darwin.zig +++ b/lib/std/c/darwin.zig @@ -203,47 +203,6 @@ pub extern "c" fn mach_timebase_info(tinfo: ?*mach_timebase_info_data) kern_retu pub extern "c" fn malloc_size(?*const anyopaque) usize; pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int; -pub const posix_spawnattr_t = *opaque {}; -pub const posix_spawn_file_actions_t = *opaque {}; -pub extern "c" fn posix_spawnattr_init(attr: *posix_spawnattr_t) c_int; -pub extern "c" fn posix_spawnattr_destroy(attr: *posix_spawnattr_t) c_int; -pub extern "c" fn posix_spawnattr_setflags(attr: *posix_spawnattr_t, flags: c_short) c_int; -pub extern "c" fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *c_short) c_int; -pub extern "c" fn posix_spawn_file_actions_init(actions: *posix_spawn_file_actions_t) c_int; -pub extern "c" fn posix_spawn_file_actions_destroy(actions: *posix_spawn_file_actions_t) c_int; -pub extern "c" fn posix_spawn_file_actions_addclose(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int; -pub extern "c" fn posix_spawn_file_actions_addopen( - actions: *posix_spawn_file_actions_t, - filedes: fd_t, - path: [*:0]const u8, - oflag: c_int, - mode: mode_t, -) c_int; -pub extern "c" fn posix_spawn_file_actions_adddup2( - actions: *posix_spawn_file_actions_t, - filedes: fd_t, - newfiledes: fd_t, -) c_int; -pub extern "c" fn posix_spawn_file_actions_addinherit_np(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int; -pub extern "c" fn posix_spawn_file_actions_addchdir_np(actions: *posix_spawn_file_actions_t, path: [*:0]const u8) c_int; -pub extern "c" fn posix_spawn_file_actions_addfchdir_np(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int; -pub extern "c" fn posix_spawn( - pid: *pid_t, - path: [*:0]const u8, - actions: ?*const posix_spawn_file_actions_t, - attr: ?*const posix_spawnattr_t, - argv: [*:null]?[*:0]const u8, - env: [*:null]?[*:0]const u8, -) c_int; -pub extern "c" fn posix_spawnp( - pid: *pid_t, - path: [*:0]const u8, - actions: ?*const posix_spawn_file_actions_t, - attr: ?*const posix_spawnattr_t, - argv: [*:null]?[*:0]const u8, - env: [*:null]?[*:0]const u8, -) c_int; - pub extern "c" fn kevent64( kq: c_int, changelist: [*]const kevent64_s, @@ -2176,18 +2135,6 @@ pub const E = enum(u16) { _, }; -pub fn getKernError(err: kern_return_t) KernE { - return @intToEnum(KernE, @truncate(u32, @intCast(usize, err))); -} - -pub fn unexpectedKernError(err: KernE) std.os.UnexpectedError { - if (std.os.unexpected_error_tracing) { - std.debug.print("unexpected errno: {d}\n", .{@enumToInt(err)}); - std.debug.dumpCurrentStackTrace(null); - } - return error.Unexpected; -} - /// Kernel return values pub const KernE = enum(u32) { SUCCESS = 0, @@ -3063,6 +3010,29 @@ pub const CPUFAMILY = enum(u32) { _, }; +pub const PT = struct { + pub const TRACE_ME = 0; + pub const READ_I = 1; + pub const READ_D = 2; + pub const READ_U = 3; + pub const WRITE_I = 4; + pub const WRITE_D = 5; + pub const WRITE_U = 6; + pub const CONTINUE = 7; + pub const KILL = 8; + pub const STEP = 9; + pub const DETACH = 11; + pub const SIGEXC = 12; + pub const THUPDATE = 13; + pub const ATTACHEXC = 14; + pub const FORCEQUOTA = 30; + pub const DENY_ATTACH = 31; +}; + +pub const caddr_t = ?[*]u8; + +pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int; + pub const POSIX_SPAWN_RESETIDS = 0x0001; pub const POSIX_SPAWN_SETPGROUP = 0x0002; pub const POSIX_SPAWN_SETSIGDEF = 0x0004; @@ -3074,26 +3044,283 @@ pub const POSIX_SPAWN_SETSID = 0x0400; pub const _POSIX_SPAWN_RESLIDE = 0x0800; pub const POSIX_SPAWN_CLOEXEC_DEFAULT = 0x4000; -pub const PT_TRACE_ME = 0; -pub const PT_READ_I = 1; -pub const PT_READ_D = 2; -pub const PT_READ_U = 3; -pub const PT_WRITE_I = 4; -pub const PT_WRITE_D = 5; -pub const PT_WRITE_U = 6; -pub const PT_CONTINUE = 7; -pub const PT_KILL = 8; -pub const PT_STEP = 9; -pub const PT_DETACH = 11; -pub const PT_SIGEXC = 12; -pub const PT_THUPDATE = 13; -pub const PT_ATTACHEXC = 14; -pub const PT_FORCEQUOTA = 30; -pub const PT_DENY_ATTACH = 31; +pub const posix_spawnattr_t = *opaque {}; +pub const posix_spawn_file_actions_t = *opaque {}; +pub extern "c" fn posix_spawnattr_init(attr: *posix_spawnattr_t) c_int; +pub extern "c" fn posix_spawnattr_destroy(attr: *posix_spawnattr_t) c_int; +pub extern "c" fn posix_spawnattr_setflags(attr: *posix_spawnattr_t, flags: c_short) c_int; +pub extern "c" fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *c_short) c_int; +pub extern "c" fn posix_spawn_file_actions_init(actions: *posix_spawn_file_actions_t) c_int; +pub extern "c" fn posix_spawn_file_actions_destroy(actions: *posix_spawn_file_actions_t) c_int; +pub extern "c" fn posix_spawn_file_actions_addclose(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int; +pub extern "c" fn posix_spawn_file_actions_addopen( + actions: *posix_spawn_file_actions_t, + filedes: fd_t, + path: [*:0]const u8, + oflag: c_int, + mode: mode_t, +) c_int; +pub extern "c" fn posix_spawn_file_actions_adddup2( + actions: *posix_spawn_file_actions_t, + filedes: fd_t, + newfiledes: fd_t, +) c_int; +pub extern "c" fn posix_spawn_file_actions_addinherit_np(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int; +pub extern "c" fn posix_spawn_file_actions_addchdir_np(actions: *posix_spawn_file_actions_t, path: [*:0]const u8) c_int; +pub extern "c" fn posix_spawn_file_actions_addfchdir_np(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int; +pub extern "c" fn posix_spawn( + pid: *pid_t, + path: [*:0]const u8, + actions: ?*const posix_spawn_file_actions_t, + attr: ?*const posix_spawnattr_t, + argv: [*:null]?[*:0]const u8, + env: [*:null]?[*:0]const u8, +) c_int; +pub extern "c" fn posix_spawnp( + pid: *pid_t, + path: [*:0]const u8, + actions: ?*const posix_spawn_file_actions_t, + attr: ?*const posix_spawnattr_t, + argv: [*:null]?[*:0]const u8, + env: [*:null]?[*:0]const u8, +) c_int; + +pub const PosixSpawn = struct { + const errno = std.os.errno; + const unexpectedErrno = std.os.unexpectedErrno; + + pub const Error = error{ + SystemResources, + InvalidFileDescriptor, + NameTooLong, + TooBig, + PermissionDenied, + InputOutput, + FileSystem, + FileNotFound, + InvalidExe, + NotDir, + FileBusy, + /// Returned when the child fails to execute either in the pre-exec() initialization step, or + /// when exec(3) is invoked. + ChildExecFailed, + } || std.os.UnexpectedError; + + pub const Attr = struct { + attr: posix_spawnattr_t, + + pub fn init() Error!Attr { + var attr: posix_spawnattr_t = undefined; + switch (errno(posix_spawnattr_init(&attr))) { + .SUCCESS => return Attr{ .attr = attr }, + .NOMEM => return error.SystemResources, + .INVAL => unreachable, + else => |err| return unexpectedErrno(err), + } + } -pub const caddr_t = ?[*]u8; + pub fn deinit(self: *Attr) void { + defer self.* = undefined; + switch (errno(posix_spawnattr_destroy(&self.attr))) { + .SUCCESS => return, + .INVAL => unreachable, // Invalid parameters. + else => unreachable, + } + } -pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int; + pub fn get(self: Attr) Error!u16 { + var flags: c_short = undefined; + switch (errno(posix_spawnattr_getflags(&self.attr, &flags))) { + .SUCCESS => return @bitCast(u16, flags), + .INVAL => unreachable, + else => |err| return unexpectedErrno(err), + } + } + + pub fn set(self: *Attr, flags: u16) Error!void { + switch (errno(posix_spawnattr_setflags(&self.attr, @bitCast(c_short, flags)))) { + .SUCCESS => return, + .INVAL => unreachable, + else => |err| return unexpectedErrno(err), + } + } + }; + + pub const Actions = struct { + actions: posix_spawn_file_actions_t, + + pub fn init() Error!Actions { + var actions: posix_spawn_file_actions_t = undefined; + switch (errno(posix_spawn_file_actions_init(&actions))) { + .SUCCESS => return Actions{ .actions = actions }, + .NOMEM => return error.SystemResources, + .INVAL => unreachable, + else => |err| return unexpectedErrno(err), + } + } + + pub fn deinit(self: *Actions) void { + defer self.* = undefined; + switch (errno(posix_spawn_file_actions_destroy(&self.actions))) { + .SUCCESS => return, + .INVAL => unreachable, // Invalid parameters. + else => unreachable, + } + } + + pub fn open(self: *Actions, fd: fd_t, path: []const u8, flags: u32, mode: mode_t) Error!void { + const posix_path = try std.os.toPosixPath(path); + return self.openZ(fd, &posix_path, flags, mode); + } + + pub fn openZ(self: *Actions, fd: fd_t, path: [*:0]const u8, flags: u32, mode: mode_t) Error!void { + switch (errno(posix_spawn_file_actions_addopen(&self.actions, fd, path, @bitCast(c_int, flags), mode))) { + .SUCCESS => return, + .BADF => return error.InvalidFileDescriptor, + .NOMEM => return error.SystemResources, + .NAMETOOLONG => return error.NameTooLong, + .INVAL => unreachable, // the value of file actions is invalid + else => |err| return unexpectedErrno(err), + } + } + + pub fn close(self: *Actions, fd: fd_t) Error!void { + switch (errno(posix_spawn_file_actions_addclose(&self.actions, fd))) { + .SUCCESS => return, + .BADF => return error.InvalidFileDescriptor, + .NOMEM => return error.SystemResources, + .INVAL => unreachable, // the value of file actions is invalid + .NAMETOOLONG => unreachable, + else => |err| return unexpectedErrno(err), + } + } + + pub fn dup2(self: *Actions, fd: fd_t, newfd: fd_t) Error!void { + switch (errno(posix_spawn_file_actions_adddup2(&self.actions, fd, newfd))) { + .SUCCESS => return, + .BADF => return error.InvalidFileDescriptor, + .NOMEM => return error.SystemResources, + .INVAL => unreachable, // the value of file actions is invalid + .NAMETOOLONG => unreachable, + else => |err| return unexpectedErrno(err), + } + } + + pub fn inherit(self: *Actions, fd: fd_t) Error!void { + switch (errno(posix_spawn_file_actions_addinherit_np(&self.actions, fd))) { + .SUCCESS => return, + .BADF => return error.InvalidFileDescriptor, + .NOMEM => return error.SystemResources, + .INVAL => unreachable, // the value of file actions is invalid + .NAMETOOLONG => unreachable, + else => |err| return unexpectedErrno(err), + } + } + + pub fn chdir(self: *Actions, path: []const u8) Error!void { + const posix_path = try std.os.toPosixPath(path); + return self.chdirZ(&posix_path); + } + + pub fn chdirZ(self: *Actions, path: [*:0]const u8) Error!void { + switch (errno(posix_spawn_file_actions_addchdir_np(&self.actions, path))) { + .SUCCESS => return, + .NOMEM => return error.SystemResources, + .NAMETOOLONG => return error.NameTooLong, + .BADF => unreachable, + .INVAL => unreachable, // the value of file actions is invalid + else => |err| return unexpectedErrno(err), + } + } + + pub fn fchdir(self: *Actions, fd: fd_t) Error!void { + switch (errno(posix_spawn_file_actions_addfchdir_np(&self.actions, fd))) { + .SUCCESS => return, + .BADF => return error.InvalidFileDescriptor, + .NOMEM => return error.SystemResources, + .INVAL => unreachable, // the value of file actions is invalid + .NAMETOOLONG => unreachable, + else => |err| return unexpectedErrno(err), + } + } + }; + + pub fn spawn( + path: []const u8, + actions: ?Actions, + attr: ?Attr, + argv: [*:null]?[*:0]const u8, + envp: [*:null]?[*:0]const u8, + ) Error!pid_t { + const posix_path = try std.os.toPosixPath(path); + return spawnZ(&posix_path, actions, attr, argv, envp); + } + + pub fn spawnZ( + path: [*:0]const u8, + actions: ?Actions, + attr: ?Attr, + argv: [*:null]?[*:0]const u8, + envp: [*:null]?[*:0]const u8, + ) Error!pid_t { + var pid: pid_t = undefined; + switch (errno(posix_spawn( + &pid, + path, + if (actions) |a| &a.actions else null, + if (attr) |a| &a.attr else null, + argv, + envp, + ))) { + .SUCCESS => return pid, + .@"2BIG" => return error.TooBig, + .NOMEM => return error.SystemResources, + .BADF => return error.InvalidFileDescriptor, + .ACCES => return error.PermissionDenied, + .IO => return error.InputOutput, + .LOOP => return error.FileSystem, + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOEXEC => return error.InvalidExe, + .NOTDIR => return error.NotDir, + .TXTBSY => return error.FileBusy, + .BADARCH => return error.InvalidExe, + .BADEXEC => return error.InvalidExe, + .FAULT => unreachable, + .INVAL => unreachable, + else => |err| return unexpectedErrno(err), + } + } + + pub fn waitpid(pid: pid_t, flags: u32) Error!std.os.WaitPidResult { + var status: c_int = undefined; + while (true) { + const rc = waitpid(pid, &status, @intCast(c_int, flags)); + switch (errno(rc)) { + .SUCCESS => return std.os.WaitPidResult{ + .pid = @intCast(pid_t, rc), + .status = @bitCast(u32, status), + }, + .INTR => continue, + .CHILD => return error.ChildExecFailed, + .INVAL => unreachable, // Invalid flags. + else => unreachable, + } + } + } +}; + +pub fn getKernError(err: kern_return_t) KernE { + return @intToEnum(KernE, @truncate(u32, @intCast(usize, err))); +} + +pub fn unexpectedKernError(err: KernE) std.os.UnexpectedError { + if (std.os.unexpected_error_tracing) { + std.debug.print("unexpected errno: {d}\n", .{@enumToInt(err)}); + std.debug.dumpCurrentStackTrace(null); + } + return error.Unexpected; +} pub const MachError = error{ /// Not enough permissions held to perform the requested kernel |
