From acdf25b31f02c010ed2b5f655bbae0f5b75f07f6 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sun, 10 Feb 2008 22:27:24 +1100 Subject: [PATCH] - 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 --- ChangeLog | 6 +++++- sftp-client.c | 41 +++++++++++++++++------------------------ 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index dd8f6abea..dfda7a5d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -54,6 +54,10 @@ Remove the fixed 100 handle limit in sftp-server and allocate as many as we have available file descriptors. Patch from miklos AT szeredi.hu; ok dtucker@ markus@ + - 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 20080119 - (djm) Silence noice from expr in ssh-copy-id; patch from @@ -3582,4 +3586,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4830 2008/02/10 11:26:51 djm Exp $ +$Id: ChangeLog,v 1.4831 2008/02/10 11:27:24 djm Exp $ 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 @@ -/* $OpenBSD: sftp-client.c,v 1.79 2008/01/19 22:04:57 djm Exp $ */ +/* $OpenBSD: sftp-client.c,v 1.80 2008/01/21 19:20:17 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -997,7 +997,8 @@ int do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, int pflag) { - int local_fd, status; + int local_fd; + int status = SSH2_FX_OK; u_int handle_len, id, type; off_t offset; char *handle, *data; @@ -1059,7 +1060,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, if (handle == NULL) { close(local_fd); buffer_free(&msg); - return(-1); + return -1; } startid = ackid = id + 1; @@ -1079,7 +1080,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, * Simulate an EOF on interrupt, allowing ACKs from the * server to drain. */ - if (interrupted) + if (interrupted || status != SSH2_FX_OK) len = 0; else do len = read(local_fd, data, conn->transfer_buflen); @@ -1135,19 +1136,6 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, if (ack == NULL) fatal("Can't find request for ID %u", r_id); TAILQ_REMOVE(&acks, ack, tq); - - if (status != SSH2_FX_OK) { - error("Couldn't write to remote file \"%s\": %s", - remote_path, fx2txt(status)); - if (showprogress) - stop_progress_meter(); - do_close(conn, handle, handle_len); - close(local_fd); - xfree(data); - xfree(ack); - status = -1; - goto done; - } debug3("In write loop, ack for %u %u bytes at %lld", ack->id, ack->len, (long long)ack->offset); ++ackid; @@ -1157,26 +1145,31 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, if (offset < 0) fatal("%s: offset < 0", __func__); } + buffer_free(&msg); + if (showprogress) stop_progress_meter(); xfree(data); + if (status != SSH2_FX_OK) { + error("Couldn't write to remote file \"%s\": %s", + remote_path, fx2txt(status)); + status = -1; + } + if (close(local_fd) == -1) { error("Couldn't close local file \"%s\": %s", local_path, strerror(errno)); - do_close(conn, handle, handle_len); status = -1; - goto done; } /* Override umask and utimes if asked */ if (pflag) do_fsetstat(conn, handle, handle_len, &a); - status = do_close(conn, handle, handle_len); - -done: + if (do_close(conn, handle, handle_len) != SSH2_FX_OK) + status = -1; xfree(handle); - buffer_free(&msg); - return(status); + + return status; }