2018-01-07 20:54:41 +00:00
|
|
|
/* radare - LGPL - Copyright 2008-2018 - pancake */
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
|
|
#include "r_types.h"
|
2010-06-03 08:57:34 +00:00
|
|
|
#include "r_util.h"
|
2009-02-05 21:08:46 +00:00
|
|
|
#include "r_lib.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2013-06-15 00:56:25 +00:00
|
|
|
R_LIB_VERSION(r_lib);
|
|
|
|
|
2009-02-05 21:08:46 +00:00
|
|
|
/* TODO: support for nested plugins ?? here */
|
|
|
|
|
|
|
|
#if __UNIX__
|
|
|
|
#include <dlfcn.h>
|
2018-04-21 16:12:44 +00:00
|
|
|
#define DLOPEN(x) dlopen(x, RTLD_GLOBAL | RTLD_LAZY)
|
2009-02-05 21:08:46 +00:00
|
|
|
#define DLSYM(x,y) dlsym(x,y)
|
|
|
|
#define DLCLOSE(x) dlclose(x)
|
2010-04-12 00:22:52 +00:00
|
|
|
#elif __WINDOWS__
|
2009-02-05 21:08:46 +00:00
|
|
|
#include <windows.h>
|
2017-10-30 11:28:59 +00:00
|
|
|
#define DLOPEN(x) LoadLibrary(x)
|
2009-02-05 21:08:46 +00:00
|
|
|
#define DLSYM(x,y) GetProcAddress(x,y)
|
2010-01-15 12:02:54 +00:00
|
|
|
#define DLCLOSE(x) 0//(x)
|
|
|
|
//CloseLibrary(x)
|
2009-02-05 21:08:46 +00:00
|
|
|
#else
|
|
|
|
#define DLOPEN(x) NULL
|
|
|
|
#define DLSYM(x,y) NULL
|
|
|
|
#define DLCLOSE(x) NULL
|
|
|
|
#endif
|
|
|
|
|
2009-09-17 09:48:36 +00:00
|
|
|
/* XXX : this must be registered in runtime */
|
|
|
|
static const char *r_lib_types[] = {
|
2016-02-23 12:10:35 +00:00
|
|
|
"io", "dbg", "lang", "asm", "anal", "parse", "bin", "bin_xtr",
|
|
|
|
"bp", "syscall", "fastcall", "crypto", "core", "egg", "fs", NULL
|
2009-04-01 00:28:13 +00:00
|
|
|
};
|
|
|
|
|
2013-04-08 07:38:23 +00:00
|
|
|
static int __has_debug = 0;
|
|
|
|
|
|
|
|
#define IFDBG if(__has_debug)
|
2010-06-03 08:57:34 +00:00
|
|
|
|
2009-09-17 09:48:36 +00:00
|
|
|
/* XXX: Rename this helper function */
|
2010-04-12 00:22:52 +00:00
|
|
|
R_API const char *r_lib_types_get(int idx) {
|
2016-07-30 12:15:29 +00:00
|
|
|
if (idx < 0 || idx > R_LIB_TYPE_LAST - 1) {
|
2009-04-01 01:46:37 +00:00
|
|
|
return "unk";
|
2016-07-30 12:15:29 +00:00
|
|
|
}
|
2009-04-01 01:46:37 +00:00
|
|
|
return r_lib_types[idx];
|
2009-04-01 01:40:04 +00:00
|
|
|
}
|
|
|
|
|
2014-07-30 09:12:58 +00:00
|
|
|
R_API int r_lib_types_get_i(const char *str) {
|
|
|
|
int i;
|
2016-07-30 12:15:29 +00:00
|
|
|
for (i = 0; r_lib_types[i]; i++) {
|
|
|
|
if (!strcmp (str, r_lib_types[i])) {
|
2014-07-30 09:12:58 +00:00
|
|
|
return i;
|
2016-07-30 12:15:29 +00:00
|
|
|
}
|
2014-07-30 09:12:58 +00:00
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-04-12 00:22:52 +00:00
|
|
|
R_API void *r_lib_dl_open(const char *libname) {
|
2009-03-31 00:50:02 +00:00
|
|
|
void *ret;
|
2016-07-30 12:15:29 +00:00
|
|
|
#if __UNIX__
|
|
|
|
if (!libname) {
|
|
|
|
return dlopen (NULL, RTLD_NOW);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (!libname || !*libname) {
|
2014-06-16 03:58:00 +00:00
|
|
|
return NULL;
|
2016-07-30 12:15:29 +00:00
|
|
|
}
|
2017-10-30 11:28:59 +00:00
|
|
|
#if __WINDOWS__
|
|
|
|
LPTSTR libname_;
|
|
|
|
|
2017-11-02 13:17:41 +00:00
|
|
|
libname_ = r_sys_conv_utf8_to_utf16 (libname);
|
2017-10-30 11:28:59 +00:00
|
|
|
ret = DLOPEN (libname_);
|
|
|
|
#else
|
2010-04-12 00:22:52 +00:00
|
|
|
ret = DLOPEN (libname);
|
2017-10-30 11:28:59 +00:00
|
|
|
#endif
|
2016-09-19 12:44:47 +00:00
|
|
|
if (__has_debug && !ret) {
|
2010-01-15 12:02:54 +00:00
|
|
|
#if __UNIX__
|
2010-06-03 08:57:34 +00:00
|
|
|
eprintf ("dlerror(%s): %s\n", libname, dlerror ());
|
2010-01-15 12:02:54 +00:00
|
|
|
#else
|
|
|
|
eprintf ("r_lib_dl_open: Cannot open '%s'\n", libname);
|
|
|
|
#endif
|
2016-07-30 12:15:29 +00:00
|
|
|
}
|
2017-10-30 11:28:59 +00:00
|
|
|
#if __WINDOWS__
|
|
|
|
free (libname_);
|
|
|
|
#endif
|
2009-02-05 21:08:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-05-26 16:25:35 +00:00
|
|
|
R_API void *r_lib_dl_sym(void *handler, const char *name) {
|
|
|
|
return DLSYM (handler, name);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-05-26 16:25:35 +00:00
|
|
|
R_API int r_lib_dl_close(void *handler) {
|
2017-05-24 10:17:20 +00:00
|
|
|
int ret = -1;
|
|
|
|
if (handler) {
|
|
|
|
ret = DLCLOSE (handler);
|
|
|
|
}
|
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ---- */
|
|
|
|
|
2011-08-27 18:25:37 +00:00
|
|
|
R_API char *r_lib_path(const char *libname) {
|
|
|
|
char *next, *path0, libpath[1024];
|
|
|
|
#if __APPLE__
|
|
|
|
char *env = r_sys_getenv ("DYLD_LIBRARY_PATH");
|
|
|
|
const char *ext = ".dylib";
|
2017-03-16 21:29:49 +00:00
|
|
|
env = r_str_append (env, ":/lib:/usr/lib:/usr/local/lib");
|
2011-08-27 18:25:37 +00:00
|
|
|
#elif __UNIX__
|
|
|
|
char *env = r_sys_getenv ("LD_LIBRARY_PATH");
|
|
|
|
const char *ext = ".so";
|
2017-03-16 21:29:49 +00:00
|
|
|
env = r_str_append (env, ":/lib:/usr/lib:/usr/local/lib");
|
2011-08-27 18:25:37 +00:00
|
|
|
#else
|
|
|
|
char *env = strdup (".:../../../../../../../windows/system32");
|
|
|
|
const char *ext = ".dll";
|
|
|
|
#endif
|
|
|
|
if (!env) env = strdup (".");
|
|
|
|
path0 = env;
|
|
|
|
do {
|
|
|
|
next = strchr (path0, ':');
|
|
|
|
if (next) *next = 0;
|
|
|
|
snprintf (libpath, sizeof (libpath), "%s/%s%s", path0, libname, ext);
|
|
|
|
//eprintf ("--> %s\n", libpath);
|
2012-09-06 06:59:13 +00:00
|
|
|
if (r_file_exists (libpath)) {
|
2011-08-27 18:25:37 +00:00
|
|
|
free (env);
|
|
|
|
return strdup (libpath);
|
|
|
|
}
|
|
|
|
path0 = next+1;
|
|
|
|
} while (next);
|
|
|
|
free (env);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-05-20 15:40:58 +00:00
|
|
|
R_API RLib *r_lib_new(const char *symname) {
|
2011-05-13 08:22:28 +00:00
|
|
|
RLib *lib = R_NEW (RLib);
|
2014-03-08 06:41:22 +00:00
|
|
|
char *env_debug;
|
2009-09-17 09:48:36 +00:00
|
|
|
if (lib) {
|
2014-03-08 06:41:22 +00:00
|
|
|
env_debug = r_sys_getenv ("R_DEBUG");
|
2016-07-12 20:15:19 +00:00
|
|
|
__has_debug = env_debug ? true : false;
|
2014-03-08 06:41:22 +00:00
|
|
|
if (env_debug) {
|
|
|
|
free (env_debug);
|
|
|
|
}
|
2013-11-17 10:25:45 +00:00
|
|
|
lib->handlers = r_list_newf (free);
|
|
|
|
lib->plugins = r_list_newf (free);
|
2010-04-12 00:22:52 +00:00
|
|
|
strncpy (lib->symname, symname, sizeof (lib->symname)-1);
|
2009-09-17 09:48:36 +00:00
|
|
|
}
|
|
|
|
return lib;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-04-12 00:22:52 +00:00
|
|
|
R_API RLib *r_lib_free(RLib *lib) {
|
2017-09-25 14:05:42 +00:00
|
|
|
if (!lib) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-04-12 00:22:52 +00:00
|
|
|
r_lib_close (lib, NULL);
|
2013-11-17 10:25:45 +00:00
|
|
|
r_list_free (lib->handlers);
|
|
|
|
r_list_free (lib->plugins);
|
2009-02-05 21:08:46 +00:00
|
|
|
free (lib);
|
2009-09-17 09:48:36 +00:00
|
|
|
return NULL;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* THIS IS WRONG */
|
2010-04-12 00:22:52 +00:00
|
|
|
R_API int r_lib_dl_check_filename(const char *file) {
|
2016-05-02 00:46:01 +00:00
|
|
|
return (strstr (file, "."R_LIB_EXT)) != NULL;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* high level api */
|
|
|
|
|
2010-04-12 00:22:52 +00:00
|
|
|
R_API int r_lib_run_handler(RLib *lib, RLibPlugin *plugin, RLibStruct *symbol) {
|
|
|
|
RLibHandler *h = plugin->handler;
|
2014-03-26 00:34:32 +00:00
|
|
|
if (h && h->constructor) {
|
2017-07-26 14:35:27 +00:00
|
|
|
IFDBG eprintf ("PLUGIN OK %p fcn %p\n", h, h->constructor);
|
2011-10-08 21:39:06 +00:00
|
|
|
return h->constructor (plugin, h->user, symbol->data);
|
2017-07-26 14:35:27 +00:00
|
|
|
}
|
|
|
|
IFDBG eprintf ("Cannot find plugin constructor\n");
|
2009-09-17 09:48:36 +00:00
|
|
|
return R_FAIL;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-04-12 00:22:52 +00:00
|
|
|
R_API RLibHandler *r_lib_get_handler(RLib *lib, int type) {
|
2011-05-13 08:22:28 +00:00
|
|
|
RLibHandler *h;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (lib->handlers, iter, h) {
|
2009-09-17 09:48:36 +00:00
|
|
|
if (h->type == type)
|
2009-02-05 21:08:46 +00:00
|
|
|
return h;
|
|
|
|
}
|
2009-09-17 09:48:36 +00:00
|
|
|
return NULL;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2017-05-09 21:53:20 +00:00
|
|
|
R_API int r_lib_close(RLib *lib, const char *file) {
|
2011-05-13 08:22:28 +00:00
|
|
|
RLibPlugin *p;
|
2015-08-29 07:36:42 +00:00
|
|
|
RListIter *iter, *iter_tmp;
|
|
|
|
r_list_foreach_safe (lib->plugins, iter, iter_tmp, p) {
|
2014-07-29 22:33:54 +00:00
|
|
|
if ((file==NULL || (!strcmp (file, p->file)))) {
|
|
|
|
int ret = 0;
|
2017-07-23 21:35:45 +00:00
|
|
|
if (p->handler && p->handler->destructor) {
|
|
|
|
ret = p->handler->destructor (p, p->handler->user, p->data);
|
|
|
|
}
|
|
|
|
if (p->free) {
|
|
|
|
p->free (p->data);
|
2014-07-29 22:33:54 +00:00
|
|
|
}
|
|
|
|
free (p->file);
|
|
|
|
r_list_delete (lib->plugins, iter);
|
2015-08-29 07:36:42 +00:00
|
|
|
if (file != NULL) {
|
|
|
|
return ret;
|
|
|
|
}
|
2014-07-29 22:33:54 +00:00
|
|
|
}
|
|
|
|
}
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!file) {
|
2015-08-29 07:36:42 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2014-07-29 22:33:54 +00:00
|
|
|
// delete similar plugin name
|
|
|
|
r_list_foreach (lib->plugins, iter, p) {
|
|
|
|
if (strstr (p->file, file)) {
|
|
|
|
int ret = 0;
|
2017-07-23 21:35:45 +00:00
|
|
|
if (p->handler && p->handler->destructor) {
|
2014-07-29 22:33:54 +00:00
|
|
|
ret = p->handler->destructor (p,
|
|
|
|
p->handler->user, p->data);
|
|
|
|
}
|
|
|
|
eprintf ("Unloaded %s\n", p->file);
|
2011-05-13 08:22:28 +00:00
|
|
|
free (p->file);
|
|
|
|
r_list_delete (lib->plugins, iter);
|
2009-02-05 21:08:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-04-01 00:28:13 +00:00
|
|
|
// XXX ugly hack ?
|
2010-04-12 00:22:52 +00:00
|
|
|
static int samefile(const char *a, const char *b) {
|
2011-11-14 21:46:23 +00:00
|
|
|
char *sa = strdup (a);
|
|
|
|
char *sb = strdup (b);
|
2009-04-01 00:28:13 +00:00
|
|
|
char *ptr;
|
2016-07-12 20:15:19 +00:00
|
|
|
int len, ret = false;
|
2009-04-01 00:28:13 +00:00
|
|
|
|
2009-04-02 00:07:58 +00:00
|
|
|
if (sa != NULL && sb != NULL) {
|
|
|
|
do {
|
2013-11-28 04:51:09 +00:00
|
|
|
ptr = strstr (sa, "//");
|
2010-11-20 17:35:40 +00:00
|
|
|
if (ptr) {
|
|
|
|
len = strlen (ptr+1) + 1;
|
|
|
|
memmove (ptr, ptr+1, len);
|
|
|
|
}
|
2011-10-08 21:39:06 +00:00
|
|
|
} while (ptr);
|
2009-04-02 00:07:58 +00:00
|
|
|
do {
|
2013-11-28 04:51:09 +00:00
|
|
|
ptr = strstr (sb, "//");
|
2010-11-20 17:35:40 +00:00
|
|
|
if (ptr) {
|
|
|
|
len = strlen (ptr+1) + 1;
|
|
|
|
memmove (ptr, ptr+1, len);
|
|
|
|
}
|
2011-05-13 08:22:28 +00:00
|
|
|
} while (ptr);
|
2016-07-12 20:15:19 +00:00
|
|
|
ret = strcmp (sa,sb)? false: true;
|
2009-04-02 00:07:58 +00:00
|
|
|
}
|
2009-04-01 00:28:13 +00:00
|
|
|
|
2011-05-13 08:22:28 +00:00
|
|
|
free (sa);
|
|
|
|
free (sb);
|
2009-04-01 00:28:13 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-04-12 00:22:52 +00:00
|
|
|
R_API int r_lib_open(RLib *lib, const char *file) {
|
|
|
|
RLibStruct *stru;
|
2011-10-08 21:39:06 +00:00
|
|
|
void *handler;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
|
|
/* ignored by filename */
|
2010-04-12 00:22:52 +00:00
|
|
|
if (!r_lib_dl_check_filename (file)) {
|
|
|
|
eprintf ("Invalid library extension: %s\n", file);
|
2009-09-17 09:48:36 +00:00
|
|
|
return R_FAIL;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-04-12 00:22:52 +00:00
|
|
|
handler = r_lib_dl_open (file);
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!handler) {
|
2010-04-12 00:22:52 +00:00
|
|
|
IFDBG eprintf ("Cannot open library: '%s'\n", file);
|
2009-09-17 09:48:36 +00:00
|
|
|
return R_FAIL;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2014-04-25 01:01:42 +00:00
|
|
|
|
2010-04-12 00:22:52 +00:00
|
|
|
stru = (RLibStruct *) r_lib_dl_sym (handler, lib->symname);
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!stru) {
|
2013-04-08 07:38:23 +00:00
|
|
|
IFDBG eprintf ("Cannot find symbol '%s' in library '%s'\n",
|
|
|
|
lib->symname, file);
|
2014-04-25 01:01:42 +00:00
|
|
|
r_lib_dl_close (handler);
|
2009-09-17 09:48:36 +00:00
|
|
|
return R_FAIL;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2009-09-17 09:48:36 +00:00
|
|
|
|
2014-07-30 09:12:58 +00:00
|
|
|
return r_lib_open_ptr (lib, file, handler, stru);
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_lib_open_ptr (RLib *lib, const char *file, void *handler, RLibStruct *stru) {
|
|
|
|
RLibPlugin *p;
|
|
|
|
RListIter *iter;
|
2016-07-12 20:15:19 +00:00
|
|
|
int ret = false;
|
2015-06-21 08:09:12 +00:00
|
|
|
|
2017-05-23 22:33:43 +00:00
|
|
|
if (!lib || !file || !stru) {
|
2017-05-23 13:25:34 +00:00
|
|
|
return R_FAIL;
|
|
|
|
}
|
2015-06-21 08:09:12 +00:00
|
|
|
if (stru->version) {
|
|
|
|
if (strcmp (stru->version, R2_VERSION)) {
|
2017-01-29 14:25:14 +00:00
|
|
|
eprintf ("Module version mismatch %s (%s) vs (%s)\n",
|
|
|
|
file, stru->version, R2_VERSION);
|
2015-06-21 08:09:12 +00:00
|
|
|
return R_FAIL;
|
|
|
|
}
|
|
|
|
}
|
2014-03-26 00:34:32 +00:00
|
|
|
// TODO: Use Sdb here. just a single line
|
2017-05-24 10:17:20 +00:00
|
|
|
if (handler) {
|
|
|
|
r_list_foreach (lib->plugins, iter, p) {
|
|
|
|
if (samefile (file, p->file)) {
|
|
|
|
IFDBG eprintf ("Dupped\n");
|
|
|
|
// TODO: reload if opening again?
|
|
|
|
// TODO: store timestamp of file
|
|
|
|
// TODO: autoreload plugins if updated \o/
|
2017-05-23 22:33:43 +00:00
|
|
|
r_lib_dl_close (handler);
|
2017-05-24 10:17:20 +00:00
|
|
|
return R_FAIL;
|
2017-05-23 22:33:43 +00:00
|
|
|
}
|
2009-04-01 00:28:13 +00:00
|
|
|
}
|
|
|
|
}
|
2009-09-17 09:48:36 +00:00
|
|
|
|
2014-07-29 22:33:54 +00:00
|
|
|
p = R_NEW0 (RLibPlugin);
|
2009-02-05 21:08:46 +00:00
|
|
|
p->type = stru->type;
|
|
|
|
p->data = stru->data;
|
2011-05-13 08:22:28 +00:00
|
|
|
p->file = strdup (file);
|
2009-02-05 21:08:46 +00:00
|
|
|
p->dl_handler = handler;
|
2011-05-13 08:22:28 +00:00
|
|
|
p->handler = r_lib_get_handler (lib, p->type);
|
2017-07-23 21:35:45 +00:00
|
|
|
p->free = stru->free;
|
2014-04-25 01:01:42 +00:00
|
|
|
|
2011-05-13 08:22:28 +00:00
|
|
|
ret = r_lib_run_handler (lib, p, stru);
|
2009-09-17 09:48:36 +00:00
|
|
|
if (ret == R_FAIL) {
|
2010-06-03 08:57:34 +00:00
|
|
|
IFDBG eprintf ("Library handler has failed for '%s'\n", file);
|
|
|
|
free (p->file);
|
|
|
|
free (p);
|
2017-05-24 10:17:20 +00:00
|
|
|
r_lib_dl_close (handler);
|
2011-05-13 08:22:28 +00:00
|
|
|
} else r_list_append (lib->plugins, p);
|
2009-09-17 09:48:36 +00:00
|
|
|
|
2009-02-05 21:08:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-04-12 00:22:52 +00:00
|
|
|
R_API int r_lib_opendir(RLib *lib, const char *path) {
|
2017-04-11 15:13:46 +00:00
|
|
|
#if __WINDOWS__ && !defined(__CYGWIN__)
|
|
|
|
wchar_t file[1024];
|
|
|
|
WIN32_FIND_DATAW dir;
|
|
|
|
HANDLE fh;
|
|
|
|
wchar_t directory[MAX_PATH];
|
|
|
|
wchar_t *wcpath;
|
|
|
|
char *wctocbuff;
|
|
|
|
#else
|
2009-02-05 21:08:46 +00:00
|
|
|
char file[1024];
|
|
|
|
struct dirent *de;
|
2009-03-10 01:49:24 +00:00
|
|
|
DIR *dh;
|
2017-04-11 15:13:46 +00:00
|
|
|
#endif
|
2009-03-10 21:58:00 +00:00
|
|
|
#ifdef LIBR_PLUGINS
|
2017-04-11 15:13:46 +00:00
|
|
|
if (!path) {
|
2009-03-10 21:58:00 +00:00
|
|
|
path = LIBR_PLUGINS;
|
2017-04-11 15:13:46 +00:00
|
|
|
}
|
2009-03-10 21:58:00 +00:00
|
|
|
#endif
|
2017-04-11 15:13:46 +00:00
|
|
|
if (!path) {
|
2016-07-12 20:15:19 +00:00
|
|
|
return false;
|
2017-04-11 15:13:46 +00:00
|
|
|
}
|
|
|
|
#if __WINDOWS__ && !defined(__CYGWIN__)
|
2017-04-15 11:07:33 +00:00
|
|
|
wcpath = r_utf8_to_utf16 (path);
|
2017-04-11 15:13:46 +00:00
|
|
|
if (!wcpath) {
|
|
|
|
return false;
|
2017-09-17 22:06:23 +00:00
|
|
|
|
2017-04-11 15:13:46 +00:00
|
|
|
}
|
2017-09-17 22:06:23 +00:00
|
|
|
#if __MINGW32__
|
|
|
|
swprintf (directory, L"%ls\\*.*", wcpath);
|
|
|
|
#else
|
2017-07-23 21:35:45 +00:00
|
|
|
swprintf (directory, sizeof (directory), L"%ls\\*.*", wcpath);
|
2017-09-17 22:06:23 +00:00
|
|
|
#endif
|
2017-04-11 15:13:46 +00:00
|
|
|
fh = FindFirstFileW (directory, &dir);
|
|
|
|
if (fh == INVALID_HANDLE_VALUE) {
|
|
|
|
IFDBG eprintf ("Cannot open directory %ls\n", wcpath);
|
|
|
|
free (wcpath);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
do {
|
2017-09-17 22:06:23 +00:00
|
|
|
#if __MINGW32__
|
|
|
|
swprintf (file, L"%ls/%ls", wcpath, dir.cFileName);
|
|
|
|
#else
|
2017-04-11 15:13:46 +00:00
|
|
|
swprintf (file, sizeof (file), L"%ls/%ls", wcpath, dir.cFileName);
|
2017-09-17 22:06:23 +00:00
|
|
|
#endif
|
2017-04-15 11:07:33 +00:00
|
|
|
wctocbuff = r_utf16_to_utf8 (file);
|
2017-04-11 15:13:46 +00:00
|
|
|
if (wctocbuff) {
|
|
|
|
if (r_lib_dl_check_filename (wctocbuff)) {
|
|
|
|
r_lib_open (lib, wctocbuff);
|
|
|
|
} else {
|
|
|
|
IFDBG eprintf ("Cannot open %ls\n", dir.cFileName);
|
|
|
|
}
|
|
|
|
free (wctocbuff);
|
|
|
|
}
|
|
|
|
} while (FindNextFileW (fh, &dir));
|
|
|
|
FindClose (fh);
|
|
|
|
free (wcpath);
|
|
|
|
#else
|
2010-04-12 00:22:52 +00:00
|
|
|
dh = opendir (path);
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!dh) {
|
2010-04-12 00:22:52 +00:00
|
|
|
IFDBG eprintf ("Cannot open directory '%s'\n", path);
|
2016-07-12 20:15:19 +00:00
|
|
|
return false;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2010-06-03 08:57:34 +00:00
|
|
|
while ((de = (struct dirent *)readdir (dh))) {
|
2017-07-27 21:06:03 +00:00
|
|
|
if (de->d_name[0] == '.' || strstr (de->d_name, ".dSYM")) {
|
2017-07-26 14:35:27 +00:00
|
|
|
continue;
|
|
|
|
}
|
2010-04-12 00:22:52 +00:00
|
|
|
snprintf (file, sizeof (file), "%s/%s", path, de->d_name);
|
2016-05-02 00:46:01 +00:00
|
|
|
if (r_lib_dl_check_filename (file)) {
|
2017-07-26 14:35:27 +00:00
|
|
|
IFDBG eprintf ("Loading %s\n", file);
|
2010-04-12 00:22:52 +00:00
|
|
|
r_lib_open (lib, file);
|
2016-05-02 00:46:01 +00:00
|
|
|
} else {
|
|
|
|
IFDBG eprintf ("Cannot open %s\n", file);
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2010-04-12 00:22:52 +00:00
|
|
|
closedir (dh);
|
2017-04-11 15:13:46 +00:00
|
|
|
#endif
|
2016-07-12 20:15:19 +00:00
|
|
|
return true;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2018-01-07 20:54:41 +00:00
|
|
|
R_API bool r_lib_add_handler(RLib *lib,
|
2009-02-05 21:08:46 +00:00
|
|
|
int type, const char *desc,
|
2010-04-12 00:22:52 +00:00
|
|
|
int (*cb)(RLibPlugin *, void *, void *), /* constructor */
|
|
|
|
int (*dt)(RLibPlugin *, void *, void *), /* destructor */
|
2009-02-05 21:08:46 +00:00
|
|
|
void *user)
|
|
|
|
{
|
2011-05-13 08:22:28 +00:00
|
|
|
RLibHandler *h;
|
|
|
|
RListIter *iter;
|
2010-04-12 00:22:52 +00:00
|
|
|
RLibHandler *handler = NULL;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2011-05-13 08:22:28 +00:00
|
|
|
r_list_foreach (lib->handlers, iter, h) {
|
2009-02-05 21:08:46 +00:00
|
|
|
if (type == h->type) {
|
2010-06-03 08:57:34 +00:00
|
|
|
IFDBG eprintf ("Redefining library handler constructor for %d\n", type);
|
2009-02-05 21:08:46 +00:00
|
|
|
handler = h;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!handler) {
|
2011-05-13 08:22:28 +00:00
|
|
|
handler = R_NEW (RLibHandler);
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!handler)
|
2016-07-12 20:15:19 +00:00
|
|
|
return false;
|
2009-02-05 21:08:46 +00:00
|
|
|
handler->type = type;
|
2011-05-13 08:22:28 +00:00
|
|
|
r_list_append (lib->handlers, handler);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2011-09-18 18:41:36 +00:00
|
|
|
strncpy (handler->desc, desc, sizeof (handler->desc)-1);
|
2009-02-05 21:08:46 +00:00
|
|
|
handler->user = user;
|
|
|
|
handler->constructor = cb;
|
|
|
|
handler->destructor = dt;
|
|
|
|
|
2016-07-12 20:15:19 +00:00
|
|
|
return true;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2018-01-07 20:54:41 +00:00
|
|
|
R_API bool r_lib_del_handler(RLib *lib, int type) {
|
2011-05-13 08:22:28 +00:00
|
|
|
RLibHandler *h;
|
|
|
|
RListIter *iter;
|
2009-09-17 09:48:36 +00:00
|
|
|
// TODO: remove all handlers for that type? or only one?
|
2012-02-14 17:10:52 +00:00
|
|
|
/* No _safe loop necessary because we return immediately after the delete. */
|
2011-05-13 08:22:28 +00:00
|
|
|
r_list_foreach (lib->handlers, iter, h) {
|
2009-09-17 09:48:36 +00:00
|
|
|
if (type == h->type) {
|
2011-05-13 08:22:28 +00:00
|
|
|
r_list_delete (lib->handlers, iter);
|
2016-07-12 20:15:19 +00:00
|
|
|
return true;
|
2009-09-17 09:48:36 +00:00
|
|
|
}
|
|
|
|
}
|
2016-07-12 20:15:19 +00:00
|
|
|
return false;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-04-12 00:22:52 +00:00
|
|
|
R_API void r_lib_list(RLib *lib) {
|
2011-05-13 08:22:28 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RLibPlugin *p;
|
|
|
|
r_list_foreach (lib->plugins, iter, p) {
|
2011-10-08 21:39:06 +00:00
|
|
|
printf (" %5s %p %s \n", r_lib_types_get (p->type),
|
2014-07-29 22:33:54 +00:00
|
|
|
p->dl_handler, p->file);
|
2009-09-17 09:48:36 +00:00
|
|
|
}
|
|
|
|
}
|