1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-01 11:32:48 -05: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

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