mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-09 15:23:50 -05:00
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request we sent out a moment ago: in fact it can also return NULL, so it makes more sense to report a proper error message if it doesn't return the expected value, and while we're at it, have that error message whatever message was helpfully left in fxp_error() by sftp_find_request when it failed. To do this, I've written a centralised function in psftp.c called sftp_wait_for_reply, which is handed a request that's just been sent out and deals with the mechanics of waiting for its reply, returning the reply when it arrives, and aborting with a sensible error if anything else arrives instead. The numerous sites in psftp.c which called sftp_find_request have all been rewritten to do this instead, and as a side effect they now look more sensible. The only other uses of sftp_find_request were in xfer_*load_gotpkt, which had to be tweaked in its own way. While I'm here, also fix memory management in sftp_find_request, which was freeing its input packet on some but not all error return paths. [originally from svn r9894]
This commit is contained in:
170
pscp.c
170
pscp.c
@ -319,6 +319,29 @@ static void bump(char *fmt, ...)
|
||||
cleanup_exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for the reply to a single SFTP request. Parallels the same
|
||||
* function in psftp.c (but isn't centralised into sftp.c because the
|
||||
* latter module handles SFTP only and shouldn't assume that SFTP is
|
||||
* the only thing going on by calling connection_fatal).
|
||||
*/
|
||||
struct sftp_packet *sftp_wait_for_reply(struct sftp_request *req)
|
||||
{
|
||||
struct sftp_packet *pktin;
|
||||
struct sftp_request *rreq;
|
||||
|
||||
sftp_register(req);
|
||||
pktin = sftp_recv();
|
||||
if (pktin == NULL)
|
||||
connection_fatal(NULL, "did not receive SFTP response packet "
|
||||
"from server");
|
||||
rreq = sftp_find_request(pktin);
|
||||
if (rreq != req)
|
||||
connection_fatal(NULL, "unable to understand SFTP response packet "
|
||||
"from server: %s", fxp_error());
|
||||
return pktin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open an SSH connection to user@host and execute cmd.
|
||||
*/
|
||||
@ -685,7 +708,7 @@ void scp_sftp_listdir(char *dirname)
|
||||
struct fxp_names *names;
|
||||
struct fxp_name *ournames;
|
||||
struct sftp_packet *pktin;
|
||||
struct sftp_request *req, *rreq;
|
||||
struct sftp_request *req;
|
||||
int nnames, namesize;
|
||||
int i;
|
||||
|
||||
@ -697,10 +720,9 @@ void scp_sftp_listdir(char *dirname)
|
||||
|
||||
printf("Listing directory %s\n", dirname);
|
||||
|
||||
sftp_register(req = fxp_opendir_send(dirname));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
dirh = fxp_opendir_recv(pktin, rreq);
|
||||
req = fxp_opendir_send(dirname);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
dirh = fxp_opendir_recv(pktin, req);
|
||||
|
||||
if (dirh == NULL) {
|
||||
printf("Unable to open %s: %s\n", dirname, fxp_error());
|
||||
@ -710,10 +732,9 @@ void scp_sftp_listdir(char *dirname)
|
||||
|
||||
while (1) {
|
||||
|
||||
sftp_register(req = fxp_readdir_send(dirh));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
names = fxp_readdir_recv(pktin, rreq);
|
||||
req = fxp_readdir_send(dirh);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
names = fxp_readdir_recv(pktin, req);
|
||||
|
||||
if (names == NULL) {
|
||||
if (fxp_error_type() == SSH_FX_EOF)
|
||||
@ -736,10 +757,9 @@ void scp_sftp_listdir(char *dirname)
|
||||
names->nnames = 0; /* prevent free_names */
|
||||
fxp_free_names(names);
|
||||
}
|
||||
sftp_register(req = fxp_close_send(dirh));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
fxp_close_recv(pktin, rreq);
|
||||
req = fxp_close_send(dirh);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
fxp_close_recv(pktin, req);
|
||||
|
||||
/*
|
||||
* Now we have our filenames. Sort them by actual file
|
||||
@ -786,7 +806,7 @@ int scp_source_setup(char *target, int shouldbedir)
|
||||
* directory.
|
||||
*/
|
||||
struct sftp_packet *pktin;
|
||||
struct sftp_request *req, *rreq;
|
||||
struct sftp_request *req;
|
||||
struct fxp_attrs attrs;
|
||||
int ret;
|
||||
|
||||
@ -796,10 +816,9 @@ int scp_source_setup(char *target, int shouldbedir)
|
||||
return 1;
|
||||
}
|
||||
|
||||
sftp_register(req = fxp_stat_send(target));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
ret = fxp_stat_recv(pktin, rreq, &attrs);
|
||||
req = fxp_stat_send(target);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
ret = fxp_stat_recv(pktin, req, &attrs);
|
||||
|
||||
if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS))
|
||||
scp_sftp_targetisdir = 0;
|
||||
@ -850,7 +869,7 @@ int scp_send_filename(char *name, uint64 size, int permissions)
|
||||
if (using_sftp) {
|
||||
char *fullname;
|
||||
struct sftp_packet *pktin;
|
||||
struct sftp_request *req, *rreq;
|
||||
struct sftp_request *req;
|
||||
struct fxp_attrs attrs;
|
||||
|
||||
if (scp_sftp_targetisdir) {
|
||||
@ -862,12 +881,11 @@ int scp_send_filename(char *name, uint64 size, int permissions)
|
||||
attrs.flags = 0;
|
||||
PUT_PERMISSIONS(attrs, permissions);
|
||||
|
||||
sftp_register(req = fxp_open_send(fullname, SSH_FXF_WRITE |
|
||||
SSH_FXF_CREAT | SSH_FXF_TRUNC,
|
||||
&attrs));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
scp_sftp_filehandle = fxp_open_recv(pktin, rreq);
|
||||
req = fxp_open_send(fullname,
|
||||
SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC,
|
||||
&attrs);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
scp_sftp_filehandle = fxp_open_recv(pktin, req);
|
||||
|
||||
if (!scp_sftp_filehandle) {
|
||||
tell_user(stderr, "pscp: unable to open %s: %s",
|
||||
@ -907,7 +925,7 @@ int scp_send_filedata(char *data, int len)
|
||||
while (!xfer_upload_ready(scp_sftp_xfer)) {
|
||||
pktin = sftp_recv();
|
||||
ret = xfer_upload_gotpkt(scp_sftp_xfer, pktin);
|
||||
if (!ret) {
|
||||
if (ret <= 0) {
|
||||
tell_user(stderr, "error while writing: %s\n", fxp_error());
|
||||
errs++;
|
||||
return 1;
|
||||
@ -942,12 +960,17 @@ int scp_send_finish(void)
|
||||
if (using_sftp) {
|
||||
struct fxp_attrs attrs;
|
||||
struct sftp_packet *pktin;
|
||||
struct sftp_request *req, *rreq;
|
||||
struct sftp_request *req;
|
||||
int ret;
|
||||
|
||||
while (!xfer_done(scp_sftp_xfer)) {
|
||||
pktin = sftp_recv();
|
||||
xfer_upload_gotpkt(scp_sftp_xfer, pktin);
|
||||
ret = xfer_upload_gotpkt(scp_sftp_xfer, pktin);
|
||||
if (ret <= 0) {
|
||||
tell_user(stderr, "error while writing: %s\n", fxp_error());
|
||||
errs++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
xfer_cleanup(scp_sftp_xfer);
|
||||
|
||||
@ -958,19 +981,17 @@ int scp_send_finish(void)
|
||||
attrs.flags = SSH_FILEXFER_ATTR_ACMODTIME;
|
||||
attrs.atime = scp_sftp_atime;
|
||||
attrs.mtime = scp_sftp_mtime;
|
||||
sftp_register(req = fxp_fsetstat_send(scp_sftp_filehandle, attrs));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
ret = fxp_fsetstat_recv(pktin, rreq);
|
||||
req = fxp_fsetstat_send(scp_sftp_filehandle, attrs);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
ret = fxp_fsetstat_recv(pktin, req);
|
||||
if (!ret) {
|
||||
tell_user(stderr, "unable to set file times: %s\n", fxp_error());
|
||||
errs++;
|
||||
}
|
||||
}
|
||||
sftp_register(req = fxp_close_send(scp_sftp_filehandle));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
fxp_close_recv(pktin, rreq);
|
||||
req = fxp_close_send(scp_sftp_filehandle);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
fxp_close_recv(pktin, req);
|
||||
scp_has_times = 0;
|
||||
return 0;
|
||||
} else {
|
||||
@ -1000,7 +1021,7 @@ int scp_send_dirname(char *name, int modes)
|
||||
char const *err;
|
||||
struct fxp_attrs attrs;
|
||||
struct sftp_packet *pktin;
|
||||
struct sftp_request *req, *rreq;
|
||||
struct sftp_request *req;
|
||||
int ret;
|
||||
|
||||
if (scp_sftp_targetisdir) {
|
||||
@ -1016,20 +1037,18 @@ int scp_send_dirname(char *name, int modes)
|
||||
* exists and is a directory we will assume we were either
|
||||
* successful or it didn't matter.
|
||||
*/
|
||||
sftp_register(req = fxp_mkdir_send(fullname));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
ret = fxp_mkdir_recv(pktin, rreq);
|
||||
req = fxp_mkdir_send(fullname);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
ret = fxp_mkdir_recv(pktin, req);
|
||||
|
||||
if (!ret)
|
||||
err = fxp_error();
|
||||
else
|
||||
err = "server reported no error";
|
||||
|
||||
sftp_register(req = fxp_stat_send(fullname));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
ret = fxp_stat_recv(pktin, rreq, &attrs);
|
||||
req = fxp_stat_send(fullname);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
ret = fxp_stat_recv(pktin, req, &attrs);
|
||||
|
||||
if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) ||
|
||||
!(attrs.permissions & 0040000)) {
|
||||
@ -1179,7 +1198,7 @@ int scp_get_sink_action(struct scp_sink_action *act)
|
||||
int must_free_fname;
|
||||
struct fxp_attrs attrs;
|
||||
struct sftp_packet *pktin;
|
||||
struct sftp_request *req, *rreq;
|
||||
struct sftp_request *req;
|
||||
int ret;
|
||||
|
||||
if (!scp_sftp_dirstack_head) {
|
||||
@ -1248,10 +1267,9 @@ int scp_get_sink_action(struct scp_sink_action *act)
|
||||
* Now we have a filename. Stat it, and see if it's a file
|
||||
* or a directory.
|
||||
*/
|
||||
sftp_register(req = fxp_stat_send(fname));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
ret = fxp_stat_recv(pktin, rreq, &attrs);
|
||||
req = fxp_stat_send(fname);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
ret = fxp_stat_recv(pktin, req, &attrs);
|
||||
|
||||
if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
|
||||
tell_user(stderr, "unable to identify %s: %s", fname,
|
||||
@ -1304,10 +1322,9 @@ int scp_get_sink_action(struct scp_sink_action *act)
|
||||
* list), we must push the other (target,namelist) pair
|
||||
* on a stack.
|
||||
*/
|
||||
sftp_register(req = fxp_opendir_send(fname));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
dirhandle = fxp_opendir_recv(pktin, rreq);
|
||||
req = fxp_opendir_send(fname);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
dirhandle = fxp_opendir_recv(pktin, req);
|
||||
|
||||
if (!dirhandle) {
|
||||
tell_user(stderr, "scp: unable to open directory %s: %s",
|
||||
@ -1321,10 +1338,9 @@ int scp_get_sink_action(struct scp_sink_action *act)
|
||||
while (1) {
|
||||
int i;
|
||||
|
||||
sftp_register(req = fxp_readdir_send(dirhandle));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
names = fxp_readdir_recv(pktin, rreq);
|
||||
req = fxp_readdir_send(dirhandle);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
names = fxp_readdir_recv(pktin, req);
|
||||
|
||||
if (names == NULL) {
|
||||
if (fxp_error_type() == SSH_FX_EOF)
|
||||
@ -1362,10 +1378,9 @@ int scp_get_sink_action(struct scp_sink_action *act)
|
||||
names->nnames = 0; /* prevent free_names */
|
||||
fxp_free_names(names);
|
||||
}
|
||||
sftp_register(req = fxp_close_send(dirhandle));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
fxp_close_recv(pktin, rreq);
|
||||
req = fxp_close_send(dirhandle);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
fxp_close_recv(pktin, req);
|
||||
|
||||
newitem = snew(struct scp_sftp_dirstack);
|
||||
newitem->next = scp_sftp_dirstack_head;
|
||||
@ -1510,13 +1525,11 @@ int scp_accept_filexfer(void)
|
||||
{
|
||||
if (using_sftp) {
|
||||
struct sftp_packet *pktin;
|
||||
struct sftp_request *req, *rreq;
|
||||
struct sftp_request *req;
|
||||
|
||||
sftp_register(req = fxp_open_send(scp_sftp_currentname, SSH_FXF_READ,
|
||||
NULL));
|
||||
rreq = sftp_find_request(pktin = sftp_recv());
|
||||
assert(rreq == req);
|
||||
scp_sftp_filehandle = fxp_open_recv(pktin, rreq);
|
||||
req = fxp_open_send(scp_sftp_currentname, SSH_FXF_READ, NULL);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
scp_sftp_filehandle = fxp_open_recv(pktin, req);
|
||||
|
||||
if (!scp_sftp_filehandle) {
|
||||
tell_user(stderr, "pscp: unable to open %s: %s",
|
||||
@ -1545,8 +1558,7 @@ int scp_recv_filedata(char *data, int len)
|
||||
xfer_download_queue(scp_sftp_xfer);
|
||||
pktin = sftp_recv();
|
||||
ret = xfer_download_gotpkt(scp_sftp_xfer, pktin);
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret <= 0) {
|
||||
tell_user(stderr, "pscp: error while reading: %s", fxp_error());
|
||||
errs++;
|
||||
return -1;
|
||||
@ -1577,7 +1589,7 @@ int scp_finish_filerecv(void)
|
||||
{
|
||||
if (using_sftp) {
|
||||
struct sftp_packet *pktin;
|
||||
struct sftp_request *req, *rreq;
|
||||
struct sftp_request *req;
|
||||
|
||||
/*
|
||||
* Ensure that xfer_done() will work correctly, so we can
|
||||
@ -1587,19 +1599,23 @@ int scp_finish_filerecv(void)
|
||||
xfer_set_error(scp_sftp_xfer);
|
||||
while (!xfer_done(scp_sftp_xfer)) {
|
||||
void *vbuf;
|
||||
int len;
|
||||
int ret, len;
|
||||
|
||||
pktin = sftp_recv();
|
||||
xfer_download_gotpkt(scp_sftp_xfer, pktin);
|
||||
ret = xfer_download_gotpkt(scp_sftp_xfer, pktin);
|
||||
if (ret <= 0) {
|
||||
tell_user(stderr, "pscp: error while reading: %s", fxp_error());
|
||||
errs++;
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
fxp_close_recv(pktin, rreq);
|
||||
req = fxp_close_send(scp_sftp_filehandle);
|
||||
pktin = sftp_wait_for_reply(req);
|
||||
fxp_close_recv(pktin, req);
|
||||
return 0;
|
||||
} else {
|
||||
back->send(backhandle, "", 1);
|
||||
|
Reference in New Issue
Block a user