#!/bin/sh # # Oracle VM VirtualBox # VirtualBox linux installation script # # Copyright (C) 2007-2022 Oracle and/or its affiliates. # # This file is part of VirtualBox base platform packages, as # available from https://www.virtualbox.org. # # 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, in version 3 of the # License. # # 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 # along with this program; if not, see . # # SPDX-License-Identifier: GPL-3.0-only # set -e # Usage: USAGE_MESSAGE=\ 'Usage: `basename ${0}` [-h|--help| --test [ rpm|dpkg [ ]]] This script tests whether a Linux system is set up to build kernel modules, and if not prints a guess as to which distribution packages need to be installed to do so, and what commands to use. It uses the output of the "uname -r" command to guess the packages and searches for packaging tools by checking for packaging databases. For testing you can specify the output of "uname -r" which will be used instead of the real one and the package type, and optionally the expected output. --test without parameters will test a number of known inputs.' # General theory of operation (valid Nov 19 2016): we check whether this is an # rpm or dpkg system by checking for the respective non-empty database directory # (we assert that only one is present), and based on that we map uname -r output # to a kernel package name. Here is a textual description of known mappings # (not all of these are currently implemented) for both the general package name # and the version-specific package name. Keeping this here as it took some time # and pain to research. # # Debian/Ubuntu (dpkg): - -> linux-headers-, # linux-headers-- DEBIAN_FLAVOURS="generic lowlatency virtual 486 686-pae amd64 rt-686-pae \ rt-amd64 i386 586 grsec-686-pae grsec-amd64 686" # SUSE (rpm): - -> kernel--devel, # kernel--devel- SUSE_FLAVOURS="debug default ec2 pae trace vanilla vmi xen" # OL/RHEL/CentOS (rpm): [.i686|.x86_64] -> kernel--devel, # kernel--devel-<`uname -r`>, where ends in el*. EL_FLAVOURS="uek xen" # Fedora (rpm): -> kernel-devel, kernel-devel-, where # ends in fc*. # # OUTPUT NOT YET TESTED ON REAL SYSTEMS # # Mageia (rpm): -*.mga* -> kernel-linus-latest, # kernel-linus-<`uname -r`> # --*.mga* -> kernel--latest, # kernel--<`uname -r`> MAGEIA_FLAVOURS="desktop desktop586 server tmb-desktop" # PCLinuxOS (dpkg): -pclos* -> kernel-devel, kernel-devel-<`uname -r`> PATH=$PATH:/bin:/sbin:/usr/sbin HAVE_TOOLS= HAVE_HEADERS= PACKAGE_TYPE= UNAME= BASE_PACKAGE= VERSIONED_PACKAGE= TOOLS="gcc make perl" TEST= UNIT_TEST= case "${1}" in "") # Return immediately successfully if everything is installed type ${TOOLS} >/dev/null 2>&1 && HAVE_TOOLS=yes test -d "/lib/modules/`uname -r`/build/include" && HAVE_HEADERS=yes test -n "${HAVE_TOOLS}" && test -n "${HAVE_HEADERS}" && exit 0 UNAME=`uname -r` for i in rpm dpkg; do for j in /var/lib/${i}/*; do test -e "${j}" || break if test -z "${PACKAGE_TYPE}"; then PACKAGE_TYPE="${i}" else PACKAGE_TYPE=unknown fi break done done ;; -h|--help) echo "${USAGE_MESSAGE}" exit 0 ;; *) ERROR="" UNAME="${2}" PACKAGE_TYPE="${3}" BASE_EXPECTED="${4}" VERSIONED_EXPECTED="${5}" test "${1}" = --test || ERROR=yes test -n "${UNAME}" && test -n "${PACKAGE_TYPE}" || test -z "${UNAME}" || ERROR=yes test -n "${BASE_EXPECTED}" && test -n "${VERSIONED_EXPECTED}" || test -z "${BASE_EXPECTED}" || ERROR=yes case "${ERROR}" in ?*) echo "${USAGE_MESSAGE}" >&2 exit 1 esac TEST=yes TEST_PARAMS="${2} ${3} ${4} ${5}" test -z "${UNAME}" && UNIT_TEST=yes ;; esac case "${PACKAGE_TYPE}" in rpm) for i in ${SUSE_FLAVOURS}; do case "${UNAME}" in *-"${i}") BASE_PACKAGE="kernel-${i}-devel" VERSIONED_PACKAGE="kernel-${i}-devel-${UNAME%-${i}}" break esac done for i in ${EL_FLAVOURS} ""; do case "${UNAME}" in *.el5"${i}"|*.el*"${i}".i686|*.el*"${i}".x86_64) test -n "${i}" && i="${i}-" # Hack to handle empty flavour. BASE_PACKAGE="kernel-${i}devel" VERSIONED_PACKAGE="kernel-${i}devel-${UNAME}" break esac done case "${UNAME}" in *.fc*.i686|*.fc*.x86_64) # Fedora BASE_PACKAGE="kernel-devel" VERSIONED_PACKAGE="kernel-devel-${UNAME}" esac for i in ${MAGEIA_FLAVOURS} ""; do # Mageia case "${UNAME}" in *-"${i}"*.mga*) if test -z "${i}"; then BASE_PACKAGE="kernel-linus-devel" VERSIONED_PACKAGE="kernel-linus-devel-${UNAME}" else BASE_PACKAGE="kernel-${i}-devel" VERSIONED_PACKAGE="kernel-${i}-devel-${UNAME%-${i}*}${UNAME#*${i}}" fi break esac done ;; dpkg) for i in ${DEBIAN_FLAVOURS}; do # Debian/Ubuntu case "${UNAME}" in *-${i}) BASE_PACKAGE="linux-headers-${i}" VERSIONED_PACKAGE="linux-headers-${UNAME}" break esac done case "${UNAME}" in *-pclos*) # PCLinuxOS BASE_PACKAGE="kernel-devel" VERSIONED_PACKAGE="kernel-devel-${UNAME}" esac esac case "${UNIT_TEST}${BASE_EXPECTED}" in "") echo "This system is currently not set up to build kernel modules." >&2 test -n "${HAVE_TOOLS}" || echo "Please install the ${TOOLS} packages from your distribution." >&2 test -n "${HAVE_HEADERS}" && exit 1 echo "Please install the Linux kernel \"header\" files matching the current kernel" >&2 echo "for adding new hardware support to the system." >&2 if test -n "${BASE_PACKAGE}${VERSIONED_PACKAGE}"; then echo "The distribution packages containing the headers are probably:" >&2 echo " ${BASE_PACKAGE} ${VERSIONED_PACKAGE}" >&2 fi test -z "${TEST}" && exit 1 exit 0 esac case "${BASE_EXPECTED}" in ?*) case "${BASE_EXPECTED} ${VERSIONED_EXPECTED}" in "${BASE_PACKAGE} ${VERSIONED_PACKAGE}") exit 0 esac echo "Test: ${TEST_PARAMS}" >&2 echo "Result: ${BASE_PACKAGE} ${VERSIONED_PACKAGE}" exit 1 esac # Unit test as of here. # Test expected correct results. for i in \ "4.1.12-37.5.1.el6uek.x86_64 rpm kernel-uek-devel kernel-uek-devel-4.1.12-37.5.1.el6uek.x86_64" \ "2.6.32-642.el6.x86_64 rpm kernel-devel kernel-devel-2.6.32-642.el6.x86_64" \ "4.1.12-vanilla rpm kernel-vanilla-devel kernel-vanilla-devel-4.1.12" \ "4.8.8-pclos1 dpkg kernel-devel kernel-devel-4.8.8-pclos1" \ "4.8.8-desktop-1.mga6 rpm kernel-desktop-devel kernel-desktop-devel-4.8.8-1.mga6" \ "3.19.8-2.mga5 rpm kernel-linus-devel kernel-linus-devel-3.19.8-2.mga5" \ "4.8.0-27-generic dpkg linux-headers-generic linux-headers-4.8.0-27-generic" do "${0}" --test ${i} || exit 1 done # Test argument combinations expected to fail. for i in \ "--test NOT_EMPTY" \ "--test NOT_EMPTY NOT_EMPTY NOT_EMPTY" \ "--wrong" \ "--test 4.8.8-pclos1 dpkg kernel-devel kernel-devel-WRONG" \ "--test 4.8.8-pclos1 dpkg kernel-WRONG kernel-devel-4.8.8-pclos1" do "${0}" ${i} >/dev/null 2>&1 && echo "Bad argument test failed:" && echo " ${i}" && exit 1 done exit 0