summaryrefslogtreecommitdiffstats
path: root/crypto/openssh/sftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/sftp.c')
-rw-r--r--crypto/openssh/sftp.c90
1 files changed, 56 insertions, 34 deletions
diff --git a/crypto/openssh/sftp.c b/crypto/openssh/sftp.c
index ad1f8c8..788601a 100644
--- a/crypto/openssh/sftp.c
+++ b/crypto/openssh/sftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.158 2013/11/20 20:54:10 deraadt Exp $ */
+/* $OpenBSD: sftp.c,v 1.171 2015/08/20 22:32:42 deraadt Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@@ -17,6 +17,7 @@
#include "includes.h"
+#include <sys/param.h> /* MIN MAX */
#include <sys/types.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_STAT_H
@@ -46,6 +47,7 @@
#else
typedef void EditLine;
#endif
+#include <limits.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
@@ -63,7 +65,8 @@ typedef void EditLine;
#include "misc.h"
#include "sftp.h"
-#include "buffer.h"
+#include "ssherr.h"
+#include "sshbuf.h"
#include "sftp-common.h"
#include "sftp-client.h"
@@ -88,7 +91,7 @@ int showprogress = 1;
/* When this option is set, we always recursively download/upload directories */
int global_rflag = 0;
-/* When this option is set, we resume download if possible */
+/* When this option is set, we resume download or upload if possible */
int global_aflag = 0;
/* When this option is set, the file transfers will always preserve times */
@@ -151,14 +154,15 @@ enum sftp_command {
I_PUT,
I_PWD,
I_QUIT,
+ I_REGET,
I_RENAME,
+ I_REPUT,
I_RM,
I_RMDIR,
I_SHELL,
I_SYMLINK,
I_VERSION,
I_PROGRESS,
- I_REGET,
};
struct CMD {
@@ -201,6 +205,7 @@ static const struct CMD cmds[] = {
{ "quit", I_QUIT, NOARGS },
{ "reget", I_REGET, REMOTE },
{ "rename", I_RENAME, REMOTE },
+ { "reput", I_REPUT, LOCAL },
{ "rm", I_RM, REMOTE },
{ "rmdir", I_RMDIR, REMOTE },
{ "symlink", I_SYMLINK, REMOTE },
@@ -248,8 +253,9 @@ help(void)
"df [-hi] [path] Display statistics for current directory or\n"
" filesystem containing 'path'\n"
"exit Quit sftp\n"
- "get [-Ppr] remote [local] Download file\n"
- "reget remote [local] Resume download file\n"
+ "get [-afPpRr] remote [local] Download file\n"
+ "reget [-fPpRr] remote [local] Resume download file\n"
+ "reput [-fPpRr] [local] remote Resume upload file\n"
"help Display this help text\n"
"lcd path Change local directory to 'path'\n"
"lls [ls-options [path]] Display local directory listing\n"
@@ -260,7 +266,7 @@ help(void)
"lumask umask Set local umask to 'umask'\n"
"mkdir path Create remote directory\n"
"progress Toggle display of progress meter\n"
- "put [-Ppr] local [remote] Upload file\n"
+ "put [-afPpRr] local [remote] Upload file\n"
"pwd Display remote working directory\n"
"quit Quit sftp\n"
"rename oldpath newpath Rename remote file\n"
@@ -586,15 +592,19 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
char *abs_dst = NULL;
glob_t g;
char *filename, *tmp=NULL;
- int i, err = 0;
+ int i, r, err = 0;
abs_src = xstrdup(src);
abs_src = make_absolute(abs_src, pwd);
memset(&g, 0, sizeof(g));
debug3("Looking up %s", abs_src);
- if (remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) {
- error("File \"%s\" not found.", abs_src);
+ if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) {
+ if (r == GLOB_NOSPACE) {
+ error("Too many matches for \"%s\".", abs_src);
+ } else {
+ error("File \"%s\" not found.", abs_src);
+ }
err = -1;
goto out;
}
@@ -660,7 +670,7 @@ out:
static int
process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
- int pflag, int rflag, int fflag)
+ int pflag, int rflag, int resume, int fflag)
{
char *tmp_dst = NULL;
char *abs_dst = NULL;
@@ -723,16 +733,20 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
}
free(tmp);
- if (!quiet)
+ resume |= global_aflag;
+ if (!quiet && resume)
+ printf("Resuming upload of %s to %s\n", g.gl_pathv[i],
+ abs_dst);
+ else if (!quiet && !resume)
printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (upload_dir(conn, g.gl_pathv[i], abs_dst,
- pflag || global_pflag, 1,
+ pflag || global_pflag, 1, resume,
fflag || global_fflag) == -1)
err = -1;
} else {
if (do_upload(conn, g.gl_pathv[i], abs_dst,
- pflag || global_pflag,
+ pflag || global_pflag, resume,
fflag || global_fflag) == -1)
err = -1;
}
@@ -855,19 +869,23 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
{
char *fname, *lname;
glob_t g;
- int err;
+ int err, r;
struct winsize ws;
u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80;
memset(&g, 0, sizeof(g));
- if (remote_glob(conn, path,
+ if ((r = remote_glob(conn, path,
GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT|GLOB_NOSORT,
- NULL, &g) ||
+ NULL, &g)) != 0 ||
(g.gl_pathc && !g.gl_matchc)) {
if (g.gl_pathc)
globfree(&g);
- error("Can't ls: \"%s\" not found", path);
+ if (r == GLOB_NOSPACE) {
+ error("Can't ls: Too many matches for \"%s\"", path);
+ } else {
+ error("Can't ls: \"%s\" not found", path);
+ }
return -1;
}
@@ -1186,8 +1204,9 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
}
static int
-parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag,
- int *hflag, int *iflag, int *lflag, int *pflag, int *rflag, int *sflag,
+parse_args(const char **cpp, int *ignore_errors, int *aflag,
+ int *fflag, int *hflag, int *iflag, int *lflag, int *pflag,
+ int *rflag, int *sflag,
unsigned long *n_arg, char **path1, char **path2)
{
const char *cmd, *cp = *cpp;
@@ -1239,6 +1258,7 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag,
switch (cmdnum) {
case I_GET:
case I_REGET:
+ case I_REPUT:
case I_PUT:
if ((optidx = parse_getput_flags(cmd, argv, argc,
aflag, fflag, pflag, rflag)) == -1)
@@ -1256,11 +1276,6 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag,
/* Destination is not globbed */
undo_glob_escape(*path2);
}
- if (*aflag && cmdnum == I_PUT) {
- /* XXX implement resume for uploads */
- error("Resume is not supported for uploads");
- return -1;
- }
break;
case I_LINK:
if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
@@ -1382,12 +1397,13 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
int err_abort)
{
char *path1, *path2, *tmp;
- int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0, iflag = 0;
+ int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0,
+ iflag = 0;
int lflag = 0, pflag = 0, rflag = 0, sflag = 0;
int cmdnum, i;
unsigned long n_arg = 0;
Attrib a, *aa;
- char path_buf[MAXPATHLEN];
+ char path_buf[PATH_MAX];
int err = 0;
glob_t g;
@@ -1415,9 +1431,12 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
err = process_get(conn, path1, path2, *pwd, pflag,
rflag, aflag, fflag);
break;
+ case I_REPUT:
+ aflag = 1;
+ /* FALLTHROUGH */
case I_PUT:
err = process_put(conn, path1, path2, *pwd, pflag,
- rflag, fflag);
+ rflag, aflag, fflag);
break;
case I_RENAME:
path1 = make_absolute(path1, *pwd);
@@ -1503,6 +1522,9 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
err = do_df(conn, path1, hflag, iflag);
break;
case I_LCHDIR:
+ tmp = tilde_expand_filename(path1, getuid());
+ free(path1);
+ path1 = tmp;
if (chdir(path1) == -1) {
error("Couldn't change local directory to "
"\"%s\": %s", path1, strerror(errno));
@@ -1834,6 +1856,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
pwdlen = tmplen + 1; /* track last seen '/' */
}
free(tmp);
+ tmp = NULL;
if (g.gl_matchc == 0)
goto out;
@@ -1841,7 +1864,6 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
if (g.gl_matchc > 1)
complete_display(g.gl_pathv, pwdlen);
- tmp = NULL;
/* Don't try to extend globs */
if (file == NULL || hadglob)
goto out;
@@ -1904,7 +1926,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
lf = el_line(el);
if (g.gl_matchc == 1) {
i = 0;
- if (!terminated)
+ if (!terminated && quote != '\0')
ins[i++] = quote;
if (*(lf->cursor - 1) != '/' &&
(lastarg || *(lf->cursor) != ' '))
@@ -1936,7 +1958,7 @@ complete(EditLine *el, int ch)
/* Figure out which argument the cursor points to */
cursor = lf->cursor - lf->buffer;
- line = (char *)xmalloc(cursor + 1);
+ line = xmalloc(cursor + 1);
memcpy(line, lf->buffer, cursor);
line[cursor] = '\0';
argv = makeargv(line, &carg, 1, &quote, &terminated);
@@ -1944,7 +1966,7 @@ complete(EditLine *el, int ch)
/* Get all the arguments on the line */
len = lf->lastchar - lf->buffer;
- line = (char *)xmalloc(len + 1);
+ line = xmalloc(len + 1);
memcpy(line, lf->buffer, len);
line[len] = '\0';
argv = makeargv(line, &argc, 1, NULL, NULL);
@@ -2065,8 +2087,8 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
free(dir);
}
- setlinebuf(stdout);
- setlinebuf(infile);
+ setvbuf(stdout, NULL, _IOLBF, 0);
+ setvbuf(infile, NULL, _IOLBF, 0);
interactive = !batchmode && isatty(STDIN_FILENO);
err = 0;
OpenPOWER on IntegriCloud