From c99a44b122de5ae767763ee849bf730c5b666205 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Wed, 25 Jan 2017 13:25:39 +0100 Subject: [PATCH 1/5] Fix Random() function --- src/restic/test/helpers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/restic/test/helpers.go b/src/restic/test/helpers.go index 072cc4db9..4e19000e8 100644 --- a/src/restic/test/helpers.go +++ b/src/restic/test/helpers.go @@ -79,7 +79,7 @@ func Random(seed, count int) []byte { for j := range data { cur := i + j - if len(p) >= cur { + if cur >= len(p) { break } p[cur] = data[j] From 925a3cfad7a6547d6c054a1aadbcb27a60051760 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Wed, 25 Jan 2017 17:07:36 +0100 Subject: [PATCH 2/5] backend: Check that backends do not close the reader --- src/restic/backend/test/tests.go | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/restic/backend/test/tests.go b/src/restic/backend/test/tests.go index 54583b0ce..d9241ec2b 100644 --- a/src/restic/backend/test/tests.go +++ b/src/restic/backend/test/tests.go @@ -6,8 +6,10 @@ import ( "io" "io/ioutil" "math/rand" + "os" "reflect" "restic" + "restic/errors" "sort" "strings" "testing" @@ -271,6 +273,16 @@ func TestLoad(t testing.TB) { test.OK(t, b.Remove(restic.DataFile, id.String())) } +type errorCloser struct { + io.Reader + t testing.TB +} + +func (ec errorCloser) Close() error { + ec.t.Error("forbidden method close was called") + return errors.New("forbidden method close was called") +} + // TestSave tests saving data in the backend. func TestSave(t testing.TB) { b := open(t) @@ -312,6 +324,46 @@ func TestSave(t testing.TB) { t.Fatalf("error removing item: %v", err) } } + + // test saving from a tempfile + tmpfile, err := ioutil.TempFile("", "restic-backend-save-test-") + if err != nil { + t.Fatal(err) + } + + length := rand.Intn(1<<23) + 200000 + data := test.Random(23, length) + copy(id[:], data) + + if _, err = tmpfile.Write(data); err != nil { + t.Fatal(err) + } + + if _, err = tmpfile.Seek(0, 0); err != nil { + t.Fatal(err) + } + + h := restic.Handle{Type: restic.DataFile, Name: id.String()} + + // wrap the tempfile in an errorCloser, so we can detect if the backend + // closes the reader + err = b.Save(h, errorCloser{t: t, Reader: tmpfile}) + if err != nil { + t.Fatal(err) + } + + if err = tmpfile.Close(); err != nil { + t.Fatal(err) + } + + if err = os.Remove(tmpfile.Name()); err != nil { + t.Fatal(err) + } + + err = b.Remove(h.Type, h.Name) + if err != nil { + t.Fatalf("error removing item: %v", err) + } } var filenameTests = []struct { From e8995b85b8b169e5c080905e9f95026b7a101782 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Wed, 25 Jan 2017 17:07:58 +0100 Subject: [PATCH 3/5] rest backend: Do not close the reader Closes #747 --- src/restic/backend/rest/rest.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/restic/backend/rest/rest.go b/src/restic/backend/rest/rest.go index 6ed05965f..fe931a6b9 100644 --- a/src/restic/backend/rest/rest.go +++ b/src/restic/backend/rest/rest.go @@ -80,6 +80,10 @@ func (b *restBackend) Save(h restic.Handle, rd io.Reader) (err error) { return err } + // make sure that client.Post() cannot close the reader by wrapping it in + // backend.Closer, which has a noop method. + rd = backend.Closer{Reader: rd} + <-b.connChan resp, err := b.client.Post(restPath(b.url, h), "binary/octet-stream", rd) b.connChan <- struct{}{} From dceaae33ed77ef37c9084373f53a3e7c64119fe3 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Wed, 25 Jan 2017 17:08:20 +0100 Subject: [PATCH 4/5] PackerManager: Remove unused Finalize() method --- src/restic/repository/packer_manager.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/restic/repository/packer_manager.go b/src/restic/repository/packer_manager.go index 8e9327e3e..e3f49f389 100644 --- a/src/restic/repository/packer_manager.go +++ b/src/restic/repository/packer_manager.go @@ -29,20 +29,6 @@ type Packer struct { tmpfile *os.File } -// Finalize finalizes the pack.Packer and then closes the tempfile. -func (p *Packer) Finalize() (uint, error) { - n, err := p.Packer.Finalize() - if err != nil { - return n, err - } - - if err = p.tmpfile.Close(); err != nil { - return n, err - } - - return n, nil -} - // packerManager keeps a list of open packs and creates new on demand. type packerManager struct { be Saver From 8d6fdb7a3e48aba53c02aa6dd26eb6792b1bd88f Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Wed, 25 Jan 2017 17:51:34 +0100 Subject: [PATCH 5/5] Fix packer manager test on Windows --- src/restic/repository/packer_manager_test.go | 22 +++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/restic/repository/packer_manager_test.go b/src/restic/repository/packer_manager_test.go index 465fbadcb..37718a5ea 100644 --- a/src/restic/repository/packer_manager_test.go +++ b/src/restic/repository/packer_manager_test.go @@ -47,25 +47,19 @@ func randomID(rd io.Reader) restic.ID { const maxBlobSize = 1 << 20 -func saveFile(t testing.TB, be Saver, filename string, id restic.ID) { - f, err := os.Open(filename) - if err != nil { - t.Fatal(err) - } - +func saveFile(t testing.TB, be Saver, f *os.File, id restic.ID) { h := restic.Handle{Type: restic.DataFile, Name: id.String()} t.Logf("save file %v", h) - if err = be.Save(h, f); err != nil { + if err := be.Save(h, f); err != nil { t.Fatal(err) } - if err = f.Close(); err != nil { + if err := f.Close(); err != nil { t.Fatal(err) } - err = os.Remove(filename) - if err != nil { + if err := os.Remove(f.Name()); err != nil { t.Fatal(err) } } @@ -104,8 +98,12 @@ func fillPacks(t testing.TB, rnd *randReader, be Saver, pm *packerManager, buf [ t.Fatal(err) } + if _, err = packer.tmpfile.Seek(0, 0); err != nil { + t.Fatal(err) + } + packID := restic.IDFromHash(packer.hw.Sum(nil)) - saveFile(t, be, packer.tmpfile.Name(), packID) + saveFile(t, be, packer.tmpfile, packID) } return bytes @@ -121,7 +119,7 @@ func flushRemainingPacks(t testing.TB, rnd *randReader, be Saver, pm *packerMana bytes += int(n) packID := restic.IDFromHash(packer.hw.Sum(nil)) - saveFile(t, be, packer.tmpfile.Name(), packID) + saveFile(t, be, packer.tmpfile, packID) } }