]> andersk Git - openssh.git/blobdiff - sftp-client.c
- (tim) [regress/sftp-cmds.sh] s/cd/lcd/ in lls test. Reported by
[openssh.git] / sftp-client.c
index 8b4d67b58b46c9eca8bfd2b39f412fbee2af10e1..b189422d44c67fc6b143dce06bb15b55f3bce1e9 100644 (file)
@@ -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 <djm@openbsd.org>
  *
 #include "includes.h"
 
 #include <sys/types.h>
+#include <sys/param.h>
+#include "openbsd-compat/sys-queue.h"
 #ifdef HAVE_SYS_STAT_H
 # include <sys/stat.h>
 #endif
-# include <signal.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/uio.h>
 
-#include "openbsd-compat/sys-queue.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
 
-#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"
@@ -60,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);
@@ -520,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)
 {
@@ -531,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)
@@ -672,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)
 {
@@ -718,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,
@@ -805,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);
@@ -978,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;
@@ -990,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;
@@ -1040,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;
@@ -1060,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);
@@ -1116,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;
 }
This page took 0.176413 seconds and 4 git commands to generate.