mirror of
https://git.proxmox.com/git/mirror_zfs
synced 2025-11-03 08:02:03 +00:00
plymouth --command splits the command on spaces which means
that zfs-load-key was getting the filesystem name enclosed
in single quotes (since 13c59bb76) and failing. This commit
fixes it by piping the password directly to the command
similar to how it's done in other scripts (initramfs,
dracut without plymouth).
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Michal Vasilek <michal@vasilek.cz>
Related-to: #9193
Related-to: #9202
Closes #12147
208 lines
5.9 KiB
Bash
Executable File
208 lines
5.9 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
command -v getarg >/dev/null || . /lib/dracut-lib.sh
|
|
command -v getargbool >/dev/null || {
|
|
# Compatibility with older Dracut versions.
|
|
# With apologies to the Dracut developers.
|
|
getargbool() {
|
|
_default="$1"; shift
|
|
! _b=$(getarg "$@") && [ -z "$_b" ] && _b="$_default"
|
|
if [ -n "$_b" ]; then
|
|
[ "$_b" = "0" ] && return 1
|
|
[ "$_b" = "no" ] && return 1
|
|
[ "$_b" = "off" ] && return 1
|
|
fi
|
|
return 0
|
|
}
|
|
}
|
|
|
|
OLDIFS="${IFS}"
|
|
NEWLINE="
|
|
"
|
|
TAB=" "
|
|
|
|
ZPOOL_IMPORT_OPTS=""
|
|
if getargbool 0 zfs_force -y zfs.force -y zfsforce ; then
|
|
warn "ZFS: Will force-import pools if necessary."
|
|
ZPOOL_IMPORT_OPTS="${ZPOOL_IMPORT_OPTS} -f"
|
|
fi
|
|
|
|
# find_bootfs
|
|
# returns the first dataset with the bootfs attribute.
|
|
find_bootfs() {
|
|
IFS="${NEWLINE}"
|
|
for dataset in $(zpool list -H -o bootfs); do
|
|
case "${dataset}" in
|
|
"" | "-")
|
|
continue
|
|
;;
|
|
"no pools available")
|
|
IFS="${OLDIFS}"
|
|
return 1
|
|
;;
|
|
*)
|
|
IFS="${OLDIFS}"
|
|
echo "${dataset}"
|
|
return 0
|
|
;;
|
|
esac
|
|
done
|
|
|
|
IFS="${OLDIFS}"
|
|
return 1
|
|
}
|
|
|
|
# import_pool POOL
|
|
# imports the given zfs pool if it isn't imported already.
|
|
import_pool() {
|
|
pool="${1}"
|
|
|
|
if ! zpool list -H "${pool}" > /dev/null 2>&1; then
|
|
info "ZFS: Importing pool ${pool}..."
|
|
# shellcheck disable=SC2086
|
|
if ! zpool import -N ${ZPOOL_IMPORT_OPTS} "${pool}" ; then
|
|
warn "ZFS: Unable to import pool ${pool}"
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
_mount_dataset_cb() {
|
|
mount -o zfsutil -t zfs "${1}" "${NEWROOT}${2}"
|
|
}
|
|
|
|
# mount_dataset DATASET
|
|
# mounts the given zfs dataset.
|
|
mount_dataset() {
|
|
dataset="${1}"
|
|
mountpoint="$(zfs get -H -o value mountpoint "${dataset}")"
|
|
ret=0
|
|
|
|
# We need zfsutil for non-legacy mounts and not for legacy mounts.
|
|
if [ "${mountpoint}" = "legacy" ] ; then
|
|
mount -t zfs "${dataset}" "${NEWROOT}" || ret=$?
|
|
else
|
|
mount -o zfsutil -t zfs "${dataset}" "${NEWROOT}" || ret=$?
|
|
|
|
if [ "$ret" = "0" ]; then
|
|
for_relevant_root_children "${dataset}" _mount_dataset_cb || ret=$?
|
|
fi
|
|
fi
|
|
|
|
return ${ret}
|
|
}
|
|
|
|
# for_relevant_root_children DATASET EXEC
|
|
# Runs "EXEC dataset mountpoint" for all children of DATASET that are needed for system bringup
|
|
# Used by zfs-generator.sh and friends, too!
|
|
for_relevant_root_children() {
|
|
dataset="${1}"
|
|
exec="${2}"
|
|
|
|
zfs list -t filesystem -Ho name,mountpoint,canmount -r "${dataset}" |
|
|
(
|
|
_ret=0
|
|
while IFS="${TAB}" read -r dataset mountpoint canmount; do
|
|
[ "$canmount" != "on" ] && continue
|
|
|
|
case "$mountpoint" in
|
|
/etc|/bin|/lib|/lib??|/libx32|/usr)
|
|
# If these aren't mounted we may not be able to get to the real init at all, or pollute the dataset holding the rootfs
|
|
"${exec}" "${dataset}" "${mountpoint}" || _ret=$?
|
|
;;
|
|
*)
|
|
# Up to the real init to remount everything else it might need
|
|
;;
|
|
esac
|
|
done
|
|
exit ${_ret}
|
|
)
|
|
}
|
|
|
|
# export_all OPTS
|
|
# exports all imported zfs pools.
|
|
export_all() {
|
|
ret=0
|
|
|
|
IFS="${NEWLINE}"
|
|
for pool in $(zpool list -H -o name) ; do
|
|
if zpool list -H "${pool}" > /dev/null 2>&1; then
|
|
zpool export "${pool}" "$@" || ret=$?
|
|
fi
|
|
done
|
|
IFS="${OLDIFS}"
|
|
|
|
return ${ret}
|
|
}
|
|
|
|
# ask_for_password
|
|
#
|
|
# Wraps around plymouth ask-for-password and adds fallback to tty password ask
|
|
# if plymouth is not present.
|
|
#
|
|
# --cmd command
|
|
# Command to execute. Required.
|
|
# --prompt prompt
|
|
# Password prompt. Note that function already adds ':' at the end.
|
|
# Recommended.
|
|
# --tries n
|
|
# How many times repeat command on its failure. Default is 3.
|
|
# --ply-[cmd|prompt|tries]
|
|
# Command/prompt/tries specific for plymouth password ask only.
|
|
# --tty-[cmd|prompt|tries]
|
|
# Command/prompt/tries specific for tty password ask only.
|
|
# --tty-echo-off
|
|
# Turn off input echo before tty command is executed and turn on after.
|
|
# It's useful when password is read from stdin.
|
|
ask_for_password() {
|
|
ply_tries=3
|
|
tty_tries=3
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--cmd) ply_cmd="$2"; tty_cmd="$2"; shift;;
|
|
--ply-cmd) ply_cmd="$2"; shift;;
|
|
--tty-cmd) tty_cmd="$2"; shift;;
|
|
--prompt) ply_prompt="$2"; tty_prompt="$2"; shift;;
|
|
--ply-prompt) ply_prompt="$2"; shift;;
|
|
--tty-prompt) tty_prompt="$2"; shift;;
|
|
--tries) ply_tries="$2"; tty_tries="$2"; shift;;
|
|
--ply-tries) ply_tries="$2"; shift;;
|
|
--tty-tries) tty_tries="$2"; shift;;
|
|
--tty-echo-off) tty_echo_off=yes;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
{ flock -s 9;
|
|
# Prompt for password with plymouth, if installed and running.
|
|
if plymouth --ping 2>/dev/null; then
|
|
plymouth ask-for-password \
|
|
--prompt "$ply_prompt" --number-of-tries="$ply_tries" | \
|
|
eval "$ply_cmd"
|
|
ret=$?
|
|
else
|
|
if [ "$tty_echo_off" = yes ]; then
|
|
stty_orig="$(stty -g)"
|
|
stty -echo
|
|
fi
|
|
|
|
i=1
|
|
while [ "$i" -le "$tty_tries" ]; do
|
|
[ -n "$tty_prompt" ] && \
|
|
printf "%s [%i/%i]:" "$tty_prompt" "$i" "$tty_tries" >&2
|
|
eval "$tty_cmd" && ret=0 && break
|
|
ret=$?
|
|
i=$((i+1))
|
|
[ -n "$tty_prompt" ] && printf '\n' >&2
|
|
done
|
|
unset i
|
|
[ "$tty_echo_off" = yes ] && stty "$stty_orig"
|
|
fi
|
|
} 9>/.console_lock
|
|
|
|
[ $ret -ne 0 ] && echo "Wrong password" >&2
|
|
return $ret
|
|
}
|