mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-09 14:50:56 +00:00
lib/scanner: Never, ever descend into symlinks (ref #3857)
On Windows we would descend into SYMLINKD type links when we scanned them successfully, as we would return nil from the walk function and the filepath.Walk iterator apparently thought it OK to descend into the symlinked directory. With this change we always return filepath.SkipDir no matter what. Tested on Windows 10 as admin, does what it should. GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/3875
This commit is contained in:
parent
29d010ec0e
commit
926c88cfc4
@ -278,11 +278,11 @@ func (w *walker) walkAndHashFiles(fchan, dchan chan protocol.FileInfo) filepath.
|
||||
|
||||
switch {
|
||||
case info.Mode()&os.ModeSymlink == os.ModeSymlink:
|
||||
var shouldSkip bool
|
||||
shouldSkip, err = w.walkSymlink(absPath, relPath, dchan)
|
||||
if err == nil && shouldSkip {
|
||||
return skip
|
||||
if err := w.walkSymlink(absPath, relPath, dchan); err != nil {
|
||||
return err
|
||||
}
|
||||
// under no circumstances shall we descend into a symlink
|
||||
return filepath.SkipDir
|
||||
|
||||
case info.Mode().IsDir():
|
||||
err = w.walkDir(relPath, info, dchan)
|
||||
@ -376,17 +376,14 @@ func (w *walker) walkDir(relPath string, info os.FileInfo, dchan chan protocol.F
|
||||
return nil
|
||||
}
|
||||
|
||||
// walkSymlinks returns true if the symlink should be skipped, or an error if
|
||||
// we should stop walking altogether. filepath.Walk isn't supposed to
|
||||
// transcend into symlinks at all, but there are rumours that this may have
|
||||
// happened anyway under some circumstances, possibly Windows reparse points
|
||||
// or something. Hence the "skip" return from this one.
|
||||
func (w *walker) walkSymlink(absPath, relPath string, dchan chan protocol.FileInfo) (skip bool, err error) {
|
||||
// walkSymlink returns nil or an error, if the error is of the nature that
|
||||
// it should stop the entire walk.
|
||||
func (w *walker) walkSymlink(absPath, relPath string, dchan chan protocol.FileInfo) error {
|
||||
// If the target is a directory, do NOT descend down there. This will
|
||||
// cause files to get tracked, and removing the symlink will as a result
|
||||
// remove files in their real location.
|
||||
if !symlinks.Supported {
|
||||
return true, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// We always rehash symlinks as they have no modtime or
|
||||
@ -397,7 +394,7 @@ func (w *walker) walkSymlink(absPath, relPath string, dchan chan protocol.FileIn
|
||||
target, targetType, err := symlinks.Read(absPath)
|
||||
if err != nil {
|
||||
l.Debugln("readlink error:", absPath, err)
|
||||
return true, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// A symlink is "unchanged", if
|
||||
@ -409,7 +406,7 @@ func (w *walker) walkSymlink(absPath, relPath string, dchan chan protocol.FileIn
|
||||
// - the target was the same
|
||||
cf, ok := w.CurrentFiler.CurrentFile(relPath)
|
||||
if ok && !cf.IsDeleted() && cf.IsSymlink() && !cf.IsInvalid() && SymlinkTypeEqual(targetType, cf) && cf.SymlinkTarget == target {
|
||||
return true, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
f := protocol.FileInfo{
|
||||
@ -425,10 +422,10 @@ func (w *walker) walkSymlink(absPath, relPath string, dchan chan protocol.FileIn
|
||||
select {
|
||||
case dchan <- f:
|
||||
case <-w.Cancel:
|
||||
return false, errors.New("cancelled")
|
||||
return errors.New("cancelled")
|
||||
}
|
||||
|
||||
return false, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// normalizePath returns the normalized relative path (possibly after fixing
|
||||
|
Loading…
Reference in New Issue
Block a user