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

PSCP in SFTP mode now uses the fast download/upload manager.

[originally from svn r3472]
This commit is contained in:
Simon Tatham 2003-09-29 15:39:56 +00:00
parent efa05f9752
commit 150b6e0a87

77
scp.c
View File

@ -673,6 +673,7 @@ static int scp_sftp_preserve, scp_sftp_recursive;
static unsigned long scp_sftp_mtime, scp_sftp_atime;
static int scp_has_times;
static struct fxp_handle *scp_sftp_filehandle;
static struct fxp_xfer *scp_sftp_xfer;
static uint64 scp_sftp_fileoffset;
void scp_source_setup(char *target, int shouldbedir)
@ -767,6 +768,8 @@ int scp_send_filename(char *name, unsigned long size, int modes)
return 1;
}
scp_sftp_fileoffset = uint64_make(0, 0);
scp_sftp_xfer = xfer_upload_init(scp_sftp_filehandle,
scp_sftp_fileoffset);
sfree(fullname);
return 0;
} else {
@ -784,23 +787,23 @@ int scp_send_filedata(char *data, int len)
if (using_sftp) {
int ret;
struct sftp_packet *pktin;
struct sftp_request *req, *rreq;
if (!scp_sftp_filehandle) {
return 1;
}
sftp_register(req = fxp_write_send(scp_sftp_filehandle,
data, scp_sftp_fileoffset, len));
rreq = sftp_find_request(pktin = sftp_recv());
assert(rreq == req);
ret = fxp_write_recv(pktin, rreq);
if (!ret) {
tell_user(stderr, "error while writing: %s\n", fxp_error());
errs++;
return 1;
while (!xfer_upload_ready(scp_sftp_xfer)) {
pktin = sftp_recv();
ret = xfer_upload_gotpkt(scp_sftp_xfer, pktin);
if (!ret) {
tell_user(stderr, "error while writing: %s\n", fxp_error());
errs++;
return 1;
}
}
xfer_upload_data(scp_sftp_xfer, data, len);
scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, len);
return 0;
} else {
@ -830,6 +833,12 @@ int scp_send_finish(void)
struct sftp_request *req, *rreq;
int ret;
while (!xfer_done(scp_sftp_xfer)) {
pktin = sftp_recv();
xfer_upload_gotpkt(scp_sftp_xfer, pktin);
}
xfer_cleanup(scp_sftp_xfer);
if (!scp_sftp_filehandle) {
return 1;
}
@ -1388,6 +1397,8 @@ int scp_accept_filexfer(void)
return 1;
}
scp_sftp_fileoffset = uint64_make(0, 0);
scp_sftp_xfer = xfer_download_init(scp_sftp_filehandle,
scp_sftp_fileoffset);
sfree(scp_sftp_currentname);
return 0;
} else {
@ -1400,21 +1411,30 @@ int scp_recv_filedata(char *data, int len)
{
if (using_sftp) {
struct sftp_packet *pktin;
struct sftp_request *req, *rreq;
int actuallen;
int ret, actuallen;
void *vbuf;
sftp_register(req = fxp_read_send(scp_sftp_filehandle,
scp_sftp_fileoffset, len));
rreq = sftp_find_request(pktin = sftp_recv());
assert(rreq == req);
actuallen = fxp_read_recv(pktin, rreq, data, len);
xfer_download_queue(scp_sftp_xfer);
pktin = sftp_recv();
ret = xfer_download_gotpkt(scp_sftp_xfer, pktin);
if (actuallen == -1 && fxp_error_type() != SSH_FX_EOF) {
if (ret < 0) {
tell_user(stderr, "pscp: error while reading: %s", fxp_error());
errs++;
return -1;
}
if (actuallen < 0)
if (xfer_download_data(scp_sftp_xfer, &vbuf, &actuallen)) {
/*
* This assertion relies on the fact that the natural
* block size used in the xfer manager is at most that
* used in this module. I don't like crossing layers in
* this way, but it'll do for now.
*/
assert(actuallen <= len);
memcpy(data, vbuf, actuallen);
sfree(vbuf);
} else
actuallen = 0;
scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, actuallen);
@ -1431,6 +1451,23 @@ int scp_finish_filerecv(void)
struct sftp_packet *pktin;
struct sftp_request *req, *rreq;
/*
* Ensure that xfer_done() will work correctly, so we can
* clean up any outstanding requests from the file
* transfer.
*/
xfer_set_error(scp_sftp_xfer);
while (!xfer_done(scp_sftp_xfer)) {
void *vbuf;
int len;
pktin = sftp_recv();
xfer_download_gotpkt(scp_sftp_xfer, pktin);
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);