dracut.sh: speedup "strip"
[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-2010 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   -f, --force           Overwrite existing initramfs file.
46   -m, --modules [LIST]  Specify a space-separated list of dracut modules to
47                          call when building the initramfs. Modules are located
48                          in /usr/lib/dracut/modules.d.
49   -o, --omit [LIST]     Omit a space-separated list of dracut modules.
50   -a, --add [LIST]      Add a space-separated list of dracut modules.
51   -d, --drivers [LIST]  Specify a space-separated list of kernel modules to
52                         exclusively include in the initramfs.
53   --add-drivers [LIST] Specify a space-separated list of kernel
54                         modules to add to the initramfs.
55   --omit-drivers [LIST] Specify a space-separated list of kernel
56                         modules not to add to the initramfs.
57   --filesystems [LIST]  Specify a space-separated list of kernel filesystem
58                         modules to exclusively include in the generic
59                         initramfs.
60   -k, --kmoddir [DIR]   Specify the directory, where to look for kernel
61                         modules
62   --fwdir [DIR]         Specify additional directories, where to look for
63                         firmwares, separated by :
64   --kernel-only         Only install kernel drivers and firmware files
65   --no-kernel           Do not install kernel drivers and firmware files
66   --strip               Strip binaries in the initramfs
67   --nostrip             Do not strip binaries in the initramfs (default)
68   --prefix [DIR]        Prefix initramfs files with [DIR]
69   --noprefix            Do not prefix initramfs files (default)
70   --mdadmconf           Include local /etc/mdadm.conf
71   --nomdadmconf         Do not include local /etc/mdadm.conf
72   --lvmconf             Include local /etc/lvm/lvm.conf
73   --nolvmconf           Do not include local /etc/lvm/lvm.conf
74   --fscks [LIST]        Add a space-separated list of fsck helpers.
75   --nofscks             Inhibit installation of any fsck helpers.
76   -h, --help            This message
77   --debug               Output debug information of the build process
78   --profile             Output profile information of the build process
79   -L, --stdlog [0-6]    Specify logging level (to standard error)
80                          0 - suppress any messages
81                          1 - only fatal errors
82                          2 - all errors
83                          3 - warnings
84                          4 - info (default)
85                          5 - debug info (here starts lots of output)
86                          6 - trace info (and even more)
87   -v, --verbose         Increase verbosity level (default is info(4))
88   -q, --quiet           Decrease verbosity level (default is info(4))
89   -c, --conf [FILE]     Specify configuration file to use.
90                          Default: /etc/dracut.conf
91   --confdir [DIR]       Specify configuration directory to use *.conf files
92                          from. Default: /etc/dracut.conf.d
93   --tmpdir [DIR]        Temporary directory to be used instead of default
94                          /var/tmp.
95   -l, --local           Local mode. Use modules from the current working
96                          directory instead of the system-wide installed in
97                          /usr/lib/dracut/modules.d.
98                          Useful when running dracut from a git checkout.
99   -H, --hostonly        Host-Only mode: Install only what is needed for
100                          booting the local host instead of a generic host.
101   --no-hostonly         Disables Host-Only mode
102   --fstab               Use /etc/fstab to determine the root device.
103   --add-fstab [FILE]    Add file to the initramfs fstab
104   --mount "[DEV] [MP] [FSTYPE] [FSOPTS]"
105                         Mount device [DEV] on mountpoint [MP] with filesystem
106                         [FSTYPE] and options [FSOPTS] in the initramfs
107   -i, --include [SOURCE] [TARGET]
108                         Include the files in the SOURCE directory into the
109                          Target directory in the final initramfs.
110                         If SOURCE is a file, it will be installed to TARGET
111                          in the final initramfs.
112   -I, --install [LIST]  Install the space separated list of files into the
113                          initramfs.
114   --gzip                Compress the generated initramfs using gzip.
115                          This will be done by default, unless another
116                          compression option or --no-compress is passed.
117   --bzip2               Compress the generated initramfs using bzip2.
118                          Make sure your kernel has bzip2 decompression support
119                          compiled in, otherwise you will not be able to boot.
120   --lzma                Compress the generated initramfs using lzma.
121                          Make sure your kernel has lzma support compiled in,
122                          otherwise you will not be able to boot.
123   --xz                  Compress the generated initramfs using xz.
124                          Make sure that your kernel has xz support compiled
125                          in, otherwise you will not be able to boot.
126   --compress [COMPRESSION] Compress the generated initramfs with the
127                          passed compression program.  Make sure your kernel
128                          knows how to decompress the generated initramfs,
129                          otherwise you will not be able to boot.
130   --no-compress         Do not compress the generated initramfs.  This will
131                          override any other compression options.
132   --list-modules        List all available dracut modules.
133   -M, --show-modules    Print included module's name to standard output during
134                          build.
135   --keep                Keep the temporary initramfs for debugging purposes
136   --printsize           Print out the module install size
137   --sshkey [SSHKEY]     Add ssh key to initramfs (use with ssh-client module)
138
139 If [LIST] has multiple arguments, then you have to put these in quotes.
140 For example:
141 # dracut --add-drivers "module1 module2"  ...
142 EOF
143 }
144
145 # function push()
146 # push values to a stack
147 # $1 = stack variable
148 # $2.. values
149 # example:
150 # push stack 1 2 "3 4"
151 push() {
152     local __stack=$1; shift
153     for i in "$@"; do
154         eval ${__stack}'[${#'${__stack}'[@]}]="$i"'
155     done
156 }
157
158 # function pop()
159 # pops the last value from a stack
160 # assigns value to second argument variable
161 # or echo to stdout, if no second argument
162 # $1 = stack variable
163 # $2 = optional variable to store the value
164 # example:
165 # pop stack val
166 # val=$(pop stack)
167 pop() {
168     local __stack=$1; shift
169     local __resultvar=$1
170     local myresult;
171     # check for empty stack
172     eval '[[ ${#'${__stack}'[@]} -eq 0 ]] && return 1'
173
174     eval myresult='${'${__stack}'[${#'${__stack}'[@]}-1]}'
175
176     if [[ "$__resultvar" ]]; then
177         eval $__resultvar="'$myresult'"
178     else
179         echo "$myresult"
180     fi
181     eval unset ${__stack}'[${#'${__stack}'[@]}-1]'
182     return 0
183 }
184
185 # Little helper function for reading args from the commandline.
186 # it automatically handles -a b and -a=b variants, and returns 1 if
187 # we need to shift $3.
188 read_arg() {
189     # $1 = arg name
190     # $2 = arg value
191     # $3 = arg parameter
192     local rematch='^[^=]*=(.*)$'
193     if [[ $2 =~ $rematch ]]; then
194         read "$1" <<< "${BASH_REMATCH[1]}"
195     else
196         read "$1" <<< "$3"
197         # There is no way to shift our callers args, so
198         # return 1 to indicate they should do it instead.
199         return 1
200     fi
201 }
202
203 # Little helper function for reading args from the commandline to a stack.
204 # it automatically handles -a b and -a=b variants, and returns 1 if
205 # we need to shift $3.
206 push_arg() {
207     # $1 = arg name
208     # $2 = arg value
209     # $3 = arg parameter
210     local rematch='^[^=]*=(.*)$'
211     if [[ $2 =~ $rematch ]]; then
212         push "$1" "${BASH_REMATCH[1]}"
213     else
214         push "$1" "$3"
215         # There is no way to shift our callers args, so
216         # return 1 to indicate they should do it instead.
217         return 1
218     fi
219 }
220
221 verbosity_mod_l=0
222 unset kernel
223 unset outfile
224
225 while (($# > 0)); do
226     case ${1%%=*} in
227         -a|--add)      push_arg add_dracutmodules_l  "$@" || shift;;
228         --force-add)   push_arg force_add_dracutmodules_l  "$@" || shift;;
229         --add-drivers) push_arg add_drivers_l        "$@" || shift;;
230         --omit-drivers) push_arg omit_drivers_l      "$@" || shift;;
231         -m|--modules)  push_arg dracutmodules_l      "$@" || shift;;
232         -o|--omit)     push_arg omit_dracutmodules_l "$@" || shift;;
233         -d|--drivers)  push_arg drivers_l            "$@" || shift;;
234         --filesystems) push_arg filesystems_l        "$@" || shift;;
235         -I|--install)  push_arg install_items_l      "$@" || shift;;
236         --fwdir)       push_arg fw_dir_l             "$@" || shift;;
237         --libdirs)     push_arg libdirs_l            "$@" || shift;;
238         --fscks)       push_arg fscks_l              "$@" || shift;;
239         --add-fstab)   push_arg add_fstab_l          "$@" || shift;;
240         --mount)       push_arg fstab_lines          "$@" || shift;;
241         --nofscks)     nofscks_l="yes";;
242         -k|--kmoddir)  read_arg drivers_dir_l        "$@" || shift;;
243         -c|--conf)     read_arg conffile             "$@" || shift;;
244         --confdir)     read_arg confdir              "$@" || shift;;
245         --tmpdir)      read_arg tmpdir_l             "$@" || shift;;
246         -L|--stdlog)   read_arg stdloglvl_l          "$@" || shift;;
247         --compress)    read_arg compress_l           "$@" || shift;;
248         --prefix)      read_arg prefix_l             "$@" || shift;;
249         -f|--force)    force=yes;;
250         --kernel-only) kernel_only="yes"; no_kernel="no";;
251         --no-kernel)   kernel_only="no"; no_kernel="yes";;
252         --strip)       do_strip_l="yes";;
253         --nostrip)     do_strip_l="no";;
254         --noprefix)    prefix_l="/";;
255         --mdadmconf)   mdadmconf_l="yes";;
256         --nomdadmconf) mdadmconf_l="no";;
257         --lvmconf)     lvmconf_l="yes";;
258         --nolvmconf)   lvmconf_l="no";;
259         --debug)       debug="yes";;
260         --profile)     profile="yes";;
261         --sshkey)      read_arg sshkey   "$@" || shift;;
262         -v|--verbose)  ((verbosity_mod_l++));;
263         -q|--quiet)    ((verbosity_mod_l--));;
264         -l|--local)
265                        allowlocal="yes"
266                        [[ -f "$(readlink -f ${0%/*})/dracut-functions.sh" ]] \
267                            && dracutbasedir="$(readlink -f ${0%/*})"
268                        ;;
269         -H|--hostonly) hostonly_l="yes" ;;
270         --no-hostonly) hostonly_l="no" ;;
271         --fstab)       use_fstab_l="yes" ;;
272         -h|--help)     usage; exit 1 ;;
273         -i|--include)  push include_src "$2"
274                        push include_target "$3"
275                        shift 2;;
276         --bzip2)       compress_l="bzip2";;
277         --lzma)        compress_l="lzma";;
278         --xz)          compress_l="xz";;
279         --no-compress) _no_compress_l="cat";;
280         --gzip)        compress_l="gzip";;
281         --list-modules)
282             do_list="yes";
283             ;;
284         -M|--show-modules)
285                        show_modules_l="yes"
286                        ;;
287         --keep)        keep="yes";;
288         --printsize)   printsize="yes";;
289         -*) printf "\nUnknown option: %s\n\n" "$1" >&2; usage; exit 1;;
290         *)
291             if ! [[ ${outfile+x} ]]; then
292                 outfile=$1
293             elif ! [[ ${kernel+x} ]]; then
294                 kernel=$1
295             else
296                 echo "Unknown argument: $1"
297                 usage; exit 1;
298             fi
299             ;;
300     esac
301     shift
302 done
303 if ! [[ $kernel ]]; then
304     kernel=$(uname -r)
305 fi
306 [[ $outfile ]] || outfile="/boot/initramfs-$kernel.img"
307
308 for i in /usr/sbin /sbin /usr/bin /bin; do
309     rl=$i
310     if [ -L "$i" ]; then
311         rl=$(readlink -f $i)
312     fi
313     NPATH+=":$rl"
314 done
315 export PATH="${NPATH#:}"
316 unset NPATH
317 unset LD_LIBRARY_PATH
318 unset GREP_OPTIONS
319
320 [[ $debug ]] && {
321     export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): ';
322     set -x
323 }
324
325 [[ $profile ]] && {
326     export PS4='+ $(date "+%s.%N") ${BASH_SOURCE}@${LINENO}: ';
327     set -x
328     debug=yes
329 }
330
331 [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
332
333 # if we were not passed a config file, try the default one
334 if [[ ! -f $conffile ]]; then
335     [[ $allowlocal ]] && conffile="$dracutbasedir/dracut.conf" || \
336         conffile="/etc/dracut.conf"
337 fi
338
339 if [[ ! -d $confdir ]]; then
340     [[ $allowlocal ]] && confdir="$dracutbasedir/dracut.conf.d" || \
341         confdir="/etc/dracut.conf.d"
342 fi
343
344 # source our config file
345 [[ -f $conffile ]] && . "$conffile"
346
347 # source our config dir
348 if [[ $confdir && -d $confdir ]]; then
349     for f in "$confdir"/*.conf; do
350         [[ -e $f ]] && . "$f"
351     done
352 fi
353
354 # these optins add to the stuff in the config file
355 if (( ${#add_dracutmodules_l[@]} )); then
356     while pop add_dracutmodules_l val; do
357         add_dracutmodules+=" $val "
358     done
359 fi
360
361 if (( ${#force_add_dracutmodules_l[@]} )); then
362     while pop force_add_dracutmodules_l val; do
363         force_add_dracutmodules+=" $val "
364     done
365 fi
366
367 if (( ${#fscks_l[@]} )); then
368     while pop fscks_l val; do
369         fscks+=" $val "
370     done
371 fi
372
373 if (( ${#add_fstab_l[@]} )); then
374     while pop add_fstab_l val; do
375         add_fstab+=" $val "
376     done
377 fi
378
379 if (( ${#fstab_lines_l[@]} )); then
380     while pop fstab_lines_l val; do
381         push fstab_lines $val
382     done
383 fi
384
385 if (( ${#install_items_l[@]} )); then
386     while pop install_items_l val; do
387         install_items+=" $val "
388     done
389 fi
390
391 # these options override the stuff in the config file
392 if (( ${#dracutmodules_l[@]} )); then
393     dracutmodules=''
394     while pop dracutmodules_l val; do
395         dracutmodules+="$val "
396     done
397 fi
398
399 if (( ${#omit_dracutmodules_l[@]} )); then
400     omit_dracutmodules=''
401     while pop omit_dracutmodules_l val; do
402         omit_dracutmodules+="$val "
403     done
404 fi
405
406 if (( ${#filesystems_l[@]} )); then
407     filesystems=''
408     while pop filesystems_l val; do
409         filesystems+="$val "
410     done
411 fi
412
413 if (( ${#fw_dir_l[@]} )); then
414     fw_dir=''
415     while pop fw_dir_l val; do
416         fw_dir+="$val "
417     done
418 fi
419
420 if (( ${#libdirs_l[@]} )); then
421     libdirs=''
422     while pop libdirs_l val; do
423         libdirs+="$val "
424     done
425 fi
426
427 [[ $stdloglvl_l ]] && stdloglvl=$stdloglvl_l
428 [[ ! $stdloglvl ]] && stdloglvl=4
429 stdloglvl=$((stdloglvl + verbosity_mod_l))
430 ((stdloglvl > 6)) && stdloglvl=6
431 ((stdloglvl < 0)) && stdloglvl=0
432
433 [[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l
434 [[ $do_strip_l ]] && do_strip=$do_strip_l
435 [[ $prefix_l ]] && prefix=$prefix_l
436 [[ $prefix = "/" ]] && unset prefix
437 [[ $hostonly_l ]] && hostonly=$hostonly_l
438 [[ $use_fstab_l ]] && use_fstab=$use_fstab_l
439 [[ $mdadmconf_l ]] && mdadmconf=$mdadmconf_l
440 [[ $lvmconf_l ]] && lvmconf=$lvmconf_l
441 [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
442 [[ $fw_dir ]] || fw_dir="/lib/firmware/updates /lib/firmware"
443 [[ $tmpdir_l ]] && tmpdir="$tmpdir_l"
444 [[ $tmpdir ]] || tmpdir=/var/tmp
445 [[ $do_strip ]] || do_strip=no
446 [[ $compress_l ]] && compress=$compress_l
447 [[ $show_modules_l ]] && show_modules=$show_modules_l
448 [[ $nofscks_l ]] && nofscks="yes"
449 # eliminate IFS hackery when messing with fw_dir
450 fw_dir=${fw_dir//:/ }
451
452 # handle compression options.
453 [[ $compress ]] || compress="gzip"
454 case $compress in
455     bzip2) compress="bzip2 -9";;
456     lzma)  compress="lzma -9";;
457     xz)    compress="xz --check=crc32 --lzma2=dict=1MiB";;
458     gzip)  command -v pigz > /dev/null 2>&1 && compress="pigz -9" || \
459                                          compress="gzip -9";;
460 esac
461 if [[ $_no_compress_l = "cat" ]]; then
462     compress="cat"
463 fi
464
465 [[ $hostonly = yes ]] && hostonly="-h"
466 [[ $hostonly != "-h" ]] && unset hostonly
467
468 if [[ -f $dracutbasedir/dracut-functions.sh ]]; then
469     . $dracutbasedir/dracut-functions.sh
470 else
471     echo "Cannot find $dracutbasedir/dracut-functions.sh." >&2
472     echo "Are you running from a git checkout?" >&2
473     echo "Try passing -l as an argument to $0" >&2
474     exit 1
475 fi
476
477 if [[ -f $dracutbasedir/dracut-version.sh ]]; then
478     . $dracutbasedir/dracut-version.sh
479 fi
480
481 # Verify bash version, curret minimum is 3.1
482 if (( ${BASH_VERSINFO[0]} < 3 ||
483     ( ${BASH_VERSINFO[0]} == 3 && ${BASH_VERSINFO[1]} < 1 ) )); then
484     dfatal 'You need at least Bash 3.1 to use dracut, sorry.'
485     exit 1
486 fi
487
488 dracutfunctions=$dracutbasedir/dracut-functions.sh
489 export dracutfunctions
490
491 if (( ${#drivers_l[@]} )); then
492     drivers=''
493     while pop drivers_l val; do
494         drivers+="$val "
495     done
496 fi
497 drivers=${drivers/-/_}
498
499 if (( ${#add_drivers_l[@]} )); then
500     while pop add_drivers_l val; do
501         add_drivers+=" $val "
502     done
503 fi
504 add_drivers=${add_drivers/-/_}
505
506 if (( ${#omit_drivers_l[@]} )); then
507     while pop omit_drivers_l val; do
508         omit_drivers+=" $val "
509     done
510 fi
511 omit_drivers=${omit_drivers/-/_}
512
513 omit_drivers_corrected=""
514 for d in $omit_drivers; do
515     strstr " $drivers $add_drivers " " $d " && continue
516     omit_drivers_corrected+="$d|"
517 done
518 omit_drivers="${omit_drivers_corrected%|}"
519 unset omit_drivers_corrected
520
521
522 ddebug "Executing $0 $dracut_args"
523
524 [[ $do_list = yes ]] && {
525     for mod in $dracutbasedir/modules.d/*; do
526         [[ -d $mod ]] || continue;
527         [[ -e $mod/install || -e $mod/installkernel || \
528             -e $mod/module-setup.sh ]] || continue
529         echo ${mod##*/??}
530     done
531     exit 0
532 }
533
534 # This is kinda legacy -- eventually it should go away.
535 case $dracutmodules in
536     ""|auto) dracutmodules="all" ;;
537 esac
538
539 abs_outfile=$(readlink -f "$outfile") && outfile="$abs_outfile"
540
541 [[ -f $srcmods/modules.dep ]] || {
542     dfatal "$srcmods/modules.dep is missing. Did you run depmod?"
543     exit 1
544 }
545
546 if [[ -f $outfile && ! $force ]]; then
547     dfatal "Will not override existing initramfs ($outfile) without --force"
548     exit 1
549 fi
550
551 outdir=${outfile%/*}
552 [[ $outdir ]] || outdir="/"
553
554 if [[ ! -d "$outdir" ]]; then
555     dfatal "Can't write $outfile: Directory $outdir does not exist."
556     exit 1
557 elif [[ ! -w "$outdir" ]]; then
558     dfatal "No permission to write $outdir."
559     exit 1
560 elif [[ -f "$outfile" && ! -w "$outfile" ]]; then
561     dfatal "No permission to write $outfile."
562     exit 1
563 fi
564
565 readonly TMPDIR="$tmpdir"
566 readonly initdir=$(mktemp --tmpdir="$TMPDIR/" -d -t initramfs.XXXXXX)
567 [ -d "$initdir" ] || {
568     dfatal "mktemp failed."
569     exit 1
570 }
571
572 # clean up after ourselves no matter how we die.
573 trap 'ret=$?;[[ $keep ]] && echo "Not removing $initdir." >&2 || rm -rf "$initdir";exit $ret;' EXIT
574 # clean up after ourselves no matter how we die.
575 trap 'exit 1;' SIGINT
576
577 # Need to be able to have non-root users read stuff (rpcbind etc)
578 chmod 755 "$initdir"
579
580 for line in "${fstab_lines[@]}"; do
581     set -- $line
582     #dev mp fs fsopts
583     push host_devs "$1"
584     push host_fs_types "$1|$3"
585 done
586
587 for f in $add_fstab; do
588     [ -e $f ] || continue
589     while read dev rest; do
590         push host_devs $dev
591     done < $f
592 done
593
594 if [[ $hostonly ]]; then
595     # in hostonly mode, determine all devices, which have to be accessed
596     # and examine them for filesystem types
597
598     push host_mp \
599         "/" \
600         "/etc" \
601         "/usr" \
602         "/usr/bin" \
603         "/usr/sbin" \
604         "/usr/lib" \
605         "/usr/lib64" \
606         "/boot"
607
608     for mp in "${host_mp[@]}"; do
609         mountpoint "$mp" >/dev/null 2>&1 || continue
610         push host_devs $(readlink -f "/dev/block/$(find_block_device "$mp")")
611     done
612 fi
613
614 _get_fs_type() (
615     [[ $1 ]] || return
616     if [[ -b $1 ]] && get_fs_env $1; then
617         echo "$(readlink -f $1)|$ID_FS_TYPE"
618         return 1
619     fi
620     if [[ -b /dev/block/$1 ]] && get_fs_env /dev/block/$1; then
621         echo "$(readlink -f /dev/block/$1)|$ID_FS_TYPE"
622         return 1
623     fi
624     if fstype=$(find_dev_fstype $1); then
625         echo "$1|$fstype"
626         return 1
627     fi
628     return 1
629 )
630
631 for dev in "${host_devs[@]}"; do
632     unset fs_type
633     for fstype in $(_get_fs_type $dev) \
634         $(check_block_and_slaves _get_fs_type $(get_maj_min $dev)); do
635         if ! strstr " ${host_fs_types[*]} " " $fstype ";then
636             push host_fs_types "$fstype"
637         fi
638     done
639 done
640
641 [[ -d $udevdir ]] \
642     || udevdir=$(pkg-config udev --variable=udevdir 2>/dev/null)
643 if ! [[ -d "$udevdir" ]]; then
644     [[ -d /lib/udev ]] && udevdir=/lib/udev
645     [[ -d /usr/lib/udev ]] && udevdir=/usr/lib/udev
646 fi
647
648 [[ -d $systemdutildir ]] \
649     || systemdutildir=$(pkg-config systemd --variable=systemdutildir 2>/dev/null)
650 [[ -d $systemdsystemunitdir ]] \
651     || systemdsystemunitdir=$(pkg-config systemd --variable=systemdsystemunitdir 2>/dev/null)
652
653 if ! [[ -d "$systemdutildir" ]]; then
654     [[ -d /lib/systemd ]] && systemdutildir=/lib/systemd
655     [[ -d /usr/lib/systemd ]] && systemdutildir=/usr/lib/systemd
656 fi
657 [[ -d "$systemdsystemunitdir" ]] || systemdsystemunitdir=${systemdutildir}/system
658
659 export initdir dracutbasedir dracutmodules drivers \
660     fw_dir drivers_dir debug no_kernel kernel_only \
661     add_drivers omit_drivers mdadmconf lvmconf filesystems \
662     use_fstab fstab_lines libdirs fscks nofscks \
663     stdloglvl sysloglvl fileloglvl kmsgloglvl logfile \
664     debug host_fs_types host_devs sshkey add_fstab \
665     DRACUT_VERSION udevdir systemdutildir systemdsystemunitdir
666
667 # Create some directory structure first
668 [[ $prefix ]] && mkdir -m 0755 -p "${initdir}${prefix}"
669
670 [[ -h /lib ]] || mkdir -m 0755 -p "${initdir}${prefix}/lib"
671 [[ $prefix ]] && ln -sfn "${prefix#/}/lib" "$initdir/lib"
672
673 if [[ $prefix ]]; then
674     for d in bin etc lib sbin tmp usr var $libdirs; do
675         strstr "$d" "/" && continue
676         ln -sfn "${prefix#/}/${d#/}" "$initdir/$d"
677     done
678 fi
679
680 if [[ $kernel_only != yes ]]; then
681     for d in usr/bin usr/sbin bin etc lib sbin tmp usr var var/log var/run var/lock $libdirs; do
682         [[ -e "${initdir}${prefix}/$d" ]] && continue
683         if [ -L "/$d" ]; then
684             inst_symlink "/$d" "${prefix}/$d"
685         else
686             mkdir -m 0755 -p "${initdir}${prefix}/$d"
687         fi
688     done
689
690     for d in dev proc sys sysroot root run run/lock run/initramfs; do
691         if [ -L "/$d" ]; then
692             inst_symlink "/$d"
693         else
694             mkdir -m 0755 -p "$initdir/$d"
695         fi
696     done
697
698     ln -sfn /run "$initdir/var/run"
699     ln -sfn /run/lock "$initdir/var/lock"
700 else
701     for d in lib "$libdir"; do
702         [[ -e "${initdir}${prefix}/$d" ]] && continue
703         if [ -h "/$d" ]; then
704             inst "/$d" "${prefix}/$d"
705         else
706             mkdir -m 0755 -p "${initdir}${prefix}/$d"
707         fi
708     done
709 fi
710
711 if [[ $kernel_only != yes ]]; then
712     mkdir -p "${initdir}/etc/cmdline.d"
713     for _d in $hookdirs; do
714         mkdir -m 0755 -p ${initdir}/lib/dracut/hooks/$_d
715     done
716     if [[ "$UID" = "0" ]]; then
717         for i in /dev/kmsg /dev/null /dev/console; do
718             [ -e $i ] || continue
719             cp -a $i $initdir/dev
720         done
721     fi
722 fi
723
724 mkdir -p "$initdir/.kernelmodseen"
725
726 mods_to_load=""
727 # check all our modules to see if they should be sourced.
728 # This builds a list of modules that we will install next.
729 for_each_module_dir check_module
730 for_each_module_dir check_mount
731
732 _isize=0 #initramfs size
733 modules_loaded=" "
734 # source our modules.
735 for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
736     _d_mod=${moddir##*/}; _d_mod=${_d_mod#[0-9][0-9]}
737     if strstr "$mods_to_load" " $_d_mod "; then
738         [[ $show_modules = yes ]] && echo "$_d_mod" || \
739             dinfo "*** Including module: $_d_mod ***"
740         if [[ $kernel_only = yes ]]; then
741             module_installkernel $_d_mod || {
742                 dfatal "installkernel failed in module $_d_mod"
743                 exit 1
744             }
745         else
746             module_install $_d_mod
747             if [[ $no_kernel != yes ]]; then
748                 module_installkernel $_d_mod || {
749                     dfatal "installkernel failed in module $_d_mod"
750                     exit 1
751                 }
752             fi
753         fi
754         mods_to_load=${mods_to_load// $_d_mod /}
755         modules_loaded+="$_d_mod "
756
757         #print the module install size
758         if [ -n "$printsize" ]; then
759             _isize_new=$(du -sk ${initdir}|cut -f1)
760             _isize_delta=$(($_isize_new - $_isize))
761             echo "$_d_mod install size: ${_isize_delta}k"
762             _isize=$_isize_new
763         fi
764     fi
765 done
766 unset moddir
767
768 for i in $modules_loaded; do
769     mkdir -p $initdir/lib/dracut
770     echo "$i" >> $initdir/lib/dracut/modules.txt
771 done
772
773 dinfo "*** Including modules done ***"
774
775 ## final stuff that has to happen
776
777 # generate module dependencies for the initrd
778 if [[ -d $initdir/lib/modules/$kernel ]] && \
779     ! depmod -a -b "$initdir" $kernel; then
780     dfatal "\"depmod -a $kernel\" failed."
781     exit 1
782 fi
783
784 while pop include_src src && pop include_target tgt; do
785     if [[ $src && $tgt ]]; then
786         if [[ -f $src ]]; then
787             inst $src $tgt
788         else
789             ddebug "Including directory: $src"
790             mkdir -p "${initdir}/${tgt}"
791             # check for preexisting symlinks, so we can cope with the
792             # symlinks to $prefix
793             for i in "$src"/*; do
794                 [[ -e "$i" || -h "$i" ]] || continue
795                 s=${initdir}/${tgt}/${i#$src/}
796                 if [[ -d "$i" ]]; then
797                     if ! [[ -e "$s" ]]; then
798                         mkdir -m 0755 -p "$s"
799                         chmod --reference="$i" "$s"
800                     fi
801                     cp -a -t "$s" "$i"/*
802                 else
803                     cp -a -t "$s" "$i"
804                 fi
805             done
806         fi
807     fi
808 done
809
810 if [[ $kernel_only != yes ]]; then
811     for item in $install_items; do
812         dracut_install "$item"
813     done
814     unset item
815
816     while pop fstab_lines line; do
817         echo "$line 0 0" >> "${initdir}/etc/fstab"
818     done
819
820     for f in $add_fstab; do
821         cat $f >> "${initdir}/etc/fstab"
822     done
823
824     # make sure that library links are correct and up to date
825     for f in /etc/ld.so.conf /etc/ld.so.conf.d/*; do
826         [[ -f $f ]] && inst_simple "$f"
827     done
828     if ! ldconfig -r "$initdir"; then
829         if [[ $UID = 0 ]]; then
830             derror "ldconfig exited ungracefully"
831         else
832             derror "ldconfig might need uid=0 (root) for chroot()"
833         fi
834     fi
835 fi
836
837 rm -fr "$initdir/.kernelmodseen"
838
839
840 if (($maxloglvl >= 5)); then
841     ddebug "Listing sizes of included files:"
842     du -c "$initdir" | sort -n | ddebug
843 fi
844
845 # strip binaries
846 if [[ $do_strip = yes ]] ; then
847     for p in strip xargs find; do
848         if ! type -P $p >/dev/null; then
849             derror "Could not find '$p'. You should run $0 with '--nostrip'."
850             do_strip=no
851         fi
852     done
853 fi
854
855 if [[ $do_strip = yes ]] ; then
856     find "$initdir" -type f \
857          \( -perm -0100 -or -perm -0010 -or -perm -0001 \
858         -or -path '*/lib/modules/*.ko' \) -print0 \
859         | xargs -0 strip -g 2>/dev/null
860 fi
861
862 type hardlink &>/dev/null && {
863     hardlink "$initdir" 2>&1
864 }
865
866 if strstr "$modules_loaded" " fips " && command -v prelink >/dev/null; then
867     for dir in "$initdir/bin" \
868        "$initdir/sbin" \
869        "$initdir/usr/bin" \
870        "$initdir/usr/sbin"; do
871         [[ -L "$dir" ]] && continue
872         for i in "$dir"/*; do
873             [[ -x $i ]] && prelink -u $i &>/dev/null
874         done
875     done
876 fi
877
878 if ! ( cd "$initdir"; find . |cpio -R 0:0 -H newc -o --quiet| \
879     $compress > "$outfile"; ); then
880     dfatal "dracut: creation of $outfile failed"
881     exit 1
882 fi
883
884 dinfo "Wrote $outfile:"
885 dinfo "$(ls -l "$outfile")"
886
887 exit 0