From e6b69151c0d30d2df95d1f92b65784eac7d186d9 Mon Sep 17 00:00:00 2001 From: Bodie Solomon Date: Sun, 17 Jun 2018 14:35:00 -0400 Subject: [PATCH 1/3] Fix 1117: Use realpath in stage1 Darwin os_self_exe_path Issue: https://github.com/ziglang/zig/issues/1117 The macOS stage1 Zig compiler should look in Zig's real absolute path for the Zig stdlib, but os_self_exe_path looks in its path as returned by _NSGetExecutablePath, which may be a symlink. This means that a symlinked Zig cannot find the Zig stdlib. This patch fixes the issue by resolving the _NSGetExecutablePath result to the real path using realpath() before copying the result to the output path. --- src/os.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/os.cpp b/src/os.cpp index 97462bd65..75e6dd865 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -989,12 +989,28 @@ int os_self_exe_path(Buf *out_path) { } #elif defined(ZIG_OS_DARWIN) + // How long is the executable's path? uint32_t u32_len = 0; int ret1 = _NSGetExecutablePath(nullptr, &u32_len); assert(ret1 != 0); - buf_resize(out_path, u32_len); - int ret2 = _NSGetExecutablePath(buf_ptr(out_path), &u32_len); + + // Allocate a buffer for this path. + Buf *path_tmp = buf_alloc_fixed(u32_len); + // Fill the buffer with the path, which may be a symlink. + int ret2 = _NSGetExecutablePath(buf_ptr(path_tmp), &u32_len); assert(ret2 == 0); + + // Make a buffer with room for the real path. + Buf *resolve_tmp = buf_alloc_fixed(PATH_MAX); + + // Fill it with the real resolved path. + char *real_path = realpath(buf_ptr(path_tmp), buf_ptr(resolve_tmp)); + // IEEE Std 1003.1-2017: realpath() shall return a pointer to the + // buffer containing the resolved name. + assert(real_path == buf_ptr(resolve_tmp)); + + // Resize out_path and copy the resulting resolved absolute path. + buf_init_from_buf(out_path, resolve_tmp); return 0; #elif defined(ZIG_OS_LINUX) buf_resize(out_path, 256); From 045682289243c6186363e984babc706c3ed93152 Mon Sep 17 00:00:00 2001 From: Bodie Solomon Date: Mon, 18 Jun 2018 07:01:59 -0400 Subject: [PATCH 2/3] Fix 1117: Tweak realpath logic to use out_path as scratch space --- src/os.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/os.cpp b/src/os.cpp index 75e6dd865..0e3c3f9a6 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -994,23 +994,23 @@ int os_self_exe_path(Buf *out_path) { int ret1 = _NSGetExecutablePath(nullptr, &u32_len); assert(ret1 != 0); - // Allocate a buffer for this path. - Buf *path_tmp = buf_alloc_fixed(u32_len); - // Fill the buffer with the path, which may be a symlink. - int ret2 = _NSGetExecutablePath(buf_ptr(path_tmp), &u32_len); + // Make room for the executable path and resolved path in out_path, + // then subslice it for convenience. + buf_resize(out_path, u32_len + PATH_MAX); + Buf *tmp = buf_slice(out_path, 0, u32_len); + Buf *resolved = buf_slice(out_path, u32_len, u32_len + PATH_MAX); + + // Fill the executable path. + int ret2 = _NSGetExecutablePath(buf_ptr(tmp), &u32_len); assert(ret2 == 0); - // Make a buffer with room for the real path. - Buf *resolve_tmp = buf_alloc_fixed(PATH_MAX); + // Resolve the real path from that. + char *real_path = realpath(buf_ptr(tmp), buf_ptr(resolved)); + assert(real_path == buf_ptr(resolved)); - // Fill it with the real resolved path. - char *real_path = realpath(buf_ptr(path_tmp), buf_ptr(resolve_tmp)); - // IEEE Std 1003.1-2017: realpath() shall return a pointer to the - // buffer containing the resolved name. - assert(real_path == buf_ptr(resolve_tmp)); - - // Resize out_path and copy the resulting resolved absolute path. - buf_init_from_buf(out_path, resolve_tmp); + // Write the real path back into the beginning of out_path, resize. + buf_init_from_buf(out_path, resolved); + assert(buf_len(out_path) == buf_len(resolved)); return 0; #elif defined(ZIG_OS_LINUX) buf_resize(out_path, 256); From c7057bd25b2a99e5ac61963efd588f5fe4ba93c6 Mon Sep 17 00:00:00 2001 From: Bodie Solomon Date: Mon, 18 Jun 2018 07:37:26 -0400 Subject: [PATCH 3/3] Fix 1117: Revise realpath scratch logic --- src/os.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/os.cpp b/src/os.cpp index 0e3c3f9a6..75f748e2f 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -994,23 +994,24 @@ int os_self_exe_path(Buf *out_path) { int ret1 = _NSGetExecutablePath(nullptr, &u32_len); assert(ret1 != 0); - // Make room for the executable path and resolved path in out_path, - // then subslice it for convenience. - buf_resize(out_path, u32_len + PATH_MAX); - Buf *tmp = buf_slice(out_path, 0, u32_len); - Buf *resolved = buf_slice(out_path, u32_len, u32_len + PATH_MAX); + // Make a buffer having room for the temp path. + Buf *tmp = buf_alloc_fixed(u32_len); // Fill the executable path. int ret2 = _NSGetExecutablePath(buf_ptr(tmp), &u32_len); assert(ret2 == 0); // Resolve the real path from that. - char *real_path = realpath(buf_ptr(tmp), buf_ptr(resolved)); - assert(real_path == buf_ptr(resolved)); + buf_resize(out_path, PATH_MAX); + char *real_path = realpath(buf_ptr(tmp), buf_ptr(out_path)); + assert(real_path == buf_ptr(out_path)); + + // Deallocate our scratch space. + buf_deinit(tmp); + + // Resize out_path for the correct length. + buf_resize(out_path, strlen(buf_ptr(out_path))); - // Write the real path back into the beginning of out_path, resize. - buf_init_from_buf(out_path, resolved); - assert(buf_len(out_path) == buf_len(resolved)); return 0; #elif defined(ZIG_OS_LINUX) buf_resize(out_path, 256);