View | Details | Raw Unified | Return to bug 2021 | Differences between
and this patch

Collapse All | Expand All

(-)sftp-client.c (-20 / +45 lines)
Lines 105-111 send_msg(struct sftp_conn *conn, Buffer *m) Link Here
105
	iov[1].iov_len = buffer_len(m);
105
	iov[1].iov_len = buffer_len(m);
106
106
107
	if (atomiciov6(writev, conn->fd_out, iov, 2,
107
	if (atomiciov6(writev, conn->fd_out, iov, 2,
108
	    conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) != 
108
	    conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) !=
109
	    buffer_len(m) + sizeof(mlen))
109
	    buffer_len(m) + sizeof(mlen))
110
		fatal("Couldn't send packet: %s", strerror(errno));
110
		fatal("Couldn't send packet: %s", strerror(errno));
111
111
Lines 981-996 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, Link Here
981
981
982
int
982
int
983
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
983
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
984
    Attrib *a, int pflag)
984
    Attrib *a, int pflag, int resume)
985
{
985
{
986
	Attrib junk;
986
	Attrib junk;
987
	Buffer msg;
987
	Buffer msg;
988
	char *handle;
988
	char *handle;
989
	int local_fd, status = 0, write_error;
989
	int local_fd = -1, status = 0, write_error;
990
	int read_error, write_errno;
990
	int read_error, write_errno, reordered = 0;
991
	u_int64_t offset, size;
991
	u_int64_t offset = 0, size, highwater;
992
	u_int handle_len, mode, type, id, buflen, num_req, max_req;
992
	u_int handle_len, mode, type, id, buflen, num_req, max_req;
993
	off_t progress_counter;
993
	off_t progress_counter;
994
	struct stat st;
994
	struct request {
995
	struct request {
995
		u_int id;
996
		u_int id;
996
		u_int len;
997
		u_int len;
Lines 1043-1063 do_download(struct sftp_conn *conn, char *remote_path, char *local_path, Link Here
1043
		return(-1);
1044
		return(-1);
1044
	}
1045
	}
1045
1046
1046
	local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC,
1047
	local_fd = open(local_path, O_WRONLY | O_CREAT | (resume ? : O_TRUNC),
1047
	    mode | S_IWUSR);
1048
	    mode | S_IWUSR);
1048
	if (local_fd == -1) {
1049
	if (local_fd == -1) {
1049
		error("Couldn't open local file \"%s\" for writing: %s",
1050
		error("Couldn't open local file \"%s\" for writing: %s",
1050
		    local_path, strerror(errno));
1051
		    local_path, strerror(errno));
1052
		goto fail;
1053
	}
1054
	if (fstat(local_fd, &st) == -1) {
1055
		error("Unable to stat local file \"%s\": %s",
1056
		    local_path, strerror(errno));
1057
		goto fail;
1058
	}
1059
	offset = highwater = st.st_size;
1060
	if ((size_t)st.st_size > size) {
1061
		error("Unable to resume download of \"%s\": "
1062
		    "local file is larger than remote", local_path);
1063
 fail:
1051
		do_close(conn, handle, handle_len);
1064
		do_close(conn, handle, handle_len);
1052
		buffer_free(&msg);
1065
		buffer_free(&msg);
1053
		free(handle);
1066
		free(handle);
1054
		return(-1);
1067
		return -1;
1055
	}
1068
	}
1056
1069
1057
	/* Read from remote and write to local */
1070
	/* Read from remote and write to local */
1058
	write_error = read_error = write_errno = num_req = offset = 0;
1071
	write_error = read_error = write_errno = num_req = 0;
1059
	max_req = 1;
1072
	max_req = 1;
1060
	progress_counter = 0;
1073
	progress_counter = offset;
1061
1074
1062
	if (showprogress && size != 0)
1075
	if (showprogress && size != 0)
1063
		start_progress_meter(remote_path, size, &progress_counter);
1076
		start_progress_meter(remote_path, size, &progress_counter);
Lines 1132-1137 do_download(struct sftp_conn *conn, char *remote_path, char *local_path, Link Here
1132
				write_error = 1;
1145
				write_error = 1;
1133
				max_req = 0;
1146
				max_req = 0;
1134
			}
1147
			}
1148
			else if (!reordered && req->offset <= highwater)
1149
				highwater = req->offset + len;
1150
			else if (!reordered && req->offset > highwater)
1151
				reordered = 1;
1135
			progress_counter += len;
1152
			progress_counter += len;
1136
			free(data);
1153
			free(data);
1137
1154
Lines 1180-1186 do_download(struct sftp_conn *conn, char *remote_path, char *local_path, Link Here
1180
	/* Sanity check */
1197
	/* Sanity check */
1181
	if (TAILQ_FIRST(&requests) != NULL)
1198
	if (TAILQ_FIRST(&requests) != NULL)
1182
		fatal("Transfer complete, but requests still in queue");
1199
		fatal("Transfer complete, but requests still in queue");
1183
1200
	/* Truncate at highest contiguous point to avoid holes on interrupt */
1201
	if (read_error || write_error || interrupted) {
1202
		if (reordered && resume) {
1203
			error("Unable to resume download of \"%s\": "
1204
			    "server reordered requests", local_path);
1205
		}
1206
		debug("truncating at %llu", highwater);
1207
		ftruncate(local_fd, highwater);
1208
	}
1184
	if (read_error) {
1209
	if (read_error) {
1185
		error("Couldn't read from remote file \"%s\" : %s",
1210
		error("Couldn't read from remote file \"%s\" : %s",
1186
		    remote_path, fx2txt(status));
1211
		    remote_path, fx2txt(status));
Lines 1192-1198 do_download(struct sftp_conn *conn, char *remote_path, char *local_path, Link Here
1192
		do_close(conn, handle, handle_len);
1217
		do_close(conn, handle, handle_len);
1193
	} else {
1218
	} else {
1194
		status = do_close(conn, handle, handle_len);
1219
		status = do_close(conn, handle, handle_len);
1195
1220
		if (interrupted)
1221
			status = -1;
1196
		/* Override umask and utimes if asked */
1222
		/* Override umask and utimes if asked */
1197
		if (pflag && fchmod(local_fd, mode) == -1)
1223
		if (pflag && fchmod(local_fd, mode) == -1)
1198
			error("Couldn't set mode on \"%s\": %s", local_path,
1224
			error("Couldn't set mode on \"%s\": %s", local_path,
Lines 1216-1222 do_download(struct sftp_conn *conn, char *remote_path, char *local_path, Link Here
1216
1242
1217
static int
1243
static int
1218
download_dir_internal(struct sftp_conn *conn, char *src, char *dst,
1244
download_dir_internal(struct sftp_conn *conn, char *src, char *dst,
1219
    Attrib *dirattrib, int pflag, int printflag, int depth)
1245
    Attrib *dirattrib, int pflag, int printflag, int depth, int resume)
1220
{
1246
{
1221
	int i, ret = 0;
1247
	int i, ret = 0;
1222
	SFTP_DIRENT **dir_entries;
1248
	SFTP_DIRENT **dir_entries;
Lines 1269-1279 download_dir_internal(struct sftp_conn *conn, char *src, char *dst, Link Here
1269
				continue;
1295
				continue;
1270
			if (download_dir_internal(conn, new_src, new_dst,
1296
			if (download_dir_internal(conn, new_src, new_dst,
1271
			    &(dir_entries[i]->a), pflag, printflag,
1297
			    &(dir_entries[i]->a), pflag, printflag,
1272
			    depth + 1) == -1)
1298
			    depth + 1, resume) == -1)
1273
				ret = -1;
1299
				ret = -1;
1274
		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1300
		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1275
			if (do_download(conn, new_src, new_dst,
1301
			if (do_download(conn, new_src, new_dst,
1276
			    &(dir_entries[i]->a), pflag) == -1) {
1302
			    &(dir_entries[i]->a), pflag, resume) == -1) {
1277
				error("Download of file %s to %s failed",
1303
				error("Download of file %s to %s failed",
1278
				    new_src, new_dst);
1304
				    new_src, new_dst);
1279
				ret = -1;
1305
				ret = -1;
Lines 1306-1312 download_dir_internal(struct sftp_conn *conn, char *src, char *dst, Link Here
1306
1332
1307
int
1333
int
1308
download_dir(struct sftp_conn *conn, char *src, char *dst,
1334
download_dir(struct sftp_conn *conn, char *src, char *dst,
1309
    Attrib *dirattrib, int pflag, int printflag)
1335
    Attrib *dirattrib, int pflag, int printflag, int resume)
1310
{
1336
{
1311
	char *src_canon;
1337
	char *src_canon;
1312
	int ret;
1338
	int ret;
Lines 1317-1323 download_dir(struct sftp_conn *conn, char *src, char *dst, Link Here
1317
	}
1343
	}
1318
1344
1319
	ret = download_dir_internal(conn, src_canon, dst,
1345
	ret = download_dir_internal(conn, src_canon, dst,
1320
	    dirattrib, pflag, printflag, 0);
1346
	    dirattrib, pflag, printflag, 0, resume);
1321
	free(src_canon);
1347
	free(src_canon);
1322
	return ret;
1348
	return ret;
1323
}
1349
}
Lines 1541-1547 upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, Link Here
1541
	a.perm &= 01777;
1567
	a.perm &= 01777;
1542
	if (!pflag)
1568
	if (!pflag)
1543
		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1569
		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1544
	
1570
1545
	status = do_mkdir(conn, dst, &a, 0);
1571
	status = do_mkdir(conn, dst, &a, 0);
1546
	/*
1572
	/*
1547
	 * we lack a portable status for errno EEXIST,
1573
	 * we lack a portable status for errno EEXIST,
Lines 1551-1557 upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, Link Here
1551
	if (status != SSH2_FX_OK) {
1577
	if (status != SSH2_FX_OK) {
1552
		if (status != SSH2_FX_FAILURE)
1578
		if (status != SSH2_FX_FAILURE)
1553
			return -1;
1579
			return -1;
1554
		if (do_stat(conn, dst, 0) == NULL) 
1580
		if (do_stat(conn, dst, 0) == NULL)
1555
			return -1;
1581
			return -1;
1556
	}
1582
	}
1557
1583
Lines 1559-1565 upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, Link Here
1559
		error("Failed to open dir \"%s\": %s", src, strerror(errno));
1585
		error("Failed to open dir \"%s\": %s", src, strerror(errno));
1560
		return -1;
1586
		return -1;
1561
	}
1587
	}
1562
	
1588
1563
	while (((dp = readdir(dirp)) != NULL) && !interrupted) {
1589
	while (((dp = readdir(dirp)) != NULL) && !interrupted) {
1564
		if (dp->d_ino == 0)
1590
		if (dp->d_ino == 0)
1565
			continue;
1591
			continue;
Lines 1628-1631 path_append(char *p1, char *p2) Link Here
1628
1654
1629
	return(ret);
1655
	return(ret);
1630
}
1656
}
1631
(-)sftp-client.h (-2 / +2 lines)
Lines 106-118 int do_symlink(struct sftp_conn *, char *, char *); Link Here
106
 * Download 'remote_path' to 'local_path'. Preserve permissions and times
106
 * Download 'remote_path' to 'local_path'. Preserve permissions and times
107
 * if 'pflag' is set
107
 * if 'pflag' is set
108
 */
108
 */
109
int do_download(struct sftp_conn *, char *, char *, Attrib *, int);
109
int do_download(struct sftp_conn *, char *, char *, Attrib *, int, int);
110
110
111
/*
111
/*
112
 * Recursively download 'remote_directory' to 'local_directory'. Preserve 
112
 * Recursively download 'remote_directory' to 'local_directory'. Preserve 
113
 * times if 'pflag' is set
113
 * times if 'pflag' is set
114
 */
114
 */
115
int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, int);
115
int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, int, int);
116
116
117
/*
117
/*
118
 * Upload 'local_path' to 'remote_path'. Preserve permissions and times
118
 * Upload 'local_path' to 'remote_path'. Preserve permissions and times
(-)sftp.1 (-2 / +22 lines)
Lines 129-135 may be used to indicate standard input. Link Here
129
.Nm
129
.Nm
130
will abort if any of the following
130
will abort if any of the following
131
commands fail:
131
commands fail:
132
.Ic get , put , rename , ln ,
132
.Ic get , put , reget , rename , ln ,
133
.Ic rm , mkdir , chdir , ls ,
133
.Ic rm , mkdir , chdir , ls ,
134
.Ic lchdir , chmod , chown ,
134
.Ic lchdir , chmod , chown ,
135
.Ic chgrp , lpwd , df , symlink ,
135
.Ic chgrp , lpwd , df , symlink ,
Lines 343-349 extension. Link Here
343
Quit
343
Quit
344
.Nm sftp .
344
.Nm sftp .
345
.It Xo Ic get
345
.It Xo Ic get
346
.Op Fl Ppr
346
.Op Fl aPpr
347
.Ar remote-path
347
.Ar remote-path
348
.Op Ar local-path
348
.Op Ar local-path
349
.Xc
349
.Xc
Lines 363-368 is specified, then Link Here
363
.Ar local-path
363
.Ar local-path
364
must specify a directory.
364
must specify a directory.
365
.Pp
365
.Pp
366
If the
367
.Fl a
368
flag is specified, then attempt to resume partial transfers of existing files.
369
Note that resumption assumes that any partial copy of the local file matches
370
the remote copy.
371
If the remote file differs from the partial local copy then the resultant file
372
is likely to be corrupt.
373
.Pp
366
If either the
374
If either the
367
.Fl P
375
.Fl P
368
or
376
or
Lines 503-508 Display remote working directory. Link Here
503
.It Ic quit
511
.It Ic quit
504
Quit
512
Quit
505
.Nm sftp .
513
.Nm sftp .
514
.It Xo Ic reget
515
.Op Fl Ppr
516
.Ar remote-path
517
.Op Ar local-path
518
.Xc
519
Resume download of
520
.Ar remote-path .
521
Equivalent to
522
.Ic get
523
with the
524
.Fl a
525
flag set.
506
.It Ic rename Ar oldpath Ar newpath
526
.It Ic rename Ar oldpath Ar newpath
507
Rename remote file from
527
Rename remote file from
508
.Ar oldpath
528
.Ar oldpath
(-)sftp.c (-24 / +48 lines)
Lines 69-74 int showprogress = 1; Link Here
69
/* When this option is set, we always recursively download/upload directories */
69
/* When this option is set, we always recursively download/upload directories */
70
int global_rflag = 0;
70
int global_rflag = 0;
71
71
72
/* When this option is set, we resume download if possible */
73
int global_aflag = 0;
74
72
/* When this option is set, the file transfers will always preserve times */
75
/* When this option is set, the file transfers will always preserve times */
73
int global_pflag = 0;
76
int global_pflag = 0;
74
77
Lines 130-135 int remote_glob(struct sftp_conn *, const char *, int, Link Here
130
#define I_SYMLINK	21
133
#define I_SYMLINK	21
131
#define I_VERSION	22
134
#define I_VERSION	22
132
#define I_PROGRESS	23
135
#define I_PROGRESS	23
136
#define I_REGET		26
133
137
134
struct CMD {
138
struct CMD {
135
	const char *c;
139
	const char *c;
Lines 169-174 static const struct CMD cmds[] = { Link Here
169
	{ "put",	I_PUT,		LOCAL	},
173
	{ "put",	I_PUT,		LOCAL	},
170
	{ "pwd",	I_PWD,		REMOTE	},
174
	{ "pwd",	I_PWD,		REMOTE	},
171
	{ "quit",	I_QUIT,		NOARGS	},
175
	{ "quit",	I_QUIT,		NOARGS	},
176
	{ "reget",	I_REGET,	REMOTE	},
172
	{ "rename",	I_RENAME,	REMOTE	},
177
	{ "rename",	I_RENAME,	REMOTE	},
173
	{ "rm",		I_RM,		REMOTE	},
178
	{ "rm",		I_RM,		REMOTE	},
174
	{ "rmdir",	I_RMDIR,	REMOTE	},
179
	{ "rmdir",	I_RMDIR,	REMOTE	},
Lines 218-223 help(void) Link Here
218
	    "                                   filesystem containing 'path'\n"
223
	    "                                   filesystem containing 'path'\n"
219
	    "exit                               Quit sftp\n"
224
	    "exit                               Quit sftp\n"
220
	    "get [-Ppr] remote [local]          Download file\n"
225
	    "get [-Ppr] remote [local]          Download file\n"
226
	    "reget remote [local]		Resume download file\n"
221
	    "help                               Display this help text\n"
227
	    "help                               Display this help text\n"
222
	    "lcd path                           Change local directory to 'path'\n"
228
	    "lcd path                           Change local directory to 'path'\n"
223
	    "lls [ls-options [path]]            Display local directory listing\n"
229
	    "lls [ls-options [path]]            Display local directory listing\n"
Lines 329-336 make_absolute(char *p, char *pwd) Link Here
329
}
335
}
330
336
331
static int
337
static int
332
parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag,
338
parse_getput_flags(const char *cmd, char **argv, int argc,
333
    int *rflag)
339
    int *aflag, int *pflag, int *rflag)
334
{
340
{
335
	extern int opterr, optind, optopt, optreset;
341
	extern int opterr, optind, optopt, optreset;
336
	int ch;
342
	int ch;
Lines 338-346 parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag, Link Here
338
	optind = optreset = 1;
344
	optind = optreset = 1;
339
	opterr = 0;
345
	opterr = 0;
340
346
341
	*rflag = *pflag = 0;
347
	*aflag = *rflag = *pflag = 0;
342
	while ((ch = getopt(argc, argv, "PpRr")) != -1) {
348
	while ((ch = getopt(argc, argv, "aPpRr")) != -1) {
343
		switch (ch) {
349
		switch (ch) {
350
		case 'a':
351
			*aflag = 1;
352
			break;
344
		case 'p':
353
		case 'p':
345
		case 'P':
354
		case 'P':
346
			*pflag = 1;
355
			*pflag = 1;
Lines 498-504 pathname_is_dir(char *pathname) Link Here
498
507
499
static int
508
static int
500
process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
509
process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
501
    int pflag, int rflag)
510
    int pflag, int rflag, int resume)
502
{
511
{
503
	char *abs_src = NULL;
512
	char *abs_src = NULL;
504
	char *abs_dst = NULL;
513
	char *abs_dst = NULL;
Lines 550-564 process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, Link Here
550
		}
559
		}
551
		free(tmp);
560
		free(tmp);
552
561
553
		if (!quiet)
562
		resume |= global_aflag;
563
		if (!quiet && resume)
564
			printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst);
565
		else if (!quiet && !resume)
554
			printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
566
			printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
555
		if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
567
		if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
556
			if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, 
568
			if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, 
557
			    pflag || global_pflag, 1) == -1)
569
			    pflag || global_pflag, 1, resume) == -1)
558
				err = -1;
570
				err = -1;
559
		} else {
571
		} else {
560
			if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
572
			if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
561
			    pflag || global_pflag) == -1)
573
			    pflag || global_pflag, resume) == -1)
562
				err = -1;
574
				err = -1;
563
		}
575
		}
564
		free(abs_dst);
576
		free(abs_dst);
Lines 1097-1104 makeargv(const char *arg, int *argcp, int sloppy, char *lastquote, Link Here
1097
}
1109
}
1098
1110
1099
static int
1111
static int
1100
parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
1112
parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
1101
    int *hflag, int *sflag, unsigned long *n_arg, char **path1, char **path2)
1113
    int *pflag, int *rflag, int *sflag, unsigned long *n_arg,
1114
    char **path1, char **path2)
1102
{
1115
{
1103
	const char *cmd, *cp = *cpp;
1116
	const char *cmd, *cp = *cpp;
1104
	char *cp2, **argv;
1117
	char *cp2, **argv;
Lines 1142-1155 parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, Link Here
1142
	}
1155
	}
1143
1156
1144
	/* Get arguments and parse flags */
1157
	/* Get arguments and parse flags */
1145
	*lflag = *pflag = *rflag = *hflag = *n_arg = 0;
1158
	*aflag = *lflag = *pflag = *rflag = *hflag = *n_arg = 0;
1146
	*path1 = *path2 = NULL;
1159
	*path1 = *path2 = NULL;
1147
	optidx = 1;
1160
	optidx = 1;
1148
	switch (cmdnum) {
1161
	switch (cmdnum) {
1149
	case I_GET:
1162
	case I_GET:
1163
	case I_REGET:
1150
	case I_PUT:
1164
	case I_PUT:
1151
		if ((optidx = parse_getput_flags(cmd, argv, argc,
1165
		if ((optidx = parse_getput_flags(cmd, argv, argc,
1152
		    pflag, rflag)) == -1)
1166
		    aflag, pflag, rflag)) == -1)
1153
			return -1;
1167
			return -1;
1154
		/* Get first pathname (mandatory) */
1168
		/* Get first pathname (mandatory) */
1155
		if (argc - optidx < 1) {
1169
		if (argc - optidx < 1) {
Lines 1164-1169 parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, Link Here
1164
			/* Destination is not globbed */
1178
			/* Destination is not globbed */
1165
			undo_glob_escape(*path2);
1179
			undo_glob_escape(*path2);
1166
		}
1180
		}
1181
		if (*aflag && cmdnum == I_PUT) {
1182
			/* XXX implement resume for uploads */
1183
			error("Resume is not supported for uploads");
1184
			return -1;
1185
		}
1167
		break;
1186
		break;
1168
	case I_LINK:
1187
	case I_LINK:
1169
		if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
1188
		if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
Lines 1272-1278 parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, Link Here
1272
    int err_abort)
1291
    int err_abort)
1273
{
1292
{
1274
	char *path1, *path2, *tmp;
1293
	char *path1, *path2, *tmp;
1275
	int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0;
1294
	int aflag = 0, hflag = 0, iflag = 0, lflag = 0, pflag = 0;
1295
	int rflag = 0, sflag = 0;
1276
	int cmdnum, i;
1296
	int cmdnum, i;
1277
	unsigned long n_arg = 0;
1297
	unsigned long n_arg = 0;
1278
	Attrib a, *aa;
1298
	Attrib a, *aa;
Lines 1281-1289 parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, Link Here
1281
	glob_t g;
1301
	glob_t g;
1282
1302
1283
	path1 = path2 = NULL;
1303
	path1 = path2 = NULL;
1284
	cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag,
1304
	cmdnum = parse_args(&cmd, &aflag, &hflag, &iflag, &lflag, &pflag,
1285
	    &sflag, &n_arg, &path1, &path2);
1305
	    &rflag, &sflag, &n_arg, &path1, &path2); 
1286
1287
	if (iflag != 0)
1306
	if (iflag != 0)
1288
		err_abort = 0;
1307
		err_abort = 0;
1289
1308
Lines 1298-1305 parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, Link Here
1298
		/* Unrecognized command */
1317
		/* Unrecognized command */
1299
		err = -1;
1318
		err = -1;
1300
		break;
1319
		break;
1320
	case I_REGET:
1321
		aflag = 1;
1322
		/* FALLTHROUGH */
1301
	case I_GET:
1323
	case I_GET:
1302
		err = process_get(conn, path1, path2, *pwd, pflag, rflag);
1324
		err = process_get(conn, path1, path2, *pwd, pflag,
1325
		    rflag, aflag);
1303
		break;
1326
		break;
1304
	case I_PUT:
1327
	case I_PUT:
1305
		err = process_put(conn, path1, path2, *pwd, pflag, rflag);
1328
		err = process_put(conn, path1, path2, *pwd, pflag, rflag);
Lines 1924-1935 interactive_loop(struct sftp_conn *conn, char *file1, char *file2) Link Here
1924
			}
1947
			}
1925
		} else {
1948
		} else {
1926
			/* XXX this is wrong wrt quoting */
1949
			/* XXX this is wrong wrt quoting */
1927
			if (file2 == NULL)
1950
			snprintf(cmd, sizeof cmd, "get%s %s%s%s",
1928
				snprintf(cmd, sizeof cmd, "get %s", dir);
1951
			    global_aflag ? " -a" : "", dir,
1929
			else
1952
			    file2 == NULL ? "" : " ",
1930
				snprintf(cmd, sizeof cmd, "get %s %s", dir,
1953
			    file2 == NULL ? "" : file2);
1931
				    file2);
1932
1933
			err = parse_dispatch_command(conn, cmd,
1954
			err = parse_dispatch_command(conn, cmd,
1934
			    &remote_path, 1);
1955
			    &remote_path, 1);
1935
			free(dir);
1956
			free(dir);
Lines 2101-2107 main(int argc, char **argv) Link Here
2101
	infile = stdin;
2122
	infile = stdin;
2102
2123
2103
	while ((ch = getopt(argc, argv,
2124
	while ((ch = getopt(argc, argv,
2104
	    "1246hpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
2125
	    "1246ahpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
2105
		switch (ch) {
2126
		switch (ch) {
2106
		/* Passed through to ssh(1) */
2127
		/* Passed through to ssh(1) */
2107
		case '4':
2128
		case '4':
Lines 2141-2146 main(int argc, char **argv) Link Here
2141
		case '2':
2162
		case '2':
2142
			sshver = 2;
2163
			sshver = 2;
2143
			break;
2164
			break;
2165
		case 'a':
2166
			global_aflag = 1;
2167
			break;
2144
		case 'B':
2168
		case 'B':
2145
			copy_buffer_len = strtol(optarg, &cp, 10);
2169
			copy_buffer_len = strtol(optarg, &cp, 10);
2146
			if (copy_buffer_len == 0 || *cp != '\0')
2170
			if (copy_buffer_len == 0 || *cp != '\0')

Return to bug 2021