Bugzilla – Attachment 3495 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 client copy-data extension v2
0002-sftp-client-add-a-cp-helper-to-copy-files.patch (text/plain), 8.23 KB, created by
Mike Frysinger
on 2021-04-05 00:58:28 AEST
(
hide
)
Description:
sftp client copy-data extension v2
Filename:
MIME Type:
Creator:
Mike Frysinger
Created:
2021-04-05 00:58:28 AEST
Size:
8.23 KB
patch
obsolete
>From 13cd78c82b5a9a4086ce6b8ddba501c76c3226ca Mon Sep 17 00:00:00 2001 >From: Mike Frysinger <vapier@gentoo.org> >Date: Wed, 24 Oct 2018 23:22:52 -0400 >Subject: [PATCH 2/2] sftp-client: add a "cp" helper to copy files > >Use the new copy-data extension for efficient remote file copies. >At the very least, this provides a quick method for testing. >--- > sftp-client.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++ > sftp-client.h | 3 ++ > sftp.1 | 14 +++++- > sftp.c | 14 ++++++ > 4 files changed, 150 insertions(+), 1 deletion(-) > >diff --git a/sftp-client.c b/sftp-client.c >index cadaee6bdaa2..70af70aa4a22 100644 >--- a/sftp-client.c >+++ b/sftp-client.c >@@ -95,6 +95,7 @@ struct sftp_conn { > #define SFTP_EXT_FSYNC 0x00000010 > #define SFTP_EXT_LSETSTAT 0x00000020 > #define SFTP_EXT_LIMITS 0x00000040 >+#define SFTP_EXT_COPY_DATA 0x00000080 > u_int exts; > u_int64_t limit_kbps; > struct bwlimit bwlimit_in, bwlimit_out; >@@ -483,6 +484,10 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, > strcmp((char *)value, "1") == 0) { > ret->exts |= SFTP_EXT_LIMITS; > known = 1; >+ } else if (strcmp(name, "copy-data") == 0 && >+ strcmp((char *)value, "1") == 0) { >+ ret->exts |= SFTP_EXT_COPY_DATA; >+ known = 1; > } > if (known) { > debug2("Server supports extension \"%s\" revision %s", >@@ -971,6 +976,121 @@ do_realpath(struct sftp_conn *conn, const char *path) > return(filename); > } > >+int >+do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) >+{ >+ Attrib junk, *a; >+ struct sshbuf *msg; >+ u_char *old_handle, *new_handle; >+ u_int mode, status, id; >+ size_t old_handle_len, new_handle_len; >+ int r; >+ >+ /* Return if the extension is not supported */ >+ if ((conn->exts & SFTP_EXT_COPY_DATA) == 0) { >+ error("Server does not support copy-data extension"); >+ return -1; >+ } >+ >+ /* Make sure the file exists, and we can copy its perms */ >+ if ((a = do_stat(conn, oldpath, 0)) == NULL) >+ return -1; >+ >+ /* Do not preserve set[ug]id here, as we do not preserve ownership */ >+ if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { >+ mode = a->perm & 0777; >+ >+ if (!S_ISREG(a->perm)) { >+ error("Cannot copy non-regular file: %s", oldpath); >+ return -1; >+ } >+ } else { >+ /* NB: The user's umask will apply to this */ >+ mode = 0666; >+ } >+ >+ /* Set up the new perms for the new file */ >+ attrib_clear(a); >+ a->perm = mode; >+ a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; >+ >+ if ((msg = sshbuf_new()) == NULL) >+ fatal("%s: sshbuf_new failed", __func__); >+ >+ attrib_clear(&junk); /* Send empty attributes */ >+ >+ /* Open the old file for reading */ >+ id = conn->msg_id++; >+ if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || >+ (r = sshbuf_put_u32(msg, id)) != 0 || >+ (r = sshbuf_put_cstring(msg, oldpath)) != 0 || >+ (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 || >+ (r = encode_attrib(msg, &junk)) != 0) >+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); >+ send_msg(conn, msg); >+ debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, oldpath); >+ >+ sshbuf_reset(msg); >+ >+ old_handle = get_handle(conn, id, &old_handle_len, >+ "remote open(\"%s\")", oldpath); >+ if (old_handle == NULL) { >+ sshbuf_free(msg); >+ return -1; >+ } >+ >+ /* Open the new file for writing */ >+ id = conn->msg_id++; >+ if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || >+ (r = sshbuf_put_u32(msg, id)) != 0 || >+ (r = sshbuf_put_cstring(msg, newpath)) != 0 || >+ (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| >+ SSH2_FXF_TRUNC)) != 0 || >+ (r = encode_attrib(msg, a)) != 0) >+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); >+ send_msg(conn, msg); >+ debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, newpath); >+ >+ sshbuf_reset(msg); >+ >+ new_handle = get_handle(conn, id, &new_handle_len, >+ "remote open(\"%s\")", newpath); >+ if (new_handle == NULL) { >+ sshbuf_free(msg); >+ free(old_handle); >+ return -1; >+ } >+ >+ /* Copy the file data */ >+ id = conn->msg_id++; >+ if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || >+ (r = sshbuf_put_u32(msg, id)) != 0 || >+ (r = sshbuf_put_cstring(msg, "copy-data")) != 0 || >+ (r = sshbuf_put_string(msg, old_handle, old_handle_len)) != 0 || >+ (r = sshbuf_put_u64(msg, 0)) != 0 || >+ (r = sshbuf_put_u64(msg, 0)) != 0 || >+ (r = sshbuf_put_string(msg, new_handle, new_handle_len)) != 0 || >+ (r = sshbuf_put_u64(msg, 0)) != 0) >+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); >+ send_msg(conn, msg); >+ debug3("Sent message copy-data \"%s\" 0 0 -> \"%s\" 0", >+ oldpath, newpath); >+ >+ status = get_status(conn, id); >+ if (status != SSH2_FX_OK) >+ error("Couldn't copy file \"%s\" to \"%s\": %s", oldpath, >+ newpath, fx2txt(status)); >+ >+ /* Clean up everything */ >+ sshbuf_free(msg); >+ do_close(conn, old_handle, old_handle_len); >+ do_close(conn, new_handle, new_handle_len); >+ free(old_handle); >+ free(new_handle); >+ >+ return status == SSH2_FX_OK ? 0 : -1; >+} >+ > int > do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, > int force_legacy) >diff --git a/sftp-client.h b/sftp-client.h >index 6f6c49fb2099..06a6fc9f4c02 100644 >--- a/sftp-client.h >+++ b/sftp-client.h >@@ -114,6 +114,9 @@ int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int); > /* Rename 'oldpath' to 'newpath' */ > int do_rename(struct sftp_conn *, const char *, const char *, int force_legacy); > >+/* Copy 'oldpath' to 'newpath' */ >+int do_copy(struct sftp_conn *, const char *, const char *); >+ > /* Link 'oldpath' to 'newpath' */ > int do_hardlink(struct sftp_conn *, const char *, const char *); > >diff --git a/sftp.1 b/sftp.1 >index a1a6373029a4..9f1b87e41970 100644 >--- a/sftp.1 >+++ b/sftp.1 >@@ -144,7 +144,7 @@ will abort if any of the following > commands fail: > .Ic get , put , reget , reput , rename , ln , > .Ic rm , mkdir , chdir , ls , >-.Ic lchdir , chmod , chown , >+.Ic lchdir , copy , cp , chmod , chown , > .Ic chgrp , lpwd , df , symlink , > and > .Ic lmkdir . >@@ -401,6 +401,18 @@ If the > flag is specified, then symlinks will not be followed. > Note that this is only supported by servers that implement > the "lsetstat@openssh.com" extension. >+.It Ic copy Ar oldpath Ar newpath >+Copy remote file from >+.Ar oldpath >+to >+.Ar newpath . >+.Pp >+Note that this is only supported by servers that implement the "copy-data" >+extension. >+.It Ic cp Ar oldpath Ar newpath >+Alias to >+.Ic copy >+command. > .It Xo Ic df > .Op Fl hi > .Op Ar path >diff --git a/sftp.c b/sftp.c >index 3f46c55316aa..29ce24068abb 100644 >--- a/sftp.c >+++ b/sftp.c >@@ -138,6 +138,7 @@ enum sftp_command { > I_CHGRP, > I_CHMOD, > I_CHOWN, >+ I_COPY, > I_DF, > I_GET, > I_HELP, >@@ -181,6 +182,8 @@ static const struct CMD cmds[] = { > { "chgrp", I_CHGRP, REMOTE }, > { "chmod", I_CHMOD, REMOTE }, > { "chown", I_CHOWN, REMOTE }, >+ { "copy", I_COPY, REMOTE }, >+ { "cp", I_COPY, REMOTE }, > { "df", I_DF, REMOTE }, > { "dir", I_LS, REMOTE }, > { "exit", I_QUIT, NOARGS }, >@@ -280,6 +283,8 @@ help(void) > "chgrp [-h] grp path Change group of file 'path' to 'grp'\n" > "chmod [-h] mode path Change permissions of file 'path' to 'mode'\n" > "chown [-h] own path Change owner of file 'path' to 'own'\n" >+ "copy oldpath newpath Copy remote file\n" >+ "cp oldpath newpath Copy remote file\n" > "df [-hi] [path] Display statistics for current directory or\n" > " filesystem containing 'path'\n" > "exit Quit sftp\n" >@@ -1361,6 +1366,10 @@ parse_args(const char **cpp, int *ignore_errors, int *disable_echo, int *aflag, > if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) > return -1; > goto parse_two_paths; >+ case I_COPY: >+ if ((optidx = parse_no_flags(cmd, argv, argc)) == -1) >+ return -1; >+ goto parse_two_paths; > case I_RENAME: > if ((optidx = parse_rename_flags(cmd, argv, argc, lflag)) == -1) > return -1; >@@ -1528,6 +1537,11 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, > err = process_put(conn, path1, path2, *pwd, pflag, > rflag, aflag, fflag); > break; >+ case I_COPY: >+ path1 = make_absolute(path1, *pwd); >+ path2 = make_absolute(path2, *pwd); >+ err = do_copy(conn, path1, path2); >+ break; > case I_RENAME: > path1 = make_absolute(path1, *pwd); > path2 = make_absolute(path2, *pwd); >-- >2.30.2 >
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