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 */
19static char*
20append_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
38ADynamicLibrary*
39adynamicLibrary_open( const char*  libraryName,
40                      char**       pError)
41{
42    char*  libName = (char*) libraryName;
43    void*  result;
44
45    /* Append a .dll to the library name if it doesn't have an extension */
46    if (strchr(libraryName,'.') == NULL) {
47        libName = append_string(libraryName, ".dll");
48    }
49
50    /* Now do our magic */
51    *pError = NULL;
52    result = (ADynamicLibrary*) LoadLibrary( libName );
53    if (result == NULL) {
54        *pError = ASTRDUP("Could not load DLL!");
55    }
56
57    /* Free the library name if we modified it */
58    if (libName != libraryName) {
59        free(libName);
60    }
61
62    return (ADynamicLibrary*) result;
63}
64
65void*
66adynamicLibrary_findSymbol( ADynamicLibrary*  lib,
67                            const char*       symbolName,
68                            char**            pError)
69{
70    void* result;
71
72    *pError = NULL;
73
74    if (lib == NULL) {
75        *pError = strdup("NULL library pointer");
76        return NULL;
77    }
78    if (symbolName == NULL || symbolName[0] == '\0') {
79        *pError = strdup("NULL or empty symbolName");
80        return NULL;
81    }
82    result = GetProcAddress( (HMODULE)lib, symbolName );
83    if (result == NULL) {
84        *pError = ASTRDUP("Could not find symbol");
85    }
86    return result;
87}
88
89/* Close/unload a given dynamic library */
90void
91adynamicLibrary_close( ADynamicLibrary*  lib )
92{
93    if (lib != NULL) {
94        FreeLibrary( (HMODULE)lib );
95    }
96}
97
98#else /* !_WIN32 */
99
100#include <dlfcn.h>
101#include <stdlib.h>
102
103ADynamicLibrary*
104adynamicLibrary_open( const char*  libraryName,
105                      char**       pError)
106{
107    char*  libName = (char*) libraryName;
108    void*  result;
109
110#ifdef __APPLE__
111#  define SO_EXTENSION ".dylib"
112#else
113#  define SO_EXTENSION ".so"
114#endif
115
116    /* Append a .so to the library name if it doesn't have an extension */
117    if (strchr(libraryName,'.') == NULL) {
118        libName = append_string(libraryName, SO_EXTENSION);
119    }
120
121    /* Now do our magic */
122    *pError = NULL;
123    result  = dlopen( libName, RTLD_LAZY );
124    if (result == NULL) {
125        *pError = strdup(dlerror());
126    }
127
128    /* Free the library name if we modified it */
129    if (libName != (char*)libraryName) {
130        free(libName);
131    }
132
133    return (ADynamicLibrary*) result;
134}
135
136void*
137adynamicLibrary_findSymbol( ADynamicLibrary*  lib,
138                            const char*       symbolName,
139                            char**            pError)
140{
141    void* result;
142
143    *pError = NULL;
144
145    if (lib == NULL) {
146        *pError = strdup("NULL library pointer");
147        return NULL;
148    }
149    if (symbolName == NULL || symbolName[0] == '\0') {
150        *pError = strdup("NULL or empty symbolName");
151        return NULL;
152    }
153    result = dlsym(lib, symbolName);
154    if (result == NULL) {
155        *pError = strdup(dlerror());
156    }
157    return result;
158}
159
160/* Close/unload a given dynamic library */
161void
162adynamicLibrary_close( ADynamicLibrary*  lib )
163{
164    if (lib != NULL) {
165        dlclose(lib);
166    }
167}
168
169#endif /* !_WIN32 */
170