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