From a01970e53e77fa73e571cdc57e935a7cd666258d Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Thu, 17 Sep 2026 16:22:01 +0800 Subject: [PATCH] 0.2.0 --- openkal 0.13: whether a node may be started MEMFS keeps the mode a node was given, so this implementation claims KAL_FS_PROP_EXECUTABLE, reports KAL_INFO_EXECUTABLE for a file and performs kal_fs_set_executable_at with the three execute bits as one property. ENOEXEC maps to kal_err_not_program for completeness; openkal.process is not provided here, so nothing reaches it today. Comments carry no emoji. --- README.md | 6 +++--- mcpp.toml | 4 ++-- src/fs.cpp | 31 ++++++++++++++++++++++++++++++- src/sys.h | 1 + 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6c53b75..d86914c 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ So the interface is carried by a feature: ```toml [dependencies] -openkal-emscripten = { version = "0.1.1", features = ["threads"] } +openkal-emscripten = { version = "0.2.0", features = ["threads"] } ``` Without it, `src/threads/task.cpp` compiles to nothing, the eight `kal_task_*` @@ -143,10 +143,10 @@ implementation in its source: ```toml [dependencies] -openkal = "0.12.0" +openkal = "0.13.0" [target.'cfg(os = "emscripten")'.dependencies] -openkal-emscripten = "0.1.1" +openkal-emscripten = "0.2.0" ``` ## Licence diff --git a/mcpp.toml b/mcpp.toml index 4b2bcb7..5fc8b79 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,7 +1,7 @@ [package] namespace = "mcpplibs" name = "openkal-emscripten" -version = "0.1.1" +version = "0.2.0" description = "An implementation of openkal for Emscripten, written ABOVE a C library rather than beneath one, because on this platform there is no kernel to issue calls to." license = "Apache-2.0" @@ -18,7 +18,7 @@ authors = ["mcpplibs"] repo = "https://github.com/mcpplibs/openkal-emscripten" [dependencies] -openkal = "0.12.0" +openkal = "0.13.0" [build] # THE DIALECT FLAGS ARE THE SAME AS EVERY OTHER IMPLEMENTATION'S AND THE REASON diff --git a/src/fs.cpp b/src/fs.cpp index f12ca11..096d04b 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -117,6 +117,13 @@ void fill(const struct stat& st, kal_u32 wanted, kal_node_info* out) { out->identity[1] = static_cast(st.st_ino); out->present |= KAL_INFO_IDENTITY; } + // Version 0.13. MEMFS keeps the mode a node was given, so whether a node + // may be started is recorded, and it is reported for a file only. + if ((wanted & KAL_INFO_EXECUTABLE) && S_ISREG(st.st_mode) + && room_for(out, offsetof(kal_node_info, executable))) { + out->executable = (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0 ? 1 : 0; + out->present |= KAL_INFO_EXECUTABLE; + } } // The iteration word openkal hands back and forth is a pointer to the C @@ -154,6 +161,7 @@ int kal_fs_preopen(kal_uintptr index, kal_dir* out, // MODIFIED_TIME a modification time is kept. // ATOMIC_RENAME `rename` is a single operation on an in-memory tree. // MAKE_LINKS `symlink` is implemented. +// EXECUTABLE the mode a node was given is kept, and `chmod` changes it. // // WITHHELD: LOCKS, because MEMFS has no lock table and a wasm module has no // second process to contend with -- so a lock that always succeeded would tell @@ -163,7 +171,7 @@ int kal_fs_preopen(kal_uintptr index, kal_dir* out, kal_uintptr kal_fs_props(kal_dir) { return KAL_FS_PROP_CASE_SENSITIVE | KAL_FS_PROP_LINKS | KAL_FS_PROP_MODIFIED_TIME | KAL_FS_PROP_ATOMIC_RENAME - | KAL_FS_PROP_MAKE_LINKS; + | KAL_FS_PROP_MAKE_LINKS | KAL_FS_PROP_EXECUTABLE; } int kal_fs_open_dir(kal_dir base, const char* name, kal_uintptr len, @@ -370,6 +378,27 @@ int kal_fs_set_modified_at(kal_dir base, const char* name, kal_uintptr len, return kal_ok; } +// Whether a node may be started, version 0.13. The mode keeps three bits for +// one property: a class that may read the node may start it, and clearing +// clears all three. +int kal_fs_set_executable_at(kal_dir base, const char* name, kal_uintptr len, + int executable) { + const int b = oke::unpack(base.h); + if (b < 0) return kal_err_invalid; + char n[kMaxName + 1]; + if (!cname(name, len, n)) return kal_err_invalid; + struct stat st{}; + if (::fstatat(b, n, &st, 0) != 0) return oke::last(); + if (S_ISDIR(st.st_mode)) return kal_err_is_directory; + if (!S_ISREG(st.st_mode)) return kal_err_invalid; + const mode_t mode = st.st_mode & 07777; + const mode_t next = executable != 0 ? (mode | ((mode & 0444) >> 2)) + : (mode & ~static_cast(0111)); + if (next == mode) return kal_ok; + if (::fchmodat(b, n, next, 0) != 0) return oke::last(); + return kal_ok; +} + // LOCKS AND CAPACITY ARE NOT PROVIDED, AND THE PROPERTY WORD SAID SO FIRST. // // These two are the only members of this interface whose absence is reported diff --git a/src/sys.h b/src/sys.h index d1c1392..aedfbcf 100644 --- a/src/sys.h +++ b/src/sys.h @@ -71,6 +71,7 @@ inline int translate(int e) { case ENOTEMPTY: return kal_err_not_empty; case EISDIR: return kal_err_is_directory; case ENOTDIR: return kal_err_not_directory; + case ENOEXEC: return kal_err_not_program; default: return kal_err_io; } }