[arch-projects] [mkinitcpio][PATCH] functions: add_udev_rules and add_systemd_unit
Dave Reisner
d at falconindy.com
Sat Apr 13 20:19:37 EDT 2013
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
>
More information about the arch-projects
mailing list