[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.22 and 1.23

version 1.22, 2002/02/12 12:44:46 version 1.23, 2002/02/13 00:59:23
Line 1 
Line 1 
 /*  /*
  * Copyright (c) 2001-2002 Damien Miller.  All rights reserved.   * Copyright (c) 2001,2002 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 24 
Line 24 
   
 /* XXX: memleaks */  /* XXX: memleaks */
 /* XXX: signed vs unsigned */  /* XXX: signed vs unsigned */
 /* XXX: we use fatal too much, error may be more appropriate in places */  /* XXX: remove all logging, only return status codes */
 /* XXX: copy between two remote sites */  /* XXX: copy between two remote sites */
   
 #include "includes.h"  #include "includes.h"
Line 46 
Line 46 
 /* 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
   
 /* Message ID */  struct sftp_conn {
 static u_int msg_id = 1;          int fd_in;
           int fd_out;
           u_int transfer_buflen;
           u_int num_requests;
           u_int version;
           u_int msg_id;
   };
   
 static void  static void
 send_msg(int fd, Buffer *m)  send_msg(int fd, Buffer *m)
Line 215 
Line 221 
         return(a);          return(a);
 }  }
   
 int  struct sftp_conn *
 do_init(int fd_in, int fd_out)  do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
 {  {
         int type, version;          int type, version;
         Buffer msg;          Buffer msg;
           struct sftp_conn *ret;
   
         buffer_init(&msg);          buffer_init(&msg);
         buffer_put_char(&msg, SSH2_FXP_INIT);          buffer_put_char(&msg, SSH2_FXP_INIT);
Line 235 
Line 242 
                 error("Invalid packet back from SSH2_FXP_INIT (type %d)",                  error("Invalid packet back from SSH2_FXP_INIT (type %d)",
                     type);                      type);
                 buffer_free(&msg);                  buffer_free(&msg);
                 return(-1);                  return(NULL);
         }          }
         version = buffer_get_int(&msg);          version = buffer_get_int(&msg);
   
Line 253 
Line 260 
   
         buffer_free(&msg);          buffer_free(&msg);
   
         return(version);          ret = xmalloc(sizeof(*ret));
           ret->fd_in = fd_in;
           ret->fd_out = fd_out;
           ret->transfer_buflen = transfer_buflen;
           ret->num_requests = num_requests;
           ret->version = version;
           ret->msg_id = 1;
   
           /* Some filexfer v.0 servers don't support large packets */
           if (version == 0)
                   ret->transfer_buflen = MAX(ret->transfer_buflen, 20480);
   
           return(ret);
 }  }
   
   u_int
   sftp_proto_version(struct sftp_conn *conn)
   {
           return(conn->version);
   }
   
 int  int
 do_close(int fd_in, int fd_out, char *handle, u_int handle_len)  do_close(struct sftp_conn *conn, char *handle, u_int handle_len)
 {  {
         u_int id, status;          u_int id, status;
         Buffer msg;          Buffer msg;
   
         buffer_init(&msg);          buffer_init(&msg);
   
         id = msg_id++;          id = conn->msg_id++;
         buffer_put_char(&msg, SSH2_FXP_CLOSE);          buffer_put_char(&msg, SSH2_FXP_CLOSE);
         buffer_put_int(&msg, id);          buffer_put_int(&msg, id);
         buffer_put_string(&msg, handle, handle_len);          buffer_put_string(&msg, handle, handle_len);
         send_msg(fd_out, &msg);          send_msg(conn->fd_out, &msg);
         debug3("Sent message SSH2_FXP_CLOSE I:%d", id);          debug3("Sent message SSH2_FXP_CLOSE I:%d", id);
   
         status = get_status(fd_in, id);          status = get_status(conn->fd_in, id);
         if (status != SSH2_FX_OK)          if (status != SSH2_FX_OK)
                 error("Couldn't close file: %s", fx2txt(status));                  error("Couldn't close file: %s", fx2txt(status));
   
Line 282 
Line 307 
   
   
 static int  static int
 do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,  do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
     SFTP_DIRENT ***dir)      SFTP_DIRENT ***dir)
 {  {
         Buffer msg;          Buffer msg;
         u_int type, id, handle_len, i, expected_id, ents = 0;          u_int type, id, handle_len, i, expected_id, ents = 0;
         char *handle;          char *handle;
   
         id = msg_id++;          id = conn->msg_id++;
   
         buffer_init(&msg);          buffer_init(&msg);
         buffer_put_char(&msg, SSH2_FXP_OPENDIR);          buffer_put_char(&msg, SSH2_FXP_OPENDIR);
         buffer_put_int(&msg, id);          buffer_put_int(&msg, id);
         buffer_put_cstring(&msg, path);          buffer_put_cstring(&msg, path);
         send_msg(fd_out, &msg);          send_msg(conn->fd_out, &msg);
   
         buffer_clear(&msg);          buffer_clear(&msg);
   
         handle = get_handle(fd_in, id, &handle_len);          handle = get_handle(conn->fd_in, id, &handle_len);
         if (handle == NULL)          if (handle == NULL)
                 return(-1);                  return(-1);
   
Line 312 
Line 337 
         for (;;) {          for (;;) {
                 int count;                  int count;
   
                 id = expected_id = msg_id++;                  id = expected_id = conn->msg_id++;
   
                 debug3("Sending SSH2_FXP_READDIR I:%d", id);                  debug3("Sending SSH2_FXP_READDIR I:%d", id);
   
Line 320 
Line 345 
                 buffer_put_char(&msg, SSH2_FXP_READDIR);                  buffer_put_char(&msg, SSH2_FXP_READDIR);
                 buffer_put_int(&msg, id);                  buffer_put_int(&msg, id);
                 buffer_put_string(&msg, handle, handle_len);                  buffer_put_string(&msg, handle, handle_len);
                 send_msg(fd_out, &msg);                  send_msg(conn->fd_out, &msg);
   
                 buffer_clear(&msg);                  buffer_clear(&msg);
   
                 get_msg(fd_in, &msg);                  get_msg(conn->fd_in, &msg);
   
                 type = buffer_get_char(&msg);                  type = buffer_get_char(&msg);
                 id = buffer_get_int(&msg);                  id = buffer_get_int(&msg);
Line 344 
Line 369 
                         } else {                          } else {
                                 error("Couldn't read directory: %s",                                  error("Couldn't read directory: %s",
                                     fx2txt(status));                                      fx2txt(status));
                                 do_close(fd_in, fd_out, handle, handle_len);                                  do_close(conn, handle, handle_len);
                                 return(status);                                  return(status);
                         }                          }
                 } else if (type != SSH2_FXP_NAME)                  } else if (type != SSH2_FXP_NAME)
Line 382 
Line 407 
         }          }
   
         buffer_free(&msg);          buffer_free(&msg);
         do_close(fd_in, fd_out, handle, handle_len);          do_close(conn, handle, handle_len);
         xfree(handle);          xfree(handle);
   
         return(0);          return(0);
 }  }
   
 int  int
 do_ls(int fd_in, int fd_out, char *path)  do_ls(struct sftp_conn *conn, char *path)
 {  {
         return(do_lsreaddir(fd_in, fd_out, path, 1, NULL));          return(do_lsreaddir(conn, path, 1, NULL));
 }  }
   
 int  int
 do_readdir(int fd_in, int fd_out, char *path, SFTP_DIRENT ***dir)  do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir)
 {  {
         return(do_lsreaddir(fd_in, fd_out, path, 0, dir));          return(do_lsreaddir(conn, path, 0, dir));
 }  }
   
 void free_sftp_dirents(SFTP_DIRENT **s)  void free_sftp_dirents(SFTP_DIRENT **s)
Line 413 
Line 438 
 }  }
   
 int  int
 do_rm(int fd_in, int fd_out, char *path)  do_rm(struct sftp_conn *conn, char *path)
 {  {
         u_int status, id;          u_int status, id;
   
         debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);          debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
   
         id = msg_id++;          id = conn->msg_id++;
         send_string_request(fd_out, id, SSH2_FXP_REMOVE, path, strlen(path));          send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path,
         status = get_status(fd_in, id);              strlen(path));
           status = get_status(conn->fd_in, id);
         if (status != SSH2_FX_OK)          if (status != SSH2_FX_OK)
                 error("Couldn't delete file: %s", fx2txt(status));                  error("Couldn't delete file: %s", fx2txt(status));
         return(status);          return(status);
 }  }
   
 int  int
 do_mkdir(int fd_in, int fd_out, char *path, Attrib *a)  do_mkdir(struct sftp_conn *conn, char *path, Attrib *a)
 {  {
         u_int status, id;          u_int status, id;
   
         id = msg_id++;          id = conn->msg_id++;
         send_string_attrs_request(fd_out, id, SSH2_FXP_MKDIR, path,          send_string_attrs_request(conn->fd_out, id, SSH2_FXP_MKDIR, path,
             strlen(path), a);              strlen(path), a);
   
         status = get_status(fd_in, id);          status = get_status(conn->fd_in, id);
         if (status != SSH2_FX_OK)          if (status != SSH2_FX_OK)
                 error("Couldn't create directory: %s", fx2txt(status));                  error("Couldn't create directory: %s", fx2txt(status));
   
Line 444 
Line 470 
 }  }
   
 int  int
 do_rmdir(int fd_in, int fd_out, char *path)  do_rmdir(struct sftp_conn *conn, char *path)
 {  {
         u_int status, id;          u_int status, id;
   
         id = msg_id++;          id = conn->msg_id++;
         send_string_request(fd_out, id, SSH2_FXP_RMDIR, path, strlen(path));          send_string_request(conn->fd_out, id, SSH2_FXP_RMDIR, path,
               strlen(path));
   
         status = get_status(fd_in, id);          status = get_status(conn->fd_in, id);
         if (status != SSH2_FX_OK)          if (status != SSH2_FX_OK)
                 error("Couldn't remove directory: %s", fx2txt(status));                  error("Couldn't remove directory: %s", fx2txt(status));
   
Line 459 
Line 486 
 }  }
   
 Attrib *  Attrib *
 do_stat(int fd_in, int fd_out, char *path, int quiet)  do_stat(struct sftp_conn *conn, char *path, int quiet)
 {  {
         u_int id;          u_int id;
   
         id = msg_id++;          id = conn->msg_id++;
         send_string_request(fd_out, id, SSH2_FXP_STAT, path, strlen(path));  
         return(get_decode_stat(fd_in, id, quiet));          send_string_request(conn->fd_out, id,
               conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
               path, strlen(path));
   
           return(get_decode_stat(conn->fd_in, id, quiet));
 }  }
   
 Attrib *  Attrib *
 do_lstat(int fd_in, int fd_out, char *path, int quiet)  do_lstat(struct sftp_conn *conn, char *path, int quiet)
 {  {
         u_int id;          u_int id;
   
         id = msg_id++;          if (conn->version == 0) {
         send_string_request(fd_out, id, SSH2_FXP_LSTAT, path, strlen(path));                  if (quiet)
         return(get_decode_stat(fd_in, id, quiet));                          debug("Server version does not support lstat operation");
                   else
                           error("Server version does not support lstat operation");
                   return(NULL);
           }
   
           id = conn->msg_id++;
           send_string_request(conn->fd_out, id, SSH2_FXP_LSTAT, path,
               strlen(path));
   
           return(get_decode_stat(conn->fd_in, id, quiet));
 }  }
   
 Attrib *  Attrib *
 do_fstat(int fd_in, int fd_out, char *handle, u_int handle_len, int quiet)  do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
 {  {
         u_int id;          u_int id;
   
         id = msg_id++;          id = conn->msg_id++;
         send_string_request(fd_out, id, SSH2_FXP_FSTAT, handle, handle_len);          send_string_request(conn->fd_out, id, SSH2_FXP_FSTAT, handle,
         return(get_decode_stat(fd_in, id, quiet));              handle_len);
   
           return(get_decode_stat(conn->fd_in, id, quiet));
 }  }
   
 int  int
 do_setstat(int fd_in, int fd_out, char *path, Attrib *a)  do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
 {  {
         u_int status, id;          u_int status, id;
   
         id = msg_id++;          id = conn->msg_id++;
         send_string_attrs_request(fd_out, id, SSH2_FXP_SETSTAT, path,          send_string_attrs_request(conn->fd_out, id, SSH2_FXP_SETSTAT, path,
             strlen(path), a);              strlen(path), a);
   
         status = get_status(fd_in, id);          status = get_status(conn->fd_in, id);
         if (status != SSH2_FX_OK)          if (status != SSH2_FX_OK)
                 error("Couldn't setstat on \"%s\": %s", path,                  error("Couldn't setstat on \"%s\": %s", path,
                     fx2txt(status));                      fx2txt(status));
Line 506 
Line 549 
 }  }
   
 int  int
 do_fsetstat(int fd_in, int fd_out, char *handle, u_int handle_len,  do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len,
     Attrib *a)      Attrib *a)
 {  {
         u_int status, id;          u_int status, id;
   
         id = msg_id++;          id = conn->msg_id++;
         send_string_attrs_request(fd_out, id, SSH2_FXP_FSETSTAT, handle,          send_string_attrs_request(conn->fd_out, id, SSH2_FXP_FSETSTAT, handle,
             handle_len, a);              handle_len, a);
   
         status = get_status(fd_in, id);          status = get_status(conn->fd_in, id);
         if (status != SSH2_FX_OK)          if (status != SSH2_FX_OK)
                 error("Couldn't fsetstat: %s", fx2txt(status));                  error("Couldn't fsetstat: %s", fx2txt(status));
   
Line 523 
Line 566 
 }  }
   
 char *  char *
 do_realpath(int fd_in, int fd_out, char *path)  do_realpath(struct sftp_conn *conn, char *path)
 {  {
         Buffer msg;          Buffer msg;
         u_int type, expected_id, count, id;          u_int type, expected_id, count, id;
         char *filename, *longname;          char *filename, *longname;
         Attrib *a;          Attrib *a;
   
         expected_id = id = msg_id++;          expected_id = id = conn->msg_id++;
         send_string_request(fd_out, id, SSH2_FXP_REALPATH, path, strlen(path));          send_string_request(conn->fd_out, id, SSH2_FXP_REALPATH, path,
               strlen(path));
   
         buffer_init(&msg);          buffer_init(&msg);
   
         get_msg(fd_in, &msg);          get_msg(conn->fd_in, &msg);
         type = buffer_get_char(&msg);          type = buffer_get_char(&msg);
         id = buffer_get_int(&msg);          id = buffer_get_int(&msg);
   
Line 569 
Line 613 
 }  }
   
 int  int
 do_rename(int fd_in, int fd_out, char *oldpath, char *newpath)  do_rename(struct sftp_conn *conn, char *oldpath, char *newpath)
 {  {
         Buffer msg;          Buffer msg;
         u_int status, id;          u_int status, id;
Line 577 
Line 621 
         buffer_init(&msg);          buffer_init(&msg);
   
         /* Send rename request */          /* Send rename request */
         id = msg_id++;          id = conn->msg_id++;
         buffer_put_char(&msg, SSH2_FXP_RENAME);          buffer_put_char(&msg, SSH2_FXP_RENAME);
         buffer_put_int(&msg, id);          buffer_put_int(&msg, id);
         buffer_put_cstring(&msg, oldpath);          buffer_put_cstring(&msg, oldpath);
         buffer_put_cstring(&msg, newpath);          buffer_put_cstring(&msg, newpath);
         send_msg(fd_out, &msg);          send_msg(conn->fd_out, &msg);
         debug3("Sent message SSH2_FXP_RENAME \"%s\" -> \"%s\"", oldpath,          debug3("Sent message SSH2_FXP_RENAME \"%s\" -> \"%s\"", oldpath,
             newpath);              newpath);
         buffer_free(&msg);          buffer_free(&msg);
   
         status = get_status(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, newpath,                  error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
                     fx2txt(status));                      newpath, fx2txt(status));
   
         return(status);          return(status);
 }  }
   
 int  int
 do_symlink(int fd_in, int fd_out, char *oldpath, char *newpath)  do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
 {  {
         Buffer msg;          Buffer msg;
         u_int status, id;          u_int status, id;
   
           if (conn->version < 3) {
                   error("This server does not support the symlink operation");
                   return(SSH2_FX_OP_UNSUPPORTED);
           }
   
         buffer_init(&msg);          buffer_init(&msg);
   
         /* Send rename request */          /* Send rename request */
         id = msg_id++;          id = conn->msg_id++;
         buffer_put_char(&msg, SSH2_FXP_SYMLINK);          buffer_put_char(&msg, SSH2_FXP_SYMLINK);
         buffer_put_int(&msg, id);          buffer_put_int(&msg, id);
         buffer_put_cstring(&msg, oldpath);          buffer_put_cstring(&msg, oldpath);
         buffer_put_cstring(&msg, newpath);          buffer_put_cstring(&msg, newpath);
         send_msg(fd_out, &msg);          send_msg(conn->fd_out, &msg);
         debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,          debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
             newpath);              newpath);
         buffer_free(&msg);          buffer_free(&msg);
   
         status = get_status(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, newpath,                  error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
                     fx2txt(status));                      newpath, fx2txt(status));
   
         return(status);          return(status);
 }  }
   
 char *  char *
 do_readlink(int fd_in, int fd_out, char *path)  do_readlink(struct sftp_conn *conn, char *path)
 {  {
         Buffer msg;          Buffer msg;
         u_int type, expected_id, count, id;          u_int type, expected_id, count, id;
         char *filename, *longname;          char *filename, *longname;
         Attrib *a;          Attrib *a;
   
         expected_id = id = msg_id++;          expected_id = id = conn->msg_id++;
         send_string_request(fd_out, id, SSH2_FXP_READLINK, path, strlen(path));          send_string_request(conn->fd_out, id, SSH2_FXP_READLINK, path,
               strlen(path));
   
         buffer_init(&msg);          buffer_init(&msg);
   
         get_msg(fd_in, &msg);          get_msg(conn->fd_in, &msg);
         type = buffer_get_char(&msg);          type = buffer_get_char(&msg);
         id = buffer_get_int(&msg);          id = buffer_get_int(&msg);
   
Line 686 
Line 736 
 }  }
   
 int  int
 do_download(int fd_in, int fd_out, char *remote_path, char *local_path,  do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
     int pflag, size_t buflen, int num_requests)      int pflag)
 {  {
         Attrib junk, *a;          Attrib junk, *a;
         Buffer msg;          Buffer msg;
Line 695 
Line 745 
         int local_fd, status, num_req, max_req, write_error;          int local_fd, status, num_req, max_req, write_error;
         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;          u_int handle_len, mode, type, id, buflen;
         struct request {          struct request {
                 u_int id;                  u_int id;
                 u_int len;                  u_int len;
Line 707 
Line 757 
   
         TAILQ_INIT(&requests);          TAILQ_INIT(&requests);
   
         a = do_stat(fd_in, fd_out, remote_path, 0);          a = do_stat(conn, remote_path, 0);
         if (a == NULL)          if (a == NULL)
                 return(-1);                  return(-1);
   
Line 728 
Line 778 
         else          else
                 size = 0;                  size = 0;
   
         local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode);          buflen = conn->transfer_buflen;
         if (local_fd == -1) {  
                 error("Couldn't open local file \"%s\" for writing: %s",  
                     local_path, strerror(errno));  
                 return(-1);  
         }  
   
         buffer_init(&msg);          buffer_init(&msg);
   
         /* Send open request */          /* Send open request */
         id = msg_id++;          id = conn->msg_id++;
         buffer_put_char(&msg, SSH2_FXP_OPEN);          buffer_put_char(&msg, SSH2_FXP_OPEN);
         buffer_put_int(&msg, id);          buffer_put_int(&msg, id);
         buffer_put_cstring(&msg, remote_path);          buffer_put_cstring(&msg, remote_path);
         buffer_put_int(&msg, SSH2_FXF_READ);          buffer_put_int(&msg, SSH2_FXF_READ);
         attrib_clear(&junk); /* Send empty attributes */          attrib_clear(&junk); /* Send empty attributes */
         encode_attrib(&msg, &junk);          encode_attrib(&msg, &junk);
         send_msg(fd_out, &msg);          send_msg(conn->fd_out, &msg);
         debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path);          debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path);
   
         handle = get_handle(fd_in, id, &handle_len);          handle = get_handle(conn->fd_in, id, &handle_len);
         if (handle == NULL) {          if (handle == NULL) {
                 buffer_free(&msg);                  buffer_free(&msg);
                 close(local_fd);                  close(local_fd);
                 return(-1);                  return(-1);
         }          }
   
           local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode);
           if (local_fd == -1) {
                   error("Couldn't open local file \"%s\" for writing: %s",
                       local_path, strerror(errno));
                   return(-1);
           }
   
         /* 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;
Line 767 
Line 818 
                         debug3("Request range %llu -> %llu (%d/%d)",                          debug3("Request range %llu -> %llu (%d/%d)",
                             offset, offset + buflen - 1, num_req, max_req);                              offset, offset + buflen - 1, num_req, max_req);
                         req = xmalloc(sizeof(*req));                          req = xmalloc(sizeof(*req));
                         req->id = msg_id++;                          req->id = conn->msg_id++;
                         req->len = buflen;                          req->len = buflen;
                         req->offset = offset;                          req->offset = offset;
                         offset += buflen;                          offset += buflen;
                         num_req++;                          num_req++;
                         TAILQ_INSERT_TAIL(&requests, req, tq);                          TAILQ_INSERT_TAIL(&requests, req, tq);
                         send_read_request(fd_out, req->id, req->offset,                          send_read_request(conn->fd_out, req->id, req->offset,
                             req->len, handle, handle_len);                              req->len, handle, handle_len);
                 }                  }
   
                 buffer_clear(&msg);                  buffer_clear(&msg);
                 get_msg(fd_in, &msg);                  get_msg(conn->fd_in, &msg);
                 type = buffer_get_char(&msg);                  type = buffer_get_char(&msg);
                 id = buffer_get_int(&msg);                  id = buffer_get_int(&msg);
                 debug3("Received reply T:%d I:%d R:%d", type, id, max_req);                  debug3("Received reply T:%d I:%d R:%d", type, id, max_req);
Line 826 
Line 877 
                                 debug3("Short data block, re-requesting "                                  debug3("Short data block, re-requesting "
                                     "%llu -> %llu (%2d)", req->offset + len,                                      "%llu -> %llu (%2d)", req->offset + len,
                                         req->offset + req->len - 1, num_req);                                          req->offset + req->len - 1, num_req);
                                 req->id = msg_id++;                                  req->id = conn->msg_id++;
                                 req->len -= len;                                  req->len -= len;
                                 req->offset += len;                                  req->offset += len;
                                 send_read_request(fd_out, req->id,                                  send_read_request(conn->fd_out, req->id,
                                     req->offset, req->len, handle,                                      req->offset, req->len, handle, handle_len);
                                     handle_len);  
                                 /* Reduce the request size */                                  /* Reduce the request size */
                                 if (len < buflen)                                  if (len < buflen)
                                         buflen = MAX(MIN_READ_SIZE, len);                                          buflen = MAX(MIN_READ_SIZE, len);
Line 844 
Line 894 
                                             offset, num_req);                                              offset, num_req);
                                         max_req = 1;                                          max_req = 1;
                                 }                                  }
                                 else if (max_req < num_requests + 1) {                                  else if (max_req < conn->num_requests + 1) {
                                         ++max_req;                                          ++max_req;
                                 }                                  }
                         }                          }
Line 862 
Line 912 
         if (read_error) {          if (read_error) {
                 error("Couldn't read from remote file \"%s\" : %s",                  error("Couldn't read from remote file \"%s\" : %s",
                     remote_path, fx2txt(status));                      remote_path, fx2txt(status));
                 do_close(fd_in, fd_out, handle, handle_len);                  do_close(conn, handle, handle_len);
         } else if (write_error) {          } else if (write_error) {
                 error("Couldn't write to \"%s\": %s", local_path,                  error("Couldn't write to \"%s\": %s", local_path,
                     strerror(write_errno));                      strerror(write_errno));
                 status = -1;                  status = -1;
                 do_close(fd_in, fd_out, handle, handle_len);                  do_close(conn, handle, handle_len);
         } else {          } else {
                 status = do_close(fd_in, fd_out, handle, handle_len);                  status = do_close(conn, handle, handle_len);
   
                 /* 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)
Line 888 
Line 938 
         close(local_fd);          close(local_fd);
         buffer_free(&msg);          buffer_free(&msg);
         xfree(handle);          xfree(handle);
         return status;  
           return(status);
 }  }
   
 int  int
 do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,  do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
     int pflag, size_t buflen, int num_requests)      int pflag)
 {  {
         int local_fd, status;          int local_fd, status;
         u_int handle_len, id, type;          u_int handle_len, id, type;
Line 937 
Line 988 
         buffer_init(&msg);          buffer_init(&msg);
   
         /* Send open request */          /* Send open request */
         id = msg_id++;          id = conn->msg_id++;
         buffer_put_char(&msg, SSH2_FXP_OPEN);          buffer_put_char(&msg, SSH2_FXP_OPEN);
         buffer_put_int(&msg, id);          buffer_put_int(&msg, id);
         buffer_put_cstring(&msg, remote_path);          buffer_put_cstring(&msg, remote_path);
         buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC);          buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC);
         encode_attrib(&msg, &a);          encode_attrib(&msg, &a);
         send_msg(fd_out, &msg);          send_msg(conn->fd_out, &msg);
         debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path);          debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path);
   
         buffer_clear(&msg);          buffer_clear(&msg);
   
         handle = get_handle(fd_in, id, &handle_len);          handle = get_handle(conn->fd_in, id, &handle_len);
         if (handle == NULL) {          if (handle == NULL) {
                 close(local_fd);                  close(local_fd);
                 buffer_free(&msg);                  buffer_free(&msg);
Line 956 
Line 1007 
         }          }
   
         startid = ackid = id + 1;          startid = ackid = id + 1;
         data = xmalloc(buflen);          data = xmalloc(conn->transfer_buflen);
   
         /* Read from local and write to remote */          /* Read from local and write to remote */
         offset = 0;          offset = 0;
Line 968 
Line 1019 
                  * the last block of the file                   * the last block of the file
                  */                   */
                 do                  do
                         len = read(local_fd, data, buflen);                          len = read(local_fd, data, conn->transfer_buflen);
                 while ((len == -1) && (errno == EINTR || errno == EAGAIN));                  while ((len == -1) && (errno == EINTR || errno == EAGAIN));
   
                 if (len == -1)                  if (len == -1)
Line 988 
Line 1039 
                         buffer_put_string(&msg, handle, handle_len);                          buffer_put_string(&msg, handle, handle_len);
                         buffer_put_int64(&msg, offset);                          buffer_put_int64(&msg, offset);
                         buffer_put_string(&msg, data, len);                          buffer_put_string(&msg, data, len);
                         send_msg(fd_out, &msg);                          send_msg(conn->fd_out, &msg);
                         debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u",                          debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u",
                                id, (u_int64_t)offset, len);                                 id, (u_int64_t)offset, len);
                 } else if (TAILQ_FIRST(&acks) == NULL)                  } else if (TAILQ_FIRST(&acks) == NULL)
Line 997 
Line 1048 
                 if (ack == NULL)                  if (ack == NULL)
                         fatal("Unexpected ACK %u", id);                          fatal("Unexpected ACK %u", id);
   
                 if (id == startid || len == 0 || id - ackid >= num_requests) {                  if (id == startid || len == 0 ||
                       id - ackid >= conn->num_requests) {
                         buffer_clear(&msg);                          buffer_clear(&msg);
                         get_msg(fd_in, &msg);                          get_msg(conn->fd_in, &msg);
                         type = buffer_get_char(&msg);                          type = buffer_get_char(&msg);
                         id = buffer_get_int(&msg);                          id = buffer_get_int(&msg);
   
Line 1022 
Line 1074 
                         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(fd_in, fd_out, handle, handle_len);                                  do_close(conn, handle, handle_len);
                                 close(local_fd);                                  close(local_fd);
                                 goto done;                                  goto done;
                         }                          }
Line 1031 
Line 1083 
                         ++ackid;                          ++ackid;
                         free(ack);                          free(ack);
                 }                  }
   
                 offset += len;                  offset += len;
         }          }
         xfree(data);          xfree(data);
Line 1039 
Line 1090 
         if (close(local_fd) == -1) {          if (close(local_fd) == -1) {
                 error("Couldn't close local file \"%s\": %s", local_path,                  error("Couldn't close local file \"%s\": %s", local_path,
                     strerror(errno));                      strerror(errno));
                 do_close(fd_in, fd_out, handle, handle_len);                  do_close(conn, handle, handle_len);
                 status = -1;                  status = -1;
                 goto done;                  goto done;
         }          }
   
         /* Override umask and utimes if asked */          /* Override umask and utimes if asked */
         if (pflag)          if (pflag)
                 do_fsetstat(fd_in, fd_out, handle, handle_len, &a);                  do_fsetstat(conn, handle, handle_len, &a);
   
         status = do_close(fd_in, fd_out, handle, handle_len);          status = do_close(conn, handle, handle_len);
   
 done:  done:
         xfree(handle);          xfree(handle);
         buffer_free(&msg);          buffer_free(&msg);
         return status;          return(status);
 }  }

Legend:
Removed from v.1.22  
changed lines
  Added in v.1.23