add_udev_rules() adds a rules file and pulls in the necessary binaries udev rules by automatically pulling in the necessary binaries. add_systemd_unit() pulls in the necessary binaries, and also Requires= and OnFailure= units. Moreover, it respects reverse soft dependencies by including all the *.wants/ symlinks pointing to the unit. --- functions | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++ man/mkinitcpio.8.txt | 14 +++++++++ 2 files changed, 95 insertions(+) diff --git a/functions b/functions index bb28f34..0ee91d4 100644 --- a/functions +++ b/functions @@ -587,6 +587,87 @@ add_binary() { return 0 } +add_udev_rules() { + # 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 + for pair in "${rule[@]}"; do + IFS='=' read -r key value <<< "$pair" + + case $key in + RUN@({program}|)@(+|)|IMPORT{program}|ENV{REMOVE_CMD}) + binary=${value[0]#\"} + 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,/lib/systemd/system}/*.wants/${unit##*/}; do + if [[ -h "${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 +} + parse_config() { # parse key global variables set by the config file. diff --git a/man/mkinitcpio.8.txt b/man/mkinitcpio.8.txt index 56ac571..ea56741 100644 --- a/man/mkinitcpio.8.txt +++ b/man/mkinitcpio.8.txt @@ -166,6 +166,20 @@ functions exist to facilitate this. script. The name of the script is guaranteed to match the name of the hook the script is called from. +*add_udev_rules*:: + + Adds a udev rules file. Also pulls in the necessary binaries referenced in + the rules. + +*add_systemd_unit*:: + + Adds a systemd unit file. Also pulls in the necessary binaries referenced in + the unit, but only hard dependencies, so not ones prefixed with '-'. + Moreover, hard dependencies on other unit files are added, and reverse soft + dependencies are respected. The latter means that if A wants B and A is + included in the initramfs, the necessary symlink to make A want B in the + initramfs is included if and only if B is included. + About Runtime Hooks ------------------- Runtime hooks added to the image via the *add_runscript* function from an -- 1.8.2.2