diff options
author | Brandon Williams <bmwill@google.com> | 2017-04-25 16:46:59 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2017-04-25 18:45:29 -0700 |
commit | 38124a40e480c1717326b7bc27bcbca758de908e (patch) | |
tree | ce31606c4c21865813559aa1315dc4e13d111be4 /run-command.c | |
parent | 45afb1ca9c28855096c94926e5b16dfbcde7381f (diff) | |
download | git-38124a40e480c1717326b7bc27bcbca758de908e.tar.gz |
run-command: expose is_executable function
Move the logic for 'is_executable()' from help.c to run_command.c and
expose it so that callers from outside help.c can access the function.
This is to enable run-command to be able to query if a file is
executable in a future patch.
Signed-off-by: Brandon Williams <bmwill@google.com>
Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'run-command.c')
-rw-r--r-- | run-command.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/run-command.c b/run-command.c index a97d7bf9f3..2ffbd7e67b 100644 --- a/run-command.c +++ b/run-command.c @@ -117,6 +117,48 @@ static inline void close_pair(int fd[2]) close(fd[1]); } +int is_executable(const char *name) +{ + struct stat st; + + if (stat(name, &st) || /* stat, not lstat */ + !S_ISREG(st.st_mode)) + return 0; + +#if defined(GIT_WINDOWS_NATIVE) + /* + * On Windows there is no executable bit. The file extension + * indicates whether it can be run as an executable, and Git + * has special-handling to detect scripts and launch them + * through the indicated script interpreter. We test for the + * file extension first because virus scanners may make + * it quite expensive to open many files. + */ + if (ends_with(name, ".exe")) + return S_IXUSR; + +{ + /* + * Now that we know it does not have an executable extension, + * peek into the file instead. + */ + char buf[3] = { 0 }; + int n; + int fd = open(name, O_RDONLY); + st.st_mode &= ~S_IXUSR; + if (fd >= 0) { + n = read(fd, buf, 2); + if (n == 2) + /* look for a she-bang */ + if (!strcmp(buf, "#!")) + st.st_mode |= S_IXUSR; + close(fd); + } +} +#endif + return st.st_mode & S_IXUSR; +} + static char *locate_in_PATH(const char *file) { const char *p = getenv("PATH"); |