DoxigAlpha

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"),
    }
}