X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/4a8fc3c43e71f1500b1f1203431ce944a832110e..9275ca8aed9b69e7b62eab751342833eb637ff1d:/psftp.c diff --git a/psftp.c b/psftp.c index 08c89e74..1e895751 100644 --- a/psftp.c +++ b/psftp.c @@ -94,8 +94,75 @@ char *canonify(char *name) { if (canonname) { sfree(fullname); return canonname; - } else - return fullname; + } else { + /* + * Attempt number 2. Some FXP_REALPATH implementations + * (glibc-based ones, in particular) require the _whole_ + * path to point to something that exists, whereas others + * (BSD-based) only require all but the last component to + * exist. So if the first call failed, we should strip off + * everything from the last slash onwards and try again, + * then put the final component back on. + * + * Special cases: + * + * - if the last component is "/." or "/..", then we don't + * bother trying this because there's no way it can work. + * + * - if the thing actually ends with a "/", we remove it + * before we start. Except if the string is "/" itself + * (although I can't see why we'd have got here if so, + * because surely "/" would have worked the first + * time?), in which case we don't bother. + * + * - if there's no slash in the string at all, give up in + * confusion (we expect at least one because of the way + * we constructed the string). + */ + + int i; + char *returnname; + + i = strlen(fullname); + if (i > 2 && fullname[i-1] == '/') + fullname[--i] = '\0'; /* strip trailing / unless at pos 0 */ + while (i > 0 && fullname[--i] != '/'); + + /* + * Give up on special cases. + */ + if (fullname[i] != '/' || /* no slash at all */ + !strcmp(fullname+i, "/.") || /* ends in /. */ + !strcmp(fullname+i, "/..") || /* ends in /.. */ + !strcmp(fullname, "/")) { + return fullname; + } + + /* + * Now i points at the slash. Deal with the final special + * case i==0 (ie the whole path was "/nonexistentfile"). + */ + fullname[i] = '\0'; /* separate the string */ + if (i == 0) { + canonname = fxp_realpath("/"); + } else { + canonname = fxp_realpath(fullname); + } + + if (!canonname) + return fullname; /* even that failed; give up */ + + /* + * We have a canonical name for all but the last path + * component. Concatenate the last component and return. + */ + returnname = dupcat(canonname, + canonname[strlen(canonname)-1] == '/' ? "" : "/", + fullname+i+1, NULL); + sfree(fullname); + sfree(canonname); + return returnname; + } } /* ---------------------------------------------------------------------- @@ -339,7 +406,6 @@ int sftp_cmd_put(struct sftp_command *cmd) { fp = fopen(fname, "rb"); if (!fp) { printf("local: unable to open %s\n", fname); - fxp_close(fh); sfree(outfname); return 0; } @@ -523,6 +589,7 @@ void do_sftp(void) { fprintf(stderr, "Fatal: unable to initialise SFTP: %s\n", fxp_error()); + return; } /* @@ -793,10 +860,10 @@ static void ssh_sftp_init(void) { } static char *password = NULL; -static int get_password(const char *prompt, char *str, int maxlen) +static int get_line(const char *prompt, char *str, int maxlen, int is_pw) { HANDLE hin, hout; - DWORD savemode, i; + DWORD savemode, newmode, i; if (password) { static int tried_once = 0; @@ -819,8 +886,12 @@ static int get_password(const char *prompt, char *str, int maxlen) } GetConsoleMode(hin, &savemode); - SetConsoleMode(hin, (savemode & (~ENABLE_ECHO_INPUT)) | - ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT); + newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT; + if (is_pw) + newmode &= ~ENABLE_ECHO_INPUT; + else + newmode |= ENABLE_ECHO_INPUT; + SetConsoleMode(hin, newmode); WriteFile(hout, prompt, strlen(prompt), &i, NULL); ReadFile(hin, str, maxlen-1, &i, NULL); @@ -830,7 +901,8 @@ static int get_password(const char *prompt, char *str, int maxlen) if ((int)i > maxlen) i = maxlen-1; else i = i - 2; str[i] = '\0'; - WriteFile(hout, "\r\n", 2, &i, NULL); + if (is_pw) + WriteFile(hout, "\r\n", 2, &i, NULL); return 1; } @@ -881,7 +953,7 @@ int main(int argc, char *argv[]) char *err; flags = FLAG_STDERR; - ssh_get_password = &get_password; + ssh_get_line = &get_line; init_winsock(); sk_init();