diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 1e31ba986..bf4191f5f 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -749,7 +749,7 @@ func checkPack(ctx context.Context, r restic.Repository, id restic.ID, size int6 return errors.Errorf("Pack size does not match, want %v, got %v", size, realSize) } - blobs, err := pack.List(r.Key(), packfile, size) + blobs, _, err := pack.List(r.Key(), packfile, size) if err != nil { return err } diff --git a/internal/pack/pack.go b/internal/pack/pack.go index 2c39009b1..30ab9ea1b 100644 --- a/internal/pack/pack.go +++ b/internal/pack/pack.go @@ -252,21 +252,24 @@ func (e InvalidFileError) Error() string { return e.Message } -// List returns the list of entries found in a pack file. -func List(k *crypto.Key, rd io.ReaderAt, size int64) (entries []restic.Blob, err error) { +// List returns the list of entries found in a pack file and the length of the +// header (including header size and crypto overhead) +func List(k *crypto.Key, rd io.ReaderAt, size int64) (entries []restic.Blob, hdrSize uint32, err error) { buf, err := readHeader(rd, size) if err != nil { - return nil, err + return nil, 0, err } if len(buf) < k.NonceSize()+k.Overhead() { - return nil, errors.New("invalid header, too small") + return nil, 0, errors.New("invalid header, too small") } + hdrSize = headerLengthSize + uint32(len(buf)) + nonce, buf := buf[:k.NonceSize()], buf[k.NonceSize():] buf, err = k.Open(buf[:0], nonce, buf, nil) if err != nil { - return nil, err + return nil, 0, err } entries = make([]restic.Blob, 0, uint(len(buf))/entrySize) @@ -275,7 +278,7 @@ func List(k *crypto.Key, rd io.ReaderAt, size int64) (entries []restic.Blob, err for len(buf) > 0 { entry, err := parseHeaderEntry(buf) if err != nil { - return nil, err + return nil, 0, err } entry.Offset = pos @@ -284,7 +287,7 @@ func List(k *crypto.Key, rd io.ReaderAt, size int64) (entries []restic.Blob, err buf = buf[entrySize:] } - return entries, nil + return entries, hdrSize, nil } // PackedSizeOfBlob returns the size a blob actually uses when saved in a pack diff --git a/internal/pack/pack_test.go b/internal/pack/pack_test.go index 99755c36f..471e901c3 100644 --- a/internal/pack/pack_test.go +++ b/internal/pack/pack_test.go @@ -53,19 +53,18 @@ func verifyBlobs(t testing.TB, bufs []Buf, k *crypto.Key, rd io.ReaderAt, packSi for _, buf := range bufs { written += len(buf.data) } - // header length - written += binary.Size(uint32(0)) - // header + header crypto - headerSize := len(bufs) * (binary.Size(restic.BlobType(0)) + binary.Size(uint32(0)) + len(restic.ID{})) - written += restic.CiphertextLength(headerSize) + // header length + header + header crypto + headerSize := binary.Size(uint32(0)) + restic.CiphertextLength(len(bufs)*int(pack.EntrySize)) + written += headerSize // check length rtest.Equals(t, uint(written), packSize) // read and parse it again - entries, err := pack.List(k, rd, int64(packSize)) + entries, hdrSize, err := pack.List(k, rd, int64(packSize)) rtest.OK(t, err) rtest.Equals(t, len(entries), len(bufs)) + rtest.Equals(t, headerSize, int(hdrSize)) var buf []byte for i, b := range bufs { diff --git a/internal/repository/repack.go b/internal/repository/repack.go index 9304204e1..423f3c831 100644 --- a/internal/repository/repack.go +++ b/internal/repository/repack.go @@ -92,7 +92,7 @@ func Repack(ctx context.Context, repo restic.Repository, packs restic.IDSet, kee for job := range processQueue { tempfile, packID, packLength := job.tempfile, job.hash, job.packLength - blobs, err := pack.List(repo.Key(), tempfile, packLength) + blobs, _, err := pack.List(repo.Key(), tempfile, packLength) if err != nil { return err } diff --git a/internal/repository/repository.go b/internal/repository/repository.go index f40ce9097..ea79829c6 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -740,16 +740,11 @@ func (r *Repository) List(ctx context.Context, t restic.FileType, fn func(restic } // ListPack returns the list of blobs saved in the pack id and the length of -// the file as stored in the backend. -func (r *Repository) ListPack(ctx context.Context, id restic.ID, size int64) ([]restic.Blob, int64, error) { +// the the pack header. +func (r *Repository) ListPack(ctx context.Context, id restic.ID, size int64) ([]restic.Blob, uint32, error) { h := restic.Handle{Type: restic.PackFile, Name: id.String()} - blobs, err := pack.List(r.Key(), restic.ReaderAt(ctx, r.Backend(), h), size) - if err != nil { - return nil, 0, err - } - - return blobs, size, nil + return pack.List(r.Key(), restic.ReaderAt(ctx, r.Backend(), h), size) } // Delete calls backend.Delete() if implemented, and returns an error diff --git a/internal/restic/repository.go b/internal/restic/repository.go index 5efdfbc03..09001391a 100644 --- a/internal/restic/repository.go +++ b/internal/restic/repository.go @@ -32,7 +32,10 @@ type Repository interface { // // The function fn is called in the same Goroutine List() was called from. List(ctx context.Context, t FileType, fn func(ID, int64) error) error - ListPack(context.Context, ID, int64) ([]Blob, int64, error) + + // ListPack returns the list of blobs saved in the pack id and the length of + // the the pack header. + ListPack(context.Context, ID, int64) ([]Blob, uint32, error) Flush(context.Context) error