From 519b93d236ad2e9d35fe294acb020d93debf79a2 Mon Sep 17 00:00:00 2001 From: erw7 Date: Thu, 17 Jan 2019 16:05:57 +0900 Subject: win: executable(): fix relative path bug Qualified (i.e. dot-prefixed) relative paths should only search CWD, not $PATH. --- src/nvim/os/fs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 27db675c52..8f2324c554 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -242,8 +242,12 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) FUNC_ATTR_NONNULL_ARG(1) { bool no_path = !use_path || path_is_absolute(name); -#ifndef WIN32 +#ifdef WIN32 // If the filename is "qualified" (relative or absolute) do not check $PATH. + no_path |= (name[0] == '.' + && ((name[1] == '/' || name[1] == '\\') + || (name[1] == '.' && (name[2] == '/' || name[2] == '\\')))); +#else no_path |= (name[0] == '.' && (name[1] == '/' || (name[1] == '.' && name[2] == '/'))); #endif -- cgit From 6be483b6ad8112040c17d2c27c548c14446d99ed Mon Sep 17 00:00:00 2001 From: erw7 Date: Thu, 17 Jan 2019 21:54:12 +0900 Subject: win: executable(): also check extension --- src/nvim/os/fs.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 8f2324c554..0fbd1b0b34 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -258,8 +258,9 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) if (!pathext) { pathext = ".com;.exe;.bat;.cmd"; } - bool ok = is_executable((char *)name) || is_executable_ext((char *)name, - pathext); + bool ok = (is_extension_executable((char *)name) + && is_executable((char *)name)) + || is_executable_ext((char *)name, pathext); #else // Must have path separator, cannot execute files in the current directory. const bool ok = ((const char_u *)gettail_dir((const char *)name) != name @@ -277,6 +278,68 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) return is_executable_in_path(name, abspath); } +#ifdef WIN32 +/// Returns true if extension of `name` is executalbe file exteinsion. +static bool is_extension_executable(const char *name) + FUNC_ATTR_NONNULL_ALL +{ + // Don't check extensions, when a Unix-shell like 'shell'. + const char_u *shell_end = p_sh + STRLEN(p_sh); + while (true) { + if (*shell_end == '.') { + break; + } else if (shell_end == p_sh + || (*shell_end == '/' || *shell_end == '\\')) { + shell_end = p_sh + STRLEN(p_sh); + break; + } + shell_end--; + } + if (mb_strnicmp(shell_end - 2, (const char_u *)"sh", 2) == 0) { + return true; + } + + const char *pathext = os_getenv("PATHEXT"); + if (!pathext) { + pathext = ".com;.exe;.bat;.cmd"; + } + const char *ext_pos = name + STRLEN(name) - 1; + while (name != ext_pos) { + if (*ext_pos == '\\' || *ext_pos == '/') { + ext_pos = name; + break; + } + if (*ext_pos == '.') { + break; + } + ext_pos--; + } + + const char *cur_pos = pathext; + while (true) { + // Don't check extension, if $PATHEXT contain dot itself. + if (*cur_pos == '.' + && (*(cur_pos + 1) == ENV_SEPCHAR || *(cur_pos + 1) == NUL)) { + return true; + } + const char *ext_end = strchr(cur_pos, ENV_SEPCHAR); + size_t ext_len = ext_end ? + (size_t)(ext_end - cur_pos) : + (STRLEN(pathext) - (size_t)(cur_pos - pathext)); + if (ext_pos != name && mb_strnicmp((const char_u *)ext_pos, + (const char_u *)cur_pos, ext_len) == 0) { + return true; + } + if (ext_end == NULL) { + break; + } else { + cur_pos = ++ext_end; + } + } + return false; +} +#endif + /// Returns true if `name` is an executable file. static bool is_executable(const char *name) FUNC_ATTR_NONNULL_ALL @@ -378,7 +441,8 @@ static bool is_executable_in_path(const char_u *name, char_u **abspath) append_path(buf, (char *)name, buf_len); #ifdef WIN32 - bool ok = is_executable(buf) || is_executable_ext(buf, pathext); + bool ok = (is_extension_executable(buf) && is_executable(buf)) + || is_executable_ext(buf, pathext); #else bool ok = is_executable(buf); #endif -- cgit From 35c2ceba9695b2f246c11d4e457acda82bb9cb36 Mon Sep 17 00:00:00 2001 From: erw7 Date: Fri, 18 Jan 2019 00:33:40 +0900 Subject: win: exepath(): append extension if omitted fixes #9403 --- src/nvim/os/fs.c | 49 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 0fbd1b0b34..9a96241178 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -258,21 +258,18 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) if (!pathext) { pathext = ".com;.exe;.bat;.cmd"; } - bool ok = (is_extension_executable((char *)name) - && is_executable((char *)name)) - || is_executable_ext((char *)name, pathext); + if ((is_extension_executable((char *)name) + && is_executable((char *)name, abspath)) + || is_executable_ext((char *)name, pathext, abspath)) { #else // Must have path separator, cannot execute files in the current directory. - const bool ok = ((const char_u *)gettail_dir((const char *)name) != name - && is_executable((char *)name)); + if ((const char_u *)gettail_dir((const char *)name) != name + && is_executable((char *)name, abspath)) { #endif - if (ok) { - if (abspath != NULL) { - *abspath = save_abs_path(name); - } return true; + } else { + return false; } - return false; } return is_executable_in_path(name, abspath); @@ -341,8 +338,8 @@ static bool is_extension_executable(const char *name) #endif /// Returns true if `name` is an executable file. -static bool is_executable(const char *name) - FUNC_ATTR_NONNULL_ALL +static bool is_executable(const char *name, char_u **abspath) + FUNC_ATTR_NONNULL_ARG(1) { int32_t mode = os_getperm((const char *)name); @@ -353,21 +350,28 @@ static bool is_executable(const char *name) #ifdef WIN32 // Windows does not have exec bit; just check if the file exists and is not // a directory. - return (S_ISREG(mode)); + const bool ok = S_ISREG(mode); #else int r = -1; if (S_ISREG(mode)) { RUN_UV_FS_FUNC(r, uv_fs_access, name, X_OK, NULL); } - return (r == 0); + const bool ok = (r == 0); #endif + if (ok) { + if (abspath != NULL) { + *abspath = save_abs_path((char_u *)name); + } + return true; + } + return false; } #ifdef WIN32 /// Appends file extensions from `pathext` to `name` and returns true if any /// such combination is executable. -static bool is_executable_ext(char *name, const char *pathext) - FUNC_ATTR_NONNULL_ALL +static bool is_executable_ext(char *name, const char *pathext, char_u **abspath) + FUNC_ATTR_NONNULL_ARG(1, 2) { xstrlcpy(os_buf, name, sizeof(os_buf)); char *buf_end = xstrchrnul(os_buf, '\0'); @@ -381,7 +385,7 @@ static bool is_executable_ext(char *name, const char *pathext) const char *ext_end = xstrchrnul(ext, ENV_SEPCHAR); STRLCPY(buf_end, ext, ext_end - ext + 1); - if (is_executable(os_buf)) { + if (is_executable(os_buf, abspath)) { return true; } @@ -441,16 +445,11 @@ static bool is_executable_in_path(const char_u *name, char_u **abspath) append_path(buf, (char *)name, buf_len); #ifdef WIN32 - bool ok = (is_extension_executable(buf) && is_executable(buf)) - || is_executable_ext(buf, pathext); + if ((is_extension_executable(buf) && is_executable(buf, abspath)) + || is_executable_ext(buf, pathext, abspath)) { #else - bool ok = is_executable(buf); + if (is_executable(buf, abspath)) { #endif - if (ok) { - if (abspath != NULL) { // Caller asked for a copy of the path. - *abspath = save_abs_path((char_u *)buf); - } - rv = true; goto end; } -- cgit From 3be5aa1a34f63f4e5e2b384098de2020a4c5b3bc Mon Sep 17 00:00:00 2001 From: erw7 Date: Fri, 18 Jan 2019 14:11:40 +0900 Subject: test/win: executable(), exepath() #9516 --- src/nvim/os/fs.c | 2 +- src/nvim/testdir/test_functions.vim | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 9a96241178..b75607b7b1 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -276,7 +276,7 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) } #ifdef WIN32 -/// Returns true if extension of `name` is executalbe file exteinsion. +/// Returns true if extension of `name` is executable file exteinsion. static bool is_extension_executable(const char *name) FUNC_ATTR_NONNULL_ALL { diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 13e2dcf804..46c2d0f4cd 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -881,8 +881,8 @@ func Test_Executable() call assert_equal(1, executable('notepad')) call assert_equal(1, executable('notepad.exe')) call assert_equal(0, executable('notepad.exe.exe')) - call assert_equal(1, executable('shell32.dll')) - call assert_equal(1, executable('win.ini')) + call assert_equal(0, executable('shell32.dll')) + call assert_equal(0, executable('win.ini')) elseif has('unix') call assert_equal(1, executable('cat')) call assert_equal(0, executable('nodogshere')) -- cgit From 70ac7c876bac2151da467b08244c7f98a5d8bf61 Mon Sep 17 00:00:00 2001 From: erw7 Date: Sun, 20 Jan 2019 14:12:00 +0900 Subject: cleanup: PATHEXT function --- src/nvim/os/fs.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index b75607b7b1..628ef9321f 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -254,10 +254,7 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) if (no_path) { #ifdef WIN32 - const char *pathext = os_getenv("PATHEXT"); - if (!pathext) { - pathext = ".com;.exe;.bat;.cmd"; - } + const char *pathext = get_pathext(); if ((is_extension_executable((char *)name) && is_executable((char *)name, abspath)) || is_executable_ext((char *)name, pathext, abspath)) { @@ -276,6 +273,15 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) } #ifdef WIN32 +static const char *get_pathext(void) +{ + const char *pathext = os_getenv("PATHEXT"); + if (!pathext) { + pathext = ".com;.exe;.bat;.cmd"; + } + return pathext; +} + /// Returns true if extension of `name` is executable file exteinsion. static bool is_extension_executable(const char *name) FUNC_ATTR_NONNULL_ALL @@ -296,10 +302,7 @@ static bool is_extension_executable(const char *name) return true; } - const char *pathext = os_getenv("PATHEXT"); - if (!pathext) { - pathext = ".com;.exe;.bat;.cmd"; - } + const char *pathext = get_pathext(); const char *ext_pos = name + STRLEN(name) - 1; while (name != ext_pos) { if (*ext_pos == '\\' || *ext_pos == '/') { @@ -424,10 +427,7 @@ static bool is_executable_in_path(const char_u *name, char_u **abspath) size_t buf_len = STRLEN(name) + strlen(path) + 2; #ifdef WIN32 - const char *pathext = os_getenv("PATHEXT"); - if (!pathext) { - pathext = ".com;.exe;.bat;.cmd"; - } + const char *pathext = get_pathext(); buf_len += strlen(pathext); #endif -- cgit From 692b83fc927dd6173885fde0342489851d5470af Mon Sep 17 00:00:00 2001 From: erw7 Date: Mon, 28 Jan 2019 15:33:51 +0900 Subject: is_extension_executable: simplify Simplify method of determining search position of the extension. --- src/nvim/os/fs.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 628ef9321f..c475724c4e 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -282,11 +282,11 @@ static const char *get_pathext(void) return pathext; } -/// Returns true if extension of `name` is executable file exteinsion. +/// Returns true if extension of `name` is executable file extension. static bool is_extension_executable(const char *name) FUNC_ATTR_NONNULL_ALL { - // Don't check extensions, when a Unix-shell like 'shell'. + // Don't check extension for Unix-style 'shell'. const char_u *shell_end = p_sh + STRLEN(p_sh); while (true) { if (*shell_end == '.') { @@ -303,31 +303,21 @@ static bool is_extension_executable(const char *name) } const char *pathext = get_pathext(); - const char *ext_pos = name + STRLEN(name) - 1; - while (name != ext_pos) { - if (*ext_pos == '\\' || *ext_pos == '/') { - ext_pos = name; - break; - } - if (*ext_pos == '.') { - break; - } - ext_pos--; - } - const char *cur_pos = pathext; while (true) { - // Don't check extension, if $PATHEXT contain dot itself. + // Don't check extension if $PATHEXT itself contains dot. if (*cur_pos == '.' && (*(cur_pos + 1) == ENV_SEPCHAR || *(cur_pos + 1) == NUL)) { return true; } const char *ext_end = strchr(cur_pos, ENV_SEPCHAR); - size_t ext_len = ext_end ? - (size_t)(ext_end - cur_pos) : - (STRLEN(pathext) - (size_t)(cur_pos - pathext)); - if (ext_pos != name && mb_strnicmp((const char_u *)ext_pos, - (const char_u *)cur_pos, ext_len) == 0) { + size_t ext_len = ext_end + ? (size_t)(ext_end - cur_pos) + : (strlen(pathext) - (size_t)(cur_pos - pathext)); + size_t name_len = STRLEN(name); + if (name_len > ext_len && mb_strnicmp( + (char_u *)(name + name_len - ext_len), + (char_u *)cur_pos, ext_len) == 0) { return true; } if (ext_end == NULL) { -- cgit From 4b25c2b4e896eef19b8917d543b383a1d3919567 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 1 Apr 2019 00:45:46 +0200 Subject: is_extension_executable: simplify check for unix-style shell mch_expand_wildcards does it this way, it's probably good enough. --- src/nvim/os/fs.c | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index c475724c4e..aa61c086c6 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -226,13 +226,13 @@ int os_exepath(char *buffer, size_t *size) return uv_exepath(buffer, size); } -/// Checks if the given path represents an executable file. +/// Checks if the file `name` is executable. /// -/// @param[in] name Name of the executable. -/// @param[out] abspath Path of the executable, if found and not `NULL`. -/// @param[in] use_path If 'false', only check if "name" is executable +/// @param[in] name Filename to check. +/// @param[out] abspath Returns resolved executable path, if not NULL. +/// @param[in] use_path Also search $PATH. /// -/// @return `true` if `name` is executable and +/// @return true if `name` is executable and /// - can be found in $PATH, /// - is relative to current dir or /// - is absolute. @@ -242,8 +242,8 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) FUNC_ATTR_NONNULL_ARG(1) { bool no_path = !use_path || path_is_absolute(name); -#ifdef WIN32 // If the filename is "qualified" (relative or absolute) do not check $PATH. +#ifdef WIN32 no_path |= (name[0] == '.' && ((name[1] == '/' || name[1] == '\\') || (name[1] == '.' && (name[2] == '/' || name[2] == '\\')))); @@ -287,18 +287,7 @@ static bool is_extension_executable(const char *name) FUNC_ATTR_NONNULL_ALL { // Don't check extension for Unix-style 'shell'. - const char_u *shell_end = p_sh + STRLEN(p_sh); - while (true) { - if (*shell_end == '.') { - break; - } else if (shell_end == p_sh - || (*shell_end == '/' || *shell_end == '\\')) { - shell_end = p_sh + STRLEN(p_sh); - break; - } - shell_end--; - } - if (mb_strnicmp(shell_end - 2, (const char_u *)"sh", 2) == 0) { + if (strstr((char *)path_tail(p_sh), "sh") != NULL) { return true; } @@ -351,13 +340,10 @@ static bool is_executable(const char *name, char_u **abspath) } const bool ok = (r == 0); #endif - if (ok) { - if (abspath != NULL) { - *abspath = save_abs_path((char_u *)name); - } - return true; + if (ok && abspath != NULL) { + *abspath = save_abs_path((char_u *)name); } - return false; + return ok; } #ifdef WIN32 @@ -391,10 +377,10 @@ static bool is_executable_ext(char *name, const char *pathext, char_u **abspath) } #endif -/// Checks if a file is inside the `$PATH` and is executable. +/// Checks if a file is in `$PATH` and is executable. /// -/// @param[in] name The name of the executable. -/// @param[out] abspath Path of the executable, if found and not `NULL`. +/// @param[in] name Filename to check. +/// @param[out] abspath Returns resolved executable path, if not NULL. /// /// @return `true` if `name` is an executable inside `$PATH`. static bool is_executable_in_path(const char_u *name, char_u **abspath) -- cgit From 7d61b2f64ffb7b31c9f59731a77de3b8cdca19a4 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 1 Apr 2019 02:40:42 +0200 Subject: fs.c: eliminate is_extension_executable Add this functionality to is_executable_ext() instead. --- src/nvim/os/fs.c | 83 ++++++++++++++++++-------------------------------------- 1 file changed, 26 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index aa61c086c6..6ac53dd45b 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -255,9 +255,7 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) if (no_path) { #ifdef WIN32 const char *pathext = get_pathext(); - if ((is_extension_executable((char *)name) - && is_executable((char *)name, abspath)) - || is_executable_ext((char *)name, pathext, abspath)) { + if (is_executable_ext((char *)name, pathext, abspath)) { #else // Must have path separator, cannot execute files in the current directory. if ((const char_u *)gettail_dir((const char *)name) != name @@ -272,53 +270,6 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) return is_executable_in_path(name, abspath); } -#ifdef WIN32 -static const char *get_pathext(void) -{ - const char *pathext = os_getenv("PATHEXT"); - if (!pathext) { - pathext = ".com;.exe;.bat;.cmd"; - } - return pathext; -} - -/// Returns true if extension of `name` is executable file extension. -static bool is_extension_executable(const char *name) - FUNC_ATTR_NONNULL_ALL -{ - // Don't check extension for Unix-style 'shell'. - if (strstr((char *)path_tail(p_sh), "sh") != NULL) { - return true; - } - - const char *pathext = get_pathext(); - const char *cur_pos = pathext; - while (true) { - // Don't check extension if $PATHEXT itself contains dot. - if (*cur_pos == '.' - && (*(cur_pos + 1) == ENV_SEPCHAR || *(cur_pos + 1) == NUL)) { - return true; - } - const char *ext_end = strchr(cur_pos, ENV_SEPCHAR); - size_t ext_len = ext_end - ? (size_t)(ext_end - cur_pos) - : (strlen(pathext) - (size_t)(cur_pos - pathext)); - size_t name_len = STRLEN(name); - if (name_len > ext_len && mb_strnicmp( - (char_u *)(name + name_len - ext_len), - (char_u *)cur_pos, ext_len) == 0) { - return true; - } - if (ext_end == NULL) { - break; - } else { - cur_pos = ++ext_end; - } - } - return false; -} -#endif - /// Returns true if `name` is an executable file. static bool is_executable(const char *name, char_u **abspath) FUNC_ATTR_NONNULL_ARG(1) @@ -347,24 +298,43 @@ static bool is_executable(const char *name, char_u **abspath) } #ifdef WIN32 -/// Appends file extensions from `pathext` to `name` and returns true if any -/// such combination is executable. +static const char *get_pathext(void) +{ + const char *pathext = os_getenv("PATHEXT"); + if (!pathext) { + pathext = ".com;.exe;.bat;.cmd"; + } + return pathext; +} + +/// Checks if file `name` is executable under one of these conditions: +/// - if the file extension is in $PATHEXT +/// - if the result of any $PATHEXT extension appended to `name` is executable static bool is_executable_ext(char *name, const char *pathext, char_u **abspath) FUNC_ATTR_NONNULL_ARG(1, 2) { + char *nameext = strrchr(name, '.'); + size_t nameext_len = nameext ? strlen(nameext) : 0; xstrlcpy(os_buf, name, sizeof(os_buf)); char *buf_end = xstrchrnul(os_buf, '\0'); for (const char *ext = pathext; *ext; ext++) { - // Skip the extension if there is no suffix after a '.'. + // If $PATHEXT itself contains dot: if (ext[0] == '.' && (ext[1] == '\0' || ext[1] == ENV_SEPCHAR)) { + if (is_executable(name, abspath)) { + return true; + } + // Skip the extension. ext++; continue; } const char *ext_end = xstrchrnul(ext, ENV_SEPCHAR); - STRLCPY(buf_end, ext, ext_end - ext + 1); + size_t ext_len = (size_t)(ext_end - ext); + STRLCPY(buf_end, ext, ext_len + 1); + bool in_pathext = nameext_len == ext_len + && 0 == mb_strnicmp((char_u *)nameext, (char_u *)ext, ext_len); - if (is_executable(os_buf, abspath)) { + if (in_pathext || is_executable(os_buf, abspath)) { return true; } @@ -421,8 +391,7 @@ static bool is_executable_in_path(const char_u *name, char_u **abspath) append_path(buf, (char *)name, buf_len); #ifdef WIN32 - if ((is_extension_executable(buf) && is_executable(buf, abspath)) - || is_executable_ext(buf, pathext, abspath)) { + if (is_executable_ext(buf, pathext, abspath)) { #else if (is_executable(buf, abspath)) { #endif -- cgit From a7cc18e5635ca4a1515167d331cd582e53471636 Mon Sep 17 00:00:00 2001 From: erw7 Date: Mon, 1 Apr 2019 19:29:12 +0900 Subject: fs.c: fix is_executable_ext - Fix the problem of checking the extension in a UNIX like shell. - Fix the problem of not checking the existence of the file when the pathext contains an extension. --- src/nvim/os/fs.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 6ac53dd45b..388faddac1 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -331,10 +331,12 @@ static bool is_executable_ext(char *name, const char *pathext, char_u **abspath) const char *ext_end = xstrchrnul(ext, ENV_SEPCHAR); size_t ext_len = (size_t)(ext_end - ext); STRLCPY(buf_end, ext, ext_len + 1); - bool in_pathext = nameext_len == ext_len - && 0 == mb_strnicmp((char_u *)nameext, (char_u *)ext, ext_len); + bool in_pathext = (strstr((char *)path_tail(p_sh), "sh") != NULL) + || (nameext_len == ext_len + && 0 == mb_strnicmp((char_u *)nameext, (char_u *)ext, ext_len)); - if (in_pathext || is_executable(os_buf, abspath)) { + if ((in_pathext && is_executable(name, abspath)) + || is_executable(os_buf, abspath)) { return true; } -- cgit From cc6d3f79031cdae42f0717547d76c27e63e9fe07 Mon Sep 17 00:00:00 2001 From: erw7 Date: Mon, 1 Apr 2019 20:37:10 +0900 Subject: fs.c: Simplify calling is_executable_ext --- src/nvim/os/fs.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 388faddac1..5c71abd000 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -254,8 +254,7 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) if (no_path) { #ifdef WIN32 - const char *pathext = get_pathext(); - if (is_executable_ext((char *)name, pathext, abspath)) { + if (is_executable_ext((char *)name, abspath)) { #else // Must have path separator, cannot execute files in the current directory. if ((const char_u *)gettail_dir((const char *)name) != name @@ -298,25 +297,20 @@ static bool is_executable(const char *name, char_u **abspath) } #ifdef WIN32 -static const char *get_pathext(void) -{ - const char *pathext = os_getenv("PATHEXT"); - if (!pathext) { - pathext = ".com;.exe;.bat;.cmd"; - } - return pathext; -} - /// Checks if file `name` is executable under one of these conditions: /// - if the file extension is in $PATHEXT /// - if the result of any $PATHEXT extension appended to `name` is executable -static bool is_executable_ext(char *name, const char *pathext, char_u **abspath) +static bool is_executable_ext(char *name, char_u **abspath) FUNC_ATTR_NONNULL_ARG(1, 2) { char *nameext = strrchr(name, '.'); size_t nameext_len = nameext ? strlen(nameext) : 0; xstrlcpy(os_buf, name, sizeof(os_buf)); char *buf_end = xstrchrnul(os_buf, '\0'); + const char *pathext = os_getenv("PATHEXT"); + if (!pathext) { + pathext = ".com;.exe;.bat;.cmd"; + } for (const char *ext = pathext; *ext; ext++) { // If $PATHEXT itself contains dot: if (ext[0] == '.' && (ext[1] == '\0' || ext[1] == ENV_SEPCHAR)) { @@ -373,12 +367,6 @@ static bool is_executable_in_path(const char_u *name, char_u **abspath) #endif size_t buf_len = STRLEN(name) + strlen(path) + 2; - -#ifdef WIN32 - const char *pathext = get_pathext(); - buf_len += strlen(pathext); -#endif - char *buf = xmalloc(buf_len); // Walk through all entries in $PATH to check if "name" exists there and @@ -393,7 +381,7 @@ static bool is_executable_in_path(const char_u *name, char_u **abspath) append_path(buf, (char *)name, buf_len); #ifdef WIN32 - if (is_executable_ext(buf, pathext, abspath)) { + if (is_executable_ext(buf, abspath)) { #else if (is_executable(buf, abspath)) { #endif -- cgit From e62f4cc1226c27d1628437540f12e0837e8239b7 Mon Sep 17 00:00:00 2001 From: erw7 Date: Mon, 1 Apr 2019 22:14:33 +0900 Subject: fs.c: Move sh check of is_executable_ext to outside of loop --- src/nvim/os/fs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 5c71abd000..71e76e2a78 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -303,6 +303,7 @@ static bool is_executable(const char *name, char_u **abspath) static bool is_executable_ext(char *name, char_u **abspath) FUNC_ATTR_NONNULL_ARG(1, 2) { + const bool is_unix_shell = strstr((char *)path_tail(p_sh), "sh") != NULL; char *nameext = strrchr(name, '.'); size_t nameext_len = nameext ? strlen(nameext) : 0; xstrlcpy(os_buf, name, sizeof(os_buf)); @@ -325,11 +326,10 @@ static bool is_executable_ext(char *name, char_u **abspath) const char *ext_end = xstrchrnul(ext, ENV_SEPCHAR); size_t ext_len = (size_t)(ext_end - ext); STRLCPY(buf_end, ext, ext_len + 1); - bool in_pathext = (strstr((char *)path_tail(p_sh), "sh") != NULL) - || (nameext_len == ext_len - && 0 == mb_strnicmp((char_u *)nameext, (char_u *)ext, ext_len)); + bool in_pathext = nameext_len == ext_len + && 0 == mb_strnicmp((char_u *)nameext, (char_u *)ext, ext_len); - if ((in_pathext && is_executable(name, abspath)) + if (((in_pathext || is_unix_shell) && is_executable(name, abspath)) || is_executable(os_buf, abspath)) { return true; } -- cgit From a062d307fb79a36488641c0815813297efa614d0 Mon Sep 17 00:00:00 2001 From: erw7 Date: Mon, 1 Apr 2019 23:36:16 +0900 Subject: [ci skip] fs.c: fix comment --- src/nvim/os/fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 71e76e2a78..2621d9da74 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -298,7 +298,7 @@ static bool is_executable(const char *name, char_u **abspath) #ifdef WIN32 /// Checks if file `name` is executable under one of these conditions: -/// - if the file extension is in $PATHEXT +/// - if the file extension is in $PATHEXT and `name` is executable /// - if the result of any $PATHEXT extension appended to `name` is executable static bool is_executable_ext(char *name, char_u **abspath) FUNC_ATTR_NONNULL_ARG(1, 2) -- cgit From 70a0a12b5397b8b787a3196e9196f5fdbf979cf6 Mon Sep 17 00:00:00 2001 From: erw7 Date: Tue, 2 Apr 2019 05:08:40 +0900 Subject: fs.c: fix is_executable_ext() - Corresponds to the case where pathext contains a zero-length extension. - Remove unnecessary break statements. - Fix function attributes. --- src/nvim/os/fs.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 2621d9da74..91ed639a1b 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -301,7 +301,7 @@ static bool is_executable(const char *name, char_u **abspath) /// - if the file extension is in $PATHEXT and `name` is executable /// - if the result of any $PATHEXT extension appended to `name` is executable static bool is_executable_ext(char *name, char_u **abspath) - FUNC_ATTR_NONNULL_ARG(1, 2) + FUNC_ATTR_NONNULL_ARG(1) { const bool is_unix_shell = strstr((char *)path_tail(p_sh), "sh") != NULL; char *nameext = strrchr(name, '.'); @@ -325,17 +325,15 @@ static bool is_executable_ext(char *name, char_u **abspath) const char *ext_end = xstrchrnul(ext, ENV_SEPCHAR); size_t ext_len = (size_t)(ext_end - ext); - STRLCPY(buf_end, ext, ext_len + 1); - bool in_pathext = nameext_len == ext_len - && 0 == mb_strnicmp((char_u *)nameext, (char_u *)ext, ext_len); - - if (((in_pathext || is_unix_shell) && is_executable(name, abspath)) - || is_executable(os_buf, abspath)) { - return true; - } + if (ext_len != 0) { + STRLCPY(buf_end, ext, ext_len + 1); + bool in_pathext = nameext_len == ext_len + && 0 == mb_strnicmp((char_u *)nameext, (char_u *)ext, ext_len); - if (*ext_end != ENV_SEPCHAR) { - break; + if (((in_pathext || is_unix_shell) && is_executable(name, abspath)) + || is_executable(os_buf, abspath)) { + return true; + } } ext = ext_end; } -- cgit From c7039fd0d3f6f5d7c8699fd88095e100f0754e59 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 1 Apr 2019 23:21:38 +0200 Subject: test: "$PATHEXT=::" --- src/nvim/os/fs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 91ed639a1b..8d9de1253e 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -297,9 +297,9 @@ static bool is_executable(const char *name, char_u **abspath) } #ifdef WIN32 -/// Checks if file `name` is executable under one of these conditions: -/// - if the file extension is in $PATHEXT and `name` is executable -/// - if the result of any $PATHEXT extension appended to `name` is executable +/// Checks if file `name` is executable under any of these conditions: +/// - extension is in $PATHEXT and `name` is executable +/// - result of any $PATHEXT extension appended to `name` is executable static bool is_executable_ext(char *name, char_u **abspath) FUNC_ATTR_NONNULL_ARG(1) { @@ -318,7 +318,7 @@ static bool is_executable_ext(char *name, char_u **abspath) if (is_executable(name, abspath)) { return true; } - // Skip the extension. + // Skip it. ext++; continue; } -- cgit