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

Diff for /src/usr.bin/ssh/sftp.c between version 1.110 and 1.111

version 1.110, 2009/08/13 13:39:54 version 1.111, 2009/08/18 18:36:21
Line 28 
Line 28 
 #include <glob.h>  #include <glob.h>
 #include <histedit.h>  #include <histedit.h>
 #include <paths.h>  #include <paths.h>
   #include <libgen.h>
 #include <signal.h>  #include <signal.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <stdio.h>  #include <stdio.h>
Line 64 
Line 65 
 /* This is set to 0 if the progressmeter is not desired. */  /* This is set to 0 if the progressmeter is not desired. */
 int showprogress = 1;  int showprogress = 1;
   
   /* When this option is set, we always recursively download/upload directories */
   int global_rflag = 0;
   
   /* When this option is set, the file transfers will always preserve times */
   int global_pflag = 0;
   
 /* SIGINT received during command processing */  /* SIGINT received during command processing */
 volatile sig_atomic_t interrupted = 0;  volatile sig_atomic_t interrupted = 0;
   
Line 195 
Line 202 
             "df [-hi] [path]                    Display statistics for current directory or\n"              "df [-hi] [path]                    Display statistics for current directory or\n"
             "                                   filesystem containing 'path'\n"              "                                   filesystem containing 'path'\n"
             "exit                               Quit sftp\n"              "exit                               Quit sftp\n"
             "get [-P] remote-path [local-path]  Download file\n"              "get [-Pr] remote-path [local-path] Download file\n"
             "help                               Display this help text\n"              "help                               Display this help text\n"
             "lcd path                           Change local directory to 'path'\n"              "lcd path                           Change local directory to 'path'\n"
             "lls [ls-options [path]]            Display local directory listing\n"              "lls [ls-options [path]]            Display local directory listing\n"
Line 206 
Line 213 
             "lumask umask                       Set local umask to 'umask'\n"              "lumask umask                       Set local umask to 'umask'\n"
             "mkdir path                         Create remote directory\n"              "mkdir path                         Create remote directory\n"
             "progress                           Toggle display of progress meter\n"              "progress                           Toggle display of progress meter\n"
             "put [-P] local-path [remote-path]  Upload file\n"              "put [-Pr] local-path [remote-path] Upload file\n"
             "pwd                                Display remote working directory\n"              "pwd                                Display remote working directory\n"
             "quit                               Quit sftp\n"              "quit                               Quit sftp\n"
             "rename oldpath newpath             Rename remote file\n"              "rename oldpath newpath             Rename remote file\n"
Line 293 
Line 300 
 }  }
   
 static char *  static char *
 path_append(char *p1, char *p2)  
 {  
         char *ret;  
         size_t len = strlen(p1) + strlen(p2) + 2;  
   
         ret = xmalloc(len);  
         strlcpy(ret, p1, len);  
         if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/')  
                 strlcat(ret, "/", len);  
         strlcat(ret, p2, len);  
   
         return(ret);  
 }  
   
 static char *  
 make_absolute(char *p, char *pwd)  make_absolute(char *p, char *pwd)
 {  {
         char *abs_str;          char *abs_str;
Line 322 
Line 314 
 }  }
   
 static int  static int
 infer_path(const char *p, char **ifp)  parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag,
       int *rflag)
 {  {
         char *cp;  
   
         cp = strrchr(p, '/');  
         if (cp == NULL) {  
                 *ifp = xstrdup(p);  
                 return(0);  
         }  
   
         if (!cp[1]) {  
                 error("Invalid path");  
                 return(-1);  
         }  
   
         *ifp = xstrdup(cp + 1);  
         return(0);  
 }  
   
 static int  
 parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag)  
 {  
         extern int opterr, optind, optopt, optreset;          extern int opterr, optind, optopt, optreset;
         int ch;          int ch;
   
         optind = optreset = 1;          optind = optreset = 1;
         opterr = 0;          opterr = 0;
   
         *pflag = 0;          *rflag = *pflag = 0;
         while ((ch = getopt(argc, argv, "Pp")) != -1) {          while ((ch = getopt(argc, argv, "PpRr")) != -1) {
                 switch (ch) {                  switch (ch) {
                 case 'p':                  case 'p':
                 case 'P':                  case 'P':
                         *pflag = 1;                          *pflag = 1;
                         break;                          break;
                   case 'r':
                   case 'R':
                           *rflag = 1;
                           break;
                 default:                  default:
                         error("%s: Invalid flag -%c", cmd, optopt);                          error("%s: Invalid flag -%c", cmd, optopt);
                         return -1;                          return -1;
Line 468 
Line 445 
         return(S_ISDIR(a->perm));          return(S_ISDIR(a->perm));
 }  }
   
   /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
 static int  static int
 process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)  pathname_is_dir(char *pathname)
 {  {
           size_t l = strlen(pathname);
   
           return l > 0 && pathname[l - 1] == '/';
   }
   
   static int
   process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
       int pflag, int rflag)
   {
         char *abs_src = NULL;          char *abs_src = NULL;
         char *abs_dst = NULL;          char *abs_dst = NULL;
         char *tmp;  
         glob_t g;          glob_t g;
         int err = 0;          char *filename, *tmp=NULL;
         int i;          int i, err = 0;
   
         abs_src = xstrdup(src);          abs_src = xstrdup(src);
         abs_src = make_absolute(abs_src, pwd);          abs_src = make_absolute(abs_src, pwd);
   
         memset(&g, 0, sizeof(g));          memset(&g, 0, sizeof(g));
   
         debug3("Looking up %s", abs_src);          debug3("Looking up %s", abs_src);
         if (remote_glob(conn, abs_src, 0, NULL, &g)) {          if (remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) {
                 error("File \"%s\" not found.", abs_src);                  error("File \"%s\" not found.", abs_src);
                 err = -1;                  err = -1;
                 goto out;                  goto out;
         }          }
   
         /* If multiple matches, dst must be a directory or unspecified */          /*
         if (g.gl_matchc > 1 && dst && !is_dir(dst)) {           * If multiple matches then dst must be a directory or
                 error("Multiple files match, but \"%s\" is not a directory",           * unspecified.
                     dst);           */
           if (g.gl_matchc > 1 && dst != NULL && !is_dir(dst)) {
                   error("Multiple source paths, but destination "
                       "\"%s\" is not a directory", dst);
                 err = -1;                  err = -1;
                 goto out;                  goto out;
         }          }
   
         for (i = 0; g.gl_pathv[i] && !interrupted; i++) {          for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
                 if (infer_path(g.gl_pathv[i], &tmp)) {                  tmp = xstrdup(g.gl_pathv[i]);
                   if ((filename = basename(tmp)) == NULL) {
                           error("basename %s: %s", tmp, strerror(errno));
                           xfree(tmp);
                         err = -1;                          err = -1;
                         goto out;                          goto out;
                 }                  }
   
                 if (g.gl_matchc == 1 && dst) {                  if (g.gl_matchc == 1 && dst) {
                         /* If directory specified, append filename */  
                         xfree(tmp);  
                         if (is_dir(dst)) {                          if (is_dir(dst)) {
                                 if (infer_path(g.gl_pathv[0], &tmp)) {                                  abs_dst = path_append(dst, filename);
                                         err = 1;                          } else {
                                         goto out;  
                                 }  
                                 abs_dst = path_append(dst, tmp);  
                                 xfree(tmp);  
                         } else  
                                 abs_dst = xstrdup(dst);                                  abs_dst = xstrdup(dst);
                           }
                 } else if (dst) {                  } else if (dst) {
                         abs_dst = path_append(dst, tmp);                          abs_dst = path_append(dst, filename);
                         xfree(tmp);                  } else {
                 } else                          abs_dst = xstrdup(filename);
                         abs_dst = tmp;                  }
                   xfree(tmp);
   
                 printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);                  printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
                 if (do_download(conn, g.gl_pathv[i], abs_dst, pflag) == -1)                  if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
                         err = -1;                          if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
                               pflag || global_pflag, 1) == -1)
                                   err = -1;
                   } else {
                           if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
                               pflag || global_pflag) == -1)
                                   err = -1;
                   }
                 xfree(abs_dst);                  xfree(abs_dst);
                 abs_dst = NULL;                  abs_dst = NULL;
         }          }
Line 535 
Line 529 
 }  }
   
 static int  static int
 process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)  process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
       int pflag, int rflag)
 {  {
         char *tmp_dst = NULL;          char *tmp_dst = NULL;
         char *abs_dst = NULL;          char *abs_dst = NULL;
         char *tmp;          char *tmp = NULL, *filename = NULL;
         glob_t g;          glob_t g;
         int err = 0;          int err = 0;
         int i;          int i, dst_is_dir = 1;
         struct stat sb;          struct stat sb;
   
         if (dst) {          if (dst) {
Line 552 
Line 547 
   
         memset(&g, 0, sizeof(g));          memset(&g, 0, sizeof(g));
         debug3("Looking up %s", src);          debug3("Looking up %s", src);
         if (glob(src, GLOB_NOCHECK, NULL, &g)) {          if (glob(src, GLOB_NOCHECK | GLOB_MARK, NULL, &g)) {
                 error("File \"%s\" not found.", src);                  error("File \"%s\" not found.", src);
                 err = -1;                  err = -1;
                 goto out;                  goto out;
         }          }
   
           /* If we aren't fetching to pwd then stash this status for later */
           if (tmp_dst != NULL)
                   dst_is_dir = remote_is_dir(conn, tmp_dst);
   
         /* If multiple matches, dst may be directory or unspecified */          /* If multiple matches, dst may be directory or unspecified */
         if (g.gl_matchc > 1 && tmp_dst && !remote_is_dir(conn, tmp_dst)) {          if (g.gl_matchc > 1 && tmp_dst && !dst_is_dir) {
                 error("Multiple files match, but \"%s\" is not a directory",                  error("Multiple paths match, but destination "
                     tmp_dst);                      "\"%s\" is not a directory", tmp_dst);
                 err = -1;                  err = -1;
                 goto out;                  goto out;
         }          }
Line 572 
Line 571 
                         error("stat %s: %s", g.gl_pathv[i], strerror(errno));                          error("stat %s: %s", g.gl_pathv[i], strerror(errno));
                         continue;                          continue;
                 }                  }
   
                 if (!S_ISREG(sb.st_mode)) {                  tmp = xstrdup(g.gl_pathv[i]);
                         error("skipping non-regular file %s",                  if ((filename = basename(tmp)) == NULL) {
                             g.gl_pathv[i]);                          error("basename %s: %s", tmp, strerror(errno));
                         continue;                          xfree(tmp);
                 }  
                 if (infer_path(g.gl_pathv[i], &tmp)) {  
                         err = -1;                          err = -1;
                         goto out;                          goto out;
                 }                  }
   
                 if (g.gl_matchc == 1 && tmp_dst) {                  if (g.gl_matchc == 1 && tmp_dst) {
                         /* If directory specified, append filename */                          /* If directory specified, append filename */
                         if (remote_is_dir(conn, tmp_dst)) {                          if (dst_is_dir)
                                 if (infer_path(g.gl_pathv[0], &tmp)) {                                  abs_dst = path_append(tmp_dst, filename);
                                         err = 1;                          else
                                         goto out;  
                                 }  
                                 abs_dst = path_append(tmp_dst, tmp);  
                                 xfree(tmp);  
                         } else  
                                 abs_dst = xstrdup(tmp_dst);                                  abs_dst = xstrdup(tmp_dst);
   
                 } else if (tmp_dst) {                  } else if (tmp_dst) {
                         abs_dst = path_append(tmp_dst, tmp);                          abs_dst = path_append(tmp_dst, filename);
                         xfree(tmp);                  } else {
                 } else                          abs_dst = make_absolute(xstrdup(filename), pwd);
                         abs_dst = make_absolute(tmp, pwd);                  }
                   xfree(tmp);
   
                 printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);                  printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
                 if (do_upload(conn, g.gl_pathv[i], abs_dst, pflag) == -1)                  if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
                         err = -1;                          if (upload_dir(conn, g.gl_pathv[i], abs_dst,
                               pflag || global_pflag, 1) == -1)
                                   err = -1;
                   } else {
                           if (do_upload(conn, g.gl_pathv[i], abs_dst,
                               pflag || global_pflag) == -1)
                                   err = -1;
                   }
         }          }
   
 out:  out:
Line 1044 
Line 1043 
 }  }
   
 static int  static int
 parse_args(const char **cpp, int *pflag, int *lflag, int *iflag, int *hflag,  parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, int *hflag,
     unsigned long *n_arg, char **path1, char **path2)      unsigned long *n_arg, char **path1, char **path2)
 {  {
         const char *cmd, *cp = *cpp;          const char *cmd, *cp = *cpp;
Line 1088 
Line 1087 
         }          }
   
         /* Get arguments and parse flags */          /* Get arguments and parse flags */
         *lflag = *pflag = *hflag = *n_arg = 0;          *lflag = *pflag = *rflag = *hflag = *n_arg = 0;
         *path1 = *path2 = NULL;          *path1 = *path2 = NULL;
         optidx = 1;          optidx = 1;
         switch (cmdnum) {          switch (cmdnum) {
         case I_GET:          case I_GET:
         case I_PUT:          case I_PUT:
                 if ((optidx = parse_getput_flags(cmd, argv, argc, pflag)) == -1)                  if ((optidx = parse_getput_flags(cmd, argv, argc, pflag, rflag)) == -1)
                         return -1;                          return -1;
                 /* Get first pathname (mandatory) */                  /* Get first pathname (mandatory) */
                 if (argc - optidx < 1) {                  if (argc - optidx < 1) {
Line 1214 
Line 1213 
     int err_abort)      int err_abort)
 {  {
         char *path1, *path2, *tmp;          char *path1, *path2, *tmp;
         int pflag = 0, lflag = 0, iflag = 0, hflag = 0, cmdnum, i;          int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, cmdnum, i;
         unsigned long n_arg = 0;          unsigned long n_arg = 0;
         Attrib a, *aa;          Attrib a, *aa;
         char path_buf[MAXPATHLEN];          char path_buf[MAXPATHLEN];
Line 1222 
Line 1221 
         glob_t g;          glob_t g;
   
         path1 = path2 = NULL;          path1 = path2 = NULL;
         cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &hflag, &n_arg,          cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag, &n_arg,
             &path1, &path2);              &path1, &path2);
   
         if (iflag != 0)          if (iflag != 0)
Line 1240 
Line 1239 
                 err = -1;                  err = -1;
                 break;                  break;
         case I_GET:          case I_GET:
                 err = process_get(conn, path1, path2, *pwd, pflag);                  err = process_get(conn, path1, path2, *pwd, pflag, rflag);
                 break;                  break;
         case I_PUT:          case I_PUT:
                 err = process_put(conn, path1, path2, *pwd, pflag);                  err = process_put(conn, path1, path2, *pwd, pflag, rflag);
                 break;                  break;
         case I_RENAME:          case I_RENAME:
                 path1 = make_absolute(path1, *pwd);                  path1 = make_absolute(path1, *pwd);
Line 1269 
Line 1268 
                 attrib_clear(&a);                  attrib_clear(&a);
                 a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;                  a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
                 a.perm = 0777;                  a.perm = 0777;
                 err = do_mkdir(conn, path1, &a);                  err = do_mkdir(conn, path1, &a, 1);
                 break;                  break;
         case I_RMDIR:          case I_RMDIR:
                 path1 = make_absolute(path1, *pwd);                  path1 = make_absolute(path1, *pwd);
Line 1622 
Line 1621 
         extern char *__progname;          extern char *__progname;
   
         fprintf(stderr,          fprintf(stderr,
             "usage: %s [-1246Cqv] [-B buffer_size] [-b batchfile] [-c cipher]\n"              "usage: %s [-1246Cpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
             "          [-D sftp_server_path] [-F ssh_config] "              "          [-D sftp_server_path] [-F ssh_config] "
             "[-i identity_file]\n"              "[-i identity_file]\n"
             "          [-o ssh_option] [-P port] [-R num_requests] "              "          [-o ssh_option] [-P port] [-R num_requests] "
Line 1663 
Line 1662 
         infile = stdin;          infile = stdin;
   
         while ((ch = getopt(argc, argv,          while ((ch = getopt(argc, argv,
             "1246hqvCc:D:i:o:s:S:b:B:F:P:R:")) != -1) {              "1246hqrvCc:D:i:o:s:S:b:B:F:P:R:")) != -1) {
                 switch (ch) {                  switch (ch) {
                 /* Passed through to ssh(1) */                  /* Passed through to ssh(1) */
                 case '4':                  case '4':
Line 1717 
Line 1716 
                         batchmode = 1;                          batchmode = 1;
                         addargs(&args, "-obatchmode yes");                          addargs(&args, "-obatchmode yes");
                         break;                          break;
                   case 'p':
                           global_pflag = 1;
                           break;
                 case 'D':                  case 'D':
                         sftp_direct = optarg;                          sftp_direct = optarg;
                           break;
                   case 'r':
                           global_rflag = 1;
                         break;                          break;
                 case 'R':                  case 'R':
                         num_requests = strtol(optarg, &cp, 10);                          num_requests = strtol(optarg, &cp, 10);

Legend:
Removed from v.1.110  
changed lines
  Added in v.1.111