vbox: Stop hardcoding a single path for VBoxXPCOMC.so

This partly reverts df90ca7661.

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.
This commit is contained in:
Matthias Bolte 2010-10-22 21:25:03 +02:00
parent 3fb71895e8
commit f4a8542dd5
4 changed files with 132 additions and 172 deletions

View File

@ -234,8 +234,8 @@ AC_ARG_WITH([xenapi],
AC_HELP_STRING([--with-xenapi], [add XenAPI support @<:@default=check@:>@]),[],[with_xenapi=check]) AC_HELP_STRING([--with-xenapi], [add XenAPI support @<:@default=check@:>@]),[],[with_xenapi=check])
AC_ARG_WITH([vbox], AC_ARG_WITH([vbox],
AC_HELP_STRING([--with-vbox=@<:@PFX@:>@], AC_HELP_STRING([--with-vbox=@<:@PFX@:>@],
[VirtualBox XPCOMC location @<:@default=check@:>@]),[], [VirtualBox XPCOMC location @<:@default=yes@:>@]),[],
[with_vbox=check]) [with_vbox=yes])
AC_ARG_WITH([lxc], AC_ARG_WITH([lxc],
AC_HELP_STRING([--with-lxc], [add Linux Container support @<:@default=check@:>@]),[],[with_lxc=check]) AC_HELP_STRING([--with-lxc], [add Linux Container support @<:@default=check@:>@]),[],[with_lxc=check])
AC_ARG_WITH([one], AC_ARG_WITH([one],
@ -341,51 +341,10 @@ dnl
vbox_xpcomc_dir= vbox_xpcomc_dir=
if test "x$with_vbox" = "xyes" || test "x$with_vbox" = "xcheck"; then if test "x$with_vbox" != "xyes" && test "x$with_vbox" != "xno"; then
AC_MSG_CHECKING([for VirtualBox XPCOMC location]) # intentionally don't do any further checks here on the provided path
vbox_xpcomc_dir=$with_vbox
for vbox in \ with_vbox=yes
/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
fi fi
AC_DEFINE_UNQUOTED([VBOX_XPCOMC_DIR], ["$vbox_xpcomc_dir"], AC_DEFINE_UNQUOTED([VBOX_XPCOMC_DIR], ["$vbox_xpcomc_dir"],

View File

@ -93,6 +93,7 @@ src/util/util.c
src/util/virtaudit.c src/util/virtaudit.c
src/util/virterror.c src/util/virterror.c
src/util/xml.c src/util/xml.c
src/vbox/vbox_XPCOMCGlue.c
src/vbox/vbox_driver.c src/vbox/vbox_driver.c
src/vbox/vbox_tmpl.c src/vbox/vbox_tmpl.c
src/xen/proxy_internal.c src/xen/proxy_internal.c

View File

@ -32,13 +32,18 @@
#include <config.h> #include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <stdbool.h>
#include "vbox_XPCOMCGlue.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,113 +65,104 @@
*******************************************************************************/ *******************************************************************************/
/** The dlopen handle for VBoxXPCOMC. */ /** The dlopen handle for VBoxXPCOMC. */
void *g_hVBoxXPCOMC = NULL; void *g_hVBoxXPCOMC = NULL;
/** The last load error. */
char g_szVBoxErrMsg[256];
/** Pointer to the VBoxXPCOMC function table. */ /** Pointer to the VBoxXPCOMC function table. */
PCVBOXXPCOM g_pVBoxFuncs = NULL; PCVBOXXPCOM g_pVBoxFuncs = NULL;
/** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */ /** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */
PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions = NULL; 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 * Try load VBoxXPCOMC.so/dylib/dll from the specified location and resolve all
* the symbols we need. * the symbols we need.
* *
* @returns 0 on success, -1 on failure. * @returns 0 on success, -1 on failure and 1 if VBoxXPCOMC was not found.
* @param pszHome The director where to try load VBoxXPCOMC from. Can * @param dir The directory where to try load VBoxXPCOMC from. Can
* be NULL. * be NULL.
* @param fSetAppHome Whether to set the VBOX_APP_HOME env.var. or not * @param setAppHome Whether to set the VBOX_APP_HOME env.var. or not.
* (boolean). * @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; int result = -1;
size_t cbBufNeeded; char *name = NULL;
char szName[4096]; PFNVBOXGETXPCOMCFUNCTIONS pfnGetFunctions;
int rc = -1;
/* if (dir != NULL) {
* Construct the full name. if (virAsprintf(&name, "%s/%s", dir, DYNLIB_NAME) < 0) {
*/ virReportOOMError();
cbBufNeeded = cchHome + sizeof("/" DYNLIB_NAME); return -1;
if (cbBufNeeded > sizeof(szName)) }
{
setErrMsg(1, "path buffer too small: %u bytes needed", if (!virFileExists(name)) {
(unsigned)cbBufNeeded); if (!ignoreMissing) {
return -1; VIR_ERROR(_("Libaray '%s' doesn't exist"), name);
}
return -1;
}
} else {
name = strdup(DYNLIB_NAME);
if (name == NULL) {
virReportOOMError();
return -1;
}
} }
if (cchHome)
{
memcpy(szName, pszHome, cchHome);
szName[cchHome] = '/';
cchHome++;
}
memcpy(&szName[cchHome], DYNLIB_NAME, sizeof(DYNLIB_NAME));
/* /*
* Try load it by that name, setting the VBOX_APP_HOME first (for now). * Try load it by that name, setting the VBOX_APP_HOME first (for now).
* Then resolve and call the function table getter. * Then resolve and call the function table getter.
*/ */
if (fSetAppHome) if (setAppHome) {
{ if (dir != NULL) {
if (pszHome) setenv("VBOX_APP_HOME", dir, 1 /* always override */);
setenv("VBOX_APP_HOME", pszHome, 1 /* always override */); } else {
else
unsetenv("VBOX_APP_HOME"); 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); dlclose(g_hVBoxXPCOMC);
g_hVBoxXPCOMC = NULL; g_hVBoxXPCOMC = NULL;
} }
else
setErrMsg(0, "dlopen(%.80s): %.160s", szName, dlerror()); VIR_FREE(name);
return rc;
return result;
} }
@ -175,34 +171,53 @@ static int tryLoadOne(const char *pszHome, int fSetAppHome)
* function pointers. * function pointers.
* *
* @returns 0 on success, -1 on failure. * @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) int VBoxCGlueInit(void)
{ {
/* int i;
* If the user specifies the location, try only that. static const char *knownDirs[] = {
*/ "/usr/lib/virtualbox",
const char *pszHome = getenv("VBOX_APP_HOME"); "/usr/lib/virtualbox-ose",
if (pszHome) "/usr/lib64/virtualbox",
return tryLoadOne(pszHome, 0); "/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. */
* Try the configured location. if (home != NULL) {
*/ if (tryLoadOne(home, false, false) < 0) {
g_szVBoxErrMsg[0] = '\0'; return -1;
}
}
if (tryLoadOne(VBOX_XPCOMC_DIR, 1) == 0) /* Try the additionally configured location. */
return 0; if (VBOX_XPCOMC_DIR[0] != '\0') {
if (tryLoadOne(VBOX_XPCOMC_DIR, true, true) >= 0) {
/* return 0;
* Finally try the dynamic linker search path. }
*/ }
if (tryLoadOne(NULL, 1) == 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, false, true) >= 0) {
return 0; return 0;
}
/* No luck, return failure. */ /* No luck, return failure. */
return -1; return -1;
@ -214,14 +229,13 @@ int VBoxCGlueInit(void)
*/ */
void VBoxCGlueTerm(void) void VBoxCGlueTerm(void)
{ {
if (g_hVBoxXPCOMC) if (g_hVBoxXPCOMC != NULL) {
{
#if 0 /* VBoxRT.so doesn't like being reloaded. See @bugref{3725}. */ #if 0 /* VBoxRT.so doesn't like being reloaded. See @bugref{3725}. */
dlclose(g_hVBoxXPCOMC); dlclose(g_hVBoxXPCOMC);
#endif #endif
g_hVBoxXPCOMC = NULL; g_hVBoxXPCOMC = NULL;
} }
g_pVBoxFuncs = NULL; g_pVBoxFuncs = NULL;
g_pfnGetFunctions = NULL; g_pfnGetFunctions = NULL;
memset(g_szVBoxErrMsg, 0, sizeof(g_szVBoxErrMsg));
} }

View File

@ -32,26 +32,12 @@
/* This has to be the oldest version we support. */ /* This has to be the oldest version we support. */
# include "vbox_CAPI_v2_2.h" # 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. */ /** Pointer to the VBoxXPCOMC function table. */
extern PCVBOXXPCOM g_pVBoxFuncs; extern PCVBOXXPCOM g_pVBoxFuncs;
/** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */ /** Pointer to VBoxGetXPCOMCFunctions for the loaded VBoxXPCOMC so/dylib/dll. */
extern PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions; extern PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions;
int VBoxCGlueInit(void); int VBoxCGlueInit(void);
void VBoxCGlueTerm(void); void VBoxCGlueTerm(void);
# ifdef __cplusplus
}
# endif
#endif #endif