From 848f1dfb2d2f404efa5371817285236d33b32a5c Mon Sep 17 00:00:00 2001 From: tumashu Date: Tue, 22 Mar 2022 20:16:19 +0000 Subject: [PATCH] Look for thunar plugins at $THUNARX_DIRS (Issue #748) THUNARX_DIRS is a list of directories where thunar plugins are looked for. It is needed for distributions like NixOS/GuixOS that do not install all plugins in the same directory. In NixOS/GuixOS each package is installed in a self contained directory. MR !197 --- thunarx/thunarx-provider-factory.c | 86 +++++++++++++++++------------- thunarx/thunarx-provider-module.c | 68 ++++++++++++++--------- 2 files changed, 91 insertions(+), 63 deletions(-) diff --git a/thunarx/thunarx-provider-factory.c b/thunarx/thunarx-provider-factory.c index 94b11545..386c3417 100644 --- a/thunarx/thunarx-provider-factory.c +++ b/thunarx/thunarx-provider-factory.c @@ -154,54 +154,66 @@ thunarx_provider_factory_load_modules (ThunarxProviderFactory *factory) GList *modules = NULL; GList *lp; GDir *dp; + gchar *dirs_string; + gchar **dirs; - dp = g_dir_open (THUNARX_DIRECTORY, 0, NULL); - if (G_LIKELY (dp != NULL)) + dirs_string = (gchar *) g_getenv ("THUNARX_DIRS"); + if (!dirs_string) + dirs_string = THUNARX_DIRECTORY; + dirs = g_strsplit (dirs_string, G_SEARCHPATH_SEPARATOR_S, 0); + + for (int i = 0; dirs[i] != NULL; i++) { - /* determine the types for all existing plugins */ - for (;;) - { - /* read the next entry from the directory */ - name = g_dir_read_name (dp); - if (G_UNLIKELY (name == NULL)) - break; - /* check if this is a valid plugin file */ - if (g_str_has_suffix (name, "." G_MODULE_SUFFIX)) - { - /* check if we already have that module */ - for (lp = thunarx_provider_modules; lp != NULL; lp = lp->next) - if (g_str_equal (G_TYPE_MODULE (lp->data)->name, name)) - break; + dp = g_dir_open (dirs[i], 0, NULL); - /* use or allocate a new module for the file */ - if (G_UNLIKELY (lp != NULL)) - { - /* just use the existing module */ - module = THUNARX_PROVIDER_MODULE (lp->data); - } - else - { - /* allocate the new module and add it to our list */ - module = thunarx_provider_module_new (name); - thunarx_provider_modules = g_list_prepend (thunarx_provider_modules, module); - } + if (G_LIKELY (dp != NULL)) + { + /* determine the types for all existing plugins */ + for (;;) + { + /* read the next entry from the directory */ + name = g_dir_read_name (dp); + if (G_UNLIKELY (name == NULL)) + break; - /* try to load the module */ - if (g_type_module_use (G_TYPE_MODULE (module))) + /* check if this is a valid plugin file */ + if (g_str_has_suffix (name, "." G_MODULE_SUFFIX)) { - /* add the types provided by the module */ - thunarx_provider_factory_add (factory, module); - - /* add the module to our list */ - modules = g_list_prepend (modules, module); + /* check if we already have that module */ + for (lp = thunarx_provider_modules; lp != NULL; lp = lp->next) + if (g_str_equal (G_TYPE_MODULE (lp->data)->name, name)) + break; + + /* use or allocate a new module for the file */ + if (G_UNLIKELY (lp != NULL)) + { + continue; + } + else + { + /* allocate the new module and add it to our list */ + module = thunarx_provider_module_new (name); + thunarx_provider_modules = g_list_prepend (thunarx_provider_modules, module); + } + + /* try to load the module */ + if (g_type_module_use (G_TYPE_MODULE (module))) + { + /* add the types provided by the module */ + thunarx_provider_factory_add (factory, module); + + /* add the module to our list */ + modules = g_list_prepend (modules, module); + } } } - } - g_dir_close (dp); + g_dir_close (dp); + } } + g_strfreev (dirs); return modules; } diff --git a/thunarx/thunarx-provider-module.c b/thunarx/thunarx-provider-module.c index 023ad2ae..5ddf38b2 100644 --- a/thunarx/thunarx-provider-module.c +++ b/thunarx/thunarx-provider-module.c @@ -175,37 +175,53 @@ thunarx_provider_module_load (GTypeModule *type_module) { ThunarxProviderModule *module = THUNARX_PROVIDER_MODULE (type_module); gchar *path; + gchar *dirs_string; + gchar **dirs; + gboolean found; - /* load the module using the runtime link editor */ - path = g_build_filename (THUNARX_DIRECTORY, type_module->name, NULL); - module->library = g_module_open (path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); - g_free (path); + dirs_string = (gchar *) g_getenv ("THUNARX_DIRS"); + if (!dirs_string) + dirs_string = THUNARX_DIRECTORY; + dirs = g_strsplit (dirs_string, G_SEARCHPATH_SEPARATOR_S, 0); - /* check if the load operation was successfull */ - if (G_UNLIKELY (module->library == NULL)) - { - g_printerr ("Thunar :Failed to load plugin `%s': %s\n", type_module->name, g_module_error ()); - return FALSE; - } + found = FALSE; - /* verify that all required public symbols are present in the plugin's symbol table */ - if (!g_module_symbol (module->library, "thunar_extension_shutdown", (gpointer) &module->shutdown) - || !g_module_symbol (module->library, "thunar_extension_initialize", (gpointer) &module->initialize) - || !g_module_symbol (module->library, "thunar_extension_list_types", (gpointer) &module->list_types)) + for (int i = 0; !found && dirs[i] != NULL; i++) { - g_printerr ("Thunar :Plugin `%s' lacks required symbols.\n", type_module->name); - g_module_close (module->library); - return FALSE; + /* load the module using the runtime link editor */ + path = g_build_filename (dirs[i], type_module->name, NULL); + + module->library = g_module_open (path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + g_free (path); + + /* check if the load operation was successfull */ + if (G_UNLIKELY (module->library == NULL)) + { + g_printerr ("Thunar :Failed to load plugin `%s' from `%s': %s\n", type_module->name, path, g_module_error ()); + continue; + } + + /* verify that all required public symbols are present in the plugin's symbol table */ + if (!g_module_symbol (module->library, "thunar_extension_shutdown", (gpointer) &module->shutdown) + || !g_module_symbol (module->library, "thunar_extension_initialize", (gpointer) &module->initialize) + || !g_module_symbol (module->library, "thunar_extension_list_types", (gpointer) &module->list_types)) + { + g_printerr ("Thunar :Plugin `%s' in `%s' lacks required symbols.\n", type_module->name, path); + g_module_close (module->library); + continue; + } + + /* initialize the plugin */ + (*module->initialize) (module); + + /* ensure that the module will never be unloaded if it requests to be kept in memory */ + if (G_UNLIKELY (module->resident)) + g_module_make_resident (module->library); + + found = TRUE; } - - /* initialize the plugin */ - (*module->initialize) (module); - - /* ensure that the module will never be unloaded if it requests to be kept in memory */ - if (G_UNLIKELY (module->resident)) - g_module_make_resident (module->library); - - return TRUE; + g_strfreev (dirs); + return found; } -- 2.34.0