From 7d914768bb7b1d349806a63f0a5b0f03b8e90f8c Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Wed, 3 May 2017 21:18:49 +0200 Subject: [PATCH] local/sftp: Auto create directories if needed As reported in #940 --- src/restic/backend/local/local.go | 14 ++++++++++++++ src/restic/backend/sftp/sftp.go | 22 ++++++++++++++-------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/restic/backend/local/local.go b/src/restic/backend/local/local.go index 16bf92c11..3b97f761e 100644 --- a/src/restic/backend/local/local.go +++ b/src/restic/backend/local/local.go @@ -93,6 +93,16 @@ func (b *Local) Save(h restic.Handle, rd io.Reader) (err error) { // create new file f, err := fs.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY, backend.Modes.File) + if os.IsNotExist(errors.Cause(err)) { + // create the locks dir, then try again + err = fs.MkdirAll(b.Dirname(h), backend.Modes.Dir) + if err != nil { + return errors.Wrap(err, "MkdirAll") + } + + return b.Save(h, rd) + } + if err != nil { return errors.Wrap(err, "OpenFile") } @@ -215,6 +225,10 @@ func (b *Local) List(t restic.FileType, done <-chan struct{}) <-chan string { defer close(ch) fs.Walk(b.Basedir(t), func(path string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + if !isFile(fi) { return err } diff --git a/src/restic/backend/sftp/sftp.go b/src/restic/backend/sftp/sftp.go index 8b30eedf4..8f56e23e4 100644 --- a/src/restic/backend/sftp/sftp.go +++ b/src/restic/backend/sftp/sftp.go @@ -143,6 +143,10 @@ func (r *SFTP) ReadDir(dir string) ([]os.FileInfo, error) { // IsNotExist returns true if the error is caused by a not existing file. func (r *SFTP) IsNotExist(err error) bool { + if os.IsNotExist(err) { + return true + } + statusError, ok := err.(*sftp.StatusError) if !ok { return false @@ -271,16 +275,18 @@ func (r *SFTP) Save(h restic.Handle, rd io.Reader) (err error) { filename := r.Filename(h) - // create directories if necessary - if h.Type == restic.DataFile { - err := r.mkdirAll(path.Dir(filename), backend.Modes.Dir) - if err != nil { - return err - } - } - // create new file f, err := r.c.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY) + if r.IsNotExist(errors.Cause(err)) { + // create the locks dir, then try again + err = r.mkdirAll(r.Dirname(h), backend.Modes.Dir) + if err != nil { + return errors.Wrap(err, "MkdirAll") + } + + return r.Save(h, rd) + } + if err != nil { return errors.Wrap(err, "OpenFile") }