kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit 560e47bb1831c255803a9c532ab5c74b8862b826
parent 441521acb327ce5a87605bd3c6ba5ec60b743f4a
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Thu, 16 Jul 2026 10:13:40 -0700

driver: canonicalize host paths and preserve rewrite modes

Diffstat:
Mdriver/env.h | 16++++++++++++++++
Mdriver/env/posix.c | 41++++++++++++++++++++++++++++++++++++++---
Mdriver/env/windows.c | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 212 insertions(+), 3 deletions(-)

diff --git a/driver/env.h b/driver/env.h @@ -215,6 +215,14 @@ int driver_mkdir_p(DriverEnv*, const char* path); * (Windows). Used by `install` to point freshly created links at the binary. */ int driver_self_exe_path(DriverEnv*, char** out, size_t* out_size); +/* Resolve an existing host path to a normalized absolute path in a fresh + * DriverEnv allocation. POSIX uses realpath; Windows uses GetFullPathNameW. + * Returns 0 on success, nonzero for an invalid/missing path or allocation + * failure. This is the normalization boundary for support/sysroot discovery; + * callers free *out with driver_free(env, *out, *out_size). */ +int driver_path_canonicalize(DriverEnv*, const char* path, char** out, + size_t* out_size); + /* Create a symbolic link named `link_path` that resolves to `target`. Returns * 0 on success. POSIX uses symlink(2); Windows uses CreateSymbolicLinkW, which * may require privilege or Developer Mode (so `install` defaults to hard links @@ -280,6 +288,14 @@ int driver_fetch_url(const char* url, const char* dest); * Returns 0 on success, nonzero on chmod failure. */ int driver_mark_executable_output(const char* path); +/* Capture and restore the permission mode of a regular output. POSIX carries + * all permission/special bits accepted by chmod; Windows returns an opaque + * zero mode and treats restoration as a successful no-op because execution is + * extension/ACL based there. These helpers let transactional rewrites preserve + * an input's mode even though the atomic writer replaces its inode. */ +int driver_path_mode_get(const char* path, uint32_t* mode_out); +int driver_path_mode_set(const char* path, uint32_t mode); + /* Walk regular files below `root`, reporting tree-relative paths with '/' * separators. The callback returns nonzero to abort the walk. Unsupported * filesystem entries cause a nonzero return from the walk helper. */ diff --git a/driver/env/posix.c b/driver/env/posix.c @@ -24,6 +24,27 @@ extern char** environ; +int driver_path_canonicalize(DriverEnv* env, const char* path, char** out, + size_t* out_size) { + char* resolved; + char* copy; + size_t size; + if (!env || !path || !path[0] || !out || !out_size) return 1; + resolved = realpath(path, NULL); + if (!resolved) return 1; + size = driver_strlen(resolved) + 1u; + copy = (char*)driver_alloc(env, size); + if (!copy) { + free(resolved); + return 1; + } + driver_memcpy(copy, resolved, size); + free(resolved); + *out = copy; + *out_size = size; + return 0; +} + /* ---------------- exec memory: single-mapping core + registry ---------------- */ @@ -720,6 +741,19 @@ int driver_mark_executable_output(const char* path) { return chmod(path, mode) == 0 ? 0 : 1; } +int driver_path_mode_get(const char* path, uint32_t* mode_out) { + struct stat sb; + if (!path || !mode_out || stat(path, &sb) != 0 || !S_ISREG(sb.st_mode)) + return 1; + *mode_out = (uint32_t)(sb.st_mode & 07777u); + return 0; +} + +int driver_path_mode_set(const char* path, uint32_t mode) { + if (!path || mode > 07777u) return 1; + return chmod(path, (mode_t)mode) == 0 ? 0 : 1; +} + /* ---------------- link helpers (install) ---------------- */ int driver_create_symlink(const char* target, const char* link_path) { @@ -927,10 +961,11 @@ int driver_fetch_url(const char* url, const char* dest) { if (pid < 0) return 1; if (pid == 0) { /* Untrusted transport: the URL is a distinct argv element (no shell), so a - * hostile mirror URL cannot inject a command. curl first; if it is not - * installed (exec returns) fall back to wget; if neither, 127. */ + * hostile mirror URL cannot inject a command. The production update + * transport is deliberately curl-only so its TLS and redirect behavior is + * one audited contract rather than whichever downloader happens to be + * installed first. */ execlp("curl", "curl", "-fsSL", "-o", dest, "--", url, (char*)NULL); - execlp("wget", "wget", "-q", "-O", dest, "--", url, (char*)NULL); _exit(127); } do { diff --git a/driver/env/windows.c b/driver/env/windows.c @@ -63,6 +63,7 @@ #include <string.h> #include <sys/stat.h> #include <time.h> +#include <wchar.h> #include "env_internal.h" @@ -112,6 +113,48 @@ static char* narrow(const wchar_t* wide) { return out; } +int driver_path_canonicalize(DriverEnv* env, const char* path, char** out, + size_t* out_size) { + wchar_t* wpath; + wchar_t* wfull; + DWORD need; + char* narrowed; + char* copy; + size_t size; + if (!env || !path || !path[0] || !out || !out_size) return 1; + wpath = widen(path); + if (!wpath) return 1; + need = GetFullPathNameW(wpath, 0, NULL, NULL); + if (!need) { + free(wpath); + return 1; + } + wfull = (wchar_t*)malloc((size_t)need * sizeof(*wfull)); + if (!wfull || GetFullPathNameW(wpath, need, wfull, NULL) == 0) { + free(wfull); + free(wpath); + return 1; + } + free(wpath); + narrowed = narrow(wfull); + free(wfull); + if (!narrowed || !driver_path_exists(narrowed)) { + free(narrowed); + return 1; + } + size = driver_strlen(narrowed) + 1u; + copy = (char*)driver_alloc(env, size); + if (!copy) { + free(narrowed); + return 1; + } + driver_memcpy(copy, narrowed, size); + free(narrowed); + *out = copy; + *out_size = size; + return 0; +} + /* ============================================================ * exec_dual registry (write/runtime alias bookkeeping) * ============================================================ */ @@ -930,7 +973,115 @@ int driver_mark_executable_output(const char* path) { return 0; } +int driver_path_mode_get(const char* path, uint32_t* mode_out) { + if (!path || !mode_out || !driver_path_exists(path)) return 1; + *mode_out = 0; + return 0; +} + +int driver_path_mode_set(const char* path, uint32_t mode) { + (void)mode; + return path && driver_path_exists(path) ? 0 : 1; +} + /* ---------------- self executable path ---------------- */ +static int wide_dir_exists(const wchar_t* path) { + DWORD attrs = GetFileAttributesW(path); + return attrs != INVALID_FILE_ATTRIBUTES && + (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0; +} + +/* An installed Windows multicall name is a hard link, so + * GetModuleFileNameW reports the prefix alias rather than the distribution's + * bin/kit.exe name. Enumerate the file's other NTFS names and select the one + * that owns a Kit support tree. This is the hard-link analogue of POSIX + * realpath resolving an installed symlink to its distribution executable. */ +static int wide_exe_has_support(const wchar_t* exe) { + size_t n, slash, suffix_len; + wchar_t* probe; + static const wchar_t dev_suffix[] = L"support\\rt\\include"; + static const wchar_t pkg_suffix[] = L"..\\support\\rt\\include"; + const wchar_t* suffix; + int packaged; + if (!exe || !*exe) return 0; + n = wcslen(exe); + slash = n; + while (slash > 0 && exe[slash - 1] != L'\\' && exe[slash - 1] != L'/') + --slash; + if (slash == 0) return 0; + for (packaged = 0; packaged < 2; ++packaged) { + suffix = packaged ? pkg_suffix : dev_suffix; + suffix_len = wcslen(suffix); + probe = (wchar_t*)malloc((slash + suffix_len + 1u) * sizeof(*probe)); + if (!probe) return 0; + memcpy(probe, exe, slash * sizeof(*probe)); + memcpy(probe + slash, suffix, (suffix_len + 1u) * sizeof(*probe)); + if (wide_dir_exists(probe)) { + free(probe); + return 1; + } + free(probe); + } + return 0; +} + +static wchar_t* wide_find_distribution_hardlink(const wchar_t* invoked) { + wchar_t volume[MAX_PATH]; + wchar_t* link_name = NULL; + wchar_t* selected = NULL; + DWORD cap = 256; + HANDLE find = INVALID_HANDLE_VALUE; + if (!invoked || !GetVolumePathNameW(invoked, volume, MAX_PATH)) return NULL; + for (;;) { + DWORD size = cap; + wchar_t* next = (wchar_t*)realloc(link_name, (size_t)cap * sizeof(*next)); + if (!next) goto done; + link_name = next; + find = FindFirstFileNameW(invoked, 0, &size, link_name); + if (find != INVALID_HANDLE_VALUE) break; + if (GetLastError() != ERROR_MORE_DATA || size <= cap) goto done; + cap = size; + } + for (;;) { + size_t volume_len = wcslen(volume); + size_t name_off = + link_name[0] == L'\\' || link_name[0] == L'/' ? 1u : 0u; + size_t name_len = wcslen(link_name + name_off); + int need_sep = volume_len > 0 && volume[volume_len - 1] != L'\\' && + volume[volume_len - 1] != L'/'; + size_t total = volume_len + (size_t)need_sep + name_len + 1u; + wchar_t* candidate = (wchar_t*)malloc(total * sizeof(*candidate)); + if (!candidate) goto done; + memcpy(candidate, volume, volume_len * sizeof(*candidate)); + if (need_sep) candidate[volume_len++] = L'\\'; + memcpy(candidate + volume_len, link_name + name_off, + (name_len + 1u) * sizeof(*candidate)); + if (wide_exe_has_support(candidate)) { + selected = candidate; + break; + } + free(candidate); + { + DWORD size = cap; + if (FindNextFileNameW(find, &size, link_name)) continue; + if (GetLastError() != ERROR_MORE_DATA || size <= cap) break; + { + wchar_t* next = + (wchar_t*)realloc(link_name, (size_t)size * sizeof(*next)); + if (!next) goto done; + link_name = next; + cap = size; + } + size = cap; + if (!FindNextFileNameW(find, &size, link_name)) break; + } + } +done: + if (find != INVALID_HANDLE_VALUE) FindClose(find); + free(link_name); + return selected; +} + /* GetModuleFileNameW(NULL) reports the path of the running image. A return * equal to the buffer size means truncation (older Windows doesn't fail), so * grow until the result fits, then narrow to UTF-8. */ @@ -960,6 +1111,13 @@ int driver_self_exe_path(DriverEnv* env, char** out, size_t* out_size) { } cap *= 2; } + { + wchar_t* dist = wide_find_distribution_hardlink(wbuf); + if (dist) { + free(wbuf); + wbuf = dist; + } + } narrowed = narrow(wbuf); /* malloc'd UTF-8 */ free(wbuf); if (!narrowed) return 1;