[libvirt] [PATCH] vbox: Stop hardcoding a single path for VBoxXPCOMC.so

This partly reverts df90ca7661b0a789bd790ccf8258a4527c13eb8d. Don't disable the VirtualBox driver when configure can't find VBoxXPCOMC.so, rely on detection at runtime again instead. Keep --with-vbox=/path/to/virtualbox intact, added to for: https://bugzilla.redhat.com/show_bug.cgi?id=609185 Detection order for VBoxXPCOMC.so: 1. VBOX_APP_HOME environment variable 2. configure provided location 3. hardcoded list of known locations 4. dynamic linker search path Also cleanup the glue code and improve error reporting. --- Patch is based on Daniel's suggestion in: https://www.redhat.com/archives/libvir-list/2010-October/msg00852.html configure.ac | 53 +--------- po/POTFILES.in | 1 + src/vbox/vbox_XPCOMCGlue.c | 232 +++++++++++++++++++++++--------------------- src/vbox/vbox_XPCOMCGlue.h | 14 --- 4 files changed, 130 insertions(+), 170 deletions(-) diff --git a/configure.ac b/configure.ac index e41f2b5..40d6b69 100644 --- a/configure.ac +++ b/configure.ac @@ -225,8 +225,8 @@ AC_ARG_WITH([xenapi], AC_HELP_STRING([--with-xenapi], [add XenAPI support @<:@default=check@:>@]),[],[with_xenapi=check]) AC_ARG_WITH([vbox], AC_HELP_STRING([--with-vbox=@<:@PFX@:>@], - [VirtualBox XPCOMC location @<:@default=check@:>@]),[], - [with_vbox=check]) + [VirtualBox XPCOMC location @<:@default=yes@:>@]),[], + [with_vbox=yes]) AC_ARG_WITH([lxc], AC_HELP_STRING([--with-lxc], [add Linux Container support @<:@default=check@:>@]),[],[with_lxc=check]) AC_ARG_WITH([one], @@ -332,51 +332,10 @@ dnl vbox_xpcomc_dir= -if test "x$with_vbox" = "xyes" || test "x$with_vbox" = "xcheck"; then - AC_MSG_CHECKING([for VirtualBox XPCOMC location]) - - for vbox in \ - /usr/lib/virtualbox/VBoxXPCOMC.so \ - /usr/lib64/virtualbox/VBoxXPCOMC.so \ - /usr/lib/VirtualBox/VBoxXPCOMC.so \ - /opt/virtualbox/VBoxXPCOMC.so \ - /opt/VirtualBox/VBoxXPCOMC.so \ - /opt/virtualbox/i386/VBoxXPCOMC.so \ - /opt/VirtualBox/i386/VBoxXPCOMC.so \ - /opt/virtualbox/amd64/VBoxXPCOMC.so \ - /opt/VirtualBox/amd64/VBoxXPCOMC.so \ - /usr/local/lib/virtualbox/VBoxXPCOMC.so \ - /usr/local/lib/VirtualBox/VBoxXPCOMC.so \ - /Applications/VirtualBox.app/Contents/MacOS/VBoxXPCOMC.dylib \ - ; do - if test -f "$vbox"; then - vbox_xpcomc_dir=`AS_DIRNAME(["$vbox"])` - break - fi - done - - if test -n "$vbox_xpcomc_dir"; then - AC_MSG_RESULT([$vbox_xpcomc_dir]) - with_vbox=yes - else - if test "x$with_vbox" = "xcheck"; then - AC_MSG_RESULT([not found, disabling VirtualBox driver]) - with_vbox=no - else - AC_MSG_RESULT([not found]) - AC_MSG_ERROR([VirtualBox XPCOMC is required for the VirtualBox driver]) - fi - fi -else - if test "x$with_vbox" != "xno"; then - if test -f ${with_vbox}/VBoxXPCOMC.so || \ - test -f ${with_vbox}/VBoxXPCOMC.dylib; then - vbox_xpcomc_dir=$with_vbox - with_vbox=yes - else - AC_MSG_ERROR([$with_vbox does not contain VirtualBox XPCOMC]) - fi - fi +if test "x$with_vbox" != "xyes" && test "x$with_vbox" != "xno"; then + # intentionally don't do any further checks here on the provided path + vbox_xpcomc_dir=$with_vbox + with_vbox=yes fi AC_DEFINE_UNQUOTED([VBOX_XPCOMC_DIR], ["$vbox_xpcomc_dir"], diff --git a/po/POTFILES.in b/po/POTFILES.in index 541335e..dafef47 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -93,6 +93,7 @@ src/util/util.c src/util/virtaudit.c src/util/virterror.c src/util/xml.c +src/vbox/vbox_XPCOMCGlue.c src/vbox/vbox_driver.c src/vbox/vbox_tmpl.c src/xen/proxy_internal.c diff --git a/src/vbox/vbox_XPCOMCGlue.c b/src/vbox/vbox_XPCOMCGlue.c index e8b0bd1..7648e54 100644 --- a/src/vbox/vbox_XPCOMCGlue.c +++ b/src/vbox/vbox_XPCOMCGlue.c @@ -32,13 +32,18 @@ #include <config.h> -#include <stdio.h> -#include <string.h> #include <stdlib.h> -#include <stdarg.h> #include <dlfcn.h> +#include <stdbool.h> #include "vbox_XPCOMCGlue.h" +#include "internal.h" +#include "memory.h" +#include "util.h" +#include "logging.h" +#include "virterror_internal.h" + +#define VIR_FROM_THIS VIR_FROM_VBOX /******************************************************************************* @@ -60,8 +65,6 @@ *******************************************************************************/ /** The dlopen handle for VBoxXPCOMC. */ void *g_hVBoxXPCOMC = NULL; -/** The last load error. */ -char g_szVBoxErrMsg[256]; /** Pointer to the VBoxXPCOMC function table. */ PCVBOXXPCOM g_pVBoxFuncs = NULL; /** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */ @@ -69,104 +72,97 @@ PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions = NULL; /** - * Wrapper for setting g_szVBoxErrMsg. Can be an empty stub. - * - * @param fAlways When 0 the g_szVBoxErrMsg is only set if empty. - * @param pszFormat The format string. - * @param ... The arguments. - */ -static void setErrMsg(int fAlways, const char *pszFormat, ...) -{ -#ifndef LIBVIRT_VERSION - if ( fAlways - || !g_szVBoxErrMsg[0]) - { - va_list va; - va_start(va, pszFormat); - vsnprintf(g_szVBoxErrMsg, sizeof(g_szVBoxErrMsg), pszFormat, va); - va_end(va); - } -#else /* libvirt */ - (void)fAlways; - (void)pszFormat; -#endif /* libvirt */ -} - - -/** * Try load VBoxXPCOMC.so/dylib/dll from the specified location and resolve all * the symbols we need. * - * @returns 0 on success, -1 on failure. - * @param pszHome The director where to try load VBoxXPCOMC from. Can - * be NULL. - * @param fSetAppHome Whether to set the VBOX_APP_HOME env.var. or not - * (boolean). + * @returns 0 on success, -1 on failure and 1 if VBoxXPCOMC was not found. + * @param dir The directory where to try load VBoxXPCOMC from. Can + * be NULL. + * @param setAppHome Whether to set the VBOX_APP_HOME env.var. or not. + * @param ignoreMissing Whether to ignore missing library or not. */ -static int tryLoadOne(const char *pszHome, int fSetAppHome) +static int tryLoadOne(const char *dir, bool setAppHome, bool ignoreMissing) { - size_t cchHome = pszHome ? strlen(pszHome) : 0; - size_t cbBufNeeded; - char szName[4096]; - int rc = -1; + int result = -1; + char *name = NULL; + PFNVBOXGETXPCOMCFUNCTIONS pfnGetFunctions; + + if (dir != NULL) { + if (virAsprintf(&name, "%s/%s", dir, DYNLIB_NAME) < 0) { + virReportOOMError(); + return -1; + } - /* - * Construct the full name. - */ - cbBufNeeded = cchHome + sizeof("/" DYNLIB_NAME); - if (cbBufNeeded > sizeof(szName)) - { - setErrMsg(1, "path buffer too small: %u bytes needed", - (unsigned)cbBufNeeded); - return -1; - } - if (cchHome) - { - memcpy(szName, pszHome, cchHome); - szName[cchHome] = '/'; - cchHome++; + if (!virFileExists(name)) { + if (!ignoreMissing) { + VIR_ERROR(_("Libaray '%s' doesn't exist"), name); + } + + return -1; + } + } else { + name = strdup(DYNLIB_NAME); + + if (name == NULL) { + virReportOOMError(); + return -1; + } } - memcpy(&szName[cchHome], DYNLIB_NAME, sizeof(DYNLIB_NAME)); /* * Try load it by that name, setting the VBOX_APP_HOME first (for now). * Then resolve and call the function table getter. */ - if (fSetAppHome) - { - if (pszHome) - setenv("VBOX_APP_HOME", pszHome, 1 /* always override */); - else + if (setAppHome) { + if (dir != NULL) { + setenv("VBOX_APP_HOME", dir, 1 /* always override */); + } else { unsetenv("VBOX_APP_HOME"); + } } - g_hVBoxXPCOMC = dlopen(szName, RTLD_NOW | RTLD_LOCAL); - if (g_hVBoxXPCOMC) - { - PFNVBOXGETXPCOMCFUNCTIONS pfnGetFunctions; - pfnGetFunctions = (PFNVBOXGETXPCOMCFUNCTIONS) - dlsym(g_hVBoxXPCOMC, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME); - if (pfnGetFunctions) - { - g_pVBoxFuncs = pfnGetFunctions(VBOX_XPCOMC_VERSION); - if (g_pVBoxFuncs) - { - g_pfnGetFunctions = pfnGetFunctions; - return 0; - } - /* bail out */ - setErrMsg(1, "%.80s: pfnGetFunctions(%#x) failed", - szName, VBOX_XPCOMC_VERSION); - } - else - setErrMsg(1, "dlsym(%.80s/%.32s): %.128s", - szName, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME, dlerror()); + g_hVBoxXPCOMC = dlopen(name, RTLD_NOW | RTLD_LOCAL); + + if (g_hVBoxXPCOMC == NULL) { + VIR_WARN("Could not dlopen '%s': %s", name, dlerror()); + goto cleanup; + } + + pfnGetFunctions = (PFNVBOXGETXPCOMCFUNCTIONS) + dlsym(g_hVBoxXPCOMC, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME); + + if (pfnGetFunctions == NULL) { + VIR_ERROR(_("Could not dlsym %s from '%s': %s"), + VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME, name, dlerror()); + goto cleanup; + } + + g_pVBoxFuncs = pfnGetFunctions(VBOX_XPCOMC_VERSION); + + if (g_pVBoxFuncs == NULL) { + VIR_ERROR(_("Calling %s from '%s' failed"), + VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME, name); + goto cleanup; + } + + g_pfnGetFunctions = pfnGetFunctions; + result = 0; + + if (dir != NULL) { + VIR_DEBUG("Found %s in '%s'", DYNLIB_NAME, dir); + } else { + VIR_DEBUG("Found %s in dynamic linker search path", DYNLIB_NAME); + } + +cleanup: + if (g_hVBoxXPCOMC != NULL && result < 0) { dlclose(g_hVBoxXPCOMC); g_hVBoxXPCOMC = NULL; } - else - setErrMsg(0, "dlopen(%.80s): %.160s", szName, dlerror()); - return rc; + + VIR_FREE(name); + + return result; } @@ -175,34 +171,53 @@ static int tryLoadOne(const char *pszHome, int fSetAppHome) * function pointers. * * @returns 0 on success, -1 on failure. - * - * @remark This should be considered moved into a separate glue library since - * its its going to be pretty much the same for any user of VBoxXPCOMC - * and it will just cause trouble to have duplicate versions of this - * source code all around the place. */ int VBoxCGlueInit(void) { - /* - * If the user specifies the location, try only that. - */ - const char *pszHome = getenv("VBOX_APP_HOME"); - if (pszHome) - return tryLoadOne(pszHome, 0); + int i; + static const char *knownDirs[] = { + "/usr/lib/virtualbox", + "/usr/lib/virtualbox-ose", + "/usr/lib64/virtualbox", + "/usr/lib64/virtualbox-ose", + "/usr/lib/VirtualBox", + "/opt/virtualbox", + "/opt/VirtualBox", + "/opt/virtualbox/i386", + "/opt/VirtualBox/i386", + "/opt/virtualbox/amd64", + "/opt/VirtualBox/amd64", + "/usr/local/lib/virtualbox", + "/usr/local/lib/VirtualBox", + "/Applications/VirtualBox.app/Contents/MacOS" + }; + const char *home = getenv("VBOX_APP_HOME"); + + /* If the user specifies the location, try only that. */ + if (home != NULL) { + if (tryLoadOne(home, false, false) < 0) { + return -1; + } + } - /* - * Try the configured location. - */ - g_szVBoxErrMsg[0] = '\0'; + /* Try the additionally configured location. */ + if (VBOX_XPCOMC_DIR[0] != '\0') { + if (tryLoadOne(VBOX_XPCOMC_DIR, true, true) >= 0) { + return 0; + } + } - if (tryLoadOne(VBOX_XPCOMC_DIR, 1) == 0) - return 0; + /* Try the known locations. */ + for (i = 0; i < ARRAY_CARDINALITY(knownDirs); ++i) { + if (tryLoadOne(knownDirs[i], true, true) >= 0) { + return 0; + } + } - /* - * Finally try the dynamic linker search path. - */ - if (tryLoadOne(NULL, 1) == 0) + /* Finally try the dynamic linker search path. */ + if (tryLoadOne(NULL, false, true) >= 0) { return 0; + } /* No luck, return failure. */ return -1; @@ -214,14 +229,13 @@ int VBoxCGlueInit(void) */ void VBoxCGlueTerm(void) { - if (g_hVBoxXPCOMC) - { + if (g_hVBoxXPCOMC != NULL) { #if 0 /* VBoxRT.so doesn't like being reloaded. See @bugref{3725}. */ dlclose(g_hVBoxXPCOMC); #endif g_hVBoxXPCOMC = NULL; } + g_pVBoxFuncs = NULL; g_pfnGetFunctions = NULL; - memset(g_szVBoxErrMsg, 0, sizeof(g_szVBoxErrMsg)); } diff --git a/src/vbox/vbox_XPCOMCGlue.h b/src/vbox/vbox_XPCOMCGlue.h index c04eefa..6c44030 100644 --- a/src/vbox/vbox_XPCOMCGlue.h +++ b/src/vbox/vbox_XPCOMCGlue.h @@ -32,26 +32,12 @@ /* This has to be the oldest version we support. */ # include "vbox_CAPI_v2_2.h" -# ifdef __cplusplus -extern "C" { -# endif - -/** The dlopen handle for VBoxXPCOMC. */ -extern void *g_hVBoxXPCOMC; -/** The last load error. */ -extern char g_szVBoxErrMsg[256]; /** Pointer to the VBoxXPCOMC function table. */ extern PCVBOXXPCOM g_pVBoxFuncs; /** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */ extern PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions; - int VBoxCGlueInit(void); void VBoxCGlueTerm(void); - -# ifdef __cplusplus -} -# endif - #endif -- 1.7.0.4

On 10/22/2010 01:44 PM, Matthias Bolte wrote:
This partly reverts df90ca7661b0a789bd790ccf8258a4527c13eb8d.
Don't disable the VirtualBox driver when configure can't find VBoxXPCOMC.so, rely on detection at runtime again instead.
Keep --with-vbox=/path/to/virtualbox intact, added to for: https://bugzilla.redhat.com/show_bug.cgi?id=609185
Detection order for VBoxXPCOMC.so:
1. VBOX_APP_HOME environment variable 2. configure provided location 3. hardcoded list of known locations 4. dynamic linker search path
Also cleanup the glue code and improve error reporting. -if test "x$with_vbox" = "xyes" || test "x$with_vbox" = "xcheck"; then - AC_MSG_CHECKING([for VirtualBox XPCOMC location]) - - for vbox in \ - /usr/lib/virtualbox/VBoxXPCOMC.so \ - /usr/lib64/virtualbox/VBoxXPCOMC.so \ - /usr/lib/VirtualBox/VBoxXPCOMC.so \ - /opt/virtualbox/VBoxXPCOMC.so \ - /opt/VirtualBox/VBoxXPCOMC.so \ - /opt/virtualbox/i386/VBoxXPCOMC.so \ - /opt/VirtualBox/i386/VBoxXPCOMC.so \ - /opt/virtualbox/amd64/VBoxXPCOMC.so \ - /opt/VirtualBox/amd64/VBoxXPCOMC.so \ - /usr/local/lib/virtualbox/VBoxXPCOMC.so \ - /usr/local/lib/VirtualBox/VBoxXPCOMC.so \ - /Applications/VirtualBox.app/Contents/MacOS/VBoxXPCOMC.dylib \ - ; do - if test -f "$vbox"; then - vbox_xpcomc_dir=`AS_DIRNAME(["$vbox"])` - break - fi - done
I'm wondering if we still want to keep this configure-time loop anyways. As in: --with-vbox=yes => configure-time check; fatal if not found --with-vbox=no => no vbox --with-vbox=check => configure-time of check; if it passes, use that path; if not, fall back dynamic check --with-vbox=path => hard-code path at configure time in which case, the default of --with-vbox=check still makes sense, but the reaction to not finding anything in the loop changes from disabling vbox over to the better action of enabling vbox via the dynamic search fallback.
+static int tryLoadOne(const char *dir, bool setAppHome, bool ignoreMissing) { - size_t cchHome = pszHome ? strlen(pszHome) : 0; - size_t cbBufNeeded; - char szName[4096]; - int rc = -1; + int result = -1; + char *name = NULL; + PFNVBOXGETXPCOMCFUNCTIONS pfnGetFunctions;
WESHOULDALLTALKINALLCAPSWITHNOSPACES :) What a horrid upstream coding convention. But not your fault. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Fri, Oct 22, 2010 at 09:44:22PM +0200, Matthias Bolte wrote:
This partly reverts df90ca7661b0a789bd790ccf8258a4527c13eb8d.
Don't disable the VirtualBox driver when configure can't find VBoxXPCOMC.so, rely on detection at runtime again instead.
Keep --with-vbox=/path/to/virtualbox intact, added to for: https://bugzilla.redhat.com/show_bug.cgi?id=609185
Detection order for VBoxXPCOMC.so:
1. VBOX_APP_HOME environment variable 2. configure provided location 3. hardcoded list of known locations 4. dynamic linker search path
Also cleanup the glue code and improve error reporting. ---
Patch is based on Daniel's suggestion in:
https://www.redhat.com/archives/libvir-list/2010-October/msg00852.html
configure.ac | 53 +--------- po/POTFILES.in | 1 + src/vbox/vbox_XPCOMCGlue.c | 232 +++++++++++++++++++++++--------------------- src/vbox/vbox_XPCOMCGlue.h | 14 --- 4 files changed, 130 insertions(+), 170 deletions(-)
ACK, looks good to me Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

2010/10/28 Daniel P. Berrange <berrange@redhat.com>:
On Fri, Oct 22, 2010 at 09:44:22PM +0200, Matthias Bolte wrote:
This partly reverts df90ca7661b0a789bd790ccf8258a4527c13eb8d.
Don't disable the VirtualBox driver when configure can't find VBoxXPCOMC.so, rely on detection at runtime again instead.
Keep --with-vbox=/path/to/virtualbox intact, added to for: https://bugzilla.redhat.com/show_bug.cgi?id=609185
Detection order for VBoxXPCOMC.so:
1. VBOX_APP_HOME environment variable 2. configure provided location 3. hardcoded list of known locations 4. dynamic linker search path
Also cleanup the glue code and improve error reporting. ---
Patch is based on Daniel's suggestion in:
https://www.redhat.com/archives/libvir-list/2010-October/msg00852.html
configure.ac | 53 +--------- po/POTFILES.in | 1 + src/vbox/vbox_XPCOMCGlue.c | 232 +++++++++++++++++++++++--------------------- src/vbox/vbox_XPCOMCGlue.h | 14 --- 4 files changed, 130 insertions(+), 170 deletions(-)
ACK, looks good to me
Daniel
Thanks, pushed. Matthias
participants (3)
-
Daniel P. Berrange
-
Eric Blake
-
Matthias Bolte