diff --git a/internal/model/model.go b/internal/model/model.go index d6b589425..e99db243f 100644 --- a/internal/model/model.go +++ b/internal/model/model.go @@ -1065,6 +1065,7 @@ func (m *Model) ScanFolderSub(folder, sub string) error { Matcher: ignores, BlockSize: protocol.BlockSize, TempNamer: defTempNamer, + TempLifetime: time.Duration(m.cfg.Options().KeepTemporariesH) * time.Hour, CurrentFiler: cFiler{m, folder}, IgnorePerms: m.folderCfgs[folder].IgnorePerms, } diff --git a/internal/model/puller.go b/internal/model/puller.go index 968db7a76..6d3f7405f 100644 --- a/internal/model/puller.go +++ b/internal/model/puller.go @@ -91,21 +91,16 @@ func (p *Puller) Serve() { pullTimer := time.NewTimer(checkPullIntv) scanTimer := time.NewTimer(time.Millisecond) // The first scan should be done immediately. - cleanTimer := time.NewTicker(time.Hour) defer func() { pullTimer.Stop() scanTimer.Stop() - cleanTimer.Stop() // TODO: Should there be an actual FolderStopped state? p.model.setState(p.folder, FolderIdle) }() var prevVer uint64 - // Clean out old temporaries before we start pulling - p.clean() - // We don't start pulling files until a scan has been completed. initialScanCompleted := false @@ -222,10 +217,6 @@ loop: l.Infoln("Completed initial scan (rw) of folder", p.folder) initialScanCompleted = true } - - // Clean out old temporaries - case <-cleanTimer.C: - p.clean() } } } @@ -846,23 +837,6 @@ func (p *Puller) finisherRoutine(in <-chan *sharedPullerState) { } } -// clean deletes orphaned temporary files -func (p *Puller) clean() { - keep := time.Duration(p.model.cfg.Options().KeepTemporariesH) * time.Hour - now := time.Now() - filepath.Walk(p.dir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - if info.Mode().IsRegular() && defTempNamer.IsTemporary(path) && info.ModTime().Add(keep).Before(now) { - os.Remove(path) - } - - return nil - }) -} - func invalidateFolder(cfg *config.Configuration, folderID string, err error) { for i := range cfg.Folders { folder := &cfg.Folders[i] diff --git a/internal/model/puller_test.go b/internal/model/puller_test.go index 2481f8873..50408f1b6 100644 --- a/internal/model/puller_test.go +++ b/internal/model/puller_test.go @@ -19,6 +19,7 @@ import ( "os" "path/filepath" "testing" + "time" "github.com/syncthing/syncthing/internal/config" "github.com/syncthing/syncthing/internal/protocol" @@ -28,6 +29,16 @@ import ( "github.com/syndtr/goleveldb/leveldb/storage" ) +func init() { + // We do this to make sure that the temp file required for the tests does + // not get removed during the tests. + future := time.Now().Add(time.Hour) + err := os.Chtimes(filepath.Join("testdata", defTempNamer.TempName("file")), future, future) + if err != nil { + panic(err) + } +} + var blocks = []protocol.BlockInfo{ {Hash: []uint8{0xfa, 0x43, 0x23, 0x9b, 0xce, 0xe7, 0xb9, 0x7c, 0xa6, 0x2f, 0x0, 0x7c, 0xc6, 0x84, 0x87, 0x56, 0xa, 0x39, 0xe1, 0x9f, 0x74, 0xf3, 0xdd, 0xe7, 0x48, 0x6d, 0xb3, 0xf9, 0x8d, 0xf8, 0xe4, 0x71}}, // Zero'ed out block {Offset: 0, Size: 0x20000, Hash: []uint8{0x7e, 0xad, 0xbc, 0x36, 0xae, 0xbb, 0xcf, 0x74, 0x43, 0xe2, 0x7a, 0x5a, 0x4b, 0xb8, 0x5b, 0xce, 0xe6, 0x9e, 0x1e, 0x10, 0xf9, 0x8a, 0xbc, 0x77, 0x95, 0x2, 0x29, 0x60, 0x9e, 0x96, 0xae, 0x6c}}, diff --git a/internal/scanner/walk.go b/internal/scanner/walk.go index d0a1d4819..c19f5489f 100644 --- a/internal/scanner/walk.go +++ b/internal/scanner/walk.go @@ -21,6 +21,7 @@ import ( "path/filepath" "runtime" "strings" + "time" "github.com/syncthing/syncthing/internal/ignore" "github.com/syncthing/syncthing/internal/lamport" @@ -40,6 +41,8 @@ type Walker struct { Matcher *ignore.Matcher // If TempNamer is not nil, it is used to ignore tempory files when walking. TempNamer TempNamer + // Number of hours to keep temporary files for + TempLifetime time.Duration // If CurrentFiler is not nil, it is queried for the current file before rescanning. CurrentFiler CurrentFiler // If IgnorePerms is true, changes to permission bits will not be @@ -86,6 +89,7 @@ func (w *Walker) Walk() (chan protocol.FileInfo, error) { } func (w *Walker) walkAndHashFiles(fchan chan protocol.FileInfo) filepath.WalkFunc { + now := time.Now() return func(p string, info os.FileInfo, err error) error { if err != nil { if debug { @@ -111,6 +115,12 @@ func (w *Walker) walkAndHashFiles(fchan chan protocol.FileInfo) filepath.WalkFun if debug { l.Debugln("temporary:", rn) } + if info.Mode().IsRegular() && info.ModTime().Add(w.TempLifetime).Before(now) { + os.Remove(p) + if debug { + l.Debugln("removing temporary:", rn, info.ModTime()) + } + } return nil }