backend/sftp: Support atomic rename
... if the server has posix-rename@openssh.com.
OpenSSH introduced this extension in 2008:
7c29661471
This commit is contained in:
parent
b7c990871f
commit
fa8f02292e
1 changed files with 11 additions and 4 deletions
|
@ -31,6 +31,8 @@ type SFTP struct {
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
result <-chan error
|
result <-chan error
|
||||||
|
|
||||||
|
posixRename bool
|
||||||
|
|
||||||
sem *backend.Semaphore
|
sem *backend.Semaphore
|
||||||
backend.Layout
|
backend.Layout
|
||||||
Config
|
Config
|
||||||
|
@ -96,7 +98,8 @@ func startClient(program string, args ...string) (*SFTP, error) {
|
||||||
return nil, errors.Wrap(err, "bg")
|
return nil, errors.Wrap(err, "bg")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &SFTP{c: client, cmd: cmd, result: ch}, nil
|
_, posixRename := client.HasExtension("posix-rename@openssh.com")
|
||||||
|
return &SFTP{c: client, cmd: cmd, result: ch, posixRename: posixRename}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// clientError returns an error if the client has exited. Otherwise, nil is
|
// clientError returns an error if the client has exited. Otherwise, nil is
|
||||||
|
@ -269,8 +272,7 @@ func (r *SFTP) Hasher() hash.Hash {
|
||||||
|
|
||||||
// HasAtomicReplace returns whether Save() can atomically replace files
|
// HasAtomicReplace returns whether Save() can atomically replace files
|
||||||
func (r *SFTP) HasAtomicReplace() bool {
|
func (r *SFTP) HasAtomicReplace() bool {
|
||||||
// we use sftp's 'Rename()' in 'Save()' which does not allow overwriting
|
return r.posixRename
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Join joins the given paths and cleans them afterwards. This always uses
|
// Join joins the given paths and cleans them afterwards. This always uses
|
||||||
|
@ -364,7 +366,12 @@ func (r *SFTP) Save(ctx context.Context, h restic.Handle, rd restic.RewindReader
|
||||||
return errors.Wrap(err, "Close")
|
return errors.Wrap(err, "Close")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = r.c.Rename(tmpFilename, filename)
|
// Prefer POSIX atomic rename if available.
|
||||||
|
if r.posixRename {
|
||||||
|
err = r.c.PosixRename(tmpFilename, filename)
|
||||||
|
} else {
|
||||||
|
err = r.c.Rename(tmpFilename, filename)
|
||||||
|
}
|
||||||
return errors.Wrap(err, "Rename")
|
return errors.Wrap(err, "Rename")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue