X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=sftp.c;h=832dd9487179307025e3b11f21778118c38cf56e;hb=f391d066de67fc172592d8dfd27902747fa3c833;hp=ff9e04312e6f4f5a09c3b1e3f156649073017679;hpb=3730ada5ce457468441b32d7e84157e481b8ba75;p=PuTTY.git diff --git a/sftp.c b/sftp.c index ff9e0431..832dd948 100644 --- a/sftp.c +++ b/sftp.c @@ -7,13 +7,10 @@ #include #include +#include "misc.h" #include "int64.h" #include "sftp.h" -#define smalloc malloc -#define srealloc realloc -#define sfree free - #define GET_32BIT(cp) \ (((unsigned long)(unsigned char)(cp)[0] << 24) | \ ((unsigned long)(unsigned char)(cp)[1] << 16) | \ @@ -33,6 +30,9 @@ struct sftp_packet { int type; }; +static const char *fxp_error_message; +static int fxp_errtype; + /* ---------------------------------------------------------------------- * SFTP packet construction functions. */ @@ -62,6 +62,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 +104,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 +260,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 +503,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