Skip to content

Commit

Permalink
Allow references to parent properties in org.zfsbootmenu:commandline
Browse files Browse the repository at this point in the history
Any reference to "%{parent}" in org.zfsbootmenu:commandline will be
replaced with the value of the same property on the parent filesystem
(with parent references above recursively expanded), allowing easy
specification of common options at a mutual parent of two BEs and
overrides or additions of individual options per-BE. The value of
%{parent} is always an empty string on a root filesystem.

This is not intended to be sophisticated, and %{parent} appearing within
other words will be replaced regardless. The assumption is that
%{parent} is unique enough and will not conflict with real KCL options,
so dumb global replacement is sufficient.
  • Loading branch information
ahesford committed May 6, 2021
1 parent 8886db3 commit 04f5b87
Showing 1 changed file with 66 additions and 7 deletions.
73 changes: 66 additions & 7 deletions 90zfsbootmenu/zfsbootmenu-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,68 @@ find_root_prefix() {
echo "root=zfs:"
}

# arg1: ZFS filesystem
# prints: value of org.zfsbootmenu:commandline, with %{parent} recursively expanded
# returns: 0 on success

read_kcl_prop() {
local zfsbe args parfs par_args inherited

zfsbe="${1}"
if [ -z "${zfsbe}" ]; then
zerror "zfsbe is undefined"
return 1
fi

if ! args="$( zfs get -H -o value org.zfsbootmenu:commandline "${zfsbe}" )"; then
zerror "unable to read org.zfsbootmenu:commandline on ${zfsbe}"
return 1
fi

# KCL is empty, nothing to see
if [ "${args}" = "-" ]; then
zdebug "org.zfsbootmenu:commandline on ${zfsbe} has no value"
echo ""
return 0
fi

# KCL does not specify parent inheritance, just return the args
if ! [[ "${args}" =~ "%{parent}" ]]; then
zdebug "no parent reference in org.zfsbootmenu:commandline on ${zfsbe}"
echo "${args}"
return 0
fi

# Need to recursively expand "%{parent}"

parfs="${zfsbe%/*}"
if [ -z "${parfs}" ] || [ "${parfs}" = "${zfsbe}" ]; then
# There is no parent, par_args is empty
par_args=""
else
# Query the parent for kcl properties
if ! par_args="$( read_kcl_prop "${parfs}" )"; then
zwarn "failed to invoke read_kcl_prop on parent ${parfs}"
par_args=""
fi

# When the KCL property is inherited, recursive expansion fully populates
# the KCL at the level of the ancestor that actually defines the property.
if inherited="$( zfs get -H -o source -s inherited org.zfsbootmenu:commandline "${zfsbe}" 2>/dev/null )"; then
# Inherited property have a source of "inherited from <ancestor>";
# non-inherited properties will not be printed with `-s inherited`
if [ -n "${inherited}" ]; then
zdebug "org.zfsbootmenu:commandline on ${zfsbe} is inherited, using parent expansion verbatim"
echo "${par_args}"
return 0
fi
fi
fi

echo "${args//%\{parent\}/${par_args}}"
return 0
}

# arg1: ZFS filesystem
# arg2: path for a mounted filesystem
# prints: nothing
Expand All @@ -1172,13 +1234,10 @@ preload_be_cmdline() {

args_file="${BASE}/${zfsbe_fs}/cmdline"

if [ -n "${zfsbe_fs}" ]; then
zfsbe_args="$( zfs get -H -o value org.zfsbootmenu:commandline "${zfsbe_fs}" )"
if [ "${zfsbe_args}" != "-" ]; then
zdebug "using org.zfsbootmenu:commandline"
echo "${zfsbe_args}" > "${args_file}"
return
fi
if zfsbe_args="$( read_kcl_prop "${zfsbe_fs}" )" && [ -n "${zfsbe_args}" ]; then
zdebug "using org.zfsbootmenu:commandline"
echo "${zfsbe_args}" > "${args_file}"
return
fi

if [ -n "${zfsbe_mnt}" ] && [ -r "${zfsbe_mnt}/etc/default/zfsbootmenu" ]; then
Expand Down

0 comments on commit 04f5b87

Please sign in to comment.