func packIDTester(repo *repository.Repository, inChan <-chan backend.ID, errChan chan<- error, wg *sync.WaitGroup, done <-chan struct{}) { debug.Log("Checker.testPackID", "worker start") defer debug.Log("Checker.testPackID", "worker done") defer wg.Done() for id := range inChan { ok, err := repo.Backend().Test(backend.Data, id.String()) if err != nil { err = PackError{ID: id, Err: err} } else { if !ok { err = PackError{ID: id, Err: errors.New("does not exist")} } } if err != nil { debug.Log("Checker.testPackID", "error checking for pack %s: %v", id.Str(), err) select { case <-done: return case errChan <- err: } continue } debug.Log("Checker.testPackID", "pack %s exists", id.Str()) } }
func printPacks(repo *repository.Repository, wr io.Writer) error { done := make(chan struct{}) defer close(done) f := func(job worker.Job, done <-chan struct{}) (interface{}, error) { name := job.Data.(string) h := backend.Handle{Type: backend.Data, Name: name} rd := backend.NewReadSeeker(repo.Backend(), h) unpacker, err := pack.NewUnpacker(repo.Key(), rd) if err != nil { return nil, err } return unpacker.Entries, nil } jobCh := make(chan worker.Job) resCh := make(chan worker.Job) wp := worker.New(dumpPackWorkers, f, jobCh, resCh) go func() { for name := range repo.Backend().List(backend.Data, done) { jobCh <- worker.Job{Data: name} } close(jobCh) }() for job := range resCh { name := job.Data.(string) if job.Error != nil { fmt.Fprintf(os.Stderr, "error for pack %v: %v\n", name, job.Error) continue } entries := job.Result.([]pack.Blob) p := Pack{ Name: name, Blobs: make([]Blob, len(entries)), } for i, blob := range entries { p.Blobs[i] = Blob{ Type: blob.Type, Length: blob.Length, ID: blob.ID, Offset: blob.Offset, } } prettyPrintJSON(os.Stdout, p) } wp.Wait() return nil }
// FindSnapshot takes a string and tries to find a snapshot whose ID matches // the string as closely as possible. func FindSnapshot(repo *repository.Repository, s string) (backend.ID, error) { // find snapshot id with prefix name, err := backend.Find(repo.Backend(), backend.Snapshot, s) if err != nil { return backend.ID{}, err } return backend.ParseID(name) }
func TeardownRepo(repo *repository.Repository) { if !TestCleanupTempDirs { l := repo.Backend().(*local.Local) fmt.Printf("leaving local backend at %s\n", l.Location()) return } err := repo.Delete() if err != nil { panic(err) } }
func deleteKey(repo *repository.Repository, name string) error { if name == repo.KeyName() { return errors.Fatal("refusing to remove key currently used to access repository") } err := repo.Backend().Remove(restic.KeyFile, name) if err != nil { return err } Verbosef("removed key %v\n", name) return nil }
func (cmd CmdKey) deleteKey(repo *repository.Repository, name string) error { if name == repo.KeyName() { return errors.New("refusing to remove key currently used to access repository") } err := repo.Backend().Remove(backend.Key, name) if err != nil { return err } cmd.global.Verbosef("removed key %v\n", name) return nil }
// RemoveStaleLocks deletes all locks detected as stale from the repository. func RemoveStaleLocks(repo *repository.Repository) error { return eachLock(repo, func(id backend.ID, lock *Lock, err error) error { // ignore locks that cannot be loaded if err != nil { return nil } if lock.Stale() { return repo.Backend().Remove(backend.Lock, id.String()) } return nil }) }
func (cmd CmdKey) changePassword(repo *repository.Repository) error { id, err := repository.AddKey(repo, cmd.getNewPassword(), repo.Key()) if err != nil { return fmt.Errorf("creating new key failed: %v\n", err) } err = repo.Backend().Remove(backend.Key, repo.KeyName()) if err != nil { return err } cmd.global.Verbosef("saved new key as %s\n", id) return nil }
// checkPack reads a pack and checks the integrity of all blobs. func checkPack(r *repository.Repository, id backend.ID) error { debug.Log("Checker.checkPack", "checking pack %v", id.Str()) h := backend.Handle{Type: backend.Data, Name: id.String()} buf, err := backend.LoadAll(r.Backend(), h, nil) if err != nil { return err } hash := backend.Hash(buf) if !hash.Equal(id) { debug.Log("Checker.checkPack", "Pack ID does not match, want %v, got %v", id.Str(), hash.Str()) return fmt.Errorf("Pack ID does not match, want %v, got %v", id.Str(), hash.Str()) } unpacker, err := pack.NewUnpacker(r.Key(), bytes.NewReader(buf)) if err != nil { return err } var errs []error for i, blob := range unpacker.Entries { debug.Log("Checker.checkPack", " check blob %d: %v", i, blob.ID.Str()) plainBuf := make([]byte, blob.Length) plainBuf, err = crypto.Decrypt(r.Key(), plainBuf, buf[blob.Offset:blob.Offset+blob.Length]) if err != nil { debug.Log("Checker.checkPack", " error decrypting blob %v: %v", blob.ID.Str(), err) errs = append(errs, fmt.Errorf("blob %v: %v", i, err)) continue } hash := backend.Hash(plainBuf) if !hash.Equal(blob.ID) { debug.Log("Checker.checkPack", " Blob ID does not match, want %v, got %v", blob.ID.Str(), hash.Str()) errs = append(errs, fmt.Errorf("Blob ID does not match, want %v, got %v", blob.ID.Str(), hash.Str())) continue } } if len(errs) > 0 { return fmt.Errorf("pack %v contains %v errors: %v", id.Str(), len(errs), errs) } return nil }
// loadSnapshotTreeIDs loads all snapshots from backend and returns the tree IDs. func loadSnapshotTreeIDs(repo *repository.Repository) (backend.IDs, []error) { var trees struct { IDs backend.IDs sync.Mutex } var errs struct { errs []error sync.Mutex } snapshotWorker := func(strID string, done <-chan struct{}) error { id, err := backend.ParseID(strID) if err != nil { return err } debug.Log("Checker.Snaphots", "load snapshot %v", id.Str()) treeID, err := loadTreeFromSnapshot(repo, id) if err != nil { errs.Lock() errs.errs = append(errs.errs, err) errs.Unlock() return nil } debug.Log("Checker.Snaphots", "snapshot %v has tree %v", id.Str(), treeID.Str()) trees.Lock() trees.IDs = append(trees.IDs, treeID) trees.Unlock() return nil } err := repository.FilesInParallel(repo.Backend(), backend.Snapshot, defaultParallelism, snapshotWorker) if err != nil { errs.errs = append(errs.errs, err) } return trees.IDs, errs.errs }
func changePassword(gopts GlobalOptions, repo *repository.Repository) error { pw, err := getNewPassword(gopts) if err != nil { return err } id, err := repository.AddKey(repo, pw, repo.Key()) if err != nil { return errors.Fatalf("creating new key failed: %v\n", err) } err = repo.Backend().Remove(restic.KeyFile, repo.KeyName()) if err != nil { return err } Verbosef("saved new key as %s\n", id) return nil }
// Clear removes information from the cache that isn't present in the repository any more. func (c *Cache) Clear(repo *repository.Repository) error { list, err := c.list(backend.Snapshot) if err != nil { return err } for _, entry := range list { debug.Log("Cache.Clear", "found entry %v", entry) if ok, err := repo.Backend().Test(backend.Snapshot, entry.ID.String()); !ok || err != nil { debug.Log("Cache.Clear", "snapshot %v doesn't exist any more, removing %v", entry.ID, entry) err = c.purge(backend.Snapshot, entry.Subtype, entry.ID) if err != nil { return err } } } return nil }
// RemoveAllLocks removes all locks forcefully. func RemoveAllLocks(repo *repository.Repository) error { return eachLock(repo, func(id backend.ID, lock *Lock, err error) error { return repo.Backend().Remove(backend.Lock, id.String()) }) }
func lockExists(repo *repository.Repository, t testing.TB, id backend.ID) bool { exists, err := repo.Backend().Test(backend.Lock, id.String()) OK(t, err) return exists }
func removeLock(repo *repository.Repository, id backend.ID) error { return repo.Backend().Remove(backend.Lock, id.String()) }