Split the convoluted driver loader function into simpler parts which
will potentially allow reuse.
---
src/driver.c | 133 +++++++++++++++++++++++++++++-----------
src/driver.h | 3 +
src/libvirt_driver_modules.syms | 1 +
3 files changed, 101 insertions(+), 36 deletions(-)
diff --git a/src/driver.c b/src/driver.c
index 67ac02006..783e08a28 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -43,15 +43,105 @@ VIR_LOG_INIT("driver");
# include <dlfcn.h>
# define DEFAULT_DRIVER_DIR LIBDIR "/libvirt/connection-driver"
+
+static void *
+virDriverLoadModuleFile(const char *file)
+{
+ void *handle = NULL;
+
+ VIR_DEBUG("Load module file '%s'", file);
+
+ if (access(file, R_OK) < 0) {
+ VIR_INFO("Module %s not accessible", file);
+ return NULL;
+ }
+
+ virUpdateSelfLastChanged(file);
+
+ if (!(handle = dlopen(file, RTLD_NOW | RTLD_GLOBAL)))
+ VIR_ERROR(_("failed to load module %s %s"), file, dlerror());
+
+ return handle;
+}
+
+
+static void *
+virDriverLoadModuleFunc(void *handle,
+ const char *funcname)
+{
+ void *regsym;
+
+ VIR_DEBUG("Lookup function '%s'", funcname);
+
+ if (!(regsym = dlsym(handle, funcname)))
+ VIR_ERROR(_("Missing module registration symbol %s"), funcname);
+
+ return regsym;
+}
+
+
+/**
+ * virDriverLoadModuleFull:
+ * @path: filename of module to load
+ * @regfunc: name of the function that registers the module
+ * @handle: Returns handle of the loaded library if not NULL
+ *
+ * Loads a loadable module named @path and calls the
+ * registration function @regfunc. If @handle is not NULL the handle is returned
+ * in the variable. Otherwise the handle is leaked so that the module stays
+ * loaded forever.
+ *
+ * The module is automatically looked up in the appropriate place (git or
+ * installed directory).
+ *
+ * Returns 0 on success, 1 if the module was not found and -1 on any error.
+ */
+int
+virDriverLoadModuleFull(const char *path,
+ const char *regfunc,
+ void **handle)
+{
+ void *rethandle = NULL;
+ int (*regsym)(void);
+ int ret = -1;
+
+ VIR_DEBUG("Module load %s", path);
+
+ if (!(rethandle = virDriverLoadModuleFile(path))) {
+ ret = 1;
+ goto cleanup;
+ }
+
+ if (!(regsym = virDriverLoadModuleFunc(rethandle, regfunc)))
+ goto cleanup;
+
+ if ((*regsym)() < 0) {
+ VIR_ERROR(_("Failed module registration %s"), regfunc);
+ goto cleanup;
+ }
+
+ if (handle)
+ VIR_STEAL_PTR(*handle, rethandle);
+ else
+ rethandle = NULL;
+
+ ret = 0;
+
+ cleanup:
+ if (rethandle)
+ dlclose(rethandle);
+ return ret;
+}
+
+
void *
virDriverLoadModule(const char *name)
{
- char *modfile = NULL, *regfunc = NULL, *fixedname = NULL;
+ char *modfile = NULL;
+ char *fixedname = NULL;
+ char *regfunc = NULL;
char *tmp;
void *handle = NULL;
- int (*regsym)(void);
-
- VIR_DEBUG("Module load %s", name);
if (!(modfile = virFileFindResourceFull(name,
"libvirt_driver_",
@@ -61,19 +151,6 @@ virDriverLoadModule(const char *name)
"LIBVIRT_DRIVER_DIR")))
return NULL;
- if (access(modfile, R_OK) < 0) {
- VIR_INFO("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 (VIR_STRDUP_QUIET(fixedname, name) < 0) {
VIR_ERROR(_("out of memory"));
goto cleanup;
@@ -88,29 +165,13 @@ virDriverLoadModule(const char *name)
if (virAsprintfQuiet(®func, "%sRegister", fixedname) < 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);
- VIR_FREE(fixedname);
- return handle;
+ virDriverLoadModuleFull(modfile, regfunc, &handle);
cleanup:
VIR_FREE(modfile);
- VIR_FREE(regfunc);
VIR_FREE(fixedname);
- if (handle)
- dlclose(handle);
- return NULL;
+ VIR_FREE(regfunc);
+ return handle;
}
diff --git a/src/driver.h b/src/driver.h
index e4e382b63..885e8843e 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -100,5 +100,8 @@ int virSetSharedSecretDriver(virSecretDriverPtr driver)
ATTRIBUTE_RETURN_CHECK;
int virSetSharedStorageDriver(virStorageDriverPtr driver) ATTRIBUTE_RETURN_CHECK;
void *virDriverLoadModule(const char *name);
+int virDriverLoadModuleFull(const char *name,
+ const char *regfunc,
+ void **handle);
#endif /* __VIR_DRIVER_H__ */
diff --git a/src/libvirt_driver_modules.syms b/src/libvirt_driver_modules.syms
index f9d0ee9b9..bd9bf1c31 100644
--- a/src/libvirt_driver_modules.syms
+++ b/src/libvirt_driver_modules.syms
@@ -4,6 +4,7 @@
# driver.h
virDriverLoadModule;
+virDriverLoadModuleFull;
# Let emacs know we want case-insensitive sorting
# Local Variables:
--
2.11.0