2 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3 # ex: ts=8 sw=4 sts=4 et filetype=sh
10 [ "$RD_DEBUG" = "yes" ] && set -x
13 # returns OK if $1 contains $2
15 [ "${1#*$2*}" != "$1" ]
18 # returns OK if $1 contains $2 at the beginning
20 [ "${1#$2*}" != "$1" ]
23 # returns OK if $1 contains $2 at the end
25 [ "${1%*$2}" != "$1" ]
28 # replaces all occurrences of 'search' in 'str' with 'replacement'
30 # str_replace str search replacement
33 # str_replace ' one two three ' ' ' '_'
35 local in="$1"; local s
="$2"; local r
="$3"
38 while strstr
"${in}" "$s"; do
50 if [ -z "$CMDLINE" ]; then
51 unset CMDLINE_ETC CMDLINE_ETC_D
52 if [ -e /etc
/cmdline
]; then
53 while read -r _line
; do
54 CMDLINE_ETC
="$CMDLINE_ETC $_line";
57 for _i
in /etc
/cmdline.d
/*.conf
; do
58 [ -e "$_i" ] ||
continue
59 while read -r _line
; do
60 CMDLINE_ETC_D
="$CMDLINE_ETC_D $_line";
63 read -r CMDLINE
</proc
/cmdline
;
64 CMDLINE
="$CMDLINE_ETC_D $CMDLINE_ETC $CMDLINE"
75 for _o
in $CMDLINE; do
76 if [ "${_o%%=*}" = "${1%%=*}" ]; then
77 if [ -n "${1#*=}" -a "${1#*=*}" != "${1}" ]; then
78 # if $1 has a "=<value>", we want the exact match
79 if [ "$_o" = "$1" ]; then
86 if [ "${_o#*=}" = "$_o" ]; then
87 # if cmdline argument has no "=<value>", we assume "=1"
97 if [ -n "$_val" ]; then
98 [ "x$_doecho" != "x" ] && echo "$_val";
106 local _deprecated _newoption
107 while [ $# -gt 0 ]; do
109 -d) _deprecated
=1; shift;;
110 -y) if _dogetarg
$2 >/dev
/null
; then
111 if [ "$_deprecated" = "1" ]; then
112 [ -n "$_newoption" ] && warn
"Kernel command line option '$2' is deprecated, use '$_newoption' instead." || warn
"Option '$2' is deprecated."
120 -n) if _dogetarg
$2 >/dev
/null
; then
122 if [ "$_deprecated" = "1" ]; then
123 [ -n "$_newoption" ] && warn
"Kernel command line option '$2' is deprecated, use '$_newoption=0' instead." || warn
"Option '$2' is deprecated."
130 *) if [ -z "$_newoption" ]; then
133 if _dogetarg
$1; then
134 if [ "$_deprecated" = "1" ]; then
135 [ -n "$_newoption" ] && warn
"Kernel command line option '$1' is deprecated, use '$_newoption' instead." || warn
"Option '$1' is deprecated."
148 # getargbool <defaultval> <args...>
149 # False if "getarg <args...>" returns "0", "no", or "off".
150 # True if getarg returns any other non-empty string.
151 # If not found, assumes <defaultval> - usually 0 for false, 1 for true.
152 # example: getargbool 0 rd.info
153 # true: rd.info, rd.info=1, rd.info=xxx
154 # false: rd.info=0, rd.info=off, rd.info not present (default val is 0)
161 [ $?
-ne 0 -a -z "$_b" ] && _b
=$_default
162 if [ -n "$_b" ]; then
163 [ $_b = "0" ] && return 1
164 [ $_b = "no" ] && return 1
165 [ $_b = "off" ] && return 1
178 for _o
in $CMDLINE; do
179 if [ "$_o" = "$_key" ]; then
181 elif [ "${_o%%=*}" = "${_key%=}" ]; then
182 [ -n "${_o%%=*}" ] && set -- "$@" "${_o#*=}";
186 if [ -n "$_found" ]; then
187 [ $# -gt 0 ] && echo -n "$@"
195 local _val _i _args _gfound _deprecated
202 if [ "$i" = "-d" ]; then
206 _val
="$(_dogetargs $_i)"
207 if [ $?
-eq 0 ]; then
208 if [ "$_deprecated" = "1" ]; then
209 [ -n "$_newoption" ] && warn
"Option '$_i' is deprecated, use '$_newoption' instead." || warn
"Option $_i is deprecated!"
213 [ -n "$_val" ] && set -- "$@" "$_val"
216 if [ -n "$_gfound" ]; then
217 if [ $# -gt 0 ]; then
230 # Prints value of given option. If option is a flag and it's present,
231 # it just returns 0. Otherwise 1 is returned.
232 # $1 = options separated by commas
233 # $2 = option we are interested in
236 # $1 = cipher=aes-cbc-essiv:sha256,hash=sha256,verify
241 local line
=",$1,"; local opt
="$2"; local tmp
245 tmp
="${line#*,${opt}=}"
249 *,${opt},*) return 0;;
254 # Splits given string 'str' with separator 'sep' into variables 'var1', 'var2',
255 # 'varN'. If number of fields is less than number of variables, remaining are
256 # not set. If number of fields is greater than number of variables, the last
257 # variable takes remaining fields. In short - it acts similary to 'read'.
259 # splitsep sep str var1 var2 varN
262 # splitsep ':' 'foo:bar:baz' v1 v2
264 # v1='foo', v2='bar:baz'
266 # TODO: ':' inside fields.
269 local sep
="$1"; local str
="$2"; shift 2
272 while [ -n "$str" -a "$#" -gt 1 ]; do
279 [ -n "$str" -a -n "$1" ] && eval "$1='$str'"
285 if [ -z "$RD_DEBUG" ]; then
286 if [ -e /proc
/cmdline
]; then
288 if getargbool
0 rd.debug
-d -y rdinitdebug
-d -y rdnetdebug
; then
291 export PS4
='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): ';
305 [ "$_dir" ] && [ -d "/$_dir" ] ||
return
306 for f
in "/$_dir"/*.sh
; do [ -e "$f" ] && .
"$f" "$@"; done
309 hookdir
=/lib
/dracut
/hooks
315 source_all
"/lib/dracut/hooks/$_dir" "$@"
320 for f
in $hookdir/initqueue
/finished
/*.sh
; do
321 [ "$f" = "$hookdir/initqueue/finished/*.sh" ] && return 0
322 { [ -e "$f" ] && ( .
"$f" ) ; } ||
return 1
329 [ "$1" ] && [ -d "/$1" ] ||
return
330 for f
in "/$1"/*.conf
; do [ -e "$f" ] && .
"$f"; done
335 echo "<24>dracut: FATAL: $*";
336 echo "<24>dracut: Refusing to continue";
340 echo "warn dracut: FATAL: \"$*\"";
341 echo "warn dracut: Refusing to continue";
342 } >> $hookdir/emergency
/01-die.sh
344 > /run
/initramfs
/.die
350 if [ -z "$DRACUT_QUIET" ]; then
352 getargbool
0 rd.info
-d -y rdinfo
&& DRACUT_QUIET
="no"
353 getargbool
0 rd.debug
-d -y rdinitdebug
&& DRACUT_QUIET
="no"
354 getarg quiet || DRACUT_QUIET
="yes"
355 a
=$
(getarg loglevel
=)
356 [ -n "$a" ] && [ $a -ge 28 ] && DRACUT_QUIET
="yes"
361 if [ -z "$DRACUT_SYSTEMD" ]; then
365 echo "<28>dracut Warning: $*" > /dev
/kmsg
366 echo "dracut Warning: $*" >&2
371 echo "<30>dracut: $*" > /dev
/kmsg
372 [ "$DRACUT_QUIET" != "yes" ] && \
379 echo "Warning: $*" >&2
401 # Count the number of times the character $ch occurs in $str
402 # Return 0 if the count matches the expected number, 1 otherwise
408 while [ "${str#*$ch}" != "${str}" ]; do
410 count
=$
(( $count + 1 ))
413 [ $count -eq $expected ]
422 [ -z "$file" ] && return 1;
423 [ -z "$str" ] && return 1;
425 while read dummy check restofline
; do
426 if [ "$check" = "$str" ]; then
436 [ -z "$UDEVVERSION" ] && export UDEVVERSION
=$
(udevadm
--version)
438 if [ $UDEVVERSION -ge 143 ]; then
439 udevadm settle
--exit-if-exists=$hookdir/initqueue
/work
$settle_exit_if_exists
441 udevadm settle
--timeout=30
446 [ -z "$UDEVVERSION" ] && export UDEVVERSION
=$
(udevadm
--version)
448 if [ $UDEVVERSION -ge 143 ]; then
449 for i
in "$@"; do udevadm control
--property=$i; done
451 for i
in "$@"; do udevadm control
--env=$i; done
456 local dev mnt etc wanted_dev
457 wanted_dev
="$(readlink -e -q $1)"
458 while read dev mnt etc
; do
459 [ "$dev" = "$wanted_dev" ] && echo "$dev" && return 0
464 # usage: ismounted <mountpoint>
465 # usage: ismounted /dev/<device>
466 if command -v findmnt
>/dev
/null
; then
468 findmnt
"$1" > /dev
/null
2>&1
473 find_mount
"$1" > /dev
/null
&& return 0
478 [ "$m" = "$1" ] && return 0
487 while [ $cnt -lt 200 ]; do
488 li
=$
(ip
-o link show up dev
$1)
489 [ -n "$li" ] && return 0
496 wait_for_route_ok
() {
498 while [ $cnt -lt 200 ]; do
500 [ -n "$li" ] && [ -z "${li##*$1*}" ] && return 0
507 # root=nfs:[<server-ip>:]<root-dir>[:<nfs-options>]
508 # root=nfs4:[<server-ip>:]<root-dir>[:<nfs-options>]
515 # check if we have a server
516 if strstr
"$arg" ':/*' ; then
524 options
="${arg##$path}"
526 options
="${options##:}"
528 options
="${options%%:}"
530 # Does it really start with '/'?
531 [ -n "${path%%/*}" ] && path
="error";
533 #Fix kernel legacy style separating path and options with ','
534 if [ "$path" != "${path#*,}" ] ; then
540 # Create udev rule match for a device with its device name, or the udev property
541 # ID_FS_UUID or ID_FS_LABEL
544 # udevmatch LABEL=boot
546 # ENV{ID_FS_LABEL}="boot"
551 UUID
=????????
-????
-????
-????
-????????????|LABEL
=*)
552 printf 'ENV{ID_FS_%s}=="%s"' "${1%%=*}" "${1#*=}"
555 printf 'ENV{ID_FS_UUID}=="%s*"' "${1#*=}"
557 /dev
/?
*) printf 'KERNEL=="%s"' "${1#/dev/}" ;;
562 # Prints unique path for potential file inside specified directory. It consists
563 # of specified directory, prefix and number at the end which is incremented
564 # until non-existing file is found.
575 local dir
="$1"; local prefix
="$2"
578 [ -d "${dir}" ] ||
return 1
580 while [ -e "${dir}/${prefix}$i" ]; do
581 i
=$
(($i+1)) ||
return 1
584 echo "${dir}/${prefix}$i"
587 # Creates unique directory and prints its path. It's using funiq to generate
590 # mkuniqdir subdir new_dir_name
592 local dir
="$1"; local prefix
="$2"
593 local retdir
; local retdir_new
595 [ -d "${dir}" ] || mkdir
-m 0755 -p "${dir}" ||
return 1
597 retdir
=$
(funiq
"${dir}" "${prefix}") ||
return 1
598 until mkdir
-m 0755 "${retdir}" 2>/dev
/null
; do
599 retdir_new
=$
(funiq
"${dir}" "${prefix}") ||
return 1
600 [ "$retdir_new" = "$retdir" ] && return 1
607 # Copy the contents of SRC into DEST, merging the contents of existing
608 # directories (kinda like rsync, or cpio -p).
609 # Creates DEST if it doesn't exist. Overwrites files with the same names.
613 local src
="$1" dest
="$2"
614 mkdir
-p "$dest"; dest
=$
(readlink
-e -q "$dest")
615 ( cd "$src"; cp -af .
-t "$dest" )
618 # Evaluates command for UUIDs either given as arguments for this function or all
619 # listed in /dev/disk/by-uuid. UUIDs doesn't have to be fully specified. If
620 # beginning is given it is expanded to all matching UUIDs. To pass full UUID to
621 # your command use '$___' as a place holder. Remember to escape '$'!
623 # foreach_uuid_until [ -p prefix ] command UUIDs
625 # prefix - string to put just before $___
626 # command - command to be evaluated
627 # UUIDs - list of UUIDs separated by space
629 # The function returns after *first successful evaluation* of the given command
630 # with status 0. If evaluation fails for every UUID function returns with
634 # foreach_uuid_until "mount -U \$___ /mnt; echo OK; umount /mnt" \
635 # "01234 f512 a235567f-12a3-c123-a1b1-01234567abcb"
636 foreach_uuid_until
() (
639 [ "$1" = -p ] && local prefix
="$2" && shift 2
640 local cmd
="$1"; shift; local uuids_list
="$*"
641 local uuid
; local full_uuid
; local ___
643 [ -n "${cmd}" ] ||
return 1
645 for uuid
in ${uuids_list:-*}; do
646 for full_uuid
in ${uuid}*; do
647 [ -e "${full_uuid}" ] ||
continue
648 ___
="${prefix}${full_uuid}"
649 eval ${cmd} && return 0
656 # Get kernel name for given device. Device may be the name too (then the same
657 # is returned), a symlink (full path), UUID (prefixed with "UUID=") or label
658 # (prefixed with "LABEL="). If just a beginning of the UUID is specified or
659 # even an empty, function prints all device names which UUIDs match - every in
662 # NOTICE: The name starts with "/dev/".
671 local dev
="$1"; local d
; local names
675 dev
="$(foreach_uuid_until '! blkid -U $___' "${dev#UUID=}")" \
677 [ -z "$dev" ] && return 255
679 LABEL
=*) dev
="$(blkid -L "${dev#LABEL=}")" ||
return 255 ;;
686 $(readlink -e -q "$d")" ||
return 255
696 [ -d $1 ] ||
return 1
697 for _d
in proc sys dev
; do
698 [ -e "$1"/$_d ] ||
return 1
704 local _hookname _unique _name _job _exe
705 while [ $# -gt 0 ]; do
708 _hookname
="/$2";shift;;
719 if [ -z "$_unique" ]; then
729 [ -x "$_exe" ] || _exe
=$
(command -v $_exe)
731 if [ -n "$onetime" ]; then
733 echo '[ -e "$_job" ] && rm "$_job"'
735 } > "/tmp/$$-${_job}.sh"
737 echo "$_exe $@" > "/tmp/$$-${_job}.sh"
740 mv -f "/tmp/$$-${_job}.sh" "$hookdir/${_hookname}/${_job}.sh"
743 # inst_mount_hook <mountpoint> <prio> <name> <script>
745 # Install a mount hook with priority <prio>,
746 # which executes <script> as soon as <mountpoint> is mounted.
748 local _prio
="$2" _jobname
="$3" _script
="$4"
749 local _hookname
="mount-$(str_replace "$1" '/' '\\x2f')"
750 [ -d "$hookdir/${_hookname}" ] || mkdir
-p "$hookdir/${_hookname}"
751 inst_hook
--hook "$_hookname" --unique --name "${_prio}-${_jobname}" "$_script"
754 # add_mount_point <dev> <mountpoint> <filesystem> <fsopts>
756 # Mount <dev> on <mountpoint> with <filesystem> and <fsopts>
757 # and call any mount hooks, as soon, as it is mounted
759 local _dev
="$1" _mp
="$2" _fs
="$3" _fsopts
="$4"
760 local _hookname
="mount-$(str_replace "$2" '/' '\\x2f')"
761 local _devname
="dev-$(str_replace "$1" '/' '\\x2f')"
762 echo "$_dev $_mp $_fs $_fsopts 0 0" >> /etc
/fstab
764 exec 7>/etc
/udev
/rules.d
/99-mount-${_devname}.rules
765 echo 'SUBSYSTEM!="block", GOTO="mount_end"' >&7
766 echo 'ACTION!="add|change", GOTO="mount_end"' >&7
767 if [ -n "$_dev" ]; then
768 udevmatch
"$_dev" >&7 ||
{
769 warn
"add_mount_point dev=$_dev incorrect!"
776 printf -- 'RUN+="%s --unique --onetime ' $
(command -v initqueue
)
777 printf -- '--name mount-%%k '
778 printf -- '%s %s"\n' "$(command -v mount_hook)" "${_mp}"
780 echo 'LABEL="mount_end"' >&7
784 # wait_for_mount <mountpoint>
786 # Installs a initqueue-finished script,
787 # which will cause the main loop only to exit,
788 # if <mountpoint> is mounted.
792 _name
="$(str_replace "$1" '/' '\\x2f')"
793 printf '. /lib/dracut-lib.sh\nismounted "%s"\n' $1 \
794 >> "$hookdir/initqueue/finished/ismounted-${_name}.sh"
796 printf 'ismounted "%s" || ' $1
797 printf 'warn "\"%s\" is not mounted"\n' $1
798 } >> "$hookdir/emergency/90-${_name}.sh"
803 # Installs a initqueue-finished script,
804 # which will cause the main loop only to exit,
805 # if the device <dev> is recognized by the system.
809 _name
="$(str_replace "$1" '/' '\\x2f')"
810 printf '[ -e "%s" ]\n' $1 \
811 >> "$hookdir/initqueue/finished/devexists-${_name}.sh"
813 printf '[ -e "%s" ] || ' $1
814 printf 'warn "\"%s\" does not exist"\n' $1
815 } >> "$hookdir/emergency/80-${_name}.sh"
818 cancel_wait_for_dev
()
821 _name
="$(str_replace "$1" '/' '\\x2f')"
822 rm -f "$hookdir/initqueue/finished/devexists-${_name}.sh"
823 rm -f "$hookdir/emergency/80-${_name}.sh"
828 local _exe
="$(command -v $1)"
831 [ -x "$_exe" ] ||
return 1
832 for _i
in /proc
/[0-9]*; do
833 [ "$_i" = "/proc/1" ] && continue
834 if [ -e "$_i"/_exe
] && [ "$_i/_exe" -ef "$_exe" ] ; then
842 >/run
/initramfs
/.need_shutdown
847 [ "$RD_DEBUG" = "yes" ] ||
return
848 [ -e /run
/initramfs
/loginit.pipe
] ||
return
850 echo "DRACUT_LOG_END"
851 exec 0<>/dev
/console
1<>/dev
/console
2<>/dev
/console
854 while [ $i -lt 10 ]; do
855 if [ ! -e /run
/initramfs
/loginit.pipe
]; then
858 [ -z "${j##*Running*}" ] ||
break
864 if [ $i -eq 10 ]; then
865 kill %1 >/dev
/null
2>&1
866 kill $
(while read line
;do echo $line;done</run
/initramfs
/loginit.pid
)
870 rm -f /run
/initramfs
/loginit.pipe
/run
/initramfs
/loginit.pid
876 if [ -n "$DRACUT_SYSTEMD" ]; then
878 echo "PS1=\"$_name:\${PWD}# \"" >/etc
/profile
879 systemctl start dracut-emergency.service
885 echo 'You might want to save "/run/initramfs/sosreport.txt" to a USB stick or /boot'
886 echo 'after mounting them and attach it to a bug report.'
887 if ! RD_DEBUG
= getargbool
0 rd.debug
-d -y rdinitdebug
-d -y rdnetdebug
; then
889 echo 'To get more debug information in the report,'
890 echo 'reboot with "rd.debug" added to the kernel command line.'
893 echo 'Dropping to debug shell.'
895 export PS1
="$_name:\${PWD}# "
896 [ -e /.profile
] ||
>/.profile
898 _ctty
="$(RD_DEBUG= getarg rd.ctty=)" && _ctty
="/dev/${_ctty##*/}"
899 if [ -z "$_ctty" ]; then
901 while [ -f /sys
/class
/tty
/$_ctty/active
]; do
902 _ctty
=$
(cat /sys
/class
/tty
/$_ctty/active
)
903 _ctty
=${_ctty##* } # last one in the list
907 [ -c "$_ctty" ] || _ctty
=/dev
/tty1
908 case "$(/usr/bin/setsid --help 2>&1)" in *--ctty*) CTTY
="--ctty";; esac
909 setsid
$CTTY /bin
/sh
-i -l 0<>$_ctty 1<>$_ctty 2<>$_ctty
917 local _rdshell_name
="dracut" action
="Boot" hook
="emergency"
918 if [ "$1" = "-n" ]; then
921 elif [ "$1" = "--shutdown" ]; then
922 _rdshell_name
=$2; action
="Shutdown"; hook
="shutdown-emergency"
931 if getargbool
1 rd.shell
-d -y rdshell || getarg rd.
break -d rdbreak
; then
932 _emergency_shell
$_rdshell_name
934 warn
"$action has failed. To debug this issue add \"rd.shell rd.debug\" to the kernel command line."
935 # cause a kernel panic
938 [ -e /run
/initramfs
/.die
] && exit 1
941 # Retain the values of these variables but ensure that they are unexported
942 # This is a POSIX-compliant equivalent of bash's "export -n"
950 [ -n "$val" ] && eval $var=\"$val\"
954 # returns OK if list1 contains all elements of list2, i.e. checks if list2 is a
955 # sublist of list1. An order and a duplication doesn't matter.
960 # $4 = ignore values, separated by $1
963 local _list
="${_sep}${2}${_sep}"
965 [ -n "$4" ] && local _iglist
="${_sep}${4}${_sep}"
969 [ "$_list" = "$_sublist" ] && return 0
971 for _v
in $_sublist; do
972 if [ -n "$_v" ] && ! ( [ -n "$_iglist" ] && strstr
"$_iglist" "$_v" )
974 strstr
"$_list" "$_v" ||
return 1
981 # returns OK if both lists contain the same values. An order and a duplication
987 # $4 = ignore values, separated by $1
989 listlist
"$1" "$2" "$3" "$4" && listlist
"$1" "$3" "$2" "$4"