2
0
Эх сурвалжийг харах

Merge pull request #4603 from avanspector/master

Haiku: fix build and add initial `core:sys/posix` support
Laytan 8 сар өмнө
parent
commit
e4ae832775
61 өөрчлөгдсөн 1583 нэмэгдсэн , 419 устгасан
  1. 1 1
      build_odin.sh
  2. 8 7
      core/c/libc/errno.odin
  3. 1 1
      core/c/libc/locale.odin
  4. 15 0
      core/c/libc/stdlib.odin
  5. 1 1
      core/c/libc/time.odin
  6. 1 1
      core/os/dir_unix.odin
  7. 25 9
      core/os/os_haiku.odin
  8. 1 1
      core/os/stat_unix.odin
  9. 1 1
      core/path/filepath/path_unix.odin
  10. 24 26
      core/sync/futex_haiku.odin
  11. 114 51
      core/sys/haiku/errno.odin
  12. 23 20
      core/sys/haiku/find_directory.odin
  13. 143 147
      core/sys/haiku/os.odin
  14. 8 6
      core/sys/haiku/types.odin
  15. 3 1
      core/sys/posix/arpa_inet.odin
  16. 19 8
      core/sys/posix/dirent.odin
  17. 88 1
      core/sys/posix/errno.odin
  18. 68 1
      core/sys/posix/fcntl.odin
  19. 2 2
      core/sys/posix/fnmatch.odin
  20. 3 3
      core/sys/posix/glob.odin
  21. 2 2
      core/sys/posix/grp.odin
  22. 3 3
      core/sys/posix/langinfo.odin
  23. 1 1
      core/sys/posix/libgen.odin
  24. 1 1
      core/sys/posix/locale.odin
  25. 1 1
      core/sys/posix/monetary.odin
  26. 19 2
      core/sys/posix/netdb.odin
  27. 45 16
      core/sys/posix/netinet_in.odin
  28. 36 13
      core/sys/posix/poll.odin
  29. 51 1
      core/sys/posix/pthread.odin
  30. 13 1
      core/sys/posix/pwd.odin
  31. 8 1
      core/sys/posix/sched.odin
  32. 148 1
      core/sys/posix/signal.odin
  33. 1 1
      core/sys/posix/signal_libc.odin
  34. 1 1
      core/sys/posix/stdio_libc.odin
  35. 1 1
      core/sys/posix/stdlib.odin
  36. 1 1
      core/sys/posix/stdlib_libc.odin
  37. 1 1
      core/sys/posix/string.odin
  38. 1 1
      core/sys/posix/string_libc.odin
  39. 24 1
      core/sys/posix/sys_ipc.odin
  40. 19 1
      core/sys/posix/sys_msg.odin
  41. 37 16
      core/sys/posix/sys_resource.odin
  42. 11 5
      core/sys/posix/sys_select.odin
  43. 27 1
      core/sys/posix/sys_sem.odin
  44. 56 10
      core/sys/posix/sys_socket.odin
  45. 31 1
      core/sys/posix/sys_stat.odin
  46. 12 1
      core/sys/posix/sys_time.odin
  47. 2 2
      core/sys/posix/sys_times.odin
  48. 2 2
      core/sys/posix/sys_uio.odin
  49. 9 1
      core/sys/posix/sys_un.odin
  50. 3 3
      core/sys/posix/sys_utsname.odin
  51. 53 1
      core/sys/posix/sys_wait.odin
  52. 172 12
      core/sys/posix/termios.odin
  53. 12 1
      core/sys/posix/time.odin
  54. 172 2
      core/sys/posix/unistd.odin
  55. 1 1
      core/sys/posix/unistd_libc.odin
  56. 2 2
      core/sys/posix/utime.odin
  57. 1 1
      core/testing/signal_handler_posix.odin
  58. 32 14
      tests/core/sys/posix/posix.odin
  59. 1 1
      tests/core/sys/posix/structs.odin
  60. 13 0
      tests/core/sys/posix/structs/structs.c
  61. 8 3
      tests/core/sys/posix/structs/structs.odin

+ 1 - 1
build_odin.sh

@@ -115,7 +115,7 @@ OpenBSD)
 	LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
 	;;
 Haiku)
-	CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags) -I/system/develop/headers/private/shared -I/system/develop/headers/private/kernel"
+	CXXFLAGS="$CXXFLAGS -D_GNU_SOURCE $($LLVM_CONFIG --cxxflags --ldflags) -I/system/develop/headers/private/shared -I/system/develop/headers/private/kernel"
 	LDFLAGS="$LDFLAGS -liconv"
 	LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
 	;;

+ 8 - 7
core/c/libc/errno.odin

@@ -88,14 +88,15 @@ when ODIN_OS == .Haiku {
 		_get_errno :: proc() -> ^int ---
 	}
 
-	@(private="file")
-	B_GENERAL_ERROR_BASE :: min(i32)
-	@(private="file")
-	B_POSIX_ERROR_BASE   :: B_GENERAL_ERROR_BASE + 0x7000
+	_HAIKU_USE_POSITIVE_POSIX_ERRORS :: #config(HAIKU_USE_POSITIVE_POSIX_ERRORS, false)
+	_POSIX_ERROR_FACTOR              :: -1 when _HAIKU_USE_POSITIVE_POSIX_ERRORS else 1
+
+	@(private="file") _GENERAL_ERROR_BASE :: min(int)
+	@(private="file") _POSIX_ERROR_BASE   :: _GENERAL_ERROR_BASE + 0x7000
 
-	EDOM   :: B_POSIX_ERROR_BASE + 16
-	EILSEQ :: B_POSIX_ERROR_BASE + 38
-	ERANGE :: B_POSIX_ERROR_BASE + 17
+	EDOM   :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 16)
+	EILSEQ :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 38)
+	ERANGE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 17)
 }
 
 when ODIN_OS == .JS {

+ 1 - 1
core/c/libc/locale.odin

@@ -110,7 +110,7 @@ when ODIN_OS == .Windows {
 	}
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD  || ODIN_OS == .OpenBSD || ODIN_OS == .Windows {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD  || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku || ODIN_OS == .Windows {
 
 	LC_ALL      :: 0
 	LC_COLLATE  :: 1

+ 15 - 0
core/c/libc/stdlib.odin

@@ -42,6 +42,21 @@ when ODIN_OS == .Linux {
 	}
 }
 
+when ODIN_OS == .Haiku {
+	RAND_MAX :: 0x7fffffff
+
+	// GLIBC and MUSL only
+	@(private="file")
+	@(default_calling_convention="c")
+	foreign libc {
+		__ctype_get_mb_cur_max :: proc() -> ushort ---
+	}
+
+	MB_CUR_MAX :: #force_inline proc() -> size_t {
+		return size_t(__ctype_get_mb_cur_max())
+	}
+}
+
 
 when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD {
 	RAND_MAX :: 0x7fffffff

+ 1 - 1
core/c/libc/time.odin

@@ -95,7 +95,7 @@ when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS =
 
 	time_t :: distinct i64
 
-	when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD {
+	when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku {
 		clock_t :: distinct int32_t
 	} else {
 		clock_t :: distinct long

+ 1 - 1
core/os/dir_unix.odin

@@ -1,4 +1,4 @@
-#+build darwin, linux, netbsd, freebsd, openbsd
+#+build darwin, linux, netbsd, freebsd, openbsd, haiku
 package os
 
 import "core:strings"

+ 25 - 9
core/os/os_haiku.odin

@@ -1,11 +1,13 @@
 package os
 
-foreign import libc "system:c"
+foreign import lib "system:c"
 
 import "base:runtime"
 import "core:c"
+import "core:c/libc"
 import "core:strings"
 import "core:sys/haiku"
+import "core:sys/posix"
 
 Handle    :: i32
 Pid       :: i32
@@ -14,7 +16,7 @@ _Platform_Error :: haiku.Errno
 
 MAX_PATH :: haiku.PATH_MAX
 
-ENOSYS :: _Platform_Error(i32(haiku.Errno.POSIX_ERROR_BASE) + 9)
+ENOSYS :: _Platform_Error(haiku.Errno.ENOSYS)
 
 INVALID_HANDLE :: ~Handle(0)
 
@@ -117,14 +119,13 @@ S_ISBLK  :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFBLK
 S_ISFIFO :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFIFO  }
 S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK }
 
+__error :: libc.errno
+_unix_open :: posix.open
 
-foreign libc {
-	@(link_name="_errorp")        __error              :: proc() -> ^c.int ---
-
+foreign lib {
 	@(link_name="fork")           _unix_fork           :: proc() -> pid_t ---
 	@(link_name="getthrid")       _unix_getthrid       :: proc() -> int ---
 
-	@(link_name="open")           _unix_open           :: proc(path: cstring, flags: c.int, #c_vararg mode: ..u16) -> Handle ---
 	@(link_name="close")          _unix_close          :: proc(fd: Handle) -> c.int ---
 	@(link_name="read")           _unix_read           :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="pread")          _unix_pread          :: proc(fd: Handle, buf: rawptr, size: c.size_t, offset: i64) -> c.ssize_t ---
@@ -150,6 +151,7 @@ foreign libc {
 	@(link_name="closedir")       _unix_closedir       :: proc(dirp: Dir) -> c.int ---
 	@(link_name="rewinddir")      _unix_rewinddir      :: proc(dirp: Dir) ---
 	@(link_name="readdir_r")      _unix_readdir_r      :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
+	@(link_name="dup")            _unix_dup            :: proc(fd: Handle) -> Handle ---
 
 	@(link_name="malloc")         _unix_malloc         :: proc(size: c.size_t) -> rawptr ---
 	@(link_name="calloc")         _unix_calloc         :: proc(num, size: c.size_t) -> rawptr ---
@@ -157,7 +159,7 @@ foreign libc {
 	@(link_name="realloc")        _unix_realloc        :: proc(ptr: rawptr, size: c.size_t) -> rawptr ---
 
 	@(link_name="getenv")         _unix_getenv         :: proc(cstring) -> cstring ---
-	@(link_name="realpath")       _unix_realpath       :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
+	@(link_name="realpath")       _unix_realpath       :: proc(path: cstring, resolved_path: [^]byte = nil) -> cstring ---
 
 	@(link_name="exit")           _unix_exit           :: proc(status: c.int) -> ! ---
 
@@ -203,7 +205,7 @@ fork :: proc() -> (Pid, Error) {
 open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
 	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
 	cstr := strings.clone_to_cstring(path, context.temp_allocator)
-	handle := _unix_open(cstr, c.int(flags), u16(mode))
+	handle := cast(Handle)_unix_open(cstr, transmute(posix.O_Flags)i32(flags), transmute(posix.mode_t)i32(mode))
 	if handle == -1 {
 		return INVALID_HANDLE, get_last_error()
 	}
@@ -444,7 +446,7 @@ absolute_path_from_relative :: proc(rel: string, allocator := context.allocator)
 	if path_ptr == nil {
 		return "", get_last_error()
 	}
-	defer _unix_free(path_ptr)
+	defer _unix_free(rawptr(path_ptr))
 
 	path_cstr := cstring(path_ptr)
 	return strings.clone(string(path_cstr), allocator)
@@ -488,3 +490,17 @@ exit :: proc "contextless" (code: int) -> ! {
 	runtime._cleanup_runtime_contextless()
 	_unix_exit(i32(code))
 }
+
+@(require_results)
+current_thread_id :: proc "contextless" () -> int {
+	return int(haiku.find_thread(nil))
+}
+
+@(private, require_results)
+_dup :: proc(fd: Handle) -> (Handle, Error) {
+	dup := _unix_dup(fd)
+	if dup == -1 {
+		return INVALID_HANDLE, get_last_error()
+	}
+	return dup, nil
+}

+ 1 - 1
core/os/stat_unix.odin

@@ -53,7 +53,7 @@ File_Info :: struct {
 @(private, require_results)
 _make_time_from_unix_file_time :: proc(uft: Unix_File_Time) -> time.Time {
 	return time.Time{
-		_nsec = uft.nanoseconds + uft.seconds * 1_000_000_000,
+		_nsec = i64(uft.nanoseconds) + i64(uft.seconds) * 1_000_000_000,
 	}
 }
 

+ 1 - 1
core/path/filepath/path_unix.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, freebsd, openbsd, netbsd
+#+build linux, darwin, freebsd, openbsd, netbsd, haiku
 package filepath
 
 import "base:runtime"

+ 24 - 26
core/sync/futex_haiku.odin

@@ -1,14 +1,13 @@
 #+private
 package sync
 
-import "core:c"
 import "core:sys/haiku"
-import "core:sys/unix"
+import "core:sys/posix"
 import "core:time"
 
 @(private="file")
 Wait_Node :: struct {
-	thread:     unix.pthread_t,
+	thread:     posix.pthread_t,
 	futex:      ^Futex,
 	prev, next: ^Wait_Node,
 }
@@ -58,7 +57,7 @@ _futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> (ok: bool) {
 
 	head   := &waitq.list
 	waiter := Wait_Node{
-		thread = unix.pthread_self(),
+		thread = posix.pthread_self(),
 		futex  = f,
 		prev   = head,
 		next   = head.next,
@@ -67,25 +66,24 @@ _futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> (ok: bool) {
 	waiter.prev.next = &waiter
 	waiter.next.prev = &waiter
 
-	old_mask, mask: haiku.sigset_t
-	haiku.sigemptyset(&mask)
-	haiku.sigaddset(&mask, haiku.SIGCONT)
-	unix.pthread_sigmask(haiku.SIG_BLOCK, &mask, &old_mask)
+	old_mask, mask: posix.sigset_t
+	posix.sigemptyset(&mask)
+	posix.sigaddset(&mask, .SIGCONT)
+	posix.pthread_sigmask(.BLOCK, &mask, &old_mask)
 
 	if u32(atomic_load_explicit(f, .Acquire)) == expect {
 		waitq_unlock(waitq)
 		defer waitq_lock(waitq)
 		
-		sig: c.int
-		haiku.sigwait(&mask, &sig)
-		errno := haiku.errno() 
-		ok = errno == .OK
+		sig: posix.Signal
+		errno := posix.sigwait(&mask, &sig) 
+		ok = errno == nil
 	}
 
 	waiter.prev.next = waiter.next
 	waiter.next.prev = waiter.prev
 
-	_ = unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil)
+	_ = posix.pthread_sigmask(.SETMASK, &old_mask, nil)
 
  	// FIXME: Add error handling!
 	return
@@ -101,7 +99,7 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration
 
 	head   := &waitq.list
 	waiter := Wait_Node{
-		thread = unix.pthread_self(),
+		thread = posix.pthread_self(),
 		futex  = f,
 		prev   = head,
 		next   = head.next,
@@ -110,29 +108,29 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration
 	waiter.prev.next = &waiter
 	waiter.next.prev = &waiter
 
-	old_mask, mask: haiku.sigset_t
-	haiku.sigemptyset(&mask)
-	haiku.sigaddset(&mask, haiku.SIGCONT)
-	unix.pthread_sigmask(haiku.SIG_BLOCK, &mask, &old_mask)
+	old_mask, mask: posix.sigset_t
+	posix.sigemptyset(&mask)
+	posix.sigaddset(&mask, .SIGCONT)
+	posix.pthread_sigmask(.BLOCK, &mask, &old_mask)
 
 	if u32(atomic_load_explicit(f, .Acquire)) == expect {
 		waitq_unlock(waitq)
 		defer waitq_lock(waitq)
 		
-		info: haiku.siginfo_t
-		ts := unix.timespec{
-			tv_sec  = i64(duration / 1e9),
+		info: posix.siginfo_t
+		ts := posix.timespec{
+			tv_sec  = posix.time_t(i64(duration / 1e9)),
 			tv_nsec = i64(duration % 1e9),
 		}
 		haiku.sigtimedwait(&mask, &info, &ts)
-		errno := haiku.errno() 
-		ok = errno == .EAGAIN || errno == .OK
+		errno := posix.errno() 
+		ok = errno == .EAGAIN || errno == nil
 	}
 
 	waiter.prev.next = waiter.next
 	waiter.next.prev = waiter.prev
 
-	unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil)
+	posix.pthread_sigmask(.SETMASK, &old_mask, nil)
 
 	// FIXME: Add error handling!
 	return
@@ -146,7 +144,7 @@ _futex_signal :: proc "contextless" (f: ^Futex) {
 	head := &waitq.list
 	for waiter := head.next; waiter != head; waiter = waiter.next {
 		if waiter.futex == f {
-			unix.pthread_kill(waiter.thread, haiku.SIGCONT)
+			posix.pthread_kill(waiter.thread, .SIGCONT)
 			break
 		}
 	}
@@ -160,7 +158,7 @@ _futex_broadcast :: proc "contextless" (f: ^Futex) {
 	head := &waitq.list
 	for waiter := head.next; waiter != head; waiter = waiter.next {
 		if waiter.futex == f {
-			unix.pthread_kill(waiter.thread, haiku.SIGCONT)
+			posix.pthread_kill(waiter.thread, .SIGCONT)
 		}
 	}
 }

+ 114 - 51
core/sys/haiku/errors.odin → core/sys/haiku/errno.odin

@@ -1,26 +1,31 @@
 #+build haiku
 package sys_haiku
 
-import "core:c"
-
-Errno :: enum c.int {
-	// Error baselines
-	GENERAL_ERROR_BASE     = min(c.int),
-	OS_ERROR_BASE          = GENERAL_ERROR_BASE + 0x1000,
-	APP_ERROR_BASE         = GENERAL_ERROR_BASE + 0x2000,
-	INTERFACE_ERROR_BASE   = GENERAL_ERROR_BASE + 0x3000,
-	MEDIA_ERROR_BASE       = GENERAL_ERROR_BASE + 0x4000,
-	TRANSLATION_ERROR_BASE = GENERAL_ERROR_BASE + 0x4800,
-	MIDI_ERROR_BASE        = GENERAL_ERROR_BASE + 0x5000,
-	STORAGE_ERROR_BASE     = GENERAL_ERROR_BASE + 0x6000,
-	POSIX_ERROR_BASE       = GENERAL_ERROR_BASE + 0x7000,
-	MAIL_ERROR_BASE        = GENERAL_ERROR_BASE + 0x8000,
-	PRINT_ERROR_BASE       = GENERAL_ERROR_BASE + 0x9000,
-	DEVICE_ERROR_BASE      = GENERAL_ERROR_BASE + 0xa000,
-
-	// Developer-defined errors start at (ERRORS_END+1)
-	ERRORS_END             = GENERAL_ERROR_BASE + 0xffff,
+import "core:sys/posix"
 
+foreign import libroot "system:c"
+
+USE_POSITIVE_POSIX_ERRORS :: posix._HAIKU_USE_POSITIVE_POSIX_ERRORS
+POSIX_ERROR_FACTOR        :: posix._POSIX_ERROR_FACTOR
+
+// Error baselines
+GENERAL_ERROR_BASE        :: min(i32)
+OS_ERROR_BASE             :: GENERAL_ERROR_BASE + 0x1000
+APP_ERROR_BASE            :: GENERAL_ERROR_BASE + 0x2000
+INTERFACE_ERROR_BASE      :: GENERAL_ERROR_BASE + 0x3000
+MEDIA_ERROR_BASE          :: GENERAL_ERROR_BASE + 0x4000
+TRANSLATION_ERROR_BASE    :: GENERAL_ERROR_BASE + 0x4800
+MIDI_ERROR_BASE           :: GENERAL_ERROR_BASE + 0x5000
+STORAGE_ERROR_BASE        :: GENERAL_ERROR_BASE + 0x6000
+POSIX_ERROR_BASE          :: GENERAL_ERROR_BASE + 0x7000
+MAIL_ERROR_BASE           :: GENERAL_ERROR_BASE + 0x8000
+PRINT_ERROR_BASE          :: GENERAL_ERROR_BASE + 0x9000
+DEVICE_ERROR_BASE         :: GENERAL_ERROR_BASE + 0xA000
+
+// Developer-defined errors start at (ERRORS_END+1)
+ERRORS_END                :: GENERAL_ERROR_BASE + 0xFFFF
+
+Errno :: enum i32 {
 	// General Errors
 	NO_MEMORY              = GENERAL_ERROR_BASE + 0,
 	IO_ERROR               = GENERAL_ERROR_BASE + 1,
@@ -107,31 +112,95 @@ Errno :: enum c.int {
 	PARTIAL_READ                      = STORAGE_ERROR_BASE + 16,
 	PARTIAL_WRITE                     = STORAGE_ERROR_BASE + 17,
 
-	// Some POSIX errors
-	E2BIG                             = POSIX_ERROR_BASE + 1,
-	EFBIG                             = POSIX_ERROR_BASE + 4,
-	ENODEV                            = POSIX_ERROR_BASE + 7,
-	ERANGE                            = POSIX_ERROR_BASE + 17,
-	EOVERFLOW                         = POSIX_ERROR_BASE + 41,
-	EOPNOTSUPP                        = POSIX_ERROR_BASE + 43,
-
-	ENOSYS                            = POSIX_ERROR_BASE + 9,
-	EAGAIN                            = WOULD_BLOCK,
+	EIO                          = posix.EIO,
+	EACCES                       = posix.EACCES,
+	EINVAL                       = posix.EINVAL,
+	ETIMEDOUT                    = posix.ETIMEDOUT,
+	EINTR                        = posix.EINTR,
+	EAGAIN                       = posix.EAGAIN,
+	EWOULDBLOCK                  = posix.EWOULDBLOCK,
+	EBUSY                        = posix.EBUSY,
+	EPERM                        = posix.EPERM,
+	EFAULT                       = posix.EFAULT,
+	ENOEXEC                      = posix.ENOEXEC,
+	EBADF                        = posix.EBADF,
+	EEXIST                       = posix.EEXIST,
+	ENOENT                       = posix.ENOENT,
+	ENAMETOOLONG                 = posix.ENAMETOOLONG,
+	ENOTDIR                      = posix.ENOTDIR,
+	ENOTEMPTY                    = posix.ENOTEMPTY,
+	ENOSPC                       = posix.ENOSPC,
+	EROFS                        = posix.EROFS,
+	EISDIR                       = posix.EISDIR,
+	EMFILE                       = posix.EMFILE,
+	EXDEV                        = posix.EXDEV,
+	ELOOP                        = posix.ELOOP,
+	EPIPE                        = posix.EPIPE,
+	ENOMEM                       = posix.ENOMEM,
+	E2BIG                        = posix.E2BIG,
+	ECHILD                       = posix.ECHILD,
+	EDEADLK                      = posix.EDEADLK,
+	EFBIG                        = posix.EFBIG,
+	EMLINK                       = posix.EMLINK,
+	ENFILE                       = posix.ENFILE,
+	ENODEV                       = posix.ENODEV,
+	ENOLCK                       = posix.ENOLCK,
+	ENOSYS                       = posix.ENOSYS,
+	ENOTTY                       = posix.ENOTTY,
+	ENXIO                        = posix.ENXIO,
+	ESPIPE                       = posix.ESPIPE,
+	ESRCH                        = posix.ESRCH,
+	EDOM                         = posix.EDOM,
+	ERANGE                       = posix.ERANGE,
+	EPROTOTYPE                   = posix.EPROTOTYPE,
+	EPROTONOSUPPORT              = posix.EPROTONOSUPPORT,
+	EAFNOSUPPORT                 = posix.EAFNOSUPPORT,
+	EADDRINUSE                   = posix.EADDRINUSE,
+	EADDRNOTAVAIL                = posix.EADDRNOTAVAIL,
+	ENETDOWN                     = posix.ENETDOWN,
+	ENETUNREACH                  = posix.ENETUNREACH,
+	ENETRESET                    = posix.ENETRESET,
+	ECONNABORTED                 = posix.ECONNABORTED,
+	ECONNRESET                   = posix.ECONNRESET,
+	EISCONN                      = posix.EISCONN,
+	ENOTCONN                     = posix.ENOTCONN,
+	ECONNREFUSED                 = posix.ECONNREFUSED,
+	EHOSTUNREACH                 = posix.EHOSTUNREACH,
+	ENOPROTOOPT                  = posix.ENOPROTOOPT,
+	ENOBUFS                      = posix.ENOBUFS,
+	EINPROGRESS                  = posix.EINPROGRESS,
+	EALREADY                     = posix.EALREADY,
+	EILSEQ                       = posix.EILSEQ,
+	ENOMSG                       = posix.ENOMSG,
+	ESTALE                       = posix.ESTALE,
+	EOVERFLOW                    = posix.EOVERFLOW,
+	EMSGSIZE                     = posix.EMSGSIZE,
+	EOPNOTSUPP                   = posix.EOPNOTSUPP,
+	ENOTSOCK                     = posix.ENOTSOCK,
+	EBADMSG                      = posix.EBADMSG,
+	ECANCELED                    = posix.ECANCELED,
+	EDESTADDRREQ                 = posix.EDESTADDRREQ,
+	EDQUOT                       = posix.EDQUOT,
+	EIDRM                        = posix.EIDRM,
+	EMULTIHOP                    = posix.EMULTIHOP,
+	ENODATA                      = posix.ENODATA,
+	ENOLINK                      = posix.ENOLINK,
+	ENOSR                        = posix.ENOSR,
+	ENOSTR                       = posix.ENOSTR,
+	ENOTSUP                      = posix.ENOTSUP,
+	EPROTO                       = posix.EPROTO,
+	ETIME                        = posix.ETIME,
+	ETXTBSY                      = posix.ETXTBSY,
+	ENOTRECOVERABLE              = posix.ENOTRECOVERABLE,
+	EOWNERDEAD                   = posix.EOWNERDEAD,
 
 	// New error codes that can be mapped to POSIX errors
-	TOO_MANY_ARGS_NEG                 = E2BIG,
-	FILE_TOO_LARGE_NEG                = EFBIG,
-	DEVICE_NOT_FOUND_NEG              = ENODEV,
-	RESULT_NOT_REPRESENTABLE_NEG      = ERANGE,
-	BUFFER_OVERFLOW_NEG               = EOVERFLOW,
-	NOT_SUPPORTED_NEG                 = EOPNOTSUPP,
-
-	TOO_MANY_ARGS_POS                 = -E2BIG,
-	FILE_TOO_LARGE_POS                = -EFBIG,
-	DEVICE_NOT_FOUND_POS              = -ENODEV,
-	RESULT_NOT_REPRESENTABLE_POS      = -ERANGE,
-	BUFFER_OVERFLOW_POS               = -EOVERFLOW,
-	NOT_SUPPORTED_POS                 = -EOPNOTSUPP,
+	TOO_MANY_ARGS                = POSIX_ERROR_FACTOR * E2BIG,
+	FILE_TOO_LARGE               = POSIX_ERROR_FACTOR * EFBIG,
+	DEVICE_NOT_FOUND             = POSIX_ERROR_FACTOR * ENODEV,
+	RESULT_NOT_REPRESENTABLE     = POSIX_ERROR_FACTOR * ERANGE,
+	BUFFER_OVERFLOW              = POSIX_ERROR_FACTOR * EOVERFLOW,
+	NOT_SUPPORTED                = POSIX_ERROR_FACTOR * EOPNOTSUPP,
 
 	// Media Kit Errors
 	STREAM_NOT_FOUND             = MEDIA_ERROR_BASE + 0,
@@ -226,14 +295,8 @@ Errno :: enum c.int {
 	ILLEGAL_DATA                 = TRANSLATION_ERROR_BASE + 2,
 }
 
-errno :: #force_inline proc "contextless" () -> Errno {
-	return Errno(_errnop()^)
-}
-
-foreign import libroot "system:c"
+@(default_calling_convention="c")
 foreign libroot {
-	_to_positive_error :: proc(error: c.int) -> c.int ---
-	_to_negative_error :: proc(error: c.int) -> c.int ---
-
-	_errnop :: proc() -> ^c.int ---
+	_to_positive_error :: proc(error: i32) -> i32 ---
+	_to_negative_error :: proc(error: i32) -> i32 ---
 }

+ 23 - 20
core/sys/haiku/find_directory.odin

@@ -1,9 +1,11 @@
 #+build haiku
 package sys_haiku
 
-import "core:c"
+import "base:intrinsics"
 
-directory_which :: enum c.int {
+foreign import libroot "system:c"
+
+directory_which :: enum i32 {
 	// Per volume directories
 	DESKTOP_DIRECTORY = 0,
 	TRASH_DIRECTORY,
@@ -110,17 +112,18 @@ directory_which :: enum c.int {
 	BEOS_SOUNDS_DIRECTORY,
 }
 
-find_path_flags :: enum c.int {
-	CREATE_DIRECTORY        = 0x0001,
-	CREATE_PARENT_DIRECTORY = 0x0002,
-	EXISTING_ONLY           = 0x0004,
+find_path_flag :: enum u32 {
+	CREATE_DIRECTORY        = intrinsics.constant_log2(0x0001),
+	CREATE_PARENT_DIRECTORY = intrinsics.constant_log2(0x0002),
+	EXISTING_ONLY           = intrinsics.constant_log2(0x0004),
 	
-	// find_paths() only!
-	SYSTEM_ONLY             = 0x0010,
-	USER_ONLY               = 0x0020,
+	// find_paths() only
+	SYSTEM_ONLY             = intrinsics.constant_log2(0x0010),
+	USER_ONLY               = intrinsics.constant_log2(0x0020),
 }
+find_path_flags :: distinct bit_set[find_path_flag; u32]
 
-path_base_directory :: enum c.int {
+path_base_directory :: enum i32 {
 	INSTALLATION_LOCATION_DIRECTORY,
 	ADD_ONS_DIRECTORY,
 	APPS_DIRECTORY,
@@ -146,7 +149,7 @@ path_base_directory :: enum c.int {
 	TRANSLATORS_DIRECTORY,
 	VAR_DIRECTORY,
 
-	// find_path() only!
+	// find_path() only
 	IMAGE_PATH = 1000,
 	PACKAGE_PATH,
 }
@@ -154,15 +157,15 @@ path_base_directory :: enum c.int {
 // value that can be used instead of a pointer to a symbol in the program image
 APP_IMAGE_SYMBOL :: rawptr(addr_t(0))
 // pointer to a symbol in the callers image (same as B_CURRENT_IMAGE_SYMBOL)
-current_image_symbol :: proc() -> rawptr { return rawptr(current_image_symbol) }
+current_image_symbol :: proc "contextless" () -> rawptr { return rawptr(current_image_symbol) }
 
-foreign import libroot "system:c"
+@(default_calling_convention="c")
 foreign libroot {
-	find_directory         :: proc(which: directory_which, volume: dev_t, createIt: bool, pathString: [^]c.char, length: i32) -> status_t ---
-	find_path              :: proc(codePointer: rawptr, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]c.char, bufferSize: c.size_t) -> status_t ---
-	find_path_etc          :: proc(codePointer: rawptr, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]c.char, bufferSize: c.size_t) -> status_t ---
-	find_path_for_path     :: proc(path: cstring, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]c.char, bufferSize: c.size_t) -> status_t ---
-	find_path_for_path_etc :: proc(path: cstring, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]c.char, bufferSize: c.size_t) -> status_t ---
-	find_paths             :: proc(baseDirectory: path_base_directory, subPath: cstring, _paths: ^[^][^]c.char, _pathCount: ^c.size_t) -> status_t ---
-	find_paths_etc         :: proc(architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, _paths: ^[^][^]c.char, _pathCount: ^c.size_t) -> status_t ---
+	find_directory         :: proc(which: directory_which, volume: dev_t, createIt: bool, pathString: [^]byte, length: i32) -> status_t ---
+	find_path              :: proc(codePointer: rawptr, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]byte, bufferSize: uint) -> status_t ---
+	find_path_etc          :: proc(codePointer: rawptr, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]byte, bufferSize: uint) -> status_t ---
+	find_path_for_path     :: proc(path: cstring, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]byte, bufferSize: uint) -> status_t ---
+	find_path_for_path_etc :: proc(path: cstring, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]byte, bufferSize: uint) -> status_t ---
+	find_paths             :: proc(baseDirectory: path_base_directory, subPath: cstring, _paths: ^[^][^]byte, _pathCount: ^uint) -> status_t ---
+	find_paths_etc         :: proc(architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, _paths: ^[^][^]byte, _pathCount: ^uint) -> status_t ---
 }

+ 143 - 147
core/sys/haiku/os.odin

@@ -1,8 +1,8 @@
 #+build haiku
 package sys_haiku
 
-import "core:c"
-import "core:sys/unix"
+import "base:intrinsics"
+import "core:sys/posix"
 
 foreign import libroot "system:c"
 
@@ -18,8 +18,8 @@ OS_NAME_LENGTH   :: 32
 
 area_info :: struct {
 	area:       area_id,
-	name:       [OS_NAME_LENGTH]c.char,
-	size:       c.size_t,
+	name:       [OS_NAME_LENGTH]byte,
+	size:       uint,
 	lock:       u32,
 	protection: u32,
 	team:       team_id,
@@ -31,11 +31,11 @@ area_info :: struct {
 }
 
 area_locking :: enum u32 {
-	NO_LOCK           = 0,
-	LAZY_LOCK         = 1,
-	FULL_LOCK         = 2,
-	CONTIGUOUS        = 3,
-	LOMEM             = 4, // CONTIGUOUS, < 16 MB physical address
+	NO_LOCK            = 0,
+	LAZY_LOCK          = 1,
+	FULL_LOCK          = 2,
+	CONTIGUOUS         = 3,
+	LOMEM              = 4, // CONTIGUOUS, < 16 MB physical address
 	_32_BIT_FULL_LOCK  = 5, // FULL_LOCK, < 4 GB physical addresses
 	_32_BIT_CONTIGUOUS = 6, // CONTIGUOUS, < 4 GB physical address
 }
@@ -52,27 +52,29 @@ address_spec :: enum u32 {
 	RANDOMIZED_BASE_ADDRESS = 7,
 }
 
-area_protection_flags :: enum u32 {
-	READ_AREA      = 1 << 0,
-	WRITE_AREA     = 1 << 1,
-	EXECUTE_AREA   = 1 << 2,
+area_protection_flag :: enum u32 {
+	READ_AREA      = 0,
+	WRITE_AREA     = 1,
+	EXECUTE_AREA   = 2,
 	// "stack" protection is not available on most platforms - it's used
 	// to only commit memory as needed, and have guard pages at the
 	// bottom of the stack.
-	STACK_AREA     = 1 << 3,
-	CLONEABLE_AREA = 1 << 8,
+	STACK_AREA     = 3,
+	CLONEABLE_AREA = 8,
 }
+area_protection_flags :: distinct bit_set[area_protection_flag; u32]
 
+@(default_calling_convention="c")
 foreign libroot {
-	create_area         :: proc(name: cstring, startAddress: ^rawptr, addressSpec: address_spec, size: c.size_t, lock: area_locking, protection: area_protection_flags) -> area_id ---
+	create_area         :: proc(name: cstring, startAddress: ^rawptr, addressSpec: address_spec, size: uint, lock: area_locking, protection: area_protection_flags) -> area_id ---
 	clone_area          :: proc(name: cstring, destAddress: ^rawptr, addressSpec: address_spec, protection: area_protection_flags, source: area_id) -> area_id ---
 	find_area           :: proc(name: cstring) -> area_id ---
 	area_for            :: proc(address: rawptr) -> area_id ---
 	delete_area         :: proc(id: area_id) -> status_t ---
-	resize_area         :: proc(id: area_id, newSize: c.size_t) -> status_t ---
+	resize_area         :: proc(id: area_id, newSize: uint) -> status_t ---
 	set_area_protection :: proc(id: area_id, newProtection: area_protection_flags) -> status_t ---
-	_get_area_info      :: proc(id: area_id, areaInfo: ^area_info, size: c.size_t) -> status_t ---
-	_get_next_area_info :: proc(team: team_id, cookie: ^c.ssize_t, areaInfo: ^area_info, size: c.size_t) -> status_t ---
+	_get_area_info      :: proc(id: area_id, areaInfo: ^area_info, size: uint) -> status_t ---
+	_get_next_area_info :: proc(team: team_id, cookie: ^int, areaInfo: ^area_info, size: uint) -> status_t ---
 }
 
 // Ports
@@ -80,33 +82,35 @@ foreign libroot {
 port_info :: struct {
 	port:        port_id,
 	team:        team_id,
-	name:        [OS_NAME_LENGTH]c.char,
+	name:        [OS_NAME_LENGTH]byte,
 	capacity:    i32, // queue depth
 	queue_count: i32, // # msgs waiting to be read
 	total_count: i32, // total # msgs read so far
 }
 
-port_flags :: enum u32 {
-	USE_USER_MEMCPY   = 0x80000000,
+port_flag :: enum u32 {
+	USE_USER_MEMCPY   = intrinsics.constant_log2(0x80000000),
 	// read the message, but don't remove it; kernel-only; memory must be locked
-	PEEK_PORT_MESSAGE = 0x100,
+	PEEK_PORT_MESSAGE = intrinsics.constant_log2(0x100),
 }
+port_flags :: distinct bit_set[port_flag; u32]
 
+@(default_calling_convention="c")
 foreign libroot {
 	create_port          :: proc(capacity: i32, name: cstring) -> port_id ---
 	find_port            :: proc(name: cstring) -> port_id ---
-	read_port            :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: c.size_t) -> c.ssize_t ---
-	read_port_etc        :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: c.size_t, flags: port_flags, timeout: bigtime_t) -> c.ssize_t ---
-	write_port           :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: c.size_t) -> status_t ---
-	write_port_etc       :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: c.size_t, flags: port_flags, timeout: bigtime_t) -> status_t ---
+	read_port            :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uint) -> int ---
+	read_port_etc        :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uint, flags: port_flags, timeout: bigtime_t) -> int ---
+	write_port           :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uint) -> status_t ---
+	write_port_etc       :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uint, flags: port_flags, timeout: bigtime_t) -> status_t ---
 	close_port           :: proc(port: port_id) -> status_t ---
 	delete_port          :: proc(port: port_id) -> status_t ---
-	port_buffer_size     :: proc(port: port_id) -> c.ssize_t ---
-	port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> c.ssize_t ---
-	port_count           :: proc(port: port_id) -> c.ssize_t ---
+	port_buffer_size     :: proc(port: port_id) -> int ---
+	port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> int ---
+	port_count           :: proc(port: port_id) -> int ---
 	set_port_owner       :: proc(port: port_id, team: team_id) -> status_t ---
-	_get_port_info       :: proc(port: port_id, portInfo: ^port_info, portInfoSize: c.size_t) -> status_t ---
-	_get_next_port_info  :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: c.size_t) -> status_t ---
+	_get_port_info       :: proc(port: port_id, portInfo: ^port_info, portInfoSize: uint) -> status_t ---
+	_get_next_port_info  :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: uint) -> status_t ---
 }
 
 // Semaphores
@@ -114,22 +118,24 @@ foreign libroot {
 sem_info :: struct {
 	sem:           sem_id,
 	team:          team_id,
-	name:          [OS_NAME_LENGTH]c.char,
+	name:          [OS_NAME_LENGTH]byte,
 	count:         i32,
 	latest_holder: thread_id,
 }
 
-semaphore_flags :: enum u32 {
-	CAN_INTERRUPT      = 0x01, // acquisition of the semaphore can be interrupted (system use only)
-	CHECK_PERMISSION   = 0x04, // ownership will be checked (system use only)
-	KILL_CAN_INTERRUPT = 0x20, // acquisition of the semaphore can be interrupted by SIGKILL[THR], even if not CAN_INTERRUPT (system use only)
+semaphore_flag :: enum u32 {
+	CAN_INTERRUPT      = intrinsics.constant_log2(0x01), // acquisition of the semaphore can be interrupted (system use only)
+	CHECK_PERMISSION   = intrinsics.constant_log2(0x04), // ownership will be checked (system use only)
+	KILL_CAN_INTERRUPT = intrinsics.constant_log2(0x20), // acquisition of the semaphore can be interrupted by SIGKILL[THR], even if not CAN_INTERRUPT (system use only)
 	
 	// release_sem_etc() only flags
-	DO_NOT_RESCHEDULE       = 0x02, // thread is not rescheduled
-	RELEASE_ALL             = 0x08, // all waiting threads will be woken up, count will be zeroed
-	RELEASE_IF_WAITING_ONLY	= 0x10, // release count only if there are any threads waiting
+	DO_NOT_RESCHEDULE       = intrinsics.constant_log2(0x02), // thread is not rescheduled
+	RELEASE_ALL             = intrinsics.constant_log2(0x08), // all waiting threads will be woken up, count will be zeroed
+	RELEASE_IF_WAITING_ONLY	= intrinsics.constant_log2(0x10), // release count only if there are any threads waiting
 }
+semaphore_flags :: distinct bit_set[semaphore_flag; u32]
 
+@(default_calling_convention="c")
 foreign libroot {
 	create_sem         :: proc(count: i32, name: cstring) -> sem_id ---
 	delete_sem         :: proc(id: sem_id) -> status_t ---
@@ -141,8 +147,8 @@ foreign libroot {
 	switch_sem_etc     :: proc(semToBeReleased: sem_id, id: sem_id, count: i32, flags: semaphore_flags, timeout: bigtime_t) -> status_t ---
 	get_sem_count      :: proc(id: sem_id, threadCount: ^i32) -> status_t ---
 	set_sem_owner      :: proc(id: sem_id, team: team_id) -> status_t ---
-	_get_sem_info      :: proc(id: sem_id, info: ^sem_info, infoSize: c.size_t) -> status_t ---
-	_get_next_sem_info :: proc(team: team_id, cookie: ^i32, info: ^sem_info, infoSize: c.size_t) -> status_t ---
+	_get_sem_info      :: proc(id: sem_id, info: ^sem_info, infoSize: uint) -> status_t ---
+	_get_next_sem_info :: proc(team: team_id, cookie: ^i32, info: ^sem_info, infoSize: uint) -> status_t ---
 }
 
 // Teams
@@ -155,7 +161,7 @@ team_info :: struct {
 	debugger_nub_thread: thread_id,
 	debugger_nub_port:   port_id,
 	argc:                i32,
-	args:                [64]c.char,
+	args:                [64]byte,
 	uid:                 uid_t,
 	gid:                 gid_t,
 
@@ -165,7 +171,7 @@ team_info :: struct {
 	group_id:            pid_t,
 	session_id:          pid_t,
 	parent:              team_id,
-	name:                [OS_NAME_LENGTH]c.char,
+	name:                [OS_NAME_LENGTH]byte,
 	start_time:          bigtime_t,
 }
 
@@ -183,17 +189,18 @@ team_usage_who :: enum i32 {
 	CHILDREN = -1,
 }
 
+@(default_calling_convention="c")
 foreign libroot {
 	// see also: send_signal()
 	kill_team            :: proc(team: team_id) -> status_t ---
-	_get_team_info       :: proc(id: team_id, info: ^team_info, size: c.size_t) -> status_t ---
-	_get_next_team_info  :: proc(cookie: ^i32, info: ^team_info, size: c.size_t) -> status_t ---
-	_get_team_usage_info :: proc(id: team_id, who: team_usage_who, info: ^team_usage_info, size: c.size_t) -> status_t ---
+	_get_team_info       :: proc(id: team_id, info: ^team_info, size: uint) -> status_t ---
+	_get_next_team_info  :: proc(cookie: ^i32, info: ^team_info, size: uint) -> status_t ---
+	_get_team_usage_info :: proc(id: team_id, who: team_usage_who, info: ^team_usage_info, size: uint) -> status_t ---
 }
 
 // Threads
 
-thread_state :: enum c.int {
+thread_state :: enum i32 {
 	RUNNING = 1,
 	READY,
 	RECEIVING,
@@ -205,7 +212,7 @@ thread_state :: enum c.int {
 thread_info :: struct {
 	thread:      thread_id,
 	team:        team_id,
-	name:        [OS_NAME_LENGTH]c.char,
+	name:        [OS_NAME_LENGTH]byte,
 	state:       thread_state,
 	priority:    thread_priority,
 	sem:         sem_id,
@@ -234,6 +241,7 @@ SYSTEM_TIMEBASE :: 0
 
 thread_func :: #type proc "c" (rawptr) -> status_t
 
+@(default_calling_convention="c")
 foreign libroot {
 	spawn_thread          :: proc(thread_func, name: cstring, priority: thread_priority, data: rawptr) -> thread_id ---
 	kill_thread           :: proc(thread: thread_id) -> status_t ---
@@ -247,24 +255,25 @@ foreign libroot {
 	wait_for_thread_etc   :: proc(id: thread_id, flags: u32, timeout: bigtime_t, _returnCode: ^status_t) -> status_t ---
 	on_exit_thread        :: proc(callback: proc "c" (rawptr), data: rawptr) -> status_t ---
 	find_thread           :: proc(name: cstring) -> thread_id ---
-	send_data             :: proc(thread: thread_id, code: i32, buffer: rawptr, bufferSize: c.size_t) -> status_t ---
-	receive_data          :: proc(sender: ^thread_id, buffer: rawptr, bufferSize: c.size_t) -> i32 ---
+	send_data             :: proc(thread: thread_id, code: i32, buffer: rawptr, bufferSize: uint) -> status_t ---
+	receive_data          :: proc(sender: ^thread_id, buffer: rawptr, bufferSize: uint) -> i32 ---
 	has_data              :: proc(thread: thread_id) -> bool ---
 	snooze                :: proc(amount: bigtime_t) -> status_t ---
 	// FIXME: Find and define those flags.
-	snooze_etc            :: proc(amount: bigtime_t, timeBase: c.int, flags: u32) -> status_t ---
-	snooze_until          :: proc(time: bigtime_t, timeBase: c.int) -> status_t ---
-	_get_thread_info      :: proc(id: thread_id, info: ^thread_info, size: c.size_t) -> status_t ---
-	_get_next_thread_info :: proc(team: team_id, cookie: ^i32, info: ^thread_info, size: c.size_t) -> status_t ---
+	snooze_etc            :: proc(amount: bigtime_t, timeBase: i32, flags: u32) -> status_t ---
+	snooze_until          :: proc(time: bigtime_t, timeBase: i32) -> status_t ---
+	_get_thread_info      :: proc(id: thread_id, info: ^thread_info, size: uint) -> status_t ---
+	_get_next_thread_info :: proc(team: team_id, cookie: ^i32, info: ^thread_info, size: uint) -> status_t ---
 	// bridge to the pthread API
 	get_pthread_thread_id :: proc(thread: pthread_t) -> thread_id ---
 }
 
 // Time
 
+@(default_calling_convention="c")
 foreign libroot {
-	real_time_clock       :: proc() -> c.ulong ---
-	set_real_time_clock   :: proc(secsSinceJan1st1970: c.ulong) ---
+	real_time_clock       :: proc() -> uint ---
+	set_real_time_clock   :: proc(secsSinceJan1st1970: uint) ---
 	real_time_clock_usecs :: proc() -> bigtime_t ---
 	// time since booting in microseconds
 	system_time           :: proc() -> bigtime_t ---
@@ -280,12 +289,14 @@ alarm_mode :: enum u32 {
 	PERIODIC_ALARM, // "when" specifies the period
 }
 
+@(default_calling_convention="c")
 foreign libroot {
 	set_alarm :: proc(_when: bigtime_t, mode: alarm_mode) -> bigtime_t ---
 }
 
 // Debugger
 
+@(default_calling_convention="c")
 foreign libroot {
 	debugger :: proc(message: cstring) ---
 	/*
@@ -296,7 +307,7 @@ foreign libroot {
 
 		to re-enable the default debugger pass a zero.
 	*/
-	disable_debugger :: proc(state: c.int) -> c.int ---
+	disable_debugger :: proc(state: i32) -> i32 ---
 }
 
 // System information
@@ -338,15 +349,15 @@ system_info :: struct {
 	max_teams:         u32,
 	used_teams:        u32,
 
-	kernel_name:       [FILE_NAME_LENGTH]c.char,
-	kernel_build_date: [OS_NAME_LENGTH]c.char,
-	kernel_build_time: [OS_NAME_LENGTH]c.char,
+	kernel_name:       [FILE_NAME_LENGTH]byte,
+	kernel_build_date: [OS_NAME_LENGTH]byte,
+	kernel_build_time: [OS_NAME_LENGTH]byte,
 
 	kernel_version:    i64,
 	abi:               u32,       // the system API
 }
 
-topology_level_type :: enum c.int {
+topology_level_type :: enum i32 {
 	UNKNOWN,
 	ROOT,
 	SMT,
@@ -354,7 +365,7 @@ topology_level_type :: enum c.int {
 	PACKAGE,
 }
 
-cpu_platform :: enum c.int {
+cpu_platform :: enum i32 {
 	UNKNOWN,
 	x86,
 	x86_64,
@@ -370,7 +381,7 @@ cpu_platform :: enum c.int {
 	RISC_V,
 }
 
-cpu_vendor :: enum c.int {
+cpu_vendor :: enum i32 {
 	UNKNOWN,
 	AMD,
 	CYRIX,
@@ -408,95 +419,80 @@ cpu_topology_node_info :: struct {
 	},
 }
 
-// FIXME: Add cpuid_info when bit fields are ready.
+when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 {
+	cpuid_info :: struct #raw_union {
+		eax_0: struct {
+			max_eax:   u32,
+			vendor_id: [12]byte,
+		},
+
+		eax_1: struct {
+			using _: bit_field u32 {
+				stepping:        u32 | 4,
+				model:           u32 | 4,
+				family:          u32 | 4,
+				type:            u32 | 2,
+				reserved_0:      u32 | 2,
+				extended_model:  u32 | 4,
+				extended_family: u32 | 8,
+				reserved_1:      u32 | 4,
+			},
+
+			using _: bit_field u32 {
+				brand_index:  u32 | 8,
+				clflush:      u32 | 8,
+				logical_cpus: u32 | 8,
+				apic_id:      u32 | 8,
+			},
+
+			features:          u32,
+			extended_features: u32,
+		},
+
+		eax_2: struct {
+			call_num:          u8,
+			cache_descriptors: [15]u8,
+		},
+
+		eax_3: struct {
+			reserved:           [2]u32,
+			serial_number_high: u32,
+			serial_number_low:  u32,
+		},
+
+		as_chars: [16]byte,
 
+		regs: struct {
+			eax: u32,
+			ebx: u32,
+			edx: u32,
+			ecx: u32,
+		},
+	}
+}
+
+@(default_calling_convention="c")
 foreign libroot {
 	get_system_info       :: proc(info: ^system_info) -> status_t ---
-	_get_cpu_info_etc     :: proc(firstCPU: u32, cpuCount: u32, info: ^cpu_info, size: c.size_t) -> status_t ---
+	_get_cpu_info_etc     :: proc(firstCPU: u32, cpuCount: u32, info: ^cpu_info, size: uint) -> status_t ---
 	get_cpu_topology_info :: proc(topologyInfos: [^]cpu_topology_node_info, topologyInfoCount: ^u32) -> status_t ---
 
-	is_computer_on        :: proc() -> i32 ---
-	is_computer_on_fire   :: proc() -> f64 ---
-}
-
-// Signal.h
-
-SIG_BLOCK   :: 1
-SIG_UNBLOCK :: 2
-SIG_SETMASK :: 3
-
-/*
- * The list of all defined signals:
- *
- * The numbering of signals for Haiku attempts to maintain
- * some consistency with UN*X conventions so that things
- * like "kill -9" do what you expect.
- */
-
-SIGHUP     :: 1  // hangup -- tty is gone!
-SIGINT     :: 2  // interrupt
-SIGQUIT    :: 3  // `quit' special character typed in tty
-SIGILL     :: 4  // illegal instruction
-SIGCHLD    :: 5  // child process exited
-SIGABRT    :: 6  // abort() called, dont' catch
-SIGPIPE    :: 7  // write to a pipe w/no readers
-SIGFPE     :: 8  // floating point exception
-SIGKILL    :: 9  // kill a team (not catchable)
-SIGSTOP    :: 10 // suspend a thread (not catchable)
-SIGSEGV    :: 11 // segmentation violation (read: invalid pointer)
-SIGCONT    :: 12 // continue execution if suspended
-SIGTSTP    :: 13 // `stop' special character typed in tty
-SIGALRM    :: 14 // an alarm has gone off (see alarm())
-SIGTERM    :: 15 // termination requested
-SIGTTIN    :: 16 // read of tty from bg process
-SIGTTOU    :: 17 // write to tty from bg process
-SIGUSR1    :: 18 // app defined signal 1
-SIGUSR2    :: 19 // app defined signal 2
-SIGWINCH   :: 20 // tty window size changed
-SIGKILLTHR :: 21 // be specific: kill just the thread, not team
-SIGTRAP    :: 22 // Trace/breakpoint trap
-SIGPOLL    :: 23 // Pollable event
-SIGPROF    :: 24 // Profiling timer expired
-SIGSYS     :: 25 // Bad system call
-SIGURG     :: 26 // High bandwidth data is available at socket
-SIGVTALRM  :: 27 // Virtual timer expired
-SIGXCPU    :: 28 // CPU time limit exceeded
-SIGXFSZ    :: 29 // File size limit exceeded
-SIGBUS     :: 30 // access to undefined portion of a memory object
-
-sigval :: struct #raw_union {
-	sival_int: c.int,
-	sival_ptr: rawptr,
-}
-
-siginfo_t :: struct {
-	si_signo:  c.int,  // signal number
-	si_code:   c.int,  // signal code
-	si_errno:  c.int,  // if non zero, an error number associated with this signal
-
-	si_pid:    pid_t,  // sending process ID
-	si_uid:    uid_t,  // real user ID of sending process
-	si_addr:   rawptr, // address of faulting instruction
-	si_status: c.int,  // exit value or signal
-	si_band:   c.long, // band event for SIGPOLL
-	si_value:  sigval, // signal value
+	when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 {
+		get_cpuid :: proc(info: ^cpuid_info, eaxRegister: u32, cpuNum: u32) -> status_t ---
+	}
+
+	is_computer_on      :: proc() -> i32 ---
+	is_computer_on_fire :: proc() -> f64 ---
 }
 
+// POSIX signals
+
+@(default_calling_convention="c")
 foreign libroot {
-	// signal set (sigset_t) manipulation
-	sigemptyset  :: proc(set: ^sigset_t) -> c.int ---
-	sigfillset   :: proc(set: ^sigset_t) -> c.int ---
-	sigaddset    :: proc(set: ^sigset_t, _signal: c.int) -> c.int ---
-	sigdelset    :: proc(set: ^sigset_t, _signal: c.int) -> c.int ---
-	sigismember  :: proc(set: ^sigset_t, _signal: c.int) -> c.int ---
-	// querying and waiting for signals
-	sigpending   :: proc(set: ^sigset_t) -> c.int ---
-	sigsuspend   :: proc(mask: ^sigset_t) -> c.int ---
-	sigpause     :: proc(_signal: c.int) -> c.int ---
-	sigwait      :: proc(set: ^sigset_t, _signal: ^c.int) -> c.int ---
-	sigwaitinfo  :: proc(set: ^sigset_t, info: ^siginfo_t) -> c.int ---
-	sigtimedwait :: proc(set: ^sigset_t, info: ^siginfo_t, timeout: ^unix.timespec) -> c.int ---
-
-	send_signal      :: proc(threadID: thread_id, signal: c.uint) -> c.int ---
-	set_signal_stack :: proc(base: rawptr, size: c.size_t) ---
+	/*
+	Wait for queued signals.
+
+	[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html ]]
+	*/
+	sigtimedwait :: proc(set: ^posix.sigset_t, info: ^posix.siginfo_t, timeout: ^posix.timespec) -> posix.result ---
 }

+ 8 - 6
core/sys/haiku/types.odin

@@ -1,9 +1,7 @@
 #+build haiku
 package sys_haiku
 
-import "core:c"
-
-status_t       :: i32
+status_t       :: Errno
 bigtime_t      :: i64
 nanotime_t     :: i64
 type_code      :: u32
@@ -37,16 +35,20 @@ mode_t         :: u32
 umode_t        :: u32
 nlink_t        :: i32
 
-caddr_t        :: ^c.char
+caddr_t        :: [^]byte
 
 addr_t         :: phys_addr_t
 key_t          :: i32
 
 clockid_t      :: i32
 
-time_t         :: i64 when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 else i32
+time_t   :: int
+timespec :: struct {
+	tv_sec:  time_t,
+	tv_nsec: int,
+}
 
-sig_atomic_t   :: c.int
+sig_atomic_t   :: i32
 sigset_t       :: u64
 
 image_id       :: i32

+ 3 - 1
core/sys/posix/arpa_inet.odin

@@ -1,10 +1,12 @@
-#+build darwin, linux, freebsd, openbsd, netbsd
+#+build darwin, linux, freebsd, openbsd, netbsd, haiku
 package posix
 
 import "core:c"
 
 when ODIN_OS == .Darwin {
 	foreign import lib "system:System.framework"
+} else when ODIN_OS == .Haiku {
+	foreign import lib "system:network"
 } else {
 	foreign import lib "system:c"
 }

+ 19 - 8
core/sys/posix/dirent.odin

@@ -1,4 +1,4 @@
-#+build darwin, linux, freebsd, openbsd, netbsd
+#+build darwin, linux, freebsd, openbsd, netbsd, haiku
 package posix
 
 import "core:c"
@@ -219,12 +219,23 @@ when ODIN_OS == .Darwin {
 
 } else when ODIN_OS == .Linux {
 
-		dirent :: struct {
-			d_ino:    u64,                     /* [PSX] file number of entry */
-			d_off:    i64,                     /* directory offset of the next entry */
-			d_reclen: u16,                     /* length of this record */
-			d_type:   D_Type,                  /* file type  */
-			d_name:   [256]c.char `fmt:"s,0"`, /* [PSX] entry name */
-		}
+	dirent :: struct {
+		d_ino:    u64,                     /* [PSX] file number of entry */
+		d_off:    i64,                     /* directory offset of the next entry */
+		d_reclen: u16,                     /* length of this record */
+		d_type:   D_Type,                  /* file type  */
+		d_name:   [256]c.char `fmt:"s,0"`, /* [PSX] entry name */
+	}
+
+} else when ODIN_OS == .Haiku {
+
+	dirent :: struct {
+		d_dev:    dev_t,                 /* device */
+		d_pdev:   dev_t,                 /* parent device (only for queries) */
+		d_ino:    ino_t,                 /* inode number */
+		d_pino:   ino_t,                 /* parent inode (only for queries) */
+		d_reclen: c.ushort,              /* length of this record, not the name */
+		d_name:   [0]c.char `fmt:"s,0"`, /* name of the entry (null byte terminated) */
+	}
 
 }

+ 88 - 1
core/sys/posix/errno.odin

@@ -1,4 +1,4 @@
-#+build windows, darwin, linux, freebsd, openbsd, netbsd
+#+build windows, darwin, linux, freebsd, openbsd, netbsd, haiku
 package posix
 
 import "core:c"
@@ -536,5 +536,92 @@ when ODIN_OS == .Darwin {
 	ETXTBSY         :: 139
 	EWOULDBLOCK     :: 140
 	EXDEV           :: 18
+} else when ODIN_OS == .Haiku {
+	_HAIKU_USE_POSITIVE_POSIX_ERRORS :: libc._HAIKU_USE_POSITIVE_POSIX_ERRORS
+	_POSIX_ERROR_FACTOR              :: libc._POSIX_ERROR_FACTOR
+	
+	_GENERAL_ERROR_BASE :: min(c.int)
+	_OS_ERROR_BASE      :: _GENERAL_ERROR_BASE + 0x1000
+	_STORAGE_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x6000
+	_POSIX_ERROR_BASE   :: _GENERAL_ERROR_BASE + 0x7000
+
+	EIO             :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 1)     // B_IO_ERROR
+	EACCES          :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 2)     // B_PERMISSION_DENIED
+	EINVAL          :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 5)     // B_BAD_VALUE
+	ETIMEDOUT       :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 9)     // B_TIMED_OUT
+	EINTR           :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 10)    // B_INTERRUPTED
+	EAGAIN          :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 11)    // B_WOULD_BLOCK /* SysV compatibility */
+	EWOULDBLOCK     :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 11)    // B_WOULD_BLOCK /* BSD compatibility */
+	EBUSY           :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 14)    // B_BUSY
+	EPERM           :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 15)    // B_NOT_ALLOWED
+	EFAULT          :: _POSIX_ERROR_FACTOR * (_OS_ERROR_BASE      + 0x301) // B_BAD_ADDRESS
+	ENOEXEC         :: _POSIX_ERROR_FACTOR * (_OS_ERROR_BASE      + 0x302) // B_NOT_AN_EXECUTABLE
+	EBADF           :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 0)     // B_FILE_ERROR
+	EEXIST          :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 2)     // B_FILE_EXISTS
+	ENOENT          :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 3)     // B_ENTRY_NOT_FOUND
+	ENAMETOOLONG    :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 4)     // B_NAME_TOO_LONG
+	ENOTDIR         :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 5)     // B_NOT_A_DIRECTORY
+	ENOTEMPTY       :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 6)     // B_DIRECTORY_NOT_EMPTY
+	ENOSPC          :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 7)     // B_DEVICE_FULL
+	EROFS           :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 8)     // B_READ_ONLY_DEVICE
+	EISDIR          :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 9)     // B_IS_A_DIRECTORY
+	EMFILE          :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 10)    // B_NO_MORE_FDS
+	EXDEV           :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 11)    // B_CROSS_DEVICE_LINK
+	ELOOP           :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 12)    // B_LINK_LIMIT
+	EPIPE           :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 13)    // B_BUSTED_PIPE
+	ENOMEM          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 0) when _HAIKU_USE_POSITIVE_POSIX_ERRORS else (_GENERAL_ERROR_BASE + 0) // B_NO_MEMORY
+	E2BIG           :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 1)
+	ECHILD          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 2)
+	EDEADLK         :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 3)
+	EFBIG           :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 4)
+	EMLINK          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 5)
+	ENFILE          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 6)
+	ENODEV          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 7)
+	ENOLCK          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 8)
+	ENOSYS          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 9)
+	ENOTTY          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 10)
+	ENXIO           :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 11)
+	ESPIPE          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 12)
+	ESRCH           :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 13)
+	EPROTOTYPE      :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 18)
+	EPROTONOSUPPORT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 19)
+	EAFNOSUPPORT    :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 21)
+	EADDRINUSE      :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 22)
+	EADDRNOTAVAIL   :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 23)
+	ENETDOWN        :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 24)
+	ENETUNREACH     :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 25)
+	ENETRESET       :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 26)
+	ECONNABORTED    :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 27)
+	ECONNRESET      :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 28)
+	EISCONN         :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 29)
+	ENOTCONN        :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 30)
+	ECONNREFUSED    :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 32)
+	EHOSTUNREACH    :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 33)
+	ENOPROTOOPT     :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 34)
+	ENOBUFS         :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 35)
+	EINPROGRESS     :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 36)
+	EALREADY        :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 37)
+	ENOMSG          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 39)
+	ESTALE          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 40)
+	EOVERFLOW       :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 41)
+	EMSGSIZE        :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 42)
+	EOPNOTSUPP      :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 43)
+	ENOTSOCK        :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 44)
+	EBADMSG         :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 46)
+	ECANCELED       :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 47)
+	EDESTADDRREQ    :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 48)
+	EDQUOT          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 49)
+	EIDRM           :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 50)
+	EMULTIHOP       :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 51)
+	ENODATA         :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 52)
+	ENOLINK         :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 53)
+	ENOSR           :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 54)
+	ENOSTR          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 55)
+	ENOTSUP         :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 56)
+	EPROTO          :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 57)
+	ETIME           :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 58)
+	ETXTBSY         :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 59)
+	ENOTRECOVERABLE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 61)
+	EOWNERDEAD      :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE   + 62)
 }
 

+ 68 - 1
core/sys/posix/fcntl.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, openbsd, freebsd, netbsd
+#+build linux, darwin, openbsd, freebsd, netbsd, haiku
 package posix
 
 import "core:c"
@@ -343,6 +343,7 @@ when ODIN_OS == .Darwin {
 		l_type:   Lock_Type, /* [PSX] type of lock */
 		l_whence: c.short,   /* [PSX] flag (Whence) of starting offset */
 	}
+
 } else when ODIN_OS == .OpenBSD {
 
 	off_t :: distinct c.int64_t
@@ -408,6 +409,72 @@ when ODIN_OS == .Darwin {
 		l_whence: c.short,   /* [PSX] flag (Whence) of starting offset */
 	}
 
+} else when ODIN_OS == .Haiku {
+
+	off_t :: distinct c.int64_t
+	pid_t :: distinct c.int32_t
+
+	/* commands that can be passed to fcntl() */
+	F_DUPFD         :: 0x0001 /* duplicate fd */
+	F_GETFD         :: 0x0002 /* get fd flags */
+	F_SETFD         :: 0x0004 /* set fd flags */
+	F_GETFL         :: 0x0008 /* get file status flags and access mode */
+	F_SETFL         :: 0x0010 /* set file status flags */
+	F_GETLK         :: 0x0020 /* get locking information */
+	F_SETLK         :: 0x0080 /* set locking information */
+	F_SETLKW        :: 0x0100 /* as above, but waits if blocked */
+	F_DUPFD_CLOEXEC :: 0x0200 /* duplicate fd with close on exec set */
+	F_GETOWN        :: -1 // NOTE: Not supported.
+	F_SETOWN        :: -1 // NOTE: Not supported.
+
+	/* advisory locking types */
+	F_RDLCK :: 0x0040 /* read or shared lock */
+	F_UNLCK :: 0x0200 /* unlock */
+	F_WRLCK :: 0x0400 /* write or exclusive lock */
+
+	/* file descriptor flags for fcntl() */
+	FD_CLOEXEC :: 1
+
+	O_CLOEXEC   :: 0x00000040
+	O_CREAT     :: 0x0200
+	O_DIRECTORY :: 0x00200000
+	O_EXCL      :: 0x0100
+	O_NOCTTY    :: 0x1000
+	O_NOFOLLOW  :: 0x00080000
+	O_TRUNC     :: 0x0400
+
+	_O_TTY_INIT :: 0
+	O_TTY_INIT  :: O_Flags{} // NOTE: not defined in the headers
+
+	O_APPEND   :: 0x0800
+	O_DSYNC    :: 0x040000
+	O_NONBLOCK :: 0x0080
+	O_SYNC     :: 0x010000
+	O_RSYNC    :: 0x020000
+
+	O_EXEC   :: 0x04000000 // NOTE: not defined in the headers
+	O_RDONLY :: 0
+	O_RDWR   :: 0x0002
+	O_WRONLY :: 0x0001
+
+	_O_SEARCH :: 0
+	O_SEARCH  :: O_Flags{} // NOTE: not defined in the headers
+
+	AT_FDCWD: FD: -100
+
+	AT_EACCESS          :: 0x08
+	AT_SYMLINK_NOFOLLOW :: 0x01
+	AT_SYMLINK_FOLLOW   :: 0x02
+	AT_REMOVEDIR        :: 0x04
+
+	flock :: struct {
+		l_type:   Lock_Type, /* [PSX] type of lock */
+		l_whence: c.short,   /* [PSX] flag (Whence) of starting offset */
+		l_start:  off_t,     /* [PSX] relative offset in bytes */
+		l_len:    off_t,     /* [PSX] size; if 0 then until EOF */
+		l_pid:    pid_t,     /* [PSX] process ID of the process holding the lock */
+	}
+
 } else when ODIN_OS == .Linux {
 
 	off_t :: distinct c.int64_t

+ 2 - 2
core/sys/posix/fnmatch.odin

@@ -1,4 +1,4 @@
-#+build darwin, linux, openbsd, freebsd, netbsd
+#+build darwin, linux, openbsd, freebsd, netbsd, haiku
 package posix
 
 import "core:c"
@@ -46,7 +46,7 @@ FNM_Flag_Bits :: enum c.int {
 }
 FNM_Flags :: bit_set[FNM_Flag_Bits; c.int]
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku {
 
 	FNM_NOMATCH  :: 1
 

+ 3 - 3
core/sys/posix/glob.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -109,7 +109,7 @@ when ODIN_OS == .Darwin {
 	GLOB_NOMATCH :: -3
 	GLOB_NOSPACE :: -1
 
-} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD {
+} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku {
 
 	glob_t :: struct {
 		gl_pathc:  c.size_t,                      /* [PSX] count of paths matched by pattern */
@@ -134,7 +134,7 @@ when ODIN_OS == .Darwin {
 	GLOB_ERR      :: 0x0004
 	GLOB_MARK     :: 0x0008
 	GLOB_NOCHECK  :: 0x0010
-	GLOB_NOESCAPE :: 0x2000 when ODIN_OS == .FreeBSD else 0x0100
+	GLOB_NOESCAPE :: 0x2000 when ODIN_OS == .FreeBSD || ODIN_OS == .Haiku else 0x0100
 	GLOB_NOSORT   :: 0x0020
 
 	GLOB_ABORTED :: -2

+ 2 - 2
core/sys/posix/grp.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -115,7 +115,7 @@ foreign lib {
 	getgrnam_r :: proc(name: cstring, grp: ^group, buffer: [^]byte, bufsize: c.size_t, result: ^^group) -> Errno ---
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku || ODIN_OS == .Linux {
 
 	gid_t :: distinct c.uint32_t
 

+ 3 - 3
core/sys/posix/langinfo.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -143,7 +143,7 @@ nl_item :: enum nl_item_t {
 	CRNCYSTR    = CRNCYSTR,
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .Haiku {
 
 	// NOTE: declared with `_t` so we can enumerate the real `nl_info`.
 	nl_item_t :: distinct c.int
@@ -210,7 +210,7 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD {
 	YESEXPR :: 52
 	NOEXPR  :: 53
 
-	CRNCYSTR :: 56
+	CRNCYSTR :: 54 when ODIN_OS == .Haiku else 56
 
 } else when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
 

+ 1 - 1
core/sys/posix/libgen.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 when ODIN_OS == .Darwin {

+ 1 - 1
core/sys/posix/locale.odin

@@ -1,4 +1,4 @@
-#+build windows, linux, darwin, netbsd, openbsd, freebsd
+#+build windows, linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c/libc"

+ 1 - 1
core/sys/posix/monetary.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"

+ 19 - 2
core/sys/posix/netdb.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -319,7 +319,7 @@ Info_Errno :: enum c.int {
 	OVERFLOW = EAI_OVERFLOW,
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	hostent :: struct {
 		h_name:      cstring,                /* [PSX] official name of host */
@@ -431,6 +431,23 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		NI_NUMERICSCOPE :: 0x100
 		NI_DGRAM        :: 16
 
+	} else when ODIN_OS == .Haiku {
+
+		AI_PASSIVE     :: 0x001
+		AI_CANONNAME   :: 0x002
+		AI_NUMERICHOST :: 0x004
+		AI_NUMERICSERV :: 0x008
+		AI_V4MAPPED    :: 0x800
+		AI_ALL         :: 0x100
+		AI_ADDRCONFIG  :: 0x400
+
+		NI_NOFQDN       :: 0x01
+		NI_NUMERICHOST  :: 0x02
+		NI_NAMEREQD     :: 0x04
+		NI_NUMERICSERV  :: 0x08
+		NI_DGRAM        :: 0x10
+		NI_NUMERICSCOPE :: 0x40
+
 	}
 
 	when ODIN_OS == .OpenBSD {

+ 45 - 16
core/sys/posix/netinet_in.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -31,20 +31,31 @@ Protocol :: enum c.int {
 	UDP  = IPPROTO_UDP,
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	in_addr :: struct {
 		s_addr: in_addr_t, /* [PSX] big endian address */
 	}
 
-	in6_addr :: struct {
-		using _: struct #raw_union {
-			s6_addr:     [16]c.uint8_t, /* [PSX] big endian address */
-			__u6_addr16: [8]c.uint16_t,
-			__u6_addr32: [4]c.uint32_t,
-		},
+	when ODIN_OS == .Haiku {
+		in6_addr :: struct #packed {
+			using _: struct #raw_union {
+				s6_addr:     [16]c.uint8_t, /* [PSX] big endian address */
+				__u6_addr16: [8]c.uint16_t,
+				__u6_addr32: [4]c.uint32_t,
+			},
+		}
+	} else {
+		in6_addr :: struct {
+			using _: struct #raw_union {
+				s6_addr:     [16]c.uint8_t, /* [PSX] big endian address */
+				__u6_addr16: [8]c.uint16_t,
+				__u6_addr32: [4]c.uint32_t,
+			},
+		}
 	}
 
+
 	when ODIN_OS == .Linux {
 
 		sockaddr_in :: struct {
@@ -77,12 +88,20 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 
 	} else {
 
+		when ODIN_OS == .Haiku {
+			@(private)
+			_SIN_ZEROSIZE :: 24
+		} else {
+			@(private)
+			_SIN_ZEROSIZE :: 8
+		}
+
 		sockaddr_in :: struct {
 			sin_len:    c.uint8_t,
 			sin_family: sa_family_t, /* [PSX] AF_INET (but a smaller size) */
 			sin_port:   in_port_t,   /* [PSX] port number */
 			sin_addr:   in_addr,     /* [PSX] IP address */
-			sin_zero:   [8]c.char,
+			sin_zero:   [_SIN_ZEROSIZE]c.char,
 		}
 
 		sockaddr_in6 :: struct {
@@ -99,13 +118,23 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 			ipv6mr_interface: c.uint,   /* [PSX] interface index */
 		}
 
-		IPV6_JOIN_GROUP     :: 12
-		IPV6_LEAVE_GROUP    :: 13
-		IPV6_MULTICAST_HOPS :: 10
-		IPV6_MULTICAST_IF   :: 9
-		IPV6_MULTICAST_LOOP :: 11
-		IPV6_UNICAST_HOPS   :: 4
-		IPV6_V6ONLY         :: 27
+		when ODIN_OS == .Haiku {
+			IPV6_JOIN_GROUP     :: 28
+			IPV6_LEAVE_GROUP    :: 29
+			IPV6_MULTICAST_HOPS :: 25
+			IPV6_MULTICAST_IF   :: 24
+			IPV6_MULTICAST_LOOP :: 26
+			IPV6_UNICAST_HOPS   :: 27
+			IPV6_V6ONLY         :: 30	
+		} else {
+			IPV6_JOIN_GROUP     :: 12
+			IPV6_LEAVE_GROUP    :: 13
+			IPV6_MULTICAST_HOPS :: 10
+			IPV6_MULTICAST_IF   :: 9
+			IPV6_MULTICAST_LOOP :: 11
+			IPV6_UNICAST_HOPS   :: 4
+			IPV6_V6ONLY         :: 27
+		}
 
 	}
 

+ 36 - 13
core/sys/posix/poll.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "base:intrinsics"
@@ -25,7 +25,11 @@ foreign lib {
 	poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: c.int) -> c.int ---
 }
 
-nfds_t :: c.uint
+when ODIN_OS == .Haiku {
+	nfds_t :: c.ulong
+} else {
+	nfds_t :: c.uint
+}
 
 Poll_Event_Bits :: enum c.short {
 	// Data other than high-priority data may be read without blocking.
@@ -53,7 +57,7 @@ Poll_Event_Bits :: enum c.short {
 }
 Poll_Event :: bit_set[Poll_Event_Bits; c.short]
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku {
 
 	pollfd :: struct {
 		fd:      FD,         /* [PSX] the following descriptor being polled */
@@ -61,17 +65,36 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		revents: Poll_Event, /* [PSX] the output event flags */
 	}
 
-	POLLIN     :: 0x0001
-	POLLRDNORM :: 0x0040
-	POLLRDBAND :: 0x0080
-	POLLPRI    :: 0x0002
-	POLLOUT    :: 0x0004
-	POLLWRNORM :: POLLOUT
-	POLLWRBAND :: 0x0100
+	when ODIN_OS == .Haiku {
+
+		POLLIN     :: 0x0001 /* any readable data available */
+		POLLOUT    :: 0x0002 /* file descriptor is writeable */
+		POLLRDNORM :: POLLIN
+		POLLWRNORM :: POLLOUT
+		POLLRDBAND :: 0x0008 /* priority readable data */
+		POLLWRBAND :: 0x0010 /* priority data can be written */
+		POLLPRI    :: 0x0020 /* high priority readable data */
+
+		POLLERR    :: 0x0004 /* errors pending */
+		POLLHUP    :: 0x0080 /* disconnected */
+		POLLNVAL   :: 0x1000 /* invalid file descriptor */
+
+	} else {
+
+		POLLIN     :: 0x0001
+		POLLRDNORM :: 0x0040
+		POLLRDBAND :: 0x0080
+		POLLPRI    :: 0x0002
+		POLLOUT    :: 0x0004
+		POLLWRNORM :: POLLOUT
+		POLLWRBAND :: 0x0100
+
+		POLLERR    :: 0x0008
+		POLLHUP    :: 0x0010
+		POLLNVAL   :: 0x0020
+		
+	}
 
-	POLLERR    :: 0x0008
-	POLLHUP    :: 0x0010
-	POLLNVAL   :: 0x0020
 
 } else when ODIN_OS == .Linux {
 

+ 51 - 1
core/sys/posix/pthread.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -554,6 +554,56 @@ when ODIN_OS == .Darwin {
 		sched_priority: c.int,     /* [PSX] process or thread execution scheduling priority */
 	}
 
+} else when ODIN_OS == .Haiku {
+
+	PTHREAD_CANCEL_ASYNCHRONOUS :: 2
+	PTHREAD_CANCEL_DEFERRED     :: 0
+
+	PTHREAD_CANCEL_DISABLE      :: 1
+	PTHREAD_CANCEL_ENABLE       :: 0
+
+	PTHREAD_CANCELED :: rawptr(uintptr(1))
+
+	PTHREAD_CREATE_DETACHED :: 0x1
+	PTHREAD_CREATE_JOINABLE :: 0
+
+	PTHREAD_EXPLICIT_SCHED :: 0
+	PTHREAD_INHERIT_SCHED  :: 0x4
+
+	PTHREAD_PRIO_INHERIT :: 1
+	PTHREAD_PRIO_NONE    :: 0
+	PTHREAD_PRIO_PROTECT :: 2
+
+	PTHREAD_PROCESS_SHARED  :: 1
+	PTHREAD_PROCESS_PRIVATE :: 0
+
+	PTHREAD_SCOPE_PROCESS   :: 0
+	PTHREAD_SCOPE_SYSTEM    :: 0x2
+
+	pthread_t       :: distinct rawptr
+	pthread_attr_t  :: distinct rawptr
+	pthread_key_t   :: distinct c.int
+	
+	pthread_mutex_t :: struct {
+		flags:       u32,
+		lock:        i32,
+		unused:      i32,
+		owner:       i32,
+		owner_count: i32,
+	}
+	
+	pthread_cond_t :: struct {
+		flags:        u32,
+		unused:       i32,
+		mutex:        ^pthread_mutex_t,
+		waiter_count: i32,
+		lock:         i32,
+	}
+
+	sched_param :: struct {
+		sched_priority: c.int,     /* [PSX] process or thread execution scheduling priority */
+	}
+
 } else when ODIN_OS == .Linux {
 
 	PTHREAD_CANCEL_DEFERRED     :: 0

+ 13 - 1
core/sys/posix/pwd.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -176,4 +176,16 @@ when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
 		pw_shell:  cstring, /* Shell program.  */
 	}
 
+} else when ODIN_OS == .Haiku {
+
+	passwd :: struct {
+		pw_name:   cstring, /* [PSX] user name */
+		pw_passwd: cstring, /* encrypted password */
+		pw_uid:    uid_t,   /* [PSX] user uid */
+		pw_gid:    gid_t,   /* [PSX] user gid */
+		pw_dir:    cstring, /* Home directory.  */
+		pw_shell:  cstring, /* Shell program.  */
+		pw_gecos:  cstring, /* Real name.  */
+	}
+
 }

+ 8 - 1
core/sys/posix/sched.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -101,4 +101,11 @@ when ODIN_OS == .Darwin {
 	SCHED_FIFO     :: 1
 	SCHED_RR       :: 2
 
+} else when ODIN_OS == .Haiku {
+
+	SCHED_FIFO     :: 1
+	SCHED_RR       :: 2
+	// SCHED_SPORADIC :: 3 NOTE: not a thing on freebsd, netbsd and probably others, leaving it out
+	SCHED_OTHER    :: 4
+
 }

+ 148 - 1
core/sys/posix/signal.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "base:intrinsics"
@@ -1180,4 +1180,151 @@ when ODIN_OS == .Darwin {
 	SI_TIMER   :: -2
 	SI_MESGQ   :: -3
 	SI_ASYNCIO :: -4
+
+} else when ODIN_OS == .Haiku {
+
+	// Request that signal be held
+	SIG_HOLD :: rawptr(uintptr(3))
+
+	uid_t :: distinct c.uint32_t
+	sigset_t :: distinct u64
+
+	SIGHUP     :: 1  // hangup -- tty is gone!
+	//SIGINT     :: 2  // interrupt
+	SIGQUIT    :: 3  // `quit' special character typed in tty
+	//SIGILL     :: 4  // illegal instruction
+	SIGCHLD    :: 5  // child process exited
+	//SIGABRT    :: 6  // abort() called, dont' catch
+	SIGPIPE    :: 7  // write to a pipe w/no readers
+	//SIGFPE     :: 8  // floating point exception
+	SIGKILL    :: 9  // kill a team (not catchable)
+	SIGSTOP    :: 10 // suspend a thread (not catchable)
+	//SIGSEGV    :: 11 // segmentation violation (read: invalid pointer)
+	SIGCONT    :: 12 // continue execution if suspended
+	SIGTSTP    :: 13 // `stop' special character typed in tty
+	SIGALRM    :: 14 // an alarm has gone off (see alarm())
+	//SIGTERM    :: 15 // termination requested
+	SIGTTIN    :: 16 // read of tty from bg process
+	SIGTTOU    :: 17 // write to tty from bg process
+	SIGUSR1    :: 18 // app defined signal 1
+	SIGUSR2    :: 19 // app defined signal 2
+	SIGWINCH   :: 20 // tty window size changed
+	SIGKILLTHR :: 21 // be specific: kill just the thread, not team
+	SIGTRAP    :: 22 // Trace/breakpoint trap
+	SIGPOLL    :: 23 // Pollable event
+	SIGPROF    :: 24 // Profiling timer expired
+	SIGSYS     :: 25 // Bad system call
+	SIGURG     :: 26 // High bandwidth data is available at socket
+	SIGVTALRM  :: 27 // Virtual timer expired
+	SIGXCPU    :: 28 // CPU time limit exceeded
+	SIGXFSZ    :: 29 // File size limit exceeded
+	SIGBUS     :: 30 // access to undefined portion of a memory object
+
+	// NOTE: this is actually defined as `sigaction`, but due to the function with the same name
+	// `_t` has been added.
+
+	sigaction_t :: struct {
+		using _: struct #raw_union {
+			sa_handler:   proc "c" (Signal),                     /* [PSX] signal-catching function or one of the SIG_IGN or SIG_DFL */
+			sa_sigaction: proc "c" (Signal, ^siginfo_t, rawptr), /* [PSX] signal-catching function */
+		},
+		sa_mask:     sigset_t, /* [PSX] set of signals to be blocked during execution of the signal handling function */
+		sa_flags:    SA_Flags, /* [PSX] special flags */
+		sa_userdata: rawptr,   /* will be passed to the signal handler, BeOS extension */
+	}
+
+	SIG_BLOCK   :: 1
+	SIG_UNBLOCK :: 2
+	SIG_SETMASK :: 3
+
+	SA_NOCLDSTOP :: 0x01
+	SA_NOCLDWAIT :: 0x02
+	SA_RESETHAND :: 0x04
+	SA_NODEFER   :: 0x08
+	SA_RESTART   :: 0x10
+	SA_ONSTACK   :: 0x20
+	SA_SIGINFO   :: 0x40
+
+	SS_ONSTACK :: 1
+	SS_DISABLE :: 2
+
+	MINSIGSTKSZ :: 8192
+	SIGSTKSZ    :: 16384
+
+	stack_t :: struct {
+		ss_sp:    rawptr,   /* [PSX] stack base or pointer */
+		ss_size:  c.size_t, /* [PSX] stack size */
+		ss_flags: SS_Flags, /* [PSX] flags */
+	}
+
+	siginfo_t :: struct {
+		si_signo: Signal,             /* [PSX] signal number */
+		si_code:  struct #raw_union { /* [PSX] specific more detailed codes per signal */
+			ill:  ILL_Code,
+			fpe:  FPE_Code,
+			segv: SEGV_Code,
+			bus:  BUS_Code,
+			trap: TRAP_Code,
+			chld: CLD_Code,
+			poll: POLL_Code,
+			any:  Any_Code,
+		},
+		si_errno:  Errno,  /* [PSX] errno value associated with this signal */
+		si_pid:    pid_t,  /* sending process ID */
+		si_uid:    uid_t,  /* real user ID of sending process */
+		si_addr:   rawptr, /* address of faulting instruction */
+		si_status: c.int,  /* exit value or signal */
+		si_band:   c.long, /* band event for SIGPOLL */
+		si_value:  sigval, /* signal value */
+	}
+
+	/* any signal */
+	SI_USER       :: 0 /* signal sent by user */
+	SI_QUEUE      :: 1 /* signal sent by sigqueue() */
+	SI_TIMER      :: 2 /* signal sent on timer_settime() timeout */
+	SI_ASYNCIO    :: 3 /* signal sent on asynchronous I/O completion */
+	SI_MESGQ      :: 4 /* signal sent on arrival of message on empty message queue */
+	/* SIGILL */
+	ILL_ILLOPC    :: 10 /* illegal opcode */
+	ILL_ILLOPN    :: 11 /* illegal operand */
+	ILL_ILLADR    :: 12 /* illegal addressing mode */
+	ILL_ILLTRP    :: 13 /* illegal trap */
+	ILL_PRVOPC    :: 14 /* privileged opcode */
+	ILL_PRVREG    :: 15 /* privileged register */
+	ILL_COPROC    :: 16 /* coprocessor error */
+	ILL_BADSTK    :: 17 /* internal stack error */
+	/* SIGFPE */
+	FPE_INTDIV    :: 20 /* integer division by zero */
+	FPE_INTOVF    :: 21 /* integer overflow */
+	FPE_FLTDIV    :: 22 /* floating-point division by zero */
+	FPE_FLTOVF    :: 23 /* floating-point overflow */
+	FPE_FLTUND    :: 24 /* floating-point underflow */
+	FPE_FLTRES    :: 25 /* floating-point inexact result */
+	FPE_FLTINV    :: 26 /* invalid floating-point operation */
+	FPE_FLTSUB    :: 27 /* subscript out of range */
+	/* SIGSEGV */
+	SEGV_MAPERR   :: 30 /* address not mapped to object */
+	SEGV_ACCERR   :: 31 /* invalid permissions for mapped object */
+	/* SIGBUS */
+	BUS_ADRALN    :: 40 /* invalid address alignment */
+	BUS_ADRERR    :: 41 /* nonexistent physical address */
+	BUS_OBJERR    :: 42 /* object-specific hardware error */
+	/* SIGTRAP */
+	TRAP_BRKPT    :: 50 /* process breakpoint */
+	TRAP_TRACE    :: 51 /* process trace trap. */
+	/* SIGCHLD */
+	CLD_EXITED    :: 60 /* child exited */
+	CLD_KILLED    :: 61 /* child terminated abnormally without core dump */
+	CLD_DUMPED    :: 62 /* child terminated abnormally with core dump */
+	CLD_TRAPPED   :: 63 /* traced child trapped */
+	CLD_STOPPED   :: 64 /* child stopped */
+	CLD_CONTINUED :: 65 /* stopped child continued */
+	/* SIGPOLL */
+	POLL_IN       :: 70 /* input available */
+	POLL_OUT      :: 71 /* output available */
+	POLL_MSG      :: 72 /* input message available */
+	POLL_ERR      :: 73 /* I/O error */
+	POLL_PRI      :: 74 /* high priority input available */
+	POLL_HUP      :: 75 /* device disconnected */
+
 }

+ 1 - 1
core/sys/posix/signal_libc.odin

@@ -1,4 +1,4 @@
-#+build linux, windows, darwin, netbsd, openbsd, freebsd
+#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "base:intrinsics"

+ 1 - 1
core/sys/posix/stdio_libc.odin

@@ -1,4 +1,4 @@
-#+build linux, windows, linux, darwin, netbsd, openbsd, freebsd
+#+build linux, windows, linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"

+ 1 - 1
core/sys/posix/stdlib.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "base:intrinsics"

+ 1 - 1
core/sys/posix/stdlib_libc.odin

@@ -1,4 +1,4 @@
-#+build linux, windows, darwin, netbsd, openbsd, freebsd
+#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "base:intrinsics"

+ 1 - 1
core/sys/posix/string.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"

+ 1 - 1
core/sys/posix/string_libc.odin

@@ -1,4 +1,4 @@
-#+build linux, windows, darwin, netbsd, openbsd, freebsd
+#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 when ODIN_OS == .Windows {

+ 24 - 1
core/sys/posix/sys_ipc.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -111,4 +111,27 @@ when ODIN_OS == .Darwin {
 	IPC_SET  :: 1
 	IPC_STAT :: 2
 
+} else when ODIN_OS == .Haiku {
+
+	key_t :: distinct c.int32_t
+
+	ipc_perm :: struct {
+		key:  key_t,
+		uid:  uid_t,     /* [PSX] owner's user ID */
+		gid:  gid_t,     /* [PSX] owner's group ID */
+		cuid: uid_t,     /* [PSX] creator's user ID */
+		cgid: gid_t,     /* [PSX] creator's group ID */
+		mode: mode_t,    /* [PSX] read/write perms */
+	}
+
+	IPC_CREAT  :: 0o01000
+	IPC_EXCL   :: 0o02000
+	IPC_NOWAIT :: 0o04000
+
+	IPC_PRIVATE :: key_t(0)
+
+	IPC_RMID :: 0
+	IPC_SET  :: 1
+	IPC_STAT :: 2
+
 }

+ 19 - 1
core/sys/posix/sys_msg.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -171,4 +171,22 @@ when ODIN_OS == .Darwin {
 		__unused:    [2]c.ulong,
 	}
 
+} else when ODIN_OS == .Haiku {
+
+	msgqnum_t :: distinct c.uint32_t
+	msglen_t  :: distinct c.uint32_t
+
+	MSG_NOERROR :: 0o10000
+
+	msqid_ds :: struct {
+		msg_perm:   ipc_perm,  /* [PSX] operation permission structure */
+		msg_qnum:   msgqnum_t, /* [PSX] number of messages currently on queue */
+		msg_qbytes: msglen_t,  /* [PSX] maximum number of bytes allowed on queue */
+		msg_lspid:  pid_t,     /* [PSX] process ID of last msgsnd() */
+		msg_lrpid:  pid_t,     /* [PSX] process ID of last msgrcv() */
+		msg_stime:  time_t,    /* [PSX] time of last msgsnd() */
+		msg_rtime:  time_t,    /* [PSX] time of last msgrcv() */
+		msg_ctime:  time_t,    /* [PSX] time of last change */
+	}
+
 }

+ 37 - 16
core/sys/posix/sys_resource.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -96,15 +96,26 @@ when ODIN_OS == .NetBSD {
 	@(private) LGETRUSAGE :: "getrusage"
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	PRIO_PROCESS :: 0
 	PRIO_PGRP    :: 1
 	PRIO_USER    :: 2
 
-	rlim_t :: distinct c.uint64_t
+	when ODIN_OS == .Haiku {
+		rlim_t :: distinct c.ulong
+	} else {
+		rlim_t :: distinct c.uint64_t
+	}
 
-	RLIM_INFINITY  :: ~rlim_t(0) when ODIN_OS == .Linux else (rlim_t(1) << 63) - 1
+	when ODIN_OS == .Haiku {
+		RLIM_INFINITY :: rlim_t(0xFFFFFFFF)
+	} else when ODIN_OS == .Linux {
+		RLIM_INFINITY :: ~rlim_t(0)
+	} else {
+		RLIM_INFINITY :: (rlim_t(1) << 63) - 1
+	}
+	
 	RLIM_SAVED_MAX :: RLIM_INFINITY
 	RLIM_SAVED_CUR :: RLIM_INFINITY
 
@@ -140,19 +151,29 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		ru_nivcsw:   c.long, /* involuntary " */
 	}
 
-	RLIMIT_CORE   :: 4
-	RLIMIT_CPU    :: 0
-	RLIMIT_DATA   :: 2
-	RLIMIT_FSIZE  :: 1
-	RLIMIT_NOFILE :: 7 when ODIN_OS == .Linux else 8
-	RLIMIT_STACK  :: 3
-
-	when ODIN_OS == .Linux {
-		RLIMIT_AS :: 9
-	} else when ODIN_OS == .Darwin || ODIN_OS == .OpenBSD {
-		RLIMIT_AS :: 5
+	when ODIN_OS == .Haiku {
+		RLIMIT_CORE   :: 0
+		RLIMIT_CPU    :: 1
+		RLIMIT_DATA   :: 2
+		RLIMIT_FSIZE  :: 3
+		RLIMIT_NOFILE :: 4
+		RLIMIT_STACK  :: 5
+		RLIMIT_AS     :: 6
 	} else {
-		RLIMIT_AS :: 10
+		RLIMIT_CORE   :: 4
+		RLIMIT_CPU    :: 0
+		RLIMIT_DATA   :: 2
+		RLIMIT_FSIZE  :: 1
+		RLIMIT_NOFILE :: 7 when ODIN_OS == .Linux else 8
+		RLIMIT_STACK  :: 3
+	
+		when ODIN_OS == .Linux {
+			RLIMIT_AS :: 9
+		} else when ODIN_OS == .Darwin || ODIN_OS == .OpenBSD {
+			RLIMIT_AS :: 5
+		} else {
+			RLIMIT_AS :: 10
+		}
 	}
 
 }

+ 11 - 5
core/sys/posix/sys_select.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "base:intrinsics"
@@ -56,9 +56,9 @@ when ODIN_OS == .NetBSD {
 	LSELECT  :: "select"
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
-	suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD else c.long)
+	suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .Haiku else c.long)
 
 	timeval :: struct {
 		tv_sec:  time_t,      /* [PSX] seconds */
@@ -75,8 +75,14 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 	@(private)
 	ALIGN ::  align_of(c.long) when ODIN_OS == .FreeBSD || ODIN_OS == .Linux else align_of(c.int32_t)
 
-	fd_set :: struct #align(ALIGN) {
-		fds_bits: [(FD_SETSIZE / __NFDBITS) when (FD_SETSIZE % __NFDBITS) == 0 else (FD_SETSIZE / __NFDBITS) + 1]c.int32_t,
+	when ODIN_OS == .Haiku {
+		fd_set :: struct #align(ALIGN) {
+			fds_bits: [(FD_SETSIZE + (__NFDBITS - 1)) / __NFDBITS]c.int32_t,
+		}
+	} else {
+		fd_set :: struct #align(ALIGN) {
+			fds_bits: [(FD_SETSIZE / __NFDBITS) when (FD_SETSIZE % __NFDBITS) == 0 else (FD_SETSIZE / __NFDBITS) + 1]c.int32_t,
+		}
 	}
 
 	@(private)

+ 27 - 1
core/sys/posix/sys_sem.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -154,4 +154,30 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		sem_flg: c.short,  /* [PSX] operation flags */
 	}
 
+} else when ODIN_OS == .Haiku {
+
+	SEM_UNDO :: 10 // undo the operation on exit
+
+	// Commands for `semctl'.
+	GETPID  :: 3
+	GETVAL  :: 4
+	GETALL  :: 5
+	GETNCNT :: 6
+	GETZCNT :: 7
+	SETVAL  :: 8
+	SETALL  :: 9
+
+	semid_ds :: struct {
+		sem_perm:  ipc_perm,  // [PSX] operation permission structure
+		sem_nsems: c.ushort, // [PSX] number of semaphores in set
+		sem_otime: time_t,    // [PSX] last semop()
+		sem_ctime: time_t,    // [PSX] last time changed by semctl()
+	}
+
+	sembuf :: struct {
+		sem_num: c.ushort, /* [PSX] semaphore number */
+		sem_op:  c.short,  /* [PSX] semaphore operation */
+		sem_flg: c.short,  /* [PSX] operation flags */
+	}
+
 }

+ 56 - 10
core/sys/posix/sys_socket.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -328,24 +328,32 @@ when ODIN_OS == .NetBSD {
 	@(private) LSOCKET :: "socket"
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	socklen_t :: distinct c.uint
 
+	when ODIN_OS == .Haiku {
+		@(private)
+		_SA_DATASIZE :: 30
+	} else {
+		@(private)
+		_SA_DATASIZE :: 14
+	}
+
 	when ODIN_OS == .Linux {
 		_sa_family_t :: distinct c.ushort
 
 		sockaddr :: struct {
-			sa_family: sa_family_t, /* [PSX] address family */
-			sa_data:   [14]c.char,  /* [PSX] socket address */
+			sa_family: sa_family_t,           /* [PSX] address family */
+			sa_data:   [_SA_DATASIZE]c.char,  /* [PSX] socket address */
 		}
 	} else {
 		_sa_family_t :: distinct c.uint8_t
 
 		sockaddr :: struct {
-			sa_len:    c.uint8_t,   /* total length */
-			sa_family: sa_family_t, /* [PSX] address family */
-			sa_data:   [14]c.char,  /* [PSX] socket address */
+			sa_len:    c.uint8_t,             /* total length */
+			sa_family: sa_family_t,           /* [PSX] address family */
+			sa_data:   [_SA_DATASIZE]c.char,  /* [PSX] socket address */
 		}
 	}
 
@@ -355,6 +363,11 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		_SS_PAD1SIZE :: 6
 		@(private)
 		_SS_PAD2SIZE :: 240
+	} else when ODIN_OS == .Haiku {
+		@(private)
+		_SS_PAD1SIZE :: 6
+		@(private)
+		_SS_PAD2SIZE :: 112
 	} else when ODIN_OS == .Linux {
 		@(private)
 		_SS_SIZE :: 128
@@ -486,6 +499,26 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 
 		SO_RCVTIMEO   :: 66
 		SO_SNDTIMEO   :: 67
+	} else when ODIN_OS == .Haiku {
+		SOL_SOCKET :: -1
+
+		SO_ACCEPTCONN :: 0x00000001
+		SO_BROADCAST  :: 0x00000002
+		SO_DEBUG      :: 0x00000004
+		SO_DONTROUTE  :: 0x00000008
+		SO_ERROR      :: 0x40000007
+		SO_KEEPALIVE  :: 0x00000010
+		SO_OOBINLINE  :: 0x00000020
+		SO_RCVBUF     :: 0x40000004
+		SO_RCVLOWAT   :: 0x40000005
+		SO_REUSEADDR  :: 0x00000040
+		SO_SNDBUF     :: 0x40000001
+		SO_SNDLOWAT   :: 0x40000002
+		SO_TYPE       :: 0x40000008
+
+		SO_LINGER     :: 0x00000200
+		SO_RCVTIMEO   :: 0x40000006
+		SO_SNDTIMEO   :: 0x40000003
 	} else {
 		SOL_SOCKET :: 0xffff
 
@@ -523,7 +556,11 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 	}
 
 	// The maximum backlog queue length for listen().
-	SOMAXCONN :: 128
+	when ODIN_OS == .Haiku {
+		SOMAXCONN :: 32
+	} else {
+		SOMAXCONN :: 128
+	}
 
 	when ODIN_OS == .Linux {
 		MSG_CTRUNC    :: 0x008
@@ -549,11 +586,18 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 			MSG_NOSIGNAL :: 0x00020000
 		} else when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
 			MSG_NOSIGNAL :: 0x0400
+		} else when ODIN_OS == .Haiku {
+			MSG_NOSIGNAL :: 0x800
 		}
 	}
 
-	AF_INET   :: 2
-	AF_UNIX   :: 1
+	when ODIN_OS == .Haiku {
+		AF_INET :: 1
+		AF_UNIX :: 9
+	} else {
+		AF_INET :: 2
+		AF_UNIX :: 1
+	}
 
 	when ODIN_OS == .Darwin {
 		AF_INET6 :: 30
@@ -563,6 +607,8 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		AF_INET6 :: 24
 	} else when ODIN_OS == .Linux {
 		AF_INET6 :: 10
+	} else when ODIN_OS == .Haiku {
+		AF_INET6 :: 5
 	}
 
 	SHUT_RD   :: 0

+ 31 - 1
core/sys/posix/sys_stat.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -428,6 +428,36 @@ when ODIN_OS == .Darwin {
 	UTIME_NOW  :: -2
 	UTIME_OMIT :: -1
 
+} else when ODIN_OS == .Haiku {
+
+	dev_t      :: distinct c.int32_t
+	nlink_t    :: distinct c.int32_t
+	_mode_t    :: distinct c.uint32_t
+	blkcnt_t   :: distinct c.int64_t
+	blksize_t  :: distinct c.int32_t
+	ino_t      :: distinct c.int64_t
+
+	stat_t :: struct {
+		st_dev:           dev_t,        /* [PSX] ID of device containing file */
+		st_ino:           ino_t,        /* [PSX] file serial number */
+		st_mode:          mode_t,       /* [PSX] mode of file */
+		st_nlink:         nlink_t,      /* [PSX] number of hard links */
+		st_uid:           uid_t,        /* [PSX] user ID of the file */
+		st_gid:           gid_t,        /* [PSX] group ID of the file */
+		st_size:          off_t,        /* [PSX] file size, in bytes */
+		st_rdev:          dev_t,        /* [PSX] device ID */
+		st_blksize:       blksize_t,    /* [PSX] optimal blocksize for I/O */
+		st_atim:          timespec,     /* [PSX] time of last access */
+		st_mtim:          timespec,     /* [PSX] time of last data modification */
+		st_ctim:          timespec,     /* [PSX] time of last status change */
+		st_crtim:         timespec,     /* [PSX] time of last status change */
+		st_type:          c.uint32_t,
+		st_blocks:        blkcnt_t,     /* [PSX] blocks allocated for file */
+	}
+
+	UTIME_NOW  :: 1000000000
+	UTIME_OMIT :: 1000000001
+
 } else when ODIN_OS == .Linux {
 
 	dev_t     :: distinct u64

+ 12 - 1
core/sys/posix/sys_time.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -78,4 +78,15 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 	ITIMER_VIRTUAL :: 1
 	ITIMER_PROF    :: 2
 
+} else when ODIN_OS == .Haiku {
+
+	itimerval :: struct {
+		it_interval: timeval, /* [PSX] timer interval */
+		it_value:    timeval, /* [PSX] current value */
+	}
+
+	ITIMER_REAL    :: 1
+	ITIMER_VIRTUAL :: 2
+	ITIMER_PROF    :: 3
+
 }

+ 2 - 2
core/sys/posix/sys_times.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 when ODIN_OS == .Darwin {
@@ -25,7 +25,7 @@ when ODIN_OS == .NetBSD {
 	@(private) LTIMES :: "times"
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	tms :: struct {
 		tms_utime:  clock_t, /* [PSX] user CPU time */

+ 2 - 2
core/sys/posix/sys_uio.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -31,7 +31,7 @@ foreign libc {
 	writev :: proc(fildes: FD, iov: [^]iovec, iovcnt: c.int) -> c.ssize_t ---
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	iovec :: struct {
 		iov_base: rawptr,   /* [PSX] base address of I/O memory region */

+ 9 - 1
core/sys/posix/sys_un.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -20,4 +20,12 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
 		sun_path:   [108]c.char, /* [PSX] socket pathname */
 	}
 
+} else when ODIN_OS == .Haiku {
+
+	sockaddr_un :: struct {
+		sun_len:    c.uint8_t,
+		sun_family: sa_family_t, /* [PSX] address family */
+		sun_path:   [126]c.char, /* [PSX] socket pathname */
+	}
+
 }

+ 3 - 3
core/sys/posix/sys_utsname.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -38,10 +38,10 @@ foreign lib {
 	uname :: proc(uname: ^utsname) -> c.int ---
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku {
 
 	@(private)
-	_SYS_NAMELEN :: 256
+	_SYS_NAMELEN :: 32 when ODIN_OS == .Haiku else 256
 
 	utsname :: struct {
 		sysname:  [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] name of OS */

+ 53 - 1
core/sys/posix/sys_wait.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -442,4 +442,56 @@ when ODIN_OS == .Darwin {
 	_WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
 		return x == 0xffff
 	}
+
+} else when ODIN_OS == .Haiku {
+
+	id_t :: distinct c.int32_t
+
+	WCONTINUED :: 0x04
+	WNOHANG    :: 0x01
+	WUNTRACED  :: 0x02
+
+	WEXITED  :: 0x08
+	WNOWAIT  :: 0x20
+	WSTOPPED :: 0x10
+
+	_P_ALL  :: 0
+	_P_PID  :: 1
+	_P_PGID :: 2
+
+	@(private)
+	_WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
+		return (x & ~(c.int)(0xff)) == 0
+	}
+
+	@(private)
+	_WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
+		return x & 0xff
+	}
+
+	@(private)
+	_WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
+		return ((x >> 8) & 0xff) != 0
+	}
+
+	@(private)
+	_WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
+		return Signal((x >> 8) & 0xff)
+	}
+
+	@(private)
+	_WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
+		return ((x >> 16) & 0xff) != 0
+	}
+
+	@(private)
+	_WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
+		return Signal((x >> 16) & 0xff)
+	}
+
+	@(private)
+	_WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
+		return (x & 0x20000) != 0
+	}
+
 }

+ 172 - 12
core/sys/posix/termios.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -138,17 +138,30 @@ CLocal_Flag_Bits :: enum tcflag_t {
 }
 CLocal_Flags :: bit_set[CLocal_Flag_Bits; tcflag_t]
 
-CControl_Flag_Bits :: enum tcflag_t {
-	// CS5    = log2(CS5), /* 5 bits (pseudo) (default) */
-	CS6    = log2(CS6),    /* 6 bits */
-	CS7    = log2(CS7),    /* 7 bits */
-	CS8    = log2(CS8),    /* 8 bits */
-	CSTOPB = log2(CSTOPB), /* send 2 stop bits */
-	CREAD  = log2(CREAD),  /* enable receiver */
-	PARENB = log2(PARENB), /* parity enable */
-	PARODD = log2(PARODD), /* odd parity, else even */
-	HUPCL  = log2(HUPCL),  /* hang up on last close */
-	CLOCAL = log2(CLOCAL), /* ignore modem status lines */
+when ODIN_OS == .Haiku {
+	CControl_Flag_Bits :: enum tcflag_t {
+		// CS7    = log2(CS7),    /* 7 bits (default) */
+		CS8    = log2(CS8),    /* 8 bits */
+		CSTOPB = log2(CSTOPB), /* send 2 stop bits */
+		CREAD  = log2(CREAD),  /* enable receiver */
+		PARENB = log2(PARENB), /* parity enable */
+		PARODD = log2(PARODD), /* odd parity, else even */
+		HUPCL  = log2(HUPCL),  /* hang up on last close */
+		CLOCAL = log2(CLOCAL), /* ignore modem status lines */
+	}	
+} else {
+	CControl_Flag_Bits :: enum tcflag_t {
+		// CS5    = log2(CS5), /* 5 bits (pseudo) (default) */
+		CS6    = log2(CS6),    /* 6 bits */
+		CS7    = log2(CS7),    /* 7 bits */
+		CS8    = log2(CS8),    /* 8 bits */
+		CSTOPB = log2(CSTOPB), /* send 2 stop bits */
+		CREAD  = log2(CREAD),  /* enable receiver */
+		PARENB = log2(PARENB), /* parity enable */
+		PARODD = log2(PARODD), /* odd parity, else even */
+		HUPCL  = log2(HUPCL),  /* hang up on last close */
+		CLOCAL = log2(CLOCAL), /* ignore modem status lines */
+	}
 }
 CControl_Flags :: bit_set[CControl_Flag_Bits; tcflag_t]
 
@@ -597,4 +610,151 @@ when ODIN_OS == .Darwin {
 	TCOOFF :: 0
 	TCOON  :: 1
 
+} else when ODIN_OS == .Haiku {
+
+	cc_t      :: distinct c.uchar
+	_speed_t  :: distinct c.uint32_t
+	tcflag_t  :: distinct c.uint16_t
+
+	// Same as speed_t, but 16-bit.
+	CSpeed :: enum tcflag_t {
+		B0     = B0,
+		B50    = B50,
+		B75    = B75,
+		B110   = B110,
+		B134   = B134,
+		B150   = B150,
+		B200   = B200,
+		B300   = B300,
+		B600   = B600,
+		B1200  = B1200,
+		B1800  = B1800,
+		B2400  = B2400,
+		B4800  = B4800,
+		B9600  = B9600,
+		B19200 = B19200,
+		B38400 = B38400,
+	}
+
+	termios :: struct {
+		c_iflag:       CInput_Flags,   /* [XBD] input flags */
+		c_ispeed:      CSpeed,         /* input speed */
+		c_oflag:       COutput_Flags,  /* [XBD] output flags */
+		c_ospeed:      CSpeed,         /* output speed */
+		c_cflag:       CControl_Flags, /* [XBD] control flags */
+		c_ispeed_high: tcflag_t,       /* high word of input baudrate */
+		c_lflag:       CLocal_Flags,   /* [XBD] local flag */
+		c_ospeed_high: tcflag_t,       /* high word of output baudrate */
+		c_line:        c.char,
+		_padding:      c.uchar,
+		_padding2:     c.uchar,
+		c_cc:          [NCCS]cc_t,
+	}
+
+	NCCS :: 11
+
+	VINTR  :: 0
+	VQUIT  :: 1
+	VERASE :: 2
+	VKILL  :: 3
+	VEOF   :: 4
+	VEOL   :: 5
+	VMIN   :: 4
+	VTIME  :: 5
+	VEOL2  :: 6
+	VSWTCH :: 7
+	VSTART :: 8
+	VSTOP  :: 9
+	VSUSP  :: 10
+
+	IGNBRK :: 0x01   /* ignore break condition */
+	BRKINT :: 0x02   /* break sends interrupt */
+	IGNPAR :: 0x04   /* ignore characters with parity errors */
+	PARMRK :: 0x08   /* mark parity errors */
+	INPCK  :: 0x10   /* enable input parity checking */
+	ISTRIP :: 0x20   /* strip high bit from characters */
+	INLCR  :: 0x40   /* maps newline to CR on input */
+	IGNCR  :: 0x80   /* ignore carriage returns */
+	ICRNL  :: 0x100  /* map CR to newline on input */
+	IXON   :: 0x400  /* enable input SW flow control */
+	IXANY  :: 0x800  /* any character will restart input */
+	IXOFF  :: 0x1000 /* enable output SW flow control */
+
+	OPOST   :: 0x01  /* enable postprocessing of output */
+	ONLCR   :: 0x04  /* map NL to CR-NL on output */
+	OCRNL   :: 0x08  /* map CR to NL on output */
+	ONOCR   :: 0x10  /* no CR output when at column 0 */
+	ONLRET  :: 0x20  /* newline performs CR function */
+	OFILL   :: 0x40  /* use fill characters for delays */
+	OFDEL   :: 0x80  /* Fills are DEL, otherwise NUL */
+	_NLDLY  :: 0x100 /* Newline delays: */
+	NL0     :: 0x000
+	NL1     :: 0x100
+	_CRDLY  :: 0x600 /* Carriage return delays: */
+	CR0     :: 0x000
+	CR1     :: 0x200
+	CR2     :: 0x400
+	CR3     :: 0x600
+	_TABDLY :: 0x1800 /* Tab delays: */
+	TAB0    :: 0x0000
+	TAB1    :: 0x0800
+	TAB3    :: 0x1800
+	_BSDLY  :: 0x2000 /* Backspace delays: */
+	BS0     :: 0x0000
+	BS1     :: 0x2000
+	_VTDLY  :: 0x4000 /* Vertical tab delays: */
+	VT0     :: 0x0000
+	VT1     :: 0x4000
+	_FFDLY  :: 0x8000 /* Form feed delays: */
+	FF0     :: 0x0000
+	FF1     :: 0x8000
+
+	B0     :: 0x00 /* hang up */
+	B50    :: 0x01 /* 50 baud */
+	B75    :: 0x02
+	B110   :: 0x03
+	B134   :: 0x04
+	B150   :: 0x05
+	B200   :: 0x06
+	B300   :: 0x07
+	B600   :: 0x08
+	B1200  :: 0x09
+	B1800  :: 0x0A
+	B2400  :: 0x0B
+	B4800  :: 0x0C
+	B9600  :: 0x0D
+	B19200 :: 0x0E
+	B38400 :: 0x0F
+
+	_CSIZE  :: 0x20  /* character size */
+	//CS5    :: 0x00  /* only 7 and 8 bits supported */
+	//CS6    :: 0x00  /* Note, it was not very wise to set all of these */
+	//CS7    :: 0x00  /* to zero, but there is not much we can do about it*/
+	CS8    :: 0x20
+	CSTOPB :: 0x40  /* send 2 stop bits, not 1 */
+	CREAD  :: 0x80  /* enable receiver */
+	PARENB :: 0x100 /* parity enable */
+	PARODD :: 0x200 /* odd parity, else even */
+	HUPCL  :: 0x400 /* hangs up on last close */
+	CLOCAL :: 0x800 /* indicates local line */
+
+	ISIG   :: 0x01  /* enable signals */
+	ICANON :: 0x02  /* Canonical input */
+	ECHO   :: 0x08  /* Enable echo */
+	ECHOE  :: 0x10  /* Echo erase as bs-sp-bs */
+	ECHOK  :: 0x20  /* Echo nl after kill */
+	ECHONL :: 0x40  /* Echo nl */
+	NOFLSH :: 0x80  /* Disable flush after int or quit */
+	TOSTOP :: 0x100 /* stop bg processes that write to tty */
+	IEXTEN :: 0x200 /* implementation defined extensions */
+
+	TCIFLUSH  :: 1
+	TCOFLUSH  :: 2
+	TCIOFLUSH :: 3
+
+	TCIOFF :: 0x04
+	TCION  :: 0x08
+	TCOOFF :: 0x01
+	TCOON  :: 0x02
+
 }

+ 12 - 1
core/sys/posix/time.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -230,6 +230,17 @@ when ODIN_OS == .Darwin {
 
 	getdate_err: Errno = .ENOSYS // NOTE: looks like it's not a thing on OpenBSD.
 
+} else when ODIN_OS == .Haiku {
+
+	clockid_t :: distinct c.int32_t
+
+	CLOCK_MONOTONIC          :: 0
+	CLOCK_PROCESS_CPUTIME_ID :: -2
+	CLOCK_REALTIME           :: -1
+	CLOCK_THREAD_CPUTIME_ID  :: -3
+
+	getdate_err: Errno = .ENOSYS // NOTE: looks like it's not a thing on Haiku.
+
 } else when ODIN_OS == .Linux {
 
 	clockid_t :: distinct c.int

+ 172 - 2
core/sys/posix/unistd.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"
@@ -1852,7 +1852,7 @@ when ODIN_OS == .Darwin {
 	_PC_ALLOC_SIZE_MIN     :: 19
 	_PC_SYMLINK_MAX        :: 20
 	_PC_2_SYMLINK          :: 21
-
+	
 	_SC_ARG_MAX               :: 1
 	_SC_CHILD_MAX             :: 2
 	_SC_CLK_TCK               :: 3
@@ -1992,4 +1992,174 @@ when ODIN_OS == .Darwin {
 	// NOTE: Not implemented.
 	_POSIX_VDISABLE :: 0
 
+} else when ODIN_OS == .Haiku {
+
+	_F_OK   :: 0
+	X_OK    :: 1
+	W_OK    :: 2
+	R_OK    :: 4
+
+	F_LOCK  :: 1
+	F_TEST  :: 3
+	F_TLOCK :: 2
+	F_ULOCK :: 0
+
+	_CS_PATH                           :: 1
+	_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS :: 0 // Undefined.
+	_CS_POSIX_V6_ILP32_OFF32_CFLAGS    :: 0 // Undefined.
+	_CS_POSIX_V6_ILP32_OFF32_LDFLAGS   :: 0 // Undefined.
+	_CS_POSIX_V6_ILP32_OFF32_LIBS      :: 0 // Undefined.
+	_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS   :: 0 // Undefined.
+	_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS  :: 0 // Undefined.
+	_CS_POSIX_V6_ILP32_OFFBIG_LIBS     :: 0 // Undefined.
+	_CS_POSIX_V6_LP64_OFF64_CFLAGS     :: 0 // Undefined.
+	_CS_POSIX_V6_LP64_OFF64_LDFLAGS    :: 0 // Undefined.
+	_CS_POSIX_V6_LP64_OFF64_LIBS       :: 0 // Undefined.
+	_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS   :: 0 // Undefined.
+	_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS  :: 0 // Undefined.
+	_CS_POSIX_V6_LPBIG_OFFBIG_LIBS     :: 0 // Undefined.
+
+	_SC_ASYNCHRONOUS_IO      :: 0 // Undefined.
+	_SC_RAW_SOCKETS          :: 0 // Undefined.
+	_SC_SS_REPL_MAX          :: 0 // Undefined.
+	_SC_TRACE_EVENT_NAME_MAX :: 0 // Undefined.
+	_SC_TRACE_NAME_MAX       :: 0 // Undefined.
+	_SC_TRACE_SYS_MAX        :: 0 // Undefined.
+	_SC_TRACE_USER_EVENT_MAX :: 0 // Undefined.
+
+	_PC_CHOWN_RESTRICTED   :: 1
+	_PC_MAX_CANON          :: 2
+	_PC_MAX_INPUT          :: 3
+	_PC_NAME_MAX           :: 4
+	_PC_NO_TRUNC           :: 5
+	_PC_PATH_MAX           :: 6
+	_PC_PIPE_BUF           :: 7
+	_PC_VDISABLE           :: 8
+	_PC_LINK_MAX           :: 25
+	_PC_SYNC_IO            :: 26
+	_PC_ASYNC_IO           :: 27
+	_PC_PRIO_IO            :: 28
+	_PC_FILESIZEBITS       :: 30
+	_PC_REC_INCR_XFER_SIZE :: 31
+	_PC_REC_MAX_XFER_SIZE  :: 32
+	_PC_REC_MIN_XFER_SIZE  :: 33
+	_PC_REC_XFER_ALIGN     :: 34
+	_PC_ALLOC_SIZE_MIN     :: 35
+	_PC_SYMLINK_MAX        :: 36
+	_PC_2_SYMLINK          :: 37
+
+	_SC_ARG_MAX                    :: 15
+	_SC_CHILD_MAX                  :: 16
+	_SC_CLK_TCK                    :: 17
+	_SC_JOB_CONTROL                :: 18
+	_SC_NGROUPS_MAX                :: 19
+	_SC_OPEN_MAX                   :: 20
+	_SC_SAVED_IDS                  :: 21
+	_SC_STREAM_MAX                 :: 22
+	_SC_TZNAME_MAX                 :: 23
+	_SC_VERSION                    :: 24
+	_SC_GETGR_R_SIZE_MAX           :: 25
+	_SC_GETPW_R_SIZE_MAX           :: 26
+	_SC_PAGE_SIZE                  :: 27
+	_SC_PAGESIZE                   :: _SC_PAGE_SIZE
+	_SC_SEM_NSEMS_MAX              :: 28
+	_SC_SEM_VALUE_MAX              :: 29
+	_SC_SEMAPHORES                 :: 30
+	_SC_THREADS                    :: 31
+	_SC_IOV_MAX                    :: 32
+	_SC_NPROCESSORS_CONF           :: 34
+	_SC_NPROCESSORS_ONLN           :: 35
+	_SC_ATEXIT_MAX                 :: 37
+	_SC_MAPPED_FILES               :: 45
+	_SC_THREAD_PROCESS_SHARED      :: 46
+	_SC_THREAD_STACK_MIN           :: 47
+	_SC_THREAD_ATTR_STACKADDR      :: 48
+	_SC_THREAD_ATTR_STACKSIZE      :: 49
+	_SC_THREAD_PRIORITY_SCHEDULING :: 50
+	_SC_REALTIME_SIGNALS           :: 51
+	_SC_MEMORY_PROTECTION          :: 52
+	_SC_SIGQUEUE_MAX               :: 53
+	_SC_RTSIG_MAX                  :: 54
+	_SC_MONOTONIC_CLOCK            :: 55
+	_SC_DELAYTIMER_MAX             :: 56
+	_SC_TIMER_MAX                  :: 57
+	_SC_TIMERS                     :: 58
+	_SC_CPUTIME                    :: 59
+	_SC_THREAD_CPUTIME             :: 60
+	_SC_HOST_NAME_MAX              :: 61
+	_SC_REGEXP                     :: 62
+	_SC_SYMLOOP_MAX                :: 63
+	_SC_SHELL                      :: 64
+	_SC_TTY_NAME_MAX               :: 65
+	_SC_ADVISORY_INFO              :: 66
+	_SC_BARRIERS                   :: 67
+	_SC_CLOCK_SELECTION            :: 68
+	_SC_FSYNC                      :: 69
+	_SC_IPV6                       :: 70
+	_SC_MEMLOCK                    :: 71
+	_SC_MEMLOCK_RANGE              :: 72
+	_SC_MESSAGE_PASSING            :: 73
+	_SC_PRIORITIZED_IO             :: 74
+	_SC_PRIORITY_SCHEDULING        :: 75
+	_SC_READER_WRITER_LOCKS        :: 76
+	_SC_SHARED_MEMORY_OBJECTS      :: 77
+	_SC_SPAWN                      :: 78
+	_SC_SPIN_LOCKS                 :: 79
+	_SC_SPORADIC_SERVER            :: 80
+	_SC_SYNCHRONIZED_IO            :: 81
+	_SC_THREAD_PRIO_INHERIT        :: 82
+	_SC_THREAD_PRIO_PROTECT        :: 83
+	_SC_THREAD_SAFE_FUNCTIONS      :: 86
+	_SC_THREAD_SPORADIC_SERVER     :: 87
+	_SC_TIMEOUTS                   :: 88
+	_SC_TRACE                      :: 89
+	_SC_TRACE_EVENT_FILTER         :: 90
+	_SC_TRACE_INHERIT              :: 91
+	_SC_TRACE_LOG                  :: 92
+	_SC_TYPED_MEMORY_OBJECTS       :: 93
+	_SC_V6_ILP32_OFF32             :: 94
+	_SC_V6_ILP32_OFFBIG            :: 95
+	_SC_V6_LP64_OFF64              :: 96
+	_SC_V6_LPBIG_OFFBIG            :: 97
+	_SC_2_C_BIND                   :: 102
+	_SC_2_C_DEV                    :: 103
+	_SC_2_CHAR_TERM                :: 104
+	_SC_2_FORT_DEV                 :: 105
+	_SC_2_FORT_RUN                 :: 106
+	_SC_2_LOCALEDEF                :: 107
+	_SC_2_PBS                      :: 108
+	_SC_2_PBS_ACCOUNTING           :: 109
+	_SC_2_PBS_CHECKPOINT           :: 110
+	_SC_2_PBS_LOCATE               :: 111
+	_SC_2_PBS_MESSAGE              :: 112
+	_SC_2_PBS_TRACK                :: 113
+	_SC_2_SW_DEV                   :: 114
+	_SC_2_UPE                      :: 115
+	_SC_2_VERSION                  :: 116
+	_SC_XOPEN_CRYPT                :: 117
+	_SC_XOPEN_ENH_I18N             :: 118
+	_SC_XOPEN_REALTIME             :: 119
+	_SC_XOPEN_REALTIME_THREADS     :: 120
+	_SC_XOPEN_SHM                  :: 121
+	_SC_XOPEN_STREAMS              :: 122
+	_SC_XOPEN_UNIX                   :: 123
+	_SC_XOPEN_VERSION                :: 125
+	_SC_AIO_LISTIO_MAX               :: 126
+	_SC_AIO_MAX                      :: 127
+	_SC_AIO_PRIO_DELTA_MAX           :: 128
+	_SC_BC_BASE_MAX                  :: 129
+	_SC_BC_DIM_MAX                   :: 130
+	_SC_BC_SCALE_MAX                 :: 131
+	_SC_BC_STRING_MAX                :: 132
+	_SC_COLL_WEIGHTS_MAX             :: 133
+	_SC_EXPR_NEST_MAX                :: 134
+	_SC_LINE_MAX                     :: 135
+	_SC_LOGIN_NAME_MAX               :: 136
+	_SC_MQ_OPEN_MAX                  :: 137
+	_SC_MQ_PRIO_MAX                  :: 138
+	_SC_THREAD_DESTRUCTOR_ITERATIONS :: 139
+	_SC_THREAD_KEYS_MAX              :: 140
+	_SC_THREAD_THREADS_MAX           :: 141
+	_SC_RE_DUP_MAX                   :: 142
+
 }

+ 1 - 1
core/sys/posix/unistd_libc.odin

@@ -1,4 +1,4 @@
-#+build linux, windows, darwin, netbsd, openbsd, freebsd
+#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 import "core:c"

+ 2 - 2
core/sys/posix/utime.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 package posix
 
 when ODIN_OS == .Darwin {
@@ -25,7 +25,7 @@ when ODIN_OS == .NetBSD {
 	@(private) LUTIME :: "utime"
 }
 
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD	|| ODIN_OS == .Linux {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
 
 	utimbuf :: struct {
 		actime:  time_t, /* [PSX] access time (seconds since epoch) */

+ 1 - 1
core/testing/signal_handler_posix.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, netbsd, openbsd, freebsd
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
 #+private
 package testing
 

+ 32 - 14
tests/core/sys/posix/posix.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, freebsd, openbsd, netbsd
+#+build linux, darwin, freebsd, openbsd, netbsd, haiku
 package tests_core_posix
 
 import "core:log"
@@ -65,8 +65,17 @@ test_dirent :: proc(t: ^testing.T) {
 		for entry in entries {
 			defer posix.free(entry)
 
-			if entry.d_type != .REG {
-				continue
+			when ODIN_OS == .Haiku {
+				stat: posix.stat_t
+				posix.stat(cstring(raw_data(entry.d_name[:])), &stat)
+
+				if !posix.S_ISREG(stat.st_mode) {
+					continue
+				}
+			} else {
+				if entry.d_type != .REG {
+					continue
+				}
 			}
 
 			name := string(cstring(raw_data(entry.d_name[:])))
@@ -86,8 +95,17 @@ test_dirent :: proc(t: ^testing.T) {
 				break
 			}
 
-			if entry.d_type != .REG {
-				continue
+			when ODIN_OS == .Haiku {
+				stat: posix.stat_t
+				posix.stat(cstring(raw_data(entry.d_name[:])), &stat)
+
+				if !posix.S_ISREG(stat.st_mode) {
+					continue
+				}
+			} else {
+				if entry.d_type != .REG {
+					continue
+				}
 			}
 
 			name := string(cstring(raw_data(entry.d_name[:])))
@@ -140,15 +158,15 @@ test_langinfo :: proc(t: ^testing.T) {
 @(test)
 test_libgen :: proc(t: ^testing.T) {
 	tests := [][3]cstring{
-		{ "usr",              ".",          "usr" },
-		{ "usr/",             ".",          "usr" },
-		{ "",                 ".",          "." },
-		{ "/",                "/",          "/" },
-		{ "///",              "/",          "/" },
-		{ "/usr/",            "/",          "usr" },
-		{ "/usr/lib",         "/usr",       "lib" },
-		{ "//usr//lib//",     "//usr",      "lib" },
-		{ "/home//dwc//test", "/home//dwc", "test" },
+		{ "usr",              ".",                                                 "usr" },
+		{ "usr/",             ".",                                                 "usr" },
+		{ "",                 ".",                                                 "." },
+		{ "/",                "/",                                                 "/" },
+		{ "///",              "/",                                                 "/" },
+		{ "/usr/",            "/",                                                 "usr" },
+		{ "/usr/lib",         "/usr",                                              "lib" },
+		{ "//usr//lib//",     "//usr"      + ("/" when ODIN_OS == .Haiku else ""), "lib" },
+		{ "/home//dwc//test", "/home//dwc" + ("/" when ODIN_OS == .Haiku else ""), "test" },
 	}
 
 	for test in tests {

+ 1 - 1
tests/core/sys/posix/structs.odin

@@ -1,4 +1,4 @@
-#+build linux, darwin, freebsd, openbsd, netbsd
+#+build linux, darwin, freebsd, openbsd, netbsd, haiku
 package tests_core_posix
 
 import "core:log"

+ 13 - 0
tests/core/sys/posix/structs/structs.c

@@ -10,7 +10,11 @@
 #include <netdb.h>
 #include <poll.h>
 #include <pwd.h>
+
+#ifndef __HAIKU__
 #include <sys/shm.h>
+#endif
+
 #include <sys/ipc.h>
 #include <sys/msg.h>
 #include <sys/un.h>
@@ -25,7 +29,11 @@
 #include <sys/statvfs.h>
 #include <sys/time.h>
 #include <utime.h>
+
+#ifndef __HAIKU__
 #include <wordexp.h>
+#endif
+
 #include <sys/socket.h>
 
 int main(int argc, char *argv[])
@@ -67,7 +75,10 @@ int main(int argc, char *argv[])
 
 	printf("passwd %zu %zu\n", sizeof(struct passwd), _Alignof(struct passwd));
 
+#ifndef __HAIKU__
 	printf("shmid_ds %zu %zu\n", sizeof(struct shmid_ds), _Alignof(struct shmid_ds));
+#endif
+
 	printf("ipc_perm %zu %zu\n", sizeof(struct ipc_perm), _Alignof(struct ipc_perm));
 	printf("msqid_ds %zu %zu\n", sizeof(struct msqid_ds), _Alignof(struct msqid_ds));
 
@@ -95,7 +106,9 @@ int main(int argc, char *argv[])
 
 	printf("utimbuf %zu %zu\n", sizeof(struct utimbuf), _Alignof(struct utimbuf));
 
+#ifndef __HAIKU__
 	printf("wordexp_t %zu %zu\n", sizeof(wordexp_t), _Alignof(wordexp_t));
+#endif
 
 	printf("time_t %zu %zu\n", sizeof(time_t), _Alignof(time_t));
 	printf("timespec %zu %zu\n", sizeof(struct timespec), _Alignof(struct timespec));

+ 8 - 3
tests/core/sys/posix/structs/structs.odin

@@ -42,7 +42,10 @@ main :: proc() {
 	fmt.println("pollfd", size_of(posix.pollfd), align_of(posix.pollfd))
 	fmt.println("passwd", size_of(posix.passwd), align_of(posix.passwd))
 
-	fmt.println("shmid_ds", size_of(posix.shmid_ds), align_of(posix.shmid_ds))
+	when ODIN_OS != .Haiku {
+		fmt.println("shmid_ds", size_of(posix.shmid_ds), align_of(posix.shmid_ds))
+	}
+	
 	fmt.println("ipc_perm", size_of(posix.ipc_perm), align_of(posix.ipc_perm))
 	fmt.println("msqid_ds", size_of(posix.msqid_ds), align_of(posix.msqid_ds))
 
@@ -70,8 +73,10 @@ main :: proc() {
 
 	fmt.println("utimbuf", size_of(posix.utimbuf), align_of(posix.utimbuf))
 
-	fmt.println("wordexp_t", size_of(posix.wordexp_t), align_of(posix.wordexp_t))
-
+	when ODIN_OS != .Haiku {
+		fmt.println("wordexp_t", size_of(posix.wordexp_t), align_of(posix.wordexp_t))
+	}
+	
 	fmt.println("time_t", size_of(posix.time_t), align_of(posix.time_t))
 	fmt.println("timespec", size_of(posix.timespec), align_of(posix.timespec))
 	fmt.println("clock_t", size_of(posix.clock_t), align_of(posix.clock_t))