SFTP client now successfully handles cd, ls, get and put.
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 24 Feb 2001 12:02:35 +0000 (12:02 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 24 Feb 2001 12:02:35 +0000 (12:02 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@939 cda61777-01e9-0310-a592-d414129be87e

psftp.c
sftp.c
sftp.h

diff --git a/psftp.c b/psftp.c
index 4445b8b..50be458 100644 (file)
--- a/psftp.c
+++ b/psftp.c
@@ -4,8 +4,8 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <assert.h>
-#include <unistd.h>
 
 #include "sftp.h"
 #include "int64.h"
@@ -25,6 +25,39 @@ char *dupstr(char *s) {
     return p;
 }
 
+/* Allocate the concatenation of N strings. Terminate arg list with NULL. */
+char *dupcat(char *s1, ...) {
+    int len;
+    char *p, *q, *sn;
+    va_list ap;
+
+    len = strlen(s1);
+    va_start(ap, s1);
+    while (1) {
+       sn = va_arg(ap, char *);
+       if (!sn)
+           break;
+       len += strlen(sn);
+    }
+    va_end(ap);
+
+    p = smalloc(len+1);
+    strcpy(p, s1);
+    q = p + strlen(p);
+
+    va_start(ap, s1);
+    while (1) {
+       sn = va_arg(ap, char *);
+       if (!sn)
+           break;
+       strcpy(q, sn);
+       q += strlen(q);
+    }
+    va_end(ap);
+
+    return p;
+}
+
 /* ----------------------------------------------------------------------
  * sftp client state.
  */
@@ -36,13 +69,23 @@ char *pwd, *homedir;
  */
 
 /*
- * Canonify a pathname starting from the pwd.
+ * Attempt to canonify a pathname starting from the pwd. If
+ * canonification fails, at least fall back to returning a _valid_
+ * pathname (though it may be ugly, eg /home/simon/../foobar).
  */
 char *canonify(char *name) {
-    if (name[0] == '/')
-       return fxp_realpath(name, NULL);
-    else
-       return fxp_realpath(pwd, name);
+    char *fullname, *canonname;
+    if (name[0] == '/') {
+       fullname = dupstr(name);
+    } else {
+       fullname = dupcat(pwd, "/", name, NULL);
+    }
+    canonname = fxp_realpath(name);
+    if (canonname) {
+       sfree(fullname);
+       return canonname;
+    } else
+       return fullname;
 }
 
 /* ----------------------------------------------------------------------
@@ -158,7 +201,7 @@ int sftp_cmd_cd(struct sftp_command *cmd) {
     char *dir;
 
     if (cmd->nwords < 2)
-       dir = fxp_realpath(".", NULL);
+       dir = dupstr(homedir);
     else
        dir = canonify(cmd->words[1]);
 
@@ -278,7 +321,7 @@ int sftp_cmd_put(struct sftp_command *cmd) {
     fname = cmd->words[1];
     origoutfname = (cmd->nwords == 2 ? cmd->words[1] : cmd->words[2]);
     outfname = canonify(origoutfname);
-~|~    if (!outfname) {
+    if (!outfname) {
        printf("%s: %s\n", origoutfname, fxp_error());
        return 0;
     }
@@ -309,14 +352,14 @@ int sftp_cmd_put(struct sftp_command *cmd) {
        char buffer[4096];
        int len;
 
-       len = fread(buffer, 1, len, fp);
+       len = fread(buffer, 1, sizeof(buffer), fp);
        if (len == -1) {
            printf("error while reading local file\n");
            break;
        } else if (len == 0) {
            break;
        }
-       if (!fxp_write(fh, buffer, offset, sizeof(buffer))) {
+       if (!fxp_write(fh, buffer, offset, len)) {
            printf("error while writing: %s\n", fxp_error());
            break;
        }
@@ -474,7 +517,7 @@ void do_sftp(void) {
     /*
      * Find out where our home directory is.
      */
-    homedir = fxp_realpath(".", NULL);
+    homedir = fxp_realpath(".");
     if (!homedir) {
        fprintf(stderr,
                "Warning: failed to resolve home directory: %s\n",
diff --git a/sftp.c b/sftp.c
index 6b519b6..51384be 100644 (file)
--- a/sftp.c
+++ b/sftp.c
@@ -185,6 +185,8 @@ int io_init(void) {
        close(0); dup2(to[0], 0); close(to[1]);
        close(1); dup2(from[1], 1); close(from[0]);
        execl("/home/simon/src/openssh/openssh_cvs/prefix/bin/ssh", "ssh", "-2", "simon@localhost", "-s", "sftp", NULL);
+       //execl("/root/ssh-research/ssh-2.4.0/apps/ssh/sftp-server2", "sftp-server2", NULL);
+       //execl("/usr/lib/sftp-server", "sftp-server", NULL);
        assert(0);                     /* bomb out if not */
     } else {
        /* We are parent. Close wrong end of each pipe, assign to glob vars. */
@@ -343,10 +345,9 @@ int fxp_init(void) {
 }
 
 /*
- * Canonify a pathname. Concatenate the two given path elements
- * with a separating slash, unless the second is NULL.
+ * Canonify a pathname.
  */
-char *fxp_realpath(char *path, char *path2) {
+char *fxp_realpath(char *path) {
     struct sftp_packet *pktin, *pktout;
     int id;
 
@@ -354,10 +355,6 @@ char *fxp_realpath(char *path, char *path2) {
     sftp_pkt_adduint32(pktout, 0x123); /* request id */
     sftp_pkt_addstring_start(pktout);
     sftp_pkt_addstring_str(pktout, path);
-    if (path2) {
-       sftp_pkt_addstring_str(pktout, "/");
-       sftp_pkt_addstring_str(pktout, path2);
-    }
     sftp_send(pktout);
     pktin = sftp_recv();
     id = sftp_pkt_getuint32(pktin);
@@ -421,6 +418,7 @@ struct fxp_handle *fxp_open(char *path, int type) {
        }
        handle = smalloc(sizeof(struct fxp_handle));
        handle->hstring = mkstr(hstring, len);
+       handle->hlen = len;
        sftp_pkt_free(pktin);
        return handle;
     } else {
@@ -459,6 +457,7 @@ struct fxp_handle *fxp_opendir(char *path) {
        }
        handle = smalloc(sizeof(struct fxp_handle));
        handle->hstring = mkstr(hstring, len);
+       handle->hlen = len;
        sftp_pkt_free(pktin);
        return handle;
     } else {
@@ -476,7 +475,8 @@ void fxp_close(struct fxp_handle *handle) {
 
     pktout = sftp_pkt_init(SSH_FXP_CLOSE);
     sftp_pkt_adduint32(pktout, 0x789); /* request id */
-    sftp_pkt_addstring(pktout, handle->hstring);
+    sftp_pkt_addstring_start(pktout);
+    sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
     sftp_send(pktout);
     pktin = sftp_recv();
     id = sftp_pkt_getuint32(pktin);
@@ -501,7 +501,8 @@ int fxp_read(struct fxp_handle *handle, char *buffer, uint64 offset, int len) {
 
     pktout = sftp_pkt_init(SSH_FXP_READ);
     sftp_pkt_adduint32(pktout, 0xBCD); /* request id */
-    sftp_pkt_addstring(pktout, handle->hstring);
+    sftp_pkt_addstring_start(pktout);
+    sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
     sftp_pkt_adduint64(pktout, offset);
     sftp_pkt_adduint32(pktout, len);
     sftp_send(pktout);
@@ -540,7 +541,8 @@ struct fxp_names *fxp_readdir(struct fxp_handle *handle) {
 
     pktout = sftp_pkt_init(SSH_FXP_READDIR);
     sftp_pkt_adduint32(pktout, 0xABC); /* request id */
-    sftp_pkt_addstring(pktout, handle->hstring);
+    sftp_pkt_addstring_start(pktout);
+    sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
     sftp_send(pktout);
     pktin = sftp_recv();
     id = sftp_pkt_getuint32(pktin);
@@ -579,7 +581,8 @@ int fxp_write(struct fxp_handle *handle, char *buffer, uint64 offset, int len) {
 
     pktout = sftp_pkt_init(SSH_FXP_WRITE);
     sftp_pkt_adduint32(pktout, 0xDCB); /* request id */
-    sftp_pkt_addstring(pktout, handle->hstring);
+    sftp_pkt_addstring_start(pktout);
+    sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
     sftp_pkt_adduint64(pktout, offset);
     sftp_pkt_addstring_start(pktout);
     sftp_pkt_addstring_data(pktout, buffer, len);
diff --git a/sftp.h b/sftp.h
index f62f2a1..bee6bbe 100644 (file)
--- a/sftp.h
+++ b/sftp.h
@@ -67,6 +67,7 @@ struct fxp_attrs {
 
 struct fxp_handle {
     char *hstring;
+    int hlen;
 };
 
 struct fxp_name {
@@ -91,7 +92,7 @@ int fxp_init(void);
  * Canonify a pathname. Concatenate the two given path elements
  * with a separating slash, unless the second is NULL.
  */
-char *fxp_realpath(char *path, char *path2);
+char *fxp_realpath(char *path);
 
 /*
  * Open a file.