diff --git a/.gitignore b/.gitignore index c1926ca2..f0ebb623 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ bufferflow_tinyg_old.md +/arduino-create-agent* /arduino-cloud-agent* !/arduino-cloud-agent*/ rsrc.syso @@ -19,3 +20,7 @@ logs/ # Python __pycache__ + +# Debugging +__debug_bin*.exe* +vendor/ \ No newline at end of file diff --git a/updater/elevate_unix.go b/updater/elevate_unix.go new file mode 100644 index 00000000..17e81950 --- /dev/null +++ b/updater/elevate_unix.go @@ -0,0 +1,17 @@ +//go:build !windows + +package updater + +import ( + "os" + "os/exec" +) + +func elevate() error { + args := append([]string{os.Args[0]}, os.Args[1:]...) + cmd := exec.Command("sudo", args...) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} diff --git a/updater/elevate_windows.go b/updater/elevate_windows.go new file mode 100644 index 00000000..ab3c3493 --- /dev/null +++ b/updater/elevate_windows.go @@ -0,0 +1,32 @@ +package updater + +import ( + "os" + "strings" + "syscall" + + "golang.org/x/sys/windows" +) + +func elevate() error { + verb := "runas" + exe, _ := os.Executable() + cwd, _ := os.Getwd() + args := strings.Join(os.Args[1:], " ") + + verbPtr, err := syscall.UTF16PtrFromString(verb) + if err != nil { + return err + } + exePtr, err := syscall.UTF16PtrFromString(exe) + if err != nil { + return err + } + cwdPtr, err := syscall.UTF16PtrFromString(cwd) + if err != nil { + return err + } + argPtr, _ := syscall.UTF16PtrFromString(args) + var showCmd int32 = 1 + return windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd) +} diff --git a/updater/updater.go b/updater/updater.go index db4e5454..891ba438 100644 --- a/updater/updater.go +++ b/updater/updater.go @@ -83,9 +83,11 @@ func fetch(url string) (io.ReadCloser, error) { // addTempSuffixToPath adds the "-temp" suffix to the path to an executable file (a ".exe" extension is replaced with "-temp.exe") func addTempSuffixToPath(path string) string { - if filepath.Ext(path) == "exe" { + if filepath.Ext(path) == ".exe" { + // Windows path = strings.Replace(path, ".exe", "-temp.exe", -1) } else { + // Unix path = path + "-temp" } @@ -110,3 +112,15 @@ func copyExe(from, to string) error { } return nil } + +// requestElevation requests this program to rerun as administrator, for when we don't have permission over the update files +func requestElevation() { + log.Println("Permission denied. Requesting elevated privileges...") + + var err error = elevate() + + if err != nil { + log.Println("Failed to request elevation:", err) + return + } +} diff --git a/updater/updater_default.go b/updater/updater_default.go index 2cf01b8a..c603ea1d 100644 --- a/updater/updater_default.go +++ b/updater/updater_default.go @@ -66,6 +66,9 @@ func start(src string) string { if strings.Contains(src, "-temp") { newPath := removeTempSuffixFromPath(src) if err := copyExe(src, newPath); err != nil { + if os.IsPermission(err) { + requestElevation() + } log.Println("Copy error: ", err) panic(err) } @@ -74,6 +77,9 @@ func start(src string) string { // Otherwise copy to a path with -temp suffix if err := copyExe(src, addTempSuffixToPath(src)); err != nil { + if os.IsPermission(err) { + requestElevation() + } panic(err) } return ""