Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/std/c/darwin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ usingnamespace @import("../os/bits.zig");

extern "c" fn __error() *c_int;
pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32;
pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int;
pub extern "c" fn _NSGetExecutablePath(buf: [*:0]u8, bufsize: *u32) c_int;
pub extern "c" fn _dyld_image_count() u32;
pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header;
pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize;
Expand Down
16 changes: 12 additions & 4 deletions lib/std/fs.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2162,7 +2162,7 @@ pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File {
return openFileAbsoluteZ(buf[0..self_exe_path.len :0].ptr, flags);
}

pub const SelfExePathError = os.ReadLinkError || os.SysCtlError;
pub const SelfExePathError = os.ReadLinkError || os.SysCtlError || os.RealPathError;

/// `selfExePath` except allocates the result on the heap.
/// Caller owns returned memory.
Expand Down Expand Up @@ -2190,10 +2190,18 @@ pub fn selfExePathAlloc(allocator: *Allocator) ![]u8 {
/// TODO make the return type of this a null terminated pointer
pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
if (is_darwin) {
var u32_len: u32 = @intCast(u32, math.min(out_buffer.len, math.maxInt(u32)));
const rc = std.c._NSGetExecutablePath(out_buffer.ptr, &u32_len);
// 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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since _NSGetExecutablePath first parameter is null-terminated and this is the only callsite can you change the signature in darwin.zig?
That'd also help to get rid of the ptrCast below

if (rc != 0) return error.NameTooLong;
return mem.spanZ(@ptrCast([*:0]u8, out_buffer));

var real_path_buf: [MAX_PATH_BYTES]u8 = undefined;
const real_path = try std.os.realpathZ(&symlink_path_buf, &real_path_buf);
if (real_path.len > out_buffer.len) return error.NameTooLong;
std.mem.copy(u8, out_buffer, real_path);
return out_buffer[0..real_path.len];
}
switch (builtin.os.tag) {
.linux => return os.readlinkZ("/proc/self/exe", out_buffer),
Expand Down
2 changes: 1 addition & 1 deletion lib/std/os.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3993,7 +3993,7 @@ pub const RealPathError = error{
/// Expands all symbolic links and resolves references to `.`, `..`, and
/// extra `/` characters in `pathname`.
/// The return value is a slice of `out_buffer`, but not necessarily from the beginning.
/// See also `realpathC` and `realpathW`.
/// See also `realpathZ` and `realpathW`.
pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
if (builtin.os.tag == .windows) {
const pathname_w = try windows.sliceToPrefixedFileW(pathname);
Expand Down