forked from TrueCloudLab/restic
local: Fix creating data dirs
This commit is contained in:
parent
227b01395f
commit
5bf2228596
3 changed files with 97 additions and 1 deletions
|
@ -57,11 +57,14 @@ func Open(cfg Config) (*Local, error) {
|
|||
// if data dir exists, make sure that all subdirs also exist
|
||||
datadir := be.Dirname(restic.Handle{Type: restic.DataFile})
|
||||
if dirExists(datadir) {
|
||||
debug.Log("datadir %v exists", datadir)
|
||||
for _, d := range be.Paths() {
|
||||
if _, err := filepath.Rel(datadir, d); err != nil {
|
||||
if !fs.HasPathPrefix(datadir, d) {
|
||||
debug.Log("%v is not subdir of datadir %v", d, datadir)
|
||||
continue
|
||||
}
|
||||
|
||||
debug.Log("MkdirAll %v", d)
|
||||
err := fs.MkdirAll(d, backend.Modes.Dir)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "MkdirAll")
|
||||
|
|
41
internal/fs/path_prefix.go
Normal file
41
internal/fs/path_prefix.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package fs
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// HasPathPrefix returns true if p is a subdir of (or a file within) base. It
|
||||
// assumes a file system which is case sensitive. For relative paths, false is
|
||||
// returned.
|
||||
func HasPathPrefix(base, p string) bool {
|
||||
if filepath.VolumeName(base) != filepath.VolumeName(p) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(base) || !filepath.IsAbs(p) {
|
||||
return false
|
||||
}
|
||||
|
||||
base = filepath.Clean(base)
|
||||
p = filepath.Clean(p)
|
||||
|
||||
if base == p {
|
||||
return true
|
||||
}
|
||||
|
||||
for {
|
||||
dir := filepath.Dir(p)
|
||||
|
||||
if base == dir {
|
||||
return true
|
||||
}
|
||||
|
||||
if p == dir {
|
||||
break
|
||||
}
|
||||
|
||||
p = dir
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
52
internal/fs/path_prefix_test.go
Normal file
52
internal/fs/path_prefix_test.go
Normal file
|
@ -0,0 +1,52 @@
|
|||
package fs
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func fromSlashAbs(p string) string {
|
||||
if runtime.GOOS == "windows" {
|
||||
if len(p) > 0 && p[0] == '/' {
|
||||
p = "c:" + p
|
||||
}
|
||||
}
|
||||
|
||||
return filepath.FromSlash(p)
|
||||
}
|
||||
|
||||
func TestHasPathPrefix(t *testing.T) {
|
||||
var tests = []struct {
|
||||
base, p string
|
||||
result bool
|
||||
}{
|
||||
{"", "", false},
|
||||
{"/", "", false},
|
||||
{"/", "x", false},
|
||||
{"x", "/", false},
|
||||
{"/", "/x", true},
|
||||
{"/x", "/y", false},
|
||||
{"/home/user/foo", "/home", false},
|
||||
{"/home/user/foo/", "/home", false},
|
||||
{"/home/user/foo", "/home/", false},
|
||||
{"/home/user/foo/", "/home/", false},
|
||||
{"/home/user/foo", "/home/user/foo/bar", true},
|
||||
{"/home/user/foo", "/home/user/foo/bar/baz/x/y/z", true},
|
||||
{"/home/user/foo", "/home/user/foobar", false},
|
||||
{"/home/user/Foo", "/home/user/foo/bar/baz", false},
|
||||
{"/home/user/foo", "/home/user/Foo/bar/baz", false},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run("", func(t *testing.T) {
|
||||
base := fromSlashAbs(test.base)
|
||||
p := fromSlashAbs(test.p)
|
||||
result := HasPathPrefix(base, p)
|
||||
if result != test.result {
|
||||
t.Fatalf("wrong result for HasPathPrefix(%q, %q): want %v, got %v",
|
||||
base, p, test.result, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue