beautified shell code
[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         printf "%s" "$_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 dropindirs_sort()
241 {
242     local suffix=$1; shift
243     local -a files
244     local f d
245
246     readarray -t files < <(
247         for d in "$@"; do
248             for i in "$d/"*"$suffix"; do
249                 if [[ -e "$i" ]]; then
250                     printf "%s" "${i##*/}"
251                 fi
252             done
253         done | sort -Vu
254     )
255
256     for f in "${files[@]}"; do
257         for d in "$@"; do
258             if [[ -e "$d/$f" ]]; then
259                 printf "%s" "$d/$f"
260                 continue 2
261             fi
262         done
263     done
264 }
265
266 verbosity_mod_l=0
267 unset kernel
268 unset outfile
269
270 # Workaround -i, --include taking 2 arguments
271 set -- "${@/--include/++include}"
272
273 # This prevents any long argument ending with "-i"
274 # -i, like --opt-i but I think we can just prevent that
275 set -- "${@/%-i/++include}"
276
277 TEMP=$(unset POSIXLY_CORRECT; getopt \
278     -o "a:m:o:d:I:k:c:L:fvqlHhMN" \
279     --long kver: \
280     --long add: \
281     --long force-add: \
282     --long add-drivers: \
283     --long omit-drivers: \
284     --long modules: \
285     --long omit: \
286     --long drivers: \
287     --long filesystems: \
288     --long install: \
289     --long fwdir: \
290     --long libdirs: \
291     --long fscks: \
292     --long add-fstab: \
293     --long mount: \
294     --long device: \
295     --long nofscks: \
296     --long ro-mnt \
297     --long kmoddir: \
298     --long conf: \
299     --long confdir: \
300     --long tmpdir: \
301     --long stdlog: \
302     --long compress: \
303     --long prefix: \
304     --long force \
305     --long kernel-only \
306     --long no-kernel \
307     --long kernel-cmdline: \
308     --long strip \
309     --long nostrip \
310     --long hardlink \
311     --long nohardlink \
312     --long noprefix \
313     --long mdadmconf \
314     --long nomdadmconf \
315     --long lvmconf \
316     --long nolvmconf \
317     --long debug \
318     --long profile \
319     --long sshkey: \
320     --long verbose \
321     --long quiet \
322     --long local \
323     --long hostonly \
324     --long host-only \
325     --long no-hostonly \
326     --long no-host-only \
327     --long fstab \
328     --long help \
329     --long bzip2 \
330     --long lzma \
331     --long xz \
332     --long no-compress \
333     --long gzip \
334     --long list-modules \
335     --long show-modules \
336     --long keep \
337     --long printsize \
338     --long regenerate-all \
339     --long noimageifnotneeded \
340     -- "$@")
341
342 if (( $? != 0 )); then
343     usage
344     exit 1
345 fi
346
347 eval set -- "$TEMP"
348
349 while :; do
350     case $1 in
351         --kver)        kernel="$2"; shift;;
352         -a|--add)      push add_dracutmodules_l  "$2"; shift;;
353         --force-add)   push force_add_dracutmodules_l  "$2"; shift;;
354         --add-drivers) push add_drivers_l        "$2"; shift;;
355         --omit-drivers) push omit_drivers_l      "$2"; shift;;
356         -m|--modules)  push dracutmodules_l      "$2"; shift;;
357         -o|--omit)     push omit_dracutmodules_l "$2"; shift;;
358         -d|--drivers)  push drivers_l            "$2"; shift;;
359         --filesystems) push filesystems_l        "$2"; shift;;
360         -I|--install)  push install_items_l      "$2"; shift;;
361         --fwdir)       push fw_dir_l             "$2"; shift;;
362         --libdirs)     push libdirs_l            "$2"; shift;;
363         --fscks)       push fscks_l              "$2"; shift;;
364         --add-fstab)   push add_fstab_l          "$2"; shift;;
365         --mount)       push fstab_lines          "$2"; shift;;
366         --add-device|--device)
367                        push add_device_l         "$2"; shift;;
368         --kernel-cmdline) push kernel_cmdline_l  "$2"; shift;;
369         --nofscks)     nofscks_l="yes";;
370         --ro-mnt)      ro_mnt_l="yes";;
371         -k|--kmoddir)  drivers_dir_l="$2"; shift;;
372         -c|--conf)     conffile="$2"; shift;;
373         --confdir)     confdir="$2"; shift;;
374         --tmpdir)      tmpdir_l="$2"; shift;;
375         -L|--stdlog)   stdloglvl_l="$2"; shift;;
376         --compress)    compress_l="$2"; shift;;
377         --prefix)      prefix_l="$2"; shift;;
378         -f|--force)    force=yes;;
379         --kernel-only) kernel_only="yes"; no_kernel="no";;
380         --no-kernel)   kernel_only="no"; no_kernel="yes";;
381         --strip)       do_strip_l="yes";;
382         --nostrip)     do_strip_l="no";;
383         --hardlink)    do_hardlink_l="yes";;
384         --nohardlink)  do_hardlink_l="no";;
385         --noprefix)    prefix_l="/";;
386         --mdadmconf)   mdadmconf_l="yes";;
387         --nomdadmconf) mdadmconf_l="no";;
388         --lvmconf)     lvmconf_l="yes";;
389         --nolvmconf)   lvmconf_l="no";;
390         --debug)       debug="yes";;
391         --profile)     profile="yes";;
392         --sshkey)      sshkey="$2"; shift;;
393         -v|--verbose)  ((verbosity_mod_l++));;
394         -q|--quiet)    ((verbosity_mod_l--));;
395         -l|--local)
396                        allowlocal="yes"
397                        [[ -f "$(readlink -f "${0%/*}")/dracut-functions.sh" ]] \
398                            && dracutbasedir="$(readlink -f "${0%/*}")"
399                        ;;
400         -H|--hostonly|--host-only)
401                        hostonly_l="yes" ;;
402         -N|--no-hostonly|--no-host-only)
403                        hostonly_l="no" ;;
404         --fstab)       use_fstab_l="yes" ;;
405         -h|--help)     long_usage; exit 1 ;;
406         -i|--include)  push include_src "$2"
407                        shift;;
408         --bzip2)       compress_l="bzip2";;
409         --lzma)        compress_l="lzma";;
410         --xz)          compress_l="xz";;
411         --no-compress) _no_compress_l="cat";;
412         --gzip)        compress_l="gzip";;
413         --list-modules) do_list="yes";;
414         -M|--show-modules)
415                        show_modules_l="yes"
416                        ;;
417         --keep)        keep="yes";;
418         --printsize)   printsize="yes";;
419         --regenerate-all) regenerate_all="yes";;
420         --noimageifnotneeded) noimageifnotneeded="yes";;
421
422         --) shift; break;;
423
424         *)  # should not even reach this point
425             printf "\n!Unknown option: '%s'\n\n" "$1" >&2; usage; exit 1;;
426     esac
427     shift
428 done
429
430 # getopt cannot handle multiple arguments, so just handle "-I,--include"
431 # the old fashioned way
432
433 while (($# > 0)); do
434     case ${1%%=*} in
435         ++include) push include_src "$2"
436                        push include_target "$3"
437                        shift 2;;
438         *)
439             if ! [[ ${outfile+x} ]]; then
440                 outfile=$1
441             elif ! [[ ${kernel+x} ]]; then
442                 kernel=$1
443             else
444                 printf "\nUnknown arguments: %s\n\n" "$*" >&2
445                 usage; exit 1;
446             fi
447             ;;
448     esac
449     shift
450 done
451
452 if [[ $regenerate_all == "yes" ]]; then
453     ret=0
454     if [[ $kernel ]]; then
455         printf -- "--regenerate-all cannot be called with a kernel version\n" >&2
456         exit 1
457     fi
458
459     if [[ $outfile ]]; then
460         printf -- "--regenerate-all cannot be called with a image file\n" >&2
461         exit 1
462     fi
463
464     ((len=${#dracut_args[@]}))
465     for ((i=0; i < len; i++)); do
466         [[ ${dracut_args[$i]} == "--regenerate-all" ]] && \
467             unset dracut_args[$i]
468     done
469
470     cd /lib/modules
471     for i in *; do
472         [[ -f $i/modules.builtin ]] || continue
473         dracut --kver="$i" "${dracut_args[@]}"
474         ((ret+=$?))
475     done
476     exit $ret
477 fi
478
479 if ! [[ $kernel ]]; then
480     kernel=$(uname -r)
481 fi
482
483 if ! [[ $outfile ]]; then
484     [[ -f /etc/machine-id ]] && read MACHINE_ID < /etc/machine-id
485
486     if [[ $MACHINE_ID ]] && ( [[ -d /boot/${MACHINE_ID} ]] || [[ -L /boot/${MACHINE_ID} ]] ); then
487         outfile="/boot/${MACHINE_ID}/$kernel/initrd"
488     else
489         outfile="/boot/initramfs-$kernel.img"
490     fi
491 fi
492
493 for i in /usr/sbin /sbin /usr/bin /bin; do
494     rl=$i
495     if [ -L "$i" ]; then
496         rl=$(readlink -f $i)
497     fi
498     if [[ "$NPATH" != "*:$rl*" ]] ; then
499         NPATH+=":$rl"
500     fi
501 done
502 export PATH="${NPATH#:}"
503 unset NPATH
504 unset LD_LIBRARY_PATH
505 unset GREP_OPTIONS
506
507 export DRACUT_LOG_LEVEL=warning
508 [[ $debug ]] && {
509     export DRACUT_LOG_LEVEL=debug
510     export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): ';
511     set -x
512 }
513
514 [[ $profile ]] && {
515     export PS4='+ $(date "+%s.%N") ${BASH_SOURCE}@${LINENO}: ';
516     set -x
517     debug=yes
518 }
519
520 [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
521
522 # if we were not passed a config file, try the default one
523 if [[ ! -f $conffile ]]; then
524     if [[ $allowlocal ]]; then
525         conffile="$dracutbasedir/dracut.conf"
526     else
527         conffile="/etc/dracut.conf"
528     fi
529 fi
530
531 if [[ ! -d $confdir ]]; then
532     if [[ $allowlocal ]]; then
533         confdir="$dracutbasedir/dracut.conf.d"
534     else
535         confdir="/etc/dracut.conf.d"
536     fi
537 fi
538
539 # source our config file
540 [[ -f $conffile ]] && . "$conffile"
541
542 # source our config dir
543 for f in $(dropindirs_sort ".conf" "$confdir" "$dracutbasedir/dracut.conf.d"); do
544     [[ -e $f ]] && . "$f"
545 done
546
547 # these optins add to the stuff in the config file
548 if (( ${#add_dracutmodules_l[@]} )); then
549     while pop add_dracutmodules_l val; do
550         add_dracutmodules+=" $val "
551     done
552 fi
553
554 if (( ${#force_add_dracutmodules_l[@]} )); then
555     while pop force_add_dracutmodules_l val; do
556         force_add_dracutmodules+=" $val "
557     done
558 fi
559
560 if (( ${#fscks_l[@]} )); then
561     while pop fscks_l val; do
562         fscks+=" $val "
563     done
564 fi
565
566 if (( ${#add_fstab_l[@]} )); then
567     while pop add_fstab_l val; do
568         add_fstab+=" $val "
569     done
570 fi
571
572 if (( ${#fstab_lines_l[@]} )); then
573     while pop fstab_lines_l val; do
574         push fstab_lines $val
575     done
576 fi
577
578 if (( ${#install_items_l[@]} )); then
579     while pop install_items_l val; do
580         install_items+=" $val "
581     done
582 fi
583
584 # these options override the stuff in the config file
585 if (( ${#dracutmodules_l[@]} )); then
586     dracutmodules=''
587     while pop dracutmodules_l val; do
588         dracutmodules+="$val "
589     done
590 fi
591
592 if (( ${#omit_dracutmodules_l[@]} )); then
593     omit_dracutmodules=''
594     while pop omit_dracutmodules_l val; do
595         omit_dracutmodules+="$val "
596     done
597 fi
598
599 if (( ${#filesystems_l[@]} )); then
600     filesystems=''
601     while pop filesystems_l val; do
602         filesystems+="$val "
603     done
604 fi
605
606 if (( ${#fw_dir_l[@]} )); then
607     fw_dir=''
608     while pop fw_dir_l val; do
609         fw_dir+="$val "
610     done
611 fi
612
613 if (( ${#libdirs_l[@]} )); then
614     libdirs=''
615     while pop libdirs_l val; do
616         libdirs+="$val "
617     done
618 fi
619
620 [[ $stdloglvl_l ]] && stdloglvl=$stdloglvl_l
621 [[ ! $stdloglvl ]] && stdloglvl=4
622 stdloglvl=$((stdloglvl + verbosity_mod_l))
623 ((stdloglvl > 6)) && stdloglvl=6
624 ((stdloglvl < 0)) && stdloglvl=0
625
626 [[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l
627 [[ $do_strip_l ]] && do_strip=$do_strip_l
628 [[ $do_strip ]] || do_strip=yes
629 [[ $do_hardlink_l ]] && do_hardlink=$do_hardlink_l
630 [[ $do_hardlink ]] || do_hardlink=yes
631 [[ $prefix_l ]] && prefix=$prefix_l
632 [[ $prefix = "/" ]] && unset prefix
633 [[ $hostonly_l ]] && hostonly=$hostonly_l
634 [[ $use_fstab_l ]] && use_fstab=$use_fstab_l
635 [[ $mdadmconf_l ]] && mdadmconf=$mdadmconf_l
636 [[ $lvmconf_l ]] && lvmconf=$lvmconf_l
637 [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
638 [[ $fw_dir ]] || fw_dir="/lib/firmware/updates /lib/firmware"
639 [[ $tmpdir_l ]] && tmpdir="$tmpdir_l"
640 [[ $tmpdir ]] || tmpdir=/var/tmp
641 [[ $compress_l ]] && compress=$compress_l
642 [[ $show_modules_l ]] && show_modules=$show_modules_l
643 [[ $nofscks_l ]] && nofscks="yes"
644 [[ $ro_mnt_l ]] && ro_mnt="yes"
645 # eliminate IFS hackery when messing with fw_dir
646 fw_dir=${fw_dir//:/ }
647
648 # handle compression options.
649 [[ $compress ]] || compress="gzip"
650 case $compress in
651     bzip2) compress="bzip2 -9";;
652     lzma)  compress="lzma -9";;
653     xz)    compress="xz --check=crc32 --lzma2=dict=1MiB";;
654     gzip)  compress="gzip -9"; command -v pigz > /dev/null 2>&1 && compress="pigz -9";;
655 esac
656 if [[ $_no_compress_l = "cat" ]]; then
657     compress="cat"
658 fi
659
660 [[ $hostonly = yes ]] && hostonly="-h"
661 [[ $hostonly != "-h" ]] && unset hostonly
662
663 readonly TMPDIR="$tmpdir"
664 readonly initdir="$(mktemp --tmpdir="$TMPDIR/" -d -t initramfs.XXXXXX)"
665 [ -d "$initdir" ] || {
666     printf "%s\n" "dracut: mktemp --tmpdir=\"$TMPDIR/\" -d -t initramfs.XXXXXX failed." >&2
667     exit 1
668 }
669
670 # clean up after ourselves no matter how we die.
671 trap 'ret=$?;[[ $outfile ]] && [[ -f $outfile.$$ ]] && rm -f -- "$outfile.$$";[[ $keep ]] && printf "%s\n" "Not removing $initdir." >&2 || { [[ $initdir ]] && rm -rf -- "$initdir";exit $ret; };' EXIT
672 # clean up after ourselves no matter how we die.
673 trap 'exit 1;' SIGINT
674
675 export DRACUT_KERNEL_LAZY="1"
676 export DRACUT_RESOLVE_LAZY="1"
677
678 if [[ -f $dracutbasedir/dracut-functions.sh ]]; then
679     . $dracutbasedir/dracut-functions.sh
680 else
681     printf "%s\n" "dracut: Cannot find $dracutbasedir/dracut-functions.sh." >&2
682     printf "%s\n" "dracut: Are you running from a git checkout?" >&2
683     printf "%s\n" "dracut: Try passing -l as an argument to $0" >&2
684     exit 1
685 fi
686
687 inst /bin/sh
688 if ! $DRACUT_INSTALL ${initdir+-D "$initdir"} -R "$initdir/bin/sh" &>/dev/null; then
689     unset DRACUT_RESOLVE_LAZY
690     export DRACUT_RESOLVE_DEPS=1
691 fi
692 rm -fr -- ${initdir}/*
693
694 if [[ -f $dracutbasedir/dracut-version.sh ]]; then
695     . $dracutbasedir/dracut-version.sh
696 fi
697
698 # Verify bash version, current minimum is 3.1
699 if (( BASH_VERSINFO[0] < 4 )); then
700     dfatal 'You need at least Bash 4 to use dracut, sorry.'
701     exit 1
702 fi
703
704 dracutfunctions=$dracutbasedir/dracut-functions.sh
705 export dracutfunctions
706
707 if (( ${#drivers_l[@]} )); then
708     drivers=''
709     while pop drivers_l val; do
710         drivers+="$val "
711     done
712 fi
713 drivers=${drivers/-/_}
714
715 if (( ${#add_drivers_l[@]} )); then
716     while pop add_drivers_l val; do
717         add_drivers+=" $val "
718     done
719 fi
720 add_drivers=${add_drivers/-/_}
721
722 if (( ${#omit_drivers_l[@]} )); then
723     while pop omit_drivers_l val; do
724         omit_drivers+=" $val "
725     done
726 fi
727 omit_drivers=${omit_drivers/-/_}
728
729 if (( ${#kernel_cmdline_l[@]} )); then
730     while pop kernel_cmdline_l val; do
731         kernel_cmdline+=" $val "
732     done
733 fi
734
735 omit_drivers_corrected=""
736 for d in $omit_drivers; do
737     [[ " $drivers $add_drivers " == *\ $d\ * ]] && continue
738     omit_drivers_corrected+="$d|"
739 done
740 omit_drivers="${omit_drivers_corrected%|}"
741 unset omit_drivers_corrected
742
743 # prepare args for logging
744 for ((i=0; i < ${#dracut_args[@]}; i++)); do
745     [[ "${dracut_args[$i]}" == *\ * ]] && \
746         dracut_args[$i]="\"${dracut_args[$i]}\""
747         #" keep vim happy
748 done
749 ddebug "Executing: $0 ${dracut_args[@]}"
750
751 [[ $do_list = yes ]] && {
752     for mod in $dracutbasedir/modules.d/*; do
753         [[ -d $mod ]] || continue;
754         [[ -e $mod/install || -e $mod/installkernel || \
755             -e $mod/module-setup.sh ]] || continue
756         printf "%s\n" "${mod##*/??}"
757     done
758     exit 0
759 }
760
761 # This is kinda legacy -- eventually it should go away.
762 case $dracutmodules in
763     ""|auto) dracutmodules="all" ;;
764 esac
765
766 abs_outfile=$(readlink -f "$outfile") && outfile="$abs_outfile"
767
768 if [[ -d $srcmods ]]; then
769     [[ -f $srcmods/modules.dep ]] || {
770       dwarn "$srcmods/modules.dep is missing. Did you run depmod?"
771     }
772 fi
773
774 if [[ -f $outfile && ! $force ]]; then
775     dfatal "Will not override existing initramfs ($outfile) without --force"
776     exit 1
777 fi
778
779 outdir=${outfile%/*}
780 [[ $outdir ]] || outdir="/"
781
782 if [[ ! -d "$outdir" ]]; then
783     dfatal "Can't write to $outdir: Directory $outdir does not exist or is not accessible."
784     exit 1
785 elif [[ ! -w "$outdir" ]]; then
786     dfatal "No permission to write to $outdir."
787     exit 1
788 elif [[ -f "$outfile" && ! -w "$outfile" ]]; then
789     dfatal "No permission to write $outfile."
790     exit 1
791 fi
792
793 # Need to be able to have non-root users read stuff (rpcbind etc)
794 chmod 755 "$initdir"
795
796 if [[ $hostonly ]]; then
797     for i in /sys /proc /run /dev; do
798         if ! findmnt --target "$i" &>/dev/null; then
799             dwarning "Turning off host-only mode: '$i' is not mounted!"
800             unset hostonly
801         fi
802     done
803     if ! [[ -d /run/udev/data ]]; then
804         dwarning "Turning off host-only mode: udev database not found!"
805         unset hostonly
806     fi
807 fi
808
809 declare -A host_fs_types
810
811 for line in "${fstab_lines[@]}"; do
812     set -- $line
813     #dev mp fs fsopts
814     push host_devs "$1"
815     host_fs_types["$1"]="$3"
816 done
817
818 for f in $add_fstab; do
819     [[ -e $f ]] || continue
820     while read dev rest; do
821         push host_devs "$dev"
822     done < "$f"
823 done
824
825 for dev in $add_device; do
826     push host_devs "$dev"
827 done
828
829 if (( ${#add_device_l[@]} )); then
830     while pop add_device_l val; do
831         add_device+=" $val "
832         push host_devs "$val"
833     done
834 fi
835
836 if [[ $hostonly ]]; then
837     # in hostonly mode, determine all devices, which have to be accessed
838     # and examine them for filesystem types
839
840     for mp in \
841         "/" \
842         "/etc" \
843         "/usr" \
844         "/usr/bin" \
845         "/usr/sbin" \
846         "/usr/lib" \
847         "/usr/lib64" \
848         "/boot";
849     do
850         mountpoint "$mp" >/dev/null 2>&1 || continue
851         push host_devs "$(readlink -f "/dev/block/$(find_block_device "$mp")")"
852     done
853
854     while read dev type rest; do
855         [[ -b $dev ]] || continue
856         [[ "$type" == "partition" ]] || continue
857         while read _d _m _t _o _r; do
858             [[ "$_d" == \#* ]] && continue
859             [[ $_d ]] || continue
860             [[ $_t != "swap" ]] || [[ $_m != "swap" ]] && continue
861             [[ "$_o" == *noauto* ]] && continue
862             [[ "$_d" == UUID\=* ]] && _d="/dev/disk/by-uuid/${_d#UUID=}"
863             [[ "$_d" == LABEL\=* ]] && _d="/dev/disk/by-label/$_d#LABEL=}"
864             [[ "$_d" -ef "$dev" ]] || continue
865
866             while read _mapper _a _p _o; do
867                 [[ $_mapper = \#* ]] && continue
868                 [[ "$_d" -ef /dev/mapper/"$_mapper" ]] || continue
869                 [[ "$_o" ]] || _o="$_p"
870                 # skip mkswap swap
871                 [[ $_o == *swap* ]] && continue 2
872             done < /etc/crypttab
873
874             push host_devs "$(readlink -f "$dev")"
875             break
876         done < /etc/fstab
877     done < /proc/swaps
878 fi
879
880 _get_fs_type() { (
881     [[ $1 ]] || return
882     if [[ -b /dev/block/$1 ]] && ID_FS_TYPE=$(get_fs_env "/dev/block/$1"); then
883         printf "%s\n" "$(readlink -f "/dev/block/$1")" "$ID_FS_TYPE"
884         return 1
885     fi
886     if [[ -b $1 ]] && ID_FS_TYPE=$(get_fs_env "$1"); then
887         printf "%s\n" "$(readlink -f "$1")" "$ID_FS_TYPE"
888         return 1
889     fi
890     if fstype=$(find_dev_fstype "$1"); then
891         printf "%s\n" "$1" "$fstype"
892         return 1
893     fi
894     return 1
895 ) }
896
897 for dev in "${host_devs[@]}"; do
898     while read key; do
899         read val
900         host_fs_types["$key"]="$val"
901     done < <(
902         _get_fs_type "$dev"
903         check_block_and_slaves_all _get_fs_type "$(get_maj_min "$dev")"
904     )
905 done
906
907 [[ -d $udevdir ]] \
908     || udevdir="$(pkg-config udev --variable=udevdir 2>/dev/null)"
909 if ! [[ -d "$udevdir" ]]; then
910     [[ -d /lib/udev ]] && udevdir=/lib/udev
911     [[ -d /usr/lib/udev ]] && udevdir=/usr/lib/udev
912 fi
913
914 [[ -d $systemdutildir ]] \
915     || systemdutildir=$(pkg-config systemd --variable=systemdutildir 2>/dev/null)
916
917 if ! [[ -d "$systemdutildir" ]]; then
918     [[ -d /lib/systemd ]] && systemdutildir=/lib/systemd
919     [[ -d /usr/lib/systemd ]] && systemdutildir=/usr/lib/systemd
920 fi
921
922 [[ -d $systemdsystemunitdir ]] \
923     || systemdsystemunitdir=$(pkg-config systemd --variable=systemdsystemunitdir 2>/dev/null)
924
925 [[ -d "$systemdsystemunitdir" ]] || systemdsystemunitdir=${systemdutildir}/system
926
927 [[ -d $systemdsystemconfdir ]] \
928     || systemdsystemconfdir=$(pkg-config systemd --variable=systemdsystemconfdir 2>/dev/null)
929
930 [[ -d "$systemdsystemconfdir" ]] || systemdsystemconfdir=/etc/systemd/system
931
932 export initdir dracutbasedir dracutmodules \
933     fw_dir drivers_dir debug no_kernel kernel_only \
934     omit_drivers mdadmconf lvmconf \
935     use_fstab fstab_lines libdirs fscks nofscks ro_mnt \
936     stdloglvl sysloglvl fileloglvl kmsgloglvl logfile \
937     debug host_fs_types host_devs sshkey add_fstab \
938     DRACUT_VERSION udevdir prefix filesystems drivers \
939     systemdutildir systemdsystemunitdir systemdsystemconfdir
940
941 # Create some directory structure first
942 [[ $prefix ]] && mkdir -m 0755 -p "${initdir}${prefix}"
943
944 [[ -h /lib ]] || mkdir -m 0755 -p "${initdir}${prefix}/lib"
945 [[ $prefix ]] && ln -sfn "${prefix#/}/lib" "$initdir/lib"
946
947 if [[ $prefix ]]; then
948     for d in bin etc lib sbin tmp usr var $libdirs; do
949         [[ "$d" == */* ]] && continue
950         ln -sfn "${prefix#/}/${d#/}" "$initdir/$d"
951     done
952 fi
953
954 if [[ $kernel_only != yes ]]; then
955     for d in usr/bin usr/sbin bin etc lib sbin tmp usr var $libdirs; do
956         [[ -e "${initdir}${prefix}/$d" ]] && continue
957         if [ -L "/$d" ]; then
958             inst_symlink "/$d" "${prefix}/$d"
959         else
960             mkdir -m 0755 -p "${initdir}${prefix}/$d"
961         fi
962     done
963
964     for d in dev proc sys sysroot root run run/lock run/initramfs; do
965         if [ -L "/$d" ]; then
966             inst_symlink "/$d"
967         else
968             mkdir -m 0755 -p "$initdir/$d"
969         fi
970     done
971
972     ln -sfn ../run "$initdir/var/run"
973     ln -sfn ../run/lock "$initdir/var/lock"
974     ln -sfn ../run/log "$initdir/var/log"
975 else
976     for d in lib "$libdir"; do
977         [[ -e "${initdir}${prefix}/$d" ]] && continue
978         if [ -h "/$d" ]; then
979             inst "/$d" "${prefix}/$d"
980         else
981             mkdir -m 0755 -p "${initdir}${prefix}/$d"
982         fi
983     done
984 fi
985
986 if [[ $kernel_only != yes ]]; then
987     mkdir -p "${initdir}/etc/cmdline.d"
988     for _d in $hookdirs; do
989         mkdir -m 0755 -p ${initdir}/lib/dracut/hooks/$_d
990     done
991     if [[ "$UID" = "0" ]]; then
992         [ -c ${initdir}/dev/null ] || mknod ${initdir}/dev/null c 1 3
993         [ -c ${initdir}/dev/kmsg ] || mknod ${initdir}/dev/kmsg c 1 11
994         [ -c ${initdir}/dev/console ] || mknod ${initdir}/dev/console c 5 1
995     fi
996 fi
997
998 mods_to_load=""
999 # check all our modules to see if they should be sourced.
1000 # This builds a list of modules that we will install next.
1001 for_each_module_dir check_module
1002 for_each_module_dir check_mount
1003
1004 [[ "$mods_to_load " == *01fips\ * ]] && export DRACUT_FIPS_MODE=1
1005
1006 _isize=0 #initramfs size
1007 modules_loaded=" "
1008 # source our modules.
1009 for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
1010     _d_mod=${moddir##*/}; _d_mod=${_d_mod#[0-9][0-9]}
1011     if [[ "$mods_to_load" == *\ $_d_mod\ * ]]; then
1012         if [[ $show_modules = yes ]]; then
1013             printf "%s\n" "$_d_mod"
1014         else
1015             dinfo "*** Including module: $_d_mod ***"
1016         fi
1017         if [[ $kernel_only == yes ]]; then
1018             module_installkernel "$_d_mod" || {
1019                 dfatal "installkernel failed in module $_d_mod"
1020                 exit 1
1021             }
1022         else
1023             module_install "$_d_mod"
1024             if [[ $no_kernel != yes ]]; then
1025                 module_installkernel "$_d_mod" || {
1026                     dfatal "installkernel failed in module $_d_mod"
1027                     exit 1
1028                 }
1029             fi
1030         fi
1031         mods_to_load=${mods_to_load// $_d_mod /}
1032         modules_loaded+="$_d_mod "
1033
1034         #print the module install size
1035         if [ -n "$printsize" ]; then
1036             _isize_new=$(du -sk ${initdir}|cut -f1)
1037             _isize_delta=$((_isize_new - _isize))
1038             printf "%s\n" "$_d_mod install size: ${_isize_delta}k"
1039             _isize=$_isize_new
1040         fi
1041     fi
1042 done
1043 unset moddir
1044
1045 for i in $modules_loaded; do
1046     mkdir -p $initdir/lib/dracut
1047     printf "%s\n" "$i" >> $initdir/lib/dracut/modules.txt
1048 done
1049
1050 dinfo "*** Including modules done ***"
1051
1052 ## final stuff that has to happen
1053 if [[ $no_kernel != yes ]]; then
1054
1055     if [[ $drivers ]]; then
1056         hostonly='' instmods $drivers
1057     fi
1058
1059     if [[ $add_drivers ]]; then
1060         hostonly='' instmods -c $add_drivers
1061     fi
1062     if [[ $filesystems ]]; then
1063         hostonly='' instmods -c $filesystems
1064     fi
1065
1066     dinfo "*** Installing kernel module dependencies and firmware ***"
1067     dracut_kernel_post
1068     dinfo "*** Installing kernel module dependencies and firmware done ***"
1069
1070     if [[ $noimageifnotneeded == yes ]] && [[ $hostonly ]]; then
1071         if [[ ! -f "$initdir/lib/dracut/need-initqueue" ]] && \
1072             [[ -f ${initdir}/lib/modules/$kernel/modules.dep && ! -s ${initdir}/lib/modules/$kernel/modules.dep ]]; then
1073             for i in ${initdir}/etc/cmdline.d/*.conf; do
1074                 # We need no initramfs image and do not generate one.
1075                 [[ $i == "${initdir}/etc/cmdline.d/*.conf" ]] && exit 0
1076             done
1077         fi
1078     fi
1079 fi
1080
1081 if [[ $kernel_only != yes ]]; then
1082     (( ${#install_items[@]} > 0 )) && dracut_install ${install_items[@]}
1083
1084     [[ $kernel_cmdline ]] && printf "%s\n" "$kernel_cmdline" >> "${initdir}/etc/cmdline.d/01-default.conf"
1085
1086     while pop fstab_lines line; do
1087         printf "%s\n" "$line 0 0" >> "${initdir}/etc/fstab"
1088     done
1089
1090     for f in $add_fstab; do
1091         cat "$f" >> "${initdir}/etc/fstab"
1092     done
1093
1094     if [ -d ${initdir}/$systemdutildir ]; then
1095         mkdir -p ${initdir}/etc/conf.d
1096         {
1097             printf "%s\n" "systemdutildir=\"$systemdutildir\""
1098             printf "%s\n" "systemdsystemunitdir=\"$systemdsystemunitdir\""
1099             printf "%s\n" "systemdsystemconfdir=\"$systemdsystemconfdir\""
1100         } > ${initdir}/etc/conf.d/systemd.conf
1101     fi
1102
1103     if [[ $DRACUT_RESOLVE_LAZY ]] && [[ $DRACUT_INSTALL ]]; then
1104         dinfo "*** Resolving executable dependencies ***"
1105         find "$initdir" -type f \
1106             '(' -perm -0100 -or -perm -0010 -or -perm -0001 ')' \
1107             -not -path '*.ko' -print0 \
1108         | xargs -r -0 $DRACUT_INSTALL ${initdir+-D "$initdir"} -R ${DRACUT_FIPS_MODE+-H} --
1109         dinfo "*** Resolving executable dependencies done***"
1110     fi
1111 fi
1112
1113 while pop include_src src && pop include_target tgt; do
1114     if [[ $src && $tgt ]]; then
1115         if [[ -f $src ]]; then
1116             inst $src $tgt
1117         else
1118             ddebug "Including directory: $src"
1119             mkdir -p "${initdir}/${tgt}"
1120             # check for preexisting symlinks, so we can cope with the
1121             # symlinks to $prefix
1122             for i in "$src"/*; do
1123                 [[ -e "$i" || -h "$i" ]] || continue
1124                 s=${initdir}/${tgt}/${i#$src/}
1125                 if [[ -d "$i" ]]; then
1126                     if ! [[ -e "$s" ]]; then
1127                         mkdir -m 0755 -p "$s"
1128                         chmod --reference="$i" "$s"
1129                     fi
1130                     cp --reflink=auto --sparse=auto -fa -t "$s" "$i"/*
1131                 else
1132                     cp --reflink=auto --sparse=auto -fa -t "$s" "$i"
1133                 fi
1134             done
1135         fi
1136     fi
1137 done
1138
1139 if [[ $kernel_only != yes ]]; then
1140     # make sure that library links are correct and up to date
1141     for f in /etc/ld.so.conf /etc/ld.so.conf.d/*; do
1142         [[ -f $f ]] && inst_simple "$f"
1143     done
1144     if ! ldconfig -r "$initdir"; then
1145         if [[ $UID = 0 ]]; then
1146             derror "ldconfig exited ungracefully"
1147         else
1148             derror "ldconfig might need uid=0 (root) for chroot()"
1149         fi
1150     fi
1151 fi
1152
1153 if (( maxloglvl >= 5 )); then
1154     ddebug "Listing sizes of included files:"
1155     du -c "$initdir" | sort -n | ddebug
1156 fi
1157
1158 PRELINK_BIN="$(command -v prelink)"
1159 if [[ $UID = 0 ]] && [[ $PRELINK_BIN ]]; then
1160     if [[ $DRACUT_FIPS_MODE ]]; then
1161         dinfo "*** Installing prelink files ***"
1162         dracut_install -o prelink /etc/prelink.conf /etc/prelink.conf.d/*.conf /etc/prelink.cache
1163     else
1164         dinfo "*** Pre-linking files ***"
1165         dracut_install -o prelink /etc/prelink.conf /etc/prelink.conf.d/*.conf
1166         chroot "$initdir" "$PRELINK_BIN" -a
1167         rm -f -- "$initdir/$PRELINK_BIN"
1168         rm -fr -- "$initdir"/etc/prelink.*
1169         dinfo "*** Pre-linking files done ***"
1170     fi
1171 fi
1172
1173 if [[ $do_hardlink = yes ]] && command -v hardlink >/dev/null; then
1174     dinfo "*** Hardlinking files ***"
1175     hardlink "$initdir" 2>&1
1176     dinfo "*** Hardlinking files done ***"
1177 fi
1178
1179 # strip binaries
1180 if [[ $do_strip = yes ]] ; then
1181     for p in strip xargs find; do
1182         if ! type -P $p >/dev/null; then
1183             dinfo "Could not find '$p'. Not stripping the initramfs."
1184             do_strip=no
1185         fi
1186     done
1187 fi
1188
1189 if [[ $do_strip = yes ]] ; then
1190     dinfo "*** Stripping files ***"
1191     if [[ $DRACUT_FIPS_MODE ]]; then
1192         find "$initdir" -type f \
1193             -executable -not -path '*/lib/modules/*.ko' -print0 \
1194             | while read -r -d $'\0' f; do
1195             if ! [[ -e "${f%/*}/.${f##*/}.hmac" ]] \
1196                 && ! [[ -e "/lib/hmaccalc/${f##*/}.hmac" ]] \
1197                 && ! [[ -e "/lib64/hmaccalc/${f##*/}.hmac" ]] \
1198                 && ! [[ -e "/lib/fipscheck/${f##*/}.hmac" ]] \
1199                 && ! [[ -e "/lib64/fipscheck/${f##*/}.hmac" ]]; then
1200                 printf "%s\000" "$f";
1201             fi
1202         done | xargs -r -0 strip -g 2>/dev/null
1203     else
1204         find "$initdir" -type f \
1205             -executable -not -path '*/lib/modules/*.ko' -print0 \
1206             | xargs -r -0 strip -g 2>/dev/null
1207     fi
1208
1209     # strip kernel modules, but do not touch signed modules
1210     find "$initdir" -type f -path '*/lib/modules/*.ko' -print0 \
1211         | while read -r -d $'\0' f; do
1212         SIG=$(tail -c 28 "$f")
1213         [[ $SIG == '~Module signature appended~' ]] || { printf "%s\000" "$f"; }
1214     done | xargs -r -0 strip -g
1215
1216     dinfo "*** Stripping files done ***"
1217 fi
1218
1219 rm -f -- "$outfile"
1220 dinfo "*** Creating image file ***"
1221 if ! ( umask 077; cd "$initdir"; find . | cpio -R 0:0 -H newc -o --quiet | \
1222     $compress > "$outfile.$$"; ); then
1223     dfatal "dracut: creation of $outfile.$$ failed"
1224     exit 1
1225 fi
1226 mv -- "$outfile.$$" "$outfile"
1227 dinfo "*** Creating image file done ***"
1228
1229 dinfo "Wrote $outfile:"
1230 dinfo "$(ls -l "$outfile")"
1231
1232 exit 0