Commit c60d6c0b authored by Ian Lance Taylor's avatar Ian Lance Taylor

os: on OpenBSD implement Executable using Args[0]

OpenBSD no longer has procfs.

Based on a patch by Matthieu Sarter.

Fixes #19453.

Change-Id: Ia09d16f8a1cbef2f8cc1c5f49e9c61ec7d026a40
Reviewed-on: https://go-review.googlesource.com/46004
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent fddc5983
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build openbsd
package os
// We query the working directory at init, to use it later to search for the
// executable file
// errWd will be checked later, if we need to use initWd
var initWd, errWd = Getwd()
func executable() (string, error) {
var exePath string
if len(Args) == 0 || Args[0] == "" {
return "", ErrNotExist
}
if IsPathSeparator(Args[0][0]) {
// Args[0] is an absolute path, so it is the executable.
// Note that we only need to worry about Unix paths here.
exePath = Args[0]
} else {
for i := 1; i < len(Args[0]); i++ {
if IsPathSeparator(Args[0][i]) {
// Args[0] is a relative path: prepend the
// initial working directory.
if errWd != nil {
return "", errWd
}
exePath = initWd + string(PathSeparator) + Args[0]
break
}
}
}
if exePath != "" {
if err := isExecutable(exePath); err != nil {
return "", err
}
return exePath, nil
}
// Search for executable in $PATH.
for _, dir := range splitPathList(Getenv("PATH")) {
if len(dir) == 0 {
dir = "."
}
if !IsPathSeparator(dir[0]) {
if errWd != nil {
return "", errWd
}
dir = initWd + string(PathSeparator) + dir
}
exePath = dir + string(PathSeparator) + Args[0]
switch isExecutable(exePath) {
case nil:
return exePath, nil
case ErrPermission:
return "", ErrPermission
}
}
return "", ErrNotExist
}
// isExecutable returns an error if a given file is not an executable.
func isExecutable(path string) error {
stat, err := Stat(path)
if err != nil {
return err
}
mode := stat.Mode()
if !mode.IsRegular() {
return ErrPermission
}
if (mode & 0111) == 0 {
return ErrPermission
}
return nil
}
// splitPathList splits a path list.
// This is based on genSplit from strings/strings.go
func splitPathList(pathList string) []string {
if pathList == "" {
return nil
}
n := 1
for i := 0; i < len(pathList); i++ {
if pathList[i] == PathListSeparator {
n++
}
}
start := 0
a := make([]string, n)
na := 0
for i := 0; i+1 <= len(pathList) && na+1 < n; i++ {
if pathList[i] == PathListSeparator {
a[na] = pathList[start:i]
na++
start = i + 1
}
}
a[na] = pathList[start:]
return a[:na+1]
}
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux netbsd openbsd dragonfly nacl
// +build linux netbsd dragonfly nacl
package os
......@@ -23,8 +23,6 @@ var executablePath, executablePathErr = func() (string, error) {
procfn = "/proc/self/exe"
case "netbsd":
procfn = "/proc/curproc/exe"
case "openbsd":
procfn = "/proc/curproc/file"
case "dragonfly":
procfn = "/proc/curproc/file"
}
......
......@@ -20,10 +20,6 @@ func TestExecutable(t *testing.T) {
testenv.MustHaveExec(t) // will also execlude nacl, which doesn't support Executable anyway
ep, err := os.Executable()
if err != nil {
switch goos := runtime.GOOS; goos {
case "openbsd": // procfs is not mounted by default
t.Skipf("Executable failed on %s: %v, expected", goos, err)
}
t.Fatalf("Executable failed: %v", err)
}
// we want fn to be of the form "dir/prog"
......@@ -32,6 +28,13 @@ func TestExecutable(t *testing.T) {
if err != nil {
t.Fatalf("filepath.Rel: %v", err)
}
if runtime.GOOS == "openbsd" {
// The rest of the test doesn't work on OpenBSD,
// which relies on argv[0].
t.Skipf("skipping remainder of test on %s", runtime.GOOS)
}
cmd := &osexec.Cmd{}
// make child start with a relative program path
cmd.Dir = dir
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment