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 1166-1171 parse_args(const char **cpp, int *pflag, Link Here
1166
	optidx = 1;
1176
	optidx = 1;
1167
	switch (cmdnum) {
1177
	switch (cmdnum) {
1168
	case I_GET:
1178
	case I_GET:
1179
	case I_REGET:
1169
	case I_PUT:
1180
	case I_PUT:
1170
		if ((optidx = parse_getput_flags(cmd, argv, argc,
1181
		if ((optidx = parse_getput_flags(cmd, argv, argc,
1171
		    pflag, rflag)) == -1)
1182
		    pflag, rflag)) == -1)
Lines 1291-1297 parse_dispatch_command(struct sftp_conn Link Here
1291
    int err_abort)
1302
    int err_abort)
1292
{
1303
{
1293
	char *path1, *path2, *tmp;
1304
	char *path1, *path2, *tmp;
1294
	int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0;
1305
	int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0; 
1306
	int resume = 0;
1295
	int cmdnum, i;
1307
	int cmdnum, i;
1296
	unsigned long n_arg = 0;
1308
	unsigned long n_arg = 0;
1297
	Attrib a, *aa;
1309
	Attrib a, *aa;
Lines 1318-1324 parse_dispatch_command(struct sftp_conn Link Here
1318
		err = -1;
1330
		err = -1;
1319
		break;
1331
		break;
1320
	case I_GET:
1332
	case I_GET:
1321
		err = process_get(conn, path1, path2, *pwd, pflag, rflag);
1333
		resume = 0;
1334
		err = process_get(conn, path1, path2, *pwd, pflag, rflag,
1335
			 	  resume);
1336
		break;
1337
	case I_REGET:
1338
		resume = 1;
1339
		err = process_get(conn, path1, path2, *pwd, pflag, rflag,
1340
				  resume);
1322
		break;
1341
		break;
1323
	case I_PUT:
1342
	case I_PUT:
1324
		err = process_put(conn, path1, path2, *pwd, pflag, rflag);
1343
		err = process_put(conn, path1, path2, *pwd, pflag, rflag);
Lines 1939-1948 interactive_loop(struct sftp_conn *conn, Link Here
1939
			/* XXX this is wrong wrt quoting */
1958
			/* XXX this is wrong wrt quoting */
1940
			if (file2 == NULL)
1959
			if (file2 == NULL)
1941
				snprintf(cmd, sizeof cmd, "get %s", dir);
1960
				snprintf(cmd, sizeof cmd, "get %s", dir);
1942
			else
1961
			else {
1943
				snprintf(cmd, sizeof cmd, "get %s %s", dir,
1962
				if (cresume)
1944
				    file2);
1963
					snprintf(cmd, sizeof cmd,
1945
1964
					"reget %s %s", dir, file2);
1965
				else
1966
					snprintf(cmd, sizeof cmd,
1967
					"get %s %s", dir, file2);
1968
			}
1946
			err = parse_dispatch_command(conn, cmd,
1969
			err = parse_dispatch_command(conn, cmd,
1947
			    &remote_path, 1);
1970
			    &remote_path, 1);
1948
			xfree(dir);
1971
			xfree(dir);
Lines 2130-2136 main(int argc, char **argv) Link Here
2130
	infile = stdin;
2153
	infile = stdin;
2131
2154
2132
	while ((ch = getopt(argc, argv,
2155
	while ((ch = getopt(argc, argv,
2133
	    "1246hpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
2156
	    "1246ahpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
2134
		switch (ch) {
2157
		switch (ch) {
2135
		/* Passed through to ssh(1) */
2158
		/* Passed through to ssh(1) */
2136
		case '4':
2159
		case '4':
Lines 2167-2172 main(int argc, char **argv) Link Here
2167
			break;
2190
			break;
2168
		case '2':
2191
		case '2':
2169
			sshver = 2;
2192
			sshver = 2;
2193
			break;
2194
		case 'a':
2195
			cresume = 1;
2170
			break;
2196
			break;
2171
		case 'B':
2197
		case 'B':
2172
			copy_buffer_len = strtol(optarg, &cp, 10);
2198
			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 / +48 lines)
Lines 988-1003 send_read_request(struct sftp_conn *conn Link Here
988
988
989
int
989
int
990
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
990
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
991
    Attrib *a, int pflag)
991
    Attrib *a, int pflag, int resume)
992
{
992
{
993
	Attrib junk;
993
	Attrib junk;
994
	Buffer msg;
994
	Buffer msg;
995
	char *handle;
995
	char *handle;
996
	int local_fd, status = 0, write_error;
996
	int local_fd = -1, status = 0, write_error, bigger;
997
	int read_error, write_errno;
997
	int read_error, write_errno;
998
	u_int64_t offset, size;
998
	u_int64_t offset = 0, size, highwater;
999
	u_int handle_len, mode, type, id, buflen, num_req, max_req;
999
	u_int handle_len, mode, type, id, buflen, num_req, max_req;
1000
	off_t progress_counter;
1000
	off_t progress_counter;
1001
	struct stat st;
1001
	struct request {
1002
	struct request {
1002
		u_int id;
1003
		u_int id;
1003
		u_int len;
1004
		u_int len;
Lines 1050-1060 do_download(struct sftp_conn *conn, char Link Here
1050
		return(-1);
1051
		return(-1);
1051
	}
1052
	}
1052
1053
1053
	local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC,
1054
	if (resume) {
1054
	    mode | S_IWRITE);
1055
		if (stat(local_path, &st) == -1) {
1056
			offset = 0;
1057
			highwater = 0;
1058
			local_fd = open(local_path, O_WRONLY | O_CREAT,
1059
					mode | S_IWRITE);
1060
		}
1061
		else {
1062
			if ((size_t)st.st_size > size) {
1063
				bigger = 1;
1064
				local_fd = -1;
1065
			}
1066
			else {
1067
				offset = st.st_size;
1068
				highwater = st.st_size;	
1069
				local_fd = open(local_path,
1070
						O_WRONLY | O_CREAT,
1071
						mode | S_IWRITE);
1072
			}
1073
		}
1074
	}
1075
	else
1076
		local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC,
1077
				mode | S_IWRITE);
1055
	if (local_fd == -1) {
1078
	if (local_fd == -1) {
1056
		error("Couldn't open local file \"%s\" for writing: %s",
1079
		if (bigger)
1057
		    local_path, strerror(errno));
1080
			error("destination file bigger than source file");
1081
		else
1082
			error("Couldn't open local file \"%s\" for writing: %s",
1083
		    	      local_path, strerror(errno));
1058
		do_close(conn, handle, handle_len);
1084
		do_close(conn, handle, handle_len);
1059
		buffer_free(&msg);
1085
		buffer_free(&msg);
1060
		xfree(handle);
1086
		xfree(handle);
Lines 1062-1070 do_download(struct sftp_conn *conn, char Link Here
1062
	}
1088
	}
1063
1089
1064
	/* Read from remote and write to local */
1090
	/* Read from remote and write to local */
1065
	write_error = read_error = write_errno = num_req = offset = 0;
1091
	write_error = read_error = write_errno = num_req = 0;
1066
	max_req = 1;
1092
	max_req = 1;
1067
	progress_counter = 0;
1093
	progress_counter = offset;
1068
1094
1069
	if (showprogress && size != 0)
1095
	if (showprogress && size != 0)
1070
		start_progress_meter(remote_path, size, &progress_counter);
1096
		start_progress_meter(remote_path, size, &progress_counter);
Lines 1139-1144 do_download(struct sftp_conn *conn, char Link Here
1139
				write_error = 1;
1165
				write_error = 1;
1140
				max_req = 0;
1166
				max_req = 0;
1141
			}
1167
			}
1168
			else if (req->offset <= highwater)
1169
				highwater = req->offset + len;
1170
			else if (req->offset > highwater) {
1171
				ftruncate(local_fd, 0);
1172
				printf("reordered blocks detected");	
1173
			}	
1142
			progress_counter += len;
1174
			progress_counter += len;
1143
			xfree(data);
1175
			xfree(data);
1144
1176
Lines 1187-1192 do_download(struct sftp_conn *conn, char Link Here
1187
	/* Sanity check */
1219
	/* Sanity check */
1188
	if (TAILQ_FIRST(&requests) != NULL)
1220
	if (TAILQ_FIRST(&requests) != NULL)
1189
		fatal("Transfer complete, but requests still in queue");
1221
		fatal("Transfer complete, but requests still in queue");
1222
	/* Truncate at highest contiguous point to avoid holes on interrupt */
1223
	if (read_error || write_error || interrupted) {
1224
		debug("truncating at %llu", highwater);
1225
		ftruncate(local_fd, highwater);
1226
	}
1190
1227
1191
	if (read_error) {
1228
	if (read_error) {
1192
		error("Couldn't read from remote file \"%s\" : %s",
1229
		error("Couldn't read from remote file \"%s\" : %s",
Lines 1233-1238 download_dir_internal(struct sftp_conn * Link Here
1233
	SFTP_DIRENT **dir_entries;
1270
	SFTP_DIRENT **dir_entries;
1234
	char *filename, *new_src, *new_dst;
1271
	char *filename, *new_src, *new_dst;
1235
	mode_t mode = 0777;
1272
	mode_t mode = 0777;
1273
	int resume = 0;
1236
1274
1237
	if (depth >= MAX_DIR_DEPTH) {
1275
	if (depth >= MAX_DIR_DEPTH) {
1238
		error("Maximum directory depth exceeded: %d levels", depth);
1276
		error("Maximum directory depth exceeded: %d levels", depth);
Lines 1284-1290 download_dir_internal(struct sftp_conn * Link Here
1284
				ret = -1;
1322
				ret = -1;
1285
		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1323
		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1286
			if (do_download(conn, new_src, new_dst,
1324
			if (do_download(conn, new_src, new_dst,
1287
			    &(dir_entries[i]->a), pflag) == -1) {
1325
			    &(dir_entries[i]->a), pflag, resume) == -1) {
1288
				error("Download of file %s to %s failed",
1326
				error("Download of file %s to %s failed",
1289
				    new_src, new_dst);
1327
				    new_src, new_dst);
1290
				ret = -1;
1328
				ret = -1;
Lines 1638-1641 path_append(char *p1, char *p2) Link Here
1638
1676
1639
	return(ret);
1677
	return(ret);
1640
}
1678
}
1641

Return to bug 2021