source: roaraudio/libroar/roardl.c @ 5482:ba865ae62928

Last change on this file since 5482:ba865ae62928 was 5482:ba865ae62928, checked in by phi, 12 years ago

support quoted strings

File size: 21.3 KB
Line 
1//roardl.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2012
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38#ifdef ROAR_HAVE_H_DIRENT
39#include <dirent.h>
40#endif
41
42#if defined(ROAR_HAVE_LIBDL) && !defined(RTLD_NEXT)
43#define RTLD_NEXT ((void *) -1L)
44#endif
45
46struct roar_dl_lhandle {
47 size_t refc; // currently unused.
48 int flags;
49 char * libname; // only used for ROAR_DL_FLAG_STATIC.
50 struct roar_dl_librarypara * para;
51 struct roar_dl_libraryinst * lib;
52 struct {
53  struct roar_error_state error_state;
54  void *  global_data;
55  void *  global_data_state;
56  struct roar_notify_core * notifycore;
57 } context;
58 int ra_inited;
59#if defined(ROAR_HAVE_LIBDL)
60 void * handle;
61#elif defined(ROAR_TARGET_WIN32)
62 HMODULE handle;
63#endif
64};
65
66
67struct roar_dl_librarypara * roar_dl_para_new(const char * args, void * binargv,
68                                              const char * appname, const char * abiversion) {
69 struct roar_dl_librarypara * ret = roar_mm_malloc(sizeof(struct roar_dl_librarypara));
70 ssize_t argc;
71 int err;
72
73 if ( ret == NULL )
74  return NULL;
75
76 memset(ret, 0, sizeof(struct roar_dl_librarypara));
77
78 ret->version    = ROAR_DL_LIBPARA_VERSION;
79 ret->len        = sizeof(struct roar_dl_librarypara);
80 ret->refc       = 1;
81 ret->argc       = 0;
82 ret->argv       = NULL;
83 ret->args_store = NULL;
84 ret->binargv    = binargv;
85 ret->appname    = appname;
86 ret->abiversion = abiversion;
87
88 if ( args != NULL ) {
89  ret->args_store = roar_mm_strdup(args);
90  if ( ret->args_store == NULL ) {
91   err = roar_error;
92   roar_mm_free(ret);
93   roar_error = err;
94   return NULL;
95  }
96
97  argc = roar_keyval_split(&(ret->argv), ret->args_store, NULL, NULL, 1);
98  if ( argc == -1 ) {
99   err = roar_error;
100   roar_mm_free(ret->args_store);
101   roar_mm_free(ret);
102   roar_error = err;
103   return NULL;
104  }
105
106  ret->argc = argc;
107 }
108
109 return ret;
110}
111
112int roar_dl_para_ref                    (struct roar_dl_librarypara * para) {
113 if ( para == NULL ) {
114  ROAR_DBG("roar_dl_para_ref(para=%p) = -1 // error=FAULT", para);
115  roar_err_set(ROAR_ERROR_FAULT);
116  return -1;
117 }
118
119 para->refc++;
120
121 ROAR_DBG("roar_dl_para_ref(para=%p) = 0", para);
122 return 0;
123}
124
125int roar_dl_para_unref                  (struct roar_dl_librarypara * para) {
126 if ( para == NULL ) {
127  ROAR_DBG("roar_dl_para_unref(para=%p) = -1 // error=FAULT", para);
128  roar_err_set(ROAR_ERROR_FAULT);
129  return -1;
130 }
131
132 para->refc--;
133
134 if ( para->refc ) {
135  ROAR_DBG("roar_dl_para_unref(para=%p) = 0", para);
136  return 0;
137 }
138
139 if ( para->notifycore != NULL )
140  roar_notify_core_unref(para->notifycore);
141
142 if ( para->args_store != NULL ) {
143  roar_mm_free(para->args_store);
144  roar_mm_free(para->argv);
145 }
146
147 roar_mm_free(para);
148
149 ROAR_DBG("roar_dl_para_unref(para=%p) = 0", para);
150 return 0;
151}
152int roar_dl_para_check_version          (struct roar_dl_librarypara * para,
153                                         const char * appname, const char * abiversion) {
154 if ( para == NULL ) {
155  roar_err_set(ROAR_ERROR_FAULT);
156  return -1;
157 }
158
159 // check if both appnames are NULL or non-NULL.
160 if ( (para->appname == NULL && appname != NULL) || (para->appname != NULL && appname == NULL) ) {
161  roar_err_set(ROAR_ERROR_BADHOST);
162  return -1;
163 }
164
165 // check if the appname matches if given.
166 if ( para->appname != NULL && !!strcmp(para->appname, appname) ) {
167  roar_err_set(ROAR_ERROR_BADHOST);
168  return -1;
169 }
170
171 // check if both ABI versions are NULL or non-NULL.
172 if ( (para->abiversion == NULL && abiversion != NULL) || (para->abiversion != NULL && abiversion == NULL) ) {
173  roar_err_set(ROAR_ERROR_BADVERSION);
174  return -1;
175 }
176
177 // check if the ABI versions matches if given.
178 if ( para->abiversion != NULL && !!strcmp(para->abiversion, abiversion) ) {
179  roar_err_set(ROAR_ERROR_BADVERSION);
180  return -1;
181 }
182
183 return 0;
184}
185
186
187#if defined(ROAR_HAVE_LIBDL)
188static void * _roardl2ldl (struct roar_dl_lhandle * lhandle) {
189 ROAR_DBG("_roardl2ldl(lhandle=%p) = ?", lhandle);
190
191 if ( lhandle == ROAR_DL_HANDLE_DEFAULT ) {
192  ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)RTLD_DEFAULT);
193  return RTLD_DEFAULT;
194 }
195
196 if ( lhandle == ROAR_DL_HANDLE_NEXT ) {
197  ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)RTLD_NEXT);
198  return RTLD_NEXT;
199 }
200
201 ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)(lhandle->handle));
202 return lhandle->handle;
203}
204#elif defined(ROAR_TARGET_WIN32)
205static HMODULE _roardl2winhandle(struct roar_dl_lhandle * lhandle) {
206 if ( (void*)lhandle < (void*)128 ) {
207  return NULL;
208 }
209 return lhandle->handle;
210}
211#endif
212
213#ifdef ROAR_HAVE_H_DIRENT
214// pvn = prefix, host vendor, host name
215static struct roar_dl_lhandle * _load_from_path_pvn(const char * name,
216                                                    int flags, int ra_init,
217                                                    struct roar_dl_librarypara * para,
218                                                    const char * prefix,
219                                                    const char * hostvendor,
220                                                    const char * hostname) {
221 struct roar_dl_lhandle * ret = NULL;
222 int i, j;
223 char path[1024];
224 const char * path_format[] = {"%s/%s/%s", "%s/%s/universal", "%s/universal/universal"};
225 DIR * dir;
226 struct dirent * dirent;
227 char file[1024];
228 const char * file_format[] = {"%s/%s/%s", "%s/%s/%s" ROAR_SHARED_SUFFIX, "%s/%s/lib%s" ROAR_SHARED_SUFFIX};
229//  cont->handle[idx] = roar_dl_open(name, ROAR_DL_FLAG_DEFAULTS, 1, para);
230//#vars: $PREFIX_PLUGINS, $hostvendor, $hostname, $name
231//#search order: $PREFIX_PLUGINS/{$hostvendor/{$hostname,universal},universal/universal}/*/{,lib}$name.so
232
233 for (i = 0; i < 3; i++) {
234  snprintf(path, sizeof(path), path_format[i], prefix, hostvendor, hostname);
235  dir = opendir(path);
236  if ( dir == NULL )
237   continue;
238
239  while ((dirent = readdir(dir)) != NULL) {
240   if ( !strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..") )
241    continue;
242
243   for (j = 0; j < 3; j++) {
244    snprintf(file, sizeof(file), file_format[j], path, dirent->d_name, name);
245    ret = roar_dl_open(file, flags, ra_init, para);
246    if ( ret != NULL ) {
247     closedir(dir);
248     return ret;
249    }
250   }
251  }
252
253  closedir(dir);
254 }
255
256 return NULL;
257}
258
259static struct roar_dl_lhandle * _load_from_path(const char * name, int flags, int ra_init,
260                                                struct roar_dl_librarypara * para) {
261 struct roar_dl_lhandle * ret = NULL;
262 char * host = NULL;
263 char * hostvendor_buffer = NULL;
264 char * hostvendor = NULL;
265 char * hostname = NULL;
266 char * c, * d;
267
268 if ( para != NULL && para->appname != NULL && para->appname[0] != 0 ) {
269  host = roar_mm_strdup(para->appname);
270
271  // if we are out of memory we will likely not pass the rest, so just return in error.
272  if ( host == NULL )
273   return NULL;
274
275  hostname = host;
276  c = strstr(host, "<");
277  if ( c != NULL ) {
278   while (c[-1] == ' ') c--;
279   *c = 0;
280   c++;
281   while (*c == ' ' || *c == '<') c++;
282   if ( *c ) {
283    d = strstr(c, ">");
284    if ( d != NULL )
285     *d = 0;
286
287    d = strstr(c, "/");
288    if ( d != NULL ) {
289     *d = '-';
290     hostvendor = c;
291    } else {
292     hostvendor_buffer = roar_mm_malloc(roar_mm_strlen(c) + 1 /* tailing \0 */ + 6 /* "unreg-" */);
293
294     // see above
295     if ( hostvendor_buffer == NULL ) {
296      roar_mm_free(host);
297      return NULL;
298     }
299
300     strcpy(hostvendor_buffer, "unreg-");
301     strcat(hostvendor_buffer, c);
302     hostvendor = hostvendor_buffer;
303    }
304   }
305  }
306 }
307
308 if ( hostvendor == NULL )
309  hostvendor = "universal";
310
311 if ( hostname == NULL )
312  hostname = "universal";
313
314 ret = _load_from_path_pvn(name, flags, ra_init, para, ROAR_PREFIX_PLUGINS, hostvendor, hostname);
315
316 if ( host != NULL )
317  roar_mm_free(host);
318 if ( hostvendor_buffer != NULL )
319  roar_mm_free(hostvendor_buffer);
320 return ret;
321}
322#endif
323
324static struct roar_dl_lhandle * _roar_dl_open_pluginpath(const char * filename, int flags,
325                                      int ra_init, struct roar_dl_librarypara * para) {
326 flags |= ROAR_DL_FLAG_PLUGINPATH;
327 flags -= ROAR_DL_FLAG_PLUGINPATH;
328
329#ifdef ROAR_HAVE_H_DIRENT
330 // do normal open for everything with a path name.
331 if ( strstr(filename, "/") != NULL )
332  return roar_dl_open(filename, flags, ra_init, para);
333
334 return _load_from_path(filename, flags, ra_init, para);
335#else
336 // fall back to system open function.
337 return roar_dl_open(filename, flags, ra_init, para);
338#endif
339}
340
341struct roar_dl_lhandle * roar_dl_open(const char * filename, int flags,
342                                      int ra_init, struct roar_dl_librarypara * para) {
343 struct roar_dl_lhandle * ret = NULL;
344#if defined(ROAR_HAVE_LIBDL)
345#ifdef RTLD_DEEPBIND
346 int libdl_flags = RTLD_DEEPBIND;
347#else
348 int libdl_flags = 0;
349#endif
350#endif
351 int err;
352
353 switch (flags) {
354  case ROAR_DL_FLAG_DEFAULTS: flags = ROAR_DL_FLAG_NONE;       break;
355  case ROAR_DL_FLAG_PLUGIN:   flags = ROAR_DL_FLAG_PLUGINPATH; break;
356 }
357
358 if ( flags & ROAR_DL_FLAG_PLUGINPATH )
359  return _roar_dl_open_pluginpath(filename, flags, ra_init, para);
360
361#if defined(ROAR_HAVE_LIBDL)
362 if ( flags & ROAR_DL_FLAG_LAZY ) {
363  libdl_flags |= RTLD_LAZY;
364 } else {
365  libdl_flags |= RTLD_NOW;
366 }
367#endif
368
369 if ( (ret = roar_mm_malloc(sizeof(struct roar_dl_lhandle))) == NULL )
370  return NULL;
371
372 memset(ret, 0, sizeof(struct roar_dl_lhandle));
373
374 roar_err_initstore(&(ret->context.error_state));
375
376 ret->flags = flags;
377 ret->refc  = 1;
378
379 if ( flags & ROAR_DL_FLAG_STATIC ) {
380  if ( filename == NULL ) {
381   ret->libname = NULL;
382  } else {
383   ret->libname = roar_mm_strdup(filename);
384  }
385 } else {
386#if defined(ROAR_HAVE_LIBDL)
387  ret->handle = dlopen(filename, libdl_flags);
388
389  if ( ret->handle == NULL ) {
390   ROAR_DBG("roar_dl_open(filename='%s', flags=%i, ra_init=%i, para=%p): Can not load library: %s", filename, flags, ra_init, para, roar_dl_errstr(ret));
391   roar_mm_free(ret);
392   return NULL;
393  }
394#elif defined(ROAR_TARGET_WIN32)
395  ret->handle = LoadLibrary(filename);
396
397  if ( ret->handle == NULL ) {
398   roar_mm_free(ret);
399   return NULL;
400  }
401#else
402  roar_mm_free(ret);
403  roar_err_set(ROAR_ERROR_NOSYS);
404  return NULL;
405#endif
406 }
407
408 ret->para = para;
409
410 if ( ra_init ) {
411  if ( roar_dl_ra_init(ret, NULL, para) == -1 ) {
412   err = roar_error;
413   ROAR_WARN("roar_dl_open(filename='%s', flags=%i, ra_init=%i, para=%p): Can not init RA lib: %s", filename, flags, ra_init, para, roar_error2str(err));
414#if defined(ROAR_HAVE_LIBDL)
415   if ( ret->handle != NULL )
416    dlclose(ret->handle);
417#elif defined(ROAR_TARGET_WIN32)
418   if ( ret->handle != NULL )
419    FreeLibrary(ret->handle);
420#endif
421   roar_mm_free(ret);
422   roar_error = err;
423   return NULL;
424  }
425 }
426
427 if ( para != NULL )
428  roar_dl_para_ref(para);
429
430 return ret;
431}
432
433int                      roar_dl_ref    (struct roar_dl_lhandle * lhandle) {
434 if ( (void*)lhandle < (void*)128 ) {
435  ROAR_DBG("roar_dl_ref(lhandle=%p) = -1 // error=BADFH", lhandle);
436  roar_err_set(ROAR_ERROR_BADFH);
437  return -1;
438 }
439
440 lhandle->refc++;
441
442 ROAR_DBG("roar_dl_ref(lhandle=%p) = 0", lhandle);
443 return 0;
444}
445
446int                      roar_dl_unref  (struct roar_dl_lhandle * lhandle) {
447 int ret = -1;
448
449 if ( (void*)lhandle < (void*)128 ) {
450  ROAR_DBG("roar_dl_unref(lhandle=%p) = -1 // error=BADFH", lhandle);
451  roar_err_set(ROAR_ERROR_BADFH);
452  return -1;
453 }
454
455 lhandle->refc--;
456
457 if ( lhandle->refc ) {
458  ROAR_DBG("roar_dl_unref(lhandle=%p) = 0", lhandle);
459  return 0;
460 }
461
462 if ( lhandle->lib != NULL && lhandle->lib->unload != NULL ) {
463  roar_dl_context_restore(lhandle);
464  lhandle->lib->unload(lhandle->para, lhandle->lib);
465  roar_dl_context_store(lhandle);
466 }
467
468#if defined(ROAR_HAVE_LIBDL)
469 if ( lhandle->handle == NULL ) {
470  ret = 0;
471 } else {
472  ret = dlclose(_roardl2ldl(lhandle));
473 }
474#elif defined(ROAR_TARGET_WIN32)
475 if ( lhandle->handle == NULL ) {
476  ret = 0;
477 } else {
478  if ( FreeLibrary(_roardl2winhandle(lhandle)) ) {
479   ret = 0;
480  } else {
481   ret = -1;
482  }
483 }
484#else
485 ret = -1;
486#endif
487
488 if ( lhandle->context.global_data != NULL )
489  roar_mm_free(lhandle->context.global_data);
490
491 if ( lhandle->para != NULL )
492  roar_dl_para_unref(lhandle->para);
493
494 if ( lhandle->libname != NULL )
495  roar_mm_free(lhandle->libname);
496
497 roar_mm_free(lhandle);
498
499 ROAR_DBG("roar_dl_unref(lhandle=%p) = %i", lhandle, ret);
500 return ret;
501}
502
503void                   * roar_dl_getsym(struct roar_dl_lhandle * lhandle, const char * sym, int type) {
504#if defined(ROAR_HAVE_LIBDL)
505 void * ret = dlsym(_roardl2ldl(lhandle), sym);
506
507 (void)type;
508
509 ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i): errno=%s, dlerror()='%s'", lhandle, sym, type, ret, strerror(errno), dlerror());
510 ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i) = %p", lhandle, sym, type, ret);
511
512 return ret;
513#elif defined(ROAR_TARGET_WIN32)
514 FARPROC ret = GetProcAddress(_roardl2winhandle(lhandle), sym);
515 return (void*)ret;
516#else
517 ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i) = NULL // errno=NOSYS", lhandle, sym, type, ret);
518 roar_err_set(ROAR_ERROR_NOSYS);
519 return NULL;
520#endif
521}
522
523int                      roar_dl_ra_init(struct roar_dl_lhandle * lhandle,
524                                         const char * prefix,
525                                         struct roar_dl_librarypara * para) {
526#define _SUFFIX "_roaraudio_library_init"
527 char name[80] = _SUFFIX;
528 struct roar_dl_libraryinst * (*func)(struct roar_dl_librarypara * para);
529 struct roar_dl_libraryinst * lib;
530 struct roar_dl_lhandle     * getsymhandle = lhandle;
531 void * global_data_state = NULL;
532 int i;
533
534 if ( (void*)lhandle < (void*)128 ) {
535  if ( prefix == NULL )
536   return -1;
537 } else {
538  if ( lhandle->ra_inited )
539   return 0;
540
541  if ( prefix == NULL )
542   prefix = lhandle->libname;
543
544  if ( para == NULL )
545   para = lhandle->para;
546
547  if ( lhandle->flags & ROAR_DL_FLAG_STATIC )
548   getsymhandle = ROAR_DL_HANDLE_DEFAULT;
549 }
550
551
552 if ( prefix != NULL ) {
553  roar_mm_strscpy(name, "_");
554  roar_mm_strscat(name, prefix);
555  roar_mm_strscat(name, _SUFFIX);
556 }
557
558 ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s'): name='%s'", lhandle, prefix, name);
559
560 if ( (func = roar_dl_getsym(getsymhandle, name, -1)) == NULL ) {
561  ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s') = -1", lhandle, prefix);
562  return -1;
563 }
564
565 ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s'): func=%p", lhandle, prefix, func);
566
567 lib = func(para);
568
569 if ( lib == NULL )
570  return -1;
571
572 if ( lib->version != ROAR_DL_LIBINST_VERSION )
573  return -1;
574
575 if ( sizeof(struct roar_dl_libraryinst) > lib->len )
576  return -1;
577
578 if ( lib->host_appname != NULL || lib->host_abiversion != NULL ) {
579  // check for correct host.
580  if ( para == NULL ) {
581   roar_err_set(ROAR_ERROR_INVAL);
582   return -1;
583  }
584  if ( roar_dl_para_check_version(para, lib->host_appname, lib->host_abiversion) == -1 )
585   return -1;
586 }
587
588 if ( (lib->libdep == NULL && lib->libdep_len) || (lib->libdep != NULL && !lib->libdep_len) ) {
589  roar_err_set(ROAR_ERROR_BADLIB);
590  return -1;
591 }
592
593 if ( lib->libdep != NULL && lib->libdep_len ) {
594  // dynamic loader infos are currently not supported.
595  roar_err_set(ROAR_ERROR_NOTSUP);
596  return -1;
597 }
598
599 if ( !((void*)lhandle < (void*)128) ) {
600  lhandle->lib = lib;
601
602  if ( lib->global_data_len ) {
603   lhandle->context.global_data = roar_mm_malloc(lib->global_data_len);
604   if ( lhandle->context.global_data == NULL )
605    return -1;
606
607   if ( lib->global_data_init == NULL ) {
608    memset(lhandle->context.global_data, 0, lib->global_data_len);
609   } else {
610    memcpy(lhandle->context.global_data, lib->global_data_init, lib->global_data_len);
611   }
612  }
613 }
614
615 if ( lib->global_data_pointer != NULL ) {
616  global_data_state = *(lib->global_data_pointer);
617  if ( (void*)lhandle < (void*)128 ) {
618   *(lib->global_data_pointer) = lib->global_data_init;
619  } else {
620   *(lib->global_data_pointer) = lhandle->context.global_data;
621  }
622 }
623
624 for (i = 0; i < ROAR_DL_FN_MAX; i++) {
625  if ( lib->func[i] != NULL )
626   lib->func[i](para, lib);
627 }
628
629 if ( lib->global_data_pointer != NULL ) {
630  if ( !((void*)lhandle < (void*)128) ) {
631   *(lib->global_data_pointer) = global_data_state;
632  }
633 }
634
635 if ( !((void*)lhandle < (void*)128) )
636  lhandle->ra_inited = 1;
637
638 return 0;
639}
640
641const char * roar_dl_errstr(struct roar_dl_lhandle * lhandle) {
642#if defined(ROAR_HAVE_LIBDL)
643 (void)lhandle;
644 return dlerror();
645#elif defined(ROAR_TARGET_WIN32)
646 roar_err_from_errno();
647 return roar_error2str(roar_error);
648#else
649 return NULL;
650#endif
651}
652
653struct roar_dl_librarypara       * roar_dl_getpara(struct roar_dl_lhandle * lhandle) {
654 if ( (void*)lhandle < (void*)128 ) {
655  roar_err_set(ROAR_ERROR_NOTSUP);
656  return NULL;
657 }
658
659 if ( lhandle->para == NULL ) {
660  roar_err_set(ROAR_ERROR_NOENT);
661  return NULL;
662 }
663
664 if ( roar_dl_para_ref(lhandle->para) == -1 )
665  return NULL;
666
667 return lhandle->para;
668}
669
670const struct roar_dl_libraryname * roar_dl_getlibname(struct roar_dl_lhandle * lhandle) {
671 if ( (void*)lhandle < (void*)128 ) {
672  roar_err_set(ROAR_ERROR_NOTSUP);
673  return NULL;
674 }
675
676 if ( lhandle->lib == NULL ) {
677  roar_err_set(ROAR_ERROR_BADLIB);
678  return NULL;
679 }
680
681 if ( lhandle->lib->libname == NULL ) {
682  roar_err_set(ROAR_ERROR_NOENT);
683  return NULL;
684 }
685
686 if ( lhandle->lib->libname->version != ROAR_DL_LIBNAME_VERSION ) {
687  roar_err_set(ROAR_ERROR_BADVERSION);
688  return NULL;
689 }
690
691 if ( lhandle->lib->libname->len != sizeof(struct roar_dl_libraryname) ) {
692  roar_err_set(ROAR_ERROR_HOLE);
693  return NULL;
694 }
695
696 return lhandle->lib->libname;
697}
698
699int                      roar_dl_context_restore(struct roar_dl_lhandle * lhandle) {
700 struct roar_error_state error_state;
701
702 ROAR_DBG("roar_dl_context_restore(lhandle=%p) = ?", lhandle);
703
704 if ( (void*)lhandle < (void*)128 ) {
705  ROAR_DBG("roar_dl_context_restore(lhandle=%p) = -1 // errno=NOTSUP", lhandle);
706  roar_err_set(ROAR_ERROR_NOTSUP);
707  return -1;
708 }
709
710 roar_err_store(&error_state);
711 roar_err_restore(&(lhandle->context.error_state));
712 lhandle->context.error_state = error_state;
713
714 if ( lhandle->lib->global_data_pointer != NULL ) {
715  ROAR_DBG("roar_dl_context_restore(lhandle=%p): gptr(%p): %p -> %p", lhandle,
716           lhandle->lib->global_data_pointer, *(lhandle->lib->global_data_pointer), lhandle->context.global_data);
717  lhandle->context.global_data_state = *(lhandle->lib->global_data_pointer);
718  *(lhandle->lib->global_data_pointer) = lhandle->context.global_data;
719 }
720
721 if ( lhandle->para->notifycore != NULL )
722  lhandle->context.notifycore = roar_notify_core_swap_global(lhandle->para->notifycore);
723
724 ROAR_DBG("roar_dl_context_restore(lhandle=%p) = 0", lhandle);
725 return 0;
726}
727
728int                      roar_dl_context_store(struct roar_dl_lhandle * lhandle) {
729 struct roar_error_state error_state;
730
731 ROAR_DBG("roar_dl_context_store(lhandle=%p) = ?", lhandle);
732
733 if ( (void*)lhandle < (void*)128 ) {
734  ROAR_DBG("roar_dl_context_store(lhandle=%p) = -1 // errno=NOTSUP", lhandle);
735  roar_err_set(ROAR_ERROR_NOTSUP);
736  return -1;
737 }
738
739 if ( lhandle->para->notifycore != NULL ) {
740  roar_notify_core_unref(roar_notify_core_swap_global(lhandle->context.notifycore));
741  roar_notify_core_unref(lhandle->context.notifycore);
742  lhandle->context.notifycore = NULL;
743 }
744
745 if ( lhandle->lib->global_data_pointer != NULL ) {
746  ROAR_DBG("roar_dl_context_store(lhandle=%p): gptr(%p): %p -> %p", lhandle,
747           lhandle->lib->global_data_pointer, *(lhandle->lib->global_data_pointer), lhandle->context.global_data_state);
748  *(lhandle->lib->global_data_pointer) = lhandle->context.global_data_state;
749 }
750
751 roar_err_store(&error_state);
752 roar_err_restore(&(lhandle->context.error_state));
753 lhandle->context.error_state = error_state;
754
755 ROAR_DBG("roar_dl_context_store(lhandle=%p) = 0", lhandle);
756 return 0;
757}
758
759int                      roar_dl_appsched_trigger(struct roar_dl_lhandle * lhandle, enum roar_dl_appsched_trigger trigger) {
760 int (*func)  (struct roar_dl_librarypara * para) = NULL;
761 int ret;
762
763 if ( (void*)lhandle < (void*)128 ) {
764  roar_err_set(ROAR_ERROR_NOTSUP);
765  return -1;
766 }
767
768 if ( lhandle->lib == NULL ) {
769  roar_err_set(ROAR_ERROR_TYPEMM);
770  return -1;
771 }
772
773 if ( lhandle->lib->appsched == NULL ) {
774  roar_err_set(ROAR_ERROR_NOENT);
775  return -1;
776 }
777
778 switch (trigger) {
779#define _trig(lname,uname) \
780  case ROAR_DL_APPSCHED_ ## uname :             \
781    func = lhandle->lib->appsched->lname;       \
782   break;
783  _trig(init, INIT);
784  _trig(free, FREE);
785  _trig(update, UPDATE);
786  _trig(tick, TICK);
787  _trig(wait, WAIT);
788// use ifndef here so warnings of unhandled enum values will be shown in DEBUG mode.
789#ifndef DEBUG
790  default:
791    roar_err_set(ROAR_ERROR_BADRQC);
792    return -1;
793   break;
794#endif
795 }
796
797 if ( func == NULL ) {
798  roar_err_set(ROAR_ERROR_NOENT);
799  return -1;
800 }
801
802 roar_dl_context_restore(lhandle);
803 ret = func(lhandle->para);
804 roar_dl_context_store(lhandle);
805 return ret;
806}
807
808//ll
Note: See TracBrowser for help on using the repository browser.