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

Collapse All | Expand All

(-)sftp.c (-9 / +37 lines)
Lines 88-93 int showprogress = 1; Link Here
88
/* When this option is set, we always recursively download/upload directories */
88
/* When this option is set, we always recursively download/upload directories */
89
int global_rflag = 0;
89
int global_rflag = 0;
90
90
91
/* When this option is set, we resume download if possible */
92
int cresume = 0;
93
91
/* When this option is set, the file transfers will always preserve times */
94
/* When this option is set, the file transfers will always preserve times */
92
int global_pflag = 0;
95
int global_pflag = 0;
93
96
Lines 151-156 extern char *__progname; Link Here
151
#define I_SYMLINK	21
154
#define I_SYMLINK	21
152
#define I_VERSION	22
155
#define I_VERSION	22
153
#define I_PROGRESS	23
156
#define I_PROGRESS	23
157
#define I_REGET		26
154
158
155
struct CMD {
159
struct CMD {
156
	const char *c;
160
	const char *c;
Lines 190-195 static const struct CMD cmds[] = { Link Here
190
	{ "put",	I_PUT,		LOCAL	},
194
	{ "put",	I_PUT,		LOCAL	},
191
	{ "pwd",	I_PWD,		REMOTE	},
195
	{ "pwd",	I_PWD,		REMOTE	},
192
	{ "quit",	I_QUIT,		NOARGS	},
196
	{ "quit",	I_QUIT,		NOARGS	},
197
	{ "reget",	I_REGET,	REMOTE	},
193
	{ "rename",	I_RENAME,	REMOTE	},
198
	{ "rename",	I_RENAME,	REMOTE	},
194
	{ "rm",		I_RM,		REMOTE	},
199
	{ "rm",		I_RM,		REMOTE	},
195
	{ "rmdir",	I_RMDIR,	REMOTE	},
200
	{ "rmdir",	I_RMDIR,	REMOTE	},
Lines 239-244 help(void) Link Here
239
	    "                                   filesystem containing 'path'\n"
244
	    "                                   filesystem containing 'path'\n"
240
	    "exit                               Quit sftp\n"
245
	    "exit                               Quit sftp\n"
241
	    "get [-Ppr] remote [local]          Download file\n"
246
	    "get [-Ppr] remote [local]          Download file\n"
247
	    "reget remote [local]		Resume download file\n"
242
	    "help                               Display this help text\n"
248
	    "help                               Display this help text\n"
243
	    "lcd path                           Change local directory to 'path'\n"
249
	    "lcd path                           Change local directory to 'path'\n"
244
	    "lls [ls-options [path]]            Display local directory listing\n"
250
	    "lls [ls-options [path]]            Display local directory listing\n"
Lines 519-525 pathname_is_dir(char *pathname) Link Here
519
525
520
static int
526
static int
521
process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
527
process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
522
    int pflag, int rflag)
528
    int pflag, int rflag, int resume)
523
{
529
{
524
	char *abs_src = NULL;
530
	char *abs_src = NULL;
525
	char *abs_dst = NULL;
531
	char *abs_dst = NULL;
Lines 571-577 process_get(struct sftp_conn *conn, char Link Here
571
		}
577
		}
572
		free(tmp);
578
		free(tmp);
573
579
574
		if (!quiet)
580
		if (cresume)
581
			resume = cresume;
582
		if (!quiet && resume)
583
			printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst);
584
		else if (!quiet && !resume)
575
			printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
585
			printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
576
		if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
586
		if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
577
			if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, 
587
			if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, 
Lines 579-585 process_get(struct sftp_conn *conn, char Link Here
579
				err = -1;
589
				err = -1;
580
		} else {
590
		} else {
581
			if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
591
			if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
582
			    pflag || global_pflag) == -1)
592
			    pflag || global_pflag, resume) == -1)
583
				err = -1;
593
				err = -1;
584
		}
594
		}
585
		free(abs_dst);
595
		free(abs_dst);
Lines 1168-1173 parse_args(const char **cpp, int *pflag, Link Here
1168
	optidx = 1;
1178
	optidx = 1;
1169
	switch (cmdnum) {
1179
	switch (cmdnum) {
1170
	case I_GET:
1180
	case I_GET:
1181
	case I_REGET:
1171
	case I_PUT:
1182
	case I_PUT:
1172
		if ((optidx = parse_getput_flags(cmd, argv, argc,
1183
		if ((optidx = parse_getput_flags(cmd, argv, argc,
1173
		    pflag, rflag)) == -1)
1184
		    pflag, rflag)) == -1)
Lines 1294-1299 parse_dispatch_command(struct sftp_conn Link Here
1294
{
1305
{
1295
	char *path1, *path2, *tmp;
1306
	char *path1, *path2, *tmp;
1296
	int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0;
1307
	int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0;
1308
	int resume = 0;
1297
	int cmdnum, i;
1309
	int cmdnum, i;
1298
	unsigned long n_arg = 0;
1310
	unsigned long n_arg = 0;
1299
	Attrib a, *aa;
1311
	Attrib a, *aa;
Lines 1320-1327 parse_dispatch_command(struct sftp_conn Link Here
1320
		err = -1;
1332
		err = -1;
1321
		break;
1333
		break;
1322
	case I_GET:
1334
	case I_GET:
1323
		err = process_get(conn, path1, path2, *pwd, pflag, rflag);
1335
		resume = 0;
1324
		break;
1336
		err = process_get(conn, path1, path2, *pwd, pflag, rflag,
1337
				  resume);
1338
		break;
1339
	case I_REGET:
1340
		resume = 1;
1341
		err = process_get(conn, path1, path2, *pwd, pflag, rflag,
1342
				  resume);
1343
 		break;
1325
	case I_PUT:
1344
	case I_PUT:
1326
		err = process_put(conn, path1, path2, *pwd, pflag, rflag);
1345
		err = process_put(conn, path1, path2, *pwd, pflag, rflag);
1327
		break;
1346
		break;
Lines 1950-1958 interactive_loop(struct sftp_conn *conn, Link Here
1950
			/* XXX this is wrong wrt quoting */
1969
			/* XXX this is wrong wrt quoting */
1951
			if (file2 == NULL)
1970
			if (file2 == NULL)
1952
				snprintf(cmd, sizeof cmd, "get %s", dir);
1971
				snprintf(cmd, sizeof cmd, "get %s", dir);
1953
			else
1972
			else {
1954
				snprintf(cmd, sizeof cmd, "get %s %s", dir,
1973
				if (cresume)
1955
				    file2);
1974
					snprintf(cmd, sizeof cmd,
1975
					"reget %s %s", dir, file2);
1976
				else
1977
					snprintf(cmd, sizeof cmd,
1978
					"get %s %s", dir, file2);
1979
			}
1980
1956
1981
1957
			err = parse_dispatch_command(conn, cmd,
1982
			err = parse_dispatch_command(conn, cmd,
1958
			    &remote_path, 1);
1983
			    &remote_path, 1);
Lines 2142-2148 main(int argc, char **argv) Link Here
2142
	infile = stdin;
2167
	infile = stdin;
2143
2168
2144
	while ((ch = getopt(argc, argv,
2169
	while ((ch = getopt(argc, argv,
2145
	    "1246hpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
2170
	    "1246ahpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
2146
		switch (ch) {
2171
		switch (ch) {
2147
		/* Passed through to ssh(1) */
2172
		/* Passed through to ssh(1) */
2148
		case '4':
2173
		case '4':
Lines 2181-2186 main(int argc, char **argv) Link Here
2181
			break;
2206
			break;
2182
		case '2':
2207
		case '2':
2183
			sshver = 2;
2208
			sshver = 2;
2209
			break;
2210
		case 'a':
2211
			cresume = 1;
2184
			break;
2212
			break;
2185
		case 'B':
2213
		case 'B':
2186
			copy_buffer_len = strtol(optarg, &cp, 10);
2214
			copy_buffer_len = strtol(optarg, &cp, 10);
(-)sftp-client.c (-16 / +54 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, once = 0;
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-1070 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
	local_fd = open(local_path, O_WRONLY | O_CREAT | (resume ? : O_TRUNC), 
1054
	    mode | S_IWUSR);
1055
			mode | S_IWUSR);
1055
	if (local_fd == -1) {
1056
        if (local_fd == -1) {
1056
		error("Couldn't open local file \"%s\" for writing: %s",
1057
                error("Couldn't open local file \"%s\" for writing: %s",
1057
		    local_path, strerror(errno));
1058
                        local_path, strerror(errno));
1059
                do_close(conn, handle, handle_len);
1060
                buffer_free(&msg);
1061
                free(handle);
1062
                return(-1);
1063
        }	
1064
	if (fstat(local_fd, &st) == -1) {
1065
		error("unable to stat local file");
1058
		do_close(conn, handle, handle_len);
1066
		do_close(conn, handle, handle_len);
1059
		buffer_free(&msg);
1067
		buffer_free(&msg);
1060
		free(handle);
1068
		free(handle);
1061
		return(-1);
1069
		return (-1);
1070
	}
1071
	offset = highwater = st.st_size;
1072
	if ((size_t)st.st_size > size) {
1073
		bigger = 1;
1074
		error("Bigger file encountered");
1075
		do_close(conn, handle, handle_len);
1076
		buffer_free(&msg);
1077
		free(handle);
1078
		return (-1);
1062
	}
1079
	}
1063
1080
1081
1064
	/* Read from remote and write to local */
1082
	/* Read from remote and write to local */
1065
	write_error = read_error = write_errno = num_req = offset = 0;
1083
	write_error = read_error = write_errno = num_req = 0;
1066
	max_req = 1;
1084
	max_req = 1;
1067
	progress_counter = 0;
1085
	progress_counter = offset;
1068
1086
1069
	if (showprogress && size != 0)
1087
	if (showprogress && size != 0)
1070
		start_progress_meter(remote_path, size, &progress_counter);
1088
		start_progress_meter(remote_path, size, &progress_counter);
Lines 1073-1078 do_download(struct sftp_conn *conn, char Link Here
1073
		char *data;
1091
		char *data;
1074
		u_int len;
1092
		u_int len;
1075
1093
1094
		if (once == 0)
1095
			once++;
1096
1076
		/*
1097
		/*
1077
		 * Simulate EOF on interrupt: stop sending new requests and
1098
		 * Simulate EOF on interrupt: stop sending new requests and
1078
		 * allow outstanding requests to drain gracefully
1099
		 * allow outstanding requests to drain gracefully
Lines 1139-1144 do_download(struct sftp_conn *conn, char Link Here
1139
				write_error = 1;
1160
				write_error = 1;
1140
				max_req = 0;
1161
				max_req = 0;
1141
			}
1162
			}
1163
			else if (req->offset <= highwater)
1164
				highwater = req->offset + len;
1165
			else if (req->offset > highwater) {
1166
				highwater = 0;
1167
				if (once)
1168
					debug("reordered blocks detected");	
1169
			}
1142
			progress_counter += len;
1170
			progress_counter += len;
1143
			free(data);
1171
			free(data);
1144
1172
Lines 1187-1193 do_download(struct sftp_conn *conn, char Link Here
1187
	/* Sanity check */
1215
	/* Sanity check */
1188
	if (TAILQ_FIRST(&requests) != NULL)
1216
	if (TAILQ_FIRST(&requests) != NULL)
1189
		fatal("Transfer complete, but requests still in queue");
1217
		fatal("Transfer complete, but requests still in queue");
1190
1218
	/* Truncate at highest contiguous point to avoid holes on interrupt */
1219
	if (read_error || write_error || interrupted || (highwater == 0)) {
1220
		debug("truncating at %llu", highwater);
1221
		ftruncate(local_fd, highwater);
1222
	}
1191
	if (read_error) {
1223
	if (read_error) {
1192
		error("Couldn't read from remote file \"%s\" : %s",
1224
		error("Couldn't read from remote file \"%s\" : %s",
1193
		    remote_path, fx2txt(status));
1225
		    remote_path, fx2txt(status));
Lines 1197-1203 do_download(struct sftp_conn *conn, char Link Here
1197
		    strerror(write_errno));
1229
		    strerror(write_errno));
1198
		status = -1;
1230
		status = -1;
1199
		do_close(conn, handle, handle_len);
1231
		do_close(conn, handle, handle_len);
1200
	} else {
1232
	} else if (highwater == 0) {
1233
		error("Server reordered requests: %s download \
1234
			cannot be resumed", local_path);
1235
		status = -1;
1236
		do_close(conn, handle, handle_len); 
1237
	}
1238
	else {
1201
		status = do_close(conn, handle, handle_len);
1239
		status = do_close(conn, handle, handle_len);
1202
1240
1203
		/* Override umask and utimes if asked */
1241
		/* Override umask and utimes if asked */
Lines 1233-1238 download_dir_internal(struct sftp_conn * Link Here
1233
	SFTP_DIRENT **dir_entries;
1271
	SFTP_DIRENT **dir_entries;
1234
	char *filename, *new_src, *new_dst;
1272
	char *filename, *new_src, *new_dst;
1235
	mode_t mode = 0777;
1273
	mode_t mode = 0777;
1274
	int resume = 0;
1236
1275
1237
	if (depth >= MAX_DIR_DEPTH) {
1276
	if (depth >= MAX_DIR_DEPTH) {
1238
		error("Maximum directory depth exceeded: %d levels", depth);
1277
		error("Maximum directory depth exceeded: %d levels", depth);
Lines 1284-1290 download_dir_internal(struct sftp_conn * Link Here
1284
				ret = -1;
1323
				ret = -1;
1285
		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1324
		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1286
			if (do_download(conn, new_src, new_dst,
1325
			if (do_download(conn, new_src, new_dst,
1287
			    &(dir_entries[i]->a), pflag) == -1) {
1326
			    &(dir_entries[i]->a), pflag, resume) == -1) {
1288
				error("Download of file %s to %s failed",
1327
				error("Download of file %s to %s failed",
1289
				    new_src, new_dst);
1328
				    new_src, new_dst);
1290
				ret = -1;
1329
				ret = -1;
Lines 1640-1643 path_append(char *p1, char *p2) Link Here
1640
1679
1641
	return(ret);
1680
	return(ret);
1642
}
1681
}
1643
(-)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 

Return to bug 2021