diff options
| author | t <t@tjp.lol> | 2026-06-23 09:38:23 -0600 |
|---|---|---|
| committer | t <t@tjp.lol> | 2026-06-23 10:53:26 -0600 |
| commit | 69a1ee138bb78ad4663fe2d9e58678f7b0d07b74 (patch) | |
| tree | 453d3ad42a07536220e6ca5d91b439ff57793e32 /src/self_exe.zig | |
| parent | 538a5d926fa626a00cc3dc12c555f11f82867efd (diff) | |
ponytail simplifications to panto cli and lua extensiosn
Diffstat (limited to 'src/self_exe.zig')
| -rw-r--r-- | src/self_exe.zig | 90 |
1 files changed, 0 insertions, 90 deletions
diff --git a/src/self_exe.zig b/src/self_exe.zig deleted file mode 100644 index 6eda92d..0000000 --- a/src/self_exe.zig +++ /dev/null @@ -1,90 +0,0 @@ -//! Resolve the absolute path of the currently running executable. -//! -//! Used to find the panto binary so we can launch ourselves as `panto -//! lua` from inside the bootstrap (the embedded luarocks shells out to -//! its configured `LUA` interpreter, which we point at a wrapper script -//! that exec's panto's `lua` subcommand). -//! -//! Zig's standard library doesn't expose a portable `selfExePath` in -//! the current API, so this module wraps the per-OS syscall. -//! -//! Supported: -//! - macOS / iOS / tvOS / watchOS: `_NSGetExecutablePath` + realpath -//! - Linux: `readlink("/proc/self/exe")` -//! - FreeBSD / NetBSD / DragonFly: `readlink("/proc/curproc/file")` -//! -//! Other targets currently return `error.SelfExePathUnavailable`. - -const std = @import("std"); -const builtin = @import("builtin"); - -const Allocator = std.mem.Allocator; - -pub const ResolveError = error{ - SelfExePathUnavailable, - SelfExePathTooLong, - SelfExePathReadFailed, - OutOfMemory, -}; - -/// Return the absolute, symlink-resolved path of the current process's -/// executable. Caller owns the returned slice. -pub fn selfExePathAlloc(allocator: Allocator) ResolveError![]u8 { - var buf: [std.fs.max_path_bytes]u8 = undefined; - const path = try selfExePath(&buf); - return allocator.dupe(u8, path); -} - -/// Fill `buf` with the absolute path. Returns the slice that was used. -pub fn selfExePath(buf: []u8) ResolveError![]u8 { - return switch (builtin.os.tag) { - .macos, .ios, .tvos, .watchos => try macosSelfExePath(buf), - .linux => try readLinkSelfExe(buf, "/proc/self/exe"), - .freebsd, .netbsd, .dragonfly => try readLinkSelfExe(buf, "/proc/curproc/file"), - else => return ResolveError.SelfExePathUnavailable, - }; -} - -fn readLinkSelfExe(buf: []u8, link_path: []const u8) ResolveError![]u8 { - const link_z = std.posix.toPosixPath(link_path) catch return ResolveError.SelfExePathTooLong; - const n = posixReadlink(&link_z, buf) catch return ResolveError.SelfExePathReadFailed; - return buf[0..n]; -} - -/// Thin wrapper around the POSIX `readlink` syscall using libc directly, -/// since std.posix's surface here has been in flux. libc is linked into -/// panto already (Lua needs it), so this stays cheap. -extern "c" fn readlink(path: [*:0]const u8, buf: [*]u8, bufsize: usize) isize; - -fn posixReadlink(path: [*:0]const u8, buf: []u8) !usize { - const n = readlink(path, buf.ptr, buf.len); - if (n < 0) return error.SelfExePathReadFailed; - return @intCast(n); -} - -extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int; - -fn macosSelfExePath(buf: []u8) ResolveError![]u8 { - var stage: [std.fs.max_path_bytes]u8 = undefined; - var size: u32 = @intCast(stage.len); - if (_NSGetExecutablePath(&stage, &size) != 0) return ResolveError.SelfExePathTooLong; - // _NSGetExecutablePath populates `size` on overflow; on success - // we need to find the NUL ourselves. - const len = std.mem.indexOfScalar(u8, &stage, 0) orelse return ResolveError.SelfExePathTooLong; - - // The returned path may include `..` and symlinks; canonicalize so - // downstream consumers don't have to. realpath(3) on POSIX, both - // libc-resident on macOS and Linux. - const path_z = std.posix.toPosixPath(stage[0..len]) catch return ResolveError.SelfExePathTooLong; - - // libc realpath: NULL second arg => malloc; we want stack buffer. - var real_buf: [std.fs.max_path_bytes]u8 = undefined; - if (libc_realpath(&path_z, &real_buf) == null) return ResolveError.SelfExePathReadFailed; - const real_len = std.mem.indexOfScalar(u8, &real_buf, 0) orelse return ResolveError.SelfExePathTooLong; - if (real_len > buf.len) return ResolveError.SelfExePathTooLong; - @memcpy(buf[0..real_len], real_buf[0..real_len]); - return buf[0..real_len]; -} - -extern "c" fn realpath(path: [*:0]const u8, resolved: [*]u8) ?[*]u8; -const libc_realpath = realpath; |
