From 32a5c2c1f6d656d122d25517ec2a1c81437222db Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Fri, 13 Jan 2017 12:57:05 +0100 Subject: [PATCH] Add a few functions to calculate Blob buffer len --- src/restic/archiver/archive_reader_test.go | 3 +-- src/restic/buffer.go | 21 +++++++++++++++++++++ src/restic/node.go | 3 +-- src/restic/pack/pack.go | 8 ++++---- src/restic/pack/pack_test.go | 7 +++---- src/restic/repository/index.go | 9 ++++----- src/restic/repository/repository.go | 8 ++++---- src/restic/repository/repository_test.go | 7 +++---- 8 files changed, 41 insertions(+), 25 deletions(-) create mode 100644 src/restic/buffer.go diff --git a/src/restic/archiver/archive_reader_test.go b/src/restic/archiver/archive_reader_test.go index 82a432f00..c24a0be5e 100644 --- a/src/restic/archiver/archive_reader_test.go +++ b/src/restic/archiver/archive_reader_test.go @@ -5,7 +5,6 @@ import ( "io" "math/rand" "restic" - "restic/crypto" "restic/repository" "testing" ) @@ -45,7 +44,7 @@ func checkSavedFile(t *testing.T, repo restic.Repository, treeID restic.ID, name t.Fatal(err) } - buf := make([]byte, int(size), int(size)+crypto.Extension) + buf := restic.NewBlobBuffer(int(size)) n := loadBlob(t, repo, id, buf) if n != len(buf) { t.Errorf("wrong number of bytes read, want %d, got %d", len(buf), n) diff --git a/src/restic/buffer.go b/src/restic/buffer.go new file mode 100644 index 000000000..d822fced9 --- /dev/null +++ b/src/restic/buffer.go @@ -0,0 +1,21 @@ +package restic + +import "restic/crypto" + +// NewBlobBuffer returns a buffer that is large enough to hold a blob of size +// plaintext bytes, including the crypto overhead. +func NewBlobBuffer(size int) []byte { + return make([]byte, size, size+crypto.Extension) +} + +// PlaintextLength returns the plaintext length of a blob with ciphertextSize +// bytes. +func PlaintextLength(ciphertextSize int) int { + return ciphertextSize - crypto.Extension +} + +// CiphertextLength returns the encrypted length of a blob with plaintextSize +// bytes. +func CiphertextLength(plaintextSize int) int { + return plaintextSize + crypto.Extension +} diff --git a/src/restic/node.go b/src/restic/node.go index 82de2bd6a..bf41f4201 100644 --- a/src/restic/node.go +++ b/src/restic/node.go @@ -10,7 +10,6 @@ import ( "syscall" "time" - "restic/crypto" "restic/errors" "runtime" @@ -209,7 +208,7 @@ func (node Node) createFileAt(path string, repo Repository) error { buf = buf[:cap(buf)] if uint(len(buf)) < size { - buf = make([]byte, size, size+crypto.Extension) + buf = NewBlobBuffer(int(size)) } n, err := repo.LoadBlob(DataBlob, id, buf) diff --git a/src/restic/pack/pack.go b/src/restic/pack/pack.go index 17f79b09a..be4fcc087 100644 --- a/src/restic/pack/pack.go +++ b/src/restic/pack/pack.go @@ -85,15 +85,15 @@ func (p *Packer) Finalize() (uint, error) { return 0, errors.Wrap(err, "Write") } - hdrBytes := bytesHeader + crypto.Extension - if uint(n) != hdrBytes { + hdrBytes := restic.CiphertextLength(int(bytesHeader)) + if n != hdrBytes { return 0, errors.New("wrong number of bytes written") } - bytesWritten += hdrBytes + bytesWritten += uint(hdrBytes) // write length - err = binary.Write(p.wr, binary.LittleEndian, uint32(uint(len(p.blobs))*entrySize+crypto.Extension)) + err = binary.Write(p.wr, binary.LittleEndian, uint32(restic.CiphertextLength(len(p.blobs)*int(entrySize)))) if err != nil { return 0, errors.Wrap(err, "binary.Write") } diff --git a/src/restic/pack/pack_test.go b/src/restic/pack/pack_test.go index f90d1a426..c797cb1c0 100644 --- a/src/restic/pack/pack_test.go +++ b/src/restic/pack/pack_test.go @@ -54,10 +54,9 @@ func verifyBlobs(t testing.TB, bufs []Buf, k *crypto.Key, rd io.ReaderAt, packSi } // header length written += binary.Size(uint32(0)) - // header - written += len(bufs) * (binary.Size(restic.BlobType(0)) + binary.Size(uint32(0)) + len(restic.ID{})) - // header crypto - written += crypto.Extension + // header + header crypto + headerSize := len(bufs) * (binary.Size(restic.BlobType(0)) + binary.Size(uint32(0)) + len(restic.ID{})) + written += restic.CiphertextLength(headerSize) // check length Equals(t, uint(written), packSize) diff --git a/src/restic/repository/index.go b/src/restic/repository/index.go index 1ca9525d0..9aeedfb32 100644 --- a/src/restic/repository/index.go +++ b/src/restic/repository/index.go @@ -10,7 +10,6 @@ import ( "restic/errors" - "restic/crypto" "restic/debug" ) @@ -177,15 +176,15 @@ func (idx *Index) Has(id restic.ID, tpe restic.BlobType) bool { return false } -// LookupSize returns the length of the cleartext content behind the -// given id -func (idx *Index) LookupSize(id restic.ID, tpe restic.BlobType) (cleartextLength uint, err error) { +// LookupSize returns the length of the plaintext content of the blob with the +// given id. +func (idx *Index) LookupSize(id restic.ID, tpe restic.BlobType) (plaintextLength uint, err error) { blobs, err := idx.Lookup(id, tpe) if err != nil { return 0, err } - return blobs[0].Length - crypto.Extension, nil + return uint(restic.PlaintextLength(int(blobs[0].Length))), nil } // Supersedes returns the list of indexes this index supersedes, if any. diff --git a/src/restic/repository/repository.go b/src/restic/repository/repository.go index cb1e3ad69..c71c75e41 100644 --- a/src/restic/repository/repository.go +++ b/src/restic/repository/repository.go @@ -213,7 +213,7 @@ func (r *Repository) SaveJSONUnpacked(t restic.FileType, item interface{}) (rest // SaveUnpacked encrypts data and stores it in the backend. Returned is the // storage hash. func (r *Repository) SaveUnpacked(t restic.FileType, p []byte) (id restic.ID, err error) { - ciphertext := make([]byte, len(p)+crypto.Extension) + ciphertext := restic.NewBlobBuffer(len(p)) ciphertext, err = r.Encrypt(ciphertext, p) if err != nil { return restic.ID{}, err @@ -528,8 +528,8 @@ func (r *Repository) LoadBlob(t restic.BlobType, id restic.ID, buf []byte) (int, } buf = buf[:cap(buf)] - if len(buf) < int(size)+crypto.Extension { - return 0, errors.Errorf("buffer is too small for data blob (%d < %d)", len(buf), size+crypto.Extension) + if len(buf) < restic.CiphertextLength(int(size)) { + return 0, errors.Errorf("buffer is too small for data blob (%d < %d)", len(buf), restic.CiphertextLength(int(size))) } n, err := r.loadBlob(id, t, buf) @@ -563,7 +563,7 @@ func (r *Repository) LoadTree(id restic.ID) (*restic.Tree, error) { } debug.Log("size is %d, create buffer", size) - buf := make([]byte, size+crypto.Extension) + buf := restic.NewBlobBuffer(int(size)) n, err := r.loadBlob(id, restic.TreeBlob, buf) if err != nil { diff --git a/src/restic/repository/repository_test.go b/src/restic/repository/repository_test.go index b2f04ab1d..6cb1defd6 100644 --- a/src/restic/repository/repository_test.go +++ b/src/restic/repository/repository_test.go @@ -11,7 +11,6 @@ import ( "restic" "restic/archiver" - "restic/crypto" "restic/repository" . "restic/test" ) @@ -41,7 +40,7 @@ func TestSave(t *testing.T) { // OK(t, repo.SaveIndex()) // read back - buf := make([]byte, size, size+crypto.Extension) + buf := restic.NewBlobBuffer(size) n, err := repo.LoadBlob(restic.DataBlob, id, buf) OK(t, err) Equals(t, len(buf), n) @@ -75,7 +74,7 @@ func TestSaveFrom(t *testing.T) { OK(t, repo.Flush()) // read back - buf := make([]byte, size, size+crypto.Extension) + buf := restic.NewBlobBuffer(size) n, err := repo.LoadBlob(restic.DataBlob, id, buf) OK(t, err) Equals(t, len(buf), n) @@ -153,7 +152,7 @@ func BenchmarkLoadBlob(b *testing.B) { defer cleanup() length := 1000000 - buf := make([]byte, length, length+crypto.Extension) + buf := restic.NewBlobBuffer(length) _, err := io.ReadFull(rnd, buf) OK(b, err)