#include "tree234.h"
#include "sftp.h"
-#define GET_32BIT(cp) \
- (((unsigned long)(unsigned char)(cp)[0] << 24) | \
- ((unsigned long)(unsigned char)(cp)[1] << 16) | \
- ((unsigned long)(unsigned char)(cp)[2] << 8) | \
- ((unsigned long)(unsigned char)(cp)[3]))
-
-#define PUT_32BIT(cp, value) { \
- (cp)[0] = (unsigned char)((value) >> 24); \
- (cp)[1] = (unsigned char)((value) >> 16); \
- (cp)[2] = (unsigned char)((value) >> 8); \
- (cp)[3] = (unsigned char)(value); }
-
struct sftp_packet {
char *data;
unsigned length, maxlen;
*/
static void sftp_pkt_ensure(struct sftp_packet *pkt, int length)
{
- if (pkt->maxlen < length) {
+ if ((int)pkt->maxlen < length) {
pkt->maxlen = length + 256;
pkt->data = sresize(pkt->data, pkt->maxlen, char);
}
{
sftp_pkt_adddata(pkt, &byte, 1);
}
+static void sftp_pkt_adduint32(struct sftp_packet *pkt,
+ unsigned long value)
+{
+ unsigned char x[4];
+ PUT_32BIT(x, value);
+ sftp_pkt_adddata(pkt, x, 4);
+}
static struct sftp_packet *sftp_pkt_init(int pkt_type)
{
struct sftp_packet *pkt;
pkt->savedpos = -1;
pkt->length = 0;
pkt->maxlen = 0;
+ sftp_pkt_adduint32(pkt, 0); /* length field will be filled in later */
sftp_pkt_addbyte(pkt, (unsigned char) pkt_type);
return pkt;
}
sftp_pkt_adddata(pkt, &value, 1);
}
*/
-static void sftp_pkt_adduint32(struct sftp_packet *pkt,
- unsigned long value)
-{
- unsigned char x[4];
- PUT_32BIT(x, value);
- sftp_pkt_adddata(pkt, x, 4);
-}
static void sftp_pkt_adduint64(struct sftp_packet *pkt, uint64 value)
{
unsigned char x[8];
*p = NULL;
if (pkt->length - pkt->savedpos < 4)
return 0;
- *length = GET_32BIT(pkt->data + pkt->savedpos);
+ *length = toint(GET_32BIT(pkt->data + pkt->savedpos));
pkt->savedpos += 4;
- if (pkt->length - pkt->savedpos < *length || *length < 0) {
+ if ((int)(pkt->length - pkt->savedpos) < *length || *length < 0) {
*length = 0;
return 0;
}
int sftp_send(struct sftp_packet *pkt)
{
int ret;
- char x[4];
- PUT_32BIT(x, pkt->length);
- ret = (sftp_senddata(x, 4) && sftp_senddata(pkt->data, pkt->length));
+ PUT_32BIT(pkt->data, pkt->length - 4);
+ ret = sftp_senddata(pkt->data, pkt->length);
sftp_pkt_free(pkt);
return ret;
}
void sftp_cleanup_request(void)
{
- if (sftp_requests == NULL) {
+ if (sftp_requests != NULL) {
freetree234(sftp_requests);
sftp_requests = NULL;
}
if (!req || !req->registered) {
fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
return NULL;
}
/*
* Open a file.
*/
-struct sftp_request *fxp_open_send(char *path, int type)
+struct sftp_request *fxp_open_send(char *path, int type,
+ struct fxp_attrs *attrs)
{
struct sftp_request *req = sftp_alloc_request();
struct sftp_packet *pktout;
sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring(pktout, path);
sftp_pkt_adduint32(pktout, type);
- sftp_pkt_adduint32(pktout, 0); /* (FIXME) empty ATTRS structure */
+ if (attrs)
+ sftp_pkt_addattrs(pktout, *attrs);
+ else
+ sftp_pkt_adduint32(pktout, 0); /* empty ATTRS structure */
sftp_send(pktout);
return req;
ret = snew(struct fxp_names);
ret->nnames = i;
ret->names = snewn(ret->nnames, struct fxp_name);
- for (i = 0; i < ret->nnames; i++) {
+ for (i = 0; i < (unsigned long)ret->nnames; i++) {
char *str1, *str2;
int len1, len2;
if (!sftp_pkt_getstring(pktin, &str1, &len1) ||
xfer->offset = offset;
xfer->head = xfer->tail = NULL;
xfer->req_totalsize = 0;
- xfer->req_maxsize = 16384;
+ xfer->req_maxsize = 1048576;
xfer->err = 0;
xfer->filesize = uint64_make(ULONG_MAX, ULONG_MAX);
xfer->furthestdata = uint64_make(0, 0);
xfer->tail = rr;
rr->next = NULL;
- rr->len = 4096;
+ 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);
return xfer;
}
+/*
+ * Returns INT_MIN to indicate that it didn't even get as far as
+ * fxp_read_recv and hence has not freed pktin.
+ */
int xfer_download_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
{
struct sftp_request *rreq;
struct req *rr;
rreq = sftp_find_request(pktin);
+ if (!rreq)
+ return INT_MIN; /* this packet doesn't even make sense */
rr = (struct req *)fxp_get_userdata(rreq);
- if (!rr)
- return 0; /* this packet isn't ours */
+ if (!rr) {
+ fxp_internal_error("request ID is not part of the current download");
+ return INT_MIN; /* this packet isn't ours */
+ }
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
}
+/*
+ * Returns INT_MIN to indicate that it didn't even get as far as
+ * fxp_write_recv and hence has not freed pktin.
+ */
int xfer_upload_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
{
struct sftp_request *rreq;
int ret;
rreq = sftp_find_request(pktin);
+ if (!rreq)
+ return INT_MIN; /* this packet doesn't even make sense */
rr = (struct req *)fxp_get_userdata(rreq);
- if (!rr)
- return 0; /* this packet isn't ours */
+ if (!rr) {
+ fxp_internal_error("request ID is not part of the current upload");
+ return INT_MIN; /* this packet isn't ours */
+ }
ret = fxp_write_recv(pktin, rreq);
#ifdef DEBUG_UPLOAD
printf("write request %p has returned [%d]\n", rr, ret);