sftp: fix move to allow overwriting existing files

Before this change rclone used a normal SFTP rename if present to
implement Move.

However the normal SFTP rename won't overwrite existing files.

This fixes it to either use the POSIX rename extension
("posix-rename@openssh.com") or to delete the source first before
renaming using the normal SFTP rename.

This isn't normally a problem as rclone always removes any existing
objects first, however to implement non --inplace operations we do
require overwriting an existing file.
This commit is contained in:
Nick Craig-Wood 2023-05-09 15:29:55 +01:00
parent c18c66f167
commit aaacfa51a0

View File

@ -1329,10 +1329,17 @@ func (f *Fs) Move(ctx context.Context, src fs.Object, remote string) (fs.Object,
if err != nil { if err != nil {
return nil, fmt.Errorf("Move: %w", err) return nil, fmt.Errorf("Move: %w", err)
} }
err = c.sftpClient.Rename( srcPath, dstPath := srcObj.path(), path.Join(f.absRoot, remote)
srcObj.path(), if _, ok := c.sftpClient.HasExtension("posix-rename@openssh.com"); ok {
path.Join(f.absRoot, remote), err = c.sftpClient.PosixRename(srcPath, dstPath)
) } else {
// If haven't got PosixRename then remove source first before renaming
err = c.sftpClient.Remove(dstPath)
if err != nil && !errors.Is(err, iofs.ErrNotExist) {
fs.Errorf(f, "Move: Failed to remove existing file %q: %v", dstPath, err)
}
err = c.sftpClient.Rename(srcPath, dstPath)
}
f.putSftpConnection(&c, err) f.putSftpConnection(&c, err)
if err != nil { if err != nil {
return nil, fmt.Errorf("Move Rename failed: %w", err) return nil, fmt.Errorf("Move Rename failed: %w", err)