Bugzilla – Attachment 2422 Details for
Bug 2224
SFTP upload resume
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
sftp_resume_upload.diff
file_2224.txt (text/plain), 11.00 KB, created by
Loganaden Velvindron
on 2014-04-09 17:50:56 AEST
(
hide
)
Description:
sftp_resume_upload.diff
Filename:
MIME Type:
Creator:
Loganaden Velvindron
Created:
2014-04-09 17:50:56 AEST
Size:
11.00 KB
patch
obsolete
>diff --git a/sftp-client.c b/sftp-client.c >index 2f5907c..514cc2f 100644 >--- a/sftp-client.c >+++ b/sftp-client.c >@@ -1420,7 +1420,7 @@ download_dir(struct sftp_conn *conn, char *src, char *dst, > > int > do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, >- int preserve_flag, int fsync_flag) >+ int preserve_flag, int resume, int fsync_flag) > { > int local_fd; > int status = SSH2_FX_OK; >@@ -1429,7 +1429,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, > char *handle, *data; > Buffer msg; > struct stat sb; >- Attrib a; >+ Attrib a, *c = NULL; > u_int32_t startid; > u_int32_t ackid; > struct outstanding_ack { >@@ -1467,6 +1467,25 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, > if (!preserve_flag) > a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; > >+ if (resume) { >+ /* Get remote file size if it exists */ >+ if ((c = do_stat(conn, remote_path, 0)) == NULL) { >+ close(local_fd); >+ return -1; >+ } >+ >+ if ((off_t)c->size > sb.st_size || >+ (off_t)c->size == sb.st_size) { >+ error("destination file bigger or same size as source file"); >+ close(local_fd); >+ return -1; >+ } >+ >+ if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) { >+ close(local_fd); >+ return -1; >+ } >+ } > buffer_init(&msg); > > /* Send open request */ >@@ -1474,7 +1493,8 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, > buffer_put_char(&msg, SSH2_FXP_OPEN); > buffer_put_int(&msg, id); > buffer_put_cstring(&msg, remote_path); >- buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); >+ buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| >+ (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC)); > encode_attrib(&msg, &a); > send_msg(conn, &msg); > debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); >@@ -1493,7 +1513,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, > data = xmalloc(conn->transfer_buflen); > > /* Read from local and write to remote */ >- offset = progress_counter = 0; >+ offset = progress_counter = (resume ? c->size : 0); > if (showprogress) > start_progress_meter(local_path, sb.st_size, > &progress_counter); >@@ -1608,7 +1628,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, > > static int > upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, >- int preserve_flag, int print_flag, int fsync_flag) >+ int preserve_flag, int print_flag, int resume, int fsync_flag) > { > int ret = 0, status; > DIR *dirp; >@@ -1677,12 +1697,12 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, > continue; > > if (upload_dir_internal(conn, new_src, new_dst, >- depth + 1, preserve_flag, print_flag, >+ depth + 1, preserve_flag, print_flag, resume, > fsync_flag) == -1) > ret = -1; > } else if (S_ISREG(sb.st_mode)) { > if (do_upload(conn, new_src, new_dst, >- preserve_flag, fsync_flag) == -1) { >+ preserve_flag, resume, fsync_flag) == -1) { > error("Uploading of file %s to %s failed!", > new_src, new_dst); > ret = -1; >@@ -1701,7 +1721,7 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, > > int > upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, >- int print_flag, int fsync_flag) >+ int print_flag, int resume, int fsync_flag) > { > char *dst_canon; > int ret; >@@ -1712,7 +1732,7 @@ upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, > } > > ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, >- print_flag, fsync_flag); >+ print_flag, resume, fsync_flag); > > free(dst_canon); > return ret; >diff --git a/sftp-client.h b/sftp-client.h >index ba92ad0..920f40b 100644 >--- a/sftp-client.h >+++ b/sftp-client.h >@@ -120,13 +120,13 @@ int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, > * Upload 'local_path' to 'remote_path'. Preserve permissions and times > * if 'pflag' is set > */ >-int do_upload(struct sftp_conn *, char *, char *, int, int); >+int do_upload(struct sftp_conn *, char *, char *, int, int, int); > > /* > * Recursively upload 'local_directory' to 'remote_directory'. Preserve > * times if 'pflag' is set > */ >-int upload_dir(struct sftp_conn *, char *, char *, int, int, int); >+int upload_dir(struct sftp_conn *, char *, char *, int, int, int, int); > > /* Concatenate paths, taking care of slashes. Caller must free result. */ > char *path_append(char *, char *); >diff --git a/sftp.c b/sftp.c >index ad1f8c8..fff159c 100644 >--- a/sftp.c >+++ b/sftp.c >@@ -91,6 +91,9 @@ int global_rflag = 0; > /* When this option is set, we resume download if possible */ > int global_aflag = 0; > >+/* When this option is set, we resume upload if possible */ >+int global_ruflag = 0; >+ > /* When this option is set, the file transfers will always preserve times */ > int global_pflag = 0; > >@@ -159,6 +162,7 @@ enum sftp_command { > I_VERSION, > I_PROGRESS, > I_REGET, >+ I_REPUT > }; > > struct CMD { >@@ -200,6 +204,7 @@ static const struct CMD cmds[] = { > { "pwd", I_PWD, REMOTE }, > { "quit", I_QUIT, NOARGS }, > { "reget", I_REGET, REMOTE }, >+ { "reput", I_REPUT, LOCAL }, > { "rename", I_RENAME, REMOTE }, > { "rm", I_RM, REMOTE }, > { "rmdir", I_RMDIR, REMOTE }, >@@ -250,6 +255,7 @@ help(void) > "exit Quit sftp\n" > "get [-Ppr] remote [local] Download file\n" > "reget remote [local] Resume download file\n" >+ "reput [local] remote Resume upload 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" >@@ -362,7 +368,7 @@ make_absolute(char *p, char *pwd) > > static int > parse_getput_flags(const char *cmd, char **argv, int argc, >- int *aflag, int *fflag, int *pflag, int *rflag) >+ int *aflag, int *ruflag, int *fflag, int *pflag, int *rflag) > { > extern int opterr, optind, optopt, optreset; > int ch; >@@ -370,8 +376,8 @@ parse_getput_flags(const char *cmd, char **argv, int argc, > optind = optreset = 1; > opterr = 0; > >- *aflag = *fflag = *rflag = *pflag = 0; >- while ((ch = getopt(argc, argv, "afPpRr")) != -1) { >+ *aflag = *ruflag = *fflag = *rflag = *pflag = 0; >+ while ((ch = getopt(argc, argv, "afPpuRr")) != -1) { > switch (ch) { > case 'a': > *aflag = 1; >@@ -387,6 +393,9 @@ parse_getput_flags(const char *cmd, char **argv, int argc, > case 'R': > *rflag = 1; > break; >+ case 'u': >+ *ruflag = 1; >+ break; > default: > error("%s: Invalid flag -%c", cmd, optopt); > return -1; >@@ -660,7 +669,7 @@ out: > > static int > process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, >- int pflag, int rflag, int fflag) >+ int pflag, int rflag, int resume, int fflag) > { > char *tmp_dst = NULL; > char *abs_dst = NULL; >@@ -723,16 +732,19 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, > } > free(tmp); > >- if (!quiet) >+ resume |= global_ruflag; >+ if (!quiet && resume) >+ printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst); >+ else if (!quiet && !resume) > printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); > if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { > if (upload_dir(conn, g.gl_pathv[i], abs_dst, >- pflag || global_pflag, 1, >+ pflag || global_pflag, 1, resume, > fflag || global_fflag) == -1) > err = -1; > } else { > if (do_upload(conn, g.gl_pathv[i], abs_dst, >- pflag || global_pflag, >+ pflag || global_pflag, resume, > fflag || global_fflag) == -1) > err = -1; > } >@@ -1186,8 +1198,9 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote, > } > > static int >-parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag, >- int *hflag, int *iflag, int *lflag, int *pflag, int *rflag, int *sflag, >+parse_args(const char **cpp, int *ignore_errors, int *aflag, int *ruflag, >+ int *fflag, int *hflag, int *iflag, int *lflag, int *pflag, >+ int *rflag, int *sflag, > unsigned long *n_arg, char **path1, char **path2) > { > const char *cmd, *cp = *cpp; >@@ -1233,15 +1246,16 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag, > > /* Get arguments and parse flags */ > *aflag = *fflag = *hflag = *iflag = *lflag = *pflag = 0; >- *rflag = *sflag = 0; >+ *rflag = *ruflag = *sflag = 0; > *path1 = *path2 = NULL; > optidx = 1; > switch (cmdnum) { > case I_GET: > case I_REGET: >+ case I_REPUT: > case I_PUT: > if ((optidx = parse_getput_flags(cmd, argv, argc, >- aflag, fflag, pflag, rflag)) == -1) >+ aflag, ruflag, fflag, pflag, rflag)) == -1) > return -1; > /* Get first pathname (mandatory) */ > if (argc - optidx < 1) { >@@ -1256,11 +1270,6 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag, > /* Destination is not globbed */ > undo_glob_escape(*path2); > } >- if (*aflag && cmdnum == I_PUT) { >- /* XXX implement resume for uploads */ >- error("Resume is not supported for uploads"); >- return -1; >- } > break; > case I_LINK: > if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) >@@ -1382,7 +1391,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, > int err_abort) > { > char *path1, *path2, *tmp; >- int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0, iflag = 0; >+ int ignore_errors = 0, aflag = 0, ruflag = 0, fflag = 0, hflag = 0, >+ iflag = 0; > int lflag = 0, pflag = 0, rflag = 0, sflag = 0; > int cmdnum, i; > unsigned long n_arg = 0; >@@ -1392,7 +1402,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, > glob_t g; > > path1 = path2 = NULL; >- cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag, >+ cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &ruflag, &fflag, >+ &hflag, > &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, &path1, &path2); > if (ignore_errors != 0) > err_abort = 0; >@@ -1415,9 +1426,12 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, > err = process_get(conn, path1, path2, *pwd, pflag, > rflag, aflag, fflag); > break; >+ case I_REPUT: >+ ruflag = 1; >+ /* FALLTHROUGH */ > case I_PUT: > err = process_put(conn, path1, path2, *pwd, pflag, >- rflag, fflag); >+ rflag, ruflag, fflag); > break; > case I_RENAME: > path1 = make_absolute(path1, *pwd); >@@ -2243,7 +2257,7 @@ main(int argc, char **argv) > infile = stdin; > > while ((ch = getopt(argc, argv, >- "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) { >+ "1246afhpqruvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) { > switch (ch) { > /* Passed through to ssh(1) */ > case '4': >@@ -2335,6 +2349,9 @@ main(int argc, char **argv) > ssh_program = optarg; > replacearg(&args, 0, "%s", ssh_program); > break; >+ case 'u': >+ global_ruflag = 1; >+ break; > case 'h': > default: > usage();
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 Raw
Actions:
View
Attachments on
bug 2224
: 2422