libvirt/src/driver.c
Daniel P. Berrange 10ec072545 Add helper APIs to track if libvirtd or loadable modules have changed
The future QEMU capabilities cache needs to be able to invalidate
itself if the libvirtd binary or any loadable modules are changed
on disk. Record the 'ctime' value for these binaries and provide
helper APIs to query it. This approach assumes that if libvirt.so
is changed, then libvirtd will also change, which should usually
be the case with libtool's wrapper scripts that cause libvirtd to
get re-linked

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-03-11 10:51:49 +00:00

116 lines
2.7 KiB
C

/*
* driver.c: Helpers for loading drivers
*
* Copyright (C) 2006-2011 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
#include <config.h>
#include <unistd.h>
#include "driver.h"
#include "viralloc.h"
#include "virlog.h"
#include "virutil.h"
#include "configmake.h"
#include "virstring.h"
#define DEFAULT_DRIVER_DIR LIBDIR "/libvirt/connection-driver"
#ifdef WITH_DRIVER_MODULES
/* XXX re-implment this for other OS, or use libtools helper lib ? */
# include <dlfcn.h>
static const char *moddir = NULL;
void
virDriverModuleInitialize(const char *defmoddir)
{
const char *custommoddir = virGetEnvBlockSUID("LIBVIRT_DRIVER_DIR");
if (custommoddir)
moddir = custommoddir;
else if (defmoddir)
moddir = defmoddir;
else
moddir = DEFAULT_DRIVER_DIR;
VIR_DEBUG("Module dir %s", moddir);
}
void *
virDriverLoadModule(const char *name)
{
char *modfile = NULL, *regfunc = NULL;
void *handle = NULL;
int (*regsym)(void);
if (moddir == NULL)
virDriverModuleInitialize(NULL);
VIR_DEBUG("Module load %s", name);
if (virAsprintfQuiet(&modfile, "%s/libvirt_driver_%s.so", moddir, name) < 0)
return NULL;
if (access(modfile, R_OK) < 0) {
VIR_WARN("Module %s not accessible", modfile);
goto cleanup;
}
virUpdateSelfLastChanged(modfile);
handle = dlopen(modfile, RTLD_NOW | RTLD_GLOBAL);
if (!handle) {
VIR_ERROR(_("failed to load module %s %s"), modfile, dlerror());
goto cleanup;
}
if (virAsprintfQuiet(&regfunc, "%sRegister", name) < 0) {
goto cleanup;
}
regsym = dlsym(handle, regfunc);
if (!regsym) {
VIR_ERROR(_("Missing module registration symbol %s"), regfunc);
goto cleanup;
}
if ((*regsym)() < 0) {
VIR_ERROR(_("Failed module registration %s"), regfunc);
goto cleanup;
}
VIR_FREE(modfile);
VIR_FREE(regfunc);
return handle;
cleanup:
VIR_FREE(modfile);
VIR_FREE(regfunc);
if (handle)
dlclose(handle);
return NULL;
}
/* XXX unload modules, but we can't until we can unregister libvirt drivers */
#endif