00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <dlfcn.h>
00023
00024 #include <cerrno>
00025 #include <string>
00026
00027 #include <boost/filesystem.hpp>
00028
00029 #include <drizzled/plugin.h>
00030 #include <drizzled/definitions.h>
00031 #include <drizzled/error.h>
00032 #include <drizzled/errmsg_print.h>
00033 #include <drizzled/module/library.h>
00034
00035 using namespace std;
00036 namespace fs=boost::filesystem;
00037
00038 namespace drizzled
00039 {
00040
00041 module::Library::Library(const std::string &name_arg,
00042 void *handle_arg,
00043 const Manifest *manifest_arg)
00044 : name(name_arg), handle(handle_arg), manifest(manifest_arg)
00045 {}
00046
00047 module::Library::~Library()
00048 {
00054 }
00055
00056 const fs::path module::Library::getLibraryPath(const string &plugin_name)
00057 {
00058 string plugin_lib_name("lib");
00059 plugin_lib_name.append(plugin_name);
00060 plugin_lib_name.append("_plugin");
00061 #if defined(TARGET_OS_OSX)
00062 plugin_lib_name.append(".dylib");
00063 #else
00064 plugin_lib_name.append(".so");
00065 #endif
00066
00067
00068 return plugin_dir / plugin_lib_name;
00069 }
00070
00071 module::Library *module::Library::loadLibrary(const string &plugin_name, bool builtin)
00072 {
00073
00074
00075
00076
00077
00078 size_t found= plugin_name.find(FN_LIBCHAR);
00079 if (found != string::npos)
00080 {
00081 errmsg_printf(error::ERROR, "%s",ER(ER_PLUGIN_NO_PATHS));
00082 return NULL;
00083 }
00084
00085 void *dl_handle= NULL;
00086 string dlpath("");
00087
00088 if (builtin)
00089 {
00090 dlpath.assign("<builtin>");
00091 dl_handle= dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
00092 if (dl_handle == NULL)
00093 {
00094 const char *errmsg= dlerror();
00095 errmsg_printf(error::ERROR, ER(ER_CANT_OPEN_LIBRARY),
00096 dlpath.c_str(), errno, errmsg);
00097 (void)dlerror();
00098
00099 return NULL;
00100 }
00101 }
00102 else
00103 {
00104
00105 dlpath.assign(Library::getLibraryPath(plugin_name).file_string());
00106 dl_handle= dlopen(dlpath.c_str(), RTLD_NOW|RTLD_GLOBAL);
00107 if (dl_handle == NULL)
00108 {
00109 const char *errmsg= dlerror();
00110 uint32_t dlpathlen= dlpath.length();
00111 if (not dlpath.compare(0, dlpathlen, errmsg))
00112 {
00113 errmsg+= dlpathlen;
00114 if (*errmsg == ':') errmsg++;
00115 if (*errmsg == ' ') errmsg++;
00116 }
00117 errmsg_printf(error::ERROR, ER(ER_CANT_OPEN_LIBRARY),
00118 dlpath.c_str(), errno, errmsg);
00119
00120
00121
00122 (void)dlerror();
00123
00124 return NULL;
00125 }
00126 }
00127
00128 string plugin_decl_sym("_drizzled_");
00129 plugin_decl_sym.append(plugin_name);
00130 plugin_decl_sym.append("_plugin_");
00131
00132
00133 void *sym= dlsym(dl_handle, plugin_decl_sym.c_str());
00134 if (sym == NULL)
00135 {
00136 const char* errmsg= dlerror();
00137 errmsg_printf(error::ERROR, errmsg);
00138 errmsg_printf(error::ERROR, ER(ER_CANT_FIND_DL_ENTRY),
00139 plugin_decl_sym.c_str(), dlpath.c_str());
00140 (void)dlerror();
00141 dlclose(dl_handle);
00142 return NULL;
00143 }
00144
00145 const Manifest *module_manifest= static_cast<module::Manifest *>(sym);
00146 if (module_manifest->drizzle_version != DRIZZLE_VERSION_ID)
00147 {
00148 errmsg_printf(error::ERROR,
00149 _("Plugin module %s was compiled for version %" PRIu64 ", "
00150 "which does not match the current running version of "
00151 "Drizzle: %" PRIu64"."),
00152 dlpath.c_str(), module_manifest->drizzle_version,
00153 static_cast<uint64_t>(DRIZZLE_VERSION_ID));
00154 return NULL;
00155 }
00156
00157 return new (nothrow) module::Library(plugin_name, dl_handle, module_manifest);
00158 }
00159
00160 }