From 77efd03be8160f0f16276944d72e492c23d58f77 Mon Sep 17 00:00:00 2001 From: Vinicius Rangel <vinicius.l.rangel@gmail.com> Date: Mon, 13 Nov 2023 09:43:13 -0300 Subject: [PATCH] [orbis-kenel] implement sys_kenv (#60) --- orbis-kernel/include/orbis/KernelContext.hpp | 14 +++- orbis-kernel/src/sys/sys_environment.cpp | 80 +++++++++++++++++++- 2 files changed, 90 insertions(+), 4 deletions(-) diff --git a/orbis-kernel/include/orbis/KernelContext.hpp b/orbis-kernel/include/orbis/KernelContext.hpp index a6e55e9d..49d6c58b 100644 --- a/orbis-kernel/include/orbis/KernelContext.hpp +++ b/orbis-kernel/include/orbis/KernelContext.hpp @@ -55,9 +55,7 @@ class alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) KernelContext final { void deleteProcess(Process *proc); Process *findProcessById(pid_t pid) const; - utils::LinkedNode<Process> *getProcessList() { - return m_processes; - } + utils::LinkedNode<Process> *getProcessList() { return m_processes; } long allocatePid() { std::lock_guard lock(m_thread_id_mtx); @@ -143,6 +141,13 @@ class alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) KernelContext final { return {}; } + std::tuple<utils::kmap<utils::kstring, char[128]> &, + std::unique_lock<shared_mutex>> + getKernelEnv() { + std::unique_lock lock(m_kenv_mtx); + return {m_kenv, std::move(lock)}; + } + enum { c_golden_ratio_prime = 2654404609u, c_umtx_chains = 512, @@ -193,6 +198,9 @@ class alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) KernelContext final { shared_mutex mIpmiServerMtx; utils::kmap<utils::kstring, Ref<IpmiServer>> mIpmiServers; + + shared_mutex m_kenv_mtx; + utils::kmap<utils::kstring, char[128]> m_kenv; // max size: 127 + '\0' }; extern KernelContext &g_context; diff --git a/orbis-kernel/src/sys/sys_environment.cpp b/orbis-kernel/src/sys/sys_environment.cpp index 8b394e2a..e22a3de9 100644 --- a/orbis-kernel/src/sys/sys_environment.cpp +++ b/orbis-kernel/src/sys/sys_environment.cpp @@ -1,7 +1,85 @@ #include "sys/sysproto.hpp" +#include "KernelContext.hpp" + orbis::SysResult orbis::sys_kenv(Thread *thread, sint what, ptr<const char> name, ptr<char> value, sint len) { - return ErrorCode::NOSYS; + enum action { kenv_get, kenv_set, kenv_unset, kenv_dump }; + + const auto &[kenv, _] = thread->tproc->context->getKernelEnv(); + + if (what == kenv_dump) { + int needed = 0; + int done = 0; + + for (const auto &[key, env_value] : kenv) { + size_t entry = 0; + // Entry: size of both full buffers, the '=' and the '\0' at the end + if (value == nullptr || len == 0) { + entry = key.size() + 1 + strnlen(env_value, 128) + 1; + } else { + char buf[128 * 2 + 2]; + + char *_buf = buf; + std::strncpy(buf, key.data(), key.size()); + _buf += key.size(); + + *_buf++ = '='; + + const size_t value_size = strnlen(env_value, 128); + std::strncpy(_buf, env_value, value_size); + _buf += value_size; + + *_buf++ = '\0'; + + entry = _buf - buf; + ORBIS_RET_ON_ERROR(uwriteRaw(value + done, buf, entry)); + len -= entry; + done += entry; + } + needed += entry; + } + + if (done != needed) { + thread->retval[0] = needed; + } + return {}; + } + + char _name_buf[128]; + ORBIS_RET_ON_ERROR(ureadString(_name_buf, sizeof(_name_buf), name)); + const std::string_view _name(_name_buf, strnlen(_name_buf, 128)); + + switch (what) { + case kenv_get: { + const auto it = kenv.find(_name); + if (it == kenv.end()) { + return ErrorCode::NOENT; + } + const char *buf = it->second; + ORBIS_RET_ON_ERROR(uwriteRaw(value, buf, std::min(len, 128))); + break; + } + case kenv_set: { + if (len < 1) { + return ErrorCode::INVAL; + } + char *_value_buf = kenv[kstring(_name)]; + ORBIS_RET_ON_ERROR(ureadString(_value_buf, 128, value)); + break; + } + case kenv_unset: { + const auto it = kenv.find(_name); + if (it == kenv.end()) { + return ErrorCode::NOENT; + } + kenv.erase(it); + break; + } + default: + return ErrorCode::INVAL; + } + + return {}; }