~ubuntu-branches/debian/stretch/dkms/stretch

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