summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2020-12-24 13:32:39 +0100
committerBruno Haible <bruno@clisp.org>2020-12-24 13:32:39 +0100
commitd9c121346a283503350c0ac7cd6eb5092e87181b (patch)
treef1100d1ef70a766d85c09ac957b4d162ed5f73c8
parent2845b3bed86ca649d3206d9b1e0fe30a4ca33110 (diff)
downloadgnulib-d9c121346a283503350c0ac7cd6eb5092e87181b.tar.gz
findprog-in: Improve errno upon failure on native Windows.
* lib/findprog-in.c (find_in_given_path): If the file basename has no dot and the search with a suffix returned no result, do also a search without a suffix, and set errno = ENOEXEC if we find a file in this way. * tests/test-spawn-pipe-script.c (main): Update expected errno.
-rw-r--r--ChangeLog8
-rw-r--r--lib/findprog-in.c75
-rw-r--r--tests/test-spawn-pipe-script.c4
3 files changed, 81 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index e7e5f11ed9..72eb502393 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2020-12-24 Bruno Haible <bruno@clisp.org>
+
+ findprog-in: Improve errno upon failure on native Windows.
+ * lib/findprog-in.c (find_in_given_path): If the file basename has no
+ dot and the search with a suffix returned no result, do also a search
+ without a suffix, and set errno = ENOEXEC if we find a file in this way.
+ * tests/test-spawn-pipe-script.c (main): Update expected errno.
+
2020-12-23 Bruno Haible <bruno@clisp.org>
posix_spawn, posix_spawnp: Fix execution of scripts.
diff --git a/lib/findprog-in.c b/lib/findprog-in.c
index 63b8419630..d0505fb0df 100644
--- a/lib/findprog-in.c
+++ b/lib/findprog-in.c
@@ -118,6 +118,8 @@ find_in_given_path (const char *progname, const char *path,
if (ISSLASH (*p))
progbasename = p + 1;
}
+
+ bool progbasename_has_dot = (strchr (progbasename, '.') != NULL);
#endif
/* Try all platform-dependent suffixes. */
@@ -129,7 +131,7 @@ find_in_given_path (const char *progname, const char *path,
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
/* File names without a '.' are not considered executable, and
for file names with a '.' no additional suffix is tried. */
- if ((*suffix != '\0') != (strchr (progbasename, '.') != NULL))
+ if ((*suffix != '\0') != progbasename_has_dot)
#endif
{
/* Concatenate directory_as_prefix, progname, suffix. */
@@ -174,6 +176,36 @@ find_in_given_path (const char *progname, const char *path,
free (progpathname);
}
}
+ #if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
+ if (failure_errno == ENOENT && !progbasename_has_dot)
+ {
+ /* In the loop above, we skipped suffix = "". Do this loop
+ round now, merely to provide a better errno than ENOENT. */
+
+ char *progpathname =
+ concatenated_filename (directory_as_prefix, progname, "");
+
+ if (progpathname == NULL)
+ return NULL; /* errno is set here */
+
+ if (eaccess (progpathname, X_OK) == 0)
+ {
+ struct stat statbuf;
+
+ if (stat (progpathname, &statbuf) >= 0)
+ {
+ if (! S_ISDIR (statbuf.st_mode))
+ errno = ENOEXEC;
+ else
+ errno = EACCES;
+ }
+ }
+
+ failure_errno = errno;
+
+ free (progpathname);
+ }
+ #endif
errno = failure_errno;
return NULL;
@@ -196,6 +228,10 @@ find_in_given_path (const char *progname, const char *path,
char *path_rest;
char *cp;
+ #if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
+ bool progname_has_dot = (strchr (progname, '.') != NULL);
+ #endif
+
failure_errno = ENOENT;
for (path_rest = path_copy; ; path_rest = cp + 1)
{
@@ -243,7 +279,7 @@ find_in_given_path (const char *progname, const char *path,
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
/* File names without a '.' are not considered executable, and
for file names with a '.' no additional suffix is tried. */
- if ((*suffix != '\0') != (strchr (progname, '.') != NULL))
+ if ((*suffix != '\0') != progname_has_dot)
#endif
{
/* Concatenate dir_as_prefix, progname, and suffix. */
@@ -311,6 +347,41 @@ find_in_given_path (const char *progname, const char *path,
free (progpathname);
}
}
+ #if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
+ if (failure_errno == ENOENT && !progname_has_dot)
+ {
+ /* In the loop above, we skipped suffix = "". Do this loop
+ round now, merely to provide a better errno than ENOENT. */
+
+ char *progpathname =
+ concatenated_filename (dir_as_prefix, progname, "");
+
+ if (progpathname == NULL)
+ {
+ /* errno is set here. */
+ failure_errno = errno;
+ free (dir_as_prefix_to_free);
+ goto failed;
+ }
+
+ if (eaccess (progpathname, X_OK) == 0)
+ {
+ struct stat statbuf;
+
+ if (stat (progpathname, &statbuf) >= 0)
+ {
+ if (! S_ISDIR (statbuf.st_mode))
+ errno = ENOEXEC;
+ else
+ errno = EACCES;
+ }
+ }
+
+ failure_errno = errno;
+
+ free (progpathname);
+ }
+ #endif
free (dir_as_prefix_to_free);
diff --git a/tests/test-spawn-pipe-script.c b/tests/test-spawn-pipe-script.c
index 44f9d2cea6..dbd28ed5ab 100644
--- a/tests/test-spawn-pipe-script.c
+++ b/tests/test-spawn-pipe-script.c
@@ -56,11 +56,7 @@ main ()
else
{
ASSERT (pid == -1);
-#if defined _WIN32 && !defined __CYGWIN__
- ASSERT (errno == ENOENT);
-#else
ASSERT (errno == ENOEXEC);
-#endif
}
}