authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-10-17 20:17:27-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-21 10:04:01-07:00
log07ea1c97ee891ea259020fe28fba317c20c3b03a
tree9b75c8b6e8f34729d412d4c0c64de786318bc077
parented136f830665c38af3d0d4beb1177584cb6d40d7

process: fix bsd `spawn`


3 files changed, 111 insertions(+), 70 deletions(-)

lib/std/Io/Threaded.zig+79-54
...@@ -7191,9 +7191,9 @@ fn realPathPosix(fd: posix.fd_t, out_buffer: []u8) File.RealPathError!usize {...@@ -7191,9 +7191,9 @@ fn realPathPosix(fd: posix.fd_t, out_buffer: []u8) File.RealPathError!usize {
7191 return n;7191 return n;
7192 },7192 },
7193 .linux, .serenity, .illumos => {7193 .linux, .serenity, .illumos => {
7194 var procfs_buf: ["/proc/self/path/-2147483648\x00".len]u8 = undefined;7194 var proc_buf: [std.fmt.count("/proc/self/path/{d}\x00", .{std.math.minInt(posix.fd_t)})]u8 = undefined;
7195 const template = if (native_os == .illumos) "/proc/self/path/{d}" else "/proc/self/fd/{d}";7195 const template = if (native_os == .illumos) "/proc/self/path/{d}" else "/proc/self/fd/{d}";
7196 const proc_path = std.mem.printSentinel(&procfs_buf, template, .{fd}, 0) catch unreachable;7196 const proc_path = std.mem.printSentinel(&proc_buf, template, .{fd}, 0) catch unreachable;
7197 const syscall: Syscall = try .start();7197 const syscall: Syscall = try .start();
7198 while (true) {7198 while (true) {
7199 const rc = posix.system.readlink(proc_path, out_buffer.ptr, out_buffer.len);7199 const rc = posix.system.readlink(proc_path, out_buffer.ptr, out_buffer.len);
...@@ -7266,27 +7266,32 @@ fn fileHardLink(...@@ -7266,27 +7266,32 @@ fn fileHardLink(
7266 new_sub_path: []const u8,7266 new_sub_path: []const u8,
7267 options: File.HardLinkOptions,7267 options: File.HardLinkOptions,
7268) File.HardLinkError!void {7268) File.HardLinkError!void {
7269 _ = userdata;7269 const t: *Threaded = @ptrCast(@alignCast(userdata));
7270 if (native_os != .linux) return error.OperationUnsupported;7270 _ = t;
72717271
7272 var new_path_buffer: [posix.PATH_MAX]u8 = undefined;7272 var new_path_buffer: [posix.PATH_MAX]u8 = undefined;
7273 const new_sub_path_posix = try pathToPosix(new_sub_path, &new_path_buffer);7273 const new_sub_path_posix = try pathToPosix(new_sub_path, &new_path_buffer);
72747274
7275 const flags: u32 = if (options.follow_symlinks)7275 switch (native_os) {
7276 posix.AT.SYMLINK_FOLLOW | posix.AT.EMPTY_PATH7276 else => return error.OperationUnsupported,
7277 else7277 .freebsd, .linux => {
7278 posix.AT.EMPTY_PATH;7278 const flags: u32 = if (options.follow_symlinks)
7279 posix.AT.SYMLINK_FOLLOW | posix.AT.EMPTY_PATH
7280 else
7281 posix.AT.EMPTY_PATH;
72797282
7280 return linkat(file.handle, "", new_dir.handle, new_sub_path_posix, flags) catch |err| switch (err) {7283 return linkat(file.handle, "", new_dir.handle, new_sub_path_posix, flags) catch |err| switch (err) {
7281 error.FileNotFound => {7284 error.FileNotFound => {},
7282 if (options.follow_symlinks) return error.FileNotFound;7285 else => |e| return e,
7283 var proc_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined;7286 };
7284 const proc_path = std.mem.printSentinel(&proc_buf, "/proc/self/fd/{d}", .{file.handle}, 0) catch
7285 unreachable;
7286 return linkat(posix.AT.FDCWD, proc_path, new_dir.handle, new_sub_path_posix, posix.AT.SYMLINK_FOLLOW);
7287 },7287 },
7288 else => |e| return e,7288 .netbsd, .openbsd => {},
7289 };7289 }
7290
7291 if (options.follow_symlinks) return error.FileNotFound;
7292 var dev_buf: [std.fmt.count("/dev/fd/{d}\x00", .{std.math.minInt(posix.fd_t)})]u8 = undefined;
7293 const dev_path = std.mem.printSentinel(&dev_buf, "/dev/fd/{d}", .{file.handle}, 0) catch unreachable;
7294 return linkat(posix.AT.FDCWD, dev_path, new_dir.handle, new_sub_path_posix, posix.AT.SYMLINK_FOLLOW);
7290}7295}
72917296
7292fn linkat(7297fn linkat(
...@@ -8732,12 +8737,12 @@ fn fchmodatFallback(...@@ -8732,12 +8737,12 @@ fn fchmodatFallback(
8732) Dir.SetFilePermissionsError!void {8737) Dir.SetFilePermissionsError!void {
8733 comptime assert(native_os == .linux);8738 comptime assert(native_os == .linux);
87348739
8735 // Fallback to changing permissions using procfs:8740 // Fallback to changing permissions using devfs:
8736 //8741 //
8737 // 1. Open `path` as a `PATH` descriptor.8742 // 1. Open `path` as a `PATH` descriptor.
8738 // 2. Stat the fd and check if it isn't a symbolic link.8743 // 2. Stat the fd and check if it isn't a symbolic link.
8739 // 3. Generate the procfs reference to the fd via `/proc/self/fd/{fd}`.8744 // 3. Generate the devfs reference to the fd via `/dev/fd/{fd}`.
8740 // 4. Pass the procfs path to `chmod` with the `mode`.8745 // 4. Pass the devfs path to `chmod` with the `mode`.
8741 const path_fd: posix.fd_t = fd: {8746 const path_fd: posix.fd_t = fd: {
8742 const syscall: Syscall = try .start();8747 const syscall: Syscall = try .start();
8743 while (true) {8748 while (true) {
...@@ -8808,11 +8813,11 @@ fn fchmodatFallback(...@@ -8808,11 +8813,11 @@ fn fchmodatFallback(
8808 if ((path_mode & posix.S.IFMT) == posix.S.IFLNK)8813 if ((path_mode & posix.S.IFMT) == posix.S.IFLNK)
8809 return error.OperationUnsupported;8814 return error.OperationUnsupported;
88108815
8811 var procfs_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined;8816 var dev_buf: [std.fmt.count("/dev/fd/{d}\x00", .{std.math.minInt(posix.fd_t)})]u8 = undefined;
8812 const proc_path = std.mem.printSentinel(&procfs_buf, "/proc/self/fd/{d}", .{path_fd}, 0) catch unreachable;8817 const dev_path = std.mem.printSentinel(&dev_buf, "/dev/fd/{d}", .{path_fd}, 0) catch unreachable;
8813 const syscall: Syscall = try .start();8818 const syscall: Syscall = try .start();
8814 while (true) {8819 while (true) {
8815 switch (posix.errno(posix.system.chmod(proc_path, mode))) {8820 switch (posix.errno(posix.system.chmod(dev_path, mode))) {
8816 .SUCCESS => return syscall.finish(),8821 .SUCCESS => return syscall.finish(),
8817 .INTR => {8822 .INTR => {
8818 try syscall.checkCancel();8823 try syscall.checkCancel();
...@@ -8821,7 +8826,7 @@ fn fchmodatFallback(...@@ -8821,7 +8826,7 @@ fn fchmodatFallback(
8821 else => |e| {8826 else => |e| {
8822 syscall.finish();8827 syscall.finish();
8823 switch (e) {8828 switch (e) {
8824 .NOENT => return error.OperationUnsupported, // procfs not mounted.8829 .NOENT => return error.OperationUnsupported, // devfs not mounted.
8825 .BADF => |err| return errnoBug(err),8830 .BADF => |err| return errnoBug(err),
8826 .FAULT => |err| return errnoBug(err),8831 .FAULT => |err| return errnoBug(err),
8827 .INVAL => |err| return errnoBug(err),8832 .INVAL => |err| return errnoBug(err),
...@@ -17446,9 +17451,6 @@ pub fn posixExecveat(...@@ -17446,9 +17451,6 @@ pub fn posixExecveat(
17446) process.ReplaceError {17451) process.ReplaceError {
17447 try Thread.checkCancel();17452 try Thread.checkCancel();
17448 switch (err: {17453 switch (err: {
17449 if (path) |p| if (dir == posix.AT.FDCWD or Dir.path.isAbsoluteZ(p)) {
17450 break :err posix.errno(posix.system.execve(p, argv, env_block.slice.ptr));
17451 };
17452 if (comptime native_os == .linux and (!builtin.link_libc or17454 if (comptime native_os == .linux and (!builtin.link_libc or
17453 (builtin.target.isGnuLibC() and builtin.target.os.version_range.linux.glibc.order(17455 (builtin.target.isGnuLibC() and builtin.target.os.version_range.linux.glibc.order(
17454 .{ .major = 2, .minor = 34, .patch = 0 },17456 .{ .major = 2, .minor = 34, .patch = 0 },
...@@ -17462,34 +17464,57 @@ pub fn posixExecveat(...@@ -17462,34 +17464,57 @@ pub fn posixExecveat(
17462 .NOSYS => {},17464 .NOSYS => {},
17463 }17465 }
17464 }17466 }
17465 var path_buffer: [posix.PATH_MAX]u8 = undefined;17467 if (path) |p| if (dir == posix.AT.FDCWD or Dir.path.isAbsoluteZ(p)) {
17466 var path_len = realPathPosix(dir, &path_buffer) catch |err| switch (err) {17468 break :err posix.errno(posix.system.execve(p, argv, env_block.slice.ptr));
17467 else => |e| return e,
17468 error.InputOutput,
17469 error.FileTooBig,
17470 error.NoSpaceLeft,
17471 error.PathAlreadyExists,
17472 error.SymLinkLoop,
17473 error.NetworkNotFound,
17474 error.PipeBusy,
17475 error.AntivirusInterference,
17476 => return error.FileNotFound,
17477 error.DeviceBusy,
17478 error.NoDevice,
17479 error.UnrecognizedVolume,
17480 => return error.FileSystem,
17481 };17469 };
17482 if (path) |p| {17470 const exe: posix.fd_t = if (path) |p| exe: {
17483 const path_slice = std.mem.span(p);17471 var flags: posix.O = .{};
17484 path_buffer[path_len] = Dir.path.sep;17472 if (@hasField(posix.O, "CLOEXEC")) flags.CLOEXEC = true;
17485 path_len += 1;17473 if (@hasField(posix.O, "LARGEFILE")) flags.LARGEFILE = true;
17486 @memcpy(path_buffer[path_len..][0..path_slice.len], path_slice);17474 if (@hasField(posix.O, "NOCTTY")) flags.NOCTTY = true;
17487 path_len += path_slice.len;17475 if (@hasField(posix.O, "PATH")) flags.PATH = true;
17488 }17476 if (@hasField(posix.O, "EXEC")) flags.EXEC = true;
17489 path_buffer[path_len] = 0;17477 const rc = openat_sym(dir, p, flags, @as(posix.mode_t, 0));
17490 break :err posix.errno(17478 while (true) switch (posix.errno(rc)) {
17491 posix.system.execve(path_buffer[0..path_len :0], argv, env_block.slice.ptr),17479 .SUCCESS => break :exe @intCast(rc),
17492 );17480 .INTR, .AGAIN => {},
17481 .FAULT => |err| return errnoBug(err),
17482 .INVAL => return error.BadPathName,
17483 .BADF => |err| return errnoBug(err), // File descriptor used after closed.
17484 .ACCES => return error.AccessDenied,
17485 .FBIG => return error.InvalidExe,
17486 .OVERFLOW => return error.InvalidExe,
17487 .ISDIR => return error.IsDir,
17488 .LOOP => return error.InvalidExe,
17489 .MFILE => return error.ProcessFdQuotaExceeded,
17490 .NAMETOOLONG => return error.NameTooLong,
17491 .NFILE => return error.SystemFdQuotaExceeded,
17492 .NODEV => return error.FileSystem,
17493 .NOENT => return error.FileNotFound,
17494 .SRCH => return error.FileNotFound, // Linux when opening procfs files.
17495 .NOMEM => return error.SystemResources,
17496 .NOTDIR => return error.NotDir,
17497 .PERM => return error.PermissionDenied,
17498 .BUSY => return error.FileSystem,
17499 .TXTBSY => return error.FileBusy,
17500 .NXIO => return error.FileSystem,
17501 .ILSEQ => return error.BadPathName,
17502 else => |err| return posix.unexpectedErrno(err),
17503 };
17504 } else dir;
17505 defer closeFd(exe);
17506 if (builtin.link_libc and @TypeOf(posix.system.fexecve) != void) {
17507 break :err posix.errno(posix.system.fexecve(exe, argv, env_block.slice.ptr));
17508 }
17509 switch (native_os) {
17510 else => return error.OperationUnsupported,
17511 .linux, .serenity, .illumos => {
17512 var proc_buf: [std.fmt.count("/proc/self/path/{d}\x00", .{std.math.minInt(posix.fd_t)})]u8 = undefined;
17513 const template = if (native_os == .illumos) "/proc/self/path/{d}" else "/proc/self/fd/{d}";
17514 const proc_path = std.mem.printSentinel(&proc_buf, template, .{exe}, 0) catch unreachable;
17515 break :err posix.errno(posix.system.execve(proc_path, argv, env_block.slice.ptr));
17516 },
17517 }
17493 }) {17518 }) {
17494 .FAULT => |err| return errnoBug(err), // Bad pointer parameter.17519 .FAULT => |err| return errnoBug(err), // Bad pointer parameter.
17495 .@"2BIG" => return error.SystemResources,17520 .@"2BIG" => return error.SystemResources,
lib/std/c.zig+26-11
...@@ -8387,6 +8387,8 @@ pub const AT = switch (native_os) {...@@ -8387,6 +8387,8 @@ pub const AT = switch (native_os) {
8387 /// to determine the target of relative file paths in the openat() and8387 /// to determine the target of relative file paths in the openat() and
8388 /// similar syscalls.8388 /// similar syscalls.
8389 pub const FDCWD = -100;8389 pub const FDCWD = -100;
8390 /// Fail rename if target exists
8391 pub const RENAME_NOREPLACE = 0x0001;
8390 /// Check access using effective user and group ID8392 /// Check access using effective user and group ID
8391 pub const EACCESS = 0x0100;8393 pub const EACCESS = 0x0100;
8392 /// Do not follow symbolic links8394 /// Do not follow symbolic links
...@@ -8397,6 +8399,10 @@ pub const AT = switch (native_os) {...@@ -8397,6 +8399,10 @@ pub const AT = switch (native_os) {
8397 pub const REMOVEDIR = 0x0800;8399 pub const REMOVEDIR = 0x0800;
8398 /// Fail if not under dirfd8400 /// Fail if not under dirfd
8399 pub const BENEATH = 0x1000;8401 pub const BENEATH = 0x1000;
8402 /// Do not allow name resolution to walk out of dirfd
8403 pub const RESOLVE_BENEATH = 0x2000;
8404 /// Operate on dirfd if path is empty
8405 pub const EMPTY_PATH = 0x4000;
8400 },8406 },
8401 .netbsd => struct {8407 .netbsd => struct {
8402 /// Magic value that specify the use of the current working directory8408 /// Magic value that specify the use of the current working directory
...@@ -8552,7 +8558,11 @@ pub const O = switch (native_os) {...@@ -8552,7 +8558,11 @@ pub const O = switch (native_os) {
8552 DIRECTORY: bool = false,8558 DIRECTORY: bool = false,
8553 CLOEXEC: bool = false,8559 CLOEXEC: bool = false,
8554 SEARCH: bool = false,8560 SEARCH: bool = false,
8555 _: u8 = 0,8561 NOSIGPIPE: bool = false,
8562 REGULAR: bool = false,
8563 EXEC: bool = false,
8564 CLOFORK: bool = false,
8565 _: u4 = 0,
8556 },8566 },
8557 .openbsd => packed struct(u32) {8567 .openbsd => packed struct(u32) {
8558 ACCMODE: std.posix.ACCMODE = .RDONLY,8568 ACCMODE: std.posix.ACCMODE = .RDONLY,
...@@ -10937,9 +10947,13 @@ pub extern "c" fn mkdirat(dirfd: fd_t, path: [*:0]const u8, mode: mode_t) c_int;...@@ -10937,9 +10947,13 @@ pub extern "c" fn mkdirat(dirfd: fd_t, path: [*:0]const u8, mode: mode_t) c_int;
10937pub extern "c" fn symlink(existing: [*:0]const u8, new: [*:0]const u8) c_int;10947pub extern "c" fn symlink(existing: [*:0]const u8, new: [*:0]const u8) c_int;
10938pub extern "c" fn symlinkat(oldpath: [*:0]const u8, newdirfd: fd_t, newpath: [*:0]const u8) c_int;10948pub extern "c" fn symlinkat(oldpath: [*:0]const u8, newdirfd: fd_t, newpath: [*:0]const u8) c_int;
10939pub extern "c" fn rename(old: [*:0]const u8, new: [*:0]const u8) c_int;10949pub extern "c" fn rename(old: [*:0]const u8, new: [*:0]const u8) c_int;
10940pub extern "c" fn renameat(olddirfd: fd_t, old: [*:0]const u8, newdirfd: fd_t, new: [*:0]const u8) c_int;10950pub extern "c" fn renameat(olddirfd: fd_t, oldpath: [*:0]const u8, newdirfd: fd_t, newpath: [*:0]const u8) c_int;
10941pub extern "c" fn chdir(path: [*:0]const u8) c_int;10951pub extern "c" fn chdir(path: [*:0]const u8) c_int;
10942pub extern "c" fn fchdir(fd: fd_t) c_int;10952pub extern "c" fn fchdir(fd: fd_t) c_int;
10953pub const fexecve = switch (native_os) {
10954 else => {},
10955 .freebsd, .linux, .netbsd => private.fexecve,
10956};
10943pub extern "c" fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) c_int;10957pub extern "c" fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) c_int;
10944pub extern "c" fn execveat(dirfd: fd_t, path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8, flags: EXECVEAT) c_int;10958pub extern "c" fn execveat(dirfd: fd_t, path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8, flags: EXECVEAT) c_int;
10945pub extern "c" fn dup(fd: fd_t) c_int;10959pub extern "c" fn dup(fd: fd_t) c_int;
...@@ -11791,34 +11805,35 @@ pub const setkeymap = serenity.setkeymap;...@@ -11791,34 +11805,35 @@ pub const setkeymap = serenity.setkeymap;
1179111805
11792/// External definitions shared by two or more operating systems.11806/// External definitions shared by two or more operating systems.
11793const private = struct {11807const private = struct {
11794 pub extern "c" fn strdup(s: [*:0]const c_char) ?[*:0]c_char;11808 extern "c" fn strdup(s: [*:0]const c_char) ?[*:0]c_char;
11795 pub extern "c" fn _strdup(s: [*:0]const c_char) ?[*:0]c_char;11809 extern "c" fn _strdup(s: [*:0]const c_char) ?[*:0]c_char;
11796 pub extern "c" fn wcsdup(s: [*:0]const wchar_t) ?[*:0]wchar_t;11810 extern "c" fn wcsdup(s: [*:0]const wchar_t) ?[*:0]wchar_t;
11797 pub extern "c" fn _wcsdup(s: [*:0]const wchar_t) ?[*:0]wchar_t;11811 extern "c" fn _wcsdup(s: [*:0]const wchar_t) ?[*:0]wchar_t;
1179811812
11799 pub extern "c" fn swab(noalias from: *const anyopaque, noalias to: *anyopaque, n: isize) void;11813 extern "c" fn swab(noalias from: *const anyopaque, noalias to: *anyopaque, n: isize) void;
11800 pub extern "c" fn _swab(noalias from: *const anyopaque, noalias to: *anyopaque, n: isize) void;11814 extern "c" fn _swab(noalias from: *const anyopaque, noalias to: *anyopaque, n: isize) void;
1180111815
11802 extern "c" fn close(fd: fd_t) c_int;
11803 extern "c" fn clock_getres(clk_id: clockid_t, tp: *timespec) c_int;11816 extern "c" fn clock_getres(clk_id: clockid_t, tp: *timespec) c_int;
11804 extern "c" fn clock_gettime(clk_id: clockid_t, tp: *timespec) c_int;11817 extern "c" fn clock_gettime(clk_id: clockid_t, tp: *timespec) c_int;
11818 extern "c" fn clock_nanosleep(clockid: clockid_t, flags: TIMER, t: *const timespec, remain: ?*timespec) c_int;
11819 extern "c" fn close(fd: fd_t) c_int;
11805 extern "c" fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, len: usize, flags: c_uint) isize;11820 extern "c" fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, len: usize, flags: c_uint) isize;
11821 extern "c" fn fexecve(fd: fd_t, argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) c_int;
11806 extern "c" fn flock(fd: fd_t, operation: c_int) c_int;11822 extern "c" fn flock(fd: fd_t, operation: c_int) c_int;
11807 extern "c" fn fork() c_int;11823 extern "c" fn fork() c_int;
11808 extern "c" fn fstat(fd: fd_t, buf: *Stat) c_int;11824 extern "c" fn fstat(fd: fd_t, buf: *Stat) c_int;
11809 extern "c" fn fstatat(dirfd: fd_t, path: [*:0]const u8, buf: *Stat, flag: u32) c_int;11825 extern "c" fn fstatat(dirfd: fd_t, path: [*:0]const u8, buf: *Stat, flag: u32) c_int;
11810 extern "c" fn getdirentries(fd: fd_t, buf_ptr: [*]u8, nbytes: usize, basep: *i64) isize;11826 extern "c" fn getdirentries(fd: fd_t, buf_ptr: [*]u8, nbytes: usize, basep: *i64) isize;
11811 extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) switch (native_os) {11827 extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) switch (native_os) {
11828 else => c_int,
11812 .freebsd => isize,11829 .freebsd => isize,
11813 .illumos => usize,11830 .illumos => usize,
11814 else => c_int,
11815 };11831 };
11816 extern "c" fn getrusage(who: c_int, usage: *rusage) c_int;11832 extern "c" fn getrusage(who: c_int, usage: *rusage) c_int;
11817 extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;11833 extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;
11818 extern "c" fn ioctl(fd: fd_t, request: c_int, ...) c_int;11834 extern "c" fn ioctl(fd: fd_t, request: c_int, ...) c_int;
11819 extern "c" fn msync(addr: *align(page_size) const anyopaque, len: usize, flags: c_int) c_int;11835 extern "c" fn msync(addr: *align(page_size) const anyopaque, len: usize, flags: c_int) c_int;
11820 extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int;11836 extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int;
11821 extern "c" fn clock_nanosleep(clockid: clockid_t, flags: TIMER, t: *const timespec, remain: ?*timespec) c_int;
11822 extern "c" fn pipe2(fds: *[2]fd_t, flags: O) c_int;11837 extern "c" fn pipe2(fds: *[2]fd_t, flags: O) c_int;
11823 extern "c" fn readdir(dir: *DIR) ?*dirent;11838 extern "c" fn readdir(dir: *DIR) ?*dirent;
11824 extern "c" fn realpath(noalias file_name: [*:0]const u8, noalias resolved_name: [*]u8) ?[*:0]u8;11839 extern "c" fn realpath(noalias file_name: [*:0]const u8, noalias resolved_name: [*]u8) ?[*:0]u8;
test/src/Runner.zig+6-5
...@@ -822,7 +822,7 @@ fn handleCommand(...@@ -822,7 +822,7 @@ fn handleCommand(
822 .pic = pic,822 .pic = pic,
823 };823 };
824 }) catch |err| switch (err) {824 }) catch |err| switch (err) {
825 error.Canceled, error.OutOfMemory, error.AlreadyReported => |e| return e,825 error.Canceled, error.OutOfMemory, error.AlreadyReported, error.SkipTest => |e| return e,
826 error.ReadFailed => return error.ContentsReadFailed,826 error.ReadFailed => return error.ContentsReadFailed,
827 },827 },
828 .write => {828 .write => {
...@@ -1006,7 +1006,7 @@ fn spawnCompiler(...@@ -1006,7 +1006,7 @@ fn spawnCompiler(
1006 output_mode: std.lang.OutputMode,1006 output_mode: std.lang.OutputMode,
1007 args_r: *std.Io.Reader,1007 args_r: *std.Io.Reader,
1008 target: Compiler.Target,1008 target: Compiler.Target,
1009) (std.Io.Reader.ShortError || FailError)!void {1009) (std.Io.Reader.ShortError || TestError)!void {
1010 const gpa = runner.gpa;1010 const gpa = runner.gpa;
1011 const arena = runner.arena.allocator();1011 const arena = runner.arena.allocator();
1012 if (compiler.*) |*comp| {1012 if (compiler.*) |*comp| {
...@@ -1118,6 +1118,7 @@ fn spawnCompiler(...@@ -1118,6 +1118,7 @@ fn spawnCompiler(
1118 .stderr = .pipe,1118 .stderr = .pipe,
1119 }) catch |err| switch (err) {1119 }) catch |err| switch (err) {
1120 error.Canceled, error.OutOfMemory => |e| return e,1120 error.Canceled, error.OutOfMemory => |e| return e,
1121 error.OperationUnsupported => return error.SkipTest,
1121 else => |e| return runner.fail("unable to spawn compiler: {t}", .{e}),1122 else => |e| return runner.fail("unable to spawn compiler: {t}", .{e}),
1122 };1123 };
1123 compiler.* = .{1124 compiler.* = .{
...@@ -1222,7 +1223,7 @@ const Compiler = struct {...@@ -1222,7 +1223,7 @@ const Compiler = struct {
1222 expected: []const u8,1223 expected: []const u8,
1223 src_dir: std.Io.Dir,1224 src_dir: std.Io.Dir,
1224 digest: *const std.Build.Cache.BinDigest,1225 digest: *const std.Build.Cache.BinDigest,
1225 ) FailError!void {1226 ) TestError!void {
1226 const runner = comp.runner;1227 const runner = comp.runner;
1227 const gpa = runner.gpa;1228 const gpa = runner.gpa;
1228 const arena = runner.arena.allocator();1229 const arena = runner.arena.allocator();
...@@ -1560,7 +1561,7 @@ const Compiler = struct {...@@ -1560,7 +1561,7 @@ const Compiler = struct {
1560 }1561 }
1561 }1562 }
15621563
1563 fn compileC(parent_comp: *Compiler, src_dir: std.Io.Dir, c_path: []const u8) FailError![]const u8 {1564 fn compileC(parent_comp: *Compiler, src_dir: std.Io.Dir, c_path: []const u8) TestError![]const u8 {
1564 const runner = parent_comp.runner;1565 const runner = parent_comp.runner;
1565 const arena = runner.arena.allocator();1566 const arena = runner.arena.allocator();
1566 var compiler: ?Compiler = null;1567 var compiler: ?Compiler = null;
...@@ -1577,7 +1578,7 @@ const Compiler = struct {...@@ -1577,7 +1578,7 @@ const Compiler = struct {
1577 .linker = .lld,1578 .linker = .lld,
1578 .pic = parent_comp.target.pic,1579 .pic = parent_comp.target.pic,
1579 }) catch |err| switch (err) {1580 }) catch |err| switch (err) {
1580 error.Canceled, error.OutOfMemory, error.AlreadyReported => |e| return e,1581 error.Canceled, error.OutOfMemory, error.AlreadyReported, error.SkipTest => |e| return e,
1581 error.ReadFailed => unreachable, // .fixed1582 error.ReadFailed => unreachable, // .fixed
1582 };1583 };
1583 const comp = &compiler.?;1584 const comp = &compiler.?;