From 78306c910d0eab48d273f5e4c05d7fe163013141 Mon Sep 17 00:00:00 2001 From: Ray Hayes Date: Tue, 18 Oct 2016 17:11:28 -0700 Subject: [PATCH] Issues with chdir and input conversion. --- contrib/win32/win32compat/inc/fcntl.h | 6 ++- contrib/win32/win32compat/inc/sys/stat.h | 1 + contrib/win32/win32compat/inc/w32posix.h | 2 +- contrib/win32/win32compat/w32fd.c | 20 ++++++++- scp.c | 12 +++--- sftp.c | 55 ++++++++++++++++-------- 6 files changed, 67 insertions(+), 29 deletions(-) diff --git a/contrib/win32/win32compat/inc/fcntl.h b/contrib/win32/win32compat/inc/fcntl.h index 8fe222f..8f874e5 100644 --- a/contrib/win32/win32compat/inc/fcntl.h +++ b/contrib/win32/win32compat/inc/fcntl.h @@ -11,4 +11,8 @@ #define O_TRUNC 0x0200 // open and truncate #define O_EXCL 0x0400 // open only if file doesn't already exist -#define O_BINARY 0x8000 // file mode is binary (untranslated) \ No newline at end of file +#define O_TEXT 0x4000 /* file mode is text (translated) */ +#define O_BINARY 0x8000 /* file mode is binary (untranslated) */ +#define O_WTEXT 0x10000 /* file mode is UTF16 (translated) */ +#define O_U16TEXT 0x20000 /* file mode is UTF16 no BOM (translated) */ +#define O_U8TEXT 0x40000 /* file mode is UTF8 no BOM (translated) */ diff --git a/contrib/win32/win32compat/inc/sys/stat.h b/contrib/win32/win32compat/inc/sys/stat.h index e18f2bb..e4a8954 100644 --- a/contrib/win32/win32compat/inc/sys/stat.h +++ b/contrib/win32/win32compat/inc/sys/stat.h @@ -29,6 +29,7 @@ #define stat w32_stat #define lstat w32_stat #define mkdir w32_mkdir +#define chdir w32_chdir struct w32_stat { dev_t st_dev; /* ID of device containing file */ diff --git a/contrib/win32/win32compat/inc/w32posix.h b/contrib/win32/win32compat/inc/w32posix.h index 3f7fd0d..c98dfbb 100644 --- a/contrib/win32/win32compat/inc/w32posix.h +++ b/contrib/win32/win32compat/inc/w32posix.h @@ -52,6 +52,7 @@ long w32_lseek( int fd, long offset, int origin); int w32_isatty(int fd); FILE* w32_fdopen(int fd, const char *mode); int w32_mkdir(const char *pathname, unsigned short mode); +int w32_chdir(const char *dirname); /*common i/o*/ #define fcntl(a,b,...) w32_fcntl((a), (b), __VA_ARGS__) @@ -72,7 +73,6 @@ int w32_raise(int sig); int w32_kill(int pid, int sig); FILE* w32_fopen_utf8(const char *, const char *); - /* Shutdown constants */ #define SHUT_WR SD_SEND #define SHUT_RD SD_RECEIVE diff --git a/contrib/win32/win32compat/w32fd.c b/contrib/win32/win32compat/w32fd.c index 40446d2..ce16e04 100644 --- a/contrib/win32/win32compat/w32fd.c +++ b/contrib/win32/win32compat/w32fd.c @@ -389,7 +389,7 @@ int w32_writev(int fd, const struct iovec *iov, int iovcnt) { CHECK_FD(fd); for (i = 0; i < iovcnt; i++) { - int ret = write(fd, iov[i].iov_base, iov[i].iov_len); + int ret = w32_write(fd, iov[i].iov_base, iov[i].iov_len); if (ret > 0) { written += ret; @@ -418,7 +418,23 @@ w32_lseek(int fd, long offset, int origin) { int w32_mkdir(const char *pathname, unsigned short mode) { - return _mkdir(pathname); + wchar_t wdirname[MAX_PATH]; + + if (MultiByteToWideChar(CP_UTF8, 0, pathname, -1, wdirname, MAX_PATH)) { + return _wmkdir(wdirname); + } + + return 0; +} + +int w32_chdir(const char *dirname) { + wchar_t wdirname[MAX_PATH]; + + if (MultiByteToWideChar(CP_UTF8, 0, dirname, -1, wdirname, MAX_PATH)) { + return _wchdir(wdirname); + } + + return 0; } int diff --git a/scp.c b/scp.c index dcf2a3d..76cfd85 100644 --- a/scp.c +++ b/scp.c @@ -1092,9 +1092,9 @@ main(int argc, char **argv) args.list = remote_remote_args.list = NULL; addargs(&args, "%s", ssh_program); addargs(&args, "-x"); - addargs(&args, "-oForwardAgent=no"); - addargs(&args, "-oPermitLocalCommand=no"); - addargs(&args, "-oClearAllForwardings=yes"); + addargs(&args, "\"-oForwardAgent no\""); + addargs(&args, "\"-oPermitLocalCommand no\""); + addargs(&args, "\"-oClearAllForwardings yes\""); fflag = tflag = 0; while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1) @@ -1127,8 +1127,8 @@ main(int argc, char **argv) addargs(&args, "%s", optarg); break; case 'B': - addargs(&remote_remote_args, "-oBatchmode=yes"); - addargs(&args, "-oBatchmode=yes"); + addargs(&remote_remote_args, "\"-oBatchmode yes\""); + addargs(&args, "\"-oBatchmode yes\""); break; case 'l': limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, @@ -1347,7 +1347,7 @@ toremote(char *targ, int argc, char **argv) freeargs(&alist); addargs(&alist, "%s", ssh_program); addargs(&alist, "-x"); - addargs(&alist, "-oClearAllForwardings=yes"); + addargs(&alist, "-\"oClearAllForwardings yes\""); addargs(&alist, "-n"); for (j = 0; j < remote_remote_args.num; j++) { addargs(&alist, "%s", diff --git a/sftp.c b/sftp.c index b2a02ae..19dbdc0 100644 --- a/sftp.c +++ b/sftp.c @@ -73,7 +73,9 @@ typedef void EditLine; #define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */ #define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */ -#ifdef WIN32_VS +#ifdef WINDOWS +#include +#include #include "win32_dirent.h" #endif @@ -1425,6 +1427,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, glob_t g; path1 = path2 = NULL; + cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag, &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, &path1, &path2); if (ignore_errors != 0) @@ -2104,7 +2107,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) free(dir); } - #ifndef WIN32_VS + #ifndef WINDOWS setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(infile, NULL, _IOLBF, 0); #endif @@ -2117,13 +2120,26 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) signal(SIGINT, SIG_IGN); if (el == NULL) { - if (interactive) - printf("sftp> "); - if (fgets(cmd, sizeof(cmd), infile) == NULL) { - if (interactive) - printf("\n"); - break; - } + if (interactive) { + wchar_t wcmd[2048]; + printf("sftp> "); + if (fgetws(wcmd, sizeof(cmd)/sizeof(wchar_t), infile) == NULL) { + if (interactive) + printf("\n"); + break; + } + else { + int needed; + if ((needed = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, wcmd, -1, NULL, 0, NULL, NULL)) == 0 || + WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, wcmd, -1, cmd, needed, NULL, NULL) != needed) + fatal("failed to covert input arguments"); + } + } + else { + if (fgets(cmd, sizeof(cmd), infile) == NULL) { + break; + } + } if (!interactive) { /* Echo command */ printf("sftp> %s", cmd); if (strlen(cmd) > 0 && @@ -2335,13 +2351,14 @@ main(int argc, char **argv) args.list = NULL; addargs(&args, "%s", ssh_program); - addargs(&args, "-oForwardX11 no"); - addargs(&args, "-oForwardAgent no"); - addargs(&args, "-oPermitLocalCommand no"); - addargs(&args, "-oClearAllForwardings yes"); + addargs(&args, "\"-oForwardX11 no\""); + addargs(&args, "\"-oForwardAgent no\""); + addargs(&args, "\"-oPermitLocalCommand no\""); + addargs(&args, "\"-oClearAllForwardings yes\""); ll = SYSLOG_LEVEL_INFO; infile = stdin; + _setmode(_fileno(infile), O_U16TEXT); while ((ch = getopt(argc, argv, "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) { @@ -2367,8 +2384,8 @@ main(int argc, char **argv) addargs(&args, "-%c", ch); break; case 'P': - addargs(&args, "-oPort %s", optarg); - break; + addargs(&args, "\"-oPort %s\"", optarg); + break; case 'v': if (debug_level < 3) { addargs(&args, "-v"); @@ -2402,8 +2419,8 @@ main(int argc, char **argv) fatal("%s (%s).", strerror(errno), optarg); showprogress = 0; quiet = batchmode = 1; - addargs(&args, "-obatchmode yes"); - break; + addargs(&args, "\"-obatchmode yes\""); + break; case 'f': global_fflag = 1; break; @@ -2476,8 +2493,8 @@ main(int argc, char **argv) fprintf(stderr, "Missing hostname\n"); usage(); } - addargs(&args, "-oProtocol %d", sshver); - + addargs(&args, "\"-oProtocol %d\"", sshver); + /* no subsystem if the server-spec contains a '/' */ if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) addargs(&args, "-s");