From 0c83fa2fd03fec86c4e36075978646f202deec32 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 6 Apr 2024 17:47:54 -0400 Subject: [PATCH] haiku: fix directory iteration --- lib/std/c/haiku.zig | 1321 ++++++++++++++++++++++++------------------- lib/std/fs/Dir.zig | 103 +++- 2 files changed, 796 insertions(+), 628 deletions(-) diff --git a/lib/std/c/haiku.zig b/lib/std/c/haiku.zig index d75dd3bf0066f9ecf265b1e46f3eb39cdfecf48a..cd2e4bc2962a25f7c9555cd0994082a27a8d0062 100644 --- a/lib/std/c/haiku.zig +++ b/lib/std/c/haiku.zig @@ -5,28 +5,18 @@ const maxInt = std.math.maxInt; const iovec = std.posix.iovec; const iovec_const = std.posix.iovec_const; -extern "c" fn _errnop() *c_int; +pub extern "root" fn find_directory(which: directory_which, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64; -pub const _errno = _errnop; +pub extern "root" fn find_thread(thread_name: ?*anyopaque) i32; -pub extern "c" fn find_directory(which: directory_which, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64; +pub extern "root" fn get_system_info(system_info: *system_info) usize; -pub extern "c" fn find_thread(thread_name: ?*anyopaque) i32; +pub extern "root" fn _get_team_info(team: i32, team_info: *team_info, size: usize) i32; -pub extern "c" fn get_system_info(system_info: *system_info) usize; - -pub extern "c" fn _get_team_info(team: c_int, team_info: *team_info, size: usize) i32; - -pub extern "c" fn _get_next_area_info(team: c_int, cookie: *i64, area_info: *area_info, size: usize) i32; +pub extern "root" fn _get_next_area_info(team: i32, cookie: *i64, area_info: *area_info, size: usize) i32; // TODO revisit if abi changes or better option becomes apparent -pub extern "c" fn _get_next_image_info(team: c_int, cookie: *i32, image_info: *image_info, size: usize) i32; - -pub extern "c" fn _kern_read_dir(fd: c_int, buf_ptr: [*]u8, nbytes: usize, maxcount: u32) usize; - -pub extern "c" fn _kern_read_stat(fd: c_int, path_ptr: [*]u8, traverse_link: bool, st: *Stat, stat_size: i32) usize; - -pub extern "c" fn _kern_get_current_team() i32; +pub extern "root" fn _get_next_image_info(team: i32, cookie: *i32, image_info: *image_info, size: usize) i32; pub const sem_t = extern struct { type: i32, @@ -45,7 +35,7 @@ pub const pthread_attr_t = extern struct { __stack_address: ?*anyopaque, }; -pub const EAI = enum(c_int) { +pub const EAI = enum(i32) { /// address family for hostname not supported ADDRFAMILY = 1, @@ -99,11 +89,7 @@ pub const AI = struct { pub const AI_NUMERICSERV = AI.NUMERICSERV; -pub const fd_t = c_int; -pub const pid_t = c_int; -pub const uid_t = u32; -pub const gid_t = u32; -pub const mode_t = c_uint; +pub const fd_t = i32; pub const socklen_t = u32; @@ -129,8 +115,8 @@ pub const dl_phdr_info = extern struct { }; pub const Flock = extern struct { - type: c_short, - whence: c_short, + type: i16, + whence: i16, start: off_t, len: off_t, pid: pid_t, @@ -159,54 +145,6 @@ pub const msghdr = extern struct { msg_flags: i32, }; -pub const off_t = i64; -pub const ino_t = u64; - -pub const Stat = extern struct { - dev: i32, - ino: u64, - mode: u32, - nlink: i32, - uid: i32, - gid: i32, - size: i64, - rdev: i32, - blksize: i32, - atim: timespec, - mtim: timespec, - ctim: timespec, - crtim: timespec, - st_type: u32, - blocks: i64, - - pub fn atime(self: @This()) timespec { - return self.atim; - } - pub fn mtime(self: @This()) timespec { - return self.mtim; - } - pub fn ctime(self: @This()) timespec { - return self.ctim; - } - pub fn birthtime(self: @This()) timespec { - return self.crtim; - } -}; - -pub const timespec = extern struct { - tv_sec: isize, - tv_nsec: isize, -}; - -pub const dirent = extern struct { - dev: i32, - pdev: i32, - ino: i64, - pino: i64, - reclen: u16, - name: [256]u8, -}; - pub const B_OS_NAME_LENGTH = 32; // OS.h pub const area_info = extern struct { @@ -354,17 +292,6 @@ pub const PROT = struct { pub const NONE = 0x00; }; -pub const CLOCK = struct { - /// system-wide monotonic clock (aka system time) - pub const MONOTONIC = 0; - /// system-wide real time clock - pub const REALTIME = -1; - /// clock measuring the used CPU time of the current process - pub const PROCESS_CPUTIME_ID = -2; - /// clock measuring the used CPU time of the current thread - pub const THREAD_CPUTIME_ID = -3; -}; - pub const MSF = struct { pub const ASYNC = 1; pub const INVALIDATE = 2; @@ -404,424 +331,6 @@ pub const W = struct { } }; -// /system/develop/headers/posix/poll.h - -pub const nfds_t = usize; - -pub const pollfd = extern struct { - fd: i32, - events: i16, - revents: i16, -}; - -pub const POLL = struct { - /// any readable data available - pub const IN = 0x0001; - /// file descriptor is writeable - pub const OUT = 0x0002; - pub const RDNORM = IN; - pub const WRNORM = OUT; - /// priority readable data - pub const RDBAND = 0x0008; - /// priority data can be written - pub const WRBAND = 0x0010; - /// high priority readable data - pub const PRI = 0x0020; - - /// errors pending - pub const ERR = 0x0004; - /// disconnected - pub const HUP = 0x0080; - /// invalid file descriptor - pub const NVAL = 0x1000; -}; - -// /system/develop/headers/posix/signal.h - -pub const sigset_t = u64; -pub const empty_sigset: sigset_t = 0; -pub const filled_sigset = ~@as(sigset_t, 0); - -pub const SIG = struct { - pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); - pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); - pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); - - pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(3); - - pub const HUP = 1; - pub const INT = 2; - pub const QUIT = 3; - pub const ILL = 4; - pub const CHLD = 5; - pub const ABRT = 6; - pub const IOT = ABRT; - pub const PIPE = 7; - pub const FPE = 8; - pub const KILL = 9; - pub const STOP = 10; - pub const SEGV = 11; - pub const CONT = 12; - pub const TSTP = 13; - pub const ALRM = 14; - pub const TERM = 15; - pub const TTIN = 16; - pub const TTOU = 17; - pub const USR1 = 18; - pub const USR2 = 19; - pub const WINCH = 20; - pub const KILLTHR = 21; - pub const TRAP = 22; - pub const POLL = 23; - pub const PROF = 24; - pub const SYS = 25; - pub const URG = 26; - pub const VTALRM = 27; - pub const XCPU = 28; - pub const XFSZ = 29; - pub const BUS = 30; - pub const RESERVED1 = 31; - pub const RESERVED2 = 32; - - pub const BLOCK = 1; - pub const UNBLOCK = 2; - pub const SETMASK = 3; -}; - -pub const siginfo_t = extern struct { - signo: c_int, - code: c_int, - errno: c_int, - - pid: pid_t, - uid: uid_t, - addr: *allowzero anyopaque, -}; - -/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. -pub const Sigaction = extern struct { - pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; - pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; - - /// signal handler - handler: extern union { - handler: handler_fn, - sigaction: sigaction_fn, - }, - - /// signal mask to apply - mask: sigset_t, - - /// see signal options - flags: c_int, - - /// will be passed to the signal handler, BeOS extension - userdata: *allowzero anyopaque = undefined, -}; - -pub const SA = struct { - pub const NOCLDSTOP = 0x01; - pub const NOCLDWAIT = 0x02; - pub const RESETHAND = 0x04; - pub const NODEFER = 0x08; - pub const RESTART = 0x10; - pub const ONSTACK = 0x20; - pub const SIGINFO = 0x40; - pub const NOMASK = NODEFER; - pub const STACK = ONSTACK; - pub const ONESHOT = RESETHAND; -}; - -pub const SS = struct { - pub const ONSTACK = 0x1; - pub const DISABLE = 0x2; -}; - -pub const MINSIGSTKSZ = 8192; -pub const SIGSTKSZ = 16384; - -pub const stack_t = extern struct { - sp: [*]u8, - size: isize, - flags: i32, -}; - -pub const NSIG = 65; - -pub const mcontext_t = vregs; - -pub const ucontext_t = extern struct { - link: ?*ucontext_t, - sigmask: sigset_t, - stack: stack_t, - mcontext: mcontext_t, -}; - -// /system/develop/headers/posix/arch/*/signal.h - -pub const vregs = switch (builtin.cpu.arch) { - .arm, .thumb => extern struct { - r0: u32, - r1: u32, - r2: u32, - r3: u32, - r4: u32, - r5: u32, - r6: u32, - r7: u32, - r8: u32, - r9: u32, - r10: u32, - r11: u32, - r12: u32, - r13: u32, - r14: u32, - r15: u32, - cpsr: u32, - }, - .aarch64 => extern struct { - x: [10]u64, - lr: u64, - sp: u64, - elr: u64, - spsr: u64, - fp_q: [32]u128, - fpsr: u32, - fpcr: u32, - }, - .m68k => extern struct { - pc: u32, - d0: u32, - d1: u32, - d2: u32, - d3: u32, - d4: u32, - d5: u32, - d6: u32, - d7: u32, - a0: u32, - a1: u32, - a2: u32, - a3: u32, - a4: u32, - a5: u32, - a6: u32, - a7: u32, - ccr: u8, - f0: f64, - f1: f64, - f2: f64, - f3: f64, - f4: f64, - f5: f64, - f6: f64, - f7: f64, - f8: f64, - f9: f64, - f10: f64, - f11: f64, - f12: f64, - f13: f64, - }, - .mipsel => extern struct { - r0: u32, - }, - .powerpc => extern struct { - pc: u32, - r0: u32, - r1: u32, - r2: u32, - r3: u32, - r4: u32, - r5: u32, - r6: u32, - r7: u32, - r8: u32, - r9: u32, - r10: u32, - r11: u32, - r12: u32, - f0: f64, - f1: f64, - f2: f64, - f3: f64, - f4: f64, - f5: f64, - f6: f64, - f7: f64, - f8: f64, - f9: f64, - f10: f64, - f11: f64, - f12: f64, - f13: f64, - reserved: u32, - fpscr: u32, - ctr: u32, - xer: u32, - cr: u32, - msr: u32, - lr: u32, - }, - .riscv64 => extern struct { - x: [31]u64, - pc: u64, - f: [32]f64, - fcsr: u64, - }, - .sparc64 => extern struct { - g1: u64, - g2: u64, - g3: u64, - g4: u64, - g5: u64, - g6: u64, - g7: u64, - o0: u64, - o1: u64, - o2: u64, - o3: u64, - o4: u64, - o5: u64, - sp: u64, - o7: u64, - l0: u64, - l1: u64, - l2: u64, - l3: u64, - l4: u64, - l5: u64, - l6: u64, - l7: u64, - i0: u64, - i1: u64, - i2: u64, - i3: u64, - i4: u64, - i5: u64, - fp: u64, - i7: u64, - }, - .x86 => extern struct { - pub const old_extended_regs = extern struct { - control: u16, - reserved1: u16, - status: u16, - reserved2: u16, - tag: u16, - reserved3: u16, - eip: u32, - cs: u16, - opcode: u16, - datap: u32, - ds: u16, - reserved4: u16, - fp_mmx: [8][10]u8, - }; - - pub const fp_register = extern struct { value: [10]u8, reserved: [6]u8 }; - - pub const xmm_register = extern struct { value: [16]u8 }; - - pub const new_extended_regs = extern struct { - control: u16, - status: u16, - tag: u16, - opcode: u16, - eip: u32, - cs: u16, - reserved1: u16, - datap: u32, - ds: u16, - reserved2: u16, - mxcsr: u32, - reserved3: u32, - fp_mmx: [8]fp_register, - xmmx: [8]xmm_register, - reserved4: [224]u8, - }; - - pub const extended_regs = extern struct { - state: extern union { - old_format: old_extended_regs, - new_format: new_extended_regs, - }, - format: u32, - }; - - eip: u32, - eflags: u32, - eax: u32, - ecx: u32, - edx: u32, - esp: u32, - ebp: u32, - reserved: u32, - xregs: extended_regs, - edi: u32, - esi: u32, - ebx: u32, - }, - .x86_64 => extern struct { - pub const fp_register = extern struct { - value: [10]u8, - reserved: [6]u8, - }; - - pub const xmm_register = extern struct { - value: [16]u8, - }; - - pub const fpu_state = extern struct { - control: u16, - status: u16, - tag: u16, - opcode: u16, - rip: u64, - rdp: u64, - mxcsr: u32, - mscsr_mask: u32, - - fp_mmx: [8]fp_register, - xmm: [16]xmm_register, - reserved: [96]u8, - }; - - pub const xstate_hdr = extern struct { - bv: u64, - xcomp_bv: u64, - reserved: [48]u8, - }; - - pub const savefpu = extern struct { - fxsave: fpu_state, - xstate: xstate_hdr, - ymm: [16]xmm_register, - }; - - rax: u64, - rbx: u64, - rcx: u64, - rdx: u64, - rdi: u64, - rsi: u64, - rbp: u64, - r8: u64, - r9: u64, - r10: u64, - r11: u64, - r12: u64, - r13: u64, - r14: u64, - r15: u64, - rsp: u64, - rip: u64, - rflags: u64, - fpu: savefpu, - }, - else => void, -}; - // access function pub const F_OK = 0; // test for existence of file pub const X_OK = 1; // test for execute or search permission @@ -1033,100 +542,6 @@ pub const winsize = extern struct { ws_ypixel: u16, }; -const B_POSIX_ERROR_BASE = -2147454976; - -pub const E = enum(i32) { - @"2BIG" = B_POSIX_ERROR_BASE + 1, - CHILD = B_POSIX_ERROR_BASE + 2, - DEADLK = B_POSIX_ERROR_BASE + 3, - FBIG = B_POSIX_ERROR_BASE + 4, - MLINK = B_POSIX_ERROR_BASE + 5, - NFILE = B_POSIX_ERROR_BASE + 6, - NODEV = B_POSIX_ERROR_BASE + 7, - NOLCK = B_POSIX_ERROR_BASE + 8, - NOSYS = B_POSIX_ERROR_BASE + 9, - NOTTY = B_POSIX_ERROR_BASE + 10, - NXIO = B_POSIX_ERROR_BASE + 11, - SPIPE = B_POSIX_ERROR_BASE + 12, - SRCH = B_POSIX_ERROR_BASE + 13, - FPOS = B_POSIX_ERROR_BASE + 14, - SIGPARM = B_POSIX_ERROR_BASE + 15, - DOM = B_POSIX_ERROR_BASE + 16, - RANGE = B_POSIX_ERROR_BASE + 17, - PROTOTYPE = B_POSIX_ERROR_BASE + 18, - PROTONOSUPPORT = B_POSIX_ERROR_BASE + 19, - PFNOSUPPORT = B_POSIX_ERROR_BASE + 20, - AFNOSUPPORT = B_POSIX_ERROR_BASE + 21, - ADDRINUSE = B_POSIX_ERROR_BASE + 22, - ADDRNOTAVAIL = B_POSIX_ERROR_BASE + 23, - NETDOWN = B_POSIX_ERROR_BASE + 24, - NETUNREACH = B_POSIX_ERROR_BASE + 25, - NETRESET = B_POSIX_ERROR_BASE + 26, - CONNABORTED = B_POSIX_ERROR_BASE + 27, - CONNRESET = B_POSIX_ERROR_BASE + 28, - ISCONN = B_POSIX_ERROR_BASE + 29, - NOTCONN = B_POSIX_ERROR_BASE + 30, - SHUTDOWN = B_POSIX_ERROR_BASE + 31, - CONNREFUSED = B_POSIX_ERROR_BASE + 32, - HOSTUNREACH = B_POSIX_ERROR_BASE + 33, - NOPROTOOPT = B_POSIX_ERROR_BASE + 34, - NOBUFS = B_POSIX_ERROR_BASE + 35, - INPROGRESS = B_POSIX_ERROR_BASE + 36, - ALREADY = B_POSIX_ERROR_BASE + 37, - ILSEQ = B_POSIX_ERROR_BASE + 38, - NOMSG = B_POSIX_ERROR_BASE + 39, - STALE = B_POSIX_ERROR_BASE + 40, - OVERFLOW = B_POSIX_ERROR_BASE + 41, - MSGSIZE = B_POSIX_ERROR_BASE + 42, - OPNOTSUPP = B_POSIX_ERROR_BASE + 43, - NOTSOCK = B_POSIX_ERROR_BASE + 44, - HOSTDOWN = B_POSIX_ERROR_BASE + 45, - BADMSG = B_POSIX_ERROR_BASE + 46, - CANCELED = B_POSIX_ERROR_BASE + 47, - DESTADDRREQ = B_POSIX_ERROR_BASE + 48, - DQUOT = B_POSIX_ERROR_BASE + 49, - IDRM = B_POSIX_ERROR_BASE + 50, - MULTIHOP = B_POSIX_ERROR_BASE + 51, - NODATA = B_POSIX_ERROR_BASE + 52, - NOLINK = B_POSIX_ERROR_BASE + 53, - NOSR = B_POSIX_ERROR_BASE + 54, - NOSTR = B_POSIX_ERROR_BASE + 55, - NOTSUP = B_POSIX_ERROR_BASE + 56, - PROTO = B_POSIX_ERROR_BASE + 57, - TIME = B_POSIX_ERROR_BASE + 58, - TXTBSY = B_POSIX_ERROR_BASE + 59, - NOATTR = B_POSIX_ERROR_BASE + 60, - NOTRECOVERABLE = B_POSIX_ERROR_BASE + 61, - OWNERDEAD = B_POSIX_ERROR_BASE + 62, - - ACCES = -0x7ffffffe, // Permission denied - INTR = -0x7ffffff6, // Interrupted system call - IO = -0x7fffffff, // Input/output error - BUSY = -0x7ffffff2, // Device busy - FAULT = -0x7fffecff, // Bad address - TIMEDOUT = -2147483639, // Operation timed out - AGAIN = -0x7ffffff5, - BADF = -0x7fffa000, // Bad file descriptor - EXIST = -0x7fff9ffe, // File exists - INVAL = -0x7ffffffb, // Invalid argument - NAMETOOLONG = -2147459068, // File name too long - NOENT = -0x7fff9ffd, // No such file or directory - PERM = -0x7ffffff1, // Operation not permitted - NOTDIR = -0x7fff9ffb, // Not a directory - ISDIR = -0x7fff9ff7, // Is a directory - NOTEMPTY = -2147459066, // Directory not empty - NOSPC = -0x7fff9ff9, // No space left on device - ROFS = -0x7fff9ff8, // Read-only filesystem - MFILE = -0x7fff9ff6, // Too many open files - XDEV = -0x7fff9ff5, // Cross-device link - NOEXEC = -0x7fffecfe, // Exec format error - PIPE = -0x7fff9ff3, // Broken pipe - NOMEM = -0x80000000, // Cannot allocate memory - LOOP = -2147459060, // Too many levels of symbolic links - SUCCESS = 0, - _, -}; - pub const S = struct { pub const IFMT = 0o170000; pub const IFSOCK = 0o140000; @@ -1221,7 +636,7 @@ pub const IPPROTO = struct { pub const MAX = 256; }; -pub const rlimit_resource = enum(c_int) { +pub const rlimit_resource = enum(i32) { CORE = 0, CPU = 1, DATA = 2, @@ -1257,10 +672,722 @@ pub const SHUT = struct { }; // TODO fill out if needed -pub const directory_which = enum(c_int) { +pub const directory_which = enum(i32) { B_USER_SETTINGS_DIRECTORY = 0xbbe, _, }; pub const MSG_NOSIGNAL = 0x0800; + +// /system/develop/headers/os/kernel/OS.h + +pub const area_id = i32; +pub const port_id = i32; +pub const sem_id = i32; +pub const team_id = i32; +pub const thread_id = i32; + +// /system/develop/headers/os/support/Errors.h + +pub const E = enum(i32) { + pub const B_GENERAL_ERROR_BASE: i32 = std.math.minInt(i32); + pub const B_OS_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x1000; + pub const B_APP_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x2000; + pub const B_INTERFACE_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x3000; + pub const B_MEDIA_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x4000; + pub const B_TRANSLATION_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x4800; + pub const B_MIDI_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x5000; + pub const B_STORAGE_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x6000; + pub const B_POSIX_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x7000; + pub const B_MAIL_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x8000; + pub const B_PRINT_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x9000; + pub const B_DEVICE_ERROR_BASE = B_GENERAL_ERROR_BASE + 0xa000; + + pub const B_ERRORS_END = B_GENERAL_ERROR_BASE + 0xffff; + + pub const B_NO_MEMORY = B_GENERAL_ERROR_BASE + 0; + pub const B_IO_ERROR = B_GENERAL_ERROR_BASE + 1; + pub const B_PERMISSION_DENIED = B_GENERAL_ERROR_BASE + 2; + pub const B_BAD_INDEX = B_GENERAL_ERROR_BASE + 3; + pub const B_BAD_TYPE = B_GENERAL_ERROR_BASE + 4; + pub const B_BAD_VALUE = B_GENERAL_ERROR_BASE + 5; + pub const B_MISMATCHED_VALUES = B_GENERAL_ERROR_BASE + 6; + pub const B_NAME_NOT_FOUND = B_GENERAL_ERROR_BASE + 7; + pub const B_NAME_IN_USE = B_GENERAL_ERROR_BASE + 8; + pub const B_TIMED_OUT = B_GENERAL_ERROR_BASE + 9; + pub const B_INTERRUPTED = B_GENERAL_ERROR_BASE + 10; + pub const B_WOULD_BLOCK = B_GENERAL_ERROR_BASE + 11; + pub const B_CANCELED = B_GENERAL_ERROR_BASE + 12; + pub const B_NO_INIT = B_GENERAL_ERROR_BASE + 13; + pub const B_NOT_INITIALIZED = B_GENERAL_ERROR_BASE + 13; + pub const B_BUSY = B_GENERAL_ERROR_BASE + 14; + pub const B_NOT_ALLOWED = B_GENERAL_ERROR_BASE + 15; + pub const B_BAD_DATA = B_GENERAL_ERROR_BASE + 16; + pub const B_DONT_DO_THAT = B_GENERAL_ERROR_BASE + 17; + + pub const B_BAD_IMAGE_ID = B_OS_ERROR_BASE + 0x300; + pub const B_BAD_ADDRESS = B_OS_ERROR_BASE + 0x301; + pub const B_NOT_AN_EXECUTABLE = B_OS_ERROR_BASE + 0x302; + pub const B_MISSING_LIBRARY = B_OS_ERROR_BASE + 0x303; + pub const B_MISSING_SYMBOL = B_OS_ERROR_BASE + 0x304; + pub const B_UNKNOWN_EXECUTABLE = B_OS_ERROR_BASE + 0x305; + pub const B_LEGACY_EXECUTABLE = B_OS_ERROR_BASE + 0x306; + + pub const B_FILE_ERROR = B_STORAGE_ERROR_BASE + 0; + pub const B_FILE_EXISTS = B_STORAGE_ERROR_BASE + 2; + pub const B_ENTRY_NOT_FOUND = B_STORAGE_ERROR_BASE + 3; + pub const B_NAME_TOO_LONG = B_STORAGE_ERROR_BASE + 4; + pub const B_NOT_A_DIRECTORY = B_STORAGE_ERROR_BASE + 5; + pub const B_DIRECTORY_NOT_EMPTY = B_STORAGE_ERROR_BASE + 6; + pub const B_DEVICE_FULL = B_STORAGE_ERROR_BASE + 7; + pub const B_READ_ONLY_DEVICE = B_STORAGE_ERROR_BASE + 8; + pub const B_IS_A_DIRECTORY = B_STORAGE_ERROR_BASE + 9; + pub const B_NO_MORE_FDS = B_STORAGE_ERROR_BASE + 10; + pub const B_CROSS_DEVICE_LINK = B_STORAGE_ERROR_BASE + 11; + pub const B_LINK_LIMIT = B_STORAGE_ERROR_BASE + 12; + pub const B_BUSTED_PIPE = B_STORAGE_ERROR_BASE + 13; + pub const B_UNSUPPORTED = B_STORAGE_ERROR_BASE + 14; + pub const B_PARTITION_TOO_SMALL = B_STORAGE_ERROR_BASE + 15; + pub const B_PARTIAL_READ = B_STORAGE_ERROR_BASE + 16; + pub const B_PARTIAL_WRITE = B_STORAGE_ERROR_BASE + 17; + + SUCCESS = 0, + + @"2BIG" = B_POSIX_ERROR_BASE + 1, + CHILD = B_POSIX_ERROR_BASE + 2, + DEADLK = B_POSIX_ERROR_BASE + 3, + FBIG = B_POSIX_ERROR_BASE + 4, + MLINK = B_POSIX_ERROR_BASE + 5, + NFILE = B_POSIX_ERROR_BASE + 6, + NODEV = B_POSIX_ERROR_BASE + 7, + NOLCK = B_POSIX_ERROR_BASE + 8, + NOSYS = B_POSIX_ERROR_BASE + 9, + NOTTY = B_POSIX_ERROR_BASE + 10, + NXIO = B_POSIX_ERROR_BASE + 11, + SPIPE = B_POSIX_ERROR_BASE + 12, + SRCH = B_POSIX_ERROR_BASE + 13, + FPOS = B_POSIX_ERROR_BASE + 14, + SIGPARM = B_POSIX_ERROR_BASE + 15, + DOM = B_POSIX_ERROR_BASE + 16, + RANGE = B_POSIX_ERROR_BASE + 17, + PROTOTYPE = B_POSIX_ERROR_BASE + 18, + PROTONOSUPPORT = B_POSIX_ERROR_BASE + 19, + PFNOSUPPORT = B_POSIX_ERROR_BASE + 20, + AFNOSUPPORT = B_POSIX_ERROR_BASE + 21, + ADDRINUSE = B_POSIX_ERROR_BASE + 22, + ADDRNOTAVAIL = B_POSIX_ERROR_BASE + 23, + NETDOWN = B_POSIX_ERROR_BASE + 24, + NETUNREACH = B_POSIX_ERROR_BASE + 25, + NETRESET = B_POSIX_ERROR_BASE + 26, + CONNABORTED = B_POSIX_ERROR_BASE + 27, + CONNRESET = B_POSIX_ERROR_BASE + 28, + ISCONN = B_POSIX_ERROR_BASE + 29, + NOTCONN = B_POSIX_ERROR_BASE + 30, + SHUTDOWN = B_POSIX_ERROR_BASE + 31, + CONNREFUSED = B_POSIX_ERROR_BASE + 32, + HOSTUNREACH = B_POSIX_ERROR_BASE + 33, + NOPROTOOPT = B_POSIX_ERROR_BASE + 34, + NOBUFS = B_POSIX_ERROR_BASE + 35, + INPROGRESS = B_POSIX_ERROR_BASE + 36, + ALREADY = B_POSIX_ERROR_BASE + 37, + ILSEQ = B_POSIX_ERROR_BASE + 38, + NOMSG = B_POSIX_ERROR_BASE + 39, + STALE = B_POSIX_ERROR_BASE + 40, + OVERFLOW = B_POSIX_ERROR_BASE + 41, + MSGSIZE = B_POSIX_ERROR_BASE + 42, + OPNOTSUPP = B_POSIX_ERROR_BASE + 43, + NOTSOCK = B_POSIX_ERROR_BASE + 44, + HOSTDOWN = B_POSIX_ERROR_BASE + 45, + BADMSG = B_POSIX_ERROR_BASE + 46, + CANCELED = B_POSIX_ERROR_BASE + 47, + DESTADDRREQ = B_POSIX_ERROR_BASE + 48, + DQUOT = B_POSIX_ERROR_BASE + 49, + IDRM = B_POSIX_ERROR_BASE + 50, + MULTIHOP = B_POSIX_ERROR_BASE + 51, + NODATA = B_POSIX_ERROR_BASE + 52, + NOLINK = B_POSIX_ERROR_BASE + 53, + NOSR = B_POSIX_ERROR_BASE + 54, + NOSTR = B_POSIX_ERROR_BASE + 55, + NOTSUP = B_POSIX_ERROR_BASE + 56, + PROTO = B_POSIX_ERROR_BASE + 57, + TIME = B_POSIX_ERROR_BASE + 58, + TXTBSY = B_POSIX_ERROR_BASE + 59, + NOATTR = B_POSIX_ERROR_BASE + 60, + NOTRECOVERABLE = B_POSIX_ERROR_BASE + 61, + OWNERDEAD = B_POSIX_ERROR_BASE + 62, + + NOMEM = B_NO_MEMORY, + + ACCES = B_PERMISSION_DENIED, + INTR = B_INTERRUPTED, + IO = B_IO_ERROR, + BUSY = B_BUSY, + FAULT = B_BAD_ADDRESS, + TIMEDOUT = B_TIMED_OUT, + /// Also used for WOULDBLOCK + AGAIN = B_WOULD_BLOCK, + BADF = B_FILE_ERROR, + EXIST = B_FILE_EXISTS, + INVAL = B_BAD_VALUE, + NAMETOOLONG = B_NAME_TOO_LONG, + NOENT = B_ENTRY_NOT_FOUND, + PERM = B_NOT_ALLOWED, + NOTDIR = B_NOT_A_DIRECTORY, + ISDIR = B_IS_A_DIRECTORY, + NOTEMPTY = B_DIRECTORY_NOT_EMPTY, + NOSPC = B_DEVICE_FULL, + ROFS = B_READ_ONLY_DEVICE, + MFILE = B_NO_MORE_FDS, + XDEV = B_CROSS_DEVICE_LINK, + LOOP = B_LINK_LIMIT, + NOEXEC = B_NOT_AN_EXECUTABLE, + PIPE = B_BUSTED_PIPE, + + _, +}; + +// /system/develop/headers/os/support/SupportDefs.h + +pub const status_t = i32; + +// /system/develop/headers/posix/arch/*/signal.h + +pub const vregs = switch (builtin.cpu.arch) { + .arm, .thumb => extern struct { + r0: u32, + r1: u32, + r2: u32, + r3: u32, + r4: u32, + r5: u32, + r6: u32, + r7: u32, + r8: u32, + r9: u32, + r10: u32, + r11: u32, + r12: u32, + r13: u32, + r14: u32, + r15: u32, + cpsr: u32, + }, + .aarch64 => extern struct { + x: [10]u64, + lr: u64, + sp: u64, + elr: u64, + spsr: u64, + fp_q: [32]u128, + fpsr: u32, + fpcr: u32, + }, + .m68k => extern struct { + pc: u32, + d0: u32, + d1: u32, + d2: u32, + d3: u32, + d4: u32, + d5: u32, + d6: u32, + d7: u32, + a0: u32, + a1: u32, + a2: u32, + a3: u32, + a4: u32, + a5: u32, + a6: u32, + a7: u32, + ccr: u8, + f0: f64, + f1: f64, + f2: f64, + f3: f64, + f4: f64, + f5: f64, + f6: f64, + f7: f64, + f8: f64, + f9: f64, + f10: f64, + f11: f64, + f12: f64, + f13: f64, + }, + .mipsel => extern struct { + r0: u32, + }, + .powerpc => extern struct { + pc: u32, + r0: u32, + r1: u32, + r2: u32, + r3: u32, + r4: u32, + r5: u32, + r6: u32, + r7: u32, + r8: u32, + r9: u32, + r10: u32, + r11: u32, + r12: u32, + f0: f64, + f1: f64, + f2: f64, + f3: f64, + f4: f64, + f5: f64, + f6: f64, + f7: f64, + f8: f64, + f9: f64, + f10: f64, + f11: f64, + f12: f64, + f13: f64, + reserved: u32, + fpscr: u32, + ctr: u32, + xer: u32, + cr: u32, + msr: u32, + lr: u32, + }, + .riscv64 => extern struct { + x: [31]u64, + pc: u64, + f: [32]f64, + fcsr: u64, + }, + .sparc64 => extern struct { + g1: u64, + g2: u64, + g3: u64, + g4: u64, + g5: u64, + g6: u64, + g7: u64, + o0: u64, + o1: u64, + o2: u64, + o3: u64, + o4: u64, + o5: u64, + sp: u64, + o7: u64, + l0: u64, + l1: u64, + l2: u64, + l3: u64, + l4: u64, + l5: u64, + l6: u64, + l7: u64, + i0: u64, + i1: u64, + i2: u64, + i3: u64, + i4: u64, + i5: u64, + fp: u64, + i7: u64, + }, + .x86 => extern struct { + pub const old_extended_regs = extern struct { + control: u16, + reserved1: u16, + status: u16, + reserved2: u16, + tag: u16, + reserved3: u16, + eip: u32, + cs: u16, + opcode: u16, + datap: u32, + ds: u16, + reserved4: u16, + fp_mmx: [8][10]u8, + }; + + pub const fp_register = extern struct { value: [10]u8, reserved: [6]u8 }; + + pub const xmm_register = extern struct { value: [16]u8 }; + + pub const new_extended_regs = extern struct { + control: u16, + status: u16, + tag: u16, + opcode: u16, + eip: u32, + cs: u16, + reserved1: u16, + datap: u32, + ds: u16, + reserved2: u16, + mxcsr: u32, + reserved3: u32, + fp_mmx: [8]fp_register, + xmmx: [8]xmm_register, + reserved4: [224]u8, + }; + + pub const extended_regs = extern struct { + state: extern union { + old_format: old_extended_regs, + new_format: new_extended_regs, + }, + format: u32, + }; + + eip: u32, + eflags: u32, + eax: u32, + ecx: u32, + edx: u32, + esp: u32, + ebp: u32, + reserved: u32, + xregs: extended_regs, + edi: u32, + esi: u32, + ebx: u32, + }, + .x86_64 => extern struct { + pub const fp_register = extern struct { + value: [10]u8, + reserved: [6]u8, + }; + + pub const xmm_register = extern struct { + value: [16]u8, + }; + + pub const fpu_state = extern struct { + control: u16, + status: u16, + tag: u16, + opcode: u16, + rip: u64, + rdp: u64, + mxcsr: u32, + mscsr_mask: u32, + + fp_mmx: [8]fp_register, + xmm: [16]xmm_register, + reserved: [96]u8, + }; + + pub const xstate_hdr = extern struct { + bv: u64, + xcomp_bv: u64, + reserved: [48]u8, + }; + + pub const savefpu = extern struct { + fxsave: fpu_state, + xstate: xstate_hdr, + ymm: [16]xmm_register, + }; + + rax: u64, + rbx: u64, + rcx: u64, + rdx: u64, + rdi: u64, + rsi: u64, + rbp: u64, + r8: u64, + r9: u64, + r10: u64, + r11: u64, + r12: u64, + r13: u64, + r14: u64, + r15: u64, + rsp: u64, + rip: u64, + rflags: u64, + fpu: savefpu, + }, + else => void, +}; + +// /system/develop/headers/posix/dirent.h + +pub const DirEnt = extern struct { + /// device + dev: dev_t, + /// parent device (only for queries) + pdev: dev_t, + /// inode number + ino: ino_t, + /// parent inode (only for queries) + pino: ino_t, + /// length of this record, not the name + reclen: u16, + /// name of the entry (null byte terminated) + name: [0]u8, + pub fn getName(dirent: *const DirEnt) [*:0]const u8 { + return @ptrCast(&dirent.name); + } +}; + +// /system/develop/headers/posix/errno.h + +extern "root" fn _errnop() *i32; +pub const _errno = _errnop; + +// /system/develop/headers/posix/poll.h + +pub const nfds_t = usize; + +pub const pollfd = extern struct { + fd: i32, + events: i16, + revents: i16, +}; + +pub const POLL = struct { + /// any readable data available + pub const IN = 0x0001; + /// file descriptor is writeable + pub const OUT = 0x0002; + pub const RDNORM = IN; + pub const WRNORM = OUT; + /// priority readable data + pub const RDBAND = 0x0008; + /// priority data can be written + pub const WRBAND = 0x0010; + /// high priority readable data + pub const PRI = 0x0020; + + /// errors pending + pub const ERR = 0x0004; + /// disconnected + pub const HUP = 0x0080; + /// invalid file descriptor + pub const NVAL = 0x1000; +}; + +// /system/develop/headers/posix/signal.h + +pub const sigset_t = u64; +pub const empty_sigset: sigset_t = 0; +pub const filled_sigset = ~@as(sigset_t, 0); + +pub const SIG = struct { + pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); + pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); + pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); + + pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(3); + + pub const HUP = 1; + pub const INT = 2; + pub const QUIT = 3; + pub const ILL = 4; + pub const CHLD = 5; + pub const ABRT = 6; + pub const IOT = ABRT; + pub const PIPE = 7; + pub const FPE = 8; + pub const KILL = 9; + pub const STOP = 10; + pub const SEGV = 11; + pub const CONT = 12; + pub const TSTP = 13; + pub const ALRM = 14; + pub const TERM = 15; + pub const TTIN = 16; + pub const TTOU = 17; + pub const USR1 = 18; + pub const USR2 = 19; + pub const WINCH = 20; + pub const KILLTHR = 21; + pub const TRAP = 22; + pub const POLL = 23; + pub const PROF = 24; + pub const SYS = 25; + pub const URG = 26; + pub const VTALRM = 27; + pub const XCPU = 28; + pub const XFSZ = 29; + pub const BUS = 30; + pub const RESERVED1 = 31; + pub const RESERVED2 = 32; + + pub const BLOCK = 1; + pub const UNBLOCK = 2; + pub const SETMASK = 3; +}; + +pub const siginfo_t = extern struct { + signo: i32, + code: i32, + errno: i32, + + pid: pid_t, + uid: uid_t, + addr: *allowzero anyopaque, +}; + +/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. +pub const Sigaction = extern struct { + pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; + pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; + + /// signal handler + handler: extern union { + handler: handler_fn, + sigaction: sigaction_fn, + }, + + /// signal mask to apply + mask: sigset_t, + + /// see signal options + flags: i32, + + /// will be passed to the signal handler, BeOS extension + userdata: *allowzero anyopaque = undefined, +}; + +pub const SA = struct { + pub const NOCLDSTOP = 0x01; + pub const NOCLDWAIT = 0x02; + pub const RESETHAND = 0x04; + pub const NODEFER = 0x08; + pub const RESTART = 0x10; + pub const ONSTACK = 0x20; + pub const SIGINFO = 0x40; + pub const NOMASK = NODEFER; + pub const STACK = ONSTACK; + pub const ONESHOT = RESETHAND; +}; + +pub const SS = struct { + pub const ONSTACK = 0x1; + pub const DISABLE = 0x2; +}; + +pub const MINSIGSTKSZ = 8192; +pub const SIGSTKSZ = 16384; + +pub const stack_t = extern struct { + sp: [*]u8, + size: isize, + flags: i32, +}; + +pub const NSIG = 65; + +pub const mcontext_t = vregs; + +pub const ucontext_t = extern struct { + link: ?*ucontext_t, + sigmask: sigset_t, + stack: stack_t, + mcontext: mcontext_t, +}; + +// /system/develop/headers/posix/sys/stat.h + +pub const Stat = extern struct { + dev: dev_t, + ino: ino_t, + mode: mode_t, + nlink: nlink_t, + uid: uid_t, + gid: gid_t, + size: off_t, + rdev: dev_t, + blksize: blksize_t, + atim: timespec, + mtim: timespec, + ctim: timespec, + crtim: timespec, + type: u32, + blocks: blkcnt_t, + + pub fn atime(self: @This()) timespec { + return self.atim; + } + pub fn mtime(self: @This()) timespec { + return self.mtim; + } + pub fn ctime(self: @This()) timespec { + return self.ctim; + } + pub fn birthtime(self: @This()) timespec { + return self.crtim; + } +}; + +// /system/develop/headers/posix/sys/types.h + +pub const blkcnt_t = i64; +pub const blksize_t = i32; +pub const fsblkcnt_t = i64; +pub const fsfilcnt_t = i64; +pub const off_t = i64; +pub const ino_t = i64; +pub const cnt_t = i32; +pub const dev_t = i32; +pub const pid_t = i32; +pub const id_t = i32; + +pub const uid_t = u32; +pub const gid_t = u32; +pub const mode_t = u32; +pub const umode_t = u32; +pub const nlink_t = i32; + +pub const clockid_t = i32; +pub const timer_t = *opaque {}; + +// /system/develop/headers/posix/time.h + +pub const clock_t = i32; +pub const suseconds_t = i32; +pub const useconds_t = u32; + +pub const time_t = isize; + +pub const CLOCKS_PER_SEC = 1_000_000; +pub const CLK_TCK = CLOCKS_PER_SEC; +pub const TIME_UTC = 1; + +pub const CLOCK = struct { + /// system-wide monotonic clock (aka system time) + pub const MONOTONIC: clockid_t = 0; + /// system-wide real time clock + pub const REALTIME: clockid_t = -1; + /// clock measuring the used CPU time of the current process + pub const PROCESS_CPUTIME_ID: clockid_t = -2; + /// clock measuring the used CPU time of the current thread + pub const THREAD_CPUTIME_ID: clockid_t = -3; +}; + +pub const timespec = extern struct { + /// seconds + tv_sec: time_t, + /// and nanoseconds + tv_nsec: isize, +}; + +pub const itimerspec = extern struct { + interval: timespec, + value: timespec, +}; + +// /system/develop/headers/private/system/syscalls.h + +pub extern "root" fn _kern_get_current_team() team_id; +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: *Stat, statSize: usize) status_t; diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig index 74d91239f81047a6c097c1e76ea2f9a9023f6f0e..785e9541e2c842cf12c18e374c6c801b78c27b78 100644 --- a/lib/std/fs/Dir.zig +++ b/lib/std/fs/Dir.zig @@ -220,71 +220,83 @@ pub const Iterator = switch (native_os) { }, .haiku => struct { dir: Dir, - buf: [1024]u8, // TODO align(@alignOf(posix.dirent64)), + buf: [@sizeOf(DirEnt) + posix.PATH_MAX]u8 align(@alignOf(DirEnt)), + offset: usize, index: usize, end_index: usize, first_iter: bool, const Self = @This(); + const DirEnt = posix.system.DirEnt; pub const Error = IteratorError; /// Memory such as file names referenced in this returned entry becomes invalid /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. pub fn next(self: *Self) Error!?Entry { - start_over: while (true) { - // TODO: find a better max - const HAIKU_MAX_COUNT = 10000; + while (true) { if (self.index >= self.end_index) { if (self.first_iter) { - posix.lseek_SET(self.dir.fd, 0) catch unreachable; // EBADF here likely means that the Dir was not opened with iteration permissions + switch (@as(posix.E, @enumFromInt(posix.system._kern_rewind_dir(self.dir.fd)))) { + .SUCCESS => {}, + .BADF => unreachable, // Dir is invalid + .FAULT => unreachable, + .NOTDIR => unreachable, + .INVAL => unreachable, + .ACCES => return error.AccessDenied, + .PERM => return error.AccessDenied, + else => |err| return posix.unexpectedErrno(err), + } self.first_iter = false; } const rc = posix.system._kern_read_dir( self.dir.fd, &self.buf, self.buf.len, - HAIKU_MAX_COUNT, + self.buf.len / @sizeOf(DirEnt), ); if (rc == 0) return null; if (rc < 0) { - switch (posix.errno(rc)) { - .BADF => unreachable, // Dir is invalid or was opened without iteration ability + switch (@as(posix.E, @enumFromInt(rc))) { + .BADF => unreachable, // Dir is invalid .FAULT => unreachable, .NOTDIR => unreachable, .INVAL => unreachable, + .OVERFLOW => unreachable, + .ACCES => return error.AccessDenied, + .PERM => return error.AccessDenied, else => |err| return posix.unexpectedErrno(err), } } + self.offset = 0; self.index = 0; - self.end_index = @as(usize, @intCast(rc)); - } - const haiku_entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index])); - const next_index = self.index + haiku_entry.reclen; - self.index = next_index; - const name = mem.sliceTo(@as([*:0]u8, @ptrCast(&haiku_entry.name)), 0); - - if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or (haiku_entry.ino == 0)) { - continue :start_over; + self.end_index = @intCast(rc); } + const dirent: *DirEnt = @ptrCast(@alignCast(&self.buf[self.offset])); + self.offset += dirent.reclen; + self.index += 1; + const name = mem.span(dirent.getName()); + if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or dirent.ino == 0) continue; var stat_info: posix.Stat = undefined; - const rc = posix.system._kern_read_stat( + switch (@as(posix.E, @enumFromInt(posix.system._kern_read_stat( self.dir.fd, - &haiku_entry.name, + name, false, &stat_info, 0, - ); - if (rc != 0) { - switch (posix.errno(rc)) { - .SUCCESS => {}, - .BADF => unreachable, // Dir is invalid or was opened without iteration ability - .FAULT => unreachable, - .NOTDIR => unreachable, - .INVAL => unreachable, - else => |err| return posix.unexpectedErrno(err), - } + )))) { + .SUCCESS => {}, + .INVAL => unreachable, + .BADF => unreachable, // Dir is invalid + .NOMEM => return error.SystemResources, + .ACCES => return error.AccessDenied, + .PERM => return error.AccessDenied, + .FAULT => unreachable, + .NAMETOOLONG => unreachable, + .LOOP => unreachable, + .NOENT => continue, + else => |err| return posix.unexpectedErrno(err), } const statmode = stat_info.mode & posix.S.IFMT; @@ -315,7 +327,7 @@ pub const Iterator = switch (native_os) { dir: Dir, // The if guard is solely there to prevent compile errors from missing `linux.dirent64` // definition when compiling for other OSes. It doesn't do anything when compiling for Linux. - buf: [1024]u8 align(if (native_os != .linux) 1 else @alignOf(linux.dirent64)), + buf: [1024]u8 align(@alignOf(linux.dirent64)), index: usize, end_index: usize, first_iter: bool, @@ -599,13 +611,21 @@ fn iterateImpl(self: Dir, first_iter_start_value: bool) Iterator { .buf = undefined, .first_iter = first_iter_start_value, }, - .linux, .haiku => return Iterator{ + .linux => return Iterator{ .dir = self, .index = 0, .end_index = 0, .buf = undefined, .first_iter = first_iter_start_value, }, + .haiku => return Iterator{ + .dir = self, + .offset = 0, + .index = 0, + .end_index = 0, + .buf = undefined, + .first_iter = first_iter_start_value, + }, .windows => return Iterator{ .dir = self, .index = 0, @@ -1429,6 +1449,27 @@ pub fn openDirZ(self: Dir, sub_path_c: [*:0]const u8, args: OpenDirOptions) Open .wasi => { return openDir(self, mem.sliceTo(sub_path_c, 0), args); }, + .haiku => { + const rc = posix.system._kern_open_dir(self.fd, sub_path_c); + if (rc >= 0) return .{ .fd = rc }; + switch (@as(posix.E, @enumFromInt(rc))) { + .FAULT => unreachable, + .INVAL => unreachable, + .BADF => unreachable, + .ACCES => return error.AccessDenied, + .LOOP => return error.SymLinkLoop, + .MFILE => return error.ProcessFdQuotaExceeded, + .NAMETOOLONG => return error.NameTooLong, + .NFILE => return error.SystemFdQuotaExceeded, + .NODEV => return error.NoDevice, + .NOENT => return error.FileNotFound, + .NOMEM => return error.SystemResources, + .NOTDIR => return error.NotDir, + .PERM => return error.AccessDenied, + .BUSY => return error.DeviceBusy, + else => |err| return posix.unexpectedErrno(err), + } + }, else => { var symlink_flags: posix.O = .{ .ACCMODE = .RDONLY, -- 2.54.0