summaryrefslogtreecommitdiffstats
path: root/dkms_common.postinst.in
blob: fe5d0379d57054a0aa47034c3894ff332ea1422b (plain)
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#!/bin/sh
# Copyright (C) 2002-2005 Flavio Stanchina
# Copyright (C) 2005-2006 Aric Cyr
# Copyright (C) 2007 Mario Limonciello
# Copyright (C) 2009 Alberto Milone

set -e

uname_s=$(uname -s)

_get_kernel_dir() {
    KVER=$1
    case ${uname_s} in
	Linux)		DIR="@MODDIR@/$KVER/build" ;;
	GNU/kFreeBSD)	DIR="/usr/src/kfreebsd-headers-$KVER/sys" ;;
    esac
    echo $DIR
}

_check_kernel_dir() {
    DIR=$(_get_kernel_dir $1)
    case ${uname_s} in
	Linux)		test -e $DIR/include ;;
	GNU/kFreeBSD)	test -e $DIR/kern && test -e $DIR/conf/kmod.mk ;;
	*)		return 1 ;;
    esac
    return $?
}

# Check the existence of a kernel named as $1
_is_kernel_name_correct() {
    if [ -e "@MODDIR@/$1" ]; then
        echo yes
    else
        echo no
    fi
}


# Get the most recent kernel on Debian based systems. This keeps
# into account both the version and the ABI. If the current kernel
# is the most recent kernel then the function will print a null string.
_get_newest_kernel_debian() {
    NEWEST_KERNEL=
    NEWEST_VERSION=
    NEWEST_ABI=

    for kernel in /boot/config-*; do
        [ -f "$kernel" ] || continue
        KERNEL=${kernel#*-}
        KERNEL_VERSION=${KERNEL%%-*}
        ABI=${KERNEL#*-}
        ABI=${ABI%%-*}

        if [ -z "$NEWEST_KERNEL" ]; then
            # The 1st time get a version which is bigger than $1
            COMPARE_TO=$1
        else
            # Get the biggest version
            COMPARE_TO="$NEWEST_VERSION-$NEWEST_ABI"
        fi

        # if $kernel is greater than $COMPARE_TO
        if [ $(dpkg --compare-versions "$KERNEL_VERSION-$ABI" ge "$COMPARE_TO" && echo "yes" || \
              echo "no") = "yes" ]; then
            NEWEST_KERNEL=$KERNEL
            NEWEST_VERSION=$KERNEL_VERSION
            NEWEST_ABI=$ABI
        fi
    done

    echo "$NEWEST_KERNEL"
}

# Get the most recent kernel in Rhel based systems.
_get_newest_kernel_rhel() {
    rpm -q --qf="%{VERSION}-%{RELEASE}.%{ARCH}\n" --whatprovides kernel | tail -n 1
}

# Get the newest kernel on Debian and Rhel based systems.
get_newest_kernel() {
    NEWEST_KERNEL=
    # Try Debian first as rpm can be installed in Debian based distros
    if [ -e /usr/bin/dpkg ]; then
        # If DEB based
        CURRENT_VERSION=${CURRENT_KERNEL%%-*}
        CURRENT_ABI=${CURRENT_KERNEL#*-}
        CURRENT_FLAVOUR=${CURRENT_ABI#*-}
        CURRENT_ABI=${CURRENT_ABI%%-*}
        NEWEST_KERNEL=$(_get_newest_kernel_debian "$CURRENT_VERSION-$CURRENT_ABI")

    elif which rpm >>/dev/null 2>&1; then
        # If RPM based
        NEWEST_KERNEL=$(_get_newest_kernel_rhel)
    fi

    # Make sure that kernel name that we extracted corresponds to an installed
    # kernel
    if [ -n "$NEWEST_KERNEL" ] && [ $(_is_kernel_name_correct $NEWEST_KERNEL) = "no" ]; then
        NEWEST_KERNEL=
    fi

    echo $NEWEST_KERNEL
}

NAME=$1
VERSION=$2
TARBALL_ROOT=$3
ARCH=$4
UPGRADE=$5

if [ -z "$NAME" ] || [ -z "$VERSION" ]; then
    echo "Need NAME, and VERSION defined"
    echo "ARCH is optional"
    exit 1
fi

if [ -f /etc/dkms/no-autoinstall ]; then
    echo "autoinstall for dkms modules has been disabled."
    exit 0
fi

# read framework configuration options
if [ -r /etc/dkms/framework.conf ]; then
    . /etc/dkms/framework.conf
fi

KERNELS=$(ls -dv @MODDIR@/*/build 2>/dev/null | cut -d/ -f4 || true)
CURRENT_KERNEL=$(uname -r)

#We never want to keep an older version side by side to prevent conflicts
if [ -e "/var/lib/dkms/$NAME/$VERSION" ]; then
    echo "Removing old $NAME-$VERSION DKMS files..."
    dkms remove -m $NAME -v $VERSION --all
fi

#Load new files, by source package and by tarball
if [ -f "$TARBALL_ROOT/$NAME-$VERSION.dkms.tar.gz" ]; then
    if ! dkms ldtarball --archive "$TARBALL_ROOT/$NAME-$VERSION.dkms.tar.gz"; then
        echo ""
        echo ""
        echo "Unable to load DKMS tarball $TARBALL_ROOT/$NAME-$VERSION.dkms.tar.gz."
        echo "Common causes include: "
        echo " - You must be using DKMS 2.1.0.0 or later to support binaries only"
        echo "   distribution specific archives."
        echo " - Corrupt distribution specific archive"
        echo ""
        echo ""
        exit 2
    fi
elif [ -d "/usr/src/$NAME-$VERSION" ]; then
    echo "Loading new $NAME-$VERSION DKMS files..."
    dkms add -m $NAME -v $VERSION > /dev/null
fi

dkms_conf="/var/lib/dkms/$NAME/$VERSION/source/dkms.conf"
autoinstall=$(bash -c 'AUTOINSTALL=; . "'"$dkms_conf"'" >/dev/null 2>&1; echo $AUTOINSTALL')
if [ -z "$autoinstall" ]; then
    echo "Not building the $NAME module which does not have AUTOINSTALL enabled."
    exit 0
fi

# On 1st installation, let us look for a directory
# in @MODDIR@ which matches $(uname -r). If none
# is found it is possible that buildd is being used
# and that uname -r is giving us the name of the
# kernel used by the buildd machine.
#
# If this is the case we try to build the kernel
# module for each kernel which has a directory in
# @MODDIR@. Furthermore we will have to tell
# DKMS which architecture it should build the module
# for (e.g. if the buildd machine is using a
# 2.6.24-23-xen 64bit kernel).
#
# NOTE: if the headers are not installed then the
#       module won't be built, as usual

# Here we look for the most recent kernel so that we can
# build the module for it (in addition to doing it for the
# current kernel.
NEWEST_KERNEL=$(get_newest_kernel)

if [ -z "$autoinstall_all_kernels" ]; then
    # If the current kernel is installed on the system or chroot
    if [ $(_is_kernel_name_correct $CURRENT_KERNEL) = "yes" ]; then
        if [ -n "$NEWEST_KERNEL" ] && [ ${CURRENT_KERNEL} != ${NEWEST_KERNEL} ]; then
            KERNELS="$CURRENT_KERNEL $NEWEST_KERNEL"
        else
            KERNELS=$CURRENT_KERNEL
        fi
    # The current kernel is not useful as it's not installed
    else
        echo "It is likely that $CURRENT_KERNEL belongs to a chroot's host"

        # Let's use only the newest kernel if this is not a first installation
        # otherwise build for all kernels
        if [ -n "$NEWEST_KERNEL" -a -n "$UPGRADE" ]; then
            KERNELS="$NEWEST_KERNEL"
        fi
    fi
fi

# Take care of displaying newline separated list
echo "Building for $KERNELS" | tr '\n' ',' \
    | sed -e 's/,/, /g; s/, $/\n/; s/, \([^,]\+\)$/ and \1/'

if [ -n "$ARCH" ]; then
    echo "Building for architecture $ARCH"
    ARCH="-a $ARCH"
fi

for KERNEL in $KERNELS; do
    dkms_status=$(dkms status -m $NAME -v $VERSION -k $KERNEL $ARCH)
    if [ $(echo $KERNEL | grep -c "BOOT") -gt 0 ]; then
        echo ""
        echo "Module build and install for $KERNEL was skipped as "
        echo "it is a BOOT variant"
        continue
    fi


    #if the module isn't yet built, try to build it
    if [ $(echo $dkms_status | grep -c ": built") -eq 0 ]; then
        if [ ! -L /var/lib/dkms/$NAME/$VERSION/source ]; then
            echo "This package appears to be a binaries-only package"
            echo " you will not be able to build against kernel $KERNEL"
            echo " since the package source was not provided"
            continue
        fi
        if _check_kernel_dir $KERNEL; then
            echo "Building initial module for $KERNEL"
            set +e
            dkms build -m $NAME -v $VERSION -k $KERNEL $ARCH > /dev/null
            case $? in
            77)
                set -e
                echo "Skipped."
                continue
                ;;
            0)
                set -e
                echo "Done."
                ;;
            *)
                exit $?
                ;;
            esac
            dkms_status=$(dkms status -m $NAME -v $VERSION -k $KERNEL $ARCH)
        else
            echo "Module build for kernel $KERNEL was skipped since the"
            echo "kernel headers for this kernel do not seem to be installed."
        fi
    fi

    #if the module is built (either pre-built or just now), install it
    if [ $(echo $dkms_status | grep -c ": built") -eq 1 ] &&
       [ $(echo $dkms_status | grep -c ": installed") -eq 0 ]; then
        dkms install -m $NAME -v $VERSION -k $KERNEL $ARCH
    fi
done