Bugzilla – Attachment 2302 Details for
Bug 2021
sftp resume support (using size and offset)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
resume diff with corrections
resume4.diff (text/plain), 9.51 KB, created by
Loganaden Velvindron
on 2013-06-19 19:59:12 AEST
(
hide
)
Description:
resume diff with corrections
Filename:
MIME Type:
Creator:
Loganaden Velvindron
Created:
2013-06-19 19:59:12 AEST
Size:
9.51 KB
patch
obsolete
>Index: sftp.c >=================================================================== >RCS file: /cvs/openssh/sftp.c,v >retrieving revision 1.159 >diff -u -p -r1.159 sftp.c >--- sftp.c 5 Jun 2013 22:30:21 -0000 1.159 >+++ sftp.c 19 Jun 2013 09:53:32 -0000 >@@ -88,6 +88,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 cresume = 0; >+ > /* When this option is set, the file transfers will always preserve times */ > int global_pflag = 0; > >@@ -151,6 +154,7 @@ extern char *__progname; > #define I_SYMLINK 21 > #define I_VERSION 22 > #define I_PROGRESS 23 >+#define I_REGET 26 > > struct CMD { > const char *c; >@@ -190,6 +194,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 }, >@@ -239,6 +244,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" >@@ -519,7 +525,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; >@@ -571,7 +577,11 @@ process_get(struct sftp_conn *conn, char > } > free(tmp); > >- if (!quiet) >+ if (cresume) >+ resume = cresume; >+ 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, >@@ -579,7 +589,7 @@ process_get(struct sftp_conn *conn, char > 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); >@@ -1168,6 +1178,7 @@ parse_args(const char **cpp, int *pflag, > optidx = 1; > switch (cmdnum) { > case I_GET: >+ case I_REGET: > case I_PUT: > if ((optidx = parse_getput_flags(cmd, argv, argc, > pflag, rflag)) == -1) >@@ -1294,6 +1305,7 @@ parse_dispatch_command(struct sftp_conn > { > char *path1, *path2, *tmp; > int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0; >+ int resume = 0; > int cmdnum, i; > unsigned long n_arg = 0; > Attrib a, *aa; >@@ -1320,8 +1332,15 @@ parse_dispatch_command(struct sftp_conn > err = -1; > break; > case I_GET: >- err = process_get(conn, path1, path2, *pwd, pflag, rflag); >- break; >+ resume = 0; >+ err = process_get(conn, path1, path2, *pwd, pflag, rflag, >+ resume); >+ break; >+ case I_REGET: >+ resume = 1; >+ err = process_get(conn, path1, path2, *pwd, pflag, rflag, >+ resume); >+ break; > case I_PUT: > err = process_put(conn, path1, path2, *pwd, pflag, rflag); > break; >@@ -1950,9 +1969,15 @@ interactive_loop(struct sftp_conn *conn, > /* 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); >+ else { >+ if (cresume) >+ snprintf(cmd, sizeof cmd, >+ "reget %s %s", dir, file2); >+ else >+ snprintf(cmd, sizeof cmd, >+ "get %s %s", dir, file2); >+ } >+ > > err = parse_dispatch_command(conn, cmd, > &remote_path, 1); >@@ -2142,7 +2167,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': >@@ -2181,6 +2206,9 @@ main(int argc, char **argv) > break; > case '2': > sshver = 2; >+ break; >+ case 'a': >+ cresume = 1; > break; > case 'B': > copy_buffer_len = strtol(optarg, &cp, 10); >Index: sftp-client.c >=================================================================== >RCS file: /cvs/openssh/sftp-client.c,v >retrieving revision 1.111 >diff -u -p -r1.111 sftp-client.c >--- sftp-client.c 1 Jun 2013 22:37:06 -0000 1.111 >+++ sftp-client.c 19 Jun 2013 09:53:32 -0000 >@@ -988,16 +988,17 @@ send_read_request(struct sftp_conn *conn > > int > do_download(struct sftp_conn *conn, char *remote_path, char *local_path, >- Attrib *a, int pflag) >+ Attrib *a, int pflag, int resume) > { > Attrib junk; > Buffer msg; > char *handle; >- int local_fd, status = 0, write_error; >+ int local_fd = -1, status = 0, write_error, bigger; > int read_error, write_errno; >- u_int64_t offset, size; >- u_int handle_len, mode, type, id, buflen, num_req, max_req; >+ u_int64_t offset = 0, size, highwater; >+ u_int handle_len, mode, type, id, buflen, num_req, max_req, once = 0; > off_t progress_counter; >+ struct stat st; > struct request { > u_int id; > u_int len; >@@ -1050,21 +1051,38 @@ do_download(struct sftp_conn *conn, char > return(-1); > } > >- local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, >- mode | S_IWUSR); >- if (local_fd == -1) { >- error("Couldn't open local file \"%s\" for writing: %s", >- local_path, strerror(errno)); >+ local_fd = open(local_path, O_WRONLY | O_CREAT | (resume ? : O_TRUNC), >+ mode | S_IWUSR); >+ if (local_fd == -1) { >+ error("Couldn't open local file \"%s\" for writing: %s", >+ local_path, strerror(errno)); >+ do_close(conn, handle, handle_len); >+ buffer_free(&msg); >+ free(handle); >+ return(-1); >+ } >+ if (fstat(local_fd, &st) == -1) { >+ error("unable to stat local file"); > do_close(conn, handle, handle_len); > buffer_free(&msg); > free(handle); >- return(-1); >+ return (-1); >+ } >+ offset = highwater = st.st_size; >+ if ((size_t)st.st_size > size) { >+ bigger = 1; >+ error("Bigger file encountered"); >+ do_close(conn, handle, handle_len); >+ buffer_free(&msg); >+ free(handle); >+ return (-1); > } > >+ > /* Read from remote and write to local */ >- write_error = read_error = write_errno = num_req = offset = 0; >+ write_error = read_error = write_errno = num_req = 0; > max_req = 1; >- progress_counter = 0; >+ progress_counter = offset; > > if (showprogress && size != 0) > start_progress_meter(remote_path, size, &progress_counter); >@@ -1073,6 +1091,9 @@ do_download(struct sftp_conn *conn, char > char *data; > u_int len; > >+ if (once == 0) >+ once++; >+ > /* > * Simulate EOF on interrupt: stop sending new requests and > * allow outstanding requests to drain gracefully >@@ -1139,6 +1160,13 @@ do_download(struct sftp_conn *conn, char > write_error = 1; > max_req = 0; > } >+ else if (req->offset <= highwater) >+ highwater = req->offset + len; >+ else if (req->offset > highwater) { >+ highwater = 0; >+ if (once) >+ debug("reordered blocks detected"); >+ } > progress_counter += len; > free(data); > >@@ -1187,7 +1215,11 @@ do_download(struct sftp_conn *conn, char > /* Sanity check */ > if (TAILQ_FIRST(&requests) != NULL) > fatal("Transfer complete, but requests still in queue"); >- >+ /* Truncate at highest contiguous point to avoid holes on interrupt */ >+ if (read_error || write_error || interrupted || (highwater == 0)) { >+ debug("truncating at %llu", highwater); >+ ftruncate(local_fd, highwater); >+ } > if (read_error) { > error("Couldn't read from remote file \"%s\" : %s", > remote_path, fx2txt(status)); >@@ -1197,7 +1229,13 @@ do_download(struct sftp_conn *conn, char > strerror(write_errno)); > status = -1; > do_close(conn, handle, handle_len); >- } else { >+ } else if (highwater == 0) { >+ error("Server reordered requests: %s download \ >+ cannot be resumed", local_path); >+ status = -1; >+ do_close(conn, handle, handle_len); >+ } >+ else { > status = do_close(conn, handle, handle_len); > > /* Override umask and utimes if asked */ >@@ -1233,6 +1271,7 @@ download_dir_internal(struct sftp_conn * > SFTP_DIRENT **dir_entries; > char *filename, *new_src, *new_dst; > mode_t mode = 0777; >+ int resume = 0; > > if (depth >= MAX_DIR_DEPTH) { > error("Maximum directory depth exceeded: %d levels", depth); >@@ -1284,7 +1323,7 @@ download_dir_internal(struct sftp_conn * > ret = -1; > } else if (S_ISREG(dir_entries[i]->a.perm) ) { > if (do_download(conn, new_src, new_dst, >- &(dir_entries[i]->a), pflag) == -1) { >+ &(dir_entries[i]->a), pflag, resume) == -1) { > error("Download of file %s to %s failed", > new_src, new_dst); > ret = -1; >@@ -1640,4 +1679,3 @@ path_append(char *p1, char *p2) > > return(ret); > } >- >Index: sftp-client.h >=================================================================== >RCS file: /cvs/openssh/sftp-client.h,v >retrieving revision 1.20 >diff -u -p -r1.20 sftp-client.h >--- sftp-client.h 4 Dec 2010 22:02:48 -0000 1.20 >+++ sftp-client.h 19 Jun 2013 09:53:32 -0000 >@@ -106,7 +106,7 @@ int do_symlink(struct sftp_conn *, char > * Download 'remote_path' to 'local_path'. Preserve permissions and times > * if 'pflag' is set > */ >-int do_download(struct sftp_conn *, char *, char *, Attrib *, int); >+int do_download(struct sftp_conn *, char *, char *, Attrib *, int, int); > > /* > * Recursively download 'remote_directory' to 'local_directory'. Preserve
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 2021
:
2165
|
2168
|
2170
|
2198
|
2199
|
2302
|
2304
|
2305
|
2313
|
2314
|
2316