Large file support for psftp and pscp on both Windows and Unix. On Unix
authorowen <owen@cda61777-01e9-0310-a592-d414129be87e>
Sat, 12 Aug 2006 15:20:19 +0000 (15:20 +0000)
committerowen <owen@cda61777-01e9-0310-a592-d414129be87e>
Sat, 12 Aug 2006 15:20:19 +0000 (15:20 +0000)
we set _FILE_OFFSET_BITS to 64 on the compiler command line (via mkfiles.pl),
and on Windows we use SetFilePointer and GetFileSize to cope with 64-bit sizes
where possible.  Not tested on Win9x.

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

mkfiles.pl
pscp.c
psftp.c
psftp.h
unix/uxsftp.c
windows/winsftp.c

index b13c4eb..79a2f0a 100755 (executable)
@@ -927,7 +927,8 @@ if (defined $makefiles{'gtk'}) {
     "\n".
     &splitline("CFLAGS = -O2 -Wall -Werror -g " .
               (join " ", map {"-I$dirpfx$_"} @srcdirs) .
-              " `gtk-config --cflags`")."\n".
+              " `gtk-config --cflags`").
+                " -D _FILE_OFFSET_BITS=64\n".
     "XLDFLAGS = `gtk-config --libs`\n".
     "ULDFLAGS =#\n".
     "INSTALL=install\n",
diff --git a/pscp.c b/pscp.c
index 5792c3e..a906303 100644 (file)
--- a/pscp.c
+++ b/pscp.c
@@ -25,6 +25,7 @@
 #include "ssh.h"
 #include "sftp.h"
 #include "storage.h"
+#include "int64.h"
 
 static int list = 0;
 static int verbose = 0;
@@ -35,7 +36,6 @@ static int statistics = 1;
 static int prev_stats_len = 0;
 static int scp_unsafe_mode = 0;
 static int errs = 0;
-static int gui_mode = 0;
 static int try_scp = 1;
 static int try_sftp = 1;
 static int main_cmd_is_sftp = 0;
@@ -69,10 +69,7 @@ void ldisc_send(void *handle, char *buf, int len, int interactive)
 
 static void tell_char(FILE * stream, char c)
 {
-    if (!gui_mode)
-       fputc(c, stream);
-    else
-       gui_send_char(stream == stderr, c);
+    fputc(c, stream);
 }
 
 static void tell_str(FILE * stream, char *str)
@@ -112,9 +109,6 @@ void fatalbox(char *fmt, ...)
     sfree(str2);
     errs++;
 
-    if (gui_mode)
-       gui_send_errcount(list, errs);
-
     cleanup_exit(1);
 }
 void modalfatalbox(char *fmt, ...)
@@ -130,9 +124,6 @@ void modalfatalbox(char *fmt, ...)
     sfree(str2);
     errs++;
 
-    if (gui_mode)
-       gui_send_errcount(list, errs);
-
     cleanup_exit(1);
 }
 void connection_fatal(void *frontend, char *fmt, ...)
@@ -148,9 +139,6 @@ void connection_fatal(void *frontend, char *fmt, ...)
     sfree(str2);
     errs++;
 
-    if (gui_mode)
-       gui_send_errcount(list, errs);
-
     cleanup_exit(1);
 }
 
@@ -310,9 +298,6 @@ static void bump(char *fmt, ...)
        ssh_scp_recv((unsigned char *) &ch, 1);
     }
 
-    if (gui_mode)
-       gui_send_errcount(list, errs);
-
     cleanup_exit(1);
 }
 
@@ -495,7 +480,7 @@ static void do_cmd(char *host, char *user, char *cmd)
 /*
  *  Update statistic information about current file.
  */
-static void print_stats(char *name, unsigned long size, unsigned long done,
+static void print_stats(char *name, uint64 size, uint64 done,
                        time_t start, time_t now)
 {
     float ratebs;
@@ -504,34 +489,42 @@ static void print_stats(char *name, unsigned long size, unsigned long done,
     int pct;
     int len;
     int elap;
+    double donedbl;
+    double sizedbl;
 
     elap = (unsigned long) difftime(now, start);
 
     if (now > start)
-       ratebs = (float) done / elap;
+       ratebs = (float) (uint64_to_double(done) / elap);
     else
-       ratebs = (float) done;
+       ratebs = (float) uint64_to_double(done);
 
     if (ratebs < 1.0)
-       eta = size - done;
-    else
-       eta = (unsigned long) ((size - done) / ratebs);
+       eta = (unsigned long) (uint64_to_double(uint64_subtract(size, done)));
+    else {
+        eta = (unsigned long)
+           ((uint64_to_double(uint64_subtract(size, done)) / ratebs));
+    }
+
     etastr = dupprintf("%02ld:%02ld:%02ld",
                       eta / 3600, (eta % 3600) / 60, eta % 60);
 
-    pct = (int) (100 * (done * 1.0 / size));
+    donedbl = uint64_to_double(done);
+    sizedbl = uint64_to_double(size);
+    pct = (int) (100 * (donedbl * 1.0 / sizedbl));
 
-    if (gui_mode) {
-       gui_update_stats(name, size, pct, elap, done, eta,
-                        (unsigned long) ratebs);
-    } else {
-       len = printf("\r%-25.25s | %10ld kB | %5.1f kB/s | ETA: %8s | %3d%%",
-                    name, done / 1024, ratebs / 1024.0, etastr, pct);
+    {
+       char donekb[40];
+       /* divide by 1024 to provide kB */
+       uint64_decimal(uint64_shift_right(done, 10), donekb);
+       len = printf("\r%-25.25s | %s kB | %5.1f kB/s | ETA: %8s | %3d%%",
+                    name,
+                    donekb, ratebs / 1024.0, etastr, pct);
        if (len < prev_stats_len)
            printf("%*s", prev_stats_len - len, "");
        prev_stats_len = len;
 
-       if (done == size)
+       if (uint64_compare(done, size) == 0)
            printf("\n");
 
        fflush(stdout);
@@ -822,7 +815,7 @@ int scp_send_filetimes(unsigned long mtime, unsigned long atime)
     }
 }
 
-int scp_send_filename(char *name, unsigned long size, int modes)
+int scp_send_filename(char *name, uint64 size, int modes)
 {
     if (using_sftp) {
        char *fullname;
@@ -854,7 +847,9 @@ int scp_send_filename(char *name, unsigned long size, int modes)
        return 0;
     } else {
        char buf[40];
-       sprintf(buf, "C%04o %lu ", modes, size);
+       char sizestr[40];
+       uint64_decimal(size, sizestr);
+       sprintf(buf, "C%04o %s ", modes, sizestr);
        back->send(backhandle, buf, strlen(buf));
        back->send(backhandle, name, strlen(name));
        back->send(backhandle, "\n", 1);
@@ -1135,7 +1130,7 @@ struct scp_sink_action {
     char *buf;                        /* will need freeing after use */
     char *name;                               /* filename or dirname (not ENDDIR) */
     int mode;                         /* access mode (not ENDDIR) */
-    unsigned long size;                       /* file size (not ENDDIR) */
+    uint64 size;                      /* file size (not ENDDIR) */
     int settime;                      /* 1 if atime and mtime are filled */
     unsigned long atime, mtime;               /* access times for the file */
 };
@@ -1359,7 +1354,7 @@ int scp_get_sink_action(struct scp_sink_action *act)
                act->action = SCP_SINK_DIR;
                act->buf = dupstr(stripslashes(fname, 0));
                act->name = act->buf;
-               act->size = 0;         /* duhh, it's a directory */
+               act->size = uint64_make(0,0);     /* duhh, it's a directory */
                act->mode = 07777 & attrs.permissions;
                if (scp_sftp_preserve &&
                    (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {
@@ -1379,13 +1374,9 @@ int scp_get_sink_action(struct scp_sink_action *act)
            act->buf = dupstr(stripslashes(fname, 0));
            act->name = act->buf;
            if (attrs.flags & SSH_FILEXFER_ATTR_SIZE) {
-               if (uint64_compare(attrs.size,
-                                  uint64_make(0, ULONG_MAX)) > 0) {
-                   act->size = ULONG_MAX;   /* *boggle* */
-               } else
-                   act->size = attrs.size.lo;
+               act->size = attrs.size;
            } else
-               act->size = ULONG_MAX;   /* no idea */
+               act->size = uint64_make(ULONG_MAX,ULONG_MAX);   /* no idea */
            act->mode = 07777 & attrs.permissions;
            if (scp_sftp_preserve &&
                (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {
@@ -1465,10 +1456,15 @@ int scp_get_sink_action(struct scp_sink_action *act)
         * If we get here, we must have seen SCP_SINK_FILE or
         * SCP_SINK_DIR.
         */
-       if (sscanf(act->buf, "%o %lu %n", &act->mode, &act->size, &i) != 2)
-           bump("Protocol error: Illegal file descriptor format");
-       act->name = act->buf + i;
-       return 0;
+       {
+           char sizestr[40];
+       
+           if (sscanf(act->buf, "%o %s %n", &act->mode, sizestr, &i) != 2)
+               bump("Protocol error: Illegal file descriptor format");
+           act->size = uint64_from_decimal(sizestr);
+           act->name = act->buf + i;
+           return 0;
+       }
     }
 }
 
@@ -1596,13 +1592,13 @@ static void run_err(const char *fmt, ...)
  */
 static void source(char *src)
 {
-    unsigned long size;
+    uint64 size;
     unsigned long mtime, atime;
     char *last;
     RFile *f;
     int attr;
-    unsigned long i;
-    unsigned long stat_bytes;
+    uint64 i;
+    uint64 stat_bytes;
     time_t stat_starttime, stat_lasttime;
 
     attr = file_type(src);
@@ -1655,21 +1651,26 @@ static void source(char *src)
            return;
     }
 
-    if (verbose)
-       tell_user(stderr, "Sending file %s, size=%lu", last, size);
+    if (verbose) {
+       char sizestr[40];
+       uint64_decimal(size, sizestr);
+       tell_user(stderr, "Sending file %s, size=%s", last, sizestr);
+    }
     if (scp_send_filename(last, size, 0644))
        return;
 
-    stat_bytes = 0;
+    stat_bytes = uint64_make(0,0);
     stat_starttime = time(NULL);
     stat_lasttime = 0;
 
-    for (i = 0; i < size; i += 4096) {
+    for (i = uint64_make(0,0);
+        uint64_compare(i,size) < 0;
+        i = uint64_add32(i,4096)) {
        char transbuf[4096];
        int j, k = 4096;
 
-       if (i + k > size)
-           k = size - i;
+       if (uint64_compare(uint64_add32(i, k),size) > 0) /* i + k > size */ 
+           k = (uint64_subtract(size, i)).lo;  /* k = size - i; */
        if ((j = read_from_file(f, transbuf, k)) != k) {
            if (statistics)
                printf("\n");
@@ -1679,8 +1680,9 @@ static void source(char *src)
            bump("%s: Network error occurred", src);
 
        if (statistics) {
-           stat_bytes += k;
-           if (time(NULL) != stat_lasttime || i + k == size) {
+           stat_bytes = uint64_add32(stat_bytes, k);
+           if (time(NULL) != stat_lasttime ||
+               (uint64_compare(uint64_add32(i, k), size) == 0)) {
                stat_lasttime = time(NULL);
                print_stats(last, size, stat_bytes,
                            stat_starttime, stat_lasttime);
@@ -1747,9 +1749,9 @@ static void sink(char *targ, char *src)
     int exists;
     int attr;
     WFile *f;
-    unsigned long received;
+    uint64 received;
     int wrerror = 0;
-    unsigned long stat_bytes;
+    uint64 stat_bytes;
     time_t stat_starttime, stat_lasttime;
     char *stat_name;
 
@@ -1880,20 +1882,20 @@ static void sink(char *targ, char *src)
        if (scp_accept_filexfer())
            return;
 
-       stat_bytes = 0;
+       stat_bytes = uint64_make(0, 0);
        stat_starttime = time(NULL);
        stat_lasttime = 0;
        stat_name = stripslashes(destfname, 1);
 
-       received = 0;
-       while (received < act.size) {
+       received = uint64_make(0, 0);
+       while (uint64_compare(received,act.size) < 0) {
            char transbuf[32768];
-           unsigned long blksize;
+           uint64 blksize;
            int read;
-           blksize = 32768;
-           if (blksize > (act.size - received))
-               blksize = act.size - received;
-           read = scp_recv_filedata(transbuf, (int)blksize);
+           blksize = uint64_make(0, 32768);
+           if (uint64_compare(blksize,uint64_subtract(act.size,received)) > 0)
+             blksize = uint64_subtract(act.size,received);
+           read = scp_recv_filedata(transbuf, (int)blksize.lo);
            if (read <= 0)
                bump("Lost connection");
            if (wrerror)
@@ -1908,15 +1910,15 @@ static void sink(char *targ, char *src)
                continue;
            }
            if (statistics) {
-               stat_bytes += read;
+               stat_bytes = uint64_add32(stat_bytes,read);
                if (time(NULL) > stat_lasttime ||
-                   received + read == act.size) {
+                   uint64_compare(uint64_add32(received, read), act.size) == 0) {
                    stat_lasttime = time(NULL);
                    print_stats(stat_name, act.size, stat_bytes,
                                stat_starttime, stat_lasttime);
                }
            }
-           received += read;
+           received = uint64_add32(received, read);
        }
        if (act.settime) {
            set_file_times(f, act.mtime, act.atime);
@@ -2244,10 +2246,6 @@ int psftp_main(int argc, char *argv[])
            usage();
        } else if (strcmp(argv[i], "-V") == 0) {
             version();
-       } else if (strcmp(argv[i], "-gui") == 0 && i + 1 < argc) {
-           gui_enable(argv[++i]);
-           gui_mode = 1;
-           console_batch_mode = TRUE;
         } else if (strcmp(argv[i], "-ls") == 0) {
            list = 1;
        } else if (strcmp(argv[i], "-batch") == 0) {
@@ -2294,9 +2292,6 @@ int psftp_main(int argc, char *argv[])
     }
     random_save_seed();
 
-    if (gui_mode)
-       gui_send_errcount(list, errs);
-
     cmdline_cleanup();
     console_provide_logctx(NULL);
     back->free(backhandle);
diff --git a/psftp.c b/psftp.c
index 2b0a137..2a74bcd 100644 (file)
--- a/psftp.c
+++ b/psftp.c
@@ -204,7 +204,7 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
     struct sftp_request *req, *rreq;
     struct fxp_xfer *xfer;
     uint64 offset;
-    FILE *fp;
+    WFile *file;
     int ret, shown_err = FALSE;
 
     /*
@@ -386,12 +386,12 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
     }
 
     if (restart) {
-       fp = fopen(outfname, "rb+");
+       file = open_existing_wfile(outfname, NULL);
     } else {
-       fp = fopen(outfname, "wb");
+       file = open_new_file(outfname);
     }
 
-    if (!fp) {
+    if (!file) {
        printf("local: unable to open %s\n", outfname);
 
        sftp_register(req = fxp_close_send(fh));
@@ -403,11 +403,21 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
     }
 
     if (restart) {
-       long posn;
-       fseek(fp, 0L, SEEK_END);
-       posn = ftell(fp);
-       printf("reget: restarting at file position %ld\n", posn);
-       offset = uint64_make(0, posn);
+       char decbuf[30];
+       if (seek_file(file, uint64_make(0,0) , FROM_END) == -1) {
+           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);
+               
+               return 0;
+       }
+           
+       offset = get_file_posn(file);
+       uint64_decimal(offset, decbuf);
+       printf("reget: restarting at file position %s\n", decbuf);
     } else {
        offset = uint64_make(0, 0);
     }
@@ -442,7 +452,7 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
 
            wpos = 0;
            while (wpos < len) {
-               wlen = fwrite(buf + wpos, 1, len - wpos, fp);
+               wlen = write_to_file(file, buf + wpos, len - wpos);
                if (wlen <= 0) {
                    printf("error while writing local file\n");
                    ret = 0;
@@ -461,7 +471,7 @@ int sftp_get_file(char *fname, char *outfname, int recurse, int restart)
 
     xfer_cleanup(xfer);
 
-    fclose(fp);
+    close_wfile(file);
 
     sftp_register(req = fxp_close_send(fh));
     rreq = sftp_find_request(pktin = sftp_recv());
@@ -478,7 +488,7 @@ int sftp_put_file(char *fname, char *outfname, int recurse, int restart)
     struct sftp_packet *pktin;
     struct sftp_request *req, *rreq;
     uint64 offset;
-    FILE *fp;
+    RFile *file;
     int ret, err, eof;
 
     /*
@@ -608,8 +618,8 @@ int sftp_put_file(char *fname, char *outfname, int recurse, int restart)
        return 1;
     }
 
-    fp = fopen(fname, "rb");
-    if (!fp) {
+    file = open_existing_file(fname, NULL, NULL, NULL);
+    if (!file) {
        printf("local: unable to open %s\n", fname);
        return 0;
     }
@@ -649,12 +659,9 @@ int sftp_put_file(char *fname, char *outfname, int recurse, int restart)
        offset = attrs.size;
        uint64_decimal(offset, decbuf);
        printf("reput: restarting at file position %s\n", decbuf);
-       if (uint64_compare(offset, uint64_make(0, LONG_MAX)) > 0) {
-           printf("reput: remote file is larger than we can deal with\n");
-           return 0;
-       }
-       if (fseek(fp, offset.lo, SEEK_SET) != 0)
-           fseek(fp, 0, SEEK_END);    /* *shrug* */
+
+       if (seek_file((WFile *)file, offset, FROM_START) != 0)
+           seek_file((WFile *)file, uint64_make(0,0), FROM_END);    /* *shrug* */
     } else {
        offset = uint64_make(0, 0);
     }
@@ -673,7 +680,7 @@ int sftp_put_file(char *fname, char *outfname, int recurse, int restart)
        int len, ret;
 
        while (xfer_upload_ready(xfer) && !err && !eof) {
-           len = fread(buffer, 1, sizeof(buffer), fp);
+           len = read_from_file(file, buffer, sizeof(buffer));
            if (len == -1) {
                printf("error while reading local file\n");
                err = 1;
@@ -701,7 +708,7 @@ int sftp_put_file(char *fname, char *outfname, int recurse, int restart)
     assert(rreq == req);
     fxp_close_recv(pktin, rreq);
 
-    fclose(fp);
+    close_rfile(file);
 
     return ret;
 }
diff --git a/psftp.h b/psftp.h
index 2f323c7..8d9391c 100644 (file)
--- a/psftp.h
+++ b/psftp.h
@@ -3,6 +3,8 @@
  * platform-specific SFTP module.
  */
 
+#include "int64.h"
+
 #ifndef PUTTY_PSFTP_H
 #define PUTTY_PSFTP_H
 
@@ -78,16 +80,15 @@ void gui_enable(char *arg);
  * the times when saving a new file.
  * 
  * On the other hand, the abstraction is pretty simple: it supports
- * only opening a file and reading it, or creating a file and
- * writing it. (FIXME: to use this in PSFTP it will also need to
- * support seeking to a starting point for restarted transfers.)
- * None of this read-and-write, seeking-back-and-forth stuff.
+ * only opening a file and reading it, or creating a file and writing
+ * it. None of this read-and-write, seeking-back-and-forth stuff.
  */
 typedef struct RFile RFile;
 typedef struct WFile WFile;
 /* Output params size, mtime and atime can all be NULL if desired */
-RFile *open_existing_file(char *name, unsigned long *size,
+RFile *open_existing_file(char *name, uint64 *size,
                          unsigned long *mtime, unsigned long *atime);
+WFile *open_existing_wfile(char *name, uint64 *size);
 /* Returns <0 on error, 0 on eof, or number of bytes read, as usual */
 int read_from_file(RFile *f, void *buffer, int length);
 /* Closes and frees the RFile */
@@ -98,7 +99,11 @@ int write_to_file(WFile *f, void *buffer, int length);
 void set_file_times(WFile *f, unsigned long mtime, unsigned long atime);
 /* Closes and frees the WFile */
 void close_wfile(WFile *f);
-
+/* Seek offset bytes through file */
+enum { FROM_START, FROM_CURRENT, FROM_END };
+int seek_file(WFile *f, uint64 offset, int whence);
+/* Get file position */
+uint64 get_file_posn(WFile *f);
 /*
  * Determine the type of a file: nonexistent, file, directory or
  * weird. `weird' covers anything else - named pipes, Unix sockets,
index 0779ff1..8db397a 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "putty.h"
 #include "psftp.h"
+#include "int64.h"
 
 /*
  * In PSFTP our selects are synchronous, so these functions are
@@ -80,18 +81,6 @@ int get_userpass_input(prompts_t *p, unsigned char *in, int inlen)
 }
 
 /*
- * Stubs for the GUI feedback mechanism in Windows PSCP.
- */
-void gui_update_stats(char *name, unsigned long size,
-                     int percentage, unsigned long elapsed,
-                     unsigned long done, unsigned long eta,
-                     unsigned long ratebs) {}
-void gui_send_errcount(int list, int errs) {}
-void gui_send_char(int is_stderr, int c) {}
-void gui_enable(char *arg) {}
-
-
-/*
  * Set local current directory. Returns NULL on success, or else an
  * error message which must be freed after printing.
  */
@@ -134,7 +123,7 @@ struct RFile {
     int fd;
 };
 
-RFile *open_existing_file(char *name, unsigned long *size,
+RFile *open_existing_file(char *name, uint64 *size,
                          unsigned long *mtime, unsigned long *atime)
 {
     int fd;
@@ -154,9 +143,15 @@ RFile *open_existing_file(char *name, unsigned long *size,
            memset(&statbuf, 0, sizeof(statbuf));
        }
 
-       if (size)
-           *size = statbuf.st_size;
-
+       if (size) {
+           if (sizeof(statbuf.st_size) == 8) {
+               size->hi = statbuf.st_size >> 32;
+               size->lo = (long) statbuf.st_size;
+           } else {
+               *size = uint64_make(0, statbuf.st_size);
+           }
+       }
+               
        if (mtime)
            *mtime = statbuf.st_mtime;
 
@@ -199,6 +194,37 @@ WFile *open_new_file(char *name)
     return ret;
 }
 
+
+WFile *open_existing_wfile(char *name, uint64 *size)
+{
+    int fd;
+    WFile *ret;
+
+    fd = open(name, O_APPEND | O_WRONLY);
+    if (fd < 0)
+       return NULL;
+
+    ret = snew(WFile);
+    ret->fd = fd;
+
+    if (size) {
+       struct stat statbuf;
+       if (fstat(fd, &statbuf) < 0) {
+           fprintf(stderr, "%s: stat: %s\n", name, strerror(errno));
+           memset(&statbuf, 0, sizeof(statbuf));
+       }
+
+       if (sizeof(statbuf.st_size) == 8) {
+           size->hi = statbuf.st_size >> 32;
+           size->lo = (long) statbuf.st_size;
+       } else {
+           *size = uint64_make(0, statbuf.st_size);
+       }
+    }
+
+    return ret;
+}
+
 int write_to_file(WFile *f, void *buffer, int length)
 {
     char *p = (char *)buffer;
@@ -240,6 +266,53 @@ void close_wfile(WFile *f)
     sfree(f);
 }
 
+/* Seek offset bytes through file, from whence, where whence is
+   FROM_START, FROM_CURRENT, or FROM_END */
+int seek_file(WFile *f, uint64 offset, int whence)
+{
+    off_t fileofft;
+    int lseek_whence;
+    
+    if (sizeof(off_t) == 8) {
+       fileofft = ((off_t) offset.hi << 32) + offset.lo;
+    } else {
+       fileofft = offset.lo;
+    }
+
+    switch (whence) {
+    case FROM_START:
+       lseek_whence = SEEK_SET;
+       break;
+    case FROM_CURRENT:
+       lseek_whence = SEEK_CUR;
+       break;
+    case FROM_END:
+       lseek_whence = SEEK_END;
+       break;
+    default:
+       return -1;
+    }
+
+    return lseek(f->fd, fileofft, lseek_whence) >= 0 ? 0 : -1;
+}
+
+uint64 get_file_posn(WFile *f)
+{
+    off_t fileofft;
+    uint64 ret;
+
+    fileofft = lseek(f->fd, (off_t) 0, SEEK_CUR);
+
+    if (sizeof(off_t) == 8) {
+       ret.hi = fileofft >> 32;
+       ret.lo = (long) fileofft;
+    } else {
+       ret = uint64_make(0, fileofft);
+    }
+
+    return ret;
+}
+
 int file_type(char *name)
 {
     struct stat statbuf;
index 47d3c43..d14e817 100644 (file)
@@ -6,124 +6,7 @@
 
 #include "putty.h"
 #include "psftp.h"
-
-/* ----------------------------------------------------------------------
- * Interface to GUI driver program.
- */
-
-/* This is just a base value from which the main message numbers are
- * derived. */
-#define   WM_APP_BASE          0x8000
-
-/* These two pass a single character value in wParam. They represent
- * the visible output from PSCP. */
-#define   WM_STD_OUT_CHAR      ( WM_APP_BASE+400 )
-#define   WM_STD_ERR_CHAR      ( WM_APP_BASE+401 )
-
-/* These pass a transfer status update. WM_STATS_CHAR passes a single
- * character in wParam, and is called repeatedly to pass the name of
- * the file, terminated with "\n". WM_STATS_SIZE passes the size of
- * the file being transferred in wParam. WM_STATS_ELAPSED is called
- * to pass the elapsed time (in seconds) in wParam, and
- * WM_STATS_PERCENT passes the percentage of the transfer which is
- * complete, also in wParam. */
-#define   WM_STATS_CHAR                ( WM_APP_BASE+402 )
-#define   WM_STATS_SIZE        ( WM_APP_BASE+403 )
-#define   WM_STATS_PERCENT     ( WM_APP_BASE+404 )
-#define   WM_STATS_ELAPSED     ( WM_APP_BASE+405 )
-
-/* These are used at the end of a run to pass an error code in
- * wParam: zero means success, nonzero means failure. WM_RET_ERR_CNT
- * is used after a copy, and WM_LS_RET_ERR_CNT is used after a file
- * list operation. */
-#define   WM_RET_ERR_CNT       ( WM_APP_BASE+406 )
-#define   WM_LS_RET_ERR_CNT    ( WM_APP_BASE+407 )
-
-/* More transfer status update messages. WM_STATS_DONE passes the
- * number of bytes sent so far in wParam. WM_STATS_ETA passes the
- * estimated time to completion (in seconds). WM_STATS_RATEBS passes
- * the average transfer rate (in bytes per second). */
-#define   WM_STATS_DONE                ( WM_APP_BASE+408 )
-#define   WM_STATS_ETA         ( WM_APP_BASE+409 )
-#define   WM_STATS_RATEBS      ( WM_APP_BASE+410 )
-
-#define NAME_STR_MAX 2048
-static char statname[NAME_STR_MAX + 1];
-static unsigned long statsize = 0;
-static unsigned long statdone = 0;
-static unsigned long stateta = 0;
-static unsigned long statratebs = 0;
-static int statperct = 0;
-static unsigned long statelapsed = 0;
-
-static HWND gui_hwnd = NULL;
-
-static void send_msg(HWND h, UINT message, WPARAM wParam)
-{
-    while (!PostMessage(h, message, wParam, 0))
-       SleepEx(1000, TRUE);
-}
-
-void gui_send_char(int is_stderr, int c)
-{
-    unsigned int msg_id = WM_STD_OUT_CHAR;
-    if (is_stderr)
-       msg_id = WM_STD_ERR_CHAR;
-    send_msg(gui_hwnd, msg_id, (WPARAM) c);
-}
-
-void gui_send_errcount(int list, int errs)
-{
-    unsigned int msg_id = WM_RET_ERR_CNT;
-    if (list)
-       msg_id = WM_LS_RET_ERR_CNT;
-    while (!PostMessage(gui_hwnd, msg_id, (WPARAM) errs, 0))
-       SleepEx(1000, TRUE);
-}
-
-void gui_update_stats(char *name, unsigned long size,
-                     int percentage, unsigned long elapsed,
-                     unsigned long done, unsigned long eta,
-                     unsigned long ratebs)
-{
-    unsigned int i;
-
-    if (strcmp(name, statname) != 0) {
-       for (i = 0; i < strlen(name); ++i)
-           send_msg(gui_hwnd, WM_STATS_CHAR, (WPARAM) name[i]);
-       send_msg(gui_hwnd, WM_STATS_CHAR, (WPARAM) '\n');
-       strcpy(statname, name);
-    }
-    if (statsize != size) {
-       send_msg(gui_hwnd, WM_STATS_SIZE, (WPARAM) size);
-       statsize = size;
-    }
-    if (statdone != done) {
-       send_msg(gui_hwnd, WM_STATS_DONE, (WPARAM) done);
-       statdone = done;
-    }
-    if (stateta != eta) {
-       send_msg(gui_hwnd, WM_STATS_ETA, (WPARAM) eta);
-       stateta = eta;
-    }
-    if (statratebs != ratebs) {
-       send_msg(gui_hwnd, WM_STATS_RATEBS, (WPARAM) ratebs);
-       statratebs = ratebs;
-    }
-    if (statelapsed != elapsed) {
-       send_msg(gui_hwnd, WM_STATS_ELAPSED, (WPARAM) elapsed);
-       statelapsed = elapsed;
-    }
-    if (statperct != percentage) {
-       send_msg(gui_hwnd, WM_STATS_PERCENT, (WPARAM) percentage);
-       statperct = percentage;
-    }
-}
-
-void gui_enable(char *arg)
-{
-    gui_hwnd = (HWND) atoi(arg);
-}
+#include "int64.h"
 
 char *get_ttymode(void *frontend, const char *mode) { return NULL; }
 
@@ -188,7 +71,7 @@ struct RFile {
     HANDLE h;
 };
 
-RFile *open_existing_file(char *name, unsigned long *size,
+RFile *open_existing_file(char *name, uint64 *size,
                          unsigned long *mtime, unsigned long *atime)
 {
     HANDLE h;
@@ -203,7 +86,7 @@ RFile *open_existing_file(char *name, unsigned long *size,
     ret->h = h;
 
     if (size)
-       *size = GetFileSize(h, NULL);
+        size->lo=GetFileSize(h, &(size->hi));
 
     if (mtime || atime) {
        FILETIME actime, wrtime;
@@ -253,6 +136,25 @@ WFile *open_new_file(char *name)
     return ret;
 }
 
+WFile *open_existing_wfile(char *name, uint64 *size)
+{
+    HANDLE h;
+    WFile *ret;
+
+    h = CreateFile(name, GENERIC_WRITE, FILE_SHARE_READ, NULL,
+                  OPEN_EXISTING, 0, 0);
+    if (h == INVALID_HANDLE_VALUE)
+       return NULL;
+
+    ret = snew(WFile);
+    ret->h = h;
+
+    if (size)
+       size->lo=GetFileSize(h, &(size->hi));
+
+    return ret;
+}
+
 int write_to_file(WFile *f, void *buffer, int length)
 {
     int ret, written;
@@ -277,6 +179,44 @@ void close_wfile(WFile *f)
     sfree(f);
 }
 
+/* Seek offset bytes through file, from whence, where whence is
+   FROM_START, FROM_CURRENT, or FROM_END */
+int seek_file(WFile *f, uint64 offset, int whence)
+{
+    DWORD movemethod;
+
+    switch (whence) {
+    case FROM_START:
+       movemethod = FILE_BEGIN;
+       break;
+    case FROM_CURRENT:
+       movemethod = FILE_CURRENT;
+       break;
+    case FROM_END:
+       movemethod = FILE_END;
+       break;
+    default:
+       return -1;
+    }
+
+    SetFilePointer(f->h, offset.lo, &(offset.hi), movemethod);
+    
+    if (GetLastError() != NO_ERROR)
+       return -1;
+    else 
+       return 0;
+}
+
+uint64 get_file_posn(WFile *f)
+{
+    uint64 ret;
+
+    ret.hi = 0L;
+    ret.lo = SetFilePointer(f->h, 0L, &(ret.hi), FILE_CURRENT);
+
+    return ret;
+}
+
 int file_type(char *name)
 {
     DWORD attr;