Sebastian Kuschel reports that pfd_closing can be called for a socket
[u/mdw/putty] / pscp.c
diff --git a/pscp.c b/pscp.c
index 50bea93..3209932 100644 (file)
--- a/pscp.c
+++ b/pscp.c
@@ -41,6 +41,7 @@ static int try_sftp = 1;
 static int main_cmd_is_sftp = 0;
 static int fallback_cmd_is_sftp = 0;
 static int using_sftp = 0;
+static int uploading = 0;
 
 static Backend *back;
 static void *backhandle;
@@ -129,6 +130,19 @@ void modalfatalbox(char *fmt, ...)
 
     cleanup_exit(1);
 }
+void nonfatal(char *fmt, ...)
+{
+    char *str, *str2;
+    va_list ap;
+    va_start(ap, fmt);
+    str = dupvprintf(fmt, ap);
+    str2 = dupcat("Error: ", str, "\n", NULL);
+    sfree(str);
+    va_end(ap);
+    tell_str(stderr, str2);
+    sfree(str2);
+    errs++;
+}
 void connection_fatal(void *frontend, char *fmt, ...)
 {
     char *str, *str2;
@@ -218,11 +232,12 @@ int from_backend_untrusted(void *frontend_handle, const char *data, int len)
 int from_backend_eof(void *frontend)
 {
     /*
-     * We expect to be the party deciding when to close the
+     * We usually expect to be the party deciding when to close the
      * connection, so if we see EOF before we sent it ourselves, we
-     * should panic.
+     * should panic. The exception is if we're using old-style scp and
+     * downloading rather than uploading.
      */
-    if (!sent_eof) {
+    if ((using_sftp || uploading) && !sent_eof) {
         connection_fatal(frontend,
                          "Received unexpected end-of-file from server");
     }
@@ -773,6 +788,8 @@ void scp_sftp_listdir(char *dirname)
         */
        for (i = 0; i < nnames; i++)
            printf("%s\n", ournames[i].longname);
+
+        sfree(ournames);
     }
 }
 
@@ -891,6 +908,7 @@ int scp_send_filename(char *name, uint64 size, int permissions)
        if (!scp_sftp_filehandle) {
            tell_user(stderr, "pscp: unable to open %s: %s",
                      fullname, fxp_error());
+            sfree(fullname);
            errs++;
            return 1;
        }
@@ -1059,6 +1077,7 @@ int scp_send_dirname(char *name, int modes)
            !(attrs.permissions & 0040000)) {
            tell_user(stderr, "unable to create directory %s: %s",
                      fullname, err);
+            sfree(fullname);
            errs++;
            return 1;
        }
@@ -1114,6 +1133,9 @@ int scp_sink_setup(char *source, int preserve, int recursive)
        if (!wc_unescape(newsource, source)) {
            /* Yes, here we go; it's a wildcard. Bah. */
            char *dupsource, *lastpart, *dirpart, *wildcard;
+
+           sfree(newsource);
+
            dupsource = dupstr(source);
            lastpart = stripslashes(dupsource, 0);
            wildcard = dupstr(lastpart);
@@ -1279,6 +1301,7 @@ int scp_get_sink_action(struct scp_sink_action *act)
        if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
            tell_user(stderr, "unable to identify %s: %s", fname,
                      ret ? "file type not supplied" : fxp_error());
+            if (must_free_fname) sfree(fname);
            errs++;
            return 1;
        }
@@ -1717,8 +1740,10 @@ static void source(char *src)
        return;
     }
     if (preserve) {
-       if (scp_send_filetimes(mtime, atime))
+       if (scp_send_filetimes(mtime, atime)) {
+            close_rfile(f);
            return;
+        }
     }
 
     if (verbose) {
@@ -1726,8 +1751,10 @@ static void source(char *src)
        uint64_decimal(size, sizestr);
        tell_user(stderr, "Sending file %s, size=%s", last, sizestr);
     }
-    if (scp_send_filename(last, size, permissions))
+    if (scp_send_filename(last, size, permissions)) {
+        close_rfile(f);
        return;
+    }
 
     stat_bytes = uint64_make(0,0);
     stat_starttime = time(NULL);
@@ -1930,27 +1957,34 @@ static void sink(char *targ, char *src)
        if (act.action == SCP_SINK_DIR) {
            if (exists && attr != FILE_TYPE_DIRECTORY) {
                run_err("%s: Not a directory", destfname);
+                sfree(destfname);
                continue;
            }
            if (!exists) {
                if (!create_directory(destfname)) {
                    run_err("%s: Cannot create directory", destfname);
+                    sfree(destfname);
                    continue;
                }
            }
            sink(destfname, NULL);
            /* can we set the timestamp for directories ? */
+            sfree(destfname);
            continue;
        }
 
        f = open_new_file(destfname, act.permissions);
        if (f == NULL) {
            run_err("%s: Cannot create file", destfname);
+            sfree(destfname);
            continue;
        }
 
-       if (scp_accept_filexfer())
+       if (scp_accept_filexfer()) {
+            sfree(destfname);
+            close_wfile(f);
            return;
+        }
 
        stat_bytes = uint64_make(0, 0);
        stat_starttime = time(NULL);
@@ -1997,6 +2031,7 @@ static void sink(char *targ, char *src)
        close_wfile(f);
        if (wrerror) {
            run_err("%s: Write error", destfname);
+            sfree(destfname);
            continue;
        }
        (void) scp_finish_filerecv();
@@ -2014,6 +2049,8 @@ static void toremote(int argc, char *argv[])
     char *cmd;
     int i, wc_type;
 
+    uploading = 1;
+
     targ = argv[argc - 1];
 
     /* Separate host from filename */
@@ -2103,6 +2140,8 @@ static void tolocal(int argc, char *argv[])
     char *src, *targ, *host, *user;
     char *cmd;
 
+    uploading = 0;
+
     if (argc != 2)
        bump("More than one remote source not supported");