summaryrefslogtreecommitdiff
path: root/run-command.c
diff options
context:
space:
mode:
authorBrandon Williams <bmwill@google.com>2017-04-25 23:46:59 (GMT)
committerJunio C Hamano <gitster@pobox.com>2017-04-26 01:45:29 (GMT)
commit38124a40e480c1717326b7bc27bcbca758de908e (patch)
treece31606c4c21865813559aa1315dc4e13d111be4 /run-command.c
parent45afb1ca9c28855096c94926e5b16dfbcde7381f (diff)
downloadgit-38124a40e480c1717326b7bc27bcbca758de908e.zip
git-38124a40e480c1717326b7bc27bcbca758de908e.tar.gz
git-38124a40e480c1717326b7bc27bcbca758de908e.tar.bz2
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.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/run-command.c b/run-command.c
index a97d7bf..2ffbd7e 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");