]> git.ipfire.org Git - thirdparty/dracut.git/blame - modules.d/99base/dracut-lib.sh
removed trailing whitespaces
[thirdparty/dracut.git] / modules.d / 99base / dracut-lib.sh
CommitLineData
8ce58f1f 1#!/bin/sh
cc02093d
HH
2# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3# ex: ts=8 sw=4 sts=4 et filetype=sh
c98bcec8
HH
4
5# returns OK if $1 contains $2
6strstr() {
cc02093d 7 [ "${1#*$2*}" != "$1" ]
c98bcec8
HH
8}
9
ccb0ab73
10# returns OK if $1 contains $2 at the beginning
11str_starts() {
12 [ "${1#$2*}" != "$1" ]
13}
14
15# replaces all occurrences of 'search' in 'str' with 'replacement'
16#
17# str_replace str search replacement
18#
19# example:
20# str_replace ' one two three ' ' ' '_'
21str_replace() {
22 local in="$1"; local s="$2"; local r="$3"
23 local out=''
24
25 while strstr "${in}" "$s"; do
26 chop="${in%%$s*}"
27 out="${out}${chop# }$r"
28 in="${in#*$s}"
29 done
30 echo "${out}${in}"
31}
32
fa7ada31
HH
33_getcmdline() {
34 local _line
35 unset _line
c1a37d92 36 if [ -z "$CMDLINE" ]; then
2dfdcbf4 37 if [ -e /etc/cmdline ]; then
fa7ada31
HH
38 while read _line; do
39 CMDLINE_ETC="$CMDLINE_ETC $_line";
2dfdcbf4
HH
40 done </etc/cmdline;
41 fi
cc02093d
HH
42 read CMDLINE </proc/cmdline;
43 CMDLINE="$CMDLINE $CMDLINE_ETC"
c1a37d92 44 fi
fa7ada31
HH
45}
46
47_dogetarg() {
48 local _o _val
49 unset _val
50 unset _o
51 _getcmdline
52
53 for _o in $CMDLINE; do
54 if [ "$_o" = "$1" ]; then
3b403b32 55 return 0;
3a4d0c9c 56 fi
fa7ada31 57 [ "${_o%%=*}" = "${1%=}" ] && _val=${_o#*=};
df44688f 58 done
fa7ada31 59 if [ -n "$_val" ]; then
3b403b32 60 echo $_val;
cc02093d 61 return 0;
3a4d0c9c 62 fi
fa7ada31
HH
63 return 1;
64}
65
66getarg() {
67 set +x
68 while [ $# -gt 0 ]; do
69 case $1 in
70 -y) if _dogetarg $2; then
71 echo 1
9e7a3bf2 72 [ "$RD_DEBUG" = "yes" ] && set -x
fa7ada31
HH
73 return 0
74 fi
75 shift 2;;
76 -n) if _dogetarg $2; then
77 echo 0;
9e7a3bf2 78 [ "$RD_DEBUG" = "yes" ] && set -x
fa7ada31
HH
79 return 1
80 fi
81 shift 2;;
82 *) if _dogetarg $1; then
9e7a3bf2 83 [ "$RD_DEBUG" = "yes" ] && set -x
fa7ada31
HH
84 return 0;
85 fi
86 shift;;
87 esac
88 done
3b403b32 89 [ "$RD_DEBUG" = "yes" ] && set -x
df44688f
DD
90 return 1
91}
ae5bc1fd 92
fa7ada31
HH
93getargbool() {
94 local _b
95 unset _b
96 local _default
97 _default=$1; shift
98 _b=$(getarg "$@")
99 [ $? -ne 0 -a -z "$_b" ] && _b=$_default
100 if [ -n "$_b" ]; then
4ad45344 101 [ $_b = "0" ] && return 1
fa7ada31 102 [ $_b = "no" ] && return 1
c1a37d92 103 fi
fa7ada31
HH
104 return 0
105}
106
107_dogetargs() {
3b403b32 108 set +x
fa7ada31
HH
109 local _o _found
110 unset _o
111 unset _found
112 _getcmdline
113
114 for _o in $CMDLINE; do
115 if [ "$_o" = "$1" ]; then
cc02093d
HH
116 return 0;
117 fi
fa7ada31 118 if [ "${_o%%=*}" = "${1%=}" ]; then
3b403b32 119 echo -n "${_o#*=} ";
fa7ada31 120 _found=1;
cc02093d 121 fi
da1c03c8 122 done
fa7ada31
HH
123 [ -n "$_found" ] && return 0;
124 return 1;
125}
126
127getargs() {
128 local _val
129 unset _val
130 set +x
131 while [ $# -gt 0 ]; do
132 _val="$_val $(_dogetargs $1)"
133 shift
134 done
135 if [ -n "$_val" ]; then
136 echo -n $_val
3b403b32 137 [ "$RD_DEBUG" = "yes" ] && set -x
fa7ada31 138 return 0
3a4d0c9c 139 fi
3b403b32 140 [ "$RD_DEBUG" = "yes" ] && set -x
4bb570c9 141 return 1;
da1c03c8
HH
142}
143
fa7ada31 144
2926b5b3
145# Prints value of given option. If option is a flag and it's present,
146# it just returns 0. Otherwise 1 is returned.
147# $1 = options separated by commas
148# $2 = option we are interested in
3b403b32 149#
2926b5b3
150# Example:
151# $1 = cipher=aes-cbc-essiv:sha256,hash=sha256,verify
152# $2 = hash
153# Output:
154# sha256
155getoptcomma() {
156 local line=",$1,"; local opt="$2"; local tmp
157
158 case "${line}" in
159 *,${opt}=*,*)
160 tmp="${line#*,${opt}=}"
161 echo "${tmp%%,*}"
162 return 0
cc02093d
HH
163 ;;
164 *,${opt},*) return 0;;
2926b5b3 165 esac
2926b5b3
166 return 1
167}
168
ccb0ab73
169# Splits given string 'str' with separator 'sep' into variables 'var1', 'var2',
170# 'varN'. If number of fields is less than number of variables, remaining are
171# not set. If number of fields is greater than number of variables, the last
172# variable takes remaining fields. In short - it acts similary to 'read'.
173#
174# splitsep sep str var1 var2 varN
175#
176# example:
177# splitsep ':' 'foo:bar:baz' v1 v2
178# in result:
179# v1='foo', v2='bar:baz'
180#
181# TODO: ':' inside fields.
182splitsep() {
183 local sep="$1"; local str="$2"; shift 2
184 local tmp
185
186 while [ -n "$str" -a -n "$*" ]; do
7a8a33b6 187 tmp="${str%%$sep*}"
ccb0ab73
188 eval "$1=${tmp}"
189 str="${str#$tmp}"
7a8a33b6 190 str="${str#$sep}"
ccb0ab73
191 shift
192 done
193
194 return 0
195}
196
4bb570c9 197setdebug() {
9e7a3bf2 198 if [ -z "$RD_DEBUG" ]; then
4bb570c9 199 if [ -e /proc/cmdline ]; then
9e7a3bf2 200 RD_DEBUG=no
fa7ada31 201 if getargbool 0 rd.debug -y rdinitdebug -y rdnetdebug; then
3b403b32 202 RD_DEBUG=yes
0d837ebf
HH
203 [ -n "$BASH" ] && \
204 export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): ';
205 fi
4bb570c9 206 fi
9e7a3bf2 207 export RD_DEBUG
4bb570c9 208 fi
3b403b32 209 [ "$RD_DEBUG" = "yes" ] && set -x
4bb570c9
HH
210}
211
c98bcec8 212setdebug
4bb570c9 213
ae5bc1fd
DD
214source_all() {
215 local f
216 [ "$1" ] && [ -d "/$1" ] || return
54a73cbb 217 for f in "/$1"/*.sh; do [ -e "$f" ] && . "$f"; done
ae5bc1fd 218}
51031303 219
0b53ca70
HH
220hookdir=/lib/dracut/hooks
221export hookdir
222
223source_hook() {
224 source_all "/lib/dracut/hooks/$1"
225}
226
8238850c
HH
227check_finished() {
228 local f
0b53ca70 229 for f in $hookdir/initqueue/finished/*.sh; do { [ -e "$f" ] && ( . "$f" ) ; } || return 1 ; done
8238850c
HH
230 return 0
231}
232
0375106c
HH
233source_conf() {
234 local f
235 [ "$1" ] && [ -d "/$1" ] || return
54a73cbb 236 for f in "/$1"/*.conf; do [ -e "$f" ] && . "$f"; done
0375106c
HH
237}
238
311a2769 239die() {
449adc61 240 {
79471f36
HH
241 echo "<24>dracut: FATAL: $@";
242 echo "<24>dracut: Refusing to continue";
449adc61
HH
243 } > /dev/kmsg
244
3b403b32 245 {
535ad9d1
HH
246 echo "warn dracut: FATAL: \"$@\"";
247 echo "warn dracut: Refusing to continue";
248 echo "exit 1"
0b53ca70 249 } >> $hookdir/emergency/01-die.sh
535ad9d1 250
03f405bc 251 > /run/initramfs/.die
311a2769
PS
252 exit 1
253}
254
695de849
HH
255check_quiet() {
256 if [ -z "$DRACUT_QUIET" ]; then
cc02093d 257 DRACUT_QUIET="yes"
fa7ada31 258 getargbool 0 rd.info -y rdinfo && DRACUT_QUIET="no"
cc02093d 259 getarg quiet || DRACUT_QUIET="yes"
695de849
HH
260 fi
261}
262
9f10836d 263warn() {
695de849 264 check_quiet
79471f36 265 echo "<28>dracut Warning: $@" > /dev/kmsg
695de849 266 [ "$DRACUT_QUIET" != "yes" ] && \
cc02093d 267 echo "dracut Warning: $@" >&2
449adc61
HH
268}
269
270info() {
695de849 271 check_quiet
79471f36 272 echo "<30>dracut: $@" > /dev/kmsg
c0dc4c5d 273 [ "$DRACUT_QUIET" != "yes" ] && \
3b403b32 274 echo "dracut: $@"
449adc61
HH
275}
276
277vinfo() {
3b403b32 278 while read line; do
449adc61
HH
279 info $line;
280 done
9f10836d
PS
281}
282
51031303
DD
283check_occurances() {
284 # Count the number of times the character $ch occurs in $str
285 # Return 0 if the count matches the expected number, 1 otherwise
286 local str="$1"
287 local ch="$2"
288 local expected="$3"
289 local count=0
290
291 while [ "${str#*$ch}" != "${str}" ]; do
cc02093d
HH
292 str="${str#*$ch}"
293 count=$(( $count + 1 ))
51031303
DD
294 done
295
296 [ $count -eq $expected ]
297}
07b2fbb1
PS
298
299incol2() {
300 local dummy check;
301 local file="$1";
302 local str="$2";
303
a2cb4dbc
HH
304 [ -z "$file" ] && return 1;
305 [ -z "$str" ] && return 1;
07b2fbb1
PS
306
307 while read dummy check restofline; do
cc02093d 308 [ "$check" = "$str" ] && return 0
07b2fbb1
PS
309 done < $file
310 return 1
311}
5c6a593f
HH
312
313udevsettle() {
8ef0be56
HH
314 [ -z "$UDEVVERSION" ] && UDEVVERSION=$(udevadm --version)
315
5c6a593f 316 if [ $UDEVVERSION -ge 143 ]; then
0b53ca70 317 udevadm settle --exit-if-exists=$hookdir/initqueue/work $settle_exit_if_exists
5c6a593f
HH
318 else
319 udevadm settle --timeout=30
320 fi
321}
273b197d 322
1dd5bc3f
HH
323udevproperty() {
324 [ -z "$UDEVVERSION" ] && UDEVVERSION=$(udevadm --version)
325
326 if [ $UDEVVERSION -ge 143 ]; then
cc02093d 327 for i in "$@"; do udevadm control --property=$i; done
1dd5bc3f 328 else
cc02093d 329 for i in "$@"; do udevadm control --env=$i; done
1dd5bc3f
HH
330 fi
331}
332
6822764f
HH
333ismounted() {
334 while read a m a; do
335 [ "$m" = "$1" ] && return 0
336 done < /proc/mounts
337 return 1
338}
339
bf87d252
HH
340wait_for_if_up() {
341 local cnt=0
3b403b32 342 while [ $cnt -lt 20 ]; do
cc02093d
HH
343 li=$(ip link show $1)
344 [ -z "${li##*state UP*}" ] && return 0
345 sleep 0.1
346 cnt=$(($cnt+1))
3b403b32 347 done
bf87d252
HH
348 return 1
349}
c98bcec8 350
3b403b32 351# root=nfs:[<server-ip>:]<root-dir>[:<nfs-options>]
c98bcec8
HH
352# root=nfs4:[<server-ip>:]<root-dir>[:<nfs-options>]
353nfsroot_to_var() {
354 # strip nfs[4]:
355 local arg="$@:"
356 nfs="${arg%%:*}"
357 arg="${arg##$nfs:}"
c98bcec8
HH
358
359 # check if we have a server
360 if strstr "$arg" ':/*' ; then
cc02093d
HH
361 server="${arg%%:/*}"
362 arg="/${arg##*:/}"
c98bcec8
HH
363 fi
364
365 path="${arg%%:*}"
366
367 # rest are options
368 options="${arg##$path}"
369 # strip leading ":"
370 options="${options##:}"
371 # strip ":"
372 options="${options%%:}"
3b403b32 373
c98bcec8
HH
374 # Does it really start with '/'?
375 [ -n "${path%%/*}" ] && path="error";
3b403b32 376
c98bcec8
HH
377 #Fix kernel legacy style separating path and options with ','
378 if [ "$path" != "${path#*,}" ] ; then
cc02093d
HH
379 options=${path#*,}
380 path=${path%%,*}
c98bcec8
HH
381 fi
382}
383
384ip_to_var() {
385 local v=${1}:
386 local i
3b403b32 387 set --
c98bcec8 388 while [ -n "$v" ]; do
cc02093d
HH
389 if [ "${v#\[*:*:*\]:}" != "$v" ]; then
390 # handle IPv6 address
391 i="${v%%\]:*}"
392 i="${i##\[}"
393 set -- "$@" "$i"
394 v=${v#\[$i\]:}
3b403b32 395 else
cc02093d
HH
396 set -- "$@" "${v%%:*}"
397 v=${v#*:}
398 fi
c98bcec8
HH
399 done
400
401 unset ip srv gw mask hostname dev autoconf
402 case $# in
cc02093d
HH
403 0) autoconf="error" ;;
404 1) autoconf=$1 ;;
405 2) dev=$1; autoconf=$2 ;;
406 *) ip=$1; srv=$2; gw=$3; mask=$4; hostname=$5; dev=$6; autoconf=$7 ;;
c98bcec8
HH
407 esac
408}
409
ccb0ab73
410# Create udev rule match for a device with its device name, or the udev property
411# ID_FS_UUID or ID_FS_LABEL
412#
413# example:
414# udevmatch LABEL=boot
415# prints:
416# ENV{ID_FS_LABEL}="boot"
417#
418# TOOD: symlinks
419udevmatch() {
420 case "$1" in
421 UUID=????????-????-????-????-????????????|LABEL=*)
422 printf 'ENV{ID_FS_%s}=="%s"' "${1%%=*}" "${1#*=}"
423 ;;
424 UUID=*)
425 printf 'ENV{ID_FS_UUID}=="%s*"' "${1#*=}"
426 ;;
427 /dev/?*) printf 'KERNEL=="%s"' "${1#/dev/}" ;;
428 *) return 255 ;;
429 esac
430}
431
432# Prints unique path for potential file inside specified directory. It consists
433# of specified directory, prefix and number at the end which is incremented
434# until non-existing file is found.
435#
436# funiq dir prefix
437#
438# example:
439# # ls /mnt
440# cdrom0 cdrom1
441#
442# # funiq /mnt cdrom
443# /mnt/cdrom2
444funiq() {
445 local dir="$1"; local prefix="$2"
446 local i=0
447
448 [ -d "${dir}" ] || return 1
449
450 while [ -e "${dir}/${prefix}$i" ]; do
451 i=$(($i+1)) || return 1
452 done
453
454 echo "${dir}/${prefix}$i"
455}
456
457# Creates unique directory and prints its path. It's using funiq to generate
458# path.
459#
460# mkuniqdir subdir new_dir_name
461mkuniqdir() {
462 local dir="$1"; local prefix="$2"
463 local retdir; local retdir_new
464
d125a470 465 [ -d "${dir}" ] || mkdir -m 0755 -p "${dir}" || return 1
ccb0ab73
466
467 retdir=$(funiq "${dir}" "${prefix}") || return 1
d125a470 468 until mkdir -m 0755 "${retdir}" 2>/dev/null; do
ccb0ab73
469 retdir_new=$(funiq "${dir}" "${prefix}") || return 1
470 [ "$retdir_new" = "$retdir" ] && return 1
471 retdir="$retdir_new"
472 done
473
474 echo "${retdir}"
475}
476
477# Evaluates command for UUIDs either given as arguments for this function or all
2926b5b3 478# listed in /dev/disk/by-uuid. UUIDs doesn't have to be fully specified. If
ccb0ab73
479# beginning is given it is expanded to all matching UUIDs. To pass full UUID to
480# your command use '$___' as a place holder. Remember to escape '$'!
481#
482# foreach_uuid_until [ -p prefix ] command UUIDs
2926b5b3 483#
ccb0ab73
484# prefix - string to put just before $___
485# command - command to be evaluated
486# UUIDs - list of UUIDs separated by space
2926b5b3
487#
488# The function returns after *first successful evaluation* of the given command
489# with status 0. If evaluation fails for every UUID function returns with
490# status 1.
491#
492# Example:
ccb0ab73 493# foreach_uuid_until "mount -U \$___ /mnt; echo OK; umount /mnt" \
2926b5b3
494# "01234 f512 a235567f-12a3-c123-a1b1-01234567abcb"
495foreach_uuid_until() (
496 cd /dev/disk/by-uuid
497
ccb0ab73 498 [ "$1" = -p ] && local prefix="$2" && shift 2
2926b5b3 499 local cmd="$1"; shift; local uuids_list="$*"
ccb0ab73 500 local uuid; local full_uuid; local ___
2926b5b3
501
502 [ -n "${cmd}" ] || return 1
503
504 for uuid in ${uuids_list:-*}; do
505 for full_uuid in ${uuid}*; do
506 [ -e "${full_uuid}" ] || continue
ccb0ab73 507 ___="${prefix}${full_uuid}"
2926b5b3
508 eval ${cmd} && return 0
509 done
510 done
511
512 return 1
513)