[PATCH 1/2] Implement recursive upload resume support in sftp client

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

 



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



[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux