155 lines
3.5 KiB
C
155 lines
3.5 KiB
C
|
|
#include <lighttpd/module.h>
|
|
|
|
liModules *li_modules_new(gpointer main, const gchar *module_dir, gboolean module_resident) {
|
|
liModules *m = g_slice_new(liModules);
|
|
|
|
m->version = MODULE_VERSION;
|
|
m->main = main;
|
|
m->mods = g_array_new(FALSE, TRUE, sizeof(liModule*));
|
|
m->module_dir = g_strdup(module_dir);
|
|
m->module_resident = module_resident;
|
|
m->sizeof_off_t = sizeof(off_t);
|
|
|
|
return m;
|
|
}
|
|
|
|
liModule *li_module_lookup(liModules *mods, const gchar *name) {
|
|
liModule *mod;
|
|
GArray *a = mods->mods;
|
|
|
|
for (guint i = 0; i < a->len; i++) {
|
|
mod = g_array_index(a, liModule*, i);
|
|
if (mod != NULL && g_str_equal(mod->name->str, name))
|
|
return mod;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void li_modules_free(liModules* mods) {
|
|
/* unload all modules */
|
|
GArray *a = mods->mods;
|
|
liModule *mod;
|
|
|
|
for (guint i = 0; i < a->len; i++) {
|
|
mod = g_array_index(a, liModule*, i);
|
|
if (!mod)
|
|
continue;
|
|
li_module_release(mods, mod);
|
|
}
|
|
|
|
g_array_free(mods->mods, TRUE);
|
|
g_free(mods->module_dir);
|
|
g_slice_free(liModules, mods);
|
|
}
|
|
|
|
|
|
liModule* li_module_load(liModules *mods, const gchar* name) {
|
|
liModule *mod;
|
|
liModuleInitCB m_init;
|
|
GString *m_init_str, *m_free_str;
|
|
guint i;
|
|
|
|
mod = li_module_lookup(mods, name);
|
|
|
|
if (mod) {
|
|
/* module already loaded, increment refcount and return */
|
|
mod->refcount++;
|
|
return mod;
|
|
}
|
|
|
|
mod = g_slice_new0(liModule);
|
|
mod->name = g_string_new(name);
|
|
mod->refcount = 1;
|
|
mod->path = g_module_build_path(mods->module_dir, name);
|
|
|
|
mod->module = g_module_open(mod->path, G_MODULE_BIND_LAZY);
|
|
|
|
if (!mod->module) {
|
|
g_string_free(mod->name, TRUE);
|
|
g_free(mod->path);
|
|
g_slice_free(liModule, mod);
|
|
return NULL;
|
|
}
|
|
|
|
/* temporary strings for mod_xyz_init and mod_xyz_free */
|
|
m_init_str = g_string_new(name);
|
|
g_string_append_len(m_init_str, CONST_STR_LEN("_init"));
|
|
m_free_str = g_string_new(name);
|
|
g_string_append_len(m_free_str, CONST_STR_LEN("_free"));
|
|
|
|
if (!g_module_symbol(mod->module, m_init_str->str, (gpointer *)&m_init)
|
|
|| !g_module_symbol(mod->module, m_free_str->str, (gpointer *)&mod->free)
|
|
|| m_init == NULL || mod->free == NULL) {
|
|
|
|
/* mod_init or mod_free couldn't be located, something went wrong */
|
|
g_string_free(m_init_str, TRUE);
|
|
g_string_free(m_free_str, TRUE);
|
|
g_free(mod->path);
|
|
g_string_free(mod->name, TRUE);
|
|
g_slice_free(liModule, mod);
|
|
return NULL;
|
|
}
|
|
|
|
/* call mod_xyz_init */
|
|
if (!m_init(mods, mod)) {
|
|
g_string_free(m_init_str, TRUE);
|
|
g_string_free(m_free_str, TRUE);
|
|
g_free(mod->path);
|
|
g_string_free(mod->name, TRUE);
|
|
g_slice_free(liModule, mod);
|
|
return NULL;
|
|
}
|
|
|
|
if (mods->module_resident)
|
|
g_module_make_resident(mod->module);
|
|
|
|
/* insert into free slot */
|
|
for (i = 0; i < mods->mods->len; i++) {
|
|
if (!g_array_index(mods->mods, liModule*, i))
|
|
{
|
|
g_array_index(mods->mods, liModule*, i) = mod;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* if no free slot was found, append */
|
|
if (i == mods->mods->len)
|
|
g_array_append_val(mods->mods, mod);
|
|
|
|
/* free temp strings */
|
|
g_string_free(m_free_str, TRUE);
|
|
g_string_free(m_init_str, TRUE);
|
|
|
|
return mod;
|
|
}
|
|
|
|
void li_module_release(liModules *mods, liModule *mod) {
|
|
guint i;
|
|
|
|
if (--mod->refcount > 0)
|
|
return;
|
|
|
|
for (i = 0; i < mods->mods->len; i++) {
|
|
if (g_array_index(mods->mods, liModule*, i) == mod)
|
|
{
|
|
g_array_index(mods->mods, liModule*, i) = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
mod->free(mods, mod);
|
|
g_module_close(mod->module);
|
|
g_free(mod->path);
|
|
g_string_free(mod->name, TRUE);
|
|
g_slice_free(liModule, mod);
|
|
}
|
|
|
|
void li_module_release_name(liModules *mods, const gchar* name) {
|
|
liModule *mod = li_module_lookup(mods, name);
|
|
|
|
if (mod)
|
|
li_module_release(mods, mod);
|
|
}
|