X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/3eee3b86610204038cf2216886afafb5954cdfef..caba7de7d39b58f9f4fa9f33ca04531e0358e266:/sftp-client.c diff --git a/sftp-client.c b/sftp-client.c index 05bce336..b189422d 100644 --- a/sftp-client.c +++ b/sftp-client.c @@ -1,3 +1,4 @@ +/* $OpenBSD: sftp-client.c,v 1.80 2008/01/21 19:20:17 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -20,17 +21,32 @@ /* XXX: copy between two remote sites */ #include "includes.h" -RCSID("$OpenBSD: sftp-client.c,v 1.58 2006/01/02 01:20:31 djm Exp $"); +#include +#include #include "openbsd-compat/sys-queue.h" +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_SYS_TIME_H +# include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include -#include "buffer.h" -#include "bufaux.h" -#include "getput.h" #include "xmalloc.h" +#include "buffer.h" #include "log.h" #include "atomicio.h" #include "progressmeter.h" +#include "misc.h" #include "sftp.h" #include "sftp-common.h" @@ -39,7 +55,7 @@ RCSID("$OpenBSD: sftp-client.c,v 1.58 2006/01/02 01:20:31 djm Exp $"); extern volatile sig_atomic_t interrupted; extern int showprogress; -/* Minimum amount of data to read at at time */ +/* Minimum amount of data to read at a time */ #define MIN_READ_SIZE 512 struct sftp_conn { @@ -55,16 +71,19 @@ static void send_msg(int fd, Buffer *m) { u_char mlen[4]; + struct iovec iov[2]; if (buffer_len(m) > SFTP_MAX_MSG_LENGTH) fatal("Outbound message too long %u", buffer_len(m)); /* Send length first */ - PUT_32BIT(mlen, buffer_len(m)); - if (atomicio(vwrite, fd, mlen, sizeof(mlen)) != sizeof(mlen)) - fatal("Couldn't send packet: %s", strerror(errno)); + put_u32(mlen, buffer_len(m)); + iov[0].iov_base = mlen; + iov[0].iov_len = sizeof(mlen); + iov[1].iov_base = buffer_ptr(m); + iov[1].iov_len = buffer_len(m); - if (atomicio(vwrite, fd, buffer_ptr(m), buffer_len(m)) != buffer_len(m)) + if (atomiciov(writev, fd, iov, 2) != buffer_len(m) + sizeof(mlen)) fatal("Couldn't send packet: %s", strerror(errno)); buffer_clear(m); @@ -388,8 +407,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag, printf("%s\n", longname); if (dir) { - *dir = xrealloc(*dir, sizeof(**dir) * - (ents + 2)); + *dir = xrealloc(*dir, ents + 2, sizeof(**dir)); (*dir)[ents] = xmalloc(sizeof(***dir)); (*dir)[ents]->filename = xstrdup(filename); (*dir)[ents]->longname = xstrdup(longname); @@ -516,6 +534,7 @@ do_lstat(struct sftp_conn *conn, char *path, int quiet) return(get_decode_stat(conn->fd_in, id, quiet)); } +#ifdef notyet Attrib * do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) { @@ -527,6 +546,7 @@ do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) return(get_decode_stat(conn->fd_in, id, quiet)); } +#endif int do_setstat(struct sftp_conn *conn, char *path, Attrib *a) @@ -668,6 +688,7 @@ do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) return(status); } +#ifdef notyet char * do_readlink(struct sftp_conn *conn, char *path) { @@ -714,6 +735,7 @@ do_readlink(struct sftp_conn *conn, char *path) return(filename); } +#endif static void send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len, @@ -801,6 +823,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, if (local_fd == -1) { error("Couldn't open local file \"%s\" for writing: %s", local_path, strerror(errno)); + do_close(conn, handle, handle_len); buffer_free(&msg); xfree(handle); return(-1); @@ -974,9 +997,10 @@ 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; - u_int64_t offset; + off_t offset; char *handle, *data; Buffer msg; struct stat sb; @@ -986,7 +1010,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, struct outstanding_ack { u_int id; u_int len; - u_int64_t offset; + off_t offset; TAILQ_ENTRY(outstanding_ack) tq; }; TAILQ_HEAD(ackhead, outstanding_ack) acks; @@ -1036,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; @@ -1056,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); @@ -1112,43 +1136,40 @@ 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)); - do_close(conn, handle, handle_len); - close(local_fd); - xfree(data); - xfree(ack); - goto done; - } - debug3("In write loop, ack for %u %u bytes at %llu", - ack->id, ack->len, (unsigned long long)ack->offset); + debug3("In write loop, ack for %u %u bytes at %lld", + ack->id, ack->len, (long long)ack->offset); ++ackid; xfree(ack); } offset += len; + 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; }