=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/sftp-client.c,v retrieving revision 1.114 retrieving revision 1.115 diff -u -r1.114 -r1.115 --- src/usr.bin/ssh/sftp-client.c 2014/01/31 16:39:19 1.114 +++ src/usr.bin/ssh/sftp-client.c 2014/04/21 14:36:16 1.115 @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-client.c,v 1.114 2014/01/31 16:39:19 tedu Exp $ */ +/* $OpenBSD: sftp-client.c,v 1.115 2014/04/21 14:36:16 logan Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -1409,7 +1409,7 @@ int do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, - int preserve_flag, int fsync_flag) + int preserve_flag, int resume, int fsync_flag) { int local_fd; int status = SSH2_FX_OK; @@ -1418,7 +1418,7 @@ char *handle, *data; Buffer msg; struct stat sb; - Attrib a; + Attrib a, *c = NULL; u_int32_t startid; u_int32_t ackid; struct outstanding_ack { @@ -1456,6 +1456,26 @@ if (!preserve_flag) a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; + if (resume) { + /* Get remote file size if it exists */ + if ((c = do_stat(conn, remote_path, 0)) == NULL) { + 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; + } + + if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) { + close(local_fd); + return -1; + } + } + buffer_init(&msg); /* Send open request */ @@ -1463,7 +1483,8 @@ buffer_put_char(&msg, SSH2_FXP_OPEN); buffer_put_int(&msg, id); buffer_put_cstring(&msg, remote_path); - buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); + buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| + (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC)); encode_attrib(&msg, &a); send_msg(conn, &msg); debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); @@ -1482,7 +1503,7 @@ data = xmalloc(conn->transfer_buflen); /* Read from local and write to remote */ - offset = progress_counter = 0; + offset = progress_counter = (resume ? c->size : 0); if (showprogress) start_progress_meter(local_path, sb.st_size, &progress_counter); @@ -1596,7 +1617,7 @@ static int upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, - int preserve_flag, int print_flag, int fsync_flag) + int preserve_flag, int print_flag, int resume, int fsync_flag) { int ret = 0, status; DIR *dirp; @@ -1665,12 +1686,12 @@ continue; if (upload_dir_internal(conn, new_src, new_dst, - depth + 1, preserve_flag, print_flag, + depth + 1, preserve_flag, print_flag, resume, fsync_flag) == -1) ret = -1; } else if (S_ISREG(sb.st_mode)) { if (do_upload(conn, new_src, new_dst, - preserve_flag, fsync_flag) == -1) { + preserve_flag, resume, fsync_flag) == -1) { error("Uploading of file %s to %s failed!", new_src, new_dst); ret = -1; @@ -1689,7 +1710,7 @@ int upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, - int print_flag, int fsync_flag) + int print_flag, int resume, int fsync_flag) { char *dst_canon; int ret; @@ -1700,7 +1721,7 @@ } ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, - print_flag, fsync_flag); + print_flag, resume, fsync_flag); free(dst_canon); return ret;