]> Savannah Git Hosting - gnulib.git/commitdiff
findprog-in: Improve errno upon failure on native Windows.
authorBruno Haible <bruno@clisp.org>
Thu, 24 Dec 2020 12:32:39 +0000 (13:32 +0100)
committerBruno Haible <bruno@clisp.org>
Thu, 24 Dec 2020 12:32:39 +0000 (13:32 +0100)
* 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.

ChangeLog
lib/findprog-in.c
tests/test-spawn-pipe-script.c

index e7e5f11ed95e4601af78034f781ae71ac154b0d9..72eb5023933510430589dbbaf704df889e92ffa3 100644 (file)
--- 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.
index 63b8419630f788cb75141f2cf36846073b6835bf..d0505fb0df534022cf674edb437fb291ce1b774a 100644 (file)
@@ -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);
 
index 44f9d2cea602c99bec4dbdf92cec526c46812fb5..dbd28ed5ab72b81dd5ab51e5760a401385bc6ca1 100644 (file)
@@ -56,11 +56,7 @@ main ()
     else
       {
         ASSERT (pid == -1);
-#if defined _WIN32 && !defined __CYGWIN__
-        ASSERT (errno == ENOENT);
-#else
         ASSERT (errno == ENOEXEC);
-#endif
       }
   }