]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Change snd_dlopen() function to return the error string
authorJaroslav Kysela <perex@perex.cz>
Wed, 22 Nov 2017 12:23:45 +0000 (13:23 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 27 Nov 2017 20:48:20 +0000 (21:48 +0100)
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>
13 files changed:
include/global.h
modules/mixer/simple/sbasedl.c
src/Versions.in
src/conf.c
src/dlmisc.c
src/hwdep/hwdep.c
src/mixer/simple_abst.c
src/pcm/pcm_hooks.c
src/pcm/pcm_meter.c
src/rawmidi/rawmidi.c
src/seq/seq.c
src/timer/timer.c
src/timer/timer_query.c

index 41680829b0344cb5f21d6b273fe63816145bbd54..d73d333aae19d916243a7a87343cb55705652a2b 100644 (file)
@@ -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);
 
index 5c3825f51e5193a0070da711fdb062f8d1ae2aa0..d8cbf0f10ee00701f208f625992bcd3b3d48e0c7 100644 (file)
@@ -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");
index 8d2dd116c8214075bec853c662e0c52a9e345288..5daccbd417f5a5c7aba96c6b3af84bfd3dec6161 100644 (file)
@@ -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;
index c410bfb8a9d90203716f00b21db317c0c78b8c26..e71bb972015bcd877e7e6959ff8c4bbae6c3e979 100644 (file)
@@ -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) {
index f154ebd09aa8be9f960b5e4856f23e6161bd1c0f..b10aef4d53743453e70af3297bf3d4248c4a08f0 100644 (file)
@@ -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,23 +79,45 @@ 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.
@@ -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;
        }
index 29350936670d7d142995b830bcf1b30f44dbc4e0..7aa475c02e9069b5b247e296fd11ce744066b89e 100644 (file)
@@ -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);
index 7352839367cdde82fc5d05ab80ea67a97159e03c..32a3f621f70c4da24906f8ba6b4ee7a72c0881f3 100644 (file)
@@ -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);
index adb7230b88d5f4382ab0cc696709cb4609cae309..1f08bd78d5dd23a15a7285863085ff00ab18913d 100644 (file)
@@ -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,
index 536850944e2a8e5ecb16a68880707db51736542c..75df09ca7ed36bf90744270399e35a2507f33fcb 100644 (file)
@@ -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);
index 7180becd007ac83f1f510b32472b13af969d9c3c..88d43017fd18bec6ee4f82c7f337b4c532cf0ce0 100644 (file)
@@ -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);
index 630f52c3d763e138868c865991a7b83a210920ae..983c4fab9ba69bd41b62602a2b70fb5f14dbb503 100644 (file)
@@ -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);
index e027c903078f9c32cfed15c4eaad64b13cd2540f..8c49737e859cd36f830fd9c48d2e9dcad2d5b341 100644 (file)
@@ -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);
index d999d21b765784f4029fa4a08f7269fe72a1508f..6739f3c4109b0f8accbc399a0d5404a3fb95ab7c 100644 (file)
@@ -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);