The dlopen() function might fail also for another reason than a missing file, thus return the error string from dlerror(). Signed-off-by: Jaroslav Kysela <perex@xxxxxxxx> --- include/global.h | 2 +- src/Versions.in | 5 +++++ src/conf.c | 13 ++++++----- src/dlmisc.c | 60 +++++++++++++++++++++++++++++++++++++++---------- src/hwdep/hwdep.c | 6 ++--- src/mixer/simple_abst.c | 10 ++++----- src/pcm/pcm_hooks.c | 8 +++---- src/pcm/pcm_meter.c | 6 ++--- src/rawmidi/rawmidi.c | 6 ++--- src/seq/seq.c | 6 ++--- src/timer/timer.c | 6 ++--- src/timer/timer_query.c | 6 ++--- 12 files changed, 88 insertions(+), 46 deletions(-) diff --git a/include/global.h b/include/global.h index 41680829..d73d333a 100644 --- a/include/global.h +++ b/include/global.h @@ -97,7 +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) -void *snd_dlopen(const char *file, int mode); +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/src/Versions.in b/src/Versions.in index 8d2dd116..2f9e1697 100644 --- a/src/Versions.in +++ b/src/Versions.in @@ -129,3 +129,8 @@ ALSA_0.9.7 { @SYMBOL_PREFIX@alsa_lisp_*; } ALSA_0.9.5; +ALSA_1.1.6 { + global: + + @SYMBOL_PREFIX@snd_dlopen; +} ALSA_1.1.6; diff --git a/src/conf.c b/src/conf.c index c410bfb8..e71bb972 100644 --- a/src/conf.c +++ b/src/conf.c @@ -982,6 +982,7 @@ static int get_freestring(char **string, int id, input_t *input) case '.': if (!id) break; + /* fall through */ case ' ': case '\f': case '\t': @@ -3477,7 +3478,7 @@ static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_c { void *h = NULL; snd_config_t *c, *func_conf = NULL; - char *buf = NULL; + char *buf = NULL, errbuf[256]; const char *lib = NULL, *func_name = NULL; const char *str; int (*func)(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data) = NULL; @@ -3537,11 +3538,11 @@ static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_c buf[len-1] = '\0'; func_name = buf; } - h = snd_dlopen(lib, RTLD_NOW); + h = snd_dlopen(lib, RTLD_NOW, errbuf, sizeof(errbuf)); func = h ? snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_HOOK)) : NULL; err = 0; if (!h) { - SNDERR("Cannot open shared library %s", lib); + SNDERR("Cannot open shared library %s (%s)", lib, errbuf); err = -ENOENT; } else if (!func) { SNDERR("symbol %s is not defined inside %s", func_name, lib); @@ -4471,7 +4472,7 @@ static int _snd_config_evaluate(snd_config_t *src, { int err; if (pass == SND_CONFIG_WALK_PASS_PRE) { - char *buf = NULL; + char *buf = NULL, errbuf[256]; const char *lib = NULL, *func_name = NULL; const char *str; int (*func)(snd_config_t **dst, snd_config_t *root, @@ -4530,12 +4531,12 @@ static int _snd_config_evaluate(snd_config_t *src, buf[len-1] = '\0'; func_name = buf; } - h = snd_dlopen(lib, RTLD_NOW); + h = snd_dlopen(lib, RTLD_NOW, errbuf, sizeof(errbuf)); if (h) func = snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_EVALUATE)); err = 0; if (!h) { - SNDERR("Cannot open shared library %s", lib); + SNDERR("Cannot open shared library %s (%s)", lib, errbuf); err = -ENOENT; goto _errbuf; } else if (!func) { diff --git a/src/dlmisc.c b/src/dlmisc.c index f154ebd0..fca843e1 100644 --- a/src/dlmisc.c +++ b/src/dlmisc.c @@ -43,12 +43,18 @@ struct snd_dlsym_link *snd_dlsym_start = NULL; * \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. + * \param errbuf a string buffer for the error message \c dlerror. + * \param errbuflen a length of the string buffer for the error message. * \return Library handle if successful, otherwise \c NULL. * * This function can emulate dynamic linking for the static build of * the alsa-lib library. In that case, \p name is set to \c NULL. */ -void *snd_dlopen(const char *name, int mode) +#ifndef DOXYGEN +void *INTERNAL(snd_dlopen)(const char *name, int mode, char *errbuf, size_t errbuflen) +#else +void *snd_dlopen(const char *name, int mode, char *errbuf, size_t errbuflen) +#endif { #ifndef PIC if (name == NULL) @@ -73,24 +79,49 @@ void *snd_dlopen(const char *name, int mode) * via ld.so.conf. */ void *handle = NULL; - char *filename; + char *filename = NULL; if (name && name[0] != '/') { - filename = malloc(sizeof(ALSA_PLUGIN_DIR) + 1 + strlen(name) + 1); - strcpy(filename, ALSA_PLUGIN_DIR); - strcat(filename, "/"); - strcat(filename, name); - handle = dlopen(filename, mode); - free(filename); + filename = alloca(sizeof(ALSA_PLUGIN_DIR) + 1 + strlen(name) + 1); + if (filename) { + strcpy(filename, ALSA_PLUGIN_DIR); + strcat(filename, "/"); + strcat(filename, name); + handle = dlopen(filename, mode); + if (!handle) { + /* if the filename exists and cannot be opened */ + /* return immediately */ + if (access(filename, X_OK) == 0) + goto errpath; + } + } } - if (!handle) + if (!handle) { handle = dlopen(name, mode); + if (!handle) + goto errpath; + } return handle; +errpath: + if (errbuf) + snprintf(errbuf, errbuflen, "%s: %s", filename, dlerror()); + return NULL; + #else return NULL; #endif } +#ifndef DOXYGEN +void *INTERNAL(snd_dlopen_old)(const char *name, int mode) +{ + return INTERNAL(snd_dlopen)(name, mode, NULL, 0); +} +#endif + +use_symbol_version(__snd_dlopen_old, snd_dlopen, ALSA_0.9); +use_default_symbol_version(__snd_dlopen, snd_dlopen, ALSA_1.1.6); + /** * \brief Closes a dynamic library - ALSA wrapper for \c dlclose. * \param handle Library handle, similar to \c dlclose. @@ -229,6 +260,7 @@ void *snd_dlobj_cache_get(const char *lib, const char *name, struct list_head *p; struct dlobj_cache *c; void *func, *dlobj; + char errbuf[256]; snd_dlobj_lock(); list_for_each(p, &pcm_dlobj_list) { @@ -247,11 +279,15 @@ void *snd_dlobj_cache_get(const char *lib, const char *name, } } - dlobj = snd_dlopen(lib, RTLD_NOW); + errbuf[0] = '\0'; + dlobj = snd_dlopen(lib, RTLD_NOW, + verbose ? errbuf : 0, + verbose ? sizeof(errbuf) : 0); if (dlobj == NULL) { if (verbose) - SNDERR("Cannot open shared library %s", - lib ? lib : "[builtin]"); + SNDERR("Cannot open shared library %s (%s)", + lib ? lib : "[builtin]", + errbuf); snd_dlobj_unlock(); return NULL; } diff --git a/src/hwdep/hwdep.c b/src/hwdep/hwdep.c index 29350936..7aa475c0 100644 --- a/src/hwdep/hwdep.c +++ b/src/hwdep/hwdep.c @@ -41,7 +41,7 @@ static int snd_hwdep_open_conf(snd_hwdep_t **hwdep, snd_config_t *hwdep_conf, int mode) { const char *str; - char buf[256]; + char buf[256], errbuf[256]; int err; snd_config_t *conf, *type_conf = NULL; snd_config_iterator_t i, next; @@ -116,12 +116,12 @@ static int snd_hwdep_open_conf(snd_hwdep_t **hwdep, #ifndef PIC snd_hwdep_open_symbols(); #endif - h = snd_dlopen(lib, RTLD_NOW); + h = snd_dlopen(lib, RTLD_NOW, errbuf, sizeof(errbuf)); if (h) open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_HWDEP_DLSYM_VERSION)); err = 0; if (!h) { - SNDERR("Cannot open shared library %s", lib); + SNDERR("Cannot open shared library %s (%s)", lib, errbuf); err = -ENOENT; } else if (!open_func) { SNDERR("symbol %s is not defined inside %s", open_name, lib); diff --git a/src/mixer/simple_abst.c b/src/mixer/simple_abst.c index 73528393..32a3f621 100644 --- a/src/mixer/simple_abst.c +++ b/src/mixer/simple_abst.c @@ -66,7 +66,7 @@ static int try_open(snd_mixer_class_t *class, const char *lib) class_priv_t *priv = snd_mixer_class_get_private(class); snd_mixer_event_t event_func; snd_mixer_sbasic_init_t init_func = NULL; - char *xlib, *path; + char *xlib, *path, errbuf[256]; void *h; int err = 0; @@ -81,9 +81,9 @@ static int try_open(snd_mixer_class_t *class, const char *lib) strcpy(xlib, path); strcat(xlib, "/"); strcat(xlib, lib); - h = snd_dlopen(xlib, RTLD_NOW); + h = snd_dlopen(xlib, RTLD_NOW, errbuf, sizeof(errbuf)); if (h == NULL) { - SNDERR("Unable to open library '%s'", xlib); + SNDERR("Unable to open library '%s' (%s)", xlib, errbuf); free(xlib); return -ENXIO; } @@ -114,7 +114,7 @@ static int try_open_full(snd_mixer_class_t *class, snd_mixer_t *mixer, class_priv_t *priv = snd_mixer_class_get_private(class); snd_mixer_event_t event_func; snd_mixer_sfbasic_init_t init_func = NULL; - char *xlib, *path; + char *xlib, *path, errbuf[256]; void *h; int err = 0; @@ -128,7 +128,7 @@ static int try_open_full(snd_mixer_class_t *class, snd_mixer_t *mixer, strcat(xlib, "/"); strcat(xlib, lib); /* note python modules requires RTLD_GLOBAL */ - h = snd_dlopen(xlib, RTLD_NOW|RTLD_GLOBAL); + h = snd_dlopen(xlib, RTLD_NOW|RTLD_GLOBAL, errbuf, sizeof(errbuf)); if (h == NULL) { SNDERR("Unable to open library '%s'", xlib); free(xlib); diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c index adb7230b..1f08bd78 100644 --- a/src/pcm/pcm_hooks.c +++ b/src/pcm/pcm_hooks.c @@ -341,7 +341,7 @@ even if the specified control doesn't exist. static int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_t *conf) { int err; - char buf[256]; + char buf[256], errbuf[256]; const char *str, *id; const char *lib = NULL, *install = NULL; snd_config_t *type = NULL, *args = NULL; @@ -424,12 +424,12 @@ static int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_ install = buf; snprintf(buf, sizeof(buf), "_snd_pcm_hook_%s_install", str); } - h = snd_dlopen(lib, RTLD_NOW); + h = snd_dlopen(lib, RTLD_NOW, errbuf, sizeof(errbuf)); install_func = h ? snd_dlsym(h, install, SND_DLSYM_VERSION(SND_PCM_DLSYM_VERSION)) : NULL; err = 0; if (!h) { - SNDERR("Cannot open shared library %s", - lib ? lib : "[builtin]"); + SNDERR("Cannot open shared library %s (%s)", + lib ? lib : "[builtin]", errbuf); err = -ENOENT; } else if (!install_func) { SNDERR("symbol %s is not defined inside %s", install, diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c index 53685094..75df09ca 100644 --- a/src/pcm/pcm_meter.c +++ b/src/pcm/pcm_meter.c @@ -605,7 +605,7 @@ int snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name, unsigned int frequenc static int snd_pcm_meter_add_scope_conf(snd_pcm_t *pcm, const char *name, snd_config_t *root, snd_config_t *conf) { - char buf[256]; + char buf[256], errbuf[256]; snd_config_iterator_t i, next; const char *id; const char *lib = NULL, *open_name = NULL, *str = NULL; @@ -670,11 +670,11 @@ static int snd_pcm_meter_add_scope_conf(snd_pcm_t *pcm, const char *name, open_name = buf; snprintf(buf, sizeof(buf), "_snd_pcm_scope_%s_open", str); } - h = snd_dlopen(lib, RTLD_NOW); + h = snd_dlopen(lib, RTLD_NOW, errbuf, sizeof(errbuf)); open_func = h ? dlsym(h, open_name) : NULL; err = 0; if (!h) { - SNDERR("Cannot open shared library %s", lib); + SNDERR("Cannot open shared library %s (%s)", lib, errbuf); err = -ENOENT; } else if (!open_func) { SNDERR("symbol %s is not defined inside %s", open_name, lib); diff --git a/src/rawmidi/rawmidi.c b/src/rawmidi/rawmidi.c index 7180becd..88d43017 100644 --- a/src/rawmidi/rawmidi.c +++ b/src/rawmidi/rawmidi.c @@ -162,7 +162,7 @@ static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp snd_config_t *rawmidi_conf, int mode) { const char *str; - char buf[256]; + char buf[256], errbuf[256]; int err; snd_config_t *conf, *type_conf = NULL; snd_config_iterator_t i, next; @@ -239,12 +239,12 @@ static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp #ifndef PIC snd_rawmidi_open_symbols(); #endif - h = snd_dlopen(lib, RTLD_NOW); + h = snd_dlopen(lib, RTLD_NOW, errbuf, sizeof(errbuf)); if (h) open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_RAWMIDI_DLSYM_VERSION)); err = 0; if (!h) { - SNDERR("Cannot open shared library %s", lib); + SNDERR("Cannot open shared library %s (%s)", lib, errbuf); err = -ENOENT; } else if (!open_func) { SNDERR("symbol %s is not defined inside %s", open_name, lib); diff --git a/src/seq/seq.c b/src/seq/seq.c index 630f52c3..983c4fab 100644 --- a/src/seq/seq.c +++ b/src/seq/seq.c @@ -823,7 +823,7 @@ static int snd_seq_open_conf(snd_seq_t **seqp, const char *name, int streams, int mode) { const char *str; - char buf[256]; + char buf[256], errbuf[256]; int err; snd_config_t *conf, *type_conf = NULL; snd_config_iterator_t i, next; @@ -899,12 +899,12 @@ static int snd_seq_open_conf(snd_seq_t **seqp, const char *name, #ifndef PIC snd_seq_open_symbols(); #endif - h = snd_dlopen(lib, RTLD_NOW); + h = snd_dlopen(lib, RTLD_NOW, errbuf, sizeof(errbuf)); if (h) open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_SEQ_DLSYM_VERSION)); err = 0; if (!h) { - SNDERR("Cannot open shared library %s", lib); + SNDERR("Cannot open shared library %s (%s)", lib, errbuf); err = -ENOENT; } else if (!open_func) { SNDERR("symbol %s is not defined inside %s", open_name, lib); diff --git a/src/timer/timer.c b/src/timer/timer.c index e027c903..8c49737e 100644 --- a/src/timer/timer.c +++ b/src/timer/timer.c @@ -76,7 +76,7 @@ static int snd_timer_open_conf(snd_timer_t **timer, snd_config_t *timer_conf, int mode) { const char *str; - char buf[256]; + char buf[256], errbuf[256]; int err; snd_config_t *conf, *type_conf = NULL; snd_config_iterator_t i, next; @@ -150,12 +150,12 @@ static int snd_timer_open_conf(snd_timer_t **timer, #ifndef PIC snd_timer_open_symbols(); #endif - h = snd_dlopen(lib, RTLD_NOW); + h = snd_dlopen(lib, RTLD_NOW, errbuf, sizeof(errbuf)); if (h) open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_TIMER_DLSYM_VERSION)); err = 0; if (!h) { - SNDERR("Cannot open shared library %s", lib); + SNDERR("Cannot open shared library %s (%s)", lib, errbuf); err = -ENOENT; } else if (!open_func) { SNDERR("symbol %s is not defined inside %s", open_name, lib); diff --git a/src/timer/timer_query.c b/src/timer/timer_query.c index d999d21b..6739f3c4 100644 --- a/src/timer/timer_query.c +++ b/src/timer/timer_query.c @@ -33,7 +33,7 @@ static int snd_timer_query_open_conf(snd_timer_query_t **timer, snd_config_t *timer_conf, int mode) { const char *str; - char buf[256]; + char buf[256], errbuf[256]; int err; snd_config_t *conf, *type_conf = NULL; snd_config_iterator_t i, next; @@ -108,12 +108,12 @@ static int snd_timer_query_open_conf(snd_timer_query_t **timer, #ifndef PIC snd_timer_query_open_symbols(); #endif - h = snd_dlopen(lib, RTLD_NOW); + h = snd_dlopen(lib, RTLD_NOW, errbuf, sizeof(errbuf)); if (h) open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_TIMER_QUERY_DLSYM_VERSION)); err = 0; if (!h) { - SNDERR("Cannot open shared library %s", lib); + SNDERR("Cannot open shared library %s (%s)", lib, errbuf); err = -ENOENT; } else if (!open_func) { SNDERR("symbol %s is not defined inside %s", open_name, lib); -- 2.13.6 _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel