2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-26 14:56:29 +00:00

Add a few functions to calculate Blob buffer len

This commit is contained in:
Alexander Neumann 2017-01-13 12:57:05 +01:00
parent 91dcb958e0
commit 32a5c2c1f6
8 changed files with 41 additions and 25 deletions

View File

@ -5,7 +5,6 @@ import (
"io" "io"
"math/rand" "math/rand"
"restic" "restic"
"restic/crypto"
"restic/repository" "restic/repository"
"testing" "testing"
) )
@ -45,7 +44,7 @@ func checkSavedFile(t *testing.T, repo restic.Repository, treeID restic.ID, name
t.Fatal(err) t.Fatal(err)
} }
buf := make([]byte, int(size), int(size)+crypto.Extension) buf := restic.NewBlobBuffer(int(size))
n := loadBlob(t, repo, id, buf) n := loadBlob(t, repo, id, buf)
if n != len(buf) { if n != len(buf) {
t.Errorf("wrong number of bytes read, want %d, got %d", len(buf), n) t.Errorf("wrong number of bytes read, want %d, got %d", len(buf), n)

21
src/restic/buffer.go Normal file
View File

@ -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
}

View File

@ -10,7 +10,6 @@ import (
"syscall" "syscall"
"time" "time"
"restic/crypto"
"restic/errors" "restic/errors"
"runtime" "runtime"
@ -209,7 +208,7 @@ func (node Node) createFileAt(path string, repo Repository) error {
buf = buf[:cap(buf)] buf = buf[:cap(buf)]
if uint(len(buf)) < size { if uint(len(buf)) < size {
buf = make([]byte, size, size+crypto.Extension) buf = NewBlobBuffer(int(size))
} }
n, err := repo.LoadBlob(DataBlob, id, buf) n, err := repo.LoadBlob(DataBlob, id, buf)

View File

@ -85,15 +85,15 @@ func (p *Packer) Finalize() (uint, error) {
return 0, errors.Wrap(err, "Write") return 0, errors.Wrap(err, "Write")
} }
hdrBytes := bytesHeader + crypto.Extension hdrBytes := restic.CiphertextLength(int(bytesHeader))
if uint(n) != hdrBytes { if n != hdrBytes {
return 0, errors.New("wrong number of bytes written") return 0, errors.New("wrong number of bytes written")
} }
bytesWritten += hdrBytes bytesWritten += uint(hdrBytes)
// write length // 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 { if err != nil {
return 0, errors.Wrap(err, "binary.Write") return 0, errors.Wrap(err, "binary.Write")
} }

View File

@ -54,10 +54,9 @@ func verifyBlobs(t testing.TB, bufs []Buf, k *crypto.Key, rd io.ReaderAt, packSi
} }
// header length // header length
written += binary.Size(uint32(0)) written += binary.Size(uint32(0))
// header // header + header crypto
written += len(bufs) * (binary.Size(restic.BlobType(0)) + binary.Size(uint32(0)) + len(restic.ID{})) headerSize := len(bufs) * (binary.Size(restic.BlobType(0)) + binary.Size(uint32(0)) + len(restic.ID{}))
// header crypto written += restic.CiphertextLength(headerSize)
written += crypto.Extension
// check length // check length
Equals(t, uint(written), packSize) Equals(t, uint(written), packSize)

View File

@ -10,7 +10,6 @@ import (
"restic/errors" "restic/errors"
"restic/crypto"
"restic/debug" "restic/debug"
) )
@ -177,15 +176,15 @@ func (idx *Index) Has(id restic.ID, tpe restic.BlobType) bool {
return false return false
} }
// LookupSize returns the length of the cleartext content behind the // LookupSize returns the length of the plaintext content of the blob with the
// given id // given id.
func (idx *Index) LookupSize(id restic.ID, tpe restic.BlobType) (cleartextLength uint, err error) { func (idx *Index) LookupSize(id restic.ID, tpe restic.BlobType) (plaintextLength uint, err error) {
blobs, err := idx.Lookup(id, tpe) blobs, err := idx.Lookup(id, tpe)
if err != nil { if err != nil {
return 0, err 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. // Supersedes returns the list of indexes this index supersedes, if any.

View File

@ -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 // SaveUnpacked encrypts data and stores it in the backend. Returned is the
// storage hash. // storage hash.
func (r *Repository) SaveUnpacked(t restic.FileType, p []byte) (id restic.ID, err error) { 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) ciphertext, err = r.Encrypt(ciphertext, p)
if err != nil { if err != nil {
return restic.ID{}, err 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)] buf = buf[:cap(buf)]
if len(buf) < int(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), size+crypto.Extension) 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) 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) 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) n, err := r.loadBlob(id, restic.TreeBlob, buf)
if err != nil { if err != nil {

View File

@ -11,7 +11,6 @@ import (
"restic" "restic"
"restic/archiver" "restic/archiver"
"restic/crypto"
"restic/repository" "restic/repository"
. "restic/test" . "restic/test"
) )
@ -41,7 +40,7 @@ func TestSave(t *testing.T) {
// OK(t, repo.SaveIndex()) // OK(t, repo.SaveIndex())
// read back // read back
buf := make([]byte, size, size+crypto.Extension) buf := restic.NewBlobBuffer(size)
n, err := repo.LoadBlob(restic.DataBlob, id, buf) n, err := repo.LoadBlob(restic.DataBlob, id, buf)
OK(t, err) OK(t, err)
Equals(t, len(buf), n) Equals(t, len(buf), n)
@ -75,7 +74,7 @@ func TestSaveFrom(t *testing.T) {
OK(t, repo.Flush()) OK(t, repo.Flush())
// read back // read back
buf := make([]byte, size, size+crypto.Extension) buf := restic.NewBlobBuffer(size)
n, err := repo.LoadBlob(restic.DataBlob, id, buf) n, err := repo.LoadBlob(restic.DataBlob, id, buf)
OK(t, err) OK(t, err)
Equals(t, len(buf), n) Equals(t, len(buf), n)
@ -153,7 +152,7 @@ func BenchmarkLoadBlob(b *testing.B) {
defer cleanup() defer cleanup()
length := 1000000 length := 1000000
buf := make([]byte, length, length+crypto.Extension) buf := restic.NewBlobBuffer(length)
_, err := io.ReadFull(rnd, buf) _, err := io.ReadFull(rnd, buf)
OK(b, err) OK(b, err)