copy-firmware.sh (4866B)
1 #!/bin/sh 2 # SPDX-License-Identifier: GPL-2.0 3 # 4 # Copy firmware files based on WHENCE list 5 # 6 7 verbose=: 8 # shellcheck disable=SC2209 9 compress=cat 10 compext= 11 destdir= 12 num_jobs=1 13 14 usage() { 15 echo "Usage: $0 [-v] [-jN] [--xz|--zstd] <destination directory>" 16 } 17 18 err() { 19 printf "ERROR: %s\n" "$*" 20 usage 21 exit 1 22 } 23 24 warn() { 25 printf "WARNING: %s\n" "$*" 26 } 27 28 has_gnu_parallel() { 29 if command -v parallel > /dev/null; then 30 # The moreutils package comes with a simpler version of "parallel" 31 # that does not support the --version or -a options. Check for 32 # that first. In some distros, installing the "parallel" package 33 # will replace the moreutils version with the GNU version. 34 if ! parallel --version > /dev/null 2>&1; then 35 return 1 36 fi 37 if parallel --version | grep -Fqi 'gnu parallel'; then 38 return 0 39 fi 40 fi 41 return 1 42 } 43 44 while test $# -gt 0; do 45 case $1 in 46 -v | --verbose) 47 # shellcheck disable=SC2209 48 verbose=echo 49 shift 50 ;; 51 52 -j*) 53 num_jobs=$(echo "$1" | sed 's/-j//') 54 num_jobs=${num_jobs:-1} 55 if [ "$num_jobs" -gt 1 ] && ! has_gnu_parallel; then 56 err "the GNU parallel command is required to use -j" 57 fi 58 parallel_args_file=$(mktemp) 59 trap 'rm -f $parallel_args_file' EXIT INT QUIT TERM 60 shift 61 ;; 62 63 --xz) 64 if test "$compext" = ".zst"; then 65 err "cannot mix XZ and ZSTD compression" 66 fi 67 compress="xz --compress --quiet --stdout --check=crc32" 68 compext=".xz" 69 shift 70 ;; 71 72 --zstd) 73 if test "$compext" = ".xz"; then 74 err "cannot mix XZ and ZSTD compression" 75 fi 76 # shellcheck disable=SC2209 77 compress="zstd --compress --quiet --stdout" 78 compext=".zst" 79 shift 80 ;; 81 82 -h|--help) 83 usage 84 exit 1 85 ;; 86 87 -*) 88 # Ignore anything else that begins with - because that confuses 89 # the "test" command below 90 warn "ignoring option $1" 91 shift 92 ;; 93 94 *) 95 if test -n "$destdir"; then 96 err "unknown command-line options: $*" 97 fi 98 99 destdir="$1" 100 shift 101 ;; 102 esac 103 done 104 105 if test -z "$destdir"; then 106 err "destination directory was not specified" 107 fi 108 109 if test -d "$destdir"; then 110 find "$destdir" -type d -empty >/dev/null || warn "destination folder is not empty." 111 fi 112 113 if test -e .git/config; then 114 $verbose "Checking that WHENCE file is formatted properly" 115 ./check_whence.py || err "check_whence.py has detected errors." 116 fi 117 118 # shellcheck disable=SC2162 # file/folder name can include escaped symbols 119 grep -E '^(RawFile|File):' WHENCE | sed -E -e 's/^(RawFile|File): */\1 /;s/"//g' | while read k f; do 120 install -d "$destdir/$(dirname "$f")" 121 $verbose "copying/compressing file $f$compext" 122 if test "$compress" != "cat" && test "$k" = "RawFile"; then 123 $verbose "compression will be skipped for file $f" 124 if [ "$num_jobs" -gt 1 ]; then 125 echo "cat \"$f\" > \"$destdir/$f\"" >> "$parallel_args_file" 126 else 127 cat "$f" > "$destdir/$f" 128 fi 129 else 130 if [ "$num_jobs" -gt 1 ]; then 131 echo "$compress \"$f\" > \"$destdir/$f$compext\"" >> "$parallel_args_file" 132 else 133 $compress "$f" > "$destdir/$f$compext" 134 fi 135 fi 136 done 137 if [ "$num_jobs" -gt 1 ]; then 138 parallel -j"$num_jobs" -a "$parallel_args_file" 139 echo > "$parallel_args_file" # prepare for next run 140 fi 141 142 # shellcheck disable=SC2162 # file/folder name can include escaped symbols 143 grep -E '^Link:' WHENCE | sed -e 's/^Link: *//g;s/-> //g' | while read l t; do 144 directory="$destdir/$(dirname "$l")" 145 install -d "$directory" 146 target="$(cd "$directory" && realpath "$t")" 147 if test -e "$target"; then 148 $verbose "creating link $l -> $t" 149 if [ "$num_jobs" -gt 1 ]; then 150 echo "ln -s \"$t\" \"$destdir/$l\"" >> "$parallel_args_file" 151 else 152 ln -s "$t" "$destdir/$l" 153 fi 154 else 155 $verbose "creating link $l$compext -> $t$compext" 156 if [ "$num_jobs" -gt 1 ]; then 157 echo "ln -s \"$t$compext\" \"$destdir/$l$compext\"" >> "$parallel_args_file" 158 else 159 ln -s "$t$compext" "$destdir/$l$compext" 160 fi 161 fi 162 done 163 if [ "$num_jobs" -gt 1 ]; then 164 parallel -j"$num_jobs" -a "$parallel_args_file" 165 fi 166 167 # Verify no broken symlinks 168 #if test "$(find "$destdir" -xtype l | wc -l)" -ne 0 ; then 169 # err "Broken symlinks found:\n$(find "$destdir" -xtype l)" 170 #fi 171 172 exit 0 173 174 # vim: et sw=4 sts=4 ts=4