diff options
Diffstat (limited to 'src/VBox/Additions/linux/installer/install.sh.in')
-rwxr-xr-x | src/VBox/Additions/linux/installer/install.sh.in | 641 |
1 files changed, 641 insertions, 0 deletions
diff --git a/src/VBox/Additions/linux/installer/install.sh.in b/src/VBox/Additions/linux/installer/install.sh.in new file mode 100755 index 00000000..00097cf3 --- /dev/null +++ b/src/VBox/Additions/linux/installer/install.sh.in @@ -0,0 +1,641 @@ +#!/bin/sh +# +# Oracle VM VirtualBox +# VirtualBox Makeself installation starter script +# for Linux Guest Additions + +# +# Copyright (C) 2006-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 <https://www.gnu.org/licenses>. +# +# SPDX-License-Identifier: GPL-3.0-only +# + +# Testing: +# * After successful installation, 0 is returned if the vboxguest module version +# built matches the one loaded and 2 is returned otherwise. E.g. VBoxClient +# running will prevent vboxguest reloading. +# * If the kernel modules cannot be built (run the installer with KERN_VER=none) +# or loaded (run with KERN_VER=<installed non-current version>) then 1 is +# returned. + +PATH=$PATH:/bin:/sbin:/usr/sbin + +# Note: These variable names must *not* clash with variables in $CONFIG_DIR/$CONFIG! +PACKAGE="VBoxGuestAdditions" +PACKAGE_NAME="VirtualBox Guest Additions" +UNINSTALL="uninstall.sh" +PUBLIC_UNINSTALL_HOOK="/usr/sbin/vbox-uninstall-guest-additions" +ROUTINES="routines.sh" +INSTALLATION_VER="_VERSION_" +BUILD_VBOX_KBUILD_TYPE="_BUILDTYPE_" +BUILD_USERNAME="_USERNAME_" +UNINSTALL_SCRIPTS="vboxadd-x11 vboxvfs vboxadd-timesync vboxadd-service vboxadd" + +INSTALLATION_DIR="/opt/$PACKAGE-$INSTALLATION_VER" +CONFIG_DIR="/var/lib/$PACKAGE" +CONFIG="config" +CONFIG_FILES="filelist" +SELF=$1 +LOGFILE="/var/log/vboxadd-install.log" + +## Were we able to stop any previously running Additions kernel modules? +MODULES_STOPPED=1 + +. "./$ROUTINES" + +check_root + +check_deps bzip2 tar + +create_log "$LOGFILE" + +usage() +{ + catinfo << EOF + +Usage: $SELF install [<installation directory>] + [--with-<module>] + [--package-base <base> | + uninstall + [--force] [--no-setup] + +Options: + --package-base <base> For use when building distribution packages. + Installs relative to <base> instead of to "/", + does not run setup, installs to "<base>/usr/lib" + instead of to "/opt" and does not create uninstall. + --force Forces an upgrade. Not recommended. + +Example: +$SELF install +EOF + exit 1 +} + +# Create a symlink in the filesystem and add it to the list of package files +add_symlink() +{ + self=add_symlink + ## Parameters: + # The file the link should point to + target="$1" + # The name of the actual symlink file. Must be an absolute path to a + # non-existing file in an existing directory. + link="$2" + link_dir="`dirname "$link"`" + test -n "$target" || + { echo 1>&2 "$self: no target specified"; return 1; } + test -d "$link_dir" || + { echo 1>&2 "$self: link directory $link_dir does not exist"; return 1; } + expr "$link" : "/.*" > /dev/null || + { echo 1>&2 "$self: link file name is not absolute"; return 1; } + rm -f "$link" + ln -s "$target" "$link" + echo "$link" >> "$CONFIG_DIR/$CONFIG_FILES" +} + +# Create symbolic links targeting all files in a directory in another +# directory in the filesystem +link_into_fs() +{ + ## Parameters: + # Directory containing the link target files + target_branch="$1" + # Directory to create the link files in + directory="$2" + for i in "$INSTALLATION_DIR/$target_branch"/*; do + test -e "$i" && + add_symlink "$i" "$directory/`basename $i`" + done +} + +# Look for broken installations or installations without a known uninstaller +# and try to clean them up, asking the user first. +def_uninstall() +{ + ## Parameters: + # Whether to force cleanup without asking the user + force="$1" + + . ./deffiles + found=0 + for i in "/opt/$PACKAGE-"*; do + test -e "$i" && found=1 + done + for i in $DEFAULT_FILE_NAMES; do + test "$found" = 0 && test -e "$i" && found=1 + done + test "$found" = 0 && + for i in $DEFAULT_VERSIONED_FILE_NAMES; do + for j in $i-*; do + test "$found" = 0 && test -e "$j" && found=1 + done + done + test "$found" = 0 && return 0 + if ! test "$1" = "force" ; then + # Try to make the promised notification appear on next start. + VBoxControl guestproperty delete \ + /VirtualBox/GuestAdd/HostVerLastChecked 2>&1 > /dev/null + cat 1>&2 << EOF +This system appears to have a version of the VirtualBox Guest Additions +already installed. If it is part of the operating system and kept up-to-date, +there is most likely no need to replace it. If it is not up-to-date, you +should get a notification when you start the system. If you wish to replace +it with this version, please do not continue with this installation now, but +instead remove the current version first, following the instructions for the +operating system. + +If your system simply has the remains of a version of the Additions you could +not remove you should probably continue now, and these will be removed during +installation. + +Do you wish to continue? [yes or no] +EOF + read reply dummy + if ! expr "$reply" : [yY] > /dev/null && + ! expr "$reply" : [yY][eE][sS] > /dev/null + then + info + info "Cancelling installation." + return 1 + fi + fi + # Inhibit rebuilding of any installed kernels. + for i in /lib/modules/*; do + ver="${i##*/}" + test ! -d "$i"/build || touch /var/lib/VBoxGuestAdditions/skip-"$ver" + done + # Stop what we can in the way of services and remove them from the + # system + for i in $UNINSTALL_SCRIPTS; do + stop_init_script "$i" 2>> "${LOGFILE}" + test -z "$NO_CLEANUP" && test -x "./$i" && "./$i" cleanup 1>&2 2>> "$LOGFILE" + delrunlevel "$i" 2>> "${LOGFILE}" + remove_init_script "$i" 2>> "${LOGFILE}" + done + for i in "/opt/$PACKAGE-"*/init; do + for j in $UNINSTALL_SCRIPTS; do + script="${i}/${j}" + test -x "${script}" && test -z "$NO_CLEANUP" && + grep -q '^# *cleanup_script *$' "${script}" && + "${script}" cleanup 1>&2 2>> "$LOGFILE" + done + done + + # Get rid of any remaining files + for i in $DEFAULT_FILE_NAMES; do + rm -f "$i" 2> /dev/null + done + for i in $DEFAULT_VERSIONED_FILE_NAMES; do + rm -f "$i-"* 2> /dev/null + done + rm -f "/usr/lib/$PACKAGE" "/usr/lib64/$PACKAGE" "/usr/share/$PACKAGE" \ + "/usr/lib/i386-linux-gnu/$PACKAGE" "/usr/lib/x86_64-linux-gnu/$PACKAGE" + + # And any packages left under /opt + for i in "/opt/$PACKAGE-"*; do + test -d "$i" && rm -rf "$i" + done + return 0 +} + +info "$PACKAGE_NAME installer" + +# Sensible default actions +ACTION="install" +NO_CLEANUP="" +FORCE_UPGRADE="" +PACKAGE_BASE="" + +while [ $# -ge 2 ]; +do + ARG=$2 + shift + + if [ -z "$MY_END_OF_OPTIONS" ]; then + case "$ARG" in + + install) + ACTION="install" + ;; + + uninstall) + ACTION="uninstall" + ;; + + package) + ACTION="package" + INSTALLATION_DIR=/usr/lib + PACKAGE_BASE="$2" + shift + if test ! -d "${PACKAGE_BASE}"; then + info "Package base directory not found." + usage + fi + ;; + + ## @todo Add per-module options handling, e.g. --lightdm-greeter-dir + # or --lightdm-config + + ## @todo Add listing all available modules (+ their options, e.g. + # with callback mod_mymod_show_options?) + + --with-*) + MODULE_CUR=`expr "$ARG" : '--with-\(.*\)'` + # Check if corresponding module in installer/module-$1 exists. + # Note: Module names may not contain spaces or other funny things. + if [ ! -f "./installer/module-${MODULE_CUR}" ]; then + info "Error: Module \"${MODULE_CUR}\" does not exist." + usage + fi + # Give the module the chance of doing initialization work / checks. + . "./installer/module-${MODULE_CUR}" + mod_${MODULE_CUR}_init + if test $? -ne 0; then + echo 1>&2 "Module '${MODULE_CUR}' failed to initialize" + if ! test "$FORCE_UPGRADE" = "force"; then + return 1 + fi + # Continue initialization. + fi + # Add module to the list of modules to handle later. + if test -z "${INSTALLATION_MODULES_LIST}"; then + INSTALLATION_MODULES_LIST="${MODULE_CUR}" + else + INSTALLATION_MODULES_LIST="${INSTALLATION_MODULES_LIST} ${MODULE_CUR}" + fi + shift + ;; + + --force|force) # Keep "force" for backwards compatibility. + FORCE_UPGRADE="force" + ;; + + --no-setup|no_setup) + # Deprecated; keep this setting for backwards compatibility. + ;; + + --no-cleanup|no_cleanup) # Keep "no_cleanup" for backwards compatibility. + # Do not do cleanup of old modules when removing them. For + # testing purposes only. + NO_CLEANUP="no_cleanup" + ;; + + --) + MY_END_OF_OPTIONS="1" + ;; + + *) + if [ "`echo $1|cut -c1`" != "/" ]; then + info "Please specify an absolute path" + usage + fi + INSTALLATION_DIR="$1" + shift + ;; + esac + fi +done + +# Check architecture +cpu=`uname -m`; +case "$cpu" in + i[3456789]86|x86) + cpu="x86" + lib_candidates="/usr/lib/i386-linux-gnu /usr/lib /lib" + ;; + x86_64|amd64) + cpu="amd64" + lib_candidates="/usr/lib/x86_64-linux-gnu /usr/lib64 /usr/lib /lib64 /lib" + ;; + *) + cpu="unknown" +esac +ARCH_PACKAGE="$PACKAGE-$cpu.tar.bz2" +if [ ! -r "$ARCH_PACKAGE" ]; then + info "Detected unsupported $cpu machine type." + exit 1 +fi +# Find the most appropriate libary folder by seeing which of the candidate paths +# are actually in the shared linker path list and choosing the first. We look +# for Debian-specific paths first, then LSB ones, then the new RedHat ones. +libs=`ldconfig -v 2>/dev/null | grep -v ^$'\t'` +for i in $lib_candidates; do + if echo $libs | grep -q $i; then + lib_path=$i + break + fi +done +if [ ! -x "$lib_path" ]; then + info "Unable to determine correct library path." + exit 1 +fi + +# uninstall any previous installation +# If the currently installed Additions have provided an uninstallation hook, try +# that first. +if test -x "${PUBLIC_UNINSTALL_HOOK}"; then + "${PUBLIC_UNINSTALL_HOOK}" 1>&2 || + abort "Failed to remove existing installation. Aborting..." +fi + +INSTALL_DIR="" +uninstalled=0 +test -r "$CONFIG_DIR/$CONFIG" && . "$CONFIG_DIR/$CONFIG" +if test -n "$INSTALL_DIR" && test -n "$UNINSTALLER" && + test -x "$INSTALL_DIR/$UNINSTALLER"; then + "$INSTALL_DIR/$UNINSTALLER" $NO_CLEANUP 1>&2 || + abort "Failed to remove existing installation. Aborting..." + uninstalled=1 +fi +test "$uninstalled" = 0 && def_uninstall "$FORCE_UPGRADE" && uninstalled=1 +test "$uninstalled" = 0 && exit 1 +rm -f "$CONFIG_DIR/$CONFIG" +rm -f "$CONFIG_DIR/$CONFIG_FILES" +rmdir "$CONFIG_DIR" 2>/dev/null || true +test "$ACTION" = "install" || exit 0 + +# Now check whether the kernel modules were stopped. +lsmod | grep -q vboxguest && MODULES_STOPPED= + +# Choose a proper umask +umask 022 + +# Set installer modules directory +INSTALLATION_MODULES_DIR="$INSTALLATION_DIR/installer/" + +# install the new version +mkdir -p -m 755 "$CONFIG_DIR" +test ! -d "$INSTALLATION_DIR" && REMOVE_INSTALLATION_DIR=1 +mkdir -p -m 755 "$INSTALLATION_DIR" + +# install and load installer modules +if [ -d installer ]; then + info "Copying additional installer modules ..." + mkdir -p -m 755 "$INSTALLATION_MODULES_DIR" + for CUR_FILE in `ls installer/*`; do + install -p -m 755 "$CUR_FILE" "$INSTALLATION_MODULES_DIR" + if [ $? -ne 0 ]; then + info "Error: Failed to copy installer module \"$CUR_FILE\"" + if ! test "$FORCE_UPGRADE" = "force"; then + exit 1 + fi + fi + done +fi + +# Create a list of the files in the archive, skipping any directories which +# already exist in the filesystem. +bzip2 -d -c "$ARCH_PACKAGE" | tar -tf - | + while read name; do + fullname="$INSTALLATION_DIR/$name" + case "$fullname" in + */) + test ! -d "$fullname" && + echo "$fullname" >> "$CONFIG_DIR/$CONFIG_FILES" + ;; + *) + echo "$fullname" >> "$CONFIG_DIR/$CONFIG_FILES" + ;; + esac + done +bzip2 -d -c "$ARCH_PACKAGE" | tar -xf - -C "$INSTALLATION_DIR" || exit 1 + +# Set symlinks into /usr and /sbin +link_into_fs "bin" "${PACKAGE_BASE}/usr/bin" +link_into_fs "sbin" "${PACKAGE_BASE}/usr/sbin" +link_into_fs "lib" "$lib_path" +link_into_fs "src" "${PACKAGE_BASE}/usr/src" + +if [ -d "$INSTALLATION_MODULES_DIR" ]; then + info "Installing additional modules ..." + for CUR_MODULE in `find "$INSTALLATION_MODULES_DIR" 2>/dev/null` + do + echo "$CUR_MODULE" >> "$CONFIG_DIR/$CONFIG_FILES" + done +fi + +for CUR_MODULE in ${INSTALLATION_MODULES_LIST} +do + mod_${CUR_MODULE}_install + if [ $? -ne 0 ]; then + info "Error: Failed to install module \"$CUR_MODULE\"" + if ! test "$FORCE_UPGRADE" = "force"; then + exit 1 + fi + fi +done + +# Remember our installation configuration before we call any init scripts +cat > "$CONFIG_DIR/$CONFIG" << EOF +# $PACKAGE installation record. +# Package installation directory +INSTALL_DIR='$INSTALLATION_DIR' +# Additional installation modules +INSTALL_MODULES_DIR='$INSTALLATION_MODULES_DIR' +INSTALL_MODULES_LIST='$INSTALLATION_MODULES_LIST' +# Package uninstaller. If you repackage this software, please make sure +# that this prints a message and returns an error so that the default +# uninstaller does not attempt to delete the files installed by your +# package. +UNINSTALLER='$UNINSTALL' +# Package version +INSTALL_VER='$INSTALLATION_VER' +# Build type and user name for logging purposes +BUILD_VBOX_KBUILD_TYPE='$BUILD_BUILDTYPE' +BUILD_USERNAME='$USERNAME' +EOF + +# Give the modules the chance to write their stuff +# to the installation config as well. +if [ -n "${INSTALLATION_MODULES_LIST}" ]; then + info "Saving modules configuration ..." + for CUR_MODULE in ${INSTALLATION_MODULES_LIST} + do + echo "`mod_${CUR_MODULE}_config_save`" >> "$CONFIG_DIR/$CONFIG" + done +fi + +"$INSTALLATION_DIR"/init/vboxadd setup 2>&1 | tee -a "$LOGFILE" + +# Install, set up and start init scripts +install_init_script "$INSTALLATION_DIR"/init/vboxadd vboxadd 2>> "$LOGFILE" +install_init_script "$INSTALLATION_DIR"/init/vboxadd-service vboxadd-service \ + 2>> "$LOGFILE" +finish_init_script_install +addrunlevel vboxadd 2>> "$LOGFILE" +addrunlevel vboxadd-service 2>> "$LOGFILE" +start_init_script vboxadd 2>> "$LOGFILE" +start_init_script vboxadd-service 2>> "$LOGFILE" + +cp $ROUTINES $INSTALLATION_DIR +echo $INSTALLATION_DIR/$ROUTINES >> "$CONFIG_DIR/$CONFIG_FILES" +cat > $INSTALLATION_DIR/$UNINSTALL << EOF +#!/bin/sh +# Auto-generated uninstallation file + +PATH=\$PATH:/bin:/sbin:/usr/sbin +LOGFILE="/var/log/vboxadd-uninstall.log" + +# Read routines.sh +if ! test -r "$INSTALLATION_DIR/$ROUTINES"; then + echo 1>&2 "Required file $ROUTINES not found. Aborting..." + return 1 +fi +. "$INSTALLATION_DIR/$ROUTINES" + +# We need to be run as root +check_root + +create_log "\$LOGFILE" + +echo 1>&2 "Removing installed version $INSTALLATION_VER of $PACKAGE_NAME..." + +NO_CLEANUP="" +if test "\$1" = "no_cleanup"; then + shift + NO_CLEANUP="no_cleanup" +fi + +test -r "$CONFIG_DIR/$CONFIG_FILES" || abort "Required file $CONFIG_FILES not found. Aborting..." + +# Stop and clean up all services +if test -r "$INSTALLATION_DIR"/init/vboxadd-service; then + stop_init_script vboxadd-service 2>> "\$LOGFILE" + delrunlevel vboxadd-service 2>> "\$LOGFILE" + remove_init_script vboxadd-service 2>> "\$LOGFILE" +fi +if test -r "$INSTALLATION_DIR"/init/vboxadd; then + stop_init_script vboxadd 2>> "\$LOGFILE" + test -n "\$NO_CLEANUP" || "$INSTALLATION_DIR"/init/vboxadd cleanup 2>> "\$LOGFILE" + delrunlevel vboxadd 2>> "\$LOGFILE" + remove_init_script vboxadd 2>> "\$LOGFILE" +fi +finish_init_script_install + +# Load all modules +# Important: This needs to be done before loading the configuration +# value below to not override values which are set to a default +# value in the modules itself. +for CUR_MODULE in `find "$INSTALLATION_MODULES_DIR" -name "module-*" 2>/dev/null` + do + . "\$CUR_MODULE" + done + +# Load configuration values +test -r "$CONFIG_DIR/$CONFIG" && . "$CONFIG_DIR/$CONFIG" + +# Call uninstallation initialization of all modules +for CUR_MODULE in "$INSTALLATION_MODULES_LIST" + do + if test -z "\$CUR_MODULE"; then + continue + fi + mod_\${CUR_MODULE}_pre_uninstall + if [ $? -ne 0 ]; then + echo 1>&2 "Module \"\$CUR_MODULE\" failed to initialize uninstallation" + # Continue initialization. + fi + done + +# Call uninstallation of all modules +for CUR_MODULE in "$INSTALLATION_MODULES_LIST" + do + if test -z "\$CUR_MODULE"; then + continue + fi + mod_\${CUR_MODULE}_uninstall + if [ $? -ne 0 ]; then + echo 1>&2 "Module \"\$CUR_MODULE\" failed to uninstall" + # Continue uninstallation. + fi + done + +# And remove all files and empty installation directories +# Remove any non-directory entries +cat "$CONFIG_DIR/$CONFIG_FILES" | xargs rm 2>/dev/null +# Remove any empty (of files) directories in the file list +cat "$CONFIG_DIR/$CONFIG_FILES" | + while read file; do + case "\$file" in + */) + test -d "\$file" && + find "\$file" -depth -type d -exec rmdir '{}' ';' 2>/dev/null + ;; + esac + done + +# Remove configuration files +rm "$CONFIG_DIR/$CONFIG_FILES" 2>/dev/null +rm "$CONFIG_DIR/$CONFIG" 2>/dev/null +rmdir "$CONFIG_DIR" 2>/dev/null +exit 0 +EOF +chmod 0755 $INSTALLATION_DIR/$UNINSTALL +echo $INSTALLATION_DIR/$UNINSTALL >> "$CONFIG_DIR/$CONFIG_FILES" +test -n "$REMOVE_INSTALLATION_DIR" && + echo "$INSTALLATION_DIR/" >> "$CONFIG_DIR/$CONFIG_FILES" + +cat > "${PUBLIC_UNINSTALL_HOOK}" << EOF +#!/bin/sh +# This executable provides a well-known way to uninstall VirtualBox Guest +# Additions in order to re-install them from a different source. A common case +# is uninstalling distribution-provide Additions to install the version provided +# by VirtualBox. Distributions should put the right command in here to do the +# removal, e.g. "dnf remove VirtualBox-guest-additions". Leaving kernel modules +# provided by the distribution kernel package in place is acceptable if the +# location does not clash with the VirtualBox-provided module location (misc). +$INSTALLATION_DIR/$UNINSTALL +EOF +chmod 0755 "${PUBLIC_UNINSTALL_HOOK}" +echo "$PUBLIC_UNINSTALL_HOOK" >> "$CONFIG_DIR/$CONFIG_FILES" + +# Test for a problem with old Mesa versions which stopped our 3D libraries +# from working. Known to affect Debian 7.11, probably OL/RHEL 5. +# The problem was that the system Mesa library had an ABI note, which caused +# ldconfig to always prefer it to ours. +if ldconfig -p | grep -q "libGL.so.1.*Linux 2.4"; then + gl_with_abi=`ldconfig -p | grep "libGL.so.1.*Linux 2.4" | sed 's/.*=> //'` + cat >&2 << EOF +This system appears to be running a version of Mesa with a known problem +which will prevent VirtualBox 3D pass-through from working. See + https://bugs.freedesktop.org/show_bug.cgi?id=26663 +The following, run as root should fix this, though you will have to run it +again if the system version of Mesa is updated: +EOF + for i in ${gl_with_abi}; do + echo >&2 " strip -R .note.ABI-tag ${i}" + done + echo >&2 " ldconfig" +fi + +# setuid bit of our drm client as drm ioctl calls +# need to be done by elevated privileges +chmod 4755 "$INSTALLATION_DIR"/bin/VBoxDRMClient + +# And do a final test as to whether the kernel modules were properly created +# and loaded. Return 0 if both are true, 1 if the modules could not be built +# or loaded (except due to already running older modules) and 2 if already +# running modules probably prevented new ones from loading. vboxvideo is +# currently not tested. +# Assume that we have already printed enough messages by now and stay silent. +modinfo vboxguest >/dev/null 2>&1 || exit 1 +lsmod | grep -q vboxguest || exit 1 +test -n "${MODULES_STOPPED}" || exit 2 +exit 0 |