From 822c26f7f58afa35124da2ab9815b111e6892f93 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Fri, 30 Oct 2026 18:32:57 +0900 Subject: [PATCH] 0.16.0 --- openkal.map: a part of a file in the address space, by mmap, msync and munmap (openkal 0.18) The file's length and kind are read with fstat64 first, since the kernel maps beyond a file's end and maps some devices; kal_map_sync is msync(MS_ASYNC). No PROT_EXEC. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> --- README.md | 2 +- mcpp.toml | 5 +++-- src/map.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ src/sys.h | 4 ++-- src/version.cpp | 3 ++- 5 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 src/map.cpp diff --git a/README.md b/README.md index 44f1cf0..86d2069 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ written on the kernel's own calls. openkal = "0.17.0" [target.'cfg(os = "macos")'.dependencies] -openkal-macos = "0.15.1" +openkal-macos = "0.16.0" ``` Its purpose is as much to test the specification as to be used. A specification diff --git a/mcpp.toml b/mcpp.toml index 91f6190..5f44ef4 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,7 +1,7 @@ [package] namespace = "mcpplibs" name = "openkal-macos" -version = "0.15.1" +version = "0.16.0" description = "An implementation of openkal for macOS, written on the kernel's own calls. Its purpose is as much to test the specification as to be used." license = "Apache-2.0" @@ -54,10 +54,11 @@ provides-interfaces = [ "openkal.datagram", "openkal.space", "openkal.timeout", + "openkal.map", ] [dependencies] -openkal = "0.17.1" +openkal = "0.18.0" [build] # The flags are attached to this package's own sources rather than to the whole diff --git a/src/map.cpp b/src/map.cpp new file mode 100644 index 0000000..9347dcc --- /dev/null +++ b/src/map.cpp @@ -0,0 +1,57 @@ +#include "sys.h" +#include "handle.h" +#include + +// openkal.map on this kernel (openkal 0.18). +// +// The BSD calls: mmap, msync, munmap. The region is the address the kernel +// returned and the length the caller passed, so nothing is recorded. +// +// THE FILE'S LENGTH AND KIND ARE ASKED FIRST, with fstat64: the kernel maps +// beyond a file's end, and some devices, and the specification refuses both at +// the call. No PROT_EXEC: instructions run only from memory openkal.exec +// published, and this kernel's code signing would refuse an executable mapping +// of an unsigned file in any case. + +extern "C" { + +int kal_map_file(kal_file f, kal_u64 offset, kal_uintptr length, kal_uintptr how, void** out) { + if (out == nullptr) return kal_err_invalid; + *out = nullptr; + const int fd = okm::unpack(f.h); + if (fd < 0 || length == 0 || offset % KAL_MAP_ALIGNMENT != 0 + || (how & ~(KAL_MAP_WRITE | KAL_MAP_SHARED)) != 0) + return kal_err_invalid; + okm::kstat64 st{}; + const okm_long s = okm::sys(okm::nr_fstat64, fd, reinterpret_cast(&st)); + if (okm::failed(s)) return okm::translate(s); + if ((okm::stat_mode(st) & okm::s_ifmt) != okm::s_ifreg) return kal_err_not_supported; + const kal_u64 size = st.size > 0 ? static_cast(st.size) : 0; + if (offset > size || static_cast(length) > size - offset) return kal_err_invalid; + const okm_long prot = okm::prot_read | ((how & KAL_MAP_WRITE) ? okm::prot_write : 0); + const okm_long flags = (how & KAL_MAP_SHARED) ? okm::map_shared : okm::map_private; + const okm_long r = okm::sys(okm::nr_mmap, 0, static_cast(length), prot, flags, fd, + static_cast(offset)); + if (okm::failed(r)) { + if (-r == okm::e_nodev) return kal_err_not_supported; + return okm::translate(r); + } + *out = reinterpret_cast(r); + return kal_ok; +} + +int kal_map_sync(void* region, kal_uintptr length) { + if (region == nullptr || length == 0) return kal_err_invalid; + // MS_ASYNC: the unified buffer cache is what a read of the file reads, so + // the visibility the specification asks for needs no wait for the medium. + const okm_long r = okm::sys(okm::nr_msync, reinterpret_cast(region), + static_cast(length), okm::ms_async); + return okm::failed(r) ? okm::translate(r) : kal_ok; +} + +void kal_map_release(void* region, kal_uintptr length) { + if (region == nullptr || length == 0) return; + (void)okm::sys(okm::nr_munmap, reinterpret_cast(region), static_cast(length)); +} + +} diff --git a/src/sys.h b/src/sys.h index 6aeedf7..3eb261a 100644 --- a/src/sys.h +++ b/src/sys.h @@ -170,7 +170,7 @@ enum : okm_long { nr_chdir = 12, nr_getpid = 20, nr_getuid = 24, nr_geteuid = 25, nr_kill = 37, nr_dup = 41, nr_getegid = 43, nr_getgid = 47, nr_ioctl = 54, nr_execve = 59, nr_umask = 60, nr_pipe = 42, - nr_munmap = 73, nr_mprotect = 74, nr_madvise = 75, + nr_munmap = 73, nr_mprotect = 74, nr_madvise = 75, nr_msync = 65, nr_dup2 = 90, nr_fsync = 95, nr_gettimeofday = 116, nr_readv = 120, nr_writev = 121, nr_ftruncate = 201, nr_utimes = 138, nr_futimes = 139, @@ -312,7 +312,7 @@ enum : okm_long { o_directory = 0x100000, o_cloexec = 0x1000000, o_nofollow = 0x0100, at_fdcwd = -2, at_removedir = 0x0080, at_symlink_nofollow = 0x0020, prot_read = 1, prot_write = 2, prot_exec = 4, - map_private = 2, map_anon = 0x1000, + map_shared = 1, map_private = 2, map_anon = 0x1000, ms_async = 1, }; // The suspension primitive's operation word. diff --git a/src/version.cpp b/src/version.cpp index 519a4f4..03f4fe4 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -15,7 +15,8 @@ kal_u64 kal_interfaces(void) { | KAL_IFACE_ENV | KAL_IFACE_TIME | KAL_IFACE_RANDOM | KAL_IFACE_FS | KAL_IFACE_PROCESS | KAL_IFACE_TASK | KAL_IFACE_EXEC | KAL_IFACE_TERMINAL | KAL_IFACE_NET - | KAL_IFACE_DATAGRAM | KAL_IFACE_SPACE | KAL_IFACE_TIMEOUT; + | KAL_IFACE_DATAGRAM | KAL_IFACE_SPACE | KAL_IFACE_TIMEOUT + | KAL_IFACE_MAP; } }