diff options
Diffstat (limited to 'src/VBox/Installer')
93 files changed, 5705 insertions, 1418 deletions
diff --git a/src/VBox/Installer/darwin/DiskImage/VirtualBox_Uninstall.tool b/src/VBox/Installer/darwin/DiskImage/VirtualBox_Uninstall.tool index 31b70047..9f5150fa 100755 --- a/src/VBox/Installer/darwin/DiskImage/VirtualBox_Uninstall.tool +++ b/src/VBox/Installer/darwin/DiskImage/VirtualBox_Uninstall.tool @@ -1,8 +1,11 @@ -#!/bin/sh -# +#!/bin/bash +# $Id: VirtualBox_Uninstall.tool $ +## @file # VirtualBox Uninstaller Script. # -# Copyright (C) 2007-2010 Oracle Corporation + +# +# Copyright (C) 2007-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; @@ -45,69 +48,82 @@ fi # Collect directories and files to remove. # Note: Do NOT attempt adding directories or filenames with spaces! # -my_directories="" -my_files="" +declare -a my_directories +declare -a my_files # Users files first -test -f "${HOME}/Library/LaunchAgents/org.virtualbox.vboxwebsrv.plist" && my_files="$my_files ${HOME}/Library/LaunchAgents/org.virtualbox.vboxwebsrv.plist" - -test -d /Library/StartupItems/VirtualBox/ && my_directories="$my_directories /Library/StartupItems/VirtualBox/" -test -d /Library/Receipts/VBoxStartupItems.pkg/ && my_directories="$my_directories /Library/Receipts/VBoxStartupItems.pkg/" - -test -d /Library/Extensions/VBoxDrv.kext/ && my_directories="$my_directories /Library/Extensions/VBoxDrv.kext/" -test -d /Library/Extensions/VBoxUSB.kext/ && my_directories="$my_directories /Library/Extensions/VBoxUSB.kext/" -test -d /Library/Extensions/VBoxNetFlt.kext/ && my_directories="$my_directories /Library/Extensions/VBoxNetFlt.kext/" -test -d /Library/Extensions/VBoxNetAdp.kext/ && my_directories="$my_directories /Library/Extensions/VBoxNetAdp.kext/" +test -f "${HOME}/Library/LaunchAgents/org.virtualbox.vboxwebsrv.plist" && my_files+=("${HOME}/Library/LaunchAgents/org.virtualbox.vboxwebsrv.plist") + +test -d /Library/StartupItems/VirtualBox/ && my_directories+=("/Library/StartupItems/VirtualBox/") +test -d /Library/Receipts/VBoxStartupItems.pkg/ && my_directories+=("/Library/Receipts/VBoxStartupItems.pkg/") + +test -d "/Library/Application Support/VirtualBox/LaunchDaemons/" && my_directories+=("/Library/Application Support/VirtualBox/LaunchDaemons/") +test -d "/Library/Application Support/VirtualBox/VBoxDrv.kext/" && my_directories+=("/Library/Application Support/VirtualBox/VBoxDrv.kext/") +test -d "/Library/Application Support/VirtualBox/VBoxUSB.kext/" && my_directories+=("/Library/Application Support/VirtualBox/VBoxUSB.kext/") +test -d "/Library/Application Support/VirtualBox/VBoxNetFlt.kext/" && my_directories+=("/Library/Application Support/VirtualBox/VBoxNetFlt.kext/") +test -d "/Library/Application Support/VirtualBox/VBoxNetAdp.kext/" && my_directories+=("/Library/Application Support/VirtualBox/VBoxNetAdp.kext/") +# Pre 4.3.0rc1 locations: +test -d /Library/Extensions/VBoxDrv.kext/ && my_directories+=("/Library/Extensions/VBoxDrv.kext/") +test -d /Library/Extensions/VBoxUSB.kext/ && my_directories+=("/Library/Extensions/VBoxUSB.kext/") +test -d /Library/Extensions/VBoxNetFlt.kext/ && my_directories+=("/Library/Extensions/VBoxNetFlt.kext/") +test -d /Library/Extensions/VBoxNetAdp.kext/ && my_directories+=("/Library/Extensions/VBoxNetAdp.kext/") # Tiger support is obsolete, but we leave it here for a clean removing of older # VirtualBox versions -test -d /Library/Extensions/VBoxDrvTiger.kext/ && my_directories="$my_directories /Library/Extensions/VBoxDrvTiger.kext/" -test -d /Library/Extensions/VBoxUSBTiger.kext/ && my_directories="$my_directories /Library/Extensions/VBoxUSBTiger.kext/" -test -d /Library/Receipts/VBoxKEXTs.pkg/ && my_directories="$my_directories /Library/Receipts/VBoxKEXTs.pkg/" - -test -f /usr/bin/VirtualBox && my_files="$my_files /usr/bin/VirtualBox" -test -f /usr/bin/VBoxManage && my_files="$my_files /usr/bin/VBoxManage" -test -f /usr/bin/VBoxVRDP && my_files="$my_files /usr/bin/VBoxVRDP" -test -f /usr/bin/VBoxHeadless && my_files="$my_files /usr/bin/VBoxHeadless" -test -f /usr/bin/vboxwebsrv && my_files="$my_files /usr/bin/vboxwebsrv" -test -f /usr/bin/VBoxBalloonCtrl && my_files="$my_files /usr/bin/VBoxBalloonCtrl" -test -f /usr/bin/VBoxAutostart && my_files="$my_files /usr/bin/VBoxAutostart" -test -f /usr/bin/vbox-img && my_files="$my_files /usr/bin/vbox-img" -test -d /Library/Receipts/VirtualBoxCLI.pkg/ && my_directories="$my_directories /Library/Receipts/VirtualBoxCLI.pkg/" - -test -d /Applications/VirtualBox.app/ && my_directories="$my_directories /Applications/VirtualBox.app/" -test -d /Library/Receipts/VirtualBox.pkg/ && my_directories="$my_directories /Library/Receipts/VirtualBox.pkg/" +test -d /Library/Extensions/VBoxDrvTiger.kext/ && my_directories+=("/Library/Extensions/VBoxDrvTiger.kext/") +test -d /Library/Extensions/VBoxUSBTiger.kext/ && my_directories+=("/Library/Extensions/VBoxUSBTiger.kext/") +test -d /Library/Receipts/VBoxKEXTs.pkg/ && my_directories+=("/Library/Receipts/VBoxKEXTs.pkg/") + +test -f /usr/bin/VirtualBox && my_files+=("/usr/bin/VirtualBox") +test -f /usr/bin/VBoxManage && my_files+=("/usr/bin/VBoxManage") +test -f /usr/bin/VBoxVRDP && my_files+=("/usr/bin/VBoxVRDP") +test -f /usr/bin/VBoxHeadless && my_files+=("/usr/bin/VBoxHeadless") +test -f /usr/bin/vboxwebsrv && my_files+=("/usr/bin/vboxwebsrv") +test -f /usr/bin/VBoxBalloonCtrl && my_files+=("/usr/bin/VBoxBalloonCtrl") +test -f /usr/bin/VBoxAutostart && my_files+=("/usr/bin/VBoxAutostart") +test -f /usr/bin/vbox-img && my_files+=("/usr/bin/vbox-img") +test -d /Library/Receipts/VirtualBoxCLI.pkg/ && my_directories+=("/Library/Receipts/VirtualBoxCLI.pkg/") +test -f /Library/LaunchDaemons/org.virtualbox.startup.plist && my_files+=("/Library/LaunchDaemons/org.virtualbox.startup.plist") + +test -d /Applications/VirtualBox.app/ && my_directories+=("/Applications/VirtualBox.app/") +test -d /Library/Receipts/VirtualBox.pkg/ && my_directories+=("/Library/Receipts/VirtualBox.pkg/") # legacy -test -d /Library/Receipts/VBoxDrv.pkg/ && my_directories="$my_directories /Library/Receipts/VBoxDrv.pkg/" -test -d /Library/Receipts/VBoxUSB.pkg/ && my_directories="$my_directories /Library/Receipts/VBoxUSB.pkg/" +test -d /Library/Receipts/VBoxDrv.pkg/ && my_directories+=("/Library/Receipts/VBoxDrv.pkg/") +test -d /Library/Receipts/VBoxUSB.pkg/ && my_directories+=("/Library/Receipts/VBoxUSB.pkg/") # python stuff python_versions="2.3 2.5 2.6 2.7" for p in $python_versions; do - test -f /Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.py && my_files="$my_files /Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.py" - test -f /Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.pyc && my_files="$my_files /Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.pyc" - test -f /Library/Python/$p/site-packages/vboxapi/__init__.py && my_files="$my_files /Library/Python/$p/site-packages/vboxapi/__init__.py" - test -f /Library/Python/$p/site-packages/vboxapi/__init__.pyc && my_files="$my_files /Library/Python/$p/site-packages/vboxapi/__init__.pyc" - test -f /Library/Python/$p/site-packages/vboxapi-1.0-py$p.egg-info && my_files="$my_files /Library/Python/$p/site-packages/vboxapi-1.0-py$p.egg-info" - test -d /Library/Python/$p/site-packages/vboxapi/ && my_directories="$my_directories /Library/Python/$p/site-packages/vboxapi/" + test -f /Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.py && my_files+=("/Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.py") + test -f /Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.pyc && my_files+=("/Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.pyc") + test -f /Library/Python/$p/site-packages/vboxapi/__init__.py && my_files+=("/Library/Python/$p/site-packages/vboxapi/__init__.py") + test -f /Library/Python/$p/site-packages/vboxapi/__init__.pyc && my_files+=("/Library/Python/$p/site-packages/vboxapi/__init__.pyc") + test -f /Library/Python/$p/site-packages/vboxapi-1.0-py$p.egg-info && my_files+=("/Library/Python/$p/site-packages/vboxapi-1.0-py$p.egg-info") + test -d /Library/Python/$p/site-packages/vboxapi/ && my_directories+=("/Library/Python/$p/site-packages/vboxapi/") done # # Collect KEXTs to remove. # Note that the unload order is significant. # -my_kexts="" +declare -a my_kexts for kext in org.virtualbox.kext.VBoxUSB org.virtualbox.kext.VBoxNetFlt org.virtualbox.kext.VBoxNetAdp org.virtualbox.kext.VBoxDrv; do if /usr/sbin/kextstat -b $kext -l | grep -q $kext; then - my_kexts="$my_kexts $kext" + my_kexts+=("$kext") fi done # +# Collect packages to forget +# +my_pb='org\.virtualbox\.pkg\.' +my_pkgs=`/usr/sbin/pkgutil --pkgs="${my_pb}vboxkexts|${my_pb}vboxstartupitems|${my_pb}virtualbox|${my_pb}virtualboxcli"` + +# # Did we find anything to uninstall? # -if test -z "$my_directories" -a -z "$my_files" -a -z "$my_kexts"; then - echo "No VirtualBox files, directories or KEXTs to uninstall." +if test -z "${my_directories[*]}" -a -z "${my_files[*]}" -a -z "${my_kexts[*]}" -a -z "$my_pkgs"; then + echo "No VirtualBox files, directories, KEXTs or packages to uninstall." echo "Done." exit 0; fi @@ -120,7 +136,7 @@ fi # # Note! comm isn't supported on Tiger, so we make -c to do the stripping. # -my_processes="`ps -axco 'pid uid command' | grep -wEe '(VirtualBox|VirtualBoxVM|VBoxManage|VBoxHeadless|vboxwebsrv|VBoxXPCOMIPCD|VBoxSVC|VBoxNetDHCP)' | grep -vw grep | grep -vw VirtualBox_Uninstall.tool | tr '\n' '\a'`"; +my_processes="`ps -axco 'pid uid command' | grep -wEe '(VirtualBox|VirtualBoxVM|VBoxManage|VBoxHeadless|vboxwebsrv|VBoxXPCOMIPCD|VBoxSVC|VBoxNetDHCP|VBoxNetNAT)' | grep -vw grep | grep -vw VirtualBox_Uninstall.tool | tr '\n' '\a'`"; if test -n "$my_processes"; then echo 'Warning! Found the following active VirtualBox processes:' echo "$my_processes" | tr '\a' '\n' @@ -144,16 +160,22 @@ fi # Display the files and directories that will be removed # and get the user's consent before continuing. # -if test -n "$my_files" -o -n "$my_directories"; then +if test -n "${my_files[*]}" -o -n "${my_directories[*]}"; then echo "The following files and directories (bundles) will be removed:" - for file in $my_files; do echo " $file"; done - for dir in $my_directories; do echo " $dir"; done + for file in "${my_files[@]}"; do echo " $file"; done + for dir in "${my_directories[@]}"; do echo " $dir"; done + echo "" fi -if test -n "$my_kexts"; then -echo "And the following KEXTs will be unloaded:" - for kext in $my_kexts; do echo " $kext"; done +if test -n "${my_kexts[*]}"; then + echo "And the following KEXTs will be unloaded:" + for kext in "${my_kexts[@]}"; do echo " $kext"; done + echo "" +fi +if test -n "$my_pkgs"; then + echo "And the traces of following packages will be removed:" + for kext in $my_pkgs; do echo " $kext"; done + echo "" fi -echo "" if test "$my_default_prompt" != "Yes"; then echo "Do you wish to uninstall VirtualBox (Yes/No)?" @@ -182,8 +204,8 @@ echo "because some of the installed files cannot be removed by a normal" echo "user. You may be prompted for your password now..." echo "" -if test -n "$my_files" -o -n "$my_directories"; then - /usr/bin/sudo -p "Please enter %u's password:" /bin/rm -Rf $my_files $my_directories +if test -n "${my_files[*]}" -o -n "${my_directories[*]}"; then + /usr/bin/sudo -p "Please enter %u's password:" /bin/rm -Rf "${my_files[@]}" "${my_directories[@]}" my_rc=$? if test "$my_rc" -ne 0; then echo "An error occurred durning 'sudo rm', there should be a message above. (rc=$my_rc)" @@ -196,7 +218,7 @@ if test -n "$my_files" -o -n "$my_directories"; then fi my_rc=0 -for kext in $my_kexts; do +for kext in "${my_kexts[@]}"; do echo unloading $kext /usr/bin/sudo -p "Please enter %u's password (unloading $kext):" /sbin/kextunload -m $kext my_rc2=$? @@ -208,10 +230,17 @@ for kext in $my_kexts; do fi done if test "$my_rc" -eq 0; then - echo "Successfully uninstalled VirtualBox." + echo "Successfully unloaded VirtualBox kernel extensions." else - echo "Failed to unload on or more KEXTs, please reboot the machine to complete the uninstall." + echo "Failed to unload one or more KEXTs, please reboot the machine to complete the uninstall." + exit 1; fi + +# Cleaning up pkgutil database +for my_pkg in $my_pkgs; do + /usr/bin/sudo -p "Please enter %u's password (removing $my_pkg):" /usr/sbin/pkgutil --forget "$my_pkg" +done + echo "Done." exit 0; diff --git a/src/VBox/Installer/darwin/Makefile.kmk b/src/VBox/Installer/darwin/Makefile.kmk index a4f901b0..e3bdfaa1 100644 --- a/src/VBox/Installer/darwin/Makefile.kmk +++ b/src/VBox/Installer/darwin/Makefile.kmk @@ -165,7 +165,6 @@ endif # The meta-package. # $(VBOX_PATH_PACK_TMP)/DiskImage/VirtualBox.pkg: \ - $(VBOX_PATH_PACK_TMP)/Packages/VBoxStartupItems.pkg \ $(VBOX_PATH_PACK_TMP)/Packages/VBoxKEXTs.pkg \ $(VBOX_PATH_PACK_TMP)/Packages/VirtualBoxCLI.pkg \ $(VBOX_PATH_PACK_TMP)/Packages/VirtualBox.pkg \ @@ -232,14 +231,13 @@ $(VBOX_PATH_PACK_TMP)/DiskImage/VirtualBox.pkg: \ --identifier org.VirtualBox.mpkg.virtualbox \ --version $(VBOX_VERSION_MAJOR).$(VBOX_VERSION_MINOR).$(VBOX_VERSION_BUILD) \ $(if $(VBOX_MACOSX_INSTALLER_SIGN),--sign "$(VBOX_MACOSX_INSTALLER_SIGN)",) \ - $@ + $@ @# Cleanup. sudo rm -Rf \ $(VBOX_PATH_PACK_TMP)/VirtualBox.dist.root \ $(VBOX_PATH_PACK_TMP)/VirtualBox.dist.desc \ $(VBOX_PATH_PACK_TMP)/VirtualBox.dist.res -VirtualBox.pkg:: $(VBOX_PATH_PACK_TMP)/DiskImage/VirtualBox.pkg # # The VirtualBox Kernel extensions. @@ -270,35 +268,40 @@ $(VBOX_PATH_PACK_TMP)/Packages/VBoxKEXTs.pkg: \ $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.desc \ $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.res \ $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.res/English.lproj - $(MKDIR) -p -m 1775 $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/Library $(MKDIR) -p -m 0755 \ - $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/Library/Extensions \ + $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root \ + $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/LaunchDaemons \ $(foreach kext,$(VBOX_DI_KEXTS), \ - $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/Library/Extensions/$(kext).kext \ - $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/Library/Extensions/$(kext).kext/Contents \ - $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/Library/Extensions/$(kext).kext/Contents/MacOS ) + $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/$(kext).kext \ + $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/$(kext).kext/Contents \ + $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/$(kext).kext/Contents/MacOS ) + @# Copy the launch daemon bits. + $(INSTALL) -m 0755 $(VBOX_PATH_DI_SRC)/VBoxKEXTs/VirtualBoxStartup.sh $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/LaunchDaemons/ + $(INSTALL) -m 0644 $(VBOX_PATH_DI_SRC)/VBoxKEXTs/org.virtualbox.startup.plist $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/LaunchDaemons/ @# Copy the common files (Info.plist). $(foreach kext,$(VBOX_DI_KEXTS), \ - $(NLTAB)$(INSTALL) -m 0644 $(VBOX_PATH_DIST)/$(kext).kext/Contents/Info.plist $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/Library/Extensions/$(kext).kext/Contents/) + $(NLTAB)$(INSTALL) -m 0644 $(VBOX_PATH_DIST)/$(kext).kext/Contents/Info.plist $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/$(kext).kext/Contents/) @# Copy the binaries and invoking lipo. ifdef VBOX_WITH_COMBINED_PACKAGE $(foreach kext,$(VBOX_DI_KEXTS_UNIVERSAL), \ $(NLTAB)$(VBOX_DI_LIPO) -create \ $(VBOX_PATH_DIST_32)/$(kext).kext/Contents/MacOS/$(kext) \ $(VBOX_PATH_DIST_64)/$(kext).kext/Contents/MacOS/$(kext) \ - -output $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/Library/Extensions/$(kext).kext/Contents/MacOS/$(kext)) + -output $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/$(kext).kext/Contents/MacOS/$(kext)) else $(foreach kext,$(VBOX_DI_KEXTS), \ - $(NLTAB)$(INSTALL) -m 0755 $(VBOX_PATH_DIST)/$(kext).kext/Contents/MacOS/$(kext) $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/Library/Extensions/$(kext).kext/Contents/MacOS/) + $(NLTAB)$(INSTALL) -m 0755 $(VBOX_PATH_DIST)/$(kext).kext/Contents/MacOS/$(kext) $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/$(kext).kext/Contents/MacOS/) endif @# Signed the kext bundles. ifdef VBOX_SIGNING_MODE + $(foreach kext,$(VBOX_DI_KEXTS) \ + ,$(NLTAB)$(call VBOX_SIGN_MACHO_FN,$(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/$(kext).kext/Contents/MacOS/$(kext),org.virtualbox.app.kext.$(kext)) ) $(foreach kext,$(VBOX_DI_KEXTS), \ - $(NLTAB)$(call VBOX_SIGN_BUNDLE_FN,$(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/Library/Extensions/$(kext).kext,) ) + $(NLTAB)$(call VBOX_SIGN_BUNDLE_FN,$(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/$(kext).kext,org.virtualbox.app.kext.$(kext)) ) +## @TODO check why this fails on the build box: $(foreach kext,$(VBOX_DI_KEXTS), $(NLTAB)codesign --verify --verbose=1 $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/$(kext).kext ) endif @# Set the correct owners. - sudo chown root:admin $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/Library - sudo chown -R root:wheel $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/Library/Extensions + sudo chown -R root:wheel $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/ @# Do keyword replacement in the package info and description files. $(SED) \ -e 's/@VBOX_VERSION_STRING@/$(VBOX_VERSION_STRING)/g' \ @@ -314,12 +317,12 @@ endif $(INSTALL) -m 0755 $(VBOX_PATH_DI_SRC)/VBoxKEXTs/postflight $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.res/ @# Build the package. $(VBOX_PKGBUILD) \ - --root $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/Library/Extensions/ \ + --root $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.root/ \ --component-plist $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.desc/PkgBuildComponent.plist \ --script $(VBOX_PATH_PACK_TMP)/VBoxKEXTs.pkg.res \ --identifier org.virtualbox.pkg.vboxkexts \ --version $(VBOX_VERSION_MAJOR).$(VBOX_VERSION_MINOR).$(VBOX_VERSION_BUILD) \ - --install-location /Library/Extensions/ \ + --install-location "/Library/Application Support/VirtualBox" \ --ownership preserve \ $(if $(VBOX_MACOSX_INSTALLER_SIGN),--sign "$(VBOX_MACOSX_INSTALLER_SIGN)",) \ $@ @@ -333,61 +336,6 @@ endif # -# The VirtualBox Startupitems. -# -$(VBOX_PATH_PACK_TMP)/Packages/VBoxStartupItems.pkg: \ - $$(wildcard $(VBOX_PATH_DI_SRC)/VBoxStartupItems/VirtualBox/* \ - $(VBOX_PATH_DI_SRC)/VBoxStartupItems/VirtualBox/Resources/*.lproj/*) \ - $$(wildcard $(VBOX_PATH_DI_SRC)/VBoxStartupItems/* \ - $(VBOX_PATH_DI_SRC)/VBoxStartupItems/*.lproj/*) \ - $(foreach f,$(VBOX_INSTALLER_ADD_LANGUAGES), \ - $(VBOX_BRAND_$(f)_VBOXSTARTUPITEMS_DESCRIPTION_PLIST)) \ - $(VBOX_DARWIN_INST_DEP_ON_MAKEFILE) - $(call MSG_TOOL,pkgbuild,,,$@) - @# Cleanup any previously failed attempts. - sudo rm -Rf \ - $@ \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.desc \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.res - @# Correct directory permissions are important. - $(MKDIR) -p \ - $(@D) \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.desc \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.res \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.res/English.lproj - $(MKDIR) -p -m 0775 $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root/Library - $(MKDIR) -p -m 0755 \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root/Library/StartupItems \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root/Library/StartupItems/VirtualBox \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root/Library/StartupItems/VirtualBox/Resources \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root/Library/StartupItems/VirtualBox/Resources/English.lproj - @# Copy the files. - $(INSTALL) -m 0644 $(VBOX_PATH_DI_SRC)/VBoxStartupItems/VirtualBox/StartupParameters.plist $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root/Library/StartupItems/VirtualBox/ - $(INSTALL) -m 0755 $(VBOX_PATH_DI_SRC)/VBoxStartupItems/VirtualBox/VirtualBox $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root/Library/StartupItems/VirtualBox/ - $(INSTALL) -m 0644 $(VBOX_PATH_DI_SRC)/VBoxStartupItems/VirtualBox/Resources/English.lproj/Localizable.strings $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root/Library/StartupItems/VirtualBox/Resources/English.lproj/ - @# Set the correct owners. - sudo chown root:admin $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root/Library - sudo chown -R root:wheel $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root/Library/StartupItems - @# Build the package. - $(VBOX_PKGBUILD) \ - --root $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root/Library/StartupItems/ \ - --identifier org.virtualbox.pkg.vboxstartupitems \ - --version $(VBOX_VERSION_MAJOR).$(VBOX_VERSION_MINOR).$(VBOX_VERSION_BUILD) \ - --install-location /Library/StartupItems/ \ - --ownership preserve \ - $(if $(VBOX_MACOSX_INSTALLER_SIGN),--sign "$(VBOX_MACOSX_INSTALLER_SIGN)",) \ - $@ - @# Cleanup - sudo chown -R "$(shell whoami)" \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root/Library - sudo rm -Rf \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.root \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.desc \ - $(VBOX_PATH_PACK_TMP)/VBoxStartupItems.pkg.res - - -# # Figure out which languages that we support and construct # .qm and .lproj lists for these. # @@ -407,10 +355,10 @@ VBOX_DI_VBAPP_DYLIBS = \ MacOS/VBoxDDU.dylib \ MacOS/VBoxREM.dylib \ MacOS/VBoxRT.dylib \ - MacOS/VBoxSharedFolders.dylib \ - MacOS/VBoxSharedClipboard.dylib \ - MacOS/VBoxDragAndDropSvc.dylib \ - MacOS/VBoxGuestPropSvc.dylib \ + $(if $(VBOX_WITH_SHARED_FOLDERS),MacOS/VBoxSharedFolders.dylib,) \ + $(if $(VBOX_WITH_SHARED_CLIPBOARD),MacOS/VBoxSharedClipboard.dylib,) \ + $(if $(VBOX_WITH_DRAG_AND_DROP),MacOS/VBoxDragAndDropSvc.dylib,) \ + $(if $(VBOX_WITH_GUEST_PROPS),MacOS/VBoxGuestPropSvc.dylib,) \ MacOS/VBoxHostChannel.dylib \ MacOS/VBoxVMM.dylib \ MacOS/VBoxXPCOM.dylib \ @@ -419,15 +367,12 @@ VBOX_DI_VBAPP_DYLIBS = \ MacOS/components/VBoxSVCM.dylib \ MacOS/components/VBoxXPCOMIPCC.dylib \ MacOS/VBoxAuth.dylib \ - MacOS/VBoxAuthSimple.dylib + MacOS/VBoxAuthSimple.dylib \ + $(if $(VBOX_WITH_GUEST_CONTROL),MacOS/VBoxGuestControlSvc.dylib,) ifneq ($(wildcard $(VBOX_PATH_DIST)/VirtualBox.app/Contents/MacOS/accessible/libqtaccessiblewidgets.dylib),) VBOX_DI_VBAPP_DYLIBS += \ MacOS/accessible/libqtaccessiblewidgets.dylib endif -ifdef VBOX_WITH_GUEST_CONTROL - VBOX_DI_VBAPP_DYLIBS += \ - MacOS/VBoxGuestControlSvc.dylib -endif if defined(VBOX_WITH_VRDP) && !defined(VBOX_WITH_EXTPACK_PUEL) VBOX_DI_VBAPP_DYLIBS += \ MacOS/VBoxVRDP.dylib @@ -447,6 +392,7 @@ ifdef VBOX_WITH_HARDENING VBOX_DI_VBAPP_DYLIBS += \ MacOS/VirtualBox.dylib \ MacOS/VBoxNetDHCP.dylib \ + MacOS/VBoxNetNAT.dylib \ MacOS/VBoxHeadless.dylib endif ifdef VBOX_WITH_HDDPARALLELS_INSTALL @@ -494,17 +440,15 @@ VBOX_DI_VBAPP_PROGS = \ MacOS/VBoxSVC \ MacOS/VBoxHeadless \ MacOS/VBoxXPCOMIPCD \ - MacOS/VirtualBox \ - MacOS/VirtualBoxVM \ MacOS/VBoxNetAdpCtl \ MacOS/VBoxNetDHCP \ + MacOS/VBoxNetNAT \ MacOS/VBoxExtPackHelperApp \ MacOS/VBoxBalloonCtrl \ - MacOS/VBoxAutostart -ifdef VBOX_WITH_WEBSERVICES - VBOX_DI_VBAPP_PROGS += \ - MacOS/vboxwebsrv -endif + MacOS/VBoxAutostart \ + MacOS/VirtualBoxVM \ + $(if $(VBOX_WITH_WEBSERVICES),MacOS/vboxwebsrv) \ + MacOS/VirtualBox VBOX_DI_VBAPP_UNIVERSAL_PROGS = \ MacOS/vmstarter @@ -677,9 +621,9 @@ $(VBOX_PATH_PACK_TMP)/Packages/VirtualBox.pkg: \ ifdef VBOX_WITH_WEBSERVICES $(INSTALL) -m 0644 $(VBOX_PATH_DI_SRC)/VirtualBox/org.virtualbox.vboxwebsrv.plist $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/MacOS/ endif - $(INSTALL) -m 0644 $(VBOX_PATH_DI_SRC)/VirtualBox/org.virtualbox.vboxballoonctrl.plist $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/MacOS/ - $(INSTALL) -m 0644 $(VBOX_PATH_DI_SRC)/VirtualBox/org.virtualbox.vboxautostart.plist $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/MacOS/ - $(INSTALL) -m 0644 $(VBOX_PATH_DI_SRC)/VirtualBox/VBoxAutostartDarwin.sh $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/MacOS/ + $(INSTALL) -m 0644 $(VBOX_PATH_DI_SRC)/VirtualBox/org.virtualbox.vboxballoonctrl.plist $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/MacOS/ + $(INSTALL) -m 0644 $(VBOX_PATH_DI_SRC)/VirtualBox/org.virtualbox.vboxautostart.plist $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/MacOS/ + $(INSTALL) -m 0755 $(VBOX_PATH_DI_SRC)/VirtualBox/VBoxAutostartDarwin.sh $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/MacOS/ @# Install the python stuff ifdef VBOX_WITH_PYTHON $(foreach f,$(VBOX_DI_VBAPP_PYTHON_FILES) \ @@ -806,6 +750,21 @@ ifdef VBOX_SIGNING_MODE , $(NLTAB)$(call VBOX_SIGN_MACHO_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/$(dylib),org.virtualbox.app.macos.$(notdir $(dylib))) ) $(foreach bin, $(VBOX_DI_VBAPP_UNIVERSAL_PROGS) \ , $(NLTAB)$(call VBOX_SIGN_MACHO_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/$(bin),org.virtualbox.app.macos.$(notdir $(bin))) ) + ifdef VBOX_NOT_OSX_105 # Still being hacked on, everything needs to be signed that lives in Contents/MacOS, guess we have to MOVE files out. + $(foreach other, $(VBOX_DI_VBAPP_OTHER_UNIVERSAL_BINS) \ + , $(NLTAB)$(call VBOX_SIGN_MACHO_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/$(other),org.virtualbox.app.macos.$(notdir $(other))) ) + $(foreach arch, $(if-expr defined(VBOX_WITH_COMBINED_PACKAGE), amd64 x86, $(KBUILD_TARGET_ARCH)) \ + , $(foreach other, $(VBOX_DI_VBAPP_OTHER_BINS) \ + , $(NLTAB)$(call VBOX_SIGN_MACHO_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/$(other)-$(arch),org.virtualbox.app.macos.$(notdir $(other))-$(arch)) ) ) + $(foreach other, $(filter MacOS/%,$(VBOX_DI_VBAPP_MISC_FILES)) \ + , $(NLTAB)$(call VBOX_SIGN_VMM_MOD_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/$(other),org.virtualbox.app.macos.$(notdir $(other))) ) + else + $(foreach other, $(VBOX_DI_VBAPP_OTHER_UNIVERSAL_BINS) \ + , $(NLTAB)$(call VBOX_SIGN_VMM_MOD_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/$(other),org.virtualbox.app.macos.$(notdir $(other))) ) + $(foreach arch, $(if-expr defined(VBOX_WITH_COMBINED_PACKAGE), amd64 x86, $(KBUILD_TARGET_ARCH)) \ + , $(foreach other, $(VBOX_DI_VBAPP_OTHER_BINS) \ + , $(NLTAB)$(call VBOX_SIGN_VMM_MOD_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/$(other)-$(arch),org.virtualbox.app.macos.$(notdir $(other))-$(arch)) ) ) + endif $(foreach arch, $(if-expr defined(VBOX_WITH_COMBINED_PACKAGE), amd64 x86, $(KBUILD_TARGET_ARCH)) \ , $(foreach bin, $(VBOX_DI_VBAPP_PROGS) \ , \ @@ -813,12 +772,7 @@ ifdef VBOX_SIGNING_MODE $(NLTAB)$(call VBOX_SIGN_MACHO_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/$(bin),org.virtualbox.app.macos.$(notdir $(bin))) \ $(NLTAB)$(MV) -- $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/$(bin) $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/$(bin)-$(arch) \ )) - $(foreach other, $(VBOX_DI_VBAPP_OTHER_UNIVERSAL_BINS) \ - , $(NLTAB)$(call VBOX_SIGN_VMM_MOD_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/$(other),org.virtualbox.app.macos.$(notdir $(other))) ) - $(foreach arch, $(if-expr defined(VBOX_WITH_COMBINED_PACKAGE), amd64 x86, $(KBUILD_TARGET_ARCH)) \ - , $(foreach other, $(VBOX_DI_VBAPP_OTHER_BINS) \ - , $(NLTAB)$(call VBOX_SIGN_VMM_MOD_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/$(other)-$(arch),org.virtualbox.app.macos.$(notdir $(other))-$(arch)) ) ) - if 0 # requires codesign+framworks from Lion or later. Snow Leopard codesign says object file format invalid or unsuitable. + ifdef VBOX_NOT_OSX_105 # requires codesign+framworks from Lion or later. Snow Leopard codesign says object file format invalid or unsuitable. $(call VBOX_SIGN_BUNDLE_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/Resources/VirtualBoxVM.app,) $(call VBOX_SIGN_BUNDLE_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/Resources/vmstarter.app,) $(call VBOX_SIGN_BUNDLE_FN,$(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app,) @@ -829,12 +783,12 @@ endif ifdef VBOX_WITH_HARDENING ifdef VBOX_WITH_COMBINED_PACKAGE sudo chmod u+s \ - $(foreach bin,VBoxHeadless VirtualBox VirtualBoxVM VBoxNetAdpCtl VBoxNetDHCP,\ + $(foreach bin,VBoxHeadless VirtualBox VirtualBoxVM VBoxNetAdpCtl VBoxNetDHCP VBoxNetNAT,\ $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/MacOS/$(bin)-x86 \ $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/MacOS/$(bin)-amd64) else sudo chmod u+s \ - $(foreach bin,VBoxHeadless VirtualBox VirtualBoxVM VBoxNetAdpCtl VBoxNetDHCP,\ + $(foreach bin,VBoxHeadless VirtualBox VirtualBoxVM VBoxNetAdpCtl VBoxNetDHCP VBoxNetNAT,\ $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.root/Applications/VirtualBox.app/Contents/MacOS/$(bin)-$(KBUILD_TARGET_ARCH)) endif endif @@ -850,6 +804,7 @@ endif --output $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.desc/PkgBuildComponent.plist \ $(VBOX_PATH_DI_SRC)/VirtualBox/PkgBuildComponent.plist @# Copy the resources. + $(INSTALL) -m 0755 $(VBOX_PATH_DI_SRC)/VirtualBox/preflight $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.res/ $(INSTALL) -m 0755 $(VBOX_PATH_DI_SRC)/VirtualBox/postflight $(VBOX_PATH_PACK_TMP)/VirtualBox.pkg.res/ @# Build the package. $(VBOX_PKGBUILD) \ @@ -898,22 +853,22 @@ $(VBOX_PATH_PACK_TMP)/Packages/VirtualBoxCLI.pkg: \ $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr \ $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin @# Generate the wrapper scripts. - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VirtualBox '#!/bin/bash' - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VirtualBox 'exec /Applications/VirtualBox.app/Contents/MacOS/VirtualBox "$$@"' - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxManage '#!/bin/bash' - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxManage 'exec /Applications/VirtualBox.app/Contents/MacOS/VBoxManage "$$@"' - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxVRDP '#!/bin/bash' - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxVRDP 'exec /Applications/VirtualBox.app/Contents/MacOS/VBoxHeadless "$$@"' - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxHeadless '#!/bin/bash' - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxHeadless 'exec /Applications/VirtualBox.app/Contents/MacOS/VBoxHeadless "$$@"' + $(APPEND) -tn $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VirtualBox \ + '#!/bin/bash' 'exec /Applications/VirtualBox.app/Contents/MacOS/VirtualBox "$$@"' + $(APPEND) -tn $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxManage \ + '#!/bin/bash' 'exec /Applications/VirtualBox.app/Contents/MacOS/VBoxManage "$$@"' + $(APPEND) -tn $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxVRDP \ + '#!/bin/bash' 'exec /Applications/VirtualBox.app/Contents/MacOS/VBoxHeadless "$$@"' + $(APPEND) -tn $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxHeadless \ + '#!/bin/bash' 'exec /Applications/VirtualBox.app/Contents/MacOS/VBoxHeadless "$$@"' ifdef VBOX_WITH_WEBSERVICES - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/vboxwebsrv '#!/bin/bash' - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/vboxwebsrv 'exec /Applications/VirtualBox.app/Contents/MacOS/vboxwebsrv "$$@"' + $(APPEND) -tn $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/vboxwebsrv \ + '#!/bin/bash' 'exec /Applications/VirtualBox.app/Contents/MacOS/vboxwebsrv "$$@"' endif - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxBalloonCtrl '#!/bin/bash' - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxBalloonCtrl 'exec /Applications/VirtualBox.app/Contents/MacOS/VBoxBalloonCtrl "$$@"' - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxAutostart '#!/bin/bash' - $(APPEND) $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxAutostart 'exec /Applications/VirtualBox.app/Contents/MacOS/VBoxAutostart "$$@"' + $(APPEND) -tn $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxBalloonCtrl \ + '#!/bin/bash' 'exec /Applications/VirtualBox.app/Contents/MacOS/VBoxBalloonCtrl "$$@"' + $(APPEND) -tn $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/VBoxAutostart \ + '#!/bin/bash' 'exec /Applications/VirtualBox.app/Contents/MacOS/VBoxAutostart "$$@"' @# Set the correct owners and file permissions. sudo chmod 0755 $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root/usr/bin/* sudo chown root:admin $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.root @@ -936,3 +891,11 @@ endif $(VBOX_PATH_PACK_TMP)/VirtualBoxCLI.pkg.res +# +# Aliases. +# +VBoxKEXTs.pkg: $(VBOX_PATH_PACK_TMP)/Packages/VBoxKEXTs.pkg +VirtualBoxCLI.pkg: $(VBOX_PATH_PACK_TMP)/Packages/VirtualBoxCLI.pkg +VirtualBox.pkg: $(VBOX_PATH_PACK_TMP)/Packages/VirtualBox.pkg +VirtualBox.mpkg: $(VBOX_PATH_PACK_TMP)/DiskImage/VirtualBox.pkg +VirtualBox.dmg: $(VBOX_PATH_DIST)/VirtualBox-$(VBOX_VERSION_MAJOR).$(VBOX_VERSION_MINOR).$(VBOX_VERSION_BUILD)-r$(VBOX_SVN_REV).dmg diff --git a/src/VBox/Installer/darwin/VBoxStartupItems/VirtualBox/VirtualBox b/src/VBox/Installer/darwin/VBoxKEXTs/VirtualBoxStartup.sh index b44af242..c132ccdb 100755 --- a/src/VBox/Installer/darwin/VBoxStartupItems/VirtualBox/VirtualBox +++ b/src/VBox/Installer/darwin/VBoxKEXTs/VirtualBoxStartup.sh @@ -1,7 +1,12 @@ #!/bin/sh +# $Id: VirtualBoxStartup.sh $ +## @file +# Startup service for loading the kernel extensions and select the set of VBox +# binaries that matches the kernel architecture. +# # -# Copyright (C) 2007-2010 Oracle Corporation +# Copyright (C) 2007-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; @@ -12,7 +17,52 @@ # hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. # -. /etc/rc.common +if false; then + . /etc/rc.common +else + # Fake the startup item functions we're using. + + ConsoleMessage() + { + if [ "$1" != "-f" ]; then + echo "$@" + else + shift + echo "Fatal error: $@" + exit 1; + fi + } + + RunService() + { + case "$1" in + "start") + StartService + exit $?; + ;; + "stop") + StopService + exit $?; + ;; + "restart") + RestartService + exit $?; + ;; + "launchd") + if RestartService; then + while true; + do + sleep 3600 + done + fi + exit $?; + ;; + **) + echo "Error: Unknown action '$1'" + exit 1; + esac + } +fi StartService() @@ -35,8 +85,8 @@ StartService() VBOX_LINKNAME=`echo "$VBOX_TRG" | sed -e 's|-'"${VBOX_ARCH}"'$||' ` if test "$VBOX_LINKNAME" != "$VBOX_TRG"; then rm -f "$VBOX_LINKNAME" - if ! ln -vh "$VBOX_TRG" "$VBOX_LINKNAME"; then - ConsoleMessage "Error: ln -vh $VBOX_TRG $VBOX_LINKNAME failed" + if ! /bin/ln -vh "$VBOX_TRG" "$VBOX_LINKNAME"; then + ConsoleMessage "Error: /bin/ln -vh $VBOX_TRG $VBOX_LINKNAME failed" VBOX_RC=1 fi else @@ -48,20 +98,20 @@ StartService() # # Check that all the directories exist first. # - if [ ! -d /Library/Extensions/${VBOXDRV}.kext ]; then - ConsoleMessage "Error: /Library/Extensions/${VBOXDRV}.kext is missing" + if [ ! -d "/Library/Application Support/VirtualBox/${VBOXDRV}.kext" ]; then + ConsoleMessage "Error: /Library/Application Support/VirtualBox/${VBOXDRV}.kext is missing" VBOX_RC=1 fi - if [ ! -d /Library/Extensions/${VBOXUSB}.kext ]; then - ConsoleMessage "Error: /Library/Extensions/${VBOXUSB}.kext is missing" + if [ ! -d "/Library/Application Support/VirtualBox/${VBOXUSB}.kext" ]; then + ConsoleMessage "Error: /Library/Application Support/VirtualBox/${VBOXUSB}.kext is missing" VBOX_RC=1 fi - if [ ! -d /Library/Extensions/VBoxNetFlt.kext ]; then - ConsoleMessage "Error: /Library/Extensions/VBoxNetFlt.kext is missing" + if [ ! -d "/Library/Application Support/VirtualBox/VBoxNetFlt.kext" ]; then + ConsoleMessage "Error: /Library/Application Support/VirtualBox/VBoxNetFlt.kext is missing" VBOX_RC=1 fi - if [ ! -d /Library/Extensions/VBoxNetAdp.kext ]; then - ConsoleMessage "Error: /Library/Extensions/VBoxNetAdp.kext is missing" + if [ ! -d "/Library/Application Support/VirtualBox/VBoxNetAdp.kext" ]; then + ConsoleMessage "Error: /Library/Application Support/VirtualBox/VBoxNetAdp.kext is missing" VBOX_RC=1 fi @@ -71,19 +121,19 @@ StartService() # if [ $VBOX_RC -eq 0 ]; then if kextstat -lb org.virtualbox.kext.VBoxDrv 2>&1 | grep -q org.virtualbox.kext.VBoxDrv; then - ConsoleMessage -v "Error: ${VBOXDRV}.kext is already loaded" + ConsoleMessage "Error: ${VBOXDRV}.kext is already loaded" VBOX_RC=1 fi if kextstat -lb org.virtualbox.kext.VBoxUSB 2>&1 | grep -q org.virtualbox.kext.VBoxUSB; then - ConsoleMessage -v "Error: ${VBOXUSB}.kext is already loaded" + ConsoleMessage "Error: ${VBOXUSB}.kext is already loaded" VBOX_RC=1 fi if kextstat -lb org.virtualbox.kext.VBoxNetFlt 2>&1 | grep -q org.virtualbox.kext.VBoxNetFlt; then - ConsoleMessage -v "Error: VBoxNetFlt.kext is already loaded" + ConsoleMessage "Error: VBoxNetFlt.kext is already loaded" VBOX_RC=1 fi if kextstat -lb org.virtualbox.kext.VBoxNetAdp 2>&1 | grep -q org.virtualbox.kext.VBoxNetAdp; then - ConsoleMessage -v "Error: VBoxNetAdp.kext is already loaded" + ConsoleMessage "Error: VBoxNetAdp.kext is already loaded" VBOX_RC=1 fi fi @@ -93,26 +143,26 @@ StartService() # if [ $VBOX_RC -eq 0 ]; then ConsoleMessage "Loading ${VBOXDRV}.kext" - if ! kextload /Library/Extensions/${VBOXDRV}.kext; then - ConsoleMessage "Error: Failed to load /Library/Extensions/${VBOXDRV}.kext" + if ! kextload "/Library/Application Support/VirtualBox/${VBOXDRV}.kext"; then + ConsoleMessage "Error: Failed to load /Library/Application Support/VirtualBox/${VBOXDRV}.kext" VBOX_RC=1 fi ConsoleMessage "Loading ${VBOXUSB}.kext" - if ! kextload -d /Library/Extensions/${VBOXDRV}.kext /Library/Extensions/${VBOXUSB}.kext; then - ConsoleMessage "Error: Failed to load /Library/Extensions/${VBOXUSB}.kext" + if ! kextload -d "/Library/Application Support/VirtualBox/${VBOXDRV}.kext" "/Library/Application Support/VirtualBox/${VBOXUSB}.kext"; then + ConsoleMessage "Error: Failed to load /Library/Application Support/VirtualBox/${VBOXUSB}.kext" VBOX_RC=1 fi ConsoleMessage "Loading VBoxNetFlt.kext" - if ! kextload -d /Library/Extensions/${VBOXDRV}.kext /Library/Extensions/VBoxNetFlt.kext; then - ConsoleMessage "Error: Failed to load /Library/Extensions/VBoxNetFlt.kext" + if ! kextload -d "/Library/Application Support/VirtualBox/${VBOXDRV}.kext" "/Library/Application Support/VirtualBox/VBoxNetFlt.kext"; then + ConsoleMessage "Error: Failed to load /Library/Application Support/VirtualBox/VBoxNetFlt.kext" VBOX_RC=1 fi ConsoleMessage "Loading VBoxNetAdp.kext" - if ! kextload -d /Library/Extensions/${VBOXDRV}.kext /Library/Extensions/VBoxNetAdp.kext; then - ConsoleMessage "Error: Failed to load /Library/Extensions/VBoxNetAdp.kext" + if ! kextload -d "/Library/Application Support/VirtualBox/${VBOXDRV}.kext" "/Library/Application Support/VirtualBox/VBoxNetAdp.kext"; then + ConsoleMessage "Error: Failed to load /Library/Application Support/VirtualBox/VBoxNetAdp.kext" VBOX_RC=1 fi @@ -144,7 +194,7 @@ StopService() if kextstat -lb org.virtualbox.kext.VBoxUSB 2>&1 | grep -q org.virtualbox.kext.VBoxUSB; then ConsoleMessage "Unloading ${VBOXUSB}.kext" if ! kextunload -m org.virtualbox.kext.VBoxUSB; then - ConsoleMessage -v "Error: Failed to unload VBoxUSB.kext" + ConsoleMessage "Error: Failed to unload VBoxUSB.kext" VBOX_RC=1 fi fi @@ -152,7 +202,7 @@ StopService() if kextstat -lb org.virtualbox.kext.VBoxNetFlt 2>&1 | grep -q org.virtualbox.kext.VBoxNetFlt; then ConsoleMessage "Unloading VBoxNetFlt.kext" if ! kextunload -m org.virtualbox.kext.VBoxNetFlt; then - ConsoleMessage -v "Error: Failed to unload VBoxNetFlt.kext" + ConsoleMessage "Error: Failed to unload VBoxNetFlt.kext" VBOX_RC=1 fi fi @@ -160,7 +210,7 @@ StopService() if kextstat -lb org.virtualbox.kext.VBoxNetAdp 2>&1 | grep -q org.virtualbox.kext.VBoxNetAdp; then ConsoleMessage "Unloading VBoxNetAdp.kext" if ! kextunload -m org.virtualbox.kext.VBoxNetAdp; then - ConsoleMessage -v "Error: Failed to unload VBoxNetAdp.kext" + ConsoleMessage "Error: Failed to unload VBoxNetAdp.kext" VBOX_RC=1 fi fi @@ -169,7 +219,7 @@ StopService() if kextstat -lb org.virtualbox.kext.VBoxDrv 2>&1 | grep -q org.virtualbox.kext.VBoxDrv; then ConsoleMessage "Unloading ${VBOXDRV}.kext" if ! kextunload -m org.virtualbox.kext.VBoxDrv; then - ConsoleMessage -v "Error: Failed to unload VBoxDrv.kext" + ConsoleMessage "Error: Failed to unload VBoxDrv.kext" VBOX_RC=1 fi fi diff --git a/src/VBox/Installer/darwin/VBoxKEXTs/org.virtualbox.startup.plist b/src/VBox/Installer/darwin/VBoxKEXTs/org.virtualbox.startup.plist new file mode 100644 index 00000000..490c9ba6 --- /dev/null +++ b/src/VBox/Installer/darwin/VBoxKEXTs/org.virtualbox.startup.plist @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>Label</key> <string>org.virtualbox.startup</string> + <key>Disabled</key> <false/> + <key>RunAtLoad</key> <true/> + <key>KeepAlive</key> <false/> + <key>LaunchOnlyOnce</key> <true/> + <key>ProgramArguments</key> + <array> + <string>/Library/Application Support/VirtualBox/LaunchDaemons/VirtualBoxStartup.sh</string> + <string>restart</string> + </array> +</dict> +</plist> + diff --git a/src/VBox/Installer/darwin/VBoxKEXTs/postflight b/src/VBox/Installer/darwin/VBoxKEXTs/postflight index 3dd5a699..4cbfea13 100755 --- a/src/VBox/Installer/darwin/VBoxKEXTs/postflight +++ b/src/VBox/Installer/darwin/VBoxKEXTs/postflight @@ -1,7 +1,11 @@ #!/bin/sh +# $Id$ +## @file +# Reloads the new kernel extension at the end of installation. +# # -# Copyright (C) 2007-2010 Oracle Corporation +# Copyright (C) 2007-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; @@ -13,6 +17,38 @@ # # +# Make sure the old startup items are gone. +# +if [ -d /Library/StartupItems/VirtualBox/ ]; then + rm -vf "/Library/StartupItems/VirtualBox/StartupParameters.plist" + rm -vf "/Library/StartupItems/VirtualBox/VirtualBox" + rm -vf "/Library/StartupItems/VirtualBox/Resources/English.lproj/Localizable.strings" + test -d "/Library/StartupItems/VirtualBox/Resources/English.lproj/" && rmdir "/Library/StartupItems/VirtualBox/Resources/English.lproj/" + test -d "/Library/StartupItems/VirtualBox/Resources/" && rmdir "/Library/StartupItems/VirtualBox/Resources/" + test -d "/Library/StartupItems/VirtualBox/" && rmdir "/Library/StartupItems/VirtualBox/" +fi + +# +# Make sure old kernel extensions are gone (moved to "/Library/Application Support/VirtualBox/" with 4.3). +# +rm -Rfv \ + "/Library/Extensions/VBoxDrv.kext/" \ + "/Library/Extensions/VBoxNetFlt.kext/" \ + "/Library/Extensions/VBoxNetAdp.kext/" \ + "/Library/Extensions/VBoxUSB.kext/" \ + "/Library/Extensions/VBoxDrvTiger.kext/" \ + "/Library/Extensions/VBoxUSBTiger.kext/" + +# +# Install the launchd script. +# +rm -vf "/Library/LaunchDaemons/org.virtualbox.startup.plist" +set -e +ln -s "../Application Support/VirtualBox/LaunchDaemons/org.virtualbox.startup.plist" \ + "/Library/LaunchDaemons/org.virtualbox.startup.plist" +set +e + +# # Unload any old extension that might be loaded already (ignore failures). # sync @@ -33,8 +69,9 @@ fi # Load the extension, exit on first error. # sync -kextload /Library/Extensions/VBoxDrv.kext -kextload -d /Library/Extensions/VBoxDrv.kext /Library/Extensions/VBoxUSB.kext -kextload -d /Library/Extensions/VBoxDrv.kext /Library/Extensions/VBoxNetFlt.kext -kextload -d /Library/Extensions/VBoxDrv.kext /Library/Extensions/VBoxNetAdp.kext +set -e +kextload '/Library/Application Support/VirtualBox/VBoxDrv.kext' +kextload -d '/Library/Application Support/VirtualBox/VBoxDrv.kext' '/Library/Application Support/VirtualBox/VBoxUSB.kext' +kextload -d '/Library/Application Support/VirtualBox/VBoxDrv.kext' '/Library/Application Support/VirtualBox/VBoxNetFlt.kext' +kextload -d '/Library/Application Support/VirtualBox/VBoxDrv.kext' '/Library/Application Support/VirtualBox/VBoxNetAdp.kext' diff --git a/src/VBox/Installer/darwin/VBoxStartupItems/VirtualBox/Resources/English.lproj/Localizable.strings b/src/VBox/Installer/darwin/VBoxStartupItems/VirtualBox/Resources/English.lproj/Localizable.strings deleted file mode 100644 index 77a25c99..00000000 --- a/src/VBox/Installer/darwin/VBoxStartupItems/VirtualBox/Resources/English.lproj/Localizable.strings +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd"> -<plist version="0.9"> -<dict> - <key>VirtualBox Support Driver</key> <string>VirtualBox Support Driver</string> - <key>Loading VBoxDrv.kext</key> <string>Loading VBoxDrv.kext</string> - <key>Loading VBoxUSB.kext</key> <string>Loading VBoxUSB.kext</string> - <key>Loading VBoxNetFlt.kext</key> <string>Loading VBoxNetFlt.kext</string> - <key>Loading VBoxNetAdp.kext</key> <string>Loading VBoxNetAdp.kext</string> - <key>Unloading VBoxDrv.kext</key> <string>Unloading VBoxDrv.kext</string> - <key>Unloading VBoxUSB.kext</key> <string>Unloading VBoxUSB.kext</string> - <key>Unloading VBoxNetFlt.kext</key> <string>Unloading VBoxNetFlt.kext</string> - <key>Unloading VBoxNetAdp.kext</key> <string>Unloading VBoxNetAdp.kext</string> - <key>Error: /Library/Extensions/VBoxDrv.kext is missing</key> <string>Error: /Library/Extensions/VBoxDrv.kext is missing</string> - <key>Error: /Library/Extensions/VBoxUSB.kext is missing</key> <string>Error: /Library/Extensions/VBoxUSB.kext is missing</string> - <key>Error: /Library/Extensions/VBoxNetFlt.kext is missing</key> <string>Error: /Library/Extensions/VBoxNetFlt.kext is missing</string> - <key>Error: /Library/Extensions/VBoxNetAdp.kext is missing</key> <string>Error: /Library/Extensions/VBoxNetAdp.kext is missing</string> - <key>Error: VBoxDrv.kext is already loaded</key> <string>Error: VBoxDrv.kext is already loaded</string> - <key>Error: VBoxUSB.kext is already loaded</key> <string>Error: VBoxUSB.kext is already loaded</string> - <key>Error: VBoxNetFlt.kext is already loaded</key> <string>Error: VBoxNetFlt.kext is already loaded</string> - <key>Error: VBoxNetAdp.kext is already loaded</key> <string>Error: VBoxNetAdp.kext is already loaded</string> - <key>Error: Failed to load /Library/Extensions/VBoxDrv.kext</key> <string>Error: Failed to load /Library/Extensions/VBoxDrv.kext</string> - <key>Error: Failed to load /Library/Extensions/VBoxUSB.kext</key> <string>Error: Failed to load /Library/Extensions/VBoxUSB.kext</string> - <key>Error: Failed to load /Library/Extensions/VBoxNetFlt.kext</key> <string>Error: Failed to load /Library/Extensions/VBoxNetFlt.kext</string> - <key>Error: Failed to load /Library/Extensions/VBoxNetAdp.kext</key> <string>Error: Failed to load /Library/Extensions/VBoxNetAdp.kext</string> - <key>Error: Failed to unload VBoxDrv.kext</key> <string>Error: Failed to unload VBoxDrv.kext</string> - <key>Error: Failed to unload VBoxUSB.kext</key> <string>Error: Failed to unload VBoxUSB.kext</string> - <key>Error: Failed to unload VBoxNetFlt.kext</key> <string>Error: Failed to unload VBoxNetFlt.kext</string> - <key>Error: Failed to unload VBoxNetAdp.kext</key> <string>Error: Failed to unload VBoxNetAdp.kext</string> -</dict> -</plist> - diff --git a/src/VBox/Installer/darwin/VBoxStartupItems/VirtualBox/StartupParameters.plist b/src/VBox/Installer/darwin/VBoxStartupItems/VirtualBox/StartupParameters.plist deleted file mode 100644 index 13566bfd..00000000 --- a/src/VBox/Installer/darwin/VBoxStartupItems/VirtualBox/StartupParameters.plist +++ /dev/null @@ -1,5 +0,0 @@ -{ - Description = "VirtualBox Support and USB Drivers"; - Provides = ("VirtualBox"); - OrderPreference = "None"; -} diff --git a/src/VBox/Installer/darwin/VirtualBox/PkgBuildComponent.plist b/src/VBox/Installer/darwin/VirtualBox/PkgBuildComponent.plist index a73d8102..a67ae42c 100644 --- a/src/VBox/Installer/darwin/VirtualBox/PkgBuildComponent.plist +++ b/src/VBox/Installer/darwin/VirtualBox/PkgBuildComponent.plist @@ -8,6 +8,7 @@ <key>BundleIsVersionChecked</key> <false/> <key>BundleHasStrictIdentifier</key> <false/> <key>BundleOverwriteAction</key> <string>upgrade</string> + <key>BundlePreInstallScriptPath</key> <string>preflight</string> <key>BundlePostInstallScriptPath</key> <string>postflight</string> </dict> </array> diff --git a/src/VBox/Installer/darwin/VirtualBox/VBoxAutostartDarwin.sh b/src/VBox/Installer/darwin/VirtualBox/VBoxAutostartDarwin.sh index 87c23a34..16c1dfdf 100755 --- a/src/VBox/Installer/darwin/VirtualBox/VBoxAutostartDarwin.sh +++ b/src/VBox/Installer/darwin/VirtualBox/VBoxAutostartDarwin.sh @@ -17,7 +17,7 @@ # and starts the VMs. # -function vboxStartAllUserVms() +function vboxStartStopAllUserVms() { # Go through the list and filter out all users without a shell and a # non existing home. @@ -33,14 +33,29 @@ function vboxStartAllUserVms() continue fi - # Start the daemon - su ${user} -c "/Applications/VirtualBox.app/Contents/MacOS/VBoxAutostart --quiet --start --background --config ${1}" - + case "${1}" in + start) + # Start the daemon + su ${user} -c "/Applications/VirtualBox.app/Contents/MacOS/VBoxAutostart --quiet --start --background --config ${CONFIG}" + ;; + stop) + # Start the daemon + su ${user} -c "/Applications/VirtualBox.app/Contents/MacOS/VBoxAutostart --quiet --stop --config ${CONFIG}" + ;; + *) + echo "Usage: start|stop" + exit 1 + esac done } -case $1 in - --start) vboxStartAllUserVms ${2};; - *) echo "Unknown option ${1}";; -esac +function vboxStopAllUserVms() +{ + vboxStartStopAllUserVms "stop" +} + +CONFIG=${1} +vboxStartStopAllUserVms "start" +trap vboxStopAllUserVms HUP KILL TERM + diff --git a/src/VBox/Installer/darwin/VirtualBox/org.virtualbox.vboxautostart.plist b/src/VBox/Installer/darwin/VirtualBox/org.virtualbox.vboxautostart.plist index 1d97e16b..ca0b770e 100644 --- a/src/VBox/Installer/darwin/VirtualBox/org.virtualbox.vboxautostart.plist +++ b/src/VBox/Installer/darwin/VirtualBox/org.virtualbox.vboxautostart.plist @@ -4,15 +4,16 @@ <dict> <key>Disabled</key> <true/> - <key>KeepAlive</key> - <false/> <key>Label</key> <string>org.virtualbox.vboxautostart</string> <key>ProgramArguments</key> <array> <string>/Applications/VirtualBox.app/Contents/MacOS/VBoxAutostartDarwin.sh</string> - <string>--start</string> <string>/etc/vbox/autostart.cfg</string> </array> + <key>RunAtLoad</key> + <true/> + <key>LaunchOnlyOnce</key> + <true/> </dict> </plist> diff --git a/src/VBox/Installer/darwin/VirtualBox/postflight b/src/VBox/Installer/darwin/VirtualBox/postflight index a7f5f9b4..57271316 100755 --- a/src/VBox/Installer/darwin/VirtualBox/postflight +++ b/src/VBox/Installer/darwin/VirtualBox/postflight @@ -16,12 +16,6 @@ CP="/bin/cp -f" CPDIR="${CP} -R" # -# Correct the ownership of the directories in case there -# was an existing installation. -# -chown -R root:admin /Applications/VirtualBox.app - -# # Select the right architecture. # MY_ARCH=`uname -m` @@ -39,7 +33,7 @@ do exit 1; fi rm -f "$linkname" - ln -vh "$trg" "$linkname" + /bin/ln -vh "$trg" "$linkname" done # @@ -90,5 +84,22 @@ if [[ -e "${LSREGISTER}" && "x" != "x${USER}" ]]; then /usr/bin/sudo -u "${USER}" ${LSREGISTER} -f /Applications/VirtualBox.app/Contents/Resources/vmstarter.app fi -exit 0; +# Check environment. +if [ "${INSTALLER_TEMP}x" == "x" ]; then + echo "Required environment variable INSTALLER_TEMP is missing. Aborting installation." + exit 1; +fi +# Restore previously installed Extension Packs (if any) +if [ -d "${INSTALLER_TEMP}/ExtensionPacks" ]; then + cp -r "${INSTALLER_TEMP}/ExtensionPacks" "${VBOX_INSTALL_PATH}" + rm -rf "${INSTALLER_TEMP}/ExtensionPacks" +fi + +# +# Correct the ownership of the directories in case there +# was an existing installation. +# +chown -R root:admin /Applications/VirtualBox.app + +exit 0; diff --git a/src/VBox/Installer/darwin/VirtualBox/preflight b/src/VBox/Installer/darwin/VirtualBox/preflight new file mode 100755 index 00000000..9c264851 --- /dev/null +++ b/src/VBox/Installer/darwin/VirtualBox/preflight @@ -0,0 +1,31 @@ +#!/bin/sh + +# +# Copyright (C) 2007-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. +# + +set -e + +# Check environment. +if [ "${INSTALLER_TEMP}x" == "x" ]; then + echo "Required environment variable INSTALLER_TEMP is missing. Aborting installation." + exit 1; +fi + +# Backup previously installed Extension Packs before +# installation process will completely remove previously installed +# VirtualBox distribution. +EXTPACKS_ROOT_PATH="/Applications/VirtualBox.app/Contents/MacOS/ExtensionPacks" +if [ -d "${EXTPACKS_ROOT_PATH}" ]; then + cp -r "${EXTPACKS_ROOT_PATH}" "${INSTALLER_TEMP}" +fi + +exit 0; diff --git a/src/VBox/Installer/darwin/VirtualBox_mpkg/Localizable.strings b/src/VBox/Installer/darwin/VirtualBox_mpkg/Localizable.strings index f64f4903..0a2e8eee 100644 --- a/src/VBox/Installer/darwin/VirtualBox_mpkg/Localizable.strings +++ b/src/VBox/Installer/darwin/VirtualBox_mpkg/Localizable.strings @@ -1,10 +1,7 @@ 'VirtualBox_title' = '@VBOX_PRODUCT@'; 'choiceVBoxKEXTs_title' = '@VBOX_PRODUCT@ Kernel Extensions'; -'choiceVBoxKEXTs_msg' = 'Installs the @VBOX_PRODUCT@ Kernel Extensions into /Library/Extensions.'; - -'choiceVBoxStartup_title' = '@VBOX_PRODUCT@ Startup Items'; -'choiceVBoxStartup_msg' = 'Installs the @VBOX_PRODUCT@ Startup Items to /Library/StartupItems/VirtualBox.'; +'choiceVBoxKEXTs_msg' = 'Installs the @VBOX_PRODUCT@ Kernel Extensions into /Library/Application Support/VirtualBox.'; 'choiceVBox_title' = '@VBOX_PRODUCT@'; 'choiceVBox_msg' = 'Installs the @VBOX_PRODUCT@ application into /Applications.'; @@ -12,8 +9,8 @@ 'choiceVBoxCLI_title' = '@VBOX_PRODUCT@ Command Line Utilities'; 'choiceVBoxCLI_msg' = 'Installs the @VBOX_PRODUCT@ command line utilities into /usr/bin.'; -'RUNNING_VMS_TLE' = "Running VirtualBox VM's detected!"; -'RUNNING_VMS_MSG' = "The installer has detected running Virtual Machines. Please shutdown all running VirtualBox machines and then restart the installation."; +'RUNNING_VMS_TLE' = "Running VirtualBox virtual machines detected!"; +'RUNNING_VMS_MSG' = "The installer has detected running virtual machines. Please shut down all running VirtualBox machines and then restart the installation."; 'UNSUPPORTED_HW_MACHINE_TLE' = "Unsupported hardware architecture detected!"; 'UNSUPPORTED_HW_MACHINE_MSG' = "The installer has detected an unsupported architecture. VirtualBox only runs on the x86 and amd64 architectures."; diff --git a/src/VBox/Installer/darwin/VirtualBox_mpkg/distribution.dist b/src/VBox/Installer/darwin/VirtualBox_mpkg/distribution.dist index a2e7d633..3749e358 100644 --- a/src/VBox/Installer/darwin/VirtualBox_mpkg/distribution.dist +++ b/src/VBox/Installer/darwin/VirtualBox_mpkg/distribution.dist @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- # -# Copyright (C) 2008-2012 Oracle Corporation +# Copyright (C) 2008-2014 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -18,6 +18,7 @@ <installation-check script="checkPrerequisite()"></installation-check> <domains enable_anywhere="false" enable_currentUserHome="false" enable_localSystem="true"/> <script> +//<![CDATA[ /* js:pkmk:start */ function checkPrerequisite() { @@ -53,9 +54,27 @@ try { + /* The following shell script uses tools which were added in 10.8 + (Mountain Lion) and later, in particular pgrep and pkill. */ + if (system.compareVersions(system.version['ProductVersion'], '10.8') >= 0) + { + /* Embedded scripts are not available here. So, just do a + command line checking if any VBoxXPCOMIPCD has more than one + client, and if there are none, kill all the usual suspects to + get a clean slate. This is done because the VirtualBox event + handling had a bug which allowed no longer present passive + event listeners to block VBoxSVC processes from exiting until + the waiting time was elapsed. In the extreme case this was + infinitely long, blocking updates. */ + system.run('/bin/sh', '-c', 'pids=`/usr/bin/pgrep VBoxXPCOMIPCD` rc=0; [ -z "$pids" ] && rc=1; for i in $pids; do c=`/usr/sbin/lsof -p $i | /usr/bin/grep -E \'^[^ ]+ +[^ ]+ +[^ ]+ +[^ ]+ +unix\' | wc -l`; [ $c -le 2 ] || rc=1; done; if [ $rc -eq 0 ]; then pkill -KILL \'^(VirtualBox)|(VBoxNetDHCP)|(VBoxNetNAT)|(VBoxHeadless)|(VBoxXPCOMIPCD)|(VBoxSVC)$\'; sleep 1; fi'); + } + } catch (e) { system.log(e); } + + try + { /* Embedded scripts are not available here. So, just do a command line checking for running VMs instead. */ - rcScript = system.run('/bin/sh', '-c', '/bin/ps -e | /usr/bin/grep -E "VirtualBoxVM.*startvm|VBoxNetDHCP" | /usr/bin/grep -qv grep'); + rcScript = system.run('/bin/sh', '-c', '/bin/ps -e | /usr/bin/grep -E \'[V]irtualBox.*startvm|[V]BoxNetDHCP|[V]BoxNetNAT|[V]BoxHeadless|[V]BoxSVC\''); result = (rcScript != 0); system.log("system.run /bin/sh .. returned: " + rcScript + " result=" + result); } catch (e) { system.log(e); result = false; } @@ -72,21 +91,18 @@ return result; } /* js:pkmk:end */ +//]]> </script> <background file="background.tif" alignment="topleft" scaling="none"/> <welcome file="Welcome.rtf" mime-type="text/rtf" uti="public.rtf"/> <choices-outline> <line choice="choiceVBoxKEXTs"></line> - <line choice="choiceVBoxStartup"></line> <line choice="choiceVBox"></line> <line choice="choiceVBoxCLI"></line> </choices-outline> <choice id="choiceVBoxKEXTs" title="choiceVBoxKEXTs_title" description="choiceVBoxKEXTs_msg" start_selected="true" start_enabled="false" start_visible="true"> <pkg-ref id="org.virtualbox.pkg.vboxkexts"></pkg-ref> </choice> - <choice id="choiceVBoxStartup" title="choiceVBoxStartup_title" description="choiceVBoxStartup_msg" start_selected="true" start_enabled="false" start_visible="true"> - <pkg-ref id="org.virtualbox.pkg.vboxstartupitems"></pkg-ref> - </choice> <choice id="choiceVBox" title="choiceVBox_title" description="choiceVBox_msg" start_selected="true" start_enabled="false" start_visible="true"> <pkg-ref id="org.virtualbox.pkg.virtualbox"></pkg-ref> </choice> @@ -94,7 +110,6 @@ <pkg-ref id="org.virtualbox.pkg.virtualboxcli"></pkg-ref> </choice> <pkg-ref id="org.virtualbox.pkg.vboxkexts" auth="Root">file:./Contents/Packages/VBoxKEXTs.pkg</pkg-ref> - <pkg-ref id="org.virtualbox.pkg.vboxstartupitems" auth="Root">file:./Contents/Packages/VBoxStartupItems.pkg</pkg-ref> <pkg-ref id="org.virtualbox.pkg.virtualbox" auth="Root">file:./Contents/Packages/VirtualBox.pkg</pkg-ref> <pkg-ref id="org.virtualbox.pkg.virtualboxcli" auth="Root">file:./Contents/Packages/VirtualBoxCLI.pkg</pkg-ref> </installer-gui-script> diff --git a/src/VBox/Installer/freebsd/Makefile.kmk b/src/VBox/Installer/freebsd/Makefile.kmk index 159a04cc..4455fec3 100644 --- a/src/VBox/Installer/freebsd/Makefile.kmk +++ b/src/VBox/Installer/freebsd/Makefile.kmk @@ -4,7 +4,7 @@ # # -# Copyright (C) 2006-2012 Oracle Corporation +# Copyright (C) 2006-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; @@ -202,15 +202,6 @@ ifdef VBOX_WITH_HEADLESS VBoxHeadless endif -# BFE -ifdef VBOX_WITH_VBOXBFE - VBOX_FBSD_STRIP_BIN += \ - VBoxBFE \ - $(if $(VBOX_WITH_HARDENING),VBoxBFE.so) - VBOX_FBSD_SYMLINKS += \ - VBoxBFE -endif - # Webservices ifdef VBOX_WITH_WEBSERVICES VBOX_FBSD_STRIP_BIN += \ diff --git a/src/VBox/Installer/freebsd/pkg_plist b/src/VBox/Installer/freebsd/pkg_plist index d84c1a31..1db2493a 100644 --- a/src/VBox/Installer/freebsd/pkg_plist +++ b/src/VBox/Installer/freebsd/pkg_plist @@ -1,8 +1,6 @@ @owner root @group wheel @mode 755 -lib/virtualbox/VBoxBFE -lib/virtualbox/VBoxBFE.so lib/virtualbox/VBoxDbg.so lib/virtualbox/VBoxDD.so lib/virtualbox/VBoxDD2.so @@ -50,7 +48,6 @@ lib/virtualbox/components/VBoxXPCOMBase.xpt lib/virtualbox/components/VirtualBox_XPCOM.xpt @mode 755 bin/VirtualBox -bin/VBoxBFE bin/VBoxManage bin/VBoxSVC bin/VBoxHeadless diff --git a/src/VBox/Installer/freebsd/postdeinstall.sh b/src/VBox/Installer/freebsd/postdeinstall.sh index 394d5d4a..69ef1903 100755 --- a/src/VBox/Installer/freebsd/postdeinstall.sh +++ b/src/VBox/Installer/freebsd/postdeinstall.sh @@ -5,7 +5,7 @@ # # -# Copyright (C) 2007-2010 Oracle Corporation +# Copyright (C) 2007-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/freebsd/postinstall.sh b/src/VBox/Installer/freebsd/postinstall.sh index 7bb905b7..0a509014 100755 --- a/src/VBox/Installer/freebsd/postinstall.sh +++ b/src/VBox/Installer/freebsd/postinstall.sh @@ -5,7 +5,7 @@ # # -# Copyright (C) 2007-2010 Oracle Corporation +# Copyright (C) 2007-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/linux/Makefile.kmk b/src/VBox/Installer/linux/Makefile.kmk index 4259c8e9..78112730 100644 --- a/src/VBox/Installer/linux/Makefile.kmk +++ b/src/VBox/Installer/linux/Makefile.kmk @@ -4,7 +4,7 @@ # # -# Copyright (C) 2006-2012 Oracle Corporation +# Copyright (C) 2006-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; @@ -18,7 +18,8 @@ SUB_DEPTH = ../../../.. include $(KBUILD_PATH)/subheader.kmk -# Include sub-makefile. +# Include sub-makefiles. +include $(PATH_SUB_CURRENT)/install_service/Makefile.kmk ifdef VBOX_WITH_TESTCASES include $(PATH_SUB_CURRENT)/testcase/Makefile.kmk endif @@ -33,6 +34,7 @@ endif VBOX_PATH_LNX_INST_SRC := $(PATH_SUB_CURRENT) VBOX_LNX_INST_OUT_DIR := $(PATH_TARGET)/Installer/linux VBOX_LNX_INST_STAGE_DIR := $(PATH_TARGET)/Installer/linux/install +VBOX_LNX_INST_STAGE_DIR_REL := obj/Installer/linux/install VBOX_LNX_DBG_PATH := usr/lib/debug/opt/VirtualBox VBOX_LNX_PACKAGE_NAME = VirtualBox-$(VBOX_VERSION_STRING)-r$(VBOX_SVN_REV).run @@ -49,20 +51,12 @@ endif OTHER_CLEAN += \ $(addprefix $(VBOX_LNX_INST_STAGE_DIR)/,\ install.sh \ - uninstall.sh \ - deffiles \ - routines.sh \ - vboxautostart-service.sh \ - vboxballoonctrl-service.sh \ vboxdrv.sh \ - vboxweb-service.sh \ VirtualBox.tar.bz2 \ LICENSE) \ $(wildcard $(VBOX_LNX_INST_OUT_DIR)/VirtualBox-*) \ $(addprefix $(VBOX_LNX_INST_OUT_DIR)/,\ - vboxballoonctrl-service.sh \ vboxdrv.sh \ - vboxweb-service.sh \ install.sh) # @@ -72,11 +66,25 @@ INSTALLS += linux-bin linux-bin_INST = bin/ linux-bin_MODE = a+rx,u+w linux-bin_SOURCES = \ + scripts/install.sh=>scripts/install.sh \ + scripts/VBoxHeadlessXOrg.sh=>scripts/VBoxHeadlessXOrg.sh \ VBoxSysInfo.sh \ VBoxCreateUSBNode.sh \ VBox.sh=>VBox.sh \ $(if $(VBOX_WITH_PYTHON),$(PATH_ROOT)/src/VBox/Frontends/VBoxShell/vboxshell.py=>vboxshell.py,) +INSTALLS += linux-scripts +linux-scripts_INST = $(VBOX_LNX_INST_STAGE_DIR_REL)/ +linux-scripts_MODE = a+rx,u+w +linux-scripts_SOURCES = \ + deffiles \ + routines.sh \ + uninstall.sh \ + vboxautostart-service.sh \ + vboxballoonctrl-service.sh \ + vboxdrv-pardus.py \ + vboxweb-service.sh + INSTALLS += linux-misc linux-misc_INST = bin/ linux-misc_MODE = a+r,u+w @@ -84,8 +92,19 @@ linux-misc_SOURCES = \ $(PATH_ROOT)/src/VBox/Frontends/VirtualBox/images/$(if $(VBOX_OSE),OSE,NonOSE)/VirtualBox_32px.png=>VBox.png \ $(PATH_ROOT)/src/VBox/Installer/common/virtualbox.xml \ $(if $(VBOX_OSE),,$(VBOX_BRAND_LICENSE_TXT)=>LICENSE) \ + $(linux-misc_0_OUTDIR)/generated.sh=>scripts/generated.sh \ $(if $(VBOX_WITH_QTGUI),$(linux-misc_0_OUTDIR)/virtualbox.desktop,) -linux-misc_CLEAN = $(linux-misc_0_OUTDIR)/virtualbox.desktop +linux-misc_CLEAN = \ + $(linux-misc_0_OUTDIR)/generated.sh \ + $(linux-misc_0_OUTDIR)/virtualbox.desktop + +$$(linux-misc_0_OUTDIR)/generated.sh: $(VBOX_VERSION_STAMP) $(VBOX_LNX_INST_DEP_ON_MAKEFILE) | $$(dir $$@) + $(call MSG_GENERATE,,$@,$<) + $(QUIET)$(RM) -f '$@' + $(QUIET)$(APPEND) '$@' 'VBOX_PRODUCT="$(VBOX_PRODUCT)"' + $(QUIET)$(APPEND) '$@' 'VBOX_VERSION_STRING="$(VBOX_VERSION_STRING)"' + $(QUIET)$(APPEND) '$@' 'VBOX_C_YEAR="$(VBOX_C_YEAR)"' + $(QUIET)$(APPEND) '$@' 'VBOX_VENDOR="$(VBOX_VENDOR)"' $$(linux-misc_0_OUTDIR)/virtualbox.desktop: $(PATH_ROOT)/src/VBox/Installer/common/virtualbox.desktop.in $(VBOX_VERSION_STAMP) | $$(dir $$@) $(call MSG_GENERATE,,$@,$<) @@ -131,7 +150,9 @@ VBOX_LNX_STRIP_BIN = \ VBoxBalloonCtrl \ VBoxManage \ VBoxNetDHCP $(if $(VBOX_WITH_HARDENING),VBoxNetDHCP.so,) \ + $(if $(VBOX_WITH_LWIP_NAT),VBoxNetNAT $(if $(VBOX_WITH_HARDENING),VBoxNetNAT.so,),) \ VBoxNetAdpCtl \ + $(if $(VBOX_WITH_DEVMAPPER),VBoxVolInfo,) \ VBoxSVC \ VBoxXPCOM.so \ VBoxXPCOMC.so \ @@ -150,7 +171,8 @@ VBOX_LNX_STRIP_BIN = \ $(if $(and $(VBOX_WITH_EXTPACK_VNC),$(VBOX_WITHOUT_EXTPACK_VNC_PACKING)), \ ExtensionPacks/VNC/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/VBoxVNC.so \ ExtensionPacks/VNC/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/VBoxVNCMain.so,) \ - VBoxTunctl + VBoxTunctl \ + helpers/generate_service_file # Do not remove relocation information of these binaries VBOX_LNX_STRIP_OBJ = \ @@ -180,7 +202,8 @@ VBOX_LNX_NO_STRIP = \ VBoxSysInfo.sh \ VBoxCreateUSBNode.sh \ VBox.sh \ - VBox.png + VBox.png \ + scripts ifdef VBOX_WITH_EXTPACK VBOX_LNX_STRIP_BIN += \ @@ -275,13 +298,6 @@ ifdef VBOX_WITH_HEADLESS $(if $(VBOX_WITH_HARDENING),VBoxHeadless.so) endif -# BFE -ifdef VBOX_WITH_BFE - VBOX_LNX_STRIP_BIN += \ - VBoxBFE \ - $(if $(VBOX_WITH_HARDENING),VBoxBFE.so) -endif - # Webservices ifdef VBOX_WITH_WEBSERVICES VBOX_LNX_STRIP_BIN += \ @@ -305,7 +321,8 @@ VBOX_MIME_ICONS = \ VBOX_DESKTOP_ICONS = \ $(addprefix $(PATH_ROOT)/src/VBox/Resources/$(if $(VBOX_OSE),OSE,NonOSE)/,\ $(foreach s,16 20 32 40 48 64 128,\ - virtualbox-$(s)px.png=>$(s)x$(s)/virtualbox.png)) + virtualbox-$(s)px.png=>$(s)x$(s)/virtualbox.png) \ + virtualbox.svg=>scalable/virtualbox.svg) # # All the bin files that goes into the archives. @@ -316,59 +333,27 @@ VBOX_LNX_ARCH_FILES := $(VBOX_LNX_STRIP_BIN) $(VBOX_LNX_STRIP_OBJ) $(VBOX_LNX_NO OTHER_CLEAN += $(addprefix $(VBOX_LNX_INST_OUT_DIR)/archive/,$(VBOX_LNX_ARCH_FILES)) \ $(addprefix $(VBOX_LNX_INST_OUT_DIR)/archive-dbg/$(VBOX_LNX_DBG_PATH)/,$(VBOX_LNX_STRIP_BIN)) - # # The generic installer. # $(PATH_STAGE_BIN)/$(VBOX_LNX_PACKAGE_NAME): \ $(VBOX_LNX_INST_STAGE_DIR)/VirtualBox.tar.bz2 \ $(VBOX_VERSION_STAMP) \ - $(VBOX_PATH_LNX_INST_SRC)/routines.sh \ - $(VBOX_PATH_LNX_INST_SRC)/deffiles \ $(if $(VBOX_OSE),,$(VBOX_BRAND_LICENSE_TXT)) \ - $(VBOX_LNX_INST_OUT_DIR)/vboxautostart-service.sh \ - $(VBOX_LNX_INST_OUT_DIR)/vboxballoonctrl-service.sh \ $(VBOX_LNX_INST_OUT_DIR)/vboxdrv.sh \ - $(VBOX_LNX_INST_OUT_DIR)/vboxweb-service.sh \ $(VBOX_LNX_INST_OUT_DIR)/install.sh \ $(VBOX_PATH_LNX_INST_SRC)/installer-common.sh \ - $(VBOX_PATH_LNX_INST_SRC)/vboxdrv-pardus.py \ - $(VBOX_PATH_LNX_INST_SRC)/uninstall.sh + $$(linux-scripts_2_STAGE_TARGETS) $(call MSG_TOOL,makeself,,$@) $(QUIET)$(RM) -f $(wildcard $(PATH_STAGE_BIN)/VirtualBox-*.run) - $(QUIET)$(INSTALL) -m 0755 $(VBOX_PATH_LNX_INST_SRC)/routines.sh $(VBOX_LNX_INST_STAGE_DIR)/ - $(QUIET)$(INSTALL) -m 0755 $(VBOX_PATH_LNX_INST_SRC)/deffiles $(VBOX_LNX_INST_STAGE_DIR)/ $(QUIET)$(if $(VBOX_OSE),,$(INSTALL) -m 0644 $(VBOX_BRAND_LICENSE_TXT) $(VBOX_LNX_INST_STAGE_DIR)/LICENSE) - $(QUIET)$(INSTALL) -m 0755 $(VBOX_LNX_INST_OUT_DIR)/vboxautostart-service.sh $(VBOX_LNX_INST_STAGE_DIR)/ - $(QUIET)$(INSTALL) -m 0755 $(VBOX_LNX_INST_OUT_DIR)/vboxballoonctrl-service.sh $(VBOX_LNX_INST_STAGE_DIR)/ $(QUIET)$(INSTALL) -m 0755 $(VBOX_LNX_INST_OUT_DIR)/vboxdrv.sh $(VBOX_LNX_INST_STAGE_DIR)/ - $(QUIET)$(INSTALL) -m 0755 $(VBOX_LNX_INST_OUT_DIR)/vboxweb-service.sh $(VBOX_LNX_INST_STAGE_DIR)/ - $(QUIET)$(INSTALL) -m 0755 $(VBOX_PATH_LNX_INST_SRC)/vboxdrv-pardus.py $(VBOX_LNX_INST_STAGE_DIR)/ $(QUIET)$(INSTALL) -m 0755 $(VBOX_LNX_INST_OUT_DIR)/install.sh $(VBOX_LNX_INST_STAGE_DIR)/ - $(QUIET)$(INSTALL) -m 0755 $(VBOX_PATH_LNX_INST_SRC)/uninstall.sh $(VBOX_LNX_INST_STAGE_DIR)/ $(QUIET)$(RM) -f $@ $(QUIET)$(VBOX_MAKESELF) --follow --nocomp $(VBOX_LNX_INST_STAGE_DIR) $@ \ "VirtualBox for Linux installation" ./install.sh "\$$0 1> /dev/null" # files that needs editing before they can be included in the generic installer. -$(VBOX_LNX_INST_OUT_DIR)/vboxautostart-service.sh: $(VBOX_PATH_LNX_INST_SRC)/vboxautostart-service.sh.in | $$(dir $$@) - $(QUIET)$(SED_EXT) \ - -e "s|%NOLSB%|yes|g" \ - -e "s|%DEBIAN%||g" \ - -e "s|%PACKAGE%|virtualbox|g" \ - -e "s|%VERSION%|$(VBOX_VERSION_STRING)|g" \ - --output $@ \ - $< - -$(VBOX_LNX_INST_OUT_DIR)/vboxballoonctrl-service.sh: $(VBOX_PATH_LNX_INST_SRC)/vboxballoonctrl-service.sh.in | $$(dir $$@) - $(QUIET)$(SED_EXT) \ - -e "s|%NOLSB%|yes|g" \ - -e "s|%DEBIAN%||g" \ - -e "s|%PACKAGE%|virtualbox|g" \ - -e "s|%VERSION%|$(VBOX_VERSION_STRING)|g" \ - --output $@ \ - $< - $(VBOX_LNX_INST_OUT_DIR)/vboxdrv.sh: $(VBOX_PATH_LNX_INST_SRC)/vboxdrv.sh.in | $$(dir $$@) $(QUIET)$(SED_EXT) \ -e "s|%NOLSB%|yes|g" \ @@ -379,14 +364,6 @@ $(VBOX_LNX_INST_OUT_DIR)/vboxdrv.sh: $(VBOX_PATH_LNX_INST_SRC)/vboxdrv.sh.in | $ --output $@ \ $< -$(VBOX_LNX_INST_OUT_DIR)/vboxweb-service.sh: $(VBOX_PATH_LNX_INST_SRC)/vboxweb-service.sh.in | $$(dir $$@) - $(QUIET)$(SED_EXT) \ - -e "s|%NOLSB%|yes|g" \ - -e "s|%DEBIAN%||g" \ - -e "s|%PACKAGE%|virtualbox|g" \ - --output $@ \ - $< - $(VBOX_LNX_INST_OUT_DIR)/install.sh: $(VBOX_PATH_LNX_INST_SRC)/install.sh $(VBOX_PATH_LNX_INST_SRC)/installer-common.sh $(VBOX_VERSION_STAMP) $(VBOX_SVN_REV_KMK).ts | $$(dir $$@) $(QUIET)$(SED) \ -e "s;_VERSION_;$(VBOX_VERSION_STRING);g" \ @@ -416,7 +393,8 @@ VBOX_LNX_INST_ARCH_DEPS := \ $(wildcard $(PATH_STAGE_BIN)/src/*) \ $(wildcard $(PATH_STAGE_BIN)/src/*/*) \ $(wildcard $(PATH_STAGE_BIN)/src/*/*/*) \ - $(wildcard $(PATH_STAGE_BIN)/src/*/*/*/*) + $(wildcard $(PATH_STAGE_BIN)/src/*/*/*/*) \ + $(wildcard $(PATH_STAGE_BIN)/scripts/*) # @@ -496,6 +474,7 @@ $(addprefix $(VBOX_LNX_INST_OUT_DIR)/archive/,$(VBOX_LNX_NO_STRIP)): \ BLDDIRS += $(foreach d,\ archive \ archive/components \ + archive/helpers \ archive/nls \ $(if $(VBOX_WITH_QT4_SUN),archive/accessible,) \ $(if $(VBOX_WITH_PYTHON),\ @@ -542,6 +521,7 @@ $(addprefix $(VBOX_LNX_INST_OUT_DIR)/archive-dbg/$(VBOX_LNX_DBG_PATH)/,$(VBOX_LN BLDDIRS += $(foreach d,\ $(VBOX_LNX_DBG_PATH) \ $(VBOX_LNX_DBG_PATH)/components \ + $(VBOX_LNX_DBG_PATH)/helpers \ ,$(VBOX_LNX_INST_OUT_DIR)/archive-dbg/$(d)/) include $(FILE_KBUILD_SUB_FOOTER) diff --git a/src/VBox/Installer/linux/VBox.sh b/src/VBox/Installer/linux/VBox.sh index 2243798f..6201a66e 100755 --- a/src/VBox/Installer/linux/VBox.sh +++ b/src/VBox/Installer/linux/VBox.sh @@ -2,7 +2,7 @@ # # Oracle VM VirtualBox startup script, Linux hosts. # -# Copyright (C) 2006-2011 Oracle Corporation +# Copyright (C) 2006-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -16,12 +16,16 @@ PATH="/usr/bin:/bin:/usr/sbin:/sbin" CONFIG="/etc/vbox/vbox.cfg" -if [ ! -r "$CONFIG" ]; then - echo "Could not find VirtualBox installation. Please reinstall." - exit 1 -fi - -. "$CONFIG" +test -r "${CONFIG}" && + . "${CONFIG}" +test -z "${INSTALL_DIR}" && + if test -f /usr/lib/virtualbox/VirtualBox && + test -x /usr/lib/virtualbox/VirtualBox; then + INSTALL_DIR=/usr/lib/virtualbox + else + echo "Could not find VirtualBox installation. Please reinstall." + exit 1 + fi # Note: This script must not fail if the module was not successfully installed # because the user might not want to run a VM but only change VM params! @@ -100,9 +104,6 @@ case "$APP" in vboxwebsrv) exec "$INSTALL_DIR/vboxwebsrv" "$@" ;; - VBoxBFE|vboxbfe) - exec "$INSTALL_DIR/VBoxBFE" "$@" - ;; *) echo "Unknown application - $APP" exit 1 diff --git a/src/VBox/Installer/linux/VBoxCreateUSBNode.sh b/src/VBox/Installer/linux/VBoxCreateUSBNode.sh index 9c9a8df9..ebf6254b 100755 --- a/src/VBox/Installer/linux/VBoxCreateUSBNode.sh +++ b/src/VBox/Installer/linux/VBoxCreateUSBNode.sh @@ -6,7 +6,7 @@ # # -# Copyright (C) 2010 Oracle Corporation +# Copyright (C) 2010-2011 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/linux/VBoxSysInfo.sh b/src/VBox/Installer/linux/VBoxSysInfo.sh index 8166b288..cf1f326b 100755 --- a/src/VBox/Installer/linux/VBoxSysInfo.sh +++ b/src/VBox/Installer/linux/VBoxSysInfo.sh @@ -5,7 +5,7 @@ # Installer (Unix-like) # Information about the host system/Linux distribution -# Copyright (C) 2006-2007 Oracle Corporation +# Copyright (C) 2006-2011 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/linux/debian/LocalConfig.kmk b/src/VBox/Installer/linux/debian/LocalConfig.kmk index d25294ab..72251cb9 100644 --- a/src/VBox/Installer/linux/debian/LocalConfig.kmk +++ b/src/VBox/Installer/linux/debian/LocalConfig.kmk @@ -4,7 +4,7 @@ # # -# Copyright (C) 2006-2010 Oracle Corporation +# Copyright (C) 2006-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/linux/debian/VBox.sh b/src/VBox/Installer/linux/debian/VBox.sh deleted file mode 100755 index d7c21e20..00000000 --- a/src/VBox/Installer/linux/debian/VBox.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/sh -# -# Oracle VM VirtualBox startup script, Linux hosts. -# -# Copyright (C) 2006-2011 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. -# - -PATH="/usr/bin:/bin:/usr/sbin:/sbin" - -# Note: This script must not fail if the module was not successfully installed -# because the user might not want to run a VM but only change VM params! - -if [ "$1" = "shutdown" ]; then - SHUTDOWN="true" -elif ! lsmod|grep -q vboxdrv; then - cat << EOF -WARNING: The vboxdrv kernel module is not loaded. Either there is no module - available for the current kernel (`uname -r`) or it failed to - load. Please recompile the kernel module and install it by - - sudo /etc/init.d/vboxdrv setup - - You will not be able to start VMs until this problem is fixed. -EOF -elif [ ! -c /dev/vboxdrv ]; then - cat << EOF -WARNING: The character device /dev/vboxdrv does not exist. Try - - sudo /etc/init.d/vboxdrv restart - - and if that is not successful, try to re-install the package. - - You will not be able to start VMs until this problem is fixed. -EOF -fi - -if [ -f /etc/vbox/module_not_compiled ]; then - cat << EOF -WARNING: The compilation of the vboxdrv.ko kernel module failed during the - installation for some reason. Starting a VM will not be possible. - Please consult the User Manual for build instructions. -EOF -fi - -SERVER_PID=`ps -U \`whoami\` | grep VBoxSVC | awk '{ print $1 }'` -if [ -z "$SERVER_PID" ]; then - # Server not running yet/anymore, cleanup socket path. - # See IPC_GetDefaultSocketPath()! - if [ -n "$LOGNAME" ]; then - rm -rf /tmp/.vbox-$LOGNAME-ipc > /dev/null 2>&1 - else - rm -rf /tmp/.vbox-$USER-ipc > /dev/null 2>&1 - fi -fi - -if [ "$SHUTDOWN" = "true" ]; then - if [ -n "$SERVER_PID" ]; then - kill -TERM $SERVER_PID - sleep 2 - fi - exit 0 -fi - -INSTALL_DIR=/usr/lib/virtualbox - -APP=`basename $0` -case "$APP" in - VirtualBox|virtualbox) - exec "$INSTALL_DIR/VirtualBox" "$@" - ;; - VBoxManage|vboxmanage) - exec "$INSTALL_DIR/VBoxManage" "$@" - ;; - VBoxSDL|vboxsdl) - exec "$INSTALL_DIR/VBoxSDL" "$@" - ;; - VBoxVRDP|VBoxHeadless|vboxheadless) - exec "$INSTALL_DIR/VBoxHeadless" "$@" - ;; - VBoxBalloonCtrl|vboxballoonctrl) - exec "$INSTALL_DIR/VBoxBalloonCtrl" "$@" - ;; - vboxwebsrv) - exec "$INSTALL_DIR/vboxwebsrv" "$@" - ;; - VBoxBFE|vboxbfe) - exec "$INSTALL_DIR/VBoxBFE" "$@" - ;; - *) - echo "Unknown application - $APP" - exit 1 - ;; -esac -exit 0 diff --git a/src/VBox/Installer/linux/debian/control b/src/VBox/Installer/linux/debian/control index 0b286c7b..457b3c88 100644 --- a/src/VBox/Installer/linux/debian/control +++ b/src/VBox/Installer/linux/debian/control @@ -1,4 +1,4 @@ -Source: virtualbox-4.2 +Source: virtualbox-4.3 Section: contrib/misc Priority: optional Maintainer: Oracle Corporation <info@virtualbox.org> @@ -13,16 +13,16 @@ Build-Depends: debhelper (>= 5), libz-dev, libssl-dev, libqt4-dev, libxext-dev, libcurl-dev, libxrandr-dev, openjdk-6-jdk | sun-java6-jdk XS-Python-Version: >= 2.4 -Package: virtualbox-4.2 +Package: virtualbox-4.3 Architecture: i386 amd64 Pre-Depends: debconf (>= 1.1) | debconf-2.0 Depends: ${shlibs:Depends}, debconf (>= 0.5) | debconf-2.0, psmisc, adduser Recommends: ${alsa}, ${pulse}, ${sdlttf}, ${dkms}, linux-headers, gcc, make, binutils, - pdf-viewer, libgl1, python-central + pdf-viewer, libgl1 Provides: virtualbox Replaces: virtualbox -Conflicts: virtualbox, virtualbox-ose +Conflicts: virtualbox, virtualbox-ose, virtualbox-guest-additions-iso Description: Oracle VM VirtualBox VirtualBox is a powerful PC virtualization solution allowing you to run a wide range of PC operating systems on your Linux system. This includes @@ -31,9 +31,9 @@ Description: Oracle VM VirtualBox software solution on the market. XB-Python-Version: ${python:Versions} -Package: virtualbox-4.2-dbg +Package: virtualbox-4.3-dbg Architecture: i386 amd64 -Depends: virtualbox-4.2 (= ${Source-Version}) +Depends: virtualbox-4.3 (= ${Source-Version}) Provides: virtualbox-dbg Replaces: virtualbox-dbg Conflicts: virtualbox-dbg, virtualbox-ose-dbg diff --git a/src/VBox/Installer/linux/debian/dirs b/src/VBox/Installer/linux/debian/dirs index 1f68187f..1549fd3a 100644 --- a/src/VBox/Installer/linux/debian/dirs +++ b/src/VBox/Installer/linux/debian/dirs @@ -2,4 +2,3 @@ /etc/vbox /etc/init.d /usr/src -/usr/lib/virtualbox diff --git a/src/VBox/Installer/linux/debian/lintian-override.in b/src/VBox/Installer/linux/debian/lintian-override.in index c23755cf..e4a9eee3 100644 --- a/src/VBox/Installer/linux/debian/lintian-override.in +++ b/src/VBox/Installer/linux/debian/lintian-override.in @@ -15,6 +15,7 @@ %VERPKG%: shlib-with-non-pic-code usr/lib/virtualbox/VBoxHostChannel.so %VERPKG%: shlib-with-non-pic-code usr/lib/virtualbox/VBoxDragAndDropSvc.so %VERPKG%: shlib-with-non-pic-code usr/lib/virtualbox/VBoxNetDHCP.so +%VERPKG%: shlib-with-non-pic-code usr/lib/virtualbox/VBoxNetNAT.so %VERPKG%: shlib-with-non-pic-code usr/lib/virtualbox/VBoxVRDP.so %VERPKG%: shlib-with-non-pic-code usr/lib/virtualbox/VBoxAuth.so %VERPKG%: shlib-with-non-pic-code usr/lib/virtualbox/components/VBoxSVCM.so diff --git a/src/VBox/Installer/linux/debian/postinst.in b/src/VBox/Installer/linux/debian/postinst.in index 102ba7b1..01a16382 100755 --- a/src/VBox/Installer/linux/debian/postinst.in +++ b/src/VBox/Installer/linux/debian/postinst.in @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (C) 2006-2011 Oracle Corporation +# Copyright (C) 2006-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -66,9 +66,17 @@ if [ "$1" = "configure" ]; then if ! dpkg-statoverride --list /usr/lib/virtualbox/VBoxNetDHCP > /dev/null 2>&1; then chmod 4511 /usr/lib/virtualbox/VBoxNetDHCP fi + if ! dpkg-statoverride --list /usr/lib/virtualbox/VBoxNetNAT > /dev/null 2>&1; then + chmod 4511 /usr/lib/virtualbox/VBoxNetNAT + fi if ! dpkg-statoverride --list /usr/lib/virtualbox/VBoxNetAdpCtl > /dev/null 2>&1; then chmod 4511 /usr/lib/virtualbox/VBoxNetAdpCtl fi + if [ -x /usr/lib/virtualbox/VBoxVolInfo ]; then + if ! dpkg-statoverride --list /usr/lib/virtualbox/VBoxVolInfo > /dev/null 2>&1; then + chmod 4511 /usr/lib/virtualbox/VBoxVolInfo + fi + fi # if INSTALL_NO_VBOXDRV is set to 1, remove all shipped modules if [ "$INSTALL_NO_VBOXDRV" = "1" ]; then diff --git a/src/VBox/Installer/linux/debian/postrm b/src/VBox/Installer/linux/debian/postrm index 60a9f6fd..799412d4 100755 --- a/src/VBox/Installer/linux/debian/postrm +++ b/src/VBox/Installer/linux/debian/postrm @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (C) 2006-2010 Oracle Corporation +# Copyright (C) 2006-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/linux/debian/preinst.in b/src/VBox/Installer/linux/debian/preinst.in index 10861b48..d065ead9 100755 --- a/src/VBox/Installer/linux/debian/preinst.in +++ b/src/VBox/Installer/linux/debian/preinst.in @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (C) 2006-2011 Oracle Corporation +# Copyright (C) 2006-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/linux/debian/prerm.in b/src/VBox/Installer/linux/debian/prerm.in index d26ed562..496bbf8e 100755 --- a/src/VBox/Installer/linux/debian/prerm.in +++ b/src/VBox/Installer/linux/debian/prerm.in @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (C) 2006-2010 Oracle Corporation +# Copyright (C) 2006-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -19,7 +19,7 @@ # purge: (our version): purge this package # deconfigure: (our version): removing conflicting version -rm -f /etc/udev/rules.d/10-vboxdrv.rules +rm -f /etc/udev/rules.d/60-vboxdrv.rules rm -f /etc/vbox/license_agreed rm -f /etc/vbox/module_not_compiled diff --git a/src/VBox/Installer/linux/debian/rules b/src/VBox/Installer/linux/debian/rules index f987cb96..e9ea88c1 100755 --- a/src/VBox/Installer/linux/debian/rules +++ b/src/VBox/Installer/linux/debian/rules @@ -41,18 +41,18 @@ export DH_COMPAT=4 # BLEEDING_EDGE=xyz package := virtualbox -verpkg := virtualbox-4.2 +verpkg := virtualbox-4.3 current := $(shell pwd) vboxroot := $(shell cd ../../../..; pwd) pkgdir := $(if $(PKGDIR),$(PKGDIR),$(shell cd ../../../../..; pwd)) -builddir := $(current)/debian/builddir -moddir := $(current)/debian/modules +builddir := $(vboxroot)/out/debian/builddir +moddir := $(vboxroot)/out/debian/modules prefix := $(current)/debian/$(verpkg) arch := $(shell dpkg --print-architecture) verfile := $(builddir)/version-generated.mk ose := $(if $(OSE),1,$(if $(wildcard $(vboxroot)/src/VBox/RDP/server),,1)) -include $(vboxroot)/SVN_REVISION -svnrev :=$(if $(svn_revision),$(svn_revision),0) +svnrev :=$(if $(svn_revision),$(svn_revision),) NOMODS ?= $(ose) NOQT ?= $(HEADLESS) @@ -94,12 +94,12 @@ endif qtstdc6 := /home/vbox/Qt-4.7.4-stdc++6-$(arch) cfg_flags := $(if $(NOQT),--disable-qt,) \ - $(if $(filter _Ubuntu_hardy _Debian_lenny,$(debrel)),--with-qt4-dir=$(qtstdc6)) \ + $(if $(filter _Debian_squeeze,$(debrel)),--build-libvpx,) \ $(if $(ose),--ose,) $(if $(LINUX),--with-linux=$(LINUX),) \ $(if $(HEADLESS),--build-headless,) \ $(if $(DEBUG),--build-debug,) \ $(if $(NOWINE),,--setup-wine) \ - $(if $(NOWEBSVC),,--enable-webservice) \ + $(if $(NOWEBSVC),,$(if $(ose),--enable-webservice,)) \ $(if $(VNC),--enable-vnc,) \ --disable-extpack @@ -109,17 +109,15 @@ bld_flags := AUTOCFG=$(current)/debian/AutoConfig.kmk \ VBOX_WITHOUT_EXTPACK_PUEL_PACKING=1 \ VBOX_WITHOUT_EXTPACK_VNC_PACKING=1 \ VBOX_DO_STRIP= \ - VBOX_DO_STRIP_MODULES= \ VBOX_WITH_MULTIVERSION_PYTHON= \ VBOX_PATH_PACKAGE_DOCS="\"/usr/share/doc/$(verpkg)\"" \ $(if $(ose),,VBOX_WITH_DOCS_CHM=1) \ VBOX_PACKAGE_DIST=$(debdist) \ - VBOX_SVN_REV=$(svnrev) \ + $(if $(svnrev),VBOX_SVN_REV=$(svnrev),) \ $(if $(NODOCS),VBOX_WITH_DOCS= ,) \ $(if $(VERBOSE),--print-directory KBUILD_VERBOSE=2,--no-print-directory) \ $(if $(STAGEDISO),VBOX_WITHOUT_ADDITIONS=1,) \ - $(if $(BLEEDING_EDGE),VBOX_BLEEDING_EDGE=$(BLEEDING_EDGE),) \ - $(if $(filter _Ubuntu_hardy,$(debrel)),,VBOX_WITH_SYSFS_BY_DEFAULT=1) + $(if $(BLEEDING_EDGE),VBOX_BLEEDING_EDGE=$(BLEEDING_EDGE),) configure: debian/configure-stamp debian/configure-stamp: @@ -139,8 +137,8 @@ debian/build-stamp $(verfile): $(if $(STAGEDISO),cp $(STAGEDISO)/VBoxGuestAdditions.iso $(builddir)/bin/additions,) . debian/env.sh && kmk -C $(vboxroot) $(bld_flags) \ VBOX_NO_LINUX_RUN_INSTALLER=1 \ - VBOX_LNX_ADD_ARCHIVE.x86=$(builddir)/bin/additions/VBoxGuestAdditions-x86-r$(svnrev).tar.bz2 \ - VBOX_LNX_ADD_ARCHIVE.amd64=$(builddir)/bin/additions/VBoxGuestAdditions-amd64-r$(svnrev).tar.bz2 \ + VBOX_LNX_ADD_ARCHIVE.x86=$(builddir)/bin/additions/VBoxGuestAdditions-x86.tar.bz2 \ + VBOX_LNX_ADD_ARCHIVE.amd64=$(builddir)/bin/additions/VBoxGuestAdditions-amd64.tar.bz2 \ VBOX_PATH_ADDITIONS.linux.x86=$(builddir)/bin/additions \ VBOX_PATH_ADDITIONS.linux.amd64=$(builddir)/bin/additions \ packing @@ -207,68 +205,17 @@ binary binary-arch binary-indep: build $(if $(NOMODS),,modules) dh_clean -k dh_installdirs tar -xjC $(prefix)/opt -f $(builddir)/bin/VirtualBox.tar.bz2 - install -d -g 0 -o 0 $(prefix)/usr/share/applications - install -d -g 0 -o 0 $(prefix)/usr/lib - install -d -g 0 -o 0 $(prefix)/usr/bin - install -d -g 0 -o 0 $(prefix)/usr/lib/$(package) - install -d -g 0 -o 0 $(prefix)/usr/share/$(package) + $(if $(NOQT),,mv $(archdir)/virtualbox.xml debian/$(verpkg).sharedmimeinfo) + $(archdir)/scripts/install.sh --package $(package) --root $(prefix) \ + --prefix /usr $(if $(NOQT),--no-qt) $(if $(ose),--ose) \ + $(if $(HEADLESS),--headless) $(if $(NOWEBSVC),--no-web-service) \ + --install-folder /lib/$(package) --no-helpers install -d -g 0 -o 0 $(prefix)/usr/share/doc/$(verpkg) - $(if $(NOQT),,mv $(archdir)/virtualbox.desktop \ - $(prefix)/usr/share/applications/virtualbox.desktop) - install -d -g 0 -o 0 $(prefix)/usr/share/pixmaps - install -d -g 0 -o 0 $(prefix)/usr/share/icons/hicolor - cp $(archdir)/icons/128x128/virtualbox.png \ - $(prefix)/usr/share/pixmaps/virtualbox.png - cd $(archdir)/icons; for i in *; do \ - if [ -f $$i/virtualbox.png ]; then \ - install -d -g 0 -o 0 $(prefix)/usr/share/icons/hicolor/$$i/apps; \ - mv $$i/virtualbox.png $(prefix)/usr/share/icons/hicolor/$$i/apps; \ - fi; \ - install -d -g 0 -o 0 $(prefix)/usr/share/icons/hicolor/$$i/mimetypes; \ - mv $$i/* $(prefix)/usr/share/icons/hicolor/$$i/mimetypes || true; \ - rmdir $$i; \ - done - rmdir $(archdir)/icons - install -d -g 0 -o 0 $(prefix)/usr/lib/$(package)/ExtensionPacks - mv $(archdir)/virtualbox.xml debian/$(verpkg).sharedmimeinfo install -d -g 0 -o 0 $(prefix)/usr/share/lintian/overrides sed \ -e 's|%VERPKG%|$(verpkg)|g' \ debian/lintian-override.in > \ $(prefix)/usr/share/lintian/overrides/$(verpkg) - mv $(archdir)/VBoxEFI32.fd $(prefix)/usr/lib/$(package) - mv $(archdir)/VBoxEFI64.fd $(prefix)/usr/lib/$(package) - mv $(archdir)/VBox.png \ - $(prefix)/usr/share/pixmaps/VBox.png - mv $(archdir)/*.gc $(prefix)/usr/lib/$(package) - mv $(archdir)/*.r0 $(prefix)/usr/lib/$(package) - mv $(archdir)/*.rel $(prefix)/usr/lib/$(package) || true - mv $(archdir)/VBoxNetDHCP $(prefix)/usr/lib/$(package) - mv $(archdir)/VBoxNetAdpCtl $(prefix)/usr/lib/$(package) - mv $(archdir)/VBoxXPCOMIPCD $(prefix)/usr/lib/$(package) - mv $(archdir)/components $(prefix)/usr/lib/$(package)/components - mv $(archdir)/*.so $(prefix)/usr/lib/$(package) - mv $(archdir)/*.so.4 $(prefix)/usr/lib/$(package) || true - $(if $(NOQT),,mv $(archdir)/VBoxTestOGL $(prefix)/usr/lib/$(package)) - $(if $(NOQT),,mv $(archdir)/nls $(prefix)/usr/share/$(package)) - mv $(archdir)/src $(prefix)/usr/share/$(package) - rm $(archdir)/VBox.sh - export VBOX_INSTALL_PATH=/usr/lib/$(package) && \ - cd ./debian/builddir/bin/sdk/installer && \ - python ./vboxapisetup.py install --root $(prefix) - rm -rf $(archdir)/sdk/installer - mv $(archdir)/vboxshell.py $(prefix)/usr/lib/$(package) - mv $(archdir)/sdk $(prefix)/usr/lib/$(package) - install -D -g 0 -o 0 -m 644 debian/VBox.sh $(prefix)/usr/bin/VBox - mv $(archdir)/VBoxSysInfo.sh $(prefix)/usr/share/$(package) - mv $(archdir)/VBoxCreateUSBNode.sh $(prefix)/usr/share/$(package) - for i in VBoxManage VBoxSVC $(if $(HEADLESS),,VBoxSDL) \ - $(if $(NOQT),,VirtualBox) VBoxHeadless \ - VBoxExtPackHelperApp VBoxBalloonCtrl VBoxAutostart \ - $(if $(NOWEBSVC),,vboxwebsrv webtest); do \ - mv $(archdir)/$$i $(prefix)/usr/lib/$(package); done - $(if $(VNC),mv $(archdir)/ExtensionPacks/VNC $(prefix)/usr/lib/$(package)/ExtensionPacks,) - mv $(archdir)/VBoxTunctl $(prefix)/usr/bin $(if $(NOMODS),,for d in $(moddir)/*; do \ if [ -f $$d/vboxdrv.ko -a -f $$d/vboxnetflt.ko -a -f $$d/vboxnetadp.ko -a -f $$d/vboxpci.ko ]; then \ install -D -g 0 -o 0 -m 0644 \ @@ -282,44 +229,19 @@ binary binary-arch binary-indep: build $(if $(NOMODS),,modules) fi \ done) ifeq ($(ose),) - $(if $(NOQT),,mv $(archdir)/kchmviewer $(prefix)/usr/lib/$(package)) dh_installdocs \ $(archdir)/UserManual*.pdf $(archdir)/VirtualBox*.chm \ $(addprefix $(archdir)/, LICENSE) rm $(addprefix $(archdir)/,UserManual*.pdf VirtualBox*.chm \ LICENSE) - for i in rdesktop-vrdp.tar.gz additions/VBoxGuestAdditions.iso; do \ - mv $(archdir)/$$i $(prefix)/usr/share/$(package); done - $(if $(HEADLESS),,mv $(archdir)/rdesktop-vrdp $(prefix)/usr/bin) - $(if $(HEADLESS),,mv $(archdir)/rdesktop-vrdp-keymaps $(prefix)/usr/share/$(package)) - if [ -d $(archdir)/accessible ]; then mv $(archdir)/accessible $(prefix)/usr/lib/virtualbox; fi else dh_installdocs \ $(archdir)/UserManual*.pdf rm $(addprefix $(archdir)/,UserManual*.pdf) - for i in additions/VBoxGuestAdditions.iso; do \ - mv $(archdir)/$$i $(prefix)/usr/share/$(package); done endif - rmdir $(archdir)/additions - $(if $(VNC),rmdir $(archdir)/ExtensionPacks) - rmdir $(archdir) + mv $(archdir) $(prefix)/usr/lib/$(package) + ln -s ../VBoxVMM.so $(prefix)/usr/lib/$(package)/components/VBoxVMM.so rmdir $(prefix)/opt - dh_link \ - $(if $(NOQT),,usr/bin/VBox usr/bin/VirtualBox) \ - $(if $(NOQT),,usr/bin/VBox usr/bin/virtualbox) \ - usr/bin/VBox usr/bin/VBoxManage \ - usr/bin/VBox usr/bin/vboxmanage \ - $(if $(HEADLESS),,usr/bin/VBox usr/bin/VBoxSDL) \ - $(if $(HEADLESS),,usr/bin/VBox usr/bin/vboxsdl) \ - $(if $(ose),,usr/bin/VBox usr/bin/VBoxVRDP) \ - usr/bin/VBox usr/bin/VBoxHeadless \ - usr/bin/VBox usr/bin/vboxheadless \ - usr/bin/VBox usr/bin/VBoxBalloonCtrl \ - usr/bin/VBox usr/bin/vboxballoonctrl \ - usr/bin/VBox usr/bin/VBoxAutostart \ - usr/bin/VBox usr/bin/vboxautostart \ - $(if $(NOWEBSVC),,usr/bin/VBox usr/bin/vboxwebsrv) \ - usr/share/virtualbox/src/vboxhost usr/src/vboxhost-$(ver) dh_desktop $(if $(NOMODS),,dh_installmodules) sed \ @@ -330,23 +252,11 @@ endif -e "s|%GROUP%|$(if $(VBOX_WITHOUT_HARDENING),vboxusers,root)|g" \ $(vboxroot)/src/VBox/Installer/linux/vboxdrv.sh.in > debian/vboxdrv.init dh_installinit --name=vboxdrv --noscripts - sed \ - -e 's|%NOLSB%||g' \ - -e 's|%DEBIAN%|yes|g' \ - -e 's|%PACKAGE%|virtualbox|g' \ - $(vboxroot)/src/VBox/Installer/linux/vboxballoonctrl-service.sh.in > debian/vboxballoonctrl-service.init + cp $(vboxroot)/src/VBox/Installer/linux/vboxballoonctrl-service.sh debian/vboxballoonctrl-service.init dh_installinit --name=vboxballoonctrl-service --noscripts - sed \ - -e 's|%NOLSB%||g' \ - -e 's|%DEBIAN%|yes|g' \ - -e 's|%PACKAGE%|virtualbox|g' \ - $(vboxroot)/src/VBox/Installer/linux/vboxautostart-service.sh.in > debian/vboxautostart-service.init + cp $(vboxroot)/src/VBox/Installer/linux/vboxautostart-service.sh debian/vboxautostart-service.init dh_installinit --name=vboxautostart-service --noscripts - sed \ - -e 's|%NOLSB%||g' \ - -e 's|%DEBIAN%|yes|g' \ - -e 's|%PACKAGE%|virtualbox|g' \ - $(vboxroot)/src/VBox/Installer/linux/vboxweb-service.sh.in > debian/vboxweb-service.init + cp $(vboxroot)/src/VBox/Installer/linux/vboxweb-service.sh debian/vboxweb-service.init dh_installinit --name=vboxweb-service --noscripts sed -e 's|%VER%|$(debver)|g' \ -e 's|%DATE%|$(shell date -R)|g' \ @@ -370,21 +280,12 @@ endif dh_link ifeq ($(DEBUG),) dh_strip --keep-debug --exclude=libQtCoreVBox.so.4 --exclude=libQtGuiVBox.so.4 --exclude=libQtNetworkVBox.so.4 --exclude=libQtOpenGLVBox.so.4 --exclude=libqtaccessiblewidgets.so - # manually strip our R0/GC modules, dh_strip cannot handle them - for f in \ - $(prefix)/usr/lib/$(package)/*.r0 $(prefix)/usr/lib/$(package)/*.gc; do \ - objcopy --only-keep-debug \ - $$f \ - $(prefix)/usr/lib/debug/usr/lib/$(package)/`basename $$f`; \ - strip -S --remove-section=.comment $$f; \ - objcopy --add-gnu-debuglink=$(prefix)/usr/lib/debug/usr/lib/$(package)/`basename $$f` $$f; \ - done endif mkdir -p $(current)/debian/$(verpkg)-dbg/usr/lib ifeq ($(DEBUG),) mv $(current)/debian/$(verpkg)/usr/lib/debug $(current)/debian/$(verpkg)-dbg/usr/lib endif - dh_pycentral + $(if $(filter _Ubuntu_hardy _Ubuntu_lucid,$(debrel)),dh_pycentral,dh_python2) dh_compress -X.pdf -X.chm -X LICENSE -X.py dh_fixperms dh_makeshlibs @@ -399,7 +300,7 @@ endif -Vdkms=$(if $(filter _Debian_lenny,$(debrel)),,dkms) dh_md5sums dh_builddeb --destdir $(pkgdir) -- \ - $(if $(filter _Ubuntu_hardy _Ubuntu_lucid,$(debrel)),,-Zxz) + $(if $(filter _Ubuntu_lucid,$(debrel)),,-Zxz) endif .PHONY: binary modules binary-arch binary-indep clean checkroot diff --git a/src/VBox/Installer/linux/distributions_deb b/src/VBox/Installer/linux/distributions_deb index 3e668628..9b8f3461 100644 --- a/src/VBox/Installer/linux/distributions_deb +++ b/src/VBox/Installer/linux/distributions_deb @@ -1,19 +1,7 @@ _Debian_sid = DEBIAN_7_0 _Debian_wheezy = DEBIAN_7_0 _Debian_squeeze = DEBIAN_6_0 -_Debian_lenny = DEBIAN_5_0 -_Debian_etch = DEBIAN_4_0 -_Debian_sarge = DEBIAN_3_1 +_Ubuntu_raring = UBUNTU_13_04 _Ubuntu_quantal = UBUNTU_12_10 _Ubuntu_precise = UBUNTU_12_04 -_Ubuntu_oneiric = UBUNTU_11_10 -_Ubuntu_natty = UBUNTU_11_04 -_Ubuntu_maverick = UBUNTU_10_10 _Ubuntu_lucid = UBUNTU_10_04 -_Ubuntu_karmic = UBUNTU_9_10 -_Ubuntu_jaunty = UBUNTU_9_04 -_Ubuntu_intrepid = UBUNTU_8_10 -_Ubuntu_hardy = UBUNTU_8_04 -_Ubuntu_gutsy = UBUNTU_7_10 -_Ubuntu_dapper = UBUNTU_6_06 -_xandros4.1 = XANDROS_4_1 diff --git a/src/VBox/Installer/linux/distributions_rpm b/src/VBox/Installer/linux/distributions_rpm index 17e3e6ae..f0591237 100644 --- a/src/VBox/Installer/linux/distributions_rpm +++ b/src/VBox/Installer/linux/distributions_rpm @@ -1,36 +1,16 @@ +openSUSE123 = OPENSUSE_12_3 openSUSE114 = OPENSUSE_11_4 openSUSE113 = OPENSUSE_11_3 -openSUSE112 = OPENSUSE_11_2 -openSUSE111 = OPENSUSE_11_1 -openSUSE110 = OPENSUSE_11_0 -openSUSE103 = OPENSUSE_10_3 -openSUSE102 = OPENSUSE_10_2 sles11.0 = SLES_11_0 sles10.1 = SLES_10_1 mdv2011.0 = MANDRIVA_2011_0 -mdv2010.0 = MANDRIVA_2010_0 -mdv2009.1 = MANDRIVA_2009_1 -mdv2008.0 = MANDRIVA_2008_0 -mdv2007.1 = MANDRIVA_2007_1 +fedora18 = FEDORA_18 fedora17 = FEDORA_17 fedora16 = FEDORA_16 fedora15 = FEDORA_15 -fedora14 = FEDORA_14 -fedora13 = FEDORA_13 -fedora12 = FEDORA_12 -fedora11 = FEDORA_11 -fedora9 = FEDORA_9 -fedora8 = FEDORA_8 -fedora7 = FEDORA_7 -fedora6 = FEDORA_6 el6 = EL_6 el5 = EL_5 -el4 = EL_4 centos6 = CENTOS_6 centos5 = CENTOS_5 -centos4 = CENTOS_4 -pclinuxos2007 = PCLINUXOS_2007 -turbolinux11 = TURBOLINUX_11 ol6 = ORACLE_6 ol5 = ORACLE_5 -ol4 = ORACLE_4 diff --git a/src/VBox/Installer/linux/install.sh b/src/VBox/Installer/linux/install.sh index 67e79b4a..a590e8ae 100755 --- a/src/VBox/Installer/linux/install.sh +++ b/src/VBox/Installer/linux/install.sh @@ -4,7 +4,7 @@ # VirtualBox linux installation script # -# Copyright (C) 2007-2011 Oracle Corporation +# Copyright (C) 2007-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -246,6 +246,7 @@ if [ "$ACTION" = "install" ]; then # Terminate Server and VBoxNetDHCP if running terminate_proc VBoxSVC terminate_proc VBoxNetDHCP + terminate_proc VBoxNetNAT # Remove previous installation if [ -n "$PREV_INSTALLATION" -a -z "$FORCE_UPGRADE" -a ! "$VERSION" = "$INSTALL_VER" ] && @@ -355,22 +356,21 @@ if [ "$ACTION" = "install" ]; then # create symlinks for working around unsupported $ORIGIN/.. in VBoxC.so (setuid), # and finally make sure the directory is only writable by the user (paranoid). if [ -n "$HARDENED" ]; then - test -e $INSTALLATION_DIR/VirtualBox && chmod 4511 $INSTALLATION_DIR/VirtualBox - test -e $INSTALLATION_DIR/VBoxSDL && chmod 4511 $INSTALLATION_DIR/VBoxSDL - test -e $INSTALLATION_DIR/VBoxHeadless && chmod 4511 $INSTALLATION_DIR/VBoxHeadless - test -e $INSTALLATION_DIR/VBoxNetDHCP && chmod 4511 $INSTALLATION_DIR/VBoxNetDHCP + test -e $INSTALLATION_DIR/VirtualBox && chmod 4511 $INSTALLATION_DIR/VirtualBox + test -e $INSTALLATION_DIR/VBoxSDL && chmod 4511 $INSTALLATION_DIR/VBoxSDL + test -e $INSTALLATION_DIR/VBoxHeadless && chmod 4511 $INSTALLATION_DIR/VBoxHeadless + test -e $INSTALLATION_DIR/VBoxNetDHCP && chmod 4511 $INSTALLATION_DIR/VBoxNetDHCP + test -e $INSTALLATION_DIR/VBoxNetNAT && chmod 4511 $INSTALLATION_DIR/VBoxNetNAT ln -sf $INSTALLATION_DIR/VBoxVMM.so $INSTALLATION_DIR/components/VBoxVMM.so - ln -sf $INSTALLATION_DIR/VBoxREM.so $INSTALLATION_DIR/components/VBoxREM.so ln -sf $INSTALLATION_DIR/VBoxRT.so $INSTALLATION_DIR/components/VBoxRT.so - ln -sf $INSTALLATION_DIR/VBoxDDU.so $INSTALLATION_DIR/components/VBoxDDU.so - ln -sf $INSTALLATION_DIR/VBoxXPCOM.so $INSTALLATION_DIR/components/VBoxXPCOM.so chmod go-w $INSTALLATION_DIR fi - # This binary needs to be suid root in any case, even if not hardened + # This binaries need to be suid root in any case, even if not hardened test -e $INSTALLATION_DIR/VBoxNetAdpCtl && chmod 4511 $INSTALLATION_DIR/VBoxNetAdpCtl + test -e $INSTALLATION_DIR/VBoxVolInfo && chmod 4511 $INSTALLATION_DIR/VBoxVolInfo # Install runlevel scripts # Note: vboxdrv is also handled by setup_init_script. This function will @@ -391,7 +391,7 @@ if [ "$ACTION" = "install" ]; then addrunlevel vboxweb-service 25 75 # This may produce useful output # Create users group - groupadd $GROUPNAME 2> /dev/null + groupadd -r -f $GROUPNAME 2> /dev/null # Create symlinks to start binaries ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VirtualBox @@ -423,7 +423,7 @@ if [ "$ACTION" = "install" ]; then cd $i if [ -d /usr/share/icons/hicolor/$i ]; then for j in *; do - if [ "$j" = "virtualbox.png" ]; then + if expr "$j" : "virtualbox\..*" > /dev/null; then dst=apps else dst=mimetypes diff --git a/src/VBox/Installer/linux/install_service/Makefile.kmk b/src/VBox/Installer/linux/install_service/Makefile.kmk new file mode 100644 index 00000000..812a75ea --- /dev/null +++ b/src/VBox/Installer/linux/install_service/Makefile.kmk @@ -0,0 +1,49 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-Makefile for the Linux installer init file generator. +# + +# +# Copyright (C) 2006-2012 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. +# + +SUB_DEPTH = ../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +# +# generate_service_file +# +PROGRAMS.linux += generate_service_file + +generate_service_file_TEMPLATE = VBOXR3EXE +generate_service_file_SOURCES = generate_service_file.cpp +generate_service_file_INST = $(INST_BIN)helpers/ +generate_service_file_LIBS = $(LIB_RUNTIME) +ifdef VBOX_WITH_RUNPATH + generate_service_file_LDFLAGS = '$(VBOX_GCC_RPATH_OPT)$(VBOX_WITH_RUNPATH)' +else ifdef VBOX_WITH_RELATIVE_RUNPATH + generate_service_file_LDFLAGS = '$(VBOX_GCC_RPATH_OPT)$(VBOX_WITH_RELATIVE_RUNPATH)/..' +endif + +INSTALLS.linux += linux-install-service-bin +linux-install-service-bin_INST = bin/scripts/ +linux-install-service-bin_MODE = a+rx,u+w +linux-install-service-bin_SOURCES = \ + install_service.sh=>install_service + +INSTALLS.linux += linux-install-service-nobin +linux-install-service-nobin_INST = bin/scripts/ +linux-install-service-nobin_MODE = a+r,u+w +linux-install-service-nobin_SOURCES = \ + init_template.sh + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Installer/linux/install_service/generate_service_file.cpp b/src/VBox/Installer/linux/install_service/generate_service_file.cpp new file mode 100644 index 00000000..2ff27573 --- /dev/null +++ b/src/VBox/Installer/linux/install_service/generate_service_file.cpp @@ -0,0 +1,912 @@ +/* $Id: generate_service_file.cpp $ */ +/** @file + * Read a service file template from standard input and output a service file + * to standard output generated from the template based on arguments passed to + * the utility. See the usage text for more information. + */ + +/* + * Copyright (C) 2012-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. + */ + +/** + * Description of the generation process. + * + * A template for the service file to be generated is fed into standard input + * and the service file is sent to standard output. The following + * substitutions are performed based on the command line parameters supplied, + * with all quoting appropriate to the format of the template as specified on + * the command line. + * + * %COMMAND% -> path to the service binary or script. + * %ARGUMENTS% -> the arguments to pass to the binary when starting the + * service. + * %SERVICE_NAME% -> the name of the service. + * %DESCRIPTION% -> the short description of the service. + * %STOP_COMMAND% -> path to the command used to stop the service. + * %STOP_ARGUMENTS% -> the arguments for the stop command + * %STATUS_COMMAND% -> path to the command used to determine the service + * status. + * %STATUS_ARGUMENTS% -> the arguments for the status command + + * %NO_STOP_COMMAND% -> if no stop command was specified, this and all text + * following it on the line (including the end-of- + * line) will be removed, otherwise only the marker + * will be removed. + * %HAVE_STOP_COMMAND% -> like above, but text on the line will be removed + * if a stop command was supplied. + * %NO_STATUS_COMMAND% -> Analogue to %NO_STOP_COMMAND% for the status + * command. + * %HAVE_STATUS_COMMAND% -> Analogue to %HAVE_STOP_COMMAND% for the status + * command. + * %HAVE_ONESHOT% -> like above, text on the line will be removed unless + * --one-shot was specified on the command line. + * %HAVE_DAEMON% -> the same if --one-shot was not specified. + * + * %% will be replaced with a single %. + */ + +#include <VBox/version.h> + +#include <iprt/ctype.h> +#include <iprt/getopt.h> +#include <iprt/initterm.h> +#include <iprt/mem.h> +#include <iprt/message.h> +#include <iprt/path.h> +#include <iprt/stream.h> +#include <iprt/string.h> + +#ifndef READ_SIZE +/** How much of the input we read at a time. Override to something small for + * testing. */ +# define READ_SIZE _1M +#endif + +/* Macros for the template substitution sequences to guard against mis-types. */ +#define COMMAND "%COMMAND%" +#define ARGUMENTS "%ARGUMENTS%" +#define DESCRIPTION "%DESCRIPTION%" +#define SERVICE_NAME "%SERVICE_NAME%" +#define HAVE_ONESHOT "%HAVE_ONESHOT%" +#define HAVE_DAEMON "%HAVE_DAEMON%" +#define STOP_COMMAND "%STOP_COMMAND%" +#define STOP_ARGUMENTS "%STOP_ARGUMENTS%" +#define HAVE_STOP_COMMAND "%HAVE_STOP_COMMAND%" +#define NO_STOP_COMMAND "%NO_STOP_COMMAND%" +#define STATUS_COMMAND "%STATUS_COMMAND%" +#define STATUS_ARGUMENTS "%STATUS_ARGUMENTS%" +#define HAVE_STATUS_COMMAND "%HAVE_STATUS_COMMAND%" +#define NO_STATUS_COMMAND "%NO_STATUS_COMMAND%" + +void showLogo(void) +{ + static bool s_fShown; /* show only once */ + + RTPrintf(VBOX_PRODUCT " Service File Generator Version " + VBOX_VERSION_STRING "\n" + "(C) 2012" /* "-" VBOX_C_YEAR */ " " VBOX_VENDOR "\n" + "All rights reserved.\n" + "\n"); +} + +static void showOptions(void); + +void showUsage(const char *pcszArgv0) +{ + const char *pcszName = strrchr(pcszArgv0, '/'); + if (!pcszName) + pcszName = pcszArgv0; + RTPrintf( +"Usage:\n" +"\n" +" %s --help|-h|-?|--version|-V|--format <format> <parameters...>\n\n", + pcszArgv0); + RTPrintf( +"Read a service file template from standard input and output a service file to\n" +"standard output which was generated from the template based on parameters\n" +"passed on the utility's command line. Generation is done by replacing well-\n" +"known text sequences in the template with strings based on the parameters.\n" +"All strings should be in UTF-8 format. Processing will stop if a sequence is\n" +"read which cannot be replace based on the parameters supplied.\n\n"); + + RTPrintf( +" --help|-h|-?\n" +" Print this help text and exit.\n\n" +" --version|-V\n" +" Print version information and exit.\n\n" +" --format <shell>\n" +" The format of the template. Currently only \"shell\" for shell script\n" +" is supported. This affects escaping of strings substituted.\n\n"); + RTPrintf( +"Parameters:\n" +"\n"); + RTPrintf( +" --command <command>\n" +" The absolute path of the executable file to be started by the service.\n" +" No form of quoting should be used here.\n\n"); + RTPrintf( +" --description <description>\n" +" A short description of the service which can also be used in sentences\n" +" like \"<description> failed to start.\", as a single parameter. Characters\n" +" 0 to 31 and 127 should not be used.\n\n" + ); + RTPrintf( +" --arguments <arguments>\n" +" The arguments to pass to the executable file when it is started, as a\n" +" single parameter. Characters \" \", \"\\\" and \"%%\" must be escaped with\n" +" back-slashes and C string-style back-slash escapes are recognised. Some\n" +" systemd-style \"%%\" sequences may be added at a future time.\n\n"); + RTPrintf( +" --service-name <name>\n" +" Specify the name of the service. By default the base name without the\n" +" extension of the command binary is used. Only ASCII characters 33 to 126\n" +" should be used.\n\n"); + RTPrintf( +" --one-shot\n" +" The service command is expected to do some work and exit immediately with" +" a status indicating success or failure.\n\n" + ); + RTPrintf( +" --stop-command <command>\n" +" The command which should be used to stop the service before sending the\n" +" termination signal to the main process. No form of quoting should be\n" +" used here.\n\n" + ); + RTPrintf( +" --stop-arguments <arguments>\n" +" Arguments for the stop command. This may only be used in combination\n" +" with \"--stop-command\". Quoting is the same as for \"--arguments\".\n\n" + ); + RTPrintf( +" --status-command <command>\n" +" The command which should be used to determine the status of the service.\n" +" This may not be respected by all service management systems. The command\n" +" should return an LSB status code. No form of quoting should be used.\n\n" + ); + RTPrintf( +" --stop-arguments <arguments>\n" +" Arguments for the status command. This may only be used in combination\n" +" with \"--status-command\". Quoting is the same as for \"--arguments\".\n\n" + ); +} + +/** @name Template format. + * @{ + */ +enum ENMFORMAT +{ + /** No format selected. */ + FORMAT_NONE = 0, + /** Shell script format. */ + FORMAT_SHELL +}; +/** @} */ + +struct SERVICEPARAMETERS +{ + enum ENMFORMAT enmFormat; + const char *pcszCommand; + const char *pcszArguments; + const char *pcszDescription; + const char *pcszServiceName; + bool fOneShot; + const char *pcszStopCommand; + const char *pcszStopArguments; + const char *pcszStatusCommand; + const char *pcszStatusArguments; +}; + +static bool errorIfSet(const char *pcszName, bool isSet); +static enum ENMFORMAT getFormat(const char *pcszName, const char *pcszValue); +static bool checkAbsoluteFilePath(const char *pcszName, const char *pcszValue); +static bool checkPrintable(const char *pcszName, const char *pcszValue); +static bool checkGraphic(const char *pcszName, const char *pcszValue); +static bool createServiceFile(struct SERVICEPARAMETERS *pParameters); + +int main(int cArgs, char **apszArgs) +{ + int rc = RTR3InitExe(cArgs, &apszArgs, 0); + if (RT_FAILURE(rc)) + return RTMsgInitFailure(rc); + + enum + { + OPTION_FORMAT = 1, + OPTION_COMMAND, + OPTION_ARGUMENTS, + OPTION_DESCRIPTION, + OPTION_SERVICE_NAME, + OPTION_ONE_SHOT, + OPTION_STOP_COMMAND, + OPTION_STOP_ARGUMENTS, + OPTION_STATUS_COMMAND, + OPTION_STATUS_ARGUMENTS + }; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--format", OPTION_FORMAT, + RTGETOPT_REQ_STRING }, + { "--command", OPTION_COMMAND, + RTGETOPT_REQ_STRING }, + { "--arguments", OPTION_ARGUMENTS, + RTGETOPT_REQ_STRING }, + { "--description", OPTION_DESCRIPTION, + RTGETOPT_REQ_STRING }, + { "--service-name", OPTION_SERVICE_NAME, + RTGETOPT_REQ_STRING }, + { "--one-shot", OPTION_ONE_SHOT, + RTGETOPT_REQ_NOTHING }, + { "--stop-command", OPTION_STOP_COMMAND, + RTGETOPT_REQ_STRING }, + { "--stop-arguments", OPTION_STOP_ARGUMENTS, + RTGETOPT_REQ_STRING }, + { "--status-command", OPTION_STATUS_COMMAND, + RTGETOPT_REQ_STRING }, + { "--status-arguments", OPTION_STATUS_ARGUMENTS, + RTGETOPT_REQ_STRING } + }; + + int ch; + struct SERVICEPARAMETERS Parameters = { FORMAT_NONE }; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, cArgs, apszArgs, s_aOptions, + RT_ELEMENTS(s_aOptions), 1, 0); + while ((ch = RTGetOpt(&GetState, &ValueUnion))) + { + switch (ch) + { + case 'h': + showUsage(apszArgs[0]); + return RTEXITCODE_SUCCESS; + break; + + case 'V': + showLogo(); + return RTEXITCODE_SUCCESS; + break; + + case OPTION_FORMAT: + if (errorIfSet("--format", + Parameters.enmFormat != FORMAT_NONE)) + return(RTEXITCODE_SYNTAX); + Parameters.enmFormat + = getFormat("--format", ValueUnion.psz); + if (Parameters.enmFormat == FORMAT_NONE) + return(RTEXITCODE_SYNTAX); + break; + + case OPTION_COMMAND: + if (errorIfSet("--command", Parameters.pcszCommand)) + return(RTEXITCODE_SYNTAX); + Parameters.pcszCommand = ValueUnion.psz; + if (!checkAbsoluteFilePath("--command", + Parameters.pcszCommand)) + return(RTEXITCODE_SYNTAX); + break; + + case OPTION_ARGUMENTS: + if (errorIfSet("--arguments", + Parameters.pcszArguments)) + return(RTEXITCODE_SYNTAX); + /* Quoting will be checked while writing out the string. */ + Parameters.pcszArguments = ValueUnion.psz; + break; + + case OPTION_DESCRIPTION: + if (errorIfSet("--description", + Parameters.pcszDescription)) + return(RTEXITCODE_SYNTAX); + Parameters.pcszDescription = ValueUnion.psz; + if (!checkPrintable("--description", + Parameters.pcszDescription)) + return(RTEXITCODE_SYNTAX); + break; + + case OPTION_SERVICE_NAME: + if (errorIfSet("--service-name", + Parameters.pcszServiceName)) + return(RTEXITCODE_SYNTAX); + Parameters.pcszServiceName = ValueUnion.psz; + if (!checkGraphic("--service-name", + Parameters.pcszServiceName)) + return(RTEXITCODE_SYNTAX); + break; + + case OPTION_ONE_SHOT: + Parameters.fOneShot = true; + break; + + case OPTION_STOP_COMMAND: + if (errorIfSet("--stop-command", + Parameters.pcszStopCommand)) + return(RTEXITCODE_SYNTAX); + Parameters.pcszStopCommand = ValueUnion.psz; + if (!checkAbsoluteFilePath("--stop-command", + Parameters.pcszStopCommand)) + return(RTEXITCODE_SYNTAX); + break; + + case OPTION_STOP_ARGUMENTS: + if (errorIfSet("--stop-arguments", + Parameters.pcszStopArguments)) + return(RTEXITCODE_SYNTAX); + /* Quoting will be checked while writing out the string. */ + Parameters.pcszStopArguments = ValueUnion.psz; + break; + + case OPTION_STATUS_COMMAND: + if (errorIfSet("--status-command", + Parameters.pcszStatusCommand)) + return(RTEXITCODE_SYNTAX); + Parameters.pcszStatusCommand = ValueUnion.psz; + if (!checkAbsoluteFilePath("--status-command", + Parameters.pcszStatusCommand)) + return(RTEXITCODE_SYNTAX); + break; + + case OPTION_STATUS_ARGUMENTS: + if (errorIfSet("--status-arguments", + Parameters.pcszStatusArguments)) + return(RTEXITCODE_SYNTAX); + /* Quoting will be checked while writing out the string. */ + Parameters.pcszStatusArguments = ValueUnion.psz; + break; + + default: + return RTGetOptPrintError(ch, &ValueUnion); + } + } + if (Parameters.enmFormat == FORMAT_NONE) + { + RTStrmPrintf(g_pStdErr, "--format must be specified.\n"); + return(RTEXITCODE_SYNTAX); + } + if (Parameters.pcszArguments && !Parameters.pcszCommand) + { + RTStrmPrintf(g_pStdErr, "--arguments requires --command to be specified.\n"); + return(RTEXITCODE_SYNTAX); + } + if (Parameters.pcszStopArguments && !Parameters.pcszStopCommand) + { + RTStrmPrintf(g_pStdErr, "--stop-arguments requires --stop-command to be specified.\n"); + return(RTEXITCODE_SYNTAX); + } + if (Parameters.pcszStatusArguments && !Parameters.pcszStatusCommand) + { + RTStrmPrintf(g_pStdErr, "--status-arguments requires --status-command to be specified.\n"); + return(RTEXITCODE_SYNTAX); + } + return createServiceFile(&Parameters) + ? RTEXITCODE_SUCCESS + : RTEXITCODE_FAILURE; +} + +/** Print an error and return true if an option is already set. */ +bool errorIfSet(const char *pcszName, bool isSet) +{ + if (isSet) + RTStrmPrintf(g_pStdErr, "%s may only be specified once.\n", pcszName); + return isSet; +} + +/** Match the string to a known format and return that (or "none" and print an + * error). */ +enum ENMFORMAT getFormat(const char *pcszName, const char *pcszValue) +{ + if (!strcmp(pcszValue, "shell")) + return FORMAT_SHELL; + RTStrmPrintf(g_pStdErr, "%s: unknown format %s.\n", pcszName, pcszValue); + return FORMAT_NONE; +} + +/** Check that the string is an absolute path to a file or print an error. */ +bool checkAbsoluteFilePath(const char *pcszName, const char *pcszValue) +{ + if (RTPathFilename(pcszValue) && RTPathStartsWithRoot(pcszValue)) + return true; + RTStrmPrintf(g_pStdErr, "%s: %s must be an absolute path of a file.\n", pcszName, pcszValue); + return false; +} + +/** Check that the string does not contain any non-printable characters. */ +bool checkPrintable(const char *pcszName, const char *pcszValue) +{ + const char *pcch = pcszValue; + for (; *pcch; ++pcch) + { + if (!RT_C_IS_PRINT(*pcch)) + { + RTStrmPrintf(g_pStdErr, "%s: invalid character after \"%.*s\".\n", + pcszName, pcch - pcszValue, pcszValue); + return false; + } + } + return true; +} + +/** Check that the string does not contain any non-graphic characters. */ +static bool checkGraphic(const char *pcszName, const char *pcszValue) +{ + const char *pcch = pcszValue; + for (; *pcch; ++pcch) + { + if (!RT_C_IS_GRAPH(*pcch)) + { + RTStrmPrintf(g_pStdErr, "%s: invalid character after \"%.*s\".\n", + pcszName, pcch - pcszValue, pcszValue); + return false; + } + } + return true; +} + +static bool createServiceFileCore(char **ppachTemplate, + struct SERVICEPARAMETERS + *pParamters); + +/** + * Read standard input and write it to standard output, doing all substitutions + * as per the usage documentation. + * @note This is a wrapper around the actual function to simplify resource + * allocation without requiring a single point of exit. + */ +bool createServiceFile(struct SERVICEPARAMETERS *pParameters) +{ + char *pachTemplate = NULL; + bool rc = createServiceFileCore(&pachTemplate, pParameters); + RTMemFree(pachTemplate); + return rc; +} + +static bool getSequence(const char *pach, size_t cch, size_t *pcchRead, + const char *pcszSequence, size_t cchSequence); +static bool writeCommand(enum ENMFORMAT enmFormat, const char *pcszCommand); +static bool writeQuoted(enum ENMFORMAT enmFormat, const char *pcszQuoted); +static bool writePrintableString(enum ENMFORMAT enmFormat, + const char *pcszString); +static void skipLine(const char *pach, size_t cch, size_t *pcchRead); + +/** The actual implemenation code for @a createServiceFile. */ +bool createServiceFileCore(char **ppachTemplate, + struct SERVICEPARAMETERS *pParameters) +{ + /* The size of the template data we have read. */ + size_t cchTemplate = 0; + /* The size of the buffer we have allocated. */ + size_t cbBuffer = 0; + /* How much of the template data we have written out. */ + size_t cchWritten = 0; + int rc = VINF_SUCCESS; + /* First of all read in the file. */ + while (rc != VINF_EOF) + { + size_t cchRead; + + if (cchTemplate == cbBuffer) + { + cbBuffer += READ_SIZE; + *ppachTemplate = (char *)RTMemRealloc((void *)*ppachTemplate, + cbBuffer); + } + if (!*ppachTemplate) + { + RTStrmPrintf(g_pStdErr, "Out of memory.\n"); + return false; + } + rc = RTStrmReadEx(g_pStdIn, *ppachTemplate + cchTemplate, + cbBuffer - cchTemplate, &cchRead); + if (RT_FAILURE(rc)) + { + RTStrmPrintf(g_pStdErr, "Error reading input: %Rrc\n", rc); + return false; + } + if (!cchRead) + rc = VINF_EOF; + cchTemplate += cchRead; + } + while (true) + { + /* Find the next '%' character if any and write out up to there (or the + * end if there is no '%'). */ + char *pchNext = (char *) memchr((void *)(*ppachTemplate + cchWritten), + '%', cchTemplate - cchWritten); + size_t cchToWrite = pchNext + ? pchNext - *ppachTemplate - cchWritten + : cchTemplate - cchWritten; + rc = RTStrmWrite(g_pStdOut, *ppachTemplate + cchWritten, cchToWrite); + if (RT_FAILURE(rc)) + { + RTStrmPrintf(g_pStdErr, "Error writing output: %Rrc\n", rc); + return false; + } + cchWritten += cchToWrite; + if (!pchNext) + break; + /* And substitute any of our well-known strings. We favour code + * readability over efficiency here. */ + if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + COMMAND, sizeof(COMMAND) - 1)) + { + if (!pParameters->pcszCommand) + { + RTStrmPrintf(g_pStdErr, "--command not specified.\n"); + return false; + } + if (!writeCommand(pParameters->enmFormat, + pParameters->pcszCommand)) + return false; + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + ARGUMENTS, sizeof(ARGUMENTS) - 1)) + { + if ( pParameters->pcszArguments + && !writeQuoted(pParameters->enmFormat, + pParameters->pcszArguments)) + return false; + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + DESCRIPTION, sizeof(DESCRIPTION) - 1)) + { + if (!pParameters->pcszDescription) + { + RTStrmPrintf(g_pStdErr, "--description not specified.\n"); + return false; + } + if (!writePrintableString(pParameters->enmFormat, + pParameters->pcszDescription)) + return false; + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + SERVICE_NAME, sizeof(SERVICE_NAME) - 1)) + { + if ( !pParameters->pcszCommand + && !pParameters->pcszServiceName) + { + RTStrmPrintf(g_pStdErr, "Neither --command nor --service-name specified.\n"); + return false; + } + if (pParameters->pcszServiceName) + { + if (!writePrintableString(pParameters->enmFormat, + pParameters->pcszServiceName)) + return false; + } + else + { + const char *pcszFileName = + RTPathFilename(pParameters->pcszCommand); + const char *pcszExtension = + RTPathExt(pParameters->pcszCommand); + char *pszName = RTStrDupN(pcszFileName, + pcszExtension + ? pcszExtension - pcszFileName + : RTPATH_MAX); + bool fRc; + if (!pszName) + { + RTStrmPrintf(g_pStdErr, "Out of memory.\n"); + return false; + } + fRc = writePrintableString(pParameters->enmFormat, + pszName); + RTStrFree(pszName); + if (!fRc) + return false; + } + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + HAVE_ONESHOT, sizeof(HAVE_ONESHOT) - 1)) + { + if (!pParameters->fOneShot) + skipLine(*ppachTemplate, cchTemplate, &cchWritten); + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + HAVE_DAEMON, sizeof(HAVE_DAEMON) - 1)) + { + if (pParameters->fOneShot) + skipLine(*ppachTemplate, cchTemplate, &cchWritten); + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + STOP_COMMAND, sizeof(STOP_COMMAND) - 1)) + { + if ( pParameters->pcszStopCommand + && !writeCommand(pParameters->enmFormat, + pParameters->pcszStopCommand)) + return false; + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + STOP_ARGUMENTS, sizeof(STOP_ARGUMENTS) - 1)) + { + if ( pParameters->pcszStopArguments + && !writeQuoted(pParameters->enmFormat, + pParameters->pcszStopArguments)) + return false; + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + HAVE_STOP_COMMAND, sizeof(HAVE_STOP_COMMAND) - 1)) + { + if (!pParameters->pcszStopCommand) + skipLine(*ppachTemplate, cchTemplate, &cchWritten); + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + NO_STOP_COMMAND, sizeof(NO_STOP_COMMAND) - 1)) + { + if (pParameters->pcszStopCommand) + skipLine(*ppachTemplate, cchTemplate, &cchWritten); + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + STATUS_COMMAND, sizeof(STATUS_COMMAND) - 1)) + { + if ( pParameters->pcszStatusCommand + && !writeCommand(pParameters->enmFormat, + pParameters->pcszStatusCommand)) + return false; + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + STATUS_ARGUMENTS, sizeof(STATUS_ARGUMENTS) - 1)) + { + if ( pParameters->pcszStatusArguments + && !writeQuoted(pParameters->enmFormat, + pParameters->pcszStatusArguments)) + return false; + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + HAVE_STATUS_COMMAND, + sizeof(HAVE_STATUS_COMMAND) - 1)) + { + if (!pParameters->pcszStatusCommand) + skipLine(*ppachTemplate, cchTemplate, &cchWritten); + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + NO_STATUS_COMMAND, sizeof(NO_STATUS_COMMAND) - 1)) + { + if (pParameters->pcszStatusCommand) + skipLine(*ppachTemplate, cchTemplate, &cchWritten); + } + else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, + "%%", 2)) + { + rc = RTStrmPutCh(g_pStdOut, '%'); + if (RT_FAILURE(rc)) + { + RTStrmPrintf(g_pStdErr, "Error writing output: %Rrc\n", rc); + return false; + } + } + else + { + RTStrmPrintf(g_pStdErr, "Unknown substitution sequence in input at \"%.*s\"\n", + RT_MIN(16, cchTemplate - cchWritten), + *ppachTemplate + cchWritten); + return false; + } + } + return true; +} + +bool getSequence(const char *pach, size_t cch, size_t *pcchRead, + const char *pcszSequence, size_t cchSequence) +{ + if ( cch - *pcchRead >= cchSequence + && !RTStrNCmp(pach + *pcchRead, pcszSequence, cchSequence)) + { + *pcchRead += cchSequence; + return true; + } + return false; +} + +/** Write a character to standard output and print an error and return false on + * failure. */ +bool outputCharacter(char ch) +{ + int rc = RTStrmWrite(g_pStdOut, &ch, 1); + if (RT_FAILURE(rc)) + { + RTStrmPrintf(g_pStdErr, "Error writing output: %Rrc\n", rc); + return false; + } + return true; +} + +/** Write a string to standard output and print an error and return false on + * failure. */ +bool outputString(const char *pcsz) +{ + int rc = RTStrmPutStr(g_pStdOut, pcsz); + if (RT_FAILURE(rc)) + { + RTStrmPrintf(g_pStdErr, "Error writing output: %Rrc\n", rc); + return false; + } + return true; +} + +/** Write a character to standard output, adding any escaping needed for the + * format being written. */ +static bool escapeAndOutputCharacter(enum ENMFORMAT enmFormat, char ch) +{ + if (enmFormat == FORMAT_SHELL) + { + if (ch == '\'') + return outputString("\'\\\'\'"); + return outputCharacter(ch); + } + RTStrmPrintf(g_pStdErr, "Error: unknown template format.\n"); + return false; +} + +/** Write a character to standard output, adding any escaping needed for the + * format being written. */ +static bool outputArgumentSeparator(enum ENMFORMAT enmFormat) +{ + if (enmFormat == FORMAT_SHELL) + return outputString("\' \'"); + RTStrmPrintf(g_pStdErr, "Error: unknown template format.\n"); + return false; +} + +bool writeCommand(enum ENMFORMAT enmFormat, const char *pcszCommand) +{ + if (enmFormat == FORMAT_SHELL) + if (!outputCharacter('\'')) + return false; + for (; *pcszCommand; ++pcszCommand) + if (enmFormat == FORMAT_SHELL) + { + if (*pcszCommand == '\'') + { + if (!outputString("\'\\\'\'")) + return false; + } + else if (!outputCharacter(*pcszCommand)) + return false; + } + if (enmFormat == FORMAT_SHELL) + if (!outputCharacter('\'')) + return false; + return true; +} + +const char aachEscapes[][2] = +{ + { 'a', '\a' }, { 'b', '\b' }, { 'f', '\f' }, { 'n', '\n' }, { 'r', '\r' }, + { 't', '\t' }, { 'v', '\v' }, { 0, 0 } +}; + +bool writeQuoted(enum ENMFORMAT enmFormat, const char *pcszQuoted) +{ + /* Was the last character seen a back slash? */ + bool fEscaped = false; + /* Was the last character seen an argument separator (an unescaped space)? + */ + bool fNextArgument = false; + + if (enmFormat == FORMAT_SHELL) + if (!outputCharacter('\'')) + return false; + for (; *pcszQuoted; ++pcszQuoted) + { + if (fEscaped) + { + bool fRc = true; + const char (*pachEscapes)[2]; + fEscaped = false; + /* One-letter escapes. */ + for (pachEscapes = aachEscapes; (*pachEscapes)[0]; ++pachEscapes) + if (*pcszQuoted == (*pachEscapes)[0]) + { + if (!escapeAndOutputCharacter(enmFormat, (*pachEscapes)[1])) + return false; + break; + } + if ((*pachEscapes)[0]) + continue; + /* Octal. */ + if (*pcszQuoted >= '0' && *pcszQuoted <= '7') + { + uint8_t cNum; + char *pchNext; + char achDigits[4]; + int rc; + RTStrCopy(achDigits, sizeof(achDigits), pcszQuoted); + rc = RTStrToUInt8Ex(achDigits, &pchNext, 8, &cNum); + if (rc == VWRN_NUMBER_TOO_BIG) + { + RTStrmPrintf(g_pStdErr, "Invalid octal sequence at \"%.16s\"\n", + pcszQuoted - 1); + return false; + } + if (!escapeAndOutputCharacter(enmFormat, cNum)) + return false; + pcszQuoted += pchNext - achDigits - 1; + continue; + } + /* Hexadecimal. */ + if (*pcszQuoted == 'x') + { + uint8_t cNum; + char *pchNext; + char achDigits[3]; + int rc; + RTStrCopy(achDigits, sizeof(achDigits), pcszQuoted + 1); + rc = RTStrToUInt8Ex(achDigits, &pchNext, 16, &cNum); + if ( rc == VWRN_NUMBER_TOO_BIG + || rc == VWRN_NEGATIVE_UNSIGNED + || RT_FAILURE(rc)) + { + RTStrmPrintf(g_pStdErr, "Invalid hexadecimal sequence at \"%.16s\"\n", + pcszQuoted - 1); + return false; + } + if (!escapeAndOutputCharacter(enmFormat, cNum)) + return false; + pcszQuoted += pchNext - achDigits; + continue; + } + /* Output anything else non-zero as is. */ + if (*pcszQuoted) + { + if (!escapeAndOutputCharacter(enmFormat, *pcszQuoted)) + return false; + continue; + } + RTStrmPrintf(g_pStdErr, "Trailing back slash in argument.\n"); + return false; + } + /* Argument separator. */ + if (*pcszQuoted == ' ') + { + if (!fNextArgument && !outputArgumentSeparator(enmFormat)) + return false; + fNextArgument = true; + continue; + } + else + fNextArgument = false; + /* Start of escape sequence. */ + if (*pcszQuoted == '\\') + { + fEscaped = true; + continue; + } + /* Anything else. */ + if (!outputCharacter(*pcszQuoted)) + return false; + } + if (enmFormat == FORMAT_SHELL) + if (!outputCharacter('\'')) + return false; + return true; +} + +bool writePrintableString(enum ENMFORMAT enmFormat, const char *pcszString) +{ + if (enmFormat == FORMAT_SHELL) + return outputString(pcszString); + RTStrmPrintf(g_pStdErr, "Error: unknown template format.\n"); + return false; +} + +void skipLine(const char *pach, size_t cch, size_t *pcchRead) +{ + while ( *pcchRead < cch + && (pach)[*pcchRead] != '\n' + && (pach)[*pcchRead] != '\r') + ++*pcchRead; + while ( *pcchRead < cch + && ( (pach)[*pcchRead] == '\n' + || (pach)[*pcchRead] == '\r')) + ++*pcchRead; +} diff --git a/src/VBox/Installer/linux/install_service/init_template.sh b/src/VBox/Installer/linux/install_service/init_template.sh new file mode 100755 index 00000000..ed9c9a48 --- /dev/null +++ b/src/VBox/Installer/linux/install_service/init_template.sh @@ -0,0 +1,317 @@ +#!/bin/sh +# +# VirtualBox generic init script. +# +# Copyright (C) 2012-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. +# + +### BEGIN INIT INFO +# Required-Start: $local_fs +# Should-Start: $syslog +# Required-Stop: $local_fs +# Should-Stop: $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: %DESCRIPTION% +### END INIT INFO + +## @todo We should really replace the daemon starting, stopping and checking +# code with a tool of our own written in C, which we could always use +# instead of the LSB functions. + +cr=" +" +tab=" " +IFS=" ${cr}${tab}" +'unset' -f unalias +'unalias' -a +unset -f command +PATH=/bin:/sbin:/usr/bin:/usr/sbin:$PATH + +## A generic service script which can be used, after substituting some place- +# holders with service-specific values, to run most services on LSB, System V +# or BSD-compatible service management systems. As we control both the service +# code and the init script we try to push as much as possible of the logic into +# the service and out of the very system-dependent service configuration +# scripts and files. See the help text of the "install_service.sh" helper +# script for more details. +# +# Furthermore, to simplify deployment, we will install all init scripts using +# this generic template manually during the post install phase or at run time +# using LSB functions if they are available (as they should be on most common +# modern distributions) or manually placing the file in the appropriate +# directory and creating symbolic links on System V or writing to rc.local on +# BSD-compatible systems. Systems requiring different treatment will be added +# here when we add support for them, but we will try to keep everything as +# generic as we can. +# +# In general, we try to behave as natively as we reasonably can on the most +# important target systems we support and to work well enough on as many others +# as possible, but in particular without trying to look perfectly native. +# +# See the inline documentation in the code for generate_service_file for +# details of the generation process. + +## Time out in seconds when shutting down the service. +SHUT_DOWN_TIME_OUT=5 +## If this is set to an empty value then the LSB init functions will not be +# used. This is intended for testing the fallback commands. +LSB_FUNCTIONS="/lib/lsb/init-functions" + +# Silently exit if the package was uninstalled but not purged. +test -r %COMMAND% || exit 0 + +## The function definition at the start of every non-trivial shell script! +abort() +{ + log_failure_msg "$*" + exit 1 +} + +## Exit successfully. +do_success() +{ + log_success_msg "%DESCRIPTION% successfully started." + exit 0 +} + +## Set the error message. +set_error() +{ + test -z "${error}" && error="${1}" +} + +# Gentoo/OpenRC perculiarity. +if test "x${0}" = "x/sbin/rc" || test "x${0}" = "xrc"; then + shift +fi + +# Process arguments. +action="" +error="" +prefix="/var" +while test x"${#}" != "x0"; do + case "${1}" in + --lsb-functions) + test x"${#}" = "x1" && + set_error "${1}: missing argument." + LSB_FUNCTIONS="${2}" + shift 2;; + --prefix) + test x"${#}" = "x1" && + set_error "${1}: missing argument." + prefix="${2}" + shift 2;; + --help) + cat << EOF +Usage: + + ${0} {start|stop|restart|status} [<options>] + + start|stop|restart|status + Start/stop/restart/report status for the service. + +Options: + + --lsb-functions <script> + Take the standard LSB init functions from <script> instead of from the + normal location, or use our own versions if <script> is an empty string. + + --prefix <folder> + Use the folder <folder> for storing variable data instead of "/var". The + child folder "run" must exist. +EOF + exit 0;; + start|stop|restart|force-reload|condrestart|try-restart|reload|status) + test -z "${action}" || + set_error "More than one action requested." + action="${1}" + shift;; + *) + set_error "Unknown option \"${1}\". Try \"${0} --help\" for more information." + shift;; + esac +done + +## Set Redhat and Fedora lock directory +LOCK_FOLDER="${prefix}/lock/subsys/" +LOCK_FILE="${LOCK_FOLDER}/%SERVICE_NAME%" + +# Use LSB functions if available. Success and failure messages default to just +# "echo" if the LSB functions are not available, so call these functions with +# messages which clearly read as success or failure messages. +test -n "${LSB_FUNCTIONS}" && test -f "${LSB_FUNCTIONS}" && + . "${LSB_FUNCTIONS}" + +type log_success_msg >/dev/null 2>&1 || + log_success_msg() + { + cat << EOF +${*} +EOF + } + +type log_failure_msg >/dev/null 2>&1 || + log_failure_msg() + { + cat << EOF +${*} +EOF + } + +## Get the LSB standard PID-file name for a binary. +pidfilename() +{ + echo "${prefix}/run/${1##*/}.pid" +} + +## Get the PID-file for a process like the LSB functions do ( "-p" or by name). +pidfileofproc() +{ + if test x"${1}" = "x-p"; then + echo "${2}" + else + pidfilename "${1}" + fi +} + +## Read the pids from an LSB PID-file, checking that they are positive numbers. +pidsfromfile() +{ + pids="" + test -r "${1}" && + read -r pids < "${1}" 2>/dev/null + for i in $pids; do + test 1 -le "${i}" || return 1 + done + echo "${pids}" +} + +## Check whether the binary $1 with the pids $2... is running. +procrunning() +{ + binary="${1}" + shift + case "`ps -p "${@}" -f 2>/dev/null`" in *"${binary}"*) + return 0;; + esac + return 1 +} + +# We prefer our own implementations of pidofproc and killproc over falling back +# to distribution ones with unknown quirks. +# type pidofproc >/dev/null 2>&1 || + pidofproc() + { + pidfile="`pidfileofproc "${@}"`" + test "x${1}" = "x-p" && shift 2 + pids="`pidsfromfile "${pidfile}"`" + procrunning "${1}" ${pids} && echo "${pids}" + } + +# type killproc >/dev/null 2>&1 || + killproc() + { + pidfile="`pidfileofproc "${@}"`" + test "x${1}" = "x-p" && shift 2 + pids="`pidsfromfile "${pidfile}"`" + if test -n "${2}"; then + procrunning "${1}" ${pids} || return 1 + kill "${2}" ${pids} + return 0 + else + rm -f "${pidfile}" + procrunning "${1}" ${pids} || return 0 + kill "${pids}" + # Short busy wait for the process to terminate. + stamp="`times`" + while test x"${stamp}" = x"`times`"; do + procrunning "${1}" ${pids} || return 0 + done + # Slow sleeping wait if it is still running. + for high in "" 1 2 3 4 5 6 7 8 9; do + for time in ${high}0 ${high}1 ${high}2 ${high}3 ${high}4 ${high}5 ${high}6 ${high}7 ${high}8 ${high}9; do + sleep 1 + procrunning "${1}" ${pids} || return 0 + if test "${time}" = "${SHUT_DOWN_TIME_OUT}"; then + kill -9 "${pid}" + return 0 + fi + done + done + return 0 + fi + } + +start() +{ + test -d "${LOCK_FOLDER}" && touch "${LOCK_FILE}" + test -n "`pidofproc %COMMAND%`" && exit 0 +%HAVE_DAEMON% %COMMAND% %ARGUMENTS% >/dev/null 2>&1 & +%HAVE_DAEMON% pid="$!" +%HAVE_DAEMON% pidfile="`pidfilename %COMMAND%`" +%HAVE_DAEMON% echo "${pid}" > "${pidfile}" +%HAVE_ONESHOT% %COMMAND% %ARGUMENTS% >/dev/null 2>&1 || abort "%DESCRIPTION% failed to start!" + do_success +} + +stop() +{ +%HAVE_STOP_COMMAND% %STOP_COMMAND% %STOP_ARGUMENTS% || abort "%DESCRIPTION% failed to stop!" +%HAVE_DAEMON% killproc %COMMAND% || abort "%DESCRIPTION% failed to stop!" + rm -f "${LOCK_FILE}" + log_success_msg "%DESCRIPTION% successfully stopped." + return 0 +} + +status() +{ +%HAVE_STATUS_COMMAND% %STATUS_COMMAND% %STATUS_ARGUMENTS% +%HAVE_STATUS_COMMAND% exit +%NO_STATUS_COMMAND% pid="`pidofproc %COMMAND%`" +%NO_STATUS_COMMAND% test -n "${pid}" && +%NO_STATUS_COMMAND% { +%NO_STATUS_COMMAND% echo "%SERVICE_NAME% running, process ${pid}" +%NO_STATUS_COMMAND% exit 0 +%NO_STATUS_COMMAND% } +%NO_STATUS_COMMAND% test -f "`pidfilename %COMMAND%`" && +%NO_STATUS_COMMAND% { +%NO_STATUS_COMMAND% echo "%SERVICE_NAME% not running but PID-file present." +%NO_STATUS_COMMAND% exit 1 +%NO_STATUS_COMMAND% } +%NO_STATUS_COMMAND% test -f "${LOCK_FILE}" && +%NO_STATUS_COMMAND% { +%NO_STATUS_COMMAND% echo "%SERVICE_NAME% not running but lock file present." +%NO_STATUS_COMMAND% exit 2 +%NO_STATUS_COMMAND% } +%NO_STATUS_COMMAND% echo "%SERVICE_NAME% not running." +%NO_STATUS_COMMAND% exit 3 +} + +test -z "${error}" || abort "${error}" + +case "${action}" in +start) + start;; +stop) + stop;; +restart|force-reload) + start + stop;; +condrestart|try-restart) + status || exit 0 + stop + start;; +reload) + ;; +status) + status;; +esac diff --git a/src/VBox/Installer/linux/install_service/install_service.sh b/src/VBox/Installer/linux/install_service/install_service.sh new file mode 100755 index 00000000..89311043 --- /dev/null +++ b/src/VBox/Installer/linux/install_service/install_service.sh @@ -0,0 +1,209 @@ +#!/bin/sh + +# +# Script to install services within a VirtualBox installation. +# +# Copyright (C) 2012-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. +# + +# Clean up before we start. +cr=" +" +tab=" " +IFS=" ${cr}${tab}" +'unset' -f unalias +'unalias' -a 2>/dev/null +'unset' -f command +PATH=/bin:/sbin:/usr/bin:/usr/sbin:$PATH + +# Get the folder we are running from, as we need other files there. +script_folder="`dirname "$0"`" + +## Script usage documentation. +usage() { + cat << EOF +Usage: + + `basename $0` --help|--enable|--disable|--force-enable|--force-disable + |--remove [--prefix <prefix>] + -- <pass-through parameters> + +Create a system service which runs a command. In order to make it possible to +do this in a simple and portable manner, we place a number of requirements on +the command to be run: + - That it can be started safely even if all its dependencies are not started + and will sleep if necessary until it can start work. Ideally it should + start accepting input as early as it can, but delay handling it if + necessary, and delay accessing its dependencies until it actually needs + them. + - That it does not background to simplify service process management. + - That it can be safely shut down using SIGTERM. + - That if all running copies of the main process binary are stopped first the + service can be re-started and will do any necessary clean-up automatically. + - That any output which must not be lost go either to the system log or to the + service's private log. + +We currently support System V init only. This will probably soon be extended +to BSD init, OpenRC and systemd, but probably not Upstart which currently +requires modifying init files to disable a service. We also try to enable our +service (if requested) in all init systems we find, as we do not know which one +is in active use. We assume that this will not have any adverse effects. + + --help|--usage + Print this help text and exit. + + --enable|--disable|--force-enable|--force-disable + These actions install the service. If a version of the service was not + installed previously, "--enable" and "--force-enable" make it start when + entering normal user run-levels and "--disable" and "--force-disable" + prevents it from starting when entering any run-level. If a version of + the service was already installed previously, "--enable" and "--disable" + simply update it without changing when it starts; "--force-enable" and + "--force-disable" behave the same as when no previous version was found. + Only one of these options or "--remove" may be specified. + + --remove + This action uninstalls the service. It may not be used in combination + with "--enable", "--disable", "--force-enable" or "--force-disable". + +Option: + + --prefix <prefix> + Treat all paths as relative to <prefix> rather than /etc. + +Pass-through parameters will be passed through to the "generate_service_file" +tool. +EOF +} + +## The function definition at the start of every non-trivial shell script! +abort() { + ## $1 Error text to output to standard error. + cat >&2 << EOF +$1 +EOF + exit 1 +} + +ACTION="" +PREFIX="/etc/" +SERVICE_NAME="" + +# Process arguments. +while test x"${1}" != "x--"; do + case "${1}" in + "--help"|"--usage") + usage + exit 0;; + "--enable"|"--disable"|"--force-enable"|"--force-disable"|"--remove") + test -z "${ACTION}" || abort "More than one action specified." + ACTION="true" + ENABLE="" + INSTALL="true" + UPDATE="" + { test "${1}" = "--enable" || test "${1}" = "--disable"; } && + UPDATE="true" + { test "${1}" = "--enable" || test "${1}" = "--force-enable"; } && + ENABLE="true" + test "${1}" = "--remove" && + INSTALL="" + shift;; + "--prefix") + test -z "${2}" && abort "${1}: missing argument." + PREFIX="${2}" + shift 2;; + *) + abort "Unknown option ${1}.";; + esac +done +shift + +# Check required options and set default values for others. +test -z "${ACTION}" && + abort "Please supply an install action." + +# Get the service name. +SERVICE_NAME=`echo "%SERVICE_NAME%" | + "${script_folder}/../helpers/generate_service_file" --format shell "${@}"` +test -z "${SERVICE_NAME}" && + abort "Please supply a command path." + +# Keep track of whether we found at least one initialisation system. +found_init="" + +# Find the best System V/BSD init path if any is present. +for path in "${PREFIX}/init.d/rc.d" "${PREFIX}/init.d/" "${PREFIX}/rc.d/init.d" "${PREFIX}/rc.d"; do + if test -d "${path}"; then + # Check permissions for the init path. + test -w "${path}" || abort "No permission to write to \"${path}\"." + # And for the System V symlink directories. + for i in rc0.d rc1.d rc6.d rc.d/rc0.d rc.d/rc1.d rc.d/rc6.d; do + if test -d "${PREFIX}/${i}"; then + test -w "${PREFIX}/${i}" || + abort "No permission to write to \"${PREFIX}/${i}\"." + fi + done + # And for the OpenRC symlink directories. + if test -d "${PREFIX}/runlevel/"; then + test -w "${PREFIX}/runlevel/" || + abort "No permission to write to \"${PREFIX}/runlevel\"". + fi + found_init="true" + update="" + test -f "${path}/${SERVICE_NAME}" && update="${UPDATE}" + if test -n "${INSTALL}"; then + "${script_folder}/../helpers/generate_service_file" --format shell "${@}" < "${script_folder}/init_template.sh" > "${path}/${SERVICE_NAME}" + chmod a+x "${path}/${SERVICE_NAME}" + else + rm "${path}/${SERVICE_NAME}" + fi + # Attempt to install using both system V symlinks and OpenRC, assuming + # that both will not be in operation simultaneously (but may be + # switchable). BSD init expects the user to enable services + # explicitly. + if test -z "${update}"; then + # Various known combinations of sysvinit rc directories. + for i in "${PREFIX}"/rc*.d/[KS]??"${SERVICE_NAME}" "${PREFIX}"/rc.d/rc*.d/[KS]??"${SERVICE_NAME}"; do + rm -f "${i}" + done + # And OpenRC. + test -d "${PREFIX}/runlevel/" && + for i in "/${PREFIX}/runlevel"/*/"${SERVICE_NAME}"; do + rm -f "${i}" + done + # Various known combinations of sysvinit rc directories. + if test -n "${ENABLE}"; then + for i in rc0.d rc1.d rc6.d rc.d/rc0.d rc.d/rc1.d rc.d/rc6.d; do + if test -d "${PREFIX}/${i}"; then + # Paranoia test first. + test -d "${PREFIX}/${i}/K80${SERVICE_NAME}" || + ln -sf "${path}/${SERVICE_NAME}" "${PREFIX}/${i}/K80${SERVICE_NAME}" + fi + done + for i in rc2.d rc3.d rc4.d rc5.d rc.d/rc2.d rc.d/rc3.d rc.d/rc4.d rc.d/rc5.d; do + if test -d "${PREFIX}/${i}"; then + # Paranoia test first. + test -d "${PREFIX}/${i}/S20${SERVICE_NAME}" || + ln -sf "${path}/${SERVICE_NAME}" "${PREFIX}/${i}/S20${SERVICE_NAME}" + fi + done + # And OpenRC. + test -d "${PREFIX}/runlevel/default" && + ln -sf "${path}/${SERVICE_NAME}" "/${PREFIX}/runlevel/default/" + fi + fi + break + fi +done + +test -z "${found_init}" && + abort "No supported initialisation system found." +exit 0 diff --git a/src/VBox/Installer/linux/installer-common.sh b/src/VBox/Installer/linux/installer-common.sh index 3e4e6653..5bb51b8d 100644 --- a/src/VBox/Installer/linux/installer-common.sh +++ b/src/VBox/Installer/linux/installer-common.sh @@ -25,6 +25,7 @@ udev_write_vboxdrv() { VBOXDRV_MODE="$2" echo "KERNEL==\"vboxdrv\", NAME=\"vboxdrv\", OWNER=\"root\", GROUP=\"$VBOXDRV_GRP\", MODE=\"$VBOXDRV_MODE\"" + echo "KERNEL==\"vboxdrvu\", NAME=\"vboxdrvu\", OWNER=\"root\", GROUP=\"root\", MODE=\"0666\"" echo "KERNEL==\"vboxnetctl\", NAME=\"vboxnetctl\", OWNER=\"root\", GROUP=\"$VBOXDRV_GRP\", MODE=\"$VBOXDRV_MODE\"" } @@ -88,7 +89,7 @@ install_udev() { "$USB_GROUP" "$NO_INSTALL" "$udev_out" fi # Remove old udev description file - rm -f /etc/udev/rules.d/60-vboxdrv.rules 2> /dev/null + rm -f /etc/udev/rules.d/10-vboxdrv.rules 2> /dev/null } # Add a unit test if/when needed following the same pattern as for @@ -110,7 +111,7 @@ install_create_usb_node_for_sysfs() { } # install_device_node_setup contains some aliases for unit testing purposes. # Set them to their normal values here. -udev_rule_file=/etc/udev/rules.d/10-vboxdrv.rules # Set this to /dev/null +udev_rule_file=/etc/udev/rules.d/60-vboxdrv.rules # Set this to /dev/null # for unit testing sysfs_usb_devices="/sys/bus/usb/devices/*" @@ -163,6 +164,8 @@ set_selinux_permissions() { > /dev/null 2>&1 chcon -t java_exec_t "$INSTALLATION_DIR"/VBoxNetDHCP \ > /dev/null 2>&1 + chcon -t java_exec_t "$INSTALLATION_DIR"/VBoxNetNAT \ + > /dev/null 2>&1 chcon -t java_exec_t "$INSTALLATION_DIR"/VBoxExtPackHelperApp \ > /dev/null 2>&1 chcon -t java_exec_t "$INSTALLATION_DIR"/vboxwebsrv > /dev/null 2>&1 diff --git a/src/VBox/Installer/linux/routines.sh b/src/VBox/Installer/linux/routines.sh index 5cf42bb2..8f720a97 100644 --- a/src/VBox/Installer/linux/routines.sh +++ b/src/VBox/Installer/linux/routines.sh @@ -2,7 +2,7 @@ # VirtualBox installer shell routines # -# Copyright (C) 2007-2011 Oracle Corporation +# Copyright (C) 2007-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -620,3 +620,4 @@ maybe_run_python_bindings_installer() { return 0 } + diff --git a/src/VBox/Installer/linux/rpm/LocalConfig.kmk b/src/VBox/Installer/linux/rpm/LocalConfig.kmk index 921b63fb..a9bebf87 100644 --- a/src/VBox/Installer/linux/rpm/LocalConfig.kmk +++ b/src/VBox/Installer/linux/rpm/LocalConfig.kmk @@ -4,7 +4,7 @@ # # -# Copyright (C) 2006-2010 Oracle Corporation +# Copyright (C) 2006-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec b/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec index 0baac2a9..07bc38cc 100644 --- a/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec +++ b/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec @@ -79,11 +79,16 @@ mv *.gc $RPM_BUILD_ROOT/usr/lib/virtualbox mv *.r0 $RPM_BUILD_ROOT/usr/lib/virtualbox mv *.rel $RPM_BUILD_ROOT/usr/lib/virtualbox || true mv VBoxNetDHCP $RPM_BUILD_ROOT/usr/lib/virtualbox +mv VBoxNetNAT $RPM_BUILD_ROOT/usr/lib/virtualbox mv VBoxNetAdpCtl $RPM_BUILD_ROOT/usr/lib/virtualbox +if [ -f VBoxVolInfo ]; then + mv VBoxVolInfo $RPM_BUILD_ROOT/usr/lib/virtualbox +fi mv VBoxXPCOMIPCD $RPM_BUILD_ROOT/usr/lib/virtualbox mv components $RPM_BUILD_ROOT/usr/lib/virtualbox/components mv *.so $RPM_BUILD_ROOT/usr/lib/virtualbox mv *.so.4 $RPM_BUILD_ROOT/usr/lib/virtualbox || true +ln -s ../VBoxVMM.so $RPM_BUILD_ROOT/usr/lib/virtualbox/components/VBoxVMM.so mv VBoxTestOGL $RPM_BUILD_ROOT/usr/lib/virtualbox mv vboxshell.py $RPM_BUILD_ROOT/usr/lib/virtualbox (export VBOX_INSTALL_PATH=/usr/lib/virtualbox && \ @@ -99,9 +104,9 @@ mv VBoxCreateUSBNode.sh $RPM_BUILD_ROOT/usr/share/virtualbox cp icons/128x128/virtualbox.png $RPM_BUILD_ROOT/usr/share/pixmaps/virtualbox.png cd icons for i in *; do - if [ -f $i/virtualbox.png ]; then + if [ -f $i/virtualbox.* ]; then install -d $RPM_BUILD_ROOT/usr/share/icons/hicolor/$i/apps - mv $i/virtualbox.png $RPM_BUILD_ROOT/usr/share/icons/hicolor/$i/apps + mv $i/virtualbox.* $RPM_BUILD_ROOT/usr/share/icons/hicolor/$i/apps fi install -d $RPM_BUILD_ROOT/usr/share/icons/hicolor/$i/mimetypes mv $i/* $RPM_BUILD_ROOT/usr/share/icons/hicolor/$i/mimetypes || true @@ -116,8 +121,11 @@ if %WEBSVC%; then for i in vboxwebsrv webtest; do mv $i $RPM_BUILD_ROOT/usr/lib/virtualbox; done fi -for i in VBoxSDL VirtualBox VBoxHeadless VBoxNetDHCP VBoxNetAdpCtl; do +for i in VBoxSDL VirtualBox VBoxHeadless VBoxNetDHCP VBoxNetNAT VBoxNetAdpCtl; do chmod 4511 $RPM_BUILD_ROOT/usr/lib/virtualbox/$i; done +if [ -f $RPM_BUILD_ROOT/usr/lib/virtualbox/VBoxVolInfo ]; then + chmod 4511 $RPM_BUILD_ROOT/usr/lib/virtualbox/VBoxVolInfo +fi if [ -d ExtensionPacks/VNC ]; then mv ExtensionPacks/VNC $RPM_BUILD_ROOT/usr/lib/virtualbox/ExtensionPacks fi @@ -272,7 +280,7 @@ if [ "$INSTALL_NO_GROUP" != "1" ]; then echo echo "Creating group 'vboxusers'. VM users must be member of that group!" echo - groupadd -f vboxusers 2> /dev/null + groupadd -r -f vboxusers 2> /dev/null fi # install udev rule (disable with INSTALL_NO_UDEV=1 in /etc/default/virtualbox) @@ -391,7 +399,7 @@ if [ "$1" = 0 ]; then /sbin/service vboxdrv stop > /dev/null /sbin/chkconfig --del vboxdrv %endif - rm -f /etc/udev/rules.d/10-vboxdrv.rules + rm -f /etc/udev/rules.d/60-vboxdrv.rules rm -f /etc/vbox/license_agreed rm -f /etc/vbox/module_not_compiled fi @@ -445,13 +453,13 @@ rm -rf $RPM_BUILD_ROOT %{?rpm_suse: /sbin/rcvboxballoonctrl-service} %{?rpm_suse: /sbin/rcvboxautostart-service} %{?rpm_suse: /sbin/rcvboxweb-service} -/lib/modules /etc/vbox -/usr/bin +/usr/bin/* /usr/src/vbox* /usr/lib/virtualbox -/usr/share/applications -/usr/share/icons -/usr/share/mime/packages -/usr/share/pixmaps +/usr/share/applications/* +/usr/share/icons/hicolor/*/apps/* +/usr/share/icons/hicolor/*/mimetypes/* +/usr/share/mime/packages/* +/usr/share/pixmaps/* /usr/share/virtualbox diff --git a/src/VBox/Installer/linux/rpm/rules b/src/VBox/Installer/linux/rpm/rules index 8e22093b..91606c44 100755 --- a/src/VBox/Installer/linux/rpm/rules +++ b/src/VBox/Installer/linux/rpm/rules @@ -52,7 +52,7 @@ ifeq ($(shell if grep -q '^%disttag' /usr/lib/rpm/macros.d/mandriva 2>/dev/null; $(error Fix /usr/lib/rpm/macros.d/mandriva) endif -verpkg := VirtualBox-4.2 +verpkg := VirtualBox-4.3 current := $(shell pwd) vboxroot := $(shell cd ../../../..; pwd) pkgdir := $(if $(PKGDIR),$(PKGDIR),$(shell cd ../../../../..; pwd)) @@ -62,7 +62,7 @@ arch := $(shell if [ `uname -m` = "x86_64" ]; then echo "amd64"; else echo " verfile := $(builddir)/version-generated.mk ose := $(if $(OSE),1,$(if $(wildcard $(vboxroot)/src/VBox/RDP/server),,1)) -include $(vboxroot)/SVN_REVISION -svnrev :=$(if $(svn_revision),$(svn_revision),0) +svnrev :=$(if $(svn_revision),$(svn_revision),) NOMODS ?= $(ose) NOQT ?= $(HEADLESS) @@ -84,10 +84,10 @@ ifneq ($(MAKECMDGOALS),clean) $(error Cannot detect package distribution (rpmrel=$(rpmrel))) endif - ifeq ($(filter-out el4 el5 el6 ol4 ol5 ol6 centos4 centos5 centos6 fedora9 fedora11 fedora12 fedora13 fedora14 fedora15 fedora16 fedora17 turbolinux11,$(rpmrel)),) + ifeq ($(filter-out el5 el6 ol5 ol6 centos5 centos6 fedora15 fedora16 fedora17 fedora18,$(rpmrel)),) rpmspec := rpm_redhat endif - ifeq ($(filter-out openSUSE110 openSUSE111 openSUSE112 openSUSE113 openSUSE114 sles10.1 sles11.0,$(rpmrel)),) + ifeq ($(filter-out openSUSE110 openSUSE111 openSUSE112 openSUSE113 openSUSE114 openSUSE123 sles10.1 sles11.0,$(rpmrel)),) rpmspec := rpm_suse endif ifeq ($(filter-out mdv2009.1 mdv2010.0 mdv2011.0,$(rpmrel)),) @@ -109,8 +109,8 @@ rpmver :=$(ver)$(if $(NOSUBVER),,$(if $(svn_revision),_$(svn_revision),)$(VERS archdir := $(current)/rpm/VirtualBox-$(ver) rpmname := $(verpkg)-$(rpmver)_$(rpmrel) -# Fedora13/14 is bleeding edge, the other jails have outdated kernel headers -instmod := $(if $(filter el4 el5 el6 ol4 ol5 ol6 centos4 centos5 centos6 sles10.1 sles11.0 fedora13 fedora14 fedora15 fedora16 fedora17,$(rpmrel)),,install_rpm) +# never ship any modules +instmod := ifneq ($(STAGEDISO),) ifeq ($(wildcard $(STAGEDISO)/VBoxGuestAdditions.iso),) @@ -132,18 +132,18 @@ else endif cfg_flags := $(if $(NOQT),--disable-qt,) \ - $(if $(filter el4 sles10.1,$(rpmrel)),--build-libxml2,) \ - $(if $(filter el4,$(rpmrel)),--build-libssl,) \ - $(if $(filter el4 el5 ol4 ol5 centos4 centos5 sles10.1,$(rpmrel)),--build-libcurl,) \ + $(if $(filter sles10.1,$(rpmrel)),--build-libxml2,) \ + $(if $(filter el5 el6 sles10.1 sles11.0 mdv2011.0,$(rpmrel)),--build-libvpx,) \ + $(if $(filter el5 ol5 centos5 sles10.1 sles11.0,$(rpmrel)),--build-libcurl,) \ $(if $(filter el5 centos5 sles10.1,$(rpmrel)),--disable-sdl-ttf,) \ - $(if $(filter sles10.1 turbolinux11,$(rpmrel)),--disable-pulse,) \ - $(if $(filter el4 el5 ol4 ol5 centos4 centos5,$(rpmrel)),--enable-pulse,) \ - $(if $(filter el4 el5 ol4 ol5 centos4 centos5 mdv2010.0 sles10.1 sles11.0 turbolinux11,$(rpmrel)),--with-qt4-dir=/home/vbox/Qt-4.7.4-stdc++6-$(arch)) \ + $(if $(filter sles10.1,$(rpmrel)),--disable-pulse,) \ + $(if $(filter el5 ol5 centos5,$(rpmrel)),--enable-pulse,) \ + $(if $(filter el5 ol5 centos5 sles10.1 sles11.0,$(rpmrel)),--with-qt4-dir=/home/vbox/Qt-4.7.4-stdc++6-$(arch)) \ $(if $(ose),--ose,) $(if $(LINUX),--with-linux=$(LINUX),) \ $(if $(HEADLESS),--build-headless,) \ $(if $(DEBUG),--build-debug,) \ $(if $(NOWINE),,--setup-wine) \ - $(if $(NOWEBSVC),,--enable-webservice) \ + $(if $(NOWEBSVC),,$(if $(ose),--enable-webservice,)) \ $(if $(VNC),--enable-vnc,) \ --disable-extpack @@ -153,17 +153,16 @@ bld_flags := AUTOCFG=$(current)/rpm/AutoConfig.kmk \ VBOX_WITHOUT_EXTPACK_PUEL_PACKING=1 \ VBOX_WITHOUT_EXTPACK_VNC_PACKING=1 \ VBOX_DO_STRIP= \ - VBOX_DO_STRIP_MODULES= \ VBOX_WITH_MULTIVERSION_PYTHON= \ $(doc_dir) \ $(if $(ose),,VBOX_WITH_DOCS_CHM=1) \ VBOX_PACKAGE_DIST=$(rpmdist) \ - VBOX_SVN_REV=$(svnrev) \ + $(if $(svnrev),VBOX_SVN_REV=$(svnrev),) \ $(if $(NODOCS),VBOX_WITH_DOCS= ,) \ $(if $(VERBOSE),--print-directory KBUILD_VERBOSE=2,--no-print-directory) \ $(if $(STAGEDISO),VBOX_WITHOUT_ADDITIONS=1,) \ $(if $(BLEEDING_EDGE),VBOX_BLEEDING_EDGE=$(BLEEDING_EDGE),) \ - $(if $(filter el4 el5 ol4 ol5 centos4 centos5 fedora9 fedora10 sles10.1 turbolinux11,$(rpmrel)),,VBOX_WITH_SYSFS_BY_DEFAULT=1) + $(if $(filter el5 ol5 centos5 sles10.1,$(rpmrel)),,VBOX_WITH_SYSFS_BY_DEFAULT=1) rpm/configure-stamp: cd $(vboxroot) && ./configure --odir=$(current)/rpm $(cfg_flags) @@ -179,8 +178,8 @@ rpm/build-stamp: rpm/configure-stamp $(if $(STAGEDISO),cp $(STAGEDISO)/VBoxGuestAdditions.iso $(builddir)/bin/additions,) . rpm/env.sh && kmk -C $(vboxroot) $(bld_flags) \ VBOX_NO_LINUX_RUN_INSTALLER=1 \ - VBOX_LNX_ADD_ARCHIVE.x86=$(builddir)/bin/additions/VBoxGuestAdditions-x86-r$(svnrev).tar.bz2 \ - VBOX_LNX_ADD_ARCHIVE.amd64=$(builddir)/bin/additions/VBoxGuestAdditions-amd64-r$(svnrev).tar.bz2 \ + VBOX_LNX_ADD_ARCHIVE.x86=$(builddir)/bin/additions/VBoxGuestAdditions-x86.tar.bz2 \ + VBOX_LNX_ADD_ARCHIVE.amd64=$(builddir)/bin/additions/VBoxGuestAdditions-amd64.tar.bz2 \ VBOX_PATH_ADDITIONS.linux.x86=$(builddir)/bin/additions \ VBOX_PATH_ADDITIONS.linux.amd64=$(builddir)/bin/additions \ packing @@ -227,22 +226,10 @@ binary: rpm/build-stamp -e "s|%VERSION%|$(VBOX_VERSION_STRING)|g" \ -e "s|%GROUP%|$(if $(VBOX_WITHOUT_HARDENING),vboxusers,root)|g" \ vboxdrv.sh.in > $(archdir)/vboxdrv.init - sed \ - -e 's|%NOLSB%|yes|g' \ - -e 's|%DEBIAN%||g' \ - -e 's|%PACKAGE%|virtualbox|g' \ - vboxballoonctrl-service.sh.in > $(archdir)/vboxballoonctrl-service.init - sed \ - -e 's|%NOLSB%|yes|g' \ - -e 's|%DEBIAN%||g' \ - -e 's|%PACKAGE%|virtualbox|g' \ - vboxautostart-service.sh.in > $(archdir)/vboxautostart-service.init - sed \ - -e 's|%NOLSB%|yes|g' \ - -e 's|%DEBIAN%||g' \ - -e 's|%PACKAGE%|virtualbox|g' \ - vboxweb-service.sh.in > $(archdir)/vboxweb-service.init - cp debian/VBox.sh $(archdir) + cp vboxballoonctrl-service.sh $(archdir)/vboxballoonctrl-service.init + cp vboxautostart-service.sh $(archdir)/vboxautostart-service.init + cp vboxweb-service.sh $(archdir)/vboxweb-service.init + cp VBox.sh $(archdir) mv rpm/VirtualBox-$(ver) rpm/$(rpmname) tar -cjf rpm/VirtualBox.tar.bz2 -C rpm $(rpmname) rm -f /usr/src/packages/RPMS/*/VirtualBox*rpm diff --git a/src/VBox/Installer/linux/run-inst.sh b/src/VBox/Installer/linux/run-inst.sh index 44c11835..e1964892 100755 --- a/src/VBox/Installer/linux/run-inst.sh +++ b/src/VBox/Installer/linux/run-inst.sh @@ -1,10 +1,11 @@ #!/bin/sh # # Oracle VM VirtualBox -# VirtualBox Makeself installation starter script for Linux +# VirtualBox Makeself installation starter script +# for Linux Guest Additions # -# Copyright (C) 2006-2009 Oracle Corporation +# Copyright (C) 2006-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; @@ -20,7 +21,6 @@ # the package into the filesystem (by default under /opt) and starts the real # installation script. # - PATH=$PATH:/bin:/sbin:/usr/sbin # Note: These variable names must *not* clash with variables in $CONFIG_DIR/$CONFIG! @@ -48,10 +48,15 @@ check_root create_log "$LOGFILE" +## @todo r=andy: Explain options like "force" and "no_setup" -- not self-explanatory +# to the user. usage() { info "" - info "Usage: install [<installation directory>] | uninstall [force] [no_setup]" + info "Usage: $SELF install [<installation directory>]" + info " [--with-<module>] |" + info " uninstall" + info " [--force] [--no-setup]" info "" info "Example:" info "$SELF install" @@ -107,12 +112,17 @@ def_uninstall() . ./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 -a -e "$i" && found=1 + test "$found" = 0 && test -e "$i" && found=1 done test "$found" = 0 && - for i in $DEFAULT_VERSIONED_FILE_NAMES-*; do - test "$found" = 0 -a -e "$i" && found=1 + 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 @@ -152,7 +162,8 @@ EOF 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" + 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 @@ -170,15 +181,11 @@ cpu=`uname -m`; case "$cpu" in i[3456789]86|x86) cpu="x86" - lib_path="/usr/lib" + lib_candidates="/usr/lib/i386-linux-gnu /usr/lib /lib" ;; x86_64|amd64) cpu="amd64" - if test -d "/usr/lib64"; then - lib_path="/usr/lib64" - else - lib_path="/usr/lib" - fi + lib_candidates="/usr/lib/x86_64-linux-gnu /usr/lib64 /usr/lib /lib64 /lib" ;; *) cpu="unknown" @@ -188,47 +195,105 @@ 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 # Sensible default actions ACTION="install" DO_SETUP="true" NO_CLEANUP="" FORCE_UPGRADE="" -while true + +while [ $# -ge 2 ]; do - if [ "$2" = "" ]; then - break - fi + ARG=$2 shift - case "$1" in - install) - ACTION="install" - ;; - - uninstall) - ACTION="uninstall" - ;; - force) - FORCE_UPGRADE="force" - ;; - no_setup) - DO_SETUP="" - ;; - no_cleanup) - # Do not do cleanup of old modules when removing them. For - # testing purposes only. - DO_SETUP="" - NO_CLEANUP="no_cleanup" - ;; - *) - if [ "`echo $1|cut -c1`" != "/" ]; then - info "Please specify an absolute path" - usage - fi - INSTALLATION_DIR="$1" - ;; - esac + if [ -z "$MY_END_OF_OPTIONS" ]; then + case "$ARG" in + + install) + ACTION="install" + ;; + + uninstall) + ACTION="uninstall" + ;; + + ## @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) # Keep "no_setup" for backwards compatibility. + DO_SETUP="" + ;; + + --no-cleanup|no_cleanup) # Keep "no_cleanup" for backwards compatibility. + # Do not do cleanup of old modules when removing them. For + # testing purposes only. + DO_SETUP="" + 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 # uninstall any previous installation @@ -247,6 +312,27 @@ rm -f "$CONFIG_DIR/$CONFIG_FILES" rmdir "$CONFIG_DIR" 2>/dev/null test "$ACTION" = "install" || exit 0 +# Choose a proper umask +umask 022 + +# Set installer modules directory +INSTALLATION_MODULES_DIR="$INSTALLATION_DIR/installer/" + +# 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 + # install the new version mkdir -p -m 755 "$CONFIG_DIR" test ! -d "$INSTALLATION_DIR" && REMOVE_INSTALLATION_DIR=1 @@ -275,11 +361,33 @@ link_into_fs "lib" "$lib_path" link_into_fs "share" "/usr/share" link_into_fs "src" "/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 @@ -293,6 +401,16 @@ BUILD_TYPE='$BUILD_TYPE' 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 + # Install, set up and start init scripts for i in "$INSTALLATION_DIR/init/"*; do if test -r "$i"; then @@ -342,6 +460,44 @@ for i in "$INSTALLATION_DIR/init/"*; do fi done +# 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 @@ -355,6 +511,8 @@ cat "$CONFIG_DIR/$CONFIG_FILES" | ;; 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 @@ -364,3 +522,4 @@ 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" + diff --git a/src/VBox/Installer/linux/scripts/VBoxHeadlessXOrg.sh b/src/VBox/Installer/linux/scripts/VBoxHeadlessXOrg.sh new file mode 100755 index 00000000..fd76d1ea --- /dev/null +++ b/src/VBox/Installer/linux/scripts/VBoxHeadlessXOrg.sh @@ -0,0 +1,379 @@ +#!/bin/sh +# $Id: VBoxHeadlessXOrg.sh $ +# +# VirtualBox X Server auto-start service. +# +# Copyright (C) 2012-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. +# + +PATH=$PATH:/bin:/sbin:/usr/sbin + +## Start one or several X servers in the background for use with headless +# rendering. For details, options and configuration see the usage() function +# further down. +# +# I have tried to follow the best practices I could find for writing a Linux +# service (and doing it in shell script) which should work well with +# traditional and modern service systems using minimal init or service files. +# In our case this boils down to: +# * Start with a single command line, stop using one of ${EXIT_SIGNALS} below. +# * Stopping with a signal can be done safely using the pid stored in the +# pid-file and our (presumably unique) command name. For this reason we +# only support running one instance of the service though. +# * Start in the foreground. Systems without proper service control can take +# care of the backgrounding in the init script. +# * Clean up all sub-processes (X servers) ourselves when we are stopped +# cleanly and don't provide any other way to clean them up automatically (in +# case we are stopped uncleanly) as we don't know of a generic safe way to +# do so, though some service management systems (i.e. systemd) can do so. +# (A more thorough automatic clean-up would be possible if Xorg didn't +# potentially have to be run as root, so that we could run all processes +# using a service-specific user account and just terminate all processes +# run by that user to clean up.) + +## Default configuration file name. +# @note This is not very nice - /etc/default is actually Debian-specific. +CONFIGURATION_FILE=/etc/default/virtualbox +## The name of this script. +SCRIPT_NAME="$0" +## The service name. +SERVICE_NAME="vboxheadlessxorg" +## The service description. +SERVICE_DESCRIPTION="Headless rendering service" +## Signals and conditions which may be used to terminate the service. +EXIT_SIGNALS="EXIT HUP INT QUIT ABRT TERM" +## The default run-time data folder. +DEFAULT_RUN_FOLDER="/var/run/${SERVICE_NAME}/" +## The default X server configuration directory. +DEFAULT_CONFIGURATION_FOLDER="${DEFAULT_RUN_FOLDER}/xorg.conf.d/" +## The extra data key used to provide the list of available X server displays. +EXTRA_DATA_KEY_DISPLAYS="HeadlessXServer/Displays" +## The extra data key used to specify the X server authority file. +EXTRA_DATA_KEY_AUTH="HeadlessXServer/AuthFile" + +## Print usage information for the service script. +## @todo Perhaps we should support some of the configuration file options from +# the command line. Opinions welcome. +## @todo Possibly extract this information for the user manual. +usage() { + cat << EOF +Usage: + + $(basename "${SCRIPT_NAME}") [<options>] + +Start one or several X servers in the background for use with headless +rendering. We only support X.Org Server at the moment. On service start-up available graphics devices are detected and an X server configuration file is +generated for each. We attempt to start an X server process for each +configuration file. The process is configurable by setting values in a file as +described below. + +Options: + + -c|--conf-file Specify an alternative locations for the configuration + file. The default location is: + "${CONFIGURATION_FILE}" + + --install Install the service to run at system start-up. + + --uninstall Revert the installation done by the "--install" option. + + --help|--usage Print this text. + +The optional configuration file should contain a series of lines of the form +"KEY=value". It will be read in as a command shell sub-script. Here is the +current list of possible key settings with a short explanation. Usually it +should be sufficient to change the value of \${HEADLESS_X_ORG_USERS} and to +leave all other settings unchanged. + + HEADLESS_X_ORG_CONFIGURATION_FOLDER + The folder where the X server configuration files are to be created. + + HEADLESS_X_ORG_LOG_FOLDER + The folder where log files will be saved. + + HEADLESS_X_ORG_LOG_FILE + The main log file name. + + HEADLESS_X_ORG_RUN_FOLDER + The folder to store run-time data in. + + HEADLESS_X_ORG_WAIT_FOR_PREREQUISITES + Command to execute to wait until all dependencies for the X servers are + available. The default command waits until the udev event queue has + settled. The command may return failure to signal that it has given up. + No arguments may be passsed. + + HEADLESS_X_ORG_USERS + List of users who will have access to the X servers started and for whom we + will provide the configuration details via VirtualBox extra data. This + variable is only used by the commands in the default configuration + (\${HEADLESS_X_ORG_SERVER_PRE_COMMAND} and + \${HEADLESS_X_ORG_SERVER_POST_COMMAND}), and not by the service itself. + + HEADLESS_X_ORG_FIRST_DISPLAY + The first display number which will be used for a started X server. The + others will use the following numbers. + + HEADLESS_X_ORG_SERVER_PRE_COMMAND + Command to execute once to perform any set-up needed before starting the + X servers, such as setting up the X server authentication. The default + command creates an authority file for each of the users in the list + \${HEADLESS_X_ORG_USERS} and generates server configuration files for all + detected graphics cards. No arguments may be passed. + + HEADLESS_X_ORG_SERVER_COMMAND + The default X server start-up command. It will be passed three parameters + - in order, the screen number to use, the path of the X.Org configuration + file to use and the path of the X server log file to create. + + HEADLESS_X_ORG_SERVER_POST_COMMAND + Command to execute once the X servers have been successfully started. It + will be passed a single parameter which is a space-separated list of the + X server screen numbers. By default this stores the service configuration + information to VirtualBox extra data for each of the users in the list + from the variable HEADLESS_X_ORG_USERS: the list of displays is set to the + key "${EXTRA_DATA_KEY_DISPLAYS}" and the path of the authority file to + "${EXTRA_DATA_KEY_AUTH}". +EOF +} + +# Default configuration. +HEADLESS_X_ORG_CONFIGURATION_FOLDER="${DEFAULT_CONFIGURATION_FOLDER}" +HEADLESS_X_ORG_LOG_FOLDER="/var/log/${SERVICE_NAME}" +HEADLESS_X_ORG_LOG_FILE="${SERVICE_NAME}.log" +HEADLESS_X_ORG_RUN_FOLDER="/var/run/${SERVICE_NAME}" +HEADLESS_X_ORG_USERS="" +HEADLESS_X_ORG_FIRST_DISPLAY=40 +X_AUTH_FILE="${HEADLESS_X_ORG_RUN_FOLDER}/xauth" + +default_wait_for_prerequisites() +{ + udevadm settle || udevsettle # Fails if no udevadm. +} +HEADLESS_X_ORG_WAIT_FOR_PREREQUISITES="default_wait_for_prerequisites" + +default_pre_command() +{ + # Create new authority file. + echo > "${X_AUTH_FILE}" + # Create the xorg.conf files. + mkdir -p "${HEADLESS_X_ORG_CONFIGURATION_FOLDER}" || return 1 + display="${HEADLESS_X_ORG_FIRST_DISPLAY}" + for i in /sys/bus/pci/devices/*; do + read class < "${i}/class" + case "${class}" in *03????) + address="${i##*/}" + address="${address%%:*}${address#*:}" + address="PCI:${address%%.*}:${address#*.}" + read vendor < "${i}/vendor" + case "${vendor}" in *10de|*10DE) # NVIDIA + cat > "${HEADLESS_X_ORG_CONFIGURATION_FOLDER}/xorg.conf.${display}" << EOF +Section "Module" + Load "glx" +EndSection +Section "Device" + Identifier "Device${display}" + Driver "nvidia" + Option "UseDisplayDevice" "none" +EndSection +Section "Screen" + Identifier "Screen${display}" + Device "Device${display}" +EndSection +Section "ServerLayout" + Identifier "Layout${display}" + Screen "Screen${display}" + Option "AllowMouseOpenFail" "true" + Option "AutoAddDevices" "false" + Option "AutoAddGPU" "false" + Option "AutoEnableDevices" "false" + Option "IsolateDevice" "${address}" +EndSection +EOF + esac + # Add key to the authority file. + key="$(dd if=/dev/urandom count=1 bs=16 2>/dev/null | od -An -x)" + xauth -f "${X_AUTH_FILE}" add :${display} . "${key}" + display=`expr ${display} + 1` + esac + done + # Duplicate the authority file. + for i in ${HEADLESS_X_ORG_USERS}; do + cp "${X_AUTH_FILE}" "${X_AUTH_FILE}.${i}" + chown "${i}" "${X_AUTH_FILE}.${i}" + done +} +HEADLESS_X_ORG_SERVER_PRE_COMMAND="default_pre_command" + +default_command() +{ + auth="${HEADLESS_X_ORG_RUN_FOLDER}/xauth" + # screen=$1 + # conf_file=$2 + # log_file=$3 + trap "kill \${PID}; sleep 5; kill -KILL \${PID} 2>/dev/null" ${EXIT_SIGNALS} + Xorg :"${1}" -auth "${auth}" -config "${2}" -logverbose 0 -logfile /dev/null -verbose 7 > "${3}" 2>&1 & + PID="$!" + wait + exit +} +HEADLESS_X_ORG_SERVER_COMMAND="default_command" + +default_post_command() +{ + # screens=$1 + for i in ${HEADLESS_X_ORG_USERS}; do + su ${i} -c "VBoxManage setextradata global ${EXTRA_DATA_KEY_DISPLAYS} \"${1}\"" + su ${i} -c "VBoxManage setextradata global ${EXTRA_DATA_KEY_AUTH} \"${HEADLESS_X_ORG_RUN_FOLDER}/xauth\"" + done +} +HEADLESS_X_ORG_SERVER_POST_COMMAND="default_post_command" + +## The function definition at the start of every non-trivial shell script! +abort() { + ## $@, ... Error text to output to standard error in printf format. + printf "$@" >&2 + exit 1 +} + +## Milder version of abort, when we can't continue because of a valid condition. +abandon() { + ## $@, ... Text to output to standard error in printf format. + printf "$@" >&2 + exit 0 +} + +abort_usage() { + usage >&2 + abort "$@" +} + +# Print a banner message +banner() { + cat << EOF +${VBOX_PRODUCT} VBoxHeadless X Server start-up service Version ${VBOX_VERSION_STRING} +(C) 2005-${VBOX_C_YEAR} ${VBOX_VENDOR} +All rights reserved. + +EOF +} + +# Get the directory where the script is located. +SCRIPT_FOLDER=$(dirname "${SCRIPT_NAME}")"/" +[ -r "${SCRIPT_FOLDER}generated.sh" ] || + abort "${LOG_FILE}" "Failed to find installation information.\n" +. "${SCRIPT_FOLDER}generated.sh" + +# Parse our arguments. +do_install="" +while [ "$#" -gt 0 ]; do + case $1 in + -c|--conf-file) + [ "$#" -gt 1 ] || + { + banner + abort "%s requires at least one argument.\n" "$1" + } + CONFIGURATION_FILE="$2" + shift + ;; + --help|--usage) + banner + usage + exit 0 + ;; + --install) + do_install="install" + ;; + --uninstall) + do_install="uninstall" + ;; + *) + banner + abort_usage "Unknown argument $1.\n" + ;; + esac + shift +done + +[ -r "${CONFIGURATION_FILE}" ] && . "${CONFIGURATION_FILE}" + +if [ -n "${do_install}" ]; then + SCRIPT_FOLDER=$(cd "${SCRIPT_FOLDER}" && pwd)"/" + CONFIGURATION_FILE_ESCAPED=$(echo "${CONFIGURATION_FILE}" | sed 's/\([ \%]\)/\\\1/g') + if [ "x${do_install}" = "xinstall" ]; then + ${SCRIPT_FOLDER}install_service --enable -- --command "${SCRIPT_FOLDER}"$(basename "${SCRIPT_NAME}") --arguments "--conf-file ${CONFIGURATION_FILE_ESCAPED}" --service-name "${SERVICE_NAME}" --description "${SERVICE_DESCRIPTION}" + else + ${SCRIPT_FOLDER}install_service --remove -- --service-name "${SERVICE_NAME}" + fi + exit 0 +fi + +# Change to the root directory so we don't hold any other open. +cd / + +# If something fails here we will catch it when we create the directory. +[ -e "${HEADLESS_X_ORG_LOG_FOLDER}" ] && + [ -d "${HEADLESS_X_ORG_LOG_FOLDER}" ] && + rm -rf "${HEADLESS_X_ORG_LOG_FOLDER}.old" 2> /dev/null && +mv "${HEADLESS_X_ORG_LOG_FOLDER}" "${HEADLESS_X_ORG_LOG_FOLDER}.old" 2> /dev/null +mkdir -p "${HEADLESS_X_ORG_LOG_FOLDER}" 2>/dev/null || +{ + banner + abort "Failed to create log folder \"${HEADLESS_X_ORG_LOG_FOLDER}\".\n" +} +mkdir -p "${HEADLESS_X_ORG_RUN_FOLDER}" 2>/dev/null || +{ + banner + abort "Failed to create run folder \"${HEADLESS_X_ORG_RUN_FOLDER}\".\n" +} +exec > "${HEADLESS_X_ORG_LOG_FOLDER}/${HEADLESS_X_ORG_LOG_FILE}" 2>&1 + +banner + +# Wait for our dependencies to become available. +if [ -n "${HEADLESS_X_ORG_WAIT_FOR_PREREQUISITES}" ]; then + "${HEADLESS_X_ORG_WAIT_FOR_PREREQUISITES}" || + abort "Service prerequisites not available.\n" +fi + +# Do any pre-start setup. +if [ -n "${HEADLESS_X_ORG_SERVER_PRE_COMMAND}" ]; then + "${HEADLESS_X_ORG_SERVER_PRE_COMMAND}" || + abort "Pre-requisite failed.\n" +fi + +X_SERVER_PIDS="" +X_SERVER_SCREENS="" +trap "kill \${X_SERVER_PIDS} 2>/dev/null" ${EXIT_SIGNALS} +space="" # Hack to put spaces between the pids but not before or after. +for conf_file in "${HEADLESS_X_ORG_CONFIGURATION_FOLDER}"/*; do + [ x"${conf_file}" = x"${HEADLESS_X_ORG_CONFIGURATION_FOLDER}/*" ] && + ! [ -e "${conf_file}" ] && + abort "No configuration files found.\n" + filename="$(basename "${conf_file}")" + screen="$(expr "${filename}" : "xorg\.conf\.\(.*\)")" + [ 0 -le "${screen}" ] 2>/dev/null || + abort "Badly formed file name \"${conf_file}\".\n" + log_file="${HEADLESS_X_ORG_LOG_FOLDER}/Xorg.${screen}.log" + "${HEADLESS_X_ORG_SERVER_COMMAND}" "${screen}" "${conf_file}" "${log_file}" & + X_SERVER_PIDS="${X_SERVER_PIDS}${space}$!" + X_SERVER_SCREENS="${X_SERVER_SCREENS}${space}${screen}" + space=" " +done + +# Do any post-start work. +if [ -n "${HEADLESS_X_ORG_SERVER_POST_COMMAND}" ]; then + "${HEADLESS_X_ORG_SERVER_POST_COMMAND}" "${X_SERVER_SCREENS}" || + abort "Post-command failed.\n" +fi + +wait diff --git a/src/VBox/Installer/linux/helpers/install_module_dependencies.sh b/src/VBox/Installer/linux/scripts/check_module_dependencies.sh index 25884af3..b3baf039 100755 --- a/src/VBox/Installer/linux/helpers/install_module_dependencies.sh +++ b/src/VBox/Installer/linux/scripts/check_module_dependencies.sh @@ -4,7 +4,7 @@ # VirtualBox linux installation script # -# Copyright (C) 2007-2011 Oracle Corporation +# Copyright (C) 2007-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -369,8 +369,8 @@ get_system_information() ## Determine the commands needed to install gcc, make and the kernel headers on # the current system. -# @param INSTALL_GCC_MAKE [out] Command to install gcc and make. -# @param INSTALL_HEADERS [out] Command to install gcc and make. +# @param INSTALL_GCC_MAKE [out] Command to install gcc and make. +# @param INSTALL_HEADERS [out] Command to install gcc and make. # @param INSTALL_HEADERS_META [out] Command to install a dependency on the # current kernel headers. May be empty. generate_install_commands() diff --git a/src/VBox/Installer/linux/scripts/install.sh b/src/VBox/Installer/linux/scripts/install.sh new file mode 100755 index 00000000..576eb4e9 --- /dev/null +++ b/src/VBox/Installer/linux/scripts/install.sh @@ -0,0 +1,270 @@ +#!/bin/sh + +# +# Script to handle VirtualBox installation on a Linux host. +# +# Copyright (C) 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. +# + +# This script is invoked as part of the installation of VirtualBox on a Linux +# host system (see next paragraph for details). When we install using the +# makeself installer it will be executed at installation time, whereas with RPM +# or deb packages it will be executed by the %install section of the template, +# respectively the binary rule from the rules file when the package is created. +# The plan is to gradually move anything here which is identical across the +# three installer types and to put new things in here straight away. We should +# maintain an uninstall.sh script in parallel, but this will only be needed by +# the makeself installer as the other two deal with that automatically. Perhaps +# once we have made some progress at factoring out common bits in the three +# installers we can even try doing it accross other POSIX platforms. +# +# The general idea (mine at least) of how this works/should work is that the +# build system installs everything needed for VirtualBox to run (provided all +# drivers it needs are currently loaded) into the output bin/ folder. The +# Makeself installer duplicates this folder as /opt/VirtualBox (or whatever), +# the other two as <prefix>/lib/virtualbox (again, or whatever). The installer +# then installs scripts into <prefix>/bin to start binaries in the duplicated +# main folder, builds drivers which are put into the kernel module directories +# and creates init/start-up scripts which load drivers and/or start binaries in +# the main folder. As mentioned above, this installation is done at the time +# the package is created for RPM/deb packages and shouldn't create anything +# which is not supposed to be included in a package file list (other things can +# be done in a post-install step). + +# Clean up before we start. +cr=" +" +tab=" " +IFS=" ${cr}${tab}" +'unset' -f unalias +'unalias' -a 2>/dev/null +'unset' -f command +PATH=/bin:/sbin:/usr/bin:/usr/sbin:$PATH + +# Exit on any errors. +set -e + +# Get the folder we are installed to, as we need other files there. May be +# relative to the current directory. +# I hope we never install to a folder with a new-line at the end of the name, +# but the code should(!) still work. +INSTALL_SOURCE=`expr "$0" : '\(.*/\)[^/][^/]*/*'`".." +. "${INSTALL_SOURCE}/scripts/generated.sh" + +# Default settings values. +## Root of installation target file system. +ROOT="" +## Prefix to install to. +RELATIVE_PREFIX="/usr" +## Package name. +PACKAGE="VirtualBox" +## Init script folder. Scripts will not be installed at this stage if empty. +INIT_FOLDER="" +## Do not install Qt front-end-related files. +NO_QT="" +## Do a headless installation. +HEADLESS="" +## Do not install the web service. +NO_WEB_SERVICE="" +## OSE installation - does this still mean anything? +OSE="" +## Do not create <prefix>/share/<package>. +NO_SHARE_PACKAGE="" +## Delete the helpers and scripts folders. +NO_HELPERS="" +## The command to use to run the Python interpreter. +PYTHON_COMMAND="python" +## The folder where the main VirtualBox binaries and libraries will be, relative +# to <prefix>. +INSTALL_FOLDER="/lib/${PACKAGE}" + +while test "${#}" -gt 0; do + case $1 in + --prefix) + test "${#}" -gt 1 || + { + echo "${1} requires at least one argument." >&2 + exit 1 + } + RELATIVE_PREFIX="${2}" + shift + ;; + --root) + test "${#}" -gt 1 || + { + echo "${1} requires at least one argument." >&2 + exit 1 + } + ROOT="${2}" + shift + ;; + --package) + test "${#}" -gt 1 || + { + echo "${1} requires at least one argument." >&2 + exit 1 + } + PACKAGE="${2}" + shift + ;; + --init-folder) + test "${#}" -gt 1 || + { + echo "${1} requires at least one argument." >&2 + exit 1 + } + INIT_FOLDER="${2}" + shift + ;; + --no-qt) + NO_QT="true" + ;; + --headless) + HEADLESS="true" + ;; + --no-web-service) + NO_WEB_SERVICE="true" + ;; + --ose) + OSE="true" + ;; + --no-share-package) + NO_SHARE_PACKAGE="true" + ;; + --no-helpers) + NO_HELPERS="true" + ;; + --python-command) + test "${#}" -gt 1 || + { + echo "${1} requires at least one argument." >&2 + exit 1 + } + PYTHON_COMMAND="${2}" + shift + ;; + + --install-folder) + test "${#}" -gt 1 || + { + echo "${1} requires at least one argument." >&2 + exit 1 + } + INSTALL_FOLDER="${2}" + shift + ;; + *) + echo "Unknown argument ${1}." + exit 1 + ;; + esac + shift +done + +PREFIX="${ROOT}${RELATIVE_PREFIX}" + +# Note: install(1) is not POSIX, but it is available on Linux, Darwin and all +# Solaris versions I could check (the oldest was 2.6). It is a BSD command. +install -d -g 0 -o 0 "${PREFIX}/bin" +install -d -g 0 -o 0 "${PREFIX}/share/applications" +# We use this as our base install folder. +test -z "${NO_QT}" && + mv "${INSTALL_SOURCE}/virtualbox.desktop" "${PREFIX}/share/applications/" +install -d -g 0 -o 0 "${PREFIX}/share/pixmaps" +test -z "${NO_QT}" && + install -d -g 0 -o 0 "${PREFIX}/share/icons/hicolor" +test -z "${NO_QT}" && + cp "${INSTALL_SOURCE}/icons/128x128/virtualbox.png" "${PREFIX}/share/pixmaps/" +test -z "${NO_QT}" && + for i in "${INSTALL_SOURCE}/icons/"*; do + folder=`expr "${i}/" : '.*/\([^/][^/]*/\)/*'` + if test -f "${i}/virtualbox."*; then + install -d -g 0 -o 0 "${PREFIX}/share/icons/hicolor/${folder}/apps" + mv "${i}/virtualbox."* "${PREFIX}/share/icons/hicolor/${folder}/apps" + fi + install -d -g 0 -o 0 "${PREFIX}/share/icons/hicolor/${folder}/mimetypes" + mv "${i}/"* "${PREFIX}/share/icons/hicolor/${folder}/mimetypes" 2>/dev/null || true + rmdir "${i}" + done +test -z "${NO_QT}" && + rmdir "${INSTALL_SOURCE}/icons" +if test -w "${INSTALL_SOURCE}/virtualbox.xml"; then + install -d -g 0 -o 0 "${PREFIX}/share/mime/packages" + mv "${INSTALL_SOURCE}/virtualbox.xml" "${PREFIX}/share/mime/packages/" +fi +mv "${INSTALL_SOURCE}/VBox.png" "${PREFIX}/share/pixmaps/" +test -n "${NO_QT}" && + test ! -r ${INSTALL_SOURCE}/VBoxTestOGL +test -n "${NO_QT}" && + test ! -r ${INSTALL_SOURCE}/nls +install -D -g 0 -o 0 -m 644 "${INSTALL_SOURCE}/VBox.sh" "${PREFIX}/bin/VBox" +rm "${INSTALL_SOURCE}/VBox.sh" +( + cd "${INSTALL_SOURCE}/sdk/installer" + export VBOX_INSTALL_PATH="${RELATIVE_PREFIX}${INSTALL_FOLDER}" + "${PYTHON_COMMAND}" "vboxapisetup.py" install --root "${ROOT}" --prefix "${RELATIVE_PREFIX}" +) +rm -rf ${INSTALL_SOURCE}/sdk/installer +test -n "${HEADLESS}" && + test ! -r "${INSTALL_SOURCE}/VBoxSDL" +test -n "${NO_QT}" && + test ! -r "${INSTALL_SOURCE}/VirtualBox" +test -n "${NO_WEB_SERVICE}" && + test ! -r "${INSTALL_SOURCE}/vboxwebsrv" +test -n "${NO_WEB_SERVICE}" && + test ! -r "${INSTALL_SOURCE}/webtest" +mv "${INSTALL_SOURCE}/VBoxTunctl" "${PREFIX}/bin" +test -n "${OSE}" || test -n "${NO_QT}" && + test ! -r ${INSTALL_SOURCE}/kchmviewer +test -z "${OSE}" && test -z "${HEADLESS}" && + mv "${INSTALL_SOURCE}/rdesktop-vrdp" "${PREFIX}/bin" +if test -z "${NO_SHARE_PACKAGE}"; then + install -d -g 0 -o 0 "${PREFIX}/share/${PACKAGE}" + mv "${INSTALL_SOURCE}/VBoxSysInfo.sh" "${PREFIX}/share/${PACKAGE}" + mv "${INSTALL_SOURCE}/VBoxCreateUSBNode.sh" "${PREFIX}/share/${PACKAGE}" + mv "${INSTALL_SOURCE}/src" "${PREFIX}/share/${PACKAGE}" + test -z "${NO_QT}" && + mv "${INSTALL_SOURCE}/nls" "${PREFIX}/share/${PACKAGE}" + mv "${INSTALL_SOURCE}/additions/VBoxGuestAdditions.iso" "${PREFIX}/share/${PACKAGE}" + # The original code did not fail if this file did not exist. + test -z "${OSE}" && test -f "${INSTALL_SOURCE}/rdesktop-vrdp.tar.gz" && + mv "${INSTALL_SOURCE}/rdesktop-vrdp.tar.gz" "${PREFIX}/share/${PACKAGE}" + test -z "${OSE}" && test -z "${HEADLESS}" && + mv "${INSTALL_SOURCE}/rdesktop-vrdp-keymaps" "${PREFIX}/share/${PACKAGE}" + ln -s "../share/virtualbox/src/vboxhost" "${PREFIX}/src/vboxhost-${VBOX_VERSION_STRING}" +else + mv "${INSTALL_SOURCE}/src/vboxhost" "${PREFIX}/src/vboxhost-${VBOX_VERSION_STRING}" +fi +test -z "${NO_QT}" && ln -s "VBox" "${PREFIX}/bin/VirtualBox" +test -z "${NO_QT}" && ln -sf "VBox" "${PREFIX}/bin/virtualbox" +ln -s "VBox" "${PREFIX}/bin/VBoxManage" +ln -sf "VBox" "${PREFIX}/bin/vboxmanage" +test -z "${HEADLESS}" && ln -s "VBox" "${PREFIX}/bin/VBoxSDL" +test -z "${HEADLESS}" && ln -sf "VBox" "${PREFIX}/bin/vboxsdl" +test -z "${OSE}" && ln -s "VBox" "${PREFIX}/bin/VBoxVRDP" +ln -s "VBox" "${PREFIX}/bin/VBoxHeadless" +ln -sf "VBox" "${PREFIX}/bin/vboxheadless" +ln -s "VBox" "${PREFIX}/bin/VBoxBalloonCtrl" +ln -sf "VBox" "${PREFIX}/bin/vboxballoonctrl" +ln -s "VBox" "${PREFIX}/bin/VBoxAutostart" +ln -s "VBox" "${PREFIX}/bin/vboxautostart" +test -z "${NO_WEB_SERVICE}" && ln -s "VBox" "${PREFIX}/bin/vboxwebsrv" +rmdir ${INSTALL_SOURCE}/additions +rm "${INSTALL_SOURCE}/scripts/install.sh" +## @todo Move this to a make file. +install -d -g 0 -o 0 "${INSTALL_SOURCE}/ExtensionPacks" +# For now. +test -n "${NO_HELPERS}" && + rm -r "${INSTALL_SOURCE}/helpers" +# And the very last bit. +test -n "${NO_HELPERS}" && + rm -r "${INSTALL_SOURCE}/scripts" +exit 0 diff --git a/src/VBox/Installer/linux/testcase/Makefile.kmk b/src/VBox/Installer/linux/testcase/Makefile.kmk index 7b365f84..c1d8d8de 100644 --- a/src/VBox/Installer/linux/testcase/Makefile.kmk +++ b/src/VBox/Installer/linux/testcase/Makefile.kmk @@ -38,4 +38,16 @@ $$(tstInstallerLinux_0_OUTDIR)/tstInstallerLinux.sh: \ $< $(QUIET)$(CHMOD) a+rx,u+w $@ +INSTALLS += tstHeadlessXOrg +TESTING += tstHeadlessXOrg +tstHeadlessXOrg_INST = $(INST_TESTCASE) +tstHeadlessXOrg_MODE = a+rx,u+w +tstHeadlessXOrg_SOURCES = tstHeadlessXOrg.sh + +INSTALLS += tstInstallInit +TESTING += tstInstallInit +tstInstallInit_INST = $(INST_TESTCASE) +tstInstallInit_MODE = a+rx,u+w +tstInstallInit_SOURCES = tstInstallInit.sh + include $(FILE_KBUILD_SUB_FOOTER) diff --git a/src/VBox/Installer/linux/testcase/tstHeadlessXOrg.sh b/src/VBox/Installer/linux/testcase/tstHeadlessXOrg.sh new file mode 100755 index 00000000..ba00e85e --- /dev/null +++ b/src/VBox/Installer/linux/testcase/tstHeadlessXOrg.sh @@ -0,0 +1,305 @@ +#!/bin/sh +# $Id: tstHeadlessXOrg.sh $ +## @file +# VirtualBox X Server auto-start service unit test. +# + +# +# Copyright (C) 2012-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. +# + +## The function definition at the start of every non-trivial shell script! +abort() +{ + ## $@, ... Error text to output to standard error in printf format. + format="$1" + shift + printf "${TEST_NAME}: ${format}" "$@" >&2 + exit 1 +} + +## Print a TESTING line. Takes printf arguments but without a '\n'. +print_line() +{ + format="$1" + shift + printf "${TEST_NAME}: TESTING ${format}... " "$@" +} + +## Expected a process to complete within a certain time and call a function if +# it does which should check whether the test was successful and print status +# information. The function takes the exit status as its single parameter. +expect_exit() +{ + PID="$1" ## The PID we are waiting for. + TIME_OUT="$2" ## The time-out before we terminate the process. + TEST_FUNCTION="$3" ## The function to call on exit to check the test result. + + # Give it time to complete. + { sleep "${TIME_OUT}"; kill "${PID}" 2>/dev/null; } & + + wait "${PID}" + STATUS="$?" + case "${STATUS}" in + 143) # SIGTERM + printf "\nFAILED: time-out.\n" + ;; + *) + ${TEST_FUNCTION} "${STATUS}" +esac +} + +## Create a simple configuration file. Add items onto the end to override them +# on an item-by-item basis. +create_basic_configuration() +{ + TEST_FOLDER="${1}" + FILE_NAME="${TEST_FOLDER}conf" ## The name of the configuration file to create. + BASE_FOLDER="${TEST_FOLDER}" + XORG_FOLDER="${TEST_FOLDER}/xorg" + mkdir -p "${XORG_FOLDER}" + cat > "${FILE_NAME}" << EOF +HEADLESS_X_ORG_CONFIGURATION_FOLDER="${BASE_FOLDER}/xorg" +HEADLESS_X_ORG_LOG_FOLDER="${BASE_FOLDER}/log" +HEADLESS_X_ORG_LOG_FILE="log" +HEADLESS_X_ORG_RUN_FOLDER="${BASE_FOLDER}/run" +HEADLESS_X_ORG_WAIT_FOR_PREREQUISITES="true" +HEADLESS_X_ORG_SERVER_PRE_COMMAND= +HEADLESS_X_ORG_SERVER_COMMAND="echo" +EOF + +} + +# Get the directory where the script is located and the parent. +OUR_FOLDER="$(dirname "$0")" +OUR_FOLDER=$(cd "${OUR_FOLDER}" && pwd) +VBOX_FOLDER=$(cd "${OUR_FOLDER}/.." && pwd) +[ -d "${VBOX_FOLDER}" ] || + abort "Failed to change to directory ${VBOX_FOLDER}.\n" +cd "${VBOX_FOLDER}" + +# Get our name for output. +TEST_NAME="$(basename "$0" .sh)" + +# And remember the full path. +TEST_NAME_FULL="${OUR_FOLDER}/$(basename "$0")" + +# Create a temporary directory for configuration and logging. +TEST_FOLDER_BASE="/tmp/${TEST_NAME} 99/" # Space in the name to test quoting. +if [ -n "${TESTBOX_PATH_SCRATCH}" ]; then + TEST_FOLDER_BASE="${TESTBOX_PATH_SCRATCH}/${TEST_NAME} 99/" +fi +{ + rm -rf "${TEST_FOLDER_BASE}" 2>/dev/null && + mkdir -m 0700 "${TEST_FOLDER_BASE}" 2>/dev/null +} || abort "Could not create test folder (${TEST_FOLDER_BASE}).\n" + +############################################################################### +# Simple start-up test. # +############################################################################### +print_line "simple start-up test" +create_basic_configuration "${TEST_FOLDER_BASE}simple_start-up_test/" +touch "${XORG_FOLDER}/xorg.conf.2" +touch "${XORG_FOLDER}/xorg.conf.4" + +test_simple_start_up() +{ + STATUS="$1" + case "${STATUS}" in + 0) + LOG_FOLDER="${TEST_FOLDER}/log" + LOG="${LOG_FOLDER}/log" + if grep -q "2 ${XORG_FOLDER}/xorg.conf.2 ${LOG_FOLDER}/Xorg.2.log" "${LOG}" && + grep -q "4 ${XORG_FOLDER}/xorg.conf.4 ${LOG_FOLDER}/Xorg.4.log" "${LOG}"; then + printf "SUCCESS.\n" + else + printf "\nFAILED: incorrect log output.\n" + fi + ;; + *) + printf "\nFAILED: exit status ${STATUS}.\n" + esac +} + +scripts/VBoxHeadlessXOrg.sh -c "${TEST_FOLDER}conf" & +PID=$! +expect_exit "${PID}" 5 test_simple_start_up + +############################################################################### +# No configuration files. # +############################################################################### +create_basic_configuration "${TEST_FOLDER_BASE}no_configuration_files/" +print_line "no configuration files" + +test_should_fail() +{ + STATUS="$1" + case "${STATUS}" in + 0) + printf "\nFAILED: successful exit when an error was expected.\n" + ;; + *) + printf "SUCCESS.\n" # At least it behaved the way we wanted. + esac +} + +scripts/VBoxHeadlessXOrg.sh -c "${TEST_FOLDER}conf" & +PID=$! +expect_exit "${PID}" 5 test_should_fail + +############################################################################### +# Bad configuration files. # +############################################################################### +print_line "bad configuration files" +create_basic_configuration "${TEST_FOLDER_BASE}bad_configuration_files/" +touch "${XORG_FOLDER}/xorg.conf.2" +touch "${XORG_FOLDER}/xorg.conf.4" +touch "${XORG_FOLDER}/xorg.conf.other" +scripts/VBoxHeadlessXOrg.sh -c "${TEST_FOLDER}conf" & +PID=$! +expect_exit "${PID}" 5 test_should_fail + +############################################################################### +# Long running server command. # +############################################################################### + +# Set up a configuration file for a long-running command. +create_basic_configuration "${TEST_FOLDER_BASE}long-running_command/" +cat >> "${TEST_FOLDER}conf" << EOF +HEADLESS_X_ORG_SERVER_COMMAND="${TEST_FOLDER}command.sh" +EOF + +cat > "${TEST_FOLDER}command.sh" << EOF +#!/bin/sh +touch "${TEST_FOLDER}stopped" +touch "${TEST_FOLDER}started" +trap "touch \\"${TEST_FOLDER}stopped\\"; exit" TERM +rm "${TEST_FOLDER}stopped" +while true; do :; done +EOF +chmod a+x "${TEST_FOLDER}command.sh" + +print_line "long running server command" +touch "${XORG_FOLDER}/xorg.conf.5" +FAILURE="" +scripts/VBoxHeadlessXOrg.sh -c "${TEST_FOLDER}conf" & +PID="$!" +while [ ! -f "${TEST_FOLDER}started" ]; do :; done +while [ -f "${TEST_FOLDER}stopped" ]; do :; done +[ -n "${PID}" ] && kill "${PID}" 2>/dev/null +while [ ! -f "${TEST_FOLDER}stopped" ]; do :; done +printf "SUCCESS.\n" + +############################################################################### +# Pre-requisite test. # +############################################################################### + +# Set up a configuration file with a pre-requisite. +create_basic_configuration "${TEST_FOLDER_BASE}pre-requisite/" +cat >> "${TEST_FOLDER}conf" << EOF +HEADLESS_X_ORG_WAIT_FOR_PREREQUISITES="false" +EOF + +print_line "configuration file with failed pre-requisite" +touch "${XORG_FOLDER}/xorg.conf.2" +touch "${XORG_FOLDER}/xorg.conf.4" +if scripts/VBoxHeadlessXOrg.sh -c "${TEST_FOLDER}conf"; then + echo "\nFAILED to stop for failed pre-requisite.\n" +else + echo "SUCCESS" +fi + +############################################################################### +# Pre-command test. # +############################################################################### + +# Set up our pre-command test configuration file. +create_basic_configuration "${TEST_FOLDER_BASE}pre-command/" + +cat >> "${TEST_FOLDER}conf" << EOF +test_pre_command_server_pre_command() +{ + touch "${TEST_FOLDER}/run/pre" +} +test_pre_command_server_command() +{ + cp "${TEST_FOLDER}/run/pre" "${TEST_FOLDER}/run/pre2" +} +HEADLESS_X_ORG_SERVER_PRE_COMMAND="test_pre_command_server_pre_command" +HEADLESS_X_ORG_SERVER_COMMAND="test_pre_command_server_command" +EOF + +print_line "pre-command test" +touch "${XORG_FOLDER}/xorg.conf.2" + +test_pre_command() +{ + STATUS="$1" + case "${STATUS}" in + 0) + LOG_FOLDER="${TEST_FOLDER}/log" + LOG="${LOG_FOLDER}/log" + if [ -e "${TEST_FOLDER}/run/pre" ] && [ -e "${TEST_FOLDER}/run/pre2" ]; then + printf "SUCCESS.\n" + else + printf "\nFAILED: pre-command not executed.\n" + fi + ;; + *) + printf "\nFAILED: exit status ${STATUS}.\n" + esac +} + +rm -f "${TEST_FOLDER}/run/pre" +scripts/VBoxHeadlessXOrg.sh -c "${TEST_FOLDER}conf" & +PID=$! +expect_exit "${PID}" 5 test_pre_command + +############################################################################### +# Post-command test. # +############################################################################### + +# Set up our post-command test configuration file. +create_basic_configuration "${TEST_FOLDER_BASE}post-command/" +cat >> "${TEST_FOLDER}conf" << EOF +test_post_command_post_command() +{ + echo "\${1}" > "${TEST_FOLDER}/run/post" +} +HEADLESS_X_ORG_SERVER_POST_COMMAND="test_post_command_post_command" +EOF + +print_line "post-command test" +touch "${XORG_FOLDER}/xorg.conf.2" +touch "${XORG_FOLDER}/xorg.conf.4" + +test_post_command() +{ + STATUS="$1" + case "${STATUS}" in + 0) + LOG_FOLDER="${TEST_FOLDER}/log" + LOG="${LOG_FOLDER}/log" + if grep -q "2 4" "${TEST_FOLDER}/run/post"; then + printf "SUCCESS.\n" + else + printf "\nFAILED: post-command not executed.\n" + fi + ;; + *) + printf "\nFAILED: exit status ${STATUS}.\n" + esac +} + +rm -f "${TEST_FOLDER}/run/post" +scripts/VBoxHeadlessXOrg.sh -c "${TEST_FOLDER}conf" & +PID=$! +expect_exit "${PID}" 5 test_post_command diff --git a/src/VBox/Installer/linux/testcase/tstInstallInit.sh b/src/VBox/Installer/linux/testcase/tstInstallInit.sh new file mode 100755 index 00000000..9c6c1bab --- /dev/null +++ b/src/VBox/Installer/linux/testcase/tstInstallInit.sh @@ -0,0 +1,365 @@ +#!/bin/sh +# $Id: tstInstallInit.sh $ +## @file +# VirtualBox init file creator unit test. +# + +# +# Copyright (C) 2012-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. +# + +# This will initially be a skeleton with a couple of tests - add more for quick +# debugging when you suspect that something isn't working as specified. + +tab=" " +tmpbase="/tmp/tstInstallInit 99" # Space in the name for a little stress... +if [ -n "${TESTBOX_PATH_SCRATCH}" ]; then + tmpbase="${TESTBOX_PATH_SCRATCH}/tstInstallInit 99" +fi + +## The function definition at the start of every non-trivial shell script! +abort() +{ + ## $1 Error text to output to standard error in printf format. + cat >&2 << EOF +${TEST_NAME}: $1 +EOF + exit 1 +} + +## Print a TESTING line. +print_line() +{ + cat >&2 << EOF +${TEST_NAME}: TESTING $1 +EOF +} + +## Set the failure message if it is not yet set. +fail_msg() +{ + test -z "${failed}" && failed="FAILED: ${1}" +} + +# Get the directory where the script is located and the parent. +OUR_FOLDER=`dirname "$0"` +OUR_FOLDER=`cd "${OUR_FOLDER}" && pwd` +VBOX_FOLDER=`cd "${OUR_FOLDER}/.." && pwd` +[ -d "${VBOX_FOLDER}" ] || + abort "Failed to change to directory ${VBOX_FOLDER}.\n" +cd "${VBOX_FOLDER}" + +# Get our name for output. +TEST_NAME="$(basename "$0" .sh)" + +# Create a trivial test service in temporary directory $1 with name $2. +test_service() +{ + cat > "${1}/${2}" << EOF +#!/bin/sh +trap "touch \"${1}/stopped\"; exit" TERM +echo "1: \${1} 2: \${2} 3: \${3}" > "${1}/started" +while true; do true; done +EOF +chmod u+x "${1}/${2}" +} + +# Create a trivial test command in temporary directory $1 with name $2. +test_oneshot() +{ + cat > "${1}/${2}" << EOF +#!/bin/sh +if test "\${1}" = start; then + touch "${1}/started" +else + rm "${1}/started" +fi +exit 0 +EOF +chmod u+x "${1}/${2}" +} + +# Test some dodgy input values against generate_service_file. +# Make sure there is a substitution pattern at the end too. +print_line "generation of shell script from template." +input='TEST1%DESCRIPTION%%%%SERVICE_NAME%%STOP_COMMAND% TST2 TEST %ARGUMENTS%%COMMAND%' +out=`echo "${input}" | + helpers/generate_service_file --command '/usr/bin +aries/hello +world' --arguments 'p\x0a0\n\ \t' --format shell --description ''` +expected='TEST1%hello +world TST2 TEST '\''p +0 + '"${tab}"\'\''/usr/bin +aries/hello +world'\' +case "${out}" in ${expected}) +echo "SUCCESS (1)";; +*) +cat << EOF +FAILED: expected +${expected} +but got +${out} +EOF +esac +input='TEST%HAVE_STOP_COMMAND%%SERVICE_NAME%%STOP_COMMAND% TST2 + TEST %COMMAND%' +out=`echo "${input}" | + helpers/generate_service_file --command '/usr/bin/hello' --format shell --description ''` +expected='TEST TEST '\''/usr/bin/hello'\''' +case "${out}" in ${expected}) +echo "SUCCESS (2)";; +*) +cat << EOF +FAILED: expected +${expected} +but got +${out} +EOF +esac +input='TEST%HAVE_STOP_COMMAND%%SERVICE_NAME%%STOP_COMMAND% %STOP_ARGUMENTS% TST2 + TEST %COMMAND%' +out=`echo "${input}" | + helpers/generate_service_file --command '/usr/bin/hello' --format shell --description '' --stop-command /usr/bin/stop --stop-arguments hello` +expected='TESThello'\''/usr/bin/stop'\'' '\''hello'\'' TST2 + TEST '\''/usr/bin/hello'\''' +case "${out}" in ${expected}) +echo "SUCCESS (3)";; +*) +cat << EOF +FAILED: expected +${expected} +but got +${out} +EOF +esac + +# Create a simulated init system layout. +create_simulated_init_tree() +{ + tmpdir="${1}" + rm -rf "${tmpdir}" + mkdir -m 0700 "${tmpdir}" || abort "Failed to create a temporary folder." + mkdir -p "${tmpdir}/init.d/" "${tmpdir}/rc.d/init.d/" + for i in 0 1 2 3 4 5 6; do + mkdir "${tmpdir}/rc${i}.d/" "${tmpdir}/rc.d/rc${i}.d/" + done + mkdir -p "${tmpdir}/runlevel/default" "${tmpdir}/runlevel/boot" + mkdir "${tmpdir}/run" +} + +# Test an init script installation. +print_line "installing an init script." +failed="" +# Create a simulated init system layout. +tmpdir="${tmpbase}0" +create_simulated_init_tree "${tmpdir}" +# Create the service binary. +test_service "${tmpdir}" "service" +# And install it. +scripts/install_service --prefix "${tmpdir}" --enable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || + fail_msg "\"scripts/install_service\" failed." +# Check that the main service file was created as specified. +if test -x "${tmpdir}/init.d/service"; then + grep "Short-Description: My description" "${tmpdir}/init.d/service" >/dev/null || + fail_msg "Description not set in \"${tmpdir}/init.d/service\"" +else + fail_msg "\"${tmpdir}/init.d/service\" not correctly created." +fi +test -x "${tmpdir}/init.d/rc.d/service" && + fail_msg "\"${tmpdir}/init.d/rc.d/service\" created but shouldn't have been." +# Try to start the service using the symbolic links which should have been +# created. +if "${tmpdir}/rc3.d/S20service" --prefix "${tmpdir}" --lsb-functions "" start >/dev/null 2>&1; then + if grep "1: test 2: of 3: my arguments" "${tmpdir}/started" >/dev/null; then + test -f "${tmpdir}/stopped" && + fail_msg "\"${tmpdir}/rc3.d/S20service\" stopped immediately." + else + fail_msg "\"${tmpdir}/rc3.d/S20service\" did not start correctly." + fi +else + fail_msg "could not start \"${tmpdir}/rc3.d/S20service\"." +fi +# Check the status. +"${tmpdir}/rc.d/rc5.d/S20service" --prefix "${tmpdir}" --lsb-functions "" status >/dev/null 2>&1 || + fail_msg "\"${tmpdir}/rc.d/rc5.d/S20service\" reported the wrong status." +# Try to stop the service using the symbolic links which should have been +# created. +if "${tmpdir}/rc.d/rc6.d/K80service" --prefix "${tmpdir}" --lsb-functions "" stop >/dev/null 2>&1; then + test -f "${tmpdir}/stopped" || + echo "\"${tmpdir}/rc.d/rc6.d/K80service\" did not stop correctly." +else + fail_msg "could not stop \"${tmpdir}/rc.d/rc6.d/K80service\"." +fi +# Check the status again - now it should be stopped. +"${tmpdir}/runlevel/service" --prefix "${tmpdir}" --lsb-functions "" status >/dev/null 2>&1 && + fail_msg "\"${tmpdir}/runlevel/service\" reported the wrong status." +# Final summary. +if test -n "${failed}"; then + echo "${failed}" +else + echo SUCCESS +fi + +# Test an one shot init script installation. +print_line "installing a one shot init script." +failed="" +# Create a simulated init system layout. +tmpdir="${tmpbase}0" +create_simulated_init_tree "${tmpdir}" +# Create the command binary. +test_oneshot "${tmpdir}" "command" +# And install the script. +scripts/install_service --prefix "${tmpdir}" --enable -- --command "${tmpdir}/command" --arguments "start" --description "My description" --stop-command "${tmpdir}/command" --stop-arguments "stop" --one-shot || + fail_msg "\"scripts/install_service\" failed." +# Sanity test. +test -f "${tmpdir}/started" && + fail_msg "\"${tmpdir}/started\" already exists!" +# Try to start the service using the symbolic links which should have been +# created. +if "${tmpdir}/rc3.d/S20command" --prefix "${tmpdir}" --lsb-functions "" start >/dev/null 2>&1; then + test -f "${tmpdir}/started" || + fail_msg "\"${tmpdir}/rc3.d/S20command\" did not start correctly." +else + fail_msg "could not start \"${tmpdir}/rc3.d/S20command\"." +fi +# Try to stop the service using the symbolic links which should have been +# created. +if "${tmpdir}/rc.d/rc6.d/K80command" --prefix "${tmpdir}" --lsb-functions "" stop >/dev/null 2>&1; then + test -f "${tmpdir}/started" && + echo "\"${tmpdir}/rc.d/rc6.d/K80command\" did not stop correctly." +else + fail_msg "could not stop \"${tmpdir}/rc.d/rc6.d/K80command\"." +fi +# Final summary. +if test -n "${failed}"; then + echo "${failed}" +else + echo SUCCESS +fi + +# Test an init script removal. +print_line "removing an init script." +failed="" +# Create a simulated init system layout. +tmpdir="${tmpbase}0" +create_simulated_init_tree "${tmpdir}" +# Create the service binary. +test_service "${tmpdir}" "service" +# Install it. +scripts/install_service --prefix "${tmpdir}" --enable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || + fail_msg "\"scripts/install_service\" failed." +# And remove it again. +scripts/install_service --prefix "${tmpdir}" --remove -- --command "${tmpdir}/service" || + fail_msg "\"scripts/install_service\" failed." +# After uninstallation this should be the only file left in the init tree. +rm "${tmpdir}/service" +test "x`find "${tmpdir}" -type f -o -type l`" = "x" || + fail_msg "not all files were removed." +# Final summary. +if test -n "${failed}"; then + echo "${failed}" +else + echo SUCCESS +fi + +# Test an enabled init script update with --disable. +print_line "updating an enabled init script with --disable." +failed="" +# Create a simulated init system layout. +tmpdir="${tmpbase}1" +create_simulated_init_tree "${tmpdir}" +# Create the service binary. +test_service "${tmpdir}" "service" +# Install it. +scripts/install_service --prefix "${tmpdir}" --enable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || + fail_msg "\"scripts/install_service\" failed." +# Install it disabled without forcing. +scripts/install_service --prefix "${tmpdir}" --disable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || + fail_msg "\"scripts/install_service\" failed." +test "x`find "${tmpdir}"/rc*.d "${tmpdir}/runlevel" -type l | wc -l`" = "x15" || + fail_msg "links were removed on non-forced disable." +# Final summary. +if test -n "${failed}"; then + echo "${failed}" +else + echo SUCCESS +fi + +# Test updating a disabled init script with --enable. +print_line "updating a disabled init script with --enable." +failed="" +# Create a simulated init system layout. +tmpdir="${tmpbase}2" +create_simulated_init_tree "${tmpdir}" +# Create the service binary. +test_service "${tmpdir}" "service" +# Install it. +scripts/install_service --prefix "${tmpdir}" --disable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || + fail_msg "\"scripts/install_service\" failed." +# Install it disabled without forcing. +scripts/install_service --prefix "${tmpdir}" --enable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || + fail_msg "\"scripts/install_service\" failed." +test "x`find "${tmpdir}"/rc*.d "${tmpdir}/runlevel" -type l`" = "x" || + fail_msg "files were installed on non-forced enable." +# Final summary. +if test -n "${failed}"; then + echo "${failed}" +else + echo SUCCESS +fi + +# Test an enabled init script update with --force-disable. +print_line "updating an enabled init script with --force-disable." +failed="" +# Create a simulated init system layout. +tmpdir="${tmpbase}3" +create_simulated_init_tree "${tmpdir}" +# Create the service binary. +test_service "${tmpdir}" "service" +# Install it. +scripts/install_service --prefix "${tmpdir}" --enable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || + fail_msg "\"scripts/install_service\" failed." +# Install it disabled without forcing. +scripts/install_service --prefix "${tmpdir}" --force-disable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || + fail_msg "\"scripts/install_service\" failed." +test "x`find "${tmpdir}"/rc*.d "${tmpdir}/runlevel" -type l`" = "x" || + fail_msg "links were not removed on forced disable." +# Final summary. +if test -n "${failed}"; then + echo "${failed}" +else + echo SUCCESS +fi + +# Test updating a disabled init script with --force-enable. +print_line "updating a disabled init script with --force-enable." +failed="" +# Create a simulated init system layout. +tmpdir="${tmpbase}4" +create_simulated_init_tree "${tmpdir}" +# Create the service binary. +test_service "${tmpdir}" "service" +# Install it. +scripts/install_service --prefix "${tmpdir}" --disable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || + fail_msg "\"scripts/install_service\" failed." +# Install it disabled without forcing. +scripts/install_service --prefix "${tmpdir}" --force-enable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || + fail_msg "\"scripts/install_service\" failed." +test "x`find "${tmpdir}"/rc*.d "${tmpdir}/runlevel" -type l | wc -l`" = "x15" || + fail_msg "files were not installed on forced enable." +# Final summary. +if test -n "${failed}"; then + echo "${failed}" +else + echo SUCCESS +fi diff --git a/src/VBox/Installer/linux/testcase/tstInstallerLinux.sh b/src/VBox/Installer/linux/testcase/tstInstallerLinux.sh index 1a5f0ce8..d2708ed3 100755 --- a/src/VBox/Installer/linux/testcase/tstInstallerLinux.sh +++ b/src/VBox/Installer/linux/testcase/tstInstallerLinux.sh @@ -83,7 +83,7 @@ extern_test_input_install_device_node_setup() { do_install_create_usb_node_for_sysfs "$@";; *) echo Unknown command $command >&2; exit 1;; - esac + esac } setup_test_input_install_device_node_setup() { diff --git a/src/VBox/Installer/linux/uninstall.sh b/src/VBox/Installer/linux/uninstall.sh index 947f3435..b479b19c 100755 --- a/src/VBox/Installer/linux/uninstall.sh +++ b/src/VBox/Installer/linux/uninstall.sh @@ -4,7 +4,7 @@ # VirtualBox linux uninstallation script # -# Copyright (C) 2009-2010 Oracle Corporation +# Copyright (C) 2009-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -57,6 +57,8 @@ stop_init_script vboxweb-service check_running # Terminate VBoxNetDHCP if running terminate_proc VBoxNetDHCP +# Terminate VBoxNetNAT if running +terminate_proc VBoxNetNAT delrunlevel vboxballoonctrl-service > /dev/null 2>&1 remove_init_script vboxballoonctrl-service delrunlevel vboxautostart-service > /dev/null 2>&1 @@ -98,6 +100,7 @@ rm -f \ /usr/bin/VBoxBalloonCtrl \ /usr/bin/VBoxAutostart \ /usr/bin/VBoxNetDHCP \ + /usr/bin/VBoxNetNAT \ /usr/bin/vboxwebsrv \ /usr/bin/VBoxAddIF \ /usr/bin/VBoxDeleteIf \ diff --git a/src/VBox/Installer/linux/vboxautostart-service.sh.in b/src/VBox/Installer/linux/vboxautostart-service.sh index 9487b8f9..33462e18 100755 --- a/src/VBox/Installer/linux/vboxautostart-service.sh.in +++ b/src/VBox/Installer/linux/vboxautostart-service.sh @@ -26,23 +26,21 @@ ### END INIT INFO PATH=$PATH:/bin:/sbin:/usr/sbin -DEBIAN=%DEBIAN% -NOLSB=%NOLSB% -[ -f /lib/lsb/init-functions ] || NOLSB=yes +[ -f /etc/debian_release -a -f /lib/lsb/init-functions ] || NOLSB=yes [ -f /etc/vbox/vbox.cfg ] && . /etc/vbox/vbox.cfg if [ -n "$INSTALL_DIR" ]; then binary="$INSTALL_DIR/VBoxAutostart" else - binary="/usr/lib/%PACKAGE%/VBoxAutostart" + binary="/usr/lib/virtualbox/VBoxAutostart" fi # silently exit if the package was uninstalled but not purged, -# applies to Debian packages only -[ -z "$DEBIAN" -o -x $binary ] || exit 0 +# applies to Debian packages only (but shouldn't hurt elsewhere) +[ ! -f /etc/debian_release -o -x $binary ] || exit 0 -[ -r /etc/default/%PACKAGE% ] && . /etc/default/%PACKAGE% +[ -r /etc/default/virtualbox ] && . /etc/default/virtualbox system=unknown if [ -f /etc/redhat-release ]; then @@ -292,25 +290,17 @@ stop() { [ -z "$VBOXAUTOSTART_DB" ] && exit 0 [ -z "$VBOXAUTOSTART_CONFIG" ] && exit 0 - exit 0 - - #begin_msg "Stopping VirtualBox VMs configured for autostop"; - #vboxdrvrunning || { - # fail_msg "VirtualBox kernel module not loaded!" - # exit 0 - #} - #PARAMS="--stop" - #[ -n "$VBOXAUTOSTART_CONFIG" ] && PARAMS="$PARAMS -c $VBOXAUTOSTART_CONFIG" + PARAMS="--stop --config $VBOXAUTOSTART_CONFIG" # prevent inheriting this setting to VBoxSVC - #unset VBOX_RELEASE_LOG_DEST + unset VBOX_RELEASE_LOG_DEST - #for user in `ls $VBOXAUTOSTART_DB/*.stop` - #do - # start_daemon `basename $user | sed -ne "s/\(.*\).stop/\1/p"` $binary $PARAMS > /dev/null 2>&1 - #done + for user in `ls $VBOXAUTOSTART_DB/*.stop` + do + start_daemon `basename $user | sed -ne "s/\(.*\).stop/\1/p"` $binary $PARAMS > /dev/null 2>&1 + done - #return $RETVAL + return $RETVAL } case "$1" in diff --git a/src/VBox/Installer/linux/vboxballoonctrl-service.sh.in b/src/VBox/Installer/linux/vboxballoonctrl-service.sh index 3f0b8ea8..e10b86af 100755 --- a/src/VBox/Installer/linux/vboxballoonctrl-service.sh.in +++ b/src/VBox/Installer/linux/vboxballoonctrl-service.sh @@ -1,8 +1,8 @@ #!/bin/sh # -# VirtualBox balloon control daemon init script. +# VirtualBox watchdog daemon init script. # -# Copyright (C) 2006-2012 Oracle Corporation +# Copyright (C) 2006-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; @@ -14,7 +14,7 @@ # # chkconfig: 35 35 65 -# description: VirtualBox balloon control daemon +# description: VirtualBox watchdog daemon # ### BEGIN INIT INFO # Provides: vboxballoonctrl-service @@ -22,27 +22,25 @@ # Required-Stop: vboxdrv # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 -# Description: VirtualBox balloon control daemon +# Description: VirtualBox watchdog daemon ### END INIT INFO PATH=$PATH:/bin:/sbin:/usr/sbin -DEBIAN=%DEBIAN% -NOLSB=%NOLSB% -[ -f /lib/lsb/init-functions ] || NOLSB=yes +[ -f /lib/lsb/init-functions -a -f /etc/debian_release ] || NOLSB=yes [ -f /etc/vbox/vbox.cfg ] && . /etc/vbox/vbox.cfg if [ -n "$INSTALL_DIR" ]; then binary="$INSTALL_DIR/VBoxBalloonCtrl" else - binary="/usr/lib/%PACKAGE%/VBoxBalloonCtrl" + binary="/usr/lib/virtualbox/VBoxBalloonCtrl" fi # silently exit if the package was uninstalled but not purged, -# applies to Debian packages only -[ -z "$DEBIAN" -o -x $binary ] || exit 0 +# applies to Debian packages only (but shouldn't hurt elsewhere) +[ ! -f /etc/debian_release -o -x $binary ] || exit 0 -[ -r /etc/default/%PACKAGE% ] && . /etc/default/%PACKAGE% +[ -r /etc/default/virtualbox ] && . /etc/default/virtualbox system=unknown if [ -f /etc/redhat-release ]; then @@ -279,31 +277,43 @@ vboxdrvrunning() { check_single_user() { if [ -n "$2" ]; then - fail_msg "VBOXBALLOONCTRL_USER must not contain multiple users!" + fail_msg "VBOXWATCHDOG_USER must not contain multiple users!" exit 1 fi } start() { if ! test -f $PIDFILE; then - [ -z "$VBOXBALLOONCTRL_USER" ] && exit 0 - begin_msg "Starting VirtualBox balloon control service"; - check_single_user $VBOXBALLOONCTRL_USER + [ -z "$VBOXWATCHDOG_USER" -a -z "$VBOXBALLOONCTRL_USER" ] && exit 0 + [ -z "$VBOXWATCHDOG_USER" ] && VBOXWATCHDOG_USER="$VBOXBALLOONCTRL_USER" + begin_msg "Starting VirtualBox watchdog service"; + check_single_user $VBOXWATCHDOG_USER vboxdrvrunning || { fail_msg "VirtualBox kernel module not loaded!" exit 0 } + # Handle legacy parameters, do not add any further ones unless absolutely necessary. + [ -z "$VBOXWATCHDOG_BALLOON_INTERVAL" -a -n "$VBOXBALLOONCTRL_INTERVAL" ] && VBOXWATCHDOG_BALLOON_INTERVAL="$VBOXBALLOONCTRL_INTERVAL" + [ -z "$VBOXWATCHDOG_BALLOON_INCREMENT" -a -n "$VBOXBALLOONCTRL_INCREMENT" ] && VBOXWATCHDOG_BALLOON_INCREMENT="$VBOXBALLOONCTRL_INCREMENT" + [ -z "$VBOXWATCHDOG_BALLOON_DECREMENT" -a -n "$VBOXBALLOONCTRL_DECREMENT" ] && VBOXWATCHDOG_BALLOON_DECREMENT="$VBOXBALLOONCTRL_DECREMENT" + [ -z "$VBOXWATCHDOG_BALLOON_LOWERLIMIT" -a -n "$VBOXBALLOONCTRL_LOWERLIMIT" ] && VBOXWATCHDOG_BALLOON_LOWERLIMIT="$VBOXBALLOONCTRL_LOWERLIMIT" + [ -z "$VBOXWATCHDOG_BALLOON_SAFETYMARGIN" -a -n "$VBOXBALLOONCTRL_SAFETYMARGIN" ] && VBOXWATCHDOG_BALLOON_SAFETYMARGIN="$VBOXBALLOONCTRL_SAFETYMARGIN" + [ -z "$VBOXWATCHDOG_ROTATE" -a -n "$VBOXBALLOONCTRL_ROTATE" ] && VBOXWATCHDOG_ROTATE="$VBOXBALLOONCTRL_ROTATE" + [ -z "$VBOXWATCHDOG_LOGSIZE" -a -n "$VBOXBALLOONCTRL_LOGSIZE" ] && VBOXWATCHDOG_LOGSIZE="$VBOXBALLOONCTRL_LOGSIZE" + [ -z "$VBOXWATCHDOG_LOGINTERVAL" -a -n "$VBOXBALLOONCTRL_LOGINTERVAL" ] && VBOXWATCHDOG_LOGINTERVAL="$VBOXBALLOONCTRL_LOGINTERVAL" + PARAMS="--background" - [ -n "$VBOXBALLOONCTRL_INTERVAL" ] && PARAMS="$PARAMS --balloon-interval $VBOXBALLOONCTRL_INTERVAL" - [ -n "$VBOXBALLOONCTRL_INCREMENT" ] && PARAMS="$PARAMS --balloon-inc $VBOXBALLOONCTRL_INCREMENT" - [ -n "$VBOXBALLOONCTRL_DECREMENT" ] && PARAMS="$PARAMS --balloon-dec $VBOXBALLOONCTRL_DECREMENT" - [ -n "$VBOXBALLOONCTRL_LOWERLIMIT" ] && PARAMS="$PARAMS --balloon-lower-limit $VBOXBALLOONCTRL_LOWERLIMIT" - [ -n "$VBOXBALLOONCTRL_ROTATE" ] && PARAMS="$PARAMS -R $VBOXBALLOONCTRL_ROTATE" - [ -n "$VBOXBALLOONCTRL_LOGSIZE" ] && PARAMS="$PARAMS -S $VBOXBALLOONCTRL_LOGSIZE" - [ -n "$VBOXBALLOONCTRL_LOGINTERVAL" ] && PARAMS="$PARAMS -I $VBOXBALLOONCTRL_LOGINTERVAL" + [ -n "$VBOXWATCHDOG_BALLOON_INTERVAL" ] && PARAMS="$PARAMS --balloon-interval \"$VBOXWATCHDOG_BALLOON_INTERVAL\"" + [ -n "$VBOXWATCHDOG_BALLOON_INCREMENT" ] && PARAMS="$PARAMS --balloon-inc \"$VBOXWATCHDOG_BALLOON_INCREMENT\"" + [ -n "$VBOXWATCHDOG_BALLOON_DECREMENT" ] && PARAMS="$PARAMS --balloon-dec \"$VBOXWATCHDOG_BALLOON_DECREMENT\"" + [ -n "$VBOXWATCHDOG_BALLOON_LOWERLIMIT" ] && PARAMS="$PARAMS --balloon-lower-limit \"$VBOXWATCHDOG_BALLOON_LOWERLIMIT\"" + [ -n "$VBOXWATCHDOG_BALLOON_SAFETYMARGIN" ] && PARAMS="$PARAMS --balloon-safety-margin \"$VBOXWATCHDOG_BALLOON_SAFETYMARGIN\"" + [ -n "$VBOXWATCHDOG_ROTATE" ] && PARAMS="$PARAMS -R \"$VBOXWATCHDOG_ROTATE\"" + [ -n "$VBOXWATCHDOG_LOGSIZE" ] && PARAMS="$PARAMS -S \"$VBOXWATCHDOG_LOGSIZE\"" + [ -n "$VBOXWATCHDOG_LOGINTERVAL" ] && PARAMS="$PARAMS -I \"$VBOXWATCHDOG_LOGINTERVAL\"" # prevent inheriting this setting to VBoxSVC unset VBOX_RELEASE_LOG_DEST - start_daemon $VBOXBALLOONCTRL_USER $binary $PARAMS > /dev/null 2>&1 + start_daemon $VBOXWATCHDOG_USER $binary $PARAMS > /dev/null 2>&1 # ugly: wait until the final process has forked sleep .1 PID=`pidof $binary 2>/dev/null` @@ -321,7 +331,7 @@ start() { stop() { if test -f $PIDFILE; then - begin_msg "Stopping VirtualBox balloon control service"; + begin_msg "Stopping VirtualBox watchdog service"; killproc $binary RETVAL=$? if ! pidof $binary > /dev/null 2>&1; then @@ -339,7 +349,7 @@ restart() { } status() { - echo -n "Checking for VBox balloon control service" + echo -n "Checking for VBox watchdog service" if [ -f $PIDFILE ]; then echo " ...running" else diff --git a/src/VBox/Installer/linux/vboxdrv.sh.in b/src/VBox/Installer/linux/vboxdrv.sh.in index 6e33f233..82bbdbf1 100755 --- a/src/VBox/Installer/linux/vboxdrv.sh.in +++ b/src/VBox/Installer/linux/vboxdrv.sh.in @@ -3,7 +3,7 @@ # Linux kernel module init script # -# Copyright (C) 2006-2010 Oracle Corporation +# Copyright (C) 2006-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; @@ -29,8 +29,6 @@ PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH DEVICE=/dev/vboxdrv LOG="/var/log/vbox-install.log" -NOLSB=%NOLSB% -DEBIAN=%DEBIAN% VERSION=%VERSION% MODPROBE=/sbin/modprobe @@ -38,7 +36,7 @@ if $MODPROBE -c | grep -q '^allow_unsupported_modules *0'; then MODPROBE="$MODPROBE --allow-unsupported-modules" fi -[ -f /lib/lsb/init-functions ] || NOLSB=yes +[ -f /etc/debian_release -a -f /lib/lsb/init-functions ] || NOLSB=yes [ -f /etc/vbox/vbox.cfg ] && . /etc/vbox/vbox.cfg export BUILD_TYPE export USERNAME @@ -48,15 +46,15 @@ if [ -n "$INSTALL_DIR" ]; then VBOXMANAGE="$INSTALL_DIR/VBoxManage" MODULE_SRC="$INSTALL_DIR/src/vboxhost" else - VBOXMANAGE="/usr/lib/%PACKAGE%/VBoxManage" - MODULE_SRC="/usr/share/%PACKAGE%/src/vboxhost" + VBOXMANAGE="/usr/lib/virtualbox/VBoxManage" + MODULE_SRC="/usr/share/virtualbox/src/vboxhost" fi BUILDINTMP="$MODULE_SRC/build_in_tmp" DODKMS="$MODULE_SRC/do_dkms" # silently exit if the package was uninstalled but not purged, -# applies to Debian packages only -[ -z "$DEBIAN" -o -x $VBOXMANAGE -a -x $BUILDINTMP ] || exit 0 +# applies to Debian packages only (but shouldn't hurt elsewhere) +[ ! -f /etc/debian_release -o -x $VBOXMANAGE -a -x $BUILDINTMP ] || exit 0 if [ -n "$NOLSB" ]; then if [ -f /etc/redhat-release ]; then @@ -68,7 +66,7 @@ if [ -n "$NOLSB" ]; then fi fi -[ -r /etc/default/%PACKAGE% ] && . /etc/default/%PACKAGE% +[ -r /etc/default/virtualbox ] && . /etc/default/virtualbox if [ -z "$NOLSB" ]; then . /lib/lsb/init-functions @@ -247,7 +245,7 @@ stop() succ_msg } -# enter the following variables in /etc/default/%PACKAGE%: +# enter the following variables in /etc/default/virtualbox: # SHUTDOWN_USERS="foo bar" # check for running VMs of user foo and user bar # SHUTDOWN=poweroff diff --git a/src/VBox/Installer/linux/vboxweb-service.sh.in b/src/VBox/Installer/linux/vboxweb-service.sh index 173fd7a9..4d6d4dd7 100755 --- a/src/VBox/Installer/linux/vboxweb-service.sh.in +++ b/src/VBox/Installer/linux/vboxweb-service.sh @@ -26,25 +26,23 @@ ### END INIT INFO PATH=$PATH:/bin:/sbin:/usr/sbin -DEBIAN=%DEBIAN% -NOLSB=%NOLSB% -[ -f /lib/lsb/init-functions ] || NOLSB=yes +[ -f /etc/debian_release -a -f /lib/lsb/init-functions ] || NOLSB=yes [ -f /etc/vbox/vbox.cfg ] && . /etc/vbox/vbox.cfg if [ -n "$INSTALL_DIR" ]; then binary="$INSTALL_DIR/vboxwebsrv" vboxmanage="$INSTALL_DIR/VBoxManage" else - binary="/usr/lib/%PACKAGE%/vboxwebsrv" - vboxmanage="/usr/lib/%PACKAGE%/VBoxManage" + binary="/usr/lib/virtualbox/vboxwebsrv" + vboxmanage="/usr/lib/virtualbox/VBoxManage" fi # silently exit if the package was uninstalled but not purged, -# applies to Debian packages only -[ -z "$DEBIAN" -o -x $binary ] || exit 0 +# applies to Debian packages only (but shouldn't hurt elsewhere) +[ ! -f /etc/debian_release -o -x $binary ] || exit 0 -[ -r /etc/default/%PACKAGE% ] && . /etc/default/%PACKAGE% +[ -r /etc/default/virtualbox ] && . /etc/default/virtualbox system=unknown if [ -f /etc/redhat-release ]; then diff --git a/src/VBox/Installer/solaris/Makefile.kmk b/src/VBox/Installer/solaris/Makefile.kmk index a94d1bb4..11a3519e 100644 --- a/src/VBox/Installer/solaris/Makefile.kmk +++ b/src/VBox/Installer/solaris/Makefile.kmk @@ -4,7 +4,7 @@ # # -# Copyright (C) 2007-2012 Oracle Corporation +# Copyright (C) 2007-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; @@ -206,10 +206,10 @@ SOLARIS_STRIP_EXES = \ VBoxZoneAccess \ $(if $(VBOX_WITH_QTGUI),VirtualBox,) \ VBoxManage \ - $(if $(VBOX_WITH_VBOXBFE),VBoxBFE,) \ $(if $(VBOX_WITH_VBOXSDL),VBoxSDL,) \ $(if $(VBOX_WITH_NETADP),VBoxNetAdpCtl,) \ VBoxNetDHCP \ + VBoxNetNAT \ $(if $(VBOX_WITH_EXTPACK),VBoxExtPackHelperApp,) \ VBoxSVC \ $(if $(VBOX_WITH_CROGL),VBoxTestOGL,) \ @@ -266,10 +266,18 @@ SOLARIS_STRIP_BINS = \ components/VBoxC.so \ components/VBoxSVCM.so \ components/VBoxXPCOMIPCC.so +ifdef VBOX_WITH_32_ON_64_MAIN_API + SOLARIS_STRIP_BINS += \ + VBoxRT-x86.so \ + VBoxXPCOM-x86.so \ + components/VBoxClient-x86.so \ + components/VBoxSVCM-x86.so \ + components/VBoxXPCOMIPCC-x86.so +endif ifdef VBOX_WITH_HARDENING -SOLARIS_STRIP_BINS += \ + SOLARIS_STRIP_BINS += \ VBoxNetDHCP.so \ - $(if $(VBOX_WITH_VBOXBFE),VBoxBFE.so,) \ + VBoxNetNAT.so \ $(if $(VBOX_WITH_VBOXSDL),VBoxSDL.so,) \ $(if $(VBOX_WITH_QTGUI),VirtualBox.so,) endif @@ -472,7 +480,8 @@ else $(ifeq ($(KBUILD_TARGET_ARCH),amd64),$(addprefix $(SOLARIS_VBOXINST_DIR_ISA)/,$(SOLARIS_STRIP_OBJ_64)),) \ $(addprefix $(SOLARIS_VBOXINST_DIR_ISA)/,$(SOLARIS_STRIP_OBJS)) \ $(addprefix $(SOLARIS_VBOXINST_DIR_ISA)/,$(SOLARIS_NO_STRIP)) \ - $(addprefix $(SOLARIS_VBOXINST_DIR_ISA)/,$(SOLARIS_QTLIBS)) + $(addprefix $(SOLARIS_VBOXINST_DIR_ISA)/,$(SOLARIS_QTLIBS)) \ + $(wildcard $(addprefix $(SOLARIS_OUT_BIN)/,VBoxPython*.so)) SOLARIS_DBG_DEPFILES = $(addprefix $(SOLARIS_DBG_DIR_ISA)/,$(SOLARIS_DBG_FILES)) endif SOLARIS_ARCH_DEPFILES += $(addprefix $(SOLARIS_VBOXINST_DIR)/,$(SOLARIS_COMMON)) \ @@ -529,6 +538,10 @@ include $(FILE_KBUILD_SUB_FOOTER) # # -=-=-=-=-=-=-=- Main package -=-=-=-=-=-=-=- # +# !!WARNING!! The current packing may NOT produce the expected rules in +# !!WARNING!! incremental build! Removed and renamed components may +# !!WARNING!! appear in the package! Always do clean builds for customers. +# ## @todo r=bird: makepackage.sh packing a directory tree, right? So, there is no guarantee that it's not # containing any obsolete files the way packing is performed here. Consider recursively @@ -613,7 +626,12 @@ else @# @todo -XXX- how to get rid of this manual MKDIR ? ifdef VBOX_WITH_PYTHON $(QUIET)$(if $(SOL64_PKG),$(MKDIR) -p $(SOLARIS_VBOXINST_DIR)/$(VBOX_SOL_PYTHON_DIR_64),) + ifdef VBOX_WITH_32_ON_64_MAIN_API + $(QUIET)$(INSTALL) -m 0644 $(if $(VBOX_DO_STRIP),-s) $(filter %_x86.so,$(wildcard $(SOLARIS_OUT_BIN)/VBoxPython*.so)) $(SOLARIS_VBOXINST_DIR)/ + $(QUIET)$(INSTALL) -m 0644 $(if $(VBOX_DO_STRIP),-s) $(filter-out %_x86.so,$(wildcard $(SOLARIS_OUT_BIN)/VBoxPython*.so)) $(SOLARIS_VBOXINST_DIR)/$(VBOX_SOL_PYTHON_DIR_64)/ + else $(QUIET)$(INSTALL) -m 0644 $(if $(VBOX_DO_STRIP),-s) $(wildcard $(SOLARIS_OUT_BIN)/VBoxPython*.so) $(SOLARIS_VBOXINST_DIR)/$(if $(SOL64_PKG),$(VBOX_SOL_PYTHON_DIR_64)/,) + endif endif $(QUIET)$(if $(VBOX_WITH_QTGUI),$(if $(VBOX_WITH_QT4_SUN),$(INSTALL) -m 0755 $(VBOX_PATH_QT4)/bin/qtconfig $(SOLARIS_VBOXINST_DIR_ISA)/VBoxQtconfig,),) $(QUIET)$(INSTALL) -m 0755 $(SOLARIS_OUT_BIN)/VBoxISAExec $(SOLARIS_VBOXINST_DIR)/VBoxISAExec @@ -688,7 +706,7 @@ endif @# Clean up files emitted as side-effect or result of packing $(QUIET)$(RM) -f $(SOLARIS_BASEINST_DIR)/$(PKG_FILENAME).tar.gz $(QUIET)$(RM) -f $(SOLARIS_BASEINST_DIR)/$(PKG_FILENAME).pkg - $(call MSG_L1,Packaging completed.) + $(call MSG_L1,Packaging $@ is completed.) # @@ -783,8 +801,7 @@ $(addprefix $(SOLARIS_USRSHR_ICONS_DIR)/,$(SOLARIS_COMMON_ICONS)): \ # Some symlinks are created manually in the prepackage steps above (eg. VBoxQtconfig) # as those binaries do not originate from $(PATH_STAGE_BIN) # -$(addprefix $(SOLARIS_USRBIN_DIR)/,$(SOLARIS_USRBIN_LINKS)): \ - $(SOLARIS_USRBIN_DIR)/% : % | $$(dir $$@) +$(addprefix $(SOLARIS_USRBIN_DIR)/,$(SOLARIS_USRBIN_LINKS)): | $$(dir $$@) $(LN_SYMLINK) -f ../../$(SOLARIS_VBOXINST_SUBDIR)/VBox.sh $@ @@ -798,9 +815,10 @@ $(PATH_STAGE_BIN)/$(DBG_ARCHIVE): \ $(SOLARIS_DBG_DEPFILES) $(call MSG_L1,Installing debug binaries $(SOLARIS_DBG_DIR)) $(call MSG_L1,Packing $@) - $(QUIET)/usr/sfw/bin/gtar --dereference --owner 0 --group 0 \ + $(QUIET)$(SOL_GTAR) --dereference --owner 0 --group 0 \ -cjRhf "$(PATH_STAGE_BIN)/$(DBG_ARCHIVE)" -C "$(SOLARIS_INST_OUT_DIR)" "$(SOLARIS_DBG_DIR_NAME)" $(QUIET)$(CHMOD) 0644 $@ + $(call MSG_L1,Packaging $@ is completed.) # # 32-bit Debug package diff --git a/src/VBox/Installer/solaris/VBox.sh b/src/VBox/Installer/solaris/VBox.sh index 50a68260..c8f3584a 100755 --- a/src/VBox/Installer/solaris/VBox.sh +++ b/src/VBox/Installer/solaris/VBox.sh @@ -2,7 +2,7 @@ # # Oracle VM VirtualBox startup script, Solaris hosts. # -# Copyright (C) 2006-2011 Oracle Corporation +# Copyright (C) 2006-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -43,9 +43,6 @@ case "$APP" in vboxwebsrv) exec "$INSTALL_DIR/vboxwebsrv" "$@" ;; - VBoxBFE|vboxbfe) - exec "$INSTALL_DIR/VBoxBFE" "$@" - ;; VBoxQtconfig) exec "$INSTALL_DIR/VBoxQtconfig" "$@" ;; diff --git a/src/VBox/Installer/solaris/VBoxISAExec.c b/src/VBox/Installer/solaris/VBoxISAExec.c index 97f8ad9f..ed33f198 100644 --- a/src/VBox/Installer/solaris/VBoxISAExec.c +++ b/src/VBox/Installer/solaris/VBoxISAExec.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/solaris/VBoxZoneAccess.c b/src/VBox/Installer/solaris/VBoxZoneAccess.c index a77f32cb..5ec8c309 100644 --- a/src/VBox/Installer/solaris/VBoxZoneAccess.c +++ b/src/VBox/Installer/solaris/VBoxZoneAccess.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -26,11 +26,16 @@ #include <iprt/process.h> -#define DEVICE_NAME "/dev/vboxdrv" +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +#define DEVICE_NAME "/devices/pseudo/vboxdrv@0:vboxdrv" +#define DEVICE_NAME_USR "/devices/pseudo/vboxdrv@0:vboxdrvu" int main(int argc, char *argv[]) { int hDevice = -1; + int hDeviceUsr = -1; /* Check root permissions. */ if (geteuid() != 0) @@ -52,11 +57,22 @@ int main(int argc, char *argv[]) return errno; } + /* Open the user device. */ + hDeviceUsr = open(DEVICE_NAME_USR, O_RDWR, 0); + if (hDeviceUsr < 0) + { + fprintf(stderr, "Failed to open '%s'. errno=%d\n", DEVICE_NAME_USR, errno); + close(hDevice); + return errno; + } + /* Mark the file handle close on exec. */ - if (fcntl(hDevice, F_SETFD, FD_CLOEXEC) != 0) + if ( fcntl(hDevice, F_SETFD, FD_CLOEXEC) != 0 + || fcntl(hDeviceUsr, F_SETFD, FD_CLOEXEC) != 0) { fprintf(stderr, "Failed to set close on exec. errno=%d\n", errno); close(hDevice); + close(hDeviceUsr); return errno; } @@ -65,6 +81,7 @@ int main(int argc, char *argv[]) sleep(500000000U); close(hDevice); + close(hDeviceUsr); return 0; } diff --git a/src/VBox/Installer/solaris/checkinstall.sh b/src/VBox/Installer/solaris/checkinstall.sh index 92c186ce..8dec8036 100755 --- a/src/VBox/Installer/solaris/checkinstall.sh +++ b/src/VBox/Installer/solaris/checkinstall.sh @@ -5,7 +5,7 @@ # # -# Copyright (C) 2009-2010 Oracle Corporation +# Copyright (C) 2009-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -162,6 +162,13 @@ if test ! -z "$VBOXNETDHCP_PID" && test "$VBOXNETDHCP_PID" -ge 0; then abort_error fi +# Check if VBoxNetNAT is currently running +VBOXNETNAT_PID=`ps -eo pid,fname | grep VBoxNetNAT | grep -v grep | awk '{ print $1 }'` +if test ! -z "$VBOXNETNAT_PID" && test "$VBOXNETNAT_PID" -ge 0; then + errorprint "VirtualBox's VBoxNetNAT (pid $VBOXNETNAT_PID) still appears to be running." + abort_error +fi + # Check if vboxnet is still plumbed, if so try unplumb it BIN_IFCONFIG=`which ifconfig 2> /dev/null` if test -x "$BIN_IFCONFIG"; then @@ -187,5 +194,22 @@ if test -x "$BIN_IFCONFIG"; then fi fi +# If we are using SVR4 packages then make sure that SMF has finished +# disabling any services left over from a previous installation which +# may interfere with installing new ones. Should only be relevant on +# Solaris 11. +if test -x "$BIN_PKGINFO"; then + for i in 1 2 3 4 5 6 7 8 9 10; do + svcs -a | grep virtualbox >/dev/null || break + if test "${i}" = "1"; then + printf "Waiting for services from previous installation to be removed." + else + printf "." + fi + sleep 1 + done + test "${i}" = "1" || printf "\n" +fi + exit 0 diff --git a/src/VBox/Installer/solaris/makepackage.sh b/src/VBox/Installer/solaris/makepackage.sh index 439923d1..1a82f18a 100755 --- a/src/VBox/Installer/solaris/makepackage.sh +++ b/src/VBox/Installer/solaris/makepackage.sh @@ -1,11 +1,11 @@ #!/bin/sh +# $Id: makepackage.sh $ ## @file -# # VirtualBox package creation script, Solaris hosts. # # -# Copyright (C) 2007-2011 Oracle Corporation +# Copyright (C) 2007-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -117,6 +117,7 @@ ln -f ./VBoxISAExec $VBOX_INSTALLED_DIR/VBoxAutostart ln -f ./VBoxISAExec $VBOX_INSTALLED_DIR/vboxwebsrv ln -f ./VBoxISAExec $VBOX_INSTALLED_DIR/webtest ln -f ./VBoxISAExec $VBOX_INSTALLED_DIR/VBoxZoneAccess +ln -f ./VBoxISAExec $VBOX_INSTALLED_DIR/VBoxSVC if test -f $VBOX_INSTALLED_DIR/amd64/VBoxTestOGL || test -f $VBOX_INSTALLED_DIR/i386/VBoxTestOGL; then ln -f ./VBoxISAExec $VBOX_INSTALLED_DIR/VBoxTestOGL fi @@ -124,9 +125,6 @@ fi if test -f $VBOX_INSTALLED_DIR/amd64/VirtualBox || test -f $VBOX_INSTALLED_DIR/i386/VirtualBox; then ln -f ./VBoxISAExec $VBOX_INSTALLED_DIR/VirtualBox fi -if test -f $VBOX_INSTALLED_DIR/amd64/VBoxBFE || test -f $VBOX_INSTALLED_DIR/i386/VBoxBFE; then - ln -f ./VBoxISAExec $VBOX_INSTALLED_DIR/VBoxBFE -fi if test -f $VBOX_INSTALLED_DIR/amd64/VBoxHeadless || test -f $VBOX_INSTALLED_DIR/i386/VBoxHeadless; then ln -f ./VBoxISAExec $VBOX_INSTALLED_DIR/VBoxHeadless ln -fs ./VBoxHeadless $VBOX_INSTALLED_DIR/VBoxVRDP @@ -192,12 +190,10 @@ if test -n "$HARDENED"; then || $3 == "opt/VirtualBox/amd64/VirtualBox3" \ || $3 == "opt/VirtualBox/amd64/VBoxHeadless" \ || $3 == "opt/VirtualBox/amd64/VBoxSDL" \ - || $3 == "opt/VirtualBox/amd64/VBoxBFE" \ || $3 == "opt/VirtualBox/i386/VirtualBox" \ || $3 == "opt/VirtualBox/i386/VirtualBox3" \ || $3 == "opt/VirtualBox/i386/VBoxHeadless" \ || $3 == "opt/VirtualBox/i386/VBoxSDL" \ - || $3 == "opt/VirtualBox/i386/VBoxBFE" \ ) \ { $4 = "4755" } { print }' prototype > prototype2 mv -f prototype2 prototype @@ -209,6 +205,8 @@ $VBOX_AWK 'NF == 6 \ || $3 == "opt/VirtualBox/i386/VBoxNetAdpCtl" \ || $3 == "opt/VirtualBox/amd64/VBoxNetDHCP" \ || $3 == "opt/VirtualBox/i386/VBoxNetDHCP" \ + || $3 == "opt/VirtualBox/amd64/VBoxNetNAT" \ + || $3 == "opt/VirtualBox/i386/VBoxNetNAT" \ ) \ { $4 = "4755" } { print }' prototype > prototype2 mv -f prototype2 prototype diff --git a/src/VBox/Installer/solaris/pkginstall.sh b/src/VBox/Installer/solaris/pkginstall.sh index 49aea0cf..79b0d7c8 100755 --- a/src/VBox/Installer/solaris/pkginstall.sh +++ b/src/VBox/Installer/solaris/pkginstall.sh @@ -1,4 +1,5 @@ #!/bin/sh +# $Id: pkginstall.sh $ ## @file # # VirtualBox postinstall script for Solaris. @@ -8,7 +9,7 @@ # # -# Copyright (C) 2009-2010 Oracle Corporation +# Copyright (C) 2009-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -29,12 +30,18 @@ else ISIPS="" fi +# pkgadd -v +if test "$1" = "--sh-trace" || test "$2" = "--sh-trace" || test "$3" = "--sh-trace"; then + set -x +fi +DEBUGOPT=`set -o 2>/dev/null | sed -ne 's/^xtrace *on$/--sh-trace/p'` # propagate pkgadd -v + # If PKG_INSTALL_ROOT is undefined or NULL, redefine to '/' and carry on. -${PKG_INSTALL_ROOT:=/}/opt/VirtualBox/vboxconfig.sh --preremove --fatal "$ISIPS" +${PKG_INSTALL_ROOT:=/}/opt/VirtualBox/vboxconfig.sh --preremove --fatal ${ISIPS} ${DEBUGOPT} if test "$?" -eq 0; then echo "Installing new ones..." - $PKG_INSTALL_ROOT/opt/VirtualBox/vboxconfig.sh --postinstall + $PKG_INSTALL_ROOT/opt/VirtualBox/vboxconfig.sh --postinstall ${DEBUGOPT} rc=$? if test "$rc" -ne 0; then echo 1>&2 "## Completed but with errors." diff --git a/src/VBox/Installer/solaris/postinstall.sh b/src/VBox/Installer/solaris/postinstall.sh index 1dbfa2bd..6264ac61 100755 --- a/src/VBox/Installer/solaris/postinstall.sh +++ b/src/VBox/Installer/solaris/postinstall.sh @@ -1,11 +1,11 @@ #!/bin/sh +# $Id: postinstall.sh $ ## @file -# # VirtualBox postinstall script for Solaris. # # -# Copyright (C) 2007-2010 Oracle Corporation +# Copyright (C) 2007-2012 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -19,7 +19,8 @@ rc=0 currentzone=`zonename` if test "$currentzone" = "global"; then - ${PKG_INSTALL_ROOT:=/}/opt/VirtualBox/pkginstall.sh --srv4 + DEBUGOPT=`set -o 2>/dev/null | sed -ne 's/^xtrace *on$/--sh-trace/p'` # propagate pkgadd -v + ${PKG_INSTALL_ROOT:=/}/opt/VirtualBox/pkginstall.sh --srv4 ${DEBUGOPT} rc=$? fi diff --git a/src/VBox/Installer/solaris/preremove.sh b/src/VBox/Installer/solaris/preremove.sh index a0ab4b52..388980f9 100755 --- a/src/VBox/Installer/solaris/preremove.sh +++ b/src/VBox/Installer/solaris/preremove.sh @@ -1,8 +1,13 @@ #!/bin/sh +# $Id: preremove.sh $ +## @file +# VirtualBox preremove script for Solaris. +# + # # VirtualBox preremove script for Solaris. # -# Copyright (C) 2007-2010 Oracle Corporation +# Copyright (C) 2007-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; diff --git a/src/VBox/Installer/solaris/smf-vboxautostart.sh b/src/VBox/Installer/solaris/smf-vboxautostart.sh index 5a9314fa..6e0332b0 100755 --- a/src/VBox/Installer/solaris/smf-vboxautostart.sh +++ b/src/VBox/Installer/solaris/smf-vboxautostart.sh @@ -1,7 +1,7 @@ #!/sbin/sh # $Id: smf-vboxautostart.sh $ -# Copyright (C) 2012 Oracle Corporation +# Copyright (C) 2012-2014 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; @@ -24,13 +24,13 @@ VW_EXIT=0 case $VW_OPT in start) - if [ ! -x /opt/VirtualBox/VBoxAutostart ]; then + if [ ! -f /opt/VirtualBox/VBoxAutostart ]; then echo "ERROR: /opt/VirtualBox/VBoxAutostart does not exist." return $SMF_EXIT_ERR_CONFIG fi - if [ ! -f /opt/VirtualBox/VBoxAutostart ]; then - echo "ERROR: /opt/VirtualBox/VBoxAutostart does not exist." + if [ ! -x /opt/VirtualBox/VBoxAutostart ]; then + echo "ERROR: /opt/VirtualBox/VBoxAutostart is not exectuable." return $SMF_EXIT_ERR_CONFIG fi @@ -43,17 +43,20 @@ case $VW_OPT in [ $? != 0 ] && VW_LOGSIZE= VW_LOGINTERVAL=`/usr/bin/svcprop -p config/loginterval $SMF_FMRI 2>/dev/null` [ $? != 0 ] && VW_LOGINTERVAL= + VW_VBOXGROUP=`/usr/bin/svcprop -p config/vboxgroup $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VW_VBOXGROUP= # Provide sensible defaults [ -z "$VW_CONFIG" ] && VW_CONFIG=/etc/vbox/autostart.cfg [ -z "$VW_ROTATE" ] && VW_ROTATE=10 [ -z "$VW_LOGSIZE" ] && VW_LOGSIZE=104857600 [ -z "$VW_LOGINTERVAL" ] && VW_LOGINTERVAL=86400 + [ -z "$VW_VBOXGROUP" ] && VW_VBOXGROUP=staff # Get all users - for VW_USER in `logins -g staff` + for VW_USER in `logins -g $VW_VBOXGROUP | cut -d' ' -f1` do - exec su - "$VW_USER" -c "/opt/VirtualBox/VBoxAutostart --background --start --config \"$VW_CONFIG\" --logrotate \"$VW_ROTATE\" --logsize \"$VW_LOGSIZE\" --loginterval \"$VW_LOGINTERVAL\"" + su - "$VW_USER" -c "/opt/VirtualBox/VBoxAutostart --background --start --config \"$VW_CONFIG\" --logrotate \"$VW_ROTATE\" --logsize \"$VW_LOGSIZE\" --loginterval \"$VW_LOGINTERVAL\"" VW_EXIT=$? if [ $VW_EXIT != 0 ]; then @@ -64,8 +67,47 @@ case $VW_OPT in done ;; stop) - # Kill service contract - smf_kill_contract $2 TERM 1 + if [ ! -f /opt/VirtualBox/VBoxAutostart ]; then + echo "ERROR: /opt/VirtualBox/VBoxAutostart does not exist." + return $SMF_EXIT_ERR_CONFIG + fi + + if [ ! -x /opt/VirtualBox/VBoxAutostart ]; then + echo "ERROR: /opt/VirtualBox/VBoxAutostart is not executable." + return $SMF_EXIT_ERR_CONFIG + fi + + # Get svc configuration + VW_CONFIG=`/usr/bin/svcprop -p config/config $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VW_CONFIG= + VW_ROTATE=`/usr/bin/svcprop -p config/logrotate $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VW_ROTATE= + VW_LOGSIZE=`/usr/bin/svcprop -p config/logsize $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VW_LOGSIZE= + VW_LOGINTERVAL=`/usr/bin/svcprop -p config/loginterval $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VW_LOGINTERVAL= + VW_VBOXGROUP=`/usr/bin/svcprop -p config/vboxgroup $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VW_VBOXGROUP= + + # Provide sensible defaults + [ -z "$VW_CONFIG" ] && VW_CONFIG=/etc/vbox/autostart.cfg + [ -z "$VW_ROTATE" ] && VW_ROTATE=10 + [ -z "$VW_LOGSIZE" ] && VW_LOGSIZE=104857600 + [ -z "$VW_LOGINTERVAL" ] && VW_LOGINTERVAL=86400 + [ -z "$VW_VBOXGROUP" ] && VW_VBOXGROUP=staff + + # Get all users + for VW_USER in `logins -g $VW_VBOXGROUP | cut -d' ' -f1` + do + su - "$VW_USER" -c "/opt/VirtualBox/VBoxAutostart --stop --config \"$VW_CONFIG\" --logrotate \"$VW_ROTATE\" --logsize \"$VW_LOGSIZE\" --loginterval \"$VW_LOGINTERVAL\"" + + VW_EXIT=$? + if [ $VW_EXIT != 0 ]; then + echo "VBoxAutostart failed with $VW_EXIT." + VW_EXIT=1 + break + fi + done ;; *) VW_EXIT=$SMF_EXIT_ERR_CONFIG diff --git a/src/VBox/Installer/solaris/smf-vboxballoonctrl.sh b/src/VBox/Installer/solaris/smf-vboxballoonctrl.sh index a01b4681..d27124cf 100755 --- a/src/VBox/Installer/solaris/smf-vboxballoonctrl.sh +++ b/src/VBox/Installer/solaris/smf-vboxballoonctrl.sh @@ -1,7 +1,7 @@ #!/sbin/sh # $Id: smf-vboxballoonctrl.sh $ -# Copyright (C) 2008-2012 Oracle Corporation +# Copyright (C) 2008-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; @@ -35,33 +35,62 @@ case $VW_OPT in fi # Get svc configuration - VW_USER=`/usr/bin/svcprop -p config/user $SMF_FMRI 2>/dev/null` - [ $? != 0 ] && VW_USER= - VW_INTERVAL=`/usr/bin/svcprop -p config/interval $SMF_FMRI 2>/dev/null` - [ $? != 0 ] && VW_INTERVAL= - VW_INCREMENT=`/usr/bin/svcprop -p config/increment $SMF_FMRI 2>/dev/null` - [ $? != 0 ] && VW_INCREMENT= - VW_DECREMENT=`/usr/bin/svcprop -p config/decrement $SMF_FMRI 2>/dev/null` - [ $? != 0 ] && VW_DECREMENT= - VW_LOWERLIMIT=`/usr/bin/svcprop -p config/lowerlimit $SMF_FMRI 2>/dev/null` - [ $? != 0 ] && VW_LOWERLIMIT= - VW_ROTATE=`/usr/bin/svcprop -p config/logrotate $SMF_FMRI 2>/dev/null` - [ $? != 0 ] && VW_ROTATE= - VW_LOGSIZE=`/usr/bin/svcprop -p config/logsize $SMF_FMRI 2>/dev/null` - [ $? != 0 ] && VW_LOGSIZE= - VW_LOGINTERVAL=`/usr/bin/svcprop -p config/loginterval $SMF_FMRI 2>/dev/null` - [ $? != 0 ] && VW_LOGINTERVAL= + VBOXWATCHDOG_USER=`/usr/bin/svcprop -p config/user $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_USER= + VBOXWATCHDOG_BALLOON_INTERVAL=`/usr/bin/svcprop -p config/balloon_interval $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_BALLOON_INTERVAL= + VBOXWATCHDOG_BALLOON_INCREMENT=`/usr/bin/svcprop -p config/balloon_increment $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_BALLOON_INCREMENT= + VBOXWATCHDOG_BALLOON_DECREMENT=`/usr/bin/svcprop -p config/balloon_decrement $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_BALLOON_DECREMENT= + VBOXWATCHDOG_BALLOON_LOWERLIMIT=`/usr/bin/svcprop -p config/balloon_lowerlimit $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_BALLOON_LOWERLIMIT= + VBOXWATCHDOG_BALLOON_SAFETYMARGIN=`/usr/bin/svcprop -p config/balloon_safetymargin $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_BALLOON_SAFETYMARGIN= + VBOXWATCHDOG_ROTATE=`/usr/bin/svcprop -p config/logrotate $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_ROTATE= + VBOXWATCHDOG_LOGSIZE=`/usr/bin/svcprop -p config/logsize $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_LOGSIZE= + VBOXWATCHDOG_LOGINTERVAL=`/usr/bin/svcprop -p config/loginterval $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_LOGINTERVAL= + + # Handle legacy parameters, do not add any further ones unless absolutely necessary. + if [ -z "$VBOXWATCHDOG_BALLOON_INTERVAL" ]; then + VBOXWATCHDOG_BALLOON_INTERVAL=`/usr/bin/svcprop -p config/interval $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_BALLOON_INTERVAL= + fi + if [ -z "$VBOXWATCHDOG_BALLOON_INCREMENT" ]; then + VBOXWATCHDOG_BALLOON_INCREMENT=`/usr/bin/svcprop -p config/increment $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_BALLOON_INCREMENT= + fi + if [ -z "$VBOXWATCHDOG_BALLOON_DECREMENT" ]; then + VBOXWATCHDOG_BALLOON_DECREMENT=`/usr/bin/svcprop -p config/decrement $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_BALLOON_DECREMENT= + fi + if [ -z "$VBOXWATCHDOG_BALLOON_LOWERLIMIT" ]; then + VBOXWATCHDOG_BALLOON_LOWERLIMIT=`/usr/bin/svcprop -p config/lowerlimit $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_BALLOON_LOWERLIMIT= + fi + if [ -z "$VBOXWATCHDOG_BALLOON_SAFETYMARGIN" ]; then + VBOXWATCHDOG_BALLOON_SAFETYMARGIN=`/usr/bin/svcprop -p config/safetymargin $SMF_FMRI 2>/dev/null` + [ $? != 0 ] && VBOXWATCHDOG_BALLOON_SAFETYMARGIN= + fi # Provide sensible defaults - [ -z "$VW_USER" ] && VW_USER=root - [ -z "$VW_INTERVAL" ] && VW_INTERVAL=10000 - [ -z "$VW_INCREMENT" ] && VW_INCREMENT=256 - [ -z "$VW_DECREMENT" ] && VW_DECREMENT=128 - [ -z "$VW_LOWERLIMIT" ] && VW_LOWERLIMIT=64 - [ -z "$VW_ROTATE" ] && VW_ROTATE=10 - [ -z "$VW_LOGSIZE" ] && VW_LOGSIZE=104857600 - [ -z "$VW_LOGINTERVAL" ] && VW_LOGINTERVAL=86400 - exec su - "$VW_USER" -c "/opt/VirtualBox/VBoxBalloonCtrl --background --balloon-interval \"$VW_INTERVAL\" --balloon-inc \"$VW_INCREMENT\" --balloon-dec \"$VW_DECREMENT\" --balloon-lower-limit \"$VW_LOWERLIMIT\" --logrotate \"$VW_ROTATE\" --logsize \"$VW_LOGSIZE\" --loginterval \"$VW_LOGINTERVAL\"" + [ -z "$VBOXWATCHDOG_USER" ] && VBOXWATCHDOG_USER=root + + # Assemble the parameter list + PARAMS="--background" + [ -n "$VBOXWATCHDOG_BALLOON_INTERVAL" ] && PARAMS="$PARAMS --balloon-interval \"$VBOXWATCHDOG_BALLOON_INTERVAL\"" + [ -n "$VBOXWATCHDOG_BALLOON_INCREMENT" ] && PARAMS="$PARAMS --balloon-inc \"$VBOXWATCHDOG_BALLOON_INCREMENT\"" + [ -n "$VBOXWATCHDOG_BALLOON_DECREMENT" ] && PARAMS="$PARAMS --balloon-dec \"$VBOXWATCHDOG_BALLOON_DECREMENT\"" + [ -n "$VBOXWATCHDOG_BALLOON_LOWERLIMIT" ] && PARAMS="$PARAMS --balloon-lower-limit \"$VBOXWATCHDOG_BALLOON_LOWERLIMIT\"" + [ -n "$VBOXWATCHDOG_BALLOON_SAFETYMARGIN" ] && PARAMS="$PARAMS --balloon-safety-margin \"$VBOXWATCHDOG_BALLOON_SAFETYMARGIN\"" + [ -n "$VBOXWATCHDOG_ROTATE" ] && PARAMS="$PARAMS -R \"$VBOXWATCHDOG_ROTATE\"" + [ -n "$VBOXWATCHDOG_LOGSIZE" ] && PARAMS="$PARAMS -S \"$VBOXWATCHDOG_LOGSIZE\"" + [ -n "$VBOXWATCHDOG_LOGINTERVAL" ] && PARAMS="$PARAMS -I \"$VBOXWATCHDOG_LOGINTERVAL\"" + + exec su - "$VBOXWATCHDOG_USER" -c "/opt/VirtualBox/VBoxBalloonCtrl $PARAMS" VW_EXIT=$? if [ $VW_EXIT != 0 ]; then diff --git a/src/VBox/Installer/solaris/vboxconfig.sh b/src/VBox/Installer/solaris/vboxconfig.sh index f06823ae..85448d80 100755 --- a/src/VBox/Installer/solaris/vboxconfig.sh +++ b/src/VBox/Installer/solaris/vboxconfig.sh @@ -1,10 +1,11 @@ #!/bin/sh # $Id: vboxconfig.sh $ - -# +## @file # VirtualBox Configuration Script, Solaris host. # -# Copyright (C) 2009-2010 Oracle Corporation + +# +# 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; @@ -40,7 +41,7 @@ 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_SVCS=/usr/bin/svcs BIN_IFCONFIG=/sbin/ifconfig BIN_SVCS=/usr/bin/svcs BIN_ID=/usr/bin/id @@ -256,9 +257,10 @@ get_sysinfo() # 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 + 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 + if test "$HOST_OS_MAJORVERSION" = "5.12"; then + HOST_OS_MAJORVERSION="12" HOST_OS_MINORVERSION=`echo "$BRANCH_VERSION" | cut -f2 -d'-' | cut -f6 -d'.'` return 0 else @@ -488,7 +490,7 @@ rem_driver() fi } -# unload_module(modname, moddesc, [fatal]) +# unload_module(modname, moddesc, retry, [fatal]) # failure: fatal unload_module() { @@ -504,16 +506,42 @@ unload_module() modname=$1 moddesc=$2 - fatal=$3 + 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 - subprint "Unloading: $moddesc module ...FAILED!" - if test "$fatal" = "$FATALOP"; then - exit 1 + # + # 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 @@ -580,9 +608,9 @@ 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'" + 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'" + 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 @@ -590,20 +618,21 @@ install_drivers() return 1 fi - # Add vboxdrv to devlink.tab + ## Add vboxdrv to devlink.tab (KEEP TABS!) if test -f "$PKG_INSTALL_ROOT/etc/devlink.tab"; then - sed -e '/name=vboxdrv/d' "$PKG_INSTALL_ROOT/etc/devlink.tab" > "$PKG_INSTALL_ROOT/etc/devlink.vbox" - echo "type=ddi_pseudo;name=vboxdrv \D" >> "$PKG_INSTALL_ROOT/etc/devlink.vbox" + 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 + # 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"; then + 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 @@ -624,9 +653,10 @@ install_drivers() # 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 - infoprint "here" + 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 @@ -687,11 +717,11 @@ remove_drivers() { fatal=$1 - # Remove vboxdrv from devlink.tab + # Remove vboxdrv[u] 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" + sed -e '/name=vboxdrv/d' -e '/name=vboxdrvu/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 @@ -703,28 +733,31 @@ remove_drivers() fi fi - unload_module "$MOD_VBOXUSB" "$DESC_VBOXUSB" "$fatal" + unload_module "$MOD_VBOXUSB" "$DESC_VBOXUSB" 0 "$fatal" rem_driver "$MOD_VBOXUSB" "$DESC_VBOXUSB" "$fatal" - unload_module "$MOD_VBOXUSBMON" "$DESC_VBOXUSBMON" "$fatal" + unload_module "$MOD_VBOXUSBMON" "$DESC_VBOXUSBMON" 0 "$fatal" rem_driver "$MOD_VBOXUSBMON" "$DESC_VBOXUSBMON" "$fatal" - unload_module "$MOD_VBOXFLT" "$DESC_VBOXFLT" "$fatal" + unload_module "$MOD_VBOXFLT" "$DESC_VBOXFLT" 0 "$fatal" rem_driver "$MOD_VBOXFLT" "$DESC_VBOXFLT" "$fatal" - unload_module "$MOD_VBOXBOW" "$DESC_VBOXBOW" "$fatal" + unload_module "$MOD_VBOXBOW" "$DESC_VBOXBOW" 0 "$fatal" rem_driver "$MOD_VBOXBOW" "$DESC_VBOXBOW" "$fatal" - unload_module "$MOD_VBOXNET" "$DESC_VBOXNET" "$fatal" + unload_module "$MOD_VBOXNET" "$DESC_VBOXNET" 0 "$fatal" rem_driver "$MOD_VBOXNET" "$DESC_VBOXNET" "$fatal" - unload_module "$MOD_VBOXDRV" "$DESC_VBOXDRV" "$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 @@ -774,6 +807,13 @@ install_python_bindings() 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 @@ -786,6 +826,24 @@ install_python_bindings() 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() @@ -795,6 +853,7 @@ 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 @@ -864,7 +923,7 @@ stop_service() errorprint "missing argument to stop_service()" exit 1 fi - servicefound=`$BIN_SVCS -a | grep "$2" 2>/dev/null` + 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 @@ -925,8 +984,40 @@ cleanup_install() done # Stop our other daemons, non-fatal - stop_process VBoxSVC - stop_process VBoxNetDHCP + 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 } @@ -991,13 +1082,13 @@ postinstall() 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 + # 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 + fi echo "#VirtualBox_SectionStart" >> $nmaskbackupfile inst=0 @@ -1039,10 +1130,14 @@ postinstall() if test "$REMOTEINST" -eq 1; then subprint "Skipped for targetted installs." else - # Start ZoneAccess service, other services are disabled by default. + # 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" + "/var/svc/log/application-virtualbox-zoneaccess:default.log" fi fi @@ -1073,7 +1168,7 @@ postinstall() INSTALLEDIT=0 fi PYTHONBIN=`which python2.5 2>/dev/null` - install_python_bindings "$PYTHONBIN" "Python 2.5" + install_python_bindings "$PYTHONBIN" "Python 2.5" if test "$?" -eq 0; then INSTALLEDIT=0 fi @@ -1099,7 +1194,7 @@ postinstall() fi update_boot_archive - + return 0 else errorprint "Failed to install drivers" @@ -1157,12 +1252,17 @@ do # Use alternate kernel driver config folder (dev only) DIR_CONF="/usr/kernel/drv" ;; + --sh-trace) # forwarded pkgadd -v + set -x + ;; --help) printusage exit 1 ;; *) - break + # Take a hard line on invalid options. + errorprint "Invalid command line option: \"$1\"" + exit 1; ;; esac shift diff --git a/src/VBox/Installer/solaris/virtualbox-autostart.xml b/src/VBox/Installer/solaris/virtualbox-autostart.xml index ed079394..e523b9f2 100644 --- a/src/VBox/Installer/solaris/virtualbox-autostart.xml +++ b/src/VBox/Installer/solaris/virtualbox-autostart.xml @@ -33,6 +33,14 @@ </dependency> <dependency + name='fs-autofs' + grouping='optional_all' + restart_on='none' + type='service'> + <service_fmri value='svc:/system/filesystem/autofs' /> + </dependency> + + <dependency name='network-service' grouping='require_all' restart_on='none' @@ -70,8 +78,8 @@ <exec_method type='method' name='stop' - exec=':kill' - timeout_seconds='15'> + exec='/opt/VirtualBox/smf-vboxautostart.sh %m' + timeout_seconds='0'> <method_context> <method_credential user='root' group='root' /> </method_context> @@ -85,6 +93,7 @@ <property_group name='config' type='application'> <propval name='config' type='astring' value='/etc/vbox/autostart.cfg' /> + <propval name='vboxgroup' type='astring' value='staff' /> </property_group> <template> diff --git a/src/VBox/Installer/solaris/virtualbox-balloonctrl.xml b/src/VBox/Installer/solaris/virtualbox-balloonctrl.xml index 44080c1b..5150f055 100644 --- a/src/VBox/Installer/solaris/virtualbox-balloonctrl.xml +++ b/src/VBox/Installer/solaris/virtualbox-balloonctrl.xml @@ -2,9 +2,9 @@ <!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> <!-- # Solaris SMF service manifest for VirtualBox balloon control service. -# $Id$ +# $Id: virtualbox-balloonctrl.xml $ - Copyright (C) 2008-2011 Oracle Corporation + Copyright (C) 2008-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; @@ -33,6 +33,14 @@ </dependency> <dependency + name='fs-autofs' + grouping='optional_all' + restart_on='none' + type='service'> + <service_fmri value='svc:/system/filesystem/autofs' /> + </dependency> + + <dependency name='network-service' grouping='require_all' restart_on='none' diff --git a/src/VBox/Installer/solaris/virtualbox-webservice.xml b/src/VBox/Installer/solaris/virtualbox-webservice.xml index 6f7ac8f0..50af4f9d 100644 --- a/src/VBox/Installer/solaris/virtualbox-webservice.xml +++ b/src/VBox/Installer/solaris/virtualbox-webservice.xml @@ -33,6 +33,14 @@ </dependency> <dependency + name='fs-autofs' + grouping='optional_all' + restart_on='none' + type='service'> + <service_fmri value='svc:/system/filesystem/autofs' /> + </dependency> + + <dependency name='network-service' grouping='require_all' restart_on='none' diff --git a/src/VBox/Installer/solaris/virtualbox-zoneaccess.xml b/src/VBox/Installer/solaris/virtualbox-zoneaccess.xml index 3efc6a2b..9ca61223 100644 --- a/src/VBox/Installer/solaris/virtualbox-zoneaccess.xml +++ b/src/VBox/Installer/solaris/virtualbox-zoneaccess.xml @@ -3,7 +3,7 @@ # # Solaris SMF service manifest for Solaris Zone Access. # - Copyright (C) 2008-2010 Oracle Corporation + Copyright (C) 2008-2012 Oracle Corporation This file is part of VirtualBox Open Source Edition (OSE), as available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/win/Makefile.kmk b/src/VBox/Installer/win/Makefile.kmk index d2f67183..6621d1de 100644 --- a/src/VBox/Installer/win/Makefile.kmk +++ b/src/VBox/Installer/win/Makefile.kmk @@ -4,7 +4,7 @@ # # -# Copyright (C) 2006-2012 Oracle Corporation +# Copyright (C) 2006-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; @@ -48,9 +48,20 @@ include $(PATH_SUB_CURRENT)/Resources/Makefile.kmk # # Globals and targets. # -VBOX_INSTALLER_LANGUAGES = en_US +VBOX_INSTALLER_LANGUAGES = de_DE en_US fr_FR it_IT zh_TW VBOX_INSTALLER_LANGUAGES += $(VBOX_INSTALLER_ADD_LANGUAGES) +# +# We don't have the license text in another language than English yet, +# so just define the branding targets to use the English one for now. +# +$(foreach lang,$(VBOX_INSTALLER_LANGUAGES), \ + $(eval VBOX_BRAND_$(lang)_LICENSE_RTF := $(VBOX_BRAND_LICENSE_RTF)) \ + $(eval VBOX_BRAND_$(lang)_LANGUAGE_CODEPAGE := 1252)) + +# Some languages need another codepage than 1252. Override them here. +VBOX_BRAND_zh_TW_LANGUAGE_CODEPAGE := 950 + VBOX_PATH_WIN_INST_SRC := $(PATH_SUB_CURRENT) VBOX_WIN_INST_OUT_DIR := $(PATH_TARGET)/Installer/win @@ -91,7 +102,7 @@ else endif BLDDIRS += \ $(VBOX_WIN_INST_OUT_DIR) \ - $(VBOX_WIN_INST_OUT_DIR)/Languages/ + $(VBOX_WIN_INST_OUT_DIR)/NLS/ OTHER_CLEAN += \ $(VBOX_WIN_INST_OUT_DIR)/VirtualBox.wixobj \ @@ -100,9 +111,9 @@ OTHER_CLEAN += \ $(VBOX_WIN_INST_OUT_DIR)/VBoxGuiNLS.wxi \ $(VBOX_WIN_INST_OUT_DIR)/VBoxKey.wxi \ $(foreach lang,$(VBOX_INSTALLER_LANGUAGES), \ - $(VBOX_WIN_INST_OUT_DIR)/Languages/Language_$(lang).wxl \ - $(VBOX_WIN_INST_OUT_DIR)/Languages/License_$(lang).wxl \ - $(VBOX_WIN_INST_OUT_DIR)/Languages/$(lang).mst \ + $(VBOX_WIN_INST_OUT_DIR)/NLS/Language_$(lang).wxl \ + $(VBOX_WIN_INST_OUT_DIR)/NLS/License_$(lang).wxl \ + $(VBOX_WIN_INST_OUT_DIR)/NLS/$(lang).mst \ $(VBOX_WIN_INST_OUT_DIR)/VirtualBox_$(lang).wixobj \ $(VBOX_WIN_INST_OUT_DIR)/$(PACKAGE_NAME_LANG)_$(lang).msi) \ $(VBOX_WIN_INST_OUT_DIR)/Files_Doc.wxi \ @@ -163,7 +174,7 @@ VBOX_MSI_ICE_IGNORE := \ # takes place after all makefiles has been loaded and with the @ variable defined. # define def_vbox_lang_xml -$(VBOX_WIN_INST_OUT_DIR)/Languages/Language_$(lang).wxl: $(VBOX_PATH_WIN_INST_SRC)/Languages/$(lang).wxl | $$$$(dir $$$$@) +$(VBOX_WIN_INST_OUT_DIR)/NLS/Language_$(lang).wxl: $(VBOX_PATH_WIN_INST_SRC)/NLS/$(lang).wxl | $$$$(dir $$$$@) $$(call MSG_GENERATE,,$$@,$$<) $(QUIET)$(INSTALL) -m 0644 $$< $$@ endef @@ -186,12 +197,12 @@ $(foreach lang,$(VBOX_INSTALLER_LANGUAGES),$(eval $(def_vbox_lang_xml))) # between the tag and the RTF license text. # define def_vbox_license_xml -$(VBOX_WIN_INST_OUT_DIR)/Languages/License_$(lang).wxl: $(license_file) $(MAKEFILE_CURRENT) | $$$$(dir $$$$@) +$(VBOX_WIN_INST_OUT_DIR)/NLS/License_$(lang).wxl: $(license_file) $(MAKEFILE_CURRENT) | $$$$(dir $$$$@) $$(call MSG_GENERATE,,$$@,$$<) $(APPEND) -t $$@ '<?xml version="1.0" encoding="utf-8"?>' - $(APPEND) $$@ '<WixLocalization xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage="1252" Culture="$(lang)">' + $(APPEND) $$@ '<WixLocalization xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage="$(VBOX_BRAND_$(lang)_LANGUAGE_CODEPAGE)" Culture="$(lang)">' - $(REDIRECT) -a+to $$@ -- $(ECHO_EXT) -n '<String Id=\"LicenseText\">' + $(REDIRECT) -a+to $$@ -- $(ECHO_EXT) -n '<String Id="LicenseText">' $(REDIRECT) -a+to $$@ -- $(SED) -e "s|<|\<|g" -e "s|>|\>|g" $(license_file) $(APPEND) $$@ '</String>' @@ -218,22 +229,24 @@ $(VBOX_WIN_INST_OUT_DIR)/Files_Main.wxi: $(MAKEFILE_CURRENT) | $$(dir $$@) $(call MSG_GENERATE,,$@,$<) $(APPEND) -t $@ '<?xml version="1.0" ?>' $(APPEND) $@ '<Include xmlns="http://schemas.microsoft.com/wix/2006/wi">' - ifdef VBOX_WITH_DOCS_CHM - $(APPEND) $@ ' <File Id="file_VirtualBox.chm" Name="VirtualBox.chm" DiskId="$(VBOX_INSTALLER_COMMON_DISKID)" Vital="yes" Source="$(PATH_STAGE_BIN)/VirtualBox.chm"></File>' - $(APPEND) -n $@ $(foreach lang,$(VBOX_MANUAL_ADD_LANGUAGES), \ - ' <File Id="file_VirtualBox_$(lang).chm" Name="VirtualBox_$(lang).chm" DiskId="$(VBOX_INSTALLER_COMMON_DISKID)" Vital="yes" Source="$(PATH_STAGE_BIN)/VirtualBox_$(lang).chm"></File>') - endif +ifdef VBOX_WITH_DOCS_PACKING + $(APPEND) $@ ' <File Id="file_VirtualBox.chm" Name="VirtualBox.chm" DiskId="$(VBOX_INSTALLER_COMMON_DISKID)" Vital="yes" Source="$(PATH_STAGE_BIN)/VirtualBox.chm"></File>' + $(APPEND) -n $@ $(foreach lang,$(VBOX_MANUAL_ADD_LANGUAGES), \ + ' <File Id="file_VirtualBox_$(lang).chm" Name="VirtualBox_$(lang).chm" DiskId="$(VBOX_INSTALLER_COMMON_DISKID)" Vital="yes" Source="$(PATH_STAGE_BIN)/VirtualBox_$(lang).chm"></File>') +endif $(APPEND) $@ '</Include>' -$(VBOX_WIN_INST_OUT_DIR)/Files_Doc.wxi: $(MAKEFILE_CURRENT) | $$(dir $$@) +$(VBOX_WIN_INST_OUT_DIR)/Files_Doc.wxi: $(MAKEFILE_CURRENT) | $$(dir $$@) $(call MSG_GENERATE,,$@,$<) $(APPEND) -t $@ '<?xml version="1.0" ?>' $(APPEND) $@ '<Include xmlns="http://schemas.microsoft.com/wix/2006/wi">' +ifdef VBOX_WITH_DOCS_PACKING $(APPEND) $@ ' <File Id="file_UserManual.pdf" Name="UserManual.pdf" DiskId="$(VBOX_INSTALLER_COMMON_DISKID)" Vital="yes" Source="$(PATH_STAGE_BIN)/UserManual.pdf">' $(APPEND) $@ ' </File>' $(APPEND) -n $@ $(foreach lang,$(VBOX_MANUAL_ADD_LANGUAGES), \ ' <File Id="file_UserManual_$(lang).pdf" Name="UserManual_$(lang).pdf" DiskId="$(VBOX_INSTALLER_COMMON_DISKID)" Vital="yes" Source="$(PATH_STAGE_BIN)/UserManual_$(lang).pdf">' \ ' </File>') +endif $(APPEND) $@ '</Include>' $(VBOX_WIN_INST_OUT_DIR)/Files_License.wxi: $(MAKEFILE_CURRENT) | $$(dir $$@) @@ -254,13 +267,13 @@ $(VBOX_WIN_INST_OUT_DIR)/Shortcuts_StartMenu.wxi: $(MAKEFILE_CURRENT) | $$(dir $ # # Documentation (PDF/CHM) # - ifdef VBOX_WITH_DOCS_CHM +ifdef VBOX_WITH_DOCS_PACKING $(APPEND) $@ ' <Shortcut Id="sc_StartMenu_ManualCHM_en_US" Directory="dir_StartMenuVBox" Name="!(loc.StartMenu_UserManual) (CHM, English)" Description="!(loc.StartMenu_UserManual)"' \ ' Target="[INSTALLDIR]\VirtualBox.chm" WorkingDirectory="dir_Documents" Advertise="no"/>' $(APPEND) -n $@ $(foreach lang,$(VBOX_MANUAL_ADD_LANGUAGES), \ ' <Shortcut Id="sc_StartMenu_ManualCHM_$(lang)" Directory="dir_StartMenuVBox" Name="$!(loc.StartMenu_UserManual) (CHM, $(VBOX_BRAND_$(lang)_LANG_NAME))"' \ ' Description="$!(loc.StartMenu_UserManual) ($(VBOX_BRAND_$(lang)_LANG_NAME))" Target="[INSTALLDIR]\VirtualBox_$(lang).chm" WorkingDirectory="dir_Documents"/>') - endif +endif $(APPEND) $@ ' <Shortcut Id="sc_StartMenu_ManualPDF_en_US" Directory="dir_StartMenuVBox" Name="!(loc.StartMenu_UserManual) (PDF, English)" Description="!(loc.StartMenu_UserManual)"' \ ' Target="[INSTALLDIR]\doc\UserManual.pdf" WorkingDirectory="dir_Documents" Advertise="no"/>' $(APPEND) -n $@ $(foreach lang,$(VBOX_MANUAL_ADD_LANGUAGES), \ @@ -282,11 +295,14 @@ $(VBOX_WIN_INST_OUT_DIR)/Shortcuts_StartMenu.wxi: $(MAKEFILE_CURRENT) | $$(dir $ # Note: This will clean up any previous .msi to prevent dep build boxes from # filling up with old files. # +# Note: Disable parallel jobs here because of shared common.cab access issues. +# define def_vbox_link_msi +.NOTPARALLEL: $(VBOX_WIN_INST_OUT_DIR)/$(PACKAGE_NAME_LANG)_$(lang).msi $(VBOX_WIN_INST_OUT_DIR)/$(PACKAGE_NAME_LANG)_$(lang).msi: \ $(VBOX_WIN_INST_OUT_DIR)/VirtualBox_$(lang).wixobj \ - $(VBOX_WIN_INST_OUT_DIR)/Languages/Language_$(lang).wxl \ - $(VBOX_WIN_INST_OUT_DIR)/Languages/License_$(lang).wxl \ + $(VBOX_WIN_INST_OUT_DIR)/NLS/Language_$(lang).wxl \ + $(VBOX_WIN_INST_OUT_DIR)/NLS/License_$(lang).wxl \ $(PATH_STAGE_BIN)/VBoxInstallHelper.dll \ $(VBOX_SVN_REV_KMK) \ $(MAKEFILE_CURRENT) \ @@ -294,8 +310,8 @@ $(VBOX_WIN_INST_OUT_DIR)/$(PACKAGE_NAME_LANG)_$(lang).msi: \ $$(call MSG_L1,Linking installer $$@) $(QUIET)$(RM) -f $$(wildcard $(VBOX_WIN_INST_OUT_DIR)/$(PACKAGE_BASE)-r*_$(lang).msi) $(VBOX_PATH_WIX)/light.exe -nologo \ - -loc $(VBOX_WIN_INST_OUT_DIR)/Languages/Language_$(lang).wxl \ - -loc $(VBOX_WIN_INST_OUT_DIR)/Languages/License_$(lang).wxl \ + -loc $(VBOX_WIN_INST_OUT_DIR)/NLS/Language_$(lang).wxl \ + -loc $(VBOX_WIN_INST_OUT_DIR)/NLS/License_$(lang).wxl \ -ext $(VBOX_PATH_WIX)/WixUIExtension.dll \ -ext $(VBOX_PATH_WIX)/WixDifxAppExtension.dll \ $(VBOX_MSI_ICE_IGNORE) \ @@ -304,7 +320,7 @@ $(VBOX_WIN_INST_OUT_DIR)/$(PACKAGE_NAME_LANG)_$(lang).msi: \ $(if-expr "$(KBUILD_TARGET_ARCH)" == "x86", \ $(VBOX_PATH_WIX)/difxapp_x86.wixlib, \ $(VBOX_PATH_WIX)/difxapp_x64.wixlib) - $(RM) -f $(VBOX_WIN_INST_OUT_DIR)/Languages/$(lang).mst + $(RM) -f $(VBOX_WIN_INST_OUT_DIR)/NLS/$(lang).mst $(call VBOX_SIGN_FILE_FN,$$@,$(VBOX_PRODUCT) $(VBOX_VERSION_STRING)r$(VBOX_SVN_REV) ($(KBUILD_TARGET_ARCH))) endef @@ -399,8 +415,10 @@ endif define def_vbox_compile_wixobj $(VBOX_WIN_INST_OUT_DIR)/VirtualBox_$(lang).wixobj: \ $(PATH_SUB_CURRENT)/VirtualBox.wxs \ + $(VBOX_WIN_INST_OUT_DIR)/Shortcuts_StartMenu.wxi \ $(PATH_SUB_CURRENT)/UserInterface.wxi \ $(VBOX_WIN_INST_OUT_DIR)/VirtualBox_TypeLib.wxi \ + $(if $(VBOX_WITH_32_ON_64_MAIN_API),$(VBOX_WIN_INST_OUT_DIR)/VirtualBox_TypeLib_x86.wxi,) \ $(VBOX_WIN_INST_OUT_DIR)/VBoxKey.wxi \ $(VBOX_WIN_INST_OUT_DIR)/VBoxGuiNLS.wxi \ $(VBOX_MSI_DEPENDENCIES) \ @@ -429,6 +447,7 @@ $(VBOX_WIN_INST_OUT_DIR)/VirtualBox_$(lang).wixobj: \ -E 'VBOX_VERSION_MINOR_INST=$(VBOX_VERSION_MINOR)' \ -E 'VBOX_SIGNING_MODE=$(strip $(if $(VBOX_SIGNING_MODE),$(VBOX_SIGNING_MODE),none))' \ -E 'VBOX_GUI_USE_QGL=$(if $(VBOX_GUI_USE_QGL),yes,no)' \ + -E 'VBOX_WITH_32_ON_64_MAIN_API=$(if $(VBOX_WITH_32_ON_64_MAIN_API),yes,no)' \ -E 'VBOX_WITH_ADDITIONS_PACKING=$(if $(VBOX_WITH_ADDITIONS_PACKING),yes,no)' \ -E 'VBOX_WITH_COMBINED_PACKAGE=$(if $(VBOX_WITH_COMBINED_PACKAGE),yes,no)' \ -E 'VBOX_WITH_CROGL=$(if $(VBOX_WITH_CROGL),yes,no)' \ @@ -483,6 +502,15 @@ $(VBOX_WIN_INST_OUT_DIR)/VirtualBox_TypeLib.wxi: \ | $$(dir $$@) $(VBOX_XSLTPROC) -o $@ $< $(VBOX_XIDL_FILE) +$(VBOX_WIN_INST_OUT_DIR)/VirtualBox_TypeLib_x86.wxi: \ + $(PATH_SUB_CURRENT)/VirtualBox_TypeLib.xsl \ + $(VBOX_XIDL_FILE) \ + | $$(dir $$@) + $(VBOX_XSLTPROC) --stringparam "a_sTarget" "VBoxClient-x86" -o $@.tmp $< $(VBOX_XIDL_FILE) + $(SED) -e 's/VBoxC/VBoxClient_x86/g' --output $@ $@.tmp + $(RM) -f $@.tmp + + # # Construct the list of GUI translations. # ('-t' -- truncate file; '-n' -- new line between arguments) @@ -516,8 +544,8 @@ $(VBOX_WIN_INST_OUT_DIR)/VBoxKey.wxi: $(PATH_SUB_CURRENT)/VBoxKey.wxi $(VBOX_VER # programs / scripts involved in this step. # define def_vbox_create_mst -.NOTPARALLEL: $(VBOX_WIN_INST_OUT_DIR)/Languages/$(lang).mst -$(VBOX_WIN_INST_OUT_DIR)/Languages/$(lang).mst: \ +.NOTPARALLEL: $(VBOX_WIN_INST_OUT_DIR)/NLS/$(lang).mst +$(VBOX_WIN_INST_OUT_DIR)/NLS/$(lang).mst: \ $(VBOX_WIN_INST_OUT_DIR)/$(PACKAGE_NAME_LANG)_en_US.msi \ $(VBOX_WIN_INST_OUT_DIR)/$(PACKAGE_NAME_LANG)_$(lang).msi \ | $$$$(dir $$$$@) @@ -550,7 +578,7 @@ $(PACKAGE_NAME_FINAL): \ $(VBOX_WIN_INST_OUT_DIR)/Files_License.wxi \ $(VBOX_WIN_INST_OUT_DIR)/Shortcuts_StartMenu.wxi \ $(foreach lang,$(VBOX_INSTALLER_LANGUAGES), $(VBOX_WIN_INST_OUT_DIR)/$(PACKAGE_NAME_LANG)_$(lang).msi) \ - $(foreach lang,$(VBOX_INSTALLER_ADD_LANGUAGES), $(VBOX_WIN_INST_OUT_DIR)/Languages/$(lang).mst) \ + $(foreach lang,$(VBOX_INSTALLER_ADD_LANGUAGES), $(VBOX_WIN_INST_OUT_DIR)/NLS/$(lang).mst) \ $(VBOX_SVN_REV_KMK) \ | $$(dir $$@) $(QUIET)$(RM) -f $(wildcard $(PATH_STAGE_BIN)/$(PACKAGE_BASE)-r*.msi) @@ -568,11 +596,13 @@ if defined(VBOX_WITH_COMBINED_PACKAGE) && "$(KBUILD_TARGET_ARCH)" == "x86" # $(PATH_STAGE_BIN)/$(PACKAGE_NAME_MULTIARCH_FINAL): \ $(PATH_MULTIARCH_TEMP)/$(PACKAGE_NAME_MULTIARCH.x86) \ - $(PATH_MULTIARCH_TEMP)/$(PACKAGE_NAME_MULTIARCH.amd64) + $(PATH_MULTIARCH_TEMP)/$(PACKAGE_NAME_MULTIARCH.amd64) \ + $(PATH_STAGE_BIN)/VBoxStub.exe \ + $$(VBoxStubBld_1_TARGET) $(call MSG_L1,Building Windows combined package) $(call VBOX_SIGN_FILE_FN,$(VBOX_WIN_INST_OUT_DIR)/$(PACKAGE_NAME_MULTIARCH_COMMONCAB)) $(REDIRECT) -C $(@D) -- \ - VBoxStubBld -out $@ \ + $(VBoxStubBld_1_TARGET) -out $@ \ -target-x86 $(PATH_MULTIARCH_TEMP)/$(PACKAGE_NAME_MULTIARCH.x86) \ -target-amd64 $(PATH_MULTIARCH_TEMP)/$(PACKAGE_NAME_MULTIARCH.amd64) \ -target-all $(VBOX_WIN_INST_OUT_DIR)/$(PACKAGE_NAME_MULTIARCH_COMMONCAB) \ diff --git a/src/VBox/Installer/win/Languages/de_DE.wxl b/src/VBox/Installer/win/NLS/de_DE.wxl index a7d095f1..8f666ba7 100644 --- a/src/VBox/Installer/win/Languages/de_DE.wxl +++ b/src/VBox/Installer/win/NLS/de_DE.wxl @@ -119,6 +119,7 @@ <String Id="Customize2Dlg_Desc">Bitte unten die gewünschten Optionen auswählen:</String>
<String Id="Customize2Dlg_CreateShortcut">Verknüpfung auf dem Desktop anlegen</String>
<String Id="Customize2Dlg_CreateQuickLaunch">Verknüpfung in der Schnellstartleiste anlegen</String>
+ <String Id="Customize2Dlg_RegisterFileExtensions">Dateizuordnungen registrieren</String>
<!---->
diff --git a/src/VBox/Installer/win/Languages/en_US.wxl b/src/VBox/Installer/win/NLS/en_US.wxl index dd7f1283..8ffa8343 100644 --- a/src/VBox/Installer/win/Languages/en_US.wxl +++ b/src/VBox/Installer/win/NLS/en_US.wxl @@ -123,6 +123,7 @@ <String Id="Customize2Dlg_Desc">Please choose from the options below:</String>
<String Id="Customize2Dlg_CreateShortcut">Create a shortcut on the desktop</String>
<String Id="Customize2Dlg_CreateQuickLaunch">Create a shortcut in the Quick Launch Bar</String>
+ <String Id="Customize2Dlg_RegisterFileExtensions">Register file associations</String>
<!---->
diff --git a/src/VBox/Installer/win/Languages/fa_IR.wxl b/src/VBox/Installer/win/NLS/fa_IR.wxl index 446b89fe..37b7f672 100644 --- a/src/VBox/Installer/win/Languages/fa_IR.wxl +++ b/src/VBox/Installer/win/NLS/fa_IR.wxl @@ -90,6 +90,7 @@ <String Id="Customize2Dlg_Desc">لطفاً از گزینه های زیر انتخاب کنید:</String> <String Id="Customize2Dlg_CreateShortcut">ایجاد یک میانبر روی دسکتاپ</String> <String Id="Customize2Dlg_CreateQuickLaunch">ایجاد یک میانبر در اِجرای سریع</String> + <String Id="Customize2Dlg_RegisterFileExtensions">ثبت نام انجمن فایل</String> <!----> <String Id="WarnDisconNetIfacesDlg_Title">هشدار:</String> <String Id="WarnDisconNetIfacesDlg_Title2">رابط های شبکه</String> @@ -509,4 +510,4 @@ <String Id="UITextVolumeCostRequired">موردنیاز</String> <String Id="UITextVolumeCostSize">حجم دیسک</String> <String Id="UITextVolumeCostVolume">درایو</String> -</WixLocalization>
\ No newline at end of file +</WixLocalization>
\ No newline at end of file diff --git a/src/VBox/Installer/win/Languages/fr_FR.wxl b/src/VBox/Installer/win/NLS/fr_FR.wxl index bb726b50..fa3d77f3 100644 --- a/src/VBox/Installer/win/Languages/fr_FR.wxl +++ b/src/VBox/Installer/win/NLS/fr_FR.wxl @@ -58,7 +58,6 @@ <String Id="WrongOS">Cette application nécéssite Windows XP ou plus récent.</String>
<String Id="Only32Bit">Cette application ne marche que sur des systèmes Windows 32-bit. Veuillez installer la version 64-bit de [ProductName]!</String>
<String Id="Only64Bit">Cette application ne marche que sur des systèmes Windows 64-bit. Veuillez installer la version 32-bit de [ProductName]!</String>
- <String Id="InnotekFound">Vous avez une ancienne installation de Sun VirtualBox sur cette machine. Il vous faudra la désinstaller avant de pouvoir installer [ProductName].</String>
<String Id="InnotekFound">Vous avez une ancienne installation de innotek VirtualBox sur cette machine. Il vous faudra la désinstaller avant de pouvoir installer [ProductName].</String>
<!---->
@@ -118,6 +117,7 @@ <String Id="Customize2Dlg_Desc">Veuillez choisir une des options suivantes:</String>
<String Id="Customize2Dlg_CreateShortcut">Créer un raccourci sur le bureau</String>
<String Id="Customize2Dlg_CreateQuickLaunch">Créer un raccourci dans la barre de lancement rapide</String>
+ <String Id="Customize2Dlg_RegisterFileExtensions">Inscription des associations de fichiers</String>
<!---->
diff --git a/src/VBox/Installer/win/Languages/it_IT.wxl b/src/VBox/Installer/win/NLS/it_IT.wxl index 907e3369..98e6bc30 100644 --- a/src/VBox/Installer/win/Languages/it_IT.wxl +++ b/src/VBox/Installer/win/NLS/it_IT.wxl @@ -90,6 +90,7 @@ <String Id="Customize2Dlg_Desc">Scegli dalle opzioni seguenti:</String> <String Id="Customize2Dlg_CreateShortcut">Crea una scorciatoia sul desktop</String> <String Id="Customize2Dlg_CreateQuickLaunch">Crea una scorciatoia nella barra di avvio veloce</String> + <String Id="Customize2Dlg_RegisterFileExtensions">Registrati associazioni di file</String> <!----> <String Id="WarnDisconNetIfacesDlg_Title">Avviso:</String> <String Id="WarnDisconNetIfacesDlg_Title2">Interfacce di rete</String> @@ -509,4 +510,4 @@ <String Id="UITextVolumeCostRequired">Richiesto</String> <String Id="UITextVolumeCostSize">Dimensione disco</String> <String Id="UITextVolumeCostVolume">Volume</String> -</WixLocalization>
\ No newline at end of file +</WixLocalization>
\ No newline at end of file diff --git a/src/VBox/Installer/win/Languages/tr_TR.wxl b/src/VBox/Installer/win/NLS/tr_TR.wxl index e907e91a..e907e91a 100644 --- a/src/VBox/Installer/win/Languages/tr_TR.wxl +++ b/src/VBox/Installer/win/NLS/tr_TR.wxl diff --git a/src/VBox/Installer/win/NLS/zh_TW.wxl b/src/VBox/Installer/win/NLS/zh_TW.wxl new file mode 100644 index 00000000..383a8127 --- /dev/null +++ b/src/VBox/Installer/win/NLS/zh_TW.wxl @@ -0,0 +1,587 @@ +<?xml version="1.0" encoding="utf-8"?>
+<WixLocalization xmlns="http://schemas.microsoft.com/wix/2003/11/localization" Codepage="65001" Culture="zh_TW">
+
+ <!--
+ Language Definition Include for VirtualBox WiX script.
+
+ Copyright (C) 2011-2012 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.
+ -->
+
+ <String Id="LANG">1024</String>
+ <String Id="LangName">正體中文</String>
+
+ <String Id="ButtonText_No">否(&N)</String>
+ <String Id="ButtonText_Yes">是(&Y)</String>
+ <String Id="ButtonText_Cancel">取消(&C)</String>
+ <String Id="ButtonText_Next">下一步(&N) ></String>
+ <String Id="ButtonText_Back">< 上一步(&B)</String>
+ <String Id="ButtonText_Browse">瀏覽(&O)</String>
+ <String Id="ButtonText_OK">確定(&K)</String>
+ <String Id="ButtonText_Check">檢查(&C)</String>
+ <String Id="ButtonText_Install">安裝(&I)</String>
+ <String Id="ButtonText_Remove">移除(&R)</String>
+ <String Id="ButtonText_Finish">完成(&F)</String>
+ <String Id="ButtonText_Repair">修理(&R)</String>
+ <String Id="ButtonText_Return">返回(&R)</String>
+ <String Id="ButtonText_Retry">重試(&T)</String>
+ <String Id="ButtonText_Ignore">忽略(&G)</String>
+ <String Id="ButtonText_Exit">結束(&X)</String>
+
+ <String Id="InstallModeCustom">自訂</String>
+ <String Id="Setup">設定</String>
+
+ <!---->
+
+ <String Id="StartMenu_License">授權</String>
+ <String Id="StartMenu_UserManual">使用者手冊</String>
+
+ <!---->
+
+ <String Id="VB_App">[ProductName] 應用程式。</String>
+ <String Id="VB_USBDriver">[ProductName] USB 裝置驅動程式針對 USB 裝置支援。</String>
+ <String Id="VB_Network">[ProductName] 網路裝置驅動程式針對網路支援。</String>
+ <String Id="VB_NetFltDriver">[ProductName] 驅動程式針對橋接網路。</String>
+ <String Id="VB_NetAdpDriver">[ProductName] 虛擬網路介面卡針對「僅限主機」網路。</String>
+
+ <String Id="VB_Python">VirtualBox 的 Python 支援。</String>
+
+ <!---->
+
+ <String Id="NeedAdmin">您需要有系統管理員特殊權限以安裝 (或解除安裝)[ProductName]!此安裝程式現在將中止。</String>
+ <String Id="WrongOS">此應用程式只能執行在 Windows XP 或以上。</String>
+ <String Id="Only32Bit">此應用程式只能執行在 32 位元的 Windows 系統。 請安裝 [ProductName] 的 64 位元版本!</String>
+ <String Id="Only64Bit">此應用程式只能執行在 64 位元的 Windows 系統。 請安裝 [ProductName] 的 32 位元版本!</String>
+ <String Id="SunFound">在此電腦發現舊的 Sun VirtualBox 安裝。 請先解除安裝此套件然後安裝 [ProductName]!</String>
+ <String Id="InnotekFound">在此電腦發現舊的 innotek VirtualBox 安裝。 請先解除安裝此套件然後安裝 [ProductName]!</String>
+
+ <!---->
+
+ <String Id="CancelDlg_Question">您確定要取消 [ProductName] 安裝嗎?</String>
+
+ <!---->
+
+ <String Id="WelcomeDlg_Header">歡迎使用 [ProductName] 安裝精靈</String>
+ <String Id="WelcomeDlg_Body">安裝精靈將在您的電腦安裝 [ProductName]。 按一下「下一步」繼續或「取消」結束安裝精靈。</String>
+
+ <!---->
+
+ <String Id="LicenseAgreementDlg_Header">最終使用者授權協議</String>
+ <String Id="LicenseAgreementDlg_Body">請仔細閱讀以下授權協議。</String>
+ <String Id="LicenseAgreementDlg_Accept">我接受授權協議中條款(&A)</String>
+ <String Id="LicenseAgreementDlg_Decline">我不接受授權協議中條款(&D)</String>
+
+ <!---->
+
+ <String Id="CheckSerialDlg_Header">序號</String>
+ <String Id="CheckSerialDlg_Body">請在以下欄位輸入您的序號。 您可以在 VirtualBox CD 盒內的貼紙找到。</String>
+ <String Id="CheckSerialDlg_Footer">序號輸入完成時,按一下以下「檢查」按鈕。</String>
+
+ <!---->
+
+ <String Id="WrongSerialDlg_Header">輸入的序號無效!</String>
+ <String Id="WrongSerialDlg_Desc1">請返回再次輸入您的序號。</String>
+ <String Id="WrongSerialDlg_Desc2">請記得,序號必須和印在貼紙上的拼字完全一樣。</String>
+
+ <!---->
+
+ <String Id="WarnSaveStatesDlg_Header">警告:</String>
+ <String Id="WarnSaveStatesDlg_Header2">已經的儲存狀態不相容!</String>
+ <String Id="WarnSaveStatesDlg_Desc">升級 [ProductName] 時,所有來自已經存在機器的儲存狀態不再能動作!安裝後,您必須手動捨棄。</String>
+ <String Id="WarnSaveStatesDlg_Proceed">立即進行安裝嗎?</String>
+
+ <!---->
+
+ <String Id="WarnTAPDevicesDlg_Header">主機介面</String>
+ <String Id="WarnTAPDevicesDlg_Desc">如果您的機器在先前版本使用某些主機介面。 在此安裝後您必須重新建立它們。</String>
+
+ <!---->
+
+ <String Id="NetCfgLocked">繼續安裝前,必須關閉以下應用程式:"[2]"</String>
+
+ <!---->
+
+ <String Id="CustomizeDlg_Location">位置:</String>
+ <String Id="CustomizeDlg_DiskUsage">磁碟使用量(&U)</String>
+ <String Id="CustomizeDlg_SelFeatures">選取您要安裝功能的方式。</String>
+ <String Id="CustomizeDlg_IconTree">按一下以下樹狀中圖示以變更安裝功能的方式。</String>
+ <String Id="CustomizeDlg_CustomSetup">自訂安裝</String>
+ <String Id="CustomizeDlg_SelItemDesc">CustomizeDlgItemDescription-CustomizeDlgItemDescription</String>
+ <String Id="CustomizeDlg_SelItemSize">CustomizeDlgItemSize-CustomizeDlgItemSize</String>
+ <String Id="CustomizeDlg_SelItemPath">CustomizeDlgLocation-CustomizeDlgLocation</String>
+
+ <!---->
+
+ <String Id="Customize2Dlg_Header">自訂</String>
+ <String Id="Customize2Dlg_Desc">請選擇以下選項:</String>
+ <String Id="Customize2Dlg_CreateShortcut">在桌面建立捷徑</String>
+ <String Id="Customize2Dlg_CreateQuickLaunch">在快速啟動列建立捷徑</String>
+ <String Id="Customize2Dlg_RegisterFileExtensions">註冊文件關聯</String>
+
+ <!---->
+
+ <String Id="WarnDisconNetIfacesDlg_Title">警告:</String>
+ <String Id="WarnDisconNetIfacesDlg_Title2">網路介面</String>
+ <String Id="WarnDisconNetIfacesDlg_Desc">安裝 [ProductName] 網路功能將重設您的網路連線並暫時中斷網路連線。</String>
+ <String Id="WarnDisconNetIfacesDlg_Question">立即進行安裝嗎?</String>
+
+ <!---->
+
+ <String Id="DiskCostDlg_SpaceRequired">安裝選取功能所需的磁碟空間。</String>
+ <String Id="DiskCostDlg_NotEnoughSpace">反白的磁碟區(如果有)對於目前選取的功能沒有足夠的磁碟空間可以使用。 您可以從反白的磁碟區移除一些檔案,或選擇安裝較少功能在本機磁碟機,或選取不同目的地磁碟機。</String>
+ <String Id="DiskCostDlg_SpaceRequirements">磁碟空間需求</String>
+ <String Id="DiskCostDlg_VolumeList">{120}{70}{70}{70}{70}</String>
+
+ <!---->
+
+ <String Id="BrowseDlg_BrowseDestFolder">瀏覽目的地資料夾</String>
+ <String Id="BrowseDlg_ChangeCurFolder">變更目前目的地資料夾</String>
+ <String Id="BrowseDlg_UpOneLevelTooltip">上一層</String>
+ <String Id="BrowseDlg_CreateNewFolderTooltip">建立新的資料夾</String>
+ <String Id="BrowseDlg_LookIn">瀏覽(&L):</String>
+ <String Id="BrowseDlg_FolderName">資料夾名稱(&F):</String>
+
+ <!---->
+
+ <String Id="VerifyReadyDlg_ReadyToBegin">安裝精靈準備好進行 [InstallMode] 安裝。</String>
+ <String Id="VerifyReadyDlg_ClickInstall">按一下「安裝」開始安裝。 如果您要檢閱或變更任何安裝設定,按一下「上一步」。 按一下「取消」結束精靈。</String>
+ <String Id="VerifyReadyDlg_ReadyToInstall">準備好安裝</String>
+
+ <!---->
+
+ <String Id="ExitDlg_ClickFinish">按一下「完成」按鈕結束安裝精靈。</String>
+ <String Id="ExitDlg_InstComplete">[ProductName] 安裝完成。</String>
+ <String Id="ExitDlg_StartVBox">安裝後啟動 [ProductName]</String>
+
+ <!---->
+
+ <String Id="FatalErrorDlg_Header">[ProductName] 安裝精靈太早結束</String>
+ <String Id="FatalErrorDlg_Desc">[ProductName] 安裝因為錯誤太早結束。 您的系統未做修改。 若要稍後安裝此程式,請再次執行安裝。</String>
+ <String Id="FatalErrorDlg_Footer">按一下「完成」按鈕結束安裝精靈。</String>
+
+ <!---->
+
+ <String Id="FilesInUse_Text">以下應用程式使用此安裝需要更新的檔案。 關閉這些應用程式接著按一下「重試(&R)」以繼續安裝或「取消」結束精靈。</String>
+ <String Id="FilesInUse_Description">某些需要更新的檔案目前使用中。</String>
+ <String Id="FilesInUse_Title">檔案使用中</String>
+
+ <!---->
+
+ <String Id="UserExitDlg_Header">[ProductName] 安裝精靈中斷</String>
+ <String Id="UserExitDlg_Desc">[ProductName] 安裝中斷。 您的系統未做修改。 若要稍後安裝此程式,請再次執行安裝。</String>
+ <String Id="UserExitDlg_Footer">按一下「完成」按鈕結束安裝精靈。</String>
+
+ <!---->
+
+ <String Id="ProgressDlg_PleaseWait">在安裝精靈安裝 [ProductName] 時請稍候。 這需要幾分鐘時間。</String>
+
+ <!---->
+
+ <String Id="ResumeDlg_Header">正在繼續 [ProductName] 安裝精靈</String>
+ <String Id="ResumeDlg_Desc">安裝精靈將在您的電腦完成 [ProductName] 的安裝。 按一下「安裝」以繼續或「取消」結束安裝精靈。</String>
+
+ <!---->
+
+ <String Id="MaintenanceTypeDlg_Header">修改、修復或移除安裝</String>
+ <String Id="MaintenanceTypeDlg_SelOption">選取您希望執行的操作。</String>
+ <String Id="MaintenanceTypeDlg_Repair">修復(&P)</String>
+ <String Id="MaintenanceTypeDlg_RepairText">修復在最近安裝狀態的錯誤 - 修復缺少或損毀的檔案、捷徑和登錄檔項目。</String>
+ <String Id="MaintenanceTypeDlg_RepairTooltip">修復安裝</String>
+ <String Id="MaintenanceTypeDlg_RepairProgress1">正在修復</String>
+ <String Id="MaintenanceTypeDlg_RepairProgress2">repairs</String>
+ <String Id="MaintenanceTypeDlg_Remove">移除(&R)</String>
+ <String Id="MaintenanceTypeDlg_RemoveText">從電腦移除 [ProductName]。</String>
+ <String Id="MaintenanceTypeDlg_RemoveTooltip">移除安裝</String>
+ <String Id="MaintenanceTypeDlg_RemoveProgress1">正在移除</String>
+ <String Id="MaintenanceTypeDlg_RemoveProgress2">removes</String>
+
+ <!---->
+
+ <String Id="MaintenanceWelcomeDlg_Header">歡迎使用 [ProductName] 安裝精靈</String>
+ <String Id="MaintenanceWelcomeDlg_Desc">安裝精靈將允許您修復目前的安裝或從您的電腦移除 [ProductName]。 按一下「下一步」以繼續或「取消」結束安裝精靈。</String>
+
+ <!---->
+
+ <String Id="OutOfDiskDlg_InstallationExceeds">安裝所需的磁碟空間超過可用的磁碟空間。</String>
+ <String Id="OutOfDiskDlg_NotEnoughDiskSpace">反白的磁碟區對於目前選取的功能沒有足夠的磁碟空間可以使用。 您可以從反白的磁碟區移除一些檔案,或選擇安裝較少功能在本機磁碟機,或選取不同目的地磁碟機。</String>
+ <String Id="OutOfDiskDlg_OutOfDiskSpace">磁碟空間不足</String>
+
+ <!---->
+
+ <String Id="OutOfRbDiskDlg_InstallationExceeds">安裝所需的磁碟空間超過可用的磁碟空間。</String>
+ <String Id="OutOfRbDiskDlg_NotEnoughDiskSpace">反白的磁碟區對於目前選取的功能沒有足夠的磁碟空間可以使用。 您可以從反白的磁碟區移除一些檔案,或選擇安裝較少功能在本機磁碟機,或選取不同目的地磁碟機。</String>
+ <String Id="OutOfRbDiskDlg_OutOfDiskSpace">磁碟空間不足</String>
+ <String Id="OutOfRbDiskDlg_Desc">或者,您可以選擇停用安裝程式的回復功能。 這允許安裝程式在任何方式中斷安裝時還原您電腦的原始狀態。 按一下「是」如果您希望承擔停用回復功能的風險。</String>
+
+ <!---->
+
+ <String Id="VerifyRemoveDlg_Header">移除 [ProductName]</String>
+ <String Id="VerifyRemoveDlg_Desc">您已經選擇從您的電腦移除程式。</String>
+ <String Id="VerifyRemoveDlg_ClickRemove">按一下「移除」以從您的電腦移除 [ProductName]。 如果您要檢閱或變更任何安裝設定,按一下「上一步」。 按一下「取消」結束精靈。</String>
+
+ <!---->
+
+ <String Id="VerifyRepairDlg_Header">修復 [ProductName]</String>
+ <String Id="VerifyRepairDlg_ReadyToBegin">安裝精靈準備好開始修復 [ProductName]。</String>
+ <String Id="VerifyRepairDlg_ClickRepair">按一下「修復」以修復 [ProductName] 的安裝。 如果您要檢閱或變更任何安裝設定,按一下「上一步」。 按一下「取消」結束精靈。</String>
+
+ <!---->
+
+ <String Id="WaitForCostingDlg_PleaseWait">在安裝程式完成判斷您的磁碟空間需求時請稍候。</String>
+
+ <!---->
+
+ <String Id="MsiRMFilesInUse_Text">以下應用程式使用此安裝需要更新的檔案。 您可以讓安裝精靈關閉並嘗試重新啟動這些應用程式或稍後重新啟動電腦。</String>
+ <String Id="MsiRMFilesInUse_Description">某些需要更新的檔案目前使用中。</String>
+ <String Id="MsiRMFilesInUse_Title">檔案使用中</String>
+ <String Id="MsiRMFilesInUse_UseRM">關閉應用程式並嘗試重新啟動它們。 (&C)</String>
+ <String Id="MsiRMFilesInUse_DontUseRM">不要關閉應用程式,將需要重新開機。 (&D)</String>
+
+ <!-- The following strings are internally used by WiX and MSI -->
+ <String Id="Error0">{{嚴重錯誤:}}</String>
+ <String Id="Error1">{{錯誤 [1]。}}</String>
+ <String Id="Error2">警告 [1]。</String>
+ <String Id="Error3"/>
+ <String Id="Error4">資訊 [1]。</String>
+ <String Id="Error5">安裝程式安裝這個封裝時發生未預期的錯誤。 這可能表示這個封裝的問題。 錯誤碼 [1]。 {{引數:[2], [3], [4]}}</String>
+ <String Id="Error6"/>
+ <String Id="Error7">{{磁碟已滿:}}</String>
+ <String Id="Error8">動作 [Time]:[1]. [2]</String>
+ <String Id="Error9">[ProductName]</String>
+ <String Id="Error10">{[2]}{, [3]}{, [4]}</String>
+ <String Id="Error11">訊息類型:[1], 引數:[2]</String>
+ <String Id="Error12">=== 開啟記錄時間:[Date] [Time] ===</String>
+ <String Id="Error13">=== 停止記錄時間:[Date] [Time] ===</String>
+ <String Id="Error14">動作開始 [Time]:[1]。</String>
+ <String Id="Error15">動作結束 [Time]:[1]。 傳回值 [2]。</String>
+ <String Id="Error16">剩餘時間:{[1] 分 }{[2] 秒}</String>
+ <String Id="Error17">記憶體不足,重試之前先關閉其它應用程式。</String>
+ <String Id="Error18">安裝程式不再有回應。</String>
+ <String Id="Error19">安裝程式已經永久中止。</String>
+ <String Id="Error20">在 Windows 組態 [ProductName] 時請稍候</String>
+ <String Id="Error21">正在收集所需的資訊...</String>
+ <String Id="Error22">正在移除此應用程式的舊版本...</String>
+ <String Id="Error23">正在準備移除此應用程式的舊版本...</String>
+ <String Id="Error32">{[ProductName] } 安裝成功完成。</String>
+ <String Id="Error33">{[ProductName] } 安裝失敗。</String>
+ <String Id="Error1101">讀取檔案錯誤:[2]。{{ 系統錯誤 [3]。}} 檢查檔案是否存在,並且可以存取。</String>
+ <String Id="Error1301">無法建立目錄 '[2]'。 同名的目錄已經存在。 取消安裝並嘗試安裝到不同位置。</String>
+ <String Id="Error1302">請插入磁碟:[2]</String>
+ <String Id="Error1303">安裝程式的權限不足,無法存取這個目錄:[2],安裝無法繼續,以系統管理員的身份登入或是連絡您的系統管理員。</String>
+ <String Id="Error1304">寫入至檔案時發生錯誤:[2]。請檢查您可以存取那個目錄。</String>
+ <String Id="Error1305">讀取檔案時發生錯誤:[2]。{{ 系統錯誤 [3]。}} 請檢查檔案是否存在,並且可以存取。</String>
+ <String Id="Error1306">另一個應用程序獨占存取檔案 '[2]'。 請關閉所有其它應用程式,然後按一下「重試」。</String>
+ <String Id="Error1307">磁碟空間不足,無法安裝這個檔案:[2]。釋放一些磁碟空間然後按一下「重試」,或按一下「取消」結束。</String>
+ <String Id="Error1308">找不到來源檔案:[2]。 請驗證檔案存在並且您可以存取它。</String>
+ <String Id="Error1309">讀取檔案錯誤:[3]。{{ 系統錯誤 [2]。}} 請檢查檔案是否存在,並且可以存取。</String>
+ <String Id="Error1310">寫入至檔案時發生錯誤:[3]。{{ 系統錯誤 [2]。}} 請檢查您可以存取那個目錄。</String>
+ <String Id="Error1311">找不到來源檔案 {{(cabinet)}}:[2]。 請檢查檔案存在並且可以存取。</String>
+ <String Id="Error1312">無法建立目錄 '[2]'。 同名的檔案已經存在。 請重新命名或移除檔案並按一下「重試」,或按一下「取消」結束。</String>
+ <String Id="Error1313">磁碟區 [2] 目前不可使用。 請選取另一個。</String>
+ <String Id="Error1314">指定的路徑 '[2]' 不可使用。</String>
+ <String Id="Error1315">無法寫入指定的資料夾:[2]。</String>
+ <String Id="Error1316">嘗試從檔案讀取時發生網路錯誤:[2]</String>
+ <String Id="Error1317">嘗試建立目錄時發生錯誤:[2]</String>
+ <String Id="Error1318">嘗試建立目錄時發生網路錯誤:[2]</String>
+ <String Id="Error1319">嘗試開啟來源檔案時發生網路錯誤:[2]</String>
+ <String Id="Error1320">指定的路徑太長:[2]</String>
+ <String Id="Error1321">Installer 的權限不足以修改這個檔案:[2]。</String>
+ <String Id="Error1322">資料夾路徑的部份 '[2]' 無效。其為空或超過系統允許的長度。</String>
+ <String Id="Error1323">資料夾路徑 '[2]' 包含無效的字在資料夾路徑。</String>
+ <String Id="Error1324">資料夾路徑 '[2]' 包含無效字元。</String>
+ <String Id="Error1325">'[2]' 不是有效的短檔名。</String>
+ <String Id="Error1326">取得檔案安全性錯誤:[3] GetLastString:[2]</String>
+ <String Id="Error1327">無效的磁碟機:[2]</String>
+ <String Id="Error1328">套用修正檔到檔案 [2] 錯誤。 可能已由其他主機更新,且這個修正檔不再能修改。 更多資訊請聯絡您的修正檔供應商。 {{系統錯誤:[3]}}</String>
+ <String Id="Error1329">無法安裝所需的檔案,因為 cabinet 檔案 [2] 沒有數位簽章。 這表示 cabinet 檔案已經損毀。</String>
+ <String Id="Error1330">無法安裝所需的檔案,因為 cabinet 檔案 [2] 有無效的數位簽章。 這表示 cabinet 檔案已經損毀。 {{ WinVerifyTrust 返回錯誤 [3]。}}</String>
+ <String Id="Error1331">修正複製 [2] 檔案失敗:CRC 錯誤。</String>
+ <String Id="Error1332">修正移動 [2] 檔案失敗:CRC 錯誤。</String>
+ <String Id="Error1333">修正路徑 [2] 檔案失敗:CRC 錯誤。</String>
+ <String Id="Error1334">無法安裝 '[2]' 因為在 cainet 檔案 '[3]' 中找不到檔案。 這表示網路錯誤、從 CD-ROM 讀取錯誤、或此安裝包問題。</String>
+ <String Id="Error1335">此安裝所需的 cabinet 檔案 '[2]' 已經損毀且無法使用。 這表示網路錯誤、從 CD-ROM 讀取錯誤、或此安裝包問題。</String>
+ <String Id="Error1336">完成這個安裝所需的暫存檔案建立錯誤。 {{ 資料夾:[3]。 系統錯誤碼:[2]}}</String>
+ <String Id="Error1401">無法建立機碼:[2]。{{ 系統錯誤 [3]。}} 檢查您是有足夠的權限存取該機碼,或是連絡您的支援人員。</String>
+ <String Id="Error1402">無法開啟機碼:[2]。{{ 系統錯誤 [3]。}} 檢查您是有足夠的權限存取該機碼,或是連絡您的支援人員。</String>
+ <String Id="Error1403">無法從機碼 [3] 刪除值:[2]。{{ 系統錯誤 [4]。}} 檢查您是有足夠的權限存取該機碼,或是連絡您的支援人員。</String>
+ <String Id="Error1404">無法刪除機碼:[2]。{{ 系統錯誤 [3]。}} 檢查您是有足夠的權限存取該機碼,或是連絡您的支援人員。</String>
+ <String Id="Error1405">無法從機碼 [3] 讀取值 [2]。{{ 系統錯誤 [4]。}} 檢查您是有足夠的權限存取該機碼,或是連絡您的支援人員。</String>
+ <String Id="Error1406">無法寫入值 [2] 至機碼 [3]。{{ 系統錯誤 [4]。}} 檢查您是有足夠的權限存取該機碼,或是連絡您的支援人員。</String>
+ <String Id="Error1407">無法取得機碼 [2] 的值名稱。{{ 系統錯誤 [3]。}} 檢查您是有足夠的權限存取該機碼,或是連絡您的支援人員。</String>
+ <String Id="Error1408">無法取得機碼 [2] 的子機碼名稱。{{ 系統錯誤 [3]。}} 檢查您是有足夠的權限存取該機碼,或是連絡您的支援人員。</String>
+ <String Id="Error1409">無法讀取機碼 [2] 的安全資訊。{{ 系統錯誤 [3]。}} 檢查您是有足夠的權限存取該機碼,或是連絡您的支援人員。</String>
+ <String Id="Error1410">無法增加可用的登錄空間。 此應用程式須要 [2] KB 以上的空間。</String>
+ <String Id="Error1500">其它的安裝正在進行中,您必須完成該項安裝之後才能繼續。</String>
+ <String Id="Error1501">存取保全資料時發生錯誤,請確定 Windows Installer 是否正確組態,然後再試一次。</String>
+ <String Id="Error1502">使用者 '[2]' 先前已經啟動產品 '[3]' 的安裝。 該使用者在可以使用該產品前需要再次執行安裝。您目前的安裝現在將繼續。</String>
+ <String Id="Error1503">使用者 '[2]' 先前已經啟動產品 '[3]' 的安裝。 該使用者在可以使用該產品前需要再次執行安裝。</String>
+ <String Id="Error1601">磁碟空間不足 -- 磁碟區:'[2]',所需空間:[3] KB; 可用空間:[4] KB。 釋放一些磁碟空間並重試。</String>
+ <String Id="Error1602">您確定要取消嗎?</String>
+ <String Id="Error1603">檔案 [2][3] 正在由 { 以下處理程序:名稱:[4],Id:[5],視窗標題:'[6]'} 使用中。 關閉該應用程式並重試。</String>
+ <String Id="Error1604">已經安裝產品 '[2]',此產品防止安裝。 兩個產品不相容。</String>
+ <String Id="Error1605">磁碟區 '[2]' 沒有足夠的磁碟空間以啟用復原的安裝繼續。 需要 [3] KB,但只有 [4] KB 可以使用。 按一下「忽略」以不儲存復原資訊繼續安裝,按一下「重試」以再次檢查可用空間,或按一下「取消」以離開安裝。</String>
+ <String Id="Error1606">無法存取網路位置 [2]。</String>
+ <String Id="Error1607">繼續安裝前應該關閉以下應用程式:</String>
+ <String Id="Error1608">無法在本機中找到任何先前已安裝的合格版本。</String>
+ <String Id="Error1609">套用安全性設定時發生錯誤。 [2] 不是有效的使用者或群組。 這會是安裝包的問題或連線到網路上網域控制站的問題。 檢查您的網路連線並按一下「重試」,或「取消」以結束安裝。 {{找不到使用者的 SID,系統錯誤 [3]}}</String>
+ <String Id="Error1701">金鑰 [2] 是無效的,檢查您輸入的金鑰是否正確。</String>
+ <String Id="Error1702">要繼續設定 [2] 之前,Installer 必須重新啟動您的系統,按「是」將立即重新啟動;如果您想要稍後手動重新啟動請按「否」。</String>
+ <String Id="Error1703">您必須重新啟動您的系統,對 [2] 所做的組態變更才會生效,按「是」立即重新啟動;如果您想要稍後手動重新啟動請按「否」。</String>
+ <String Id="Error1704">安裝 [2] 目前已經暫停,您必須復原該安裝所做的變更才能繼續,您要復原這些變更嗎?</String>
+ <String Id="Error1705">另一個安裝這個產品的程式正在進行中,您必須復原該安裝所做的變更才能繼續,您要復原這些變更嗎?</String>
+ <String Id="Error1706">找不到產品 [2] 的安裝包。 嘗試使用安裝包 '[3]' 的有效副本嘗試再次安裝。</String>
+ <String Id="Error1707">安裝成功完成。</String>
+ <String Id="Error1708">安裝失敗。</String>
+ <String Id="Error1709">產品:[2] -- [3]</String>
+ <String Id="Error1710">您可以將電腦還原成先前的狀態或稍後繼續安裝,您希望還原嗎?</String>
+ <String Id="Error1711">寫入安裝資訊至磁碟時發生錯誤,確定磁碟的空間足夠,並按「重試」,或按「取消」來結束安裝。</String>
+ <String Id="Error1712">還原您的電腦成之前的狀態所需的一個或數個檔案找不到。 無法還原。</String>
+ <String Id="Error1713">[2] 無法安裝其所需的產品之一。 請聯絡您的技術支援小組。 {{系統字串:[3]。}}</String>
+ <String Id="Error1714">無法移除 [2] 的舊版本。 請聯絡您的技術支援小組。 {{系統字串 [3]。}}</String>
+ <String Id="Error1715">已經安裝 [2]</String>
+ <String Id="Error1716">已經組態 [2]</String>
+ <String Id="Error1717">已經移除 [2]</String>
+ <String Id="Error1718">數位簽章原則拒絕檔案 [2] 。</String>
+ <String Id="Error1719">無法存取 Windows Installer 服務。 如果您正執行在 Windows 安全模式,這將會發生。 請聯絡您的技術支援人員以取得協助。</String>
+ <String Id="Error1720">這個 Windows Installer 封裝有問題。 完成這個安裝需要的指令碼無法執行。 聯絡您的支援人員或封裝供應商。 {{自訂動作 [2] 指令碼錯誤 [3],[4]:[5] 行 [6],欄 [7],[8] }}</String>
+ <String Id="Error1721">這個 Windows Installer 封裝有問題。 完成這個安裝需要的程式無法執行。 聯絡您的支援人員或封裝供應商。 {{動作 [2],位置:[3],命令:[4] }}</String>
+ <String Id="Error1722">這個 Windows Installer 封裝有問題。 以 setup 部分執行的程式無法如預期完成。 聯絡您的支援人員或封裝供應商。 {{動作 [2],位置:[3],命令:[4] }}</String>
+ <String Id="Error1723">這個 Windows Installer 封裝有問題。 完成這個安裝需要的 DLL 無法執行。 聯絡您的支援人員或封裝供應商。 {{動作 [2],項目:[3],程式庫:[4] }}</String>
+ <String Id="Error1724">移除成功完成。</String>
+ <String Id="Error1725">移除失敗。</String>
+ <String Id="Error1726">宣告成功完成。</String>
+ <String Id="Error1727">宣告失敗。</String>
+ <String Id="Error1728">組態成功完成。</String>
+ <String Id="Error1729">組態失敗。</String>
+ <String Id="Error1730">您必須是管理者以移除這個應用程式。 要移除這個應用程式,您可以使用系統管理員登入或聯絡您的技術支援群組取得協助。</String>
+ <String Id="Error1801">路徑 [2] 無效。 請指定有效的路徑。</String>
+ <String Id="Error1802">記憶體不足,重試之前先關閉其它應用程式。</String>
+ <String Id="Error1803">磁碟機 [2] 中沒有磁片,請插入磁片然後重試,或按「取消」回到上次選取的磁碟區。</String>
+ <String Id="Error1804">磁碟機 [2] 中沒有磁片,請插入磁片然後按「重試」,或按「取消」回到瀏覽對話方塊,並選取不同的磁碟區。</String>
+ <String Id="Error1805">資料夾 [2] 不存在,請輸入一個現有的資料夾路徑。</String>
+ <String Id="Error1806">您的權限不足,無法讀取這個資料夾。</String>
+ <String Id="Error1807">無法決定合法的目的資料夾。</String>
+ <String Id="Error1901">嘗試讀取來源安裝資料庫時發生錯誤:[2]。</String>
+ <String Id="Error1902">正在排定重新開機作業:正在更改檔案名稱 [2] 成 [3],必須重新開機才能完成作業。</String>
+ <String Id="Error1903">正在排定重新開機作業:正在刪除檔案 [2],必須重新開機才能完成作業。</String>
+ <String Id="Error1904">註冊模組 [2] 失敗。HRESULT [3]。連絡您的支援人員。</String>
+ <String Id="Error1905">取消註冊模組 [2] 失敗。HRESULT [3]。連絡您的支援人員。</String>
+ <String Id="Error1906">無法預存封裝 [2]。錯誤:[3]。請連絡支援人員。</String>
+ <String Id="Error1907">無法註冊字型 [2]。 請確認是否有足夠的權限及系統支援。</String>
+ <String Id="Error1908">無法解除註冊字型 [2]。 請確認您有足夠的權限來移除字型。</String>
+ <String Id="Error1909">無法建立捷徑 [2]。 請確認目地資料夾是否存在及您的存取權。</String>
+ <String Id="Error1910">無法移除捷徑 [2]。 請確認目地資料夾是否存在及您的存取權。</String>
+ <String Id="Error1911">無法註冊檔案 [2] 的類型程式庫。 請連絡系統支援人員。</String>
+ <String Id="Error1912">無法解除註冊檔案 [2] 的 type library。 請連絡系統支援人員。</String>
+ <String Id="Error1913">無法更新 ini 檔 [2][3]。 請確認檔案是否存在及您的存取權。</String>
+ <String Id="Error1914">無法預定在重開機時將檔案 [2] 取代 [3]。 請確認您有 [3] 的存取權。</String>
+ <String Id="Error1915">移除 ODBC 驅動程式管理員錯誤,ODBC 錯誤 [2]:[3]。請連絡系統支援人員。</String>
+ <String Id="Error1916">安裝 ODBC 驅動程式管理員錯誤,ODBC 錯誤 [2]:[3]。請連絡系統支援人員。</String>
+ <String Id="Error1917">移除 ODBC 驅動程式管理員錯誤:[4],ODBC 錯誤 [2]:[3]。請確認您有足夠權限。</String>
+ <String Id="Error1918">安裝 ODBC 驅動程式管理員錯誤:[4],ODBC 錯誤 [2]:[3]。請確認檔案[4]存在並可存取。</String>
+ <String Id="Error1919">設定 ODBC 資料來源錯誤:[4],ODBC 錯誤 [2]:[3]。請確認檔案[4]存在並可存取。</String>
+ <String Id="Error1920">啟動服務 '[2]' ([3]) 失敗。 請確認您有足夠的特殊權限以啟動系統服務。</String>
+ <String Id="Error1921">停止服務 '[2]' ([3]) 失敗。 請確認您有足夠的特殊權限以啟動系統服務。</String>
+ <String Id="Error1922">刪除服務 '[2]' ([3]) 失敗。 請確認您有足夠的特殊權限以啟動系統服務。</String>
+ <String Id="Error1923">無法安裝服務 '[2]' ([3]) 。 請確認您有足夠的特殊權限以啟動系統服務。</String>
+ <String Id="Error1924">無法更新環境變數 '[2]'。 請確認您有足夠的特殊權限以修改環境變數。</String>
+ <String Id="Error1925">您沒有足夠的特殊權限使電腦的所有使用者都完成此安裝。請以系統管理員權限登入,接著再重試此安裝。</String>
+ <String Id="Error1926">無法設定檔案 '[3]' 的檔案安全性。 錯誤:[2]。 請確認您有足夠的特殊權限以修改此檔案的安全性權限。</String>
+ <String Id="Error1927">這台電腦並未安裝 Component Services (COM+ 1.0)。這項安裝需要有 Component Services 才能進行。Component Services 包含在 Windows XP 中。</String>
+ <String Id="Error1928">登錄 COM+ 應用程式時發生錯誤。請聯絡您的支援人員以取得其他資訊。</String>
+ <String Id="Error1929">解除 COM+ 應用程式登錄時發生錯誤。請聯絡您的支援人員以取得其他資訊。</String>
+ <String Id="Error1930">無法變更服務 '[2]' ([3]) 的描述。</String>
+ <String Id="Error1931">Windows Installer 服務無法更新系統檔案 [2] 因為檔案受 Windows 保護。 您可能需要更新您的作業系統使這個程式正確動作。 {{{封裝版本:[3],受 OS 保護的版本:[4]}}</String>
+ <String Id="Error1932">Windows Installer 服務無法更新受保護的 Windows 檔案 [2]。 {{封裝版本:[3],受 OS 保護的版本:[4],SFP 錯誤:[5]}}</String>
+ <String Id="Error1933">Windows Installer 服務無法更新一個或數個受保護的 Windows 檔案。 {{SFP 字串:[2]。 受保護的檔案清單:\r\n[3]}}</String>
+ <String Id="Error1934">電腦的原則停用使用者安裝。</String>
+ <String Id="Error1935">組件元件 [2] 的安裝期間發生錯誤。 HRESULT:[3]。 {{組件介面:[4],函數:[5],組件名稱:[6]}}</String>
+
+ <!-- Own / special errors -->
+ <String Id="Error25001">需要關閉應用程式 "[2]" 以繼續關閉。</String>
+
+ <String Id="ProgressTextInstallValidate">正在驗證安裝</String>
+ <String Id="ProgressTextInstallFiles">正在複製新檔案</String>
+ <String Id="ProgressTextInstallFilesTemplate">檔案:[1], 目錄:[9], 大小:[6]</String>
+ <String Id="ProgressTextInstallAdminPackage">正在複製網路安裝檔案</String>
+ <String Id="ProgressTextInstallAdminPackageTemplate">檔案:[1], 目錄:[9], 大小:[6]</String>
+ <String Id="ProgressTextFileCost">正在計算空間需求</String>
+ <String Id="ProgressTextCostInitialize">正在計算空間需求</String>
+ <String Id="ProgressTextCostFinalize">正在計算空間需求</String>
+ <String Id="ProgressTextCreateShortcuts">正在建立捷徑</String>
+ <String Id="ProgressTextCreateShortcutsTemplate">捷徑:[1]</String>
+ <String Id="ProgressTextPublishComponents">正在發佈合格的元件</String>
+ <String Id="ProgressTextPublishComponentsTemplate">元件 ID:[1], 公佈者:[2]</String>
+ <String Id="ProgressTextPublishFeatures">正在發佈產品功能</String>
+ <String Id="ProgressTextPublishFeaturesTemplate">功能:[1]</String>
+ <String Id="ProgressTextPublishProduct">正在發佈產品資訊</String>
+ <String Id="ProgressTextRegisterClassInfo">正在登錄類別伺服器</String>
+ <String Id="ProgressTextRegisterClassInfoTemplate">類別 Id:[1]</String>
+ <String Id="ProgressTextRegisterExtensionInfo">正在登錄擴充伺服器</String>
+ <String Id="ProgressTextRegisterExtensionInfoTemplate">副檔名 [1]</String>
+ <String Id="ProgressTextRegisterMIMEInfo">正在登錄 MIME 資訊</String>
+ <String Id="ProgressTextRegisterMIMEInfoTemplate">MIME 內容類型:[1],副檔名:[2]</String>
+ <String Id="ProgressTextRegisterProgIdInfo">正在登錄程式辨識字元</String>
+ <String Id="ProgressTextRegisterProgIdInfoTemplate">ProgId: [1]</String>
+ <String Id="ProgressTextAllocateRegistrySpace">正在配置登錄空間</String>
+ <String Id="ProgressTextAllocateRegistrySpaceTemplate">可用空間:[1]</String>
+ <String Id="ProgressTextAppSearch">正在搜尋已安裝的應用程式</String>
+ <String Id="ProgressTextAppSearchTemplate">內容:[1], 簽章:[2]</String>
+ <String Id="ProgressTextBindImage">正在繫結執行檔</String>
+ <String Id="ProgressTextBindImageTemplate">檔案:[1]</String>
+ <String Id="ProgressTextCCPSearch">正在搜尋查詢產品</String>
+ <String Id="ProgressTextCreateFolders">正在建立資料夾</String>
+ <String Id="ProgressTextCreateFoldersTemplate">資料夾:[1]</String>
+ <String Id="ProgressTextDeleteServices">正在刪除服務</String>
+ <String Id="ProgressTextDeleteServicesTemplate">服務:[1]</String>
+ <String Id="ProgressTextDuplicateFiles">正在建立重複檔案</String>
+ <String Id="ProgressTextDuplicateFilesTemplate">檔案:[1], 目錄:[9], 大小:[6]</String>
+ <String Id="ProgressTextFindRelatedProducts">正在搜尋相關的應用程式</String>
+ <String Id="ProgressTextFindRelatedProductsTemplate">找到應用程式:[1]</String>
+ <String Id="ProgressTextInstallODBC">正在安裝 ODBC 元件</String>
+ <String Id="ProgressTextInstallServices">正在安裝新服務</String>
+ <String Id="ProgressTextInstallServicesTemplate">服務:[2]</String>
+ <String Id="ProgressTextLaunchConditions">正在評估啟動條件</String>
+ <String Id="ProgressTextMigrateFeatureStates">正在從相關的應用程式遷移功能狀態</String>
+ <String Id="ProgressTextMigrateFeatureStatesTemplate">應用程式:[1]</String>
+ <String Id="ProgressTextMoveFiles">正在移動檔案</String>
+ <String Id="ProgressTextMoveFilesTemplate">檔案:[1], 目錄:[9], 大小:[6]</String>
+ <String Id="ProgressTextPatchFiles">正在修補檔案</String>
+ <String Id="ProgressTextPatchFilesTemplate">檔案:[1], 目錄:[2], 大小:[3]</String>
+ <String Id="ProgressTextProcessComponents">正在更新元件註冊</String>
+ <String Id="ProgressTextRegisterComPlus">正在註冊 COM+ 應用程式和元件</String>
+ <String Id="ProgressTextRegisterComPlusTemplate">AppId:[1]{{, AppType:[2],使用者:[3],RSN:[4]}}</String>
+ <String Id="ProgressTextRegisterFonts">正在註冊字型</String>
+ <String Id="ProgressTextRegisterFontsTemplate">字型:[1]</String>
+ <String Id="ProgressTextRegisterProduct">正在註冊產品</String>
+ <String Id="ProgressTextRegisterProductTemplate">[1]</String>
+ <String Id="ProgressTextRegisterTypeLibraries">正在登錄類別程式庫</String>
+ <String Id="ProgressTextRegisterTypeLibrariesTemplate">LibID: [1]</String>
+ <String Id="ProgressTextRegisterUser">正在登錄使用者</String>
+ <String Id="ProgressTextRegisterUserTemplate">[1]</String>
+ <String Id="ProgressTextRemoveDuplicateFiles">正在移除重複的檔案</String>
+ <String Id="ProgressTextRemoveDuplicateFilesTemplate">檔案:[1], 目錄:[9]</String>
+ <String Id="ProgressTextRemoveEnvironmentStrings">正在更新環境字串</String>
+ <String Id="ProgressTextRemoveEnvironmentStringsTemplate">名稱:[1], 數值:[2], 動作:[3]</String>
+ <String Id="ProgressTextRemoveExistingProducts">正在移除應用程式</String>
+ <String Id="ProgressTextRemoveExistingProductsTemplate">應用程式:[1], 命令列:[2]</String>
+ <String Id="ProgressTextRemoveFiles">正在移除檔案</String>
+ <String Id="ProgressTextRemoveFilesTemplate">檔案:[1], 目錄:[9]</String>
+ <String Id="ProgressTextRemoveFolders">正在移除資料夾</String>
+ <String Id="ProgressTextRemoveFoldersTemplate">資料夾:[1]</String>
+ <String Id="ProgressTextRemoveIniValues">正在移除 INI 檔案項目</String>
+ <String Id="ProgressTextRemoveIniValuesTemplate">檔案:[1], 區段:[2], 機碼:[3], 數值:[4]</String>
+ <String Id="ProgressTextRemoveODBC">正在移除 ODBC 元件</String>
+ <String Id="ProgressTextRemoveRegistryValues">正在移除系統登錄檔數值</String>
+ <String Id="ProgressTextRemoveRegistryValuesTemplate">機碼:[1], 名稱:[2]</String>
+ <String Id="ProgressTextRemoveShortcuts">正在移除捷徑</String>
+ <String Id="ProgressTextRemoveShortcutsTemplate">捷徑:[1]</String>
+ <String Id="ProgressTextRMCCPSearch">正在搜尋查詢產品</String>
+ <String Id="ProgressTextSelfRegModules">正在註冊模組</String>
+ <String Id="ProgressTextSelfRegModulesTemplate">檔案:[1], 資料夾:[2]</String>
+ <String Id="ProgressTextSelfUnregModules">正在解除模組登錄</String>
+ <String Id="ProgressTextSelfUnregModulesTemplate">檔案:[1], 資料夾:[2]</String>
+ <String Id="ProgressTextSetODBCFolders">正在初始化 ODBC 目錄</String>
+ <String Id="ProgressTextStartServices">正在啟動服務</String>
+ <String Id="ProgressTextStartServicesTemplate">服務:[1]</String>
+ <String Id="ProgressTextStopServices">正在停止服務</String>
+ <String Id="ProgressTextStopServicesTemplate">服務:[1]</String>
+ <String Id="ProgressTextUnpublishComponents">正在取消元件公佈</String>
+ <String Id="ProgressTextUnpublishComponentsTemplate">元件 ID:[1], 公佈者:[2]</String>
+ <String Id="ProgressTextUnpublishFeatures">正在取消功能公佈</String>
+ <String Id="ProgressTextUnpublishFeaturesTemplate">功能:[1]</String>
+ <String Id="ProgressTextUnregisterClassInfo">解除類別伺服器登錄</String>
+ <String Id="ProgressTextUnregisterClassInfoTemplate">類別 Id:[1]</String>
+ <String Id="ProgressTextUnregisterComPlus">正在解除 COM+ 應用程式和元件登錄</String>
+ <String Id="ProgressTextUnregisterComPlusTemplate">AppId: [1]{{, AppType: [2]}}</String>
+ <String Id="ProgressTextUnregisterExtensionInfo">正在解除擴充伺服器登錄</String>
+ <String Id="ProgressTextUnregisterExtensionInfoTemplate">副檔名 [1]</String>
+ <String Id="ProgressTextUnregisterFonts">正在解除字型登錄</String>
+ <String Id="ProgressTextUnregisterFontsTemplate">字型:[1]</String>
+ <String Id="ProgressTextUnregisterMIMEInfo">正在解除 MIME 資訊登錄</String>
+ <String Id="ProgressTextUnregisterMIMEInfoTemplate">MIME 內容類型:[1],副檔名:[2]</String>
+ <String Id="ProgressTextUnregisterProgIdInfo">正在解除程式識別碼登錄</String>
+ <String Id="ProgressTextUnregisterProgIdInfoTemplate">ProgId: [1]</String>
+ <String Id="ProgressTextUnregisterTypeLibraries">正在解除類別程式庫登錄</String>
+ <String Id="ProgressTextUnregisterTypeLibrariesTemplate">LibID: [1]</String>
+ <String Id="ProgressTextWriteEnvironmentStrings">正在更新環境字串</String>
+ <String Id="ProgressTextWriteEnvironmentStringsTemplate">名稱:[1], 數值:[2], 動作:[3]</String>
+ <String Id="ProgressTextWriteIniValues">正在寫入 INI 檔案數值</String>
+ <String Id="ProgressTextWriteIniValuesTemplate">檔案:[1], 區段:[2], 機碼:[3], 數值:[4]</String>
+ <String Id="ProgressTextWriteRegistryValues">正在寫入系統登錄檔數值</String>
+ <String Id="ProgressTextWriteRegistryValuesTemplate">機碼:[1],名稱:[2],值:[3]</String>
+ <String Id="ProgressTextAdvertise">正在宣告應用程式</String>
+ <String Id="ProgressTextGenerateScript">正在產生動作的 script 操作:</String>
+ <String Id="ProgressTextGenerateScriptTemplate">[1]</String>
+ <String Id="ProgressTextInstallSFPCatalogFile">正在安裝系統目錄</String>
+ <String Id="ProgressTextInstallSFPCatalogFileTemplate">檔案:[1],依存關係:[2]</String>
+ <String Id="ProgressTextMsiPublishAssemblies">正在發佈組件資訊</String>
+ <String Id="ProgressTextMsiPublishAssembliesTemplate">應用程式內容:[1],組件名稱:[2]</String>
+ <String Id="ProgressTextMsiUnpublishAssemblies">正在取消資訊公佈</String>
+ <String Id="ProgressTextMsiUnpublishAssembliesTemplate">應用程式內容:[1],組件名稱:[2]</String>
+ <String Id="ProgressTextRollback">回復動作:</String>
+ <String Id="ProgressTextRollbackTemplate">[1]</String>
+ <String Id="ProgressTextRollbackCleanup">正在移除備份檔案</String>
+ <String Id="ProgressTextRollbackCleanupTemplate">檔案:[1]</String>
+ <String Id="ProgressTextUnmoveFiles">正在移除移動的檔案</String>
+ <String Id="ProgressTextUnmoveFilesTemplate">檔案:[1], 目錄:[9]</String>
+ <String Id="ProgressTextUnpublishProduct">正在取消發佈產品資訊</String>
+
+ <String Id="UITextbytes">位元組</String>
+ <String Id="UITextGB">GB</String>
+ <String Id="UITextKB">KB</String>
+ <String Id="UITextMB">MB</String>
+ <String Id="UITextMenuAbsent">整個功能將不可用</String>
+ <String Id="UITextMenuAdvertise">需要時將安裝的功能</String>
+ <String Id="UITextMenuAllCD">整個功能將會安裝成從 CD 上執行</String>
+ <String Id="UITextMenuAllLocal">整個功能將會安裝到本機硬碟</String>
+ <String Id="UITextMenuAllNetwork">整個功能將會安裝成從網路上執行</String>
+ <String Id="UITextMenuCD">將會安裝成從 CD 上執行</String>
+ <String Id="UITextMenuLocal">將會安裝到本機硬碟</String>
+ <String Id="UITextMenuNetwork">將會安裝成從網路執行</String>
+ <String Id="UITextScriptInProgress">正在收集所需的資訊...</String>
+ <String Id="UITextSelAbsentAbsent">這個功能將保持未安裝的狀態</String>
+ <String Id="UITextSelAbsentAdvertise">這個功能會設定成視需要進行安裝</String>
+ <String Id="UITextSelAbsentCD">這個功能將會安裝成從 CD 執行</String>
+ <String Id="UITextSelAbsentLocal">這個功能將會安裝在本機硬碟中</String>
+ <String Id="UITextSelAbsentNetwork">這個功能將會安裝成從網路執行</String>
+ <String Id="UITextSelAdvertiseAbsent">這個功能將無法使用</String>
+ <String Id="UITextSelAdvertiseAdvertise">將會視需要進行安裝</String>
+ <String Id="UITextSelAdvertiseCD">這個功能可以從 CD 上執行</String>
+ <String Id="UITextSelAdvertiseLocal">這個功能將安裝在您的本機硬碟</String>
+ <String Id="UITextSelAdvertiseNetwork">這個功能可以從網路執行</String>
+ <String Id="UITextSelCDAbsent">這個功能將完整解除安裝,您將不能從 CD 執行</String>
+ <String Id="UITextSelCDAdvertise">這個功能會從 CD 執行變更成視需要進行安裝</String>
+ <String Id="UITextSelCDCD">這個功能仍將從 CD 執行</String>
+ <String Id="UITextSelCDLocal">這個功能將會從 CD 執行變更為安裝在本機硬碟中</String>
+ <String Id="UITextSelChildCostNeg">這個功能會在您的硬碟釋放 [1] 。</String>
+ <String Id="UITextSelChildCostPos">這個功能要求 [1] 在您的硬碟上。</String>
+ <String Id="UITextSelCostPending">正在編譯這個功能的花費...</String>
+ <String Id="UITextSelLocalAbsent">這個功能將會完整移除</String>
+ <String Id="UITextSelLocalAdvertise">這個功能會從您的本機硬碟上移除,但是會設定成視需要進行安裝</String>
+ <String Id="UITextSelLocalCD">這個功能將會從您的本機硬碟中移除,但是仍然可以從 CD 執行</String>
+ <String Id="UITextSelLocalLocal">這個功能將會保留在您的本機硬碟中</String>
+ <String Id="UITextSelLocalNetwork">這個功能將會從您的本機硬碟中移除,但是仍然可從網路上執行</String>
+ <String Id="UITextSelNetworkAbsent">這個功能將完整解除安裝,您將不能從網路執行</String>
+ <String Id="UITextSelNetworkAdvertise">這個功能將會從網路執行變更成視需要進行安裝</String>
+ <String Id="UITextSelNetworkLocal">這個功能將會從網路執行變更為安裝在本機硬碟中。</String>
+ <String Id="UITextSelNetworkNetwork">這個功能仍將保留成從網路執行</String>
+ <String Id="UITextSelParentCostNegNeg">這個功能在您的硬碟釋放 [1]。 它已選取 [2] 之 [3] 子功能。 子功能在您的硬碟釋放 [4] 。</String>
+ <String Id="UITextSelParentCostNegPos">這個功能在您的硬碟釋放 [1]。 它已選取 [2] 之 [3] 子功能。 子功能在您的硬碟需要 [4] 。</String>
+ <String Id="UITextSelParentCostPosNeg">這個功能在您的硬碟需要 [1]。 它已選取 [2] 之 [3] 子功能。 子功能在您的硬碟釋放 [4] 。</String>
+ <String Id="UITextSelParentCostPosPos">這個功能在您的硬碟需要 [1]。 它已選取 [2] 之 [3] 子功能。 子功能在您的硬碟需要 [4] 。</String>
+ <String Id="UITextTimeRemaining">剩餘時間:{[1] 分 }{[2] 秒}</String>
+ <String Id="UITextVolumeCostAvailable">可用</String>
+ <String Id="UITextVolumeCostDifference">差異</String>
+ <String Id="UITextVolumeCostRequired">需求</String>
+ <String Id="UITextVolumeCostSize">磁碟大小</String>
+ <String Id="UITextVolumeCostVolume">分割區</String>
+
+</WixLocalization>
diff --git a/src/VBox/Installer/win/Resources/resource.h b/src/VBox/Installer/win/Resources/resource.h index e2ea716e..ddc26153 100644 --- a/src/VBox/Installer/win/Resources/resource.h +++ b/src/VBox/Installer/win/Resources/resource.h @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2010 Oracle Corporation + * Copyright (C) 2010-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/win/Stub/Makefile.kmk b/src/VBox/Installer/win/Stub/Makefile.kmk index a2420c3f..5117edd3 100644 --- a/src/VBox/Installer/win/Stub/Makefile.kmk +++ b/src/VBox/Installer/win/Stub/Makefile.kmk @@ -21,43 +21,61 @@ include $(KBUILD_PATH)/subheader.kmk # This has to be 32-bit, so don't include it in the 64-bit build. if "$(KBUILD_TARGET_ARCH)" == "x86" -TEMPLATE_VBOXSTUB = Drop the signing, we will sign it later. -TEMPLATE_VBOXSTUB_EXTENDS = VBOXR3STATIC -TEMPLATE_VBOXSTUB_POST_CMDS = $(NO_SUCH_VARIABLE) - -PROGRAMS.x86 += VBoxStub -VBoxStub_TEMPLATE= VBOXSTUB -VBoxStub_DEFS = _WIN32_WINNT=0x0501 IN_RT_R3 -VBoxStub_SOURCES = \ - VBoxStub.cpp \ - VBoxStub.rc -VBoxStub_SDKS += \ - VBOX_NTDLL -VBoxStub_LIBS = \ - $(VBOX_LIB_RUNTIME_STATIC) \ - $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/Msi.lib - -VBoxStub.cpp_DEFS += VBOX_SVN_REV=$(VBOX_SVN_REV) -VBoxStub.cpp_DEPS = $(VBOX_SVN_REV_KMK) - -# The icon location is configurable. -VBoxStub.rc_INCS += $(VBoxStub_0_OUTDIR) -VBoxStub.rc_DEPS += \ - $(VBoxStub_0_OUTDIR)/VBoxStub-icon.rc \ - $(VBoxStub_0_OUTDIR)/VBoxStub-manifest.rc -VBoxStub.rc_CLEAN = \ - $(VBoxStub_0_OUTDIR)/VBoxStub-icon.rc \ - $(VBoxStub_0_OUTDIR)/VBoxStub-manifest.rc - -# Icon include file. -$$(VBoxStub_0_OUTDIR)/VBoxStub-icon.rc: $(VBOX_WINDOWS_ICON_FILE) $(MAKEFILE_CURRENT) | $$(dir $$@) + TEMPLATE_VBOXSTUB = Drop the signing, we will sign it later. + TEMPLATE_VBOXSTUB_EXTENDS = VBOXR3STATIC + TEMPLATE_VBOXSTUB_POST_CMDS = $(NO_SUCH_VARIABLE) + + PROGRAMS += VBoxStub + VBoxStub_TEMPLATE= VBOXSTUB + VBoxStub_DEFS = _WIN32_WINNT=0x0501 IN_RT_R3 + + VBoxStub_SOURCES = \ + VBoxStub.cpp \ + VBoxStub.rc + + VBoxStub_SDKS += \ + VBOX_NTDLL + VBoxStub_LIBS = \ + $(VBOX_LIB_RUNTIME_STATIC) \ + $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/Msi.lib + + VBoxStub.cpp_DEFS += VBOX_SVN_REV=$(VBOX_SVN_REV) + VBoxStub.cpp_DEPS = $(VBOX_SVN_REV_KMK) + + # If signing mode is enabled, then add the possibility to + # install public certificate automatically in /silent mode + ifdef VBOX_SIGNING_MODE + + VBoxStub_SOURCES += VBoxStubCertUtil.cpp + VBoxStub_LIBS += crypt32.lib + VBoxStub.cpp_DEPS += $(VBoxStub_0_OUTDIR)/VBoxStubPublicCert.h + VBoxStub.cpp_INCS += $(VBoxStub_0_OUTDIR) + VBoxStub.cpp_DEFS += VBOX_WITH_CODE_SIGNING + + $$(VBoxStub_0_OUTDIR)/VBoxStubPublicCert.h: $(VBOX_BIN2C) $(PATH_ROOT)/src/VBox/Additions/WINNT/tools/oracle-vbox.cer | $$(dir $$@) + $(VBOX_BIN2C) _VBoxStubPublicCert $(PATH_ROOT)/src/VBox/Additions/WINNT/tools/oracle-vbox.cer $@ + + endif + + # The icon location is configurable. + VBoxStub.rc_INCS += $(VBoxStub_0_OUTDIR) + VBoxStub.rc_DEPS += \ + $(VBoxStub_0_OUTDIR)/VBoxStub-icon.rc \ + $(VBoxStub_0_OUTDIR)/VBoxStub-manifest.rc + VBoxStub.rc_CLEAN = \ + $(VBoxStub_0_OUTDIR)/VBoxStub-icon.rc \ + $(VBoxStub_0_OUTDIR)/VBoxStub-manifest.rc + + # Icon include file. + $$(VBoxStub_0_OUTDIR)/VBoxStub-icon.rc: $(VBOX_WINDOWS_ICON_FILE) $(MAKEFILE_CURRENT) | $$(dir $$@) $(APPEND) -t $@ 'IDI_VIRTUALBOX ICON DISCARDABLE "$(subst /,\\,$(VBOX_WINDOWS_ICON_FILE))"' -# Manifest. -VBOX_STUB_MANIFEST_FILE := $(PATH_SUB_CURRENT)/VBoxStub.manifest -$$(VBoxStub_0_OUTDIR)/VBoxStub-manifest.rc: $(VBOX_STUB_MANIFEST_FILE) $(MAKEFILE_CURRENT) | $$(dir $$@) + # Manifest. + VBOX_STUB_MANIFEST_FILE := $(PATH_SUB_CURRENT)/VBoxStub.manifest + $$(VBoxStub_0_OUTDIR)/VBoxStub-manifest.rc: $(VBOX_STUB_MANIFEST_FILE) $(MAKEFILE_CURRENT) | $$(dir $$@) $(APPEND) -t $@ 'APP_MANIFEST RT_MANIFEST "$(subst /,\\,$(VBOX_STUB_MANIFEST_FILE))"' + endif # x86 only include $(FILE_KBUILD_SUB_FOOTER) diff --git a/src/VBox/Installer/win/Stub/VBoxStub.cpp b/src/VBox/Installer/win/Stub/VBoxStub.cpp index 22b9bccb..188bf5e6 100644 --- a/src/VBox/Installer/win/Stub/VBoxStub.cpp +++ b/src/VBox/Installer/win/Stub/VBoxStub.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2010 Oracle Corporation + * Copyright (C) 2010-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; @@ -18,11 +18,12 @@ /******************************************************************************* * Header Files * *******************************************************************************/ -#include <windows.h> +#include <Windows.h> #include <commctrl.h> #include <lmerr.h> #include <msiquery.h> #include <objbase.h> + #include <shlobj.h> #include <stdlib.h> #include <stdio.h> @@ -34,10 +35,14 @@ #include <iprt/assert.h> #include <iprt/dir.h> #include <iprt/file.h> +#include <iprt/getopt.h> #include <iprt/initterm.h> +#include <iprt/list.h> #include <iprt/mem.h> -#include <iprt/path.h> +#include <iprt/message.h> #include <iprt/param.h> +#include <iprt/path.h> +#include <iprt/stream.h> #include <iprt/string.h> #include <iprt/thread.h> @@ -45,109 +50,192 @@ #include "../StubBld/VBoxStubBld.h" #include "resource.h" -#ifndef _UNICODE -#define _UNICODE +#ifdef VBOX_WITH_CODE_SIGNING +# include "VBoxStubCertUtil.h" +# include "VBoxStubPublicCert.h" #endif +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +#define MY_UNICODE_SUB(str) L ##str +#define MY_UNICODE(str) MY_UNICODE_SUB(str) + + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ /** - * Shows a message box with a printf() style formatted string. - * - * @returns Message box result (IDOK, IDCANCEL, ...). - * - * @param uType Type of the message box (see MSDN). - * @param pszFmt Printf-style format string to show in the message box body. - * + * Cleanup record. */ -static int ShowInfo(const char *pszFmt, ...) +typedef struct STUBCLEANUPREC { - char *pszMsg; - va_list va; + /** List entry. */ + RTLISTNODE ListEntry; + /** True if file, false if directory. */ + bool fFile; + /** The path to the file or directory to clean up. */ + char szPath[1]; +} STUBCLEANUPREC; +/** Pointer to a cleanup record. */ +typedef STUBCLEANUPREC *PSTUBCLEANUPREC; - va_start(va, pszFmt); - RTStrAPrintfV(&pszMsg, pszFmt, va); - va_end(va); - int rc; - if (pszMsg) - rc = MessageBox(GetDesktopWindow(), pszMsg, VBOX_STUB_TITLE, MB_ICONINFORMATION); - else - rc = MessageBox(GetDesktopWindow(), pszFmt, VBOX_STUB_TITLE, MB_ICONINFORMATION); - RTStrFree(pszMsg); - return rc; -} +/******************************************************************************* +* Global Variables * +*******************************************************************************/ +/** Whether it's a silent or interactive GUI driven install. */ +static bool g_fSilent = false; +/** List of temporary files. */ +static RTLISTANCHOR g_TmpFiles; + /** * Shows an error message box with a printf() style formatted string. * - * @returns Message box result (IDOK, IDCANCEL, ...). - * + * @returns RTEXITCODE_FAILURE * @param pszFmt Printf-style format string to show in the message box body. * */ -static int ShowError(const char *pszFmt, ...) +static RTEXITCODE ShowError(const char *pszFmt, ...) { char *pszMsg; va_list va; - int rc; va_start(va, pszFmt); if (RTStrAPrintfV(&pszMsg, pszFmt, va)) { - rc = MessageBox(GetDesktopWindow(), pszMsg, VBOX_STUB_TITLE, MB_ICONERROR); + if (g_fSilent) + RTMsgError("%s", pszMsg); + else + { + PRTUTF16 pwszMsg; + int rc = RTStrToUtf16(pszMsg, &pwszMsg); + if (RT_SUCCESS(rc)) + { + MessageBoxW(GetDesktopWindow(), pwszMsg, MY_UNICODE(VBOX_STUB_TITLE), MB_ICONERROR); + RTUtf16Free(pwszMsg); + } + else + MessageBoxA(GetDesktopWindow(), pszMsg, VBOX_STUB_TITLE, MB_ICONERROR); + } RTStrFree(pszMsg); } else /* Should never happen! */ AssertMsgFailed(("Failed to format error text of format string: %s!\n", pszFmt)); va_end(va); - return rc; + return RTEXITCODE_FAILURE; } /** - * Reads data from a built-in resource. - * - * @returns iprt status code. + * Shows a message box with a printf() style formatted string. * - * @param hInst Instance to read the data from. - * @param pszDataName Name of resource to read. - * @param ppvResource Pointer to buffer which holds the read resource data. - * @param pdwSize Pointer which holds the read data size. + * @param uType Type of the message box (see MSDN). + * @param pszFmt Printf-style format string to show in the message box body. * */ -static int ReadData(HINSTANCE hInst, - const char *pszDataName, - PVOID *ppvResource, - DWORD *pdwSize) +static void ShowInfo(const char *pszFmt, ...) { - do + char *pszMsg; + va_list va; + va_start(va, pszFmt); + int rc = RTStrAPrintfV(&pszMsg, pszFmt, va); + va_end(va); + if (rc >= 0) { - AssertMsgBreak(pszDataName, ("Resource name is empty!\n")); + if (g_fSilent) + RTPrintf("%s\n", pszMsg); + else + { + PRTUTF16 pwszMsg; + int rc = RTStrToUtf16(pszMsg, &pwszMsg); + if (RT_SUCCESS(rc)) + { + MessageBoxW(GetDesktopWindow(), pwszMsg, MY_UNICODE(VBOX_STUB_TITLE), MB_ICONINFORMATION); + RTUtf16Free(pwszMsg); + } + else + MessageBoxA(GetDesktopWindow(), pszMsg, VBOX_STUB_TITLE, MB_ICONINFORMATION); + } + } + else /* Should never happen! */ + AssertMsgFailed(("Failed to format error text of format string: %s!\n", pszFmt)); + RTStrFree(pszMsg); +} - /* Find our resource. */ - HRSRC hRsrc = FindResourceEx(hInst, RT_RCDATA, pszDataName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)); - AssertMsgBreak(hRsrc, ("Could not find resource!\n")); - /* Get resource size. */ - *pdwSize = SizeofResource(hInst, hRsrc); - AssertMsgBreak(*pdwSize > 0, ("Size of resource is invalid!\n")); +/** + * Finds the specified in the resource section of the executable. + * + * @returns IPRT status code. + * + * @param pszDataName Name of resource to read. + * @param ppvResource Where to return the pointer to the data. + * @param pdwSize Where to return the size of the data (if found). + * Optional. + */ +static int FindData(const char *pszDataName, PVOID *ppvResource, DWORD *pdwSize) +{ + AssertReturn(pszDataName, VERR_INVALID_PARAMETER); + HINSTANCE hInst = NULL; /* indicates the executable image */ + + /* Find our resource. */ + PRTUTF16 pwszDataName; + int rc = RTStrToUtf16(pszDataName, &pwszDataName); + AssertRCReturn(rc, rc); + HRSRC hRsrc = FindResourceExW(hInst, + (LPWSTR)RT_RCDATA, + pwszDataName, + MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)); + RTUtf16Free(pwszDataName); + AssertReturn(hRsrc, VERR_IO_GEN_FAILURE); + + /* Get resource size. */ + DWORD cb = SizeofResource(hInst, hRsrc); + AssertReturn(cb > 0, VERR_NO_DATA); + if (pdwSize) + *pdwSize = cb; + + /* Get pointer to resource. */ + HGLOBAL hData = LoadResource(hInst, hRsrc); + AssertReturn(hData, VERR_IO_GEN_FAILURE); + + /* Lock resource. */ + *ppvResource = LockResource(hData); + AssertReturn(*ppvResource, VERR_IO_GEN_FAILURE); + return VINF_SUCCESS; +} - /* Get pointer to resource. */ - HGLOBAL hData = LoadResource(hInst, hRsrc); - AssertMsgBreak(hData, ("Could not load resource!\n")); - /* Lock resource. */ - *ppvResource = LockResource(hData); - AssertMsgBreak(*ppvResource, ("Could not lock resource!\n")); - return VINF_SUCCESS; +/** + * Finds the header for the given package. + * + * @returns Pointer to the package header on success. On failure NULL is + * returned after ShowError has been invoked. + * @param iPackage The package number. + */ +static PVBOXSTUBPKG FindPackageHeader(unsigned iPackage) +{ + char szHeaderName[32]; + RTStrPrintf(szHeaderName, sizeof(szHeaderName), "HDR_%02d", iPackage); - } while (0); + PVBOXSTUBPKG pPackage; + int rc = FindData(szHeaderName, (PVOID *)&pPackage, NULL); + if (RT_FAILURE(rc)) + { + ShowError("Internal error: Could not find package header #%u: %Rrc", iPackage, rc); + return NULL; + } - return VERR_IO_GEN_FAILURE; + /** @todo validate it. */ + return pPackage; } + /** * Constructs a full temporary file path from the given parameters. * @@ -192,7 +280,7 @@ static int ExtractFile(const char *pszResourceName, /* Read the data of the built-in resource. */ PVOID pvData = NULL; DWORD dwDataSize = 0; - rc = ReadData(NULL, pszResourceName, &pvData, &dwDataSize); + rc = FindData(pszResourceName, &pvData, &dwDataSize); AssertMsgRCBreak(rc, ("Could not read resource data!\n")); /* Create new (and replace an old) file. */ @@ -266,61 +354,427 @@ static BOOL IsWow64(void) /** * Decides whether we need a specified package to handle or not. * - * @returns TRUE if we need to handle the specified package, FALSE if not. + * @returns @c true if we need to handle the specified package, @c false if not. * * @param pPackage Pointer to a VBOXSTUBPKG struct that contains the resource. * */ -static BOOL PackageIsNeeded(PVBOXSTUBPKG pPackage) +static bool PackageIsNeeded(PVBOXSTUBPKG pPackage) { - BOOL bIsWow64 = IsWow64(); - if ((bIsWow64 && pPackage->byArch == VBOXSTUBPKGARCH_AMD64)) /* 64bit Windows. */ + if (pPackage->byArch == VBOXSTUBPKGARCH_ALL) + return true; + VBOXSTUBPKGARCH enmArch = IsWow64() ? VBOXSTUBPKGARCH_AMD64 : VBOXSTUBPKGARCH_X86; + return pPackage->byArch == enmArch; +} + + +/** + * Adds a cleanup record. + * + * @returns Fully complained boolean success indicator. + * @param pszPath The path to the file or directory to clean up. + * @param fFile @c true if file, @c false if directory. + */ +static bool AddCleanupRec(const char *pszPath, bool fFile) +{ + size_t cchPath = strlen(pszPath); Assert(cchPath > 0); + PSTUBCLEANUPREC pRec = (PSTUBCLEANUPREC)RTMemAlloc(RT_OFFSETOF(STUBCLEANUPREC, szPath[cchPath + 1])); + if (!pRec) { - return TRUE; + ShowError("Out of memory!"); + return false; } - else if ((!bIsWow64 && pPackage->byArch == VBOXSTUBPKGARCH_X86)) /* 32bit. */ + pRec->fFile = fFile; + memcpy(pRec->szPath, pszPath, cchPath + 1); + + RTListPrepend(&g_TmpFiles, &pRec->ListEntry); + return true; +} + + +/** + * Cleans up all the extracted files and optionally removes the package + * directory. + * + * @param cPackages The number of packages. + * @param pszPkgDir The package directory, NULL if it shouldn't be + * removed. + */ +static void CleanUp(unsigned cPackages, const char *pszPkgDir) +{ + for (int i = 0; i < 5; i++) { - return TRUE; + int rc; + bool fFinalTry = i == 4; + + PSTUBCLEANUPREC pCur, pNext; + RTListForEachSafe(&g_TmpFiles, pCur, pNext, STUBCLEANUPREC, ListEntry) + { + if (pCur->fFile) + rc = RTFileDelete(pCur->szPath); + else + { + rc = RTDirRemoveRecursive(pCur->szPath, RTDIRRMREC_F_CONTENT_AND_DIR); + if (rc == VERR_DIR_NOT_EMPTY && fFinalTry) + rc = VINF_SUCCESS; + } + if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND) + rc = VINF_SUCCESS; + if (RT_SUCCESS(rc)) + { + RTListNodeRemove(&pCur->ListEntry); + RTMemFree(pCur); + } + else if (fFinalTry) + { + if (pCur->fFile) + ShowError("Failed to delete temporary file '%s': %Rrc", pCur->szPath, rc); + else + ShowError("Failed to delete temporary directory '%s': %Rrc", pCur->szPath, rc); + } + } + + if (RTListIsEmpty(&g_TmpFiles) || fFinalTry) + { + if (!pszPkgDir) + return; + rc = RTDirRemove(pszPkgDir); + if (RT_SUCCESS(rc) || rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND || fFinalTry) + return; + } + + /* Delay a little and try again. */ + RTThreadSleep(i == 0 ? 100 : 3000); + } +} + + +/** + * Processes an MSI package. + * + * @returns Fully complained exit code. + * @param pszMsi The path to the MSI to process. + * @param pszMsiArgs Any additional installer (MSI) argument + * @param fLogging Whether to enable installer logging. + */ +static RTEXITCODE ProcessMsiPackage(const char *pszMsi, const char *pszMsiArgs, bool fLogging) +{ + int rc; + + /* + * Set UI level. + */ + INSTALLUILEVEL enmDesiredUiLevel = g_fSilent ? INSTALLUILEVEL_NONE : INSTALLUILEVEL_FULL; + INSTALLUILEVEL enmRet = MsiSetInternalUI(enmDesiredUiLevel, NULL); + if (enmRet == INSTALLUILEVEL_NOCHANGE /* means error */) + return ShowError("Internal error: MsiSetInternalUI failed."); + + /* + * Enable logging? + */ + if (fLogging) + { + char szLogFile[RTPATH_MAX]; + rc = RTStrCopy(szLogFile, sizeof(szLogFile), pszMsi); + if (RT_SUCCESS(rc)) + { + RTPathStripFilename(szLogFile); + rc = RTPathAppend(szLogFile, sizeof(szLogFile), "VBoxInstallLog.txt"); + } + if (RT_FAILURE(rc)) + return ShowError("Internal error: Filename path too long."); + + PRTUTF16 pwszLogFile; + rc = RTStrToUtf16(szLogFile, &pwszLogFile); + if (RT_FAILURE(rc)) + return ShowError("RTStrToUtf16 failed on '%s': %Rrc", szLogFile, rc); + + UINT uLogLevel = MsiEnableLogW(INSTALLLOGMODE_VERBOSE, + pwszLogFile, + INSTALLLOGATTRIBUTES_FLUSHEACHLINE); + RTUtf16Free(pwszLogFile); + if (uLogLevel != ERROR_SUCCESS) + return ShowError("MsiEnableLogW failed"); } - else if (pPackage->byArch == VBOXSTUBPKGARCH_ALL) + + /* + * Initialize the common controls (extended version). This is necessary to + * run the actual .MSI installers with the new fancy visual control + * styles (XP+). Also, an integrated manifest is required. + */ + INITCOMMONCONTROLSEX ccEx; + ccEx.dwSize = sizeof(INITCOMMONCONTROLSEX); + ccEx.dwICC = ICC_LINK_CLASS | ICC_LISTVIEW_CLASSES | ICC_PAGESCROLLER_CLASS | + ICC_PROGRESS_CLASS | ICC_STANDARD_CLASSES | ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES | + ICC_UPDOWN_CLASS | ICC_USEREX_CLASSES | ICC_WIN95_CLASSES; + InitCommonControlsEx(&ccEx); /* Ignore failure. */ + + /* + * Convert both strings to UTF-16 and start the installation. + */ + PRTUTF16 pwszMsi; + rc = RTStrToUtf16(pszMsi, &pwszMsi); + if (RT_FAILURE(rc)) + return ShowError("RTStrToUtf16 failed on '%s': %Rrc", pszMsi, rc); + PRTUTF16 pwszMsiArgs; + rc = RTStrToUtf16(pszMsiArgs, &pwszMsiArgs); + if (RT_FAILURE(rc)) { - return TRUE; + RTUtf16Free(pwszMsi); + return ShowError("RTStrToUtf16 failed on '%s': %Rrc", pszMsi, rc); } - return FALSE; + + UINT uStatus = MsiInstallProductW(pwszMsi, pwszMsiArgs); + RTUtf16Free(pwszMsi); + RTUtf16Free(pwszMsiArgs); + + if (uStatus == ERROR_SUCCESS) + return RTEXITCODE_SUCCESS; + if (uStatus == ERROR_SUCCESS_REBOOT_REQUIRED) + return RTEXITCODE_SUCCESS; /* we currently don't indicate this */ + + /* + * Installation failed. Figure out what to say. + */ + switch (uStatus) + { + case ERROR_INSTALL_USEREXIT: + /* Don't say anything? */ + break; + + case ERROR_INSTALL_PACKAGE_VERSION: + ShowError("This installation package cannot be installed by the Windows Installer service.\n" + "You must install a Windows service pack that contains a newer version of the Windows Installer service."); + break; + + case ERROR_INSTALL_PLATFORM_UNSUPPORTED: + ShowError("This installation package is not supported on this platform."); + break; + + default: + { + /* + * Try get windows to format the message. + */ + DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_IGNORE_INSERTS + | FORMAT_MESSAGE_FROM_SYSTEM; + HMODULE hModule = NULL; + if (uStatus >= NERR_BASE && uStatus <= MAX_NERR) + { + hModule = LoadLibraryExW(L"netmsg.dll", + NULL, + LOAD_LIBRARY_AS_DATAFILE); + if (hModule != NULL) + dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE; + } + + PWSTR pwszMsg; + if (FormatMessageW(dwFormatFlags, + hModule, /* If NULL, load system stuff. */ + uStatus, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (PWSTR)&pwszMsg, + 0, + NULL) > 0) + { + ShowError("Installation failed! Error: %ls", pwszMsg); + LocalFree(pwszMsg); + } + else /* If text lookup failed, show at least the error number. */ + ShowError("Installation failed! Error: %u", uStatus); + + if (hModule) + FreeLibrary(hModule); + break; + } + } + + return RTEXITCODE_FAILURE; } /** - * Recursively copies a directory to another location. + * Processes a package. * - * @returns iprt status code. + * @returns Fully complained exit code. + * @param iPackage The package number. + * @param pszPkgDir The package directory (aka extraction dir). + * @param pszMsiArgs Any additional installer (MSI) argument + * @param fLogging Whether to enable installer logging. + */ +static RTEXITCODE ProcessPackage(unsigned iPackage, const char *pszPkgDir, const char *pszMsiArgs, bool fLogging) +{ + /* + * Get the package header and check if it's needed. + */ + PVBOXSTUBPKG pPackage = FindPackageHeader(iPackage); + if (pPackage == NULL) + return RTEXITCODE_FAILURE; + + if (!PackageIsNeeded(pPackage)) + return RTEXITCODE_SUCCESS; + + /* + * Deal with the file based on it's extension. + */ + char szPkgFile[RTPATH_MAX]; + int rc = RTPathJoin(szPkgFile, sizeof(szPkgFile), pszPkgDir, pPackage->szFileName); + if (RT_FAILURE(rc)) + return ShowError("Internal error: RTPathJoin failed: %Rrc", rc); + RTPathChangeToDosSlashes(szPkgFile, true /* Force conversion. */); /* paranoia */ + + RTEXITCODE rcExit; + const char *pszExt = RTPathExt(szPkgFile); + if (RTStrICmp(pszExt, ".msi") == 0) + rcExit = ProcessMsiPackage(szPkgFile, pszMsiArgs, fLogging); + else if (RTStrICmp(pszExt, ".cab") == 0) + rcExit = RTEXITCODE_SUCCESS; /* Ignore .cab files, they're generally referenced by other files. */ + else + rcExit = ShowError("Internal error: Do not know how to handle file '%s'.", pPackage->szFileName); + + return rcExit; +} + + +#ifdef VBOX_WITH_CODE_SIGNING +/** + * Install the public certificate into TrustedPublishers so the installer won't + * prompt the user during silent installs. + * + * @returns Fully complained exit code. + */ +static RTEXITCODE InstallCertificate(void) +{ + if (addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, + "TrustedPublisher", + g_ab_VBoxStubPublicCert, + sizeof(g_ab_VBoxStubPublicCert))) + return RTEXITCODE_SUCCESS; + return ShowError("Failed to construct install certificate."); +} +#endif /* VBOX_WITH_CODE_SIGNING */ + + +/** + * Copies the "<exepath>.custom" directory to the extraction path if it exists. * - * @param pszDestDir Location to copy the source directory to. - * @param pszSourceDir The source directory to copy. + * This is used by the MSI packages from the resource section. * + * @returns Fully complained exit code. + * @param pszDstDir The destination directory. */ -int CopyDir(const char *pszDestDir, const char *pszSourceDir) +static RTEXITCODE CopyCustomDir(const char *pszDstDir) { - char szDest[RTPATH_MAX + 1]; - char szSource[RTPATH_MAX + 1]; + char szSrcDir[RTPATH_MAX]; + int rc = RTPathExecDir(szSrcDir, sizeof(szSrcDir)); + if (RT_SUCCESS(rc)) + rc = RTPathAppend(szSrcDir, sizeof(szSrcDir), ".custom"); + if (RT_FAILURE(rc)) + return ShowError("Failed to construct '.custom' dir path: %Rrc", rc); + + if (RTDirExists(szSrcDir)) + { + /* + * Use SHFileOperation w/ FO_COPY to do the job. This API requires an + * extra zero at the end of both source and destination paths. + */ + size_t cwc; + RTUTF16 wszSrcDir[RTPATH_MAX + 1]; + PRTUTF16 pwszSrcDir = wszSrcDir; + rc = RTStrToUtf16Ex(szSrcDir, RTSTR_MAX, &pwszSrcDir, RTPATH_MAX, &cwc); + if (RT_FAILURE(rc)) + return ShowError("RTStrToUtf16Ex failed on '%s': %Rrc", szSrcDir, rc); + wszSrcDir[cwc] = '\0'; + + RTUTF16 wszDstDir[RTPATH_MAX + 1]; + PRTUTF16 pwszDstDir = wszSrcDir; + rc = RTStrToUtf16Ex(pszDstDir, RTSTR_MAX, &pwszDstDir, RTPATH_MAX, &cwc); + if (RT_FAILURE(rc)) + return ShowError("RTStrToUtf16Ex failed on '%s': %Rrc", pszDstDir, rc); + wszDstDir[cwc] = '\0'; + + SHFILEOPSTRUCTW FileOp; + RT_ZERO(FileOp); /* paranoia */ + FileOp.hwnd = NULL; + FileOp.wFunc = FO_COPY; + FileOp.pFrom = wszSrcDir; + FileOp.pTo = wszDstDir; + FileOp.fFlags = FOF_SILENT + | FOF_NOCONFIRMATION + | FOF_NOCONFIRMMKDIR + | FOF_NOERRORUI; + FileOp.fAnyOperationsAborted = FALSE; + FileOp.hNameMappings = NULL; + FileOp.lpszProgressTitle = NULL; + + rc = SHFileOperationW(&FileOp); + if (rc != 0) /* Not a Win32 status code! */ + return ShowError("Copying the '.custom' dir failed: %#x", rc); + + /* + * Add a cleanup record for recursively deleting the destination + * .custom directory. We should actually add this prior to calling + * SHFileOperationW since it may partially succeed... + */ + char *pszDstSubDir = RTPathJoinA(pszDstDir, ".custom"); + if (!pszDstSubDir) + return ShowError("Out of memory!"); + bool fRc = AddCleanupRec(pszDstSubDir, false /*fFile*/); + RTStrFree(pszDstSubDir); + if (!fRc) + return RTEXITCODE_FAILURE; + } + + return RTEXITCODE_SUCCESS; +} - AssertStmt(pszDestDir, "Destination directory invalid!"); - AssertStmt(pszSourceDir, "Source directory invalid!"); - SHFILEOPSTRUCT s = {0}; - if ( RTStrPrintf(szDest, _MAX_PATH, "%s%c", pszDestDir, '\0') > 0 - && RTStrPrintf(szSource, _MAX_PATH, "%s%c", pszSourceDir, '\0') > 0) +static RTEXITCODE ExtractFiles(unsigned cPackages, const char *pszDstDir, bool fExtractOnly, bool *pfCreatedExtractDir) +{ + int rc; + + /* + * Make sure the directory exists. + */ + *pfCreatedExtractDir = false; + if (!RTDirExists(pszDstDir)) + { + rc = RTDirCreate(pszDstDir, 0700, 0); + if (RT_FAILURE(rc)) + return ShowError("Failed to create extraction path '%s': %Rrc", pszDstDir, rc); + *pfCreatedExtractDir = true; + } + + /* + * Extract files. + */ + for (unsigned k = 0; k < cPackages; k++) { - s.hwnd = NULL; - s.wFunc = FO_COPY; - s.pTo = szDest; - s.pFrom = szSource; - s.fFlags = FOF_SILENT | - FOF_NOCONFIRMATION | - FOF_NOCONFIRMMKDIR | - FOF_NOERRORUI; + PVBOXSTUBPKG pPackage = FindPackageHeader(k); + if (!pPackage) + return RTEXITCODE_FAILURE; /* Done complaining already. */ + + if (fExtractOnly || PackageIsNeeded(pPackage)) + { + char szDstFile[RTPATH_MAX]; + rc = RTPathJoin(szDstFile, sizeof(szDstFile), pszDstDir, pPackage->szFileName); + if (RT_FAILURE(rc)) + return ShowError("Internal error: RTPathJoin failed: %Rrc", rc); + + rc = Extract(pPackage, szDstFile); + if (RT_FAILURE(rc)) + return ShowError("Error extracting package #%u: %Rrc", k, rc); + + if (!fExtractOnly && !AddCleanupRec(szDstFile, true /*fFile*/)) + { + RTFileDelete(szDstFile); + return RTEXITCODE_FAILURE; + } + } } - return RTErrConvertFromWin32(SHFileOperation(&s)); + + return RTEXITCODE_SUCCESS; } @@ -334,361 +788,223 @@ int WINAPI WinMain(HINSTANCE hInstance, /* Check if we're already running and jump out if so. */ /* Do not use a global namespace ("Global\\") for mutex name here, will blow up NT4 compatibility! */ - HANDLE hMutexAppRunning = CreateMutex (NULL, FALSE, "VBoxStubInstaller"); - if ( (hMutexAppRunning != NULL) - && (GetLastError() == ERROR_ALREADY_EXISTS)) + HANDLE hMutexAppRunning = CreateMutex(NULL, FALSE, "VBoxStubInstaller"); + if ( hMutexAppRunning != NULL + && GetLastError() == ERROR_ALREADY_EXISTS) { /* Close the mutex for this application instance. */ CloseHandle(hMutexAppRunning); hMutexAppRunning = NULL; - return 1; + return RTEXITCODE_FAILURE; } /* Init IPRT. */ int vrc = RTR3InitExe(argc, &argv, 0); if (RT_FAILURE(vrc)) - return vrc; + return RTMsgInitFailure(vrc); - BOOL fExtractOnly = FALSE; - BOOL fSilent = FALSE; - BOOL fEnableLogging = FALSE; - BOOL fExit = FALSE; + /* + * Parse arguments. + */ - /* Temp variables for arguments. */ + /* Parameter variables. */ + bool fExtractOnly = false; + bool fEnableLogging = false; +#ifdef VBOX_WITH_CODE_SIGNING + bool fEnableSilentCert = true; +#endif char szExtractPath[RTPATH_MAX] = {0}; - char szMSIArgs[RTPATH_MAX] = {0}; + char szMSIArgs[4096] = {0}; - /* Process arguments. */ - for (int i = 0; i < argc; i++) + /* Parameter definitions. */ + static const RTGETOPTDEF s_aOptions[] = { - if ( (0 == RTStrICmp(argv[i], "-x")) - || (0 == RTStrICmp(argv[i], "-extract")) - || (0 == RTStrICmp(argv[i], "/extract"))) - { - fExtractOnly = TRUE; - } - - else if ( (0 == RTStrICmp(argv[i], "-s")) - || (0 == RTStrICmp(argv[i], "-silent")) - || (0 == RTStrICmp(argv[i], "/silent"))) - { - fSilent = TRUE; - } - - else if ( (0 == RTStrICmp(argv[i], "-l")) - || (0 == RTStrICmp(argv[i], "-logging")) - || (0 == RTStrICmp(argv[i], "/logging"))) - { - fEnableLogging = TRUE; - } - - else if (( (0 == RTStrICmp(argv[i], "-p")) - || (0 == RTStrICmp(argv[i], "-path")) - || (0 == RTStrICmp(argv[i], "/path"))) - ) - { - if (argc > i) - { - vrc = ::StringCbCat(szExtractPath, sizeof(szExtractPath), argv[i+1]); - i++; /* Avoid the specified path from being parsed. */ - } - else - { - ShowError("No path for extraction specified!"); - fExit = TRUE; - } - } - - else if (( (0 == RTStrICmp(argv[i], "-msiparams")) - || (0 == RTStrICmp(argv[i], "/msiparams"))) - && (argc > i)) + { "--extract", 'x', RTGETOPT_REQ_NOTHING }, + { "-extract", 'x', RTGETOPT_REQ_NOTHING }, + { "/extract", 'x', RTGETOPT_REQ_NOTHING }, + { "--silent", 's', RTGETOPT_REQ_NOTHING }, + { "-silent", 's', RTGETOPT_REQ_NOTHING }, + { "/silent", 's', RTGETOPT_REQ_NOTHING }, +#ifdef VBOX_WITH_CODE_SIGNING + { "--no-silent-cert", 'c', RTGETOPT_REQ_NOTHING }, + { "-no-silent-cert", 'c', RTGETOPT_REQ_NOTHING }, + { "/no-silent-cert", 'c', RTGETOPT_REQ_NOTHING }, +#endif + { "--logging", 'l', RTGETOPT_REQ_NOTHING }, + { "-logging", 'l', RTGETOPT_REQ_NOTHING }, + { "/logging", 'l', RTGETOPT_REQ_NOTHING }, + { "--path", 'p', RTGETOPT_REQ_STRING }, + { "-path", 'p', RTGETOPT_REQ_STRING }, + { "/path", 'p', RTGETOPT_REQ_STRING }, + { "--msiparams", 'm', RTGETOPT_REQ_STRING }, + { "-msiparams", 'm', RTGETOPT_REQ_STRING }, + { "--version", 'V', RTGETOPT_REQ_NOTHING }, + { "-version", 'V', RTGETOPT_REQ_NOTHING }, + { "/version", 'V', RTGETOPT_REQ_NOTHING }, + { "-v", 'V', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING }, + { "-help", 'h', RTGETOPT_REQ_NOTHING }, + { "/help", 'h', RTGETOPT_REQ_NOTHING }, + { "/?", 'h', RTGETOPT_REQ_NOTHING }, + }; + + /* Parse the parameters. */ + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); + while ((ch = RTGetOpt(&GetState, &ValueUnion))) + { + switch (ch) { - for (int a = i + 1; a < argc; a++) - { - if (a > i+1) /* Insert a space. */ - vrc = ::StringCbCat(szMSIArgs, sizeof(szMSIArgs), " "); + case 'x': + fExtractOnly = true; + break; + + case 's': + g_fSilent = true; + break; + +#ifdef VBOX_WITH_CODE_SIGNING + case 'c': + fEnableSilentCert = false; + break; +#endif - vrc = ::StringCbCat(szMSIArgs, sizeof(szMSIArgs), argv[a]); - } - } + case 'l': + fEnableLogging = true; + break; - else if ( (0 == RTStrICmp(argv[i], "-v")) - || (0 == RTStrICmp(argv[i], "-version")) - || (0 == RTStrICmp(argv[i], "/version"))) - { - ShowInfo("Version: %d.%d.%d.%d", - VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV); - fExit = TRUE; - } + case 'p': + vrc = RTStrCopy(szExtractPath, sizeof(szExtractPath), ValueUnion.psz); + if (RT_FAILURE(vrc)) + return ShowError("Extraction path is too long."); + break; - else if ( (0 == RTStrICmp(argv[i], "-help")) - || (0 == RTStrICmp(argv[i], "/help")) - || (0 == RTStrICmp(argv[i], "/?"))) - { - ShowInfo("-- %s v%d.%d.%d.%d --\n" + case 'm': + if (szMSIArgs[0]) + vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs), " "); + if (RT_SUCCESS(vrc)) + vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs), ValueUnion.psz); + if (RT_FAILURE(vrc)) + return ShowError("MSI parameters are too long."); + break; + + case 'V': + ShowInfo("Version: %d.%d.%d.%d", + VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV); + return VINF_SUCCESS; + + case 'h': + ShowInfo("-- %s v%d.%d.%d.%d --\n" + "\n" "Command Line Parameters:\n\n" - "-extract | -x - Extract file contents to temporary directory\n" - "-silent | -s - Enables silent mode installation\n" - "-path | -p - Sets the path of the extraction directory\n" - "-help | /? - Print this help and exit\n" - "-msiparams <parameters> - Specifies extra parameters for the MSI installers\n" - "-logging | -l - Enables installer logging\n" - "-version | -v - Print version number and exit\n\n" + "--extract - Extract file contents to temporary directory\n" + "--silent - Enables silent mode installation\n" + "--no-silent-cert - Do not install VirtualBox Certificate automatically when --silent option is specified\n" + "--path - Sets the path of the extraction directory\n" + "--msiparams <parameters> - Specifies extra parameters for the MSI installers\n" + "--logging - Enables installer logging\n" + "--help - Print this help and exit\n" + "--version - Print version number and exit\n\n" "Examples:\n" - "%s -msiparams INSTALLDIR=C:\\VBox\n" - "%s -extract -path C:\\VBox\n", + "%s --msiparams INSTALLDIR=C:\\VBox\n" + "%s --extract -path C:\\VBox", VBOX_STUB_TITLE, VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV, argv[0], argv[0]); - fExit = TRUE; - } - else - { - if (i > 0) - { - ShowError("Unknown option \"%s\"!\n" - "Please refer to the command line help by specifying \"/?\"\n" - "to get more information.", argv[i]); - fExit = TRUE; - } - } - } + return VINF_SUCCESS; - if (fExit) - return 0; + default: + if (g_fSilent) + return RTGetOptPrintError(ch, &ValueUnion); + if (ch == VINF_GETOPT_NOT_OPTION || ch == VERR_GETOPT_UNKNOWN_OPTION) + ShowError("Unknown option \"%s\"!\n" + "Please refer to the command line help by specifying \"/?\"\n" + "to get more information.", ValueUnion.psz); + else + ShowError("Parameter parsing error: %Rrc\n" + "Please refer to the command line help by specifying \"/?\"\n" + "to get more information.", ch); + return RTEXITCODE_SYNTAX; - HRESULT hr = S_OK; + } + } - do /* break loop */ + /* + * Determine the extration path if not given by the user, and gather some + * other bits we'll be needing later. + */ + if (szExtractPath[0] == '\0') { - /* Get/create our temp path (only if not already set). */ - if (szExtractPath[0] == '\0') - { - vrc = RTPathTemp(szExtractPath, sizeof(szExtractPath)); - AssertMsgRCBreak(vrc, ("Could not retrieve temp directory!\n")); - + vrc = RTPathTemp(szExtractPath, sizeof(szExtractPath)); + if (RT_SUCCESS(vrc)) vrc = RTPathAppend(szExtractPath, sizeof(szExtractPath), "VirtualBox"); - AssertMsgRCBreak(vrc, ("Could not construct temp directory!\n")); - - /* Convert slahes; this is necessary for MSI routines later! */ - RTPathChangeToDosSlashes(szExtractPath, true /* Force conversion. */); - } - if (!RTDirExists(szExtractPath)) - { - vrc = RTDirCreate(szExtractPath, 0700, 0); - AssertMsgRCBreak(vrc, ("Could not create temp directory!\n")); - } + if (RT_FAILURE(vrc)) + return ShowError("Failed to determin extraction path (%Rrc)", vrc); - /* Get our executable path */ - char szPathExe[_MAX_PATH]; - vrc = RTPathExecDir(szPathExe, sizeof(szPathExe)); - /** @todo error checking */ - - /* Read our manifest. */ - PVBOXSTUBPKGHEADER pHeader = NULL; - DWORD cbHeader = 0; - vrc = ReadData(NULL, "MANIFEST", (LPVOID*)&pHeader, &cbHeader); - AssertMsgRCBreak(vrc, ("Manifest not found!\n")); - - /* Extract files. */ - for (BYTE k = 0; k < pHeader->byCntPkgs; k++) - { - PVBOXSTUBPKG pPackage = NULL; - DWORD cbPackage = 0; - char szHeaderName[RTPATH_MAX + 1] = {0}; - - hr = ::StringCchPrintf(szHeaderName, RTPATH_MAX, "HDR_%02d", k); - vrc = ReadData(NULL, szHeaderName, (LPVOID*)&pPackage, &cbPackage); - AssertMsgRCBreak(vrc, ("Header not found!\n")); /** @todo include header name, how? */ - - if (PackageIsNeeded(pPackage) || fExtractOnly) - { - char *pszTempFile = NULL; - vrc = GetTempFileAlloc(szExtractPath, pPackage->szFileName, &pszTempFile); - AssertMsgRCBreak(vrc, ("Could not create name for temporary extracted file!\n")); - vrc = Extract(pPackage, pszTempFile); - AssertMsgRCBreak(vrc, ("Could not extract file!\n")); - RTStrFree(pszTempFile); - } - } + } + else + { + /** @todo should check if there is a .custom subdirectory there or not. */ + } + RTPathChangeToDosSlashes(szExtractPath, true /* Force conversion. */); /* MSI requirement. */ - if (FALSE == fExtractOnly && !RT_FAILURE(vrc)) + /* Read our manifest. */ + PVBOXSTUBPKGHEADER pHeader; + vrc = FindData("MANIFEST", (PVOID *)&pHeader, NULL); + if (RT_FAILURE(vrc)) + return ShowError("Internal package error: Manifest not found (%Rrc)", vrc); + /** @todo If we could, we should validate the header. Only the magic isn't + * commonly defined, nor the version number... */ + + RTListInit(&g_TmpFiles); + + /* + * Up to this point, we haven't done anything that requires any cleanup. + * From here on, we do everything in function so we can counter clean up. + */ + bool fCreatedExtractDir; + RTEXITCODE rcExit = ExtractFiles(pHeader->byCntPkgs, szExtractPath, fExtractOnly, &fCreatedExtractDir); + if (rcExit == RTEXITCODE_SUCCESS) + { + if (fExtractOnly) + ShowInfo("Files were extracted to: %s", szExtractPath); + else { - /* - * Copy ".custom" directory into temp directory so that the extracted .MSI - * file(s) can use it. - */ - char *pszPathCustomDir = RTPathJoinA(szPathExe, ".custom"); - pszPathCustomDir = RTPathChangeToDosSlashes(pszPathCustomDir, true /* Force conversion. */); - if (pszPathCustomDir && RTDirExists(pszPathCustomDir)) + rcExit = CopyCustomDir(szExtractPath); +#ifdef VBOX_WITH_CODE_SIGNING + if (rcExit == RTEXITCODE_SUCCESS && fEnableSilentCert && g_fSilent) + rcExit = InstallCertificate(); +#endif + unsigned iPackage = 0; + while (iPackage < pHeader->byCntPkgs && rcExit == RTEXITCODE_SUCCESS) { - vrc = CopyDir(szExtractPath, pszPathCustomDir); - if (RT_FAILURE(vrc)) /* Don't fail if it's missing! */ - vrc = VINF_SUCCESS; - - RTStrFree(pszPathCustomDir); + rcExit = ProcessPackage(iPackage, szExtractPath, szMSIArgs, fEnableLogging); + iPackage++; } - /* Do actions on files. */ - for (BYTE k = 0; k < pHeader->byCntPkgs; k++) - { - PVBOXSTUBPKG pPackage = NULL; - DWORD cbPackage = 0; - char szHeaderName[RTPATH_MAX] = {0}; - - hr = StringCchPrintf(szHeaderName, RTPATH_MAX, "HDR_%02d", k); - vrc = ReadData(NULL, szHeaderName, (LPVOID*)&pPackage, &cbPackage); - AssertMsgRCBreak(vrc, ("Package not found!\n")); - - if (PackageIsNeeded(pPackage)) - { - char *pszTempFile = NULL; - - vrc = GetTempFileAlloc(szExtractPath, pPackage->szFileName, &pszTempFile); - AssertMsgRCBreak(vrc, ("Could not create name for temporary action file!\n")); - - /* Handle MSI files. */ - if (RTStrICmp(RTPathExt(pszTempFile), ".msi") == 0) - { - /* Set UI level. */ - INSTALLUILEVEL UILevel = MsiSetInternalUI( fSilent - ? INSTALLUILEVEL_NONE - : INSTALLUILEVEL_FULL, - NULL); - AssertMsgBreak(UILevel != INSTALLUILEVEL_NOCHANGE, ("Could not set installer UI level!\n")); - - /* Enable logging? */ - if (fEnableLogging) - { - char *pszLog = RTPathJoinA(szExtractPath, "VBoxInstallLog.txt"); - /* Convert slahes; this is necessary for MSI routines! */ - pszLog = RTPathChangeToDosSlashes(pszLog, true /* Force conversion. */); - AssertMsgBreak(pszLog, ("Could not construct path for log file!\n")); - UINT uLogLevel = MsiEnableLog(INSTALLLOGMODE_VERBOSE, - pszLog, INSTALLLOGATTRIBUTES_FLUSHEACHLINE); - RTStrFree(pszLog); - AssertMsgBreak(uLogLevel == ERROR_SUCCESS, ("Could not set installer logging level!\n")); - } - - /* Initialize the common controls (extended version). This is necessary to - * run the actual .MSI installers with the new fancy visual control - * styles (XP+). Also, an integrated manifest is required. */ - INITCOMMONCONTROLSEX ccEx; - ccEx.dwSize = sizeof(INITCOMMONCONTROLSEX); - ccEx.dwICC = ICC_LINK_CLASS | ICC_LISTVIEW_CLASSES | ICC_PAGESCROLLER_CLASS | - ICC_PROGRESS_CLASS | ICC_STANDARD_CLASSES | ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES | - ICC_UPDOWN_CLASS | ICC_USEREX_CLASSES | ICC_WIN95_CLASSES; - InitCommonControlsEx(&ccEx); /* Ignore failure. */ - - UINT uStatus = ::MsiInstallProductA(pszTempFile, szMSIArgs); - if ( (uStatus != ERROR_SUCCESS) - && (uStatus != ERROR_SUCCESS_REBOOT_REQUIRED) - && (uStatus != ERROR_INSTALL_USEREXIT)) - { - if (!fSilent) - { - switch (uStatus) - { - case ERROR_INSTALL_PACKAGE_VERSION: - - ShowError("This installation package cannot be installed by the Windows Installer service.\n" - "You must install a Windows service pack that contains a newer version of the Windows Installer service."); - break; - - case ERROR_INSTALL_PLATFORM_UNSUPPORTED: - - ShowError("This installation package is not supported on this platform."); - break; - - default: - { - DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_IGNORE_INSERTS - | FORMAT_MESSAGE_FROM_SYSTEM; - HMODULE hModule = NULL; - if (uStatus >= NERR_BASE && uStatus <= MAX_NERR) - { - hModule = LoadLibraryEx(TEXT("netmsg.dll"), - NULL, - LOAD_LIBRARY_AS_DATAFILE); - if (hModule != NULL) - dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE; - } - - DWORD dwBufferLength; - LPSTR szMessageBuffer; - if (dwBufferLength = FormatMessageA(dwFormatFlags, - hModule, /* If NULL, load system stuff. */ - uStatus, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&szMessageBuffer, - 0, - NULL)) - { - ShowError("Installation failed! Error: %s", szMessageBuffer); - LocalFree(szMessageBuffer); - } - else /* If text lookup failed, show at least the error number. */ - ShowError("Installation failed! Error: %u", uStatus); - if (hModule) - FreeLibrary(hModule); - break; - } - } - } - - vrc = VERR_NO_CHANGE; /* No change done to the system. */ - } - } - RTStrFree(pszTempFile); - } /* Package needed? */ - } /* For all packages */ - } - - /* Clean up (only on success - prevent deleting the log). */ - if ( !fExtractOnly - && RT_SUCCESS(vrc)) - { - for (int i=0; i<5; i++) - { - vrc = RTDirRemoveRecursive(szExtractPath, 0 /*fFlags*/); - if (RT_SUCCESS(vrc)) - break; - RTThreadSleep(3000 /* Wait 3 seconds.*/); - } + /* Don't fail if cleanup fail. At least for now. */ + CleanUp(pHeader->byCntPkgs, !fEnableLogging && fCreatedExtractDir ? szExtractPath : NULL); } + } - } while (0); - - if (RT_SUCCESS(vrc)) + /* Free any left behind cleanup records (not strictly needed). */ + PSTUBCLEANUPREC pCur, pNext; + RTListForEachSafe(&g_TmpFiles, pCur, pNext, STUBCLEANUPREC, ListEntry) { - if ( fExtractOnly - && !fSilent) - { - ShowInfo("Files were extracted to: %s", szExtractPath); - } - - /** @todo Add more post installation stuff here if required. */ + RTListNodeRemove(&pCur->ListEntry); + RTMemFree(pCur); } - /* Release instance mutex. */ + /* + * Release instance mutex. + */ if (hMutexAppRunning != NULL) { CloseHandle(hMutexAppRunning); hMutexAppRunning = NULL; } - /* Set final exit (return) code (error level). */ - if (RT_FAILURE(vrc)) - { - switch(vrc) - { - case VERR_NO_CHANGE: - default: - vrc = 1; - } - } - else /* Always set to (VINF_SUCCESS), even if we got something else (like a VWRN etc). */ - vrc = VINF_SUCCESS; - return vrc; + return rcExit; } diff --git a/src/VBox/Installer/win/Stub/VBoxStub.h b/src/VBox/Installer/win/Stub/VBoxStub.h index 455023a6..e50bca06 100644 --- a/src/VBox/Installer/win/Stub/VBoxStub.h +++ b/src/VBox/Installer/win/Stub/VBoxStub.h @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2009 Oracle Corporation + * Copyright (C) 2009-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/win/Stub/VBoxStubCertUtil.cpp b/src/VBox/Installer/win/Stub/VBoxStubCertUtil.cpp new file mode 100644 index 00000000..cfa3b5e5 --- /dev/null +++ b/src/VBox/Installer/win/Stub/VBoxStubCertUtil.cpp @@ -0,0 +1,140 @@ +/* $Id: VBoxStubCertUtil.cpp $ */ +/** @file + * VBoxStub - VirtualBox's Windows installer stub (certificate manipulations). + * + * NOTE: The content of this file is partly + * grabbed from src/VBox/Additions/WINNT/tools/VBoxCertUtil.cpp + */ + +/* + * Copyright (C) 2012 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. + */ + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include <Windows.h> +#include <Wincrypt.h> + +#include <iprt/string.h> +#include <iprt/message.h> +#include <iprt/err.h> + + +/** + * Reads a certificate from a (const char []) buffer, returning a context + * or a the handle to a temporary memory store. + * + * @returns true on success, false on failure (error message written). + * @param kpCertBuf The pointer to the buffer containing the + * certificates. + * @param cbCertBuf Size of @param kpCertBuf in bytes. + * @param ppOutCtx Where to return the handle to the temporary + * memory store. + */ +static bool readCertBuf(const unsigned char kpCertBuf[], DWORD cbCertBuf, PCCERT_CONTEXT *ppOutCtx) +{ + *ppOutCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + (PBYTE)kpCertBuf, cbCertBuf); + if (*ppOutCtx) + return true; + + return false; +} + +/** + * Opens a certificate store. + * + * @returns true on success, false on failure (error message written). + * @param dwDst The destination, like + * CERT_SYSTEM_STORE_LOCAL_MACHINE or + * CERT_SYSTEM_STORE_CURRENT_USER. + * @param pszStoreNm The store name. + */ +static HCERTSTORE openCertStore(DWORD dwDst, const char *pszStoreNm) +{ + HCERTSTORE hStore = NULL; + PRTUTF16 pwszStoreNm; + int rc = RTStrToUtf16(pszStoreNm, &pwszStoreNm); + if (RT_SUCCESS(rc)) + { + /* + * Make sure CERT_STORE_OPEN_EXISTING_FLAG is not set. This causes Windows XP + * to return ACCESS_DENIED when installing TrustedPublisher certificates via + * CertAddCertificateContextToStore() if the TrustedPublisher store never has + * been used (through certmgr.exe and friends) yet. + * + * According to MSDN, if neither CERT_STORE_OPEN_EXISTING_FLAG nor + * CERT_STORE_CREATE_NEW_FLAG is set, the store will be either opened or + * created accordingly. + */ + dwDst &= ~CERT_STORE_OPEN_EXISTING_FLAG; + + hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, + PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, + NULL /* hCryptProv = default */, + dwDst, + pwszStoreNm); + + RTUtf16Free(pwszStoreNm); + } + return hStore; +} + +/** + * Adds a certificate to a store. + * + * @returns true on success, false on failure (error message written). + * @param dwDst The destination, like + * CERT_SYSTEM_STORE_LOCAL_MACHINE or + * CERT_SYSTEM_STORE_CURRENT_USER. + * @param pszStoreNm The store name. + * @param kpCertBuf Buffer that contains a certificate + * @param cbCertBuf Size of @param kpCertBuf in bytes + */ +bool addCertToStore(DWORD dwDst, const char *pszStoreNm, const unsigned char kpCertBuf[], DWORD cbCertBuf) +{ + /* + * Get certificate from buffer. + */ + PCCERT_CONTEXT pSrcCtx = NULL; + bool fRc = false; + + if (!readCertBuf(kpCertBuf, cbCertBuf, &pSrcCtx)) + { + RTMsgError("Unable to get certificate context: %d", GetLastError()); + return fRc; + } + + /* + * Open the certificates store. + */ + HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm); + if (hDstStore) + { + /* + * Finally, add certificate to store + */ + if (CertAddCertificateContextToStore(hDstStore, pSrcCtx, CERT_STORE_ADD_REPLACE_EXISTING, NULL)) + fRc = true; + else + RTMsgError("Unable to install certificate: %d", GetLastError()); + + CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG); + } + else + RTMsgError("Unable to open certificates store: %d", GetLastError()); + + /* Release resources */ + CertFreeCertificateContext(pSrcCtx); + + return fRc; +} diff --git a/src/VBox/Installer/win/Stub/VBoxStubCertUtil.h b/src/VBox/Installer/win/Stub/VBoxStubCertUtil.h new file mode 100644 index 00000000..59bf0847 --- /dev/null +++ b/src/VBox/Installer/win/Stub/VBoxStubCertUtil.h @@ -0,0 +1,20 @@ +/* $Id: VBoxStubCertUtil.h $ */ +/** @file + * VBoxStub - VirtualBox's Windows installer stub (certificate manipulations). + */ + +/* + * Copyright (C) 2012 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. + */ + +#pragma once + +extern bool addCertToStore(DWORD dwDst, const char *pszStoreNm, const unsigned char kpCertBuf[], DWORD cbCertBuf); diff --git a/src/VBox/Installer/win/Stub/resource.h b/src/VBox/Installer/win/Stub/resource.h index fbffe226..fbc557a6 100644 --- a/src/VBox/Installer/win/Stub/resource.h +++ b/src/VBox/Installer/win/Stub/resource.h @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2009 Oracle Corporation + * Copyright (C) 2009-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -14,8 +14,12 @@ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ + + #define IDI_VIRTUALBOX 101 -#define RT_MANIFEST 24 +#ifndef RT_MANIFEST +# define RT_MANIFEST 24 +#endif #define APP_MANIFEST 1 diff --git a/src/VBox/Installer/win/StubBld/VBoxStubBld.cpp b/src/VBox/Installer/win/StubBld/VBoxStubBld.cpp index 862b088d..b0ad0cb9 100644 --- a/src/VBox/Installer/win/StubBld/VBoxStubBld.cpp +++ b/src/VBox/Installer/win/StubBld/VBoxStubBld.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2009 Oracle Corporation + * Copyright (C) 2009-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Installer/win/StubBld/VBoxStubBld.h b/src/VBox/Installer/win/StubBld/VBoxStubBld.h index 67005674..49919f9b 100644 --- a/src/VBox/Installer/win/StubBld/VBoxStubBld.h +++ b/src/VBox/Installer/win/StubBld/VBoxStubBld.h @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2009 Oracle Corporation + * Copyright (C) 2009-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -15,37 +15,52 @@ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ -#pragma once +#ifndef ___VBoxStubBld_h___ +#define ___VBoxStubBld_h___ #define VBOXSTUB_MAX_PACKAGES 128 -typedef struct +typedef struct VBOXSTUBPKGHEADER { - char szMagic[9]; - DWORD dwVersion; - BYTE byCntPkgs; + /** Some magic string not defined by this header? Turns out it's a write only + * field... */ + char szMagic[9]; + /* Inbetween szMagic and dwVersion there are 3 bytes of implicit padding. */ + /** Some version number not defined by this header? Also write only field. + * Should be a uint32_t, not DWORD. */ + DWORD dwVersion; + /** Number of packages following the header. byte is prefixed 'b', not 'by'! + * Use uint8_t instead of BYTE. */ + BYTE byCntPkgs; + /* There are 3 bytes of implicit padding here. */ +} VBOXSTUBPKGHEADER; +typedef VBOXSTUBPKGHEADER *PVBOXSTUBPKGHEADER; -} VBOXSTUBPKGHEADER, *PVBOXSTUBPKGHEADER; - -enum VBOXSTUBPKGARCH +typedef enum VBOXSTUBPKGARCH { VBOXSTUBPKGARCH_ALL = 0, - VBOXSTUBPKGARCH_X86 = 1, - VBOXSTUBPKGARCH_AMD64 = 2 -}; + VBOXSTUBPKGARCH_X86, + VBOXSTUBPKGARCH_AMD64 +} VBOXSTUBPKGARCH; -typedef struct +typedef struct VBOXSTUBPKG { BYTE byArch; + /** Probably the name of the PE resource or something, read the source to + * find out for sure. Don't use _MAX_PATH, define your own max lengths! */ char szResourceName[_MAX_PATH]; char szFileName[_MAX_PATH]; -} VBOXSTUBPKG, *PVBOXSTUBPKG; +} VBOXSTUBPKG; +typedef VBOXSTUBPKG *PVBOXSTUBPKG; /* Only for construction. */ +/* Since it's only used by VBoxStubBld.cpp, why not just keep it there? */ -typedef struct +typedef struct VBOXSTUBBUILDPKG { char szSourcePath[_MAX_PATH]; BYTE byArch; -} VBOXSTUBBUILDPKG, *PVBOXSTUBBUILDPKG; +} VBOXSTUBBUILDPKG; +typedef VBOXSTUBBUILDPKG *PVBOXSTUBBUILDPKG; +#endif diff --git a/src/VBox/Installer/win/UserInterface.wxi b/src/VBox/Installer/win/UserInterface.wxi index 20a6e27b..9886befe 100644 --- a/src/VBox/Installer/win/UserInterface.wxi +++ b/src/VBox/Installer/win/UserInterface.wxi @@ -60,7 +60,7 @@ <Publish Event="NewDialog" Value="VBoxLicenseAgreementDlg">1</Publish> <?else ?> <!-- Decide which dialog to show next: The serial number dialog (if this is a branded build) - or directly proceed to the customization dialog (Vbox not installed yet) --> + or directly proceed to the customization dialog (VBox not installed yet) --> <?if $(env.VBOX_WITH_SERIALNUMBER_INSTALL) = "yes" ?> <Publish Event="NewDialog" Value="VBoxCheckSerialDlg">1</Publish> <?else ?> @@ -126,7 +126,7 @@ <Condition Action="disable"><![CDATA[IAgree <> "Yes"]]></Condition> <Condition Action="enable"><![CDATA[IAgree = "Yes"]]></Condition> <!-- Decide which dialog to show next: The serial number dialog (if this is a branded build) - or directly proceed to the customization dialog (Vbox not installed yet) --> + or directly proceed to the customization dialog (VBox not installed yet) --> <?if $(env.VBOX_WITH_SERIALNUMBER_INSTALL) = "yes" ?> <Publish Event="NewDialog" Value="VBoxCheckSerialDlg">1</Publish> <?else ?> @@ -334,6 +334,10 @@ Property="INSTALLQUICKLAUNCHSHORTCUT" CheckBoxValue="1"> <Text>!(loc.Customize2Dlg_CreateQuickLaunch)</Text> </Control> + <Control Id="RegisterFileExtensionsCheckBox" Type="CheckBox" X="25" Y="135" Width="200" Height="17" + Property="REGISTERFILEEXTENSIONS" CheckBoxValue="1"> + <Text>!(loc.Customize2Dlg_RegisterFileExtensions)</Text> + </Control> <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="!(loc.ButtonText_Next)"> diff --git a/src/VBox/Installer/win/VirtualBox.wxs b/src/VBox/Installer/win/VirtualBox.wxs index 9823155a..176c1e17 100644 --- a/src/VBox/Installer/win/VirtualBox.wxs +++ b/src/VBox/Installer/win/VirtualBox.wxs @@ -2,7 +2,7 @@ <!-- VirtualBox Windows Installation Script (WiX) - Copyright (C) 2006-2012 Oracle Corporation + Copyright (C) 2006-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; @@ -116,6 +116,7 @@ <Property Id="ARPURLUPDATEINFO">http://www.virtualbox.org</Property> <Property Id="INSTALLDESKTOPSHORTCUT" Value="1"></Property> <Property Id="INSTALLQUICKLAUNCHSHORTCUT" Value="1"></Property> + <Property Id="REGISTERFILEEXTENSIONS" Value="1"></Property> <Property Id="STARTVBOX" Value="1"></Property> <!-- Install the product for all users on the system --> @@ -334,6 +335,16 @@ </Component> </Directory> +<?if $(env.VBOX_WITH_32_ON_64_MAIN_API) = "yes" ?> + <!-- The 32-bit client COM component (see also cp_MainCom below). --> + <Component Id="cp_MainCOM_x86" Guid="B600824E-4A25-2EB3-4B44-3D8CB7F9B92D" Win64="no"> + <File Id="VBoxClient_x86" Name="VBoxClient-x86.dll" + Source="$(env.PATH_OUT)\bin\VBoxClient-x86.dll" KeyPath="yes"> + </File> + <?include $(env.PATH_TARGET)\VirtualBox_TypeLib_x86.wxi ?> + </Component> +<?endif?> + <!-- COM components have a separate entry mainly because of the KeyPath attribute (that hints the TypeLib element where to take the TLB resource from) may appear only once per Component. --> <Component Id="cp_MainCOM" Guid="CD4A3C6C-C2D5-428D-90A1-B6DA3D0777D6" Win64="$(var.Property_Win64)"> @@ -358,7 +369,7 @@ <!-- - <Component Id="Cp_StartMenuShortcut" Guid="1C137D24-E599-47BD-98D0-2F62F202A8EA" Win64="$(var.Property_Win64)"> + <Component Id="cp_StartMenuShortcut" Guid="1C137D24-E599-47BD-98D0-2F62F202A8EA" Win64="$(var.Property_Win64)"> <RegistryValue Root="HKCU" Key="$(var.Property_RegKeyInstall)" Type="string" Value="installed" KeyPath="yes" /> <Shortcut Id="ShortcutStartMenuVBox" Directory="ProgramMenuDir" @@ -368,14 +379,8 @@ <!----> - <!-- All Binaries, DLLs (except COM) and drivers are in one component because they belong together. Additional - binaries e.g. test tools, utilities etc. should be in another component so they"re clearly separated. --> - <Component Id="cp_MainBinaries" Guid="5C8FE57A-F744-4DE0-AA3F-A563F486AD98" Win64="$(var.Property_Win64)"> - - <!-- Set required environment variables. --> - <Environment Id="env_VBoxInstallDir" Action="set" Name="VBOX_INSTALL_PATH" - System="yes" Part="last" Permanent="no" Value="[INSTALLDIR]" /> - + <Component Id="cp_RegisterExtensions" Guid="FEB8943E-5D60-4E2D-846F-458207019D40" Win64="$(var.Property_Win64)"> + <Condition>REGISTERFILEEXTENSIONS</Condition> <!-- Register file extensions. Note: Extension Id's *must not* be changed! These specify the actual file extension to handle. Also, here would be the place to add more fancy DDE stuff later. Important: The IDs in "IconIndex" *must* be matching "Resources\resource.h". --> @@ -411,6 +416,15 @@ <ProgId Id="progId_VirtualBox.Shell.hdd" Description="Virtual Hard Disk" Icon="file_VBoxRes.dll" IconIndex="-306"> <Extension Id="hdd" ContentType="application/x-virtualbox-hdd" /> </ProgId> + </Component> <!-- RegisterExtensions --> + + <!-- All Binaries, DLLs (except COM) and drivers are in one component because they belong together. Additional + binaries e.g. test tools, utilities etc. should be in another component so they"re clearly separated. --> + <Component Id="cp_MainBinaries" Guid="5C8FE57A-F744-4DE0-AA3F-A563F486AD98" Win64="$(var.Property_Win64)"> + + <!-- Set required environment variables. --> + <Environment Id="env_VBoxInstallDir" Action="set" Name="VBOX_INSTALL_PATH" + System="yes" Part="last" Permanent="no" Value="[INSTALLDIR]" /> <!-- Files --> <?if $(env.VBOX_WITH_DOCS_PACKING) = "yes" ?> @@ -434,6 +448,8 @@ <!-- Misc tools --> <File Id="file_VBoxNetDHCP.exe" Name="VBoxNetDHCP.exe" Source="$(env.PATH_OUT)\bin\VBoxNetDHCP.exe"/> + <File Id="file_VBoxNetNAT.exe" Name="VBoxNetNAT.exe" + Source="$(env.PATH_OUT)\bin\VBoxNetNAT.exe"/> <?if $(env.VBOX_WITH_EXTPACK) = "yes" ?> <File Id="file_VBoxExtPackHelperApp.exe" Name="VBoxExtPackHelperApp.exe" Source="$(env.PATH_OUT)\bin\VBoxExtPackHelperApp.exe"/> @@ -624,6 +640,12 @@ </Component> <?endif?> + <!-- C API (glue) binding --> + <Component Id="cp_VBoxCAPI" Guid="097F7F53-7111-467F-8E0C-257D9926FDA0"> + <File Id="file_VBoxCAPI.dll" Name="VBoxCAPI.dll" + Source="$(env.PATH_OUT)\bin\VBoxCAPI.dll" /> + </Component> + <?if $(env.VBOX_WITH_PYTHON) = "yes" ?> <Component Id="cp_VBoxPythonBinding" Guid="293D7E11-78DA-4C31-AEED-AE2FE42F6881"> <Condition>PYTHON_INSTALLED</Condition> @@ -688,11 +710,15 @@ <ComponentRef Id="cp_StartMenuVBox" /> <ComponentRef Id="cp_DesktopShortcut" /> <ComponentRef Id="cp_QuickLaunchVBox" /> + <ComponentRef Id="cp_RegisterExtensions" /> <?if $(env.VBOX_WITH_DOCS_PACKING) = "yes" ?> <ComponentRef Id="cp_Docs" /> <?endif?> <ComponentRef Id="cp_NLS" /> +<?if $(env.VBOX_WITH_32_ON_64_MAIN_API) = "yes" ?> + <ComponentRef Id="cp_MainCOM_x86" /> +<?endif?> <ComponentRef Id="cp_MainCOM" /> <ComponentRef Id="cp_MainBinaries" /> <?if $(env.VBOX_WITH_QTGUI) = "yes" ?> @@ -710,6 +736,7 @@ <?if $(env.VBOX_WITH_WEBSERVICES) = "yes" ?> <ComponentRef Id="cp_VBoxWebService" /> <?endif?> + <ComponentRef Id="cp_VBoxCAPI" /> <ComponentRef Id="cp_VBoxDrv" /> <Feature Id="VBoxUSB" Title="VirtualBox USB Support" Level="1" @@ -802,7 +829,7 @@ <?if $(env.VBOX_WITH_NETFLT) = "yes" ?> <!-- Create host-only interfaces on first-time install. --> <Custom Action="ca_CreateHostOnlyInterfaceArgs" Before="ca_CreateHostOnlyInterface" ><![CDATA[&VBoxNetworkAdp=3]]></Custom> - <Custom Action="ca_CreateHostOnlyInterface" Before="InstallFinalize" ><![CDATA[&VBoxNetworkAdp=3]]></Custom> + <Custom Action="ca_CreateHostOnlyInterface" Before="InstallFinalize" ><![CDATA[&VBoxNetworkAdp=3]]></Custom> <!-- Don't remove the host-only interfaces on update, only on uninstall. --> <Custom Action="ca_RemoveHostOnlyInterfaces" After="ca_UninstallNetFlt" ><![CDATA[(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")]]></Custom> <!-- First stop the existing host-only interfaces on update ... --> diff --git a/src/VBox/Installer/win/VirtualBox_TypeLib.xsl b/src/VBox/Installer/win/VirtualBox_TypeLib.xsl index c0ccf6de..15fd770e 100644 --- a/src/VBox/Installer/win/VirtualBox_TypeLib.xsl +++ b/src/VBox/Installer/win/VirtualBox_TypeLib.xsl @@ -5,7 +5,7 @@ * type library definitions for VirtualBox COM components * from the generic interface definition expressed in XML. - Copyright (C) 2007-2010 Oracle Corporation + Copyright (C) 2007-2012 Oracle Corporation This file is part of VirtualBox Open Source Edition (OSE), as available from http://www.virtualbox.org. This file is free software; @@ -26,6 +26,8 @@ <xsl:strip-space elements="*"/> +<xsl:param name="a_sTarget">all</xsl:param> + <!-- // templates @@ -45,6 +47,7 @@ * * Source : src/VBox/Main/idl/VirtualBox.xidl * Generator : src/VBox/Installer/VirtualBox_TypeLib.xsl + * Arguments : a_sTarget=<xsl:value-of select="$a_sTarget"/> */ </xsl:comment> <xsl:apply-templates/> @@ -66,7 +69,14 @@ <AppId> <xsl:attribute name="Id"><xsl:value-of select="@appUuid"/></xsl:attribute> <xsl:attribute name="Description"><xsl:value-of select="@name"/> Application</xsl:attribute> - <xsl:apply-templates select="module/class"/> + <xsl:choose> + <xsl:when test="$a_sTarget = 'VBoxClient-x86'"> + <xsl:apply-templates select="module[@name='VBoxC']/class"/> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="module/class"/> + </xsl:otherwise> + </xsl:choose> </AppId> </TypeLib> </Include> |