| #!/bin/bash |
| |
| # If using normal root, avoid changing anything. |
| if [ -z "$RPM_BUILD_ROOT" -o "$RPM_BUILD_ROOT" = "/" ]; then |
| exit 0 |
| fi |
| |
| exclude_files="" |
| exclude_files_from="" |
| exclude_shebangs="" |
| exclude_shebangs_from="" |
| |
| usage() { |
| local verbose=$1 && shift |
| local outfile=$1 && shift |
| local status=$1 && shift |
| |
| ( |
| echo 'usage: brp-mangle-shebangs [--files <regexp>] [--files-from <file>] [--shebangs <regexp>] [--shebangs-from <file>]' |
| if [ "${verbose}" == "yes" ]; then |
| echo ' --files: extended regexp of files to ignore' |
| echo ' --files-from: file containing a list of extended regexps of files to ignore' |
| echo ' --shebangs: extended regexp of shebangs to ignore' |
| echo ' --shebangs-from: file containing a list of extended regexps of shebangs to ignore' |
| fi |
| ) >>${outfile} |
| exit ${status} |
| } |
| |
| while [ $# -gt 0 ] ; do |
| case "$1" in |
| --files) |
| exclude_files="${2}" |
| shift |
| ;; |
| --files=*) |
| exclude_files="${1##--files=}" |
| ;; |
| --files-from) |
| exclude_files_from="${2}" |
| shift |
| ;; |
| --files-from=*) |
| exclude_files_from="${1##--files-from=}" |
| ;; |
| --shebangs) |
| exclude_shebangs="${2}" |
| shift |
| ;; |
| --shebangs=*) |
| exclude_shebangs="${1##--shebangs=}" |
| ;; |
| --shebangs-from) |
| exclude_shebangs_from="${2}" |
| shift |
| ;; |
| --shebangs-from=*) |
| exclude_shebangs_from="${1##--shebangs-from=}" |
| ;; |
| --help|--usage|"-?"|-h) |
| usage yes /dev/stdout 0 |
| ;; |
| *) |
| echo "Unknown option \"${1}\"" 1>&2 |
| usage no /dev/stderr 1 |
| ;; |
| esac |
| shift |
| done |
| |
| cd "$RPM_BUILD_ROOT" |
| |
| # 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 line; do |
| f=${line%%:*} |
| |
| # Remove the dot |
| path="${f#.}" |
| |
| if [ -n "$exclude_files" ]; then |
| echo "$path" | grep -q -E "$exclude_files" && continue |
| fi |
| if [ -n "$exclude_files_from" ]; then |
| echo "$path" | grep -q -E -f "$exclude_files_from" && continue |
| fi |
| |
| |
| 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 |
| |
| 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 shebang, removing executable bit" |
| ts=$(stat -c %y "$f") |
| chmod -x "$f" |
| touch -d "$ts" "$f" |
| continue |
| fi |
| if [ -n "${shebang##/*}" ]; then |
| echo >&2 "*** ERROR: $f has shebang which doesn't start with '/' ($shebang)" |
| fail=1 |
| continue |
| fi |
| |
| if ! { echo "$shebang" | grep -q -P "^/(?:usr/)?(?:bin|sbin)/"; }; then |
| continue |
| 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@') |
| |
| # Replace python3 with the desired Python 3 shebang, |
| # if passed as an non-empty environment variable PYTHON3 |
| if [ -n "${PYTHON3:+x}" ]; then |
| shebang=$(echo "$shebang" | sed -r -e "s@/usr/bin/python3(\s|$)@${PYTHON3}\1@") |
| fi |
| |
| # Replace ambiguous python with python2 |
| py_shebang=$(echo "$shebang" | sed -r -e 's@/usr/bin/python(\s|$)@/usr/bin/python2\1@') |
| |
| 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 |
| 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 |
| |
| done |
| |
| exit $fail |
| } |