commit a8226cd536f50fd14c059812388b87bf99324d51 (tree)
parent 2b48f559f424d8bf790bf54f4bb83d631461a681
Author: Andrew Kelley <andrew@ziglang.org>
Date: Thu, 16 Apr 2026 22:18:58 +0200
Merge pull request 'Haiku fixes' (#31851) from ypsvlq/zig:master into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31851
Reviewed-by: Andrew Kelley <andrew@ziglang.org>
Diffstat:
5 files changed, 133 insertions(+), 12 deletions(-)
diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
@@ -5367,7 +5367,7 @@ fn dirOpenDirHaiku(
.NOMEM => return error.SystemResources,
.NOTDIR => return error.NotDir,
.PERM => return error.PermissionDenied,
- .BUSY => return error.DeviceBusy,
+ .BUSY => |err| return errnoBug(err),
else => |err| return posix.unexpectedErrno(err),
}
},
@@ -5813,10 +5813,119 @@ fn dirReadIllumos(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) D
}
fn dirReadHaiku(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir.Reader.Error!usize {
- _ = userdata;
- _ = dr;
- _ = buffer;
- @panic("TODO implement dirReadHaiku");
+ const t: *Threaded = @ptrCast(@alignCast(userdata));
+ _ = t;
+ var buffer_index: usize = 0;
+ while (buffer.len - buffer_index != 0) {
+ if (dr.end - dr.index == 0) {
+ // Refill the buffer, unless we've already created references to
+ // buffered data.
+ if (buffer_index != 0) break;
+ if (dr.state == .reset) {
+ const syscall: Syscall = try .start();
+ while (true) {
+ const rc = posix.system._kern_rewind_dir(dr.dir.handle);
+ switch (@as(posix.E, @enumFromInt(@min(rc, 0)))) {
+ .SUCCESS => {
+ syscall.finish();
+ break;
+ },
+ .INTR => {
+ try syscall.checkCancel();
+ continue;
+ },
+ else => |e| {
+ syscall.finish();
+ switch (e) {
+ else => |err| return posix.unexpectedErrno(err),
+ }
+ },
+ }
+ }
+ dr.state = .reading;
+ }
+ const syscall: Syscall = try .start();
+ const n: usize = while (true) {
+ const rc = posix.system._kern_read_dir(dr.dir.handle, dr.buffer.ptr, dr.buffer.len, @truncate(dr.buffer.len / @sizeOf(posix.system.DirEnt)));
+ switch (@as(posix.E, @enumFromInt(@min(rc, 0)))) {
+ .SUCCESS => {
+ syscall.finish();
+ break @intCast(rc);
+ },
+ .INTR => {
+ try syscall.checkCancel();
+ continue;
+ },
+ else => |e| {
+ syscall.finish();
+ switch (e) {
+ else => |err| return posix.unexpectedErrno(err),
+ }
+ },
+ }
+ };
+ if (n == 0) {
+ dr.state = .finished;
+ return 0;
+ }
+ dr.index = 0;
+ // _kern_read_dir returns entry count, but Dir.Reader is designed for byte count
+ dr.end = 0;
+ var i: usize = 0;
+ while (i < n) : (i += 1) {
+ const entry = @as(*align(1) posix.system.DirEnt, @ptrCast(&dr.buffer[dr.end]));
+ dr.end += entry.reclen;
+ }
+ }
+ const entry = @as(*align(1) posix.system.DirEnt, @ptrCast(&dr.buffer[dr.index]));
+ const next_index = dr.index + entry.reclen;
+ dr.index = next_index;
+
+ const name = std.mem.sliceTo(@as([*:0]u8, @ptrCast(&entry.name)), 0);
+ if (std.mem.eql(u8, name, ".") or std.mem.eql(u8, name, "..") or entry.ino == 0) continue;
+
+ // haiku dirent doesn't expose type, so we have to call stat to get it.
+ var stat: std.c.Stat = undefined;
+ {
+ const syscall: Syscall = try .start();
+ while (true) {
+ const rc = posix.system._kern_read_stat(dr.dir.handle, name, false, &stat, @sizeOf(std.c.Stat));
+ switch (@as(posix.E, @enumFromInt(@min(rc, 0)))) {
+ .SUCCESS => {
+ syscall.finish();
+ break;
+ },
+ .INTR => {
+ try syscall.checkCancel();
+ continue;
+ },
+ else => |e| {
+ syscall.finish();
+ switch (e) {
+ else => |err| return posix.unexpectedErrno(err),
+ }
+ },
+ }
+ }
+ }
+
+ const entry_kind: File.Kind = switch (stat.mode & posix.S.IFMT) {
+ posix.S.IFBLK => .block_device,
+ posix.S.IFCHR => .character_device,
+ posix.S.IFDIR => .directory,
+ posix.S.IFIFO => .named_pipe,
+ posix.S.IFLNK => .sym_link,
+ posix.S.IFREG => .file,
+ else => .unknown,
+ };
+ buffer[buffer_index] = .{
+ .name = name,
+ .kind = entry_kind,
+ .inode = entry.ino,
+ };
+ buffer_index += 1;
+ }
+ return buffer_index;
}
fn dirReadWindows(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir.Reader.Error!usize {
@@ -9834,7 +9943,10 @@ fn fileReadPositionalPosix(file: File, data: []const []u8, offset: u64) File.Rea
if (have_preadv) {
const syscall: Syscall = try .start();
while (true) {
- const rc = preadv_sym(file.handle, dest.ptr, @intCast(dest.len), @bitCast(offset));
+ const rc = if (native_os == .haiku)
+ posix.system.readv_pos(file.handle, @bitCast(offset), dest.ptr, @intCast(dest.len))
+ else
+ preadv_sym(file.handle, dest.ptr, @intCast(dest.len), @bitCast(offset));
switch (posix.errno(rc)) {
.SUCCESS => {
syscall.finish();
@@ -9868,7 +9980,7 @@ fn fileReadPositionalPosix(file: File, data: []const []u8, offset: u64) File.Rea
const syscall: Syscall = try .start();
while (true) {
- const rc = posix.pread(file.handle, dest[0].ptr, @intCast(dest[0].len), @bitCast(offset));
+ const rc = pread_sym(file.handle, dest[0].base, @intCast(dest[0].len), @bitCast(offset));
switch (posix.errno(rc)) {
.SUCCESS => {
syscall.finish();
@@ -10572,7 +10684,10 @@ fn fileWritePositional(
const syscall: Syscall = try .start();
while (true) {
- const rc = pwritev_sym(file.handle, &iovecs, @intCast(iovlen), @bitCast(offset));
+ const rc = if (native_os == .haiku)
+ posix.system.writev_pos(file.handle, @bitCast(offset), &iovecs, @intCast(iovlen))
+ else
+ pwritev_sym(file.handle, &iovecs, @intCast(iovlen), @bitCast(offset));
switch (posix.errno(rc)) {
.SUCCESS => {
syscall.finish();
@@ -14082,7 +14197,7 @@ pub fn posixSocketModeProtocol(family: posix.sa_family_t, mode: net.Socket.Mode,
.dgram => posix.SOCK.DGRAM,
.seqpacket => posix.SOCK.SEQPACKET,
.raw => posix.SOCK.RAW,
- .rdm => posix.SOCK.RDM,
+ .rdm => if (@hasDecl(posix.SOCK, "RDM")) posix.SOCK.RDM else return error.OptionUnsupported,
},
if (protocol) |p| @intFromEnum(p) else if (is_windows) switch (family) {
posix.AF.UNIX => switch (mode) {
diff --git a/lib/std/c.zig b/lib/std/c.zig
@@ -3260,8 +3260,8 @@ pub const Sigaction = switch (native_os) {
/// signal handler
handler: extern union {
- handler: handler_fn,
- sigaction: sigaction_fn,
+ handler: ?handler_fn,
+ sigaction: ?sigaction_fn,
},
/// signal mask to apply
@@ -11150,6 +11150,8 @@ pub const _kern_open_dir = haiku._kern_open_dir;
pub const _kern_read_dir = haiku._kern_read_dir;
pub const _kern_read_stat = haiku._kern_read_stat;
pub const _kern_rewind_dir = haiku._kern_rewind_dir;
+pub const readv_pos = haiku.readv_pos;
+pub const writev_pos = haiku.writev_pos;
pub const area_id = haiku.area_id;
pub const area_info = haiku.area_info;
pub const directory_which = haiku.directory_which;
diff --git a/lib/std/c/haiku.zig b/lib/std/c/haiku.zig
@@ -6,6 +6,7 @@ const iovec = std.posix.iovec;
const iovec_const = std.posix.iovec_const;
const socklen_t = std.c.socklen_t;
const fd_t = std.c.fd_t;
+const off_t = std.c.off_t;
const PATH_MAX = std.c.PATH_MAX;
const uid_t = std.c.uid_t;
const gid_t = std.c.gid_t;
@@ -28,6 +29,8 @@ pub extern "root" fn _kern_open_dir(fd: fd_t, path: [*:0]const u8) fd_t;
pub extern "root" fn _kern_read_dir(fd: fd_t, buffer: [*]u8, bufferSize: usize, maxCount: u32) isize;
pub extern "root" fn _kern_rewind_dir(fd: fd_t) status_t;
pub extern "root" fn _kern_read_stat(fd: fd_t, path: [*:0]const u8, traverseLink: bool, stat: *std.c.Stat, statSize: usize) status_t;
+pub extern "root" fn readv_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec, count: i32) isize;
+pub extern "root" fn writev_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec_const, count: i32) isize;
pub const area_info = extern struct {
area: u32,
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
@@ -1576,12 +1576,12 @@ fn handleSegfaultPosix(sig: posix.SIG, info: *const posix.siginfo_t, ctx_ptr: ?*
.tvos,
.visionos,
.watchos,
+ .haiku,
=> @intFromPtr(info.addr),
.linux,
=> @intFromPtr(info.fields.sigfault.addr),
.netbsd,
=> @intFromPtr(info.info.reason.fault.addr),
- .haiku,
.openbsd,
=> @intFromPtr(info.data.fault.addr),
.illumos,
diff --git a/lib/std/zig/LibCInstallation.zig b/lib/std/zig/LibCInstallation.zig
@@ -459,6 +459,7 @@ fn findNativeCrtDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, args:
fn findNativeGccDirHaiku(self: *LibCInstallation, gpa: Allocator, io: Io, args: FindNativeOptions) FindError!void {
self.gcc_dir = try ccPrintFileName(gpa, io, .{
+ .environ_map = args.environ_map,
.search_basename = "crtbeginS.o",
.want_dirname = .only_dir,
.verbose = args.verbose,