From 49ddbd9b99ec5832b06d279ef7e172e69fba2e2e Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Sun, 20 Oct 2024 18:38:37 +0200 Subject: [PATCH] sys/posix: impl rest of linux, impl some of Windows --- core/c/libc/README.md | 4 +- core/c/libc/locale.odin | 133 ++++++++++++++ core/os/os_linux.odin | 2 +- core/sys/posix/arpa_inet.odin | 1 + core/sys/posix/dirent.odin | 3 +- core/sys/posix/dlfcn.odin | 3 +- core/sys/posix/errno.odin | 82 ++++++++- core/sys/posix/fcntl.odin | 7 +- core/sys/posix/fnmatch.odin | 3 +- core/sys/posix/glob.odin | 3 +- core/sys/posix/grp.odin | 3 +- core/sys/posix/iconv.odin | 1 + core/sys/posix/langinfo.odin | 1 + core/sys/posix/libgen.odin | 8 + core/sys/posix/limits.odin | 3 +- core/sys/posix/locale.odin | 132 +------------- core/sys/posix/monetary.odin | 1 + core/sys/posix/net_if.odin | 3 +- core/sys/posix/netdb.odin | 3 +- core/sys/posix/netinet_in.odin | 8 +- core/sys/posix/netinet_tcp.odin | 3 +- core/sys/posix/poll.odin | 4 +- core/sys/posix/posix.odin | 3 + core/sys/posix/pthread.odin | 5 +- core/sys/posix/pwd.odin | 15 +- core/sys/posix/sched.odin | 3 +- core/sys/posix/setjmp.odin | 6 +- core/sys/posix/setjmp_libc.odin | 11 ++ core/sys/posix/signal.odin | 111 +----------- core/sys/posix/signal_libc.odin | 145 +++++++++++++++ core/sys/posix/stdio.odin | 173 +----------------- core/sys/posix/stdio_libc.odin | 207 ++++++++++++++++++++++ core/sys/posix/stdlib.odin | 79 +-------- core/sys/posix/stdlib_libc.odin | 101 +++++++++++ core/sys/posix/string.odin | 15 +- core/sys/posix/string_libc.odin | 30 ++++ core/sys/posix/sys_ipc.odin | 3 +- core/sys/posix/sys_mman.odin | 3 +- core/sys/posix/sys_msg.odin | 23 ++- core/sys/posix/sys_resource.odin | 3 +- core/sys/posix/sys_select.odin | 5 +- core/sys/posix/sys_sem.odin | 3 +- core/sys/posix/sys_shm.odin | 23 ++- core/sys/posix/sys_socket.odin | 10 +- core/sys/posix/sys_stat.odin | 187 ++++++++++++------- core/sys/posix/sys_statvfs.odin | 26 ++- core/sys/posix/sys_time.odin | 3 +- core/sys/posix/sys_times.odin | 3 +- core/sys/posix/sys_uio.odin | 3 +- core/sys/posix/sys_un.odin | 3 +- core/sys/posix/sys_utsname.odin | 27 +-- core/sys/posix/sys_wait.odin | 53 +++++- core/sys/posix/termios.odin | 17 +- core/sys/posix/time.odin | 15 +- core/sys/posix/ulimit.odin | 3 +- core/sys/posix/unistd.odin | 112 +----------- core/sys/posix/unistd_libc.odin | 153 ++++++++++++++++ core/sys/posix/utime.odin | 3 +- core/sys/posix/wordexp.odin | 3 +- tests/core/sys/posix/posix.odin | 17 +- tests/core/sys/posix/structs.odin | 2 +- tests/core/sys/posix/structs/structs.c | 2 + tests/core/sys/posix/structs/structs.odin | 6 +- 63 files changed, 1237 insertions(+), 789 deletions(-) create mode 100644 core/c/libc/locale.odin create mode 100644 core/sys/posix/setjmp_libc.odin create mode 100644 core/sys/posix/signal_libc.odin create mode 100644 core/sys/posix/stdio_libc.odin create mode 100644 core/sys/posix/stdlib_libc.odin create mode 100644 core/sys/posix/string_libc.odin create mode 100644 core/sys/posix/unistd_libc.odin diff --git a/core/c/libc/README.md b/core/c/libc/README.md index 95053b963..08e789757 100644 --- a/core/c/libc/README.md +++ b/core/c/libc/README.md @@ -14,7 +14,7 @@ The following is a mostly-complete projection of the C11 standard library as def | `` | Fully projected | | `` | Not applicable, use Odin's operators | | `` | Not projected | -| `` | Not projected | +| `` | Fully projected | | `` | Mostly projected, see [limitations](#Limitations) | | `` | Fully projected | | `` | Fully projected | @@ -70,4 +70,4 @@ with the following copyright. ``` Copyright 2021 Dale Weiler . -``` \ No newline at end of file +``` diff --git a/core/c/libc/locale.odin b/core/c/libc/locale.odin new file mode 100644 index 000000000..371d755c5 --- /dev/null +++ b/core/c/libc/locale.odin @@ -0,0 +1,133 @@ +package libc + +import "core:c" + +when ODIN_OS == .Windows { + foreign import libc "system:libucrt.lib" +} else when ODIN_OS == .Darwin { + foreign import libc "system:System.framework" +} else { + foreign import libc "system:c" +} + +// locale.h - category macros + +foreign libc { + /* + Sets the components of an object with the type lconv with the values appropriate for the + formatting of numeric quantities (monetary and otherwise) according to the rules of the current + locale. + + Returns: a pointer to the lconv structure, might be invalidated by subsequent calls to localeconv() and setlocale() + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/localeconv.html ]] + */ + localeconv :: proc() -> ^lconv --- + + /* + Selects the appropriate piece of the global locale, as specified by the category and locale arguments, + and can be used to change or query the entire global locale or portions thereof. + + Returns: the current locale if `locale` is `nil`, the set locale otherwise + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setlocale.html ]] + */ + @(link_name=LSETLOCALE) + setlocale :: proc(category: Locale_Category, locale: cstring) -> cstring --- +} + +Locale_Category :: enum c.int { + ALL = LC_ALL, + COLLATE = LC_COLLATE, + CTYPE = LC_CTYPE, + MESSAGES = LC_MESSAGES, + MONETARY = LC_MONETARY, + NUMERIC = LC_NUMERIC, + TIME = LC_TIME, +} + +when ODIN_OS == .NetBSD { + @(private) LSETLOCALE :: "__setlocale50" +} else { + @(private) LSETLOCALE :: "setlocale" +} + +when ODIN_OS == .Windows { + lconv :: struct { + decimal_point: cstring, + thousand_sep: cstring, + grouping: cstring, + int_curr_symbol: cstring, + currency_symbol: cstring, + mon_decimal_points: cstring, + mon_thousands_sep: cstring, + mon_grouping: cstring, + positive_sign: cstring, + negative_sign: cstring, + int_frac_digits: c.char, + frac_digits: c.char, + p_cs_precedes: c.char, + p_sep_by_space: c.char, + n_cs_precedes: c.char, + n_sep_by_space: c.char, + p_sign_posn: c.char, + n_sign_posn: c.char, + _W_decimal_point: [^]u16 `fmt:"s,0"`, + _W_thousands_sep: [^]u16 `fmt:"s,0"`, + _W_int_curr_symbol: [^]u16 `fmt:"s,0"`, + _W_currency_symbol: [^]u16 `fmt:"s,0"`, + _W_mon_decimal_point: [^]u16 `fmt:"s,0"`, + _W_mon_thousands_sep: [^]u16 `fmt:"s,0"`, + _W_positive_sign: [^]u16 `fmt:"s,0"`, + _W_negative_sign: [^]u16 `fmt:"s,0"`, + } +} else { + lconv :: struct { + decimal_point: cstring, + thousand_sep: cstring, + grouping: cstring, + int_curr_symbol: cstring, + currency_symbol: cstring, + mon_decimal_points: cstring, + mon_thousands_sep: cstring, + mon_grouping: cstring, + positive_sign: cstring, + negative_sign: cstring, + int_frac_digits: c.char, + frac_digits: c.char, + p_cs_precedes: c.char, + p_sep_by_space: c.char, + n_cs_precedes: c.char, + n_sep_by_space: c.char, + p_sign_posn: c.char, + n_sign_posn: c.char, + _int_p_cs_precedes: c.char, + _int_n_cs_precedes: c.char, + _int_p_sep_by_space: c.char, + _int_n_sep_by_space: c.char, + _int_p_sign_posn: c.char, + _int_n_sign_posn: c.char, + } +} + +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Windows { + + LC_ALL :: 0 + LC_COLLATE :: 1 + LC_CTYPE :: 2 + LC_MESSAGES :: 6 + LC_MONETARY :: 3 + LC_NUMERIC :: 4 + LC_TIME :: 5 + +} else when ODIN_OS == .Linux { + + LC_CTYPE :: 0 + LC_NUMERIC :: 1 + LC_TIME :: 2 + LC_COLLATE :: 3 + LC_MONETARY :: 4 + LC_MESSAGES :: 5 + LC_ALL :: 6 + +} diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index fe8215135..e023ce7cb 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -490,7 +490,7 @@ foreign libc { @(link_name="free") _unix_free :: proc(ptr: rawptr) --- @(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr --- - @(link_name="execvp") _unix_execvp :: proc(path: cstring, argv: [^]cstring) -> int --- + @(link_name="execvp") _unix_execvp :: proc(path: cstring, argv: [^]cstring) -> c.int --- @(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring --- @(link_name="putenv") _unix_putenv :: proc(cstring) -> c.int --- @(link_name="setenv") _unix_setenv :: proc(key: cstring, value: cstring, overwrite: c.int) -> c.int --- diff --git a/core/sys/posix/arpa_inet.odin b/core/sys/posix/arpa_inet.odin index 7e950c4be..d3592dd80 100644 --- a/core/sys/posix/arpa_inet.odin +++ b/core/sys/posix/arpa_inet.odin @@ -1,3 +1,4 @@ +#+build darwin, linux, freebsd, openbsd, netbsd package posix import "core:c" diff --git a/core/sys/posix/dirent.odin b/core/sys/posix/dirent.odin index 48830b030..836800397 100644 --- a/core/sys/posix/dirent.odin +++ b/core/sys/posix/dirent.odin @@ -1,3 +1,4 @@ +#+build darwin, linux, freebsd, openbsd, netbsd package posix import "core:c" @@ -210,6 +211,4 @@ when ODIN_OS == .Darwin { d_name: [256]c.char `fmt:"s,0"`, /* [PSX] entry name */ } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/dlfcn.odin b/core/sys/posix/dlfcn.odin index 6a467a2bd..e84b29d79 100644 --- a/core/sys/posix/dlfcn.odin +++ b/core/sys/posix/dlfcn.odin @@ -1,3 +1,4 @@ +#+build darwin, linux, freebsd, openbsd, netbsd package posix import "core:c" @@ -120,7 +121,5 @@ when ODIN_OS == .Darwin { _RTLD_LOCAL :: 0 RTLD_LOCAL :: RTLD_Flags{} -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/errno.odin b/core/sys/posix/errno.odin index e670ca889..9bc77f12e 100644 --- a/core/sys/posix/errno.odin +++ b/core/sys/posix/errno.odin @@ -1,3 +1,4 @@ +#+build windows, darwin, linux, freebsd, openbsd, netbsd package posix import "core:c" @@ -456,7 +457,84 @@ when ODIN_OS == .Darwin { EOWNERDEAD :: 130 ENOTRECOVERABLE :: 131 -} else { - #panic("posix is unimplemented for the current target") +} else when ODIN_OS == .Windows { + E2BIG :: 7 + EACCES :: 13 + EADDRINUSE :: 100 + EADDRNOTAVAIL :: 101 + EAFNOSUPPORT :: 102 + EAGAIN :: 11 + EALREADY :: 103 + EBADF :: 9 + EBADMSG :: 104 + EBUSY :: 16 + ECANCELED :: 105 + ECHILD :: 10 + ECONNABORTED :: 106 + ECONNREFUSED :: 107 + ECONNRESET :: 108 + EDEADLK :: 36 + EDESTADDRREQ :: 109 + EDQUOT :: -1 // NOTE: not defined + EEXIST :: 17 + EFAULT :: 14 + EFBIG :: 27 + EHOSTUNREACH :: 110 + EIDRM :: 111 + EINPROGRESS :: 112 + EINTR :: 4 + EINVAL :: 22 + EIO :: 5 + EISCONN :: 113 + EISDIR :: 21 + ELOOP :: 114 + EMFILE :: 24 + EMLINK :: 31 + EMSGSIZE :: 115 + EMULTIHOP :: -1 // NOTE: not defined + ENAMETOOLONG :: 38 + ENETDOWN :: 116 + ENETRESET :: 117 + ENETUNREACH :: 118 + ENFILE :: 23 + ENOBUFS :: 119 + ENODATA :: 120 + ENODEV :: 19 + ENOENT :: 2 + ENOEXEC :: 8 + ENOLCK :: 39 + ENOLINK :: 121 + ENOMEM :: 12 + ENOMSG :: 122 + ENOPROTOOPT :: 123 + ENOSPC :: 28 + ENOSR :: 124 + ENOSTR :: 125 + ENOSYS :: 40 + ENOTCONN :: 126 + ENOTDIR :: 20 + ENOTEMPTY :: 41 + ENOTRECOVERABLE :: 127 + ENOTSOCK :: 128 + ENOTSUP :: 129 + ENOTTY :: 25 + ENXIO :: 6 + EOPNOTSUPP :: 130 + EOVERFLOW :: 132 + EOWNERDEAD :: 133 + EPERM :: 1 + EPIPE :: 32 + EPROTO :: 134 + EPROTONOSUPPORT :: 135 + EPROTOTYPE :: 136 + EROFS :: 30 + ESPIPE :: 29 + ESRCH :: 3 + ESTALE :: -1 // NOTE: not defined + ETIME :: 137 + ETIMEDOUT :: 138 + ETXTBSY :: 139 + EWOULDBLOCK :: 140 + EXDEV :: 18 } diff --git a/core/sys/posix/fcntl.odin b/core/sys/posix/fcntl.odin index 1ccc07c54..d948af600 100644 --- a/core/sys/posix/fcntl.odin +++ b/core/sys/posix/fcntl.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, openbsd, freebsd, netbsd package posix import "core:c" @@ -466,13 +467,11 @@ when ODIN_OS == .Darwin { AT_REMOVEDIR :: 0x200 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. */ - l_type: Lock_Type, /* [PSX] type of lock. */ - l_whence: c.short, /* [PSX] flag (Whence) of starting offset. */ } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/fnmatch.odin b/core/sys/posix/fnmatch.odin index 1326ce9e4..2d582705c 100644 --- a/core/sys/posix/fnmatch.odin +++ b/core/sys/posix/fnmatch.odin @@ -1,3 +1,4 @@ +#+build darwin, linux, openbsd, freebsd, netbsd package posix import "core:c" @@ -61,6 +62,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS FNM_NOESCAPE :: 0x02 FNM_PERIOD :: 0x04 -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/glob.odin b/core/sys/posix/glob.odin index c17f8b2c3..7c8009a59 100644 --- a/core/sys/posix/glob.odin +++ b/core/sys/posix/glob.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -203,6 +204,4 @@ when ODIN_OS == .Darwin { GLOB_ABORTED :: 2 GLOB_NOMATCH :: 3 -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/grp.odin b/core/sys/posix/grp.odin index 3a78e2c4c..956ed148b 100644 --- a/core/sys/posix/grp.odin +++ b/core/sys/posix/grp.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -125,6 +126,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS gr_mem: [^]cstring, /* [PSX] group members */ } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/iconv.odin b/core/sys/posix/iconv.odin index 59248890f..f7447be9e 100644 --- a/core/sys/posix/iconv.odin +++ b/core/sys/posix/iconv.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" diff --git a/core/sys/posix/langinfo.odin b/core/sys/posix/langinfo.odin index 04b46921c..3c001aee0 100644 --- a/core/sys/posix/langinfo.odin +++ b/core/sys/posix/langinfo.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" diff --git a/core/sys/posix/libgen.odin b/core/sys/posix/libgen.odin index 99506797e..69176a557 100644 --- a/core/sys/posix/libgen.odin +++ b/core/sys/posix/libgen.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix when ODIN_OS == .Darwin { @@ -56,6 +57,7 @@ foreign lib { [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/basename.html ]] */ + @(link_name=LBASENAME) basename :: proc(path: cstring) -> cstring --- /* @@ -72,3 +74,9 @@ foreign lib { */ dirname :: proc(path: cstring) -> cstring --- } + +when ODIN_OS == .Linux { + @(private) LBASENAME :: "__xpg_basename" +} else { + @(private) LBASENAME :: "basename" +} diff --git a/core/sys/posix/limits.odin b/core/sys/posix/limits.odin index 58adce0a1..6680986ad 100644 --- a/core/sys/posix/limits.odin +++ b/core/sys/posix/limits.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix // limits.h - implementation-defined constants @@ -549,6 +550,4 @@ when ODIN_OS == .Darwin { NL_TEXTMAX :: 2048 // 255 on glibc, 2048 on musl NZERO :: 20 -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/locale.odin b/core/sys/posix/locale.odin index fae692bcb..5b8d7c216 100644 --- a/core/sys/posix/locale.odin +++ b/core/sys/posix/locale.odin @@ -1,131 +1,11 @@ +#+build windows, linux, darwin, netbsd, openbsd, freebsd package posix -import "core:c" +import "core:c/libc" -when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" -} else { - foreign import lib "system:c" -} +localeconv :: libc.localeconv +setlocale :: libc.setlocale -// locale.h - category macros +lconv :: libc.lconv -foreign lib { - /* - Sets the components of an object with the type lconv with the values appropriate for the - formatting of numeric quantities (monetary and otherwise) according to the rules of the current - locale. - - Returns: a pointer to the lconv structure, might be invalidated by subsequent calls to localeconv() and setlocale() - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/localeconv.html ]] - */ - localeconv :: proc() -> ^lconv --- - - /* - Selects the appropriate piece of the global locale, as specified by the category and locale arguments, - and can be used to change or query the entire global locale or portions thereof. - - Returns: the current locale if `locale` is `nil`, the set locale otherwise - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setlocale.html ]] - */ - @(link_name=LSETLOCALE) - setlocale :: proc(category: Locale_Category, locale: cstring) -> cstring --- -} - -Locale_Category :: enum c.int { - ALL = LC_ALL, - COLLATE = LC_COLLATE, - CTYPE = LC_CTYPE, - MESSAGES = LC_MESSAGES, - MONETARY = LC_MONETARY, - NUMERIC = LC_NUMERIC, - TIME = LC_TIME, -} - -when ODIN_OS == .NetBSD { - @(private) LSETLOCALE :: "__setlocale50" -} else { - @(private) LSETLOCALE :: "setlocale" -} - -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { - - // NOTE: All of these fields are standard ([PSX]). - lconv :: struct { - decimal_point: cstring, - thousand_sep: cstring, - grouping: cstring, - int_curr_symbol: cstring, - currency_symbol: cstring, - mon_decimal_points: cstring, - mon_thousands_sep: cstring, - mon_grouping: cstring, - positive_sign: cstring, - negative_sign: cstring, - int_frac_digits: c.char, - frac_digits: c.char, - p_cs_precedes: c.char, - p_sep_by_space: c.char, - n_cs_precedes: c.char, - n_sep_by_space: c.char, - p_sign_posn: c.char, - n_sign_posn: c.char, - int_p_cs_precedes: c.char, - int_n_cs_precedes: c.char, - int_p_sep_by_space: c.char, - int_n_sep_by_space: c.char, - int_p_sign_posn: c.char, - int_n_sign_posn: c.char, - } - - LC_ALL :: 0 - LC_COLLATE :: 1 - LC_CTYPE :: 2 - LC_MESSAGES :: 6 - LC_MONETARY :: 3 - LC_NUMERIC :: 4 - LC_TIME :: 5 - -} else when ODIN_OS == .Linux { - - // NOTE: All of these fields are standard ([PSX]). - lconv :: struct { - decimal_point: cstring, - thousand_sep: cstring, - grouping: cstring, - int_curr_symbol: cstring, - currency_symbol: cstring, - mon_decimal_points: cstring, - mon_thousands_sep: cstring, - mon_grouping: cstring, - positive_sign: cstring, - negative_sign: cstring, - int_frac_digits: c.char, - frac_digits: c.char, - p_cs_precedes: c.char, - p_sep_by_space: c.char, - n_cs_precedes: c.char, - n_sep_by_space: c.char, - p_sign_posn: c.char, - n_sign_posn: c.char, - int_p_cs_precedes: c.char, - int_n_cs_precedes: c.char, - int_p_sep_by_space: c.char, - int_n_sep_by_space: c.char, - int_p_sign_posn: c.char, - int_n_sign_posn: c.char, - } - - LC_CTYPE :: 0 - LC_NUMERIC :: 1 - LC_TIME :: 2 - LC_COLLATE :: 3 - LC_MONETARY :: 4 - LC_MESSAGES :: 5 - LC_ALL :: 6 - -} else { - #panic("posix is unimplemented for the current target") -} +Locale_Category :: libc.Locale_Category diff --git a/core/sys/posix/monetary.odin b/core/sys/posix/monetary.odin index b4f0c31ee..ee342e211 100644 --- a/core/sys/posix/monetary.odin +++ b/core/sys/posix/monetary.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" diff --git a/core/sys/posix/net_if.odin b/core/sys/posix/net_if.odin index 75c1a863e..774d11b72 100644 --- a/core/sys/posix/net_if.odin +++ b/core/sys/posix/net_if.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -55,6 +56,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS IF_NAMESIZE :: 16 -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/netdb.odin b/core/sys/posix/netdb.odin index f31de2c2b..79e13a140 100644 --- a/core/sys/posix/netdb.odin +++ b/core/sys/posix/netdb.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -472,6 +473,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS EAI_OVERFLOW :: 14 } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/netinet_in.odin b/core/sys/posix/netinet_in.odin index 22bfde9bc..a2cf904ce 100644 --- a/core/sys/posix/netinet_in.odin +++ b/core/sys/posix/netinet_in.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -61,6 +62,11 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS sin6_scope_id: c.uint32_t, /* [PSX] set of interfaces for a scope */ } + ipv6_mreq :: struct { + ipv6mr_multiaddr: in6_addr, /* [PSX] IPv6 multicast address */ + ipv6mr_interface: c.uint, /* [PSX] interface index */ + } + IPV6_MULTICAST_IF :: 17 IPV6_UNICAST_HOPS :: 16 IPV6_MULTICAST_HOPS :: 18 @@ -223,6 +229,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS ) } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/netinet_tcp.odin b/core/sys/posix/netinet_tcp.odin index 284351732..b1da12f5e 100644 --- a/core/sys/posix/netinet_tcp.odin +++ b/core/sys/posix/netinet_tcp.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix // netinet/tcp.h - definitions for the Internet Transmission Control Protocol (TCP) @@ -6,6 +7,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS TCP_NODELAY :: 0x01 -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/poll.odin b/core/sys/posix/poll.odin index 9e38afe12..9c3b8b081 100644 --- a/core/sys/posix/poll.odin +++ b/core/sys/posix/poll.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "base:intrinsics" @@ -92,7 +93,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS POLLHUP :: 0x0010 POLLNVAL :: 0x0020 -} else { - #panic("posix is unimplemented for the current target") } - diff --git a/core/sys/posix/posix.odin b/core/sys/posix/posix.odin index 44486e424..d56217407 100644 --- a/core/sys/posix/posix.odin +++ b/core/sys/posix/posix.odin @@ -11,6 +11,9 @@ The struct fields that are cross-platform are documented with `[PSX]`. Accessing these fields on one target should be the same on others. Other fields are implementation specific. +The parts of POSIX that Windows implements are also supported here, but +other symbols are undefined on Windows targets. + Most macros have been reimplemented in Odin with inlined functions. Unimplemented headers: diff --git a/core/sys/posix/pthread.odin b/core/sys/posix/pthread.odin index 76acb1a3d..6e894117a 100644 --- a/core/sys/posix/pthread.odin +++ b/core/sys/posix/pthread.odin @@ -1,10 +1,11 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { foreign import lib "system:System.framework" -} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD { +} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Linux { foreign import lib "system:pthread" } else { foreign import lib "system:c" @@ -557,6 +558,4 @@ when ODIN_OS == .Darwin { __reserved3: c.int, } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/pwd.odin b/core/sys/posix/pwd.odin index 546d58309..33cbcd7c5 100644 --- a/core/sys/posix/pwd.odin +++ b/core/sys/posix/pwd.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -163,6 +164,16 @@ when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { pw_fields: c.int, } -} else { - #panic("posix is unimplemented for the current target") +} else when ODIN_OS == .Linux { + + 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_gecos: cstring, /* Real name. */ + pw_dir: cstring, /* Home directory. */ + pw_shell: cstring, /* Shell program. */ + } + } diff --git a/core/sys/posix/sched.odin b/core/sys/posix/sched.odin index 3923257aa..e91178b09 100644 --- a/core/sys/posix/sched.odin +++ b/core/sys/posix/sched.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -100,6 +101,4 @@ when ODIN_OS == .Darwin { SCHED_FIFO :: 1 SCHED_RR :: 2 -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/setjmp.odin b/core/sys/posix/setjmp.odin index cb1dad184..926dbd3ad 100644 --- a/core/sys/posix/setjmp.odin +++ b/core/sys/posix/setjmp.odin @@ -1,7 +1,7 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" -import "core:c/libc" when ODIN_OS == .Darwin { foreign import lib "system:System.framework" @@ -43,12 +43,8 @@ foreign lib { sigsetjmp :: proc(env: ^sigjmp_buf, savemask: b32) -> c.int --- } -jmp_buf :: libc.jmp_buf sigjmp_buf :: distinct jmp_buf -longjmp :: libc.longjmp -setjmp :: libc.setjmp - when ODIN_OS == .NetBSD { @(private) LSIGSETJMP :: "__sigsetjmp14" @(private) LSIGLONGJMP :: "__siglongjmp14" diff --git a/core/sys/posix/setjmp_libc.odin b/core/sys/posix/setjmp_libc.odin new file mode 100644 index 000000000..a69dff09f --- /dev/null +++ b/core/sys/posix/setjmp_libc.odin @@ -0,0 +1,11 @@ +#+build windows, linux, darwin, netbsd, openbsd, freebsd +package posix + +import "core:c/libc" + +// setjmp.h - stack environment declarations + +jmp_buf :: libc.jmp_buf + +longjmp :: libc.longjmp +setjmp :: libc.setjmp diff --git a/core/sys/posix/signal.odin b/core/sys/posix/signal.odin index 1e3f05104..4ba4e9943 100644 --- a/core/sys/posix/signal.odin +++ b/core/sys/posix/signal.odin @@ -1,9 +1,9 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "base:intrinsics" import "core:c" -import "core:c/libc" when ODIN_OS == .Darwin { foreign import lib "system:System.framework" @@ -14,31 +14,6 @@ when ODIN_OS == .Darwin { // signal.h - signals foreign lib { - // LIBC: - - /* - Set a signal handler. - - func can either be: - - `auto_cast posix.SIG_DFL` setting the default handler for that specific signal - - `auto_cast posix.SIG_IGN` causing the specific signal to be ignored - - a custom signal handler - - Returns: SIG_ERR (setting errno), the last value of func on success - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html ]] - */ - signal :: proc(sig: Signal, func: proc "c" (Signal)) -> proc "c" (Signal) --- - - /* - Raises a signal, calling its handler and then returning. - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/raise.html ]] - */ - raise :: proc(sig: Signal) -> result --- - - // POSIX: - /* Raise a signal to the process/group specified by pid. @@ -227,72 +202,6 @@ sigval :: struct #raw_union { sigval_ptr: rawptr, /* [PSX] pointer signal value */ } -Signal :: enum c.int { - NONE, - - // LIBC: - - // Process abort signal. - SIGABRT = SIGABRT, - // Erronous arithemtic operation. - SIGFPE = SIGFPE, - // Illegal instruction. - SIGILL = SIGILL, - // Terminal interrupt signal. - SIGINT = SIGINT, - // Invalid memory reference. - SIGSEGV = SIGSEGV, - // Termination signal. - SIGTERM = SIGTERM, - - // POSIX: - - // Process abort signal. - SIGALRM = SIGALRM, - // Access to an undefined portion of a memory object. - SIGBUS = SIGBUS, - // Child process terminated, stopped, or continued. - SIGCHLD = SIGCHLD, - // Continue execution, if stopped. - SIGCONT = SIGCONT, - // Hangup. - SIGHUP = SIGHUP, - // Kill (cannot be caught or ignored). - SIGKILL = SIGKILL, - // Write on a pipe with no one to read it. - SIGPIPE = SIGPIPE, - // Terminal quit signal. - SIGQUIT = SIGQUIT, - // Stop executing (cannot be caught or ignored). - SIGSTOP = SIGSTOP, - // Terminal stop process. - SIGTSTP = SIGTSTP, - // Background process attempting read. - SIGTTIN = SIGTTIN, - // Background process attempting write. - SIGTTOU = SIGTTOU, - // User-defined signal 1. - SIGUSR1 = SIGUSR1, - // User-defined signal 2. - SIGUSR2 = SIGUSR2, - // Pollable event. - SIGPOLL = SIGPOLL, - // Profiling timer expired. - SIGPROF = SIGPROF, - // Bad system call. - SIGSYS = SIGSYS, - // Trace/breakpoint trap. - SIGTRAP = SIGTRAP, - // High bandwidth data is available at a socket. - SIGURG = SIGURG, - // Virtual timer expired. - SIGVTALRM = SIGVTALRM, - // CPU time limit exceeded. - SIGXCPU = SIGXCPU, - // File size limit exceeded. - SIGXFSZ = SIGXFSZ, -} - ILL_Code :: enum c.int { // Illegal opcode. ILLOPC = ILL_ILLOPC, @@ -434,20 +343,6 @@ Sig :: enum c.int { SETMASK = SIG_SETMASK, } -// Request for default signal handling. -SIG_DFL :: libc.SIG_DFL -// Return value from signal() in case of error. -SIG_ERR :: libc.SIG_ERR -// Request that signal be ignored. -SIG_IGN :: libc.SIG_IGN - -SIGABRT :: libc.SIGABRT -SIGFPE :: libc.SIGFPE -SIGILL :: libc.SIGILL -SIGINT :: libc.SIGINT -SIGSEGV :: libc.SIGSEGV -SIGTERM :: libc.SIGTERM - when ODIN_OS == .NetBSD { @(private) LSIGPROCMASK :: "__sigprocmask14" @(private) LSIGACTION :: "__sigaction_siginfo" @@ -1118,7 +1013,7 @@ when ODIN_OS == .Darwin { uid_t :: distinct c.uint32_t sigset_t :: struct { - [1024/(8 * size_of(c.ulong))]val, + __val: [1024/(8 * size_of(c.ulong))]c.ulong, } SIGHUP :: 1 @@ -1285,6 +1180,4 @@ when ODIN_OS == .Darwin { SI_TIMER :: -2 SI_MESGQ :: -3 SI_ASYNCIO :: -4 -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/signal_libc.odin b/core/sys/posix/signal_libc.odin new file mode 100644 index 000000000..aef22da29 --- /dev/null +++ b/core/sys/posix/signal_libc.odin @@ -0,0 +1,145 @@ +#+build linux, windows, darwin, netbsd, openbsd, freebsd +package posix + +import "base:intrinsics" + +import "core:c" +import "core:c/libc" + +when ODIN_OS == .Windows { + foreign import lib "system:libucrt.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "system:System.framework" +} else { + foreign import lib "system:c" +} + +// signal.h - signals + +foreign lib { + /* + Set a signal handler. + + func can either be: + - `auto_cast posix.SIG_DFL` setting the default handler for that specific signal + - `auto_cast posix.SIG_IGN` causing the specific signal to be ignored + - a custom signal handler + + Returns: SIG_ERR (setting errno), the last value of func on success + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html ]] + */ + signal :: proc(sig: Signal, func: proc "c" (Signal)) -> proc "c" (Signal) --- + + /* + Raises a signal, calling its handler and then returning. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/raise.html ]] + */ + raise :: proc(sig: Signal) -> result --- +} + +Signal :: enum c.int { + NONE, + + // LIBC: + + // Process abort signal. + SIGABRT = SIGABRT, + // Erronous arithemtic operation. + SIGFPE = SIGFPE, + // Illegal instruction. + SIGILL = SIGILL, + // Terminal interrupt signal. + SIGINT = SIGINT, + // Invalid memory reference. + SIGSEGV = SIGSEGV, + // Termination signal. + SIGTERM = SIGTERM, + + // POSIX: + + // Process abort signal. + SIGALRM = SIGALRM, + // Access to an undefined portion of a memory object. + SIGBUS = SIGBUS, + // Child process terminated, stopped, or continued. + SIGCHLD = SIGCHLD, + // Continue execution, if stopped. + SIGCONT = SIGCONT, + // Hangup. + SIGHUP = SIGHUP, + // Kill (cannot be caught or ignored). + SIGKILL = SIGKILL, + // Write on a pipe with no one to read it. + SIGPIPE = SIGPIPE, + // Terminal quit signal. + SIGQUIT = SIGQUIT, + // Stop executing (cannot be caught or ignored). + SIGSTOP = SIGSTOP, + // Terminal stop process. + SIGTSTP = SIGTSTP, + // Background process attempting read. + SIGTTIN = SIGTTIN, + // Background process attempting write. + SIGTTOU = SIGTTOU, + // User-defined signal 1. + SIGUSR1 = SIGUSR1, + // User-defined signal 2. + SIGUSR2 = SIGUSR2, + // Pollable event. + SIGPOLL = SIGPOLL, + // Profiling timer expired. + SIGPROF = SIGPROF, + // Bad system call. + SIGSYS = SIGSYS, + // Trace/breakpoint trap. + SIGTRAP = SIGTRAP, + // High bandwidth data is available at a socket. + SIGURG = SIGURG, + // Virtual timer expired. + SIGVTALRM = SIGVTALRM, + // CPU time limit exceeded. + SIGXCPU = SIGXCPU, + // File size limit exceeded. + SIGXFSZ = SIGXFSZ, +} + +// Request for default signal handling. +SIG_DFL :: libc.SIG_DFL +// Return value from signal() in case of error. +SIG_ERR :: libc.SIG_ERR +// Request that signal be ignored. +SIG_IGN :: libc.SIG_IGN + +SIGABRT :: libc.SIGABRT +SIGFPE :: libc.SIGFPE +SIGILL :: libc.SIGILL +SIGINT :: libc.SIGINT +SIGSEGV :: libc.SIGSEGV +SIGTERM :: libc.SIGTERM + +when ODIN_OS == .Windows { + SIGALRM :: -1 + SIGBUS :: -1 + SIGCHLD :: -1 + SIGCONT :: -1 + SIGHUP :: -1 + SIGKILL :: -1 + SIGPIPE :: -1 + SIGQUIT :: -1 + SIGSTOP :: -1 + SIGTSTP :: -1 + SIGTTIN :: -1 + SIGTTOU :: -1 + SIGUSR1 :: -1 + SIGUSR2 :: -1 + SIGPOLL :: -1 + SIGPROF :: -1 + SIGSYS :: -1 + SIGTRAP :: -1 + SIGURG :: -1 + SIGVTALRM :: -1 + SIGXCPU :: -1 + SIGXFSZ :: -1 +} diff --git a/core/sys/posix/stdio.odin b/core/sys/posix/stdio.odin index de716f8d7..24464dfd8 100644 --- a/core/sys/posix/stdio.odin +++ b/core/sys/posix/stdio.odin @@ -1,7 +1,7 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" -import "core:c/libc" when ODIN_OS == .Darwin { foreign import lib "system:System.framework" @@ -32,16 +32,6 @@ foreign lib { */ dprintf :: proc(fildse: FD, format: cstring, #c_vararg args: ..any) -> c.int --- - /* - Equivalent to fprintf but output is written to s, it is the user's responsibility to - ensure there is enough space. - - Return: number of bytes written, negative (setting errno) on failure - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/dprintf.html ]] - */ - sprintf :: proc(s: [^]byte, format: cstring, #c_vararg args: ..any) -> c.int --- - /* Associate a stream with a file descriptor. @@ -115,34 +105,6 @@ foreign lib { */ open_memstream :: proc(bufp: ^[^]byte, sizep: ^c.size_t) -> ^FILE --- - /* - Equivalent to getc but unaffected by locks. - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getc_unlocked.html ]] - */ - getc_unlocked :: proc(stream: ^FILE) -> c.int --- - - /* - Equivalent to getchar but unaffected by locks. - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getc_unlocked.html ]] - */ - getchar_unlocked :: proc() -> c.int --- - - /* - Equivalent to putc but unaffected by locks. - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getc_unlocked.html ]] - */ - putc_unlocked :: proc(ch: c.int, stream: ^FILE) -> c.int --- - - /* - Equivalent to putchar but unaffected by locks. - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getc_unlocked.html ]] - */ - putchar_unlocked :: proc(ch: c.int) -> c.int --- - /* Read a delimited record from the stream. @@ -181,60 +143,6 @@ foreign lib { */ getline :: proc(lineptr: ^cstring, n: ^c.size_t, stream: ^FILE) -> c.ssize_t --- - /* - Get a string from the stdin stream. - - It is up to the user to make sure s is big enough. - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/gets.html ]] - */ - gets :: proc(s: [^]byte) -> cstring --- - - /* - Create a name for a temporary file. - - Returns: an allocated cstring that needs to be freed, nil on failure - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/tempnam.html ]] - */ - tempnam :: proc(dir: cstring, pfx: cstring) -> cstring --- - - /* - Executes the command specified, creating a pipe and returning a pointer to a stream that can - read or write from/to the pipe. - - Returns: nil (setting errno) on failure or a pointer to the stream - - Example: - fp := posix.popen("ls *", "r") - if fp == nil { - /* Handle error */ - } - - path: [1024]byte - for posix.fgets(raw_data(path[:]), len(path), fp) != nil { - posix.printf("%s", &path) - } - - status := posix.pclose(fp) - if status == -1 { - /* Error reported by pclose() */ - } else { - /* Use functions described under wait() to inspect `status` in order - to determine success/failure of the command executed by popen() */ - } - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/popen.html ]] - */ - popen :: proc(command: cstring, mode: cstring) -> ^FILE --- - - /* - Closes a pipe stream to or from a process. - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pclose.html ]] - */ - pclose :: proc(stream: ^FILE) -> c.int --- - /* Equivalent to rename but relative directories are resolved from their respective fds. @@ -243,76 +151,6 @@ foreign lib { renameat :: proc(oldfd: FD, old: cstring, newfd: FD, new: cstring) -> result --- } -clearerr :: libc.clearerr -fclose :: libc.fclose -feof :: libc.feof -ferror :: libc.ferror -fflush :: libc.fflush -fgetc :: libc.fgetc -fgetpos :: libc.fgetpos -fgets :: libc.fgets -fopen :: libc.fopen -fprintf :: libc.fprintf -fputc :: libc.fputc -fread :: libc.fread -freopen :: libc.freopen -fscanf :: libc.fscanf -fseek :: libc.fseek -fsetpos :: libc.fsetpos -ftell :: libc.ftell -fwrite :: libc.fwrite -getc :: libc.getc -getchar :: libc.getchar -perror :: libc.perror -printf :: libc.printf -putc :: libc.puts -putchar :: libc.putchar -puts :: libc.puts -remove :: libc.remove -rename :: libc.rename -rewind :: libc.rewind -scanf :: libc.scanf -setbuf :: libc.setbuf -setvbuf :: libc.setvbuf -snprintf :: libc.snprintf -sscanf :: libc.sscanf -tmpfile :: libc.tmpfile -tmpnam :: libc.tmpnam -vfprintf :: libc.vfprintf -vfscanf :: libc.vfscanf -vprintf :: libc.vprintf -vscanf :: libc.vscanf -vsnprintf :: libc.vsnprintf -vsprintf :: libc.vsprintf -vsscanf :: libc.vsscanf -ungetc :: libc.ungetc - -to_stream :: libc.to_stream - -Whence :: libc.Whence -FILE :: libc.FILE -fpos_t :: libc.fpos_t - -BUFSIZ :: libc.BUFSIZ - -_IOFBF :: libc._IOFBF -_IOLBF :: libc._IOLBF -_IONBF :: libc._IONBF - -SEEK_CUR :: libc.SEEK_CUR -SEEK_END :: libc.SEEK_END -SEEK_SET :: libc.SEEK_SET - -FILENAME_MAX :: libc.FILENAME_MAX -FOPEN_MAX :: libc.FOPEN_MAX -TMP_MAX :: libc.TMP_MAX - -EOF :: libc.EOF - -stderr := libc.stderr -stdin := libc.stdin -stdout := libc.stdout - when ODIN_OS == .Darwin { L_ctermid :: 1024 @@ -327,6 +165,11 @@ when ODIN_OS == .Darwin { P_tmpdir :: "/tmp/" -} else { - #panic("posix is unimplemented for the current target") +} else when ODIN_OS == .Linux { + + L_ctermid :: 20 // 20 on musl, 9 on glibc + L_tmpnam :: 20 + + P_tmpdir :: "/tmp/" + } diff --git a/core/sys/posix/stdio_libc.odin b/core/sys/posix/stdio_libc.odin new file mode 100644 index 000000000..fbd949b2c --- /dev/null +++ b/core/sys/posix/stdio_libc.odin @@ -0,0 +1,207 @@ +#+build linux, windows, linux, darwin, netbsd, openbsd, freebsd +package posix + +import "core:c" +import "core:c/libc" + +when ODIN_OS == .Windows { + foreign import lib { + "system:libucrt.lib", + "system:legacy_stdio_definitions.lib", + } +} else when ODIN_OS == .Darwin { + foreign import lib "system:System.framework" +} else { + foreign import lib "system:c" +} + +// stdio.h - standard buffered input/output + +when ODIN_OS == .Windows { + @(private) LGETC_UNLOCKED :: "_getc_nolock" + @(private) LGETCHAR_UNLOCKED :: "_getchar_nolock" + @(private) LPUTC_UNLOCKED :: "_putc_nolock" + @(private) LPUTCHAR_UNLOCKED :: "_putchar_nolock" + @(private) LTEMPNAM :: "_tempnam" + @(private) LPOPEN :: "_popen" + @(private) LPCLOSE :: "_pclose" +} else { + @(private) LGETC_UNLOCKED :: "getc_unlocked" + @(private) LGETCHAR_UNLOCKED :: "getchar_unlocked" + @(private) LPUTC_UNLOCKED :: "putc_unlocked" + @(private) LPUTCHAR_UNLOCKED :: "putchar_unlocked" + @(private) LTEMPNAM :: "tempnam" + @(private) LPOPEN :: "popen" + @(private) LPCLOSE :: "pclose" +} + +foreign lib { + /* + Equivalent to fprintf but output is written to s, it is the user's responsibility to + ensure there is enough space. + + Return: number of bytes written, negative (setting errno) on failure + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/dprintf.html ]] + */ + sprintf :: proc(s: [^]byte, format: cstring, #c_vararg args: ..any) -> c.int --- + + /* + Equivalent to getc but unaffected by locks. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getc_unlocked.html ]] + */ + @(link_name=LGETC_UNLOCKED) + getc_unlocked :: proc(stream: ^FILE) -> c.int --- + + /* + Equivalent to getchar but unaffected by locks. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getc_unlocked.html ]] + */ + @(link_name=LGETCHAR_UNLOCKED) + getchar_unlocked :: proc() -> c.int --- + + /* + Equivalent to putc but unaffected by locks. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getc_unlocked.html ]] + */ + @(link_name=LPUTC_UNLOCKED) + putc_unlocked :: proc(ch: c.int, stream: ^FILE) -> c.int --- + + /* + Equivalent to putchar but unaffected by locks. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getc_unlocked.html ]] + */ + @(link_name=LPUTCHAR_UNLOCKED) + putchar_unlocked :: proc(ch: c.int) -> c.int --- + + /* + Get a string from the stdin stream. + + It is up to the user to make sure s is big enough. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/gets.html ]] + */ + gets :: proc(s: [^]byte) -> cstring --- + + /* + Create a name for a temporary file. + + Returns: an allocated cstring that needs to be freed, nil on failure + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/tempnam.html ]] + */ + @(link_name=LTEMPNAM) + tempnam :: proc(dir: cstring, pfx: cstring) -> cstring --- + + /* + Executes the command specified, creating a pipe and returning a pointer to a stream that can + read or write from/to the pipe. + + Returns: nil (setting errno) on failure or a pointer to the stream + + Example: + fp := posix.popen("ls *", "r") + if fp == nil { + /* Handle error */ + } + + path: [1024]byte + for posix.fgets(raw_data(path[:]), len(path), fp) != nil { + posix.printf("%s", &path) + } + + status := posix.pclose(fp) + if status == -1 { + /* Error reported by pclose() */ + } else { + /* Use functions described under wait() to inspect `status` in order + to determine success/failure of the command executed by popen() */ + } + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/popen.html ]] + */ + @(link_name=LPOPEN) + popen :: proc(command: cstring, mode: cstring) -> ^FILE --- + + /* + Closes a pipe stream to or from a process. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pclose.html ]] + */ + @(link_name=LPCLOSE) + pclose :: proc(stream: ^FILE) -> c.int --- +} + +clearerr :: libc.clearerr +fclose :: libc.fclose +feof :: libc.feof +ferror :: libc.ferror +fflush :: libc.fflush +fgetc :: libc.fgetc +fgetpos :: libc.fgetpos +fgets :: libc.fgets +fopen :: libc.fopen +fprintf :: libc.fprintf +fputc :: libc.fputc +fread :: libc.fread +freopen :: libc.freopen +fscanf :: libc.fscanf +fseek :: libc.fseek +fsetpos :: libc.fsetpos +ftell :: libc.ftell +fwrite :: libc.fwrite +getc :: libc.getc +getchar :: libc.getchar +perror :: libc.perror +printf :: libc.printf +putc :: libc.puts +putchar :: libc.putchar +puts :: libc.puts +remove :: libc.remove +rename :: libc.rename +rewind :: libc.rewind +scanf :: libc.scanf +setbuf :: libc.setbuf +setvbuf :: libc.setvbuf +snprintf :: libc.snprintf +sscanf :: libc.sscanf +tmpfile :: libc.tmpfile +tmpnam :: libc.tmpnam +vfprintf :: libc.vfprintf +vfscanf :: libc.vfscanf +vprintf :: libc.vprintf +vscanf :: libc.vscanf +vsnprintf :: libc.vsnprintf +vsprintf :: libc.vsprintf +vsscanf :: libc.vsscanf +ungetc :: libc.ungetc + +to_stream :: libc.to_stream + +Whence :: libc.Whence +FILE :: libc.FILE +fpos_t :: libc.fpos_t + +BUFSIZ :: libc.BUFSIZ + +_IOFBF :: libc._IOFBF +_IOLBF :: libc._IOLBF +_IONBF :: libc._IONBF + +SEEK_CUR :: libc.SEEK_CUR +SEEK_END :: libc.SEEK_END +SEEK_SET :: libc.SEEK_SET + +FILENAME_MAX :: libc.FILENAME_MAX +FOPEN_MAX :: libc.FOPEN_MAX +TMP_MAX :: libc.TMP_MAX + +EOF :: libc.EOF + +stderr := libc.stderr +stdin := libc.stdin +stdout := libc.stdout diff --git a/core/sys/posix/stdlib.odin b/core/sys/posix/stdlib.odin index a1e2eab50..640c70b5a 100644 --- a/core/sys/posix/stdlib.odin +++ b/core/sys/posix/stdlib.odin @@ -1,9 +1,9 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "base:intrinsics" import "core:c" -import "core:c/libc" when ODIN_OS == .Darwin { foreign import lib "system:System.framework" @@ -11,56 +11,6 @@ when ODIN_OS == .Darwin { foreign import lib "system:c" } -// stdlib.h - standard library definitions - -atof :: libc.atof -atoi :: libc.atoi -atol :: libc.atol -atoll :: libc.atoll -strtod :: libc.strtod -strtof :: libc.strtof -strtol :: libc.strtol -strtoll :: libc.strtoll -strtoul :: libc.strtoul -strtoull :: libc.strtoull - -rand :: libc.rand -srand :: libc.srand - -calloc :: libc.calloc -malloc :: libc.malloc -realloc :: libc.realloc - -abort :: libc.abort -atexit :: libc.atexit -at_quick_exit :: libc.at_quick_exit -exit :: libc.exit -_Exit :: libc._Exit -getenv :: libc.getenv -quick_exit :: libc.quick_exit -system :: libc.system - -bsearch :: libc.bsearch -qsort :: libc.qsort - -abs :: libc.abs -labs :: libc.labs -llabs :: libc.llabs -div :: libc.div -ldiv :: libc.ldiv -lldiv :: libc.lldiv - -mblen :: libc.mblen -mbtowc :: libc.mbtowc -wctomb :: libc.wctomb - -mbstowcs :: libc.mbstowcs -wcstombs :: libc.wcstombs - -free :: #force_inline proc(ptr: $T) where intrinsics.type_is_pointer(T) || intrinsics.type_is_multi_pointer(T) || T == cstring { - libc.free(rawptr(ptr)) -} - foreign lib { /* Takes a pointer to a radix-64 representation, in which the first digit is the least significant, @@ -342,21 +292,6 @@ foreign lib { */ unlockpt :: proc(fildes: FD) -> result --- - /* - Uses the string argument to set environment variable values. - - Returns: 0 on success, non-zero (setting errno) on failure - - Example: - if posix.putenv("HOME=/usr/home") != 0 { - fmt.panicf("putenv failure: %v", posix.strerror(posix.errno())) - } - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/putenv.html ]] - */ - @(link_name=LPUTENV) - putenv :: proc(string: cstring) -> c.int --- - /* Updates or add a variable in the environment of the calling process. @@ -427,23 +362,11 @@ foreign lib { setkey :: proc(key: [^]byte) --- } -EXIT_FAILURE :: libc.EXIT_FAILURE -EXIT_SUCCESS :: libc.EXIT_SUCCESS - -RAND_MAX :: libc.RAND_MAX -MB_CUR_MAX :: libc.MB_CUR_MAX - -div_t :: libc.div_t -ldiv_t :: libc.ldiv_t -lldiv_t :: libc.lldiv_t - when ODIN_OS == .NetBSD { - @(private) LPUTENV :: "__putenv50" @(private) LINITSTATE :: "__initstate60" @(private) LSRANDOM :: "__srandom60" @(private) LUNSETENV :: "__unsetenv13" } else { - @(private) LPUTENV :: "putenv" @(private) LINITSTATE :: "initstate" @(private) LSRANDOM :: "srandom" @(private) LUNSETENV :: "unsetenv" diff --git a/core/sys/posix/stdlib_libc.odin b/core/sys/posix/stdlib_libc.odin new file mode 100644 index 000000000..fa4d925b2 --- /dev/null +++ b/core/sys/posix/stdlib_libc.odin @@ -0,0 +1,101 @@ +#+build linux, windows, darwin, netbsd, openbsd, freebsd +package posix + +import "base:intrinsics" + +import "core:c" +import "core:c/libc" + +when ODIN_OS == .Windows { + foreign import lib "system:libucrt.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "system:System.framework" +} else { + foreign import lib "system:c" +} + +// stdlib.h - standard library definitions + +atof :: libc.atof +atoi :: libc.atoi +atol :: libc.atol +atoll :: libc.atoll +strtod :: libc.strtod +strtof :: libc.strtof +strtol :: libc.strtol +strtoll :: libc.strtoll +strtoul :: libc.strtoul +strtoull :: libc.strtoull + +rand :: libc.rand +srand :: libc.srand + +calloc :: libc.calloc +malloc :: libc.malloc +realloc :: libc.realloc + +abort :: libc.abort +atexit :: libc.atexit +at_quick_exit :: libc.at_quick_exit +exit :: libc.exit +_Exit :: libc._Exit +getenv :: libc.getenv +quick_exit :: libc.quick_exit +system :: libc.system + +bsearch :: libc.bsearch +qsort :: libc.qsort + +abs :: libc.abs +labs :: libc.labs +llabs :: libc.llabs +div :: libc.div +ldiv :: libc.ldiv +lldiv :: libc.lldiv + +mblen :: libc.mblen +mbtowc :: libc.mbtowc +wctomb :: libc.wctomb + +mbstowcs :: libc.mbstowcs +wcstombs :: libc.wcstombs + +free :: #force_inline proc(ptr: $T) where intrinsics.type_is_pointer(T) || intrinsics.type_is_multi_pointer(T) || T == cstring { + libc.free(rawptr(ptr)) +} + +foreign lib { + + /* + Uses the string argument to set environment variable values. + + Returns: 0 on success, non-zero (setting errno) on failure + + Example: + if posix.putenv("HOME=/usr/home") != 0 { + fmt.panicf("putenv failure: %v", posix.strerror(posix.errno())) + } + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/putenv.html ]] + */ + @(link_name=LPUTENV) + putenv :: proc(string: cstring) -> c.int --- +} + +EXIT_FAILURE :: libc.EXIT_FAILURE +EXIT_SUCCESS :: libc.EXIT_SUCCESS + +RAND_MAX :: libc.RAND_MAX +MB_CUR_MAX :: libc.MB_CUR_MAX + +div_t :: libc.div_t +ldiv_t :: libc.ldiv_t +lldiv_t :: libc.lldiv_t + +when ODIN_OS == .Windows { + @(private) LPUTENV :: "_putenv" +} else when ODIN_OS == .NetBSD { + @(private) LPUTENV :: "__putenv50" +} else { + @(private) LPUTENV :: "putenv" +} diff --git a/core/sys/posix/string.odin b/core/sys/posix/string.odin index d22f49a96..96b6a9007 100644 --- a/core/sys/posix/string.odin +++ b/core/sys/posix/string.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -13,16 +14,6 @@ when ODIN_OS == .Darwin { // NOTE: most of the symbols in this header are not useful in Odin and have been left out. foreign lib { - /* - Map the error number to a locale-dependent error message string. - - Returns: a string that may be invalidated by subsequent calls - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/strerror.html ]] - */ - @(link_name="strerror") - _strerror :: proc(errnum: Errno) -> cstring --- - /* Map the error number to a locale-dependent error message string and put it in the buffer. @@ -41,7 +32,3 @@ foreign lib { */ strsignal :: proc(sig: Signal) -> cstring --- } - -strerror :: #force_inline proc "contextless" (errnum: Maybe(Errno) = nil) -> cstring { - return _strerror(errnum.? or_else errno()) -} diff --git a/core/sys/posix/string_libc.odin b/core/sys/posix/string_libc.odin new file mode 100644 index 000000000..336352cbc --- /dev/null +++ b/core/sys/posix/string_libc.odin @@ -0,0 +1,30 @@ +#+build linux, windows, darwin, netbsd, openbsd, freebsd +package posix + +when ODIN_OS == .Windows { + foreign import lib "system:libucrt.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "system:System.framework" +} else { + foreign import lib "system:c" +} + +// string.h - string operations + +// NOTE: most of the symbols in this header are not useful in Odin and have been left out. + +foreign lib { + /* + Map the error number to a locale-dependent error message string. + + Returns: a string that may be invalidated by subsequent calls + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/strerror.html ]] + */ + @(link_name="strerror") + _strerror :: proc(errnum: Errno) -> cstring --- +} + +strerror :: #force_inline proc "contextless" (errnum: Maybe(Errno) = nil) -> cstring { + return _strerror(errnum.? or_else errno()) +} diff --git a/core/sys/posix/sys_ipc.odin b/core/sys/posix/sys_ipc.odin index 33f8fa259..0f7ec06c5 100644 --- a/core/sys/posix/sys_ipc.odin +++ b/core/sys/posix/sys_ipc.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -110,6 +111,4 @@ when ODIN_OS == .Darwin { IPC_SET :: 1 IPC_STAT :: 2 -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/sys_mman.odin b/core/sys/posix/sys_mman.odin index 2f4eb566b..9e2939a05 100644 --- a/core/sys/posix/sys_mman.odin +++ b/core/sys/posix/sys_mman.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -225,6 +226,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS POSIX_MADV_SEQUENTIAL :: 2 POSIX_MADV_WILLNEED :: 3 -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/sys_msg.odin b/core/sys/posix/sys_msg.odin index 98b76c3a5..0e78777f9 100644 --- a/core/sys/posix/sys_msg.odin +++ b/core/sys/posix/sys_msg.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -150,6 +151,24 @@ when ODIN_OS == .Darwin { msg_pad4: [4]c.long, } -} else { - #panic("posix is unimplemented for the current target") +} else when ODIN_OS == .Linux { + + msgqnum_t :: distinct c.ulong + msglen_t :: distinct c.ulong + + MSG_NOERROR :: 0o10000 + + msqid_ds :: struct { + msg_perm: ipc_perm, /* [PSX] operation permission structure */ + 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 */ + msg_cbytes: c.ulong, + 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() */ + __unused: [2]c.ulong, + } + } diff --git a/core/sys/posix/sys_resource.odin b/core/sys/posix/sys_resource.odin index 55789ee95..9af2a929b 100644 --- a/core/sys/posix/sys_resource.odin +++ b/core/sys/posix/sys_resource.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -154,6 +155,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS RLIMIT_AS :: 10 } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/sys_select.odin b/core/sys/posix/sys_select.odin index c20636b21..2058ee777 100644 --- a/core/sys/posix/sys_select.odin +++ b/core/sys/posix/sys_select.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "base:intrinsics" @@ -72,7 +73,7 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS // NOTE: this seems correct for FreeBSD but they do use a set backed by the long type themselves (thus the align change). @(private) - ALIGN :: align_of(c.long) when ODIN_OS == .FreeBSD else align_of(c.int32_t) + 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, @@ -115,6 +116,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS intrinsics.mem_zero(_p, size_of(fd_set)) } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/sys_sem.odin b/core/sys/posix/sys_sem.odin index 2d7bd1b1e..6b695e766 100644 --- a/core/sys/posix/sys_sem.odin +++ b/core/sys/posix/sys_sem.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -153,6 +154,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS sem_flg: c.short, /* [PSX] operation flags */ } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/sys_shm.odin b/core/sys/posix/sys_shm.odin index ff56ba441..8f3c56b9c 100644 --- a/core/sys/posix/sys_shm.odin +++ b/core/sys/posix/sys_shm.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -137,6 +138,24 @@ when ODIN_OS == .Darwin { _shm_internal: rawptr, } -} else { - #panic("posix is unimplemented for the current target") +} else when ODIN_OS == .Linux { + + SHM_RDONLY :: 0o10000 + SHM_RND :: 0o20000 + + SHMLBA :: 4096 + + shmatt_t :: distinct c.ulong + + shmid_ds :: struct { + shm_perm: ipc_perm, /* [PSX] operation permission structure */ + shm_segsz: c.size_t, /* [PSX] size of segment in bytes */ + shm_atime: time_t, /* [PSX] time of last shmat() */ + shm_dtime: time_t, /* [PSX] time of last shmdt() */ + shm_ctime: time_t, /* [PSX] time of last change by shmctl() */ + shm_cpid: pid_t, /* [PSX] process ID of creator */ + shm_lpid: pid_t, /* [PSX] process ID of last shared memory operation */ + shm_nattch: shmatt_t, /* [PSX] number of current attaches */ + _: [2]c.ulong, + } } diff --git a/core/sys/posix/sys_socket.odin b/core/sys/posix/sys_socket.odin index e613f0a10..3c9db5bfa 100644 --- a/core/sys/posix/sys_socket.odin +++ b/core/sys/posix/sys_socket.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -325,14 +326,16 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS socklen_t :: distinct c.uint - _sa_family_t :: distinct c.uint8_t - 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 */ } } 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 */ @@ -560,7 +563,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS SHUT_RDWR :: 2 SHUT_WR :: 1 -} else { - #panic("posix is unimplemented for the current target") } - diff --git a/core/sys/posix/sys_stat.odin b/core/sys/posix/sys_stat.odin index dd66d7d14..61b98ef35 100644 --- a/core/sys/posix/sys_stat.odin +++ b/core/sys/posix/sys_stat.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -280,20 +281,20 @@ when ODIN_OS == .Darwin { ino_t :: distinct c.uint64_t stat_t :: struct { - st_dev: dev_t, /* [XSI] ID of device containing file */ - st_mode: mode_t, /* [XSI] mode of file */ - st_nlink: nlink_t, /* [XSI] number of hard links */ - st_ino: ino_t, /* [XSI] file serial number */ - st_uid: uid_t, /* [XSI] user ID of the file */ - st_gid: gid_t, /* [XSI] group ID of the file */ - st_rdev: dev_t, /* [XSI] device ID */ - st_atim: timespec, /* [XSI] time of last access */ - st_mtim: timespec, /* [XSI] time of last data modification */ - st_ctim: timespec, /* [XSI] time of last status change */ + st_dev: dev_t, /* [PSX] ID of device containing file */ + st_mode: mode_t, /* [PSX] mode of file */ + st_nlink: nlink_t, /* [PSX] number of hard links */ + st_ino: ino_t, /* [PSX] file serial number */ + st_uid: uid_t, /* [PSX] user ID of the file */ + st_gid: gid_t, /* [PSX] group ID of the file */ + st_rdev: dev_t, /* [PSX] device ID */ + 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_birthtimespec: timespec, /* time of file creation(birth) */ - st_size: off_t, /* [XSI] file size, in bytes */ - st_blocks: blkcnt_t, /* [XSI] blocks allocated for file */ - st_blksize: blksize_t, /* [XSI] optimal blocksize for I/O */ + st_size: off_t, /* [PSX] file size, in bytes */ + st_blocks: blkcnt_t, /* [PSX] blocks allocated for file */ + st_blksize: blksize_t, /* [PSX] optimal blocksize for I/O */ st_flags: c.uint32_t, /* user defined flags for file */ st_gen: c.uint32_t, /* file generation number */ st_lspare: c.int32_t, /* RESERVED */ @@ -314,47 +315,47 @@ when ODIN_OS == .Darwin { when ODIN_ARCH == .i386 { stat_t :: struct { - st_dev: dev_t, /* [XSI] ID of device containing file */ - st_ino: ino_t, /* [XSI] file serial number */ - st_nlink: nlink_t, /* [XSI] number of hard links */ - st_mode: mode_t, /* [XSI] mode of file */ + st_dev: dev_t, /* [PSX] ID of device containing file */ + st_ino: ino_t, /* [PSX] file serial number */ + st_nlink: nlink_t, /* [PSX] number of hard links */ + st_mode: mode_t, /* [PSX] mode of file */ st_padding0: c.int16_t, - st_uid: uid_t, /* [XSI] user ID of the file */ - st_gid: gid_t, /* [XSI] group ID of the file */ + st_uid: uid_t, /* [PSX] user ID of the file */ + st_gid: gid_t, /* [PSX] group ID of the file */ st_padding1: c.int32_t, - st_rdev: dev_t, /* [XSI] device ID */ + st_rdev: dev_t, /* [PSX] device ID */ st_atim_ext: c.int32_t, - st_atim: timespec, /* [XSI] time of last access */ + st_atim: timespec, /* [PSX] time of last access */ st_mtim_ext: c.int32_t, - st_mtim: timespec, /* [XSI] time of last data modification */ + st_mtim: timespec, /* [PSX] time of last data modification */ st_ctim_ext: c.int32_t, - st_ctim: timespec, /* [XSI] time of last status change */ + st_ctim: timespec, /* [PSX] time of last status change */ st_birthtimespec: timespec, /* time of file creation(birth) */ - st_size: off_t, /* [XSI] file size, in bytes */ - st_blocks: blkcnt_t, /* [XSI] blocks allocated for file */ - st_blksize: blksize_t, /* [XSI] optimal blocksize for I/O */ + st_size: off_t, /* [PSX] file size, in bytes */ + st_blocks: blkcnt_t, /* [PSX] blocks allocated for file */ + st_blksize: blksize_t, /* [PSX] optimal blocksize for I/O */ st_flags: c.uint32_t, /* user defined flags for file */ st_gen: c.uint64_t, st_spare: [10]c.uint64_t, } } else { stat_t :: struct { - st_dev: dev_t, /* [XSI] ID of device containing file */ - st_ino: ino_t, /* [XSI] file serial number */ - st_nlink: nlink_t, /* [XSI] number of hard links */ - st_mode: mode_t, /* [XSI] mode of file */ + st_dev: dev_t, /* [PSX] ID of device containing file */ + st_ino: ino_t, /* [PSX] file serial number */ + st_nlink: nlink_t, /* [PSX] number of hard links */ + st_mode: mode_t, /* [PSX] mode of file */ st_padding0: c.int16_t, - st_uid: uid_t, /* [XSI] user ID of the file */ - st_gid: gid_t, /* [XSI] group ID of the file */ + st_uid: uid_t, /* [PSX] user ID of the file */ + st_gid: gid_t, /* [PSX] group ID of the file */ st_padding1: c.int32_t, - st_rdev: dev_t, /* [XSI] device ID */ - st_atim: timespec, /* [XSI] time of last access */ - st_mtim: timespec, /* [XSI] time of last data modification */ - st_ctim: timespec, /* [XSI] time of last status change */ + st_rdev: dev_t, /* [PSX] device ID */ + 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_birthtimespec: timespec, /* time of file creation(birth) */ - st_size: off_t, /* [XSI] file size, in bytes */ - st_blocks: blkcnt_t, /* [XSI] blocks allocated for file */ - st_blksize: blksize_t, /* [XSI] optimal blocksize for I/O */ + st_size: off_t, /* [PSX] file size, in bytes */ + st_blocks: blkcnt_t, /* [PSX] blocks allocated for file */ + st_blksize: blksize_t, /* [PSX] optimal blocksize for I/O */ st_flags: c.uint32_t, /* user defined flags for file */ st_gen: c.uint64_t, st_spare: [10]c.uint64_t, @@ -374,20 +375,20 @@ when ODIN_OS == .Darwin { ino_t :: distinct c.uint64_t stat_t :: struct { - st_dev: dev_t, /* [XSI] ID of device containing file */ - st_mode: mode_t, /* [XSI] mode of file */ - st_ino: ino_t, /* [XSI] file serial number */ - st_nlink: nlink_t, /* [XSI] number of hard links */ - st_uid: uid_t, /* [XSI] user ID of the file */ - st_gid: gid_t, /* [XSI] group ID of the file */ - st_rdev: dev_t, /* [XSI] device ID */ - st_atim: timespec, /* [XSI] time of last access */ - st_mtim: timespec, /* [XSI] time of last data modification */ - st_ctim: timespec, /* [XSI] time of last status change */ + st_dev: dev_t, /* [PSX] ID of device containing file */ + st_mode: mode_t, /* [PSX] mode of file */ + st_ino: ino_t, /* [PSX] file serial number */ + 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_rdev: dev_t, /* [PSX] device ID */ + 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_birthtimespec: timespec, /* time of file creation(birth) */ - st_size: off_t, /* [XSI] file size, in bytes */ - st_blocks: blkcnt_t, /* [XSI] blocks allocated for file */ - st_blksize: blksize_t, /* [XSI] optimal blocksize for I/O */ + st_size: off_t, /* [PSX] file size, in bytes */ + st_blocks: blkcnt_t, /* [PSX] blocks allocated for file */ + st_blksize: blksize_t, /* [PSX] optimal blocksize for I/O */ st_flags: c.uint32_t, /* user defined flags for file */ st_gen: c.uint64_t, st_spare: [2]c.uint32_t, @@ -406,19 +407,19 @@ when ODIN_OS == .Darwin { ino_t :: distinct c.uint64_t stat_t :: struct { - st_mode: mode_t, /* [XSI] mode of file */ - st_dev: dev_t, /* [XSI] ID of device containing file */ - st_ino: ino_t, /* [XSI] file serial number */ - st_nlink: nlink_t, /* [XSI] number of hard links */ - st_uid: uid_t, /* [XSI] user ID of the file */ - st_gid: gid_t, /* [XSI] group ID of the file */ - st_rdev: dev_t, /* [XSI] device ID */ - st_atim: timespec, /* [XSI] time of last access */ - st_mtim: timespec, /* [XSI] time of last data modification */ - st_ctim: timespec, /* [XSI] time of last status change */ - st_size: off_t, /* [XSI] file size, in bytes */ - st_blocks: blkcnt_t, /* [XSI] blocks allocated for file */ - st_blksize: blksize_t, /* [XSI] optimal blocksize for I/O */ + st_mode: mode_t, /* [PSX] mode of file */ + st_dev: dev_t, /* [PSX] ID of device containing file */ + st_ino: ino_t, /* [PSX] file serial number */ + 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_rdev: dev_t, /* [PSX] device ID */ + 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_size: off_t, /* [PSX] file size, in bytes */ + st_blocks: blkcnt_t, /* [PSX] blocks allocated for file */ + st_blksize: blksize_t, /* [PSX] optimal blocksize for I/O */ st_flags: c.uint32_t, /* user defined flags for file */ st_gen: c.int32_t, st_birthtimespec: timespec, @@ -427,6 +428,58 @@ when ODIN_OS == .Darwin { UTIME_NOW :: -2 UTIME_OMIT :: -1 -} else { - #panic("posix is unimplemented for the current target") +} else when ODIN_OS == .Linux { + + dev_t :: distinct u64 + _mode_t :: distinct c.uint + blkcnt_t :: distinct i64 + + when ODIN_ARCH == .arm64 || ODIN_ARCH == .riscv64 { + nlink_t :: distinct c.uint + blksize_t :: distinct c.int + } else { + nlink_t :: distinct c.size_t + blksize_t :: distinct c.long + } + + ino_t :: distinct u64 + + when ODIN_ARCH == .amd64 { + stat_t :: struct { + st_dev: dev_t, /* [PSX] ID of device containing file */ + st_ino: ino_t, /* [PSX] file serial number */ + st_nlink: nlink_t, /* [PSX] number of hard links */ + st_mode: mode_t, /* [PSX] mode of file */ + st_uid: uid_t, /* [PSX] user ID of the file */ + st_gid: gid_t, /* [PSX] group ID of the file */ + _pad0: c.uint, + st_rdev: dev_t, /* [PSX] device ID */ + st_size: off_t, /* [PSX] file size, in bytes */ + st_blksize: blksize_t, /* [PSX] optimal blocksize for I/O */ + st_blocks: blkcnt_t, /* [PSX] blocks allocated for file */ + 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 */ + __unused: [3]c.long, + } + } else { + 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_rdev: dev_t, /* [PSX] device ID */ + __pad: c.ulonglong, + st_size: off_t, /* [PSX] file size, in bytes */ + st_blksize: blksize_t, /* [PSX] optimal blocksize for I/O */ + __pad2: c.int, + st_blocks: blkcnt_t, /* [PSX] blocks allocated for file */ + 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 */ + __unused: [2]c.uint, + } + } } diff --git a/core/sys/posix/sys_statvfs.odin b/core/sys/posix/sys_statvfs.odin index eb6c16806..47c810135 100644 --- a/core/sys/posix/sys_statvfs.odin +++ b/core/sys/posix/sys_statvfs.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -130,6 +131,27 @@ when ODIN_OS == .Darwin || ODIN_OS == .OpenBSD { ST_RDONLY :: 0x00000001 ST_NOSUID :: 0x00000008 -} else { - #panic("posix is unimplemented for the current target") +} else when ODIN_OS == .Linux { + + fsblkcnt_t :: distinct c.uint64_t + + statvfs_t :: struct { + f_bsize: c.ulong, /* [PSX] file system block size */ + f_frsize: c.ulong, /* [PSX] fundamental file system block size */ + f_blocks: fsblkcnt_t, /* [PSX] total number of blocks on file system in units of f_frsize */ + f_bfree: fsblkcnt_t, /* [PSX] total number of free blocks */ + f_bavail: fsblkcnt_t, /* [PSX] number of free blocks available to non-privileged process */ + f_files: fsblkcnt_t, /* [PSX] total number of file serial numbers */ + f_ffree: fsblkcnt_t, /* [PSX] total number of free file serial numbers */ + f_favail: fsblkcnt_t, /* [PSX] number of file serial numbers available to non-privileged process */ + f_fsid: c.ulong, /* [PSX] file system ID */ + _: [2*size_of(c.int)-size_of(c.long)]byte, + f_flag: VFS_Flags, /* [PSX] bit mask of f_flag values */ + f_namemax: c.ulong, /* [PSX] maximum filename length */ + f_type: c.uint, + __reserved: [5]c.int, + } + + ST_RDONLY :: 0x00000001 + ST_NOSUID :: 0x00000002 } diff --git a/core/sys/posix/sys_time.odin b/core/sys/posix/sys_time.odin index fd2e58121..3036352aa 100644 --- a/core/sys/posix/sys_time.odin +++ b/core/sys/posix/sys_time.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -77,6 +78,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS ITIMER_VIRTUAL :: 1 ITIMER_PROF :: 2 -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/sys_times.odin b/core/sys/posix/sys_times.odin index d38f3efc4..113e3f963 100644 --- a/core/sys/posix/sys_times.odin +++ b/core/sys/posix/sys_times.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix when ODIN_OS == .Darwin { @@ -33,6 +34,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS tms_cstime: clock_t, /* [PSX] terminated children system CPU time */ } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/sys_uio.odin b/core/sys/posix/sys_uio.odin index 6755fe2ae..a0ad2934e 100644 --- a/core/sys/posix/sys_uio.odin +++ b/core/sys/posix/sys_uio.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -37,6 +38,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS iov_len: c.size_t, /* [PSX] size of the region iov_base points to */ } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/sys_un.odin b/core/sys/posix/sys_un.odin index 15eb7b5fc..ca5c4ee31 100644 --- a/core/sys/posix/sys_un.odin +++ b/core/sys/posix/sys_un.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -19,6 +20,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS sun_path: [108]c.char, /* [PSX] socket pathname */ } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/sys_utsname.odin b/core/sys/posix/sys_utsname.odin index 4786eb4fd..64930160f 100644 --- a/core/sys/posix/sys_utsname.odin +++ b/core/sys/posix/sys_utsname.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -37,15 +38,10 @@ foreign lib { uname :: proc(uname: ^utsname) -> c.int --- } -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 { - when ODIN_OS == .Linux { - @(private) - _SYS_NAMELEN :: 65 - } else { - @(private) - _SYS_NAMELEN :: 256 - } + @(private) + _SYS_NAMELEN :: 256 utsname :: struct { sysname: [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] name of OS */ @@ -55,6 +51,17 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS machine: [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] hardware type */ } -} else { - #panic("posix is unimplemented for the current target") +} else when ODIN_OS == .Linux { + + @(private) + _SYS_NAMELEN :: 65 + + utsname :: struct { + sysname: [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] name of OS */ + nodename: [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] name of this network node */ + release: [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] release level */ + version: [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] version level */ + machine: [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] hardware type */ + __domainname: [_SYS_NAMELEN]c.char `fmt:"s,0"`, + } } diff --git a/core/sys/posix/sys_wait.odin b/core/sys/posix/sys_wait.odin index e0e2ae21b..812bd8c62 100644 --- a/core/sys/posix/sys_wait.odin +++ b/core/sys/posix/sys_wait.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -391,6 +392,54 @@ when ODIN_OS == .Darwin { return (x & _WCONTINUED) == _WCONTINUED } -} else { - #panic("posix is unimplemented for the current target") +} else when ODIN_OS == .Linux { + + id_t :: distinct c.uint + + WCONTINUED :: 8 + WNOHANG :: 1 + WUNTRACED :: 2 + + WEXITED :: 4 + WNOWAIT :: 0x1000000 + WSTOPPED :: 2 + + _P_ALL :: 0 + _P_PID :: 1 + _P_PGID :: 2 + + @(private) + _WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool { + return _WTERMSIG(x) == nil + } + + @(private) + _WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int { + return (x & 0xff00) >> 8 + } + + @(private) + _WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool { + return (x & 0xffff) - 1 < 0xff + } + + @(private) + _WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal { + return Signal(x & 0x7f) + } + + @(private) + _WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool { + return ((x & 0xffff) * 0x10001) >> 8 > 0x7f00 + } + + @(private) + _WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal { + return Signal(_WEXITSTATUS(x)) + } + + @(private) + _WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool { + return x == 0xffff + } } diff --git a/core/sys/posix/termios.odin b/core/sys/posix/termios.odin index c73936d58..0c07eceb9 100644 --- a/core/sys/posix/termios.odin +++ b/core/sys/posix/termios.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -152,7 +153,7 @@ CControl_Flag_Bits :: enum tcflag_t { CControl_Flags :: bit_set[CControl_Flag_Bits; tcflag_t] // character size mask -CSIZE :: CControl_Flags{ .CS6, .CS7, .CS8 } +CSIZE :: transmute(CControl_Flags)tcflag_t(_CSIZE) COutput_Flag_Bits :: enum tcflag_t { OPOST = log2(OPOST), /* enable following output processing */ @@ -181,17 +182,17 @@ COutput_Flag_Bits :: enum tcflag_t { COutput_Flags :: bit_set[COutput_Flag_Bits; tcflag_t] // \n delay mask -NLDLY :: COutput_Flags{ .NL1, COutput_Flag_Bits(9) } +NLDLY :: transmute(COutput_Flags)tcflag_t(_NLDLY) // \r delay mask -CRDLY :: COutput_Flags{ .CR1, .CR2, .CR3 } +CRDLY :: transmute(COutput_Flags)tcflag_t(_CRDLY) // horizontal tab delay mask -TABDLY :: COutput_Flags{ .TAB1, .TAB3, COutput_Flag_Bits(2) } +TABDLY :: transmute(COutput_Flags)tcflag_t(_TABDLY) // \b delay mask -BSDLY :: COutput_Flags{ .BS1 } +BSDLY :: transmute(COutput_Flags)tcflag_t(_BSDLY) // vertical tab delay mask -VTDLY :: COutput_Flags{ .VT1 } +VTDLY :: transmute(COutput_Flags)tcflag_t(_VTDLY) // form feed delay mask -FFDLY :: COutput_Flags{ .FF1 } +FFDLY :: transmute(COutput_Flags)tcflag_t(_FFDLY) speed_t :: enum _speed_t { B0 = B0, @@ -596,6 +597,4 @@ when ODIN_OS == .Darwin { TCOOFF :: 0 TCOON :: 1 -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/time.odin b/core/sys/posix/time.odin index 5c6ebcf2f..f9c51c63c 100644 --- a/core/sys/posix/time.odin +++ b/core/sys/posix/time.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -229,6 +230,16 @@ when ODIN_OS == .Darwin { getdate_err: Errno = .ENOSYS // NOTE: looks like it's not a thing on OpenBSD. -} else { - #panic("posix is unimplemented for the current target") +} else when ODIN_OS == .Linux { + + clockid_t :: distinct c.int + + CLOCK_MONOTONIC :: 1 + CLOCK_PROCESS_CPUTIME_ID :: 2 + CLOCK_REALTIME :: 0 + CLOCK_THREAD_CPUTIME_ID :: 3 + + foreign lib { + getdate_err: Errno + } } diff --git a/core/sys/posix/ulimit.odin b/core/sys/posix/ulimit.odin index 782756f6e..0f87641fa 100644 --- a/core/sys/posix/ulimit.odin +++ b/core/sys/posix/ulimit.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -38,6 +39,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS // NOTE: I don't think OpenBSD implements this API. -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/unistd.odin b/core/sys/posix/unistd.odin index 5b428ef6f..0526b3235 100644 --- a/core/sys/posix/unistd.odin +++ b/core/sys/posix/unistd.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -11,19 +12,6 @@ when ODIN_OS == .Darwin { // unistd.h - standard symbolic constants and types foreign lib { - /* - Checks the file named by the pathname pointed to by the path argument for - accessibility according to the bit pattern contained in amode. - - Example: - if (posix.access("/tmp/myfile", posix.F_OK) != .OK) { - fmt.printfln("/tmp/myfile access check failed: %v", posix.strerror(posix.errno())) - } - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html ]] - */ - access :: proc(path: cstring, amode: Mode_Flags = F_OK) -> result --- - /* Equivalent to `access` but relative paths are resolved based on `fd`. @@ -42,18 +30,6 @@ foreign lib { */ alarm :: proc(seconds: c.uint) -> c.uint --- - /* - Causes the directory named by path to become the current working directory. - - Example: - if (posix.chdir("/tmp") == .OK) { - fmt.println("changed current directory to /tmp") - } - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html ]] - */ - chdir :: proc(path: cstring) -> result --- - /* Equivalent to chdir but instead of a path the fildes is resolved to a directory. @@ -204,15 +180,6 @@ foreign lib { */ dup2 :: proc(fildes, fildes2: FD) -> FD --- - /* - Exits but, shall not call functions registered with atexit() nor any registered signal handlers. - Open streams shall not be flushed. - Whether open streams are closed (without flushing) is implementation-defined. Finally, the calling process shall be terminated with the consequences described below. - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/_exit.html ]] - */ - _exit :: proc(status: c.int) -> ! --- - /* The exec family of functions shall replace the current process image with a new process image. The new image shall be constructed from a regular, executable file called the new process image file. @@ -392,44 +359,6 @@ foreign lib { */ ftruncate :: proc(fildes: FD, length: off_t) -> result --- - /* - Places an absolute pathname of the current working directory into buf. - - Returns: buf as a cstring on success, nil (setting errno) on failure - - Example: - size: int - path_max := posix.pathconf(".", ._PATH_MAX) - if path_max == -1 { - size = 1024 - } else if path_max > 10240 { - size = 10240 - } else { - size = int(path_max) - } - - buf: [dynamic]byte - cwd: cstring - for ; cwd == nil; size *= 2 { - if err := resize(&buf, size); err != nil { - fmt.panicf("allocation failure: %v", err) - } - - cwd = posix.getcwd(raw_data(buf), len(buf)) - if cwd == nil { - errno := posix.errno() - if errno != .ERANGE { - fmt.panicf("getcwd failure: %v", posix.strerror(errno)) - } - } - } - - fmt.println(path_max, cwd) - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html ]] - */ - getcwd :: proc(buf: [^]c.char, size: c.size_t) -> cstring --- - /* Returns the effective group ID of the calling process. @@ -829,13 +758,6 @@ foreign lib { */ readlinkat :: proc(fd: FD, path: cstring, buf: [^]byte, bufsize: c.size_t) -> c.ssize_t --- - /* - Remove an (empty) directory. - - ]] More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html ]] - */ - rmdir :: proc(path: cstring) -> result --- - /* Set the effective group ID. @@ -912,13 +834,6 @@ foreign lib { */ sleep :: proc(seconds: c.uint) -> c.uint --- - /* - Copy nbyte bytes, from src, to dest, exchanging adjecent bytes. - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/swab.html ]] - */ - swab :: proc(src: [^]byte, dest: [^]byte, nbytes: c.ssize_t) --- - /* Schedule file system updates. @@ -958,13 +873,6 @@ foreign lib { */ ttyname_r :: proc(fildes: FD, name: [^]byte, namesize: c.size_t) -> Errno --- - /* - Remove a directory entry. - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html ]] - */ - unlink :: proc(path: cstring) -> result --- - /* Equivalent to unlink or rmdir (if flag is .REMOVEDIR) but relative paths are relative to the dir fd. @@ -973,20 +881,6 @@ foreign lib { unlinkat :: proc(fd: FD, path: cstring, flag: AT_Flags) -> result --- } -STDERR_FILENO :: 2 -STDIN_FILENO :: 0 -STDOUT_FILENO :: 1 - -Mode_Flag_Bits :: enum c.int { - X_OK = log2(X_OK), - W_OK = log2(W_OK), - R_OK = log2(R_OK), -} -Mode_Flags :: bit_set[Mode_Flag_Bits; c.int] - -#assert(_F_OK == 0) -F_OK :: Mode_Flags{} - CS :: enum c.int { _PATH = _CS_PATH, _POSIX_V6_ILP32_OFF32_CFLAGS = _CS_POSIX_V6_ILP32_OFF32_CFLAGS, @@ -2063,6 +1957,7 @@ when ODIN_OS == .Darwin { _SC_TYPED_MEMORY_OBJECTS :: 165 _SC_2_PBS :: 168 _SC_2_PBS_ACCOUNTING :: 169 + _SC_2_PBS_LOCATE :: 170 _SC_2_PBS_MESSAGE :: 171 _SC_2_PBS_TRACK :: 172 _SC_SYMLOOP_MAX :: 173 @@ -2097,7 +1992,4 @@ when ODIN_OS == .Darwin { // NOTE: Not implemented. _POSIX_VDISABLE :: 0 -} else { - #panic("posix is unimplemented for the current target") } - diff --git a/core/sys/posix/unistd_libc.odin b/core/sys/posix/unistd_libc.odin new file mode 100644 index 000000000..bbfe3d59d --- /dev/null +++ b/core/sys/posix/unistd_libc.odin @@ -0,0 +1,153 @@ +#+build linux, windows, darwin, netbsd, openbsd, freebsd +package posix + +import "core:c" + +when ODIN_OS == .Windows { + foreign import lib "system:libucrt.lib" +} else when ODIN_OS == .Darwin { + foreign import lib "system:System.framework" +} else { + foreign import lib "system:c" +} + +// unistd.h - standard symbolic constants and types + +foreign lib { + /* + Checks the file named by the pathname pointed to by the path argument for + accessibility according to the bit pattern contained in amode. + + Example: + if (posix.access("/tmp/myfile", posix.F_OK) != .OK) { + fmt.printfln("/tmp/myfile access check failed: %v", posix.strerror(posix.errno())) + } + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html ]] + */ + @(link_name=LACCESS) + access :: proc(path: cstring, amode: Mode_Flags = F_OK) -> result --- + + /* + Causes the directory named by path to become the current working directory. + + Example: + if (posix.chdir("/tmp") == .OK) { + fmt.println("changed current directory to /tmp") + } + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html ]] + */ + @(link_name=LCHDIR) + chdir :: proc(path: cstring) -> result --- + + /* + Exits but, shall not call functions registered with atexit() nor any registered signal handlers. + Open streams shall not be flushed. + Whether open streams are closed (without flushing) is implementation-defined. Finally, the calling process shall be terminated with the consequences described below. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/_exit.html ]] + */ + _exit :: proc(status: c.int) -> ! --- + + /* + Places an absolute pathname of the current working directory into buf. + + Returns: buf as a cstring on success, nil (setting errno) on failure + + Example: + size: int + path_max := posix.pathconf(".", ._PATH_MAX) + if path_max == -1 { + size = 1024 + } else if path_max > 10240 { + size = 10240 + } else { + size = int(path_max) + } + + buf: [dynamic]byte + cwd: cstring + for ; cwd == nil; size *= 2 { + if err := resize(&buf, size); err != nil { + fmt.panicf("allocation failure: %v", err) + } + + cwd = posix.getcwd(raw_data(buf), len(buf)) + if cwd == nil { + errno := posix.errno() + if errno != .ERANGE { + fmt.panicf("getcwd failure: %v", posix.strerror(errno)) + } + } + } + + fmt.println(path_max, cwd) + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html ]] + */ + @(link_name=LGETCWD) + getcwd :: proc(buf: [^]c.char, size: c.size_t) -> cstring --- + + /* + Remove an (empty) directory. + + ]] More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html ]] + */ + @(link_name=LRMDIR) + rmdir :: proc(path: cstring) -> result --- + + /* + Copy nbyte bytes, from src, to dest, exchanging adjecent bytes. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/swab.html ]] + */ + @(link_name=LSWAB) + swab :: proc(src: [^]byte, dest: [^]byte, nbytes: c.ssize_t) --- + + /* + Remove a directory entry. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html ]] + */ + @(link_name=LUNLINK) + unlink :: proc(path: cstring) -> result --- +} + +when ODIN_OS == .Windows { + @(private) LACCESS :: "_access" + @(private) LCHDIR :: "_chdir" + @(private) LGETCWD :: "_getcwd" + @(private) LRMDIR :: "_rmdir" + @(private) LSWAB :: "_swab" + @(private) LUNLINK :: "_unlink" +} else { + @(private) LACCESS :: "access" + @(private) LCHDIR :: "chdir" + @(private) LGETCWD :: "getcwd" + @(private) LRMDIR :: "rmdir" + @(private) LSWAB :: "swab" + @(private) LUNLINK :: "unlink" +} + +STDERR_FILENO :: 2 +STDIN_FILENO :: 0 +STDOUT_FILENO :: 1 + +Mode_Flag_Bits :: enum c.int { + X_OK = log2(X_OK), + W_OK = log2(W_OK), + R_OK = log2(R_OK), +} +Mode_Flags :: bit_set[Mode_Flag_Bits; c.int] + +#assert(_F_OK == 0) +F_OK :: Mode_Flags{} + +when ODIN_OS == .Windows { + _F_OK :: 0 + X_OK :: 1 + W_OK :: 2 + R_OK :: 4 + #assert(W_OK|R_OK == 6) +} diff --git a/core/sys/posix/utime.odin b/core/sys/posix/utime.odin index 1207cb402..e884eb1a3 100644 --- a/core/sys/posix/utime.odin +++ b/core/sys/posix/utime.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix when ODIN_OS == .Darwin { @@ -31,6 +32,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS modtime: time_t, /* [PSX] modification time (seconds since epoch) */ } -} else { - #panic("posix is unimplemented for the current target") } diff --git a/core/sys/posix/wordexp.odin b/core/sys/posix/wordexp.odin index 6bb362625..a9e6f39a7 100644 --- a/core/sys/posix/wordexp.odin +++ b/core/sys/posix/wordexp.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -123,6 +124,4 @@ when ODIN_OS == .Darwin { WRDE_CMDSUB :: 4 WRDE_SYNTAX :: 5 -} else { - #panic("posix is unimplemented for the current target") } diff --git a/tests/core/sys/posix/posix.odin b/tests/core/sys/posix/posix.odin index d73e49ffb..c215747e4 100644 --- a/tests/core/sys/posix/posix.odin +++ b/tests/core/sys/posix/posix.odin @@ -1,4 +1,4 @@ -#+build darwin, freebsd, openbsd, netbsd +#+build linux, darwin, freebsd, openbsd, netbsd package tests_core_posix import "core:log" @@ -144,7 +144,6 @@ test_libgen :: proc(t: ^testing.T) { { "usr/", ".", "usr" }, { "", ".", "." }, { "/", "/", "/" }, - { "//", "/", "/" }, { "///", "/", "/" }, { "/usr/", "/", "usr" }, { "/usr/lib", "/usr", "lib" }, @@ -197,24 +196,12 @@ test_stat :: proc(t: ^testing.T) { stat: posix.stat_t testing.expect_value(t, posix.stat(#file, &stat), posix.result.OK) testing.expect(t, posix.S_ISREG(stat.st_mode)) - testing.expect_value(t, stat.st_mode, posix.mode_t{.IROTH, .IRGRP, .IRUSR, .IWUSR, .IFREG}) + testing.expect_value(t, stat.st_mode, posix.mode_t{.IROTH, .IRGRP, .IRUSR, .IWGRP, .IWUSR, .IFREG}) CONTENT := #load(#file) testing.expect_value(t, stat.st_size, posix.off_t(len(CONTENT))) } -@(test) -test_termios :: proc(t: ^testing.T) { - testing.expect_value(t, transmute(posix.CControl_Flags)posix.tcflag_t(posix._CSIZE), posix.CSIZE) - - testing.expect_value(t, transmute(posix.COutput_Flags)posix.tcflag_t(posix._NLDLY), posix.NLDLY) - testing.expect_value(t, transmute(posix.COutput_Flags)posix.tcflag_t(posix._CRDLY), posix.CRDLY) - testing.expect_value(t, transmute(posix.COutput_Flags)posix.tcflag_t(posix._TABDLY), posix.TABDLY) - testing.expect_value(t, transmute(posix.COutput_Flags)posix.tcflag_t(posix._BSDLY), posix.BSDLY) - testing.expect_value(t, transmute(posix.COutput_Flags)posix.tcflag_t(posix._VTDLY), posix.VTDLY) - testing.expect_value(t, transmute(posix.COutput_Flags)posix.tcflag_t(posix._FFDLY), posix.FFDLY) -} - @(test) test_pthreads :: proc(t: ^testing.T) { testing.set_fail_timeout(t, time.Second) diff --git a/tests/core/sys/posix/structs.odin b/tests/core/sys/posix/structs.odin index de9511634..a0e8fea99 100644 --- a/tests/core/sys/posix/structs.odin +++ b/tests/core/sys/posix/structs.odin @@ -1,4 +1,4 @@ -#+build darwin, freebsd, openbsd, netbsd +#+build linux, darwin, freebsd, openbsd, netbsd package tests_core_posix import "core:log" diff --git a/tests/core/sys/posix/structs/structs.c b/tests/core/sys/posix/structs/structs.c index 7d8038fbb..6cabb8488 100644 --- a/tests/core/sys/posix/structs/structs.c +++ b/tests/core/sys/posix/structs/structs.c @@ -40,7 +40,9 @@ int main(int argc, char *argv[]) printf("pthread_attr_t %zu %zu\n", sizeof(pthread_attr_t), _Alignof(pthread_attr_t)); printf("pthread_key_t %zu %zu\n", sizeof(pthread_key_t), _Alignof(pthread_key_t)); +#ifndef __linux__ printf("sched_param %zu %zu\n", sizeof(struct sched_param), _Alignof(struct sched_param)); +#endif printf("termios %zu %zu\n", sizeof(struct termios), _Alignof(struct termios)); diff --git a/tests/core/sys/posix/structs/structs.odin b/tests/core/sys/posix/structs/structs.odin index 2663d1e30..e159ddf3c 100644 --- a/tests/core/sys/posix/structs/structs.odin +++ b/tests/core/sys/posix/structs/structs.odin @@ -14,7 +14,11 @@ main :: proc() { fmt.println("pthread_attr_t", size_of(posix.pthread_attr_t), align_of(posix.pthread_attr_t)) fmt.println("pthread_key_t", size_of(posix.pthread_key_t), align_of(posix.pthread_key_t)) - fmt.println("sched_param", size_of(posix.sched_param), align_of(posix.sched_param)) + // NOTE: On Linux, differences between libc may mean the Odin side is larger than the other side, + // this is fine in practice. + when ODIN_OS != .Linux { + fmt.println("sched_param", size_of(posix.sched_param), align_of(posix.sched_param)) + } fmt.println("termios", size_of(posix.termios), align_of(posix.termios))