X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/c229ef97dfba4dee7d2fc0a098e0343dc87dc004..1bc24185fa9eb390d005d9655be64b33c4a2287b:/scp.c diff --git a/scp.c b/scp.c index 9dda0672..f146bd77 100644 --- a/scp.c +++ b/scp.c @@ -101,6 +101,7 @@ static int using_sftp = 0; static Backend *back; static void *backhandle; +static Config cfg; static void source(char *src); static void rsource(char *src); @@ -304,6 +305,16 @@ char *do_select(SOCKET skt, int startup) extern int select_result(WPARAM, LPARAM); /* + * In pscp, all agent requests should be synchronous, so this is a + * never-called stub. + */ +void agent_schedule_callback(void (*callback)(void *, void *, int), + void *callback_ctx, void *data, int len) +{ + assert(!"We shouldn't be here"); +} + +/* * Receive a block of data from the SSH link. Block until all data * is available. * @@ -316,7 +327,7 @@ static unsigned char *outptr; /* where to put the data */ static unsigned outlen; /* how much data required */ static unsigned char *pending = NULL; /* any spare data */ static unsigned pendlen = 0, pendsize = 0; /* length and phys. size of buffer */ -int from_backend(void *frontend, int is_stderr, char *data, int datalen) +int from_backend(void *frontend, int is_stderr, const char *data, int datalen) { unsigned char *p = (unsigned char *) data; unsigned len = (unsigned) datalen; @@ -352,8 +363,7 @@ int from_backend(void *frontend, int is_stderr, char *data, int datalen) if (len > 0) { if (pendsize < pendlen + len) { pendsize = pendlen + len + 4096; - pending = (pending ? srealloc(pending, pendsize) : - smalloc(pendsize)); + pending = sresize(pending, pendsize, unsigned char); if (!pending) fatalbox("Out of memory"); } @@ -425,6 +435,12 @@ static void ssh_scp_init(void) select_result((WPARAM) scp_ssh_socket, (LPARAM) FD_READ); } using_sftp = !ssh_fallback_cmd(backhandle); + if (verbose) { + if (using_sftp) + tell_user(stderr, "Using SFTP"); + else + tell_user(stderr, "Using SCP1"); + } } /* @@ -466,7 +482,8 @@ static void bump(char *fmt, ...) */ static void do_cmd(char *host, char *user, char *cmd) { - char *err, *realhost; + const char *err; + char *realhost; DWORD namelen; if (host == NULL || host[0] == '\0') @@ -544,7 +561,7 @@ static void do_cmd(char *host, char *user, char *cmd) namelen = 0; if (GetUserName(user, &namelen) == FALSE) bump("Empty user name"); - user = smalloc(namelen * sizeof(char)); + user = snewn(namelen, char); GetUserName(user, &namelen); if (verbose) tell_user(stderr, "Guessing user name: %s", user); @@ -579,6 +596,7 @@ static void do_cmd(char *host, char *user, char *cmd) bump("ssh_init: %s", err); logctx = log_init(NULL, &cfg); back->provide_logctx(backhandle, logctx); + console_provide_logctx(logctx); ssh_scp_init(); if (verbose && realhost != NULL) tell_user(stderr, "Connected to %s\n", realhost); @@ -741,6 +759,8 @@ void scp_sftp_listdir(char *dirname) struct fxp_handle *dirh; struct fxp_names *names; struct fxp_name *ournames; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; int nnames, namesize; int i; @@ -752,7 +772,11 @@ void scp_sftp_listdir(char *dirname) printf("Listing directory %s\n", dirname); - dirh = fxp_opendir(dirname); + sftp_register(req = fxp_opendir_send(dirname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + dirh = fxp_opendir_recv(pktin); + if (dirh == NULL) { printf("Unable to open %s: %s\n", dirname, fxp_error()); } else { @@ -761,7 +785,11 @@ void scp_sftp_listdir(char *dirname) while (1) { - names = fxp_readdir(dirh); + sftp_register(req = fxp_readdir_send(dirh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + names = fxp_readdir_recv(pktin); + if (names == NULL) { if (fxp_error_type() == SSH_FX_EOF) break; @@ -775,8 +803,7 @@ void scp_sftp_listdir(char *dirname) if (nnames + names->nnames >= namesize) { namesize += names->nnames + 128; - ournames = - srealloc(ournames, namesize * sizeof(*ournames)); + ournames = sresize(ournames, namesize, struct fxp_name); } for (i = 0; i < names->nnames; i++) @@ -785,7 +812,10 @@ void scp_sftp_listdir(char *dirname) names->nnames = 0; /* prevent free_names */ fxp_free_names(names); } - fxp_close(dirh); + sftp_register(req = fxp_close_send(dirh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin); /* * Now we have our filenames. Sort them by actual file @@ -830,7 +860,10 @@ void scp_source_setup(char *target, int shouldbedir) * Find out whether the target filespec is in fact a * directory. */ + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; struct fxp_attrs attrs; + int ret; if (!fxp_init()) { tell_user(stderr, "unable to initialise SFTP: %s", fxp_error()); @@ -838,8 +871,12 @@ void scp_source_setup(char *target, int shouldbedir) return; } - if (!fxp_stat(target, &attrs) || - !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) + sftp_register(req = fxp_stat_send(target)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + ret = fxp_stat_recv(pktin, &attrs); + + if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) scp_sftp_targetisdir = 0; else scp_sftp_targetisdir = (attrs.permissions & 0040000) != 0; @@ -886,13 +923,21 @@ int scp_send_filename(char *name, unsigned long size, int modes) { if (using_sftp) { char *fullname; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; + if (scp_sftp_targetisdir) { fullname = dupcat(scp_sftp_remotepath, "/", name, NULL); } else { fullname = dupstr(scp_sftp_remotepath); } - scp_sftp_filehandle = - fxp_open(fullname, SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC); + + sftp_register(req = fxp_open_send(fullname, SSH_FXF_WRITE | + SSH_FXF_CREAT | SSH_FXF_TRUNC)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + scp_sftp_filehandle = fxp_open_recv(pktin); + if (!scp_sftp_filehandle) { tell_user(stderr, "pscp: unable to open %s: %s", fullname, fxp_error()); @@ -915,10 +960,21 @@ int scp_send_filename(char *name, unsigned long size, int modes) int scp_send_filedata(char *data, int len) { if (using_sftp) { + int ret; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; + if (!scp_sftp_filehandle) { return 1; } - if (!fxp_write(scp_sftp_filehandle, data, scp_sftp_fileoffset, len)) { + + sftp_register(req = fxp_write_send(scp_sftp_filehandle, + data, scp_sftp_fileoffset, len)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + ret = fxp_write_recv(pktin); + + if (!ret) { tell_user(stderr, "error while writing: %s\n", fxp_error()); errs++; return 1; @@ -948,6 +1004,10 @@ int scp_send_finish(void) { if (using_sftp) { struct fxp_attrs attrs; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; + int ret; + if (!scp_sftp_filehandle) { return 1; } @@ -955,12 +1015,19 @@ int scp_send_finish(void) attrs.flags = SSH_FILEXFER_ATTR_ACMODTIME; attrs.atime = scp_sftp_atime; attrs.mtime = scp_sftp_mtime; - if (!fxp_fsetstat(scp_sftp_filehandle, attrs)) { + sftp_register(req = fxp_fsetstat_send(scp_sftp_filehandle, attrs)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + ret = fxp_fsetstat_recv(pktin); + if (!ret) { tell_user(stderr, "unable to set file times: %s\n", fxp_error()); errs++; } } - fxp_close(scp_sftp_filehandle); + sftp_register(req = fxp_close_send(scp_sftp_filehandle)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin); scp_has_times = 0; return 0; } else { @@ -989,6 +1056,10 @@ int scp_send_dirname(char *name, int modes) char *fullname; char const *err; struct fxp_attrs attrs; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; + int ret; + if (scp_sftp_targetisdir) { fullname = dupcat(scp_sftp_remotepath, "/", name, NULL); } else { @@ -1002,12 +1073,22 @@ int scp_send_dirname(char *name, int modes) * exists and is a directory we will assume we were either * successful or it didn't matter. */ - if (!fxp_mkdir(fullname)) + sftp_register(req = fxp_mkdir_send(fullname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + ret = fxp_mkdir_recv(pktin); + + if (!ret) err = fxp_error(); else err = "server reported no error"; - if (!fxp_stat(fullname, &attrs) || - !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) || + + sftp_register(req = fxp_stat_send(fullname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + ret = fxp_stat_recv(pktin, &attrs); + + if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) || !(attrs.permissions & 0040000)) { tell_user(stderr, "unable to create directory %s: %s", fullname, err); @@ -1062,7 +1143,7 @@ int scp_sink_setup(char *source, int preserve, int recursive) * wildcardness comes before the final slash) and arrange * things so that a dirstack entry will be set up. */ - newsource = smalloc(1+strlen(source)); + newsource = snewn(1+strlen(source), char); if (!wc_unescape(newsource, source)) { /* Yes, here we go; it's a wildcard. Bah. */ char *dupsource, *lastpart, *dirpart, *wildcard; @@ -1095,7 +1176,7 @@ int scp_sink_setup(char *source, int preserve, int recursive) * wildcard escapes from the directory part, throwing * an error if it contains a real wildcard. */ - dirpart = smalloc(1+strlen(dupsource)); + dirpart = snewn(1+strlen(dupsource), char); if (!wc_unescape(dirpart, dupsource)) { tell_user(stderr, "%s: multiple-level wildcards unsupported", source); @@ -1154,6 +1235,8 @@ int scp_get_sink_action(struct scp_sink_action *act) char *fname; int must_free_fname; struct fxp_attrs attrs; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; int ret; if (!scp_sftp_dirstack_head) { @@ -1222,7 +1305,11 @@ int scp_get_sink_action(struct scp_sink_action *act) * Now we have a filename. Stat it, and see if it's a file * or a directory. */ - ret = fxp_stat(fname, &attrs); + sftp_register(req = fxp_stat_send(fname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + ret = fxp_stat_recv(pktin, &attrs); + if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) { tell_user(stderr, "unable to identify %s: %s", fname, ret ? "file type not supplied" : fxp_error()); @@ -1274,7 +1361,11 @@ int scp_get_sink_action(struct scp_sink_action *act) * list), we must push the other (target,namelist) pair * on a stack. */ - dirhandle = fxp_opendir(fname); + sftp_register(req = fxp_opendir_send(fname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + dirhandle = fxp_opendir_recv(pktin); + if (!dirhandle) { tell_user(stderr, "scp: unable to open directory %s: %s", fname, fxp_error()); @@ -1287,7 +1378,11 @@ int scp_get_sink_action(struct scp_sink_action *act) while (1) { int i; - names = fxp_readdir(dirhandle); + sftp_register(req = fxp_readdir_send(dirhandle)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + names = fxp_readdir_recv(pktin); + if (names == NULL) { if (fxp_error_type() == SSH_FX_EOF) break; @@ -1304,17 +1399,19 @@ int scp_get_sink_action(struct scp_sink_action *act) } if (nnames + names->nnames >= namesize) { namesize += names->nnames + 128; - ournames = - srealloc(ournames, namesize * sizeof(*ournames)); + ournames = sresize(ournames, namesize, struct fxp_name); } for (i = 0; i < names->nnames; i++) ournames[nnames++] = names->names[i]; names->nnames = 0; /* prevent free_names */ fxp_free_names(names); } - fxp_close(dirhandle); + sftp_register(req = fxp_close_send(dirhandle)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin); - newitem = smalloc(sizeof(struct scp_sftp_dirstack)); + newitem = snew(struct scp_sftp_dirstack); newitem->next = scp_sftp_dirstack_head; newitem->names = ournames; newitem->namepos = 0; @@ -1402,7 +1499,7 @@ int scp_get_sink_action(struct scp_sink_action *act) bump("Lost connection"); if (i >= bufsize) { bufsize = i + 128; - act->buf = srealloc(act->buf, bufsize); + act->buf = sresize(act->buf, bufsize, char); } act->buf[i++] = ch; } while (ch != '\n'); @@ -1454,8 +1551,14 @@ int scp_get_sink_action(struct scp_sink_action *act) int scp_accept_filexfer(void) { if (using_sftp) { - scp_sftp_filehandle = - fxp_open(scp_sftp_currentname, SSH_FXF_READ); + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; + + sftp_register(req = fxp_open_send(scp_sftp_currentname, SSH_FXF_READ)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + scp_sftp_filehandle = fxp_open_recv(pktin); + if (!scp_sftp_filehandle) { tell_user(stderr, "pscp: unable to open %s: %s", scp_sftp_currentname, fxp_error()); @@ -1474,8 +1577,16 @@ int scp_accept_filexfer(void) int scp_recv_filedata(char *data, int len) { if (using_sftp) { - int actuallen = fxp_read(scp_sftp_filehandle, data, - scp_sftp_fileoffset, len); + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; + int actuallen; + + sftp_register(req = fxp_read_send(scp_sftp_filehandle, + scp_sftp_fileoffset, len)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + actuallen = fxp_read_recv(pktin, data, len); + if (actuallen == -1 && fxp_error_type() != SSH_FX_EOF) { tell_user(stderr, "pscp: error while reading: %s", fxp_error()); errs++; @@ -1495,7 +1606,13 @@ int scp_recv_filedata(char *data, int len) int scp_finish_filerecv(void) { if (using_sftp) { - fxp_close(scp_sftp_filehandle); + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; + + sftp_register(req = fxp_close_send(scp_sftp_filehandle)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin); return 0; } else { back->send(backhandle, "", 1); @@ -2078,7 +2195,7 @@ static void get_dir_list(int argc, char *argv[]) user = NULL; } - cmd = smalloc(4 * strlen(src) + 100); + cmd = snewn(4 * strlen(src) + 100, char); strcpy(cmd, "ls -la '"); p = cmd + strlen(cmd); for (q = src; *q; q++) { @@ -2179,7 +2296,7 @@ int main(int argc, char *argv[]) default_protocol = PROT_TELNET; - flags = FLAG_STDERR; + flags = FLAG_STDERR | FLAG_SYNCAGENT; cmdline_tooltype = TOOLTYPE_FILETRANSFER; ssh_get_line = &console_get_line; init_winsock();