2008-12-18 00:57:43 +03:00
#!/bin/bash
2010-09-10 17:23:06 +04:00
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
2008-12-18 00:57:43 +03:00
#
2009-07-22 14:43:26 +04:00
# functions used by dracut and other tools.
2008-12-18 00:57:43 +03:00
#
2009-07-22 14:43:26 +04:00
# Copyright 2005-2009 Red Hat, Inc. All rights reserved.
2008-12-18 00:57:43 +03:00
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
2009-03-04 19:29:42 +03:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2008-12-18 00:57:43 +03:00
#
2011-03-25 17:40:51 +03:00
if ! [ [ $dracutbasedir ] ] ; then
dracutbasedir = ${ BASH_SOURCE [0]%/* }
[ [ $dracutbasedir = "dracut-functions" ] ] && dracutbasedir = "."
[ [ $dracutbasedir ] ] || dracutbasedir = "."
dracutbasedir = " $( readlink -f $dracutbasedir ) "
fi
2011-03-25 17:38:54 +03:00
if ! type dinfo >/dev/null 2>& 1; then
2012-02-22 13:14:17 +04:00
. " $dracutbasedir /dracut-logger.sh "
2011-03-15 21:37:45 +03:00
dlog_init
fi
2012-02-16 14:49:19 +04:00
# export standard hookdirs
[ [ $hookdirs ] ] || {
2012-03-02 17:46:11 +04:00
hookdirs = "cmdline pre-udev pre-trigger netroot "
hookdirs += "initqueue initqueue/settled initqueue/finished initqueue/timeout "
hookdirs += "pre-mount pre-pivot mount "
hookdirs += "emergency shutdown-emergency shutdown cleanup "
2012-02-16 14:49:19 +04:00
export hookdirs
}
2009-03-07 06:41:31 +03:00
# Generic substring function. If $2 is in $1, return 0.
2012-02-22 16:04:16 +04:00
strstr( ) { [ " ${ 1 #* $2 * } " != " $1 " ] ; }
2009-02-13 15:43:26 +03:00
2010-07-01 23:17:37 +04:00
# Create all subdirectories for given path without creating the last element.
# $1 = path
2011-03-25 15:04:16 +03:00
mksubdirs( ) { mkdir -m 0755 -p ${ 1 %/* } ; }
2010-07-01 23:17:37 +04:00
2010-06-11 23:10:34 +04:00
# Version comparision function. Assumes Linux style version scheme.
# $1 = version a
# $2 = comparision op (gt, ge, eq, le, lt, ne)
# $3 = version b
2010-06-09 12:36:05 +04:00
vercmp( ) {
2011-05-12 13:03:30 +04:00
local _n1 = ( ${ 1 //./ } ) _op = $2 _n2 = ( ${ 3 //./ } ) _i _res
2010-06-09 12:36:05 +04:00
2011-05-12 13:03:30 +04:00
for ( ( _i = 0; ; _i++) )
2010-06-11 23:10:34 +04:00
do
2011-05-12 13:03:30 +04:00
if [ [ ! ${ _n1 [_i] } ${ _n2 [_i] } ] ] ; then _res = 0
elif ( ( ${ _n1 [_i] :- 0 } > ${ _n2 [_i] :- 0 } ) ) ; then _res = 1
elif ( ( ${ _n1 [_i] :- 0 } < ${ _n2 [_i] :- 0 } ) ) ; then _res = 2
2010-06-11 23:10:34 +04:00
else continue
fi
break
2010-06-09 12:36:05 +04:00
done
2011-05-12 13:03:30 +04:00
case $_op in
gt) ( ( _res = = 1) ) ; ;
ge) ( ( _res != 2) ) ; ;
eq) ( ( _res = = 0) ) ; ;
le) ( ( _res != 1) ) ; ;
lt) ( ( _res = = 2) ) ; ;
ne) ( ( _res != 0) ) ; ;
2010-06-11 23:10:34 +04:00
esac
2010-06-09 12:36:05 +04:00
}
2012-02-16 14:49:19 +04:00
# is_func <command>
# Check whether $1 is a function.
2011-02-02 15:34:58 +03:00
is_func( ) {
2011-03-25 17:56:46 +03:00
[ [ $( type -t $1 ) = "function" ] ]
2011-02-02 15:34:58 +03:00
}
2010-07-01 23:17:37 +04:00
# Function prints global variables in format name=value line by line.
# $@ = list of global variables' name
print_vars( ) {
2011-05-12 13:03:30 +04:00
local _var _value
2010-07-01 23:17:37 +04:00
2011-05-12 13:03:30 +04:00
for _var in $@
2010-07-01 23:17:37 +04:00
do
2011-05-12 13:03:30 +04:00
_value = $( eval echo \$ $_var )
[ [ ${ _value } ] ] && echo " ${ _var } =\" ${ _value } \" "
2010-07-01 23:17:37 +04:00
done
}
2012-02-16 14:49:19 +04:00
# normalize_path <path>
# Prints the normalized path, where it removes any duplicated
# and trailing slashes.
# Example:
# $ normalize_path ///test/test//
# /test/test
2011-07-25 16:28:55 +04:00
normalize_path( ) {
2011-10-08 02:20:50 +04:00
shopt -q -s extglob
set -- " ${ 1 //+( \/ )// } "
shopt -q -u extglob
echo " ${ 1 %/ } "
2011-07-25 16:28:55 +04:00
}
2011-07-25 12:25:44 +04:00
2012-02-16 14:49:19 +04:00
# convert_abs_rel <from> <to>
# Prints the relative path, when creating a symlink to <to> from <from>.
# Example:
# $ convert_abs_rel /usr/bin/test /bin/test-2
# ../../bin/test-2
# $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test
2011-07-25 12:25:44 +04:00
convert_abs_rel( ) {
2012-02-22 16:04:37 +04:00
local __current __absolute __abssize __cursize __newpath
2011-10-08 02:20:50 +04:00
local -i __i __level
2011-07-25 12:25:44 +04:00
2011-10-08 02:20:50 +04:00
set -- " $( normalize_path " $1 " ) " " $( normalize_path " $2 " ) "
2011-10-08 00:23:49 +04:00
# corner case #1 - self looping link
[ [ " $1 " = = " $2 " ] ] && { echo " ${ 1 ##*/ } " ; return ; }
# corner case #2 - own dir link
[ [ " ${ 1 %/* } " = = " $2 " ] ] && { echo "." ; return ; }
2012-02-22 16:04:37 +04:00
IFS = "/" __current = ( $1 )
IFS = "/" __absolute = ( $2 )
2011-07-25 12:25:44 +04:00
__abssize = ${# __absolute [@] }
__cursize = ${# __current [@] }
while [ [ ${ __absolute [__level] } = = ${ __current [__level] } ] ]
do
( ( __level++ ) )
if ( ( __level > __abssize || __level > __cursize ) )
then
break
fi
done
for ( ( __i = __level; __i < __cursize-1; __i++) )
do
if ( ( __i > __level) )
then
__newpath = $__newpath "/"
fi
__newpath = $__newpath ".."
done
for ( ( __i = __level; __i < __abssize; __i++) )
do
if [ [ -n $__newpath ] ]
then
__newpath = $__newpath "/"
fi
__newpath = $__newpath ${ __absolute [__i] }
done
echo " $__newpath "
}
2012-02-16 14:49:19 +04:00
# get_fs_env <device>
# Get and set the ID_FS_TYPE and ID_FS_UUID variable from udev for a device.
# Example:
# $ get_fs_env /dev/sda2; echo $ID_FS_TYPE; echo $ID_FS_UUID
# ext4
# 551a39aa-4ae9-4e70-a262-ef665cadb574
2009-08-22 21:04:11 +04:00
get_fs_env( ) {
2010-08-06 15:54:34 +04:00
[ [ $1 ] ] || return
2011-05-12 13:03:30 +04:00
unset ID_FS_TYPE
unset ID_FS_UUID
2012-02-25 19:07:45 +04:00
eval $( udevadm info --query= env --name= $1 \
| while read line; do
[ [ " $line " = ~ 'ID_FS_(TYPE|UUID)=' ] ] && echo $line ;
done )
2010-05-03 13:34:30 +04:00
[ [ $ID_FS_TYPE ] ] && return
2009-08-20 00:51:54 +04:00
if [ [ -x /lib/udev/vol_id ] ] ; then
2010-09-10 17:23:06 +04:00
eval $( /lib/udev/vol_id --export $1 )
2009-08-22 21:04:11 +04:00
elif find_binary blkid >/dev/null; then
2010-09-10 17:23:06 +04:00
eval $( blkid -o udev $1 )
2009-08-20 00:51:54 +04:00
else
2010-09-10 17:23:06 +04:00
return 1
2009-08-20 00:51:54 +04:00
fi
2009-08-22 21:04:11 +04:00
}
2012-02-16 14:49:19 +04:00
# get_fs_uuid <device>
# Prints the filesystem UUID for a device.
# Example:
# $ get_fs_uuid /dev/sda2
# 551a39aa-4ae9-4e70-a262-ef665cadb574
get_fs_uuid( ) (
get_fs_env $1 || return
echo $ID_FS_UUID
)
# get_fs_type <device>
# Prints the filesystem type for a device.
# Example:
# $ get_fs_type /dev/sda1
# ext4
2009-08-22 21:04:11 +04:00
get_fs_type( ) (
2010-08-06 15:54:34 +04:00
[ [ $1 ] ] || return
if [ [ $1 != ${ 1 #/dev/block/nfs : } ] ] \
2010-09-10 17:23:06 +04:00
|| [ [ $1 != ${ 1 #/dev/block/nfs3 : } ] ] \
|| [ [ $1 != ${ 1 #/dev/block/nfs4 : } ] ] ; then
echo "nfs"
return
2010-08-06 15:54:34 +04:00
fi
2011-12-08 13:25:58 +04:00
if get_fs_env $1 ; then
echo $ID_FS_TYPE
return
fi
find_dev_fstype $1
2009-08-22 21:04:11 +04:00
)
2012-02-16 14:49:19 +04:00
# get_maj_min <device>
# Prints the major and minor of a device node.
# Example:
# $ get_maj_min /dev/sda2
# 8:2
2011-12-08 13:43:29 +04:00
get_maj_min( ) {
local _dev
2012-01-23 16:50:05 +04:00
_dev = $( stat -L -c '$((0x%t)):$((0x%T))' " $1 " 2>/dev/null)
2011-12-08 13:43:29 +04:00
_dev = $( eval " echo $_dev " )
echo $_dev
}
2012-02-16 14:49:19 +04:00
# find_block_device <mountpoint>
# Prints the major and minor number of the block device
# for a given mountpoint.
# Unless $use_fstab is set to "yes" the functions
# uses /proc/self/mountinfo as the primary source of the
# information and only falls back to /etc/fstab, if the mountpoint
# is not found there.
# Example:
# $ find_block_device /usr
# 8:4
2009-08-20 07:20:12 +04:00
find_block_device( ) {
2011-05-12 13:03:30 +04:00
local _x _mpt _majmin _dev _fs _maj _min
2011-03-25 17:56:46 +03:00
if [ [ $use_fstab != yes ] ] ; then
2011-05-12 13:03:30 +04:00
while read _x _x _majmin _x _mpt _x _x _fs _dev _x; do
2011-12-08 13:25:58 +04:00
[ [ $_mpt = $1 ] ] || continue
2011-05-12 13:03:30 +04:00
[ [ $_fs = nfs ] ] && { echo $_dev ; return 0; }
[ [ $_fs = nfs3 ] ] && { echo $_dev ; return 0; }
[ [ $_fs = nfs4 ] ] && { echo $_dev ; return 0; }
[ [ $_fs = btrfs ] ] && {
2011-12-08 13:43:29 +04:00
get_maj_min $_dev
return 0;
2010-10-29 14:34:27 +04:00
}
2011-12-08 13:25:58 +04:00
if [ [ ${ _majmin #0 : } = $_majmin ] ] ; then
2011-05-12 13:03:30 +04:00
echo $_majmin
2010-09-10 17:23:06 +04:00
return 0 # we have a winner!
fi
2011-03-25 17:56:46 +03:00
done < /proc/self/mountinfo
2010-08-06 15:54:34 +04:00
fi
2011-03-25 17:56:46 +03:00
# fall back to /etc/fstab
2011-05-12 13:03:30 +04:00
while read _dev _mpt _fs _x; do
if [ [ $_mpt = $1 ] ] ; then
[ [ $_fs = nfs ] ] && { echo $_dev ; return 0; }
[ [ $_fs = nfs3 ] ] && { echo $_dev ; return 0; }
[ [ $_fs = nfs4 ] ] && { echo $_dev ; return 0; }
[ [ $_dev != ${ _dev #UUID= } ] ] && _dev = /dev/disk/by-uuid/${ _dev #UUID= }
[ [ $_dev != ${ _dev #LABEL= } ] ] && _dev = /dev/disk/by-label/${ _dev #LABEL= }
[ [ -b $_dev ] ] || return 1 # oops, not a block device.
2012-02-16 14:48:17 +04:00
get_maj_min " $_dev " && return 0
2010-09-10 17:23:06 +04:00
fi
2010-08-06 15:54:34 +04:00
done < /etc/fstab
2011-03-25 17:56:46 +03:00
return 1
2009-08-16 19:29:21 +04:00
}
2012-02-16 14:49:19 +04:00
# find_dev_fstype <device>
# Echo the filesystem type for a given device.
# /proc/self/mountinfo is taken as the primary source of information
# and /etc/fstab is used as a fallback.
# No newline is appended!
# Example:
# $ find_dev_fstype /dev/sda2;echo
# ext4
2011-12-08 13:25:58 +04:00
find_dev_fstype( ) {
local _x _mpt _majmin _dev _fs _maj _min
while read _x _x _majmin _x _mpt _x _x _fs _dev _x; do
[ [ $_dev = $1 ] ] || continue
echo -n $_fs ;
return 0;
done < /proc/self/mountinfo
# fall back to /etc/fstab
while read _dev _mpt _fs _x; do
[ [ $_dev = $1 ] ] || continue
echo -n $_fs ;
return 0;
done < /etc/fstab
return 1
}
# finds the major:minor of the block device backing the root filesystem.
2009-08-20 07:20:12 +04:00
find_root_block_device( ) { find_block_device /; }
2012-02-16 14:49:19 +04:00
# for_each_host_dev_fs <func>
# Execute "<func> <dev> <filesystem>" for every "<dev>|<fs>" pair found
# in ${host_fs_types[@]}
2011-12-08 13:43:29 +04:00
for_each_host_dev_fs( )
{
local _func = " $1 "
2011-12-20 10:09:59 +04:00
local _dev
local _fs
2012-02-22 22:06:00 +04:00
local _ret = 1
2011-12-08 13:43:29 +04:00
for f in ${ host_fs_types [@] } ; do
OLDIFS = " $IFS "
IFS = "|"
set -- $f
IFS = " $OLDIFS "
2011-12-20 10:09:59 +04:00
_dev = " $1 "
[ [ -b " $_dev " ] ] || continue
_fs = " $2 "
2012-02-22 22:06:00 +04:00
$_func $_dev $_fs && _ret = 0
2011-12-08 13:43:29 +04:00
done
2012-02-22 22:06:00 +04:00
return $_ret
2011-12-08 13:43:29 +04:00
}
2009-08-16 19:29:21 +04:00
# Walk all the slave relationships for a given block device.
# Stop when our helper function returns success
# $1 = function to call on every found block device
# $2 = block device in major:minor format
2011-03-25 17:56:46 +03:00
check_block_and_slaves( ) {
2011-05-12 13:03:30 +04:00
local _x
2009-08-16 19:29:21 +04:00
[ [ -b /dev/block/$2 ] ] || return 1 # Not a block device? So sorry.
" $1 " $2 && return
2009-08-31 16:58:44 +04:00
check_vol_slaves " $@ " && return 0
2010-08-14 23:23:24 +04:00
if [ [ -f /sys/dev/block/$2 /../dev ] ] ; then
2011-03-25 17:56:46 +03:00
check_block_and_slaves $1 $( cat " /sys/dev/block/ $2 /../dev " ) && return 0
2010-05-19 10:13:12 +04:00
fi
2009-08-16 19:29:21 +04:00
[ [ -d /sys/dev/block/$2 /slaves ] ] || return 1
2011-05-12 13:03:30 +04:00
for _x in /sys/dev/block/$2 /slaves/*/dev; do
[ [ -f $_x ] ] || continue
check_block_and_slaves $1 $( cat " $_x " ) && return 0
2009-08-16 19:29:21 +04:00
done
return 1
}
2009-08-31 16:58:44 +04:00
# ugly workaround for the lvm design
# There is no volume group device,
# so, there are no slave devices for volume groups.
# Logical volumes only have the slave devices they really live on,
# but you cannot create the logical volume without the volume group.
2009-10-29 12:29:58 +03:00
# And the volume group might be bigger than the devices the LV needs.
2009-08-31 16:58:44 +04:00
check_vol_slaves( ) {
2011-05-12 13:03:30 +04:00
local _lv _vg _pv
2011-03-25 17:56:46 +03:00
for i in /dev/mapper/*; do
2012-02-16 14:48:17 +04:00
_lv = $( get_maj_min $i )
2011-05-12 13:03:30 +04:00
if [ [ $_lv = $2 ] ] ; then
_vg = $( lvm lvs --noheadings -o vg_name $i 2>/dev/null)
2010-09-10 17:23:06 +04:00
# strip space
2011-05-12 13:03:30 +04:00
_vg = $( echo $_vg )
if [ [ $_vg ] ] ; then
for _pv in $( lvm vgs --noheadings -o pv_name " $_vg " 2>/dev/null)
2011-03-25 17:56:46 +03:00
do
2012-02-16 14:48:17 +04:00
check_block_and_slaves $1 $( get_maj_min $_pv ) && return 0
2010-09-10 17:23:06 +04:00
done
fi
fi
2009-08-31 16:58:44 +04:00
done
return 1
}
2009-09-27 08:33:41 +04:00
# Install a directory, keeping symlinks as on the original system.
2011-08-27 00:01:33 +04:00
# Example: if /lib points to /lib64 on the host, "inst_dir /lib/file"
2009-09-27 08:33:41 +04:00
# will create ${initdir}/lib64, ${initdir}/lib64/file,
# and a symlink ${initdir}/lib -> lib64.
inst_dir( ) {
2011-10-21 12:09:55 +04:00
[ [ -e ${ initdir } /" $1 " ] ] && return 0 # already there
2011-08-19 12:24:49 +04:00
2011-09-23 19:02:23 +04:00
local _dir = " $1 " _part = " ${ 1 %/* } " _file
2011-10-21 12:09:55 +04:00
while [ [ " $_part " != " ${ _part %/* } " ] ] && ! [ [ -e " ${ initdir } / ${ _part } " ] ] ; do
2011-08-19 12:24:49 +04:00
_dir = " $_part $_dir "
_part = ${ _part %/* }
done
2009-09-27 08:33:41 +04:00
2011-08-19 12:24:49 +04:00
# iterate over parent directories
for _file in $_dir ; do
2012-02-24 00:09:39 +04:00
[ [ -e " ${ initdir } / $_file " ] ] && continue
2011-05-12 13:03:30 +04:00
if [ [ -L $_file ] ] ; then
2011-07-25 12:25:44 +04:00
inst_symlink " $_file "
2009-09-27 08:33:41 +04:00
else
# create directory
2012-02-24 00:09:39 +04:00
mkdir -m 0755 -p " ${ initdir } / $_file " || return 1
[ [ -e " $_file " ] ] && chmod --reference= " $_file " " ${ initdir } / $_file "
chmod u+w " ${ initdir } / $_file "
2009-09-27 08:33:41 +04:00
fi
done
}
2009-02-13 15:42:28 +03:00
# $1 = file to copy to ramdisk
# $2 (optional) Name for the file on the ramdisk
# Location of the image dir is assumed to be $initdir
2009-03-07 06:41:31 +03:00
# We never overwrite the target if it exists.
2009-02-13 15:42:28 +03:00
inst_simple( ) {
2011-10-21 12:09:55 +04:00
[ [ -f " $1 " ] ] || return 1
strstr " $1 " "/" || return 1
2011-08-27 00:01:33 +04:00
local _src = $1 target = " ${ 2 :- $1 } "
2011-10-21 12:09:55 +04:00
if ! [ [ -d ${ initdir } /$target ] ] ; then
[ [ -e ${ initdir } /$target ] ] && return 0
2012-02-22 16:05:23 +04:00
[ [ -L ${ initdir } /$target ] ] && return 0
[ [ -d " ${ initdir } / ${ target %/* } " ] ] || inst_dir " ${ target %/* } "
2009-11-26 12:53:09 +03:00
fi
2011-03-07 15:06:14 +03:00
# install checksum files also
2011-05-12 13:03:30 +04:00
if [ [ -e " ${ _src %/* } /. ${ _src ##*/ } .hmac " ] ] ; then
2011-08-31 17:22:09 +04:00
inst " ${ _src %/* } /. ${ _src ##*/ } .hmac " " ${ target %/* } /. ${ target ##*/ } .hmac "
2011-03-07 15:06:14 +03:00
fi
2011-05-12 13:03:30 +04:00
ddebug " Installing $_src "
2012-01-22 23:02:47 +04:00
cp --sparse= always -pfL " $_src " " ${ initdir } / $target "
2009-02-13 15:42:28 +03:00
}
2010-07-07 18:39:09 +04:00
# find symlinks linked to given library file
# $1 = library file
# Function searches for symlinks by stripping version numbers appended to
# library filename, checks if it points to the same target and finally
# prints the list of symlinks to stdout.
#
# Example:
# rev_lib_symlinks libfoo.so.8.1
# output: libfoo.so.8 libfoo.so
# (Only if libfoo.so.8 and libfoo.so exists on host system.)
rev_lib_symlinks( ) {
[ [ ! $1 ] ] && return 0
local fn = " $1 " orig = " $( readlink -f " $1 " ) " links = ''
[ [ ${ fn } = ~ .*\. so\. .* ] ] || return 1
until [ [ ${ fn ##*. } = = so ] ] ; do
fn = " ${ fn %.* } "
[ [ -L ${ fn } && $( readlink -f " ${ fn } " ) = = ${ orig } ] ] && links += " ${ fn } "
done
2011-03-25 17:56:46 +03:00
echo " ${ links } "
2010-07-07 18:39:09 +04:00
}
2009-10-29 12:29:58 +03:00
# Same as above, but specialized to handle dynamic libraries.
2009-03-07 06:41:31 +03:00
# It handles making symlinks according to how the original library
# is referenced.
2009-02-13 15:42:28 +03:00
inst_library( ) {
2011-10-21 12:09:55 +04:00
local _src = " $1 " _dest = ${ 2 :- $1 } _lib _reallib _symlink
strstr " $1 " "/" || return 1
[ [ -e $initdir /$_dest ] ] && return 0
2011-05-12 13:03:30 +04:00
if [ [ -L $_src ] ] ; then
2011-03-25 17:56:46 +03:00
# install checksum files also
2011-05-12 13:03:30 +04:00
if [ [ -e " ${ _src %/* } /. ${ _src ##*/ } .hmac " ] ] ; then
2011-08-31 17:22:09 +04:00
inst " ${ _src %/* } /. ${ _src ##*/ } .hmac " " ${ _dest %/* } /. ${ _dest ##*/ } .hmac "
2011-02-25 11:59:34 +03:00
fi
2011-05-12 13:03:30 +04:00
_reallib = $( readlink -f " $_src " )
inst_simple " $_reallib " " $_reallib "
inst_dir " ${ _dest %/* } "
2012-02-22 16:06:05 +04:00
[ [ -d " ${ _dest %/* } " ] ] && _dest = $( readlink -f " ${ _dest %/* } " ) /${ _dest ##*/ }
2011-10-21 12:09:55 +04:00
ln -sfn $( convert_abs_rel " ${ _dest } " " ${ _reallib } " ) " ${ initdir } / ${ _dest } "
2009-02-13 15:42:28 +03:00
else
2011-05-12 13:03:30 +04:00
inst_simple " $_src " " $_dest "
2009-02-13 15:42:28 +03:00
fi
2010-07-07 18:39:09 +04:00
# Create additional symlinks. See rev_symlinks description.
2011-05-12 13:03:30 +04:00
for _symlink in $( rev_lib_symlinks $_src ) $( rev_lib_symlinks $_reallib ) ; do
2011-10-21 12:09:55 +04:00
[ [ ! -e $initdir /$_symlink ] ] && {
2011-05-12 13:03:30 +04:00
ddebug " Creating extra symlink: $_symlink "
inst_symlink $_symlink
2010-07-07 18:39:09 +04:00
}
done
2009-02-13 15:42:28 +03:00
}
2009-03-07 06:41:31 +03:00
# find a binary. If we were not passed the full path directly,
# search in the usual places to find the binary.
2009-03-06 22:56:06 +03:00
find_binary( ) {
2011-02-17 12:48:35 +03:00
if [ [ -z ${ 1 ##/* } ] ] ; then
2012-02-24 14:47:17 +04:00
if [ [ -x $1 ] ] || { strstr " $1 " ".so" && ldd $1 & >/dev/null; } ; then
2011-02-17 12:48:35 +03:00
echo $1
return 0
fi
fi
2011-08-12 15:22:17 +04:00
2012-02-07 20:13:07 +04:00
type -P $1
2009-02-13 15:43:09 +03:00
}
2009-02-13 15:42:28 +03:00
2009-03-07 06:41:31 +03:00
# Same as above, but specialized to install binary executables.
# Install binary executable, and all shared library dependencies, if any.
2009-02-13 15:42:28 +03:00
inst_binary( ) {
2012-02-24 15:49:49 +04:00
local _bin _target
2011-05-12 13:03:30 +04:00
_bin = $( find_binary " $1 " ) || return 1
_target = ${ 2 :- $_bin }
2011-10-21 12:09:55 +04:00
[ [ -e $initdir /$_target ] ] && return 0
2012-02-24 15:49:49 +04:00
[ [ -L $_bin ] ] && inst_symlink $_bin $_target && return 0
local _file _line
local _so_regex = '([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
2009-02-13 15:42:20 +03:00
# I love bash!
2012-02-24 15:49:49 +04:00
LC_ALL = C ldd " $_bin " 2>/dev/null | while read _line; do
[ [ $_line = 'not a dynamic executable' ] ] && break
if [ [ $_line = ~ $_so_regex ] ] ; then
_file = ${ BASH_REMATCH [1] }
[ [ -e ${ initdir } /$_file ] ] && continue
inst_library " $_file "
continue
fi
2011-05-12 13:03:30 +04:00
if [ [ $_line = ~ not\ found ] ] ; then
dfatal " Missing a shared library required by $_bin . "
dfatal " Run \"ldd $_bin \" to find out what it is. "
2012-02-24 15:49:49 +04:00
dfatal " $_line "
2011-03-25 17:56:47 +03:00
dfatal "dracut cannot create an initrd."
2010-09-10 17:23:06 +04:00
exit 1
fi
2009-03-09 11:17:41 +03:00
done
2012-02-24 15:49:49 +04:00
inst_simple " $_bin " " $_target "
2009-02-13 15:42:28 +03:00
}
2008-12-18 00:57:43 +03:00
2009-02-13 15:42:28 +03:00
# same as above, except for shell scripts.
# If your shell script does not start with shebang, it is not a shell script.
inst_script( ) {
2011-10-21 12:09:55 +04:00
local _bin
_bin = $( find_binary " $1 " ) || return 1
2011-10-21 14:33:05 +04:00
shift
2011-05-12 13:03:30 +04:00
local _line _shebang_regex
2011-10-21 12:09:55 +04:00
read -r -n 80 _line <" $_bin "
2009-05-20 11:03:01 +04:00
# If debug is set, clean unprintable chars to prevent messing up the term
2011-05-12 13:03:30 +04:00
[ [ $debug ] ] && _line = $( echo -n " $_line " | tr -c -d '[:print:][:space:]' )
_shebang_regex = '(#! *)(/[^ ]+).*'
[ [ $_line = ~ $_shebang_regex ] ] || return 1
2011-11-01 23:13:57 +04:00
inst " ${ BASH_REMATCH [2] } " && inst_simple " $_bin " " $@ "
2008-12-18 00:57:43 +03:00
}
2009-02-13 15:42:28 +03:00
# same as above, but specialized for symlinks
inst_symlink( ) {
2012-02-07 20:15:11 +04:00
local _src = $1 _target = ${ 2 :- $1 } _realsrc
2011-10-21 12:09:55 +04:00
strstr " $1 " "/" || return 1
2009-02-13 15:42:28 +03:00
[ [ -L $1 ] ] || return 1
2012-02-07 20:15:11 +04:00
[ [ -L $initdir /$_target ] ] && return 0
2011-05-12 13:03:30 +04:00
_realsrc = $( readlink -f " $_src " )
2012-02-24 00:09:39 +04:00
if ! [ [ -e $initdir /$_realsrc ] ] ; then
if [ [ -d $_realsrc ] ] ; then
inst_dir " $_realsrc "
else
2012-02-07 20:15:11 +04:00
inst " $_realsrc "
2012-02-24 00:09:39 +04:00
fi
2011-05-20 01:18:47 +04:00
fi
2012-02-24 00:09:39 +04:00
[ [ -d ${ _target %/* } ] ] && _target = $( readlink -f ${ _target %/* } ) /${ _target ##*/ }
ln -sfn $( convert_abs_rel " ${ _target } " " ${ _realsrc } " ) " $initdir / $_target "
2009-02-13 15:42:28 +03:00
}
2011-12-17 04:35:08 +04:00
# attempt to install any programs specified in a udev rule
inst_rule_programs( ) {
local _prog _bin
if grep -qE 'PROGRAM==?"[^ "]+' " $1 " ; then
for _prog in $( grep -E 'PROGRAM==?"[^ "]+' " $1 " | sed -r 's/.*PROGRAM==?"([^ "]+).*/\1/' ) ; do
if [ -x /lib/udev/$_prog ] ; then
_bin = /lib/udev/$_prog
else
_bin = $( find_binary " $_prog " ) || {
dinfo " Skipping program $_prog using in udev rule $( basename $1 ) as it cannot be found "
continue ;
}
fi
#dinfo "Installing $_bin due to it's use in the udev rule $(basename $1)"
dracut_install " $_bin "
done
fi
}
2009-02-13 15:43:26 +03:00
# udev rules always get installed in the same place, so
# create a function to install them to make life simpler.
2011-03-25 17:56:46 +03:00
inst_rules( ) {
2011-05-12 13:03:30 +04:00
local _target = /etc/udev/rules.d _rule _found
2010-07-05 13:25:21 +04:00
2009-09-27 08:33:41 +04:00
inst_dir "/lib/udev/rules.d"
2011-05-12 13:03:30 +04:00
inst_dir " $_target "
for _rule in " $@ " ; do
2011-09-22 18:14:38 +04:00
if [ " ${ rule #/ } " = " $rule " ] ; then
2011-09-22 17:43:34 +04:00
for r in /lib/udev/rules.d /etc/udev/rules.d; do
if [ [ -f $r /$_rule ] ] ; then
_found = " $r / $_rule "
inst_simple " $_found "
2011-12-17 04:35:08 +04:00
inst_rule_programs " $_found "
2011-09-22 17:43:34 +04:00
fi
done
fi
2011-03-25 15:05:05 +03:00
for r in '' ./ $dracutbasedir /rules.d/; do
2011-05-12 13:03:30 +04:00
if [ [ -f ${ r } $_rule ] ] ; then
_found = " ${ r } $_rule "
inst_simple " $_found " " $_target / ${ _found ##*/ } "
2011-12-17 04:35:08 +04:00
inst_rule_programs " $_found "
2011-03-25 15:05:05 +03:00
fi
done
2011-05-12 13:03:30 +04:00
[ [ $_found ] ] || dinfo " Skipping udev rule: $_rule "
2009-02-13 15:43:26 +03:00
done
}
2009-02-13 15:42:28 +03:00
# general purpose installation function
# Same args as above.
2009-02-13 15:42:15 +03:00
inst( ) {
2011-05-12 13:03:30 +04:00
local _x
2009-09-14 21:33:54 +04:00
case $# in
1) ; ;
2010-08-14 23:23:24 +04:00
2) [ [ ! $initdir && -d $2 ] ] && export initdir = $2
2010-09-10 17:23:06 +04:00
[ [ $initdir = $2 ] ] && set $1 ; ;
2011-03-25 17:56:46 +03:00
3) [ [ -z $initdir ] ] && export initdir = $2
2010-09-10 17:23:06 +04:00
set $1 $3 ; ;
2011-03-25 17:56:47 +03:00
*) dfatal "inst only takes 1 or 2 or 3 arguments"
2010-09-10 17:23:06 +04:00
exit 1; ;
2009-09-14 21:33:54 +04:00
esac
2011-05-12 13:03:30 +04:00
for _x in inst_symlink inst_script inst_binary inst_simple; do
$_x " $@ " && return 0
2009-02-13 15:42:28 +03:00
done
return 1
2008-12-18 00:57:43 +03:00
}
2009-02-13 15:43:29 +03:00
# install function specialized for hooks
# $1 = type of hook, $2 = hook priority (lower runs first), $3 = hook
# All hooks should be POSIX/SuS compliant, they will be sourced by init.
inst_hook( ) {
2009-05-23 06:24:31 +04:00
if ! [ [ -f $3 ] ] ; then
2011-03-25 17:56:47 +03:00
dfatal " Cannot install a hook ( $3 ) that does not exist. "
dfatal "Aborting initrd creation."
2010-09-10 17:23:06 +04:00
exit 1
2009-05-23 06:24:31 +04:00
elif ! strstr " $hookdirs " " $1 " ; then
2011-05-10 13:39:10 +04:00
dfatal " No such hook type $1 . Aborting initrd creation. "
2010-09-10 17:23:06 +04:00
exit 1
2009-05-23 06:24:31 +04:00
fi
2011-03-25 15:31:34 +03:00
inst_simple " $3 " " /lib/dracut/hooks/ ${ 1 } / ${ 2 } ${ 3 ##*/ } "
2009-02-13 15:43:29 +03:00
}
2011-08-21 14:47:13 +04:00
# install any of listed files
#
# If first argument is '-d' and second some destination path, first accessible
# source is installed into this path, otherwise it will installed in the same
# path as source. If none of listed files was installed, function return 1.
# On first successful installation it returns with 0 status.
#
# Example:
#
# inst_any -d /bin/foo /bin/bar /bin/baz
#
# Lets assume that /bin/baz exists, so it will be installed as /bin/foo in
# initramfs.
inst_any( ) {
local to f
[ [ $1 = '-d' ] ] && to = " $2 " && shift 2
for f in " $@ " ; do
if [ [ -e $f ] ] ; then
[ [ $to ] ] && inst " $f " " $to " && return 0
inst " $f " && return 0
fi
done
return 1
}
2012-02-16 14:49:19 +04:00
# dracut_install [-o ] <file> [<file> ... ]
# Install <file> to the initramfs image
# -o optionally install the <file> and don't fail, if it is not there
2009-02-13 15:43:24 +03:00
dracut_install( ) {
2011-05-12 13:03:30 +04:00
local _optional = no
2011-03-25 17:56:46 +03:00
if [ [ $1 = '-o' ] ] ; then
2011-05-12 13:03:30 +04:00
_optional = yes
2010-09-10 17:23:06 +04:00
shift
2009-08-15 16:55:59 +04:00
fi
2009-02-13 15:43:24 +03:00
while ( ( $# > 0) ) ; do
2010-09-10 17:23:06 +04:00
if ! inst " $1 " ; then
2011-05-12 13:03:30 +04:00
if [ [ $_optional = yes ] ] ; then
2011-07-22 16:18:23 +04:00
dinfo " Skipping program $1 as it cannot be found and is " \
2011-03-25 17:56:47 +03:00
"flagged to be optional"
2010-09-10 17:23:06 +04:00
else
2011-03-25 17:56:47 +03:00
dfatal " Failed to install $1 "
2010-09-10 17:23:06 +04:00
exit 1
2009-08-15 16:55:59 +04:00
fi
2010-09-10 17:23:06 +04:00
fi
shift
2009-02-13 15:43:24 +03:00
done
}
2010-07-01 23:17:37 +04:00
# install function decompressing the target and handling symlinks
# $@ = list of compressed (gz or bz2) files or symlinks pointing to such files
#
# Function install targets in the same paths inside overlay but decompressed
# and without extensions (.gz, .bz2).
inst_decompress( ) {
2011-05-12 13:03:30 +04:00
local _src _dst _realsrc _realdst _cmd
2010-07-01 23:17:37 +04:00
2011-05-12 13:03:30 +04:00
for _src in $@
2010-07-01 23:17:37 +04:00
do
2011-05-12 13:03:30 +04:00
case ${ _src } in
*.gz) _cmd = 'gzip -d' ; ;
*.bz2) _cmd = 'bzip2 -d' ; ;
2010-07-01 23:17:37 +04:00
*) return 1 ; ;
esac
2011-05-12 13:03:30 +04:00
if [ [ -L ${ _src } ] ]
2010-07-01 23:17:37 +04:00
then
2011-05-12 13:03:30 +04:00
_realsrc = " $( readlink -f ${ _src } ) " # symlink target with extension
_dst = " ${ _src %.* } " # symlink without extension
_realdst = " ${ _realsrc %.* } " # symlink target without extension
mksubdirs " ${ initdir } / ${ _src } "
2010-07-01 23:17:37 +04:00
# Create symlink without extension to target without extension.
2011-05-12 13:03:30 +04:00
ln -sfn " ${ _realdst } " " ${ initdir } / ${ _dst } "
2010-07-01 23:17:37 +04:00
fi
# If the source is symlink we operate on its target.
2011-05-12 13:03:30 +04:00
[ [ ${ _realsrc } ] ] && _src = ${ _realsrc }
inst ${ _src }
2010-07-01 23:17:37 +04:00
# Decompress with chosen tool. We assume that tool changes name e.g.
# from 'name.gz' to 'name'.
2011-05-12 13:03:30 +04:00
${ _cmd } " ${ initdir } ${ _src } "
2010-07-01 23:17:37 +04:00
done
}
# It's similar to above, but if file is not compressed, performs standard
# install.
# $@ = list of files
inst_opt_decompress( ) {
2011-05-12 13:03:30 +04:00
local _src
2010-07-01 23:17:37 +04:00
2011-05-12 13:03:30 +04:00
for _src in $@
2010-07-01 23:17:37 +04:00
do
2011-05-12 13:03:30 +04:00
inst_decompress " ${ _src } " || inst " ${ _src } "
2010-07-01 23:17:37 +04:00
done
}
2012-02-16 14:49:19 +04:00
# module_check <dracut module>
# execute the check() function of module-setup.sh of <dracut module>
# or the "check" script, if module-setup.sh is not found
# "check $hostonly" is called
2011-02-02 15:34:58 +03:00
module_check( ) {
2011-05-12 13:03:30 +04:00
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
2011-08-01 06:01:23 +04:00
local _forced = 0
local _hostonly = $hostonly
[ $# -eq 2 ] && _forced = $2
2011-05-12 13:03:30 +04:00
[ [ -d $_moddir ] ] || return 1
if [ [ ! -f $_moddir /module-setup.sh ] ] ; then
2011-02-02 15:34:58 +03:00
# if we do not have a check script, we are unconditionally included
2011-05-12 13:03:30 +04:00
[ [ -x $_moddir /check ] ] || return 0
2011-08-01 06:01:23 +04:00
[ $_forced -ne 0 ] && unset hostonly
2011-05-12 13:03:30 +04:00
$_moddir /check $hostonly
2011-08-01 06:01:23 +04:00
_ret = $?
2011-02-02 15:34:58 +03:00
else
unset check depends install installkernel
2011-05-12 13:03:30 +04:00
. $_moddir /module-setup.sh
2011-02-02 15:34:58 +03:00
is_func check || return 0
2011-08-01 06:01:23 +04:00
[ $_forced -ne 0 ] && unset hostonly
check $hostonly
2011-05-12 13:03:30 +04:00
_ret = $?
2011-02-02 15:34:58 +03:00
unset check depends install installkernel
2009-05-24 09:29:44 +04:00
fi
2011-08-01 06:01:23 +04:00
hostonly = $_hostonly
return $_ret
2009-05-24 09:29:44 +04:00
}
2012-02-16 14:49:19 +04:00
# module_check_mount <dracut module>
# execute the check() function of module-setup.sh of <dracut module>
# or the "check" script, if module-setup.sh is not found
# "mount_needs=1 check 0" is called
module_check_mount( ) {
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
mount_needs = 1
[ [ -d $_moddir ] ] || return 1
if [ [ ! -f $_moddir /module-setup.sh ] ] ; then
# if we do not have a check script, we are unconditionally included
[ [ -x $_moddir /check ] ] || return 0
mount_needs = 1 $_moddir /check 0
_ret = $?
else
unset check depends install installkernel
. $_moddir /module-setup.sh
is_func check || return 1
check 0
_ret = $?
unset check depends install installkernel
fi
unset mount_needs
return $_ret
}
# module_depends <dracut module>
# execute the depends() function of module-setup.sh of <dracut module>
# or the "depends" script, if module-setup.sh is not found
2011-02-02 15:34:58 +03:00
module_depends( ) {
2011-05-12 13:03:30 +04:00
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
[ [ -d $_moddir ] ] || return 1
if [ [ ! -f $_moddir /module-setup.sh ] ] ; then
2011-02-02 15:34:58 +03:00
# if we do not have a check script, we have no deps
2011-05-12 13:03:30 +04:00
[ [ -x $_moddir /check ] ] || return 0
$_moddir /check -d
2011-02-02 15:34:58 +03:00
return $?
else
unset check depends install installkernel
2011-05-12 13:03:30 +04:00
. $_moddir /module-setup.sh
2011-02-02 15:34:58 +03:00
is_func depends || return 0
depends
2011-05-12 13:03:30 +04:00
_ret = $?
2011-02-02 15:34:58 +03:00
unset check depends install installkernel
2011-05-12 13:03:30 +04:00
return $_ret
2009-07-22 14:43:26 +04:00
fi
2009-05-24 09:29:44 +04:00
}
2012-02-16 14:49:19 +04:00
# module_install <dracut module>
# execute the install() function of module-setup.sh of <dracut module>
# or the "install" script, if module-setup.sh is not found
2011-02-02 15:34:58 +03:00
module_install( ) {
2011-05-12 13:03:30 +04:00
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
[ [ -d $_moddir ] ] || return 1
if [ [ ! -f $_moddir /module-setup.sh ] ] ; then
[ [ -x $_moddir /install ] ] && . " $_moddir /install "
2011-02-02 15:34:58 +03:00
return $?
else
unset check depends install installkernel
2011-05-12 13:03:30 +04:00
. $_moddir /module-setup.sh
2011-02-02 15:34:58 +03:00
is_func install || return 0
install
2011-05-12 13:03:30 +04:00
_ret = $?
2011-02-02 15:34:58 +03:00
unset check depends install installkernel
2011-05-12 13:03:30 +04:00
return $_ret
2011-02-02 15:34:58 +03:00
fi
}
2012-02-16 14:49:19 +04:00
# module_installkernel <dracut module>
# execute the installkernel() function of module-setup.sh of <dracut module>
# or the "installkernel" script, if module-setup.sh is not found
2011-02-02 15:34:58 +03:00
module_installkernel( ) {
2011-05-12 13:03:30 +04:00
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
[ [ -d $_moddir ] ] || return 1
if [ [ ! -f $_moddir /module-setup.sh ] ] ; then
[ [ -x $_moddir /installkernel ] ] && . " $_moddir /installkernel "
2011-02-02 15:34:58 +03:00
return $?
else
unset check depends install installkernel
2011-05-12 13:03:30 +04:00
. $_moddir /module-setup.sh
2011-02-02 15:34:58 +03:00
is_func installkernel || return 0
installkernel
2011-05-12 13:03:30 +04:00
_ret = $?
2011-02-02 15:34:58 +03:00
unset check depends install installkernel
2011-05-12 13:03:30 +04:00
return $_ret
2011-02-02 15:34:58 +03:00
fi
}
2012-02-16 14:49:19 +04:00
# check_mount <dracut module>
# check_mount checks, if a dracut module is needed for the given
# device and filesystem types in "${host_fs_types[@]}"
2011-12-20 10:09:57 +04:00
check_mount( ) {
local _mod = $1
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
local _moddep
# If we are already scheduled to be loaded, no need to check again.
strstr " $mods_to_load " " $_mod " && return 0
strstr " $mods_checked_as_dep " " $_mod " && return 1
# This should never happen, but...
[ [ -d $_moddir ] ] || return 1
[ [ $2 ] ] || mods_checked_as_dep += " $_mod "
strstr " $omit_dracutmodules " " $_mod " && return 1
if [ " ${# host_fs_types [*] } " -gt 0 ] ; then
module_check_mount $_mod || return 1
else
# skip this module
return 1
fi
for _moddep in $( module_depends $_mod ) ; do
# handle deps as if they were manually added
strstr " $add_dracutmodules " " $_moddep " || \
add_dracutmodules += " $_moddep "
strstr " $force_add_dracutmodules " " $_moddep " || \
force_add_dracutmodules += " $_moddep "
# if a module we depend on fail, fail also
check_module $_moddep || return 1
done
strstr " $mods_to_load " " $_mod " || \
mods_to_load += " $_mod "
return 0
}
2012-02-16 14:49:19 +04:00
# check_module <dracut module> [<use_as_dep>]
# check if a dracut module is to be used in the initramfs process
# if <use_as_dep> is set, then the process also keeps track
# that the modules were checked for the dependency tracking process
2011-02-02 15:34:58 +03:00
check_module( ) {
2011-05-12 13:03:30 +04:00
local _mod = $1
local _moddir = $( echo ${ dracutbasedir } /modules.d/??${ 1 } )
local _ret
local _moddep
2011-02-02 15:34:58 +03:00
# If we are already scheduled to be loaded, no need to check again.
2011-05-12 13:03:30 +04:00
strstr " $mods_to_load " " $_mod " && return 0
strstr " $mods_checked_as_dep " " $_mod " && return 1
2011-02-02 15:34:58 +03:00
# This should never happen, but...
2011-05-12 13:03:30 +04:00
[ [ -d $_moddir ] ] || return 1
2011-02-02 15:34:58 +03:00
2011-05-12 13:03:30 +04:00
[ [ $2 ] ] || mods_checked_as_dep += " $_mod "
2011-02-02 15:34:58 +03:00
2011-05-12 13:03:30 +04:00
strstr " $omit_dracutmodules " " $_mod " && return 1
2011-02-02 15:34:58 +03:00
2011-08-01 06:01:23 +04:00
if strstr " $dracutmodules $add_dracutmodules $force_add_dracutmodules " " $_mod " ; then
if strstr " $force_add_dracutmodules " " $_mod " ; then
module_check $_mod 1; ret = $?
else
module_check $_mod 0; ret = $?
fi
2011-02-02 15:34:58 +03:00
# explicit module, so also accept ret=255
[ [ $ret = 0 || $ret = 255 ] ] || return 1
else
# module not in our list
if [ [ $dracutmodules = all ] ] ; then
# check, if we can and should install this module
2011-05-12 13:03:30 +04:00
module_check $_mod || return 1
2010-09-10 17:23:06 +04:00
else
2011-02-02 15:34:58 +03:00
# skip this module
return 1
2009-07-02 13:57:23 +04:00
fi
2011-02-02 15:34:58 +03:00
fi
2010-07-27 13:51:27 +04:00
2011-05-12 13:03:30 +04:00
for _moddep in $( module_depends $_mod ) ; do
2011-02-02 15:34:58 +03:00
# handle deps as if they were manually added
2011-05-12 13:03:30 +04:00
strstr " $add_dracutmodules " " $_moddep " || \
add_dracutmodules += " $_moddep "
2011-08-01 06:01:23 +04:00
strstr " $force_add_dracutmodules " " $_moddep " || \
force_add_dracutmodules += " $_moddep "
2011-02-02 15:34:58 +03:00
# if a module we depend on fail, fail also
2011-05-12 13:03:30 +04:00
check_module $_moddep || return 1
2009-05-24 09:29:44 +04:00
done
2010-05-26 19:42:57 +04:00
2011-05-12 13:03:30 +04:00
strstr " $mods_to_load " " $_mod " || \
mods_to_load += " $_mod "
2011-02-02 15:34:58 +03:00
return 0
}
2012-02-16 14:49:19 +04:00
# for_each_module_dir <func>
# execute "<func> <dracut module> 1"
2011-12-20 10:09:57 +04:00
for_each_module_dir( ) {
2011-05-12 13:03:30 +04:00
local _modcheck
local _mod
local _moddir
2011-12-20 10:09:57 +04:00
local _func
_func = $1
2011-05-12 13:03:30 +04:00
for _moddir in " $dracutbasedir /modules.d " /[ 0-9] [ 0-9] *; do
_mod = ${ _moddir ##*/ } ; _mod = ${ _mod #[0-9][0-9] }
2011-12-20 10:09:57 +04:00
$_func $_mod 1
2010-05-26 19:42:57 +04:00
done
2011-03-07 15:08:13 +03:00
# Report any missing dracut modules, the user has specified
2011-08-01 06:01:23 +04:00
_modcheck = " $add_dracutmodules $force_add_dracutmodules "
2011-05-12 13:03:30 +04:00
[ [ $dracutmodules != all ] ] && _modcheck = " $m $dracutmodules "
for _mod in $_modcheck ; do
strstr " $mods_to_load " " $_mod " && continue
strstr " $omit_dracutmodules " " $_mod " && continue
derror " Dracut module \" $_mod \" cannot be found. "
2011-03-07 15:08:13 +03:00
done
2009-05-24 09:29:44 +04:00
}
2009-08-15 23:17:19 +04:00
# Install a single kernel module along with any firmware it may require.
# $1 = full path to kernel module to install
install_kmod_with_fw( ) {
2011-03-07 15:09:25 +03:00
# no need to go further if the module is already installed
2012-02-25 19:11:36 +04:00
2011-03-25 17:56:46 +03:00
[ [ -e " ${ initdir } /lib/modules/ $kernel / ${ 1 ##*/lib/modules/ $kernel / } " ] ] \
&& return 0
2012-02-15 17:53:18 +04:00
2012-02-25 19:11:36 +04:00
[ [ -e " $initdir /.kernelmodseen/ ${ 1 ##*/ } " ] ] && return 0
2012-02-15 17:53:18 +04:00
if [ [ $omit_drivers ] ] ; then
local _kmod = ${ 1 ##*/ }
_kmod = ${ _kmod %.ko }
_kmod = ${ _kmod /-/_ }
2012-02-22 19:12:10 +04:00
if [ [ " $_kmod " = ~ $omit_drivers ] ] ; then
dinfo " Omitting driver $_kmod "
return 1
fi
if [ [ " ${ 1 ##*/lib/modules/ $kernel / } " = ~ $omit_drivers ] ] ; then
2012-02-15 17:53:18 +04:00
dinfo " Omitting driver $_kmod "
return 1
fi
fi
2012-03-02 15:01:49 +04:00
[ -d " $initdir /.kernelmodseen " ] && \
> " $initdir /.kernelmodseen/ ${ 1 ##*/ } "
2012-03-01 20:45:30 +04:00
2011-03-25 17:56:46 +03:00
inst_simple " $1 " " /lib/modules/ $kernel / ${ 1 ##*/lib/modules/ $kernel / } " \
|| return $?
2011-08-29 00:24:58 +04:00
local _modname = ${ 1 ##*/ } _fwdir _found _fw
_modname = ${ _modname %.ko* }
2011-05-12 13:03:30 +04:00
for _fw in $( modinfo -k $kernel -F firmware $1 2>/dev/null) ; do
_found = ''
for _fwdir in $fw_dir ; do
if [ [ -d $_fwdir && -f $_fwdir /$_fw ] ] ; then
inst_simple " $_fwdir / $_fw " " /lib/firmware/ $_fw "
_found = yes
2010-09-10 17:23:06 +04:00
fi
done
2011-05-12 13:03:30 +04:00
if [ [ $_found != yes ] ] ; then
if ! grep -qe " \< ${ _modname //-/_ } \> " /proc/modules; then
dinfo " Possible missing firmware \" ${ _fw } \" for kernel module " \
" \" ${ _modname } .ko\" "
2011-05-10 13:18:58 +04:00
else
2011-05-12 13:03:30 +04:00
dwarn " Possible missing firmware \" ${ _fw } \" for kernel module " \
" \" ${ _modname } .ko\" "
2011-05-10 13:18:58 +04:00
fi
2010-09-10 17:23:06 +04:00
fi
2009-08-15 23:17:19 +04:00
done
2011-03-07 15:09:25 +03:00
return 0
2009-08-15 23:17:19 +04:00
}
# Do something with all the dependencies of a kernel module.
# Note that kernel modules depend on themselves using the technique we use
2011-03-25 17:56:46 +03:00
# $1 = function to call for each dependency we find
# It will be passed the full path to the found kernel module
2009-08-15 23:17:19 +04:00
# $2 = module to get dependencies for
# rest of args = arguments to modprobe
2011-10-11 01:58:04 +04:00
# _fderr specifies FD passed from surrounding scope
2009-08-15 23:17:19 +04:00
for_each_kmod_dep( ) {
2011-05-12 13:03:30 +04:00
local _func = $1 _kmod = $2 _cmd _modpath _options _found = 0
2009-08-15 23:17:19 +04:00
shift 2
2011-10-11 01:58:04 +04:00
modprobe " $@ " --ignore-install --show-depends $_kmod 2>& ${ _fderr } | (
2011-05-12 13:03:30 +04:00
while read _cmd _modpath _options; do
[ [ $_cmd = insmod ] ] || continue
$_func ${ _modpath } || exit $?
_found = 1
2011-03-25 17:56:46 +03:00
done
2011-05-12 13:03:30 +04:00
[ [ $_found -eq 0 ] ] && exit 1
2011-03-25 17:56:46 +03:00
exit 0
)
2009-08-15 23:17:19 +04:00
}
2011-08-12 12:29:00 +04:00
# filter kernel modules to install certain modules that meet specific
# requirements.
# $1 = search only in subdirectory of /kernel/$1
# $2 = function to call with module name to filter.
# This function will be passed the full path to the module to test.
# The behaviour of this function can vary depending on whether $hostonly is set.
# If it is, we will only look at modules that are already in memory.
# If it is not, we will look at all kernel modules
# This function returns the full filenames of modules that match $1
filter_kernel_modules_by_path ( ) (
local _modname _filtercmd
if ! [ [ $hostonly ] ] ; then
_filtercmd = 'find "$srcmods/kernel/$1" "$srcmods/extra"'
_filtercmd += ' "$srcmods/weak-updates" -name "*.ko" -o -name "*.ko.gz"'
2012-01-22 23:02:47 +04:00
_filtercmd += ' -o -name "*.ko.xz"'
2011-08-12 12:29:00 +04:00
_filtercmd += ' 2>/dev/null'
else
_filtercmd = 'cut -d " " -f 1 </proc/modules|xargs modinfo -F filename '
_filtercmd += '-k $kernel 2>/dev/null'
fi
for _modname in $( eval $_filtercmd ) ; do
case $_modname in
*.ko) " $2 " " $_modname " && echo " $_modname " ; ;
*.ko.gz) gzip -dc " $_modname " > $initdir /$$ .ko
$2 $initdir /$$ .ko && echo " $_modname "
rm -f $initdir /$$ .ko
; ;
2012-01-22 23:02:47 +04:00
*.ko.xz) xz -dc " $_modname " > $initdir /$$ .ko
$2 $initdir /$$ .ko && echo " $_modname "
rm -f $initdir /$$ .ko
; ;
2011-08-12 12:29:00 +04:00
esac
done
)
2011-08-30 00:40:21 +04:00
find_kernel_modules_by_path ( ) (
if ! [ [ $hostonly ] ] ; then
find " $srcmods /kernel/ $1 " " $srcmods /extra " " $srcmods /weak-updates " \
2012-01-22 23:02:47 +04:00
-name "*.ko" -o -name "*.ko.gz" -o -name "*.ko.xz" 2>/dev/null
2011-08-30 00:40:21 +04:00
else
cut -d " " -f 1 </proc/modules \
| xargs modinfo -F filename -k $kernel 2>/dev/null
fi
)
2011-08-12 12:29:00 +04:00
2011-08-28 01:43:49 +04:00
filter_kernel_modules ( ) {
filter_kernel_modules_by_path drivers " $1 "
}
2009-08-21 00:52:45 +04:00
2011-08-30 00:40:21 +04:00
find_kernel_modules ( ) {
find_kernel_modules_by_path drivers
}
2012-02-16 14:49:19 +04:00
# instmods <kernel module> [<kernel module> ... ]
# instmods <kernel subsystem>
2009-08-15 23:17:19 +04:00
# install kernel modules along with all their dependencies.
2012-02-16 14:49:19 +04:00
# <kernel subsystem> can be e.g. "=block" or "=drivers/usb/storage"
2009-02-13 15:42:25 +03:00
instmods( ) {
2009-08-15 19:56:36 +04:00
[ [ $no_kernel = yes ] ] && return
2011-10-11 01:58:04 +04:00
# called [sub]functions inherit _fderr
local _fderr = 9
2011-08-30 00:40:21 +04:00
function inst1mod( ) {
local _mod = " $1 "
2011-05-12 13:03:30 +04:00
case $_mod in
2011-03-25 17:56:46 +03:00
= *)
2012-02-25 19:09:38 +04:00
if [ -f $srcmods /modules.${ _mod #= } ] ; then
2011-08-30 01:46:25 +04:00
( [ [ " $_mpargs " ] ] && echo $_mpargs
cat " ${ srcmods } /modules. ${ _mod #= } " ) \
2011-08-30 00:40:21 +04:00
| instmods
2010-09-10 17:23:06 +04:00
else
2011-08-30 01:46:25 +04:00
( [ [ " $_mpargs " ] ] && echo $_mpargs
2012-02-25 19:10:07 +04:00
find " $srcmods " -path " */ ${ _mod #= } /* " -printf '%f\n' ) \
2011-08-30 00:40:21 +04:00
| instmods
2010-09-10 17:23:06 +04:00
fi
; ;
2011-08-30 01:46:25 +04:00
--*) _mpargs += " $_mod " ; ;
2011-08-30 00:40:21 +04:00
i2o_scsi) return ; ; # Do not load this diagnostic-only module
2012-02-22 19:12:10 +04:00
*)
2012-02-25 19:11:36 +04:00
_mod = ${ _mod ##*/ }
2009-08-28 15:28:19 +04:00
# if we are already installed, skip this module and go on
2010-09-10 17:23:06 +04:00
# to the next one.
2012-02-25 19:11:36 +04:00
[ [ -f " $initdir /.kernelmodseen/ ${ _mod %.ko } .ko " ] ] && return
2011-08-30 00:40:21 +04:00
2012-02-22 19:12:10 +04:00
if [ [ $omit_drivers ] ] && [ [ " $1 " = ~ $omit_drivers ] ] ; then
dinfo " Omitting driver ${ _mod ## $srcmods } "
return
fi
2010-09-10 17:23:06 +04:00
# If we are building a host-specific initramfs and this
# module is not already loaded, move on to the next one.
2011-05-12 13:03:30 +04:00
[ [ $hostonly ] ] && ! grep -qe " \< ${ _mod //-/_ } \> " /proc/modules \
2011-08-30 00:40:21 +04:00
&& ! echo $add_drivers | grep -qe " \< ${ _mod } \> " \
&& return
2008-12-18 00:57:43 +03:00
2010-09-10 17:23:06 +04:00
# We use '-d' option in modprobe only if modules prefix path
# differs from default '/'. This allows us to use Dracut with
# old version of modprobe which doesn't have '-d' option.
2011-08-30 00:40:21 +04:00
local _moddirname = ${ srcmods %%/lib/modules/* }
2011-05-12 13:03:30 +04:00
[ [ -n ${ _moddirname } ] ] && _moddirname = " -d ${ _moddirname } / "
2011-03-25 17:56:46 +03:00
2010-09-10 17:23:06 +04:00
# ok, load the module, all its dependencies, and any firmware
# it may require
2011-05-12 13:03:30 +04:00
for_each_kmod_dep install_kmod_with_fw $_mod \
2011-08-30 01:42:15 +04:00
--set-version $kernel ${ _moddirname } $_mpargs
2011-05-12 13:03:30 +04:00
( ( _ret += $? ) )
2010-09-10 17:23:06 +04:00
; ;
2011-03-25 17:56:46 +03:00
esac
2011-08-30 00:40:21 +04:00
}
2011-08-30 03:03:35 +04:00
function instmods_1( ) {
local _ret = 0 _mod _mpargs
if ( ( $# = = 0) ) ; then # filenames from stdin
while read _mod; do
inst1mod " ${ _mod %.ko* } "
done
fi
while ( ( $# > 0) ) ; do # filenames as arguments
inst1mod ${ 1 %.ko* }
shift
2011-08-30 00:40:21 +04:00
done
2011-08-30 03:03:35 +04:00
return $_ret
}
2012-02-25 19:08:30 +04:00
local _filter_not_found = 'FATAL: Module .* not found.'
2011-10-11 01:58:04 +04:00
# Capture all stderr from modprobe to _fderr. We could use {var}>...
# redirections, but that would make dracut require bash4 at least.
eval " ( instmods_1 \"\$@\" ) ${ _fderr } >&1 " \
2012-02-25 19:08:30 +04:00
| while read line; do [ [ " $line " = ~ $_filter_not_found ] ] || echo $line ; done | derror
2011-08-30 03:03:35 +04:00
return $?
2011-03-25 17:56:46 +03:00
}