2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-25 22:27:35 +00:00

Merge pull request #2530 from restic/fix-sftp-mkdirall

sftp: Use MkdirAll provided by the client
This commit is contained in:
rawtaz 2020-02-13 01:12:59 +01:00 committed by GitHub
commit 680a14afa1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 37 deletions

View File

@ -0,0 +1,16 @@
Bugfix: Do not crash with Synology NAS sftp server
It was found that when restic is used to store data on an sftp server on a
Synology NAS with a relative path (one which does not start with a slash), it
may go into an endless loop trying to create directories on the server. We've
fixed this bug by using a function in the sftp library instead of our own
implementation.
The bug was discovered because the Synology sftp server behaves erratic with
non-absolute path (e.g. `home/restic-repo`). This can be resolved by just using
an absolute path instead (`/home/restic-repo`). We've also added a paragraph in
the FAQ.
https://github.com/restic/restic/issues/2518
https://github.com/restic/restic/issues/2363
https://github.com/restic/restic/pull/2530

View File

@ -142,6 +142,9 @@ is not slowed down, which is particularly useful for servers.
Creating new repo on a Synology NAS via sftp fails Creating new repo on a Synology NAS via sftp fails
-------------------------------------------------- --------------------------------------------------
For using restic with a Synology NAS via sftp, please make sure that the
specified path is absolute, it must start with a slash (``/``).
Sometimes creating a new restic repository on a Synology NAS via sftp fails Sometimes creating a new restic repository on a Synology NAS via sftp fails
with an error similar to the following: with an error similar to the following:
@ -160,8 +163,8 @@ different than the directory structure on the device and maybe even as exposed
via other protocols. via other protocols.
Try removing the /volume1 prefix in your paths. If this does not work, use sftp Try removing the ``/volume1`` prefix in your paths. If this does not work, use
and ls to explore the SFTP file system hierarchy on your NAS. sftp and ls to explore the SFTP file system hierarchy on your NAS.
The following may work: The following may work:

View File

@ -138,8 +138,7 @@ func Open(cfg Config) (*SFTP, error) {
func (r *SFTP) mkdirAllDataSubdirs() error { func (r *SFTP) mkdirAllDataSubdirs() error {
for _, d := range r.Paths() { for _, d := range r.Paths() {
err := r.mkdirAll(d, backend.Modes.Dir) err := r.c.MkdirAll(d)
debug.Log("mkdirAll %v -> %v", d, err)
if err != nil { if err != nil {
return err return err
} }
@ -250,38 +249,6 @@ func (r *SFTP) Location() string {
return r.p return r.p
} }
func (r *SFTP) mkdirAll(dir string, mode os.FileMode) error {
// check if directory already exists
fi, err := r.c.Lstat(dir)
if err == nil {
if fi.IsDir() {
return nil
}
return errors.Errorf("mkdirAll(%s): entry exists but is not a directory", dir)
}
// create parent directories
errMkdirAll := r.mkdirAll(path.Dir(dir), backend.Modes.Dir)
// create directory
errMkdir := r.c.Mkdir(dir)
// test if directory was created successfully
fi, err = r.c.Lstat(dir)
if err != nil {
// return previous errors
return errors.Errorf("mkdirAll(%s): unable to create directories: %v, %v", dir, errMkdirAll, errMkdir)
}
if !fi.IsDir() {
return errors.Errorf("mkdirAll(%s): entry exists but is not a directory", dir)
}
// set mode
return r.c.Chmod(dir, mode)
}
// Join joins the given paths and cleans them afterwards. This always uses // Join joins the given paths and cleans them afterwards. This always uses
// forward slashes, which is required by sftp. // forward slashes, which is required by sftp.
func Join(parts ...string) string { func Join(parts ...string) string {
@ -306,7 +273,7 @@ func (r *SFTP) Save(ctx context.Context, h restic.Handle, rd restic.RewindReader
if r.IsNotExist(err) { if r.IsNotExist(err) {
// error is caused by a missing directory, try to create it // error is caused by a missing directory, try to create it
mkdirErr := r.mkdirAll(r.Dirname(h), backend.Modes.Dir) mkdirErr := r.c.MkdirAll(r.Dirname(h))
if mkdirErr != nil { if mkdirErr != nil {
debug.Log("error creating dir %v: %v", r.Dirname(h), mkdirErr) debug.Log("error creating dir %v: %v", r.Dirname(h), mkdirErr)
} else { } else {