2001-02-23 18:21:44 +00:00
|
|
|
/*
|
|
|
|
* sftp.c: SFTP generic client code.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2001-02-24 16:08:56 +00:00
|
|
|
#include <string.h>
|
2001-02-23 18:21:44 +00:00
|
|
|
#include <assert.h>
|
2003-09-27 17:52:34 +00:00
|
|
|
#include <limits.h>
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2001-11-14 12:58:42 +00:00
|
|
|
#include "misc.h"
|
2003-06-29 14:26:09 +00:00
|
|
|
#include "tree234.h"
|
2001-02-23 18:21:44 +00:00
|
|
|
#include "sftp.h"
|
|
|
|
|
2001-08-04 14:19:51 +00:00
|
|
|
static const char *fxp_error_message;
|
|
|
|
static int fxp_errtype;
|
|
|
|
|
2015-05-15 10:15:42 +00:00
|
|
|
static void fxp_internal_error(const char *msg);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
Add an SFTP server to the SSH server code.
Unlike the traditional Unix SSH server organisation, the SFTP server
is built into the same process as all the rest of the code. sesschan.c
spots a subsystem request for "sftp", and responds to it by
instantiating an SftpServer object and swapping out its own vtable for
one that talks to it.
(I rather like the idea of an object swapping its own vtable for a
different one in the middle of its lifetime! This is one of those
tricks that would be absurdly hard to implement in a 'proper' OO
language, but when you're doing vtables by hand in C, it's no more
difficult than any other piece of ordinary pointer manipulation. As
long as the methods in both vtables expect the same physical structure
layout, it doesn't cause a problem.)
The SftpServer object doesn't deal directly with SFTP packet formats;
it implements the SFTP server logic in a more abstract way, by having
a vtable method for each SFTP request type with an appropriate
parameter list. It sends its replies by calling methods in another
vtable called SftpReplyBuilder, which in the normal case will write an
SFTP reply packet to send back to the client. So SftpServer can focus
more or less completely on the details of a particular filesystem API
- and hence, the implementation I've got lives in the unix source
directory, and works directly with file descriptors and struct stat
and the like.
(One purpose of this abstraction layer is that I may well want to
write a second dummy implementation, for test-suite purposes, with
completely controllable behaviour, and now I have a handy place to
plug it in in place of the live filesystem.)
In between sesschan's parsing of the byte stream into SFTP packets and
the SftpServer object, there's a layer in the new file sftpserver.c
which does the actual packet decoding and encoding: each request
packet is passed to that, which pulls the fields out of the request
packet and calls the appropriate method of SftpServer. It also
provides the default SftpReplyBuilder which makes the output packet.
I've moved some code out of the previous SFTP client implementation -
basic packet construction code, and in particular the BinarySink/
BinarySource marshalling fuinction for fxp_attrs - into sftpcommon.c,
so that the two directions can share as much as possible.
2018-10-20 21:10:32 +00:00
|
|
|
* Client-specific parts of the send- and receive-packet system.
|
2001-02-23 18:21:44 +00:00
|
|
|
*/
|
2018-10-06 10:52:04 +00:00
|
|
|
|
2022-09-03 11:02:48 +00:00
|
|
|
static bool sftp_send(struct sftp_packet *pkt)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool ret;
|
Add an SFTP server to the SSH server code.
Unlike the traditional Unix SSH server organisation, the SFTP server
is built into the same process as all the rest of the code. sesschan.c
spots a subsystem request for "sftp", and responds to it by
instantiating an SftpServer object and swapping out its own vtable for
one that talks to it.
(I rather like the idea of an object swapping its own vtable for a
different one in the middle of its lifetime! This is one of those
tricks that would be absurdly hard to implement in a 'proper' OO
language, but when you're doing vtables by hand in C, it's no more
difficult than any other piece of ordinary pointer manipulation. As
long as the methods in both vtables expect the same physical structure
layout, it doesn't cause a problem.)
The SftpServer object doesn't deal directly with SFTP packet formats;
it implements the SFTP server logic in a more abstract way, by having
a vtable method for each SFTP request type with an appropriate
parameter list. It sends its replies by calling methods in another
vtable called SftpReplyBuilder, which in the normal case will write an
SFTP reply packet to send back to the client. So SftpServer can focus
more or less completely on the details of a particular filesystem API
- and hence, the implementation I've got lives in the unix source
directory, and works directly with file descriptors and struct stat
and the like.
(One purpose of this abstraction layer is that I may well want to
write a second dummy implementation, for test-suite purposes, with
completely controllable behaviour, and now I have a handy place to
plug it in in place of the live filesystem.)
In between sesschan's parsing of the byte stream into SFTP packets and
the SftpServer object, there's a layer in the new file sftpserver.c
which does the actual packet decoding and encoding: each request
packet is passed to that, which pulls the fields out of the request
packet and calls the appropriate method of SftpServer. It also
provides the default SftpReplyBuilder which makes the output packet.
I've moved some code out of the previous SFTP client implementation -
basic packet construction code, and in particular the BinarySink/
BinarySource marshalling fuinction for fxp_attrs - into sftpcommon.c,
so that the two directions can share as much as possible.
2018-10-20 21:10:32 +00:00
|
|
|
sftp_send_prepare(pkt);
|
2012-08-12 20:17:13 +00:00
|
|
|
ret = sftp_senddata(pkt->data, pkt->length);
|
2001-02-23 18:21:44 +00:00
|
|
|
sftp_pkt_free(pkt);
|
2001-02-24 16:08:56 +00:00
|
|
|
return ret;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
Add an SFTP server to the SSH server code.
Unlike the traditional Unix SSH server organisation, the SFTP server
is built into the same process as all the rest of the code. sesschan.c
spots a subsystem request for "sftp", and responds to it by
instantiating an SftpServer object and swapping out its own vtable for
one that talks to it.
(I rather like the idea of an object swapping its own vtable for a
different one in the middle of its lifetime! This is one of those
tricks that would be absurdly hard to implement in a 'proper' OO
language, but when you're doing vtables by hand in C, it's no more
difficult than any other piece of ordinary pointer manipulation. As
long as the methods in both vtables expect the same physical structure
layout, it doesn't cause a problem.)
The SftpServer object doesn't deal directly with SFTP packet formats;
it implements the SFTP server logic in a more abstract way, by having
a vtable method for each SFTP request type with an appropriate
parameter list. It sends its replies by calling methods in another
vtable called SftpReplyBuilder, which in the normal case will write an
SFTP reply packet to send back to the client. So SftpServer can focus
more or less completely on the details of a particular filesystem API
- and hence, the implementation I've got lives in the unix source
directory, and works directly with file descriptors and struct stat
and the like.
(One purpose of this abstraction layer is that I may well want to
write a second dummy implementation, for test-suite purposes, with
completely controllable behaviour, and now I have a handy place to
plug it in in place of the live filesystem.)
In between sesschan's parsing of the byte stream into SFTP packets and
the SftpServer object, there's a layer in the new file sftpserver.c
which does the actual packet decoding and encoding: each request
packet is passed to that, which pulls the fields out of the request
packet and calls the appropriate method of SftpServer. It also
provides the default SftpReplyBuilder which makes the output packet.
I've moved some code out of the previous SFTP client implementation -
basic packet construction code, and in particular the BinarySink/
BinarySource marshalling fuinction for fxp_attrs - into sftpcommon.c,
so that the two directions can share as much as possible.
2018-10-20 21:10:32 +00:00
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
struct sftp_packet *sftp_recv(void)
|
|
|
|
{
|
2001-02-23 18:21:44 +00:00
|
|
|
struct sftp_packet *pkt;
|
|
|
|
char x[4];
|
|
|
|
|
2001-02-24 16:08:56 +00:00
|
|
|
if (!sftp_recvdata(x, 4))
|
2019-09-08 19:29:00 +00:00
|
|
|
return NULL;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2021-04-09 17:19:44 +00:00
|
|
|
/* Impose _some_ upper bound on packet size. We never expect to
|
|
|
|
* receive more than 32K of data in response to an FXP_READ,
|
|
|
|
* because we decide how much data to ask for. FXP_READDIR and
|
|
|
|
* pathname-returning things like FXP_REALPATH don't have an
|
|
|
|
* explicit bound, so I suppose we just have to trust the server
|
|
|
|
* to be sensible. */
|
|
|
|
unsigned pktlen = GET_32BIT_MSB_FIRST(x);
|
|
|
|
if (pktlen > (1<<20))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pkt = sftp_recv_prepare(pktlen);
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2001-02-24 16:08:56 +00:00
|
|
|
if (!sftp_recvdata(pkt->data, pkt->length)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
sftp_pkt_free(pkt);
|
|
|
|
return NULL;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
Add an SFTP server to the SSH server code.
Unlike the traditional Unix SSH server organisation, the SFTP server
is built into the same process as all the rest of the code. sesschan.c
spots a subsystem request for "sftp", and responds to it by
instantiating an SftpServer object and swapping out its own vtable for
one that talks to it.
(I rather like the idea of an object swapping its own vtable for a
different one in the middle of its lifetime! This is one of those
tricks that would be absurdly hard to implement in a 'proper' OO
language, but when you're doing vtables by hand in C, it's no more
difficult than any other piece of ordinary pointer manipulation. As
long as the methods in both vtables expect the same physical structure
layout, it doesn't cause a problem.)
The SftpServer object doesn't deal directly with SFTP packet formats;
it implements the SFTP server logic in a more abstract way, by having
a vtable method for each SFTP request type with an appropriate
parameter list. It sends its replies by calling methods in another
vtable called SftpReplyBuilder, which in the normal case will write an
SFTP reply packet to send back to the client. So SftpServer can focus
more or less completely on the details of a particular filesystem API
- and hence, the implementation I've got lives in the unix source
directory, and works directly with file descriptors and struct stat
and the like.
(One purpose of this abstraction layer is that I may well want to
write a second dummy implementation, for test-suite purposes, with
completely controllable behaviour, and now I have a handy place to
plug it in in place of the live filesystem.)
In between sesschan's parsing of the byte stream into SFTP packets and
the SftpServer object, there's a layer in the new file sftpserver.c
which does the actual packet decoding and encoding: each request
packet is passed to that, which pulls the fields out of the request
packet and calls the appropriate method of SftpServer. It also
provides the default SftpReplyBuilder which makes the output packet.
I've moved some code out of the previous SFTP client implementation -
basic packet construction code, and in particular the BinarySink/
BinarySource marshalling fuinction for fxp_attrs - into sftpcommon.c,
so that the two directions can share as much as possible.
2018-10-20 21:10:32 +00:00
|
|
|
if (!sftp_recv_finish(pkt)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
sftp_pkt_free(pkt);
|
|
|
|
return NULL;
|
2005-02-20 10:30:05 +00:00
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
return pkt;
|
|
|
|
}
|
|
|
|
|
2003-06-29 14:26:09 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* Request ID allocation and temporary dispatch routines.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define REQUEST_ID_OFFSET 256
|
|
|
|
|
|
|
|
struct sftp_request {
|
|
|
|
unsigned id;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool registered;
|
2003-09-27 17:52:34 +00:00
|
|
|
void *userdata;
|
2003-06-29 14:26:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int sftp_reqcmp(void *av, void *bv)
|
|
|
|
{
|
|
|
|
struct sftp_request *a = (struct sftp_request *)av;
|
|
|
|
struct sftp_request *b = (struct sftp_request *)bv;
|
|
|
|
if (a->id < b->id)
|
2019-09-08 19:29:00 +00:00
|
|
|
return -1;
|
2003-06-29 14:26:09 +00:00
|
|
|
if (a->id > b->id)
|
2019-09-08 19:29:00 +00:00
|
|
|
return +1;
|
2003-06-29 14:26:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
static int sftp_reqfind(void *av, void *bv)
|
|
|
|
{
|
|
|
|
unsigned *a = (unsigned *) av;
|
|
|
|
struct sftp_request *b = (struct sftp_request *)bv;
|
|
|
|
if (*a < b->id)
|
2019-09-08 19:29:00 +00:00
|
|
|
return -1;
|
2003-06-29 14:26:09 +00:00
|
|
|
if (*a > b->id)
|
2019-09-08 19:29:00 +00:00
|
|
|
return +1;
|
2003-06-29 14:26:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static tree234 *sftp_requests;
|
|
|
|
|
|
|
|
static struct sftp_request *sftp_alloc_request(void)
|
|
|
|
{
|
|
|
|
unsigned low, high, mid;
|
|
|
|
int tsize;
|
|
|
|
struct sftp_request *r;
|
|
|
|
|
|
|
|
if (sftp_requests == NULL)
|
2019-09-08 19:29:00 +00:00
|
|
|
sftp_requests = newtree234(sftp_reqcmp);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* First-fit allocation of request IDs: always pick the lowest
|
|
|
|
* unused one. To do this, binary-search using the counted
|
|
|
|
* B-tree to find the largest ID which is in a contiguous
|
|
|
|
* sequence from the beginning. (Precisely everything in that
|
|
|
|
* sequence must have ID equal to its tree index plus
|
2003-08-24 13:22:17 +00:00
|
|
|
* REQUEST_ID_OFFSET.)
|
2003-06-29 14:26:09 +00:00
|
|
|
*/
|
|
|
|
tsize = count234(sftp_requests);
|
|
|
|
|
|
|
|
low = -1;
|
|
|
|
high = tsize;
|
|
|
|
while (high - low > 1) {
|
2019-09-08 19:29:00 +00:00
|
|
|
mid = (high + low) / 2;
|
|
|
|
r = index234(sftp_requests, mid);
|
|
|
|
if (r->id == mid + REQUEST_ID_OFFSET)
|
|
|
|
low = mid; /* this one is fine */
|
|
|
|
else
|
|
|
|
high = mid; /* this one is past it */
|
2003-06-29 14:26:09 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Now low points to either -1, or the tree index of the
|
|
|
|
* largest ID in the initial sequence.
|
|
|
|
*/
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
unsigned i = low + 1 + REQUEST_ID_OFFSET;
|
|
|
|
assert(NULL == find234(sftp_requests, &i, sftp_reqfind));
|
2003-06-29 14:26:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* So the request ID we need to create is
|
|
|
|
* low + 1 + REQUEST_ID_OFFSET.
|
|
|
|
*/
|
|
|
|
r = snew(struct sftp_request);
|
|
|
|
r->id = low + 1 + REQUEST_ID_OFFSET;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
r->registered = false;
|
2003-09-27 17:52:34 +00:00
|
|
|
r->userdata = NULL;
|
2003-06-29 14:26:09 +00:00
|
|
|
add234(sftp_requests, r);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2003-12-19 12:44:46 +00:00
|
|
|
void sftp_cleanup_request(void)
|
|
|
|
{
|
2005-02-25 09:59:24 +00:00
|
|
|
if (sftp_requests != NULL) {
|
2019-09-08 19:29:00 +00:00
|
|
|
freetree234(sftp_requests);
|
|
|
|
sftp_requests = NULL;
|
2003-12-19 12:44:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-29 14:26:09 +00:00
|
|
|
void sftp_register(struct sftp_request *req)
|
|
|
|
{
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
req->registered = true;
|
2003-06-29 14:26:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct sftp_request *sftp_find_request(struct sftp_packet *pktin)
|
|
|
|
{
|
2018-06-02 08:41:39 +00:00
|
|
|
unsigned id;
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req;
|
|
|
|
|
|
|
|
if (!pktin) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_internal_error("did not receive a valid SFTP packet\n");
|
|
|
|
return NULL;
|
2003-06-29 14:26:09 +00:00
|
|
|
}
|
|
|
|
|
2018-06-02 08:41:39 +00:00
|
|
|
id = get_uint32(pktin);
|
|
|
|
if (get_err(pktin)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_internal_error("did not receive a valid SFTP packet\n");
|
|
|
|
return NULL;
|
2005-02-20 10:30:05 +00:00
|
|
|
}
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2018-06-02 08:41:39 +00:00
|
|
|
req = find234(sftp_requests, &id, sftp_reqfind);
|
2003-06-29 14:26:09 +00:00
|
|
|
if (!req || !req->registered) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_internal_error("request ID mismatch\n");
|
|
|
|
return NULL;
|
2003-06-29 14:26:09 +00:00
|
|
|
}
|
|
|
|
|
2003-06-29 14:47:14 +00:00
|
|
|
del234(sftp_requests, req);
|
|
|
|
|
2003-06-29 14:26:09 +00:00
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* SFTP primitives.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Deal with (and free) an FXP_STATUS packet. Return 1 if
|
|
|
|
* SSH_FX_OK, 0 if SSH_FX_EOF, and -1 for anything else (error).
|
|
|
|
* Also place the status into fxp_errtype.
|
|
|
|
*/
|
2001-05-06 14:35:20 +00:00
|
|
|
static int fxp_got_status(struct sftp_packet *pktin)
|
|
|
|
{
|
2001-02-23 18:21:44 +00:00
|
|
|
static const char *const messages[] = {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* SSH_FX_OK. The only time we will display a _message_ for this
|
|
|
|
* is if we were expecting something other than FXP_STATUS on
|
|
|
|
* success, so this is actually an error message! */
|
|
|
|
"unexpected OK response",
|
|
|
|
"end of file",
|
|
|
|
"no such file or directory",
|
|
|
|
"permission denied",
|
|
|
|
"failure",
|
|
|
|
"bad message",
|
|
|
|
"no connection",
|
|
|
|
"connection lost",
|
|
|
|
"operation unsupported",
|
2001-02-23 18:21:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if (pktin->type != SSH_FXP_STATUS) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_error_message = "expected FXP_STATUS packet";
|
|
|
|
fxp_errtype = -1;
|
2001-02-23 18:21:44 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_errtype = get_uint32(pktin);
|
|
|
|
if (get_err(pktin)) {
|
|
|
|
fxp_error_message = "malformed FXP_STATUS packet";
|
|
|
|
fxp_errtype = -1;
|
|
|
|
} else {
|
|
|
|
if (fxp_errtype < 0 || fxp_errtype >= lenof(messages))
|
|
|
|
fxp_error_message = "unknown error code";
|
|
|
|
else
|
|
|
|
fxp_error_message = messages[fxp_errtype];
|
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fxp_errtype == SSH_FX_OK)
|
2019-09-08 19:29:00 +00:00
|
|
|
return 1;
|
2001-02-23 18:21:44 +00:00
|
|
|
else if (fxp_errtype == SSH_FX_EOF)
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
2001-02-23 18:21:44 +00:00
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
return -1;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
2015-05-15 10:15:42 +00:00
|
|
|
static void fxp_internal_error(const char *msg)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-02-23 18:21:44 +00:00
|
|
|
fxp_error_message = msg;
|
|
|
|
fxp_errtype = -1;
|
|
|
|
}
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
const char *fxp_error(void)
|
|
|
|
{
|
2001-02-23 18:21:44 +00:00
|
|
|
return fxp_error_message;
|
|
|
|
}
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
int fxp_error_type(void)
|
|
|
|
{
|
2001-02-23 18:21:44 +00:00
|
|
|
return fxp_errtype;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Perform exchange of init/version packets. Return 0 on failure.
|
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool fxp_init(void)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-02-23 18:21:44 +00:00
|
|
|
struct sftp_packet *pktout, *pktin;
|
2005-02-20 10:30:05 +00:00
|
|
|
unsigned long remotever;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_INIT);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, SFTP_PROTO_VERSION);
|
2001-02-23 18:21:44 +00:00
|
|
|
sftp_send(pktout);
|
|
|
|
|
|
|
|
pktin = sftp_recv();
|
2001-02-27 09:11:42 +00:00
|
|
|
if (!pktin) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_internal_error("could not connect");
|
|
|
|
return false;
|
2001-02-27 09:11:42 +00:00
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
if (pktin->type != SSH_FXP_VERSION) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_internal_error("did not receive FXP_VERSION");
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
2018-06-02 08:41:39 +00:00
|
|
|
remotever = get_uint32(pktin);
|
|
|
|
if (get_err(pktin)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_internal_error("malformed FXP_VERSION packet");
|
2005-02-20 10:30:05 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2005-02-20 10:30:05 +00:00
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
if (remotever > SFTP_PROTO_VERSION) {
|
2022-08-03 19:48:46 +00:00
|
|
|
fxp_internal_error("remote protocol is more advanced than we support");
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* In principle, this packet might also contain extension-
|
|
|
|
* string pairs. We should work through them and look for any
|
|
|
|
* we recognise. In practice we don't currently do so because
|
|
|
|
* we know we don't recognise _any_.
|
|
|
|
*/
|
|
|
|
sftp_pkt_free(pktin);
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return true;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2001-02-24 12:02:35 +00:00
|
|
|
* Canonify a pathname.
|
2001-02-23 18:21:44 +00:00
|
|
|
*/
|
2015-05-15 10:15:42 +00:00
|
|
|
struct sftp_request *fxp_realpath_send(const char *path)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_REALPATH);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_stringz(pktout, path);
|
2001-02-23 18:21:44 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
2003-06-29 14:47:14 +00:00
|
|
|
char *fxp_realpath_recv(struct sftp_packet *pktin, struct sftp_request *req)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
sfree(req);
|
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
if (pktin->type == SSH_FXP_NAME) {
|
2019-09-08 19:29:00 +00:00
|
|
|
unsigned long count;
|
2018-06-02 08:41:39 +00:00
|
|
|
char *path;
|
|
|
|
ptrlen name;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2018-06-02 08:41:39 +00:00
|
|
|
count = get_uint32(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (get_err(pktin) || count != 1) {
|
|
|
|
fxp_internal_error("REALPATH did not return name count of 1\n");
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2018-06-02 08:41:39 +00:00
|
|
|
name = get_string(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (get_err(pktin)) {
|
|
|
|
fxp_internal_error("REALPATH returned malformed FXP_NAME\n");
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2018-06-02 08:41:39 +00:00
|
|
|
path = mkstr(name);
|
2019-09-08 19:29:00 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2018-06-02 08:41:39 +00:00
|
|
|
return path;
|
2001-02-23 18:21:44 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return NULL;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Open a file.
|
|
|
|
*/
|
2015-05-15 10:15:42 +00:00
|
|
|
struct sftp_request *fxp_open_send(const char *path, int type,
|
2018-10-06 10:52:04 +00:00
|
|
|
const struct fxp_attrs *attrs)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_OPEN);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_stringz(pktout, path);
|
|
|
|
put_uint32(pktout, type);
|
2018-10-06 10:52:04 +00:00
|
|
|
put_fxp_attrs(pktout, attrs ? *attrs : no_attrs);
|
2001-02-23 18:21:44 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
2018-06-02 08:41:39 +00:00
|
|
|
static struct fxp_handle *fxp_got_handle(struct sftp_packet *pktin)
|
|
|
|
{
|
|
|
|
ptrlen id;
|
|
|
|
struct fxp_handle *handle;
|
|
|
|
|
|
|
|
id = get_string(pktin);
|
|
|
|
if (get_err(pktin)) {
|
|
|
|
fxp_internal_error("received malformed FXP_HANDLE");
|
|
|
|
sftp_pkt_free(pktin);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
handle = snew(struct fxp_handle);
|
|
|
|
handle->hstring = mkstr(id);
|
|
|
|
handle->hlen = id.len;
|
|
|
|
sftp_pkt_free(pktin);
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
2003-06-29 14:47:14 +00:00
|
|
|
struct fxp_handle *fxp_open_recv(struct sftp_packet *pktin,
|
2019-09-08 19:29:00 +00:00
|
|
|
struct sftp_request *req)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
sfree(req);
|
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
if (pktin->type == SSH_FXP_HANDLE) {
|
2018-06-02 08:41:39 +00:00
|
|
|
return fxp_got_handle(pktin);
|
2001-02-23 18:21:44 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return NULL;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Open a directory.
|
|
|
|
*/
|
2015-05-15 10:15:42 +00:00
|
|
|
struct sftp_request *fxp_opendir_send(const char *path)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_OPENDIR);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_stringz(pktout, path);
|
2001-02-23 18:21:44 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
2003-06-29 14:47:14 +00:00
|
|
|
struct fxp_handle *fxp_opendir_recv(struct sftp_packet *pktin,
|
2019-09-08 19:29:00 +00:00
|
|
|
struct sftp_request *req)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
sfree(req);
|
2001-02-23 18:21:44 +00:00
|
|
|
if (pktin->type == SSH_FXP_HANDLE) {
|
2018-06-02 08:41:39 +00:00
|
|
|
return fxp_got_handle(pktin);
|
2001-02-23 18:21:44 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return NULL;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Close a file/dir.
|
|
|
|
*/
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *fxp_close_send(struct fxp_handle *handle)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_CLOSE);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_string(pktout, handle->hstring, handle->hlen);
|
2001-02-23 18:21:44 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
sfree(handle->hstring);
|
|
|
|
sfree(handle);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool fxp_close_recv(struct sftp_packet *pktin, struct sftp_request *req)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
sfree(req);
|
2003-06-29 14:26:09 +00:00
|
|
|
fxp_got_status(pktin);
|
|
|
|
sftp_pkt_free(pktin);
|
2016-12-28 14:34:53 +00:00
|
|
|
return fxp_errtype == SSH_FX_OK;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
2018-10-06 10:52:04 +00:00
|
|
|
struct sftp_request *fxp_mkdir_send(const char *path,
|
|
|
|
const struct fxp_attrs *attrs)
|
2001-08-04 14:19:51 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-08-04 14:19:51 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_MKDIR);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_stringz(pktout, path);
|
2018-10-06 10:52:04 +00:00
|
|
|
put_fxp_attrs(pktout, attrs ? *attrs : no_attrs);
|
2001-08-04 14:19:51 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool fxp_mkdir_recv(struct sftp_packet *pktin, struct sftp_request *req)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
int id;
|
|
|
|
sfree(req);
|
|
|
|
id = fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return id == 1;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
2015-05-15 10:15:42 +00:00
|
|
|
struct sftp_request *fxp_rmdir_send(const char *path)
|
2001-08-04 14:19:51 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-08-04 14:19:51 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_RMDIR);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_stringz(pktout, path);
|
2001-08-04 14:19:51 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool fxp_rmdir_recv(struct sftp_packet *pktin, struct sftp_request *req)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
int id;
|
|
|
|
sfree(req);
|
|
|
|
id = fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return id == 1;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
2015-05-15 10:15:42 +00:00
|
|
|
struct sftp_request *fxp_remove_send(const char *fname)
|
2001-08-04 14:19:51 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-08-04 14:19:51 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_REMOVE);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_stringz(pktout, fname);
|
2001-08-26 11:35:11 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool fxp_remove_recv(struct sftp_packet *pktin, struct sftp_request *req)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
int id;
|
|
|
|
sfree(req);
|
|
|
|
id = fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return id == 1;
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
|
|
|
|
2015-05-15 10:15:42 +00:00
|
|
|
struct sftp_request *fxp_rename_send(const char *srcfname,
|
|
|
|
const char *dstfname)
|
2001-08-26 11:35:11 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-08-26 11:35:11 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_RENAME);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_stringz(pktout, srcfname);
|
|
|
|
put_stringz(pktout, dstfname);
|
2001-08-26 11:35:11 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool fxp_rename_recv(struct sftp_packet *pktin, struct sftp_request *req)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
int id;
|
|
|
|
sfree(req);
|
|
|
|
id = fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return id == 1;
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Retrieve the attributes of a file. We have fxp_stat which works
|
|
|
|
* on filenames, and fxp_fstat which works on open file handles.
|
|
|
|
*/
|
2015-05-15 10:15:42 +00:00
|
|
|
struct sftp_request *fxp_stat_send(const char *fname)
|
2001-08-26 11:35:11 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-08-26 11:35:11 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_STAT);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_stringz(pktout, fname);
|
2001-08-26 11:35:11 +00:00
|
|
|
sftp_send(pktout);
|
|
|
|
|
2003-06-29 14:26:09 +00:00
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool fxp_got_attrs(struct sftp_packet *pktin, struct fxp_attrs *attrs)
|
2018-06-02 08:41:39 +00:00
|
|
|
{
|
|
|
|
get_fxp_attrs(pktin, attrs);
|
|
|
|
if (get_err(pktin)) {
|
|
|
|
fxp_internal_error("malformed SSH_FXP_ATTRS packet");
|
|
|
|
sftp_pkt_free(pktin);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return false;
|
2018-06-02 08:41:39 +00:00
|
|
|
}
|
|
|
|
sftp_pkt_free(pktin);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return true;
|
2018-06-02 08:41:39 +00:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool fxp_stat_recv(struct sftp_packet *pktin, struct sftp_request *req,
|
2022-08-03 19:48:46 +00:00
|
|
|
struct fxp_attrs *attrs)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
sfree(req);
|
2001-08-26 11:35:11 +00:00
|
|
|
if (pktin->type == SSH_FXP_ATTRS) {
|
2018-06-02 08:41:39 +00:00
|
|
|
return fxp_got_attrs(pktin, attrs);
|
2001-08-26 11:35:11 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *fxp_fstat_send(struct fxp_handle *handle)
|
2001-08-26 11:35:11 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-08-26 11:35:11 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_FSTAT);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_string(pktout, handle->hstring, handle->hlen);
|
2001-08-26 11:35:11 +00:00
|
|
|
sftp_send(pktout);
|
|
|
|
|
2003-06-29 14:26:09 +00:00
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool fxp_fstat_recv(struct sftp_packet *pktin, struct sftp_request *req,
|
|
|
|
struct fxp_attrs *attrs)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
sfree(req);
|
2001-08-26 11:35:11 +00:00
|
|
|
if (pktin->type == SSH_FXP_ATTRS) {
|
2018-06-02 08:41:39 +00:00
|
|
|
return fxp_got_attrs(pktin, attrs);
|
2001-08-26 11:35:11 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the attributes of a file.
|
|
|
|
*/
|
2015-05-15 10:15:42 +00:00
|
|
|
struct sftp_request *fxp_setstat_send(const char *fname,
|
|
|
|
struct fxp_attrs attrs)
|
2001-08-26 11:35:11 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-08-26 11:35:11 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_SETSTAT);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_stringz(pktout, fname);
|
|
|
|
put_fxp_attrs(pktout, attrs);
|
2001-08-04 14:19:51 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool fxp_setstat_recv(struct sftp_packet *pktin, struct sftp_request *req)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
int id;
|
|
|
|
sfree(req);
|
|
|
|
id = fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return id == 1;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
struct sftp_request *fxp_fsetstat_send(struct fxp_handle *handle,
|
2019-09-08 19:29:00 +00:00
|
|
|
struct fxp_attrs attrs)
|
2001-08-26 18:32:28 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-08-26 18:32:28 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_FSETSTAT);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_string(pktout, handle->hstring, handle->hlen);
|
|
|
|
put_fxp_attrs(pktout, attrs);
|
2001-08-26 18:32:28 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool fxp_fsetstat_recv(struct sftp_packet *pktin, struct sftp_request *req)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
int id;
|
|
|
|
sfree(req);
|
|
|
|
id = fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return id == 1;
|
2001-08-26 18:32:28 +00:00
|
|
|
}
|
2001-08-04 14:19:51 +00:00
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
/*
|
|
|
|
* Read from a file. Returns the number of bytes read, or -1 on an
|
|
|
|
* error, or possibly 0 if EOF. (I'm not entirely sure whether it
|
|
|
|
* will return 0 on EOF, or return -1 and store SSH_FX_EOF in the
|
|
|
|
* error indicator. It might even depend on the SFTP server.)
|
|
|
|
*/
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *fxp_read_send(struct fxp_handle *handle,
|
2019-09-08 19:29:00 +00:00
|
|
|
uint64_t offset, int len)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_READ);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_string(pktout, handle->hstring, handle->hlen);
|
|
|
|
put_uint64(pktout, offset);
|
|
|
|
put_uint32(pktout, len);
|
2001-02-23 18:21:44 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
2003-06-29 14:47:14 +00:00
|
|
|
int fxp_read_recv(struct sftp_packet *pktin, struct sftp_request *req,
|
2019-09-08 19:29:00 +00:00
|
|
|
char *buffer, int len)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
sfree(req);
|
2001-02-23 18:21:44 +00:00
|
|
|
if (pktin->type == SSH_FXP_DATA) {
|
2018-06-02 08:41:39 +00:00
|
|
|
ptrlen data;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2018-06-02 08:41:39 +00:00
|
|
|
data = get_string(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (get_err(pktin)) {
|
|
|
|
fxp_internal_error("READ returned malformed SSH_FXP_DATA packet");
|
2005-02-20 10:30:05 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (data.len > len) {
|
|
|
|
fxp_internal_error("READ returned more bytes than requested");
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
memcpy(buffer, data.ptr, data.len);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return data.len;
|
2001-02-23 18:21:44 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return -1;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read from a directory.
|
|
|
|
*/
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *fxp_readdir_send(struct fxp_handle *handle)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_READDIR);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_string(pktout, handle->hstring, handle->hlen);
|
2001-02-23 18:21:44 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
2003-06-29 14:47:14 +00:00
|
|
|
struct fxp_names *fxp_readdir_recv(struct sftp_packet *pktin,
|
2019-09-08 19:29:00 +00:00
|
|
|
struct sftp_request *req)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
sfree(req);
|
2001-02-23 18:21:44 +00:00
|
|
|
if (pktin->type == SSH_FXP_NAME) {
|
Rename 'ret' variables passed from allocation to return.
I mentioned recently (in commit 9e7d4c53d80b6eb) message that I'm no
longer fond of the variable name 'ret', because it's used in two quite
different contexts: it's the return value from a subroutine you just
called (e.g. 'int ret = read(fd, buf, len);' and then check for error
or EOF), or it's the value you're preparing to return from the
_containing_ routine (maybe by assigning it a default value and then
conditionally modifying it, or by starting at NULL and reallocating,
or setting it just before using the 'goto out' cleanup idiom). In the
past I've occasionally made mistakes by forgetting which meaning the
variable had, or accidentally conflating both uses.
If all else fails, I now prefer 'retd' (short for 'returned') in the
former situation, and 'toret' (obviously, the value 'to return') in
the latter case. But even better is to pick a name that actually says
something more specific about what the thing actually is.
One particular bad habit throughout this codebase is to have a set of
functions that deal with some object type (say 'Foo'), all *but one*
of which take a 'Foo *foo' parameter, but the foo_new() function
starts with 'Foo *ret = snew(Foo)'. If all the rest of them think the
canonical name for the ambient Foo is 'foo', so should foo_new()!
So here's a no-brainer start on cutting down on the uses of 'ret': I
looked for all the cases where it was being assigned the result of an
allocation, and renamed the variable to be a description of the thing
being allocated. In the case of a new() function belonging to a
family, I picked the same name as the rest of the functions in its own
family, for consistency. In other cases I picked something sensible.
One case where it _does_ make sense not to use your usual name for the
variable type is when you're cloning an existing object. In that case,
_neither_ of the Foo objects involved should be called 'foo', because
it's ambiguous! They should be named so you can see which is which. In
the two cases I found here, I've called them 'orig' and 'copy'.
As in the previous refactoring, many thanks to clang-rename for the
help.
2022-09-13 13:53:36 +00:00
|
|
|
struct fxp_names *names;
|
2019-09-08 19:29:00 +00:00
|
|
|
unsigned long i;
|
2005-02-20 10:30:05 +00:00
|
|
|
|
2018-06-02 08:41:39 +00:00
|
|
|
i = get_uint32(pktin);
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Sanity-check the number of names. Minimum is obviously
|
|
|
|
* zero. Maximum is the remaining space in the packet
|
|
|
|
* divided by the very minimum length of a name, which is
|
|
|
|
* 12 bytes (4 for an empty filename, 4 for an empty
|
|
|
|
* longname, 4 for a set of attribute flags indicating that
|
|
|
|
* no other attributes are supplied).
|
|
|
|
*/
|
|
|
|
if (get_err(pktin) || i > get_avail(pktin) / 12) {
|
|
|
|
fxp_internal_error("malformed FXP_NAME packet");
|
|
|
|
sftp_pkt_free(pktin);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ensure the implicit multiplication in the snewn() call
|
|
|
|
* doesn't suffer integer overflow and cause us to malloc
|
|
|
|
* too little space.
|
|
|
|
*/
|
|
|
|
if (i > INT_MAX / sizeof(struct fxp_name)) {
|
|
|
|
fxp_internal_error("unreasonably large FXP_NAME packet");
|
|
|
|
sftp_pkt_free(pktin);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
Rename 'ret' variables passed from allocation to return.
I mentioned recently (in commit 9e7d4c53d80b6eb) message that I'm no
longer fond of the variable name 'ret', because it's used in two quite
different contexts: it's the return value from a subroutine you just
called (e.g. 'int ret = read(fd, buf, len);' and then check for error
or EOF), or it's the value you're preparing to return from the
_containing_ routine (maybe by assigning it a default value and then
conditionally modifying it, or by starting at NULL and reallocating,
or setting it just before using the 'goto out' cleanup idiom). In the
past I've occasionally made mistakes by forgetting which meaning the
variable had, or accidentally conflating both uses.
If all else fails, I now prefer 'retd' (short for 'returned') in the
former situation, and 'toret' (obviously, the value 'to return') in
the latter case. But even better is to pick a name that actually says
something more specific about what the thing actually is.
One particular bad habit throughout this codebase is to have a set of
functions that deal with some object type (say 'Foo'), all *but one*
of which take a 'Foo *foo' parameter, but the foo_new() function
starts with 'Foo *ret = snew(Foo)'. If all the rest of them think the
canonical name for the ambient Foo is 'foo', so should foo_new()!
So here's a no-brainer start on cutting down on the uses of 'ret': I
looked for all the cases where it was being assigned the result of an
allocation, and renamed the variable to be a description of the thing
being allocated. In the case of a new() function belonging to a
family, I picked the same name as the rest of the functions in its own
family, for consistency. In other cases I picked something sensible.
One case where it _does_ make sense not to use your usual name for the
variable type is when you're cloning an existing object. In that case,
_neither_ of the Foo objects involved should be called 'foo', because
it's ambiguous! They should be named so you can see which is which. In
the two cases I found here, I've called them 'orig' and 'copy'.
As in the previous refactoring, many thanks to clang-rename for the
help.
2022-09-13 13:53:36 +00:00
|
|
|
names = snew(struct fxp_names);
|
|
|
|
names->nnames = i;
|
|
|
|
names->names = snewn(names->nnames, struct fxp_name);
|
|
|
|
for (i = 0; i < (unsigned long)names->nnames; i++) {
|
|
|
|
names->names[i].filename = mkstr(get_string(pktin));
|
|
|
|
names->names[i].longname = mkstr(get_string(pktin));
|
|
|
|
get_fxp_attrs(pktin, &names->names[i].attrs);
|
2018-06-02 08:41:39 +00:00
|
|
|
}
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (get_err(pktin)) {
|
2018-06-02 08:41:39 +00:00
|
|
|
fxp_internal_error("malformed FXP_NAME packet");
|
Rename 'ret' variables passed from allocation to return.
I mentioned recently (in commit 9e7d4c53d80b6eb) message that I'm no
longer fond of the variable name 'ret', because it's used in two quite
different contexts: it's the return value from a subroutine you just
called (e.g. 'int ret = read(fd, buf, len);' and then check for error
or EOF), or it's the value you're preparing to return from the
_containing_ routine (maybe by assigning it a default value and then
conditionally modifying it, or by starting at NULL and reallocating,
or setting it just before using the 'goto out' cleanup idiom). In the
past I've occasionally made mistakes by forgetting which meaning the
variable had, or accidentally conflating both uses.
If all else fails, I now prefer 'retd' (short for 'returned') in the
former situation, and 'toret' (obviously, the value 'to return') in
the latter case. But even better is to pick a name that actually says
something more specific about what the thing actually is.
One particular bad habit throughout this codebase is to have a set of
functions that deal with some object type (say 'Foo'), all *but one*
of which take a 'Foo *foo' parameter, but the foo_new() function
starts with 'Foo *ret = snew(Foo)'. If all the rest of them think the
canonical name for the ambient Foo is 'foo', so should foo_new()!
So here's a no-brainer start on cutting down on the uses of 'ret': I
looked for all the cases where it was being assigned the result of an
allocation, and renamed the variable to be a description of the thing
being allocated. In the case of a new() function belonging to a
family, I picked the same name as the rest of the functions in its own
family, for consistency. In other cases I picked something sensible.
One case where it _does_ make sense not to use your usual name for the
variable type is when you're cloning an existing object. In that case,
_neither_ of the Foo objects involved should be called 'foo', because
it's ambiguous! They should be named so you can see which is which. In
the two cases I found here, I've called them 'orig' and 'copy'.
As in the previous refactoring, many thanks to clang-rename for the
help.
2022-09-13 13:53:36 +00:00
|
|
|
for (i = 0; i < (unsigned long)names->nnames; i++) {
|
|
|
|
sfree(names->names[i].filename);
|
|
|
|
sfree(names->names[i].longname);
|
2018-06-02 08:41:39 +00:00
|
|
|
}
|
Rename 'ret' variables passed from allocation to return.
I mentioned recently (in commit 9e7d4c53d80b6eb) message that I'm no
longer fond of the variable name 'ret', because it's used in two quite
different contexts: it's the return value from a subroutine you just
called (e.g. 'int ret = read(fd, buf, len);' and then check for error
or EOF), or it's the value you're preparing to return from the
_containing_ routine (maybe by assigning it a default value and then
conditionally modifying it, or by starting at NULL and reallocating,
or setting it just before using the 'goto out' cleanup idiom). In the
past I've occasionally made mistakes by forgetting which meaning the
variable had, or accidentally conflating both uses.
If all else fails, I now prefer 'retd' (short for 'returned') in the
former situation, and 'toret' (obviously, the value 'to return') in
the latter case. But even better is to pick a name that actually says
something more specific about what the thing actually is.
One particular bad habit throughout this codebase is to have a set of
functions that deal with some object type (say 'Foo'), all *but one*
of which take a 'Foo *foo' parameter, but the foo_new() function
starts with 'Foo *ret = snew(Foo)'. If all the rest of them think the
canonical name for the ambient Foo is 'foo', so should foo_new()!
So here's a no-brainer start on cutting down on the uses of 'ret': I
looked for all the cases where it was being assigned the result of an
allocation, and renamed the variable to be a description of the thing
being allocated. In the case of a new() function belonging to a
family, I picked the same name as the rest of the functions in its own
family, for consistency. In other cases I picked something sensible.
One case where it _does_ make sense not to use your usual name for the
variable type is when you're cloning an existing object. In that case,
_neither_ of the Foo objects involved should be called 'foo', because
it's ambiguous! They should be named so you can see which is which. In
the two cases I found here, I've called them 'orig' and 'copy'.
As in the previous refactoring, many thanks to clang-rename for the
help.
2022-09-13 13:53:36 +00:00
|
|
|
sfree(names->names);
|
|
|
|
sfree(names);
|
2018-06-02 08:41:39 +00:00
|
|
|
sfree(pktin);
|
|
|
|
return NULL;
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
Rename 'ret' variables passed from allocation to return.
I mentioned recently (in commit 9e7d4c53d80b6eb) message that I'm no
longer fond of the variable name 'ret', because it's used in two quite
different contexts: it's the return value from a subroutine you just
called (e.g. 'int ret = read(fd, buf, len);' and then check for error
or EOF), or it's the value you're preparing to return from the
_containing_ routine (maybe by assigning it a default value and then
conditionally modifying it, or by starting at NULL and reallocating,
or setting it just before using the 'goto out' cleanup idiom). In the
past I've occasionally made mistakes by forgetting which meaning the
variable had, or accidentally conflating both uses.
If all else fails, I now prefer 'retd' (short for 'returned') in the
former situation, and 'toret' (obviously, the value 'to return') in
the latter case. But even better is to pick a name that actually says
something more specific about what the thing actually is.
One particular bad habit throughout this codebase is to have a set of
functions that deal with some object type (say 'Foo'), all *but one*
of which take a 'Foo *foo' parameter, but the foo_new() function
starts with 'Foo *ret = snew(Foo)'. If all the rest of them think the
canonical name for the ambient Foo is 'foo', so should foo_new()!
So here's a no-brainer start on cutting down on the uses of 'ret': I
looked for all the cases where it was being assigned the result of an
allocation, and renamed the variable to be a description of the thing
being allocated. In the case of a new() function belonging to a
family, I picked the same name as the rest of the functions in its own
family, for consistency. In other cases I picked something sensible.
One case where it _does_ make sense not to use your usual name for the
variable type is when you're cloning an existing object. In that case,
_neither_ of the Foo objects involved should be called 'foo', because
it's ambiguous! They should be named so you can see which is which. In
the two cases I found here, I've called them 'orig' and 'copy'.
As in the previous refactoring, many thanks to clang-rename for the
help.
2022-09-13 13:53:36 +00:00
|
|
|
return names;
|
2001-02-23 18:21:44 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2019-09-08 19:29:00 +00:00
|
|
|
return NULL;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Write to a file. Returns 0 on error, 1 on OK.
|
|
|
|
*/
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *fxp_write_send(struct fxp_handle *handle,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *buffer, uint64_t offset, int len)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_request *req = sftp_alloc_request();
|
|
|
|
struct sftp_packet *pktout;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
pktout = sftp_pkt_init(SSH_FXP_WRITE);
|
2018-05-24 09:42:40 +00:00
|
|
|
put_uint32(pktout, req->id);
|
|
|
|
put_string(pktout, handle->hstring, handle->hlen);
|
|
|
|
put_uint64(pktout, offset);
|
|
|
|
put_string(pktout, buffer, len);
|
2001-02-23 18:21:44 +00:00
|
|
|
sftp_send(pktout);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool fxp_write_recv(struct sftp_packet *pktin, struct sftp_request *req)
|
2003-06-29 14:26:09 +00:00
|
|
|
{
|
2003-06-29 14:47:14 +00:00
|
|
|
sfree(req);
|
2001-02-23 18:21:44 +00:00
|
|
|
fxp_got_status(pktin);
|
2002-03-01 13:16:25 +00:00
|
|
|
sftp_pkt_free(pktin);
|
2001-02-23 18:21:44 +00:00
|
|
|
return fxp_errtype == SSH_FX_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Free up an fxp_names structure.
|
|
|
|
*/
|
2001-05-06 14:35:20 +00:00
|
|
|
void fxp_free_names(struct fxp_names *names)
|
|
|
|
{
|
2001-02-23 18:21:44 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < names->nnames; i++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(names->names[i].filename);
|
|
|
|
sfree(names->names[i].longname);
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
sfree(names->names);
|
|
|
|
sfree(names);
|
|
|
|
}
|
2002-03-31 16:26:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Duplicate an fxp_name structure.
|
|
|
|
*/
|
Rename 'ret' variables passed from allocation to return.
I mentioned recently (in commit 9e7d4c53d80b6eb) message that I'm no
longer fond of the variable name 'ret', because it's used in two quite
different contexts: it's the return value from a subroutine you just
called (e.g. 'int ret = read(fd, buf, len);' and then check for error
or EOF), or it's the value you're preparing to return from the
_containing_ routine (maybe by assigning it a default value and then
conditionally modifying it, or by starting at NULL and reallocating,
or setting it just before using the 'goto out' cleanup idiom). In the
past I've occasionally made mistakes by forgetting which meaning the
variable had, or accidentally conflating both uses.
If all else fails, I now prefer 'retd' (short for 'returned') in the
former situation, and 'toret' (obviously, the value 'to return') in
the latter case. But even better is to pick a name that actually says
something more specific about what the thing actually is.
One particular bad habit throughout this codebase is to have a set of
functions that deal with some object type (say 'Foo'), all *but one*
of which take a 'Foo *foo' parameter, but the foo_new() function
starts with 'Foo *ret = snew(Foo)'. If all the rest of them think the
canonical name for the ambient Foo is 'foo', so should foo_new()!
So here's a no-brainer start on cutting down on the uses of 'ret': I
looked for all the cases where it was being assigned the result of an
allocation, and renamed the variable to be a description of the thing
being allocated. In the case of a new() function belonging to a
family, I picked the same name as the rest of the functions in its own
family, for consistency. In other cases I picked something sensible.
One case where it _does_ make sense not to use your usual name for the
variable type is when you're cloning an existing object. In that case,
_neither_ of the Foo objects involved should be called 'foo', because
it's ambiguous! They should be named so you can see which is which. In
the two cases I found here, I've called them 'orig' and 'copy'.
As in the previous refactoring, many thanks to clang-rename for the
help.
2022-09-13 13:53:36 +00:00
|
|
|
struct fxp_name *fxp_dup_name(struct fxp_name *orig)
|
|
|
|
{
|
|
|
|
struct fxp_name *copy;
|
|
|
|
copy = snew(struct fxp_name);
|
|
|
|
copy->filename = dupstr(orig->filename);
|
|
|
|
copy->longname = dupstr(orig->longname);
|
|
|
|
copy->attrs = orig->attrs; /* structure copy */
|
|
|
|
return copy;
|
2002-03-31 16:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Free up an fxp_name structure.
|
|
|
|
*/
|
|
|
|
void fxp_free_name(struct fxp_name *name)
|
|
|
|
{
|
|
|
|
sfree(name->filename);
|
|
|
|
sfree(name->longname);
|
|
|
|
sfree(name);
|
|
|
|
}
|
2003-09-27 17:52:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Store user data in an sftp_request structure.
|
|
|
|
*/
|
|
|
|
void *fxp_get_userdata(struct sftp_request *req)
|
|
|
|
{
|
|
|
|
return req->userdata;
|
|
|
|
}
|
|
|
|
|
|
|
|
void fxp_set_userdata(struct sftp_request *req, void *data)
|
|
|
|
{
|
|
|
|
req->userdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A wrapper to go round fxp_read_* and fxp_write_*, which manages
|
|
|
|
* the queueing of multiple read/write requests.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct req {
|
|
|
|
char *buffer;
|
|
|
|
int len, retlen, complete;
|
2018-10-26 22:08:58 +00:00
|
|
|
uint64_t offset;
|
2003-09-27 17:52:34 +00:00
|
|
|
struct req *next, *prev;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct fxp_xfer {
|
2018-10-26 22:08:58 +00:00
|
|
|
uint64_t offset, furthestdata, filesize;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
int req_totalsize, req_maxsize;
|
|
|
|
bool eof, err;
|
2003-09-27 17:52:34 +00:00
|
|
|
struct fxp_handle *fh;
|
|
|
|
struct req *head, *tail;
|
|
|
|
};
|
|
|
|
|
2018-10-26 22:08:58 +00:00
|
|
|
static struct fxp_xfer *xfer_init(struct fxp_handle *fh, uint64_t offset)
|
2003-09-27 17:52:34 +00:00
|
|
|
{
|
|
|
|
struct fxp_xfer *xfer = snew(struct fxp_xfer);
|
|
|
|
|
|
|
|
xfer->fh = fh;
|
|
|
|
xfer->offset = offset;
|
|
|
|
xfer->head = xfer->tail = NULL;
|
2003-09-28 14:24:01 +00:00
|
|
|
xfer->req_totalsize = 0;
|
2006-06-02 08:46:34 +00:00
|
|
|
xfer->req_maxsize = 1048576;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
xfer->err = false;
|
2018-10-26 22:08:58 +00:00
|
|
|
xfer->filesize = UINT64_MAX;
|
|
|
|
xfer->furthestdata = 0;
|
2003-09-27 17:52:34 +00:00
|
|
|
|
|
|
|
return xfer;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool xfer_done(struct fxp_xfer *xfer)
|
2003-09-27 17:52:34 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We're finished if we've seen EOF _and_ there are no
|
|
|
|
* outstanding requests.
|
|
|
|
*/
|
|
|
|
return (xfer->eof || xfer->err) && !xfer->head;
|
|
|
|
}
|
|
|
|
|
|
|
|
void xfer_download_queue(struct fxp_xfer *xfer)
|
|
|
|
{
|
2004-12-17 13:39:41 +00:00
|
|
|
while (xfer->req_totalsize < xfer->req_maxsize &&
|
2019-09-08 19:29:00 +00:00
|
|
|
!xfer->eof && !xfer->err) {
|
|
|
|
/*
|
|
|
|
* Queue a new read request.
|
|
|
|
*/
|
|
|
|
struct req *rr;
|
|
|
|
struct sftp_request *req;
|
|
|
|
|
|
|
|
rr = snew(struct req);
|
|
|
|
rr->offset = xfer->offset;
|
|
|
|
rr->complete = 0;
|
|
|
|
if (xfer->tail) {
|
|
|
|
xfer->tail->next = rr;
|
|
|
|
rr->prev = xfer->tail;
|
|
|
|
} else {
|
|
|
|
xfer->head = rr;
|
|
|
|
rr->prev = NULL;
|
|
|
|
}
|
|
|
|
xfer->tail = rr;
|
|
|
|
rr->next = NULL;
|
|
|
|
|
|
|
|
rr->len = 32768;
|
|
|
|
rr->buffer = snewn(rr->len, char);
|
|
|
|
sftp_register(req = fxp_read_send(xfer->fh, rr->offset, rr->len));
|
|
|
|
fxp_set_userdata(req, rr);
|
|
|
|
|
|
|
|
xfer->offset += rr->len;
|
|
|
|
xfer->req_totalsize += rr->len;
|
2003-09-27 17:52:34 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG_DOWNLOAD
|
2018-10-26 22:08:58 +00:00
|
|
|
printf("queueing read request %p at %"PRIu64"\n", rr, rr->offset);
|
2003-09-27 17:52:34 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-26 22:08:58 +00:00
|
|
|
struct fxp_xfer *xfer_download_init(struct fxp_handle *fh, uint64_t offset)
|
2003-09-27 17:52:34 +00:00
|
|
|
{
|
|
|
|
struct fxp_xfer *xfer = xfer_init(fh, offset);
|
|
|
|
|
2018-10-29 19:50:29 +00:00
|
|
|
xfer->eof = false;
|
2003-09-27 17:52:34 +00:00
|
|
|
xfer_download_queue(xfer);
|
|
|
|
|
|
|
|
return xfer;
|
|
|
|
}
|
|
|
|
|
2013-07-11 17:24:53 +00:00
|
|
|
/*
|
|
|
|
* Returns INT_MIN to indicate that it didn't even get as far as
|
|
|
|
* fxp_read_recv and hence has not freed pktin.
|
|
|
|
*/
|
2003-09-27 17:52:34 +00:00
|
|
|
int xfer_download_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
|
|
|
|
{
|
|
|
|
struct sftp_request *rreq;
|
|
|
|
struct req *rr;
|
|
|
|
|
|
|
|
rreq = sftp_find_request(pktin);
|
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]
2013-07-06 20:43:21 +00:00
|
|
|
if (!rreq)
|
2013-07-11 17:24:53 +00:00
|
|
|
return INT_MIN; /* this packet doesn't even make sense */
|
2003-09-27 17:52:34 +00:00
|
|
|
rr = (struct req *)fxp_get_userdata(rreq);
|
2013-07-11 17:24:53 +00:00
|
|
|
if (!rr) {
|
|
|
|
fxp_internal_error("request ID is not part of the current download");
|
2019-09-08 19:29:00 +00:00
|
|
|
return INT_MIN; /* this packet isn't ours */
|
2013-07-11 17:24:53 +00:00
|
|
|
}
|
2003-09-27 17:52:34 +00:00
|
|
|
rr->retlen = fxp_read_recv(pktin, rreq, rr->buffer, rr->len);
|
|
|
|
#ifdef DEBUG_DOWNLOAD
|
|
|
|
printf("read request %p has returned [%d]\n", rr, rr->retlen);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ((rr->retlen < 0 && fxp_error_type()==SSH_FX_EOF) || rr->retlen == 0) {
|
2019-09-08 19:29:00 +00:00
|
|
|
xfer->eof = true;
|
2017-02-15 21:39:23 +00:00
|
|
|
rr->retlen = 0;
|
2019-09-08 19:29:00 +00:00
|
|
|
rr->complete = -1;
|
2003-09-27 17:52:34 +00:00
|
|
|
#ifdef DEBUG_DOWNLOAD
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("setting eof\n");
|
2003-09-27 17:52:34 +00:00
|
|
|
#endif
|
|
|
|
} else if (rr->retlen < 0) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* some error other than EOF; signal it back to caller */
|
|
|
|
xfer_set_error(xfer);
|
|
|
|
rr->complete = -1;
|
|
|
|
return -1;
|
2003-09-27 17:52:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rr->complete = 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Special case: if we have received fewer bytes than we
|
|
|
|
* actually read, we should do something. For the moment I'll
|
|
|
|
* just throw an ersatz FXP error to signal this; the SFTP
|
|
|
|
* draft I've got says that it can't happen except on special
|
|
|
|
* files, in which case seeking probably has very little
|
|
|
|
* meaning and so queueing an additional read request to fill
|
|
|
|
* up the gap sounds like the wrong answer. I'm not sure what I
|
|
|
|
* should be doing here - if it _was_ a special file, I suspect
|
|
|
|
* I simply shouldn't have been queueing multiple requests in
|
|
|
|
* the first place...
|
|
|
|
*/
|
2018-10-26 22:08:58 +00:00
|
|
|
if (rr->retlen > 0 && xfer->furthestdata < rr->offset) {
|
2019-09-08 19:29:00 +00:00
|
|
|
xfer->furthestdata = rr->offset;
|
2003-09-27 17:52:34 +00:00
|
|
|
#ifdef DEBUG_DOWNLOAD
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("setting furthestdata = %"PRIu64"\n", xfer->furthestdata);
|
2003-09-27 17:52:34 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rr->retlen < rr->len) {
|
2019-09-08 19:29:00 +00:00
|
|
|
uint64_t filesize = rr->offset + (rr->retlen < 0 ? 0 : rr->retlen);
|
2003-09-27 17:52:34 +00:00
|
|
|
#ifdef DEBUG_DOWNLOAD
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("short block! trying filesize = %"PRIu64"\n", filesize);
|
2003-09-27 17:52:34 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
if (xfer->filesize > filesize) {
|
|
|
|
xfer->filesize = filesize;
|
2003-09-27 17:52:34 +00:00
|
|
|
#ifdef DEBUG_DOWNLOAD
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("actually changing filesize\n");
|
|
|
|
#endif
|
|
|
|
}
|
2003-09-27 17:52:34 +00:00
|
|
|
}
|
|
|
|
|
2018-10-26 22:08:58 +00:00
|
|
|
if (xfer->furthestdata > xfer->filesize) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_error_message = "received a short buffer from FXP_READ, but not"
|
|
|
|
" at EOF";
|
|
|
|
fxp_errtype = -1;
|
|
|
|
xfer_set_error(xfer);
|
|
|
|
return -1;
|
2003-09-27 17:52:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void xfer_set_error(struct fxp_xfer *xfer)
|
|
|
|
{
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
xfer->err = true;
|
2003-09-27 17:52:34 +00:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool xfer_download_data(struct fxp_xfer *xfer, void **buf, int *len)
|
2003-09-27 17:52:34 +00:00
|
|
|
{
|
|
|
|
void *retbuf = NULL;
|
|
|
|
int retlen = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Discard anything at the head of the rr queue with complete <
|
|
|
|
* 0; return the first thing with complete > 0.
|
|
|
|
*/
|
|
|
|
while (xfer->head && xfer->head->complete && !retbuf) {
|
2019-09-08 19:29:00 +00:00
|
|
|
struct req *rr = xfer->head;
|
2003-09-27 17:52:34 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (rr->complete > 0) {
|
|
|
|
retbuf = rr->buffer;
|
|
|
|
retlen = rr->retlen;
|
2003-09-27 17:52:34 +00:00
|
|
|
#ifdef DEBUG_DOWNLOAD
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("handing back data from read request %p\n", rr);
|
2003-09-27 17:52:34 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2003-09-27 17:52:34 +00:00
|
|
|
#ifdef DEBUG_DOWNLOAD
|
2019-09-08 19:29:00 +00:00
|
|
|
else
|
|
|
|
printf("skipping failed read request %p\n", rr);
|
2003-09-27 17:52:34 +00:00
|
|
|
#endif
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
xfer->head = xfer->head->next;
|
|
|
|
if (xfer->head)
|
|
|
|
xfer->head->prev = NULL;
|
|
|
|
else
|
|
|
|
xfer->tail = NULL;
|
|
|
|
xfer->req_totalsize -= rr->len;
|
|
|
|
sfree(rr);
|
2003-09-27 17:52:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (retbuf) {
|
2019-09-08 19:29:00 +00:00
|
|
|
*buf = retbuf;
|
|
|
|
*len = retlen;
|
|
|
|
return true;
|
2003-09-27 17:52:34 +00:00
|
|
|
} else
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2003-09-27 17:52:34 +00:00
|
|
|
}
|
|
|
|
|
2018-10-26 22:08:58 +00:00
|
|
|
struct fxp_xfer *xfer_upload_init(struct fxp_handle *fh, uint64_t offset)
|
2003-09-28 14:24:01 +00:00
|
|
|
{
|
|
|
|
struct fxp_xfer *xfer = xfer_init(fh, offset);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We set `eof' to 1 because this will cause xfer_done() to
|
|
|
|
* return true iff there are no outstanding requests. During an
|
|
|
|
* upload, our caller will be responsible for working out
|
|
|
|
* whether all the data has been sent, so all it needs to know
|
|
|
|
* from us is whether the outstanding requests have been
|
|
|
|
* handled once that's done.
|
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
xfer->eof = true;
|
2003-09-28 14:24:01 +00:00
|
|
|
|
|
|
|
return xfer;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool xfer_upload_ready(struct fxp_xfer *xfer)
|
2003-09-28 14:24:01 +00:00
|
|
|
{
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return sftp_sendbuffer() == 0;
|
2003-09-28 14:24:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void xfer_upload_data(struct fxp_xfer *xfer, char *buffer, int len)
|
|
|
|
{
|
|
|
|
struct req *rr;
|
|
|
|
struct sftp_request *req;
|
|
|
|
|
|
|
|
rr = snew(struct req);
|
|
|
|
rr->offset = xfer->offset;
|
|
|
|
rr->complete = 0;
|
|
|
|
if (xfer->tail) {
|
2019-09-08 19:29:00 +00:00
|
|
|
xfer->tail->next = rr;
|
|
|
|
rr->prev = xfer->tail;
|
2003-09-28 14:24:01 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
xfer->head = rr;
|
|
|
|
rr->prev = NULL;
|
2003-09-28 14:24:01 +00:00
|
|
|
}
|
|
|
|
xfer->tail = rr;
|
|
|
|
rr->next = NULL;
|
|
|
|
|
|
|
|
rr->len = len;
|
|
|
|
rr->buffer = NULL;
|
|
|
|
sftp_register(req = fxp_write_send(xfer->fh, buffer, rr->offset, len));
|
|
|
|
fxp_set_userdata(req, rr);
|
|
|
|
|
2018-10-26 22:08:58 +00:00
|
|
|
xfer->offset += rr->len;
|
2003-09-28 14:24:01 +00:00
|
|
|
xfer->req_totalsize += rr->len;
|
|
|
|
|
|
|
|
#ifdef DEBUG_UPLOAD
|
2018-10-26 22:08:58 +00:00
|
|
|
printf("queueing write request %p at %"PRIu64" [len %d]\n",
|
|
|
|
rr, rr->offset, len);
|
2003-09-28 14:24:01 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-07-11 17:24:53 +00:00
|
|
|
/*
|
|
|
|
* Returns INT_MIN to indicate that it didn't even get as far as
|
|
|
|
* fxp_write_recv and hence has not freed pktin.
|
|
|
|
*/
|
2003-09-28 14:24:01 +00:00
|
|
|
int xfer_upload_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
|
|
|
|
{
|
|
|
|
struct sftp_request *rreq;
|
|
|
|
struct req *rr, *prev, *next;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool ret;
|
2003-09-28 14:24:01 +00:00
|
|
|
|
|
|
|
rreq = sftp_find_request(pktin);
|
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]
2013-07-06 20:43:21 +00:00
|
|
|
if (!rreq)
|
2013-07-11 17:24:53 +00:00
|
|
|
return INT_MIN; /* this packet doesn't even make sense */
|
2003-09-28 14:24:01 +00:00
|
|
|
rr = (struct req *)fxp_get_userdata(rreq);
|
2013-07-11 17:24:53 +00:00
|
|
|
if (!rr) {
|
|
|
|
fxp_internal_error("request ID is not part of the current upload");
|
2019-09-08 19:29:00 +00:00
|
|
|
return INT_MIN; /* this packet isn't ours */
|
2013-07-11 17:24:53 +00:00
|
|
|
}
|
2003-09-28 14:24:01 +00:00
|
|
|
ret = fxp_write_recv(pktin, rreq);
|
|
|
|
#ifdef DEBUG_UPLOAD
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
printf("write request %p has returned [%d]\n", rr, ret ? 1 : 0);
|
2003-09-28 14:24:01 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove this one from the queue.
|
|
|
|
*/
|
|
|
|
prev = rr->prev;
|
|
|
|
next = rr->next;
|
|
|
|
if (prev)
|
2019-09-08 19:29:00 +00:00
|
|
|
prev->next = next;
|
2003-09-28 14:24:01 +00:00
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
xfer->head = next;
|
2003-09-28 14:24:01 +00:00
|
|
|
if (next)
|
2019-09-08 19:29:00 +00:00
|
|
|
next->prev = prev;
|
2003-09-28 14:24:01 +00:00
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
xfer->tail = prev;
|
2003-09-28 14:24:01 +00:00
|
|
|
xfer->req_totalsize -= rr->len;
|
|
|
|
sfree(rr);
|
|
|
|
|
|
|
|
if (!ret)
|
2019-09-08 19:29:00 +00:00
|
|
|
return -1;
|
2003-09-28 14:24:01 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2003-09-27 17:52:34 +00:00
|
|
|
void xfer_cleanup(struct fxp_xfer *xfer)
|
|
|
|
{
|
|
|
|
struct req *rr;
|
|
|
|
while (xfer->head) {
|
2019-09-08 19:29:00 +00:00
|
|
|
rr = xfer->head;
|
|
|
|
xfer->head = xfer->head->next;
|
|
|
|
sfree(rr->buffer);
|
|
|
|
sfree(rr);
|
2003-09-27 17:52:34 +00:00
|
|
|
}
|
|
|
|
sfree(xfer);
|
|
|
|
}
|