summaryrefslogtreecommitdiff
path: root/sftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp.c')
-rw-r--r--sftp.c66
1 files changed, 41 insertions, 25 deletions
diff --git a/sftp.c b/sftp.c
index ad1f8c84d..ff4d63d5c 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp.c,v 1.158 2013/11/20 20:54:10 deraadt Exp $ */ 1/* $OpenBSD: sftp.c,v 1.164 2014/07/09 01:45:10 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -88,7 +88,7 @@ int showprogress = 1;
88/* When this option is set, we always recursively download/upload directories */ 88/* When this option is set, we always recursively download/upload directories */
89int global_rflag = 0; 89int global_rflag = 0;
90 90
91/* When this option is set, we resume download if possible */ 91/* When this option is set, we resume download or upload if possible */
92int global_aflag = 0; 92int global_aflag = 0;
93 93
94/* When this option is set, the file transfers will always preserve times */ 94/* When this option is set, the file transfers will always preserve times */
@@ -151,14 +151,15 @@ enum sftp_command {
151 I_PUT, 151 I_PUT,
152 I_PWD, 152 I_PWD,
153 I_QUIT, 153 I_QUIT,
154 I_REGET,
154 I_RENAME, 155 I_RENAME,
156 I_REPUT,
155 I_RM, 157 I_RM,
156 I_RMDIR, 158 I_RMDIR,
157 I_SHELL, 159 I_SHELL,
158 I_SYMLINK, 160 I_SYMLINK,
159 I_VERSION, 161 I_VERSION,
160 I_PROGRESS, 162 I_PROGRESS,
161 I_REGET,
162}; 163};
163 164
164struct CMD { 165struct CMD {
@@ -201,6 +202,7 @@ static const struct CMD cmds[] = {
201 { "quit", I_QUIT, NOARGS }, 202 { "quit", I_QUIT, NOARGS },
202 { "reget", I_REGET, REMOTE }, 203 { "reget", I_REGET, REMOTE },
203 { "rename", I_RENAME, REMOTE }, 204 { "rename", I_RENAME, REMOTE },
205 { "reput", I_REPUT, LOCAL },
204 { "rm", I_RM, REMOTE }, 206 { "rm", I_RM, REMOTE },
205 { "rmdir", I_RMDIR, REMOTE }, 207 { "rmdir", I_RMDIR, REMOTE },
206 { "symlink", I_SYMLINK, REMOTE }, 208 { "symlink", I_SYMLINK, REMOTE },
@@ -250,6 +252,7 @@ help(void)
250 "exit Quit sftp\n" 252 "exit Quit sftp\n"
251 "get [-Ppr] remote [local] Download file\n" 253 "get [-Ppr] remote [local] Download file\n"
252 "reget remote [local] Resume download file\n" 254 "reget remote [local] Resume download file\n"
255 "reput [local] remote Resume upload file\n"
253 "help Display this help text\n" 256 "help Display this help text\n"
254 "lcd path Change local directory to 'path'\n" 257 "lcd path Change local directory to 'path'\n"
255 "lls [ls-options [path]] Display local directory listing\n" 258 "lls [ls-options [path]] Display local directory listing\n"
@@ -586,15 +589,19 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
586 char *abs_dst = NULL; 589 char *abs_dst = NULL;
587 glob_t g; 590 glob_t g;
588 char *filename, *tmp=NULL; 591 char *filename, *tmp=NULL;
589 int i, err = 0; 592 int i, r, err = 0;
590 593
591 abs_src = xstrdup(src); 594 abs_src = xstrdup(src);
592 abs_src = make_absolute(abs_src, pwd); 595 abs_src = make_absolute(abs_src, pwd);
593 memset(&g, 0, sizeof(g)); 596 memset(&g, 0, sizeof(g));
594 597
595 debug3("Looking up %s", abs_src); 598 debug3("Looking up %s", abs_src);
596 if (remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) { 599 if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) {
597 error("File \"%s\" not found.", abs_src); 600 if (r == GLOB_NOSPACE) {
601 error("Too many matches for \"%s\".", abs_src);
602 } else {
603 error("File \"%s\" not found.", abs_src);
604 }
598 err = -1; 605 err = -1;
599 goto out; 606 goto out;
600 } 607 }
@@ -660,7 +667,7 @@ out:
660 667
661static int 668static int
662process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, 669process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
663 int pflag, int rflag, int fflag) 670 int pflag, int rflag, int resume, int fflag)
664{ 671{
665 char *tmp_dst = NULL; 672 char *tmp_dst = NULL;
666 char *abs_dst = NULL; 673 char *abs_dst = NULL;
@@ -723,16 +730,20 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
723 } 730 }
724 free(tmp); 731 free(tmp);
725 732
726 if (!quiet) 733 resume |= global_aflag;
734 if (!quiet && resume)
735 printf("Resuming upload of %s to %s\n", g.gl_pathv[i],
736 abs_dst);
737 else if (!quiet && !resume)
727 printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); 738 printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
728 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { 739 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
729 if (upload_dir(conn, g.gl_pathv[i], abs_dst, 740 if (upload_dir(conn, g.gl_pathv[i], abs_dst,
730 pflag || global_pflag, 1, 741 pflag || global_pflag, 1, resume,
731 fflag || global_fflag) == -1) 742 fflag || global_fflag) == -1)
732 err = -1; 743 err = -1;
733 } else { 744 } else {
734 if (do_upload(conn, g.gl_pathv[i], abs_dst, 745 if (do_upload(conn, g.gl_pathv[i], abs_dst,
735 pflag || global_pflag, 746 pflag || global_pflag, resume,
736 fflag || global_fflag) == -1) 747 fflag || global_fflag) == -1)
737 err = -1; 748 err = -1;
738 } 749 }
@@ -855,19 +866,23 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
855{ 866{
856 char *fname, *lname; 867 char *fname, *lname;
857 glob_t g; 868 glob_t g;
858 int err; 869 int err, r;
859 struct winsize ws; 870 struct winsize ws;
860 u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80; 871 u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80;
861 872
862 memset(&g, 0, sizeof(g)); 873 memset(&g, 0, sizeof(g));
863 874
864 if (remote_glob(conn, path, 875 if ((r = remote_glob(conn, path,
865 GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT|GLOB_NOSORT, 876 GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT|GLOB_NOSORT,
866 NULL, &g) || 877 NULL, &g)) != 0 ||
867 (g.gl_pathc && !g.gl_matchc)) { 878 (g.gl_pathc && !g.gl_matchc)) {
868 if (g.gl_pathc) 879 if (g.gl_pathc)
869 globfree(&g); 880 globfree(&g);
870 error("Can't ls: \"%s\" not found", path); 881 if (r == GLOB_NOSPACE) {
882 error("Can't ls: Too many matches for \"%s\"", path);
883 } else {
884 error("Can't ls: \"%s\" not found", path);
885 }
871 return -1; 886 return -1;
872 } 887 }
873 888
@@ -1186,8 +1201,9 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
1186} 1201}
1187 1202
1188static int 1203static int
1189parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag, 1204parse_args(const char **cpp, int *ignore_errors, int *aflag,
1190 int *hflag, int *iflag, int *lflag, int *pflag, int *rflag, int *sflag, 1205 int *fflag, int *hflag, int *iflag, int *lflag, int *pflag,
1206 int *rflag, int *sflag,
1191 unsigned long *n_arg, char **path1, char **path2) 1207 unsigned long *n_arg, char **path1, char **path2)
1192{ 1208{
1193 const char *cmd, *cp = *cpp; 1209 const char *cmd, *cp = *cpp;
@@ -1239,6 +1255,7 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag,
1239 switch (cmdnum) { 1255 switch (cmdnum) {
1240 case I_GET: 1256 case I_GET:
1241 case I_REGET: 1257 case I_REGET:
1258 case I_REPUT:
1242 case I_PUT: 1259 case I_PUT:
1243 if ((optidx = parse_getput_flags(cmd, argv, argc, 1260 if ((optidx = parse_getput_flags(cmd, argv, argc,
1244 aflag, fflag, pflag, rflag)) == -1) 1261 aflag, fflag, pflag, rflag)) == -1)
@@ -1256,11 +1273,6 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag,
1256 /* Destination is not globbed */ 1273 /* Destination is not globbed */
1257 undo_glob_escape(*path2); 1274 undo_glob_escape(*path2);
1258 } 1275 }
1259 if (*aflag && cmdnum == I_PUT) {
1260 /* XXX implement resume for uploads */
1261 error("Resume is not supported for uploads");
1262 return -1;
1263 }
1264 break; 1276 break;
1265 case I_LINK: 1277 case I_LINK:
1266 if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) 1278 if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
@@ -1382,7 +1394,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1382 int err_abort) 1394 int err_abort)
1383{ 1395{
1384 char *path1, *path2, *tmp; 1396 char *path1, *path2, *tmp;
1385 int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0, iflag = 0; 1397 int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0,
1398 iflag = 0;
1386 int lflag = 0, pflag = 0, rflag = 0, sflag = 0; 1399 int lflag = 0, pflag = 0, rflag = 0, sflag = 0;
1387 int cmdnum, i; 1400 int cmdnum, i;
1388 unsigned long n_arg = 0; 1401 unsigned long n_arg = 0;
@@ -1415,9 +1428,12 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1415 err = process_get(conn, path1, path2, *pwd, pflag, 1428 err = process_get(conn, path1, path2, *pwd, pflag,
1416 rflag, aflag, fflag); 1429 rflag, aflag, fflag);
1417 break; 1430 break;
1431 case I_REPUT:
1432 aflag = 1;
1433 /* FALLTHROUGH */
1418 case I_PUT: 1434 case I_PUT:
1419 err = process_put(conn, path1, path2, *pwd, pflag, 1435 err = process_put(conn, path1, path2, *pwd, pflag,
1420 rflag, fflag); 1436 rflag, aflag, fflag);
1421 break; 1437 break;
1422 case I_RENAME: 1438 case I_RENAME:
1423 path1 = make_absolute(path1, *pwd); 1439 path1 = make_absolute(path1, *pwd);
@@ -1834,6 +1850,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1834 pwdlen = tmplen + 1; /* track last seen '/' */ 1850 pwdlen = tmplen + 1; /* track last seen '/' */
1835 } 1851 }
1836 free(tmp); 1852 free(tmp);
1853 tmp = NULL;
1837 1854
1838 if (g.gl_matchc == 0) 1855 if (g.gl_matchc == 0)
1839 goto out; 1856 goto out;
@@ -1841,7 +1858,6 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1841 if (g.gl_matchc > 1) 1858 if (g.gl_matchc > 1)
1842 complete_display(g.gl_pathv, pwdlen); 1859 complete_display(g.gl_pathv, pwdlen);
1843 1860
1844 tmp = NULL;
1845 /* Don't try to extend globs */ 1861 /* Don't try to extend globs */
1846 if (file == NULL || hadglob) 1862 if (file == NULL || hadglob)
1847 goto out; 1863 goto out;
@@ -1904,7 +1920,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1904 lf = el_line(el); 1920 lf = el_line(el);
1905 if (g.gl_matchc == 1) { 1921 if (g.gl_matchc == 1) {
1906 i = 0; 1922 i = 0;
1907 if (!terminated) 1923 if (!terminated && quote != '\0')
1908 ins[i++] = quote; 1924 ins[i++] = quote;
1909 if (*(lf->cursor - 1) != '/' && 1925 if (*(lf->cursor - 1) != '/' &&
1910 (lastarg || *(lf->cursor) != ' ')) 1926 (lastarg || *(lf->cursor) != ' '))