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:
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;