From 4519dd07ae9a50d5e4a2a105982d7e1250a81484 Mon Sep 17 00:00:00 2001 From: Mauricio Date: Fri, 16 Aug 2024 17:03:39 -0700 Subject: [PATCH 1/2] attempt to write symlinks w/ sudo --- go/install/install_darwin.go | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/go/install/install_darwin.go b/go/install/install_darwin.go index f4cc22b44eed..7988644f59be 100644 --- a/go/install/install_darwin.go +++ b/go/install/install_darwin.go @@ -697,8 +697,34 @@ func createCommandLine(binPath string, linkPath string, log Log) error { } } - log.Info("Linking %s to %s", linkPath, binPath) - return os.Symlink(binPath, linkPath) + dirPath := filepath.Dir(linkPath) + + if !isWritable(dirPath) { + log.Info("Directory %s is not writable, using sudo to create symlink", dirPath) + cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("sudo ln -s %s %s", binPath, linkPath)) + output, err := cmd.CombinedOutput() + if err != nil { + log.Error("Failed to create symlink with sudo: %s", string(output)) + return err + } + log.Info("Symlink created with sudo") + + return nil + } else { + log.Info("Linking %s to %s", linkPath, binPath) + return os.Symlink(binPath, linkPath) + } +} + +func isWritable(dirPath string) bool { + testFile := filepath.Join(dirPath, ".writable-test") + file, err := os.OpenFile(testFile, os.O_CREATE|os.O_WRONLY, 0666) + if err != nil { + return false + } + file.Close() + os.Remove(testFile) + return true } func installCommandLineForBinPath(binPath string, linkPath string, force bool, log Log) error { From ee3a9a42923e0a3f1a77bfcd18957cb64ec55acd Mon Sep 17 00:00:00 2001 From: Mauricio Date: Fri, 16 Aug 2024 17:14:48 -0700 Subject: [PATCH 2/2] Check dir permissions with unix.Access --- go/install/install_darwin.go | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/go/install/install_darwin.go b/go/install/install_darwin.go index 7988644f59be..9eb51446fd5e 100644 --- a/go/install/install_darwin.go +++ b/go/install/install_darwin.go @@ -24,6 +24,8 @@ import ( "github.com/keybase/client/go/logger" "github.com/keybase/client/go/mounter" "github.com/keybase/client/go/protocol/keybase1" + + "golang.org/x/sys/unix" ) // defaultLaunchdWait is how long we should wait after install & start. @@ -699,7 +701,7 @@ func createCommandLine(binPath string, linkPath string, log Log) error { dirPath := filepath.Dir(linkPath) - if !isWritable(dirPath) { + if err := unix.Access(dirPath, unix.W_OK); err != nil { log.Info("Directory %s is not writable, using sudo to create symlink", dirPath) cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("sudo ln -s %s %s", binPath, linkPath)) output, err := cmd.CombinedOutput() @@ -716,17 +718,6 @@ func createCommandLine(binPath string, linkPath string, log Log) error { } } -func isWritable(dirPath string) bool { - testFile := filepath.Join(dirPath, ".writable-test") - file, err := os.OpenFile(testFile, os.O_CREATE|os.O_WRONLY, 0666) - if err != nil { - return false - } - file.Close() - os.Remove(testFile) - return true -} - func installCommandLineForBinPath(binPath string, linkPath string, force bool, log Log) error { fi, err := os.Lstat(linkPath) if os.IsNotExist(err) {