commit:     1fcf8f53423288232b6c3ea15c1e288b62fabbba
Author:     Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Wed Jun 25 00:58:29 2025 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Sat Jun 28 02:30:15 2025 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=1fcf8f53

ecompress-file: correctly delete compressed files in compress_file()

Presently, the compress_file() function contains a command whose purpose
is to delete any existing, compressed instances of the files whose names
are defined by the positional parameters. It employs a pattern-replacing
parameter expansion, transforming the positional parameters in such a
way that the value of the 'PORTAGE_COMPRESS_SUFFIX' variable is appended
to each of the resulting words.

However, it also appends the <SOH> character to each word, ostensibly
for the purpose of being treated as a pathname terminator. To do so is
fundamentally incorrect, since all bytes are legal in pathname
components, save for <slash> and the null byte.

What's more, the resulting words are conveyed to the echo builtin,
whereupon they are joined by a <space> into a single stream. This stream
then undergoes a transformation whereby <SOH> is replaced by the null
byte. Finally, the resulting stream is conveyed to xargs(1) for reading.

Put simply, the code is poppycock. Consider the following.

$ set -- foo bar baz
$ touch "$@"
$ echo -n "${@/%/$'\001'}" | tr '\001' '\000' | xargs -0 rm
rm: cannot remove ' bar': No such file or directory
rm: cannot remove ' baz': No such file or directory

The correct way to write the above would be as follows.

$ printf '%s\0' "$@" | xargs -0 rm --

This commit addresses the aforementioned defects in the manner
described. Namely, by using the printf builtin to produce a stream of
null-terminated pathnames that is directly consumed by xargs(1).
Further, the "--" operand is passed to rm(1) to signify end-of-options.

Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
Signed-off-by: Sam James <sam <AT> gentoo.org>

 bin/ecompress-file | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/bin/ecompress-file b/bin/ecompress-file
index a1009c0289..2916ecf171 100755
--- a/bin/ecompress-file
+++ b/bin/ecompress-file
@@ -44,8 +44,10 @@ compress_file() {
        # If a compressed version of the file already exists, simply
        # delete it so that the compressor doesn't whine (bzip2 will
        # complain and skip, gzip will prompt for input)
-       [[ -n ${PORTAGE_COMPRESS_SUFFIX} ]] && echo -n 
"${@/%/${PORTAGE_COMPRESS_SUFFIX}$'\001'}" | \
-               tr '\001' '\000' | ${XARGS} -0 rm -f
+       if [[ ${PORTAGE_COMPRESS_SUFFIX} ]]; then
+               printf '%s\0' "${@/%/${PORTAGE_COMPRESS_SUFFIX}}" \
+               | ${XARGS} -0 rm -f --
+       fi
 
        # forcibly break all hard links as some compressors whine about it
        while IFS= read -d '' -r x ; do

Reply via email to