diff options
Diffstat (limited to 'brp-mangle-shebangs')
-rwxr-xr-x | brp-mangle-shebangs | 72 |
1 files changed, 48 insertions, 24 deletions
diff --git a/brp-mangle-shebangs b/brp-mangle-shebangs index ecf8ae7..f27ad73 100755 --- a/brp-mangle-shebangs +++ b/brp-mangle-shebangs @@ -1,4 +1,4 @@ -#!/bin/bash -eu +#!/usr/bin/bash -eu # If using normal root, avoid changing anything. if [ -z "$RPM_BUILD_ROOT" -o "$RPM_BUILD_ROOT" = "/" ]; then @@ -70,13 +70,17 @@ done cd "$RPM_BUILD_ROOT" -trim() { - printf '%s' "$*" -} - +# Large packages such as kernel can have thousands of executable files. +# We take care to not fork/exec thousands of "file"s and "grep"s, +# but run just two of them. +# (Take care to exclude filenames which would mangle "file" output). +find -executable -type f ! -path '*:*' ! -path $'*\n*' \ +| file -N --mime-type -f - \ +| grep -P ".+(?=: (text/|application/javascript))" \ +| { fail=0 -while IFS= read -r -d $'\0' f; do - file -N --mime-type "$f" | grep -q -P ".+(?=: text/)" || continue +while IFS= read -r line; do + f=${line%%:*} # Remove the dot path="${f#.}" @@ -88,24 +92,41 @@ while IFS= read -r -d $'\0' f; do echo "$path" | grep -q -E -f "$exclude_files_from" && continue fi - ts=$(stat -c %y "$f") - read shebang_line < "$f" || : - orig_shebang=$(trim $(echo "$shebang_line" | grep -Po "#!\K.*" || echo)) - shebang="$orig_shebang" - if [ -n "$exclude_shebangs" ]; then - echo "$shebang" | grep -q -E "$exclude_shebangs" && continue + if ! read shebang_line < "$f"; then + echo >&2 "*** WARNING: Cannot read the first line from $f, removing executable bit" + ts=$(stat -c %y "$f") + chmod -x "$f" + touch -d "$ts" "$f" + continue fi - if [ -n "$exclude_shebangs_from" ]; then - echo "$shebang" | grep -q -E -f "$exclude_shebangs_from" && continue + + orig_shebang="${shebang_line#\#!}" + if [ "$orig_shebang" = "$shebang_line" ]; then + echo >&2 "*** WARNING: $f is executable but has no shebang, removing executable bit" + ts=$(stat -c %y "$f") + chmod -x "$f" + touch -d "$ts" "$f" + continue fi + # Trim spaces + while shebang="${orig_shebang// / }"; [ "$shebang" != "$orig_shebang" ]; do + orig_shebang="$shebang" + done + # Treat "#! /path/to " as "#!/path/to" + orig_shebang="${orig_shebang# }" + + shebang="$orig_shebang" + if [ -z "$shebang" ]; then - echo >&2 "*** WARNING: $f is executable but has empty or no shebang, removing executable bit" + echo >&2 "*** WARNING: $f is executable but has empty shebang, removing executable bit" + ts=$(stat -c %y "$f") chmod -x "$f" touch -d "$ts" "$f" continue - elif [ -n "${shebang##/*}" ]; then + fi + if [ -n "${shebang##/*}" ]; then echo >&2 "*** ERROR: $f has shebang which doesn't start with '/' ($shebang)" fail=1 continue @@ -116,10 +137,10 @@ while IFS= read -r -d $'\0' f; do fi # Replace "special" env shebang: - # /whatsoever/env /whatever/foo → /whatever/foo - shebang=$(echo "$shebang" | sed -r -e 's@^(.+)/env /(.+)$@/\2@') - # /whatsoever/env foo → /whatsoever/foo - shebang=$(echo "$shebang" | sed -r -e 's@^(.+/)env (.+)$@\1\2@') + # /whatsoever/env -whatever /whatever/foo → /whatever/foo + shebang=$(echo "$shebang" | sed -r -e 's@^(.+)/env( -[^ ]+)* /(.+)$@/\3@') + # /whatsoever/env -whatever foo → /whatsoever/foo + shebang=$(echo "$shebang" | sed -r -e 's@^(.+/)env( -[^ ]+)* (.+)$@\1\3@') # If the shebang now starts with /bin, change it to /usr/bin # https://bugzilla.redhat.com/show_bug.cgi?id=1581757 @@ -130,12 +151,15 @@ while IFS= read -r -d $'\0' f; do if [ "$shebang" != "$py_shebang" ]; then echo >&2 "*** ERROR: ambiguous python shebang in $path: #!$orig_shebang. Change it to python3 (or python2) explicitly." + fail=1 elif [ "#!$shebang" != "#!$orig_shebang" ]; then - sed -i -e "1c #!$shebang" "$f" echo "mangling shebang in $path from $orig_shebang to #!$shebang" + ts=$(stat -c %y "$f") + sed -i -e "1c #!$shebang" "$f" + touch -d "$ts" "$f" fi - touch -d "$ts" "$f" -done < <(find -executable -type f -print0) +done exit $fail +} |