Bugzilla – Attachment 1905 Details for
Bug 1798
Add fsync() support to sftp/sftp-server
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Correct return code from do_fsync() when server does not support the extension
sftp-fsync.diff (text/plain), 14.51 KB, created by
Iain Morgan
on 2010-07-20 05:36:40 AEST
(
hide
)
Description:
Correct return code from do_fsync() when server does not support the extension
Filename:
MIME Type:
Creator:
Iain Morgan
Created:
2010-07-20 05:36:40 AEST
Size:
14.51 KB
patch
obsolete
>Index: sftp-client.c >=================================================================== >RCS file: /cvs/openssh/sftp-client.c,v >retrieving revision 1.102 >diff -u -r1.102 sftp-client.c >--- sftp-client.c 25 Jun 2010 23:38:23 -0000 1.102 >+++ sftp-client.c 19 Jul 2010 19:21:58 -0000 >@@ -75,6 +75,7 @@ > #define SFTP_EXT_POSIX_RENAME 0x00000001 > #define SFTP_EXT_STATVFS 0x00000002 > #define SFTP_EXT_FSTATVFS 0x00000004 >+#define SFTP_EXT_FSYNC 0x00000008 > u_int exts; > }; > >@@ -352,10 +353,14 @@ > strcmp(value, "2") == 0) { > exts |= SFTP_EXT_STATVFS; > known = 1; >- } if (strcmp(name, "fstatvfs@openssh.com") == 0 && >+ } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && > strcmp(value, "2") == 0) { > exts |= SFTP_EXT_FSTATVFS; > known = 1; >+ } else if (strcmp(name, "fsync@openssh.com") == 0 && >+ strcmp(value, "1") == 0) { >+ exts |= SFTP_EXT_FSYNC; >+ known = 1; > } > if (known) { > debug2("Server supports extension \"%s\" revision %s", >@@ -802,6 +807,36 @@ > return(status); > } > >+int >+do_fsync(struct sftp_conn *conn, char *handle, u_int handle_len) >+{ >+ Buffer msg; >+ u_int status, id; >+ >+ /* Silently return if the extension is not supported */ >+ if ((conn->exts & SFTP_EXT_FSYNC) == 0) >+ return -1; >+ >+ buffer_init(&msg); >+ >+ /* Send fsync request */ >+ id = conn->msg_id++; >+ >+ buffer_put_char(&msg, SSH2_FXP_EXTENDED); >+ buffer_put_int(&msg, id); >+ buffer_put_cstring(&msg, "fsync@openssh.com"); >+ buffer_put_string(&msg, handle, handle_len); >+ send_msg(conn->fd_out, &msg); >+ debug3("Sent message fsync@openssh.com I:%u", id); >+ buffer_free(&msg); >+ >+ status = get_status(conn->fd_in, id); >+ if (status != SSH2_FX_OK) >+ error("Couldn't sync file: %s", fx2txt(status)); >+ >+ return(status); >+} >+ > #ifdef notyet > char * > do_readlink(struct sftp_conn *conn, char *path) >@@ -924,7 +959,7 @@ > > int > do_download(struct sftp_conn *conn, char *remote_path, char *local_path, >- Attrib *a, int pflag) >+ Attrib *a, int pflag, int sflag) > { > Attrib junk; > Buffer msg; >@@ -1153,6 +1188,13 @@ > error("Can't set times on \"%s\": %s", > local_path, strerror(errno)); > } >+ /* Flush file to disk if requested */ >+ if (sflag) { >+ debug("syncing \"%s\"", local_path); >+ if (fsync(local_fd) == -1) >+ error("Couldn't sync file \"%s\": %s", >+ local_path, strerror(errno)); >+ } > } > close(local_fd); > buffer_free(&msg); >@@ -1163,7 +1205,7 @@ > > static int > download_dir_internal(struct sftp_conn *conn, char *src, char *dst, >- Attrib *dirattrib, int pflag, int printflag, int depth) >+ Attrib *dirattrib, int pflag, int sflag, int printflag, int depth) > { > int i, ret = 0; > SFTP_DIRENT **dir_entries; >@@ -1215,12 +1257,12 @@ > strcmp(filename, "..") == 0) > continue; > if (download_dir_internal(conn, new_src, new_dst, >- &(dir_entries[i]->a), pflag, printflag, >+ &(dir_entries[i]->a), pflag, sflag, printflag, > depth + 1) == -1) > 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, sflag) == -1) { > error("Download of file %s to %s failed", > new_src, new_dst); > ret = -1; >@@ -1253,7 +1295,7 @@ > > int > download_dir(struct sftp_conn *conn, char *src, char *dst, >- Attrib *dirattrib, int pflag, int printflag) >+ Attrib *dirattrib, int pflag, int sflag, int printflag) > { > char *src_canon; > int ret; >@@ -1264,14 +1306,14 @@ > } > > ret = download_dir_internal(conn, src_canon, dst, >- dirattrib, pflag, printflag, 0); >+ dirattrib, pflag, sflag, printflag, 0); > xfree(src_canon); > return ret; > } > > int > do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, >- int pflag) >+ int pflag, int sflag) > { > int local_fd; > int status = SSH2_FX_OK; >@@ -1445,6 +1487,9 @@ > if (pflag) > do_fsetstat(conn, handle, handle_len, &a); > >+ if (sflag) >+ (void)do_fsync(conn, handle, handle_len); >+ > if (do_close(conn, handle, handle_len) != SSH2_FX_OK) > status = -1; > xfree(handle); >@@ -1454,7 +1499,7 @@ > > static int > upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, >- int pflag, int printflag, int depth) >+ int pflag, int sflag, int printflag, int depth) > { > int ret = 0, status; > DIR *dirp; >@@ -1523,10 +1568,11 @@ > continue; > > if (upload_dir_internal(conn, new_src, new_dst, >- pflag, depth + 1, printflag) == -1) >+ pflag, sflag, depth + 1, printflag) == -1) > ret = -1; > } else if (S_ISREG(sb.st_mode)) { >- if (do_upload(conn, new_src, new_dst, pflag) == -1) { >+ if (do_upload(conn, new_src, new_dst, pflag, >+ sflag) == -1) { > error("Uploading of file %s to %s failed!", > new_src, new_dst); > ret = -1; >@@ -1545,7 +1591,7 @@ > > int > upload_dir(struct sftp_conn *conn, char *src, char *dst, int printflag, >- int pflag) >+ int pflag, int sflag) > { > char *dst_canon; > int ret; >@@ -1555,7 +1601,7 @@ > return -1; > } > >- ret = upload_dir_internal(conn, src, dst_canon, pflag, printflag, 0); >+ ret = upload_dir_internal(conn, src, dst_canon, pflag, sflag, printflag, 0); > xfree(dst_canon); > return ret; > } >Index: sftp-client.h >=================================================================== >RCS file: /cvs/openssh/sftp-client.h,v >retrieving revision 1.18 >diff -u -r1.18 sftp-client.h >--- sftp-client.h 6 Oct 2009 21:37:48 -0000 1.18 >+++ sftp-client.h 19 Jul 2010 19:21:58 -0000 >@@ -103,25 +103,25 @@ > * 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 > * times if 'pflag' is set > */ >-int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, int); >+int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, int, 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 do_upload(struct sftp_conn *, char *, char *, 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 upload_dir(struct sftp_conn *, char *, char *, int, int, int); > > /* Concatenate paths, taking care of slashes. Caller must free result. */ > char *path_append(char *, char *); >Index: sftp-server.c >=================================================================== >RCS file: /cvs/openssh/sftp-server.c,v >retrieving revision 1.108 >diff -u -r1.108 sftp-server.c >--- sftp-server.c 13 Jan 2010 11:44:06 -0000 1.108 >+++ sftp-server.c 19 Jul 2010 19:21:59 -0000 >@@ -535,6 +535,9 @@ > /* fstatvfs extension */ > buffer_put_cstring(&msg, "fstatvfs@openssh.com"); > buffer_put_cstring(&msg, "2"); /* version */ >+ /* fsync extension */ >+ buffer_put_cstring(&msg, "fsync@openssh.com"); >+ buffer_put_cstring(&msg, "1"); /* version */ > send_msg(&msg); > buffer_free(&msg); > } >@@ -1223,6 +1226,26 @@ > } > > static void >+process_extended_fsync(u_int32_t id) >+{ >+ int handle, fd, ret, status = SSH2_FX_NO_SUCH_FILE; >+ >+ handle = get_handle(); >+ debug3("request %u: fsync \"%s\" (handle %u)", >+ id, handle_to_name(handle), handle); >+ if (readonly) >+ status = SSH2_FX_PERMISSION_DENIED; >+ else if ((fd = handle_to_fd(handle)) < 0) >+ status = SSH2_FX_NO_SUCH_FILE; >+ else if (handle_is_ok(handle, HANDLE_FILE)) { >+ ret = fsync(fd); >+ status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; >+ } >+ send_status(id, status); >+} >+ >+ >+static void > process_extended(void) > { > u_int32_t id; >@@ -1236,6 +1259,8 @@ > process_extended_statvfs(id); > else if (strcmp(request, "fstatvfs@openssh.com") == 0) > process_extended_fstatvfs(id); >+ else if (strcmp(request, "fsync@openssh.com") == 0) >+ process_extended_fsync(id); > else > send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ > xfree(request); >Index: sftp.1 >=================================================================== >RCS file: /cvs/openssh/sftp.1,v >retrieving revision 1.80 >diff -u -r1.80 sftp.1 >--- sftp.1 11 Feb 2010 22:21:03 -0000 1.80 >+++ sftp.1 19 Jul 2010 19:21:59 -0000 >@@ -31,7 +31,7 @@ > .Sh SYNOPSIS > .Nm sftp > .Bk -words >-.Op Fl 1246Cpqrv >+.Op Fl 1246Cfpqrv > .Op Fl B Ar buffer_size > .Op Fl b Ar batchfile > .Op Fl c Ar cipher >@@ -152,6 +152,10 @@ > .Xr ssh 1 . > This option is directly passed to > .Xr ssh 1 . >+.It Fl f >+Requests that files be flushed to disk immediately after transfer. >+When uploading files, this feature is only enabled if the server >+implements the "fsync@openssh.com" extension. > .It Fl i Ar identity_file > Selects the file from which the identity (private key) for public key > authentication is read. >@@ -330,7 +334,7 @@ > Quit > .Nm sftp . > .It Xo Ic get >-.Op Fl Ppr >+.Op Fl fPpr > .Ar remote-path > .Op Ar local-path > .Xc >@@ -350,6 +354,13 @@ > .Ar local-path > must specify a directory. > .Pp >+If the >+.Fl f >+flag is specified, then >+.Xr fsync 2 >+will ba called after the file transfer has completed to flush the file >+to disk. >+.Pp > If either the > .Fl P > or >@@ -445,7 +456,7 @@ > .It Ic progress > Toggle display of progress meter. > .It Xo Ic put >-.Op Fl Ppr >+.Op Fl fPpr > .Ar local-path > .Op Ar remote-path > .Xc >@@ -463,6 +474,14 @@ > is specified, then > .Ar remote-path > must specify a directory. >+.Pp >+If the >+.Fl f >+flag is specified, then a request will be sent to the server to call >+.Xr fsync 2 >+after the file has been transferred. >+Note that this is only supported by servers that implement the "fsync@openssh.com" >+extension. > .Pp > If ether the > .Fl P >Index: sftp.c >=================================================================== >RCS file: /cvs/openssh/sftp.c,v >retrieving revision 1.136 >diff -u -r1.136 sftp.c >--- sftp.c 25 Jun 2010 23:36:58 -0000 1.136 >+++ sftp.c 19 Jul 2010 19:21:59 -0000 >@@ -89,6 +89,9 @@ > /* When this option is set, the file transfers will always preserve times */ > int global_pflag = 0; > >+/* When this is set, call fsync() after each file */ >+int global_sflag = 0; >+ > /* SIGINT received during command processing */ > volatile sig_atomic_t interrupted = 0; > >@@ -348,7 +351,7 @@ > > static int > parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag, >- int *rflag) >+ int *rflag, int *sflag) > { > extern int opterr, optind, optopt, optreset; > int ch; >@@ -357,7 +360,8 @@ > opterr = 0; > > *rflag = *pflag = 0; >- while ((ch = getopt(argc, argv, "PpRr")) != -1) { >+ *sflag = global_sflag; >+ while ((ch = getopt(argc, argv, "FfPpRr")) != -1) { > switch (ch) { > case 'p': > case 'P': >@@ -367,6 +371,10 @@ > case 'R': > *rflag = 1; > break; >+ case 'f': >+ case 'F': >+ *sflag = 1; >+ break; > default: > error("%s: Invalid flag -%c", cmd, optopt); > return -1; >@@ -492,7 +500,7 @@ > > static int > process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, >- int pflag, int rflag) >+ int pflag, int rflag, int sflag) > { > char *abs_src = NULL; > char *abs_dst = NULL; >@@ -547,11 +555,11 @@ > 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, >- pflag || global_pflag, 1) == -1) >+ pflag || global_pflag, sflag, 1) == -1) > err = -1; > } else { > if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, >- pflag || global_pflag) == -1) >+ pflag || global_pflag, sflag) == -1) > err = -1; > } > xfree(abs_dst); >@@ -566,7 +574,7 @@ > > static int > process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, >- int pflag, int rflag) >+ int pflag, int rflag, int sflag) > { > char *tmp_dst = NULL; > char *abs_dst = NULL; >@@ -632,11 +640,11 @@ > 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) == -1) >+ pflag || global_pflag, sflag, 1) == -1) > err = -1; > } else { > if (do_upload(conn, g.gl_pathv[i], abs_dst, >- pflag || global_pflag) == -1) >+ pflag || global_pflag, sflag) == -1) > err = -1; > } > } >@@ -1107,8 +1115,8 @@ > } > > static int >-parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, >- int *hflag, unsigned long *n_arg, char **path1, char **path2) >+parse_args(const char **cpp, int *pflag, int *rflag, int *sflag, int *lflag, >+ int *iflag, int *hflag, unsigned long *n_arg, char **path1, char **path2) > { > const char *cmd, *cp = *cpp; > char *cp2, **argv; >@@ -1158,7 +1166,7 @@ > switch (cmdnum) { > case I_GET: > case I_PUT: >- if ((optidx = parse_getput_flags(cmd, argv, argc, pflag, rflag)) == -1) >+ if ((optidx = parse_getput_flags(cmd, argv, argc, pflag, rflag, sflag)) == -1) > return -1; > /* Get first pathname (mandatory) */ > if (argc - optidx < 1) { >@@ -1278,7 +1286,7 @@ > int err_abort) > { > char *path1, *path2, *tmp; >- int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, cmdnum, i; >+ int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0, cmdnum, i; > unsigned long n_arg = 0; > Attrib a, *aa; > char path_buf[MAXPATHLEN]; >@@ -1286,8 +1294,8 @@ > glob_t g; > > path1 = path2 = NULL; >- cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag, &n_arg, >- &path1, &path2); >+ cmdnum = parse_args(&cmd, &pflag, &rflag, &sflag, &lflag, &iflag, >+ &hflag, &n_arg, &path1, &path2); > > if (iflag != 0) > err_abort = 0; >@@ -1304,10 +1312,12 @@ > err = -1; > break; > case I_GET: >- err = process_get(conn, path1, path2, *pwd, pflag, rflag); >+ err = process_get(conn, path1, path2, *pwd, pflag, >+ rflag, sflag); > break; > case I_PUT: >- err = process_put(conn, path1, path2, *pwd, pflag, rflag); >+ err = process_put(conn, path1, path2, *pwd, pflag, >+ rflag, sflag); > break; > case I_RENAME: > path1 = make_absolute(path1, *pwd); >@@ -2052,7 +2062,7 @@ > extern char *__progname; > > fprintf(stderr, >- "usage: %s [-1246Cpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n" >+ "usage: %s [-1246Cfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n" > " [-D sftp_server_path] [-F ssh_config] " > "[-i identity_file]\n" > " [-o ssh_option] [-P port] [-R num_requests] " >@@ -2097,7 +2107,7 @@ > infile = stdin; > > while ((ch = getopt(argc, argv, >- "1246hpqrvCc:D:i:o:s:S:b:B:F:P:R:")) != -1) { >+ "1246fhpqrvCc:D:i:o:s:S:b:B:F:P:R:")) != -1) { > switch (ch) { > /* Passed through to ssh(1) */ > case '4': >@@ -2151,6 +2161,9 @@ > showprogress = 0; > batchmode = 1; > addargs(&args, "-obatchmode yes"); >+ break; >+ case 'f': >+ global_sflag = 1; > break; > case 'p': > global_pflag = 1;
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 1798
:
1898
|
1905
|
2065
|
2351