[BACK]Return to sftp-client.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/sftp-client.c between version 1.35 and 1.35.2.2

version 1.35, 2002/09/11 22:41:49 version 1.35.2.2, 2003/09/16 21:20:27
Line 1 
Line 1 
 /*  /*
  * 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   * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions   * modification, are permitted provided that the following conditions
Line 38 
Line 38 
 #include "xmalloc.h"  #include "xmalloc.h"
 #include "log.h"  #include "log.h"
 #include "atomicio.h"  #include "atomicio.h"
   #include "progressmeter.h"
   
 #include "sftp.h"  #include "sftp.h"
 #include "sftp-common.h"  #include "sftp-common.h"
 #include "sftp-client.h"  #include "sftp-client.h"
   
   extern int showprogress;
   
 /* Minimum amount of data to read at at time */  /* Minimum amount of data to read at at time */
 #define MIN_READ_SIZE   512  #define MIN_READ_SIZE   512
   
   /* Maximum packet size */
   #define MAX_MSG_LENGTH  (256 * 1024)
   
 struct sftp_conn {  struct sftp_conn {
         int fd_in;          int fd_in;
         int fd_out;          int fd_out;
Line 58 
Line 64 
 static void  static void
 send_msg(int fd, Buffer *m)  send_msg(int fd, Buffer *m)
 {  {
         int mlen = buffer_len(m);          u_char mlen[4];
         int len;  
         Buffer oqueue;  
   
         buffer_init(&oqueue);          if (buffer_len(m) > MAX_MSG_LENGTH)
         buffer_put_int(&oqueue, mlen);                  fatal("Outbound message too long %u", buffer_len(m));
         buffer_append(&oqueue, buffer_ptr(m), mlen);  
         buffer_consume(m, mlen);  
   
         len = atomicio(write, fd, buffer_ptr(&oqueue), buffer_len(&oqueue));          /* Send length first */
         if (len <= 0)          PUT_32BIT(mlen, buffer_len(m));
           if (atomicio(vwrite, fd, mlen, sizeof(mlen)) <= 0)
                 fatal("Couldn't send packet: %s", strerror(errno));                  fatal("Couldn't send packet: %s", strerror(errno));
   
         buffer_free(&oqueue);          if (atomicio(vwrite, fd, buffer_ptr(m), buffer_len(m)) <= 0)
                   fatal("Couldn't send packet: %s", strerror(errno));
   
           buffer_clear(m);
 }  }
   
 static void  static void
 get_msg(int fd, Buffer *m)  get_msg(int fd, Buffer *m)
 {  {
         u_int len, msg_len;          ssize_t len;
         unsigned char buf[4096];          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)          if (len == 0)
                 fatal("Connection closed");                  fatal("Connection closed");
         else if (len == -1)          else if (len == -1)
                 fatal("Couldn't read packet: %s", strerror(errno));                  fatal("Couldn't read packet: %s", strerror(errno));
   
         msg_len = GET_32BIT(buf);          msg_len = buffer_get_int(m);
         if (msg_len > 256 * 1024)          if (msg_len > MAX_MSG_LENGTH)
                 fatal("Received message too long %u", msg_len);                  fatal("Received message too long %u", msg_len);
   
         while (msg_len) {          buffer_append_space(m, msg_len);
                 len = atomicio(read, fd, buf, MIN(msg_len, sizeof(buf)));          len = atomicio(read, fd, buffer_ptr(m), msg_len);
                 if (len == 0)          if (len == 0)
                         fatal("Connection closed");                  fatal("Connection closed");
                 else if (len == -1)          else if (len == -1)
                         fatal("Couldn't read packet: %s", strerror(errno));                  fatal("Read packet: %s", strerror(errno));
   
                 msg_len -= len;  
                 buffer_append(m, buf, len);  
         }  
 }  }
   
 static void  static void
Line 371 
Line 374 
                                 error("Couldn't read directory: %s",                                  error("Couldn't read directory: %s",
                                     fx2txt(status));                                      fx2txt(status));
                                 do_close(conn, handle, handle_len);                                  do_close(conn, handle, handle_len);
                                   xfree(handle);
                                 return(status);                                  return(status);
                         }                          }
                 } else if (type != SSH2_FXP_NAME)                  } else if (type != SSH2_FXP_NAME)
Line 503 
Line 507 
                 if (quiet)                  if (quiet)
                         debug("Server version does not support lstat operation");                          debug("Server version does not support lstat operation");
                 else                  else
                         log("Server version does not support lstat operation");                          logit("Server version does not support lstat operation");
                 return(do_stat(conn, path, quiet));                  return(do_stat(conn, path, quiet));
         }          }
   
Line 660 
Line 664 
   
         status = get_status(conn->fd_in, id);          status = get_status(conn->fd_in, id);
         if (status != SSH2_FX_OK)          if (status != SSH2_FX_OK)
                 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,                  error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath,
                     newpath, fx2txt(status));                      newpath, fx2txt(status));
   
         return(status);          return(status);
Line 741 
Line 745 
         int read_error, write_errno;          int read_error, write_errno;
         u_int64_t offset, size;          u_int64_t offset, size;
         u_int handle_len, mode, type, id, buflen;          u_int handle_len, mode, type, id, buflen;
           off_t progress_counter;
         struct request {          struct request {
                 u_int id;                  u_int id;
                 u_int len;                  u_int len;
Line 758 
Line 763 
   
         /* XXX: should we preserve set[ug]id? */          /* XXX: should we preserve set[ug]id? */
         if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)          if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
                 mode = S_IWRITE | (a->perm & 0777);                  mode = a->perm & 0777;
         else          else
                 mode = 0666;                  mode = 0666;
   
         if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&          if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
             (a->perm & S_IFDIR)) {              (!S_ISREG(a->perm))) {
                 error("Cannot download a directory: %s", remote_path);                  error("Cannot download non-regular file: %s", remote_path);
                 return(-1);                  return(-1);
         }          }
   
Line 793 
Line 798 
                 return(-1);                  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) {          if (local_fd == -1) {
                 error("Couldn't open local file \"%s\" for writing: %s",                  error("Couldn't open local file \"%s\" for writing: %s",
                     local_path, strerror(errno));                      local_path, strerror(errno));
Line 805 
Line 811 
         /* Read from remote and write to local */          /* Read from remote and write to local */
         write_error = read_error = write_errno = num_req = offset = 0;          write_error = read_error = write_errno = num_req = offset = 0;
         max_req = 1;          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) {          while (num_req > 0 || max_req > 0) {
                 char *data;                  char *data;
                 u_int len;                  u_int len;
Line 857 
Line 873 
                             (unsigned long long)req->offset + len - 1);                              (unsigned long long)req->offset + len - 1);
                         if (len > req->len)                          if (len > req->len)
                                 fatal("Received more data than asked for "                                  fatal("Received more data than asked for "
                                       "%u > %u", len, req->len);                                      "%u > %u", len, req->len);
                         if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||                          if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||
                              atomicio(write, local_fd, data, len) != len) &&                              atomicio(vwrite, local_fd, data, len) != len) &&
                             !write_error) {                              !write_error) {
                                 write_errno = errno;                                  write_errno = errno;
                                 write_error = 1;                                  write_error = 1;
                                 max_req = 0;                                  max_req = 0;
                         }                          }
                           progress_counter += len;
                         xfree(data);                          xfree(data);
   
                         if (len == req->len) {                          if (len == req->len) {
Line 907 
Line 924 
                 }                  }
         }          }
   
           if (showprogress && size)
                   stop_progress_meter();
   
         /* Sanity check */          /* Sanity check */
         if (TAILQ_FIRST(&requests) != NULL)          if (TAILQ_FIRST(&requests) != NULL)
                 fatal("Transfer complete, but requests still in queue");                  fatal("Transfer complete, but requests still in queue");
Line 926 
Line 946 
                 /* Override umask and utimes if asked */                  /* Override umask and utimes if asked */
                 if (pflag && fchmod(local_fd, mode) == -1)                  if (pflag && fchmod(local_fd, mode) == -1)
                         error("Couldn't set mode on \"%s\": %s", local_path,                          error("Couldn't set mode on \"%s\": %s", local_path,
                               strerror(errno));                              strerror(errno));
                 if (pflag && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {                  if (pflag && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
                         struct timeval tv[2];                          struct timeval tv[2];
                         tv[0].tv_sec = a->atime;                          tv[0].tv_sec = a->atime;
Line 934 
Line 954 
                         tv[0].tv_usec = tv[1].tv_usec = 0;                          tv[0].tv_usec = tv[1].tv_usec = 0;
                         if (utimes(local_path, tv) == -1)                          if (utimes(local_path, tv) == -1)
                                 error("Can't set times on \"%s\": %s",                                  error("Can't set times on \"%s\": %s",
                                       local_path, strerror(errno));                                      local_path, strerror(errno));
                 }                  }
         }          }
         close(local_fd);          close(local_fd);
Line 979 
Line 999 
                 close(local_fd);                  close(local_fd);
                 return(-1);                  return(-1);
         }          }
           if (!S_ISREG(sb.st_mode)) {
                   error("%s is not a regular file", local_path);
                   close(local_fd);
                   return(-1);
           }
         stat_to_attrib(&sb, &a);          stat_to_attrib(&sb, &a);
   
         a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;          a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
Line 1013 
Line 1038 
   
         /* Read from local and write to remote */          /* Read from local and write to remote */
         offset = 0;          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 (;;) {          for (;;) {
                 int len;                  int len;
   
Line 1043 
Line 1073 
                         buffer_put_string(&msg, data, len);                          buffer_put_string(&msg, data, len);
                         send_msg(conn->fd_out, &msg);                          send_msg(conn->fd_out, &msg);
                         debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",                          debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
                                id, (unsigned long long)offset, len);                              id, (unsigned long long)offset, len);
                 } else if (TAILQ_FIRST(&acks) == NULL)                  } else if (TAILQ_FIRST(&acks) == NULL)
                         break;                          break;
   
Line 1077 
Line 1107 
   
                         if (status != SSH2_FX_OK) {                          if (status != SSH2_FX_OK) {
                                 error("Couldn't write to remote file \"%s\": %s",                                  error("Couldn't write to remote file \"%s\": %s",
                                       remote_path, fx2txt(status));                                      remote_path, fx2txt(status));
                                 do_close(conn, handle, handle_len);                                  do_close(conn, handle, handle_len);
                                 close(local_fd);                                  close(local_fd);
                                   xfree(data);
                                   xfree(ack);
                                 goto done;                                  goto done;
                         }                          }
                         debug3("In write loop, ack for %u %u bytes at %llu",                          debug3("In write loop, ack for %u %u bytes at %llu",
Line 1089 
Line 1121 
                 }                  }
                 offset += len;                  offset += len;
         }          }
           if (showprogress)
                   stop_progress_meter();
         xfree(data);          xfree(data);
   
         if (close(local_fd) == -1) {          if (close(local_fd) == -1) {

Legend:
Removed from v.1.35  
changed lines
  Added in v.1.35.2.2