mirror of
https://github.com/restic/restic.git
synced 2025-12-11 18:47:50 +00:00
debug: convert to termstatus
This commit is contained in:
@@ -27,6 +27,8 @@ import (
|
|||||||
"github.com/restic/restic/internal/repository/index"
|
"github.com/restic/restic/internal/repository/index"
|
||||||
"github.com/restic/restic/internal/repository/pack"
|
"github.com/restic/restic/internal/repository/pack"
|
||||||
"github.com/restic/restic/internal/restic"
|
"github.com/restic/restic/internal/restic"
|
||||||
|
"github.com/restic/restic/internal/ui/progress"
|
||||||
|
"github.com/restic/restic/internal/ui/termstatus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func registerDebugCommand(cmd *cobra.Command) {
|
func registerDebugCommand(cmd *cobra.Command) {
|
||||||
@@ -66,7 +68,9 @@ Exit status is 12 if the password is incorrect.
|
|||||||
`,
|
`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runDebugDump(cmd.Context(), globalOptions, args)
|
term, cancel := setupTermstatus()
|
||||||
|
defer cancel()
|
||||||
|
return runDebugDump(cmd.Context(), globalOptions, args, term)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return cmd
|
return cmd
|
||||||
@@ -80,7 +84,9 @@ func newDebugExamineCommand() *cobra.Command {
|
|||||||
Short: "Examine a pack file",
|
Short: "Examine a pack file",
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runDebugExamine(cmd.Context(), globalOptions, opts, args)
|
term, cancel := setupTermstatus()
|
||||||
|
defer cancel()
|
||||||
|
return runDebugExamine(cmd.Context(), globalOptions, opts, args, term)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,13 +147,13 @@ type Blob struct {
|
|||||||
Offset uint `json:"offset"`
|
Offset uint `json:"offset"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func printPacks(ctx context.Context, repo *repository.Repository, wr io.Writer) error {
|
func printPacks(ctx context.Context, repo *repository.Repository, wr io.Writer, printer progress.Printer) error {
|
||||||
|
|
||||||
var m sync.Mutex
|
var m sync.Mutex
|
||||||
return restic.ParallelList(ctx, repo, restic.PackFile, repo.Connections(), func(ctx context.Context, id restic.ID, size int64) error {
|
return restic.ParallelList(ctx, repo, restic.PackFile, repo.Connections(), func(ctx context.Context, id restic.ID, size int64) error {
|
||||||
blobs, _, err := repo.ListPack(ctx, id, size)
|
blobs, _, err := repo.ListPack(ctx, id, size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Warnf("error for pack %v: %v\n", id.Str(), err)
|
printer.E("error for pack %v: %v", id.Str(), err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,9 +176,9 @@ func printPacks(ctx context.Context, repo *repository.Repository, wr io.Writer)
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpIndexes(ctx context.Context, repo restic.ListerLoaderUnpacked, wr io.Writer) error {
|
func dumpIndexes(ctx context.Context, repo restic.ListerLoaderUnpacked, wr io.Writer, printer progress.Printer) error {
|
||||||
return index.ForAllIndexes(ctx, repo, repo, func(id restic.ID, idx *index.Index, err error) error {
|
return index.ForAllIndexes(ctx, repo, repo, func(id restic.ID, idx *index.Index, err error) error {
|
||||||
Printf("index_id: %v\n", id)
|
printer.S("index_id: %v", id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -181,7 +187,9 @@ func dumpIndexes(ctx context.Context, repo restic.ListerLoaderUnpacked, wr io.Wr
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDebugDump(ctx context.Context, gopts GlobalOptions, args []string) error {
|
func runDebugDump(ctx context.Context, gopts GlobalOptions, args []string, term *termstatus.Terminal) error {
|
||||||
|
printer := newTerminalProgressPrinter(gopts.JSON, gopts.verbosity, term)
|
||||||
|
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return errors.Fatal("type not specified")
|
return errors.Fatal("type not specified")
|
||||||
}
|
}
|
||||||
@@ -196,20 +204,20 @@ func runDebugDump(ctx context.Context, gopts GlobalOptions, args []string) error
|
|||||||
|
|
||||||
switch tpe {
|
switch tpe {
|
||||||
case "indexes":
|
case "indexes":
|
||||||
return dumpIndexes(ctx, repo, globalOptions.stdout)
|
return dumpIndexes(ctx, repo, globalOptions.stdout, printer)
|
||||||
case "snapshots":
|
case "snapshots":
|
||||||
return debugPrintSnapshots(ctx, repo, globalOptions.stdout)
|
return debugPrintSnapshots(ctx, repo, globalOptions.stdout)
|
||||||
case "packs":
|
case "packs":
|
||||||
return printPacks(ctx, repo, globalOptions.stdout)
|
return printPacks(ctx, repo, globalOptions.stdout, printer)
|
||||||
case "all":
|
case "all":
|
||||||
Printf("snapshots:\n")
|
printer.S("snapshots:")
|
||||||
err := debugPrintSnapshots(ctx, repo, globalOptions.stdout)
|
err := debugPrintSnapshots(ctx, repo, globalOptions.stdout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
Printf("\nindexes:\n")
|
printer.S("indexes:")
|
||||||
err = dumpIndexes(ctx, repo, globalOptions.stdout)
|
err = dumpIndexes(ctx, repo, globalOptions.stdout, printer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -220,11 +228,11 @@ func runDebugDump(ctx context.Context, gopts GlobalOptions, args []string) error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryRepairWithBitflip(key *crypto.Key, input []byte, bytewise bool) []byte {
|
func tryRepairWithBitflip(key *crypto.Key, input []byte, bytewise bool, printer progress.Printer) []byte {
|
||||||
if bytewise {
|
if bytewise {
|
||||||
Printf(" trying to repair blob by finding a broken byte\n")
|
printer.S(" trying to repair blob by finding a broken byte")
|
||||||
} else {
|
} else {
|
||||||
Printf(" trying to repair blob with single bit flip\n")
|
printer.S(" trying to repair blob with single bit flip")
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := make(chan int)
|
ch := make(chan int)
|
||||||
@@ -234,7 +242,7 @@ func tryRepairWithBitflip(key *crypto.Key, input []byte, bytewise bool) []byte {
|
|||||||
var found bool
|
var found bool
|
||||||
|
|
||||||
workers := runtime.GOMAXPROCS(0)
|
workers := runtime.GOMAXPROCS(0)
|
||||||
Printf(" spinning up %d worker functions\n", runtime.GOMAXPROCS(0))
|
printer.S(" spinning up %d worker functions", runtime.GOMAXPROCS(0))
|
||||||
for i := 0; i < workers; i++ {
|
for i := 0; i < workers; i++ {
|
||||||
wg.Go(func() error {
|
wg.Go(func() error {
|
||||||
// make a local copy of the buffer
|
// make a local copy of the buffer
|
||||||
@@ -248,9 +256,9 @@ func tryRepairWithBitflip(key *crypto.Key, input []byte, bytewise bool) []byte {
|
|||||||
nonce, plaintext := buf[:key.NonceSize()], buf[key.NonceSize():]
|
nonce, plaintext := buf[:key.NonceSize()], buf[key.NonceSize():]
|
||||||
plaintext, err := key.Open(plaintext[:0], nonce, plaintext, nil)
|
plaintext, err := key.Open(plaintext[:0], nonce, plaintext, nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
Printf("\n")
|
printer.S("")
|
||||||
Printf(" blob could be repaired by XORing byte %v with 0x%02x\n", idx, pattern)
|
printer.S(" blob could be repaired by XORing byte %v with 0x%02x", idx, pattern)
|
||||||
Printf(" hash is %v\n", restic.Hash(plaintext))
|
printer.S(" hash is %v", restic.Hash(plaintext))
|
||||||
close(done)
|
close(done)
|
||||||
found = true
|
found = true
|
||||||
fixed = plaintext
|
fixed = plaintext
|
||||||
@@ -291,7 +299,7 @@ func tryRepairWithBitflip(key *crypto.Key, input []byte, bytewise bool) []byte {
|
|||||||
select {
|
select {
|
||||||
case ch <- i:
|
case ch <- i:
|
||||||
case <-done:
|
case <-done:
|
||||||
Printf(" done after %v\n", time.Since(start))
|
printer.S(" done after %v", time.Since(start))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +309,7 @@ func tryRepairWithBitflip(key *crypto.Key, input []byte, bytewise bool) []byte {
|
|||||||
remaining := len(input) - i
|
remaining := len(input) - i
|
||||||
eta := time.Duration(float64(remaining)/gps) * time.Second
|
eta := time.Duration(float64(remaining)/gps) * time.Second
|
||||||
|
|
||||||
Printf("\r%d byte of %d done (%.2f%%), %.0f byte per second, ETA %v",
|
printer.S("\r%d byte of %d done (%.2f%%), %.0f byte per second, ETA %v",
|
||||||
i, len(input), float32(i)/float32(len(input))*100, gps, eta)
|
i, len(input), float32(i)/float32(len(input))*100, gps, eta)
|
||||||
info = time.Now()
|
info = time.Now()
|
||||||
}
|
}
|
||||||
@@ -314,7 +322,7 @@ func tryRepairWithBitflip(key *crypto.Key, input []byte, bytewise bool) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
Printf("\n blob could not be repaired\n")
|
printer.S("\n blob could not be repaired")
|
||||||
}
|
}
|
||||||
return fixed
|
return fixed
|
||||||
}
|
}
|
||||||
@@ -335,7 +343,7 @@ func decryptUnsigned(k *crypto.Key, buf []byte) []byte {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadBlobs(ctx context.Context, opts DebugExamineOptions, repo restic.Repository, packID restic.ID, list []restic.Blob) error {
|
func loadBlobs(ctx context.Context, opts DebugExamineOptions, repo restic.Repository, packID restic.ID, list []restic.Blob, printer progress.Printer) error {
|
||||||
dec, err := zstd.NewReader(nil)
|
dec, err := zstd.NewReader(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -355,9 +363,9 @@ func loadBlobs(ctx context.Context, opts DebugExamineOptions, repo restic.Reposi
|
|||||||
|
|
||||||
wg.Go(func() error {
|
wg.Go(func() error {
|
||||||
for _, blob := range list {
|
for _, blob := range list {
|
||||||
Printf(" loading blob %v at %v (length %v)\n", blob.ID, blob.Offset, blob.Length)
|
printer.S(" loading blob %v at %v (length %v)", blob.ID, blob.Offset, blob.Length)
|
||||||
if int(blob.Offset+blob.Length) > len(pack) {
|
if int(blob.Offset+blob.Length) > len(pack) {
|
||||||
Warnf("skipping truncated blob\n")
|
printer.E("skipping truncated blob")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
buf := pack[blob.Offset : blob.Offset+blob.Length]
|
buf := pack[blob.Offset : blob.Offset+blob.Length]
|
||||||
@@ -368,16 +376,16 @@ func loadBlobs(ctx context.Context, opts DebugExamineOptions, repo restic.Reposi
|
|||||||
outputPrefix := ""
|
outputPrefix := ""
|
||||||
filePrefix := ""
|
filePrefix := ""
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Warnf("error decrypting blob: %v\n", err)
|
printer.E("error decrypting blob: %v", err)
|
||||||
if opts.TryRepair || opts.RepairByte {
|
if opts.TryRepair || opts.RepairByte {
|
||||||
plaintext = tryRepairWithBitflip(key, buf, opts.RepairByte)
|
plaintext = tryRepairWithBitflip(key, buf, opts.RepairByte, printer)
|
||||||
}
|
}
|
||||||
if plaintext != nil {
|
if plaintext != nil {
|
||||||
outputPrefix = "repaired "
|
outputPrefix = "repaired "
|
||||||
filePrefix = "repaired-"
|
filePrefix = "repaired-"
|
||||||
} else {
|
} else {
|
||||||
plaintext = decryptUnsigned(key, buf)
|
plaintext = decryptUnsigned(key, buf)
|
||||||
err = storePlainBlob(blob.ID, "damaged-", plaintext)
|
err = storePlainBlob(blob.ID, "damaged-", plaintext, printer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -388,7 +396,7 @@ func loadBlobs(ctx context.Context, opts DebugExamineOptions, repo restic.Reposi
|
|||||||
if blob.IsCompressed() {
|
if blob.IsCompressed() {
|
||||||
decompressed, err := dec.DecodeAll(plaintext, nil)
|
decompressed, err := dec.DecodeAll(plaintext, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Printf(" failed to decompress blob %v\n", blob.ID)
|
printer.S(" failed to decompress blob %v", blob.ID)
|
||||||
}
|
}
|
||||||
if decompressed != nil {
|
if decompressed != nil {
|
||||||
plaintext = decompressed
|
plaintext = decompressed
|
||||||
@@ -398,14 +406,14 @@ func loadBlobs(ctx context.Context, opts DebugExamineOptions, repo restic.Reposi
|
|||||||
id := restic.Hash(plaintext)
|
id := restic.Hash(plaintext)
|
||||||
var prefix string
|
var prefix string
|
||||||
if !id.Equal(blob.ID) {
|
if !id.Equal(blob.ID) {
|
||||||
Printf(" successfully %vdecrypted blob (length %v), hash is %v, ID does not match, wanted %v\n", outputPrefix, len(plaintext), id, blob.ID)
|
printer.S(" successfully %vdecrypted blob (length %v), hash is %v, ID does not match, wanted %v", outputPrefix, len(plaintext), id, blob.ID)
|
||||||
prefix = "wrong-hash-"
|
prefix = "wrong-hash-"
|
||||||
} else {
|
} else {
|
||||||
Printf(" successfully %vdecrypted blob (length %v), hash is %v, ID matches\n", outputPrefix, len(plaintext), id)
|
printer.S(" successfully %vdecrypted blob (length %v), hash is %v, ID matches", outputPrefix, len(plaintext), id)
|
||||||
prefix = "correct-"
|
prefix = "correct-"
|
||||||
}
|
}
|
||||||
if opts.ExtractPack {
|
if opts.ExtractPack {
|
||||||
err = storePlainBlob(id, filePrefix+prefix, plaintext)
|
err = storePlainBlob(id, filePrefix+prefix, plaintext, printer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -415,7 +423,7 @@ func loadBlobs(ctx context.Context, opts DebugExamineOptions, repo restic.Reposi
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
Printf(" uploaded %v %v\n", blob.Type, id)
|
printer.S(" uploaded %v %v", blob.Type, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,7 +436,7 @@ func loadBlobs(ctx context.Context, opts DebugExamineOptions, repo restic.Reposi
|
|||||||
return wg.Wait()
|
return wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func storePlainBlob(id restic.ID, prefix string, plain []byte) error {
|
func storePlainBlob(id restic.ID, prefix string, plain []byte, printer progress.Printer) error {
|
||||||
filename := fmt.Sprintf("%s%s.bin", prefix, id)
|
filename := fmt.Sprintf("%s%s.bin", prefix, id)
|
||||||
f, err := os.Create(filename)
|
f, err := os.Create(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -446,11 +454,13 @@ func storePlainBlob(id restic.ID, prefix string, plain []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
Printf("decrypt of blob %v stored at %v\n", id, filename)
|
printer.S("decrypt of blob %v stored at %v", id, filename)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDebugExamine(ctx context.Context, gopts GlobalOptions, opts DebugExamineOptions, args []string) error {
|
func runDebugExamine(ctx context.Context, gopts GlobalOptions, opts DebugExamineOptions, args []string, term *termstatus.Terminal) error {
|
||||||
|
printer := newTerminalProgressPrinter(gopts.JSON, gopts.verbosity, term)
|
||||||
|
|
||||||
if opts.ExtractPack && gopts.NoLock {
|
if opts.ExtractPack && gopts.NoLock {
|
||||||
return fmt.Errorf("--extract-pack and --no-lock are mutually exclusive")
|
return fmt.Errorf("--extract-pack and --no-lock are mutually exclusive")
|
||||||
}
|
}
|
||||||
@@ -467,7 +477,7 @@ func runDebugExamine(ctx context.Context, gopts GlobalOptions, opts DebugExamine
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
id, err = restic.Find(ctx, repo, restic.PackFile, name)
|
id, err = restic.Find(ctx, repo, restic.PackFile, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Warnf("error: %v\n", err)
|
printer.E("error: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -478,16 +488,16 @@ func runDebugExamine(ctx context.Context, gopts GlobalOptions, opts DebugExamine
|
|||||||
return errors.Fatal("no pack files to examine")
|
return errors.Fatal("no pack files to examine")
|
||||||
}
|
}
|
||||||
|
|
||||||
bar := newIndexProgress(gopts.Quiet, gopts.JSON)
|
bar := newIndexTerminalProgress(printer)
|
||||||
err = repo.LoadIndex(ctx, bar)
|
err = repo.LoadIndex(ctx, bar)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, id := range ids {
|
for _, id := range ids {
|
||||||
err := examinePack(ctx, opts, repo, id)
|
err := examinePack(ctx, opts, repo, id, printer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Warnf("error: %v\n", err)
|
printer.E("error: %v", err)
|
||||||
}
|
}
|
||||||
if err == context.Canceled {
|
if err == context.Canceled {
|
||||||
break
|
break
|
||||||
@@ -496,24 +506,24 @@ func runDebugExamine(ctx context.Context, gopts GlobalOptions, opts DebugExamine
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func examinePack(ctx context.Context, opts DebugExamineOptions, repo restic.Repository, id restic.ID) error {
|
func examinePack(ctx context.Context, opts DebugExamineOptions, repo restic.Repository, id restic.ID, printer progress.Printer) error {
|
||||||
Printf("examine %v\n", id)
|
printer.S("examine %v", id)
|
||||||
|
|
||||||
buf, err := repo.LoadRaw(ctx, restic.PackFile, id)
|
buf, err := repo.LoadRaw(ctx, restic.PackFile, id)
|
||||||
// also process damaged pack files
|
// also process damaged pack files
|
||||||
if buf == nil {
|
if buf == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
Printf(" file size is %v\n", len(buf))
|
printer.S(" file size is %v", len(buf))
|
||||||
gotID := restic.Hash(buf)
|
gotID := restic.Hash(buf)
|
||||||
if !id.Equal(gotID) {
|
if !id.Equal(gotID) {
|
||||||
Printf(" wanted hash %v, got %v\n", id, gotID)
|
printer.S(" wanted hash %v, got %v", id, gotID)
|
||||||
} else {
|
} else {
|
||||||
Printf(" hash for file content matches\n")
|
printer.S(" hash for file content matches")
|
||||||
}
|
}
|
||||||
|
|
||||||
Printf(" ========================================\n")
|
printer.S(" ========================================")
|
||||||
Printf(" looking for info in the indexes\n")
|
printer.S(" looking for info in the indexes")
|
||||||
|
|
||||||
blobsLoaded := false
|
blobsLoaded := false
|
||||||
// examine all data the indexes have for the pack file
|
// examine all data the indexes have for the pack file
|
||||||
@@ -523,32 +533,32 @@ func examinePack(ctx context.Context, opts DebugExamineOptions, repo restic.Repo
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
checkPackSize(blobs, len(buf))
|
checkPackSize(blobs, len(buf), printer)
|
||||||
|
|
||||||
err = loadBlobs(ctx, opts, repo, id, blobs)
|
err = loadBlobs(ctx, opts, repo, id, blobs, printer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Warnf("error: %v\n", err)
|
printer.E("error: %v", err)
|
||||||
} else {
|
} else {
|
||||||
blobsLoaded = true
|
blobsLoaded = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Printf(" ========================================\n")
|
printer.S(" ========================================")
|
||||||
Printf(" inspect the pack itself\n")
|
printer.S(" inspect the pack itself")
|
||||||
|
|
||||||
blobs, _, err := repo.ListPack(ctx, id, int64(len(buf)))
|
blobs, _, err := repo.ListPack(ctx, id, int64(len(buf)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("pack %v: %v", id.Str(), err)
|
return fmt.Errorf("pack %v: %v", id.Str(), err)
|
||||||
}
|
}
|
||||||
checkPackSize(blobs, len(buf))
|
checkPackSize(blobs, len(buf), printer)
|
||||||
|
|
||||||
if !blobsLoaded {
|
if !blobsLoaded {
|
||||||
return loadBlobs(ctx, opts, repo, id, blobs)
|
return loadBlobs(ctx, opts, repo, id, blobs, printer)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPackSize(blobs []restic.Blob, fileSize int) {
|
func checkPackSize(blobs []restic.Blob, fileSize int, printer progress.Printer) {
|
||||||
// track current size and offset
|
// track current size and offset
|
||||||
var size, offset uint64
|
var size, offset uint64
|
||||||
|
|
||||||
@@ -557,9 +567,9 @@ func checkPackSize(blobs []restic.Blob, fileSize int) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
for _, pb := range blobs {
|
for _, pb := range blobs {
|
||||||
Printf(" %v blob %v, offset %-6d, raw length %-6d\n", pb.Type, pb.ID, pb.Offset, pb.Length)
|
printer.S(" %v blob %v, offset %-6d, raw length %-6d", pb.Type, pb.ID, pb.Offset, pb.Length)
|
||||||
if offset != uint64(pb.Offset) {
|
if offset != uint64(pb.Offset) {
|
||||||
Printf(" hole in file, want offset %v, got %v\n", offset, pb.Offset)
|
printer.S(" hole in file, want offset %v, got %v", offset, pb.Offset)
|
||||||
}
|
}
|
||||||
offset = uint64(pb.Offset + pb.Length)
|
offset = uint64(pb.Offset + pb.Length)
|
||||||
size += uint64(pb.Length)
|
size += uint64(pb.Length)
|
||||||
@@ -567,8 +577,8 @@ func checkPackSize(blobs []restic.Blob, fileSize int) {
|
|||||||
size += uint64(pack.CalculateHeaderSize(blobs))
|
size += uint64(pack.CalculateHeaderSize(blobs))
|
||||||
|
|
||||||
if uint64(fileSize) != size {
|
if uint64(fileSize) != size {
|
||||||
Printf(" file sizes do not match: computed %v, file size is %v\n", size, fileSize)
|
printer.S(" file sizes do not match: computed %v, file size is %v", size, fileSize)
|
||||||
} else {
|
} else {
|
||||||
Printf(" file sizes match\n")
|
printer.S(" file sizes match")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user