#include "viralloc.h"
#include "virfile.h"
#include "virlog.h"
+#include "virmodule.h"
#include "virthread.h"
#include "configmake.h"
/* XXX re-implement this for other OS, or use libtools helper lib ? */
#define DEFAULT_DRIVER_DIR LIBDIR "/libvirt/connection-driver"
-#ifdef HAVE_DLFCN_H
-# include <dlfcn.h>
-
-
-static void *
-virDriverLoadModuleFile(const char *file)
-{
- void *handle = NULL;
- int flags = RTLD_NOW | RTLD_GLOBAL;
-
-# ifdef RTLD_NODELETE
- flags |= RTLD_NODELETE;
-# endif
-
- VIR_DEBUG("Load module file '%s'", file);
-
- virUpdateSelfLastChanged(file);
-
- if (!(handle = dlopen(file, flags))) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Failed to load module '%s': %s"), file, dlerror());
- return NULL;
- }
-
- return handle;
-}
-
-
-static void *
-virDriverLoadModuleFunc(void *handle,
- const char *file,
- const char *funcname)
-{
- void *regsym;
-
- VIR_DEBUG("Lookup function '%s'", funcname);
-
- if (!(regsym = dlsym(handle, funcname))) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Failed to find symbol '%s' in module '%s': %s"),
- funcname, file, dlerror());
- return NULL;
- }
-
- return regsym;
-}
-
-
-/**
- * virDriverLoadModuleFull:
- * @path: filename of module to load
- * @regfunc: name of the function that registers the module
- *
- * Loads a loadable module named @path and calls the
- * registration function @regfunc. The module will never
- * be unloaded because unloading is not safe in a multi-threaded
- * application.
- *
- * 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,
- bool required)
-{
- void *rethandle = NULL;
- int (*regsym)(void);
- int ret = -1;
-
- if (!virFileExists(path)) {
- if (required) {
- virReportSystemError(errno,
- _("Failed to find module '%s'"), path);
- return -1;
- } else {
- VIR_INFO("Module '%s' does not exist", path);
- return 1;
- }
- }
-
- if (!(rethandle = virDriverLoadModuleFile(path)))
- goto cleanup;
-
- if (!(regsym = virDriverLoadModuleFunc(rethandle, path, regfunc)))
- goto cleanup;
-
- if ((*regsym)() < 0) {
- /* regsym() should report an error itself, but lets
- * just make sure */
- virErrorPtr err = virGetLastError();
- if (err == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Failed to execute symbol '%s' in module '%s'"),
- regfunc, path);
- }
- goto cleanup;
- }
-
- rethandle = NULL;
- ret = 0;
-
- cleanup:
- if (rethandle)
- dlclose(rethandle);
- return ret;
-}
-
-#else /* ! HAVE_DLFCN_H */
-int
-virDriverLoadModuleFull(const char *path ATTRIBUTE_UNUSED,
- const char *regfunc ATTRIBUTE_UNUSED,
- bool required)
-{
- VIR_DEBUG("dlopen not available on this platform");
- if (required) {
- virReportSystemError(ENOSYS,
- _("Failed to find module '%s': %s"), path);
- return -1;
- } else {
- /* Since we have no dlopen(), but definition we have no
- * loadable modules on disk, so we can resaonably
- * return '1' instead of an error.
- */
- return 1;
- }
-}
-#endif /* ! HAVE_DLFCN_H */
int
"LIBVIRT_DRIVER_DIR")))
return -1;
- ret = virDriverLoadModuleFull(modfile, regfunc, required);
+ ret = virModuleLoad(modfile, regfunc, required);
VIR_FREE(modfile);
int virDriverLoadModule(const char *name,
const char *regfunc,
bool required);
-int virDriverLoadModuleFull(const char *path,
- const char *regfunc,
- bool required);
virConnectPtr virGetConnectInterface(void);
virConnectPtr virGetConnectNetwork(void);
# driver.h
virDriverLoadModule;
-virDriverLoadModuleFull;
# Let emacs know we want case-insensitive sorting
# Local Variables:
virMediatedDeviceTypeReadAttrs;
+# util/virmodule.h
+virModuleLoad;
+
# util/virnetdev.h
virNetDevAddMulti;
#include "virstoragefile.h"
#include "storage_backend.h"
#include "virlog.h"
+#include "virmodule.h"
#include "virfile.h"
#include "configmake.h"
"LIBVIRT_STORAGE_BACKEND_DIR")))
return -1;
- ret = virDriverLoadModuleFull(modfile, regfunc, forceload);
+ ret = virModuleLoad(modfile, regfunc, forceload);
VIR_FREE(modfile);
util/virmacaddr.h \
util/virmacmap.c \
util/virmacmap.h \
+ util/virmodule.c \
+ util/virmodule.h \
util/virnetdev.c \
util/virnetdev.h \
util/virnetdevbandwidth.c \
--- /dev/null
+/*
+ * virmodule.c: APIs for dlopen'ing extension modules
+ *
+ * Copyright (C) 2012-2018 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 "internal.h"
+#include "virmodule.h"
+#include "virerror.h"
+#include "virfile.h"
+#include "virlog.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_LOG_INIT("util.module");
+
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+
+static void *
+virModuleLoadFile(const char *file)
+{
+ void *handle = NULL;
+ int flags = RTLD_NOW | RTLD_GLOBAL;
+
+# ifdef RTLD_NODELETE
+ flags |= RTLD_NODELETE;
+# endif
+
+ VIR_DEBUG("Load module file '%s'", file);
+
+ virUpdateSelfLastChanged(file);
+
+ if (!(handle = dlopen(file, flags))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to load module '%s': %s"), file, dlerror());
+ return NULL;
+ }
+
+ return handle;
+}
+
+
+static void *
+virModuleLoadFunc(void *handle,
+ const char *file,
+ const char *funcname)
+{
+ void *regsym;
+
+ VIR_DEBUG("Lookup function '%s'", funcname);
+
+ if (!(regsym = dlsym(handle, funcname))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to find symbol '%s' in module '%s': %s"),
+ funcname, file, dlerror());
+ return NULL;
+ }
+
+ return regsym;
+}
+
+
+/**
+ * virModuleLoad:
+ * @path: filename of module to load
+ * @regfunc: name of the function that registers the module
+ * @required: true if module must exist on disk, false to silently skip
+ *
+ * Loads a loadable module named @path and calls the
+ * registration function @regfunc. The module will never
+ * be unloaded because unloading is not safe in a multi-threaded
+ * application.
+ *
+ * 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
+virModuleLoad(const char *path,
+ const char *regfunc,
+ bool required)
+{
+ void *rethandle = NULL;
+ int (*regsym)(void);
+ int ret = -1;
+
+ if (!virFileExists(path)) {
+ if (required) {
+ virReportSystemError(errno,
+ _("Failed to find module '%s'"), path);
+ return -1;
+ } else {
+ VIR_INFO("Module '%s' does not exist", path);
+ return 1;
+ }
+ }
+
+ if (!(rethandle = virModuleLoadFile(path)))
+ goto cleanup;
+
+ if (!(regsym = virModuleLoadFunc(rethandle, path, regfunc)))
+ goto cleanup;
+
+ if ((*regsym)() < 0) {
+ /* regsym() should report an error itself, but lets
+ * just make sure */
+ virErrorPtr err = virGetLastError();
+ if (err == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to execute symbol '%s' in module '%s'"),
+ regfunc, path);
+ }
+ goto cleanup;
+ }
+
+ rethandle = NULL;
+ ret = 0;
+
+ cleanup:
+ if (rethandle)
+ dlclose(rethandle);
+ return ret;
+}
+
+#else /* ! HAVE_DLFCN_H */
+int
+virModuleLoad(const char *path ATTRIBUTE_UNUSED,
+ const char *regfunc ATTRIBUTE_UNUSED,
+ bool required)
+{
+ VIR_DEBUG("dlopen not available on this platform");
+ if (required) {
+ virReportSystemError(ENOSYS,
+ _("Failed to find module '%s': %s"), path);
+ return -1;
+ } else {
+ /* Since we have no dlopen(), but definition we have no
+ * loadable modules on disk, so we can resaonably
+ * return '1' instead of an error.
+ */
+ return 1;
+ }
+}
+#endif /* ! HAVE_DLFCN_H */
--- /dev/null
+/*
+ * virmodule.h: APIs for dlopen'ing extension modules
+ *
+ * Copyright (C) 2012-2018 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/>.
+ *
+ */
+
+#ifndef __VIR_MODULE_H__
+# define __VIR_MODULE_H__
+
+int virModuleLoad(const char *path,
+ const char *regfunc,
+ bool required);
+
+#endif /* __VIR_MODULE_H__ */