[arch-projects] [mkinitcpio][PATCH] functions: add_udev_rules and add_systemd_unit
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 pulls in any symlinks to the unit in any .wants or .requires directories. --- functions | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+)
diff --git a/functions b/functions index 432d700..12df3cd 100644 --- a/functions +++ b/functions @@ -569,6 +569,104 @@ 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 udevdir= rules= rule= entry= key= value= binary= + + udevdir=$(pkg-config --variable=udevdir udev) + + if [[ ${1:0:1} != '/' ]]; then + rules="${udevdir}/rules.d/${1}" + else + rules=$1 + fi + + add_file "${rules}" + + while read rule; do + if [[ ${rule:0:1} == '#' ]]; then + continue + fi + + IFS=', ' + for entry in ${rule}; do + + IFS='=' read key value <<< "${entry}" + + if [[ ( ${key:0:3} == "RUN" && + ${key:4:7} != "builtin" ) || + ${key:0:7} == "PROGRAM" || + ${key:0:15} == "IMPORT{program}" || + ${key:0:15} == "ENV{REMOVE_CMD}" ]]; then + + binary=${value//"/} + if [[ ${binary:0:1} != '/' ]]; then + binary="${udevdir}/${binary}" + fi + + read -d ' ' binary <<< "${binary} " + add_binary "${binary}" + fi + done + done < "$rules" +} + +add_systemd_unit() { + # Add a systemd unit file to the initcpio image. Dependencies on binaries + # and other unit files will be discovered and added. + # $1: path to rules file (or name of rules file) + + local unitdir= unit= rule= entry= key= value= binary= dep= + + unitdir=$(pkg-config --variable=systemdsystemunitdir systemd) + + if [[ ${1:0:1} != '/' ]]; then + unit="${unitdir}/${1}" + else + unit=$1 + fi + + add_file "${unit}" + + while read entry; do + if [[ ${entry:0:1} == '#' ]]; then + continue + fi + + IFS='=' read key value <<< "${entry}" + + if [[ ${key:0:4} == 'Exec' ]]; then + binary=${value//"/} + if [[ ${binary:0:1} != '-' ]]; then + read -d ' ' binary <<< "${binary} " + add_binary "${binary}" + fi + fi + + if [[ ${key} == 'Requires' || ${key} == 'OnFailure' ]]; then + for dep in ${value}; do + add_systemd_unit ${dep} + done + fi + + done < "$unit" + + for dep in "${unitdir}"/*.{wants,requires}/$(basename $unit); do + if [[ -h "${dep}" ]]; then + add_symlink "${dep}" + fi + done + + if [[ -d "${unit}.requires" ]]; then + for dep in "${unit}".requires/*; do + add_systemd_unit $(basename $dep) + done + fi +} + parse_config() { # parse key global variables set by the config file.
On 04/12/2013 10:43 PM, Tom Gundersen wrote:
- for dep in "${unitdir}"/*.{wants,requires}/$(basename $unit); do
Instead of basename, you can use ${unit##*/}
add_systemd_unit $(basename $dep)
same here. I guess should be valid in this context, untested.
Thanks for this work!
On Sat, Apr 13, 2013 at 03:43:35AM +0200, Tom Gundersen wrote:
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 pulls in any symlinks to the unit in any .wants or .requires directories.
It'd be great if you could also prepare some doc for these in mkinitcpio(8).
functions | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+)
diff --git a/functions b/functions index 432d700..12df3cd 100644 --- a/functions +++ b/functions @@ -569,6 +569,104 @@ 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 udevdir= rules= rule= entry= key= value= binary=
- udevdir=$(pkg-config --variable=udevdir udev)
I'd like to avoid pkg-config as a dependency here. We can use a hardcoded (sane) PATH and do something like...
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
- if [[ ${1:0:1} != '/' ]]; then
rules="${udevdir}/rules.d/${1}"
- else
rules=$1
- fi
- add_file "${rules}"
- while read rule; do
if [[ ${rule:0:1} == '#' ]]; then
continue
fi
IFS=', '
There's no support for multibyte field separators. What this actually does is split lines on both ',' and ' ', which I suspect breaks a lot of the logic below here. I suspect you want to just split on commas in the outer while loop:
while IFS=, read -ra rule; do for pair in "${rule[@]}"; do IFS='=' read -ra key values <<<"$rule"
for entry in ${rule}; do
IFS='=' read key value <<< "${entry}"
if [[ ( ${key:0:3} == "RUN" &&
${key:4:7} != "builtin" ) ||
${key:0:7} == "PROGRAM" ||
${key:0:15} == "IMPORT{program}" ||
${key:0:15} == "ENV{REMOVE_CMD}" ]]; then
Perhaps a case statement? Taking my advice above gives you a nice array of key/value pairs for each entry in the rule:
case $key in RUN|RUN+|IMPORT{@(builtin|program)}|ENV{REMOVE_CMD}) binary=${value[0]#"} if [[ ${binary:0:1} = / ]]; then add_binary "$binary" else add_binary "$udevdir/$binary" fi ;; esac
binary=${value//\"/}
if [[ ${binary:0:1} != '/' ]]; then
binary="${udevdir}/${binary}"
fi
read -d ' ' binary <<< "${binary} "
add_binary "${binary}"
fi
done
- done < "$rules"
+}
+add_systemd_unit() {
- # Add a systemd unit file to the initcpio image. Dependencies on binaries
- # and other unit files will be discovered and added.
- # $1: path to rules file (or name of rules file)
- local unitdir= unit= rule= entry= key= value= binary= dep=
- unitdir=$(pkg-config --variable=systemdsystemunitdir systemd)
- if [[ ${1:0:1} != '/' ]]; then
unit="${unitdir}/${1}"
- else
unit=$1
- fi
- add_file "${unit}"
- while read entry; do
You should split the line here instead of splitting again below. You need to make sure to pass the -r flag as well:
while IFS='=' read -r key values; do read -ra values <<<"$values"
# now values is split on whitespace into an array
... done
if [[ ${entry:0:1} == '#' ]]; then
continue
fi
IFS='=' read key value <<< "${entry}"
- if [[ ${key:0:4} == 'Exec' ]]; then
binary=${value//\"/}
if [[ ${binary:0:1} != '-' ]]; then
read -d ' ' binary <<< "${binary} "
add_binary "${binary}"
fi
- fi
- if [[ ${key} == 'Requires' || ${key} == 'OnFailure' ]]; then
for dep in ${value}; do
add_systemd_unit ${dep}
done
- fi
The per-key behavior is probably better expressed in a case statement:
case $key in Requires|OnFailure) map add_systemd_unit "${values[@]}" ;; Exec) add_binary "${values[0]#-}" ;; ... esac
- done < "$unit"
- for dep in "${unitdir}"/*.{wants,requires}/$(basename $unit); do
- if [[ -h "${dep}" ]]; then
add_symlink "${dep}"
- fi
- done
- if [[ -d "${unit}.requires" ]]; then
for dep in "${unit}".requires/*; do
add_systemd_unit $(basename $dep)
done
- fi
+}
parse_config() { # parse key global variables set by the config file.
-- 1.8.2.1
participants (3)
-
Dave Reisner
-
Gerardo Exequiel Pozzi
-
Tom Gundersen