selfExePath
Get the path to the current executable. Follows symlinks. If you only need the directory, use selfExeDirPath. If you only want an open file handle, use openSelfExe. This function may return an error if the current executable was deleted after spawning. Returned value is a slice of out_buffer. On Windows, the result is encoded as WTF-8. On other platforms, the result is an opaque sequence of bytes with no particular encoding.
On Linux, depends on procfs being mounted. If the currently executing binary has
been deleted, the file path looks something like /a/b/c/exe (deleted).
TODO make the return type of this a null terminated pointer
Function parameters
Parameters
- out_buffer:[]u8
Type definitions in this namespace
Types
Functions in this namespace
Functions
- updateFileAbsolute
- Same as `Dir.updateFile`, except asserts that both `source_path` and `dest_path`
- copyFileAbsolute
- Same as `Dir.copyFile`, except asserts that both `source_path` and `dest_path`
- makeDirAbsolute
- Create a new directory, based on an absolute path.
- makeDirAbsoluteZ
- Same as `makeDirAbsolute` except the parameter is null-terminated.
- makeDirAbsoluteW
- Same as `makeDirAbsolute` except the parameter is a null-terminated WTF-16 LE-encoded string.
- deleteDirAbsolute
- Same as `Dir.deleteDir` except the path is absolute.
- deleteDirAbsoluteZ
- Same as `deleteDirAbsolute` except the path parameter is null-terminated.
- deleteDirAbsoluteW
- Same as `deleteDirAbsolute` except the path parameter is WTF-16 and target OS is assumed Windows.
- renameAbsolute
- Same as `Dir.rename` except the paths are absolute.
- renameAbsoluteZ
- Same as `renameAbsolute` except the path parameters are null-terminated.
- renameAbsoluteW
- Same as `renameAbsolute` except the path parameters are WTF-16 and target OS is assumed Windows.
- rename
- Same as `Dir.rename`, except `new_sub_path` is relative to `new_dir`
- renameZ
- Same as `rename` except the parameters are null-terminated.
- renameW
- Same as `rename` except the parameters are WTF16LE, NT prefixed.
- cwd
- Returns a handle to the current working directory.
- openDirAbsolute
- Opens a directory at the given path.
- openDirAbsoluteZ
- Same as `openDirAbsolute` but the path parameter is null-terminated.
- openDirAbsoluteW
- Same as `openDirAbsolute` but the path parameter is null-terminated.
- openFileAbsolute
- Opens a file for reading or writing, without attempting to create a new file, based on an absolute path.
- openFileAbsoluteZ
- Same as `openFileAbsolute` but the path parameter is null-terminated.
- openFileAbsoluteW
- Same as `openFileAbsolute` but the path parameter is WTF-16-encoded.
- accessAbsolute
- Test accessing `path`.
- accessAbsoluteZ
- Same as `accessAbsolute` but the path parameter is null-terminated.
- accessAbsoluteW
- Same as `accessAbsolute` but the path parameter is WTF-16 encoded.
- createFileAbsolute
- Creates, opens, or overwrites a file with write access, based on an absolute path.
- createFileAbsoluteZ
- Same as `createFileAbsolute` but the path parameter is null-terminated.
- createFileAbsoluteW
- Same as `createFileAbsolute` but the path parameter is WTF-16 encoded.
- deleteFileAbsolute
- Delete a file name and possibly the file it refers to, based on an absolute path.
- deleteFileAbsoluteZ
- Same as `deleteFileAbsolute` except the parameter is null-terminated.
- deleteFileAbsoluteW
- Same as `deleteFileAbsolute` except the parameter is WTF-16 encoded.
- deleteTreeAbsolute
- Removes a symlink, file, or directory.
- readLinkAbsolute
- Same as `Dir.readLink`, except it asserts the path is absolute.
- readlinkAbsoluteW
- Windows-only.
- readLinkAbsoluteZ
- Same as `readLink`, except the path parameter is null-terminated.
- symLinkAbsolute
- Creates a symbolic link named `sym_link_path` which contains the string `target_path`.
- symLinkAbsoluteW
- Windows-only.
- symLinkAbsoluteZ
- Same as `symLinkAbsolute` except the parameters are null-terminated pointers.
- selfExePathAlloc
- `selfExePath` except allocates the result on the heap.
- selfExePath
- Get the path to the current executable.
- selfExeDirPathAlloc
- `selfExeDirPath` except allocates the result on the heap.
- selfExeDirPath
- Get the directory path that contains the current executable.
- realpathAlloc
- `realpath`, except caller must free the returned memory.
Error sets in this namespace
Error Sets
= switch (native_os) { .windows, .wasi => false, else => true, }
Values
- has_executable_bit
- = switch (native_os) { .windows, .wasi => false, else => true, }
- max_path_bytes
- The maximum length of a file path that the operating system will accept.
- max_name_bytes
- This represents the maximum size of a `[]u8` file name component that
- base64_alphabet
- = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*
- base64_encoder
- Base64 encoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem.
- base64_decoder
- Base64 decoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem.
Source
Implementation
pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
if (is_darwin) {
// Note that _NSGetExecutablePath() will return "a path" to
// the executable not a "real path" to the executable.
var symlink_path_buf: [max_path_bytes:0]u8 = undefined;
var u32_len: u32 = max_path_bytes + 1; // include the sentinel
const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &u32_len);
if (rc != 0) return error.NameTooLong;
var real_path_buf: [max_path_bytes]u8 = undefined;
const real_path = std.posix.realpathZ(&symlink_path_buf, &real_path_buf) catch |err| switch (err) {
error.InvalidWtf8 => unreachable, // Windows-only
error.NetworkNotFound => unreachable, // Windows-only
else => |e| return e,
};
if (real_path.len > out_buffer.len) return error.NameTooLong;
const result = out_buffer[0..real_path.len];
@memcpy(result, real_path);
return result;
}
switch (native_os) {
.linux, .serenity => return posix.readlinkZ("/proc/self/exe", out_buffer) catch |err| switch (err) {
error.InvalidUtf8 => unreachable, // WASI-only
error.InvalidWtf8 => unreachable, // Windows-only
error.UnsupportedReparsePointType => unreachable, // Windows-only
error.NetworkNotFound => unreachable, // Windows-only
else => |e| return e,
},
.solaris, .illumos => return posix.readlinkZ("/proc/self/path/a.out", out_buffer) catch |err| switch (err) {
error.InvalidUtf8 => unreachable, // WASI-only
error.InvalidWtf8 => unreachable, // Windows-only
error.UnsupportedReparsePointType => unreachable, // Windows-only
error.NetworkNotFound => unreachable, // Windows-only
else => |e| return e,
},
.freebsd, .dragonfly => {
var mib = [4]c_int{ posix.CTL.KERN, posix.KERN.PROC, posix.KERN.PROC_PATHNAME, -1 };
var out_len: usize = out_buffer.len;
try posix.sysctl(&mib, out_buffer.ptr, &out_len, null, 0);
// TODO could this slice from 0 to out_len instead?
return mem.sliceTo(out_buffer, 0);
},
.netbsd => {
var mib = [4]c_int{ posix.CTL.KERN, posix.KERN.PROC_ARGS, -1, posix.KERN.PROC_PATHNAME };
var out_len: usize = out_buffer.len;
try posix.sysctl(&mib, out_buffer.ptr, &out_len, null, 0);
// TODO could this slice from 0 to out_len instead?
return mem.sliceTo(out_buffer, 0);
},
.openbsd, .haiku => {
// OpenBSD doesn't support getting the path of a running process, so try to guess it
if (std.os.argv.len == 0)
return error.FileNotFound;
const argv0 = mem.span(std.os.argv[0]);
if (mem.indexOf(u8, argv0, "/") != null) {
// argv[0] is a path (relative or absolute): use realpath(3) directly
var real_path_buf: [max_path_bytes]u8 = undefined;
const real_path = posix.realpathZ(std.os.argv[0], &real_path_buf) catch |err| switch (err) {
error.InvalidWtf8 => unreachable, // Windows-only
error.NetworkNotFound => unreachable, // Windows-only
else => |e| return e,
};
if (real_path.len > out_buffer.len)
return error.NameTooLong;
const result = out_buffer[0..real_path.len];
@memcpy(result, real_path);
return result;
} else if (argv0.len != 0) {
// argv[0] is not empty (and not a path): search it inside PATH
const PATH = posix.getenvZ("PATH") orelse return error.FileNotFound;
var path_it = mem.tokenizeScalar(u8, PATH, path.delimiter);
while (path_it.next()) |a_path| {
var resolved_path_buf: [max_path_bytes - 1:0]u8 = undefined;
const resolved_path = std.fmt.bufPrintZ(&resolved_path_buf, "{s}/{s}", .{
a_path,
std.os.argv[0],
}) catch continue;
var real_path_buf: [max_path_bytes]u8 = undefined;
if (posix.realpathZ(resolved_path, &real_path_buf)) |real_path| {
// found a file, and hope it is the right file
if (real_path.len > out_buffer.len)
return error.NameTooLong;
const result = out_buffer[0..real_path.len];
@memcpy(result, real_path);
return result;
} else |_| continue;
}
}
return error.FileNotFound;
},
.windows => {
const image_path_unicode_string = &windows.peb().ProcessParameters.ImagePathName;
const image_path_name = image_path_unicode_string.Buffer.?[0 .. image_path_unicode_string.Length / 2 :0];
// If ImagePathName is a symlink, then it will contain the path of the
// symlink, not the path that the symlink points to. We want the path
// that the symlink points to, though, so we need to get the realpath.
const pathname_w = try windows.wToPrefixedFileW(null, image_path_name);
return std.fs.cwd().realpathW(pathname_w.span(), out_buffer) catch |err| switch (err) {
error.InvalidWtf8 => unreachable,
else => |e| return e,
};
},
else => @compileError("std.fs.selfExePath not supported for this target"),
}
}