folder_recvenc.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Copyright (C) 2018 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package model
  7. import (
  8. "fmt"
  9. "sort"
  10. "github.com/syncthing/syncthing/lib/config"
  11. "github.com/syncthing/syncthing/lib/db"
  12. "github.com/syncthing/syncthing/lib/events"
  13. "github.com/syncthing/syncthing/lib/fs"
  14. "github.com/syncthing/syncthing/lib/ignore"
  15. "github.com/syncthing/syncthing/lib/protocol"
  16. "github.com/syncthing/syncthing/lib/versioner"
  17. )
  18. func init() {
  19. folderFactories[config.FolderTypeReceiveEncrypted] = newReceiveEncryptedFolder
  20. }
  21. type receiveEncryptedFolder struct {
  22. *sendReceiveFolder
  23. }
  24. func newReceiveEncryptedFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, fs fs.Filesystem, evLogger events.Logger, ioLimiter *byteSemaphore) service {
  25. return &receiveEncryptedFolder{newSendReceiveFolder(model, fset, ignores, cfg, ver, fs, evLogger, ioLimiter).(*sendReceiveFolder)}
  26. }
  27. func (f *receiveEncryptedFolder) Revert() {
  28. f.doInSync(func() error { f.revert(); return nil })
  29. }
  30. func (f *receiveEncryptedFolder) revert() {
  31. l.Infof("Reverting unexpected items in folder %v (receive-encrypted)", f.Description())
  32. f.setState(FolderScanning)
  33. defer f.setState(FolderIdle)
  34. batch := newFileInfoBatch(func(fs []protocol.FileInfo) error {
  35. f.updateLocalsFromScanning(fs)
  36. return nil
  37. })
  38. snap := f.fset.Snapshot()
  39. defer snap.Release()
  40. var iterErr error
  41. var dirs []string
  42. snap.WithHaveTruncated(protocol.LocalDeviceID, func(intf protocol.FileIntf) bool {
  43. if iterErr = batch.flushIfFull(); iterErr != nil {
  44. return false
  45. }
  46. fit := intf.(db.FileInfoTruncated)
  47. if !fit.IsReceiveOnlyChanged() || intf.IsDeleted() {
  48. return true
  49. }
  50. if fit.IsDirectory() {
  51. dirs = append(dirs, fit.Name)
  52. return true
  53. }
  54. if err := f.inWritableDir(f.fs.Remove, fit.Name); err != nil && !fs.IsNotExist(err) {
  55. f.newScanError(fit.Name, fmt.Errorf("deleting unexpected item: %w", err))
  56. }
  57. fi := fit.ConvertToDeletedFileInfo(f.shortID)
  58. // Set version to zero, such that we pull the global version in case
  59. // this is a valid filename that was erroneously changed locally.
  60. // Should already be zero from scanning, but lets be safe.
  61. fi.Version = protocol.Vector{}
  62. // Purposely not removing FlagLocalReceiveOnly as the deleted
  63. // item should still not be sent in index updates. However being
  64. // deleted, it will not show up as an unexpected file in the UI
  65. // anymore.
  66. batch.append(fi)
  67. return true
  68. })
  69. f.revertHandleDirs(dirs, snap)
  70. if iterErr == nil {
  71. iterErr = batch.flush()
  72. }
  73. if iterErr != nil {
  74. l.Infoln("Failed to delete unexpected items:", iterErr)
  75. }
  76. }
  77. func (f *receiveEncryptedFolder) revertHandleDirs(dirs []string, snap *db.Snapshot) {
  78. if len(dirs) == 0 {
  79. return
  80. }
  81. scanChan := make(chan string)
  82. go f.pullScannerRoutine(scanChan)
  83. defer close(scanChan)
  84. sort.Sort(sort.Reverse(sort.StringSlice(dirs)))
  85. for _, dir := range dirs {
  86. if err := f.deleteDirOnDisk(dir, snap, scanChan); err != nil {
  87. f.newScanError(dir, fmt.Errorf("deleting unexpected dir: %w", err))
  88. }
  89. }
  90. }