/** \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);
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;
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");
@SYMBOL_PREFIX@alsa_lisp_*;
} ALSA_0.9.5;
+ALSA_1.1.6 {
+ global:
+
+ @SYMBOL_PREFIX@snd_dlopen;
+} ALSA_0.9.7;
case '.':
if (!id)
break;
+ /* fall through */
case ' ':
case '\f':
case '\t':
{
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;
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);
{
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,
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) {
* \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)
* 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.
struct list_head *p;
struct dlobj_cache *c;
void *func, *dlobj;
+ char errbuf[256];
snd_dlobj_lock();
list_for_each(p, &pcm_dlobj_list) {
}
}
- 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;
}
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;
#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);
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;
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;
}
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;
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);
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;
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,
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;
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);
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;
#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);
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;
#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);
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;
#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);
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;
#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);