local: Fix creating data dirs

This commit is contained in:
Alexander Neumann 2017-09-11 21:29:37 +02:00
parent 227b01395f
commit 5bf2228596
3 changed files with 97 additions and 1 deletions

View File

@ -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")

View 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
}

View 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)
}
})
}
}