Michael Grauvogl
2017-Jan-29 13:00 UTC
[PATCH] Bug 2150: Recursive upload expects target directory to already exist
Hi, below is a patch for bug 2150 (Recursive upload expects target directory to already exist, https://bugzilla.mindrot.org/show_bug.cgi?id=2150). The problem is that function upload_dir calls do_realpath which will fail if the destination directory does not already exist and therefore upload_dir_internal never gets called. I used some code from upload_dir_internal to create the destination directory if it does not already exist. Cheers, Michael diff --git a/sftp-client.c b/sftp-client.c index d47be0e..f02ecd7 100644 --- a/sftp-client.c +++ b/sftp-client.c @@ -1869,6 +1869,33 @@ upload_dir(struct sftp_conn *conn, const char *src, const char *dst, { char *dst_canon; int ret; + struct stat sb; + Attrib a, *dirattrib; + + /* check if dst exists */ + if (stat(src, &sb) == -1) { + error("Couldn't stat directory \"%s\": %s", + src, strerror(errno)); + return -1; + } + + attrib_clear(&a); + stat_to_attrib(&sb, &a); + a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; + a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; + a.perm &= 01777; + if (!preserve_flag) + a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; + + /* + * sftp lacks a portable status value to match errno EEXIST, + * so if we get a failure back then we must check whether + * the path already existed and is a directory. + */ + if (do_mkdir(conn, dst, &a, 0) != 0) { + if ((dirattrib = do_stat(conn, dst, 0)) == NULL) + return -1; + } if ((dst_canon = do_realpath(conn, dst)) == NULL) { error("Unable to canonicalize path \"%s\"", dst);