| |
@@ -70,13 +70,17 @@
|
| |
|
| |
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/)" \
|
| |
+ | {
|
| |
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,34 @@
|
| |
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
|
| |
- fi
|
| |
- if [ -n "$exclude_shebangs_from" ]; then
|
| |
- echo "$shebang" | grep -q -E -f "$exclude_shebangs_from" && continue
|
| |
+ read shebang_line < "$f"
|
| |
+ 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
|
| |
@@ -132,11 +146,13 @@
|
| |
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
|
| |
+ }
|
| |
See https://bugzilla.redhat.com/show_bug.cgi?id=1773216
For kernel builds, /usr/lib/rpm/redhat/brp-mangle-shebangs runs for 25 seconds.
It's mainly caused by this loop executing "file" and "grep" for every file in the tree:
fail=0
while IFS= read -r -d $'\0' f; do
file -N --mime-type "$f" | grep -q -P ".+(?=: text/)" || continue
...
done < <(find -executable -type f -print0)
exit $fail
The following replacement runs one "file" and one "grep" process to examine all files:
find -executable -type f ! -path ':' ! -path $'\n' \
| file -N --mime-type -f - \
| grep -P ".+(?=: text/)" \
| {
fail=0
while IFS= read -r line; do
f=${line%%:*}
...
done
exit $fail
}
The complicated "find" invocation is skipping any files with colons or newlines in their names.
Tested by me to work, and completes in 3 seconds.