Bugzilla – Attachment 3344 Details for
Bug 2948
implement "copy-data" sftp extension
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
sftp server copy-data extension
sftp-copy-data.patch (text/plain), 5.93 KB, created by
Darren Tucker
on 2019-12-23 09:49:50 AEDT
(
hide
)
Description:
sftp server copy-data extension
Filename:
MIME Type:
Creator:
Darren Tucker
Created:
2019-12-23 09:49:50 AEDT
Size:
5.93 KB
patch
obsolete
> PROTOCOL | 39 ++++++++++++++++++++++- > sftp-server.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 125 insertions(+), 1 deletion(-) > >diff --git a/PROTOCOL b/PROTOCOL >index f75c1c0ae5b0..04a392db33be 100644 >--- a/PROTOCOL >+++ b/PROTOCOL >@@ -459,12 +459,49 @@ This request asks the server to call fsync(2) on an open file handle. > string "fsync@openssh.com" > string handle > >-One receiving this request, a server will call fsync(handle_fd) and will >+On receiving this request, a server will call fsync(handle_fd) and will > respond with a SSH_FXP_STATUS message. > > This extension is advertised in the SSH_FXP_VERSION hello with version > "1". > >+3.7. sftp: Extension request "copy-data" >+ >+This request asks the server to copy data from one open file handle and >+write it to a different open file handle. This avoids needing to >+download the data before uploading it across the network twice. >+ >+ byte SSH_FXP_EXTENDED >+ uint32 id >+ string "copy-data" >+ string read-from-handle >+ uint64 read-from-offset >+ uint64 read-data-length >+ string write-to-handle >+ uint64 write-to-offset >+ >+The server will copy read-data-length bytes starting from >+read-from-offset from the read-from-handle and write them to >+write-to-handle starting from write-to-offset, and then respond with a >+SSH_FXP_STATUS message. >+ >+It's equivalent to issuing a series of SSH_FXP_READ requests on >+read-from-handle and a series of requests of SSH_FXP_WRITE on >+write-to-handle. >+ >+If read-from-handle and write-to-handle are the same, the server will >+fail the request and respond with a SSH_FX_INVALID_PARAMETER message. >+ >+If read-data-length is 0, then the server will read data from the >+read-from-handle until EOF is reached. >+ >+This extension is advertised in the SSH_FXP_VERSION hello with version >+"1". >+ >+This request is identical to the "copy-data" request documented in: >+ >+https://tools.ietf.org/html/draft-ietf-secsh-filexfer-extensions-00#section-7 >+ > 4. Miscellaneous changes > > 4.1 Public key format >diff --git a/sftp-server.c b/sftp-server.c >index beac78ed0324..2d7c1c87e83f 100644 >--- a/sftp-server.c >+++ b/sftp-server.c >@@ -107,6 +107,7 @@ static void process_extended_statvfs(u_int32_t id); > static void process_extended_fstatvfs(u_int32_t id); > static void process_extended_hardlink(u_int32_t id); > static void process_extended_fsync(u_int32_t id); >+static void process_extended_copy_data(u_int32_t id); > static void process_extended(u_int32_t id); > > struct sftp_handler { >@@ -148,6 +149,7 @@ static const struct sftp_handler extended_handlers[] = { > { "fstatvfs", "fstatvfs@openssh.com", 0, process_extended_fstatvfs, 0 }, > { "hardlink", "hardlink@openssh.com", 0, process_extended_hardlink, 1 }, > { "fsync", "fsync@openssh.com", 0, process_extended_fsync, 1 }, >+ { "copy-data", "copy-data", 0, process_extended_copy_data, 1 }, > { NULL, NULL, 0, NULL, 0 } > }; > >@@ -666,6 +668,9 @@ process_init(void) > (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ > /* fsync extension */ > (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || >+ (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ >+ /* copy-data extension */ >+ (r = sshbuf_put_cstring(msg, "copy-data")) != 0 || > (r = sshbuf_put_cstring(msg, "1")) != 0) /* version */ > fatal("%s: buffer error: %s", __func__, ssh_err(r)); > send_msg(msg); >@@ -1369,6 +1374,88 @@ process_extended_fsync(u_int32_t id) > send_status(id, status); > } > >+static void >+process_extended_copy_data(u_int32_t id) >+{ >+ u_char buf[64*1024]; >+ int read_handle, read_fd, write_handle, write_fd; >+ u_int64_t len, read_off, read_len, write_off; >+ int r, ret, copy_until_eof, status = SSH2_FX_OP_UNSUPPORTED; >+ >+ if ((r = get_handle(iqueue, &read_handle)) != 0 || >+ (r = sshbuf_get_u64(iqueue, &read_off)) != 0 || >+ (r = sshbuf_get_u64(iqueue, &read_len)) != 0 || >+ (r = get_handle(iqueue, &write_handle)) != 0 || >+ (r = sshbuf_get_u64(iqueue, &write_off)) != 0) >+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); >+ >+ debug("request %u: copy-data from \"%s\" (handle %d) off %llu len %llu " >+ "to \"%s\" (handle %d) off %llu", >+ id, handle_to_name(read_handle), read_handle, >+ (unsigned long long)read_off, (unsigned long long)read_len, >+ handle_to_name(write_handle), write_handle, >+ (unsigned long long)write_off); >+ >+ /* For read length of 0, we read until EOF. */ >+ if (read_len == 0) { >+ read_len = (u_int64_t)-1 - read_off; >+ copy_until_eof = 1; >+ } else >+ copy_until_eof = 0; >+ >+ read_fd = handle_to_fd(read_handle); >+ write_fd = handle_to_fd(write_handle); >+ >+ /* Disallow reading & writing to the same handle */ >+ if (read_handle == write_handle || read_fd < 0 || write_fd < 0) { >+ status = SSH2_FX_FAILURE; >+ } else { >+ if (lseek(read_fd, read_off, SEEK_SET) < 0) { >+ status = errno_to_portable(errno); >+ error("process_extended_copy_data: read_seek failed"); >+ } else if (!(handle_to_flags(write_handle) & O_APPEND) && >+ lseek(write_fd, write_off, SEEK_SET) < 0) { >+ status = errno_to_portable(errno); >+ error("process_extended_copy_data: write_seek failed"); >+ } else { >+ /* Process the request in chunks. */ >+ while (read_len || copy_until_eof) { >+ len = MINIMUM(sizeof(buf), read_len); >+ read_len -= len; >+ >+ ret = read(read_fd, buf, len); >+ if (ret < 0) { >+ status = errno_to_portable(errno); >+ break; >+ } else if (ret == 0) { >+ status = copy_until_eof ? SSH2_FX_OK : SSH2_FX_EOF; >+ break; >+ } >+ len = ret; >+ handle_update_read(read_handle, len); >+ >+ ret = write(write_fd, buf, len); >+ if (ret < 0) { >+ status = errno_to_portable(errno); >+ error("process_extended_copy_data: write failed"); >+ break; >+ } >+ handle_update_write(write_handle, len); >+ if ((size_t)ret != len) { >+ debug2("nothing at all written"); >+ status = SSH2_FX_FAILURE; >+ break; >+ } >+ } >+ >+ if (read_len == 0) >+ status = SSH2_FX_OK; >+ } >+ } >+ >+ send_status(id, status); >+} >+ > static void > process_extended(u_int32_t id) > {
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 2948
:
3344
|
3345
|
3494
|
3495