Skip to content

Commit 5428bfd

Browse files
dgryskideadprogram
authored andcommitted
runtime,os: add os.Executable() for Darwin
1 parent 72b1955 commit 5428bfd

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed

src/os/executable_darwin.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//go:build darwin
2+
3+
package os
4+
5+
// via runtime because we need argc/argv ptrs
6+
func runtime_executable_path() string
7+
8+
func Executable() (string, error) {
9+
return runtime_executable_path(), nil
10+
}

src/os/executable_other.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build !linux || baremetal
1+
//go:build (!linux && !darwin) || baremetal
22

33
package os
44

src/runtime/os_darwin.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,3 +229,38 @@ func call_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) int32
229229

230230
//export tinygo_syscall6X
231231
func call_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr
232+
233+
//go:linkname os_runtime_executable_path os.runtime_executable_path
234+
func os_runtime_executable_path() string {
235+
argv := (*unsafe.Pointer)(unsafe.Pointer(main_argv))
236+
237+
// skip over argv
238+
argv = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(argv), (uintptr(main_argc)+1)*unsafe.Sizeof(argv)))
239+
240+
// skip over envv
241+
for (*argv) != nil {
242+
argv = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(argv), unsafe.Sizeof(argv)))
243+
}
244+
245+
// next string is exe path
246+
argv = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(argv), unsafe.Sizeof(argv)))
247+
248+
cstr := unsafe.Pointer(*argv)
249+
length := strlen(cstr)
250+
argString := _string{
251+
length: length,
252+
ptr: (*byte)(cstr),
253+
}
254+
executablePath := *(*string)(unsafe.Pointer(&argString))
255+
256+
// strip "executable_path=" prefix if available, it's added after OS X 10.11.
257+
executablePath = stringsTrimPrefix(executablePath, "executable_path=")
258+
return executablePath
259+
}
260+
261+
func stringsTrimPrefix(s, prefix string) string {
262+
if len(s) >= len(prefix) && s[:len(prefix)] == prefix {
263+
return s[len(prefix):]
264+
}
265+
return s
266+
}

0 commit comments

Comments
 (0)