dracut.sh: unset all LC_* and LANG
[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 LC_MESSAGES
504 unset LC_CTYPE
505 export LC_ALL=C
506 export LANG=C
507 unset NPATH
508 unset LD_LIBRARY_PATH
509 unset GREP_OPTIONS
510
511 export DRACUT_LOG_LEVEL=warning
512 [[ $debug ]] && {
513     export DRACUT_LOG_LEVEL=debug
514     export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): ';
515     set -x
516 }
517
518 [[ $profile ]] && {
519     export PS4='+ $(date "+%s.%N") ${BASH_SOURCE}@${LINENO}: ';
520     set -x
521     debug=yes
522 }
523
524 [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
525
526 # if we were not passed a config file, try the default one
527 if [[ ! -f $conffile ]]; then
528     if [[ $allowlocal ]]; then
529         conffile="$dracutbasedir/dracut.conf"
530     else
531         conffile="/etc/dracut.conf"
532     fi
533 fi
534
535 if [[ ! -d $confdir ]]; then
536     if [[ $allowlocal ]]; then
537         confdir="$dracutbasedir/dracut.conf.d"
538     else
539         confdir="/etc/dracut.conf.d"
540     fi
541 fi
542
543 # source our config file
544 [[ -f $conffile ]] && . "$conffile"
545
546 # source our config dir
547 for f in $(dropindirs_sort ".conf" "$confdir" "$dracutbasedir/dracut.conf.d"); do
548     [[ -e $f ]] && . "$f"
549 done
550
551 # these optins add to the stuff in the config file
552 if (( ${#add_dracutmodules_l[@]} )); then
553     while pop add_dracutmodules_l val; do
554         add_dracutmodules+=" $val "
555     done
556 fi
557
558 if (( ${#force_add_dracutmodules_l[@]} )); then
559     while pop force_add_dracutmodules_l val; do
560         force_add_dracutmodules+=" $val "
561     done
562 fi
563
564 if (( ${#fscks_l[@]} )); then
565     while pop fscks_l val; do
566         fscks+=" $val "
567     done
568 fi
569
570 if (( ${#add_fstab_l[@]} )); then
571     while pop add_fstab_l val; do
572         add_fstab+=" $val "
573     done
574 fi
575
576 if (( ${#fstab_lines_l[@]} )); then
577     while pop fstab_lines_l val; do
578         push fstab_lines $val
579     done
580 fi
581
582 if (( ${#install_items_l[@]} )); then
583     while pop install_items_l val; do
584         install_items+=" $val "
585     done
586 fi
587
588 # these options override the stuff in the config file
589 if (( ${#dracutmodules_l[@]} )); then
590     dracutmodules=''
591     while pop dracutmodules_l val; do
592         dracutmodules+="$val "
593     done
594 fi
595
596 if (( ${#omit_dracutmodules_l[@]} )); then
597     omit_dracutmodules=''
598     while pop omit_dracutmodules_l val; do
599         omit_dracutmodules+="$val "
600     done
601 fi
602
603 if (( ${#filesystems_l[@]} )); then
604     filesystems=''
605     while pop filesystems_l val; do
606         filesystems+="$val "
607     done
608 fi
609
610 if (( ${#fw_dir_l[@]} )); then
611     fw_dir=''
612     while pop fw_dir_l val; do
613         fw_dir+="$val "
614     done
615 fi
616
617 if (( ${#libdirs_l[@]} )); then
618     libdirs=''
619     while pop libdirs_l val; do
620         libdirs+="$val "
621     done
622 fi
623
624 [[ $stdloglvl_l ]] && stdloglvl=$stdloglvl_l
625 [[ ! $stdloglvl ]] && stdloglvl=4
626 stdloglvl=$((stdloglvl + verbosity_mod_l))
627 ((stdloglvl > 6)) && stdloglvl=6
628 ((stdloglvl < 0)) && stdloglvl=0
629
630 [[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l
631 [[ $do_strip_l ]] && do_strip=$do_strip_l
632 [[ $do_strip ]] || do_strip=yes
633 [[ $do_hardlink_l ]] && do_hardlink=$do_hardlink_l
634 [[ $do_hardlink ]] || do_hardlink=yes
635 [[ $prefix_l ]] && prefix=$prefix_l
636 [[ $prefix = "/" ]] && unset prefix
637 [[ $hostonly_l ]] && hostonly=$hostonly_l
638 [[ $use_fstab_l ]] && use_fstab=$use_fstab_l
639 [[ $mdadmconf_l ]] && mdadmconf=$mdadmconf_l
640 [[ $lvmconf_l ]] && lvmconf=$lvmconf_l
641 [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
642 [[ $fw_dir ]] || fw_dir="/lib/firmware/updates /lib/firmware"
643 [[ $tmpdir_l ]] && tmpdir="$tmpdir_l"
644 [[ $tmpdir ]] || tmpdir=/var/tmp
645 [[ $compress_l ]] && compress=$compress_l
646 [[ $show_modules_l ]] && show_modules=$show_modules_l
647 [[ $nofscks_l ]] && nofscks="yes"
648 [[ $ro_mnt_l ]] && ro_mnt="yes"
649 # eliminate IFS hackery when messing with fw_dir
650 fw_dir=${fw_dir//:/ }
651
652 # handle compression options.
653 [[ $compress ]] || compress="gzip"
654 case $compress in
655     bzip2) compress="bzip2 -9";;
656     lzma)  compress="lzma -9";;
657     xz)    compress="xz --check=crc32 --lzma2=dict=1MiB";;
658     gzip)  compress="gzip -9"; command -v pigz > /dev/null 2>&1 && compress="pigz -9";;
659 esac
660 if [[ $_no_compress_l = "cat" ]]; then
661     compress="cat"
662 fi
663
664 [[ $hostonly = yes ]] && hostonly="-h"
665 [[ $hostonly != "-h" ]] && unset hostonly
666
667 readonly TMPDIR="$tmpdir"
668 readonly initdir="$(mktemp --tmpdir="$TMPDIR/" -d -t initramfs.XXXXXX)"
669 [ -d "$initdir" ] || {
670     printf "%s\n" "dracut: mktemp --tmpdir=\"$TMPDIR/\" -d -t initramfs.XXXXXX failed." >&2
671     exit 1
672 }
673
674 # clean up after ourselves no matter how we die.
675 trap 'ret=$?;[[ $outfile ]] && [[ -f $outfile.$$ ]] && rm -f -- "$outfile.$$";[[ $keep ]] && printf "%s\n" "Not removing $initdir." >&2 || { [[ $initdir ]] && rm -rf -- "$initdir";exit $ret; };' EXIT
676 # clean up after ourselves no matter how we die.
677 trap 'exit 1;' SIGINT
678
679 export DRACUT_KERNEL_LAZY="1"
680 export DRACUT_RESOLVE_LAZY="1"
681
682 if [[ -f $dracutbasedir/dracut-functions.sh ]]; then
683     . $dracutbasedir/dracut-functions.sh
684 else
685     printf "%s\n" "dracut: Cannot find $dracutbasedir/dracut-functions.sh." >&2
686     printf "%s\n" "dracut: Are you running from a git checkout?" >&2
687     printf "%s\n" "dracut: Try passing -l as an argument to $0" >&2
688     exit 1
689 fi
690
691 inst /bin/sh
692 if ! $DRACUT_INSTALL ${initdir+-D "$initdir"} -R "$initdir/bin/sh" &>/dev/null; then
693     unset DRACUT_RESOLVE_LAZY
694     export DRACUT_RESOLVE_DEPS=1
695 fi
696 rm -fr -- ${initdir}/*
697
698 if [[ -f $dracutbasedir/dracut-version.sh ]]; then
699     . $dracutbasedir/dracut-version.sh
700 fi
701
702 # Verify bash version, current minimum is 3.1
703 if (( BASH_VERSINFO[0] < 4 )); then
704     dfatal 'You need at least Bash 4 to use dracut, sorry.'
705     exit 1
706 fi
707
708 dracutfunctions=$dracutbasedir/dracut-functions.sh
709 export dracutfunctions
710
711 if (( ${#drivers_l[@]} )); then
712     drivers=''
713     while pop drivers_l val; do
714         drivers+="$val "
715     done
716 fi
717 drivers=${drivers/-/_}
718
719 if (( ${#add_drivers_l[@]} )); then
720     while pop add_drivers_l val; do
721         add_drivers+=" $val "
722     done
723 fi
724 add_drivers=${add_drivers/-/_}
725
726 if (( ${#omit_drivers_l[@]} )); then
727     while pop omit_drivers_l val; do
728         omit_drivers+=" $val "
729     done
730 fi
731 omit_drivers=${omit_drivers/-/_}
732
733 if (( ${#kernel_cmdline_l[@]} )); then
734     while pop kernel_cmdline_l val; do
735         kernel_cmdline+=" $val "
736     done
737 fi
738
739 omit_drivers_corrected=""
740 for d in $omit_drivers; do
741     [[ " $drivers $add_drivers " == *\ $d\ * ]] && continue
742     omit_drivers_corrected+="$d|"
743 done
744 omit_drivers="${omit_drivers_corrected%|}"
745 unset omit_drivers_corrected
746
747 # prepare args for logging
748 for ((i=0; i < ${#dracut_args[@]}; i++)); do
749     [[ "${dracut_args[$i]}" == *\ * ]] && \
750         dracut_args[$i]="\"${dracut_args[$i]}\""
751         #" keep vim happy
752 done
753 ddebug "Executing: $0 ${dracut_args[@]}"
754
755 [[ $do_list = yes ]] && {
756     for mod in $dracutbasedir/modules.d/*; do
757         [[ -d $mod ]] || continue;
758         [[ -e $mod/install || -e $mod/installkernel || \
759             -e $mod/module-setup.sh ]] || continue
760         printf "%s\n" "${mod##*/??}"
761     done
762     exit 0
763 }
764
765 # This is kinda legacy -- eventually it should go away.
766 case $dracutmodules in
767     ""|auto) dracutmodules="all" ;;
768 esac
769
770 abs_outfile=$(readlink -f "$outfile") && outfile="$abs_outfile"
771
772 if [[ -d $srcmods ]]; then
773     [[ -f $srcmods/modules.dep ]] || {
774       dwarn "$srcmods/modules.dep is missing. Did you run depmod?"
775     }
776 fi
777
778 if [[ -f $outfile && ! $force ]]; then
779     dfatal "Will not override existing initramfs ($outfile) without --force"
780     exit 1
781 fi
782
783 outdir=${outfile%/*}
784 [[ $outdir ]] || outdir="/"
785
786 if [[ ! -d "$outdir" ]]; then
787     dfatal "Can't write to $outdir: Directory $outdir does not exist or is not accessible."
788     exit 1
789 elif [[ ! -w "$outdir" ]]; then
790     dfatal "No permission to write to $outdir."
791     exit 1
792 elif [[ -f "$outfile" && ! -w "$outfile" ]]; then
793     dfatal "No permission to write $outfile."
794     exit 1
795 fi
796
797 # Need to be able to have non-root users read stuff (rpcbind etc)
798 chmod 755 "$initdir"
799
800 if [[ $hostonly ]]; then
801     for i in /sys /proc /run /dev; do
802         if ! findmnt --target "$i" &>/dev/null; then
803             dwarning "Turning off host-only mode: '$i' is not mounted!"
804             unset hostonly
805         fi
806     done
807     if ! [[ -d /run/udev/data ]]; then
808         dwarning "Turning off host-only mode: udev database not found!"
809         unset hostonly
810     fi
811 fi
812
813 declare -A host_fs_types
814
815 for line in "${fstab_lines[@]}"; do
816     set -- $line
817     #dev mp fs fsopts
818     push host_devs "$1"
819     host_fs_types["$1"]="$3"
820 done
821
822 for f in $add_fstab; do
823     [[ -e $f ]] || continue
824     while read dev rest; do
825         push host_devs "$dev"
826     done < "$f"
827 done
828
829 for dev in $add_device; do
830     push host_devs "$dev"
831 done
832
833 if (( ${#add_device_l[@]} )); then
834     while pop add_device_l val; do
835         add_device+=" $val "
836         push host_devs "$val"
837     done
838 fi
839
840 if [[ $hostonly ]]; then
841     # in hostonly mode, determine all devices, which have to be accessed
842     # and examine them for filesystem types
843
844     for mp in \
845         "/" \
846         "/etc" \
847         "/usr" \
848         "/usr/bin" \
849         "/usr/sbin" \
850         "/usr/lib" \
851         "/usr/lib64" \
852         "/boot";
853     do
854         mountpoint "$mp" >/dev/null 2>&1 || continue
855         push host_devs "$(readlink -f "/dev/block/$(find_block_device "$mp")")"
856     done
857
858     while read dev type rest; do
859         [[ -b $dev ]] || continue
860         [[ "$type" == "partition" ]] || continue
861         while read _d _m _t _o _r; do
862             [[ "$_d" == \#* ]] && continue
863             [[ $_d ]] || continue
864             [[ $_t != "swap" ]] || [[ $_m != "swap" ]] && continue
865             [[ "$_o" == *noauto* ]] && continue
866             [[ "$_d" == UUID\=* ]] && _d="/dev/disk/by-uuid/${_d#UUID=}"
867             [[ "$_d" == LABEL\=* ]] && _d="/dev/disk/by-label/$_d#LABEL=}"
868             [[ "$_d" -ef "$dev" ]] || continue
869
870             while read _mapper _a _p _o; do
871                 [[ $_mapper = \#* ]] && continue
872                 [[ "$_d" -ef /dev/mapper/"$_mapper" ]] || continue
873                 [[ "$_o" ]] || _o="$_p"
874                 # skip mkswap swap
875                 [[ $_o == *swap* ]] && continue 2
876             done < /etc/crypttab
877
878             push host_devs "$(readlink -f "$dev")"
879             break
880         done < /etc/fstab
881     done < /proc/swaps
882 fi
883
884 _get_fs_type() { (
885     [[ $1 ]] || return
886     if [[ -b /dev/block/$1 ]] && ID_FS_TYPE=$(get_fs_env "/dev/block/$1"); then
887         printf "%s\n" "$(readlink -f "/dev/block/$1")" "$ID_FS_TYPE"
888         return 1
889     fi
890     if [[ -b $1 ]] && ID_FS_TYPE=$(get_fs_env "$1"); then
891         printf "%s\n" "$(readlink -f "$1")" "$ID_FS_TYPE"
892         return 1
893     fi
894     if fstype=$(find_dev_fstype "$1"); then
895         printf "%s\n" "$1" "$fstype"
896         return 1
897     fi
898     return 1
899 ) }
900
901 for dev in "${host_devs[@]}"; do
902     while read key; do
903         read val
904         host_fs_types["$key"]="$val"
905     done < <(
906         _get_fs_type "$dev"
907         check_block_and_slaves_all _get_fs_type "$(get_maj_min "$dev")"
908     )
909 done
910
911 [[ -d $udevdir ]] \
912     || udevdir="$(pkg-config udev --variable=udevdir 2>/dev/null)"
913 if ! [[ -d "$udevdir" ]]; then
914     [[ -d /lib/udev ]] && udevdir=/lib/udev
915     [[ -d /usr/lib/udev ]] && udevdir=/usr/lib/udev
916 fi
917
918 [[ -d $systemdutildir ]] \
919     || systemdutildir=$(pkg-config systemd --variable=systemdutildir 2>/dev/null)
920
921 if ! [[ -d "$systemdutildir" ]]; then
922     [[ -d /lib/systemd ]] && systemdutildir=/lib/systemd
923     [[ -d /usr/lib/systemd ]] && systemdutildir=/usr/lib/systemd
924 fi
925
926 [[ -d $systemdsystemunitdir ]] \
927     || systemdsystemunitdir=$(pkg-config systemd --variable=systemdsystemunitdir 2>/dev/null)
928
929 [[ -d "$systemdsystemunitdir" ]] || systemdsystemunitdir=${systemdutildir}/system
930
931 [[ -d $systemdsystemconfdir ]] \
932     || systemdsystemconfdir=$(pkg-config systemd --variable=systemdsystemconfdir 2>/dev/null)
933
934 [[ -d "$systemdsystemconfdir" ]] || systemdsystemconfdir=/etc/systemd/system
935
936 export initdir dracutbasedir dracutmodules \
937     fw_dir drivers_dir debug no_kernel kernel_only \
938     omit_drivers mdadmconf lvmconf \
939     use_fstab fstab_lines libdirs fscks nofscks ro_mnt \
940     stdloglvl sysloglvl fileloglvl kmsgloglvl logfile \
941     debug host_fs_types host_devs sshkey add_fstab \
942     DRACUT_VERSION udevdir prefix filesystems drivers \
943     systemdutildir systemdsystemunitdir systemdsystemconfdir
944
945 # Create some directory structure first
946 [[ $prefix ]] && mkdir -m 0755 -p "${initdir}${prefix}"
947
948 [[ -h /lib ]] || mkdir -m 0755 -p "${initdir}${prefix}/lib"
949 [[ $prefix ]] && ln -sfn "${prefix#/}/lib" "$initdir/lib"
950
951 if [[ $prefix ]]; then
952     for d in bin etc lib sbin tmp usr var $libdirs; do
953         [[ "$d" == */* ]] && continue
954         ln -sfn "${prefix#/}/${d#/}" "$initdir/$d"
955     done
956 fi
957
958 if [[ $kernel_only != yes ]]; then
959     for d in usr/bin usr/sbin bin etc lib sbin tmp usr var $libdirs; do
960         [[ -e "${initdir}${prefix}/$d" ]] && continue
961         if [ -L "/$d" ]; then
962             inst_symlink "/$d" "${prefix}/$d"
963         else
964             mkdir -m 0755 -p "${initdir}${prefix}/$d"
965         fi
966     done
967
968     for d in dev proc sys sysroot root run run/lock run/initramfs; do
969         if [ -L "/$d" ]; then
970             inst_symlink "/$d"
971         else
972             mkdir -m 0755 -p "$initdir/$d"
973         fi
974     done
975
976     ln -sfn ../run "$initdir/var/run"
977     ln -sfn ../run/lock "$initdir/var/lock"
978     ln -sfn ../run/log "$initdir/var/log"
979 else
980     for d in lib "$libdir"; do
981         [[ -e "${initdir}${prefix}/$d" ]] && continue
982         if [ -h "/$d" ]; then
983             inst "/$d" "${prefix}/$d"
984         else
985             mkdir -m 0755 -p "${initdir}${prefix}/$d"
986         fi
987     done
988 fi
989
990 if [[ $kernel_only != yes ]]; then
991     mkdir -p "${initdir}/etc/cmdline.d"
992     for _d in $hookdirs; do
993         mkdir -m 0755 -p ${initdir}/lib/dracut/hooks/$_d
994     done
995     if [[ "$UID" = "0" ]]; then
996         [ -c ${initdir}/dev/null ] || mknod ${initdir}/dev/null c 1 3
997         [ -c ${initdir}/dev/kmsg ] || mknod ${initdir}/dev/kmsg c 1 11
998         [ -c ${initdir}/dev/console ] || mknod ${initdir}/dev/console c 5 1
999     fi
1000 fi
1001
1002 mods_to_load=""
1003 # check all our modules to see if they should be sourced.
1004 # This builds a list of modules that we will install next.
1005 for_each_module_dir check_module
1006 for_each_module_dir check_mount
1007
1008 [[ "$mods_to_load " == *01fips\ * ]] && export DRACUT_FIPS_MODE=1
1009
1010 _isize=0 #initramfs size
1011 modules_loaded=" "
1012 # source our modules.
1013 for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
1014     _d_mod=${moddir##*/}; _d_mod=${_d_mod#[0-9][0-9]}
1015     if [[ "$mods_to_load" == *\ $_d_mod\ * ]]; then
1016         if [[ $show_modules = yes ]]; then
1017             printf "%s\n" "$_d_mod"
1018         else
1019             dinfo "*** Including module: $_d_mod ***"
1020         fi
1021         if [[ $kernel_only == yes ]]; then
1022             module_installkernel "$_d_mod" || {
1023                 dfatal "installkernel failed in module $_d_mod"
1024                 exit 1
1025             }
1026         else
1027             module_install "$_d_mod"
1028             if [[ $no_kernel != yes ]]; then
1029                 module_installkernel "$_d_mod" || {
1030                     dfatal "installkernel failed in module $_d_mod"
1031                     exit 1
1032                 }
1033             fi
1034         fi
1035         mods_to_load=${mods_to_load// $_d_mod /}
1036         modules_loaded+="$_d_mod "
1037
1038         #print the module install size
1039         if [ -n "$printsize" ]; then
1040             _isize_new=$(du -sk ${initdir}|cut -f1)
1041             _isize_delta=$((_isize_new - _isize))
1042             printf "%s\n" "$_d_mod install size: ${_isize_delta}k"
1043             _isize=$_isize_new
1044         fi
1045     fi
1046 done
1047 unset moddir
1048
1049 for i in $modules_loaded; do
1050     mkdir -p $initdir/lib/dracut
1051     printf "%s\n" "$i" >> $initdir/lib/dracut/modules.txt
1052 done
1053
1054 dinfo "*** Including modules done ***"
1055
1056 ## final stuff that has to happen
1057 if [[ $no_kernel != yes ]]; then
1058
1059     if [[ $drivers ]]; then
1060         hostonly='' instmods $drivers
1061     fi
1062
1063     if [[ $add_drivers ]]; then
1064         hostonly='' instmods -c $add_drivers
1065     fi
1066     if [[ $filesystems ]]; then
1067         hostonly='' instmods -c $filesystems
1068     fi
1069
1070     dinfo "*** Installing kernel module dependencies and firmware ***"
1071     dracut_kernel_post
1072     dinfo "*** Installing kernel module dependencies and firmware done ***"
1073
1074     if [[ $noimageifnotneeded == yes ]] && [[ $hostonly ]]; then
1075         if [[ ! -f "$initdir/lib/dracut/need-initqueue" ]] && \
1076             [[ -f ${initdir}/lib/modules/$kernel/modules.dep && ! -s ${initdir}/lib/modules/$kernel/modules.dep ]]; then
1077             for i in ${initdir}/etc/cmdline.d/*.conf; do
1078                 # We need no initramfs image and do not generate one.
1079                 [[ $i == "${initdir}/etc/cmdline.d/*.conf" ]] && exit 0
1080             done
1081         fi
1082     fi
1083 fi
1084
1085 if [[ $kernel_only != yes ]]; then
1086     (( ${#install_items[@]} > 0 )) && dracut_install ${install_items[@]}
1087
1088     [[ $kernel_cmdline ]] && printf "%s\n" "$kernel_cmdline" >> "${initdir}/etc/cmdline.d/01-default.conf"
1089
1090     while pop fstab_lines line; do
1091         printf "%s\n" "$line 0 0" >> "${initdir}/etc/fstab"
1092     done
1093
1094     for f in $add_fstab; do
1095         cat "$f" >> "${initdir}/etc/fstab"
1096     done
1097
1098     if [ -d ${initdir}/$systemdutildir ]; then
1099         mkdir -p ${initdir}/etc/conf.d
1100         {
1101             printf "%s\n" "systemdutildir=\"$systemdutildir\""
1102             printf "%s\n" "systemdsystemunitdir=\"$systemdsystemunitdir\""
1103             printf "%s\n" "systemdsystemconfdir=\"$systemdsystemconfdir\""
1104         } > ${initdir}/etc/conf.d/systemd.conf
1105     fi
1106
1107     if [[ $DRACUT_RESOLVE_LAZY ]] && [[ $DRACUT_INSTALL ]]; then
1108         dinfo "*** Resolving executable dependencies ***"
1109         find "$initdir" -type f \
1110             '(' -perm -0100 -or -perm -0010 -or -perm -0001 ')' \
1111             -not -path '*.ko' -print0 \
1112         | xargs -r -0 $DRACUT_INSTALL ${initdir+-D "$initdir"} -R ${DRACUT_FIPS_MODE+-H} --
1113         dinfo "*** Resolving executable dependencies done***"
1114     fi
1115 fi
1116
1117 while pop include_src src && pop include_target tgt; do
1118     if [[ $src && $tgt ]]; then
1119         if [[ -f $src ]]; then
1120             inst $src $tgt
1121         else
1122             ddebug "Including directory: $src"
1123             mkdir -p "${initdir}/${tgt}"
1124             # check for preexisting symlinks, so we can cope with the
1125             # symlinks to $prefix
1126             for i in "$src"/*; do
1127                 [[ -e "$i" || -h "$i" ]] || continue
1128                 s=${initdir}/${tgt}/${i#$src/}
1129                 if [[ -d "$i" ]]; then
1130                     if ! [[ -e "$s" ]]; then
1131                         mkdir -m 0755 -p "$s"
1132                         chmod --reference="$i" "$s"
1133                     fi
1134                     cp --reflink=auto --sparse=auto -fa -t "$s" "$i"/*
1135                 else
1136                     cp --reflink=auto --sparse=auto -fa -t "$s" "$i"
1137                 fi
1138             done
1139         fi
1140     fi
1141 done
1142
1143 if [[ $kernel_only != yes ]]; then
1144     # make sure that library links are correct and up to date
1145     for f in /etc/ld.so.conf /etc/ld.so.conf.d/*; do
1146         [[ -f $f ]] && inst_simple "$f"
1147     done
1148     if ! ldconfig -r "$initdir"; then
1149         if [[ $UID = 0 ]]; then
1150             derror "ldconfig exited ungracefully"
1151         else
1152             derror "ldconfig might need uid=0 (root) for chroot()"
1153         fi
1154     fi
1155 fi
1156
1157 if (( maxloglvl >= 5 )); then
1158     ddebug "Listing sizes of included files:"
1159     du -c "$initdir" | sort -n | ddebug
1160 fi
1161
1162 PRELINK_BIN="$(command -v prelink)"
1163 if [[ $UID = 0 ]] && [[ $PRELINK_BIN ]]; then
1164     if [[ $DRACUT_FIPS_MODE ]]; then
1165         dinfo "*** Installing prelink files ***"
1166         dracut_install -o prelink /etc/prelink.conf /etc/prelink.conf.d/*.conf /etc/prelink.cache
1167     else
1168         dinfo "*** Pre-linking files ***"
1169         dracut_install -o prelink /etc/prelink.conf /etc/prelink.conf.d/*.conf
1170         chroot "$initdir" "$PRELINK_BIN" -a
1171         rm -f -- "$initdir/$PRELINK_BIN"
1172         rm -fr -- "$initdir"/etc/prelink.*
1173         dinfo "*** Pre-linking files done ***"
1174     fi
1175 fi
1176
1177 if [[ $do_hardlink = yes ]] && command -v hardlink >/dev/null; then
1178     dinfo "*** Hardlinking files ***"
1179     hardlink "$initdir" 2>&1
1180     dinfo "*** Hardlinking files done ***"
1181 fi
1182
1183 # strip binaries
1184 if [[ $do_strip = yes ]] ; then
1185     for p in strip xargs find; do
1186         if ! type -P $p >/dev/null; then
1187             dinfo "Could not find '$p'. Not stripping the initramfs."
1188             do_strip=no
1189         fi
1190     done
1191 fi
1192
1193 if [[ $do_strip = yes ]] ; then
1194     dinfo "*** Stripping files ***"
1195     if [[ $DRACUT_FIPS_MODE ]]; then
1196         find "$initdir" -type f \
1197             -executable -not -path '*/lib/modules/*.ko' -print0 \
1198             | while read -r -d $'\0' f; do
1199             if ! [[ -e "${f%/*}/.${f##*/}.hmac" ]] \
1200                 && ! [[ -e "/lib/hmaccalc/${f##*/}.hmac" ]] \
1201                 && ! [[ -e "/lib64/hmaccalc/${f##*/}.hmac" ]] \
1202                 && ! [[ -e "/lib/fipscheck/${f##*/}.hmac" ]] \
1203                 && ! [[ -e "/lib64/fipscheck/${f##*/}.hmac" ]]; then
1204                 printf "%s\000" "$f";
1205             fi
1206         done | xargs -r -0 strip -g 2>/dev/null
1207     else
1208         find "$initdir" -type f \
1209             -executable -not -path '*/lib/modules/*.ko' -print0 \
1210             | xargs -r -0 strip -g 2>/dev/null
1211     fi
1212
1213     # strip kernel modules, but do not touch signed modules
1214     find "$initdir" -type f -path '*/lib/modules/*.ko' -print0 \
1215         | while read -r -d $'\0' f; do
1216         SIG=$(tail -c 28 "$f")
1217         [[ $SIG == '~Module signature appended~' ]] || { printf "%s\000" "$f"; }
1218     done | xargs -r -0 strip -g
1219
1220     dinfo "*** Stripping files done ***"
1221 fi
1222
1223 rm -f -- "$outfile"
1224 dinfo "*** Creating image file ***"
1225 if ! ( umask 077; cd "$initdir"; find . | cpio -R 0:0 -H newc -o --quiet | \
1226     $compress > "$outfile.$$"; ); then
1227     dfatal "dracut: creation of $outfile.$$ failed"
1228     exit 1
1229 fi
1230 mv -- "$outfile.$$" "$outfile"
1231 dinfo "*** Creating image file done ***"
1232
1233 dinfo "Wrote $outfile:"
1234 dinfo "$(ls -l "$outfile")"
1235
1236 exit 0