summaryrefslogtreecommitdiff
path: root/sftp-client.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2008-02-10 22:27:24 +1100
committerDamien Miller <djm@mindrot.org>2008-02-10 22:27:24 +1100
commitacdf25b31f02c010ed2b5f655bbae0f5b75f07f6 (patch)
tree0c07fe211654f61ebc0ed3e1bd21fde7c75a35da /sftp-client.c
parent3397d0e0c5820464bea4c96e91b5e02cca98330a (diff)
- djm@cvs.openbsd.org 2008/01/21 19:20:17
[sftp-client.c] when a remote write error occurs during an upload, ensure that ACKs for all issued requests are properly drained. patch from t8m AT centrum.cz
Diffstat (limited to 'sftp-client.c')
-rw-r--r--sftp-client.c41
1 files changed, 17 insertions, 24 deletions
diff --git a/sftp-client.c b/sftp-client.c
index e8cdb96ac..b189422d4 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-client.c,v 1.79 2008/01/19 22:04:57 djm Exp $ */ 1/* $OpenBSD: sftp-client.c,v 1.80 2008/01/21 19:20:17 djm 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 *
@@ -997,7 +997,8 @@ int
997do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, 997do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
998 int pflag) 998 int pflag)
999{ 999{
1000 int local_fd, status; 1000 int local_fd;
1001 int status = SSH2_FX_OK;
1001 u_int handle_len, id, type; 1002 u_int handle_len, id, type;
1002 off_t offset; 1003 off_t offset;
1003 char *handle, *data; 1004 char *handle, *data;
@@ -1059,7 +1060,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1059 if (handle == NULL) { 1060 if (handle == NULL) {
1060 close(local_fd); 1061 close(local_fd);
1061 buffer_free(&msg); 1062 buffer_free(&msg);
1062 return(-1); 1063 return -1;
1063 } 1064 }
1064 1065
1065 startid = ackid = id + 1; 1066 startid = ackid = id + 1;
@@ -1079,7 +1080,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1079 * Simulate an EOF on interrupt, allowing ACKs from the 1080 * Simulate an EOF on interrupt, allowing ACKs from the
1080 * server to drain. 1081 * server to drain.
1081 */ 1082 */
1082 if (interrupted) 1083 if (interrupted || status != SSH2_FX_OK)
1083 len = 0; 1084 len = 0;
1084 else do 1085 else do
1085 len = read(local_fd, data, conn->transfer_buflen); 1086 len = read(local_fd, data, conn->transfer_buflen);
@@ -1135,19 +1136,6 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1135 if (ack == NULL) 1136 if (ack == NULL)
1136 fatal("Can't find request for ID %u", r_id); 1137 fatal("Can't find request for ID %u", r_id);
1137 TAILQ_REMOVE(&acks, ack, tq); 1138 TAILQ_REMOVE(&acks, ack, tq);
1138
1139 if (status != SSH2_FX_OK) {
1140 error("Couldn't write to remote file \"%s\": %s",
1141 remote_path, fx2txt(status));
1142 if (showprogress)
1143 stop_progress_meter();
1144 do_close(conn, handle, handle_len);
1145 close(local_fd);
1146 xfree(data);
1147 xfree(ack);
1148 status = -1;
1149 goto done;
1150 }
1151 debug3("In write loop, ack for %u %u bytes at %lld", 1139 debug3("In write loop, ack for %u %u bytes at %lld",
1152 ack->id, ack->len, (long long)ack->offset); 1140 ack->id, ack->len, (long long)ack->offset);
1153 ++ackid; 1141 ++ackid;
@@ -1157,26 +1145,31 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1157 if (offset < 0) 1145 if (offset < 0)
1158 fatal("%s: offset < 0", __func__); 1146 fatal("%s: offset < 0", __func__);
1159 } 1147 }
1148 buffer_free(&msg);
1149
1160 if (showprogress) 1150 if (showprogress)
1161 stop_progress_meter(); 1151 stop_progress_meter();
1162 xfree(data); 1152 xfree(data);
1163 1153
1154 if (status != SSH2_FX_OK) {
1155 error("Couldn't write to remote file \"%s\": %s",
1156 remote_path, fx2txt(status));
1157 status = -1;
1158 }
1159
1164 if (close(local_fd) == -1) { 1160 if (close(local_fd) == -1) {
1165 error("Couldn't close local file \"%s\": %s", local_path, 1161 error("Couldn't close local file \"%s\": %s", local_path,
1166 strerror(errno)); 1162 strerror(errno));
1167 do_close(conn, handle, handle_len);
1168 status = -1; 1163 status = -1;
1169 goto done;
1170 } 1164 }
1171 1165
1172 /* Override umask and utimes if asked */ 1166 /* Override umask and utimes if asked */
1173 if (pflag) 1167 if (pflag)
1174 do_fsetstat(conn, handle, handle_len, &a); 1168 do_fsetstat(conn, handle, handle_len, &a);
1175 1169
1176 status = do_close(conn, handle, handle_len); 1170 if (do_close(conn, handle, handle_len) != SSH2_FX_OK)
1177 1171 status = -1;
1178done:
1179 xfree(handle); 1172 xfree(handle);
1180 buffer_free(&msg); 1173
1181 return(status); 1174 return status;
1182} 1175}