]> git.ipfire.org Git - thirdparty/dracut.git/blob - dracut
dracut: set TMPDIR to /var/tmp
[thirdparty/dracut.git] / dracut
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 usage() {
30 # 80x25 linebreak here ^
31 cat << EOF
32 Usage: $0 [OPTION]... <initramfs> <kernel-version>
33 Creates initial ramdisk images for preloading modules
34
35 -f, --force Overwrite existing initramfs file.
36 -m, --modules [LIST] Specify a space-separated list of dracut modules to
37 call when building the initramfs. Modules are located
38 in /usr/share/dracut/modules.d.
39 -o, --omit [LIST] Omit a space-separated list of dracut modules.
40 -a, --add [LIST] Add a space-separated list of dracut modules.
41 -d, --drivers [LIST] Specify a space-separated list of kernel modules to
42 exclusively include in the initramfs.
43 --add-drivers [LIST] Specify a space-separated list of kernel
44 modules to add to the initramfs.
45 --filesystems [LIST] Specify a space-separated list of kernel filesystem
46 modules to exclusively include in the generic
47 initramfs.
48 -k, --kmoddir [DIR] Specify the directory, where to look for kernel
49 modules
50 --fwdir [DIR] Specify additional directories, where to look for
51 firmwares, separated by :
52 --kernel-only Only install kernel drivers and firmware files
53 --no-kernel Do not install kernel drivers and firmware files
54 --strip Strip binaries in the initramfs
55 --nostrip Do not strip binaries in the initramfs (default)
56 --prefix [DIR] Prefix initramfs files with [DIR]
57 --noprefix Do not prefix initramfs files (default)
58 --mdadmconf Include local /etc/mdadm.conf
59 --nomdadmconf Do not include local /etc/mdadm.conf
60 --lvmconf Include local /etc/lvm/lvm.conf
61 --nolvmconf Do not include local /etc/lvm/lvm.conf
62 -h, --help This message
63 --debug Output debug information of the build process
64 -L, --stdlog [0-6] Specify logging level (to standard error)
65 0 - suppress any messages
66 1 - only fatal errors
67 2 - all errors
68 3 - warnings
69 4 - info (default)
70 5 - debug info (here starts lots of output)
71 6 - trace info (and even more)
72 -v, --verbose Increase verbosity level (default is info(4))
73 -q, --quiet Decrease verbosity level (default is info(4))
74 -c, --conf [FILE] Specify configuration file to use.
75 Default: /etc/dracut.conf
76 --confdir [DIR] Specify configuration directory to use *.conf files
77 from. Default: /etc/dracut.conf.d
78 -l, --local Local mode. Use modules from the current working
79 directory instead of the system-wide installed in
80 /usr/share/dracut/modules.d.
81 Useful when running dracut from a git checkout.
82 -H, --hostonly Host-Only mode: Install only what is needed for
83 booting the local host instead of a generic host.
84 --fstab Use /etc/fstab to determine the root device.
85 -i, --include [SOURCE] [TARGET]
86 Include the files in the SOURCE directory into the
87 Target directory in the final initramfs.
88 If SOURCE is a file, it will be installed to TARGET
89 in the final initramfs.
90 -I, --install [LIST] Install the space separated list of files into the
91 initramfs.
92 --gzip Compress the generated initramfs using gzip.
93 This will be done by default, unless another
94 compression option or --no-compress is passed.
95 --bzip2 Compress the generated initramfs using bzip2.
96 Make sure your kernel has bzip2 decompression support
97 compiled in, otherwise you will not be able to boot.
98 --lzma Compress the generated initramfs using lzma.
99 Make sure your kernel has lzma support compiled in,
100 otherwise you will not be able to boot.
101 --xz Compress the generated initramfs using xz.
102 Make sure that your kernel has xz support compiled
103 in, otherwise you will not be able to boot.
104 --compress [COMPRESSION] Compress the generated initramfs with the
105 passed compression program. Make sure your kernel
106 knows how to decompress the generated initramfs,
107 otherwise you will not be able to boot.
108 --no-compress Do not compress the generated initramfs. This will
109 override any other compression options.
110 --list-modules List all available dracut modules.
111 -M, --show-modules Print included module's name to standard output during
112 build.
113 EOF
114 }
115
116 # function push()
117 # push values to a stack
118 # $1 = stack variable
119 # $2.. values
120 # example:
121 # push stack 1 2 "3 4"
122 push() {
123 local __stack=$1; shift
124 for i in "$@"; do
125 eval ${__stack}'[${#'${__stack}'[@]}]="$i"'
126 done
127 }
128
129 # function pop()
130 # pops the last value from a stack
131 # assigns value to second argument variable
132 # or echo to stdout, if no second argument
133 # $1 = stack variable
134 # $2 = optional variable to store the value
135 # example:
136 # pop stack val
137 # val=$(pop stack)
138 pop() {
139 local __stack=$1; shift
140 local __resultvar=$1
141 local myresult;
142 # check for empty stack
143 eval '[[ ${#'${__stack}'[@]} -eq 0 ]] && return 1'
144
145 eval myresult='${'${__stack}'[${#'${__stack}'[@]}-1]}'
146
147 if [[ "$__resultvar" ]]; then
148 eval $__resultvar="'$myresult'"
149 else
150 echo "$myresult"
151 fi
152 eval unset ${__stack}'[${#'${__stack}'[@]}-1]'
153 return 0
154 }
155
156 # Little helper function for reading args from the commandline.
157 # it automatically handles -a b and -a=b variants, and returns 1 if
158 # we need to shift $3.
159 read_arg() {
160 # $1 = arg name
161 # $2 = arg value
162 # $3 = arg parameter
163 local rematch='^[^=]*=(.*)$'
164 if [[ $2 =~ $rematch ]]; then
165 read "$1" <<< "${BASH_REMATCH[1]}"
166 else
167 read "$1" <<< "$3"
168 # There is no way to shift our callers args, so
169 # return 1 to indicate they should do it instead.
170 return 1
171 fi
172 }
173
174 # Little helper function for reading args from the commandline to a stack.
175 # it automatically handles -a b and -a=b variants, and returns 1 if
176 # we need to shift $3.
177 push_arg() {
178 # $1 = arg name
179 # $2 = arg value
180 # $3 = arg parameter
181 local rematch='^[^=]*=(.*)$'
182 if [[ $2 =~ $rematch ]]; then
183 push "$1" "${BASH_REMATCH[1]}"
184 else
185 push "$1" "$3"
186 # There is no way to shift our callers args, so
187 # return 1 to indicate they should do it instead.
188 return 1
189 fi
190 }
191
192 verbosity_mod_l=0
193
194 while (($# > 0)); do
195 case ${1%%=*} in
196 -a|--add) push_arg add_dracutmodules_l "$@" || shift;;
197 --add-drivers) push_arg add_drivers_l "$@" || shift;;
198 -m|--modules) push_arg dracutmodules_l "$@" || shift;;
199 -o|--omit) push_arg omit_dracutmodules_l "$@" || shift;;
200 -d|--drivers) push_arg drivers_l "$@" || shift;;
201 --filesystems) push_arg filesystems_l "$@" || shift;;
202 -I|--install) push_arg install_items "$@" || shift;;
203 --fwdir) push_arg fw_dir_l "$@" || shift;;
204 -k|--kmoddir) read_arg drivers_dir_l "$@" || shift;;
205 -c|--conf) read_arg conffile "$@" || shift;;
206 --confdir) read_arg confdir "$@" || shift;;
207 -L|--stdlog) read_arg stdloglvl_l "$@" || shift;;
208 -I|--install) read_arg install_items "$@" || shift;;
209 --fwdir) read_arg fw_dir_l "$@" || shift;;
210 --compress) read_arg compress_l "$@" || shift;;
211 --prefix) read_arg prefix_l "$@" || shift;;
212 -f|--force) force=yes;;
213 --kernel-only) kernel_only="yes"; no_kernel="no";;
214 --no-kernel) kernel_only="no"; no_kernel="yes";;
215 --strip) do_strip_l="yes";;
216 --nostrip) do_strip_l="no";;
217 --noprefix) prefix_l="/";;
218 --mdadmconf) mdadmconf_l="yes";;
219 --nomdadmconf) mdadmconf_l="no";;
220 --lvmconf) lvmconf_l="yes";;
221 --nolvmconf) lvmconf_l="no";;
222 --debug) debug="yes";;
223 -v|--verbose) ((verbosity_mod_l++));;
224 -q|--quiet) ((verbosity_mod_l--));;
225 -l|--local) allowlocal="yes" ;;
226 -H|--hostonly) hostonly_l="yes" ;;
227 --fstab) use_fstab_l="yes" ;;
228 -h|--help) usage; exit 1 ;;
229 -i|--include) push include_src "$2"
230 push include_target "$3"
231 shift 2;;
232 --bzip2) compress_l="bzip2";;
233 --lzma) compress_l="lzma";;
234 --xz) compress_l="xz";;
235 --no-compress) _no_compress_l="cat";;
236 --gzip) compress_l="gzip";;
237 --list-modules)
238 do_list="yes";
239 ;;
240 -M|--show-modules)
241 show_modules_l="yes"
242 ;;
243 -*) printf "\nUnknown option: %s\n\n" "$1" >&2; usage; exit 1;;
244 *)
245 if ! [[ ${outfile+x} ]]; then
246 outfile=$1
247 elif ! [[ ${kernel+x} ]]; then
248 kernel=$1
249 else
250 usage; exit 1;
251 fi
252 ;;
253 esac
254 shift
255 done
256 if ! [[ $kernel ]]; then
257 kernel=$(uname -r)
258 fi
259 [[ $outfile ]] || outfile="/boot/initramfs-$kernel.img"
260
261 PATH=/sbin:/bin:/usr/sbin:/usr/bin
262 export PATH
263
264 [[ $debug ]] && {
265 export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): ';
266 set -x
267 }
268
269 [[ $dracutbasedir ]] || dracutbasedir=/usr/share/dracut
270
271 [[ $allowlocal && -f "$(readlink -f ${0%/*})/dracut-functions" ]] && \
272 dracutbasedir="$(readlink -f ${0%/*})"
273
274 # if we were not passed a config file, try the default one
275 if [[ ! -f $conffile ]]; then
276 [[ $allowlocal ]] && conffile="$dracutbasedir/dracut.conf" || \
277 conffile="/etc/dracut.conf"
278 fi
279
280 if [[ ! -d $confdir ]]; then
281 [[ $allowlocal ]] && confdir="$dracutbasedir/dracut.conf.d" || \
282 confdir="/etc/dracut.conf.d"
283 fi
284
285 # source our config file
286 [[ -f $conffile ]] && . "$conffile"
287
288 # source our config dir
289 if [[ $confdir && -d $confdir ]]; then
290 for f in "$confdir"/*.conf; do
291 [[ -e $f ]] && . "$f"
292 done
293 fi
294
295 # these optins add to the stuff in the config file
296 if (( ${#add_dracutmodules_l[@]} )); then
297 while pop add_dracutmodules_l val; do
298 add_dracutmodules+=" $val "
299 done
300 fi
301
302 if (( ${#add_drivers_l[@]} )); then
303 while pop add_drivers_l val; do
304 add_drivers+=" $val "
305 done
306 fi
307
308 # these options override the stuff in the config file
309 if (( ${#dracutmodules_l[@]} )); then
310 dracutmodules=''
311 while pop dracutmodules_l val; do
312 dracutmodules+="$val "
313 done
314 fi
315
316 if (( ${#omit_dracutmodules_l[@]} )); then
317 omit_dracutmodules=''
318 while pop omit_dracutmodules_l val; do
319 omit_dracutmodules+="$val "
320 done
321 fi
322
323 if (( ${#drivers_l[@]} )); then
324 drivers=''
325 while pop drivers_l val; do
326 drivers+="$val "
327 done
328 fi
329
330 if (( ${#filesystems_l[@]} )); then
331 filesystems=''
332 while pop filesystems_l val; do
333 filesystems+="$val "
334 done
335 fi
336
337 if (( ${#fw_dir_l[@]} )); then
338 fw_dir=''
339 while pop fw_dir_l val; do
340 fw_dir+="$val "
341 done
342 fi
343
344 [[ $stdloglvl_l ]] && stdloglvl=$stdloglvl_l
345 [[ ! $stdloglvl ]] && stdloglvl=4
346 stdloglvl=$((stdloglvl + verbosity_mod_l))
347 ((stdloglvl > 6)) && stdloglvl=6
348 ((stdloglvl < 0)) && stdloglvl=0
349
350 [[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l
351 [[ $do_strip_l ]] && do_strip=$do_strip_l
352 [[ $prefix_l ]] && prefix=$prefix_l
353 [[ $prefix = "/" ]] && unset prefix
354 [[ $hostonly_l ]] && hostonly=$hostonly_l
355 [[ $use_fstab_l ]] && use_fstab=$use_fstab_l
356 [[ $mdadmconf_l ]] && mdadmconf=$mdadmconf_l
357 [[ $lvmconf_l ]] && lvmconf=$lvmconf_l
358 [[ $dracutbasedir ]] || dracutbasedir=/usr/share/dracut
359 [[ $fw_dir ]] || fw_dir="/lib/firmware/updates /lib/firmware"
360 [[ $do_strip ]] || do_strip=no
361 [[ $compress_l ]] && compress=$compress_l
362 [[ $show_modules_l ]] && show_modules=$show_modules_l
363 # eliminate IFS hackery when messing with fw_dir
364 fw_dir=${fw_dir//:/ }
365
366 # handle compression options.
367 case $compress in
368 bzip2) compress="bzip -9";;
369 lzma) compress="lzma -9";;
370 xz) compress="xz --check=crc32 --lzma2=dict=1MiB";;
371 gzip) type pigz > /dev/null 2>&1 && compress="pigz -9" || \
372 compress="gzip -9";;
373 esac
374 if [[ $_no_compress_l = "cat" ]]; then
375 compress="cat"
376 fi
377
378 [[ $hostonly = yes ]] && hostonly="-h"
379 [[ $hostonly != "-h" ]] && unset hostonly
380 [[ $compress ]] || compress="gzip -9"
381
382 if [[ -f $dracutbasedir/dracut-functions ]]; then
383 . $dracutbasedir/dracut-functions
384 else
385 echo "Cannot find $dracutbasedir/dracut-functions." >&2
386 echo "Are you running from a git checkout?" >&2
387 echo "Try passing -l as an argument to $0" >&2
388 exit 1
389 fi
390
391 dracutfunctions=$dracutbasedir/dracut-functions
392 export dracutfunctions
393
394 ddebug "Executing $0 $dracut_args"
395
396 [[ $do_list = yes ]] && {
397 for mod in $dracutbasedir/modules.d/*; do
398 [[ -d $mod ]] || continue;
399 [[ -e $mod/install || -e $mod/installkernel || \
400 -e $mod/module-setup.sh ]] || continue
401 echo ${mod##*/??}
402 done
403 exit 0
404 }
405
406 # Detect lib paths
407 [[ $libdir ]] || for libdir in /lib64 /lib; do
408 [[ -d $libdir ]] && break
409 done || {
410 dfatal 'No lib directory?!!!'
411 exit 1
412 }
413
414 [[ $usrlibdir ]] || for usrlibdir in /usr/lib64 /usr/lib; do
415 [[ -d $usrlibdir ]] && break
416 done || dwarn 'No usr/lib directory!'
417
418 # This is kinda legacy -- eventually it should go away.
419 case $dracutmodules in
420 ""|auto) dracutmodules="all" ;;
421 esac
422
423 abs_outfile=$(readlink -f "$outfile") && outfile="$abs_outfile"
424
425 srcmods="/lib/modules/$kernel/"
426 [[ $drivers_dir ]] && {
427 if vercmp $(modprobe --version | cut -d' ' -f3) lt 3.7; then
428 dfatal 'To use --kmoddir option module-init-tools >= 3.7 is required.'
429 exit 1
430 fi
431 srcmods="$drivers_dir"
432 }
433 export srcmods
434
435 if [[ -f $outfile && ! $force ]]; then
436 dfatal "Will not override existing initramfs ($outfile) without --force"
437 exit 1
438 fi
439
440 outdir=${outfile%/*}
441 [[ $outdir ]] || outdir="/"
442
443 if [[ ! -d "$outdir" ]]; then
444 dfatal "Can't write $outfile: Directory $outdir does not exist."
445 exit 1
446 elif [[ ! -w "$outdir" ]]; then
447 dfatal "No permission to write $outdir."
448 exit 1
449 elif [[ -f "$outfile" && ! -w "$outfile" ]]; then
450 dfatal "No permission to write $outfile."
451 exit 1
452 fi
453
454 readonly TMPDIR=/var/tmp
455 readonly initdir=$(mktemp --tmpdir=/var/tmp/ -d -t initramfs.XXXXXX)
456
457 # clean up after ourselves no matter how we die.
458 trap 'ret=$?;rm -rf "$initdir";exit $ret;' EXIT
459 # clean up after ourselves no matter how we die.
460 trap 'exit 1;' SIGINT
461
462 # Need to be able to have non-root users read stuff (rpcbind etc)
463 chmod 755 "$initdir"
464
465 export initdir dracutbasedir dracutmodules drivers \
466 fw_dir drivers_dir debug no_kernel kernel_only \
467 add_drivers mdadmconf lvmconf filesystems \
468 use_fstab libdir usrlibdir \
469 stdloglvl sysloglvl fileloglvl kmsgloglvl logfile \
470 debug
471
472 # Create some directory structure first
473 [[ $prefix ]] && mkdir -m 0755 -p "${initdir}${prefix}"
474
475 mkdir -m 0755 -p "${initdir}${prefix}/lib"
476 [[ $prefix ]] && ln -sfn "${prefix#/}/lib" "$initdir/lib"
477
478 if [[ $kernel_only != yes ]]; then
479 for d in bin etc lib "$libdir" sbin tmp usr var; do
480 [[ -e "${initdir}${prefix}/$d" ]] && continue
481 mkdir -m 0755 -p "${initdir}${prefix}/$d"
482 [[ $prefix ]] && ln -sfn "${prefix#/}/${d#/}" "$initdir/$d"
483 done
484
485 for d in proc sys sysroot root run run/lock run/initramfs; do
486 mkdir -m 0755 -p "$initdir/$d";
487 done
488
489 ln -sfn /run "$initdir/var/run"
490 ln -sfn /run/lock "$initdir/var/lock"
491 fi
492
493 # check all our modules to see if they should be sourced.
494 # This builds a list of modules that we will install next.
495 check_module_dir
496 modules_loaded=" "
497 # source our modules.
498 for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
499 _d_mod=${moddir##*/}; _d_mod=${_d_mod#[0-9][0-9]}
500 if strstr "$mods_to_load" " $_d_mod "; then
501 [[ $show_modules = yes ]] && echo "$_d_mod" || \
502 dinfo "*** Including module: $_d_mod ***"
503 if [[ $kernel_only = yes ]]; then
504 module_installkernel $_d_mod
505 else
506 module_install $_d_mod
507 if [[ $no_kernel != yes ]]; then
508 module_installkernel $_d_mod
509 fi
510 fi
511 mods_to_load=${mods_to_load// $_d_mod /}
512 modules_loaded+="$_d_mod "
513 fi
514 done
515 unset moddir
516 dinfo "*** Including modules done ***"
517
518 ## final stuff that has to happen
519
520 # generate module dependencies for the initrd
521 if [[ -d $initdir/lib/modules/$kernel ]] && \
522 ! depmod -a -b "$initdir" $kernel; then
523 dfatal "\"depmod -a $kernel\" failed."
524 exit 1
525 fi
526
527 while pop include_src src && pop include_target tgt; do
528 if [[ $src && $tgt ]]; then
529 if [[ -f $src ]]; then
530 inst $src $tgt
531 else
532 ddebug "Including directory: $src"
533 mkdir -p "${initdir}/${tgt}"
534 # check for preexisting symlinks, so we can cope with the
535 # symlinks to $prefix
536 for i in "$src"/*; do
537 [[ -e "$i" || -h "$i" ]] || continue
538 s=${initdir}/${tgt}/${i#$src/}
539 if [[ -d "$i" ]]; then
540 if ! [[ -e "$s" ]]; then
541 mkdir -m 0755 -p "$s"
542 chmod --reference="$i" "$s"
543 fi
544 cp -a -t "$s" "$i"/*
545 else
546 cp -a -t "$s" "$i"
547 fi
548 done
549 fi
550 fi
551 done
552
553 while pop install_items items; do
554 for item in $items; do
555 dracut_install "$item"
556 done
557 done
558 unset item
559
560
561 if [[ $kernel_only != yes ]]; then
562 # make sure that library links are correct and up to date
563 for f in /etc/ld.so.conf /etc/ld.so.conf.d/*; do
564 [[ -e $f ]] && dracut_install "$f"
565 done
566 if ! ldconfig -r "$initdir"; then
567 if [[ $UID = 0 ]]; then
568 derror "ldconfig exited ungracefully"
569 else
570 derror "ldconfig might need uid=0 (root) for chroot()"
571 fi
572 fi
573 fi
574
575 if (($maxloglvl >= 5)); then
576 ddebug "Listing sizes of included files:"
577 du -c "$initdir" | sort -n | ddebug
578 fi
579
580 # strip binaries
581 if [[ $do_strip = yes ]] ; then
582 for p in strip grep find; do
583 if ! type -P $p >/dev/null; then
584 derror "Could not find '$p'. You should run $0 with '--nostrip'."
585 do_strip=no
586 fi
587 done
588 fi
589
590 if [[ $do_strip = yes ]] ; then
591 for f in $(find "$initdir" -type f \
592 \( -perm -0100 -or -perm -0010 -or -perm -0001 \
593 -or -path '*/lib/modules/*.ko' \) ); do
594 dinfo "Stripping $f"
595 strip -g "$f" 2>/dev/null|| :
596 done
597 fi
598
599 type hardlink &>/dev/null && {
600 hardlink "$initdir" 2>&1
601 }
602
603 if strstr "$modules_loaded" " fips " && command -v prelink >/dev/null; then
604 for i in $initdir/bin/* \
605 $initdir/bin/* \
606 $initdir/usr/bin/* \
607 $initdir/usr/sbin/*; do
608 [ -x $i ] && prelink -u $i &>/dev/null
609 done
610 fi
611
612 if ! ( cd "$initdir"; find . |cpio -R 0:0 -H newc -o --quiet | \
613 $compress > "$outfile"; ); then
614 dfatal "dracut: creation of $outfile failed"
615 exit 1
616 fi
617
618 dinfo "Wrote $outfile:"
619 dinfo "$(ls -l "$outfile")"
620
621 exit 0