Commit c17396691c

Al Hoang <3811822-hoanga@users.noreply.gitlab.com>
2021-01-17 20:29:00
initial support for haiku sync update
* add cpu count * use haiku find_directory * add definitions and exports for building in haiku
1 parent 6b03722
lib/std/c/haiku.zig
@@ -14,10 +14,21 @@ extern "c" fn _errnop() *c_int;
 
 pub const _errno = _errnop;
 
-pub extern "c" fn _kern_read_dir(fd: c_int, buf_ptr: [*]u8, nbytes: usize, maxcount: u32) usize;
+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 _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,
     _kern: extern struct {
@@ -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,
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,
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"),
     }
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 libc_stat = extern struct {
-    dev: u64,
-    ino: ino_t,
-    nlink: usize,
+pub const nfds_t = u32;
 
-    mode: u16,
-    __pad0: u16,
-    uid: uid_t,
-    gid: gid_t,
-    __pad1: u32,
-    rdev: u64,
+pub const pollfd = extern struct {
+    fd: i32,
+    events: i16,
+    revents: i16,
+};
 
+pub const libc_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,
-    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,
+
+    _,
+};
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,
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,
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
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");
         },
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();