From 34e67e351039ee9c88365bd6504a9d388fff39de Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 20 Jan 2023 23:13:04 +0100 Subject: [PATCH 1/3] self-update: Fix handling of `--output` on windows The code always assumed that the upgrade happens in place. Thus writing the upgrade to a separate file fails, when trying to remove the file stored at that location. --- internal/selfupdate/download_windows.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/selfupdate/download_windows.go b/internal/selfupdate/download_windows.go index 4f2797385..50480eab6 100644 --- a/internal/selfupdate/download_windows.go +++ b/internal/selfupdate/download_windows.go @@ -7,11 +7,18 @@ import ( "fmt" "os" "path/filepath" + + "github.com/restic/restic/internal/errors" ) // Rename (rather than remove) the running version. The running binary will be locked // on Windows and cannot be removed while still executing. func removeResticBinary(dir, target string) error { + // nothing to do if the target does not exist + if _, err := os.Stat(target); errors.Is(err, os.ErrNotExist) { + return nil + } + backup := filepath.Join(dir, filepath.Base(target)+".bak") if _, err := os.Stat(backup); err == nil { _ = os.Remove(backup) From e16a6d4c503c47df464b56dd495ff9f1241850de Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 20 Jan 2023 23:53:20 +0100 Subject: [PATCH 2/3] self-update: add basic test for extractToFile --- internal/selfupdate/download_test.go | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 internal/selfupdate/download_test.go diff --git a/internal/selfupdate/download_test.go b/internal/selfupdate/download_test.go new file mode 100644 index 000000000..00160eef2 --- /dev/null +++ b/internal/selfupdate/download_test.go @@ -0,0 +1,44 @@ +package selfupdate + +import ( + "archive/zip" + "bytes" + "os" + "path/filepath" + "testing" + + rtest "github.com/restic/restic/internal/test" +) + +func TestExtractToFileZip(t *testing.T) { + printf := func(string, ...interface{}) {} + dir := t.TempDir() + + ext := "zip" + data := []byte("Hello World!") + + // create dummy archive + var archive bytes.Buffer + zw := zip.NewWriter(&archive) + w, err := zw.CreateHeader(&zip.FileHeader{ + Name: "example.exe", + UncompressedSize64: uint64(len(data)), + }) + rtest.OK(t, err) + _, err = w.Write(data[:]) + rtest.OK(t, err) + rtest.OK(t, zw.Close()) + + // run twice to test creating a new file and overwriting + for i := 0; i < 2; i++ { + outfn := filepath.Join(dir, ext+"-out") + rtest.OK(t, extractToFile(archive.Bytes(), "src."+ext, outfn, printf)) + + outdata, err := os.ReadFile(outfn) + rtest.OK(t, err) + rtest.Assert(t, bytes.Equal(data[:], outdata), "%v contains wrong data", outfn) + + // overwrite to test the file is properly overwritten + rtest.OK(t, os.WriteFile(outfn, []byte{1, 2, 3}, 0)) + } +} From 8aaba837196bb04938b50b7eec835dc37845508c Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sat, 21 Jan 2023 00:42:14 +0100 Subject: [PATCH 3/3] add changelog for self-upgrade bug on windows --- changelog/unreleased/pull-4163 | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 changelog/unreleased/pull-4163 diff --git a/changelog/unreleased/pull-4163 b/changelog/unreleased/pull-4163 new file mode 100644 index 000000000..16db55a82 --- /dev/null +++ b/changelog/unreleased/pull-4163 @@ -0,0 +1,12 @@ +Bugfix: Repair `self-update --output new-file.exe` on Windows + +Since restic 0.14.0 `self-update` did not work when a custom output filename +was specified via the `--output` option. This has been fixed. + +As a workaround either use an older restic version to run the self-update or +create an empty file with the output filename before updating e.g. using CMD: +`type nul > new-file.exe` +`restic self-update --output new-file.exe` + +https://github.com/restic/restic/pull/4163 +https://forum.restic.net/t/self-update-windows-started-failing-after-release-of-0-15/5836