From 5c2241c4b32607f138824c3454b7b32b2916fd02 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 26 Jul 2021 15:05:57 +0100 Subject: win32: more efficient tests for executables file_is_executable() calls access(2) and stat(2); in this case our WIN32 implementation also calls stat(2). Avoid this unnecessary duplication by copying the required test from the WIN32 access(2). In find_executable() it's possible to avoid calling file_is_executable() if add_win32_extension() returns TRUE as the latter will already have verified that the file is executable. Replace a call to file_is_executable() in the tab completion code with the equivalent tests, avoiding (up to) two calls to stat(2). These changes don't affect the size of the binary and should be faster. --- libbb/executable.c | 10 ++++++++-- libbb/lineedit.c | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libbb/executable.c b/libbb/executable.c index e20bf89e4..32b37f29d 100644 --- a/libbb/executable.c +++ b/libbb/executable.c @@ -15,7 +15,12 @@ int FAST_FUNC file_is_executable(const char *name) { struct stat s; +#if !ENABLE_PLATFORM_MINGW32 return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode)); +#else + /* expand WIN32 implementation of access(2) */ + return (!stat(name, &s) && S_ISREG(s.st_mode) && (s.st_mode & S_IXUSR)); +#endif } /* search (*PATHp) for an executable file; @@ -53,12 +58,13 @@ char* FAST_FUNC find_executable(const char *filename, char **PATHp) #if ENABLE_PLATFORM_MINGW32 { char *w = alloc_system_drive(p); - add_win32_extension(w); + ex = add_win32_extension(w) || file_is_executable(w); free(p); p = w; } -#endif +#else ex = file_is_executable(p); +#endif if (n) *n++ = PATH_SEP; if (ex) { *PATHp = n; diff --git a/libbb/lineedit.c b/libbb/lineedit.c index e7de32250..f17c9a215 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -958,8 +958,8 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) goto cont; /* hmm, remove in progress? */ # if ENABLE_PLATFORM_MINGW32 - if (type == FIND_EXE_ONLY && !S_ISDIR(st.st_mode) && - !file_is_executable(found)) + if (type == FIND_EXE_ONLY && S_ISREG(st.st_mode) && + !(st.st_mode & S_IXUSR)) goto cont; # endif -- cgit v1.2.3-55-g6feb