浏览代码

lib/config: Retain slash at end of path after expanding ~ (fixes #2782)

The various path cleaning operations done in in cleanedPath() removes
it, so we make sure it's added again at the end. This makes adding the
slash in prepare() unnecessary, but keep it anyway for display purposes
(people looking at the config).

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/3342
Jakob Borg 9 年之前
父节点
当前提交
b0d03d1f1c
共有 2 个文件被更改,包括 55 次插入0 次删除
  1. 6 0
      lib/config/folderconfiguration.go
  2. 49 0
      lib/model/model_test.go

+ 6 - 0
lib/config/folderconfiguration.go

@@ -168,6 +168,12 @@ func (f *FolderConfiguration) cleanedPath() string {
 		return `\\?\` + cleaned
 	}
 
+	// If we're not on Windows, we want the path to end with a slash to
+	// penetrate symlinks. On Windows, paths must not end with a slash.
+	if runtime.GOOS != "windows" && cleaned[len(cleaned)-1] != filepath.Separator {
+		cleaned = cleaned + string(filepath.Separator)
+	}
+
 	return cleaned
 }
 

+ 49 - 0
lib/model/model_test.go

@@ -28,6 +28,7 @@ import (
 	"github.com/syncthing/syncthing/lib/ignore"
 	"github.com/syncthing/syncthing/lib/osutil"
 	"github.com/syncthing/syncthing/lib/protocol"
+	srand "github.com/syncthing/syncthing/lib/rand"
 )
 
 var device1, device2 protocol.DeviceID
@@ -1507,6 +1508,54 @@ func TestScanNoDatabaseWrite(t *testing.T) {
 	}
 }
 
+func TestIssue2782(t *testing.T) {
+	// CheckFolderHealth should accept a symlinked folder, when using tilde-expanded path.
+
+	if runtime.GOOS == "windows" {
+		t.Skip("not reliable on Windows")
+		return
+	}
+	home := os.Getenv("HOME")
+	if home == "" {
+		t.Skip("no home")
+	}
+
+	// Create the test env. Needs to be based on $HOME as tilde expansion is
+	// part of the issue. Skip the test if any of this fails, as we are a
+	// bit outside of our stated domain here...
+
+	testName := ".syncthing-test." + srand.String(16)
+	testDir := filepath.Join(home, testName)
+	if err := osutil.RemoveAll(testDir); err != nil {
+		t.Skip(err)
+	}
+	if err := osutil.MkdirAll(testDir+"/syncdir", 0755); err != nil {
+		t.Skip(err)
+	}
+	if err := ioutil.WriteFile(testDir+"/syncdir/file", []byte("hello, world\n"), 0644); err != nil {
+		t.Skip(err)
+	}
+	if err := os.Symlink("syncdir", testDir+"/synclink"); err != nil {
+		t.Skip(err)
+	}
+	defer osutil.RemoveAll(testDir)
+
+	db := db.OpenMemory()
+	m := NewModel(defaultConfig, protocol.LocalDeviceID, "device", "syncthing", "dev", db, nil)
+	m.AddFolder(config.NewFolderConfiguration("default", "~/"+testName+"/synclink/"))
+	m.StartFolder("default")
+	m.ServeBackground()
+	defer m.Stop()
+
+	if err := m.ScanFolder("default"); err != nil {
+		t.Error("scan error:", err)
+	}
+
+	if err := m.CheckFolderHealth("default"); err != nil {
+		t.Error("health check error:", err)
+	}
+}
+
 type fakeAddr struct{}
 
 func (fakeAddr) Network() string {