tinyramfs: code cleanup

This commit is contained in:
illiliti 2021-05-10 14:42:11 +03:00
parent 50d18b28a5
commit bd16dcbd77

120
tinyramfs
View File

@ -1,8 +1,8 @@
#!/bin/sh #!/bin/sh
# #
# tiny initramfs # Tiny initramfs
# #
# false positive # https://www.shellcheck.net/wiki/SC2154
# shellcheck disable=2154 # shellcheck disable=2154
print() print()
@ -13,39 +13,27 @@ print()
panic() panic()
{ {
print "${1:-unexpected error occurred}" \ print "${1:-unexpected error occurred}" \
"\033[1;31m!!\033[m" >&2; exit 1 "\033[1;31m!!\033[m"
}
exit 1
} >&2
usage() usage()
{ {
cat << EOF cat << EOF
usage: ${0##*/} [option ...] usage: ${0##*/} [option]...
-o, --output <file> set initramfs output path -o, --output <file> set initramfs output path
default is /boot/initramfs-$(uname -r) -c, --config <file> set config file path
-m, --modules <dir> set modules directory
-c, --config <file> set config file path -s, --sources <dir> set sources directory
default is /etc/tinyramfs/config -k, --kernel <ver> set kernel version
-H, --hooks <dir> set hooks directory
-m, --modules <dir> set modules directory -d, --debug enable debug mode
default is /lib/modules -f, --force overwrite initramfs image
-s, --sources <dir> set sources directory
default is /usr/share/tinyramfs
-k, --kernel <ver> set kernel version
default is $(uname -r)
-H, --hooks <dir> set hooks directory
default is /etc/tinyramfs/hooks (user hooks)
and /usr/share/tinyramfs/hooks (system hooks)
-d, --debug enable debug mode
-f, --force overwrite initramfs image
EOF EOF
} }
prepare_environment() parse_arguments()
{ {
while [ "$1" ]; do case "$1" in while [ "$1" ]; do case "$1" in
-o | --output) -o | --output)
@ -76,15 +64,13 @@ prepare_environment()
usage; exit 0 usage; exit 0
;; ;;
*) *)
printf "invalid option: %s\n\n" "$1" printf "invalid option: %s\n" "$1"
usage; exit 1 usage; exit 1
;; ;;
esac; done esac; done
print "preparing environment" # https://www.shellcheck.net/wiki/SC1090
# false positive
# shellcheck disable=1090 # shellcheck disable=1090
. "${config:=/etc/tinyramfs/config}" . "${config:=/etc/tinyramfs/config}"
@ -95,7 +81,7 @@ prepare_environment()
mkdir -p "${tmpdir:=${TMPDIR:-/tmp}/tinyramfs.$$}" mkdir -p "${tmpdir:=${TMPDIR:-/tmp}/tinyramfs.$$}"
# false positive # https://www.shellcheck.net/wiki/SC2015
# shellcheck disable=2015 # shellcheck disable=2015
[ "$debug" = 1 ] && set -x || trap 'rm -rf $tmpdir' EXIT INT [ "$debug" = 1 ] && set -x || trap 'rm -rf $tmpdir' EXIT INT
} }
@ -104,7 +90,7 @@ prepare_initramfs()
{ {
print "preparing initramfs" print "preparing initramfs"
# make directories # https://wikipedia.org/wiki/Filesystem_Hierarchy_Standard
mkdir -p \ mkdir -p \
"${tmpdir}/dev" \ "${tmpdir}/dev" \
"${tmpdir}/sys" \ "${tmpdir}/sys" \
@ -118,7 +104,6 @@ prepare_initramfs()
"${tmpdir}/mnt/root" \ "${tmpdir}/mnt/root" \
"${tmpdir}/etc/tinyramfs" "${tmpdir}/etc/tinyramfs"
# make symlinks
ln -s usr/lib "${tmpdir}/lib" ln -s usr/lib "${tmpdir}/lib"
ln -s usr/bin "${tmpdir}/bin" ln -s usr/bin "${tmpdir}/bin"
ln -s usr/bin "${tmpdir}/sbin" ln -s usr/bin "${tmpdir}/sbin"
@ -126,7 +111,6 @@ prepare_initramfs()
ln -s ../run/lock "${tmpdir}/var/lock" ln -s ../run/lock "${tmpdir}/var/lock"
ln -s bin "${tmpdir}/usr/sbin" ln -s bin "${tmpdir}/usr/sbin"
# copy required binaries
for _binary in \ for _binary in \
\[ sh ln env kill mkdir sleep mount \ \[ sh ln env kill mkdir sleep mount \
printf switch_root "${srcdir}/device-helper" printf switch_root "${srcdir}/device-helper"
@ -144,12 +128,11 @@ copy_file()
( (
file="$1"; dest="$2"; mode="$3"; strip="$4" file="$1"; dest="$2"; mode="$3"; strip="$4"
# check if file already exist
[ -e "${tmpdir}${dest}" ] && return 0 [ -e "${tmpdir}${dest}" ] && return 0
mkdir -p "${tmpdir}${dest%/*}" || panic mkdir -p "${tmpdir}${dest%/*}" || panic
# iterate throught symlinks and copy them # Iterate throught symlinks and copy them
while [ -h "$file" ]; do while [ -h "$file" ]; do
cp -P "$file" "${tmpdir}${dest%/*}/${file##*/}" cp -P "$file" "${tmpdir}${dest%/*}/${file##*/}"
cd -P "${file%/*}" cd -P "${file%/*}"
@ -159,7 +142,7 @@ copy_file()
file="${PWD}/${symlink##*/}" file="${PWD}/${symlink##*/}"
done done
# handle case when file and dest have same basenames # Handle case when file and dest have same basenames
[ -h "${tmpdir}${dest}" ] && dest="${dest%/*}/${file##*/}" [ -h "${tmpdir}${dest}" ] && dest="${dest%/*}/${file##*/}"
{ {
@ -167,7 +150,7 @@ copy_file()
chmod "$mode" "${tmpdir}${dest}" chmod "$mode" "${tmpdir}${dest}"
} || panic } || panic
# false positive # https://www.shellcheck.net/wiki/SC2015
# shellcheck disable=2015 # shellcheck disable=2015
[ "$strip" = 1 ] && strip "${tmpdir}${dest}" > /dev/null 2>&1 || : [ "$strip" = 1 ] && strip "${tmpdir}${dest}" > /dev/null 2>&1 || :
) )
@ -176,8 +159,13 @@ copy_binary()
{ {
binary=$(command -v "$1") binary=$(command -v "$1")
# check if binary exist and builtin # If output is
# false positive #
# empty, do panic
# external command, do nothing
# builtin command, try to find external alternative.
#
# https://www.shellcheck.net/wiki/SC2086
# shellcheck disable=2086 # shellcheck disable=2086
case "$binary" in */*) ;; case "$binary" in */*) ;;
"") "")
@ -186,21 +174,17 @@ copy_binary()
*) *)
IFS=:; set -- $PATH; unset IFS IFS=:; set -- $PATH; unset IFS
# assume that `command -v` returned builtin command.
# this behavior depends on shell implementation.
# to be independent we simply iterating over PATH
# to find external alternative ( e.g kill => /bin/kill )
for _dir; do for _dir; do
[ -x "${_dir}/${binary}" ] || ! continue binary="${_dir}/${binary}"
binary="${_dir}/${binary}"; break [ -x "$binary" ] && break
done || panic "$1 does not exist" done || panic "$1 does not exist"
;; ;;
esac esac
copy_file "$binary" "/bin/${binary##*/}" 755 1 copy_file "$binary" "/bin/${binary##*/}" 755 1
# copy binary dependencies if any # Copy binary dependencies if any exist.
ldd "$binary" 2> /dev/null | ldd "$binary" 2> /dev/null |
while read -r _library || [ "$_library" ]; do while read -r _library || [ "$_library" ]; do
@ -222,8 +206,8 @@ copy_module()
while read -r _ module || [ "$module" ]; do while read -r _ module || [ "$module" ]; do
# check if module contains full path(not builtin) # Skip builtin modules.
[ "${module##*/*}" ] && continue case "$module" in */*) ;; *) continue; esac
copy_file "$module" "$module" 644 0 copy_file "$module" "$module" 644 0
done done
@ -234,12 +218,12 @@ copy_hook()
hook="$1" hook="$1"
for _dir in "$hksdir" /etc/tinyramfs/hooks /usr/share/tinyramfs/hooks; do for _dir in "$hksdir" /etc/tinyramfs/hooks /usr/share/tinyramfs/hooks; do
[ -f "${_dir}/${hook}/${hook}" ] || ! continue [ -f "${_dir}/${hook}/${hook}" ] && break
done || panic "could not find $hook hook" done || panic "could not find $hook hook"
print "running $hook hook" print "running $hook hook"
# false positive # https://www.shellcheck.net/wiki/SC1090
# shellcheck disable=1090 # shellcheck disable=1090
. "${_dir}/${hook}/${hook}" . "${_dir}/${hook}/${hook}"
@ -255,22 +239,22 @@ copy_hook()
copy_modules() copy_modules()
{ {
# skip this function if kernel # Skip this function if kernel
# compiled with builtin modules # compiled with builtin modules.
if [ "$monolith" = 1 ]; then if [ "$monolith" = 1 ]; then
return 0 return 0
elif [ "$hostonly" = 1 ]; then elif [ "$hostonly" = 1 ]; then
print "copying hostonly modules" print "copying hostonly modules"
# perform autodetection of modules via /sys # Perform autodetection of modules via /sys
# see https://wiki.archlinux.org/index.php/Modalias # https://wiki.archlinux.org/index.php/Modalias
find /sys/devices -name modalias -exec sort -u {} + | find /sys/devices -name modalias -exec sort -u {} + |
while read -r _module || [ "$_module" ]; do while read -r _module || [ "$_module" ]; do
# skip unneeded modules and skip modules which # Skip unneeded modules and skip modules which
# depends on them as well # depends on them as well.
case $(modprobe -S "$kernel" -D "$_module") in case $(modprobe -S "$kernel" -D "$_module") in
*wmi* | *gpu* | *net*) continue ;; *wmi* | *gpu* | *net*) continue ;;
esac 2> /dev/null esac 2> /dev/null
@ -278,16 +262,14 @@ copy_modules()
copy_module "$_module" copy_module "$_module"
done done
# copy root filesystem module
if [ "$root_type" ]; then if [ "$root_type" ]; then
copy_module "$root_type" copy_module "$root_type"
else else
while read -r _ _dir _type _; do while read -r _ _dir _type _; do
[ "$_dir" = / ] || ! continue [ "$_dir" = / ] && break
done < /proc/mounts || panic "failed to autodetect root fs module"
copy_module "$_type"; break copy_module "$_type"
done < /proc/mounts ||
panic "could not copy root fs module"
fi fi
else else
print "copying all modules" print "copying all modules"
@ -308,11 +290,11 @@ copy_modules()
while read -r _module || [ "$_module" ]; do while read -r _module || [ "$_module" ]; do
# strip path and extension # Strip path and extension
_module="${_module##*/}" _module="${_module##*/}"
_module="${_module%%.*}" _module="${_module%%.*}"
# skip unneeded modules and skip modules which # Skip unneeded modules and skip modules which
# depends on them as well # depends on them as well
case $(modprobe -S "$kernel" -D "$_module") in case $(modprobe -S "$kernel" -D "$_module") in
*wmi* | *gpu* | *net*) continue ;; *wmi* | *gpu* | *net*) continue ;;
@ -334,7 +316,6 @@ make_initramfs()
( (
print "generating initramfs image" print "generating initramfs image"
# check if image already exist
[ "$force" != 1 ] && [ -e "$output" ] && [ "$force" != 1 ] && [ -e "$output" ] &&
panic "initramfs image already exist" panic "initramfs image already exist"
@ -348,13 +329,12 @@ make_initramfs()
[ "$(id -u)" = 0 ] || panic "must be run as root" [ "$(id -u)" = 0 ] || panic "must be run as root"
# enable exit on error and disable globbing # Exit if command fails and disable globbing.
set -ef set -ef
prepare_environment "$@" parse_arguments "$@"
prepare_initramfs prepare_initramfs
# copy and run hooks if any
for _hook in $hooks; do for _hook in $hooks; do
copy_hook "$_hook" copy_hook "$_hook"
done done