lib/model, lib/scanner: Properly ignore symlinks on Windows (fixes #4035)

Adds a unit test to ensure we don't scan symlinks on Windows. For the
rwfolder, trusts that the logic in the invalid check is correct and that
the check is actually called from the need loop.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4042
This commit is contained in:
Jakob Borg 2017-03-18 00:25:47 +00:00 committed by Audrius Butkevicius
parent a54365424e
commit 5c27796471
3 changed files with 52 additions and 3 deletions

View File

@ -53,8 +53,9 @@ type copyBlocksState struct {
const retainBits = os.ModeSetgid | os.ModeSetuid | os.ModeSticky
var (
activity = newDeviceActivity()
errNoDevice = errors.New("peers who had this file went away, or the file has changed while syncing. will retry later")
activity = newDeviceActivity()
errNoDevice = errors.New("peers who had this file went away, or the file has changed while syncing. will retry later")
errSymlinksUnsupported = errors.New("symlinks not supported")
)
const (
@ -1759,6 +1760,9 @@ func fileValid(file db.FileIntf) error {
// We don't care about file validity if we're not supposed to have it
return nil
case runtime.GOOS == "windows" && file.IsSymlink():
return errSymlinksUnsupported
case runtime.GOOS == "windows" && windowsInvalidFilename(file.FileName()):
return errInvalidFilename
}

View File

@ -373,6 +373,12 @@ func (w *walker) walkDir(relPath string, info os.FileInfo, dchan chan protocol.F
// 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 {
// Symlinks are not supported on Windows. We ignore instead of returning
// an error.
if runtime.GOOS == "windows" {
return nil
}
// We always rehash symlinks as they have no modtime or
// permissions. We check if they point to the old target by
// checking that their existing blocks match with the blocks in

View File

@ -280,7 +280,7 @@ func TestIssue1507(t *testing.T) {
fn("", nil, protocol.ErrClosed)
}
func TestWalkSymlink(t *testing.T) {
func TestWalkSymlinkUnix(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping unsupported symlink test")
return
@ -323,6 +323,45 @@ func TestWalkSymlink(t *testing.T) {
}
}
func TestWalkSymlinkWindows(t *testing.T) {
if runtime.GOOS != "windows" {
t.Skip("skipping unsupported symlink test")
}
// Create a folder with a symlink in it
os.RemoveAll("_symlinks")
defer os.RemoveAll("_symlinks")
os.Mkdir("_symlinks", 0755)
if err := os.Symlink("destination", "_symlinks/link"); err != nil {
// Probably we require permissions we don't have.
t.Skip(err)
}
// Scan it
fchan, err := Walk(Config{
Dir: "_symlinks",
BlockSize: 128 * 1024,
})
if err != nil {
t.Fatal(err)
}
var files []protocol.FileInfo
for f := range fchan {
files = append(files, f)
}
// Verify that we got zero symlinks
if len(files) != 0 {
t.Errorf("expected zero symlinks, not %d", len(files))
}
}
func walkDir(dir string) ([]protocol.FileInfo, error) {
fchan, err := Walk(Config{
Dir: dir,