This source file includes following definitions.
- do_pdlopen
- pdlopen_open
- pdlopen_lookup
- pdlopen_close
- pdlopen_foreachfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include <src/include/pmix_config.h>
16
17 #include <stdlib.h>
18 #include <dlfcn.h>
19 #include <sys/types.h>
20 #include <dirent.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23
24 #include "pmix_common.h"
25 #include "src/mca/pdl/pdl.h"
26 #include "src/util/argv.h"
27 #include "src/util/error.h"
28
29 #include "pdl_pdlopen.h"
30
31
32
33
34
35 static void do_pdlopen(const char *fname, int flags,
36 void **handle, char **err_msg)
37 {
38 assert(handle);
39
40 *handle = dlopen(fname, flags);
41
42 if (NULL != err_msg) {
43 if (NULL != *handle) {
44 *err_msg = NULL;
45 } else {
46 *err_msg = dlerror();
47 }
48 }
49 }
50
51
52 static int pdlopen_open(const char *fname, bool use_ext, bool private_namespace,
53 pmix_pdl_handle_t **handle, char **err_msg)
54 {
55 int rc;
56
57 assert(handle);
58
59 *handle = NULL;
60
61
62 int flags = RTLD_LAZY;
63 if (private_namespace) {
64 flags |= RTLD_LOCAL;
65 } else {
66 flags |= RTLD_GLOBAL;
67 }
68
69
70
71 void *local_handle = NULL;
72 if (use_ext && NULL != fname) {
73 int i;
74 char *ext;
75
76 for (i = 0, ext = mca_pdl_pdlopen_component.filename_suffixes[i];
77 NULL != ext;
78 ext = mca_pdl_pdlopen_component.filename_suffixes[++i]) {
79 char *name;
80
81 rc = asprintf(&name, "%s%s", fname, ext);
82 if (0 > rc) {
83 return PMIX_ERR_NOMEM;
84 }
85 if (NULL == name) {
86 return PMIX_ERR_IN_ERRNO;
87 }
88
89
90 struct stat buf;
91 if (stat(name, &buf) < 0) {
92 free(name);
93 if (NULL != err_msg) {
94 *err_msg = "File not found";
95 }
96 continue;
97 }
98
99
100
101 do_pdlopen(name, flags, &local_handle, err_msg);
102 free(name);
103 break;
104 }
105 }
106
107
108
109 else {
110 do_pdlopen(fname, flags, &local_handle, err_msg);
111 }
112
113 if (NULL != local_handle) {
114 *handle = calloc(1, sizeof(pmix_pdl_handle_t));
115 (*handle)->dlopen_handle = local_handle;
116
117 #if PMIX_ENABLE_DEBUG
118 if( NULL != fname ) {
119 (*handle)->filename = strdup(fname);
120 }
121 else {
122 (*handle)->filename = strdup("(null)");
123 }
124 #endif
125 }
126 return (NULL != local_handle) ? PMIX_SUCCESS : PMIX_ERROR;
127 }
128
129
130 static int pdlopen_lookup(pmix_pdl_handle_t *handle, const char *symbol,
131 void **ptr, char **err_msg)
132 {
133 assert(handle);
134 assert(handle->dlopen_handle);
135 assert(symbol);
136 assert(ptr);
137
138 *ptr = dlsym(handle->dlopen_handle, symbol);
139 if (NULL != *ptr) {
140 return PMIX_SUCCESS;
141 }
142
143 if (NULL != err_msg) {
144 *err_msg = dlerror();
145 }
146 return PMIX_ERROR;
147 }
148
149
150 static int pdlopen_close(pmix_pdl_handle_t *handle)
151 {
152 assert(handle);
153
154 int ret;
155 ret = dlclose(handle->dlopen_handle);
156
157 #if PMIX_ENABLE_DEBUG
158 free(handle->filename);
159 #endif
160 free(handle);
161
162 return ret;
163 }
164
165
166
167
168
169 static int pdlopen_foreachfile(const char *search_path,
170 int (*func)(const char *filename, void *data),
171 void *data)
172 {
173 int ret;
174 DIR *dp = NULL;
175 char **dirs = NULL;
176 char **good_files = NULL;
177
178 dirs = pmix_argv_split(search_path, PMIX_ENV_SEP);
179 for (int i = 0; NULL != dirs && NULL != dirs[i]; ++i) {
180
181 dp = opendir(dirs[i]);
182 if (NULL == dp) {
183 ret = PMIX_ERR_IN_ERRNO;
184 goto error;
185 }
186
187 struct dirent *de;
188 while (NULL != (de = readdir(dp))) {
189
190
191 char *abs_name = NULL;
192 ret = asprintf(&abs_name, "%s/%s", dirs[i], de->d_name);
193 if (0 > ret) {
194 goto error;
195 }
196 if (NULL == abs_name) {
197 ret = PMIX_ERR_IN_ERRNO;
198 goto error;
199 }
200
201
202 struct stat buf;
203 if (stat(abs_name, &buf) < 0) {
204 free(abs_name);
205 ret = PMIX_ERR_IN_ERRNO;
206 goto error;
207 }
208
209
210 if (!S_ISREG(buf.st_mode)) {
211 free(abs_name);
212 continue;
213 }
214
215
216 char *ptr = strrchr(abs_name, '.');
217 if (NULL != ptr) {
218
219
220 if (strcmp(ptr, ".la") == 0 ||
221 strcmp(ptr, ".lo") == 0) {
222 free (abs_name);
223 continue;
224 }
225
226 *ptr = '\0';
227 }
228
229
230
231 bool found = false;
232 for (int j = 0; NULL != good_files &&
233 NULL != good_files[j]; ++j) {
234 if (strcmp(good_files[j], abs_name) == 0) {
235 found = true;
236 break;
237 }
238 }
239
240 if (!found) {
241 pmix_argv_append_nosize(&good_files, abs_name);
242 }
243 free(abs_name);
244 }
245 closedir(dp);
246 }
247 dp = NULL;
248
249
250 if (NULL != good_files) {
251 for (int i = 0; NULL != good_files[i]; ++i) {
252 ret = func(good_files[i], data);
253 if (PMIX_SUCCESS != ret) {
254 goto error;
255 }
256 }
257 }
258
259 ret = PMIX_SUCCESS;
260
261 error:
262 if (NULL != dp) {
263 closedir(dp);
264 }
265 if (NULL != dirs) {
266 pmix_argv_free(dirs);
267 }
268 if (NULL != good_files) {
269 pmix_argv_free(good_files);
270 }
271
272 return ret;
273 }
274
275
276
277
278
279 pmix_pdl_base_module_t pmix_pdl_pdlopen_module = {
280 .open = pdlopen_open,
281 .lookup = pdlopen_lookup,
282 .close = pdlopen_close,
283 .foreachfile = pdlopen_foreachfile
284 };