aboutsummaryrefslogtreecommitdiffstats
path: root/src/sort.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2025-10-30 10:15:09 +0100
committerPádraig Brady <P@draigBrady.com>2025-10-30 18:34:49 +0000
commit1cfc35ab4c41c49743c8494bea23f168eccae879 (patch)
tree8d415945f27092902a04c60b0713f0f7224c2267 /src/sort.c
parentsort: fix silent exit upon SIGPIPE from --compress-program (diff)
downloadcoreutils-1cfc35ab4c41c49743c8494bea23f168eccae879.tar.gz
coreutils-1cfc35ab4c41c49743c8494bea23f168eccae879.zip
sort: consistently diagnose access issues to --compress-program
* 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.
Diffstat (limited to '')
-rw-r--r--src/sort.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/sort.c b/src/sort.c
index 78b2f69f9..3bb5cc8dd 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -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)
{