summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2020-06-04 19:06:08 +0200
committerJaroslav Kysela <perex@perex.cz>2020-06-04 19:09:58 +0200
commit33089f30a316060094dfa95a2949fd479299c7bc (patch)
tree71489f8d69bcdc8e0e84b8508ce5dbbbb9149345
parentb2a4272ecb40d84556d8e043d0b6e89439acbc33 (diff)
downloadalsa-lib-33089f30a316060094dfa95a2949fd479299c7bc.tar.gz
snd_dlopen: implement the relocatable version for glibc
BugLink: https://github.com/alsa-project/alsa-lib/issues/34 Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r--include/global.h1
-rw-r--r--modules/mixer/simple/python.c10
-rw-r--r--src/dlmisc.c48
3 files changed, 50 insertions, 9 deletions
diff --git a/include/global.h b/include/global.h
index d73d333a..71a1b12f 100644
--- a/include/global.h
+++ b/include/global.h
@@ -97,6 +97,7 @@ extern struct snd_dlsym_link *snd_dlsym_start;
/** \brief Returns the version of a dynamic symbol as a string. */
#define SND_DLSYM_VERSION(version) __STRING(version)
+int snd_dlpath(char *path, size_t path_len, const char *name);
void *snd_dlopen(const char *file, int mode, char *errbuf, size_t errbuflen);
void *snd_dlsym(void *handle, const char *name, const char *version);
int snd_dlclose(void *handle);
diff --git a/modules/mixer/simple/python.c b/modules/mixer/simple/python.c
index 3a627ab6..8a7264d4 100644
--- a/modules/mixer/simple/python.c
+++ b/modules/mixer/simple/python.c
@@ -21,6 +21,7 @@
#include "Python.h"
#include <stddef.h>
+#include <limits.h>
#include "config.h"
#include "asoundlib.h"
#include "mixer_abst.h"
@@ -36,7 +37,7 @@ struct python_priv {
PyObject *py_mixer;
};
-#define SCRIPT ALSA_PLUGIN_DIR "/smixer/python/main.py"
+#define SCRIPT "smixer/python/main.py"
struct pymelem {
PyObject_HEAD
@@ -1110,6 +1111,7 @@ int alsa_mixer_simple_finit(snd_mixer_class_t *class,
FILE *fp;
const char *file;
PyObject *obj, *py_mod;
+ char path[PATH_MAX];
priv = calloc(1, sizeof(*priv));
if (priv == NULL)
@@ -1119,8 +1121,10 @@ int alsa_mixer_simple_finit(snd_mixer_class_t *class,
snd_mixer_sbasic_set_private_free(class, alsa_mixer_simple_free);
file = getenv("ALSA_MIXER_SIMPLE_MPYTHON");
- if (file == NULL)
- file = SCRIPT;
+ if (file == NULL) {
+ snd_dlpath(path, sizeof(path), SCRIPT);
+ file = path;
+ }
fp = fopen(file, "r");
if (fp == NULL) {
diff --git a/src/dlmisc.c b/src/dlmisc.c
index 8c8f3ff7..87a8fa00 100644
--- a/src/dlmisc.c
+++ b/src/dlmisc.c
@@ -32,6 +32,7 @@
#ifdef HAVE_LIBPTHREAD
#include <pthread.h>
#endif
+#include <limits.h>
#ifndef DOC_HIDDEN
#ifndef PIC
@@ -40,6 +41,42 @@ struct snd_dlsym_link *snd_dlsym_start = NULL;
#endif
/**
+ *
+ * \brief Compose the dynamic path
+ * \param path Returned path (string)
+ * \param path_len Returned path max size (with trailing zero)
+ * \param name Plugin name (relative)
+ * \return Zero on success, otherwise a negative error code
+ */
+int snd_dlpath(char *path, size_t path_len, const char *name)
+{
+ static const char *origin_dir = NULL;
+#ifdef HAVE_LIBDL
+#ifdef __GLIBC__
+ static int plugin_dir_set = 0;
+ if (!plugin_dir_set) {
+ struct link_map *links;
+ Dl_info info;
+ char origin[PATH_MAX];
+ if (dladdr1(&snd_dlpath, &info, (void**)&links, RTLD_DL_LINKMAP) == 0)
+ links = NULL;
+ if (links != NULL && dlinfo(links, RTLD_DI_ORIGIN, origin) == 0) {
+ snprintf(path, path_len, "%s/alsa-lib", origin);
+ if (access(path, X_OK) == 0)
+ origin_dir = origin;
+ }
+ plugin_dir_set = 1;
+ }
+#endif
+#endif
+ if (origin_dir)
+ snprintf(path, path_len, "%s/alsa-lib/%s", origin_dir, name);
+ else
+ snprintf(path, path_len, "%s/%s", ALSA_PLUGIN_DIR, name);
+ return 0;
+}
+
+/**
* \brief Opens a dynamic library - ALSA wrapper for \c dlopen.
* \param name name of the library, similar to \c dlopen.
* \param mode mode flags, similar to \c dlopen.
@@ -79,14 +116,12 @@ void *snd_dlopen(const char *name, int mode, char *errbuf, size_t errbuflen)
* via ld.so.conf.
*/
void *handle = NULL;
- char *filename = NULL;
+ const char *filename = NULL;
+ char path[PATH_MAX];
if (name && name[0] != '/') {
- filename = alloca(sizeof(ALSA_PLUGIN_DIR) + 1 + strlen(name) + 1);
- if (filename) {
- strcpy(filename, ALSA_PLUGIN_DIR);
- strcat(filename, "/");
- strcat(filename, name);
+ if (snd_dlpath(path, sizeof(path), name) == 0) {
+ filename = name;
handle = dlopen(filename, mode);
if (!handle) {
/* if the filename exists and cannot be opened */
@@ -97,6 +132,7 @@ void *snd_dlopen(const char *name, int mode, char *errbuf, size_t errbuflen)
}
}
if (!handle) {
+ filename = name;
handle = dlopen(name, mode);
if (!handle)
goto errpath;