From ff91d3eb3e61f892ae277a85fd497a70f2d98f01 Mon Sep 17 00:00:00 2001 From: Frank Benkstein Date: Thu, 15 Jan 2009 23:58:07 +0100 Subject: [PATCH] src/module.{c,h}: convert module plugins to GObject --- src/module.c | 145 +++++++++++++++++++++++++++++++++-------------------------- src/module.h | 33 ++++++++++++++ 2 files changed, 115 insertions(+), 63 deletions(-) create mode 100644 src/module.h diff --git a/src/module.c b/src/module.c index 2b91ee0..8d305db 100644 --- a/src/module.c +++ b/src/module.c @@ -29,124 +29,143 @@ #include #include +#include #include "util.h" #include "plugin.h" +#include "module.h" -static bool init_module(struct plugin *p); -static void destroy_module(struct plugin *p); -static bool call_module_hook(struct plugin *p, const char *hook_name); +G_DEFINE_TYPE(VlockModule, vlock_module, TYPE_VLOCK_PLUGIN) -struct plugin_type *module = &(struct plugin_type){ - .init = init_module, - .destroy = destroy_module, - .call_hook = call_module_hook, -}; +#define VLOCK_MODULE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), TYPE_VLOCK_MODULE, VlockModulePrivate)) /* A hook function as defined by a module. */ typedef bool (*module_hook_function)(void **); -struct module_context +struct _VlockModulePrivate { /* Handle returned by dlopen(). */ void *dl_handle; - /* Pointer to be used by the modules. */ - void *module_data; + + /* Pointer to be used by the module's hooks. */ + void *hook_context; + /* Array of hook functions befined by a single module. Stored in the same * order as the global hooks. */ module_hook_function hooks[nr_hooks]; }; - -/* Initialize a new plugin as a module. */ -bool init_module(struct plugin *p) +static bool vlock_module_open(VlockPlugin *object, GError **error) { - char *path; - struct module_context *context; + VlockModule *self = VLOCK_MODULE(object); - if (asprintf(&path, "%s/%s.so", VLOCK_MODULE_DIR, p->name) < 0) { - errno = ENOMEM; - return false; - } + g_assert(self->priv->dl_handle == NULL); + + char *path = g_strdup_printf("%s/%s.so", VLOCK_MODULE_DIR, object->name); /* Test for access. This must be done manually because vlock most likely - * runs as a setuid executable and would otherwise override restrictions. - * Also dlopen doesn't set errno on error. */ + * runs as a setuid executable and would otherwise override restrictions. */ if (access(path, R_OK) < 0) { - int errsv = errno; - free(path); - errno = errsv; - return false; - } - - context = malloc(sizeof *context); - - if (context == NULL) { - int errsv = errno; - free(path); - errno = errsv; + gint error_code = (errno == ENOENT) ? + VLOCK_PLUGIN_ERROR_NOT_FOUND : + VLOCK_PLUGIN_ERROR_FAILED; + + g_set_error( + error, + VLOCK_PLUGIN_ERROR, + error_code, + "could not open module '%s': %s", + object->name, + g_strerror(errno)); + + g_free(path); return false; } /* Open the module as a shared library. */ - context->dl_handle = dlopen(path, RTLD_NOW | RTLD_LOCAL); + void *dl_handle = self->priv->dl_handle = dlopen(path, RTLD_NOW | RTLD_LOCAL); - free(path); + g_free(path); + + if (dl_handle == NULL) { + g_set_error( + error, + VLOCK_PLUGIN_ERROR, + VLOCK_PLUGIN_ERROR_FAILED, + "could not open module '%s': %s", + object->name, + dlerror()); - if (context->dl_handle == NULL) { - errno = 0; - free(context); return false; } - /* Initialisation complete. From now on cleanup is handled by destroy_module(). */ - p->context = context; - /* Load all the hooks. Unimplemented hooks are NULL and will not be called later. */ for (size_t i = 0; i < nr_hooks; i++) - *(void **) (&context->hooks[i]) = dlsym(context->dl_handle, hooks[i].name); + *(void **) (&self->priv->hooks[i]) = dlsym(dl_handle, hooks[i].name); /* Load all dependencies. Unspecified dependencies are NULL. */ for (size_t i = 0; i < nr_dependencies; i++) { - const char *(*dependency)[] = dlsym(context->dl_handle, dependency_names[i]); + const char *(*dependency)[] = dlsym(dl_handle, dependency_names[i]); /* Append array elements to list. */ for (size_t j = 0; dependency != NULL && (*dependency)[j] != NULL; j++) { - char *s = strdup((*dependency)[j]); + char *s = g_strdup((*dependency)[j]); - if (s == NULL) - return false; - - p->dependencies[i] = g_list_append(p->dependencies[i], s); + object->dependencies[i] = g_list_append(object->dependencies[i], s); } } return true; } -static void destroy_module(struct plugin *p) -{ - struct module_context *context = p->context; - - if (context != NULL) { - dlclose(context->dl_handle); - free(context); - } -} - -static bool call_module_hook(struct plugin *p, const char *hook_name) +static bool vlock_module_call_hook(VlockPlugin *object, const gchar *hook_name) { - struct module_context *context = p->context; + VlockModule *self = VLOCK_MODULE(object); /* Find the right hook index. */ for (size_t i = 0; i < nr_hooks; i++) if (strcmp(hooks[i].name, hook_name) == 0) { - module_hook_function hook = context->hooks[i]; + module_hook_function hook = self->priv->hooks[i]; if (hook != NULL) - return hook(&context->module_data); + return hook(&self->priv->hook_context); } return true; } + +/* Initialize plugin to default values. */ +static void vlock_module_init(VlockModule *self) +{ + self->priv = VLOCK_MODULE_GET_PRIVATE(self); + self->priv->dl_handle = NULL; +} + +/* Destroy module object. */ +static void vlock_module_finalize(GObject *object) +{ + VlockModule *self = VLOCK_MODULE(object); + + if (self->priv->dl_handle != NULL) { + dlclose(self->priv->dl_handle); + self->priv->dl_handle = NULL; + } + + G_OBJECT_CLASS(vlock_module_parent_class)->finalize(object); +} + +/* Initialize module class. */ +static void vlock_module_class_init(VlockModuleClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + VlockPluginClass *plugin_class = VLOCK_PLUGIN_CLASS(klass); + + g_type_class_add_private(klass, sizeof(VlockModulePrivate)); + + /* Virtual methods. */ + gobject_class->finalize = vlock_module_finalize; + + plugin_class->open = vlock_module_open; + plugin_class->call_hook = vlock_module_call_hook; +} diff --git a/src/module.h b/src/module.h new file mode 100644 index 0000000..23831ad --- /dev/null +++ b/src/module.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include "plugin.h" + +/* + * Module type macros. + */ +#define TYPE_VLOCK_MODULE (vlock_module_get_type()) +#define VLOCK_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_VLOCK_MODULE, VlockModule)) +#define VLOCK_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_VLOCK_MODULE, VlockModuleClass)) +#define IS_VLOCK_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_VLOCK_MODULE)) +#define IS_VLOCK_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_VLOCK_MODULE)) +#define VLOCK_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_VLOCK_MODULE, VlockModuleClass)) + +typedef struct _VlockModule VlockModule; +typedef struct _VlockModuleClass VlockModuleClass; + +typedef struct _VlockModulePrivate VlockModulePrivate; + +struct _VlockModule +{ + VlockPlugin parent_instance; + + VlockModulePrivate *priv; +}; + +struct _VlockModuleClass +{ + VlockPluginClass parent_class; +}; + +GType vlock_module_get_type(void); -- 2.11.4.GIT