]> andersk Git - openssh.git/blobdiff - sftp-client.c
- djm@cvs.openbsd.org 2003/01/10 10:29:35
[openssh.git] / sftp-client.c
index df9838648f99466cd1e9d98a1398a12d8cac33b8..3fac22beeb26943da6278a0e2872e95f69246eb2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001,2002 Damien Miller.  All rights reserved.
+ * Copyright (c) 2001-2003 Damien Miller.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,7 +28,7 @@
 /* XXX: copy between two remote sites */
 
 #include "includes.h"
-RCSID("$OpenBSD: sftp-client.c,v 1.37 2002/11/21 23:03:51 deraadt Exp $");
+RCSID("$OpenBSD: sftp-client.c,v 1.40 2003/01/10 08:48:15 djm Exp $");
 
 #include "openbsd-compat/sys-queue.h"
 
@@ -38,14 +38,20 @@ RCSID("$OpenBSD: sftp-client.c,v 1.37 2002/11/21 23:03:51 deraadt Exp $");
 #include "xmalloc.h"
 #include "log.h"
 #include "atomicio.h"
+#include "progressmeter.h"
 
 #include "sftp.h"
 #include "sftp-common.h"
 #include "sftp-client.h"
 
+extern int showprogress;
+
 /* Minimum amount of data to read at at time */
 #define MIN_READ_SIZE  512
 
+/* Maximum packet size */
+#define MAX_MSG_LENGTH (256 * 1024)
+
 struct sftp_conn {
        int fd_in;
        int fd_out;
@@ -58,48 +64,45 @@ struct sftp_conn {
 static void
 send_msg(int fd, Buffer *m)
 {
-       int mlen = buffer_len(m);
-       int len;
-       Buffer oqueue;
+       u_char mlen[4];
 
-       buffer_init(&oqueue);
-       buffer_put_int(&oqueue, mlen);
-       buffer_append(&oqueue, buffer_ptr(m), mlen);
-       buffer_consume(m, mlen);
+       if (buffer_len(m) > MAX_MSG_LENGTH)
+               fatal("Outbound message too long %u", buffer_len(m));
+
+       /* Send length first */
+       PUT_32BIT(mlen, buffer_len(m));
+       if (atomicio(write, fd, mlen, sizeof(mlen)) <= 0)
+               fatal("Couldn't send packet: %s", strerror(errno));
 
-       len = atomicio(write, fd, buffer_ptr(&oqueue), buffer_len(&oqueue));
-       if (len <= 0)
+       if (atomicio(write, fd, buffer_ptr(m), buffer_len(m)) <= 0)
                fatal("Couldn't send packet: %s", strerror(errno));
 
-       buffer_free(&oqueue);
+       buffer_clear(m);
 }
 
 static void
 get_msg(int fd, Buffer *m)
 {
-       u_int len, msg_len;
-       unsigned char buf[4096];
+       ssize_t len;
+       u_int msg_len;
 
-       len = atomicio(read, fd, buf, 4);
+       buffer_append_space(m, 4);
+       len = atomicio(read, fd, buffer_ptr(m), 4);
        if (len == 0)
                fatal("Connection closed");
        else if (len == -1)
                fatal("Couldn't read packet: %s", strerror(errno));
 
-       msg_len = GET_32BIT(buf);
-       if (msg_len > 256 * 1024)
+       msg_len = buffer_get_int(m);
+       if (msg_len > MAX_MSG_LENGTH)
                fatal("Received message too long %u", msg_len);
 
-       while (msg_len) {
-               len = atomicio(read, fd, buf, MIN(msg_len, sizeof(buf)));
-               if (len == 0)
-                       fatal("Connection closed");
-               else if (len == -1)
-                       fatal("Couldn't read packet: %s", strerror(errno));
-
-               msg_len -= len;
-               buffer_append(m, buf, len);
-       }
+       buffer_append_space(m, msg_len);
+       len = atomicio(read, fd, buffer_ptr(m), msg_len);
+       if (len == 0)
+               fatal("Connection closed");
+       else if (len == -1)
+               fatal("Read packet: %s", strerror(errno));
 }
 
 static void
@@ -741,6 +744,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
        int read_error, write_errno;
        u_int64_t offset, size;
        u_int handle_len, mode, type, id, buflen;
+       off_t progress_counter;
        struct request {
                u_int id;
                u_int len;
@@ -758,7 +762,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
 
        /* XXX: should we preserve set[ug]id? */
        if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
-               mode = S_IWRITE | (a->perm & 0777);
+               mode = a->perm & 0777;
        else
                mode = 0666;
 
@@ -793,7 +797,8 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
                return(-1);
        }
 
-       local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode);
+       local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, 
+           mode | S_IWRITE);
        if (local_fd == -1) {
                error("Couldn't open local file \"%s\" for writing: %s",
                    local_path, strerror(errno));
@@ -805,6 +810,16 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
        /* Read from remote and write to local */
        write_error = read_error = write_errno = num_req = offset = 0;
        max_req = 1;
+       progress_counter = 0;
+
+       if (showprogress) {
+               if (size)
+                       start_progress_meter(remote_path, size,
+                           &progress_counter);
+               else
+                       printf("Fetching %s to %s\n", remote_path, local_path);
+       }
+
        while (num_req > 0 || max_req > 0) {
                char *data;
                u_int len;
@@ -865,6 +880,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
                                write_error = 1;
                                max_req = 0;
                        }
+                       progress_counter += len;
                        xfree(data);
 
                        if (len == req->len) {
@@ -907,6 +923,9 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
                }
        }
 
+       if (showprogress && size)
+               stop_progress_meter();
+
        /* Sanity check */
        if (TAILQ_FIRST(&requests) != NULL)
                fatal("Transfer complete, but requests still in queue");
@@ -1017,6 +1036,11 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
 
        /* Read from local and write to remote */
        offset = 0;
+       if (showprogress)
+               start_progress_meter(local_path, sb.st_size, &offset);
+       else
+               printf("Uploading %s to %s\n", local_path, remote_path);
+
        for (;;) {
                int len;
 
@@ -1093,6 +1117,8 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
                }
                offset += len;
        }
+       if (showprogress)
+               stop_progress_meter();
        xfree(data);
 
        if (close(local_fd) == -1) {
This page took 0.048606 seconds and 4 git commands to generate.