vboxconfig.sh revision bf5a2ed371c0a47483665fc30b0765a8d80b6b1f
#!/bin/sh
# $Id$
## @file
# VirtualBox Configuration Script, Solaris host.
#
#
# Copyright (C) 2009-2013 Oracle Corporation
#
# This file is part of VirtualBox Open Source Edition (OSE), as
# available from http://www.virtualbox.org. This file is free software;
# you can redistribute it and/or modify it under the terms of the GNU
# General Public License (GPL) as published by the Free Software
# Foundation, in version 2 as it comes in the "COPYING" file of the
# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
#
# Never use exit 2 or exit 20 etc., the return codes are used in
# SRv4 postinstall procedures which carry special meaning. Just use exit 1 for failure.
# LC_ALL should take precedence over LC_* and LANG but whatever...
LC_ALL=C
export LC_ALL
LANG=C
export LANG
DIR_VBOXBASE="$PKG_INSTALL_ROOT/opt/VirtualBox"
DIR_CONF="$PKG_INSTALL_ROOT/platform/i86pc/kernel/drv"
DIR_MOD_32="$PKG_INSTALL_ROOT/platform/i86pc/kernel/drv"
DIR_MOD_64="$DIR_MOD_32/amd64"
# Default paths, these will be overridden by 'which' if they don't exist
BIN_ADDDRV=/usr/sbin/add_drv
BIN_REMDRV=/usr/sbin/rem_drv
BIN_MODLOAD=/usr/sbin/modload
BIN_MODUNLOAD=/usr/sbin/modunload
BIN_MODINFO=/usr/sbin/modinfo
BIN_DEVFSADM=/usr/sbin/devfsadm
BIN_BOOTADM=/sbin/bootadm
BIN_SVCADM=/usr/sbin/svcadm
BIN_SVCCFG=/usr/sbin/svccfg
BIN_SVCS=/usr/bin/svcs
BIN_IFCONFIG=/sbin/ifconfig
BIN_SVCS=/usr/bin/svcs
BIN_ID=/usr/bin/id
BIN_PKILL=/usr/bin/pkill
# "vboxdrv" is also used in sed lines here (change those as well if it ever changes)
MOD_VBOXDRV=vboxdrv
DESC_VBOXDRV="Host"
MOD_VBOXNET=vboxnet
DESC_VBOXNET="NetAdapter"
MOD_VBOXNET_INST=32
MOD_VBOXFLT=vboxflt
DESC_VBOXFLT="NetFilter (STREAMS)"
MOD_VBOXBOW=vboxbow
DESC_VBOXBOW="NetFilter (Crossbow)"
MOD_VBOXUSBMON=vboxusbmon
DESC_VBOXUSBMON="USBMonitor"
MOD_VBOXUSB=vboxusb
DESC_VBOXUSB="USB"
UPDATEBOOTARCHIVE=0
REMOTEINST=0
FATALOP=fatal
NULLOP=nulloutput
SILENTOP=silent
IPSOP=ips
ISSILENT=
ISIPS=
infoprint()
{
if test "$ISSILENT" != "$SILENTOP"; then
echo 1>&2 "$1"
fi
}
subprint()
{
if test "$ISSILENT" != "$SILENTOP"; then
echo 1>&2 " - $1"
fi
}
warnprint()
{
if test "$ISSILENT" != "$SILENTOP"; then
echo 1>&2 " * Warning!! $1"
fi
}
errorprint()
{
echo 1>&2 "## $1"
}
helpprint()
{
echo 1>&2 "$1"
}
printusage()
{
helpprint "VirtualBox Configuration Script"
helpprint "usage: $0 <operation> [options]"
helpprint
helpprint "<operation> must be one of the following:"
helpprint " --postinstall Perform full post installation procedure"
helpprint " --preremove Perform full pre remove procedure"
helpprint " --installdrivers Only install the drivers"
helpprint " --removedrivers Only remove the drivers"
helpprint " --setupdrivers Setup drivers, reloads existing drivers"
helpprint
helpprint "[options] are one or more of the following:"
helpprint " --silent Silent mode"
helpprint " --fatal Don't continue on failure (required for postinstall)"
helpprint " --ips This is an IPS package postinstall/preremove"
helpprint " --altkerndir Use /usr/kernel/drv as the driver directory"
helpprint
}
# find_bin_path()
# !! failure is always fatal
find_bin_path()
{
if test -z "$1"; then
errorprint "missing argument to find_bin_path()"
exit 1
fi
binfilename=`basename $1`
binfilepath=`which $binfilename 2> /dev/null`
if test -x "$binfilepath"; then
echo "$binfilepath"
return 0
else
errorprint "$1 missing or is not an executable"
exit 1
fi
}
# find_bins()
# !! failure is always fatal
find_bins()
{
# Search only for binaries that might be in different locations
if test ! -x "$BIN_ID"; then
BIN_ID=`find_bin_path "$BIN_ID"`
fi
if test ! -x "$BIN_ADDDRV"; then
BIN_ADDDRV=`find_bin_path "$BIN_ADDDRV"`
fi
if test ! -x "$BIN_REMDRV"; then
BIN_REMDRV=`find_bin_path "$BIN_REMDRV"`
fi
if test ! -x "$BIN_MODLOAD"; then
BIN_MODLOAD=`check_bin_path "$BIN_MODLOAD"`
fi
if test ! -x "$BIN_MODUNLOAD"; then
BIN_MODUNLOAD=`find_bin_path "$BIN_MODUNLOAD"`
fi
if test ! -x "$BIN_MODINFO"; then
BIN_MODINFO=`find_bin_path "$BIN_MODINFO"`
fi
if test ! -x "$BIN_DEVFSADM"; then
BIN_DEVFSADM=`find_bin_path "$BIN_DEVFSADM"`
fi
if test ! -x "$BIN_BOOTADM"; then
BIN_BOOTADM=`find_bin_path "$BIN_BOOTADM"`
fi
if test ! -x "$BIN_SVCADM"; then
BIN_SVCADM=`find_bin_path "$BIN_SVCADM"`
fi
if test ! -x "$BIN_SVCCFG"; then
BIN_SVCCFG=`find_bin_path "$BIN_SVCCFG"`
fi
if test ! -x "$BIN_SVCS"; then
BIN_SVCS=`find_bin_path "$BIN_SVCS"`
fi
if test ! -x "$BIN_IFCONFIG"; then
BIN_IFCONFIG=`find_bin_path "$BIN_IFCONFIG"`
fi
if test ! -x "$BIN_PKILL"; then
BIN_PKILL=`find_bin_path "$BIN_PKILL"`
fi
}
# check_root()
# !! failure is always fatal
check_root()
{
# Don't use "-u" option as some id binaries don't support it, instead
# rely on "uid=101(username) gid=10(groupname) groups=10(staff)" output
curuid=`$BIN_ID | cut -f 2 -d '=' | cut -f 1 -d '('`
if test "$curuid" -ne 0; then
errorprint "This script must be run with administrator privileges."
exit 1
fi
}
# get_sysinfo
# cannot fail
get_sysinfo()
{
BIN_PKG=`which pkg 2> /dev/null`
if test -x "$BIN_PKG"; then
PKGFMRI=`$BIN_PKG $BASEDIR_PKGOPT contents -H -t set -a name=pkg.fmri -o pkg.fmri pkg:/system/kernel 2> /dev/null`
if test -z "$PKGFMRI"; then
# Perhaps this is old pkg without '-a' option and/or system/kernel is missing and it's part of 'entire'
# Try fallback.
PKGFMRI=`$BIN_PKG $BASEDIR_PKGOPT contents -H -t set -o pkg.fmri entire | head -1 2> /dev/null`
if test -z "$PKGFMRI"; then
# Perhaps entire is conflicting. Try using opensolaris/entire.
# Last fallback try.
PKGFMRI=`$BIN_PKG $BASEDIR_PKGOPT contents -H -t set -o pkg.fmri opensolaris.org/entire | head -1 2> /dev/null`
fi
fi
if test ! -z "$PKGFMRI"; then
# The format is "pkg://solaris/system/kernel@0.5.11,5.11-0.161:20110315T070332Z"
# or "pkg://solaris/system/kernel@5.12,5.11-5.12.0.0.0.4.1:20120908T030246Z"
# or "pkg://solaris/system/kernel@0.5.11,5.11-0.175.0.0.0.1.0:20111012T032837Z"
# or "pkg://solaris/system/kernel@5.12-5.12.0.0.0.9.1.3.0:20121012T032837Z"
STR_KERN_MAJOR=`echo "$PKGFMRI" | sed 's/^.*\@//;s/\,.*//'`
if test ! -z "$STR_KERN_MAJOR"; then
# The format is "0.5.11" or "5.12"
# Let us just hardcode these for now, instead of trying to do things more generically. It's not
# worth trying to bring more order to chaos as it's clear that the version numbering is subject to breakage
# as it has been seen in the past.
if test "$STR_KERN_MAJOR" = "5.12"; then
HOST_OS_MAJORVERSION="12"
elif test "$STR_KERN_MAJOR" = "0.5.11" || test "$STR_KERN_MAJOR" = "5.11"; then
HOST_OS_MAJORVERSION="11"
else
# This could be the PSARC/2012/240 naming scheme for S12.
# The format is "pkg://solaris/system/kernel@5.12-5.12.0.0.0.9.1.3.0:20121012T032837Z"
# The "5.12" following the "@" is the nominal version which we ignore for now as it is
# not set by most pkg(5) tools...
# STR_KERN_MAJOR is now of the format "5.12-5.12.0.0.0.9.1.3.0:20121012T032837Z" with '9' representing
# the build number.
BRANCH_VERSION=STR_KERN_MAJOR
HOST_OS_MAJORVERSION=`echo "$BRANCH_VERSION" | cut -f2 -d'-' | cut -f1,2 -d'.'`
if test "HOST_OS_MAJORVERSION" = "5.12"; then
HOST_OS_MINORVERSION=`echo "$BRANCH_VERSION" | cut -f2 -d'-' | cut -f6 -d'.'`
return 0
else
errorprint "Failed to parse the Solaris kernel major version."
exit 1
fi
fi
# This applies only to S11 and S12 where the transitional "@5.12," component version is
# still part of the pkg(5) package FMRI. The regular S12 will follow the PSARC/2012/240 naming scheme above.
STR_KERN_MINOR=`echo "$PKGFMRI" | sed 's/^.*\@//;s/\:.*//;s/.*,//'`
if test ! -z "$STR_KERN_MINOR"; then
# The HOST_OS_MINORVERSION is represented as follows:
# For S12 it represents the build numbers. e.g. for 4 : "5.11-5.12.0.0.0.4.1"
# For S11 as the "nevada" version numbers. e.g. for 175: "5.11-0.161" or "5.11-0.175.0.0.0.1.0"
if test "$HOST_OS_MAJORVERSION" -eq 12; then
HOST_OS_MINORVERSION=`echo "$STR_KERN_MINOR" | cut -f2 -d'-' | cut -f6 -d'.'`
elif test "$HOST_OS_MAJORVERSION" -eq 11; then
HOST_OS_MINORVERSION=`echo "$STR_KERN_MINOR" | cut -f2 -d'-' | cut -f2 -d'.'`
else
errorprint "Solaris kernel major version $HOST_OS_MAJORVERSION not supported."
exit 1
fi
else
errorprint "Failed to parse the Solaris kernel minor version."
exit 1
fi
else
errorprint "Failed to parse the Solaris kernel package version."
exit 1
fi
else
errorprint "Failed to detect the Solaris kernel package FMRI."
exit 1
fi
else
HOST_OS_MAJORVERSION=`uname -r`
if test -z "$HOST_OS_MAJORVERSION" || test "$HOST_OS_MAJORVERSION" != "5.10"; then
# S11 without 'pkg'?? Something's wrong... bail.
errorprint "Solaris $HOST_OS_MAJORVERSION detected without executable $BIN_PKG !? I are confused."
exit 1
fi
HOST_OS_MAJORVERSION="10"
if test "$REMOTEINST" -eq 0; then
# Use uname to verify it's S10.
# Major version is S10, Minor version is no longer relevant (or used), use uname -v so it gets something
# like "Generic_blah" for purely cosmetic purposes
HOST_OS_MINORVERSION=`uname -v`
else
# Remote installs from S10 local.
BIN_PKGCHK=`which pkgchk 2> /dev/null`
if test ! -x "$BIN_PKGCHK"; then
errorprint "Failed to find an executable pkgchk binary $BIN_PKGCHK."
errorprint "Cannot determine Solaris version on remote target $PKG_INSTALL_ROOT"
exit 1
fi
REMOTE_S10=`$BIN_PKGCHK -l -p /kernel/amd64/genunix $BASEDIR_PKGOPT 2> /dev/null | grep SUNWckr | tr -d ' \t'`
if test ! -z "$REMOTE_S10" && test "$REMOTE_S10" = "SUNWckr"; then
HOST_OS_MAJORVERSION="10"
HOST_OS_MINORVERSION=""
else
errorprint "Remote target $PKG_INSTALL_ROOT is not Solaris 10."
errorprint "Will not attempt to install to an unidentified remote target."
exit 1
fi
fi
fi
}
# check_zone()
# !! failure is always fatal
check_zone()
{
currentzone=`zonename`
if test "$currentzone" != "global"; then
errorprint "This script must be run from the global zone."
exit 1
fi
}
# check_isa()
# !! failure is always fatal
check_isa()
{
currentisa=`uname -i`
if test "$currentisa" = "i86xpv"; then
errorprint "VirtualBox cannot run under xVM Dom0! Fatal Error, Aborting installation!"
exit 1
fi
}
# check_module_arch()
# !! failure is always fatal
check_module_arch()
{
cputype=`isainfo -k`
if test "$cputype" != "amd64" && test "$cputype" != "i386"; then
errorprint "VirtualBox works only on i386/amd64 hosts, not $cputype"
exit 1
fi
}
# update_boot_archive()
# cannot fail
update_boot_archive()
{
infoprint "Updating the boot archive..."
if test "$REMOTEINST" -eq 0; then
$BIN_BOOTADM update-archive > /dev/null
else
$BIN_BOOTADM update-archive -R "$PKG_INSTALL_ROOT" > /dev/null
fi
UPDATEBOOTARCHIVE=0
}
# module_added(modname)
# returns 1 if added, 0 otherwise
module_added()
{
if test -z "$1"; then
errorprint "missing argument to module_added()"
exit 1
fi
# Add a space at end of module name to make sure we have a perfect match to avoid
# any substring matches: e.g "vboxusb" & "vboxusbmon"
loadentry=`cat "$PKG_INSTALL_ROOT/etc/name_to_major" | grep "$1 "`
if test -z "$loadentry"; then
return 1
fi
return 0
}
# module_loaded(modname)
# returns 1 if loaded, 0 otherwise
module_loaded()
{
if test -z "$1"; then
errorprint "missing argument to module_loaded()"
exit 1
fi
modname=$1
# modinfo should now work properly since we prevent module autounloading.
loadentry=`$BIN_MODINFO | grep "$modname "`
if test -z "$loadentry"; then
return 1
fi
return 0
}
# add_driver(modname, moddesc, fatal, nulloutput, [driverperm])
# failure: depends on "fatal"
add_driver()
{
if test -z "$1" || test -z "$2"; then
errorprint "missing argument to add_driver()"
exit 1
fi
modname="$1"
moddesc="$2"
fatal="$3"
nullop="$4"
modperm="$5"
if test -n "$modperm"; then
if test "$nullop" = "$NULLOP"; then
$BIN_ADDDRV $BASEDIR_OPT -m"$modperm" $modname >/dev/null 2>&1
else
$BIN_ADDDRV $BASEDIR_OPT -m"$modperm" $modname
fi
else
if test "$nullop" = "$NULLOP"; then
$BIN_ADDDRV $BASEDIR_OPT $modname >/dev/null 2>&1
else
$BIN_ADDDRV $BASEDIR_OPT $modname
fi
fi
if test $? -ne 0; then
subprint "Adding: $moddesc module ...FAILED!"
if test "$fatal" = "$FATALOP"; then
exit 1
fi
return 1
elif test "$REMOTEINST" -eq 1 && test "$?" -eq 0; then
subprint "Added: $moddesc driver"
fi
return 0
}
# rem_driver(modname, moddesc, [fatal])
# failure: depends on [fatal]
rem_driver()
{
if test -z "$1" || test -z "$2"; then
errorprint "missing argument to rem_driver()"
exit 1
fi
modname=$1
moddesc=$2
fatal=$3
module_added $modname
if test "$?" -eq 0; then
UPDATEBOOTARCHIVE=1
if test "$ISIPS" != "$IPSOP"; then
$BIN_REMDRV $BASEDIR_OPT $modname
else
$BIN_REMDRV $BASEDIR_OPT $modname >/dev/null 2>&1
fi
# for remote installs, don't bother with return values of rem_drv
if test $? -eq 0; then
subprint "Removed: $moddesc module"
return 0
else
subprint "Removing: $moddesc ...FAILED!"
if test "$fatal" = "$FATALOP"; then
exit 1
fi
return 1
fi
fi
}
# unload_module(modname, moddesc, retry, [fatal])
# failure: fatal
unload_module()
{
if test -z "$1" || test -z "$2"; then
errorprint "missing argument to unload_module()"
exit 1
fi
# No-OP for non-root installs
if test "$REMOTEINST" -eq 1; then
return 0
fi
modname=$1
moddesc=$2
retry=$3
fatal=$4
modid=`$BIN_MODINFO | grep "$modname " | cut -f 1 -d ' ' `
if test -n "$modid"; then
$BIN_MODUNLOAD -i $modid
if test $? -eq 0; then
subprint "Unloaded: $moddesc module"
else
#
# Hack for vboxdrv. Delayed removing when VMM thread-context hooks are used.
# Our automated tests are probably too quick... Fix properly later.
#
result=$?
if test "$retry" -eq 1; then
cmax=15
cslept=0
while test "$result" -ne 0;
do
subprint "Unloading: $moddesc module ...FAILED! Busy? Retrying in 3 seconds..."
sleep 3
cslept=`expr $cslept + 3`
if test "$cslept" -ge "$cmax"; then
break
fi
$BIN_MODUNLOAD -i $modid
result=$?
done
fi
if test "$result" -ne 0; then
subprint "Unloading: $moddesc module ...FAILED!"
if test "$fatal" = "$FATALOP"; then
exit 1
fi
else
subprint "Unloaded: $moddesc module"
fi
return 1
fi
fi
return 0
}
# load_module(modname, moddesc, [fatal])
# pass "drv/modname" or "misc/vbi" etc.
# failure: fatal
load_module()
{
if test -z "$1" || test -z "$2"; then
errorprint "missing argument to load_module()"
exit 1
fi
# No-OP for non-root installs
if test "$REMOTEINST" -eq 1; then
return 0
fi
modname=$1
moddesc=$2
fatal=$3
$BIN_MODLOAD -p $modname
if test $? -eq 0; then
subprint "Loaded: $moddesc module"
return 0
else
subprint "Loading: $moddesc ...FAILED!"
if test "$fatal" = "$FATALOP"; then
exit 1
fi
return 1
fi
}
load_vboxflt()
{
if test -f "$DIR_CONF/vboxflt.conf"; then
add_driver "$MOD_VBOXFLT" "$DESC_VBOXFLT" "$FATALOP"
load_module "drv/$MOD_VBOXFLT" "$DESC_VBOXFLT" "$FATALOP"
else
# For custom pkgs that optionally ship this module, let's not fail but just warn
warnprint "$DESC_VBOXFLT installation requested but not shipped in this package."
fi
}
load_vboxbow()
{
if test -f "$DIR_CONF/vboxbow.conf"; then
add_driver "$MOD_VBOXBOW" "$DESC_VBOXBOW" "$FATALOP"
load_module "drv/$MOD_VBOXBOW" "$DESC_VBOXBOW" "$FATALOP"
else
# For custom pkgs that optionally ship this module, let's not fail but just warn
warnprint "$DESC_VBOXBOW installation requested but not shipped in this package."
fi
}
# install_drivers()
# !! failure is always fatal
install_drivers()
{
if test -f "$DIR_CONF/vboxdrv.conf"; then
if test -n "_HARDENED_"; then
add_driver "$MOD_VBOXDRV" "$DESC_VBOXDRV" "$FATALOP" "not-$NULLOP" "'* 0600 root sys','vboxdrvu 0666 root sys'"
else
add_driver "$MOD_VBOXDRV" "$DESC_VBOXDRV" "$FATALOP" "not-$NULLOP" "'* 0666 root sys','vboxdrvu 0666 root sys'"
fi
load_module "drv/$MOD_VBOXDRV" "$DESC_VBOXDRV" "$FATALOP"
else
errorprint "Extreme error! Missing $DIR_CONF/vboxdrv.conf, aborting."
return 1
fi
## Add vboxdrv to devlink.tab (KEEP TABS!)
# clean up devlink.tab (KEEP TABS!)
if test -f "$PKG_INSTALL_ROOT/etc/devlink.tab"; then
sed -e '/name=vboxdrv/d' -e '/name=vboxdrvu/d' "$PKG_INSTALL_ROOT/etc/devlink.tab" > "$PKG_INSTALL_ROOT/etc/devlink.vbox"
#echo "type=ddi_pseudo;name=vboxdrv;minor=vboxdrv \D" >> "$PKG_INSTALL_ROOT/etc/devlink.vbox"
#echo "type=ddi_pseudo;name=vboxdrv;minor=vboxdrvu \M0" >> "$PKG_INSTALL_ROOT/etc/devlink.vbox"
mv -f "$PKG_INSTALL_ROOT/etc/devlink.vbox" "$PKG_INSTALL_ROOT/etc/devlink.tab"
else
errorprint "Missing $PKG_INSTALL_ROOT/etc/devlink.tab, aborting install"
return 1
fi
# Create the device link for non-remote installs (not really relevant any more)
if test "$REMOTEINST" -eq 0; then
/usr/sbin/devfsadm -i "$MOD_VBOXDRV"
#if test $? -ne 0 || test ! -h "/dev/vboxdrv" || test ! -h "/dev/vboxdrvu" ; then
# errorprint "Failed to create device link for $MOD_VBOXDRV."
# exit 1
#fi
fi
# Load VBoxNetAdp
if test -f "$DIR_CONF/vboxnet.conf"; then
add_driver "$MOD_VBOXNET" "$DESC_VBOXNET" "$FATALOP"
load_module "drv/$MOD_VBOXNET" "$DESC_VBOXNET" "$FATALOP"
fi
# If both vboxinst_vboxbow and vboxinst_vboxflt exist, bail.
if test -f "$PKG_INSTALL_ROOT/etc/vboxinst_vboxflt" && test -f "$PKG_INSTALL_ROOT/etc/vboxinst_vboxbow"; then
errorprint "Force-install files '$PKG_INSTALL_ROOT/etc/vboxinst_vboxflt' and '$PKG_INSTALL_ROOT/etc/vboxinst_vboxbow' both exist."
errorprint "Cannot load $DESC_VBOXFLT and $DESC_VBOXBOW drivers at the same time."
return 1
fi
# If the force-install files exists, install blindly
if test -f "$PKG_INSTALL_ROOT/etc/vboxinst_vboxflt"; then
subprint "Detected: Force-load file $PKG_INSTALL_ROOT/etc/vboxinst_vboxflt."
load_vboxflt
elif test -f "$PKG_INSTALL_ROOT/etc/vboxinst_vboxbow"; then
subprint "Detected: Force-load file $PKG_INSTALL_ROOT/etc/vboxinst_vboxbow."
load_vboxbow
else
# If host is S10 or S11 (< snv_159) or vboxbow isn't shipped, then load vboxflt
if test "$HOST_OS_MAJORVERSION" -eq 10 || (test "$HOST_OS_MAJORVERSION" -eq 11 && test "$HOST_OS_MINORVERSION" -lt 159) || test ! -f "$DIR_CONF/vboxbow.conf"; then
load_vboxflt
else
# For S11 snv_159+ load vboxbow
load_vboxbow
fi
fi
# Load VBoxUSBMon, VBoxUSB
if test -f "$DIR_CONF/vboxusbmon.conf" && test "$HOST_OS_MAJORVERSION" != "10"; then
# For VirtualBox 3.1 the new USB code requires Nevada > 123 i.e. S12+ or S11 b124+
if test "$HOST_OS_MAJORVERSION" -gt 11 || (test "$HOST_OS_MAJORVERSION" -eq 11 && test "$HOST_OS_MINORVERSION" -gt 123); then
# Add a group "vboxuser" (8-character limit) for USB access.
# All users which need host USB-passthrough support will have to be added to this group.
groupadd vboxuser >/dev/null 2>&1
add_driver "$MOD_VBOXUSBMON" "$DESC_VBOXUSBMON" "$FATALOP" "not-$NULLOP" "'* 0666 root sys'"
load_module "drv/$MOD_VBOXUSBMON" "$DESC_VBOXUSBMON" "$FATALOP"
chown root:vboxuser "/devices/pseudo/vboxusbmon@0:vboxusbmon"
# Add vboxusbmon to devlink.tab
sed -e '/name=vboxusbmon/d' "$PKG_INSTALL_ROOT/etc/devlink.tab" > "$PKG_INSTALL_ROOT/etc/devlink.vbox"
echo "type=ddi_pseudo;name=vboxusbmon \D" >> "$PKG_INSTALL_ROOT/etc/devlink.vbox"
mv -f "$PKG_INSTALL_ROOT/etc/devlink.vbox" "$PKG_INSTALL_ROOT/etc/devlink.tab"
# Create the device link for non-remote installs
if test "$REMOTEINST" -eq 0; then
/usr/sbin/devfsadm -i "$MOD_VBOXUSBMON"
if test $? -ne 0; then
errorprint "Failed to create device link for $MOD_VBOXUSBMON."
exit 1
fi
fi
# Add vboxusb if present
# This driver is special, we need it in the boot-archive but since there is no
# USB device to attach to now (it's done at runtime) it will fail to attach so
# redirect attaching failure output to /dev/null
if test -f "$DIR_CONF/vboxusb.conf"; then
add_driver "$MOD_VBOXUSB" "$DESC_VBOXUSB" "$FATALOP" "$NULLOP"
load_module "drv/$MOD_VBOXUSB" "$DESC_VBOXUSB" "$FATALOP"
fi
else
warnprint "Solaris 11 build 124 or higher required for USB support. Skipped installing USB support."
fi
fi
return $?
}
# remove_drivers([fatal])
# failure: depends on [fatal]
remove_drivers()
{
fatal=$1
# Remove vboxdrv from devlink.tab
if test -f "$PKG_INSTALL_ROOT/etc/devlink.tab"; then
devlinkfound=`cat "$PKG_INSTALL_ROOT/etc/devlink.tab" | grep vboxdrv`
if test -n "$devlinkfound"; then
sed -e '/name=vboxdrv/d' "$PKG_INSTALL_ROOT/etc/devlink.tab" > "$PKG_INSTALL_ROOT/etc/devlink.vbox"
mv -f "$PKG_INSTALL_ROOT/etc/devlink.vbox" "$PKG_INSTALL_ROOT/etc/devlink.tab"
fi
# Remove vboxusbmon from devlink.tab
devlinkfound=`cat "$PKG_INSTALL_ROOT/etc/devlink.tab" | grep vboxusbmon`
if test -n "$devlinkfound"; then
sed -e '/name=vboxusbmon/d' "$PKG_INSTALL_ROOT/etc/devlink.tab" > "$PKG_INSTALL_ROOT/etc/devlink.vbox"
mv -f "$PKG_INSTALL_ROOT/etc/devlink.vbox" "$PKG_INSTALL_ROOT/etc/devlink.tab"
fi
fi
unload_module "$MOD_VBOXUSB" "$DESC_VBOXUSB" 0 "$fatal"
rem_driver "$MOD_VBOXUSB" "$DESC_VBOXUSB" "$fatal"
unload_module "$MOD_VBOXUSBMON" "$DESC_VBOXUSBMON" 0 "$fatal"
rem_driver "$MOD_VBOXUSBMON" "$DESC_VBOXUSBMON" "$fatal"
unload_module "$MOD_VBOXFLT" "$DESC_VBOXFLT" 0 "$fatal"
rem_driver "$MOD_VBOXFLT" "$DESC_VBOXFLT" "$fatal"
unload_module "$MOD_VBOXBOW" "$DESC_VBOXBOW" 0 "$fatal"
rem_driver "$MOD_VBOXBOW" "$DESC_VBOXBOW" "$fatal"
unload_module "$MOD_VBOXNET" "$DESC_VBOXNET" 0 "$fatal"
rem_driver "$MOD_VBOXNET" "$DESC_VBOXNET" "$fatal"
unload_module "$MOD_VBOXDRV" "$DESC_VBOXDRV" 1 "$fatal"
rem_driver "$MOD_VBOXDRV" "$DESC_VBOXDRV" "$fatal"
# remove devlinks
if test -h "$PKG_INSTALL_ROOT/dev/vboxdrv" || test -f "$PKG_INSTALL_ROOT/dev/vboxdrv"; then
rm -f "$PKG_INSTALL_ROOT/dev/vboxdrv"
fi
if test -h "$PKG_INSTALL_ROOT/dev/vboxdrvu" || test -f "$PKG_INSTALL_ROOT/dev/vboxdrvu"; then
rm -f "$PKG_INSTALL_ROOT/dev/vboxdrvu"
fi
if test -h "$PKG_INSTALL_ROOT/dev/vboxusbmon" || test -f "$PKG_INSTALL_ROOT/dev/vboxusbmon"; then
rm -f "$PKG_INSTALL_ROOT/dev/vboxusbmon"
fi
# unpatch nwam/dhcpagent fix
nwamfile="$PKG_INSTALL_ROOT/etc/nwam/llp"
nwambackupfile=$nwamfile.vbox
if test -f "$nwamfile"; then
sed -e '/vboxnet/d' $nwamfile > $nwambackupfile
mv -f $nwambackupfile $nwamfile
fi
# remove netmask configuration
if test -h "$PKG_INSTALL_ROOT/etc/netmasks"; then
nmaskfile="$PKG_INSTALL_ROOT/etc/inet/netmasks"
else
nmaskfile="$PKG_INSTALL_ROOT/etc/netmasks"
fi
nmaskbackupfile=$nmaskfile.vbox
if test -f "$nmaskfile"; then
sed -e '/#VirtualBox_SectionStart/,/#VirtualBox_SectionEnd/d' $nmaskfile > $nmaskbackupfile
mv -f $nmaskbackupfile $nmaskfile
fi
if test $UPDATEBOOTARCHIVE -eq 1; then
update_boot_archive
fi
return 0
}
# install_python_bindings(pythonbin)
# remarks: changes pwd
# failure: non fatal
install_python_bindings()
{
# The python binary might not be there, so just exit silently
if test -z "$1"; then
return 0
fi
if test -z "$2"; then
errorprint "missing argument to install_python_bindings"
exit 1
fi
pythonbin=$1
pythondesc=$2
if test -x "$pythonbin"; then
# check if python has working distutils
$pythonbin -c "from distutils.core import setup" > /dev/null 2>&1
if test "$?" -ne 0; then
subprint "Skipped: $pythondesc install is unusable"
return 0
fi
VBOX_INSTALL_PATH="$DIR_VBOXBASE"
export VBOX_INSTALL_PATH
cd $DIR_VBOXBASE/sdk/installer
$pythonbin ./vboxapisetup.py install > /dev/null
if test "$?" -eq 0; then
subprint "Installed: Bindings for $pythondesc"
fi
return 0
fi
return 1
}
# is_process_running(processname)
# returns 1 if the process is running, 0 otherwise
is_process_running()
{
if test -z "$1"; then
errorprint "missing argument to is_process_running()"
exit 1
fi
procname=$1
procpid=`ps -eo pid,fname | grep $procname | grep -v grep | awk '{ print $1 }'`
if test ! -z "$procpid" && test "$procpid" -ge 0; then
return 1
fi
return 0
}
# stop_process(processname)
# failure: depends on [fatal]
stop_process()
{
if test -z "$1"; then
errorprint "missing argument to stop_process()"
exit 1
fi
# @todo use is_process_running()
procname=$1
procpid=`ps -eo pid,fname | grep $procname | grep -v grep | awk '{ print $1 }'`
if test ! -z "$procpid" && test "$procpid" -ge 0; then
$BIN_PKILL "$procname"
sleep 2
procpid=`ps -eo pid,fname | grep $procname | grep -v grep | awk '{ print $1 }'`
if test ! -z "$procpid" && test "$procpid" -ge 0; then
subprint "Terminating: $procname ...FAILED!"
if test "$fatal" = "$FATALOP"; then
exit 1
fi
else
subprint "Terminated: $procname"
fi
fi
}
# start_service(servicename, shortFMRI pretty printing, full FMRI, log-file path)
# failure: non-fatal
start_service()
{
if test -z "$1" || test -z "$2" || test -z "$3" || test -z "$4"; then
errorprint "missing argument to enable_service()"
exit 1
fi
# Since S11 the way to import a manifest is via restarting manifest-import which is asynchronous and can
# take a while to complete, using disable/enable -s doesn't work either. So we restart it, and poll in
# 1 second intervals to see if our service has been successfully imported and timeout after 'cmax' seconds.
cmax=32
cslept=0
success=0
$BIN_SVCS "$3" >/dev/null 2>&1
while test $? -ne 0;
do
sleep 1
cslept=`expr $cslept + 1`
if test "$cslept" -eq "$cmax"; then
success=1
break
fi
$BIN_SVCS "$3" >/dev/null 2>&1
done
if test "$success" -eq 0; then
$BIN_SVCADM enable -s "$3"
if test "$?" -eq 0; then
subprint "Loaded: $1"
return 0
else
warnprint "Loading $1 ...FAILED."
warnprint "Refer $4 for details."
fi
else
warnprint "Importing $1 ...FAILED."
warnprint "Refer /var/svc/log/system-manifest-import:default.log for details."
fi
return 1
}
# stop_service(servicename, shortFMRI-suitable for grep, full FMRI)
# failure: non fatal
stop_service()
{
if test -z "$1" || test -z "$2" || test -z "$3"; then
errorprint "missing argument to stop_service()"
exit 1
fi
servicefound=`$BIN_SVCS -H "$2" 2>/dev/null | grep '^online'`
if test ! -z "$servicefound"; then
$BIN_SVCADM disable -s "$3"
# Don't delete the manifest, this is handled by the manifest class action
# $BIN_SVCCFG delete "$3"
if test "$?" -eq 0; then
subprint "Unloaded: $1"
else
subprint "Unloading: $1 ...ERROR(S)."
fi
fi
}
# cleanup_install([fatal])
# failure: depends on [fatal]
cleanup_install()
{
fatal=$1
# No-Op for remote installs
if test "$REMOTEINST" -eq 1; then
return 0
fi
# stop the services
stop_service "Web service" "virtualbox/webservice" "svc:/application/virtualbox/webservice:default"
stop_service "Balloon control service" "virtualbox/balloonctrl" "svc:/application/virtualbox/balloonctrl:default"
stop_service "Autostart service" "virtualbox/autostart" "svc:/application/virtualbox/autostart:default"
stop_service "Zone access service" "virtualbox/zoneaccess" "svc:/application/virtualbox/zoneaccess:default"
# unplumb all vboxnet instances for non-remote installs
inst=0
while test $inst -ne $MOD_VBOXNET_INST; do
vboxnetup=`$BIN_IFCONFIG vboxnet$inst >/dev/null 2>&1`
if test "$?" -eq 0; then
$BIN_IFCONFIG vboxnet$inst unplumb
if test "$?" -ne 0; then
errorprint "VirtualBox NetAdapter 'vboxnet$inst' couldn't be unplumbed (probably in use)."
if test "$fatal" = "$FATALOP"; then
exit 1
fi
fi
fi
# unplumb vboxnet0 ipv6
vboxnetup=`$BIN_IFCONFIG vboxnet$inst inet6 >/dev/null 2>&1`
if test "$?" -eq 0; then
$BIN_IFCONFIG vboxnet$inst inet6 unplumb
if test "$?" -ne 0; then
errorprint "VirtualBox NetAdapter 'vboxnet$inst' IPv6 couldn't be unplumbed (probably in use)."
if test "$fatal" = "$FATALOP"; then
exit 1
fi
fi
fi
inst=`expr $inst + 1`
done
# Stop our other daemons, non-fatal
stop_process "VBoxNetDHCP"
stop_process "VBoxNetNAT"
# Stop VBoxSVC quickly using SIGUSR1
procname="VBoxSVC"
procpid=`ps -eo pid,fname | grep $procname | grep -v grep | awk '{ print $1 }'`
if test ! -z "$procpid" && test "$procpid" -ge 0; then
kill -USR1 $procpid
# Sleep a while and check if VBoxSVC is still running, if so fail uninstallation.
sleep 2
is_process_running "VBoxSVC"
if test "$?" -eq 1; then
errorprint "Cannot uninstall VirtualBox while VBoxSVC (pid $procpid) is still running."
errorprint "Please shutdown all VMs and VirtualBox frontends before uninstalling VirtualBox."
exit 1
fi
# Some VMs might still be alive after VBoxSVC as they poll less frequently before killing themselves
# Just check for VBoxHeadless & VirtualBox frontends for now.
is_process_running "VBoxHeadless"
if test "$?" -eq 1; then
errorprint "Cannot uninstall VirtualBox while VBoxHeadless is still running."
errorprint "Please shutdown all VMs and VirtualBox frontends before uninstalling VirtualBox."
exit 1
fi
is_process_running "VirtualBox"
if test "$?" -eq 1; then
errorprint "Cannot uninstall VirtualBox while any VM is still running."
errorprint "Please shutdown all VMs and VirtualBox frontends before uninstalling VirtualBox."
exit 1
fi
fi
}
# postinstall()
# !! failure is always fatal
postinstall()
{
infoprint "Detected Solaris $HOST_OS_MAJORVERSION Version $HOST_OS_MINORVERSION"
infoprint "Loading VirtualBox kernel modules..."
install_drivers
if test "$?" -eq 0; then
if test -f "$DIR_CONF/vboxnet.conf"; then
# nwam/dhcpagent fix
nwamfile="$PKG_INSTALL_ROOT/etc/nwam/llp"
nwambackupfile=$nwamfile.vbox
if test -f "$nwamfile"; then
sed -e '/vboxnet/d' $nwamfile > $nwambackupfile
# add all vboxnet instances as static to nwam
inst=0
networkn=56
while test $inst -ne 1; do
echo "vboxnet$inst static 192.168.$networkn.1" >> $nwambackupfile
inst=`expr $inst + 1`
networkn=`expr $networkn + 1`
done
mv -f $nwambackupfile $nwamfile
fi
# plumb and configure vboxnet0 for non-remote installs
if test "$REMOTEINST" -eq 0; then
# S11 175a renames vboxnet0 as 'netX', undo this and rename it back (S12+ or S11 b175+)
if test "$HOST_OS_MAJORVERSION" -gt 11 || (test "$HOST_OS_MAJORVERSION" -eq 11 && test "$HOST_OS_MINORVERSION" -gt 174); then
vanityname=`dladm show-phys -po link,device | grep vboxnet0 | cut -f1 -d':'`
if test $? -eq 0 && test ! -z "$vanityname" && test "$vanityname" != "vboxnet0"; then
dladm rename-link "$vanityname" vboxnet0
if test $? -ne 0; then
errorprint "Failed to rename vanity interface ($vanityname) to vboxnet0"
fi
fi
fi
$BIN_IFCONFIG vboxnet0 plumb
$BIN_IFCONFIG vboxnet0 up
if test "$?" -eq 0; then
$BIN_IFCONFIG vboxnet0 192.168.56.1 netmask 255.255.255.0 up
# /etc/netmasks is a symlink, older installers replaced this with
# a copy of the actual file, repair that behaviour here.
recreatelink=0
if test -h "$PKG_INSTALL_ROOT/etc/netmasks"; then
nmaskfile="$PKG_INSTALL_ROOT/etc/inet/netmasks"
else
nmaskfile="$PKG_INSTALL_ROOT/etc/netmasks"
recreatelink=1
fi
# add the netmask to stay persistent across host reboots
nmaskbackupfile=$nmaskfile.vbox
if test -f $nmaskfile; then
sed -e '/#VirtualBox_SectionStart/,/#VirtualBox_SectionEnd/d' $nmaskfile > $nmaskbackupfile
if test $recreatelink -eq 1; then
# Check after removing our settings if /etc/netmasks is identifcal to /etc/inet/netmasks
anydiff=`diff $nmaskbackupfile "$PKG_INSTALL_ROOT/etc/inet/netmasks"`
if test ! -z "$anydiff"; then
# User may have some custom settings in /etc/netmasks, don't overwrite /etc/netmasks!
recreatelink=2
fi
fi
echo "#VirtualBox_SectionStart" >> $nmaskbackupfile
inst=0
networkn=56
while test $inst -ne 1; do
echo "192.168.$networkn.0 255.255.255.0" >> $nmaskbackupfile
inst=`expr $inst + 1`
networkn=`expr $networkn + 1`
done
echo "#VirtualBox_SectionEnd" >> $nmaskbackupfile
mv -f $nmaskbackupfile $nmaskfile
# Recreate /etc/netmasks as a link if necessary
if test $recreatelink -eq 1; then
cp -f "$PKG_INSTALL_ROOT/etc/netmasks" "$PKG_INSTALL_ROOT/etc/inet/netmasks"
ln -sf ./inet/netmasks "$PKG_INSTALL_ROOT/etc/netmasks"
elif test $recreatelink -eq 2; then
warnprint "/etc/netmasks is a symlink (to /etc/inet/netmasks) that older"
warnprint "VirtualBox installers incorrectly overwrote. Now the contents"
warnprint "of /etc/netmasks and /etc/inet/netmasks differ, therefore "
warnprint "VirtualBox will not attempt to overwrite /etc/netmasks as a"
warnprint "symlink to /etc/inet/netmasks. Please resolve this manually"
warnprint "by updating /etc/inet/netmasks and creating /etc/netmasks as a"
warnprint "symlink to /etc/inet/netmasks"
fi
fi
else
# Should this be fatal?
warnprint "Failed to bring up vboxnet0!!"
fi
fi
fi
if test -f "$PKG_INSTALL_ROOT/var/svc/manifest/application/virtualbox/virtualbox-webservice.xml" \
|| test -f "$PKG_INSTALL_ROOT/var/svc/manifest/application/virtualbox/virtualbox-zoneaccess.xml" \
|| test -f "$PKG_INSTALL_ROOT/var/svc/manifest/application/virtualbox/virtualbox-balloonctrl.xml"\
|| test -f "$PKG_INSTALL_ROOT/var/svc/manifest/application/virtualbox/virtualbox-autostart.xml"; then
infoprint "Configuring services..."
if test "$REMOTEINST" -eq 1; then
subprint "Skipped for targetted installs."
else
# Since S11 the way to import a manifest is via restarting manifest-import which is asynchronous and can
# take a while to complete, using disable/enable -s doesn't work either. So we restart it, and poll in
# 1 second intervals to see if our service has been successfully imported and timeout after 'cmax' seconds.
$BIN_SVCADM restart svc:system/manifest-import:default
# Start ZoneAccess service, other services are disabled by default.
start_service "Zone access service" "virtualbox/zoneaccess" "svc:/application/virtualbox/zoneaccess:default" \
"/var/svc/log/application-virtualbox-zoneaccess:default.log"
fi
fi
# Update mime and desktop databases to get the right menu entries
# and icons. There is still some delay until the GUI picks it up,
# but that cannot be helped.
if test -d "$PKG_INSTALL_ROOT/usr/share/icons"; then
infoprint "Installing MIME types and icons..."
if test "$REMOTEINST" -eq 0; then
/usr/bin/update-mime-database /usr/share/mime >/dev/null 2>&1
/usr/bin/update-desktop-database -q 2>/dev/null
else
subprint "Skipped for targetted installs."
fi
fi
# Install python bindings for non-remote installs
if test "$REMOTEINST" -eq 0; then
if test -f "$DIR_VBOXBASE/sdk/installer/vboxapisetup.py" || test -h "$DIR_VBOXBASE/sdk/installer/vboxapisetup.py"; then
PYTHONBIN=`which python 2> /dev/null`
if test -f "$PYTHONBIN" || test -h "$PYTHONBIN"; then
infoprint "Installing Python bindings..."
INSTALLEDIT=1
PYTHONBIN=`which python2.4 2>/dev/null`
install_python_bindings "$PYTHONBIN" "Python 2.4"
if test "$?" -eq 0; then
INSTALLEDIT=0
fi
PYTHONBIN=`which python2.5 2>/dev/null`
install_python_bindings "$PYTHONBIN" "Python 2.5"
if test "$?" -eq 0; then
INSTALLEDIT=0
fi
PYTHONBIN=`which python2.6 2>/dev/null`
install_python_bindings "$PYTHONBIN" "Python 2.6"
if test "$?" -eq 0; then
INSTALLEDIT=0
fi
# remove files installed by Python build
rm -rf $DIR_VBOXBASE/sdk/installer/build
if test "$INSTALLEDIT" -ne 0; then
warnprint "No suitable Python version found. Required Python 2.4, 2.5 or 2.6."
warnprint "Skipped installing the Python bindings."
fi
else
warnprint "Python not found, skipped installed Python bindings."
fi
fi
else
warnprint "Skipped installing Python bindings. Run, as root, 'vboxapisetup.py install' manually from the booted system."
fi
update_boot_archive
return 0
else
errorprint "Failed to install drivers"
exit 666
fi
return 1
}
# preremove([fatal])
# failure: depends on [fatal]
preremove()
{
fatal=$1
cleanup_install "$fatal"
remove_drivers "$fatal"
if test "$?" -eq 0; then
return 0;
fi
return 1
}
# And it begins...
if test "x${PKG_INSTALL_ROOT:=/}" != "x/"; then
BASEDIR_OPT="-b $PKG_INSTALL_ROOT"
BASEDIR_PKGOPT="-R $PKG_INSTALL_ROOT"
REMOTEINST=1
fi
find_bins
check_root
check_isa
check_zone
get_sysinfo
# Get command line options
while test $# -gt 0;
do
case "$1" in
--postinstall | --preremove | --installdrivers | --removedrivers | --setupdrivers)
drvop="$1"
;;
--fatal)
fatal="$FATALOP"
;;
--silent)
ISSILENT="$SILENTOP"
;;
--ips)
ISIPS="$IPSOP"
;;
--altkerndir)
# Use alternate kernel driver config folder (dev only)
DIR_CONF="/usr/kernel/drv"
;;
--sh-trace) # forwarded pkgadd -v
set -x
;;
--help)
printusage
exit 1
;;
*)
# Take a hard line on invalid options.
errorprint "Invalid command line option: \"$1\""
exit 1;
;;
esac
shift
done
case "$drvop" in
--postinstall)
check_module_arch
postinstall
;;
--preremove)
preremove "$fatal"
;;
--installdrivers)
check_module_arch
install_drivers
;;
--removedrivers)
remove_drivers "$fatal"
;;
--setupdrivers)
remove_drivers "$fatal"
infoprint "Installing VirtualBox drivers:"
install_drivers
;;
*)
printusage
exit 1
esac
exit "$?"