From 1bc24185fa9eb390d005d9655be64b33c4a2287b Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 29 Jun 2003 14:26:09 +0000 Subject: [PATCH] First phase of SFTP re-engineering. Each base-level fxp_* function has been split into a send half and a receive half, so that callers can set several requests in motion at a time and deal with the responses in whatever order they arrive. git-svn-id: svn://svn.tartarus.org/sgt/putty@3318 cda61777-01e9-0310-a592-d414129be87e --- psftp.c | 179 +++++++++++++++++++---- scp.c | 145 +++++++++++++++--- sftp.c | 511 +++++++++++++++++++++++++++++++++++----------------------------- sftp.h | 62 +++++--- 4 files changed, 594 insertions(+), 303 deletions(-) diff --git a/psftp.c b/psftp.c index 75161519..71d57471 100644 --- a/psftp.c +++ b/psftp.c @@ -48,6 +48,8 @@ static Config cfg; char *canonify(char *name) { char *fullname, *canonname; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; if (name[0] == '/') { fullname = dupstr(name); @@ -60,7 +62,10 @@ char *canonify(char *name) fullname = dupcat(pwd, slash, name, NULL); } - canonname = fxp_realpath(fullname); + sftp_register(req = fxp_realpath_send(fullname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + canonname = fxp_realpath_recv(pktin); if (canonname) { sfree(fullname); @@ -115,10 +120,13 @@ char *canonify(char *name) */ fullname[i] = '\0'; /* separate the string */ if (i == 0) { - canonname = fxp_realpath("/"); + sftp_register(req = fxp_realpath_send("/")); } else { - canonname = fxp_realpath(fullname); + sftp_register(req = fxp_realpath_send(fullname)); } + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + canonname = fxp_realpath_recv(pktin); if (!canonname) return fullname; /* even that failed; give up */ @@ -202,6 +210,8 @@ int sftp_cmd_ls(struct sftp_command *cmd) struct fxp_name **ournames; int nnames, namesize; char *dir, *cdir; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; int i; if (back == NULL) { @@ -222,7 +232,11 @@ int sftp_cmd_ls(struct sftp_command *cmd) printf("Listing directory %s\n", cdir); - dirh = fxp_opendir(cdir); + sftp_register(req = fxp_opendir_send(cdir)); + 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", dir, fxp_error()); } else { @@ -231,7 +245,11 @@ int sftp_cmd_ls(struct sftp_command *cmd) 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; @@ -253,7 +271,10 @@ int sftp_cmd_ls(struct sftp_command *cmd) 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 @@ -283,6 +304,8 @@ int sftp_cmd_ls(struct sftp_command *cmd) int sftp_cmd_cd(struct sftp_command *cmd) { struct fxp_handle *dirh; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; char *dir; if (back == NULL) { @@ -300,14 +323,21 @@ int sftp_cmd_cd(struct sftp_command *cmd) return 0; } - dirh = fxp_opendir(dir); + sftp_register(req = fxp_opendir_send(dir)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + dirh = fxp_opendir_recv(pktin); + if (!dirh) { printf("Directory %s: %s\n", dir, fxp_error()); sfree(dir); return 0; } - fxp_close(dirh); + sftp_register(req = fxp_close_send(dirh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin); sfree(pwd); pwd = dir; @@ -339,6 +369,8 @@ int sftp_cmd_pwd(struct sftp_command *cmd) int sftp_general_get(struct sftp_command *cmd, int restart) { struct fxp_handle *fh; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; char *fname, *outfname; uint64 offset; FILE *fp; @@ -362,7 +394,11 @@ int sftp_general_get(struct sftp_command *cmd, int restart) outfname = (cmd->nwords == 2 ? stripslashes(cmd->words[1], 0) : cmd->words[2]); - fh = fxp_open(fname, SSH_FXF_READ); + sftp_register(req = fxp_open_send(fname, SSH_FXF_READ)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fh = fxp_open_recv(pktin); + if (!fh) { printf("%s: %s\n", fname, fxp_error()); sfree(fname); @@ -377,7 +413,12 @@ int sftp_general_get(struct sftp_command *cmd, int restart) if (!fp) { printf("local: unable to open %s\n", outfname); - fxp_close(fh); + + sftp_register(req = fxp_close_send(fh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin); + sfree(fname); return 0; } @@ -404,7 +445,11 @@ int sftp_general_get(struct sftp_command *cmd, int restart) int len; int wpos, wlen; - len = fxp_read(fh, buffer, offset, sizeof(buffer)); + sftp_register(req = fxp_read_send(fh, offset, sizeof(buffer))); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + len = fxp_read_recv(pktin, buffer, sizeof(buffer)); + if ((len == -1 && fxp_error_type() == SSH_FX_EOF) || len == 0) break; if (len == -1) { @@ -431,7 +476,12 @@ int sftp_general_get(struct sftp_command *cmd, int restart) } fclose(fp); - fxp_close(fh); + + sftp_register(req = fxp_close_send(fh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin); + sfree(fname); return ret; @@ -455,6 +505,8 @@ int sftp_general_put(struct sftp_command *cmd, int restart) { struct fxp_handle *fh; char *fname, *origoutfname, *outfname; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; uint64 offset; FILE *fp; int ret; @@ -485,12 +537,15 @@ int sftp_general_put(struct sftp_command *cmd, int restart) return 0; } if (restart) { - fh = fxp_open(outfname, - SSH_FXF_WRITE); + sftp_register(req = fxp_open_send(outfname, SSH_FXF_WRITE)); } else { - fh = fxp_open(outfname, - SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC); + sftp_register(req = fxp_open_send(outfname, SSH_FXF_WRITE | + SSH_FXF_CREAT | SSH_FXF_TRUNC)); } + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fh = fxp_open_recv(pktin); + if (!fh) { printf("%s: %s\n", outfname, fxp_error()); sfree(outfname); @@ -500,7 +555,14 @@ int sftp_general_put(struct sftp_command *cmd, int restart) if (restart) { char decbuf[30]; struct fxp_attrs attrs; - if (!fxp_fstat(fh, &attrs)) { + int ret; + + sftp_register(req = fxp_fstat_send(fh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + ret = fxp_fstat_recv(pktin, &attrs); + + if (!ret) { printf("read size of %s: %s\n", outfname, fxp_error()); sfree(outfname); return 0; @@ -533,7 +595,7 @@ int sftp_general_put(struct sftp_command *cmd, int restart) ret = 1; while (1) { char buffer[4096]; - int len; + int len, ret; len = fread(buffer, 1, sizeof(buffer), fp); if (len == -1) { @@ -543,7 +605,13 @@ int sftp_general_put(struct sftp_command *cmd, int restart) } else if (len == 0) { break; } - if (!fxp_write(fh, buffer, offset, len)) { + + sftp_register(req = fxp_write_send(fh, buffer, offset, len)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + ret = fxp_write_recv(pktin); + + if (!ret) { printf("error while writing: %s\n", fxp_error()); ret = 0; break; @@ -551,7 +619,11 @@ int sftp_general_put(struct sftp_command *cmd, int restart) offset = uint64_add32(offset, len); } - fxp_close(fh); + sftp_register(req = fxp_close_send(fh)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + fxp_close_recv(pktin); + fclose(fp); sfree(outfname); @@ -569,6 +641,8 @@ int sftp_cmd_reput(struct sftp_command *cmd) int sftp_cmd_mkdir(struct sftp_command *cmd) { char *dir; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; int result; if (back == NULL) { @@ -587,7 +661,11 @@ int sftp_cmd_mkdir(struct sftp_command *cmd) return 0; } - result = fxp_mkdir(dir); + sftp_register(req = fxp_mkdir_send(dir)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_mkdir_recv(pktin); + if (!result) { printf("mkdir %s: %s\n", dir, fxp_error()); sfree(dir); @@ -601,6 +679,8 @@ int sftp_cmd_mkdir(struct sftp_command *cmd) int sftp_cmd_rmdir(struct sftp_command *cmd) { char *dir; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; int result; if (back == NULL) { @@ -619,7 +699,11 @@ int sftp_cmd_rmdir(struct sftp_command *cmd) return 0; } - result = fxp_rmdir(dir); + sftp_register(req = fxp_rmdir_send(dir)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_rmdir_recv(pktin); + if (!result) { printf("rmdir %s: %s\n", dir, fxp_error()); sfree(dir); @@ -633,6 +717,8 @@ int sftp_cmd_rmdir(struct sftp_command *cmd) int sftp_cmd_rm(struct sftp_command *cmd) { char *fname; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; int result; if (back == NULL) { @@ -651,7 +737,11 @@ int sftp_cmd_rm(struct sftp_command *cmd) return 0; } - result = fxp_remove(fname); + sftp_register(req = fxp_remove_send(fname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_remove_recv(pktin); + if (!result) { printf("rm %s: %s\n", fname, fxp_error()); sfree(fname); @@ -665,6 +755,8 @@ int sftp_cmd_rm(struct sftp_command *cmd) int sftp_cmd_mv(struct sftp_command *cmd) { char *srcfname, *dstfname; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; int result; if (back == NULL) { @@ -688,7 +780,11 @@ int sftp_cmd_mv(struct sftp_command *cmd) return 0; } - result = fxp_rename(srcfname, dstfname); + sftp_register(req = fxp_rename_send(srcfname, dstfname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_rename_recv(pktin); + if (!result) { char const *error = fxp_error(); struct fxp_attrs attrs; @@ -699,7 +795,11 @@ int sftp_cmd_mv(struct sftp_command *cmd) * _is_ a directory, we re-attempt the move by appending * the basename of srcfname to dstfname. */ - result = fxp_stat(dstfname, &attrs); + sftp_register(req = fxp_stat_send(dstfname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_stat_recv(pktin, &attrs); + if (result && (attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) && (attrs.permissions & 0040000)) { @@ -714,7 +814,12 @@ int sftp_cmd_mv(struct sftp_command *cmd) if (newcanon) { sfree(dstfname); dstfname = newcanon; - result = fxp_rename(srcfname, dstfname); + + sftp_register(req = fxp_rename_send(srcfname, dstfname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_rename_recv(pktin); + error = result ? NULL : fxp_error(); } } @@ -738,6 +843,8 @@ int sftp_cmd_chmod(struct sftp_command *cmd) int result; struct fxp_attrs attrs; unsigned attrs_clr, attrs_xor, oldperms, newperms; + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; if (back == NULL) { printf("psftp: not connected to a host; use \"open host.name\"\n"); @@ -860,7 +967,11 @@ int sftp_cmd_chmod(struct sftp_command *cmd) return 0; } - result = fxp_stat(fname, &attrs); + sftp_register(req = fxp_stat_send(fname)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_stat_recv(pktin, &attrs); + if (!result || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) { printf("get attrs for %s: %s\n", fname, result ? "file permissions not provided" : fxp_error()); @@ -874,7 +985,10 @@ int sftp_cmd_chmod(struct sftp_command *cmd) attrs.permissions ^= attrs_xor; newperms = attrs.permissions & 07777; - result = fxp_setstat(fname, attrs); + sftp_register(req = fxp_setstat_send(fname, attrs)); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + result = fxp_setstat_recv(pktin); if (!result) { printf("set attrs for %s: %s\n", fname, fxp_error()); @@ -1366,6 +1480,9 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags) static int do_sftp_init(void) { + struct sftp_packet *pktin; + struct sftp_request *req, *rreq; + /* * Do protocol initialisation. */ @@ -1378,7 +1495,11 @@ static int do_sftp_init(void) /* * Find out where our home directory is. */ - homedir = fxp_realpath("."); + sftp_register(req = fxp_realpath_send(".")); + rreq = sftp_find_request(pktin = sftp_recv()); + assert(rreq == req); + homedir = fxp_realpath_recv(pktin); + if (!homedir) { fprintf(stderr, "Warning: failed to resolve home directory: %s\n", diff --git a/scp.c b/scp.c index de9559ba..f146bd77 100644 --- a/scp.c +++ b/scp.c @@ -759,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; @@ -770,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 { @@ -779,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; @@ -802,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 @@ -847,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()); @@ -855,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; @@ -903,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()); @@ -932,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; @@ -965,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; } @@ -972,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 { @@ -1006,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 { @@ -1019,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); @@ -1171,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) { @@ -1239,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()); @@ -1291,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()); @@ -1304,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; @@ -1328,7 +1406,10 @@ int scp_get_sink_action(struct scp_sink_action *act) 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 = snew(struct scp_sftp_dirstack); newitem->next = scp_sftp_dirstack_head; @@ -1470,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()); @@ -1490,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++; @@ -1511,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); diff --git a/sftp.c b/sftp.c index b49e2750..265b4a2d 100644 --- a/sftp.c +++ b/sftp.c @@ -9,6 +9,7 @@ #include "misc.h" #include "int64.h" +#include "tree234.h" #include "sftp.h" #define GET_32BIT(cp) \ @@ -33,6 +34,8 @@ struct sftp_packet { static const char *fxp_error_message; static int fxp_errtype; +static void fxp_internal_error(char *msg); + /* ---------------------------------------------------------------------- * SFTP packet construction functions. */ @@ -244,6 +247,117 @@ struct sftp_packet *sftp_recv(void) } /* ---------------------------------------------------------------------- + * 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) +{ + const unsigned CHANNEL_NUMBER_OFFSET = 256; + 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 + * SEQUENCE_NUMBER_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; + } + + return req; +} + +/* ---------------------------------------------------------------------- * String handling routines. */ @@ -360,27 +474,22 @@ int fxp_init(void) /* * 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) +{ if (pktin->type == SSH_FXP_NAME) { int count; char *path; @@ -411,28 +520,23 @@ char *fxp_realpath(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) +{ if (pktin->type == SSH_FXP_HANDLE) { char *hstring; struct fxp_handle *handle; @@ -459,26 +563,21 @@ struct fxp_handle *fxp_open(char *path, int type) /* * 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) +{ if (pktin->type == SSH_FXP_HANDLE) { char *hstring; struct fxp_handle *handle; @@ -505,55 +604,46 @@ struct fxp_handle *fxp_opendir(char *path) /* * 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; +} + +void fxp_close_recv(struct sftp_packet *pktin) +{ + fxp_got_status(pktin); + sftp_pkt_free(pktin); } -int fxp_mkdir(char *path) +struct sftp_request *fxp_mkdir_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_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; - } - id = fxp_got_status(pktin); + + return req; +} + +int fxp_mkdir_recv(struct sftp_packet *pktin) +{ + int id = fxp_got_status(pktin); sftp_pkt_free(pktin); if (id != 1) { return 0; @@ -561,27 +651,22 @@ int fxp_mkdir(char *path) 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; - } - id = fxp_got_status(pktin); + + return req; +} + +int fxp_rmdir_recv(struct sftp_packet *pktin) +{ + int id = fxp_got_status(pktin); sftp_pkt_free(pktin); if (id != 1) { return 0; @@ -589,27 +674,22 @@ int fxp_rmdir(char *path) 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; - } - id = fxp_got_status(pktin); + + return req; +} + +int fxp_remove_recv(struct sftp_packet *pktin) +{ + int id = fxp_got_status(pktin); sftp_pkt_free(pktin); if (id != 1) { return 0; @@ -617,28 +697,23 @@ int fxp_remove(char *fname) 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; - } - id = fxp_got_status(pktin); + + return req; +} + +int fxp_rename_recv(struct sftp_packet *pktin) +{ + int id = fxp_got_status(pktin); sftp_pkt_free(pktin); if (id != 1) { return 0; @@ -650,27 +725,21 @@ int fxp_rename(char *srcfname, char *dstfname) * 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 fxp_attrs *attrs) +{ if (pktin->type == SSH_FXP_ATTRS) { *attrs = sftp_pkt_getattrs(pktin); sftp_pkt_free(pktin); @@ -682,28 +751,23 @@ int fxp_stat(char *fname, struct fxp_attrs *attrs) } } -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 fxp_attrs *attrs) +{ if (pktin->type == SSH_FXP_ATTRS) { *attrs = sftp_pkt_getattrs(pktin); sftp_pkt_free(pktin); @@ -718,57 +782,49 @@ int fxp_fstat(struct fxp_handle *handle, struct fxp_attrs *attrs) /* * 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; - } - id = fxp_got_status(pktin); + + return req; +} + +int fxp_setstat_recv(struct sftp_packet *pktin) +{ + int id = fxp_got_status(pktin); sftp_pkt_free(pktin); if (id != 1) { return 0; } 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; - } - id = fxp_got_status(pktin); + + return req; +} + +int fxp_fsetstat_recv(struct sftp_packet *pktin) +{ + int id = fxp_got_status(pktin); sftp_pkt_free(pktin); if (id != 1) { return 0; @@ -782,30 +838,25 @@ int fxp_fsetstat(struct fxp_handle *handle, struct fxp_attrs attrs) * 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, char *buffer, int len) +{ if (pktin->type == SSH_FXP_DATA) { char *str; int rlen; @@ -831,27 +882,22 @@ int fxp_read(struct fxp_handle *handle, char *buffer, uint64 offset, /* * 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) +{ if (pktin->type == SSH_FXP_NAME) { struct fxp_names *ret; int i; @@ -879,31 +925,26 @@ struct fxp_names *fxp_readdir(struct fxp_handle *handle) /* * 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) +{ fxp_got_status(pktin); sftp_pkt_free(pktin); return fxp_errtype == SSH_FX_OK; diff --git a/sftp.h b/sftp.h index 8f671ad7..fd3ec71b 100644 --- a/sftp.h +++ b/sftp.h @@ -92,6 +92,9 @@ struct fxp_names { struct fxp_name *names; }; +struct sftp_request; +struct sftp_packet; + const char *fxp_error(void); int fxp_error_type(void); @@ -104,71 +107,87 @@ int fxp_init(void); * Canonify a pathname. Concatenate the two given path elements * with a separating slash, unless the second is NULL. */ -char *fxp_realpath(char *path); +struct sftp_request *fxp_realpath_send(char *path); +char *fxp_realpath_recv(struct sftp_packet *pktin); /* * Open a file. */ -struct fxp_handle *fxp_open(char *path, int type); +struct sftp_request *fxp_open_send(char *path, int type); +struct fxp_handle *fxp_open_recv(struct sftp_packet *pktin); /* * Open a directory. */ -struct fxp_handle *fxp_opendir(char *path); +struct sftp_request *fxp_opendir_send(char *path); +struct fxp_handle *fxp_opendir_recv(struct sftp_packet *pktin); /* * Close a file/dir. */ -void fxp_close(struct fxp_handle *handle); +struct sftp_request *fxp_close_send(struct fxp_handle *handle); +void fxp_close_recv(struct sftp_packet *pktin); /* * Make a directory. */ -int fxp_mkdir(char *path); +struct sftp_request *fxp_mkdir_send(char *path); +int fxp_mkdir_recv(struct sftp_packet *pktin); /* * Remove a directory. */ -int fxp_rmdir(char *path); +struct sftp_request *fxp_rmdir_send(char *path); +int fxp_rmdir_recv(struct sftp_packet *pktin); /* * Remove a file. */ -int fxp_remove(char *fname); +struct sftp_request *fxp_remove_send(char *fname); +int fxp_remove_recv(struct sftp_packet *pktin); /* * Rename a file. */ -int fxp_rename(char *srcfname, char *dstfname); +struct sftp_request *fxp_rename_send(char *srcfname, char *dstfname); +int fxp_rename_recv(struct sftp_packet *pktin); /* * Return file attributes. */ -int fxp_stat(char *fname, struct fxp_attrs *attrs); -int fxp_fstat(struct fxp_handle *handle, struct fxp_attrs *attrs); +struct sftp_request *fxp_stat_send(char *fname); +int fxp_stat_recv(struct sftp_packet *pktin, struct fxp_attrs *attrs); +struct sftp_request *fxp_fstat_send(struct fxp_handle *handle); +int fxp_fstat_recv(struct sftp_packet *pktin, struct fxp_attrs *attrs); /* * Set file attributes. */ -int fxp_setstat(char *fname, struct fxp_attrs attrs); -int fxp_fsetstat(struct fxp_handle *handle, struct fxp_attrs attrs); +struct sftp_request *fxp_setstat_send(char *fname, struct fxp_attrs attrs); +int fxp_setstat_recv(struct sftp_packet *pktin); +struct sftp_request *fxp_fsetstat_send(struct fxp_handle *handle, + struct fxp_attrs attrs); +int fxp_fsetstat_recv(struct sftp_packet *pktin); /* * Read from a file. */ -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); +int fxp_read_recv(struct sftp_packet *pktin, char *buffer, 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); +int fxp_write_recv(struct sftp_packet *pktin); /* * Read from a directory. */ -struct fxp_names *fxp_readdir(struct fxp_handle *handle); +struct sftp_request *fxp_readdir_send(struct fxp_handle *handle); +struct fxp_names *fxp_readdir_recv(struct sftp_packet *pktin); /* * Free up an fxp_names structure. @@ -180,3 +199,12 @@ void fxp_free_names(struct fxp_names *names); */ struct fxp_name *fxp_dup_name(struct fxp_name *name); void fxp_free_name(struct fxp_name *name); + +/* + * These functions might well be temporary placeholders to be + * replaced with more useful similar functions later. They form the + * main dispatch loop for processing incoming SFTP responses. + */ +void sftp_register(struct sftp_request *req); +struct sftp_request *sftp_find_request(struct sftp_packet *pktin); +struct sftp_packet *sftp_recv(void); -- 2.11.0