1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Large file support for psftp and pscp on both Windows and Unix. On Unix

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.

[originally from svn r6783]
This commit is contained in:
Owen Dunn 2006-08-12 15:20:19 +00:00
parent 3d522cfd08
commit 33b7caa590
6 changed files with 262 additions and 241 deletions

View File

@ -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",

147
pscp.c
View File

@ -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);

51
psftp.c
View File

@ -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;
}

17
psftp.h
View File

@ -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,

View File

@ -19,6 +19,7 @@
#include "putty.h"
#include "psftp.h"
#include "int64.h"
/*
* In PSFTP our selects are synchronous, so these functions are
@ -79,18 +80,6 @@ int get_userpass_input(prompts_t *p, unsigned char *in, int inlen)
return ret;
}
/*
* 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;

View 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;