diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 80de19fe19..52f625edf4 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -504,6 +504,13 @@ pub fn cpuCount() CpuCountError!usize { }; return @intCast(usize, count); } + if (std.Target.current.os.tag == .haiku) { + var count: u32 = undefined; + var system_info: os.system_info = undefined; + const rc = os.system.get_system_info(&system_info); + count = system_info.cpu_count; + return @intCast(usize, count); + } var count: c_int = undefined; var count_len: usize = @sizeOf(c_int); const name = if (comptime std.Target.current.isDarwin()) "hw.logicalcpu" else "hw.ncpu"; @@ -538,6 +545,9 @@ pub fn getCurrentThreadId() u64 { .openbsd => { return @bitCast(u32, c.getthrid()); }, + .haiku => { + return @bitCast(u32, c.find_thread(null)); + }, else => { @compileError("getCurrentThreadId not implemented for this platform"); }, diff --git a/lib/std/c/haiku.zig b/lib/std/c/haiku.zig index a00e3ec534..e361a7520e 100644 --- a/lib/std/c/haiku.zig +++ b/lib/std/c/haiku.zig @@ -14,9 +14,20 @@ extern "c" fn _errnop() *c_int; pub const _errno = _errnop; +pub extern "c" fn find_directory(which: c_int, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64; + +pub extern "c" fn find_thread(thread_name: ?*c_void) i32; + +pub extern "c" fn get_system_info(system_info: *system_info) usize; + +// 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) usize; + pub extern "c" fn _kern_read_dir(fd: c_int, buf_ptr: [*]u8, nbytes: usize, maxcount: u32) usize; -pub extern "c" fn _get_next_image_info(team: c_int, cookie: *i32, image_info: *image_info) usize; +pub extern "c" fn _kern_read_stat(fd: c_int, path_ptr: [*]u8, traverse_link: bool, libc_stat: *libc_stat, stat_size: i32) usize; + +pub extern "c" fn _kern_get_current_team() i32; pub const sem_t = extern struct { _magic: u32, @@ -27,6 +38,14 @@ pub const sem_t = extern struct { _padding: u32, }; +pub const pthread_attr_t = extern struct { + __detach_state: i32, + __sched_priority: i32, + __stack_size: i32, + __guard_size: i32, + __stack_address: ?*c_void, +}; + pub const pthread_mutex_t = extern struct { flags: u32 = 0, lock: i32 = 0, @@ -34,7 +53,6 @@ pub const pthread_mutex_t = extern struct { owner: i32 = -1, owner_count: i32 = 0, }; - pub const pthread_cond_t = extern struct { flags: u32 = 0, unused: i32 = -42, diff --git a/lib/std/crypto/tlcsprng.zig b/lib/std/crypto/tlcsprng.zig index 07844efc1b..115a7ab882 100644 --- a/lib/std/crypto/tlcsprng.zig +++ b/lib/std/crypto/tlcsprng.zig @@ -29,6 +29,7 @@ const os_has_fork = switch (std.Target.current.os.tag) { .solaris, .tvos, .watchos, + .haiku, => true, else => false, diff --git a/lib/std/fs.zig b/lib/std/fs.zig index d6ed1dfd7c..79385708af 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -472,8 +472,25 @@ pub const Dir = struct { continue :start_over; } - // TODO: determine entry kind - const entry_kind = Entry.Kind.File; + var stat_info: os.libc_stat = undefined; + const rc2 = os.system._kern_read_stat( + self.dir.fd, + &haiku_entry.d_name, + false, + &stat_info, + 0, + ); + const statmode = stat_info.mode & os.S_IFMT; + + const entry_kind = switch (statmode) { + os.S_IFDIR => Entry.Kind.Directory, + os.S_IFBLK => Entry.Kind.BlockDevice, + os.S_IFCHR => Entry.Kind.CharacterDevice, + os.S_IFLNK => Entry.Kind.SymLink, + os.S_IFREG => Entry.Kind.File, + os.S_IFIFO => Entry.Kind.NamedPipe, + else => Entry.Kind.Unknown, + }; return Entry{ .name = name, @@ -676,7 +693,13 @@ pub const Dir = struct { pub fn iterate(self: Dir) Iterator { switch (builtin.os.tag) { - .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd, => return Iterator{ + .macos, + .ios, + .freebsd, + .netbsd, + .dragonfly, + .openbsd, + => return Iterator{ .dir = self, .seek = 0, .index = 0, diff --git a/lib/std/fs/get_app_data_dir.zig b/lib/std/fs/get_app_data_dir.zig index 2199761acb..18f8458eb2 100644 --- a/lib/std/fs/get_app_data_dir.zig +++ b/lib/std/fs/get_app_data_dir.zig @@ -57,11 +57,16 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD return fs.path.join(allocator, &[_][]const u8{ home_dir, ".local", "share", appname }); }, .haiku => { - const home_dir = os.getenv("HOME") orelse { - // TODO look in /etc/passwd - return error.AppDataDirUnavailable; - }; - return fs.path.join(allocator, &[_][]const u8{ home_dir, "config", "settings", appname }); + var dir_path_ptr: [*:0]u8 = undefined; + // TODO look into directory_which + const be_user_settings = 0xbbe; + const rc = os.system.find_directory(be_user_settings, -1, true, dir_path_ptr, 1) ; + const settings_dir = try allocator.dupeZ(u8, mem.spanZ(dir_path_ptr)); + defer allocator.free(settings_dir); + switch (rc) { + 0 => return fs.path.join(allocator, &[_][]const u8{ settings_dir, appname }), + else => return error.AppDataDirUnavailable, + } }, else => @compileError("Unsupported OS"), } diff --git a/lib/std/os.zig b/lib/std/os.zig index a9578e530e..8d5c680b26 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -3941,6 +3941,9 @@ pub fn sysctl( if (builtin.os.tag == .wasi) { @panic("unsupported"); } + if (builtin.os.tag == .haiku) { + @panic("unsupported"); + } const name_len = math.cast(c_uint, name.len) catch return error.NameTooLong; switch (errno(system.sysctl(name.ptr, name_len, oldp, oldlenp, newp, newlen))) { @@ -3965,6 +3968,9 @@ pub fn sysctlbynameZ( if (builtin.os.tag == .wasi) { @panic("unsupported"); } + if (builtin.os.tag == .haiku) { + @panic("unsupported"); + } switch (errno(system.sysctlbyname(name, oldp, oldlenp, newp, newlen))) { 0 => return, diff --git a/lib/std/os/bits/haiku.zig b/lib/std/os/bits/haiku.zig index c4f6b694aa..59631fd40e 100644 --- a/lib/std/os/bits/haiku.zig +++ b/lib/std/os/bits/haiku.zig @@ -6,8 +6,6 @@ const std = @import("../../std.zig"); const maxInt = std.math.maxInt; -// See https://svnweb.freebsd.org/base/head/sys/sys/_types.h?view=co -// TODO: audit pid_t/mode_t. They should likely be i32 and u16, respectively pub const fd_t = c_int; pub const pid_t = c_int; pub const uid_t = u32; @@ -30,6 +28,11 @@ pub const Kevent = extern struct { // Modes and flags for dlopen() // include/dlfcn.h +pub const POLLIN = 0x0001; +pub const POLLERR = 0x0004; +pub const POLLNVAL = 0x1000; +pub const POLLHUP = 0x0080; + /// Bind function calls lazily. pub const RTLD_LAZY = 1; @@ -119,41 +122,43 @@ pub const msghdr_const = extern struct { pub const off_t = i64; pub const ino_t = u64; +pub const nfds_t = u32; + +pub const pollfd = extern struct { + fd: i32, + events: i16, + revents: i16, +}; + pub const libc_stat = extern struct { - dev: u64, - ino: ino_t, - nlink: usize, - - mode: u16, - __pad0: u16, - uid: uid_t, - gid: gid_t, - __pad1: u32, - rdev: u64, - + dev: i32, + ino: u64, + mode: u32, + nlink: i32, + uid: i32, + gid: i32, + size: i64, + rdev: i32, + blksize: i32, atim: timespec, mtim: timespec, ctim: timespec, - birthtim: timespec, - - size: off_t, + crtim: timespec, + st_type: u32, blocks: i64, - blksize: isize, - flags: u32, - gen: u64, - __spare: [10]u64, 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 crtime(self: @This()) timespec { + return self.crtim; + } }; pub const timespec = extern struct { @@ -192,6 +197,34 @@ pub const image_info = extern struct { abi: i32, }; +pub const system_info = extern struct { + boot_time: i64, + cpu_count: u32, + max_pages: u64, + used_pages: u64, + cached_pages: u64, + block_cache_pages: u64, + ignored_pages: u64, + needed_memory: u64, + free_memory: u64, + max_swap_pages: u64, + free_swap_pages: u64, + page_faults: u32, + max_sems: u32, + used_sems: u32, + max_ports: u32, + used_ports: u32, + max_threads: u32, + used_threads: u32, + max_teams: u32, + used_teams: u32, + kernel_name: [256]u8, + kernel_build_date: [32]u8, + kernel_build_time: [32]u8, + kernel_version: i64, + abi: u32, +}; + pub const in_port_t = u16; pub const sa_family_t = u8; @@ -1408,3 +1441,10 @@ pub const rlimit = extern struct { pub const SHUT_RD = 0; pub const SHUT_WR = 1; pub const SHUT_RDWR = 2; + +// TODO fill out if needed +pub const directory_which = extern enum(c_int) { + B_USER_SETTINGS_DIRECTORY = 0xbbe, + + _, +}; diff --git a/lib/std/target.zig b/lib/std/target.zig index ece5361927..bf0492624d 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1566,8 +1566,7 @@ pub const Target = struct { .other, => return result, - // Operating systems in this list have been verified as not having a standard - // dynamic linker path. + // TODO revisit when multi-arch for Haiku is available .haiku => return copy(&result, "/system/runtime_loader"), // TODO go over each item in this list and either move it to the above list, or diff --git a/src/libc_installation.zig b/src/libc_installation.zig index 05c85578ea..6700787925 100644 --- a/src/libc_installation.zig +++ b/src/libc_installation.zig @@ -196,6 +196,7 @@ pub const LibCInstallation = struct { switch (Target.current.os.tag) { .freebsd, .netbsd, .openbsd => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"), .linux, .dragonfly => batch.add(&async self.findNativeCrtDirPosix(args)), + .haiku => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/system/develop/lib"), else => {}, } break :blk batch.wait();