*** curl-7.16.3-20070601/lib/ssh.c	Tue May 15 04:00:02 2007
--- curl-7.16.3-20070601.new/lib/ssh.c	Tue Jun 12 17:15:34 2007
***************
*** 161,166 ****
--- 161,167 ----
  static const char *sftp_libssh2_strerror(unsigned long err);
  static CURLcode sftp_sendquote(struct connectdata *conn,
                                 struct curl_slist *quote);
+ static CURLcode sftp_create_dirs(struct connectdata *conn);
  
  static LIBSSH2_ALLOC_FUNC(libssh2_malloc);
  static LIBSSH2_REALLOC_FUNC(libssh2_realloc);
***************
*** 711,717 ****
    curl_off_t bytecount = 0;
    char *buf = data->state.buffer;
    unsigned long err = 0;
! 
    *done = TRUE; /* unconditionally */
  
    /* Send any quote commands */
--- 712,718 ----
    curl_off_t bytecount = 0;
    char *buf = data->state.buffer;
    unsigned long err = 0;
!   char *slash_pos = 0;
    *done = TRUE; /* unconditionally */
  
    /* Send any quote commands */
***************
*** 729,743 ****
       *          If this is not done the destination file will be named the
       *          same name as the last directory in the path.
       */
!     sftp->sftp_handle =
        libssh2_sftp_open(sftp->sftp_session, sftp->path,
!                         LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
!                         LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
!                         LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
      if (!sftp->sftp_handle) {
        err = libssh2_sftp_last_error(sftp->sftp_session);
        failf(conn->data, "Could not open remote file for writing: %s",
!             sftp_libssh2_strerror(err));
        return sftp_libssh2_error_to_CURLE(err);
      }
  
--- 730,768 ----
       *          If this is not done the destination file will be named the
       *          same name as the last directory in the path.
       */
! 
!     /* check existence of the remote target directory */
!     slash_pos = strrchr(sftp->path, '/'); /* ignore everything after    */
!     *slash_pos = 0;                       /* and including the last '/' */
!     sftp->sftp_handle = libssh2_sftp_opendir(sftp->sftp_session, sftp->path);
!     *slash_pos = '/'; /* repair */
!     if (!sftp->sftp_handle) {
!       err = libssh2_sftp_last_error(sftp->sftp_session);
!       res = -1;
!       if ( (err == LIBSSH2_FX_NO_SUCH_FILE || err == LIBSSH2_FX_FAILURE
!             || err == LIBSSH2_FX_NO_SUCH_PATH
!             || err == LIBSSH2_FX_NOT_A_DIRECTORY)
!           && conn->data->set.ftp_create_missing_dirs && strlen(sftp->path) > 1) {
!         /* try to create the path remotely */
!         res = sftp_create_dirs(conn);
!       }
!       if (res != CURLE_OK) { /* creation failed - bail out */
!         err = libssh2_sftp_last_error(sftp->sftp_session);
!         failf(conn->data, "Could not create remote target directory: %s (%u)",
!             sftp_libssh2_strerror(err), err);
!         return sftp_libssh2_error_to_CURLE(err);
!       }
!     }
!     /* try to open a handle and upload the file */
!     sftp->sftp_handle = 
        libssh2_sftp_open(sftp->sftp_session, sftp->path,
!           LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
!           LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
!           LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
      if (!sftp->sftp_handle) {
        err = libssh2_sftp_last_error(sftp->sftp_session);
        failf(conn->data, "Could not open remote file for writing: %s",
!           sftp_libssh2_strerror(err));
        return sftp_libssh2_error_to_CURLE(err);
      }
  
***************
*** 1392,1395 ****
--- 1417,1458 ----
    return nread;
  }
  
+ /*
+  * Create the path sftp->path on the remote site
+  * returns CURL_OK on success, -1 on failure
+  */
+ static CURLcode sftp_create_dirs(struct connectdata *conn) {
+   CURLcode res = -1;
+   unsigned long err = 0;
+   struct SSHPROTO *sftp = conn->data->reqdata.proto.ssh;
+   char *slash_pos = 0;
+ 
+   if (strlen(sftp->path) > 1) {
+     slash_pos = sftp->path + 1; /* ignore the leading '/' */
+     while((slash_pos = strchr(slash_pos, '/')) != 0) {
+       *slash_pos = 0;
+       infof(conn->data, "Creating directory '%s'\n", sftp->path);
+       /* 'mode' - parameter is preliminary - I'm not sure how to treat it */
+       res = libssh2_sftp_mkdir(sftp->sftp_session, sftp->path, 
+           LIBSSH2_SFTP_S_IRWXU | LIBSSH2_SFTP_S_IRWXG);
+       *slash_pos = '/';
+       ++slash_pos;
+       if (res == -1) { 
+         /* abort if failure wasn't that the dir already exists or the
+          * permission was denied (creation might succeed further 
+          * down the path) - retry on unspecific FAILURE also
+          */
+         err = libssh2_sftp_last_error(sftp->sftp_session);
+         failf(conn->data, "Could not create remote target directory: %s (%u)",
+             sftp_libssh2_strerror(err), err);
+         if (err != LIBSSH2_FX_FILE_ALREADY_EXISTS 
+             && err != LIBSSH2_FX_FAILURE 
+             && err != LIBSSH2_FX_PERMISSION_DENIED) {
+           break;
+         }
+       }
+     }
+   }
+   return res;
+ }
  #endif /* USE_LIBSSH2 */

