1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
#!/bin/sh
#
# dkms_autoinstaller A service to automatically install DKMS modules
# for new kernels.
# chkconfig: 345 04 04
# description: An autoinstaller bootup service for DKMS
#
### BEGIN INIT INFO
# Provides: dkms_autoinstaller dkms
# Default-Start: 2 3 4 5
# Default-Stop:
# Required-Start: $local_fs
# Required-Stop: $null
# Short-Description: Automatically install DKMS modules for new kernels
# Description: A service to automatically install DKMS modules for new kernels.
### END INIT INFO
test -f /usr/sbin/dkms || exit 0
#We only have these functions on debian/ubuntu
# so on other distros just stub them out
if [ -f /lib/lsb/init-functions ]; then
. /lib/lsb/init-functions
if [ ! -f /etc/debian_version ]; then
alias log_daemon_msg=echo
log_end_msg() { if [ "$1" = "0" ]; then echo " Done. "; else echo " Failed. "; fi }
alias log_action_begin_msg=log_daemon_msg
alias log_action_end_msg=log_end_msg
fi
fi
invoke_command ()
{
local exitval=0
local exitval_file=`mktemp /tmp/dkms.XXXXXX`
if [ "$3" = background ] && [ -z "$verbose" ]; then
(eval $1 >/dev/null 2>&1; echo "exitval=$?" >> "$exitval_file") &
while [ -e "$exitval_file" ] && ! [ -s "$exitval_file" ]; do
sleep 3
done
. "$exitval_file"
else
eval $1; exitval=$?
fi
[ $exitval -gt 0 ] && logger -t dkms_autoinstaller "(bad exit status: $exitval)"
rm -f "$exitval_file"
return $exitval
}
emit_module_status ()
{
#$1 is the signal to emit (successful|failed)
#$2 is the module name in question
if [ -x /sbin/initctl ]; then
initctl emit build-$1 MODULE=$2 2>/dev/null
fi
}
# Set Variables
uname=`uname -mr`
[ -n "$2" ] && kernel=$2 || kernel=${uname% *}
arch=${uname#* }
kernel_preparation_done=""
dkms_tree="/var/lib/dkms"
. /etc/dkms/framework.conf 2>/dev/null
# See how we were called.
case "$1" in
start)
log_daemon_msg "Running DKMS auto installation service for kernel $kernel"
# Iterate over the modules
for modulepath in $(find "$dkms_tree" -maxdepth 1 -mindepth 1 -type d); do
module_in_tree=${modulepath##*/}
# Determine which versions to show status for
do_autoinstall=""
version_count=0
already_installed=""
already_installed_version=""
for versioned_path in $(find "$modulepath" -maxdepth 1 -mindepth 1 -type d -a -not -name original_module); do
version_count=$(($version_count + 1))
version_in_tree="${versioned_path##*/}"
if [ -f $versioned_path/source/dkms.conf ]; then
do_autoinstall=$(sed -n -e 's/^\(str *\)\?AUTOINSTALL=\(.*\)$/\2/gp;' $versioned_path/source/dkms.conf)
else
current_state="broken"
continue
fi
# Get the current state
# a mod can be both built and installed-weak (stupid, but could be)
# but installed-weak comes last, so use tail
current_state=`dkms status -m $module_in_tree -v $version_in_tree -k $kernel -a $arch 2>/dev/null | awk {'print $5'} | tail -n 1`
[ "$current_state" = "installed" -o "$current_state" = "installed-weak" ] && already_installed="true" && already_installed_version=$version_in_tree
done
log_action_begin_msg " $module_in_tree ($version_in_tree)"
# Based on what we know, either do it or not
if [ "$current_state" = "broken" ]; then
logger -t dkms_autoinstaller "$module_in_tree ($version_in_tree): Unable to locate $versioned_path/source/dkms.conf"
logger -t dkms_autoinstaller " DKMS tree must be manually fixed"
log_action_end_msg 1
continue
elif [ -n "$already_installed" ]; then
emit_module_status successful $module_in_tree
log_action_end_msg 0
elif [ -z "$do_autoinstall" ]; then
logger -t dkms_autoinstaller "$module_in_tree ($version_in_tree): AUTOINSTALL not set in its dkms.conf."
log_action_end_msg 0
elif [ -n "$do_autoinstall" ] && [ "$version_count" -gt 1 ]; then
logger -t dkms_autoinstaller "$module_in_tree: Multiple versions in DKMS. Unsure what to do. Resolve manually."
emit_module_status failed $module_in_tree
log_action_end_msg 1
else
logger -t dkms_autoinstaller "$module_in_tree ($version_in_tree): Installing module on kernel $kernel."
if [ "$current_state" != "built" ] && ! [ -e /lib/modules/$kernel/build/include ]; then
logger -t dkms_autoinstaller " Kernel headers for $kernel are not installed. Cannot install this module."
logger -t dkms_autoinstaller " Try installing linux-headers-$kernel or equivalent."
log_action_end_msg 1
elif [ "$current_state" != "built" ] && [ -e /lib/modules/$kernel/build/include ]; then
return_status=""
if [ -z "$kernel_preparation_done" ]; then
invoke_command "dkms build -m $module_in_tree -v $version_in_tree -k $kernel -a $arch -q --no-clean-kernel" "." background
return_status="$?"
kernel_preparation_done="true"
else
invoke_command "dkms build -m $module_in_tree -v $version_in_tree -k $kernel -a $arch --no-prepare-kernel --no-clean-kernel -q" "." background
return_status="$?"
fi
if [ "$return_status" -eq 0 ]; then
invoke_command "dkms install -m $module_in_tree -v $version_in_tree -k $kernel -a $arch" "." background
emit_module_status successful $module_in_tree
log_action_end_msg 0
else
logger -t dkms_autoinstaller " Build failed. Installation skipped."
emit_module_status failed $module_in_tree
log_action_end_msg 1
fi
else
invoke_command "dkms install -m $module_in_tree -v $version_in_tree -k $kernel -a $arch -q" "." background
return_status=$?
if [ "$return_status" -eq 0 ]; then
emit_module_status successful $module_in_tree
elif [ "$return_status" -eq 101 ]; then
logger -t dkms_autoinstaller " A newer module version than this already exists in kernel."
logger -t dkms_autoinstaller " Skipping install... (you can manually install later with --force)"
emit_module_status successful $module_in_tree
elif [ "$return_status" -ne 0 ]; then
logger -t dkms_autoinstaller " Installation failed!"
emit_module_status failed $module_in_tree
fi
fi
fi
done
if [ -z "$modules_needing_status" ]; then
log_end_msg 0
fi
;;
stop|restart|force-reload|status|reload)
# ignore
;;
*)
echo "Usage: $0 {start}"
esac
exit 0
|