diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index aa0ff45a60..90ace09b69 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -5345,7 +5345,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), } }, @@ -5791,10 +5791,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 { @@ -9812,7 +9921,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(); @@ -9846,7 +9958,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(); @@ -10550,7 +10662,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(); @@ -14063,7 +14178,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 index f0b0391785..945df32798 100644 --- 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 @@ -11142,6 +11142,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 index 81cc3bc325..dd599ca837 100644 --- 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 index 3dac7229f7..6eb0b3d673 100644 --- 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 index 6a3f4b4813..1009d34012 100644 --- 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,