Bugzilla – Attachment 2065 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]
Updated patch vs -current
sftp-fsync.diff (text/plain), 14.21 KB, created by
Iain Morgan
on 2011-07-16 06:44:59 AEST
(
hide
)
Description:
Updated patch vs -current
Filename:
MIME Type:
Creator:
Iain Morgan
Created:
2011-07-16 06:44:59 AEST
Size:
14.21 KB
patch
obsolete
>Index: sftp-client.c >=================================================================== >RCS file: /cvs/openssh/sftp-client.c,v >retrieving revision 1.105 >diff -u -u -r1.105 sftp-client.c >--- sftp-client.c 4 Dec 2010 22:02:48 -0000 1.105 >+++ sftp-client.c 5 May 2011 19:14:15 -0000 >@@ -76,6 +76,7 @@ > #define SFTP_EXT_STATVFS 0x00000002 > #define SFTP_EXT_FSTATVFS 0x00000004 > #define SFTP_EXT_HARDLINK 0x00000008 >+#define SFTP_EXT_FSYNC 0x00000010 > u_int exts; > u_int64_t limit_kbps; > struct bwlimit bwlimit_in, bwlimit_out; >@@ -387,6 +388,10 @@ > strcmp(value, "1") == 0) { > ret->exts |= SFTP_EXT_HARDLINK; > known = 1; >+ } else if (strcmp(name, "fsync@openssh.com") == 0 && >+ strcmp(value, "1") == 0) { >+ ret->exts |= SFTP_EXT_FSYNC; >+ known = 1; > } > if (known) { > debug2("Server supports extension \"%s\" revision %s", >@@ -864,6 +869,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, &msg); >+ debug3("Sent message fsync@openssh.com I:%u", id); >+ buffer_free(&msg); >+ >+ status = get_status(conn, 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) >@@ -985,7 +1020,7 @@ > > int > do_download(struct sftp_conn *conn, char *remote_path, char *local_path, >- Attrib *a, int pflag) >+ Attrib *a, int pflag, int fflag) > { > Attrib junk; > Buffer msg; >@@ -1214,6 +1249,13 @@ > error("Can't set times on \"%s\": %s", > local_path, strerror(errno)); > } >+ /* Flush file to disk if requested */ >+ if (fflag) { >+ 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); >@@ -1224,7 +1266,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 fflag, int printflag, int depth) > { > int i, ret = 0; > SFTP_DIRENT **dir_entries; >@@ -1276,12 +1318,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, fflag, 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, fflag) == -1) { > error("Download of file %s to %s failed", > new_src, new_dst); > ret = -1; >@@ -1314,7 +1356,7 @@ > > int > download_dir(struct sftp_conn *conn, char *src, char *dst, >- Attrib *dirattrib, int pflag, int printflag) >+ Attrib *dirattrib, int pflag, int fflag, int printflag) > { > char *src_canon; > int ret; >@@ -1325,14 +1367,14 @@ > } > > ret = download_dir_internal(conn, src_canon, dst, >- dirattrib, pflag, printflag, 0); >+ dirattrib, pflag, fflag, 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 fflag) > { > int local_fd; > int status = SSH2_FX_OK; >@@ -1506,6 +1548,9 @@ > if (pflag) > do_fsetstat(conn, handle, handle_len, &a); > >+ if (fflag) >+ (void)do_fsync(conn, handle, handle_len); >+ > if (do_close(conn, handle, handle_len) != SSH2_FX_OK) > status = -1; > xfree(handle); >@@ -1515,7 +1560,7 @@ > > static int > upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, >- int pflag, int printflag, int depth) >+ int pflag, int fflag, int printflag, int depth) > { > int ret = 0, status; > DIR *dirp; >@@ -1584,10 +1629,11 @@ > continue; > > if (upload_dir_internal(conn, new_src, new_dst, >- pflag, printflag, depth + 1) == -1) >+ pflag, fflag, printflag, depth + 1) == -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, >+ fflag) == -1) { > error("Uploading of file %s to %s failed!", > new_src, new_dst); > ret = -1; >@@ -1606,7 +1652,7 @@ > > int > upload_dir(struct sftp_conn *conn, char *src, char *dst, int printflag, >- int pflag) >+ int pflag, int fflag) > { > char *dst_canon; > int ret; >@@ -1616,7 +1662,7 @@ > return -1; > } > >- ret = upload_dir_internal(conn, src, dst_canon, pflag, printflag, 0); >+ ret = upload_dir_internal(conn, src, dst_canon, pflag, fflag, printflag, 0); > xfree(dst_canon); > return ret; > } >Index: sftp-client.h >=================================================================== >RCS file: /cvs/openssh/sftp-client.h,v >retrieving revision 1.20 >diff -u -u -r1.20 sftp-client.h >--- sftp-client.h 4 Dec 2010 22:02:48 -0000 1.20 >+++ sftp-client.h 5 May 2011 19:14:15 -0000 >@@ -106,25 +106,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.110 >diff -u -u -r1.110 sftp-server.c >--- sftp-server.c 4 Dec 2010 22:02:48 -0000 1.110 >+++ sftp-server.c 5 May 2011 19:14:15 -0000 >@@ -538,6 +538,9 @@ > /* hardlink extension */ > buffer_put_cstring(&msg, "hardlink@openssh.com"); > buffer_put_cstring(&msg, "1"); /* version */ >+ /* fsync extension */ >+ buffer_put_cstring(&msg, "fsync@openssh.com"); >+ buffer_put_cstring(&msg, "1"); /* version */ > send_msg(&msg); > buffer_free(&msg); > } >@@ -1247,6 +1250,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; >@@ -1262,6 +1285,8 @@ > process_extended_fstatvfs(id); > else if (strcmp(request, "hardlink@openssh.com") == 0) > process_extended_hardlink(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.85 >diff -u -u -r1.85 sftp.1 >--- sftp.1 4 Dec 2010 22:02:48 -0000 1.85 >+++ sftp.1 5 May 2011 19:14:15 -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 >@@ -155,6 +155,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. >@@ -337,7 +341,7 @@ > Quit > .Nm sftp . > .It Xo Ic get >-.Op Fl Ppr >+.Op Fl fPpr > .Ar remote-path > .Op Ar local-path > .Xc >@@ -357,6 +361,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 >@@ -460,7 +471,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 >@@ -478,6 +489,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.143 >diff -u -u -r1.143 sftp.c >--- sftp.c 4 Dec 2010 22:02:48 -0000 1.143 >+++ sftp.c 5 May 2011 19:14:15 -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_fflag = 0; >+ > /* SIGINT received during command processing */ > volatile sig_atomic_t interrupted = 0; > >@@ -349,7 +352,7 @@ > > static int > parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag, >- int *rflag) >+ int *rflag, int *fflag) > { > extern int opterr, optind, optopt, optreset; > int ch; >@@ -358,7 +361,8 @@ > opterr = 0; > > *rflag = *pflag = 0; >- while ((ch = getopt(argc, argv, "PpRr")) != -1) { >+ *fflag = global_fflag; >+ while ((ch = getopt(argc, argv, "FfPpRr")) != -1) { > switch (ch) { > case 'p': > case 'P': >@@ -368,6 +372,10 @@ > case 'R': > *rflag = 1; > break; >+ case 'f': >+ case 'F': >+ *fflag = 1; >+ break; > default: > error("%s: Invalid flag -%c", cmd, optopt); > return -1; >@@ -517,7 +525,7 @@ > > static int > process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, >- int pflag, int rflag) >+ int pflag, int rflag, int fflag) > { > char *abs_src = NULL; > char *abs_dst = NULL; >@@ -572,11 +580,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, fflag, 1) == -1) > err = -1; > } else { > if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, >- pflag || global_pflag) == -1) >+ pflag || global_pflag, fflag) == -1) > err = -1; > } > xfree(abs_dst); >@@ -591,7 +599,7 @@ > > static int > process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, >- int pflag, int rflag) >+ int pflag, int rflag, int fflag) > { > char *tmp_dst = NULL; > char *abs_dst = NULL; >@@ -657,11 +665,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, fflag, 1) == -1) > err = -1; > } else { > if (do_upload(conn, g.gl_pathv[i], abs_dst, >- pflag || global_pflag) == -1) >+ pflag || global_pflag, fflag) == -1) > err = -1; > } > } >@@ -1113,7 +1121,7 @@ > > static int > parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, >- int *hflag, int *sflag, unsigned long *n_arg, char **path1, char **path2) >+ int *hflag, int *sflag, int *fflag, unsigned long *n_arg, char **path1, char **path2) > { > const char *cmd, *cp = *cpp; > char *cp2, **argv; >@@ -1164,7 +1172,7 @@ > case I_GET: > case I_PUT: > if ((optidx = parse_getput_flags(cmd, argv, argc, >- pflag, rflag)) == -1) >+ pflag, rflag, fflag)) == -1) > return -1; > /* Get first pathname (mandatory) */ > if (argc - optidx < 1) { >@@ -1287,7 +1295,7 @@ > int err_abort) > { > char *path1, *path2, *tmp; >- int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0; >+ int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0, fflag = 0; > int cmdnum, i; > unsigned long n_arg = 0; > Attrib a, *aa; >@@ -1297,7 +1305,7 @@ > > path1 = path2 = NULL; > cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag, >- &sflag, &n_arg, &path1, &path2); >+ &sflag, &fflag, &n_arg, &path1, &path2); > > if (iflag != 0) > err_abort = 0; >@@ -1314,10 +1322,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, fflag); > break; > case I_PUT: >- err = process_put(conn, path1, path2, *pwd, pflag, rflag); >+ err = process_put(conn, path1, path2, *pwd, pflag, >+ rflag, fflag); > break; > case I_RENAME: > path1 = make_absolute(path1, *pwd); >@@ -2066,7 +2076,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] [-l limit]\n" > " [-o ssh_option] [-P port] [-R num_requests] " >@@ -2113,7 +2123,7 @@ > infile = stdin; > > while ((ch = getopt(argc, argv, >- "1246hpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) { >+ "1246fhpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) { > switch (ch) { > /* Passed through to ssh(1) */ > case '4': >@@ -2167,6 +2177,9 @@ > showprogress = 0; > batchmode = 1; > addargs(&args, "-obatchmode yes"); >+ break; >+ case 'f': >+ global_fflag = 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