1 /* Copyright (C) 2011 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 ** GNU General Public License for more details.
11 */
12 #include <android/utils/dll.h>
13 #include <android/utils/system.h>
14 #include <android/utils/path.h>
15
16 #include <stdlib.h>
17
18 /* Utility function, append one string to another, caller must free result */
19 static char*
append_string(const char * str1,const char * str2)20 append_string( const char* str1, const char* str2 )
21 {
22 int len1 = strlen(str1);
23 int len2 = strlen(str2);
24 char* result = malloc(len1+len2+1);
25
26 if (result != NULL) {
27 memcpy(result, str1, len1);
28 memcpy(result + len1, str2, len2);
29 result[len1+len2] = '\0';
30 }
31 return result;
32 }
33
34 #ifdef _WIN32
35
36 #include <windows.h>
37
38 /* This function is used to revert all forward slashes (/) in a path
39 * string into unquoted backwards one (\). This is necessary because
40 * LoadLibrary() and AddDllDirectory() do not support forward slashes.
41 *
42 * Caller must free the result string
43 */
44 static char*
reverse_slashes(const char * path)45 reverse_slashes( const char* path )
46 {
47 int len = strlen(path);
48 char* result = malloc(len+1);
49 int nn;
50
51 for (nn = 0; nn < len; nn++) {
52 int ch = path[nn];
53 if (ch == '/') {
54 ch = '\\';
55 }
56 result[nn] = (char)ch;
57 }
58 result[nn] = '\0';
59
60 return result;
61 }
62
63 ADynamicLibrary*
adynamicLibrary_open(const char * libraryName,char ** pError)64 adynamicLibrary_open( const char* libraryName,
65 char** pError)
66 {
67 char* libName = (char*) libraryName;
68 void* result;
69
70 /* Append a .dll to the library name if it doesn't have an extension */
71 if (strchr(libraryName,'.') == NULL) {
72 libName = append_string(libraryName, ".dll");
73 }
74
75 /* Now do our magic */
76 *pError = NULL;
77 result = (ADynamicLibrary*) LoadLibrary( libName );
78 if (result == NULL) {
79 *pError = ASTRDUP("Could not load DLL!");
80 }
81
82 /* Free the library name if we modified it */
83 if (libName != libraryName) {
84 free(libName);
85 }
86
87 return (ADynamicLibrary*) result;
88 }
89
90 void*
adynamicLibrary_findSymbol(ADynamicLibrary * lib,const char * symbolName,char ** pError)91 adynamicLibrary_findSymbol( ADynamicLibrary* lib,
92 const char* symbolName,
93 char** pError)
94 {
95 void* result;
96
97 *pError = NULL;
98
99 if (lib == NULL) {
100 *pError = strdup("NULL library pointer");
101 return NULL;
102 }
103 if (symbolName == NULL || symbolName[0] == '\0') {
104 *pError = strdup("NULL or empty symbolName");
105 return NULL;
106 }
107 result = GetProcAddress( (HMODULE)lib, symbolName );
108 if (result == NULL) {
109 *pError = ASTRDUP("Could not find symbol");
110 }
111 return result;
112 }
113
114 /* Close/unload a given dynamic library */
115 void
adynamicLibrary_close(ADynamicLibrary * lib)116 adynamicLibrary_close( ADynamicLibrary* lib )
117 {
118 if (lib != NULL) {
119 FreeLibrary( (HMODULE)lib );
120 }
121 }
122
123 #else /* !_WIN32 */
124
125 #include <dlfcn.h>
126 #include <stdlib.h>
127
128 ADynamicLibrary*
adynamicLibrary_open(const char * libraryName,char ** pError)129 adynamicLibrary_open( const char* libraryName,
130 char** pError)
131 {
132 char* libName = (char*) libraryName;
133 void* result;
134
135 #ifdef __APPLE__
136 # define SO_EXTENSION ".dylib"
137 #else
138 # define SO_EXTENSION ".so"
139 #endif
140
141 /* Append a .so to the library name if it doesn't have an extension */
142 if (strchr(libraryName,'.') == NULL) {
143 libName = append_string(libraryName, SO_EXTENSION);
144 }
145
146 /* Now do our magic */
147 *pError = NULL;
148 result = dlopen( libName, RTLD_LAZY );
149 if (result == NULL) {
150 *pError = strdup(dlerror());
151 }
152
153 /* Free the library name if we modified it */
154 if (libName != (char*)libraryName) {
155 free(libName);
156 }
157
158 return (ADynamicLibrary*) result;
159 }
160
161 void*
adynamicLibrary_findSymbol(ADynamicLibrary * lib,const char * symbolName,char ** pError)162 adynamicLibrary_findSymbol( ADynamicLibrary* lib,
163 const char* symbolName,
164 char** pError)
165 {
166 void* result;
167
168 *pError = NULL;
169
170 if (lib == NULL) {
171 *pError = strdup("NULL library pointer");
172 return NULL;
173 }
174 if (symbolName == NULL || symbolName[0] == '\0') {
175 *pError = strdup("NULL or empty symbolName");
176 return NULL;
177 }
178 result = dlsym(lib, symbolName);
179 if (result == NULL) {
180 *pError = strdup(dlerror());
181 }
182 return result;
183 }
184
185 /* Close/unload a given dynamic library */
186 void
adynamicLibrary_close(ADynamicLibrary * lib)187 adynamicLibrary_close( ADynamicLibrary* lib )
188 {
189 if (lib != NULL) {
190 dlclose(lib);
191 }
192 }
193
194 #endif /* !_WIN32 */
195