summaryrefslogtreecommitdiff
path: root/sftp-client.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2014-05-15 13:46:25 +1000
committerDamien Miller <djm@mindrot.org>2014-05-15 13:46:25 +1000
commitd8accc0aa72656ba63d50937165c5ae49db1dcd6 (patch)
tree95e22a55fc9c75952f3fdc684cd96b8c0538871d /sftp-client.c
parent16cd3928a87d20c77b13592a74b60b08621d3ce6 (diff)
- logan@cvs.openbsd.org 2014/04/21 14:36:16
[sftp-client.c sftp-client.h sftp.c] Implement sftp upload resume support. OK from djm@, with input from guenther@, mlarkin@ and okan@
Diffstat (limited to 'sftp-client.c')
-rw-r--r--sftp-client.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/sftp-client.c b/sftp-client.c
index 2f5907c85..990b58d14 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-client.c,v 1.114 2014/01/31 16:39:19 tedu Exp $ */ 1/* $OpenBSD: sftp-client.c,v 1.115 2014/04/21 14:36:16 logan Exp $ */
2/* 2/*
3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -1420,7 +1420,7 @@ download_dir(struct sftp_conn *conn, char *src, char *dst,
1420 1420
1421int 1421int
1422do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, 1422do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1423 int preserve_flag, int fsync_flag) 1423 int preserve_flag, int resume, int fsync_flag)
1424{ 1424{
1425 int local_fd; 1425 int local_fd;
1426 int status = SSH2_FX_OK; 1426 int status = SSH2_FX_OK;
@@ -1429,7 +1429,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1429 char *handle, *data; 1429 char *handle, *data;
1430 Buffer msg; 1430 Buffer msg;
1431 struct stat sb; 1431 struct stat sb;
1432 Attrib a; 1432 Attrib a, *c = NULL;
1433 u_int32_t startid; 1433 u_int32_t startid;
1434 u_int32_t ackid; 1434 u_int32_t ackid;
1435 struct outstanding_ack { 1435 struct outstanding_ack {
@@ -1467,6 +1467,26 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1467 if (!preserve_flag) 1467 if (!preserve_flag)
1468 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 1468 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1469 1469
1470 if (resume) {
1471 /* Get remote file size if it exists */
1472 if ((c = do_stat(conn, remote_path, 0)) == NULL) {
1473 close(local_fd);
1474 return -1;
1475 }
1476
1477 if ((off_t)c->size >= sb.st_size) {
1478 error("destination file bigger or same size as "
1479 "source file");
1480 close(local_fd);
1481 return -1;
1482 }
1483
1484 if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) {
1485 close(local_fd);
1486 return -1;
1487 }
1488 }
1489
1470 buffer_init(&msg); 1490 buffer_init(&msg);
1471 1491
1472 /* Send open request */ 1492 /* Send open request */
@@ -1474,7 +1494,8 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1474 buffer_put_char(&msg, SSH2_FXP_OPEN); 1494 buffer_put_char(&msg, SSH2_FXP_OPEN);
1475 buffer_put_int(&msg, id); 1495 buffer_put_int(&msg, id);
1476 buffer_put_cstring(&msg, remote_path); 1496 buffer_put_cstring(&msg, remote_path);
1477 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); 1497 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
1498 (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC));
1478 encode_attrib(&msg, &a); 1499 encode_attrib(&msg, &a);
1479 send_msg(conn, &msg); 1500 send_msg(conn, &msg);
1480 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1501 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
@@ -1493,7 +1514,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1493 data = xmalloc(conn->transfer_buflen); 1514 data = xmalloc(conn->transfer_buflen);
1494 1515
1495 /* Read from local and write to remote */ 1516 /* Read from local and write to remote */
1496 offset = progress_counter = 0; 1517 offset = progress_counter = (resume ? c->size : 0);
1497 if (showprogress) 1518 if (showprogress)
1498 start_progress_meter(local_path, sb.st_size, 1519 start_progress_meter(local_path, sb.st_size,
1499 &progress_counter); 1520 &progress_counter);
@@ -1608,7 +1629,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1608 1629
1609static int 1630static int
1610upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, 1631upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth,
1611 int preserve_flag, int print_flag, int fsync_flag) 1632 int preserve_flag, int print_flag, int resume, int fsync_flag)
1612{ 1633{
1613 int ret = 0, status; 1634 int ret = 0, status;
1614 DIR *dirp; 1635 DIR *dirp;
@@ -1677,12 +1698,12 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth,
1677 continue; 1698 continue;
1678 1699
1679 if (upload_dir_internal(conn, new_src, new_dst, 1700 if (upload_dir_internal(conn, new_src, new_dst,
1680 depth + 1, preserve_flag, print_flag, 1701 depth + 1, preserve_flag, print_flag, resume,
1681 fsync_flag) == -1) 1702 fsync_flag) == -1)
1682 ret = -1; 1703 ret = -1;
1683 } else if (S_ISREG(sb.st_mode)) { 1704 } else if (S_ISREG(sb.st_mode)) {
1684 if (do_upload(conn, new_src, new_dst, 1705 if (do_upload(conn, new_src, new_dst,
1685 preserve_flag, fsync_flag) == -1) { 1706 preserve_flag, resume, fsync_flag) == -1) {
1686 error("Uploading of file %s to %s failed!", 1707 error("Uploading of file %s to %s failed!",
1687 new_src, new_dst); 1708 new_src, new_dst);
1688 ret = -1; 1709 ret = -1;
@@ -1701,7 +1722,7 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth,
1701 1722
1702int 1723int
1703upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, 1724upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag,
1704 int print_flag, int fsync_flag) 1725 int print_flag, int resume, int fsync_flag)
1705{ 1726{
1706 char *dst_canon; 1727 char *dst_canon;
1707 int ret; 1728 int ret;
@@ -1712,7 +1733,7 @@ upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag,
1712 } 1733 }
1713 1734
1714 ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, 1735 ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
1715 print_flag, fsync_flag); 1736 print_flag, resume, fsync_flag);
1716 1737
1717 free(dst_canon); 1738 free(dst_canon);
1718 return ret; 1739 return ret;