From f76f45124e6548e82c8db52e02602a51c19a9d60 Mon Sep 17 00:00:00 2001 From: George Kiagiadakis Date: Tue, 27 Feb 2024 11:59:33 +0200 Subject: [PATCH] base-dirs: add support for finding modules and remove wp_get_module_dir() This makes things more consistent and allows us also to add more search paths in the future if necessary. Also, stop using g_module_build_path() because it's deprecated and build the path manually. This obviously is not portable to Windows/Mac or other exotic platforms, but portability is not important at this point. PipeWire is also not portable beyond Linux & BSD. --- lib/wp/base-dirs.c | 77 ++++++++++++++++++++------- lib/wp/base-dirs.h | 9 ++++ lib/wp/private/internal-comp-loader.c | 10 ++-- lib/wp/wp.c | 16 ------ lib/wp/wp.h | 3 -- 5 files changed, 73 insertions(+), 42 deletions(-) diff --git a/lib/wp/base-dirs.c b/lib/wp/base-dirs.c index 0a41ff55..70a0bef9 100644 --- a/lib/wp/base-dirs.c +++ b/lib/wp/base-dirs.c @@ -15,18 +15,39 @@ WP_DEFINE_LOCAL_LOG_TOPIC ("wp-base-dirs") * \defgroup wpbasedirs Base Directories File Lookup */ +/* Returns /basedir/subdir/filename, with filename treated as a module + * if WP_BASE_DIRS_FLAG_MODULE is set. + * The basedir is assumed to be either an absolute path or NULL. + * The subdir is assumed to be a path relative to basedir or NULL. + */ static gchar * -check_path (const gchar *basedir, const gchar *subdir, const gchar *filename) +make_path (guint flags, const gchar *basedir, const gchar *subdir, + const gchar *filename) { - g_autofree gchar *path = g_build_filename (basedir, - subdir ? subdir : filename, - subdir ? filename : NULL, - NULL); - g_autofree gchar *abspath = g_canonicalize_filename (path, NULL); - wp_trace ("checking %s", abspath); - if (g_file_test (abspath, G_FILE_TEST_IS_REGULAR)) - return g_steal_pointer (&abspath); - return NULL; + g_autofree gchar *full_basedir = NULL; + g_autofree gchar *full_filename = NULL; + + /* merge subdir into basedir, if necessary */ + if (subdir) { + full_basedir = g_canonicalize_filename (subdir, basedir); + basedir = full_basedir; + } + + if (flags & WP_BASE_DIRS_FLAG_MODULE) { + g_autofree gchar *basename = g_path_get_basename (filename); + g_autofree gchar *dirname = g_path_get_dirname (filename); + const gchar *prefix = ""; + const gchar *suffix = ""; + if (!g_str_has_prefix (basename, "lib")) + prefix = "lib"; + if (!g_str_has_suffix (basename, ".so")) + suffix = ".so"; + full_filename = g_strconcat (dirname, G_DIR_SEPARATOR_S, + prefix, basename, suffix, NULL); + filename = full_filename; + } + + return g_canonicalize_filename (filename, basedir); } static GPtrArray * @@ -57,6 +78,13 @@ lookup_dirs (guint flags) g_ptr_array_add (dirs, g_canonicalize_filename (env_dirs[i], NULL)); } } + else if ((flags & WP_BASE_DIRS_ENV_MODULE) && + (dir = g_getenv ("WIREPLUMBER_MODULE_DIR"))) { + g_auto (GStrv) env_dirs = g_strsplit (dir, G_SEARCHPATH_SEPARATOR_S, 0); + for (guint i = 0; env_dirs[i]; i++) { + g_ptr_array_add (dirs, g_canonicalize_filename (env_dirs[i], NULL)); + } + } else { if (flags & WP_BASE_DIRS_XDG_CONFIG_HOME) { dir = g_get_user_config_dir (); @@ -88,6 +116,10 @@ lookup_dirs (guint flags) g_ptr_array_add (dirs, g_canonicalize_filename(WIREPLUMBER_DEFAULT_DATA_DIR, NULL)); } + if (flags & WP_BASE_DIRS_PREFIX_LIB) { + g_ptr_array_add (dirs, + g_canonicalize_filename (WIREPLUMBER_DEFAULT_MODULE_DIR, NULL)); + } } return g_steal_pointer (&dirs); @@ -124,16 +156,23 @@ gchar * wp_base_dirs_find_file (WpBaseDirsFlags flags, const gchar * subdir, const gchar * filename) { - g_autoptr(GPtrArray) dir_paths = lookup_dirs (flags); + g_autoptr (GPtrArray) dir_paths = NULL; - if (g_path_is_absolute (filename)) - return g_strdup (filename); + if (g_path_is_absolute (filename)) { + g_autofree gchar *path = make_path (flags, NULL, NULL, filename); + wp_trace ("test file: %s", path); + if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) + return g_steal_pointer (&path); + } + + dir_paths = lookup_dirs (flags); for (guint i = 0; i < dir_paths->len; i++) { - gchar *path = check_path (g_ptr_array_index (dir_paths, i), - subdir, filename); - if (path) - return path; + g_autofree gchar *path = make_path (flags, g_ptr_array_index (dir_paths, i), + subdir, filename); + wp_trace ("test file: %s", path); + if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) + return g_steal_pointer (&path); } return NULL; @@ -288,8 +327,8 @@ wp_base_dirs_new_files_iterator (WpBaseDirsFlags flags, continue; /* verify the file is regular and canonicalize the path */ - g_autofree gchar *path = check_path (dirpath, NULL, filename); - if (!path) + g_autofree gchar *path = make_path (flags, dirpath, NULL, filename); + if (!g_file_test (path, G_FILE_TEST_IS_REGULAR)) continue; /* remove item with the same filename from the global items array, diff --git a/lib/wp/base-dirs.h b/lib/wp/base-dirs.h index 122bce9b..f3b52b40 100644 --- a/lib/wp/base-dirs.h +++ b/lib/wp/base-dirs.h @@ -21,6 +21,7 @@ G_BEGIN_DECLS typedef enum { /*< flags >*/ WP_BASE_DIRS_ENV_CONFIG = (1 << 0), /*!< $WIREPLUMBER_CONFIG_DIR */ WP_BASE_DIRS_ENV_DATA = (1 << 1), /*!< $WIREPLUMBER_DATA_DIR */ + WP_BASE_DIRS_ENV_MODULE = (1 << 2), /*!< $WIREPLUMBER_MODULE_DIR */ WP_BASE_DIRS_XDG_CONFIG_HOME = (1 << 8), /*!< XDG_CONFIG_HOME/wireplumber */ WP_BASE_DIRS_XDG_DATA_HOME = (1 << 9), /*!< XDG_DATA_HOME/wireplumber */ @@ -30,6 +31,9 @@ typedef enum { /*< flags >*/ WP_BASE_DIRS_ETC = (1 << 16), /*!< ($prefix)/etc/wireplumber */ WP_BASE_DIRS_PREFIX_SHARE = (1 << 17), /*!< $prefix/share/wireplumber */ + WP_BASE_DIRS_PREFIX_LIB = (1 << 18), /*!< $prefix/$libdir/wireplumber-$ABI_version */ + + WP_BASE_DIRS_FLAG_MODULE = (1 << 24), /*!< the file is a loadable module */ WP_BASE_DIRS_CONFIGURATION = WP_BASE_DIRS_ENV_CONFIG | @@ -44,6 +48,11 @@ typedef enum { /*< flags >*/ WP_BASE_DIRS_XDG_DATA_HOME | WP_BASE_DIRS_XDG_DATA_DIRS | WP_BASE_DIRS_PREFIX_SHARE, + + WP_BASE_DIRS_MODULE = + WP_BASE_DIRS_ENV_MODULE | + WP_BASE_DIRS_PREFIX_LIB | + WP_BASE_DIRS_FLAG_MODULE, } WpBaseDirsFlags; WP_API diff --git a/lib/wp/private/internal-comp-loader.c b/lib/wp/private/internal-comp-loader.c index 097265ad..17ff327e 100644 --- a/lib/wp/private/internal-comp-loader.c +++ b/lib/wp/private/internal-comp-loader.c @@ -698,10 +698,12 @@ load_module (WpCore * core, const gchar * module_name, WpSpaJson * args, GModule *gmodule; gpointer module_init; - if (!g_file_test (module_name, G_FILE_TEST_EXISTS)) - module_path = g_module_build_path (wp_get_module_dir (), module_name); - else - module_path = g_strdup (module_name); + module_path = wp_base_dirs_find_file (WP_BASE_DIRS_MODULE, NULL, module_name); + if (!module_path) { + g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED, + "Failed to locate module %s", module_name); + return NULL; + } wp_trace_object (core, "loading %s from %s", module_name, module_path); diff --git a/lib/wp/wp.c b/lib/wp/wp.c index b97208dd..6d3e9a72 100644 --- a/lib/wp/wp.c +++ b/lib/wp/wp.c @@ -77,20 +77,4 @@ wp_get_library_api_version (void) return WIREPLUMBER_API_VERSION; } -/*! - * \brief Gets the WirePlumber module directory - * \returns WirePlumber's module directory - */ -const gchar * -wp_get_module_dir (void) -{ - static const gchar *module_dir = NULL; - if (!module_dir) { - module_dir = g_getenv ("WIREPLUMBER_MODULE_DIR"); - if (!module_dir) - module_dir = WIREPLUMBER_DEFAULT_MODULE_DIR; - } - return module_dir; -} - /*! \} */ diff --git a/lib/wp/wp.h b/lib/wp/wp.h index 944857d5..cd13993d 100644 --- a/lib/wp/wp.h +++ b/lib/wp/wp.h @@ -76,9 +76,6 @@ const char * wp_get_library_version (void); WP_API const char * wp_get_library_api_version (void); -WP_API -const gchar * wp_get_module_dir (void); - G_END_DECLS #endif