156
153
static bool plugin_load_list(plugin::Registry ®istry,
157
154
MEM_ROOT *tmp_root, int *argc, char **argv,
159
156
static int test_plugin_options(MEM_ROOT *, plugin::Module *,
161
static bool register_builtin(plugin::Registry ®istry,
164
158
static void unlock_variables(Session *session, struct system_variables *vars);
165
159
static void cleanup_variables(Session *session, struct system_variables *vars);
166
160
static void plugin_vars_free_values(sys_var *vars);
167
161
static void plugin_opt_set_limits(struct my_option *options,
168
162
const struct st_mysql_sys_var *opt);
169
static void reap_plugins(plugin::Registry &plugins);
163
static void reap_plugins(plugin::Registry ®istry);
172
166
/* declared in set_var.cc */
239
233
Plugin support code
240
234
****************************************************************************/
242
static plugin::Library *plugin_dl_find(const LEX_STRING *dl)
245
plugin::Library *tmp;
247
for (i= 0; i < plugin_dl_array.elements; i++)
249
tmp= *dynamic_element(&plugin_dl_array, i, plugin::Library **);
250
if (! my_strnncoll(files_charset_info,
251
(const unsigned char *)dl->str, dl->length,
252
(const unsigned char *)tmp->dl.str, tmp->dl.length))
258
static plugin::Library *plugin_dl_insert_or_reuse(plugin::Library *plugin_dl)
261
plugin::Library *tmp;
263
for (i= 0; i < plugin_dl_array.elements; i++)
265
tmp= *dynamic_element(&plugin_dl_array, i, plugin::Library **);
267
memcpy(tmp, plugin_dl, sizeof(plugin::Library));
271
if (insert_dynamic(&plugin_dl_array, (unsigned char*)&plugin_dl))
273
tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1,
275
(plugin::Library *) memdup_root(&plugin_mem_root,
276
(unsigned char*)plugin_dl,
277
sizeof(plugin::Library));
281
static inline void free_plugin_mem(plugin::Library *p)
289
static plugin::Library *plugin_dl_add(const LEX_STRING *dl)
292
uint32_t plugin_dir_len;
293
plugin::Library *tmp, plugin_dl;
295
plugin_dir_len= strlen(opt_plugin_dir);
296
dlpath.reserve(FN_REFLEN);
298
Ensure that the dll doesn't have a path.
299
This is done to ensure that only approved libraries from the
300
plugin directory are used (to make this even remotely secure).
302
if (strchr(dl->str, FN_LIBCHAR) ||
303
check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
304
system_charset_info, 1) ||
305
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
307
errmsg_printf(ERRMSG_LVL_ERROR, "%s",ER(ER_UDF_NO_PATHS));
310
/* If this dll is already loaded just increase ref_count. */
311
if ((tmp= plugin_dl_find(dl)))
315
memset(&plugin_dl, 0, sizeof(plugin_dl));
316
/* Compile dll path */
317
dlpath.append(opt_plugin_dir);
319
dlpath.append("lib");
320
dlpath.append(dl->str);
321
dlpath.append("_plugin.so");
322
/* Open new dll handle */
323
if (!(plugin_dl.handle= dlopen(dlpath.c_str(), RTLD_NOW|RTLD_GLOBAL)))
325
const char *errmsg= dlerror();
326
uint32_t dlpathlen= dlpath.length();
327
if (!dlpath.compare(0, dlpathlen, errmsg))
328
{ // if errmsg starts from dlpath, trim this prefix.
330
if (*errmsg == ':') errmsg++;
331
if (*errmsg == ' ') errmsg++;
333
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_OPEN_LIBRARY), dlpath.c_str(), errno, errmsg);
335
// This is, in theory, should cause dlerror() to deallocate the error
336
// message. Found this via Google'ing :)
342
/* Find plugin declarations */
343
if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
345
free_plugin_mem(&plugin_dl);
346
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
350
plugin_dl.plugins= static_cast<plugin::Manifest *>(sym);
352
/* Duplicate and convert dll name */
353
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
354
if (! (plugin_dl.dl.str= (char*) calloc(plugin_dl.dl.length, sizeof(char))))
356
free_plugin_mem(&plugin_dl);
357
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
360
strcpy(plugin_dl.dl.str, dl->str);
361
/* Add this dll to array */
362
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
364
free_plugin_mem(&plugin_dl);
365
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY),
366
sizeof(plugin::Library));
373
static void plugin_dl_del(const LEX_STRING *dl)
377
for (i= 0; i < plugin_dl_array.elements; i++)
379
plugin::Library *tmp= *dynamic_element(&plugin_dl_array, i,
381
if (! my_strnncoll(files_charset_info,
382
(const unsigned char *)dl->str, dl->length,
383
(const unsigned char *)tmp->dl.str, tmp->dl.length))
385
/* Do not remove this element, unless no other plugin uses this dll. */
387
free_plugin_mem(tmp);
388
memset(tmp, 0, sizeof(plugin::Library));
398
static plugin::Module *plugin_insert_or_reuse(plugin::Module *module)
400
if (insert_dynamic(&module_array, (unsigned char*)&module))
402
module= *dynamic_element(&module_array, module_array.elements - 1,
410
241
Requires that a write-lock is held on LOCK_system_variables_hash
412
243
static bool plugin_add(plugin::Registry ®istry, MEM_ROOT *tmp_root,
413
const LEX_STRING *name, const LEX_STRING *dl,
244
plugin::Library *library,
414
245
int *argc, char **argv)
416
plugin::Manifest *manifest;
417
247
if (! initialized)
420
if (registry.find(name))
250
if (registry.find(library->getName()))
422
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UDF_EXISTS), name->str);
252
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_PLUGIN_EXISTS),
253
library->getName().c_str());
425
plugin::Library *library= plugin_dl_add(dl);
429
257
plugin::Module *tmp= NULL;
430
258
/* Find plugin by name */
431
for (manifest= library->plugins; manifest->name; manifest++)
259
const plugin::Manifest *manifest= library->getManifest();
261
tmp= new (std::nothrow) plugin::Module(manifest, library);
265
if (!test_plugin_options(tmp_root, tmp, argc, argv))
433
if (! my_strnncoll(system_charset_info,
434
(const unsigned char *)name->str, name->length,
435
(const unsigned char *)manifest->name,
436
strlen(manifest->name)))
438
tmp= new (std::nothrow) plugin::Module(manifest, library);
442
if (!test_plugin_options(tmp_root, tmp, argc, argv))
444
if ((tmp= plugin_insert_or_reuse(tmp)))
447
init_alloc_root(&tmp->mem_root, 4096, 4096);
450
mysql_del_sys_var_chain(tmp->system_vars);
453
/* plugin was disabled */
268
init_alloc_root(&tmp->mem_root, 4096, 4096);
458
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY), name->str);
271
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_CANT_FIND_DL_ENTRY),
272
library->getName().c_str());
643
452
tmp_plugin_list.push_back(',');
644
453
tmp_plugin_list.append(opt_plugin_add);
646
plugin_load_list(registry, &tmp_root, argc, argv, tmp_plugin_list.c_str());
455
plugin_load_list(registry, &tmp_root, argc, argv, tmp_plugin_list);
650
459
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
461
free_root(&tmp_root, MYF(0));
654
466
Now we initialize all remaining plugins
656
for (idx= 0; idx < module_array.elements; idx++)
468
std::map<std::string, plugin::Module *>::const_iterator modules=
469
registry.getModulesMap().begin();
471
while (modules != registry.getModulesMap().end())
658
module= *dynamic_element(&module_array, idx, plugin::Module **);
473
module= (*modules).second;
659
475
if (module->isInited == false)
661
477
plugin_initialize_vars(module);
670
free_root(&tmp_root, MYF(0));
676
free_root(&tmp_root, MYF(0));
681
static bool register_builtin(plugin::Registry ®istry,
683
plugin::Module **ptr)
686
tmp->isInited= false;
689
if (insert_dynamic(&module_array, (unsigned char*)&tmp))
692
*ptr= *dynamic_element(&module_array, module_array.elements - 1,
485
free_root(&tmp_root, MYF(0));
702
493
called only by plugin_init()
704
static bool plugin_load_list(plugin::Registry &plugins,
495
static bool plugin_load_list(plugin::Registry ®istry,
705
496
MEM_ROOT *tmp_root, int *argc, char **argv,
708
char buffer[FN_REFLEN];
709
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
710
plugin::Library *plugin_dl;
711
plugin::Manifest *plugin;
499
plugin::Library *library= NULL;
501
const string DELIMITER(",");
502
string::size_type last_pos= plugin_list.find_first_not_of(DELIMITER);
503
string::size_type pos= plugin_list.find_first_of(DELIMITER, last_pos);
504
while (string::npos != pos || string::npos != last_pos)
715
if (p == buffer + sizeof(buffer) - 1)
717
errmsg_printf(ERRMSG_LVL_ERROR, _("plugin-load parameter too long"));
721
switch ((*(p++)= *(list++))) {
723
list= NULL; /* terminate the loop */
725
case ':': /* can't use this as delimiter as it may be drive letter */
727
str->str[str->length]= '\0';
728
if (str == &name) // load all plugins in named module
732
p--; /* reset pointer */
737
if ((plugin_dl= plugin_dl_add(&dl)))
739
for (plugin= plugin_dl->plugins; plugin->name; plugin++)
741
name.str= (char *) plugin->name;
742
name.length= strlen(name.str);
744
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
745
if (plugin_add(plugins, tmp_root, &name, &dl, argc, argv))
748
plugin_dl_del(&dl); // reduce ref count
753
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
754
if (plugin_add(plugins, tmp_root, &name, &dl, argc, argv))
757
name.length= dl.length= 0;
758
dl.str= NULL; name.str= p= buffer;
765
name.str[name.length]= '\0';
506
const string plugin_name(plugin_list.substr(last_pos, pos - last_pos));
508
library= registry.addLibrary(plugin_name);
511
errmsg_printf(ERRMSG_LVL_ERROR,
512
_("Couldn't load plugin library named '%s'."),
513
plugin_name.c_str());
517
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
518
if (plugin_add(registry, tmp_root, library, argc, argv))
520
registry.removeLibrary(plugin_name);
521
errmsg_printf(ERRMSG_LVL_ERROR,
522
_("Couldn't load plugin named '%s'."),
523
plugin_name.c_str());
527
last_pos= plugin_list.find_first_not_of(DELIMITER, pos);
528
pos= plugin_list.find_first_of(DELIMITER, last_pos);
777
errmsg_printf(ERRMSG_LVL_ERROR, _("Couldn't load plugin named '%s' with soname '%s'."),
783
534
void plugin_shutdown(plugin::Registry ®istry)
786
size_t count= module_array.elements;
787
vector<plugin::Library *> dl;