authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-16 18:48:16+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-18 21:53:15+01:00
log266c81322e4e7b6c0b7f0a7fe9873b092aef7f54
tree5f55c05f4f426e86a3aaca4f467df1438ca1c580
parente35c8a2fd6bb0eb16b45e76a39f4602f1161f357

darwin: resurrect posix_spawn wrappers


1 files changed, 298 insertions(+), 71 deletions(-)

lib/std/c/darwin.zig+298-71
...@@ -203,47 +203,6 @@ pub extern "c" fn mach_timebase_info(tinfo: ?*mach_timebase_info_data) kern_retu...@@ -203,47 +203,6 @@ pub extern "c" fn mach_timebase_info(tinfo: ?*mach_timebase_info_data) kern_retu
203pub extern "c" fn malloc_size(?*const anyopaque) usize;203pub extern "c" fn malloc_size(?*const anyopaque) usize;
204pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int;204pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int;
205205
206pub const posix_spawnattr_t = *opaque {};
207pub const posix_spawn_file_actions_t = *opaque {};
208pub extern "c" fn posix_spawnattr_init(attr: *posix_spawnattr_t) c_int;
209pub extern "c" fn posix_spawnattr_destroy(attr: *posix_spawnattr_t) c_int;
210pub extern "c" fn posix_spawnattr_setflags(attr: *posix_spawnattr_t, flags: c_short) c_int;
211pub extern "c" fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *c_short) c_int;
212pub extern "c" fn posix_spawn_file_actions_init(actions: *posix_spawn_file_actions_t) c_int;
213pub extern "c" fn posix_spawn_file_actions_destroy(actions: *posix_spawn_file_actions_t) c_int;
214pub extern "c" fn posix_spawn_file_actions_addclose(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int;
215pub extern "c" fn posix_spawn_file_actions_addopen(
216 actions: *posix_spawn_file_actions_t,
217 filedes: fd_t,
218 path: [*:0]const u8,
219 oflag: c_int,
220 mode: mode_t,
221) c_int;
222pub extern "c" fn posix_spawn_file_actions_adddup2(
223 actions: *posix_spawn_file_actions_t,
224 filedes: fd_t,
225 newfiledes: fd_t,
226) c_int;
227pub extern "c" fn posix_spawn_file_actions_addinherit_np(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int;
228pub extern "c" fn posix_spawn_file_actions_addchdir_np(actions: *posix_spawn_file_actions_t, path: [*:0]const u8) c_int;
229pub extern "c" fn posix_spawn_file_actions_addfchdir_np(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int;
230pub extern "c" fn posix_spawn(
231 pid: *pid_t,
232 path: [*:0]const u8,
233 actions: ?*const posix_spawn_file_actions_t,
234 attr: ?*const posix_spawnattr_t,
235 argv: [*:null]?[*:0]const u8,
236 env: [*:null]?[*:0]const u8,
237) c_int;
238pub extern "c" fn posix_spawnp(
239 pid: *pid_t,
240 path: [*:0]const u8,
241 actions: ?*const posix_spawn_file_actions_t,
242 attr: ?*const posix_spawnattr_t,
243 argv: [*:null]?[*:0]const u8,
244 env: [*:null]?[*:0]const u8,
245) c_int;
246
247pub extern "c" fn kevent64(206pub extern "c" fn kevent64(
248 kq: c_int,207 kq: c_int,
249 changelist: [*]const kevent64_s,208 changelist: [*]const kevent64_s,
...@@ -2176,18 +2135,6 @@ pub const E = enum(u16) {...@@ -2176,18 +2135,6 @@ pub const E = enum(u16) {
2176 _,2135 _,
2177};2136};
21782137
2179pub fn getKernError(err: kern_return_t) KernE {
2180 return @intToEnum(KernE, @truncate(u32, @intCast(usize, err)));
2181}
2182
2183pub fn unexpectedKernError(err: KernE) std.os.UnexpectedError {
2184 if (std.os.unexpected_error_tracing) {
2185 std.debug.print("unexpected errno: {d}\n", .{@enumToInt(err)});
2186 std.debug.dumpCurrentStackTrace(null);
2187 }
2188 return error.Unexpected;
2189}
2190
2191/// Kernel return values2138/// Kernel return values
2192pub const KernE = enum(u32) {2139pub const KernE = enum(u32) {
2193 SUCCESS = 0,2140 SUCCESS = 0,
...@@ -3063,6 +3010,29 @@ pub const CPUFAMILY = enum(u32) {...@@ -3063,6 +3010,29 @@ pub const CPUFAMILY = enum(u32) {
3063 _,3010 _,
3064};3011};
30653012
3013pub const PT = struct {
3014 pub const TRACE_ME = 0;
3015 pub const READ_I = 1;
3016 pub const READ_D = 2;
3017 pub const READ_U = 3;
3018 pub const WRITE_I = 4;
3019 pub const WRITE_D = 5;
3020 pub const WRITE_U = 6;
3021 pub const CONTINUE = 7;
3022 pub const KILL = 8;
3023 pub const STEP = 9;
3024 pub const DETACH = 11;
3025 pub const SIGEXC = 12;
3026 pub const THUPDATE = 13;
3027 pub const ATTACHEXC = 14;
3028 pub const FORCEQUOTA = 30;
3029 pub const DENY_ATTACH = 31;
3030};
3031
3032pub const caddr_t = ?[*]u8;
3033
3034pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int;
3035
3066pub const POSIX_SPAWN_RESETIDS = 0x0001;3036pub const POSIX_SPAWN_RESETIDS = 0x0001;
3067pub const POSIX_SPAWN_SETPGROUP = 0x0002;3037pub const POSIX_SPAWN_SETPGROUP = 0x0002;
3068pub const POSIX_SPAWN_SETSIGDEF = 0x0004;3038pub const POSIX_SPAWN_SETSIGDEF = 0x0004;
...@@ -3074,26 +3044,283 @@ pub const POSIX_SPAWN_SETSID = 0x0400;...@@ -3074,26 +3044,283 @@ pub const POSIX_SPAWN_SETSID = 0x0400;
3074pub const _POSIX_SPAWN_RESLIDE = 0x0800;3044pub const _POSIX_SPAWN_RESLIDE = 0x0800;
3075pub const POSIX_SPAWN_CLOEXEC_DEFAULT = 0x4000;3045pub const POSIX_SPAWN_CLOEXEC_DEFAULT = 0x4000;
30763046
3077pub const PT_TRACE_ME = 0;3047pub const posix_spawnattr_t = *opaque {};
3078pub const PT_READ_I = 1;3048pub const posix_spawn_file_actions_t = *opaque {};
3079pub const PT_READ_D = 2;3049pub extern "c" fn posix_spawnattr_init(attr: *posix_spawnattr_t) c_int;
3080pub const PT_READ_U = 3;3050pub extern "c" fn posix_spawnattr_destroy(attr: *posix_spawnattr_t) c_int;
3081pub const PT_WRITE_I = 4;3051pub extern "c" fn posix_spawnattr_setflags(attr: *posix_spawnattr_t, flags: c_short) c_int;
3082pub const PT_WRITE_D = 5;3052pub extern "c" fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *c_short) c_int;
3083pub const PT_WRITE_U = 6;3053pub extern "c" fn posix_spawn_file_actions_init(actions: *posix_spawn_file_actions_t) c_int;
3084pub const PT_CONTINUE = 7;3054pub extern "c" fn posix_spawn_file_actions_destroy(actions: *posix_spawn_file_actions_t) c_int;
3085pub const PT_KILL = 8;3055pub extern "c" fn posix_spawn_file_actions_addclose(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int;
3086pub const PT_STEP = 9;3056pub extern "c" fn posix_spawn_file_actions_addopen(
3087pub const PT_DETACH = 11;3057 actions: *posix_spawn_file_actions_t,
3088pub const PT_SIGEXC = 12;3058 filedes: fd_t,
3089pub const PT_THUPDATE = 13;3059 path: [*:0]const u8,
3090pub const PT_ATTACHEXC = 14;3060 oflag: c_int,
3091pub const PT_FORCEQUOTA = 30;3061 mode: mode_t,
3092pub const PT_DENY_ATTACH = 31;3062) c_int;
3063pub extern "c" fn posix_spawn_file_actions_adddup2(
3064 actions: *posix_spawn_file_actions_t,
3065 filedes: fd_t,
3066 newfiledes: fd_t,
3067) c_int;
3068pub extern "c" fn posix_spawn_file_actions_addinherit_np(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int;
3069pub extern "c" fn posix_spawn_file_actions_addchdir_np(actions: *posix_spawn_file_actions_t, path: [*:0]const u8) c_int;
3070pub extern "c" fn posix_spawn_file_actions_addfchdir_np(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int;
3071pub extern "c" fn posix_spawn(
3072 pid: *pid_t,
3073 path: [*:0]const u8,
3074 actions: ?*const posix_spawn_file_actions_t,
3075 attr: ?*const posix_spawnattr_t,
3076 argv: [*:null]?[*:0]const u8,
3077 env: [*:null]?[*:0]const u8,
3078) c_int;
3079pub extern "c" fn posix_spawnp(
3080 pid: *pid_t,
3081 path: [*:0]const u8,
3082 actions: ?*const posix_spawn_file_actions_t,
3083 attr: ?*const posix_spawnattr_t,
3084 argv: [*:null]?[*:0]const u8,
3085 env: [*:null]?[*:0]const u8,
3086) c_int;
3087
3088pub const PosixSpawn = struct {
3089 const errno = std.os.errno;
3090 const unexpectedErrno = std.os.unexpectedErrno;
3091
3092 pub const Error = error{
3093 SystemResources,
3094 InvalidFileDescriptor,
3095 NameTooLong,
3096 TooBig,
3097 PermissionDenied,
3098 InputOutput,
3099 FileSystem,
3100 FileNotFound,
3101 InvalidExe,
3102 NotDir,
3103 FileBusy,
3104 /// Returned when the child fails to execute either in the pre-exec() initialization step, or
3105 /// when exec(3) is invoked.
3106 ChildExecFailed,
3107 } || std.os.UnexpectedError;
3108
3109 pub const Attr = struct {
3110 attr: posix_spawnattr_t,
3111
3112 pub fn init() Error!Attr {
3113 var attr: posix_spawnattr_t = undefined;
3114 switch (errno(posix_spawnattr_init(&attr))) {
3115 .SUCCESS => return Attr{ .attr = attr },
3116 .NOMEM => return error.SystemResources,
3117 .INVAL => unreachable,
3118 else => |err| return unexpectedErrno(err),
3119 }
3120 }
30933121
3094pub const caddr_t = ?[*]u8;3122 pub fn deinit(self: *Attr) void {
3123 defer self.* = undefined;
3124 switch (errno(posix_spawnattr_destroy(&self.attr))) {
3125 .SUCCESS => return,
3126 .INVAL => unreachable, // Invalid parameters.
3127 else => unreachable,
3128 }
3129 }
30953130
3096pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int;3131 pub fn get(self: Attr) Error!u16 {
3132 var flags: c_short = undefined;
3133 switch (errno(posix_spawnattr_getflags(&self.attr, &flags))) {
3134 .SUCCESS => return @bitCast(u16, flags),
3135 .INVAL => unreachable,
3136 else => |err| return unexpectedErrno(err),
3137 }
3138 }
3139
3140 pub fn set(self: *Attr, flags: u16) Error!void {
3141 switch (errno(posix_spawnattr_setflags(&self.attr, @bitCast(c_short, flags)))) {
3142 .SUCCESS => return,
3143 .INVAL => unreachable,
3144 else => |err| return unexpectedErrno(err),
3145 }
3146 }
3147 };
3148
3149 pub const Actions = struct {
3150 actions: posix_spawn_file_actions_t,
3151
3152 pub fn init() Error!Actions {
3153 var actions: posix_spawn_file_actions_t = undefined;
3154 switch (errno(posix_spawn_file_actions_init(&actions))) {
3155 .SUCCESS => return Actions{ .actions = actions },
3156 .NOMEM => return error.SystemResources,
3157 .INVAL => unreachable,
3158 else => |err| return unexpectedErrno(err),
3159 }
3160 }
3161
3162 pub fn deinit(self: *Actions) void {
3163 defer self.* = undefined;
3164 switch (errno(posix_spawn_file_actions_destroy(&self.actions))) {
3165 .SUCCESS => return,
3166 .INVAL => unreachable, // Invalid parameters.
3167 else => unreachable,
3168 }
3169 }
3170
3171 pub fn open(self: *Actions, fd: fd_t, path: []const u8, flags: u32, mode: mode_t) Error!void {
3172 const posix_path = try std.os.toPosixPath(path);
3173 return self.openZ(fd, &posix_path, flags, mode);
3174 }
3175
3176 pub fn openZ(self: *Actions, fd: fd_t, path: [*:0]const u8, flags: u32, mode: mode_t) Error!void {
3177 switch (errno(posix_spawn_file_actions_addopen(&self.actions, fd, path, @bitCast(c_int, flags), mode))) {
3178 .SUCCESS => return,
3179 .BADF => return error.InvalidFileDescriptor,
3180 .NOMEM => return error.SystemResources,
3181 .NAMETOOLONG => return error.NameTooLong,
3182 .INVAL => unreachable, // the value of file actions is invalid
3183 else => |err| return unexpectedErrno(err),
3184 }
3185 }
3186
3187 pub fn close(self: *Actions, fd: fd_t) Error!void {
3188 switch (errno(posix_spawn_file_actions_addclose(&self.actions, fd))) {
3189 .SUCCESS => return,
3190 .BADF => return error.InvalidFileDescriptor,
3191 .NOMEM => return error.SystemResources,
3192 .INVAL => unreachable, // the value of file actions is invalid
3193 .NAMETOOLONG => unreachable,
3194 else => |err| return unexpectedErrno(err),
3195 }
3196 }
3197
3198 pub fn dup2(self: *Actions, fd: fd_t, newfd: fd_t) Error!void {
3199 switch (errno(posix_spawn_file_actions_adddup2(&self.actions, fd, newfd))) {
3200 .SUCCESS => return,
3201 .BADF => return error.InvalidFileDescriptor,
3202 .NOMEM => return error.SystemResources,
3203 .INVAL => unreachable, // the value of file actions is invalid
3204 .NAMETOOLONG => unreachable,
3205 else => |err| return unexpectedErrno(err),
3206 }
3207 }
3208
3209 pub fn inherit(self: *Actions, fd: fd_t) Error!void {
3210 switch (errno(posix_spawn_file_actions_addinherit_np(&self.actions, fd))) {
3211 .SUCCESS => return,
3212 .BADF => return error.InvalidFileDescriptor,
3213 .NOMEM => return error.SystemResources,
3214 .INVAL => unreachable, // the value of file actions is invalid
3215 .NAMETOOLONG => unreachable,
3216 else => |err| return unexpectedErrno(err),
3217 }
3218 }
3219
3220 pub fn chdir(self: *Actions, path: []const u8) Error!void {
3221 const posix_path = try std.os.toPosixPath(path);
3222 return self.chdirZ(&posix_path);
3223 }
3224
3225 pub fn chdirZ(self: *Actions, path: [*:0]const u8) Error!void {
3226 switch (errno(posix_spawn_file_actions_addchdir_np(&self.actions, path))) {
3227 .SUCCESS => return,
3228 .NOMEM => return error.SystemResources,
3229 .NAMETOOLONG => return error.NameTooLong,
3230 .BADF => unreachable,
3231 .INVAL => unreachable, // the value of file actions is invalid
3232 else => |err| return unexpectedErrno(err),
3233 }
3234 }
3235
3236 pub fn fchdir(self: *Actions, fd: fd_t) Error!void {
3237 switch (errno(posix_spawn_file_actions_addfchdir_np(&self.actions, fd))) {
3238 .SUCCESS => return,
3239 .BADF => return error.InvalidFileDescriptor,
3240 .NOMEM => return error.SystemResources,
3241 .INVAL => unreachable, // the value of file actions is invalid
3242 .NAMETOOLONG => unreachable,
3243 else => |err| return unexpectedErrno(err),
3244 }
3245 }
3246 };
3247
3248 pub fn spawn(
3249 path: []const u8,
3250 actions: ?Actions,
3251 attr: ?Attr,
3252 argv: [*:null]?[*:0]const u8,
3253 envp: [*:null]?[*:0]const u8,
3254 ) Error!pid_t {
3255 const posix_path = try std.os.toPosixPath(path);
3256 return spawnZ(&posix_path, actions, attr, argv, envp);
3257 }
3258
3259 pub fn spawnZ(
3260 path: [*:0]const u8,
3261 actions: ?Actions,
3262 attr: ?Attr,
3263 argv: [*:null]?[*:0]const u8,
3264 envp: [*:null]?[*:0]const u8,
3265 ) Error!pid_t {
3266 var pid: pid_t = undefined;
3267 switch (errno(posix_spawn(
3268 &pid,
3269 path,
3270 if (actions) |a| &a.actions else null,
3271 if (attr) |a| &a.attr else null,
3272 argv,
3273 envp,
3274 ))) {
3275 .SUCCESS => return pid,
3276 .@"2BIG" => return error.TooBig,
3277 .NOMEM => return error.SystemResources,
3278 .BADF => return error.InvalidFileDescriptor,
3279 .ACCES => return error.PermissionDenied,
3280 .IO => return error.InputOutput,
3281 .LOOP => return error.FileSystem,
3282 .NAMETOOLONG => return error.NameTooLong,
3283 .NOENT => return error.FileNotFound,
3284 .NOEXEC => return error.InvalidExe,
3285 .NOTDIR => return error.NotDir,
3286 .TXTBSY => return error.FileBusy,
3287 .BADARCH => return error.InvalidExe,
3288 .BADEXEC => return error.InvalidExe,
3289 .FAULT => unreachable,
3290 .INVAL => unreachable,
3291 else => |err| return unexpectedErrno(err),
3292 }
3293 }
3294
3295 pub fn waitpid(pid: pid_t, flags: u32) Error!std.os.WaitPidResult {
3296 var status: c_int = undefined;
3297 while (true) {
3298 const rc = waitpid(pid, &status, @intCast(c_int, flags));
3299 switch (errno(rc)) {
3300 .SUCCESS => return std.os.WaitPidResult{
3301 .pid = @intCast(pid_t, rc),
3302 .status = @bitCast(u32, status),
3303 },
3304 .INTR => continue,
3305 .CHILD => return error.ChildExecFailed,
3306 .INVAL => unreachable, // Invalid flags.
3307 else => unreachable,
3308 }
3309 }
3310 }
3311};
3312
3313pub fn getKernError(err: kern_return_t) KernE {
3314 return @intToEnum(KernE, @truncate(u32, @intCast(usize, err)));
3315}
3316
3317pub fn unexpectedKernError(err: KernE) std.os.UnexpectedError {
3318 if (std.os.unexpected_error_tracing) {
3319 std.debug.print("unexpected errno: {d}\n", .{@enumToInt(err)});
3320 std.debug.dumpCurrentStackTrace(null);
3321 }
3322 return error.Unexpected;
3323}
30973324
3098pub const MachError = error{3325pub const MachError = error{
3099 /// Not enough permissions held to perform the requested kernel3326 /// Not enough permissions held to perform the requested kernel