]>
Commit | Line | Data |
---|---|---|
04b56f3a JK |
1 | #!/bin/bash |
2 | # | |
33ee031c | 3 | # functions used by dracut and other tools. |
04b56f3a | 4 | # |
33ee031c | 5 | # Copyright 2005-2009 Red Hat, Inc. All rights reserved. |
04b56f3a JK |
6 | # |
7 | # This program is free software; you can redistribute it and/or modify | |
8 | # it under the terms of the GNU General Public License as published by | |
9 | # the Free Software Foundation; either version 2 of the License, or | |
10 | # (at your option) any later version. | |
11 | # | |
12 | # This program is distributed in the hope that it will be useful, | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | # GNU General Public License for more details. | |
16 | # | |
17 | # You should have received a copy of the GNU General Public License | |
0f9c78c1 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
04b56f3a | 19 | # |
04b56f3a JK |
20 | |
21 | IF_RTLD="" | |
22 | IF_dynamic="" | |
36b24d7c | 23 | |
3198f171 | 24 | # Generic substring function. If $2 is in $1, return 0. |
f04dc5f3 VL |
25 | strstr() { [[ ! ${1#*$2*} = $1 ]]; } |
26 | ||
4cf26268 | 27 | # Log initrd creation. |
1a918b40 | 28 | if ! [[ $dracutlogfile ]]; then |
73198d53 | 29 | [[ $dsrc = /usr/share/dracut ]] && \ |
c1d71b7e | 30 | dracutlogfile=/var/log/dracut.log || \ |
1a918b40 | 31 | dracutlogfile=/tmp/dracut.log |
161efa1f | 32 | [[ -w $dracutlogfile ]] || dracutlogfile=/tmp/dracut.log |
1a918b40 VL |
33 | >"$dracutlogfile" |
34 | fi | |
35 | ||
6fac4691 HH |
36 | dwarning() { |
37 | echo "W: $@" >&2 | |
161efa1f | 38 | [[ -w $dracutlogfile ]] && echo "W: $@" >>"$dracutlogfile" |
6fac4691 HH |
39 | } |
40 | ||
41 | dinfo() { | |
84ffb877 | 42 | [[ $beverbose ]] && echo "I: $@" >&2 |
161efa1f | 43 | [[ -w $dracutlogfile ]] && echo "I: $@" >>"$dracutlogfile" |
6fac4691 HH |
44 | } |
45 | ||
46 | derror() { | |
47 | echo "E: $@" >&2 | |
161efa1f | 48 | [[ -w $dracutlogfile ]] && echo "E: $@" >>"$dracutlogfile" |
6fac4691 HH |
49 | } |
50 | ||
36b24d7c VL |
51 | # $1 = file to copy to ramdisk |
52 | # $2 (optional) Name for the file on the ramdisk | |
53 | # Location of the image dir is assumed to be $initdir | |
3198f171 | 54 | # We never overwrite the target if it exists. |
36b24d7c | 55 | inst_simple() { |
54b44196 VL |
56 | local src target |
57 | [[ -f $1 ]] || return 1 | |
161efa1f | 58 | src=$1 target=${initdir}${2:-$1} |
36b24d7c | 59 | [[ -f $target ]] && return 0 |
36b24d7c | 60 | mkdir -p "${target%/*}" |
6fac4691 | 61 | dinfo "Installing $src" |
860ace56 | 62 | cp -pfL "$src" "$target" |
36b24d7c VL |
63 | } |
64 | ||
3198f171 VL |
65 | # Same as above, but specialzed to handle dynamic libraries. |
66 | # It handles making symlinks according to how the original library | |
67 | # is referenced. | |
36b24d7c VL |
68 | inst_library() { |
69 | local src=$1 dest=${2:-$1} | |
70 | [[ -f $initdir$dest ]] && return 0 | |
71 | if [[ -L $src ]]; then | |
161efa1f | 72 | reallib=$(readlink -f "$src") |
36b24d7c | 73 | lib=${src##*/} |
9f88fcd9 | 74 | inst_simple "$reallib" "$reallib" |
161efa1f | 75 | mkdir -p "${initdir}${dest%/*}" |
36b24d7c VL |
76 | (cd "${initdir}${dest%/*}" && ln -s "$reallib" "$lib") |
77 | else | |
78 | inst_simple "$src" "$dest" | |
79 | fi | |
80 | } | |
3198f171 VL |
81 | |
82 | # find a binary. If we were not passed the full path directly, | |
83 | # search in the usual places to find the binary. | |
6b25d71a VL |
84 | find_binary() { |
85 | local binpath="/bin /sbin /usr/bin /usr/sbin" p | |
0c296f15 | 86 | [[ -z ${1##/*} && -x $1 ]] && { echo $1; return 0; } |
3359c8da | 87 | for p in $binpath; do |
6b25d71a | 88 | [[ -x $p/$1 ]] && { echo "$p/$1"; return 0; } |
3359c8da VL |
89 | done |
90 | return 1 | |
91 | } | |
36b24d7c | 92 | |
3198f171 VL |
93 | # Same as above, but specialized to install binary executables. |
94 | # Install binary executable, and all shared library dependencies, if any. | |
36b24d7c | 95 | inst_binary() { |
54b44196 | 96 | local bin target |
6b25d71a | 97 | bin=$(find_binary "$1") || return 1 |
3198f171 | 98 | target=${2:-$bin} |
36b24d7c | 99 | local LDSO NAME IO FILE ADDR I1 n f TLIBDIR |
8c1faa35 | 100 | [[ -f $initdir$target ]] && return 0 |
8667f2b7 | 101 | # I love bash! |
5c862533 | 102 | ldd $bin 2>/dev/null | while read line; do |
f04dc5f3 | 103 | [[ $line = 'not a dynamic executable' ]] && return 1 |
cdad82fd | 104 | if [[ $line =~ not\ found ]]; then |
6fac4691 HH |
105 | derror "Missing a shared library required by $bin." |
106 | derror "Run \"ldd $bin\" to find out what it is." | |
107 | derror "dracut cannot create an initrd." | |
36b24d7c | 108 | exit 1 |
cdad82fd | 109 | fi |
fdb3d52d MP |
110 | so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)' |
111 | [[ $line =~ $so_regex ]] || continue | |
f04dc5f3 VL |
112 | FILE=${BASH_REMATCH[1]} |
113 | [[ -f ${initdir}$FILE ]] && continue | |
8667f2b7 | 114 | # see if we are loading an optimized version of a shared lib. |
fdb3d52d MP |
115 | lib_regex='^(/lib[^/]*).*' |
116 | if [[ $FILE =~ $lib_regex ]]; then | |
8667f2b7 | 117 | TLIBDIR=${BASH_REMATCH[1]} |
161efa1f | 118 | BASE=${FILE##*/} |
8667f2b7 VL |
119 | # prefer nosegneg libs, then unoptimized ones. |
120 | for f in "$TLIBDIR/i686/nosegneg" "$TLIBDIR"; do | |
121 | [[ -f $f/$BASE ]] || continue | |
161efa1f | 122 | FILE=$f/$BASE |
8667f2b7 VL |
123 | break |
124 | done | |
36b24d7c | 125 | inst_library "$FILE" "$TLIBDIR/$BASE" |
161efa1f | 126 | IF_dynamic=yes |
36b24d7c | 127 | continue |
cdad82fd | 128 | fi |
36b24d7c | 129 | inst_library "$FILE" |
5c862533 | 130 | done |
3198f171 | 131 | inst_simple "$bin" "$target" |
36b24d7c | 132 | } |
04b56f3a | 133 | |
36b24d7c VL |
134 | # same as above, except for shell scripts. |
135 | # If your shell script does not start with shebang, it is not a shell script. | |
136 | inst_script() { | |
54b44196 | 137 | [[ -f $1 ]] || return 1 |
c7b2624f VL |
138 | local line |
139 | read -r -n 80 line <"$1" | |
00531568 AT |
140 | # If debug is set, clean unprintable chars to prevent messing up the term |
141 | [[ $debug ]] && line=$(echo -n "$line" | tr -c -d '[:print:][:space:]') | |
fdb3d52d MP |
142 | shebang_regex='(#! *)(/[^ ]+).*' |
143 | [[ $line =~ $shebang_regex ]] || return 1 | |
c7b2624f | 144 | inst "${BASH_REMATCH[2]}" && inst_simple "$@" |
04b56f3a JK |
145 | } |
146 | ||
36b24d7c VL |
147 | # same as above, but specialized for symlinks |
148 | inst_symlink() { | |
149 | local src=$1 target=$initdir${2:-$1} realsrc | |
150 | [[ -L $1 ]] || return 1 | |
151 | [[ -L $target ]] && return 0 | |
9f88fcd9 | 152 | realsrc=$(readlink -f "$src") |
161efa1f | 153 | [[ $realsrc = ${realsrc##*/} ]] && realsrc=${src%/*}/$realsrc |
36b24d7c VL |
154 | inst "$realsrc" && ln -s "$realsrc" "$target" |
155 | } | |
156 | ||
3198f171 | 157 | # find a rule in the usual places. |
09805e02 | 158 | find_rule() { |
b649f1c2 | 159 | [[ -f $1 ]] && { echo "$1"; return 0; } |
09805e02 VL |
160 | for r in . /lib/udev/rules.d /etc/udev/rules.d $dsrc/rules.d; do |
161 | [[ -f $r/$1 ]] && { echo "$r/$1"; return 0; } | |
162 | done | |
163 | return 1 | |
164 | } | |
165 | ||
f04dc5f3 VL |
166 | # udev rules always get installed in the same place, so |
167 | # create a function to install them to make life simpler. | |
168 | inst_rules() { | |
161efa1f | 169 | local target=/etc/udev/rules.d |
8faaa8f0 | 170 | mkdir -p "$initdir/lib/udev/rules.d" "$initdir$target" |
f04dc5f3 | 171 | for rule in "$@"; do |
161efa1f | 172 | rule=$(find_rule "$rule") && \ |
496d08bb | 173 | inst_simple "$rule" "$target/${rule##*/}" |
f04dc5f3 VL |
174 | done |
175 | } | |
176 | ||
36b24d7c VL |
177 | # general purpose installation function |
178 | # Same args as above. | |
6b24de99 | 179 | inst() { |
34fffd88 | 180 | if (($# != 1 && $# != 2 )); then |
6fac4691 | 181 | derror "inst only takes 1 or 2 arguments" |
74534e19 | 182 | exit 1 |
59dc3736 | 183 | fi |
8c1faa35 | 184 | for x in inst_symlink inst_script inst_binary inst_simple; do |
34fffd88 | 185 | $x "$@" && return 0 |
36b24d7c VL |
186 | done |
187 | return 1 | |
04b56f3a JK |
188 | } |
189 | ||
53f95456 VL |
190 | # install function specialized for hooks |
191 | # $1 = type of hook, $2 = hook priority (lower runs first), $3 = hook | |
192 | # All hooks should be POSIX/SuS compliant, they will be sourced by init. | |
193 | inst_hook() { | |
cdad82fd | 194 | if ! [[ -f $3 ]]; then |
6fac4691 HH |
195 | derror "Cannot install a hook ($3) that does not exist." |
196 | derror "Aborting initrd creation." | |
53f95456 | 197 | exit 1 |
cdad82fd | 198 | elif ! strstr "$hookdirs" "$1"; then |
6fac4691 | 199 | derror "No such hook type $1. Aborting initrd creation." |
53f95456 | 200 | exit 1 |
cdad82fd | 201 | fi |
53f95456 VL |
202 | inst_simple "$3" "/${1}/${2}${3##*/}" |
203 | } | |
204 | ||
f4fff04e | 205 | dracut_install() { |
bd4c4bcb VL |
206 | if [[ $1 = '-o' ]]; then |
207 | local optional=yes | |
208 | shift | |
209 | fi | |
f4fff04e | 210 | while (($# > 0)); do |
bd4c4bcb VL |
211 | if ! inst "$1" ; then |
212 | if [[ $optional = yes ]]; then | |
213 | dwarning "Skipping program $1 as it cannot be found and is flagged to be optional" | |
214 | else | |
215 | derror "Failed to install $1" | |
216 | exit 1 | |
217 | fi | |
218 | fi | |
219 | shift | |
f4fff04e VL |
220 | done |
221 | } | |
222 | ||
0c2e3d12 | 223 | check_module_deps() { |
4cf26268 VL |
224 | local moddir dep ret |
225 | # if we are already set to be loaded, we do not have to be checked again. | |
bd4c4bcb | 226 | strstr "$mods_to_load" " $1 " && return |
0c2e3d12 VL |
227 | # turn a module name into a directory, if we can. |
228 | moddir=$(echo ${dsrc}/modules.d/??${1}) | |
229 | [[ -d $moddir && -x $moddir/install ]] || return 1 | |
230 | # if we do not have a check script, we are unconditionally included | |
231 | if [[ -x $moddir/check ]]; then | |
4cf26268 VL |
232 | "$moddir/check" |
233 | ret=$? | |
234 | # a return value of 255 = load module only as a dependency. | |
235 | ((ret==0||ret==255)) || return 1 | |
0c2e3d12 | 236 | for dep in $("$moddir/check" -d); do |
4cf26268 | 237 | check_module_deps "$dep" && continue |
0c2e3d12 VL |
238 | dwarning "Dependency $mod failed." |
239 | return 1 | |
240 | done | |
241 | fi | |
242 | mods_to_load+=" $1 " | |
243 | } | |
244 | ||
245 | should_source_module() { | |
246 | local dep | |
247 | [[ -x $1/install ]] || return 1 | |
0c1a8ebc | 248 | if [[ $kernel_only = yes ]]; then |
33ee031c HH |
249 | [[ -x $1/installkernel ]] && return 0 |
250 | return 1 | |
251 | fi | |
0c2e3d12 VL |
252 | [[ -x $1/check ]] || return 0 |
253 | "$1/check" $hostonly || return 1 | |
254 | for dep in $("$1/check" -d); do | |
4cf26268 | 255 | check_module_deps "$dep" && continue |
0c2e3d12 VL |
256 | dwarning "Cannot load $mod, dependencies failed." |
257 | return 1 | |
258 | done | |
259 | } | |
260 | ||
261 | check_modules() { | |
262 | for moddir in "$dsrc/modules.d"/[0-9][0-9]*; do | |
263 | local mod=${moddir##*/}; mod=${mod#[0-9][0-9]} | |
4cf26268 VL |
264 | # If we are already scheduled to be loaded, no need to check again. |
265 | strstr "$mods_to_load" " $mod " && continue | |
266 | # This should never happen, but... | |
0c2e3d12 VL |
267 | [[ -d $moddir ]] || continue |
268 | [[ $dracutmodules != all ]] && ! strstr "$dracutmodules" "$mod" && \ | |
269 | continue | |
270 | strstr "$omit_dracutmodules" "$mod" && continue | |
624b52c4 | 271 | if ! strstr "$add_dracutmodules" "$mod"; then |
970e646b HH |
272 | should_source_module "$moddir" || continue |
273 | fi | |
0c2e3d12 VL |
274 | mods_to_load+=" $mod " |
275 | done | |
276 | } | |
277 | ||
e19d6bf6 | 278 | # install kernel modules, and handle installing all their dependencies as well. |
6fa0c3d6 | 279 | instmods() { |
0c1a8ebc | 280 | [[ $no_kernel = yes ]] && return |
6fa0c3d6 VL |
281 | local mod mpargs modpath modname cmd |
282 | while (($# > 0)); do | |
283 | mod=${1%.ko} | |
284 | case $mod in | |
992acaa9 | 285 | =*) # This introduces 2 incompatible meanings for =* arguments |
74534e19 | 286 | # to instmods. We need to decide which one to keep. |
0c1a8ebc | 287 | if [[ $mod = =ata && -f $srcmods/modules.block ]] ; then |
c93d9f62 | 288 | instmods $mpargs $(egrep 'ata|ahci' "${srcmods}/modules.block") |
86c9fa48 | 289 | elif [ -f $srcmods/modules.${mod#=} ]; then |
8d385248 | 290 | instmods $mpargs $(cat ${srcmods}/modules.${mod#=} ) |
20122a83 | 291 | else |
8d385248 | 292 | instmods $mpargs $(find "$srcmods" -path "*/${mod#=}/*") |
20122a83 HH |
293 | fi |
294 | ;; | |
6fa0c3d6 | 295 | --*) mpargs+=" $mod";; |
71afe645 WT |
296 | i2o_scsi) |
297 | # Must never run this diagnostic-only module | |
298 | shift; continue; | |
299 | ;; | |
cfee8a70 | 300 | *) mod=${mod##*/} |
4cf26268 VL |
301 | # if we are already installed, skip this module and go on |
302 | # to the next one. | |
3198f171 | 303 | [[ -f $initdir/$1 ]] && { shift; continue; } |
4cf26268 VL |
304 | # If we are building a host-specific initramfs and this |
305 | # module is not already loaded, move on to the next one. | |
306 | [[ $hostonly ]] && ! grep -q "$mod" /proc/modules && { | |
307 | shift; continue; | |
308 | } | |
0c1a8ebc VL |
309 | # ok, load the module, all its dependencies, and any firmware |
310 | # it may require | |
33ee031c | 311 | modprobe $mpargs --ignore-install --set-version $kernel -d ${srcmods%%/lib/modules/*}/ \ |
992acaa9 VL |
312 | --show-depends $mod 2>/dev/null | \ |
313 | while read cmd modpath options; do | |
6fa0c3d6 VL |
314 | [[ $cmd = insmod ]] || continue |
315 | modname=${modpath##*/} | |
316 | modname=${modname%.ko} | |
cdad82fd | 317 | if [[ ${mod/-/_} != ${modname/-/_} ]]; then |
ac9a1183 | 318 | dinfo "Installing dependencies for $mod ($modpath)" |
6fa0c3d6 | 319 | instmods $mpargs $modname |
cdad82fd | 320 | fi |
33ee031c HH |
321 | inst_simple "$modpath" "/lib/modules/$kernel/${modpath##*/lib/modules/$kernel/}" |
322 | for fw in $(modinfo -k $kernel -F firmware $modpath 2>/dev/null); do | |
323 | unset found | |
324 | IFS=: | |
325 | for fwdir in $fw_dir; do | |
326 | if [ -d "$fwdir" -a -f $fwdir/$fw ]; then | |
327 | inst_simple "$fwdir/$fw" "/lib/firmware/$fw" | |
328 | found=yes | |
329 | fi | |
330 | done | |
0c1a8ebc | 331 | if [[ $found != yes ]]; then |
33ee031c HH |
332 | dwarning "Possible missing firmware ${fw} for module ${mod}.ko" |
333 | fi | |
334 | done | |
6fa0c3d6 VL |
335 | done |
336 | ;; | |
c93d9f62 | 337 | esac |
6fa0c3d6 | 338 | shift |
04b56f3a | 339 | done |
6fa0c3d6 | 340 | } |
04b56f3a | 341 | |
04b56f3a | 342 | # vim:ts=8:sw=4:sts=4:et |