lib/versioner: Clean the versions dir of symlinks, not the full folder

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4289
This commit is contained in:
Jakob Borg
2017-08-08 13:13:08 +00:00
parent a3c17f8f81
commit fa5c890ff6
9 changed files with 207 additions and 36 deletions

View File

@@ -178,8 +178,13 @@ func (m *Model) StartDeadlockDetector(timeout time.Duration) {
func (m *Model) StartFolder(folder string) {
m.fmut.Lock()
m.pmut.Lock()
folderType := m.startFolderLocked(folder)
folderCfg := m.folderCfgs[folder]
if folderCfg.Versioning.Type != "" && m.cfg.RawCopy().OriginalVersion < 21 {
m.attemptSymlinkRecovery(folderCfg)
}
folderType := m.startFolderLocked(folder)
m.pmut.Unlock()
m.fmut.Unlock()
@@ -2721,3 +2726,76 @@ func rootedJoinedPath(root, rel string) (string, error) {
return joined, nil
}
func (m *Model) attemptSymlinkRecovery(fcfg config.FolderConfiguration) {
fs, ok := m.folderFiles[fcfg.ID]
if !ok {
return
}
// The window during which we had a broken release out, roughly.
startDate := time.Date(2017, 8, 8, 6, 0, 0, 0, time.UTC)
endDate := time.Date(2017, 8, 8, 12, 0, 0, 0, time.UTC)
// Look through all our files looking for deleted symlinks.
fs.WithHave(protocol.LocalDeviceID, func(intf db.FileIntf) bool {
if !intf.IsSymlink() {
return true
}
symlinkPath, err := rootedJoinedPath(fcfg.Path(), intf.FileName())
if err != nil {
// odd
return true
}
if _, err := os.Lstat(symlinkPath); err == nil {
// The symlink exists. Our work here is done.
return true
}
fi := intf.(protocol.FileInfo)
if !fi.Deleted && fi.SymlinkTarget != "" {
// We haven't noticed the delete and put it into the
// index yet. Great! We can restore the symlink.
l.Infoln("Restoring incorrectly deleted symlink", symlinkPath)
os.Symlink(fi.SymlinkTarget, symlinkPath)
return true
}
// It's deleted. Check if it was deleted in the bad window.
if fi.ModTime().Before(startDate) || !fi.ModTime().Before(endDate) {
return true
}
// Try to find an older index entry.
for deviceID := range m.cfg.Devices() {
olderFI, ok := fs.Get(deviceID, fi.Name)
if !ok {
// This device doesn't have it.
continue
}
if olderFI.Deleted || !olderFI.IsSymlink() {
// The device has something deleted or not a
// symlink, doesn't help us.
continue
}
if olderFI.Version.GreaterEqual(fi.Version) {
// The device has something newer. We should
// chill and let the puller handle it. No
// need to look further for this specific
// symlink.
return true
}
if olderFI.SymlinkTarget != "" {
// It has symlink data. Restore the symlink.
l.Infoln("Restoring incorrectly deleted symlink", symlinkPath)
os.Symlink(olderFI.SymlinkTarget, symlinkPath)
return true
}
}
return true
})
}