aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornf <nf@wh3rd.net>2024-01-12 20:46:18 +1100
committerGitHub <noreply@github.com>2024-01-12 10:46:18 +0100
commit8b321387c082c178a85c8bd1b4047ff95e7a63e3 (patch)
treefcbb6d716110b557ea0324efcd01b53339352692
parent8edd67a569594bec06c395041acb7eb18f8e3b13 (diff)
downloadsyncthing-8b321387c082c178a85c8bd1b4047ff95e7a63e3.tar.gz
syncthing-8b321387c082c178a85c8bd1b4047ff95e7a63e3.zip
lib/versioner: Expand tildes in version directory (fixes #9241) (#9327)
### Purpose Fix #9241 by expanding tildes in version paths. When creating the versioner file system, first try to expand any leading tildes to the user's home directory before handling relative paths. This makes a version path `"~/p"` expand to `"$HOME/p"` instead of `"/folder/~/p"`. ### Testing Added a test to lib/versioner that exercises this code path. Also manually tested with local syncthing instances.
-rw-r--r--lib/versioner/simple_test.go66
-rw-r--r--lib/versioner/util.go16
2 files changed, 79 insertions, 3 deletions
diff --git a/lib/versioner/simple_test.go b/lib/versioner/simple_test.go
index fe92478e7..3b3abb436 100644
--- a/lib/versioner/simple_test.go
+++ b/lib/versioner/simple_test.go
@@ -8,7 +8,9 @@ package versioner
import (
"math"
+ "os"
"path/filepath"
+ "strings"
"testing"
"time"
@@ -93,3 +95,67 @@ func TestSimpleVersioningVersionCount(t *testing.T) {
time.Sleep(time.Second)
}
}
+
+func TestPathTildes(t *testing.T) {
+ // Test that folder and version paths with leading tildes are expanded
+ // to the user's home directory. (issue #9241)
+ home := t.TempDir()
+ t.Setenv("HOME", home)
+ if vn := filepath.VolumeName(home); vn != "" {
+ // Legacy Windows home stuff
+ t.Setenv("HomeDrive", vn)
+ t.Setenv("HomePath", strings.TrimPrefix(home, vn))
+ }
+ os.Mkdir(filepath.Join(home, "folder"), 0o755)
+
+ cfg := config.FolderConfiguration{
+ FilesystemType: fs.FilesystemTypeBasic,
+ Path: "~/folder",
+ Versioning: config.VersioningConfiguration{
+ FSPath: "~/versions",
+ FSType: fs.FilesystemTypeBasic,
+ Params: map[string]string{
+ "keep": "2",
+ },
+ },
+ }
+ fs := cfg.Filesystem(nil)
+ v := newSimple(cfg)
+
+ const testPath = "test"
+
+ f, err := fs.Create(testPath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ f.Close()
+ if err := v.Archive(testPath); err != nil {
+ t.Fatal(err)
+ }
+
+ // Check that there are no entries in the folder directory; this is
+ // specifically to check that there is no directory named "~" there.
+ names, err := fs.DirNames(".")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(names) != 0 {
+ t.Fatalf("found %d files in folder dir, want 0", len(names))
+ }
+
+ // Check that the versions directory contains one file that begins with
+ // our test path.
+ des, err := os.ReadDir(filepath.Join(home, "versions"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, de := range des {
+ names = append(names, de.Name())
+ }
+ if len(names) != 1 {
+ t.Fatalf("found %d files in versions dir, want 1", len(names))
+ }
+ if got := names[0]; !strings.HasPrefix(got, testPath) {
+ t.Fatalf("found versioned file %q, want one that begins with %q", got, testPath)
+ }
+}
diff --git a/lib/versioner/util.go b/lib/versioner/util.go
index cb7773da3..a0bcfba1e 100644
--- a/lib/versioner/util.go
+++ b/lib/versioner/util.go
@@ -262,10 +262,20 @@ func versionerFsFromFolderCfg(cfg config.FolderConfiguration) (versionsFs fs.Fil
folderFs := cfg.Filesystem(nil)
if cfg.Versioning.FSPath == "" {
versionsFs = fs.NewFilesystem(folderFs.Type(), filepath.Join(folderFs.URI(), DefaultPath))
- } else if cfg.Versioning.FSType == fs.FilesystemTypeBasic && !filepath.IsAbs(cfg.Versioning.FSPath) {
- // We only know how to deal with relative folders for basic filesystems, as that's the only one we know
+ } else if cfg.Versioning.FSType == fs.FilesystemTypeBasic {
+ // Expand any leading tildes for basic filesystems,
+ // before checking for absolute paths.
+ path, err := fs.ExpandTilde(cfg.Versioning.FSPath)
+ if err != nil {
+ path = cfg.Versioning.FSPath
+ }
+ // We only know how to deal with relative folders for
+ // basic filesystems, as that's the only one we know
// how to check if it's absolute or relative.
- versionsFs = fs.NewFilesystem(cfg.Versioning.FSType, filepath.Join(folderFs.URI(), cfg.Versioning.FSPath))
+ if !filepath.IsAbs(path) {
+ path = filepath.Join(folderFs.URI(), path)
+ }
+ versionsFs = fs.NewFilesystem(cfg.Versioning.FSType, path)
} else {
versionsFs = fs.NewFilesystem(cfg.Versioning.FSType, cfg.Versioning.FSPath)
}