This patch adds support for recursive upload resume (`reput -r`,
`put -a -r` commands) in sftp client. Now this combination (-a -r), despite
being valid and accepted by sftp client, does not do anything useful: it
always results in errors. Apparently possibility of recursive upload was
overlooked when upload resume support was being implemented in 2014.
I tried to make its logic similar to the already existing recursive download
resume behavior, that is:
when target file doesn't exists on the remote end:
upload the whole file
when remote file is smaller than local one:
upload the remaining part
when remote file size is equal the local one:
skip this file
when remote file is larger than local one:
skip this file with an error message
Signed-off-by: Piotr Jurkiewicz <piotr.jerzy.jurkiewicz@xxxxxxxxx>
---
sftp-client.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/sftp-client.c b/sftp-client.c
index d49bfaa..ee4d131 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1598,23 +1598,24 @@ do_upload(struct sftp_conn *conn, const char *local_path,
if (!preserve_flag)
a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
+ offset = 0;
if (resume) {
/* Get remote file size if it exists */
- if ((c = do_stat(conn, remote_path, 0)) == NULL) {
- close(local_fd);
- return -1;
- }
+ if ((c = do_stat(conn, remote_path, 1)) != NULL) {
+ if ((off_t)c->size > sb.st_size) {
+ error("Unable to resume upload of \"%s\": "
+ "remote file is larger than local",
+ remote_path);
+ close(local_fd);
+ return -1;
+ }
- if ((off_t)c->size >= sb.st_size) {
- error("destination file bigger or same size as "
- "source file");
- close(local_fd);
- return -1;
- }
+ offset = c->size;
- if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) {
- close(local_fd);
- return -1;
+ if (lseek(local_fd, offset, SEEK_SET) == -1) {
+ close(local_fd);
+ return -1;
+ }
}
}
@@ -1627,7 +1628,7 @@ do_upload(struct sftp_conn *conn, const char *local_path,
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
(r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
- (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 ||
+ (offset > 0 ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 ||
(r = encode_attrib(msg, &a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
@@ -1647,7 +1648,7 @@ do_upload(struct sftp_conn *conn, const char *local_path,
data = xmalloc(conn->transfer_buflen);
/* Read from local and write to remote */
- offset = progress_counter = (resume ? c->size : 0);
+ progress_counter = offset;
if (showprogress)
start_progress_meter(local_path, sb.st_size,
&progress_counter);
--
2.1.4
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@xxxxxxxxxxx
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev