Hello Jürgen,

Here's the patch. Seems to work correctly for me.

Regards,
Elias


On 7 April 2014 01:39, Juergen Sauermann <[email protected]>wrote:

> Hi Elias,
>
> yes, please send the patch.
>
> /// Jürgen
>
>
>
> On 04/06/2014 06:12 PM, Elias Mårtenson wrote:
>
>> The current mechanism to load native libraries first attempts to find a
>> library with the suffix .so. If that fails, it will try again with the
>> suffix .dylib (the OSX library extension).
>>
>> This poses a problem, since if the .so library failed for any reason
>> other than the file not existing, the error message in )MORE will be:
>> "filename.dylib: file not found".
>>
>> Since the dlopen facility does not provide a machine-readable way of
>> interpreting hat the error was (missing file, or failure to initialise?)
>> may I suggest we first identify which file exists and then perform a single
>> dlopen on that file.
>>
>> I can do it and send patches if you want.
>>
>> Regards,
>> Elias
>>
>
>
Index: src/NativeFunction.cc
===================================================================
--- src/NativeFunction.cc       (revision 189)
+++ src/NativeFunction.cc       (working copy)
@@ -20,6 +20,9 @@
 
 
 #include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "Error.hh"
 #include "NativeFunction.hh"
@@ -28,6 +31,61 @@
 
 vector<NativeFunction *> NativeFunction::valid_functions;
 
+static bool file_exists_and_is_readable( string pathname )
+{
+    struct stat buf;
+    const char *path = pathname.c_str();
+
+    if( stat( path, &buf ) != -1 ) {
+        if( S_ISREG( buf.st_mode ) ) {
+            if( access( path, R_OK ) == 0 ) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+static void *load_lib( string path )
+{
+    void *handle = dlopen( path.c_str(), RTLD_NOW );
+    if( handle == NULL ) {
+        Workspace::more_error() = UCS_string(dlerror());
+    }
+    return handle;
+}
+
+static void *find_lib_with_extensions( string path )
+{
+    if( file_exists_and_is_readable( path ) ) {
+        return load_lib( path );
+    }
+    else if( file_exists_and_is_readable( path + ".so" ) ) {
+        return load_lib( path + ".so" );
+    }
+    else if( file_exists_and_is_readable( path + ".dylib" ) ) {
+        return load_lib( path + ".dylib" );
+    }
+    else {
+        stringstream out;
+        out << "File not found: " << path;
+        Workspace::more_error() = out.str().c_str();
+        return NULL;
+    }
+}
+
+static void *find_library( string path )
+{
+    if( path.find( '/' ) == string::npos && path.find( '\\' ) == string::npos 
) {
+        string pkg_path = PKGLIBDIR;
+        return find_lib_with_extensions( pkg_path + path );
+    }
+    else {
+        return find_lib_with_extensions( path );
+    }
+}
+
 //-----------------------------------------------------------------------------
 NativeFunction::NativeFunction(const UCS_string & so_name,
                                const UCS_string & apl_name)
@@ -40,65 +98,9 @@
 {
    // open .so file...
    //
-   {
-     UTF8_string lib_name(so_path);
-     handle = 0;
-
-     if ((strchr(lib_name.c_str(), '/') == 0) &&
-         (strchr(lib_name.c_str(), '\\') == 0))
-        {
-          // the lib_name contains no path prefix. Try:
-          //
-          // PKGLIBDIR/lib_name
-          // PKGLIBDIR/lib_name.so
-          // PKGLIBDIR/lib_name.dylib
-          //
-          UTF8_string pkg_path = PKGLIBDIR;
-          pkg_path.append('/');
-          pkg_path.append(lib_name);
-          handle = dlopen(pkg_path.c_str(), RTLD_NOW);
-          if (handle == 0)   // no luck: try pkg_path.so
-             {
-               UTF8_string pkg_path__so(pkg_path);
-               pkg_path__so.append(UTF8_string(".so"));
-               handle = dlopen(pkg_path__so.c_str(), RTLD_NOW);
-             }
-          if (handle == 0)   // still no luck: try pkg_path.dylib
-             {
-               UTF8_string pkg_path__dylib(pkg_path);
-               pkg_path__dylib.append(UTF8_string(".dylib"));
-               handle = dlopen(pkg_path__dylib.c_str(), RTLD_NOW);
-             }
-        }
-
-     if (handle == 0)   // lib_name was not in PKGLIBDIR.
-        {
-          // Try:
-          //
-          // lib_name
-          // lib_name.so
-          // lib_name.dylib
-
-          handle = dlopen(lib_name.c_str(), RTLD_NOW);
-          if (handle == 0)   // no luck: try lib_name.so
-             {
-               UTF8_string lib_name__so(lib_name);
-               lib_name__so.append(UTF8_string(".so"));
-               handle = dlopen(lib_name__so.c_str(), RTLD_NOW);
-             }
-          if (handle == 0)   // still no luck: try lib_name.dylib
-             {
-               UTF8_string lib_name__dylib(lib_name);
-               lib_name__dylib.append(UTF8_string(".dylib"));
-               handle = dlopen(lib_name__dylib.c_str(), RTLD_NOW);
-             }
-        }
-
-     if (handle == 0)   // all dlopen() failed
-        {
-          Workspace::more_error() = UCS_string(dlerror());
-          return;
-        }
+   handle = find_library( so_path.to_string() );
+   if( handle == NULL ) {
+       return;
    }
 
    // get the function multiplexer

Reply via email to