Change snd_dlopen() function to return the error string
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@perex.cz>
This commit is contained in:
parent
38a39091e3
commit
c051036e17
13 changed files with 90 additions and 51 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ int mixer_simple_basic_dlopen(snd_mixer_class_t *class,
|
|||
struct bclass_private *priv = snd_mixer_sbasic_get_private(class);
|
||||
const char *lib = "smixer-sbase.so";
|
||||
void (*initpriv)(snd_mixer_class_t *class, struct bclass_private *priv);
|
||||
char *xlib, *path;
|
||||
char *xlib, *path, errbuf[256];
|
||||
void *h;
|
||||
int initflag = 0;
|
||||
|
||||
|
@ -63,9 +63,9 @@ int mixer_simple_basic_dlopen(snd_mixer_class_t *class,
|
|||
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);
|
||||
goto __error;
|
||||
}
|
||||
initpriv = dlsym(h, "alsa_mixer_sbasic_initpriv");
|
||||
|
|
|
@ -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_0.9.7;
|
||||
|
|
13
src/conf.c
13
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) {
|
||||
|
|
61
src/dlmisc.c
61
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,46 @@ 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;
|
||||
#else
|
||||
return NULL;
|
||||
errpath:
|
||||
if (errbuf)
|
||||
snprintf(errbuf, errbuflen, "%s: %s", filename, dlerror());
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#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 +257,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 +276,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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue