#!/bin/bash strip_quotes() { local len=${#1} quotes=$'[\'"]' str=${!1} if [[ ${str:0:1} = ${str: -1} && ${str:0:1} = $quotes ]]; then declare -g "$1=${str:1:-1}" fi } add_udev_rule() { # Add an udev rules file to the initcpio image. Dependencies on binaries # will be discovered and added. # $1: path to rules file (or name of rules file) local rules= rule= key= value= binary= rules=$(PATH=/usr/lib/udev/rules.d:/lib/udev/rules.d type -P "$1") if [[ -z $rules ]]; then # complain about not found rules return 1 fi add_file "$rules" while IFS=, read -ra rule; do # skip empty lines, comments [[ -z $rule || $rule = @(+([[:space:]])|#*) ]] && continue for pair in "${rule[@]}"; do IFS=' =' read -r key value <<< "$pair" case $key in RUN@({program}|+)|IMPORT{program}|ENV{REMOVE_CMD}) strip_quotes 'value' # just take the first word as the binary name binary=${value%% *} if [[ ${binary:0:1} != '/' ]]; then binary=$(PATH=/usr/lib/udev:/lib/udev type -P "$binary") fi add_binary "$binary" ;; esac done done <"$rules" } add_systemd_unit() { # Add a systemd unit file to the initcpio image. Hard dependencies on binaries # and other unit files will be discovered and added. # $1: path to rules file (or name of rules file) local unit= rule= entry= key= value= binary= dep= unit=$(PATH=/usr/lib/systemd/system:/lib/systemd/system type -P "$1") if [[ -z $unit ]]; then # complain about not found unit file return 1 fi add_file "$unit" while IFS='=' read -r key values; do read -ra values <<< "$values" case $key in Requires|OnFailure) # only add hard dependencies (not Wants) map add_systemd_unit "${values[@]}" ;; Exec*) # don't add binaries unless they are required if [[ ${values[0]:0:1} != '-' ]]; then add_binary "${values[0]}" fi ;; esac done <"$unit" # preserve reverse soft dependency for dep in {/usr,}/lib/systemd/system/*.wants/${unit##*/}; do if [[ -L $dep ]]; then add_symlink "$dep" fi done # add hard dependencies if [[ -d $unit.requires ]]; then for dep in "$unit".requires/*; do add_systemd_unit ${dep##*/} done fi } build() { local rules unit # from base add_binary /bin/mount add_binary /usr/bin/kmod /usr/bin/modprobe # systemd add_binary /usr/lib/systemd/systemd /init add_binary /usr/bin/systemd-tmpfiles # generate sysroot.mount and sysroot-usr.mount add_file "/usr/lib/systemd/system-generators/systemd-fstab-generator" # udev rules and systemd units map add_udev_rule "$rules" \ 50-udev-default.rules \ 60-persistent-storage.rules \ 64-btrfs.rules \ 80-drivers.rules \ 99-systemd.rules \ map add_systemd_unit \ ctrl-alt-del.target \ initrd-cleanup.service \ initrd-fs.target \ initrd-parse-etc.service \ initrd-root-fs.target \ initrd-switch-root.service \ initrd-switch-root.target \ initrd-udevadm-cleanup-db.service \ initrd.target \ kmod-static-nodes.service \ sockets.target \ systemd-fsck@.service \ systemd-journald.service \ systemd-tmpfiles-setup-dev.service \ systemd-udev-trigger.service \ systemd-udevd-control.socket \ systemd-udevd-kernel.socket \ systemd-udevd.service add_symlink "/usr/lib/systemd/system/default.target" "initrd.target" # libdbus needs the passwd info of the root user # TODO: make sure this is no longer necessary when systemctl moves to sd-bus add_file "/etc/nsswitch.conf" add_file "/etc/passwd" add_binary "$(readlink -f /usr/lib/libnss_files.so)" # udev wants /etc/group since it doesn't launch with --resolve-names=never add_file "/etc/group" } help() { cat <