summaryrefslogtreecommitdiff
path: root/openssh-8.7p1-recursive-scp.patch
diff options
context:
space:
mode:
Diffstat (limited to 'openssh-8.7p1-recursive-scp.patch')
-rw-r--r--openssh-8.7p1-recursive-scp.patch181
1 files changed, 181 insertions, 0 deletions
diff --git a/openssh-8.7p1-recursive-scp.patch b/openssh-8.7p1-recursive-scp.patch
new file mode 100644
index 0000000..f0d9b0f
--- /dev/null
+++ b/openssh-8.7p1-recursive-scp.patch
@@ -0,0 +1,181 @@
+diff -up openssh-8.7p1/scp.c.scp-sftpdirs openssh-8.7p1/scp.c
+--- openssh-8.7p1/scp.c.scp-sftpdirs 2022-02-07 12:31:07.407740407 +0100
++++ openssh-8.7p1/scp.c 2022-02-07 12:31:07.409740424 +0100
+@@ -1324,7 +1324,7 @@ source_sftp(int argc, char *src, char *t
+
+ if (src_is_dir && iamrecursive) {
+ if (upload_dir(conn, src, abs_dst, pflag,
+- SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) {
++ SFTP_PROGRESS_ONLY, 0, 0, 1, 1, 1) != 0) {
+ error("failed to upload directory %s to %s", src, targ);
+ errs = 1;
+ }
+diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c
+--- openssh-8.7p1/sftp-client.c.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200
++++ openssh-8.7p1/sftp-client.c 2022-02-07 12:47:59.117516131 +0100
+@@ -971,7 +971,7 @@ do_fsetstat(struct sftp_conn *conn, cons
+
+ /* Implements both the realpath and expand-path operations */
+ static char *
+-do_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
++do_realpath_expand(struct sftp_conn *conn, const char *path, int expand, int create_dir)
+ {
+ struct sshbuf *msg;
+ u_int expected_id, count, id;
+@@ -1033,11 +1033,43 @@ do_realpath_expand(struct sftp_conn *con
+ if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
+ (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
+ fatal_fr(r, "parse status");
+- error("%s %s: %s", expand ? "expand" : "realpath",
+- path, *errmsg == '\0' ? fx2txt(status) : errmsg);
+- free(errmsg);
+- sshbuf_free(msg);
+- return NULL;
++ if ((status == SSH2_FX_NO_SUCH_FILE) && create_dir) {
++ memset(&a, '\0', sizeof(a));
++ if ((r = do_mkdir(conn, path, &a, 0)) != 0) {
++ sshbuf_free(msg);
++ return NULL;
++ }
++ debug2("Sending SSH2_FXP_REALPATH \"%s\" - create dir", path);
++ send_string_request(conn, id, SSH2_FXP_REALPATH,
++ path, strlen(path));
++
++ get_msg(conn, msg);
++ if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
++ (r = sshbuf_get_u32(msg, &id)) != 0)
++ fatal_fr(r, "parse");
++
++ if (id != expected_id)
++ fatal("ID mismatch (%u != %u)", id, expected_id);
++
++ if (type == SSH2_FXP_STATUS) {
++ free(errmsg);
++
++ if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
++ (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
++ fatal_fr(r, "parse status");
++ error("%s %s: %s", expand ? "expand" : "realpath",
++ path, *errmsg == '\0' ? fx2txt(status) : errmsg);
++ free(errmsg);
++ sshbuf_free(msg);
++ return NULL;
++ }
++ } else {
++ error("%s %s: %s", expand ? "expand" : "realpath",
++ path, *errmsg == '\0' ? fx2txt(status) : errmsg);
++ free(errmsg);
++ sshbuf_free(msg);
++ return NULL;
++ }
+ } else if (type != SSH2_FXP_NAME)
+ fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
+ SSH2_FXP_NAME, type);
+@@ -1039,9 +1067,9 @@ do_realpath_expand(struct sftp_conn *con
+ }
+
+ char *
+-do_realpath(struct sftp_conn *conn, const char *path)
++do_realpath(struct sftp_conn *conn, const char *path, int create_dir)
+ {
+- return do_realpath_expand(conn, path, 0);
++ return do_realpath_expand(conn, path, 0, create_dir);
+ }
+
+ int
+@@ -1055,9 +1083,9 @@ do_expand_path(struct sftp_conn *conn, c
+ {
+ if (!can_expand_path(conn)) {
+ debug3_f("no server support, fallback to realpath");
+- return do_realpath_expand(conn, path, 0);
++ return do_realpath_expand(conn, path, 0, 0);
+ }
+- return do_realpath_expand(conn, path, 1);
++ return do_realpath_expand(conn, path, 1, 0);
+ }
+
+ int
+@@ -1807,7 +1835,7 @@ download_dir(struct sftp_conn *conn, con
+ char *src_canon;
+ int ret;
+
+- if ((src_canon = do_realpath(conn, src)) == NULL) {
++ if ((src_canon = do_realpath(conn, src, 0)) == NULL) {
+ error("download \"%s\": path canonicalization failed", src);
+ return -1;
+ }
+@@ -2115,12 +2143,12 @@ upload_dir_internal(struct sftp_conn *co
+ int
+ upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
+ int preserve_flag, int print_flag, int resume, int fsync_flag,
+- int follow_link_flag, int inplace_flag)
++ int follow_link_flag, int inplace_flag, int create_dir)
+ {
+ char *dst_canon;
+ int ret;
+
+- if ((dst_canon = do_realpath(conn, dst)) == NULL) {
++ if ((dst_canon = do_realpath(conn, dst, create_dir)) == NULL) {
+ error("upload \"%s\": path canonicalization failed", dst);
+ return -1;
+ }
+@@ -2557,7 +2585,7 @@ crossload_dir(struct sftp_conn *from, st
+ char *from_path_canon;
+ int ret;
+
+- if ((from_path_canon = do_realpath(from, from_path)) == NULL) {
++ if ((from_path_canon = do_realpath(from, from_path, 0)) == NULL) {
+ error("crossload \"%s\": path canonicalization failed",
+ from_path);
+ return -1;
+diff -up openssh-8.7p1/sftp-client.h.scp-sftpdirs openssh-8.7p1/sftp-client.h
+--- openssh-8.7p1/sftp-client.h.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200
++++ openssh-8.7p1/sftp-client.h 2022-02-07 12:31:07.410740433 +0100
+@@ -111,7 +111,7 @@ int do_fsetstat(struct sftp_conn *, cons
+ int do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a);
+
+ /* Canonicalise 'path' - caller must free result */
+-char *do_realpath(struct sftp_conn *, const char *);
++char *do_realpath(struct sftp_conn *, const char *, int);
+
+ /* Canonicalisation with tilde expansion (requires server extension) */
+ char *do_expand_path(struct sftp_conn *, const char *);
+@@ -159,7 +159,7 @@ int do_upload(struct sftp_conn *, const
+ * times if 'pflag' is set
+ */
+ int upload_dir(struct sftp_conn *, const char *, const char *,
+- int, int, int, int, int, int);
++ int, int, int, int, int, int, int);
+
+ /*
+ * Download a 'from_path' from the 'from' connection and upload it to
+diff -up openssh-8.7p1/sftp.c.scp-sftpdirs openssh-8.7p1/sftp.c
+--- openssh-8.7p1/sftp.c.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200
++++ openssh-8.7p1/sftp.c 2022-02-07 12:31:07.411740442 +0100
+@@ -760,7 +760,7 @@ process_put(struct sftp_conn *conn, cons
+ if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
+ if (upload_dir(conn, g.gl_pathv[i], abs_dst,
+ pflag || global_pflag, 1, resume,
+- fflag || global_fflag, 0, 0) == -1)
++ fflag || global_fflag, 0, 0, 0) == -1)
+ err = -1;
+ } else {
+ if (do_upload(conn, g.gl_pathv[i], abs_dst,
+@@ -1577,7 +1577,7 @@ parse_dispatch_command(struct sftp_conn
+ if (path1 == NULL || *path1 == '\0')
+ path1 = xstrdup(startdir);
+ path1 = make_absolute(path1, *pwd);
+- if ((tmp = do_realpath(conn, path1)) == NULL) {
++ if ((tmp = do_realpath(conn, path1, 0)) == NULL) {
+ err = 1;
+ break;
+ }
+@@ -2160,7 +2160,7 @@ interactive_loop(struct sftp_conn *conn,
+ }
+ #endif /* USE_LIBEDIT */
+
+- remote_path = do_realpath(conn, ".");
++ remote_path = do_realpath(conn, ".", 0);
+ if (remote_path == NULL)
+ fatal("Need cwd");
+ startdir = xstrdup(remote_path);