// Userspace current-directory smoke test. // Verifies CWD inheritance and parent traversal clamped at the owning RSSRV resource binding. #include #include #include #include #include #include static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(req), SysSvFromCstr(s) }; SysWriteConsole(&req); } static void exit_now(int code) { while (true) SysExitProcess(code); } static void fail_status(const char* what, KSTATUS status) { (void)status; print("cwd_userspace_smoke: "); print(what); print("\n"); exit_now(1); } static void fail(const char* what) { print("cwd_userspace_smoke: "); print(what); print("\n"); exit_now(1); } static void get_cwd_or_fail(char out[SYS_PATH_MAX + 1u]) { size_t required = 0; KSTATUS status = NtlGetCurrentDirectory(out, SYS_PATH_MAX + 1u, &required); if (status != NTLSTATUS_SUCCESS || required == 0 || required > SYS_PATH_MAX + 1u) fail_status("get cwd", status); } static void set_cwd_or_fail(const char* path, const char* what) { KSTATUS status = NtlSetCurrentDirectory(SysSvFromCstr(path)); if (status != NTLSTATUS_SUCCESS) fail_status(what, status); } static void expect_cwd(const char* expected) { char current[SYS_PATH_MAX + 1u]; get_cwd_or_fail(current); if (strcmp(current, expected) != 0) fail("cwd value mismatch"); } // Resolves the current absolute resource path and returns the owning namespace-prefix length. static size_t resource_root_length_or_fail(const char* cwd) { SYS_HANDLE session = SYS_HANDLE_INVALID; KSTATUS status = NtlResourceConnect(&session); if (status != NTLSTATUS_SUCCESS) fail_status("resource connect", status); SYS_HANDLE root = SYS_HANDLE_INVALID; uint32_t kind = NTL_RESOURCE_KIND_INVALID; uint32_t resolvedLength = 0; status = NtlResourceResolve(session, SysSvFromCstr(cwd), NTL_RESOURCE_FLAG_NONE, &root, &kind, &resolvedLength); (void)NtlResourceClose(session); if (root != SYS_HANDLE_INVALID) (void)SysCloseHandle(root); if (status != NTLSTATUS_SUCCESS) fail_status("resolve cwd root", status); size_t length = strlen(cwd); if (kind == NTL_RESOURCE_KIND_INVALID || resolvedLength < 2u || resolvedLength > length || (resolvedLength != length && cwd[resolvedLength] != '/')) fail("initial cwd malformed"); return resolvedLength; } static void parent_of_cwd(const char* cwd, size_t rootLength, char* out, size_t cap) { size_t length = strlen(cwd); if (rootLength < 2u || rootLength > length || length + 1u > cap || (rootLength != length && cwd[rootLength] != '/')) fail("initial cwd malformed"); memcpy(out, cwd, length + 1u); if (length == rootLength) return; while (length > rootLength && out[length - 1u] == '/') out[--length] = '\0'; while (length > rootLength && out[length - 1u] != '/') length--; if (length <= rootLength + 1u) length = rootLength; else length--; out[length] = '\0'; } int main(void) { char original[SYS_PATH_MAX + 1u]; char parent[SYS_PATH_MAX + 1u]; char root[SYS_PATH_MAX + 1u]; print("cwd_userspace_smoke: start\n"); get_cwd_or_fail(original); size_t rootLength = resource_root_length_or_fail(original); parent_of_cwd(original, rootLength, parent, sizeof(parent)); memcpy(root, original, rootLength); root[rootLength] = '\0'; // Refresh the cached binding boundary without changing the path. set_cwd_or_fail(".", "set dot cwd"); expect_cwd(original); set_cwd_or_fail("..", "set parent cwd"); expect_cwd(parent); // Relative traversal stops at the actual bound resource, including multi-component roots. set_cwd_or_fail(root, "set resource root cwd"); expect_cwd(root); set_cwd_or_fail("..", "clamp parent at resource root"); expect_cwd(root); set_cwd_or_fail(original, "restore original cwd"); expect_cwd(original); print("cwd_userspace_smoke: PASS\n"); exit_now(0); return 0; }