1 /*
2 * This file is part of libbluray
3 * Copyright (C) 2009-2010 Obliter0n
4 * Copyright (C) 2009-2010 John Stebbins
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
21 #if HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #ifdef HAVE_DLADDR
26 # define _GNU_SOURCE /* dladdr */
27 #endif
28
29 #include "dl.h"
30 #include "util/macro.h"
31 #include "util/logging.h"
32 #include "util/strutl.h"
33
34 #ifdef __APPLE__
35 // Required to make dladdr available
36 # define _DARWIN_C_SOURCE
37 #endif
38
39 #if defined(HAVE_DLFCN_H)
40 # include <dlfcn.h>
41 #elif defined(HAVE_SYS_DL_H)
42 # include <sys/dl.h>
43 #endif
44
45 #include <string.h>
46
_dl_dlopen(const char * path)47 static void *_dl_dlopen(const char *path)
48 {
49 void *result;
50
51 result = dlopen(path, RTLD_LAZY);
52
53 if (!result) {
54 BD_DEBUG(DBG_FILE, "can't open library '%s': %s\n", path, dlerror());
55 } else {
56 BD_DEBUG(DBG_FILE, "opened library '%s'\n", path);
57 }
58
59 return result;
60 }
61
dl_dlopen(const char * path,const char * version)62 void *dl_dlopen(const char *path, const char *version)
63 {
64 char *name;
65 void *dll;
66 int i;
67
68 #if defined(__APPLE__)
69 static const char ext[] = ".dylib";
70 /*
71 Search for the library in several locations:
72 "" - default search path (including DYLD_LIBRARY_PATH)
73 @loader_path - location of current library/binary (ex. libbluray.dylib)
74 @executable_path - location of running binary (ex. /Applications/Some.app/Contents/MacOS)
75 @rpath - search rpaths of running binary (man install_name_path)
76 /usr/local/lib/ - explicitly added path, as runtime hardened programs ignore DYLD_FALLBACK_PATH now
77 */
78 static const char *search_paths[] = {"", "@loader_path/lib/", "@loader_path/", "@executable_path/",
79 "@executable_path/lib/", "@executable_path/../lib/",
80 "@executable_path/../Resources/", "@rpath/", "/usr/local/lib/", NULL};
81 version = NULL;
82 #else
83 static const char ext[] = ".so";
84 static const char *search_paths[] = {"", NULL};
85 #endif
86
87 for (i = 0 ; search_paths[i] ; ++i) {
88 if (version) {
89 name = str_printf("%s%s%s.%s", search_paths[i], path, ext, version);
90 } else {
91 name = str_printf("%s%s%s", search_paths[i], path, ext);
92 }
93
94 if (!name) {
95 BD_DEBUG(DBG_FILE | DBG_CRIT, "out of memory\n");
96 continue;
97 }
98
99 dll = _dl_dlopen (name);
100 X_FREE(name);
101 if (dll) {
102 return dll;
103 }
104 }
105
106 return NULL;
107 }
108
dl_dlsym(void * handle,const char * symbol)109 void *dl_dlsym(void *handle, const char *symbol)
110 {
111 void *result = dlsym(handle, symbol);
112
113 if (!result) {
114 BD_DEBUG(DBG_FILE, "dlsym(%p, '%s') failed: %s\n", handle, symbol, dlerror());
115 }
116
117 return result;
118 }
119
dl_dlclose(void * handle)120 int dl_dlclose(void *handle)
121 {
122 return dlclose(handle);
123 }
124
125 #define PATH_SEPARATOR '/'
dl_get_path(void)126 const char *dl_get_path(void)
127 {
128 static char *lib_path = NULL;
129 static int initialized = 0;
130
131 if (!initialized) {
132 initialized = 1;
133
134 #if defined(__APPLE__) || defined(HAVE_DLADDR)
135 Dl_info dl_info;
136 int ret = dladdr((void *)dl_get_path, &dl_info);
137 if (ret != 0) {
138 lib_path = strdup(dl_info.dli_fname);
139
140 /* cut library name from path */
141 char *p = strrchr(lib_path, PATH_SEPARATOR);
142 if (p) {
143 *(p+1) = 0;
144 }
145 BD_DEBUG(DBG_FILE, "library file is %s\n", lib_path);
146 } else {
147 BD_DEBUG(DBG_FILE, "Can't determine libbluray.so install path\n");
148 }
149 #else
150 BD_DEBUG(DBG_FILE, "Can't determine libbluray.so install path\n");
151 #endif
152 }
153
154 return lib_path;
155 }
156