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

Collapse All | Expand All

(-)sftp.c (-11 / +37 lines)
Lines 86-91 int showprogress = 1; Link Here
86
/* When this option is set, we always recursively download/upload directories */
86
/* When this option is set, we always recursively download/upload directories */
87
int global_rflag = 0;
87
int global_rflag = 0;
88
88
89
/* When this option is set, we resume download if possible */
90
int cresume = 0;
91
89
/* When this option is set, the file transfers will always preserve times */
92
/* When this option is set, the file transfers will always preserve times */
90
int global_pflag = 0;
93
int global_pflag = 0;
91
94
Lines 149-154 extern char *__progname; Link Here
149
#define I_SYMLINK	21
152
#define I_SYMLINK	21
150
#define I_VERSION	22
153
#define I_VERSION	22
151
#define I_PROGRESS	23
154
#define I_PROGRESS	23
155
#define I_REGET		26
152
156
153
struct CMD {
157
struct CMD {
154
	const char *c;
158
	const char *c;
Lines 188-193 static const struct CMD cmds[] = { Link Here
188
	{ "put",	I_PUT,		LOCAL	},
192
	{ "put",	I_PUT,		LOCAL	},
189
	{ "pwd",	I_PWD,		REMOTE	},
193
	{ "pwd",	I_PWD,		REMOTE	},
190
	{ "quit",	I_QUIT,		NOARGS	},
194
	{ "quit",	I_QUIT,		NOARGS	},
195
	{ "reget",	I_REGET,	REMOTE	},
191
	{ "rename",	I_RENAME,	REMOTE	},
196
	{ "rename",	I_RENAME,	REMOTE	},
192
	{ "rm",		I_RM,		REMOTE	},
197
	{ "rm",		I_RM,		REMOTE	},
193
	{ "rmdir",	I_RMDIR,	REMOTE	},
198
	{ "rmdir",	I_RMDIR,	REMOTE	},
Lines 237-242 help(void) Link Here
237
	    "                                   filesystem containing 'path'\n"
242
	    "                                   filesystem containing 'path'\n"
238
	    "exit                               Quit sftp\n"
243
	    "exit                               Quit sftp\n"
239
	    "get [-Ppr] remote [local]          Download file\n"
244
	    "get [-Ppr] remote [local]          Download file\n"
245
	    "reget remote [local]		Resume download file\n"
240
	    "help                               Display this help text\n"
246
	    "help                               Display this help text\n"
241
	    "lcd path                           Change local directory to 'path'\n"
247
	    "lcd path                           Change local directory to 'path'\n"
242
	    "lls [ls-options [path]]            Display local directory listing\n"
248
	    "lls [ls-options [path]]            Display local directory listing\n"
Lines 517-523 pathname_is_dir(char *pathname) Link Here
517
523
518
static int
524
static int
519
process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
525
process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
520
    int pflag, int rflag)
526
    int pflag, int rflag, int resume)
521
{
527
{
522
	char *abs_src = NULL;
528
	char *abs_src = NULL;
523
	char *abs_dst = NULL;
529
	char *abs_dst = NULL;
Lines 568-582 process_get(struct sftp_conn *conn, char Link Here
568
			abs_dst = xstrdup(filename);
574
			abs_dst = xstrdup(filename);
569
		}
575
		}
570
		xfree(tmp);
576
		xfree(tmp);
571
577
		if (cresume)
572
		printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
578
			resume = cresume;
579
		if (resume)
580
			printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst);
581
		else
582
			printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
573
		if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
583
		if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
574
			if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, 
584
			if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, 
575
			    pflag || global_pflag, 1) == -1)
585
			    pflag || global_pflag, 1) == -1)
576
				err = -1;
586
				err = -1;
577
		} else {
587
		} else {
578
			if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
588
			if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
579
			    pflag || global_pflag) == -1)
589
			    pflag || global_pflag, resume) == -1)
580
				err = -1;
590
				err = -1;
581
		}
591
		}
582
		xfree(abs_dst);
592
		xfree(abs_dst);
Lines 1163-1168 parse_args(const char **cpp, int *pflag, Link Here
1163
	optidx = 1;
1173
	optidx = 1;
1164
	switch (cmdnum) {
1174
	switch (cmdnum) {
1165
	case I_GET:
1175
	case I_GET:
1176
	case I_REGET:
1166
	case I_PUT:
1177
	case I_PUT:
1167
		if ((optidx = parse_getput_flags(cmd, argv, argc,
1178
		if ((optidx = parse_getput_flags(cmd, argv, argc,
1168
		    pflag, rflag)) == -1)
1179
		    pflag, rflag)) == -1)
Lines 1288-1294 parse_dispatch_command(struct sftp_conn Link Here
1288
    int err_abort)
1299
    int err_abort)
1289
{
1300
{
1290
	char *path1, *path2, *tmp;
1301
	char *path1, *path2, *tmp;
1291
	int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0;
1302
	int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0; 
1303
	int resume = 0;
1292
	int cmdnum, i;
1304
	int cmdnum, i;
1293
	unsigned long n_arg = 0;
1305
	unsigned long n_arg = 0;
1294
	Attrib a, *aa;
1306
	Attrib a, *aa;
Lines 1315-1321 parse_dispatch_command(struct sftp_conn Link Here
1315
		err = -1;
1327
		err = -1;
1316
		break;
1328
		break;
1317
	case I_GET:
1329
	case I_GET:
1318
		err = process_get(conn, path1, path2, *pwd, pflag, rflag);
1330
		resume = 0;
1331
		err = process_get(conn, path1, path2, *pwd, pflag, rflag,
1332
			 	  resume);
1333
		break;
1334
	case I_REGET:
1335
		resume = 1;
1336
		err = process_get(conn, path1, path2, *pwd, pflag, rflag,
1337
				  resume);
1319
		break;
1338
		break;
1320
	case I_PUT:
1339
	case I_PUT:
1321
		err = process_put(conn, path1, path2, *pwd, pflag, rflag);
1340
		err = process_put(conn, path1, path2, *pwd, pflag, rflag);
Lines 1920-1929 interactive_loop(struct sftp_conn *conn, Link Here
1920
		} else {
1939
		} else {
1921
			if (file2 == NULL)
1940
			if (file2 == NULL)
1922
				snprintf(cmd, sizeof cmd, "get %s", dir);
1941
				snprintf(cmd, sizeof cmd, "get %s", dir);
1923
			else
1942
			else {
1924
				snprintf(cmd, sizeof cmd, "get %s %s", dir,
1943
				if (cresume)
1925
				    file2);
1944
					snprintf(cmd, sizeof cmd,
1926
1945
					"reget %s %s", dir, file2);
1946
				else
1947
					snprintf(cmd, sizeof cmd,
1948
					"get %s %s", dir, file2);
1949
			}
1927
			err = parse_dispatch_command(conn, cmd,
1950
			err = parse_dispatch_command(conn, cmd,
1928
			    &remote_path, 1);
1951
			    &remote_path, 1);
1929
			xfree(dir);
1952
			xfree(dir);
Lines 2111-2117 main(int argc, char **argv) Link Here
2111
	infile = stdin;
2134
	infile = stdin;
2112
2135
2113
	while ((ch = getopt(argc, argv,
2136
	while ((ch = getopt(argc, argv,
2114
	    "1246hpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
2137
	    "1246ahpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
2115
		switch (ch) {
2138
		switch (ch) {
2116
		/* Passed through to ssh(1) */
2139
		/* Passed through to ssh(1) */
2117
		case '4':
2140
		case '4':
Lines 2148-2153 main(int argc, char **argv) Link Here
2148
			break;
2171
			break;
2149
		case '2':
2172
		case '2':
2150
			sshver = 2;
2173
			sshver = 2;
2174
			break;
2175
		case 'a':
2176
			cresume = 1;
2151
			break;
2177
			break;
2152
		case 'B':
2178
		case 'B':
2153
			copy_buffer_len = strtol(optarg, &cp, 10);
2179
			copy_buffer_len = strtol(optarg, &cp, 10);
(-)sftp-client.h (-1 / +1 lines)
Lines 106-112 int do_symlink(struct sftp_conn *, 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 
(-)sftp-client.c (-11 / +44 lines)
Lines 987-1002 send_read_request(struct sftp_conn *conn Link Here
987
987
988
int
988
int
989
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
989
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
990
    Attrib *a, int pflag)
990
    Attrib *a, int pflag, int resume)
991
{
991
{
992
	Attrib junk;
992
	Attrib junk;
993
	Buffer msg;
993
	Buffer msg;
994
	char *handle;
994
	char *handle;
995
	int local_fd, status = 0, write_error;
995
	int local_fd = -1, status = 0, write_error, bigger;
996
	int read_error, write_errno;
996
	int read_error, write_errno;
997
	u_int64_t offset, size;
997
	u_int64_t offset = 0, size, highwater;
998
	u_int handle_len, mode, type, id, buflen, num_req, max_req;
998
	u_int handle_len, mode, type, id, buflen, num_req, max_req;
999
	off_t progress_counter;
999
	off_t progress_counter;
1000
	struct stat st;
1000
	struct request {
1001
	struct request {
1001
		u_int id;
1002
		u_int id;
1002
		u_int len;
1003
		u_int len;
Lines 1049-1059 do_download(struct sftp_conn *conn, char Link Here
1049
		return(-1);
1050
		return(-1);
1050
	}
1051
	}
1051
1052
1052
	local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC,
1053
	if (resume) {
1053
	    mode | S_IWRITE);
1054
		if (stat(local_path, &st) == -1) {
1055
			offset = 0;
1056
			local_fd = open(local_path, O_WRONLY | O_CREAT,
1057
					mode | S_IWRITE);
1058
		}
1059
		else {
1060
			if ((size_t)st.st_size > size) {
1061
				bigger = 1;
1062
				local_fd = -1;
1063
			}
1064
			else {
1065
				offset = st.st_size;	
1066
				local_fd = open(local_path,
1067
						O_WRONLY | O_CREAT,
1068
						mode | S_IWRITE);
1069
			}
1070
		}
1071
	}
1072
	else
1073
		local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC,
1074
				mode | S_IWRITE);
1054
	if (local_fd == -1) {
1075
	if (local_fd == -1) {
1055
		error("Couldn't open local file \"%s\" for writing: %s",
1076
		if (bigger)
1056
		    local_path, strerror(errno));
1077
			error("destination file bigger than source file");
1078
		else
1079
			error("Couldn't open local file \"%s\" for writing: %s",
1080
		    	      local_path, strerror(errno));
1057
		do_close(conn, handle, handle_len);
1081
		do_close(conn, handle, handle_len);
1058
		buffer_free(&msg);
1082
		buffer_free(&msg);
1059
		xfree(handle);
1083
		xfree(handle);
Lines 1061-1069 do_download(struct sftp_conn *conn, char Link Here
1061
	}
1085
	}
1062
1086
1063
	/* Read from remote and write to local */
1087
	/* Read from remote and write to local */
1064
	write_error = read_error = write_errno = num_req = offset = 0;
1088
	write_error = read_error = write_errno = num_req = 0;
1089
	highwater = 0;
1065
	max_req = 1;
1090
	max_req = 1;
1066
	progress_counter = 0;
1091
	progress_counter = offset;
1067
1092
1068
	if (showprogress && size != 0)
1093
	if (showprogress && size != 0)
1069
		start_progress_meter(remote_path, size, &progress_counter);
1094
		start_progress_meter(remote_path, size, &progress_counter);
Lines 1138-1143 do_download(struct sftp_conn *conn, char Link Here
1138
				write_error = 1;
1163
				write_error = 1;
1139
				max_req = 0;
1164
				max_req = 0;
1140
			}
1165
			}
1166
			else if (req->offset <= highwater)
1167
				highwater = req->offset + len;
1168
1141
			progress_counter += len;
1169
			progress_counter += len;
1142
			xfree(data);
1170
			xfree(data);
1143
1171
Lines 1186-1191 do_download(struct sftp_conn *conn, char Link Here
1186
	/* Sanity check */
1214
	/* Sanity check */
1187
	if (TAILQ_FIRST(&requests) != NULL)
1215
	if (TAILQ_FIRST(&requests) != NULL)
1188
		fatal("Transfer complete, but requests still in queue");
1216
		fatal("Transfer complete, but requests still in queue");
1217
	/* Truncate at highest contiguous point to avoid holes on interrupt */
1218
	if (read_error || write_error || interrupted) {
1219
		debug("truncating at %llu", highwater);
1220
		ftruncate(local_fd, highwater);
1221
	}
1189
1222
1190
	if (read_error) {
1223
	if (read_error) {
1191
		error("Couldn't read from remote file \"%s\" : %s",
1224
		error("Couldn't read from remote file \"%s\" : %s",
Lines 1232-1237 download_dir_internal(struct sftp_conn * Link Here
1232
	SFTP_DIRENT **dir_entries;
1265
	SFTP_DIRENT **dir_entries;
1233
	char *filename, *new_src, *new_dst;
1266
	char *filename, *new_src, *new_dst;
1234
	mode_t mode = 0777;
1267
	mode_t mode = 0777;
1268
	int resume = 0;
1235
1269
1236
	if (depth >= MAX_DIR_DEPTH) {
1270
	if (depth >= MAX_DIR_DEPTH) {
1237
		error("Maximum directory depth exceeded: %d levels", depth);
1271
		error("Maximum directory depth exceeded: %d levels", depth);
Lines 1283-1289 download_dir_internal(struct sftp_conn * Link Here
1283
				ret = -1;
1317
				ret = -1;
1284
		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1318
		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1285
			if (do_download(conn, new_src, new_dst,
1319
			if (do_download(conn, new_src, new_dst,
1286
			    &(dir_entries[i]->a), pflag) == -1) {
1320
			    &(dir_entries[i]->a), pflag, resume) == -1) {
1287
				error("Download of file %s to %s failed",
1321
				error("Download of file %s to %s failed",
1288
				    new_src, new_dst);
1322
				    new_src, new_dst);
1289
				ret = -1;
1323
				ret = -1;
Lines 1637-1640 path_append(char *p1, char *p2) Link Here
1637
1671
1638
	return(ret);
1672
	return(ret);
1639
}
1673
}
1640

Return to bug 2021