From 121350816c513ed59b2169a19eee976e09b88d15 Mon Sep 17 00:00:00 2001 From: Matteo Suppo Date: Wed, 8 Apr 2020 16:11:53 +0200 Subject: [PATCH 1/4] Three card trick --- go.sum | 7 +++++++ main.go | 37 +++++++++++++++++++++++++++++++++++++ update.go | 9 +++++++++ updater/updater.go | 8 ++++++++ 4 files changed, 61 insertions(+) diff --git a/go.sum b/go.sum index bd7531a0c..b7fea7221 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,10 @@ github.com/codeclysm/extract v2.0.0+incompatible/go.mod h1:2nhFMPHiU9At61hz+12bf github.com/creack/goselect v0.0.0-20180501195510-58854f77ee8d h1:6o8WW5zZ+Ny9sbk69epnAPmBzrBaRnvci+l4+pqleeY= github.com/creack/goselect v0.0.0-20180501195510-58854f77ee8d/go.mod h1:gHrIcH/9UZDn2qgeTUeW5K9eZsVYCH6/60J/FHysWyE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidmz/go-pageant v1.0.1/go.mod h1:WWOKE/93DhgsPq15jaipH4fVY+MLKKWH4Yku5Ei92rE= +github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598/go.mod h1:0FpDmbrt36utu8jEmeU05dPC9AB5tsLYVVi+ZHfyuwI= github.com/dimfeld/httptreemux v5.0.1+incompatible h1:Qj3gVcDNoOthBAqftuD596rm4wg/adLLz5xh5CmpiCA= github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0= @@ -63,6 +65,7 @@ github.com/lxn/walk v0.0.0-20191113135339-bf589de20b3c/go.mod h1:E23UucZGqpuUANJ github.com/lxn/walk v0.0.0-20191128110447-55ccb3a9f5c1/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ= github.com/lxn/win v0.0.0-20191106123917-121afc750dd3/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA= github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA= +github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/mattn/go-isatty v0.0.2-0.20170307163044-57fdcb988a5c h1:vNDTotKSxm/15mLGhBXjdU6q6Ncrx0HlVEd8ToAsGTw= github.com/mattn/go-isatty v0.0.2-0.20170307163044-57fdcb988a5c/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -70,6 +73,7 @@ github.com/mattn/go-shellwords v1.0.3 h1:K/VxK7SZ+cvuPgFSLKi5QPI9Vr/ipOf4C1gN+nt github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/miekg/dns v1.0.15 h1:9+UupePBQCG6zf1q/bGmTO1vumoG13jsrbWOSX1W6Tw= github.com/miekg/dns v1.0.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/oleksandr/bonjour v0.0.0-20160508152359-5dcf00d8b228 h1:Cvfd2dOlXIPTeEkOT/h8PyK4phBngOM4at9/jlgy7d4= github.com/oleksandr/bonjour v0.0.0-20160508152359-5dcf00d8b228/go.mod h1:MGuVJ1+5TX1SCoO2Sx0eAnjpdRytYla2uC1YIZfkC9c= @@ -80,6 +84,7 @@ github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.8.3 h1:9jSe2SxTM8/3bXZjtqnkgTBW+lA8db0knZJyns7gpBA= github.com/pkg/sftp v1.8.3/go.mod h1:NxmoDg/QLVWluQDUYG7XBZTLUpKeFa8e3aMf1BfjyHk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sfreiberg/simplessh v0.0.0-20180301191542-495cbb862a9c h1:7Q+2oF0uBoLEV+j13E3/xUkPkI7f+sFNPZOPo2jmrWk= @@ -91,11 +96,13 @@ github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:s github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/ugorji/go v0.0.0-20170215201144-c88ee250d022 h1:wIYK3i9zY6ZBcWw4GFvoPVwtb45iEm8KyOVmDhSLvsE= github.com/ugorji/go v0.0.0-20170215201144-c88ee250d022/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= github.com/xrash/smetrics v0.0.0-20170218160415-a3153f7040e9 h1:w8V9v0qVympSF6GjdjIyeqR7+EVhAF9CBQmkmW7Zw0w= github.com/xrash/smetrics v0.0.0-20170218160415-a3153f7040e9/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea h1:CyhwejzVGvZ3Q2PSbQ4NRRYn+ZWv5eS1vlaEusT+bAI= github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea/go.mod h1:eNr558nEUjP8acGw8FFjTeWvSgU1stO7FAO6eknhHe4= go.bug.st/downloader v0.0.0-20181116113543-9b8976a44d87 h1:8W/hwyrc25HrXxbtG8Ghiwgq/hDB8KCh7hKMf78gp90= go.bug.st/downloader v0.0.0-20181116113543-9b8976a44d87/go.mod h1:OUL7bexo6Ir+BRE5E7Cs3qUvO6ZgJL5Hjk/qwiy6Ze0= diff --git a/main.go b/main.go index c45e270c8..cea20e2de 100755 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ package main import ( "encoding/json" "flag" + "io/ioutil" "os" "os/user" "path/filepath" @@ -118,6 +119,42 @@ func main() { AdditionalConfig: *additionalConfig, } + path, err := osext.Executable() + if err != nil { + panic(err) + } + + // If the executable is temporary, copy it to the full path, then restart + if strings.Contains(path, "-temp") { + correctPath := strings.Replace(path, "-temp", "", -1) + data, err := ioutil.ReadFile(path) + if err != nil { + panic(err) + } + err = ioutil.WriteFile(correctPath, data, 0755) + if err != nil { + panic(err) + } + + Systray.Restart() + } else { + // Otherwise copy to a path with -temp suffix + correctPath := path + if filepath.Ext(path) == "exe" { + path = strings.Replace(path, ".exe", "-temp.exe", -1) + } else { + path = path + "-temp" + } + data, err := ioutil.ReadFile(correctPath) + if err != nil { + panic(err) + } + err = ioutil.WriteFile(path, data, 0755) + if err != nil { + panic(err) + } + } + Systray.Start() } diff --git a/update.go b/update.go index f8a17a4ac..f0739a400 100644 --- a/update.go +++ b/update.go @@ -30,6 +30,9 @@ package main import ( + "path/filepath" + "strings" + "github.com/arduino/arduino-create-agent/updater" "github.com/gin-gonic/gin" "github.com/kardianos/osext" @@ -60,6 +63,12 @@ func updateHandler(c *gin.Context) { return } + if filepath.Ext(path) == "exe" { + path = strings.Replace(path, ".exe", "-temp.exe", -1) + } else { + path = path + "-temp" + } + c.JSON(200, gin.H{"success": "Please wait a moment while the agent reboots itself"}) Systray.Update(path) } diff --git a/updater/updater.go b/updater/updater.go index d80d6ae5b..a02d18aac 100644 --- a/updater/updater.go +++ b/updater/updater.go @@ -12,6 +12,7 @@ import ( "os" "path/filepath" "runtime" + "strings" "time" "github.com/kr/binarydist" @@ -202,6 +203,12 @@ func (u *Updater) update() error { if err != nil { return err } + if filepath.Ext(path) == "exe" { + path = strings.Replace(path, ".exe", "-temp.exe", -1) + } else { + path = path + "-temp" + } + old, err := os.Open(path) if err != nil { return err @@ -241,6 +248,7 @@ func (u *Updater) update() error { // it can't be renamed if a handle to the file is still open old.Close() + up.TargetPath = path err, errRecover := up.FromStream(bytes.NewBuffer(bin)) if errRecover != nil { log.Errorf("update and recovery errors: %q %q", err, errRecover) From 36dcef5ec598e2a49e5ca8883b7630db89fc49d0 Mon Sep 17 00:00:00 2001 From: Matteo Suppo Date: Wed, 8 Apr 2020 17:07:46 +0200 Subject: [PATCH 2/4] prevent bad errors on osx --- main.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/main.go b/main.go index cea20e2de..908383238 100755 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "os" "os/user" "path/filepath" + "runtime" "runtime/debug" "strconv" "strings" @@ -97,6 +98,9 @@ func launchSelfLater() { } func main() { + // prevents bad errors in OSX, such as [NS...] is only safe to invoke on the main thread. + runtime.LockOSThread() + // Parse regular flags flag.Parse() From 7f3e25a43ae88b68a6144ae85106f2790c8d7816 Mon Sep 17 00:00:00 2001 From: Matteo Suppo Date: Tue, 14 Apr 2020 14:01:20 +0200 Subject: [PATCH 3/4] Refactor: extract copyExe func --- main.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/main.go b/main.go index 908383238..049596161 100755 --- a/main.go +++ b/main.go @@ -98,7 +98,7 @@ func launchSelfLater() { } func main() { - // prevents bad errors in OSX, such as [NS...] is only safe to invoke on the main thread. + // prevents bad errors in OSX, such as '[NS...] is only safe to invoke on the main thread'. runtime.LockOSThread() // Parse regular flags @@ -131,11 +131,7 @@ func main() { // If the executable is temporary, copy it to the full path, then restart if strings.Contains(path, "-temp") { correctPath := strings.Replace(path, "-temp", "", -1) - data, err := ioutil.ReadFile(path) - if err != nil { - panic(err) - } - err = ioutil.WriteFile(correctPath, data, 0755) + err := copyExe(path, correctPath) if err != nil { panic(err) } @@ -149,11 +145,7 @@ func main() { } else { path = path + "-temp" } - data, err := ioutil.ReadFile(correctPath) - if err != nil { - panic(err) - } - err = ioutil.WriteFile(path, data, 0755) + err := copyExe(path, correctPath) if err != nil { panic(err) } @@ -162,6 +154,18 @@ func main() { Systray.Start() } +func copyExe(from, to string) error { + data, err := ioutil.ReadFile(from) + if err != nil { + return err + } + err = ioutil.WriteFile(to, data, 0755) + if err != nil { + return err + } + return nil +} + func loop() { if *hibernate { return From fd8b6063298eeec9f204c7bea7cbc58ffb92d665 Mon Sep 17 00:00:00 2001 From: Matteo Suppo Date: Tue, 14 Apr 2020 14:07:32 +0200 Subject: [PATCH 4/4] refactor: extract TempPath and BinPath funcs --- main.go | 12 +++--------- update.go | 9 +-------- updater/updater.go | 23 ++++++++++++++++++----- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/main.go b/main.go index 049596161..a678bdc3f 100755 --- a/main.go +++ b/main.go @@ -19,6 +19,7 @@ import ( "github.com/arduino/arduino-create-agent/systray" "github.com/arduino/arduino-create-agent/tools" + "github.com/arduino/arduino-create-agent/updater" "github.com/arduino/arduino-create-agent/utilities" v2 "github.com/arduino/arduino-create-agent/v2" "github.com/gin-gonic/gin" @@ -130,8 +131,7 @@ func main() { // If the executable is temporary, copy it to the full path, then restart if strings.Contains(path, "-temp") { - correctPath := strings.Replace(path, "-temp", "", -1) - err := copyExe(path, correctPath) + err := copyExe(path, updater.BinPath(path)) if err != nil { panic(err) } @@ -139,13 +139,7 @@ func main() { Systray.Restart() } else { // Otherwise copy to a path with -temp suffix - correctPath := path - if filepath.Ext(path) == "exe" { - path = strings.Replace(path, ".exe", "-temp.exe", -1) - } else { - path = path + "-temp" - } - err := copyExe(path, correctPath) + err := copyExe(path, updater.TempPath(path)) if err != nil { panic(err) } diff --git a/update.go b/update.go index f0739a400..6a81190d4 100644 --- a/update.go +++ b/update.go @@ -30,9 +30,6 @@ package main import ( - "path/filepath" - "strings" - "github.com/arduino/arduino-create-agent/updater" "github.com/gin-gonic/gin" "github.com/kardianos/osext" @@ -63,11 +60,7 @@ func updateHandler(c *gin.Context) { return } - if filepath.Ext(path) == "exe" { - path = strings.Replace(path, ".exe", "-temp.exe", -1) - } else { - path = path + "-temp" - } + path = updater.TempPath(path) c.JSON(200, gin.H{"success": "Please wait a moment while the agent reboots itself"}) Systray.Update(path) diff --git a/updater/updater.go b/updater/updater.go index a02d18aac..4b5faaf71 100644 --- a/updater/updater.go +++ b/updater/updater.go @@ -57,6 +57,22 @@ const devValidTime = 7 * 24 * time.Hour var errHashMismatch = errors.New("new file hash mismatch after patch") var up = update.New() +// TempPath generates a temporary path for the executable +func TempPath(path string) string { + if filepath.Ext(path) == "exe" { + path = strings.Replace(path, ".exe", "-temp.exe", -1) + } else { + path = path + "-temp" + } + + return path +} + +// TempPath generates the proper path for a temporary executable +func BinPath(path string) string { + return strings.Replace(path, "-temp", "", -1) +} + // Updater is the configuration and runtime data for doing an update. // // Note that ApiURL, BinURL and DiffURL should have the same value if all files are available at the same location. @@ -203,11 +219,8 @@ func (u *Updater) update() error { if err != nil { return err } - if filepath.Ext(path) == "exe" { - path = strings.Replace(path, ".exe", "-temp.exe", -1) - } else { - path = path + "-temp" - } + + path = TempPath(path) old, err := os.Open(path) if err != nil {