Clean up handling of the return value from sftp_find_request. In many
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 6 Jul 2013 20:43:21 +0000 (20:43 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 6 Jul 2013 20:43:21 +0000 (20:43 +0000)
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.

To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.

While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.

git-svn-id: svn://svn.tartarus.org/sgt/putty@9894 cda61777-01e9-0310-a592-d414129be87e

pscp.c
psftp.c
sftp.c

diff --git a/pscp.c b/pscp.c
index 054e437..93111d3 100644 (file)
--- a/pscp.c
+++ b/pscp.c
@@ -320,6 +320,29 @@ static void bump(char *fmt, ...)
 }
 
 /*
+ * Wait for the reply to a single SFTP request. Parallels the same
+ * function in psftp.c (but isn't centralised into sftp.c because the
+ * latter module handles SFTP only and shouldn't assume that SFTP is
+ * the only thing going on by calling connection_fatal).
+ */
+struct sftp_packet *sftp_wait_for_reply(struct sftp_request *req)
+{
+    struct sftp_packet *pktin;
+    struct sftp_request *rreq;
+
+    sftp_register(req);
+    pktin = sftp_recv();
+    if (pktin == NULL)
+        connection_fatal(NULL, "did not receive SFTP response packet "
+                         "from server");
+    rreq = sftp_find_request(pktin);
+    if (rreq != req)
+        connection_fatal(NULL, "unable to understand SFTP response packet "
+                         "from server: %s", fxp_error());
+    return pktin;
+}
+
+/*
  *  Open an SSH connection to user@host and execute cmd.
  */
 static void do_cmd(char *host, char *user, char *cmd)
@@ -685,7 +708,7 @@ void scp_sftp_listdir(char *dirname)
     struct fxp_names *names;
     struct fxp_name *ournames;
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
     int nnames, namesize;
     int i;
 
@@ -697,10 +720,9 @@ void scp_sftp_listdir(char *dirname)
 
     printf("Listing directory %s\n", dirname);
 
-    sftp_register(req = fxp_opendir_send(dirname));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    dirh = fxp_opendir_recv(pktin, rreq);
+    req = fxp_opendir_send(dirname);
+    pktin = sftp_wait_for_reply(req);
+    dirh = fxp_opendir_recv(pktin, req);
 
     if (dirh == NULL) {
        printf("Unable to open %s: %s\n", dirname, fxp_error());
@@ -710,10 +732,9 @@ void scp_sftp_listdir(char *dirname)
 
        while (1) {
 
-           sftp_register(req = fxp_readdir_send(dirh));
-           rreq = sftp_find_request(pktin = sftp_recv());
-           assert(rreq == req);
-           names = fxp_readdir_recv(pktin, rreq);
+           req = fxp_readdir_send(dirh);
+            pktin = sftp_wait_for_reply(req);
+           names = fxp_readdir_recv(pktin, req);
 
            if (names == NULL) {
                if (fxp_error_type() == SSH_FX_EOF)
@@ -736,10 +757,9 @@ void scp_sftp_listdir(char *dirname)
            names->nnames = 0;         /* prevent free_names */
            fxp_free_names(names);
        }
-       sftp_register(req = fxp_close_send(dirh));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       fxp_close_recv(pktin, rreq);
+       req = fxp_close_send(dirh);
+        pktin = sftp_wait_for_reply(req);
+       fxp_close_recv(pktin, req);
 
        /*
         * Now we have our filenames. Sort them by actual file
@@ -786,7 +806,7 @@ int scp_source_setup(char *target, int shouldbedir)
         * directory.
         */
        struct sftp_packet *pktin;
-       struct sftp_request *req, *rreq;
+       struct sftp_request *req;
        struct fxp_attrs attrs;
        int ret;
 
@@ -796,10 +816,9 @@ int scp_source_setup(char *target, int shouldbedir)
            return 1;
        }
 
-       sftp_register(req = fxp_stat_send(target));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       ret = fxp_stat_recv(pktin, rreq, &attrs);
+       req = fxp_stat_send(target);
+        pktin = sftp_wait_for_reply(req);
+       ret = fxp_stat_recv(pktin, req, &attrs);
 
        if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS))
            scp_sftp_targetisdir = 0;
@@ -850,7 +869,7 @@ int scp_send_filename(char *name, uint64 size, int permissions)
     if (using_sftp) {
        char *fullname;
        struct sftp_packet *pktin;
-       struct sftp_request *req, *rreq;
+       struct sftp_request *req;
         struct fxp_attrs attrs;
 
        if (scp_sftp_targetisdir) {
@@ -862,12 +881,11 @@ int scp_send_filename(char *name, uint64 size, int permissions)
         attrs.flags = 0;
         PUT_PERMISSIONS(attrs, permissions);
 
-       sftp_register(req = fxp_open_send(fullname, SSH_FXF_WRITE |
-                                         SSH_FXF_CREAT | SSH_FXF_TRUNC,
-                                          &attrs));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       scp_sftp_filehandle = fxp_open_recv(pktin, rreq);
+       req = fxp_open_send(fullname,
+                            SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC,
+                            &attrs);
+        pktin = sftp_wait_for_reply(req);
+       scp_sftp_filehandle = fxp_open_recv(pktin, req);
 
        if (!scp_sftp_filehandle) {
            tell_user(stderr, "pscp: unable to open %s: %s",
@@ -907,7 +925,7 @@ int scp_send_filedata(char *data, int len)
        while (!xfer_upload_ready(scp_sftp_xfer)) {
            pktin = sftp_recv();
            ret = xfer_upload_gotpkt(scp_sftp_xfer, pktin);
-           if (!ret) {
+           if (ret <= 0) {
                tell_user(stderr, "error while writing: %s\n", fxp_error());
                errs++;
                return 1;
@@ -942,12 +960,17 @@ int scp_send_finish(void)
     if (using_sftp) {
        struct fxp_attrs attrs;
        struct sftp_packet *pktin;
-       struct sftp_request *req, *rreq;
+       struct sftp_request *req;
        int ret;
 
        while (!xfer_done(scp_sftp_xfer)) {
            pktin = sftp_recv();
-           xfer_upload_gotpkt(scp_sftp_xfer, pktin);
+           ret = xfer_upload_gotpkt(scp_sftp_xfer, pktin);
+           if (ret <= 0) {
+               tell_user(stderr, "error while writing: %s\n", fxp_error());
+               errs++;
+               return 1;
+           }
        }
        xfer_cleanup(scp_sftp_xfer);
 
@@ -958,19 +981,17 @@ int scp_send_finish(void)
            attrs.flags = SSH_FILEXFER_ATTR_ACMODTIME;
            attrs.atime = scp_sftp_atime;
            attrs.mtime = scp_sftp_mtime;
-           sftp_register(req = fxp_fsetstat_send(scp_sftp_filehandle, attrs));
-           rreq = sftp_find_request(pktin = sftp_recv());
-           assert(rreq == req);
-           ret = fxp_fsetstat_recv(pktin, rreq);
+           req = fxp_fsetstat_send(scp_sftp_filehandle, attrs);
+            pktin = sftp_wait_for_reply(req);
+           ret = fxp_fsetstat_recv(pktin, req);
            if (!ret) {
                tell_user(stderr, "unable to set file times: %s\n", fxp_error());
                errs++;
            }
        }
-       sftp_register(req = fxp_close_send(scp_sftp_filehandle));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       fxp_close_recv(pktin, rreq);
+       req = fxp_close_send(scp_sftp_filehandle);
+        pktin = sftp_wait_for_reply(req);
+       fxp_close_recv(pktin, req);
        scp_has_times = 0;
        return 0;
     } else {
@@ -1000,7 +1021,7 @@ int scp_send_dirname(char *name, int modes)
        char const *err;
        struct fxp_attrs attrs;
        struct sftp_packet *pktin;
-       struct sftp_request *req, *rreq;
+       struct sftp_request *req;
        int ret;
 
        if (scp_sftp_targetisdir) {
@@ -1016,20 +1037,18 @@ int scp_send_dirname(char *name, int modes)
         * exists and is a directory we will assume we were either
         * successful or it didn't matter.
         */
-       sftp_register(req = fxp_mkdir_send(fullname));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       ret = fxp_mkdir_recv(pktin, rreq);
+       req = fxp_mkdir_send(fullname);
+        pktin = sftp_wait_for_reply(req);
+       ret = fxp_mkdir_recv(pktin, req);
 
        if (!ret)
            err = fxp_error();
        else
            err = "server reported no error";
 
-       sftp_register(req = fxp_stat_send(fullname));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       ret = fxp_stat_recv(pktin, rreq, &attrs);
+       req = fxp_stat_send(fullname);
+        pktin = sftp_wait_for_reply(req);
+       ret = fxp_stat_recv(pktin, req, &attrs);
 
        if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) ||
            !(attrs.permissions & 0040000)) {
@@ -1179,7 +1198,7 @@ int scp_get_sink_action(struct scp_sink_action *act)
        int must_free_fname;
        struct fxp_attrs attrs;
        struct sftp_packet *pktin;
-       struct sftp_request *req, *rreq;
+       struct sftp_request *req;
        int ret;
 
        if (!scp_sftp_dirstack_head) {
@@ -1248,10 +1267,9 @@ int scp_get_sink_action(struct scp_sink_action *act)
         * Now we have a filename. Stat it, and see if it's a file
         * or a directory.
         */
-       sftp_register(req = fxp_stat_send(fname));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       ret = fxp_stat_recv(pktin, rreq, &attrs);
+       req = fxp_stat_send(fname);
+        pktin = sftp_wait_for_reply(req);
+       ret = fxp_stat_recv(pktin, req, &attrs);
 
        if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
            tell_user(stderr, "unable to identify %s: %s", fname,
@@ -1304,10 +1322,9 @@ int scp_get_sink_action(struct scp_sink_action *act)
             * list), we must push the other (target,namelist) pair
             * on a stack.
             */
-           sftp_register(req = fxp_opendir_send(fname));
-           rreq = sftp_find_request(pktin = sftp_recv());
-           assert(rreq == req);
-           dirhandle = fxp_opendir_recv(pktin, rreq);
+           req = fxp_opendir_send(fname);
+            pktin = sftp_wait_for_reply(req);
+           dirhandle = fxp_opendir_recv(pktin, req);
 
            if (!dirhandle) {
                tell_user(stderr, "scp: unable to open directory %s: %s",
@@ -1321,10 +1338,9 @@ int scp_get_sink_action(struct scp_sink_action *act)
            while (1) {
                int i;
 
-               sftp_register(req = fxp_readdir_send(dirhandle));
-               rreq = sftp_find_request(pktin = sftp_recv());
-               assert(rreq == req);
-               names = fxp_readdir_recv(pktin, rreq);
+               req = fxp_readdir_send(dirhandle);
+                pktin = sftp_wait_for_reply(req);
+               names = fxp_readdir_recv(pktin, req);
 
                if (names == NULL) {
                    if (fxp_error_type() == SSH_FX_EOF)
@@ -1362,10 +1378,9 @@ int scp_get_sink_action(struct scp_sink_action *act)
                names->nnames = 0;             /* prevent free_names */
                fxp_free_names(names);
            }
-           sftp_register(req = fxp_close_send(dirhandle));
-           rreq = sftp_find_request(pktin = sftp_recv());
-           assert(rreq == req);
-           fxp_close_recv(pktin, rreq);
+           req = fxp_close_send(dirhandle);
+            pktin = sftp_wait_for_reply(req);
+           fxp_close_recv(pktin, req);
 
            newitem = snew(struct scp_sftp_dirstack);
            newitem->next = scp_sftp_dirstack_head;
@@ -1510,13 +1525,11 @@ int scp_accept_filexfer(void)
 {
     if (using_sftp) {
        struct sftp_packet *pktin;
-       struct sftp_request *req, *rreq;
+       struct sftp_request *req;
 
-       sftp_register(req = fxp_open_send(scp_sftp_currentname, SSH_FXF_READ,
-                                          NULL));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       scp_sftp_filehandle = fxp_open_recv(pktin, rreq);
+       req = fxp_open_send(scp_sftp_currentname, SSH_FXF_READ, NULL);
+        pktin = sftp_wait_for_reply(req);
+       scp_sftp_filehandle = fxp_open_recv(pktin, req);
 
        if (!scp_sftp_filehandle) {
            tell_user(stderr, "pscp: unable to open %s: %s",
@@ -1545,8 +1558,7 @@ int scp_recv_filedata(char *data, int len)
        xfer_download_queue(scp_sftp_xfer);
        pktin = sftp_recv();
        ret = xfer_download_gotpkt(scp_sftp_xfer, pktin);
-
-       if (ret < 0) {
+       if (ret <= 0) {
            tell_user(stderr, "pscp: error while reading: %s", fxp_error());
            errs++;
            return -1;
@@ -1577,7 +1589,7 @@ int scp_finish_filerecv(void)
 {
     if (using_sftp) {
        struct sftp_packet *pktin;
-       struct sftp_request *req, *rreq;
+       struct sftp_request *req;
 
        /*
         * Ensure that xfer_done() will work correctly, so we can
@@ -1587,19 +1599,23 @@ int scp_finish_filerecv(void)
        xfer_set_error(scp_sftp_xfer);
        while (!xfer_done(scp_sftp_xfer)) {
            void *vbuf;
-           int len;
+           int ret, len;
 
            pktin = sftp_recv();
-           xfer_download_gotpkt(scp_sftp_xfer, pktin);
+           ret = xfer_download_gotpkt(scp_sftp_xfer, pktin);
+            if (ret <= 0) {
+                tell_user(stderr, "pscp: error while reading: %s", fxp_error());
+                errs++;
+                return -1;
+            }
            if (xfer_download_data(scp_sftp_xfer, &vbuf, &len))
                sfree(vbuf);
        }
        xfer_cleanup(scp_sftp_xfer);
 
-       sftp_register(req = fxp_close_send(scp_sftp_filehandle));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       fxp_close_recv(pktin, rreq);
+       req = fxp_close_send(scp_sftp_filehandle);
+        pktin = sftp_wait_for_reply(req);
+       fxp_close_recv(pktin, req);
        return 0;
     } else {
        back->send(backhandle, "", 1);
diff --git a/psftp.c b/psftp.c
index ab287df..33fbf08 100644 (file)
--- a/psftp.c
+++ b/psftp.c
@@ -40,6 +40,26 @@ static Conf *conf;
 int sent_eof = FALSE;
 
 /* ----------------------------------------------------------------------
+ * Manage sending requests and waiting for replies.
+ */
+struct sftp_packet *sftp_wait_for_reply(struct sftp_request *req)
+{
+    struct sftp_packet *pktin;
+    struct sftp_request *rreq;
+
+    sftp_register(req);
+    pktin = sftp_recv();
+    if (pktin == NULL)
+        connection_fatal(NULL, "did not receive SFTP response packet "
+                         "from server");
+    rreq = sftp_find_request(pktin);
+    if (rreq != req)
+        connection_fatal(NULL, "unable to understand SFTP response packet "
+                         "from server: %s", fxp_error());
+    return pktin;
+}
+
+/* ----------------------------------------------------------------------
  * Higher-level helper functions used in commands.
  */
 
@@ -52,7 +72,7 @@ char *canonify(char *name)
 {
     char *fullname, *canonname;
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
 
     if (name[0] == '/') {
        fullname = dupstr(name);
@@ -65,10 +85,9 @@ char *canonify(char *name)
        fullname = dupcat(pwd, slash, name, NULL);
     }
 
-    sftp_register(req = fxp_realpath_send(fullname));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    canonname = fxp_realpath_recv(pktin, rreq);
+    req = fxp_realpath_send(fullname);
+    pktin = sftp_wait_for_reply(req);
+    canonname = fxp_realpath_recv(pktin, req);
 
     if (canonname) {
        sfree(fullname);
@@ -123,13 +142,12 @@ char *canonify(char *name)
         */
        fullname[i] = '\0';            /* separate the string */
        if (i == 0) {
-           sftp_register(req = fxp_realpath_send("/"));
+           req = fxp_realpath_send("/");
        } else {
-           sftp_register(req = fxp_realpath_send(fullname));
+           req = fxp_realpath_send(fullname);
        }
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       canonname = fxp_realpath_recv(pktin, rreq);
+       pktin = sftp_wait_for_reply(req);
+       canonname = fxp_realpath_recv(pktin, req);
 
        if (!canonname) {
            /* Even that failed. Restore our best guess at the
@@ -208,7 +226,7 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
 {
     struct fxp_handle *fh;
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
     struct fxp_xfer *xfer;
     uint64 offset;
     WFile *file;
@@ -223,10 +241,9 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
     if (recurse) {
        int result;
 
-       sftp_register(req = fxp_stat_send(fname));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       result = fxp_stat_recv(pktin, rreq, &attrs);
+        req = fxp_stat_send(fname);
+        pktin = sftp_wait_for_reply(req);
+       result = fxp_stat_recv(pktin, req, &attrs);
 
        if (result &&
            (attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
@@ -252,10 +269,9 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
             * Now get the list of filenames in the remote
             * directory.
             */
-           sftp_register(req = fxp_opendir_send(fname));
-           rreq = sftp_find_request(pktin = sftp_recv());
-           assert(rreq == req);
-           dirhandle = fxp_opendir_recv(pktin, rreq);
+            req = fxp_opendir_send(fname);
+            pktin = sftp_wait_for_reply(req);
+           dirhandle = fxp_opendir_recv(pktin, req);
 
            if (!dirhandle) {
                printf("%s: unable to open directory: %s\n",
@@ -267,10 +283,9 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
            while (1) {
                int i;
 
-               sftp_register(req = fxp_readdir_send(dirhandle));
-               rreq = sftp_find_request(pktin = sftp_recv());
-               assert(rreq == req);
-               names = fxp_readdir_recv(pktin, rreq);
+               req = fxp_readdir_send(dirhandle);
+                pktin = sftp_wait_for_reply(req);
+               names = fxp_readdir_recv(pktin, req);
 
                if (names == NULL) {
                    if (fxp_error_type() == SSH_FX_EOF)
@@ -301,10 +316,9 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
                    }
                fxp_free_names(names);
            }
-           sftp_register(req = fxp_close_send(dirhandle));
-           rreq = sftp_find_request(pktin = sftp_recv());
-           assert(rreq == req);
-           fxp_close_recv(pktin, rreq);
+           req = fxp_close_send(dirhandle);
+            pktin = sftp_wait_for_reply(req);
+           fxp_close_recv(pktin, req);
 
            /*
             * Sort the names into a clear order. This ought to
@@ -384,16 +398,14 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
        }
     }
 
-    sftp_register(req = fxp_stat_send(fname));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    if (!fxp_stat_recv(pktin, rreq, &attrs))
+    req = fxp_stat_send(fname);
+    pktin = sftp_wait_for_reply(req);
+    if (!fxp_stat_recv(pktin, req, &attrs))
         attrs.flags = 0;
 
-    sftp_register(req = fxp_open_send(fname, SSH_FXF_READ, NULL));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    fh = fxp_open_recv(pktin, rreq);
+    req = fxp_open_send(fname, SSH_FXF_READ, NULL);
+    pktin = sftp_wait_for_reply(req);
+    fh = fxp_open_recv(pktin, req);
 
     if (!fh) {
        printf("%s: open for read: %s\n", fname, fxp_error());
@@ -409,10 +421,9 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
     if (!file) {
        printf("local: unable to open %s\n", outfname);
 
-       sftp_register(req = fxp_close_send(fh));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       fxp_close_recv(pktin, rreq);
+        req = fxp_close_send(fh);
+        pktin = sftp_wait_for_reply(req);
+       fxp_close_recv(pktin, req);
 
        return 0;
     }
@@ -423,10 +434,9 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
            close_wfile(file);
            printf("reget: cannot restart %s - file too large\n",
                   outfname);
-           sftp_register(req = fxp_close_send(fh));
-           rreq = sftp_find_request(pktin = sftp_recv());
-           assert(rreq == req);
-           fxp_close_recv(pktin, rreq);
+           req = fxp_close_send(fh);
+            pktin = sftp_wait_for_reply(req);
+           fxp_close_recv(pktin, req);
                
            return 0;
        }
@@ -454,8 +464,7 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
        xfer_download_queue(xfer);
        pktin = sftp_recv();
        ret = xfer_download_gotpkt(xfer, pktin);
-
-       if (ret < 0) {
+       if (ret <= 0) {
            if (!shown_err) {
                printf("error while reading: %s\n", fxp_error());
                shown_err = TRUE;
@@ -490,10 +499,9 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
 
     close_wfile(file);
 
-    sftp_register(req = fxp_close_send(fh));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    fxp_close_recv(pktin, rreq);
+    req = fxp_close_send(fh);
+    pktin = sftp_wait_for_reply(req);
+    fxp_close_recv(pktin, req);
 
     return ret;
 }
@@ -503,7 +511,7 @@ int sftp_put_file(char *fname, char *outfname, int recurse, int restart)
     struct fxp_handle *fh;
     struct fxp_xfer *xfer;
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
     uint64 offset;
     RFile *file;
     int ret, err, eof;
@@ -526,17 +534,15 @@ int sftp_put_file(char *fname, char *outfname, int recurse, int restart)
         * First, attempt to create the destination directory,
         * unless it already exists.
         */
-       sftp_register(req = fxp_stat_send(outfname));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       result = fxp_stat_recv(pktin, rreq, &attrs);
+       req = fxp_stat_send(outfname);
+        pktin = sftp_wait_for_reply(req);
+       result = fxp_stat_recv(pktin, req, &attrs);
        if (!result ||
            !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) ||
            !(attrs.permissions & 0040000)) {
-           sftp_register(req = fxp_mkdir_send(outfname));
-           rreq = sftp_find_request(pktin = sftp_recv());
-           assert(rreq == req);
-           result = fxp_mkdir_recv(pktin, rreq);
+           req = fxp_mkdir_send(outfname);
+            pktin = sftp_wait_for_reply(req);
+           result = fxp_mkdir_recv(pktin, req);
 
            if (!result) {
                printf("%s: create directory: %s\n",
@@ -586,10 +592,9 @@ int sftp_put_file(char *fname, char *outfname, int recurse, int restart)
             while (i < nnames) {
                 char *nextoutfname;
                 nextoutfname = dupcat(outfname, "/", ournames[i], NULL);
-                sftp_register(req = fxp_stat_send(nextoutfname));
-                rreq = sftp_find_request(pktin = sftp_recv());
-                assert(rreq == req);
-                result = fxp_stat_recv(pktin, rreq, &attrs);
+                req = fxp_stat_send(nextoutfname);
+                pktin = sftp_wait_for_reply(req);
+                result = fxp_stat_recv(pktin, req, &attrs);
                 sfree(nextoutfname);
                 if (!result)
                     break;
@@ -646,15 +651,14 @@ int sftp_put_file(char *fname, char *outfname, int recurse, int restart)
     attrs.flags = 0;
     PUT_PERMISSIONS(attrs, permissions);
     if (restart) {
-       sftp_register(req = fxp_open_send(outfname, SSH_FXF_WRITE, &attrs));
+       req = fxp_open_send(outfname, SSH_FXF_WRITE, &attrs);
     } else {
-       sftp_register(req = fxp_open_send(outfname, SSH_FXF_WRITE |
-                                         SSH_FXF_CREAT | SSH_FXF_TRUNC,
-                                          &attrs));
+       req = fxp_open_send(outfname,
+                            SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC,
+                            &attrs);
     }
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    fh = fxp_open_recv(pktin, rreq);
+    pktin = sftp_wait_for_reply(req);
+    fh = fxp_open_recv(pktin, req);
 
     if (!fh) {
        close_rfile(file);
@@ -667,10 +671,9 @@ int sftp_put_file(char *fname, char *outfname, int recurse, int restart)
        struct fxp_attrs attrs;
        int ret;
 
-       sftp_register(req = fxp_fstat_send(fh));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       ret = fxp_fstat_recv(pktin, rreq, &attrs);
+       req = fxp_fstat_send(fh);
+        pktin = sftp_wait_for_reply(req);
+       ret = fxp_fstat_recv(pktin, req, &attrs);
 
        if (!ret) {
            close_rfile(file);
@@ -729,10 +732,9 @@ int sftp_put_file(char *fname, char *outfname, int recurse, int restart)
 
     xfer_cleanup(xfer);
 
-    sftp_register(req = fxp_close_send(fh));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    fxp_close_recv(pktin, rreq);
+    req = fxp_close_send(fh);
+    pktin = sftp_wait_for_reply(req);
+    fxp_close_recv(pktin, req);
 
     close_rfile(file);
 
@@ -754,7 +756,7 @@ typedef struct SftpWildcardMatcher {
 SftpWildcardMatcher *sftp_begin_wildcard_matching(char *name)
 {
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
     char *wildcard;
     char *unwcdir, *tmpdir, *cdir;
     int len, check;
@@ -785,10 +787,9 @@ SftpWildcardMatcher *sftp_begin_wildcard_matching(char *name)
 
     cdir = canonify(unwcdir);
 
-    sftp_register(req = fxp_opendir_send(cdir));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    dirh = fxp_opendir_recv(pktin, rreq);
+    req = fxp_opendir_send(cdir);
+    pktin = sftp_wait_for_reply(req);
+    dirh = fxp_opendir_recv(pktin, req);
 
     if (dirh) {
        swcm = snew(SftpWildcardMatcher);
@@ -811,7 +812,7 @@ char *sftp_wildcard_get_filename(SftpWildcardMatcher *swcm)
 {
     struct fxp_name *name;
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
 
     while (1) {
        if (swcm->names && swcm->namepos >= swcm->names->nnames) {
@@ -820,10 +821,9 @@ char *sftp_wildcard_get_filename(SftpWildcardMatcher *swcm)
        }
 
        if (!swcm->names) {
-           sftp_register(req = fxp_readdir_send(swcm->dirh));
-           rreq = sftp_find_request(pktin = sftp_recv());
-           assert(rreq == req);
-           swcm->names = fxp_readdir_recv(pktin, rreq);
+           req = fxp_readdir_send(swcm->dirh);
+            pktin = sftp_wait_for_reply(req);
+           swcm->names = fxp_readdir_recv(pktin, req);
 
            if (!swcm->names) {
                if (fxp_error_type() != SSH_FX_EOF)
@@ -875,12 +875,11 @@ char *sftp_wildcard_get_filename(SftpWildcardMatcher *swcm)
 void sftp_finish_wildcard_matching(SftpWildcardMatcher *swcm)
 {
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
 
-    sftp_register(req = fxp_close_send(swcm->dirh));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    fxp_close_recv(pktin, rreq);
+    req = fxp_close_send(swcm->dirh);
+    pktin = sftp_wait_for_reply(req);
+    fxp_close_recv(pktin, req);
 
     if (swcm->names)
        fxp_free_names(swcm->names);
@@ -1011,7 +1010,7 @@ int sftp_cmd_ls(struct sftp_command *cmd)
     int nnames, namesize;
     char *dir, *cdir, *unwcdir, *wildcard;
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
     int i;
 
     if (back == NULL) {
@@ -1058,10 +1057,9 @@ int sftp_cmd_ls(struct sftp_command *cmd)
 
     printf("Listing directory %s\n", cdir);
 
-    sftp_register(req = fxp_opendir_send(cdir));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    dirh = fxp_opendir_recv(pktin, rreq);
+    req = fxp_opendir_send(cdir);
+    pktin = sftp_wait_for_reply(req);
+    dirh = fxp_opendir_recv(pktin, req);
 
     if (dirh == NULL) {
        printf("Unable to open %s: %s\n", dir, fxp_error());
@@ -1071,10 +1069,9 @@ int sftp_cmd_ls(struct sftp_command *cmd)
 
        while (1) {
 
-           sftp_register(req = fxp_readdir_send(dirh));
-           rreq = sftp_find_request(pktin = sftp_recv());
-           assert(rreq == req);
-           names = fxp_readdir_recv(pktin, rreq);
+           req = fxp_readdir_send(dirh);
+            pktin = sftp_wait_for_reply(req);
+           names = fxp_readdir_recv(pktin, req);
 
            if (names == NULL) {
                if (fxp_error_type() == SSH_FX_EOF)
@@ -1098,10 +1095,9 @@ int sftp_cmd_ls(struct sftp_command *cmd)
 
            fxp_free_names(names);
        }
-       sftp_register(req = fxp_close_send(dirh));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       fxp_close_recv(pktin, rreq);
+       req = fxp_close_send(dirh);
+        pktin = sftp_wait_for_reply(req);
+       fxp_close_recv(pktin, req);
 
        /*
         * Now we have our filenames. Sort them by actual file
@@ -1133,7 +1129,7 @@ int sftp_cmd_cd(struct sftp_command *cmd)
 {
     struct fxp_handle *dirh;
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
     char *dir;
 
     if (back == NULL) {
@@ -1151,10 +1147,9 @@ int sftp_cmd_cd(struct sftp_command *cmd)
        return 0;
     }
 
-    sftp_register(req = fxp_opendir_send(dir));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    dirh = fxp_opendir_recv(pktin, rreq);
+    req = fxp_opendir_send(dir);
+    pktin = sftp_wait_for_reply(req);
+    dirh = fxp_opendir_recv(pktin, req);
 
     if (!dirh) {
        printf("Directory %s: %s\n", dir, fxp_error());
@@ -1162,10 +1157,9 @@ int sftp_cmd_cd(struct sftp_command *cmd)
        return 0;
     }
 
-    sftp_register(req = fxp_close_send(dirh));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    fxp_close_recv(pktin, rreq);
+    req = fxp_close_send(dirh);
+    pktin = sftp_wait_for_reply(req);
+    fxp_close_recv(pktin, req);
 
     sfree(pwd);
     pwd = dir;
@@ -1414,7 +1408,7 @@ int sftp_cmd_mkdir(struct sftp_command *cmd)
 {
     char *dir;
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
     int result;
     int i, ret;
 
@@ -1436,10 +1430,9 @@ int sftp_cmd_mkdir(struct sftp_command *cmd)
            return 0;
        }
 
-       sftp_register(req = fxp_mkdir_send(dir));
-       rreq = sftp_find_request(pktin = sftp_recv());
-       assert(rreq == req);
-       result = fxp_mkdir_recv(pktin, rreq);
+       req = fxp_mkdir_send(dir);
+        pktin = sftp_wait_for_reply(req);
+       result = fxp_mkdir_recv(pktin, req);
 
        if (!result) {
            printf("mkdir %s: %s\n", dir, fxp_error());
@@ -1456,13 +1449,12 @@ int sftp_cmd_mkdir(struct sftp_command *cmd)
 static int sftp_action_rmdir(void *vctx, char *dir)
 {
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
     int result;
 
-    sftp_register(req = fxp_rmdir_send(dir));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    result = fxp_rmdir_recv(pktin, rreq);
+    req = fxp_rmdir_send(dir);
+    pktin = sftp_wait_for_reply(req);
+    result = fxp_rmdir_recv(pktin, req);
 
     if (!result) {
        printf("rmdir %s: %s\n", dir, fxp_error());
@@ -1498,13 +1490,12 @@ int sftp_cmd_rmdir(struct sftp_command *cmd)
 static int sftp_action_rm(void *vctx, char *fname)
 {
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
     int result;
 
-    sftp_register(req = fxp_remove_send(fname));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    result = fxp_remove_recv(pktin, rreq);
+    req = fxp_remove_send(fname);
+    pktin = sftp_wait_for_reply(req);
+    result = fxp_remove_recv(pktin, req);
 
     if (!result) {
        printf("rm %s: %s\n", fname, fxp_error());
@@ -1540,14 +1531,13 @@ int sftp_cmd_rm(struct sftp_command *cmd)
 static int check_is_dir(char *dstfname)
 {
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
     struct fxp_attrs attrs;
     int result;
 
-    sftp_register(req = fxp_stat_send(dstfname));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    result = fxp_stat_recv(pktin, rreq, &attrs);
+    req = fxp_stat_send(dstfname);
+    pktin = sftp_wait_for_reply(req);
+    result = fxp_stat_recv(pktin, req, &attrs);
 
     if (result &&
        (attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
@@ -1566,7 +1556,7 @@ static int sftp_action_mv(void *vctx, char *srcfname)
 {
     struct sftp_context_mv *ctx = (struct sftp_context_mv *)vctx;
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
     const char *error;
     char *finalfname, *newcanon = NULL;
     int ret, result;
@@ -1591,10 +1581,9 @@ static int sftp_action_mv(void *vctx, char *srcfname)
        finalfname = ctx->dstfname;
     }
 
-    sftp_register(req = fxp_rename_send(srcfname, finalfname));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    result = fxp_rename_recv(pktin, rreq);
+    req = fxp_rename_send(srcfname, finalfname);
+    pktin = sftp_wait_for_reply(req);
+    result = fxp_rename_recv(pktin, req);
 
     error = result ? NULL : fxp_error();
 
@@ -1663,15 +1652,14 @@ static int sftp_action_chmod(void *vctx, char *fname)
 {
     struct fxp_attrs attrs;
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
     int result;
     unsigned oldperms, newperms;
     struct sftp_context_chmod *ctx = (struct sftp_context_chmod *)vctx;
 
-    sftp_register(req = fxp_stat_send(fname));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    result = fxp_stat_recv(pktin, rreq, &attrs);
+    req = fxp_stat_send(fname);
+    pktin = sftp_wait_for_reply(req);
+    result = fxp_stat_recv(pktin, req, &attrs);
 
     if (!result || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
        printf("get attrs for %s: %s\n", fname,
@@ -1688,10 +1676,9 @@ static int sftp_action_chmod(void *vctx, char *fname)
     if (oldperms == newperms)
        return 1;                      /* no need to do anything! */
 
-    sftp_register(req = fxp_setstat_send(fname, attrs));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    result = fxp_setstat_recv(pktin, rreq);
+    req = fxp_setstat_send(fname, attrs);
+    pktin = sftp_wait_for_reply(req);
+    result = fxp_setstat_recv(pktin, req);
 
     if (!result) {
        printf("set attrs for %s: %s\n", fname, fxp_error());
@@ -2341,7 +2328,7 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags)
 static int do_sftp_init(void)
 {
     struct sftp_packet *pktin;
-    struct sftp_request *req, *rreq;
+    struct sftp_request *req;
 
     /*
      * Do protocol initialisation. 
@@ -2355,10 +2342,9 @@ static int do_sftp_init(void)
     /*
      * Find out where our home directory is.
      */
-    sftp_register(req = fxp_realpath_send("."));
-    rreq = sftp_find_request(pktin = sftp_recv());
-    assert(rreq == req);
-    homedir = fxp_realpath_recv(pktin, rreq);
+    req = fxp_realpath_send(".");
+    pktin = sftp_wait_for_reply(req);
+    homedir = fxp_realpath_recv(pktin, req);
 
     if (!homedir) {
        fprintf(stderr,
diff --git a/sftp.c b/sftp.c
index 19bb61a..4c05182 100644 (file)
--- a/sftp.c
+++ b/sftp.c
@@ -366,7 +366,6 @@ struct sftp_request *sftp_find_request(struct sftp_packet *pktin)
 
     if (!req || !req->registered) {
        fxp_internal_error("request ID mismatch\n");
-        sftp_pkt_free(pktin);
        return NULL;
     }
 
@@ -1203,6 +1202,8 @@ int xfer_download_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
     struct req *rr;
 
     rreq = sftp_find_request(pktin);
+    if (!rreq)
+        return 0;            /* this packet doesn't even make sense */
     rr = (struct req *)fxp_get_userdata(rreq);
     if (!rr)
        return 0;                      /* this packet isn't ours */
@@ -1383,6 +1384,8 @@ int xfer_upload_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
     int ret;
 
     rreq = sftp_find_request(pktin);
+    if (!rreq)
+        return 0;            /* this packet doesn't even make sense */
     rr = (struct req *)fxp_get_userdata(rreq);
     if (!rr)
        return 0;                      /* this packet isn't ours */