Merge pull request from restic/fix-1167

local: do not create dirs below data/ for non-existing dir
This commit is contained in:
Alexander Neumann 2017-08-28 21:13:24 +02:00
commit 48b1ab5aaf
3 changed files with 91 additions and 5 deletions
internal/backend

View file

@ -25,6 +25,25 @@ var _ restic.Backend = &Local{}
const defaultLayout = "default" const defaultLayout = "default"
// dirExists returns true if the name exists and is a directory.
func dirExists(name string) bool {
f, err := fs.Open(name)
if err != nil {
return false
}
fi, err := f.Stat()
if err != nil {
return false
}
if err = f.Close(); err != nil {
return false
}
return fi.IsDir()
}
// Open opens the local backend as specified by config. // Open opens the local backend as specified by config.
func Open(cfg Config) (*Local, error) { func Open(cfg Config) (*Local, error) {
debug.Log("open local backend at %v (layout %q)", cfg.Path, cfg.Layout) debug.Log("open local backend at %v (layout %q)", cfg.Path, cfg.Layout)
@ -35,11 +54,18 @@ func Open(cfg Config) (*Local, error) {
be := &Local{Config: cfg, Layout: l} be := &Local{Config: cfg, Layout: l}
// create paths for data and refs. MkdirAll does nothing if the directory already exists. // if data dir exists, make sure that all subdirs also exist
for _, d := range be.Paths() { datadir := be.Dirname(restic.Handle{Type: restic.DataFile})
err := fs.MkdirAll(d, backend.Modes.Dir) if dirExists(datadir) {
if err != nil { for _, d := range be.Paths() {
return nil, errors.Wrap(err, "MkdirAll") if _, err := filepath.Rel(datadir, d); err != nil {
continue
}
err := fs.MkdirAll(d, backend.Modes.Dir)
if err != nil {
return nil, errors.Wrap(err, "MkdirAll")
}
} }
} }

View file

@ -2,6 +2,8 @@ package local_test
import ( import (
"io/ioutil" "io/ioutil"
"os"
"path/filepath"
"testing" "testing"
"github.com/restic/restic/internal/backend/local" "github.com/restic/restic/internal/backend/local"
@ -59,3 +61,57 @@ func TestBackend(t *testing.T) {
func BenchmarkBackend(t *testing.B) { func BenchmarkBackend(t *testing.B) {
newTestSuite(t).RunBenchmarks(t) newTestSuite(t).RunBenchmarks(t)
} }
func readdirnames(t testing.TB, dir string) []string {
f, err := os.Open(dir)
if err != nil {
t.Fatal(err)
}
entries, err := f.Readdirnames(-1)
if err != nil {
t.Fatal(err)
}
err = f.Close()
if err != nil {
t.Fatal(err)
}
return entries
}
func empty(t testing.TB, dir string) {
entries := readdirnames(t, dir)
if len(entries) != 0 {
t.Fatalf("directory %v is not empty, contains: %v", dir, entries)
}
}
func openclose(t testing.TB, dir string) {
cfg := local.Config{Path: dir}
be, err := local.Open(cfg)
if err != nil {
t.Logf("Open returned error %v", err)
}
if be != nil {
err = be.Close()
if err != nil {
t.Logf("Close returned error %v", err)
}
}
}
func TestOpenNotExistingDirectory(t *testing.T) {
dir, cleanup := TempDir(t)
defer cleanup()
// local.Open must not create any files dirs in the repo
openclose(t, filepath.Join(dir, "repo"))
empty(t, dir)
openclose(t, dir)
empty(t, dir)
}

View file

@ -141,6 +141,10 @@ func (r *SFTP) checkDataSubdirs() error {
// check if all paths for data/ exist // check if all paths for data/ exist
entries, err := r.c.ReadDir(datadir) entries, err := r.c.ReadDir(datadir)
if r.IsNotExist(err) {
return nil
}
if err != nil { if err != nil {
return err return err
} }