1#!/bin/sh
2
3command -v getarg >/dev/null || . /lib/dracut-lib.sh
4command -v getargbool >/dev/null || {
5    # Compatibility with older Dracut versions.
6    # With apologies to the Dracut developers.
7    getargbool() {
8        if ! [ -z "$_b" ]; then
9                unset _b
10        fi
11        _default="$1"; shift
12        _b=$(getarg "$@")
13        [ $? -ne 0 ] &&  [ -z "$_b" ] && _b="$_default"
14        if [ -n "$_b" ]; then
15            [ "$_b" = "0" ] && return 1
16            [ "$_b" = "no" ] && return 1
17            [ "$_b" = "off" ] && return 1
18        fi
19        return 0
20    }
21}
22
23OLDIFS="${IFS}"
24NEWLINE="
25"
26
27ZPOOL_IMPORT_OPTS=""
28if getargbool 0 zfs_force -y zfs.force -y zfsforce ; then
29    warn "ZFS: Will force-import pools if necessary."
30    ZPOOL_IMPORT_OPTS="${ZPOOL_IMPORT_OPTS} -f"
31fi
32
33# find_bootfs
34#   returns the first dataset with the bootfs attribute.
35find_bootfs() {
36    IFS="${NEWLINE}"
37    for dataset in $(zpool list -H -o bootfs); do
38        case "${dataset}" in
39            "" | "-")
40                continue
41                ;;
42            "no pools available")
43                IFS="${OLDIFS}"
44                return 1
45                ;;
46            *)
47                IFS="${OLDIFS}"
48                echo "${dataset}"
49                return 0
50                ;;
51        esac
52    done
53
54    IFS="${OLDIFS}"
55    return 1
56}
57
58# import_pool POOL
59#   imports the given zfs pool if it isn't imported already.
60import_pool() {
61        pool="${1}"
62
63    if ! zpool list -H "${pool}" > /dev/null 2>&1; then
64        info "ZFS: Importing pool ${pool}..."
65        if ! zpool import -N ${ZPOOL_IMPORT_OPTS} "${pool}" ; then
66            warn "ZFS: Unable to import pool ${pool}"
67            return 1
68        fi
69    fi
70
71    return 0
72}
73
74# mount_dataset DATASET
75#   mounts the given zfs dataset.
76mount_dataset() {
77        dataset="${1}"
78    mountpoint="$(zfs get -H -o value mountpoint "${dataset}")"
79
80    # We need zfsutil for non-legacy mounts and not for legacy mounts.
81    if [ "${mountpoint}" = "legacy" ] ; then
82        mount -t zfs "${dataset}" "${NEWROOT}"
83    else
84        mount -o zfsutil -t zfs "${dataset}" "${NEWROOT}"
85    fi
86
87    return $?
88}
89
90# export_all OPTS
91#   exports all imported zfs pools.
92export_all() {
93        opts="${@}"
94    ret=0
95
96    IFS="${NEWLINE}"
97    for pool in $(zpool list -H -o name) ; do
98        if zpool list -H "${pool}" > /dev/null 2>&1; then
99            zpool export "${pool}" ${opts} || ret=$?
100        fi
101    done
102    IFS="${OLDIFS}"
103
104    return ${ret}
105}
106
107# ask_for_password
108#
109# Wraps around plymouth ask-for-password and adds fallback to tty password ask
110# if plymouth is not present.
111#
112# --cmd command
113#   Command to execute. Required.
114# --prompt prompt
115#   Password prompt. Note that function already adds ':' at the end.
116#   Recommended.
117# --tries n
118#   How many times repeat command on its failure.  Default is 3.
119# --ply-[cmd|prompt|tries]
120#   Command/prompt/tries specific for plymouth password ask only.
121# --tty-[cmd|prompt|tries]
122#   Command/prompt/tries specific for tty password ask only.
123# --tty-echo-off
124#   Turn off input echo before tty command is executed and turn on after.
125#   It's useful when password is read from stdin.
126ask_for_password() {
127    ply_tries=3
128    tty_tries=3
129    while [ "$#" -gt 0 ]; do
130        case "$1" in
131            --cmd) ply_cmd="$2"; tty_cmd="$2"; shift;;
132            --ply-cmd) ply_cmd="$2"; shift;;
133            --tty-cmd) tty_cmd="$2"; shift;;
134            --prompt) ply_prompt="$2"; tty_prompt="$2"; shift;;
135            --ply-prompt) ply_prompt="$2"; shift;;
136            --tty-prompt) tty_prompt="$2"; shift;;
137            --tries) ply_tries="$2"; tty_tries="$2"; shift;;
138            --ply-tries) ply_tries="$2"; shift;;
139            --tty-tries) tty_tries="$2"; shift;;
140            --tty-echo-off) tty_echo_off=yes;;
141        esac
142        shift
143    done
144
145    { flock -s 9;
146        # Prompt for password with plymouth, if installed and running.
147        if plymouth --ping 2>/dev/null; then
148            plymouth ask-for-password \
149                --prompt "$ply_prompt" --number-of-tries="$ply_tries" \
150                --command="$ply_cmd"
151            ret=$?
152        else
153            if [ "$tty_echo_off" = yes ]; then
154                stty_orig="$(stty -g)"
155                stty -echo
156            fi
157
158            i=1
159            while [ "$i" -le "$tty_tries" ]; do
160                [ -n "$tty_prompt" ] && \
161                    printf "%s [%i/%i]:" "$tty_prompt" "$i" "$tty_tries" >&2
162                eval "$tty_cmd" && ret=0 && break
163                ret=$?
164                i=$((i+1))
165                [ -n "$tty_prompt" ] && printf '\n' >&2
166            done
167            unset i
168            [ "$tty_echo_off" = yes ] && stty "$stty_orig"
169        fi
170    } 9>/.console_lock
171
172    [ $ret -ne 0 ] && echo "Wrong password" >&2
173    return $ret
174}
175