#include "misc.h"
#include "int64.h"
+#include "tree234.h"
#include "sftp.h"
#define GET_32BIT(cp) \
static const char *fxp_error_message;
static int fxp_errtype;
+static void fxp_internal_error(char *msg);
+
/* ----------------------------------------------------------------------
* SFTP packet construction functions.
*/
{
if (pkt->maxlen < length) {
pkt->maxlen = length + 256;
- pkt->data = srealloc(pkt->data, pkt->maxlen);
+ pkt->data = sresize(pkt->data, pkt->maxlen, char);
}
}
static void sftp_pkt_adddata(struct sftp_packet *pkt, void *data, int len)
static struct sftp_packet *sftp_pkt_init(int pkt_type)
{
struct sftp_packet *pkt;
- pkt = smalloc(sizeof(struct sftp_packet));
+ pkt = snew(struct sftp_packet);
pkt->data = NULL;
pkt->savedpos = -1;
pkt->length = 0;
sftp_pkt_addbyte(pkt, (unsigned char) pkt_type);
return pkt;
}
+/*
static void sftp_pkt_addbool(struct sftp_packet *pkt, unsigned char value)
{
sftp_pkt_adddata(pkt, &value, 1);
}
+*/
static void sftp_pkt_adduint32(struct sftp_packet *pkt,
unsigned long value)
{
if (!sftp_recvdata(x, 4))
return NULL;
- pkt = smalloc(sizeof(struct sftp_packet));
+ pkt = snew(struct sftp_packet);
pkt->savedpos = 0;
pkt->length = pkt->maxlen = GET_32BIT(x);
- pkt->data = smalloc(pkt->length);
+ pkt->data = snewn(pkt->length, char);
if (!sftp_recvdata(pkt->data, pkt->length)) {
sftp_pkt_free(pkt);
}
/* ----------------------------------------------------------------------
+ * Request ID allocation and temporary dispatch routines.
+ */
+
+#define REQUEST_ID_OFFSET 256
+
+struct sftp_request {
+ unsigned id;
+ int registered;
+};
+
+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)
+ return -1;
+ if (a->id > b->id)
+ return +1;
+ 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)
+ return -1;
+ if (*a > b->id)
+ return +1;
+ 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)
+ sftp_requests = newtree234(sftp_reqcmp);
+
+ /*
+ * 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
+ * REQUEST_ID_OFFSET.)
+ */
+ tsize = count234(sftp_requests);
+
+ low = -1;
+ high = tsize;
+ while (high - low > 1) {
+ 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 */
+ }
+ /*
+ * Now low points to either -1, or the tree index of the
+ * largest ID in the initial sequence.
+ */
+ {
+ unsigned i = low + 1 + REQUEST_ID_OFFSET;
+ assert(NULL == find234(sftp_requests, &i, sftp_reqfind));
+ }
+
+ /*
+ * 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;
+ r->registered = 0;
+ add234(sftp_requests, r);
+ return r;
+}
+
+void sftp_register(struct sftp_request *req)
+{
+ req->registered = 1;
+}
+
+struct sftp_request *sftp_find_request(struct sftp_packet *pktin)
+{
+ unsigned long id;
+ struct sftp_request *req;
+
+ if (!pktin) {
+ fxp_internal_error("did not receive a valid SFTP packet\n");
+ return NULL;
+ }
+
+ id = sftp_pkt_getuint32(pktin);
+ req = find234(sftp_requests, &id, sftp_reqfind);
+
+ if (!req || !req->registered) {
+ fxp_internal_error("request ID mismatch\n");
+ sftp_pkt_free(pktin);
+ return NULL;
+ }
+
+ del234(sftp_requests, req);
+
+ return req;
+}
+
+/* ----------------------------------------------------------------------
* String handling routines.
*/
static char *mkstr(char *s, int len)
{
- char *p = smalloc(len + 1);
+ char *p = snewn(len + 1, char);
memcpy(p, s, len);
p[len] = '\0';
return p;
/*
* Canonify a pathname.
*/
-char *fxp_realpath(char *path)
+struct sftp_request *fxp_realpath_send(char *path)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_REALPATH);
- sftp_pkt_adduint32(pktout, 0x123); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring_start(pktout);
sftp_pkt_addstring_str(pktout, path);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return NULL;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0x123) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return NULL;
- }
+
+ return req;
+}
+
+char *fxp_realpath_recv(struct sftp_packet *pktin, struct sftp_request *req)
+{
+ sfree(req);
+
if (pktin->type == SSH_FXP_NAME) {
int count;
char *path;
/*
* Open a file.
*/
-struct fxp_handle *fxp_open(char *path, int type)
+struct sftp_request *fxp_open_send(char *path, int type)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_OPEN);
- sftp_pkt_adduint32(pktout, 0x567); /* request id */
+ 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 */
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return NULL;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0x567) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return NULL;
- }
+
+ return req;
+}
+
+struct fxp_handle *fxp_open_recv(struct sftp_packet *pktin,
+ struct sftp_request *req)
+{
+ sfree(req);
+
if (pktin->type == SSH_FXP_HANDLE) {
char *hstring;
struct fxp_handle *handle;
sftp_pkt_free(pktin);
return NULL;
}
- handle = smalloc(sizeof(struct fxp_handle));
+ handle = snew(struct fxp_handle);
handle->hstring = mkstr(hstring, len);
handle->hlen = len;
sftp_pkt_free(pktin);
/*
* Open a directory.
*/
-struct fxp_handle *fxp_opendir(char *path)
+struct sftp_request *fxp_opendir_send(char *path)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_OPENDIR);
- sftp_pkt_adduint32(pktout, 0x456); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring(pktout, path);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return NULL;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0x456) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return NULL;
- }
+
+ return req;
+}
+
+struct fxp_handle *fxp_opendir_recv(struct sftp_packet *pktin,
+ struct sftp_request *req)
+{
+ sfree(req);
if (pktin->type == SSH_FXP_HANDLE) {
char *hstring;
struct fxp_handle *handle;
sftp_pkt_free(pktin);
return NULL;
}
- handle = smalloc(sizeof(struct fxp_handle));
+ handle = snew(struct fxp_handle);
handle->hstring = mkstr(hstring, len);
handle->hlen = len;
sftp_pkt_free(pktin);
/*
* Close a file/dir.
*/
-void fxp_close(struct fxp_handle *handle)
+struct sftp_request *fxp_close_send(struct fxp_handle *handle)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_CLOSE);
- sftp_pkt_adduint32(pktout, 0x789); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring_start(pktout);
sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0x789) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return;
- }
- fxp_got_status(pktin);
- sftp_pkt_free(pktin);
+
sfree(handle->hstring);
sfree(handle);
+
+ return req;
}
-int fxp_mkdir(char *path)
+void fxp_close_recv(struct sftp_packet *pktin, struct sftp_request *req)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ sfree(req);
+ fxp_got_status(pktin);
+ sftp_pkt_free(pktin);
+}
+
+struct sftp_request *fxp_mkdir_send(char *path)
+{
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_MKDIR);
- sftp_pkt_adduint32(pktout, 0x234); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring(pktout, path);
sftp_pkt_adduint32(pktout, 0); /* (FIXME) empty ATTRS structure */
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return 0;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0x234) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return 0;
- }
+
+ return req;
+}
+
+int fxp_mkdir_recv(struct sftp_packet *pktin, struct sftp_request *req)
+{
+ int id;
+ sfree(req);
id = fxp_got_status(pktin);
sftp_pkt_free(pktin);
if (id != 1) {
return 1;
}
-int fxp_rmdir(char *path)
+struct sftp_request *fxp_rmdir_send(char *path)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_RMDIR);
- sftp_pkt_adduint32(pktout, 0x345); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring(pktout, path);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return 0;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0x345) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return 0;
- }
+
+ return req;
+}
+
+int fxp_rmdir_recv(struct sftp_packet *pktin, struct sftp_request *req)
+{
+ int id;
+ sfree(req);
id = fxp_got_status(pktin);
sftp_pkt_free(pktin);
if (id != 1) {
return 1;
}
-int fxp_remove(char *fname)
+struct sftp_request *fxp_remove_send(char *fname)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_REMOVE);
- sftp_pkt_adduint32(pktout, 0x678); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring(pktout, fname);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return 0;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0x678) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return 0;
- }
+
+ return req;
+}
+
+int fxp_remove_recv(struct sftp_packet *pktin, struct sftp_request *req)
+{
+ int id;
+ sfree(req);
id = fxp_got_status(pktin);
sftp_pkt_free(pktin);
if (id != 1) {
return 1;
}
-int fxp_rename(char *srcfname, char *dstfname)
+struct sftp_request *fxp_rename_send(char *srcfname, char *dstfname)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_RENAME);
- sftp_pkt_adduint32(pktout, 0x678); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring(pktout, srcfname);
sftp_pkt_addstring(pktout, dstfname);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return 0;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0x678) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return 0;
- }
+
+ return req;
+}
+
+int fxp_rename_recv(struct sftp_packet *pktin, struct sftp_request *req)
+{
+ int id;
+ sfree(req);
id = fxp_got_status(pktin);
sftp_pkt_free(pktin);
if (id != 1) {
* Retrieve the attributes of a file. We have fxp_stat which works
* on filenames, and fxp_fstat which works on open file handles.
*/
-int fxp_stat(char *fname, struct fxp_attrs *attrs)
+struct sftp_request *fxp_stat_send(char *fname)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_STAT);
- sftp_pkt_adduint32(pktout, 0x678); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring(pktout, fname);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return 0;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0x678) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return 0;
- }
+ return req;
+}
+
+int fxp_stat_recv(struct sftp_packet *pktin, struct sftp_request *req,
+ struct fxp_attrs *attrs)
+{
+ sfree(req);
if (pktin->type == SSH_FXP_ATTRS) {
*attrs = sftp_pkt_getattrs(pktin);
sftp_pkt_free(pktin);
}
}
-int fxp_fstat(struct fxp_handle *handle, struct fxp_attrs *attrs)
+struct sftp_request *fxp_fstat_send(struct fxp_handle *handle)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_FSTAT);
- sftp_pkt_adduint32(pktout, 0x678); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring_start(pktout);
sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return 0;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0x678) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return 0;
- }
+ return req;
+}
+
+int fxp_fstat_recv(struct sftp_packet *pktin, struct sftp_request *req,
+ struct fxp_attrs *attrs)
+{
+ sfree(req);
if (pktin->type == SSH_FXP_ATTRS) {
*attrs = sftp_pkt_getattrs(pktin);
sftp_pkt_free(pktin);
/*
* Set the attributes of a file.
*/
-int fxp_setstat(char *fname, struct fxp_attrs attrs)
+struct sftp_request *fxp_setstat_send(char *fname, struct fxp_attrs attrs)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_SETSTAT);
- sftp_pkt_adduint32(pktout, 0x678); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring(pktout, fname);
sftp_pkt_addattrs(pktout, attrs);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return 0;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0x678) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return 0;
- }
+
+ return req;
+}
+
+int fxp_setstat_recv(struct sftp_packet *pktin, struct sftp_request *req)
+{
+ int id;
+ sfree(req);
id = fxp_got_status(pktin);
sftp_pkt_free(pktin);
if (id != 1) {
}
return 1;
}
-int fxp_fsetstat(struct fxp_handle *handle, struct fxp_attrs attrs)
+
+struct sftp_request *fxp_fsetstat_send(struct fxp_handle *handle,
+ struct fxp_attrs attrs)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_FSETSTAT);
- sftp_pkt_adduint32(pktout, 0x678); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring_start(pktout);
sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
sftp_pkt_addattrs(pktout, attrs);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return 0;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0x678) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return 0;
- }
+
+ return req;
+}
+
+int fxp_fsetstat_recv(struct sftp_packet *pktin, struct sftp_request *req)
+{
+ int id;
+ sfree(req);
id = fxp_got_status(pktin);
sftp_pkt_free(pktin);
if (id != 1) {
* 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.)
*/
-int fxp_read(struct fxp_handle *handle, char *buffer, uint64 offset,
- int len)
+struct sftp_request *fxp_read_send(struct fxp_handle *handle,
+ uint64 offset, int len)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_READ);
- sftp_pkt_adduint32(pktout, 0xBCD); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring_start(pktout);
sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
sftp_pkt_adduint64(pktout, offset);
sftp_pkt_adduint32(pktout, len);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return -1;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0xBCD) {
- fxp_internal_error("request ID mismatch");
- sftp_pkt_free(pktin);
- return -1;
- }
+
+ return req;
+}
+
+int fxp_read_recv(struct sftp_packet *pktin, struct sftp_request *req,
+ char *buffer, int len)
+{
+ sfree(req);
if (pktin->type == SSH_FXP_DATA) {
char *str;
int rlen;
/*
* Read from a directory.
*/
-struct fxp_names *fxp_readdir(struct fxp_handle *handle)
+struct sftp_request *fxp_readdir_send(struct fxp_handle *handle)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_READDIR);
- sftp_pkt_adduint32(pktout, 0xABC); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring_start(pktout);
sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return NULL;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0xABC) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return NULL;
- }
+
+ return req;
+}
+
+struct fxp_names *fxp_readdir_recv(struct sftp_packet *pktin,
+ struct sftp_request *req)
+{
+ sfree(req);
if (pktin->type == SSH_FXP_NAME) {
struct fxp_names *ret;
int i;
- ret = smalloc(sizeof(struct fxp_names));
+ ret = snew(struct fxp_names);
ret->nnames = sftp_pkt_getuint32(pktin);
- ret->names = smalloc(ret->nnames * sizeof(struct fxp_name));
+ ret->names = snewn(ret->nnames, struct fxp_name);
for (i = 0; i < ret->nnames; i++) {
char *str;
int len;
/*
* Write to a file. Returns 0 on error, 1 on OK.
*/
-int fxp_write(struct fxp_handle *handle, char *buffer, uint64 offset,
- int len)
+struct sftp_request *fxp_write_send(struct fxp_handle *handle,
+ char *buffer, uint64 offset, int len)
{
- struct sftp_packet *pktin, *pktout;
- int id;
+ struct sftp_request *req = sftp_alloc_request();
+ struct sftp_packet *pktout;
pktout = sftp_pkt_init(SSH_FXP_WRITE);
- sftp_pkt_adduint32(pktout, 0xDCB); /* request id */
+ sftp_pkt_adduint32(pktout, req->id);
sftp_pkt_addstring_start(pktout);
sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen);
sftp_pkt_adduint64(pktout, offset);
sftp_pkt_addstring_start(pktout);
sftp_pkt_addstring_data(pktout, buffer, len);
sftp_send(pktout);
- pktin = sftp_recv();
- if (!pktin) {
- fxp_internal_error("did not receive a valid SFTP packet\n");
- return 0;
- }
- id = sftp_pkt_getuint32(pktin);
- if (id != 0xDCB) {
- fxp_internal_error("request ID mismatch\n");
- sftp_pkt_free(pktin);
- return 0;
- }
+
+ return req;
+}
+
+int fxp_write_recv(struct sftp_packet *pktin, struct sftp_request *req)
+{
+ sfree(req);
fxp_got_status(pktin);
sftp_pkt_free(pktin);
return fxp_errtype == SSH_FX_OK;
sfree(names->names);
sfree(names);
}
+
+/*
+ * Duplicate an fxp_name structure.
+ */
+struct fxp_name *fxp_dup_name(struct fxp_name *name)
+{
+ struct fxp_name *ret;
+ ret = snew(struct fxp_name);
+ ret->filename = dupstr(name->filename);
+ ret->longname = dupstr(name->longname);
+ ret->attrs = name->attrs; /* structure copy */
+ return ret;
+}
+
+/*
+ * Free up an fxp_name structure.
+ */
+void fxp_free_name(struct fxp_name *name)
+{
+ sfree(name->filename);
+ sfree(name->longname);
+ sfree(name);
+}