use findmnt with "--source" or "--target"
[platform/upstream/dracut.git] / dracut.sh
1 #!/bin/bash
2 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3 # ex: ts=8 sw=4 sts=4 et filetype=sh
4 #
5 # Generator script for a dracut initramfs
6 # Tries to retain some degree of compatibility with the command line
7 # of the various mkinitrd implementations out there
8 #
9
10 # Copyright 2005-2013 Red Hat, Inc.  All rights reserved.
11 #
12 # This program is free software; you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2 of the License, or
15 # (at your option) any later version.
16 #
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 #
25
26 # store for logging
27 dracut_args=( "$@" )
28
29 set -o pipefail
30
31 usage() {
32     [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
33     if [[ -f $dracutbasedir/dracut-version.sh ]]; then
34         . $dracutbasedir/dracut-version.sh
35     fi
36
37 #                                                       80x25 linebreak here ^
38     cat << EOF
39 Usage: $0 [OPTION]... [<initramfs> [<kernel-version>]]
40
41 Version: $DRACUT_VERSION
42
43 Creates initial ramdisk images for preloading modules
44
45   -h, --help  Display all options
46
47 If a [LIST] has multiple arguments, then you have to put these in quotes.
48
49 For example:
50
51     # dracut --add-drivers "module1 module2"  ...
52
53 EOF
54 }
55
56 long_usage() {
57     [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
58     if [[ -f $dracutbasedir/dracut-version.sh ]]; then
59         . $dracutbasedir/dracut-version.sh
60     fi
61
62 #                                                       80x25 linebreak here ^
63     cat << EOF
64 Usage: $0 [OPTION]... [<initramfs> [<kernel-version>]]
65
66 Version: $DRACUT_VERSION
67
68 Creates initial ramdisk images for preloading modules
69
70   --kver [VERSION]      Set kernel version to [VERSION].
71   -f, --force           Overwrite existing initramfs file.
72   -a, --add [LIST]      Add a space-separated list of dracut modules.
73   -m, --modules [LIST]  Specify a space-separated list of dracut modules to
74                          call when building the initramfs. Modules are located
75                          in /usr/lib/dracut/modules.d.
76   -o, --omit [LIST]     Omit a space-separated list of dracut modules.
77   --force-add [LIST]    Force to add a space-separated list of dracut modules
78                          to the default set of modules, when -H is specified.
79   -d, --drivers [LIST]  Specify a space-separated list of kernel modules to
80                          exclusively include in the initramfs.
81   --add-drivers [LIST]  Specify a space-separated list of kernel
82                          modules to add to the initramfs.
83   --omit-drivers [LIST] Specify a space-separated list of kernel
84                          modules not to add to the initramfs.
85   --filesystems [LIST]  Specify a space-separated list of kernel filesystem
86                          modules to exclusively include in the generic
87                          initramfs.
88   -k, --kmoddir [DIR]   Specify the directory, where to look for kernel
89                          modules
90   --fwdir [DIR]         Specify additional directories, where to look for
91                          firmwares, separated by :
92   --kernel-only         Only install kernel drivers and firmware files
93   --no-kernel           Do not install kernel drivers and firmware files
94   --kernel-cmdline [PARAMETERS] Specify default kernel command line parameters
95   --strip               Strip binaries in the initramfs
96   --nostrip             Do not strip binaries in the initramfs
97   --hardlink            Hardlink files in the initramfs
98   --nohardlink          Do not hardlink files in the initramfs
99   --prefix [DIR]        Prefix initramfs files with [DIR]
100   --noprefix            Do not prefix initramfs files
101   --mdadmconf           Include local /etc/mdadm.conf
102   --nomdadmconf         Do not include local /etc/mdadm.conf
103   --lvmconf             Include local /etc/lvm/lvm.conf
104   --nolvmconf           Do not include local /etc/lvm/lvm.conf
105   --fscks [LIST]        Add a space-separated list of fsck helpers.
106   --nofscks             Inhibit installation of any fsck helpers.
107   --ro-mnt              Mount / and /usr read-only by default.
108   -h, --help            This message
109   --debug               Output debug information of the build process
110   --profile             Output profile information of the build process
111   -L, --stdlog [0-6]    Specify logging level (to standard error)
112                          0 - suppress any messages
113                          1 - only fatal errors
114                          2 - all errors
115                          3 - warnings
116                          4 - info
117                          5 - debug info (here starts lots of output)
118                          6 - trace info (and even more)
119   -v, --verbose         Increase verbosity level
120   -q, --quiet           Decrease verbosity level
121   -c, --conf [FILE]     Specify configuration file to use.
122                          Default: /etc/dracut.conf
123   --confdir [DIR]       Specify configuration directory to use *.conf files
124                          from. Default: /etc/dracut.conf.d
125   --tmpdir [DIR]        Temporary directory to be used instead of default
126                          /var/tmp.
127   -l, --local           Local mode. Use modules from the current working
128                          directory instead of the system-wide installed in
129                          /usr/lib/dracut/modules.d.
130                          Useful when running dracut from a git checkout.
131   -H, --hostonly        Host-Only mode: Install only what is needed for
132                          booting the local host instead of a generic host.
133   -N, --no-hostonly     Disables Host-Only mode
134   --fstab               Use /etc/fstab to determine the root device.
135   --add-fstab [FILE]    Add file to the initramfs fstab
136   --mount "[DEV] [MP] [FSTYPE] [FSOPTS]"
137                         Mount device [DEV] on mountpoint [MP] with filesystem
138                         [FSTYPE] and options [FSOPTS] in the initramfs
139   --add-device "[DEV]"  Bring up [DEV] in initramfs
140   -i, --include [SOURCE] [TARGET]
141                         Include the files in the SOURCE directory into the
142                          Target directory in the final initramfs.
143                         If SOURCE is a file, it will be installed to TARGET
144                          in the final initramfs.
145   -I, --install [LIST]  Install the space separated list of files into the
146                          initramfs.
147   --gzip                Compress the generated initramfs using gzip.
148                          This will be done by default, unless another
149                          compression option or --no-compress is passed.
150   --bzip2               Compress the generated initramfs using bzip2.
151                          Make sure your kernel has bzip2 decompression support
152                          compiled in, otherwise you will not be able to boot.
153   --lzma                Compress the generated initramfs using lzma.
154                          Make sure your kernel has lzma support compiled in,
155                          otherwise you will not be able to boot.
156   --xz                  Compress the generated initramfs using xz.
157                          Make sure that your kernel has xz support compiled
158                          in, otherwise you will not be able to boot.
159   --compress [COMPRESSION] Compress the generated initramfs with the
160                          passed compression program.  Make sure your kernel
161                          knows how to decompress the generated initramfs,
162                          otherwise you will not be able to boot.
163   --no-compress         Do not compress the generated initramfs.  This will
164                          override any other compression options.
165   --list-modules        List all available dracut modules.
166   -M, --show-modules    Print included module's name to standard output during
167                          build.
168   --keep                Keep the temporary initramfs for debugging purposes
169   --printsize           Print out the module install size
170   --sshkey [SSHKEY]     Add ssh key to initramfs (use with ssh-client module)
171
172 If [LIST] has multiple arguments, then you have to put these in quotes.
173
174 For example:
175
176     # dracut --add-drivers "module1 module2"  ...
177
178 EOF
179 }
180
181 # function push()
182 # push values to a stack
183 # $1 = stack variable
184 # $2.. values
185 # example:
186 # push stack 1 2 "3 4"
187 push() {
188     local _i
189     local __stack=$1; shift
190     for _i in "$@"; do
191         eval ${__stack}'[${#'${__stack}'[@]}]="$_i"'
192     done
193 }
194
195 # function pop()
196 # pops the last value from a stack
197 # assigns value to second argument variable
198 # or echo to stdout, if no second argument
199 # $1 = stack variable
200 # $2 = optional variable to store the value
201 # example:
202 # pop stack val
203 # val=$(pop stack)
204 pop() {
205     local __stack=$1; shift
206     local __resultvar=$1
207     local _value;
208     # check for empty stack
209     eval '[[ ${#'${__stack}'[@]} -eq 0 ]] && return 1'
210
211     eval _value='${'${__stack}'[${#'${__stack}'[@]}-1]}'
212
213     if [[ "$__resultvar" ]]; then
214         eval $__resultvar="'$_value'"
215     else
216         echo "$_value"
217     fi
218     eval unset ${__stack}'[${#'${__stack}'[@]}-1]'
219     return 0
220 }
221
222 # Little helper function for reading args from the commandline.
223 # it automatically handles -a b and -a=b variants, and returns 1 if
224 # we need to shift $3.
225 read_arg() {
226     # $1 = arg name
227     # $2 = arg value
228     # $3 = arg parameter
229     local rematch='^[^=]*=(.*)$'
230     if [[ $2 =~ $rematch ]]; then
231         read "$1" <<< "${BASH_REMATCH[1]}"
232     else
233         read "$1" <<< "$3"
234         # There is no way to shift our callers args, so
235         # return 1 to indicate they should do it instead.
236         return 1
237     fi
238 }
239
240
241 dropindirs_sort()
242 {
243     suffix=$1; shift
244     args=("$@")
245     files=$(
246         while (( $# > 0 )); do
247             for i in ${1}/*${suffix}; do
248                 [[ -f $i ]] && echo ${i##*/}
249             done
250             shift
251         done | sort -Vu
252     )
253
254     for f in $files; do
255         for d in "${args[@]}"; do
256             if [[ -f "$d/$f" ]]; then
257                 echo "$d/$f"
258                 continue 2
259             fi
260         done
261     done
262 }
263
264 verbosity_mod_l=0
265 unset kernel
266 unset outfile
267
268 # Workaround -i, --include taking 2 arguments
269 set -- "${@/--include/++include}"
270
271 # This prevents any long argument ending with "-i"
272 # -i, like --opt-i but I think we can just prevent that
273 set -- "${@/%-i/++include}"
274
275 TEMP=$(unset POSIXLY_CORRECT; getopt \
276     -o "a:m:o:d:I:k:c:L:fvqlHhMN" \
277     --long kver: \
278     --long add: \
279     --long force-add: \
280     --long add-drivers: \
281     --long omit-drivers: \
282     --long modules: \
283     --long omit: \
284     --long drivers: \
285     --long filesystems: \
286     --long install: \
287     --long fwdir: \
288     --long libdirs: \
289     --long fscks: \
290     --long add-fstab: \
291     --long mount: \
292     --long device: \
293     --long nofscks: \
294     --long ro-mnt \
295     --long kmoddir: \
296     --long conf: \
297     --long confdir: \
298     --long tmpdir: \
299     --long stdlog: \
300     --long compress: \
301     --long prefix: \
302     --long force \
303     --long kernel-only \
304     --long no-kernel \
305     --long kernel-cmdline: \
306     --long strip \
307     --long nostrip \
308     --long hardlink \
309     --long nohardlink \
310     --long noprefix \
311     --long mdadmconf \
312     --long nomdadmconf \
313     --long lvmconf \
314     --long nolvmconf \
315     --long debug \
316     --long profile \
317     --long sshkey: \
318     --long verbose \
319     --long quiet \
320     --long local \
321     --long hostonly \
322     --long host-only \
323     --long no-hostonly \
324     --long no-host-only \
325     --long fstab \
326     --long help \
327     --long bzip2 \
328     --long lzma \
329     --long xz \
330     --long no-compress \
331     --long gzip \
332     --long list-modules \
333     --long show-modules \
334     --long keep \
335     --long printsize \
336     --long regenerate-all \
337     --long noimageifnotneeded \
338     -- "$@")
339
340 if (( $? != 0 )); then
341     usage
342     exit 1
343 fi
344
345 eval set -- "$TEMP"
346
347 while :; do
348     case $1 in
349         --kver)        kernel="$2"; shift;;
350         -a|--add)      push add_dracutmodules_l  "$2"; shift;;
351         --force-add)   push force_add_dracutmodules_l  "$2"; shift;;
352         --add-drivers) push add_drivers_l        "$2"; shift;;
353         --omit-drivers) push omit_drivers_l      "$2"; shift;;
354         -m|--modules)  push dracutmodules_l      "$2"; shift;;
355         -o|--omit)     push omit_dracutmodules_l "$2"; shift;;
356         -d|--drivers)  push drivers_l            "$2"; shift;;
357         --filesystems) push filesystems_l        "$2"; shift;;
358         -I|--install)  push install_items_l      "$2"; shift;;
359         --fwdir)       push fw_dir_l             "$2"; shift;;
360         --libdirs)     push libdirs_l            "$2"; shift;;
361         --fscks)       push fscks_l              "$2"; shift;;
362         --add-fstab)   push add_fstab_l          "$2"; shift;;
363         --mount)       push fstab_lines          "$2"; shift;;
364         --add-device|--device)
365                        push add_device_l         "$2"; shift;;
366         --kernel-cmdline) push kernel_cmdline_l  "$2"; shift;;
367         --nofscks)     nofscks_l="yes";;
368         --ro-mnt)      ro_mnt_l="yes";;
369         -k|--kmoddir)  drivers_dir_l="$2"; shift;;
370         -c|--conf)     conffile="$2"; shift;;
371         --confdir)     confdir="$2"; shift;;
372         --tmpdir)      tmpdir_l="$2"; shift;;
373         -L|--stdlog)   stdloglvl_l="$2"; shift;;
374         --compress)    compress_l="$2"; shift;;
375         --prefix)      prefix_l="$2"; shift;;
376         -f|--force)    force=yes;;
377         --kernel-only) kernel_only="yes"; no_kernel="no";;
378         --no-kernel)   kernel_only="no"; no_kernel="yes";;
379         --strip)       do_strip_l="yes";;
380         --nostrip)     do_strip_l="no";;
381         --hardlink)    do_hardlink_l="yes";;
382         --nohardlink)  do_hardlink_l="no";;
383         --noprefix)    prefix_l="/";;
384         --mdadmconf)   mdadmconf_l="yes";;
385         --nomdadmconf) mdadmconf_l="no";;
386         --lvmconf)     lvmconf_l="yes";;
387         --nolvmconf)   lvmconf_l="no";;
388         --debug)       debug="yes";;
389         --profile)     profile="yes";;
390         --sshkey)      sshkey="$2"; shift;;
391         -v|--verbose)  ((verbosity_mod_l++));;
392         -q|--quiet)    ((verbosity_mod_l--));;
393         -l|--local)
394                        allowlocal="yes"
395                        [[ -f "$(readlink -f ${0%/*})/dracut-functions.sh" ]] \
396                            && dracutbasedir="$(readlink -f ${0%/*})"
397                        ;;
398         -H|--hostonly|--host-only)
399                        hostonly_l="yes" ;;
400         -N|--no-hostonly|--no-host-only)
401                        hostonly_l="no" ;;
402         --fstab)       use_fstab_l="yes" ;;
403         -h|--help)     long_usage; exit 1 ;;
404         -i|--include)  push include_src "$2"
405                        shift;;
406         --bzip2)       compress_l="bzip2";;
407         --lzma)        compress_l="lzma";;
408         --xz)          compress_l="xz";;
409         --no-compress) _no_compress_l="cat";;
410         --gzip)        compress_l="gzip";;
411         --list-modules) do_list="yes";;
412         -M|--show-modules)
413                        show_modules_l="yes"
414                        ;;
415         --keep)        keep="yes";;
416         --printsize)   printsize="yes";;
417         --regenerate-all) regenerate_all="yes";;
418         --noimageifnotneeded) noimageifnotneeded="yes";;
419
420         --) shift; break;;
421
422         *)  # should not even reach this point
423             printf "\n!Unknown option: '%s'\n\n" "$1" >&2; usage; exit 1;;
424     esac
425     shift
426 done
427
428 # getopt cannot handle multiple arguments, so just handle "-I,--include"
429 # the old fashioned way
430
431 while (($# > 0)); do
432     case ${1%%=*} in
433         ++include) push include_src "$2"
434                        push include_target "$3"
435                        shift 2;;
436         *)
437             if ! [[ ${outfile+x} ]]; then
438                 outfile=$1
439             elif ! [[ ${kernel+x} ]]; then
440                 kernel=$1
441             else
442                 printf "\nUnknown arguments: %s\n\n" "$*" >&2
443                 usage; exit 1;
444             fi
445             ;;
446     esac
447     shift
448 done
449
450 if [[ $regenerate_all == "yes" ]]; then
451     ret=0
452     if [[ $kernel ]]; then
453         echo "--regenerate-all cannot be called with a kernel version" >&2
454         exit 1
455     fi
456
457     if [[ $outfile ]]; then
458         echo "--regenerate-all cannot be called with a image file" >&2
459         exit 1
460     fi
461
462     ((len=${#dracut_args[@]}))
463     for ((i=0; i < len; i++)); do
464         [[ ${dracut_args[$i]} == "--regenerate-all" ]] && \
465             unset dracut_args[$i]
466     done
467
468     cd /lib/modules
469     for i in *; do
470         [[ -f $i/modules.builtin ]] || continue
471         dracut --kver=$i "${dracut_args[@]}"
472         ((ret+=$?))
473     done
474     exit $ret
475 fi
476
477 if ! [[ $kernel ]]; then
478     kernel=$(uname -r)
479 fi
480
481 if ! [[ $outfile ]]; then
482     [[ -f /etc/machine-id ]] && read MACHINE_ID < /etc/machine-id
483
484     if [[ $MACHINE_ID ]] && ( [[ -d /boot/${MACHINE_ID} ]] || [[ -L /boot/${MACHINE_ID} ]] ); then
485         outfile="/boot/${MACHINE_ID}/$kernel/initrd"
486     else
487         outfile="/boot/initramfs-$kernel.img"
488     fi
489 fi
490
491 for i in /usr/sbin /sbin /usr/bin /bin; do
492     rl=$i
493     if [ -L "$i" ]; then
494         rl=$(readlink -f $i)
495     fi
496     if [[ "$NPATH" != "*:$rl*" ]] ; then
497         NPATH+=":$rl"
498     fi
499 done
500 export PATH="${NPATH#:}"
501 unset NPATH
502 unset LD_LIBRARY_PATH
503 unset GREP_OPTIONS
504
505 export DRACUT_LOG_LEVEL=warning
506 [[ $debug ]] && {
507     export DRACUT_LOG_LEVEL=debug
508     export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): ';
509     set -x
510 }
511
512 [[ $profile ]] && {
513     export PS4='+ $(date "+%s.%N") ${BASH_SOURCE}@${LINENO}: ';
514     set -x
515     debug=yes
516 }
517
518 [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
519
520 # if we were not passed a config file, try the default one
521 if [[ ! -f $conffile ]]; then
522     [[ $allowlocal ]] && conffile="$dracutbasedir/dracut.conf" || \
523         conffile="/etc/dracut.conf"
524 fi
525
526 if [[ ! -d $confdir ]]; then
527     [[ $allowlocal ]] && confdir="$dracutbasedir/dracut.conf.d" || \
528         confdir="/etc/dracut.conf.d"
529 fi
530
531 # source our config file
532 [[ -f $conffile ]] && . "$conffile"
533
534 # source our config dir
535 for f in $(dropindirs_sort ".conf" "$confdir" "$dracutbasedir/dracut.conf.d"); do
536     [[ -e $f ]] && . "$f"
537 done
538
539 # these optins add to the stuff in the config file
540 if (( ${#add_dracutmodules_l[@]} )); then
541     while pop add_dracutmodules_l val; do
542         add_dracutmodules+=" $val "
543     done
544 fi
545
546 if (( ${#force_add_dracutmodules_l[@]} )); then
547     while pop force_add_dracutmodules_l val; do
548         force_add_dracutmodules+=" $val "
549     done
550 fi
551
552 if (( ${#fscks_l[@]} )); then
553     while pop fscks_l val; do
554         fscks+=" $val "
555     done
556 fi
557
558 if (( ${#add_fstab_l[@]} )); then
559     while pop add_fstab_l val; do
560         add_fstab+=" $val "
561     done
562 fi
563
564 if (( ${#fstab_lines_l[@]} )); then
565     while pop fstab_lines_l val; do
566         push fstab_lines $val
567     done
568 fi
569
570 if (( ${#install_items_l[@]} )); then
571     while pop install_items_l val; do
572         install_items+=" $val "
573     done
574 fi
575
576 # these options override the stuff in the config file
577 if (( ${#dracutmodules_l[@]} )); then
578     dracutmodules=''
579     while pop dracutmodules_l val; do
580         dracutmodules+="$val "
581     done
582 fi
583
584 if (( ${#omit_dracutmodules_l[@]} )); then
585     omit_dracutmodules=''
586     while pop omit_dracutmodules_l val; do
587         omit_dracutmodules+="$val "
588     done
589 fi
590
591 if (( ${#filesystems_l[@]} )); then
592     filesystems=''
593     while pop filesystems_l val; do
594         filesystems+="$val "
595     done
596 fi
597
598 if (( ${#fw_dir_l[@]} )); then
599     fw_dir=''
600     while pop fw_dir_l val; do
601         fw_dir+="$val "
602     done
603 fi
604
605 if (( ${#libdirs_l[@]} )); then
606     libdirs=''
607     while pop libdirs_l val; do
608         libdirs+="$val "
609     done
610 fi
611
612 [[ $stdloglvl_l ]] && stdloglvl=$stdloglvl_l
613 [[ ! $stdloglvl ]] && stdloglvl=4
614 stdloglvl=$((stdloglvl + verbosity_mod_l))
615 ((stdloglvl > 6)) && stdloglvl=6
616 ((stdloglvl < 0)) && stdloglvl=0
617
618 [[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l
619 [[ $do_strip_l ]] && do_strip=$do_strip_l
620 [[ $do_strip ]] || do_strip=yes
621 [[ $do_hardlink_l ]] && do_hardlink=$do_hardlink_l
622 [[ $do_hardlink ]] || do_hardlink=yes
623 [[ $prefix_l ]] && prefix=$prefix_l
624 [[ $prefix = "/" ]] && unset prefix
625 [[ $hostonly_l ]] && hostonly=$hostonly_l
626 [[ $use_fstab_l ]] && use_fstab=$use_fstab_l
627 [[ $mdadmconf_l ]] && mdadmconf=$mdadmconf_l
628 [[ $lvmconf_l ]] && lvmconf=$lvmconf_l
629 [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
630 [[ $fw_dir ]] || fw_dir="/lib/firmware/updates /lib/firmware"
631 [[ $tmpdir_l ]] && tmpdir="$tmpdir_l"
632 [[ $tmpdir ]] || tmpdir=/var/tmp
633 [[ $compress_l ]] && compress=$compress_l
634 [[ $show_modules_l ]] && show_modules=$show_modules_l
635 [[ $nofscks_l ]] && nofscks="yes"
636 [[ $ro_mnt_l ]] && ro_mnt="yes"
637 # eliminate IFS hackery when messing with fw_dir
638 fw_dir=${fw_dir//:/ }
639
640 # handle compression options.
641 [[ $compress ]] || compress="gzip"
642 case $compress in
643     bzip2) compress="bzip2 -9";;
644     lzma)  compress="lzma -9";;
645     xz)    compress="xz --check=crc32 --lzma2=dict=1MiB";;
646     gzip)  command -v pigz > /dev/null 2>&1 && compress="pigz -9" || \
647                                          compress="gzip -9";;
648 esac
649 if [[ $_no_compress_l = "cat" ]]; then
650     compress="cat"
651 fi
652
653 [[ $hostonly = yes ]] && hostonly="-h"
654 [[ $hostonly != "-h" ]] && unset hostonly
655
656 readonly TMPDIR="$tmpdir"
657 readonly initdir=$(mktemp --tmpdir="$TMPDIR/" -d -t initramfs.XXXXXX)
658 [ -d "$initdir" ] || {
659     echo "dracut: mktemp --tmpdir=\"$TMPDIR/\" -d -t initramfs.XXXXXX failed." >&2
660     exit 1
661 }
662
663 # clean up after ourselves no matter how we die.
664 trap 'ret=$?;[[ $outfile ]] && [[ -f $outfile.$$ ]] && rm -f "$outfile.$$";[[ $keep ]] && echo "Not removing $initdir." >&2 || { [[ $initdir ]] && rm -rf "$initdir";exit $ret; };' EXIT
665 # clean up after ourselves no matter how we die.
666 trap 'exit 1;' SIGINT
667
668 export DRACUT_KERNEL_LAZY="1"
669 export DRACUT_RESOLVE_LAZY="1"
670
671 if [[ -f $dracutbasedir/dracut-functions.sh ]]; then
672     . $dracutbasedir/dracut-functions.sh
673 else
674     echo "dracut: Cannot find $dracutbasedir/dracut-functions.sh." >&2
675     echo "dracut: Are you running from a git checkout?" >&2
676     echo "dracut: Try passing -l as an argument to $0" >&2
677     exit 1
678 fi
679
680 inst /bin/sh
681 if ! $DRACUT_INSTALL ${initdir+-D "$initdir"} -R "$initdir/bin/sh" &>/dev/null; then
682     unset DRACUT_RESOLVE_LAZY
683     export DRACUT_RESOLVE_DEPS=1
684 fi
685 rm -fr ${initdir}/*
686
687 if [[ -f $dracutbasedir/dracut-version.sh ]]; then
688     . $dracutbasedir/dracut-version.sh
689 fi
690
691 # Verify bash version, current minimum is 3.1
692 if (( ${BASH_VERSINFO[0]} < 3 ||
693     ( ${BASH_VERSINFO[0]} == 3 && ${BASH_VERSINFO[1]} < 1 ) )); then
694     dfatal 'You need at least Bash 3.1 to use dracut, sorry.'
695     exit 1
696 fi
697
698 dracutfunctions=$dracutbasedir/dracut-functions.sh
699 export dracutfunctions
700
701 if (( ${#drivers_l[@]} )); then
702     drivers=''
703     while pop drivers_l val; do
704         drivers+="$val "
705     done
706 fi
707 drivers=${drivers/-/_}
708
709 if (( ${#add_drivers_l[@]} )); then
710     while pop add_drivers_l val; do
711         add_drivers+=" $val "
712     done
713 fi
714 add_drivers=${add_drivers/-/_}
715
716 if (( ${#omit_drivers_l[@]} )); then
717     while pop omit_drivers_l val; do
718         omit_drivers+=" $val "
719     done
720 fi
721 omit_drivers=${omit_drivers/-/_}
722
723 if (( ${#kernel_cmdline_l[@]} )); then
724     while pop kernel_cmdline_l val; do
725         kernel_cmdline+=" $val "
726     done
727 fi
728
729 omit_drivers_corrected=""
730 for d in $omit_drivers; do
731     strstr " $drivers $add_drivers " " $d " && continue
732     omit_drivers_corrected+="$d|"
733 done
734 omit_drivers="${omit_drivers_corrected%|}"
735 unset omit_drivers_corrected
736
737 # prepare args for logging
738 for ((i=0; i < ${#dracut_args[@]}; i++)); do
739     strstr "${dracut_args[$i]}" " " && \
740         dracut_args[$i]="\"${dracut_args[$i]}\""
741         #" keep vim happy
742 done
743 ddebug "Executing: $0 ${dracut_args[@]}"
744
745 [[ $do_list = yes ]] && {
746     for mod in $dracutbasedir/modules.d/*; do
747         [[ -d $mod ]] || continue;
748         [[ -e $mod/install || -e $mod/installkernel || \
749             -e $mod/module-setup.sh ]] || continue
750         echo ${mod##*/??}
751     done
752     exit 0
753 }
754
755 # This is kinda legacy -- eventually it should go away.
756 case $dracutmodules in
757     ""|auto) dracutmodules="all" ;;
758 esac
759
760 abs_outfile=$(readlink -f "$outfile") && outfile="$abs_outfile"
761
762 if [[ -d $srcmods ]]; then
763     [[ -f $srcmods/modules.dep ]] || {
764       dwarn "$srcmods/modules.dep is missing. Did you run depmod?"
765     }
766 fi
767
768 if [[ -f $outfile && ! $force ]]; then
769     dfatal "Will not override existing initramfs ($outfile) without --force"
770     exit 1
771 fi
772
773 outdir=${outfile%/*}
774 [[ $outdir ]] || outdir="/"
775
776 if [[ ! -d "$outdir" ]]; then
777     dfatal "Can't write to $outdir: Directory $outdir does not exist or is not accessible."
778     exit 1
779 elif [[ ! -w "$outdir" ]]; then
780     dfatal "No permission to write to $outdir."
781     exit 1
782 elif [[ -f "$outfile" && ! -w "$outfile" ]]; then
783     dfatal "No permission to write $outfile."
784     exit 1
785 fi
786
787 # Need to be able to have non-root users read stuff (rpcbind etc)
788 chmod 755 "$initdir"
789
790 if [[ $hostonly ]]; then
791     for i in /sys /proc /run /dev; do
792         if ! findmnt --target "$i" &>/dev/null; then
793             dwarning "Turning off host-only mode: '$i' is not mounted!"
794             unset hostonly
795         fi
796     done
797     if ! [[ -d /run/udev/data ]]; then
798         dwarning "Turning off host-only mode: udev database not found!"
799         unset hostonly
800     fi
801 fi
802
803 declare -A host_fs_types
804
805 for line in "${fstab_lines[@]}"; do
806     set -- $line
807     #dev mp fs fsopts
808     push host_devs "$1"
809     host_fs_types["$1"]="$3"
810 done
811
812 for f in $add_fstab; do
813     [ -e $f ] || continue
814     while read dev rest; do
815         push host_devs $dev
816     done < $f
817 done
818
819 if (( ${#add_device_l[@]} )); then
820     while pop add_device_l val; do
821         add_device+=" $val "
822     done
823 fi
824
825 for dev in $add_device; do
826     push host_devs $dev
827 done
828
829 if [[ $hostonly ]]; then
830     # in hostonly mode, determine all devices, which have to be accessed
831     # and examine them for filesystem types
832
833     for mp in \
834         "/" \
835         "/etc" \
836         "/usr" \
837         "/usr/bin" \
838         "/usr/sbin" \
839         "/usr/lib" \
840         "/usr/lib64" \
841         "/boot";
842     do
843         mountpoint "$mp" >/dev/null 2>&1 || continue
844         push host_devs $(readlink -f "/dev/block/$(find_block_device "$mp")")
845     done
846
847     while read dev type rest; do
848         [[ -b $dev ]] || continue
849         [[ "$type" == "partition" ]] || continue
850         while read _d _m _t _o _r; do
851             [[ "$_d" == \#* ]] && continue
852             [[ $_d ]] || continue
853             [[ $_t != "swap" ]] || [[ $_m != "swap" ]] && continue
854             [[ "$_o" == *noauto* ]] && continue
855             [[ "$_d" == UUID\=* ]] && _d="/dev/disk/by-uuid/${_d#UUID=}"
856             [[ "$_d" == LABEL\=* ]] && _d="/dev/disk/by-label/$_d#LABEL=}"
857             [[ "$_d" -ef "$dev" ]] || continue
858
859             while read _mapper _a _p _o; do
860                 [[ $_mapper = \#* ]] && continue
861                 [[ "$_d" -ef /dev/mapper/"$_mapper" ]] || continue
862                 [[ "$_o" ]] || _o="$_p"
863                 # skip mkswap swap
864                 [[ $_o == *swap* ]] && continue 2
865             done < /etc/crypttab
866
867             push host_devs $(readlink -f $dev)
868             break
869         done < /etc/fstab
870     done < /proc/swaps
871 fi
872
873 _get_fs_type() (
874     [[ $1 ]] || return
875     if [[ -b $1 ]] && get_fs_env $1; then
876         echo "$(readlink -f $1) $ID_FS_TYPE"
877         return 1
878     fi
879     if [[ -b /dev/block/$1 ]] && get_fs_env /dev/block/$1; then
880         echo "$(readlink -f /dev/block/$1) $ID_FS_TYPE"
881         return 1
882     fi
883     if fstype=$(find_dev_fstype $1); then
884         echo "$1 $fstype"
885         return 1
886     fi
887     return 1
888 )
889
890 for dev in "${host_devs[@]}"; do
891     while read key val; do
892         host_fs_types["$key"]="$val"
893     done < <(
894         _get_fs_type $dev
895         check_block_and_slaves_all _get_fs_type $(get_maj_min $dev)
896     )
897 done
898
899 [[ -d $udevdir ]] \
900     || udevdir=$(pkg-config udev --variable=udevdir 2>/dev/null)
901 if ! [[ -d "$udevdir" ]]; then
902     [[ -d /lib/udev ]] && udevdir=/lib/udev
903     [[ -d /usr/lib/udev ]] && udevdir=/usr/lib/udev
904 fi
905
906 [[ -d $systemdutildir ]] \
907     || systemdutildir=$(pkg-config systemd --variable=systemdutildir 2>/dev/null)
908
909 if ! [[ -d "$systemdutildir" ]]; then
910     [[ -d /lib/systemd ]] && systemdutildir=/lib/systemd
911     [[ -d /usr/lib/systemd ]] && systemdutildir=/usr/lib/systemd
912 fi
913
914 [[ -d $systemdsystemunitdir ]] \
915     || systemdsystemunitdir=$(pkg-config systemd --variable=systemdsystemunitdir 2>/dev/null)
916
917 [[ -d "$systemdsystemunitdir" ]] || systemdsystemunitdir=${systemdutildir}/system
918
919 [[ -d $systemdsystemconfdir ]] \
920     || systemdsystemconfdir=$(pkg-config systemd --variable=systemdsystemconfdir 2>/dev/null)
921
922 [[ -d "$systemdsystemconfdir" ]] || systemdsystemconfdir=/etc/systemd/system
923
924 export initdir dracutbasedir dracutmodules \
925     fw_dir drivers_dir debug no_kernel kernel_only \
926     omit_drivers mdadmconf lvmconf \
927     use_fstab fstab_lines libdirs fscks nofscks ro_mnt \
928     stdloglvl sysloglvl fileloglvl kmsgloglvl logfile \
929     debug host_fs_types host_devs sshkey add_fstab \
930     DRACUT_VERSION udevdir prefix filesystems drivers \
931     systemdutildir systemdsystemunitdir systemdsystemconfdir
932
933 # Create some directory structure first
934 [[ $prefix ]] && mkdir -m 0755 -p "${initdir}${prefix}"
935
936 [[ -h /lib ]] || mkdir -m 0755 -p "${initdir}${prefix}/lib"
937 [[ $prefix ]] && ln -sfn "${prefix#/}/lib" "$initdir/lib"
938
939 if [[ $prefix ]]; then
940     for d in bin etc lib sbin tmp usr var $libdirs; do
941         strstr "$d" "/" && continue
942         ln -sfn "${prefix#/}/${d#/}" "$initdir/$d"
943     done
944 fi
945
946 if [[ $kernel_only != yes ]]; then
947     for d in usr/bin usr/sbin bin etc lib sbin tmp usr var $libdirs; do
948         [[ -e "${initdir}${prefix}/$d" ]] && continue
949         if [ -L "/$d" ]; then
950             inst_symlink "/$d" "${prefix}/$d"
951         else
952             mkdir -m 0755 -p "${initdir}${prefix}/$d"
953         fi
954     done
955
956     for d in dev proc sys sysroot root run run/lock run/initramfs; do
957         if [ -L "/$d" ]; then
958             inst_symlink "/$d"
959         else
960             mkdir -m 0755 -p "$initdir/$d"
961         fi
962     done
963
964     ln -sfn ../run "$initdir/var/run"
965     ln -sfn ../run/lock "$initdir/var/lock"
966     ln -sfn ../run/log "$initdir/var/log"
967 else
968     for d in lib "$libdir"; do
969         [[ -e "${initdir}${prefix}/$d" ]] && continue
970         if [ -h "/$d" ]; then
971             inst "/$d" "${prefix}/$d"
972         else
973             mkdir -m 0755 -p "${initdir}${prefix}/$d"
974         fi
975     done
976 fi
977
978 if [[ $kernel_only != yes ]]; then
979     mkdir -p "${initdir}/etc/cmdline.d"
980     for _d in $hookdirs; do
981         mkdir -m 0755 -p ${initdir}/lib/dracut/hooks/$_d
982     done
983     if [[ "$UID" = "0" ]]; then
984         [ -c ${initdir}/dev/null ] || mknod ${initdir}/dev/null c 1 3
985         [ -c ${initdir}/dev/kmsg ] || mknod ${initdir}/dev/kmsg c 1 11
986         [ -c ${initdir}/dev/console ] || mknod ${initdir}/dev/console c 5 1
987     fi
988 fi
989
990 mods_to_load=""
991 # check all our modules to see if they should be sourced.
992 # This builds a list of modules that we will install next.
993 for_each_module_dir check_module
994 for_each_module_dir check_mount
995
996 strstr "$mods_to_load" "fips" && export DRACUT_FIPS_MODE=1
997
998 _isize=0 #initramfs size
999 modules_loaded=" "
1000 # source our modules.
1001 for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
1002     _d_mod=${moddir##*/}; _d_mod=${_d_mod#[0-9][0-9]}
1003     if strstr "$mods_to_load" " $_d_mod "; then
1004         [[ $show_modules = yes ]] && echo "$_d_mod" || \
1005             dinfo "*** Including module: $_d_mod ***"
1006         if [[ $kernel_only = yes ]]; then
1007             module_installkernel $_d_mod || {
1008                 dfatal "installkernel failed in module $_d_mod"
1009                 exit 1
1010             }
1011         else
1012             module_install $_d_mod
1013             if [[ $no_kernel != yes ]]; then
1014                 module_installkernel $_d_mod || {
1015                     dfatal "installkernel failed in module $_d_mod"
1016                     exit 1
1017                 }
1018             fi
1019         fi
1020         mods_to_load=${mods_to_load// $_d_mod /}
1021         modules_loaded+="$_d_mod "
1022
1023         #print the module install size
1024         if [ -n "$printsize" ]; then
1025             _isize_new=$(du -sk ${initdir}|cut -f1)
1026             _isize_delta=$(($_isize_new - $_isize))
1027             echo "$_d_mod install size: ${_isize_delta}k"
1028             _isize=$_isize_new
1029         fi
1030     fi
1031 done
1032 unset moddir
1033
1034 for i in $modules_loaded; do
1035     mkdir -p $initdir/lib/dracut
1036     echo "$i" >> $initdir/lib/dracut/modules.txt
1037 done
1038
1039 dinfo "*** Including modules done ***"
1040
1041 ## final stuff that has to happen
1042 if [[ $no_kernel != yes ]]; then
1043
1044     if [[ $drivers ]]; then
1045         hostonly='' instmods $drivers
1046     fi
1047
1048     if [[ $add_drivers ]]; then
1049         hostonly='' instmods -c $add_drivers
1050     fi
1051     if [[ $filesystems ]]; then
1052         hostonly='' instmods -c $filesystems
1053     fi
1054
1055     dinfo "*** Installing kernel module dependencies and firmware ***"
1056     dracut_kernel_post
1057     dinfo "*** Installing kernel module dependencies and firmware done ***"
1058
1059     if [[ $noimageifnotneeded == yes ]] && [[ $hostonly ]]; then
1060         if [[ ! -f "$initdir/lib/dracut/need-initqueue" ]] && \
1061             [[ -f ${initdir}/lib/modules/$kernel/modules.dep && ! -s ${initdir}/lib/modules/$kernel/modules.dep ]]; then
1062             for i in ${initdir}/etc/cmdline.d/*.conf; do
1063                 # We need no initramfs image and do not generate one.
1064                 [[ $i == "${initdir}/etc/cmdline.d/*.conf" ]] && exit 0
1065             done
1066         fi
1067     fi
1068 fi
1069
1070 if [[ $kernel_only != yes ]]; then
1071     (( ${#install_items[@]} > 0 )) && dracut_install  ${install_items[@]}
1072
1073     [[ $kernel_cmdline ]] && echo "$kernel_cmdline" >> "${initdir}/etc/cmdline.d/01-default.conf"
1074
1075     while pop fstab_lines line; do
1076         echo "$line 0 0" >> "${initdir}/etc/fstab"
1077     done
1078
1079     for f in $add_fstab; do
1080         cat $f >> "${initdir}/etc/fstab"
1081     done
1082
1083     if [ -d ${initdir}/$systemdutildir ]; then
1084         mkdir -p ${initdir}/etc/conf.d
1085         {
1086             echo "systemdutildir=\"$systemdutildir\""
1087             echo "systemdsystemunitdir=\"$systemdsystemunitdir\""
1088             echo "systemdsystemconfdir=\"$systemdsystemconfdir\""
1089         } > ${initdir}/etc/conf.d/systemd.conf
1090     fi
1091
1092     if [[ $DRACUT_RESOLVE_LAZY ]] && [[ $DRACUT_INSTALL ]]; then
1093         dinfo "*** Resolving executable dependencies ***"
1094         find "$initdir" -type f \
1095             '(' -perm -0100 -or -perm -0010 -or -perm -0001 ')' \
1096             -not -path '*.ko' -print0 \
1097         | xargs -r -0 $DRACUT_INSTALL ${initdir+-D "$initdir"} -R ${DRACUT_FIPS_MODE+-H}
1098         dinfo "*** Resolving executable dependencies done***"
1099     fi
1100 fi
1101
1102 while pop include_src src && pop include_target tgt; do
1103     if [[ $src && $tgt ]]; then
1104         if [[ -f $src ]]; then
1105             inst $src $tgt
1106         else
1107             ddebug "Including directory: $src"
1108             mkdir -p "${initdir}/${tgt}"
1109             # check for preexisting symlinks, so we can cope with the
1110             # symlinks to $prefix
1111             for i in "$src"/*; do
1112                 [[ -e "$i" || -h "$i" ]] || continue
1113                 s=${initdir}/${tgt}/${i#$src/}
1114                 if [[ -d "$i" ]]; then
1115                     if ! [[ -e "$s" ]]; then
1116                         mkdir -m 0755 -p "$s"
1117                         chmod --reference="$i" "$s"
1118                     fi
1119                     cp --reflink=auto --sparse=auto -fa -t "$s" "$i"/*
1120                 else
1121                     cp --reflink=auto --sparse=auto -fa -t "$s" "$i"
1122                 fi
1123             done
1124         fi
1125     fi
1126 done
1127
1128 if [[ $kernel_only != yes ]]; then
1129     # make sure that library links are correct and up to date
1130     for f in /etc/ld.so.conf /etc/ld.so.conf.d/*; do
1131         [[ -f $f ]] && inst_simple "$f"
1132     done
1133     if ! ldconfig -r "$initdir"; then
1134         if [[ $UID = 0 ]]; then
1135             derror "ldconfig exited ungracefully"
1136         else
1137             derror "ldconfig might need uid=0 (root) for chroot()"
1138         fi
1139     fi
1140 fi
1141
1142 if (($maxloglvl >= 5)); then
1143     ddebug "Listing sizes of included files:"
1144     du -c "$initdir" | sort -n | ddebug
1145 fi
1146
1147 PRELINK_BIN=$(command -v prelink)
1148 if [[ $UID = 0 ]] && [[ $PRELINK_BIN ]]; then
1149     if [[ $DRACUT_FIPS_MODE ]]; then
1150         dinfo "*** Installing prelink files ***"
1151         dracut_install -o prelink /etc/prelink.conf /etc/prelink.conf.d/*.conf /etc/prelink.cache
1152     else
1153         dinfo "*** Pre-linking files ***"
1154         dracut_install -o prelink /etc/prelink.conf /etc/prelink.conf.d/*.conf
1155         chroot "$initdir" $PRELINK_BIN -a
1156         rm -f "$initdir"/$PRELINK_BIN
1157         rm -fr "$initdir"/etc/prelink.*
1158         dinfo "*** Pre-linking files done ***"
1159     fi
1160 fi
1161
1162 if [[ $do_hardlink = yes ]] && command -v hardlink >/dev/null; then
1163     dinfo "*** Hardlinking files ***"
1164     hardlink "$initdir" 2>&1
1165     dinfo "*** Hardlinking files done ***"
1166 fi
1167
1168 # strip binaries
1169 if [[ $do_strip = yes ]] ; then
1170     for p in strip xargs find; do
1171         if ! type -P $p >/dev/null; then
1172             dinfo "Could not find '$p'. Not stripping the initramfs."
1173             do_strip=no
1174         fi
1175     done
1176 fi
1177
1178 if [[ $do_strip = yes ]] ; then
1179     dinfo "*** Stripping files ***"
1180     if [[ $DRACUT_FIPS_MODE ]]; then
1181         find "$initdir" -type f \
1182             -executable -not -path '*/lib/modules/*.ko' -print0 \
1183             | while read -r -d $'\0' f; do
1184             if ! [[ -e "${f%/*}/.${f##*/}.hmac" ]] \
1185                 && ! [[ -e "/lib/hmaccalc/${f##*/}.hmac" ]] \
1186                 && ! [[ -e "/lib64/hmaccalc/${f##*/}.hmac" ]] \
1187                 && ! [[ -e "/lib/fipscheck/${f##*/}.hmac" ]] \
1188                 && ! [[ -e "/lib64/fipscheck/${f##*/}.hmac" ]]; then
1189                 echo -n "$f"; echo -n -e "\000"
1190             fi
1191         done | xargs -r -0 strip -g 2>/dev/null
1192     else
1193         find "$initdir" -type f \
1194             -executable -not -path '*/lib/modules/*.ko' -print0 \
1195             | xargs -r -0 strip -g 2>/dev/null
1196     fi
1197
1198     # strip kernel modules, but do not touch signed modules
1199     find "$initdir" -type f -path '*/lib/modules/*.ko' -print0 \
1200         | while read -r -d $'\0' f; do
1201         SIG=$(tail -c 28 "$f")
1202         [[ $SIG == '~Module signature appended~' ]] || { echo -n "$f"; echo -n -e "\000"; }
1203     done | xargs -r -0 strip -g
1204
1205     dinfo "*** Stripping files done ***"
1206 fi
1207
1208 rm -f "$outfile"
1209 dinfo "*** Creating image file ***"
1210 if ! ( umask 077; cd "$initdir"; find . |cpio -R 0:0 -H newc -o --quiet| \
1211     $compress > "$outfile.$$"; ); then
1212     dfatal "dracut: creation of $outfile.$$ failed"
1213     exit 1
1214 fi
1215 mv $outfile.$$ $outfile
1216 dinfo "*** Creating image file done ***"
1217
1218 dinfo "Wrote $outfile:"
1219 dinfo "$(ls -l "$outfile")"
1220
1221 exit 0