X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/32874aeac8dacbca26663777b39a79efc5d8dc4b..96f3c4a0baaa9231f6e28f742b64b6d7e5856d8c:/sftp.c diff --git a/sftp.c b/sftp.c index ff9e0431..99d50a70 100644 --- a/sftp.c +++ b/sftp.c @@ -33,6 +33,9 @@ struct sftp_packet { int type; }; +static const char *fxp_error_message; +static int fxp_errtype; + /* ---------------------------------------------------------------------- * SFTP packet construction functions. */ @@ -62,6 +65,7 @@ static struct sftp_packet *sftp_pkt_init(int pkt_type) pkt->length = 0; pkt->maxlen = 0; sftp_pkt_addbyte(pkt, (unsigned char) pkt_type); + fxp_error_message = NULL; return pkt; } static void sftp_pkt_addbool(struct sftp_packet *pkt, unsigned char value) @@ -103,6 +107,31 @@ static void sftp_pkt_addstring(struct sftp_packet *pkt, char *data) sftp_pkt_addstring_start(pkt); sftp_pkt_addstring_str(pkt, data); } +static void sftp_pkt_addattrs(struct sftp_packet *pkt, struct fxp_attrs attrs) +{ + sftp_pkt_adduint32(pkt, attrs.flags); + if (attrs.flags & SSH_FILEXFER_ATTR_SIZE) { + sftp_pkt_adduint32(pkt, attrs.size.hi); + sftp_pkt_adduint32(pkt, attrs.size.lo); + } + if (attrs.flags & SSH_FILEXFER_ATTR_UIDGID) { + sftp_pkt_adduint32(pkt, attrs.uid); + sftp_pkt_adduint32(pkt, attrs.gid); + } + if (attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) { + sftp_pkt_adduint32(pkt, attrs.permissions); + } + if (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME) { + sftp_pkt_adduint32(pkt, attrs.atime); + sftp_pkt_adduint32(pkt, attrs.mtime); + } + if (attrs.flags & SSH_FILEXFER_ATTR_EXTENDED) { + /* + * We currently don't support sending any extended + * attributes. + */ + } +} /* ---------------------------------------------------------------------- * SFTP packet decode functions. @@ -234,9 +263,6 @@ static char *mkstr(char *s, int len) * SFTP primitives. */ -static const char *fxp_error_message; -static int fxp_errtype; - /* * 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). @@ -480,6 +506,200 @@ void fxp_close(struct fxp_handle *handle) sfree(handle); } +int fxp_mkdir(char *path) +{ + struct sftp_packet *pktin, *pktout; + int id; + + pktout = sftp_pkt_init(SSH_FXP_MKDIR); + sftp_pkt_adduint32(pktout, 0x234); /* request id */ + sftp_pkt_addstring(pktout, path); + sftp_pkt_adduint32(pktout, 0); /* (FIXME) empty ATTRS structure */ + sftp_send(pktout); + pktin = sftp_recv(); + id = sftp_pkt_getuint32(pktin); + if (id != 0x234) { + fxp_internal_error("request ID mismatch\n"); + return 0; + } + id = fxp_got_status(pktin); + if (id != 1) { + return 0; + } + return 1; +} + +int fxp_rmdir(char *path) +{ + struct sftp_packet *pktin, *pktout; + int id; + + pktout = sftp_pkt_init(SSH_FXP_RMDIR); + sftp_pkt_adduint32(pktout, 0x345); /* request id */ + sftp_pkt_addstring(pktout, path); + sftp_send(pktout); + pktin = sftp_recv(); + id = sftp_pkt_getuint32(pktin); + if (id != 0x345) { + fxp_internal_error("request ID mismatch\n"); + return 0; + } + id = fxp_got_status(pktin); + if (id != 1) { + return 0; + } + return 1; +} + +int fxp_remove(char *fname) +{ + struct sftp_packet *pktin, *pktout; + int id; + + pktout = sftp_pkt_init(SSH_FXP_REMOVE); + sftp_pkt_adduint32(pktout, 0x678); /* request id */ + sftp_pkt_addstring(pktout, fname); + sftp_send(pktout); + pktin = sftp_recv(); + id = sftp_pkt_getuint32(pktin); + if (id != 0x678) { + fxp_internal_error("request ID mismatch\n"); + return 0; + } + id = fxp_got_status(pktin); + if (id != 1) { + return 0; + } + return 1; +} + +int fxp_rename(char *srcfname, char *dstfname) +{ + struct sftp_packet *pktin, *pktout; + int id; + + pktout = sftp_pkt_init(SSH_FXP_RENAME); + sftp_pkt_adduint32(pktout, 0x678); /* request id */ + sftp_pkt_addstring(pktout, srcfname); + sftp_pkt_addstring(pktout, dstfname); + sftp_send(pktout); + pktin = sftp_recv(); + id = sftp_pkt_getuint32(pktin); + if (id != 0x678) { + fxp_internal_error("request ID mismatch\n"); + return 0; + } + id = fxp_got_status(pktin); + if (id != 1) { + return 0; + } + return 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_packet *pktin, *pktout; + int id; + + pktout = sftp_pkt_init(SSH_FXP_STAT); + sftp_pkt_adduint32(pktout, 0x678); /* request id */ + sftp_pkt_addstring(pktout, fname); + sftp_send(pktout); + pktin = sftp_recv(); + id = sftp_pkt_getuint32(pktin); + if (id != 0x678) { + fxp_internal_error("request ID mismatch\n"); + return 0; + } + + if (pktin->type == SSH_FXP_ATTRS) { + *attrs = sftp_pkt_getattrs(pktin); + return 1; + } else { + fxp_got_status(pktin); + return 0; + } +} + +int fxp_fstat(struct fxp_handle *handle, struct fxp_attrs *attrs) +{ + struct sftp_packet *pktin, *pktout; + int id; + + pktout = sftp_pkt_init(SSH_FXP_FSTAT); + sftp_pkt_adduint32(pktout, 0x678); /* request id */ + sftp_pkt_addstring_start(pktout); + sftp_pkt_addstring_data(pktout, handle->hstring, handle->hlen); + sftp_send(pktout); + pktin = sftp_recv(); + id = sftp_pkt_getuint32(pktin); + if (id != 0x678) { + fxp_internal_error("request ID mismatch\n"); + return 0; + } + + if (pktin->type == SSH_FXP_ATTRS) { + *attrs = sftp_pkt_getattrs(pktin); + return 1; + } else { + fxp_got_status(pktin); + return 0; + } +} + +/* + * Set the attributes of a file. + */ +int fxp_setstat(char *fname, struct fxp_attrs attrs) +{ + struct sftp_packet *pktin, *pktout; + int id; + + pktout = sftp_pkt_init(SSH_FXP_SETSTAT); + sftp_pkt_adduint32(pktout, 0x678); /* request id */ + sftp_pkt_addstring(pktout, fname); + sftp_pkt_addattrs(pktout, attrs); + sftp_send(pktout); + pktin = sftp_recv(); + id = sftp_pkt_getuint32(pktin); + if (id != 0x678) { + fxp_internal_error("request ID mismatch\n"); + return 0; + } + id = fxp_got_status(pktin); + if (id != 1) { + return 0; + } + return 1; +} +int fxp_fsetstat(struct fxp_handle *handle, struct fxp_attrs attrs) +{ + struct sftp_packet *pktin, *pktout; + int id; + + pktout = sftp_pkt_init(SSH_FXP_FSETSTAT); + sftp_pkt_adduint32(pktout, 0x678); /* request 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(); + id = sftp_pkt_getuint32(pktin); + if (id != 0x678) { + fxp_internal_error("request ID mismatch\n"); + return 0; + } + id = fxp_got_status(pktin); + if (id != 1) { + return 0; + } + return 1; +} + /* * 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