summaryrefslogtreecommitdiff
path: root/usr.bin/ssh/sftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/ssh/sftp.c')
-rw-r--r--usr.bin/ssh/sftp.c76
1 files changed, 50 insertions, 26 deletions
diff --git a/usr.bin/ssh/sftp.c b/usr.bin/ssh/sftp.c
index 1a2d3b2dbc7..d495fd81c2c 100644
--- a/usr.bin/ssh/sftp.c
+++ b/usr.bin/ssh/sftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.147 2013/07/12 00:20:00 djm Exp $ */
+/* $OpenBSD: sftp.c,v 1.148 2013/07/25 00:56:52 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@@ -69,6 +69,9 @@ 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 */
+int global_aflag = 0;
+
/* When this option is set, the file transfers will always preserve times */
int global_pflag = 0;
@@ -130,6 +133,7 @@ int remote_glob(struct sftp_conn *, const char *, int,
#define I_SYMLINK 21
#define I_VERSION 22
#define I_PROGRESS 23
+#define I_REGET 26
struct CMD {
const char *c;
@@ -169,6 +173,7 @@ static const struct CMD cmds[] = {
{ "put", I_PUT, LOCAL },
{ "pwd", I_PWD, REMOTE },
{ "quit", I_QUIT, NOARGS },
+ { "reget", I_REGET, REMOTE },
{ "rename", I_RENAME, REMOTE },
{ "rm", I_RM, REMOTE },
{ "rmdir", I_RMDIR, REMOTE },
@@ -218,6 +223,7 @@ help(void)
" filesystem containing 'path'\n"
"exit Quit sftp\n"
"get [-Ppr] remote [local] Download file\n"
+ "reget remote [local] Resume download 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"
@@ -329,8 +335,8 @@ make_absolute(char *p, char *pwd)
}
static int
-parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag,
- int *rflag)
+parse_getput_flags(const char *cmd, char **argv, int argc,
+ int *aflag, int *pflag, int *rflag)
{
extern int opterr, optind, optopt, optreset;
int ch;
@@ -338,9 +344,12 @@ parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag,
optind = optreset = 1;
opterr = 0;
- *rflag = *pflag = 0;
- while ((ch = getopt(argc, argv, "PpRr")) != -1) {
+ *aflag = *rflag = *pflag = 0;
+ while ((ch = getopt(argc, argv, "aPpRr")) != -1) {
switch (ch) {
+ case 'a':
+ *aflag = 1;
+ break;
case 'p':
case 'P':
*pflag = 1;
@@ -498,7 +507,7 @@ pathname_is_dir(char *pathname)
static int
process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
- int pflag, int rflag)
+ int pflag, int rflag, int resume)
{
char *abs_src = NULL;
char *abs_dst = NULL;
@@ -550,15 +559,18 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
}
free(tmp);
- if (!quiet)
+ resume |= global_aflag;
+ if (!quiet && resume)
+ printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst);
+ else if (!quiet && !resume)
printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
- if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
- pflag || global_pflag, 1) == -1)
+ if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
+ pflag || global_pflag, 1, resume) == -1)
err = -1;
} else {
if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
- pflag || global_pflag) == -1)
+ pflag || global_pflag, resume) == -1)
err = -1;
}
free(abs_dst);
@@ -1097,8 +1109,9 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
}
static int
-parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
- int *hflag, int *sflag, unsigned long *n_arg, char **path1, char **path2)
+parse_args(const char **cpp, int *aflag, 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;
char *cp2, **argv;
@@ -1142,14 +1155,15 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
}
/* Get arguments and parse flags */
- *lflag = *pflag = *rflag = *hflag = *n_arg = 0;
+ *aflag = *lflag = *pflag = *rflag = *hflag = *n_arg = 0;
*path1 = *path2 = NULL;
optidx = 1;
switch (cmdnum) {
case I_GET:
+ case I_REGET:
case I_PUT:
if ((optidx = parse_getput_flags(cmd, argv, argc,
- pflag, rflag)) == -1)
+ aflag, pflag, rflag)) == -1)
return -1;
/* Get first pathname (mandatory) */
if (argc - optidx < 1) {
@@ -1164,6 +1178,11 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
/* 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)
@@ -1272,7 +1291,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
int err_abort)
{
char *path1, *path2, *tmp;
- int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0;
+ int aflag = 0, hflag = 0, iflag = 0, lflag = 0, pflag = 0;
+ int rflag = 0, sflag = 0;
int cmdnum, i;
unsigned long n_arg = 0;
Attrib a, *aa;
@@ -1281,9 +1301,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
glob_t g;
path1 = path2 = NULL;
- cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag,
- &sflag, &n_arg, &path1, &path2);
-
+ cmdnum = parse_args(&cmd, &aflag, &hflag, &iflag, &lflag, &pflag,
+ &rflag, &sflag, &n_arg, &path1, &path2);
if (iflag != 0)
err_abort = 0;
@@ -1298,8 +1317,12 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
/* Unrecognized command */
err = -1;
break;
+ case I_REGET:
+ aflag = 1;
+ /* FALLTHROUGH */
case I_GET:
- err = process_get(conn, path1, path2, *pwd, pflag, rflag);
+ err = process_get(conn, path1, path2, *pwd, pflag,
+ rflag, aflag);
break;
case I_PUT:
err = process_put(conn, path1, path2, *pwd, pflag, rflag);
@@ -1924,12 +1947,10 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
}
} else {
/* XXX this is wrong wrt quoting */
- if (file2 == NULL)
- snprintf(cmd, sizeof cmd, "get %s", dir);
- else
- snprintf(cmd, sizeof cmd, "get %s %s", dir,
- file2);
-
+ snprintf(cmd, sizeof cmd, "get%s %s%s%s",
+ global_aflag ? " -a" : "", dir,
+ file2 == NULL ? "" : " ",
+ file2 == NULL ? "" : file2);
err = parse_dispatch_command(conn, cmd,
&remote_path, 1);
free(dir);
@@ -2101,7 +2122,7 @@ main(int argc, char **argv)
infile = stdin;
while ((ch = getopt(argc, argv,
- "1246hpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
+ "1246ahpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
switch (ch) {
/* Passed through to ssh(1) */
case '4':
@@ -2141,6 +2162,9 @@ main(int argc, char **argv)
case '2':
sshver = 2;
break;
+ case 'a':
+ global_aflag = 1;
+ break;
case 'B':
copy_buffer_len = strtol(optarg, &cp, 10);
if (copy_buffer_len == 0 || *cp != '\0')