Skip to content

Commit 2d0ac5a

Browse files
committed
os,runtime: make sure executable path is fully resolved at process init
1 parent edaf877 commit 2d0ac5a

File tree

4 files changed

+68
-15
lines changed

4 files changed

+68
-15
lines changed

src/os/executable_darwin.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,5 @@ package os
66
func runtime_executable_path() string
77

88
func Executable() (string, error) {
9-
p := runtime_executable_path()
10-
if p != "" && p[0] == '/' {
11-
// absolute path
12-
return p, nil
13-
}
14-
cwd, err := Getwd()
15-
if err != nil {
16-
return "", err
17-
}
18-
return joinPath(cwd, p), nil
9+
return runtime_executable_path(), nil
1910
}

src/runtime/os_darwin.go

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,18 @@ func call_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr
232232

233233
//go:linkname os_runtime_executable_path os.runtime_executable_path
234234
func os_runtime_executable_path() string {
235-
argv := (*unsafe.Pointer)(unsafe.Pointer(main_argv))
235+
return executablePath
236+
}
237+
238+
var executablePath string
236239

240+
func platform_argv(argc int32, argv *unsafe.Pointer) {
241+
executablePath = executable_path(argc, argv)
242+
}
243+
244+
func executable_path(argc int32, argv *unsafe.Pointer) string {
237245
// skip over argv
238-
argv = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(argv), (uintptr(main_argc)+1)*unsafe.Sizeof(argv)))
246+
argv = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(argv), (uintptr(argc)+1)*unsafe.Sizeof(argv)))
239247

240248
// skip over envv
241249
for (*argv) != nil {
@@ -251,11 +259,21 @@ func os_runtime_executable_path() string {
251259
length: length,
252260
ptr: (*byte)(cstr),
253261
}
254-
executablePath := *(*string)(unsafe.Pointer(&argString))
262+
path := *(*string)(unsafe.Pointer(&argString))
255263

256264
// strip "executable_path=" prefix if available, it's added after OS X 10.11.
257-
executablePath = stringsTrimPrefix(executablePath, "executable_path=")
258-
return executablePath
265+
path = stringsTrimPrefix(path, "executable_path=")
266+
267+
if path != "" && path[0] == '/' {
268+
// absolute path
269+
return path
270+
}
271+
272+
cwd := getcwd()
273+
if cwd != "" {
274+
path = joinPath(cwd, path)
275+
}
276+
return path
259277
}
260278

261279
func stringsTrimPrefix(s, prefix string) string {
@@ -264,3 +282,40 @@ func stringsTrimPrefix(s, prefix string) string {
264282
}
265283
return s
266284
}
285+
286+
func joinPath(dir, name string) string {
287+
if len(dir) > 0 && dir[len(dir)-1] == '/' {
288+
return dir + name
289+
}
290+
return dir + "/" + name
291+
}
292+
293+
// from syscall
294+
func getcwd() string {
295+
const pathMax = 1024
296+
var buf [4 * pathMax]byte
297+
s := libc_getcwd(&buf[0], uint(len(buf)))
298+
if s == nil {
299+
return ""
300+
}
301+
n := clen(buf[:])
302+
if n < 1 {
303+
return ""
304+
}
305+
return string(buf[:n])
306+
}
307+
308+
// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
309+
func clen(n []byte) int {
310+
for i := 0; i < len(n); i++ {
311+
if n[i] == 0 {
312+
return i
313+
}
314+
}
315+
return len(n)
316+
}
317+
318+
// char *getcwd(char *buf, size_t size)
319+
//
320+
//export getcwd
321+
func libc_getcwd(buf *byte, size uint) *byte

src/runtime/os_linux.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,7 @@ func fcntl(fd int32, cmd int32, arg int32) (ret int32, errno int32) {
157157
errno = *libc_errno_location()
158158
return
159159
}
160+
161+
func platform_argv(argc int32, argv *unsafe.Pointer) {
162+
// nothing
163+
}

src/runtime/runtime_unix.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ func main(argc int32, argv *unsafe.Pointer) int {
9595
// The run function has been moved to a separate (non-inlined) function so
9696
// that the correct stack pointer is read.
9797
stackTop = getCurrentStackPointer()
98+
99+
platform_argv(main_argc, main_argv)
100+
98101
runMain()
99102

100103
// For libc compatibility.

0 commit comments

Comments
 (0)