]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
sort: consistently diagnose access issues to --compress-program
authorBruno Haible <bruno@clisp.org>
Thu, 30 Oct 2025 09:15:09 +0000 (10:15 +0100)
committerPádraig Brady <P@draigBrady.com>
Thu, 30 Oct 2025 18:34:49 +0000 (18:34 +0000)
* bootstrap.conf (gnulib_modules): Add findprog-in.
* src/sort.c: Include findprog.h.
(pipe_child): Look up the compress_program in $PATH and report errors
such as ENOENT or EACCES before invoking posix_spawnp.
This avoids inconsistency on systems that emulate posix_spawn through
fork/exec, as they would otherwise treat such a failure as a generic
failure and fail the sort, rather than continuing without compression.

bootstrap.conf
src/sort.c

index 6654f61ef40e2e30a0605d0a58eda03589703fb3..3a5a4cfa815d9fdbef097fd84b941e3071c14b69 100644 (file)
@@ -107,6 +107,7 @@ gnulib_modules="
   filemode
   filenamecat
   filevercmp
+  findprog-in
   flexmember
   fnmatch-gnu
   fopen-safer
index 78b2f69f96eca6419971ce57cd2691e0d607bfa6..3bb5cc8dd48d35ccd9d45e160313633efba976a9 100644 (file)
@@ -36,6 +36,7 @@
 #include "c-ctype.h"
 #include "fadvise.h"
 #include "filevercmp.h"
+#include "findprog.h"
 #include "flexmember.h"
 #include "hard-locale.h"
 #include "hash.h"
@@ -1056,6 +1057,8 @@ static int
 pipe_child (pid_t *pid, int pipefds[2], int tempfd, bool decompress,
             size_t tries)
 {
+  char const *resolved_compress_program;
+  char *compress_program_to_free;
   struct tempnode *saved_temphead;
   double wait_retry = 0.25;
   struct cs_status cs;
@@ -1063,12 +1066,25 @@ pipe_child (pid_t *pid, int pipefds[2], int tempfd, bool decompress,
   posix_spawnattr_t attr;
   posix_spawn_file_actions_t actions;
 
+  /* Lookup the program before we spawn, so that we consistently
+     handle access issues to COMPRESS_PROGRAM, because on some
+     implementations/emulations of posix_spawn we get only a
+     generic (fatal) error from the child in that case.  */
+  resolved_compress_program =
+    find_in_given_path (compress_program, getenv ("PATH"), NULL, false);
+  if (resolved_compress_program == NULL)
+    return errno;
+  compress_program_to_free = nullptr;
+  if (resolved_compress_program != compress_program)
+    compress_program_to_free = (char *) resolved_compress_program;
+
   if ((result = posix_spawnattr_init (&attr)))
     return result;
   if ((result = posix_spawnattr_setflags (&attr, POSIX_SPAWN_USEVFORK))
       || (result = posix_spawn_file_actions_init (&actions)))
     {
       posix_spawnattr_destroy (&attr);
+      free (compress_program_to_free);
       return result;
     }
 
@@ -1077,6 +1093,7 @@ pipe_child (pid_t *pid, int pipefds[2], int tempfd, bool decompress,
       int saved_errno = errno;
       posix_spawnattr_destroy (&attr);
       posix_spawn_file_actions_destroy (&actions);
+      free (compress_program_to_free);
       return saved_errno;
     }
 
@@ -1102,11 +1119,16 @@ pipe_child (pid_t *pid, int pipefds[2], int tempfd, bool decompress,
       close (pipefds[1]);
       posix_spawnattr_destroy (&attr);
       posix_spawn_file_actions_destroy (&actions);
+      free (compress_program_to_free);
       return result;
     }
 
-  char const *const argv[] = { compress_program, decompress ? "-d" : nullptr,
-                               nullptr };
+  char const *const argv[] =
+    {
+      resolved_compress_program,
+      decompress ? "-d" : nullptr,
+      nullptr
+    };
 
   /* At least NMERGE + 1 subprocesses are needed.  More could be created, but
      uncontrolled subprocess generation can hurt performance significantly.
@@ -1126,7 +1148,7 @@ pipe_child (pid_t *pid, int pipefds[2], int tempfd, bool decompress,
       saved_temphead = temphead;
       temphead = nullptr;
 
-      result = posix_spawnp (pid, compress_program, &actions, &attr,
+      result = posix_spawnp (pid, resolved_compress_program, &actions, &attr,
                              (char * const *) argv, environ);
 
       temphead = saved_temphead;
@@ -1147,6 +1169,7 @@ pipe_child (pid_t *pid, int pipefds[2], int tempfd, bool decompress,
 
   posix_spawnattr_destroy (&attr);
   posix_spawn_file_actions_destroy (&actions);
+  free (compress_program_to_free);
 
   if (result)
     {