1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2007-2011 Free Software Foundation Europe e.V.
5 Copyright (C) 2011-2016 Planets Communications B.V.
6 Copyright (C) 2013-2019 Bareos GmbH & Co. KG
7
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation, which is
11 listed in the file LICENSE.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA.
22 */
23 /*
24 * Kern Sibbald, October 2007
25 */
26 /** @file
27 * BAREOS pluginloader
28 */
29 #include "include/bareos.h"
30 #include "dird.h"
31 #include "dird/dird_globals.h"
32 #include "dird/jcr_private.h"
33 #include "dir_plugins.h"
34 #include "lib/edit.h"
35
36 namespace directordaemon {
37
38 const int debuglevel = 150;
39 #ifdef HAVE_WIN32
40 const char* plugin_type = "-dir.dll";
41 #else
42 const char* plugin_type = "-dir.so";
43 #endif
44
45 static alist* dird_plugin_list;
46 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
47
48 /* Forward referenced functions */
49 static bRC bareosGetValue(bpContext* ctx, brDirVariable var, void* value);
50 static bRC bareosSetValue(bpContext* ctx, bwDirVariable var, void* value);
51 static bRC bareosRegisterEvents(bpContext* ctx, int nr_events, ...);
52 static bRC bareosUnRegisterEvents(bpContext* ctx, int nr_events, ...);
53 static bRC bareosGetInstanceCount(bpContext* ctx, int* ret);
54 static bRC bareosJobMsg(bpContext* ctx,
55 const char* file,
56 int line,
57 int type,
58 utime_t mtime,
59 const char* fmt,
60 ...);
61 static bRC bareosDebugMsg(bpContext* ctx,
62 const char* file,
63 int line,
64 int level,
65 const char* fmt,
66 ...);
67 static bool IsPluginCompatible(Plugin* plugin);
68
69 /* BAREOS info */
70 static bDirInfo binfo = {sizeof(bDirFuncs), DIR_PLUGIN_INTERFACE_VERSION};
71
72 /* BAREOS entry points */
73 static bDirFuncs bfuncs = {sizeof(bDirFuncs), DIR_PLUGIN_INTERFACE_VERSION,
74 bareosRegisterEvents, bareosUnRegisterEvents,
75 bareosGetInstanceCount, bareosGetValue,
76 bareosSetValue, bareosJobMsg,
77 bareosDebugMsg};
78
79 /*
80 * BAREOS private context
81 */
82 struct b_plugin_ctx {
83 JobControlRecord* jcr; /* jcr for plugin */
84 bRC rc; /* last return code */
85 bool disabled; /* set if plugin disabled */
86 char events[NbytesForBits(DIR_NR_EVENTS + 1)]; /* enabled events bitmask */
87 Plugin* plugin; /* pointer to plugin of which this is an instance off */
88 };
89
IsEventEnabled(bpContext * ctx,bDirEventType eventType)90 static inline bool IsEventEnabled(bpContext* ctx, bDirEventType eventType)
91 {
92 b_plugin_ctx* b_ctx;
93 if (!ctx) { return false; }
94 b_ctx = (b_plugin_ctx*)ctx->bContext;
95 if (!b_ctx) { return false; }
96 return BitIsSet(eventType, b_ctx->events);
97 }
98
IsPluginDisabled(bpContext * ctx)99 static inline bool IsPluginDisabled(bpContext* ctx)
100 {
101 b_plugin_ctx* b_ctx;
102 if (!ctx) { return true; }
103 b_ctx = (b_plugin_ctx*)ctx->bContext;
104 if (!b_ctx) { return true; }
105 return b_ctx->disabled;
106 }
107
IsCtxGood(bpContext * ctx,JobControlRecord * & jcr,b_plugin_ctx * & bctx)108 static bool IsCtxGood(bpContext* ctx,
109 JobControlRecord*& jcr,
110 b_plugin_ctx*& bctx)
111 {
112 if (!ctx) { return false; }
113
114 bctx = (b_plugin_ctx*)ctx->bContext;
115 if (!bctx) { return false; }
116
117 jcr = bctx->jcr;
118 if (!jcr) { return false; }
119
120 return true;
121 }
122
trigger_plugin_event(JobControlRecord * jcr,bDirEventType eventType,bDirEvent * event,bpContext * ctx,void * value,alist * plugin_ctx_list,int * index,bRC * rc)123 static inline bool trigger_plugin_event(JobControlRecord* jcr,
124 bDirEventType eventType,
125 bDirEvent* event,
126 bpContext* ctx,
127 void* value,
128 alist* plugin_ctx_list,
129 int* index,
130 bRC* rc)
131 {
132 bool stop = false;
133
134 if (!IsEventEnabled(ctx, eventType)) {
135 Dmsg1(debuglevel, "Event %d disabled for this plugin.\n", eventType);
136 goto bail_out;
137 }
138
139 if (IsPluginDisabled(ctx)) {
140 Dmsg0(debuglevel, "Plugin disabled.\n");
141 goto bail_out;
142 }
143
144 /*
145 * See if we should care about the return code.
146 */
147 if (rc) {
148 *rc = DirplugFunc(ctx->plugin)->handlePluginEvent(ctx, event, value);
149 switch (*rc) {
150 case bRC_OK:
151 break;
152 case bRC_Stop:
153 case bRC_Error:
154 stop = true;
155 break;
156 case bRC_More:
157 break;
158 case bRC_Term:
159 /*
160 * Request to unload this plugin.
161 * As we remove the plugin from the list of plugins we decrement
162 * the running index value so the next plugin gets triggered as
163 * that moved back a position in the alist.
164 */
165 if (index) {
166 UnloadPlugin(plugin_ctx_list, ctx->plugin, *index);
167 *index = ((*index) - 1);
168 }
169 break;
170 case bRC_Seen:
171 break;
172 case bRC_Core:
173 break;
174 case bRC_Skip:
175 stop = true;
176 break;
177 case bRC_Cancel:
178 break;
179 default:
180 break;
181 }
182 } else {
183 DirplugFunc(ctx->plugin)->handlePluginEvent(ctx, event, value);
184 }
185
186 bail_out:
187 return stop;
188 }
189
190 /*
191 * Create a plugin event
192 */
GeneratePluginEvent(JobControlRecord * jcr,bDirEventType eventType,void * value,bool reverse)193 bRC GeneratePluginEvent(JobControlRecord* jcr,
194 bDirEventType eventType,
195 void* value,
196 bool reverse)
197 {
198 int i;
199 bDirEvent event;
200 alist* plugin_ctx_list;
201 bRC rc = bRC_OK;
202
203 if (!dird_plugin_list) {
204 Dmsg0(debuglevel, "No bplugin_list: GeneratePluginEvent ignored.\n");
205 goto bail_out;
206 }
207
208 if (!jcr) {
209 Dmsg0(debuglevel, "No jcr: GeneratePluginEvent ignored.\n");
210 goto bail_out;
211 }
212
213 /*
214 * Return if no plugins loaded
215 */
216 if (!jcr->plugin_ctx_list) {
217 Dmsg0(debuglevel, "No plugin_ctx_list: GeneratePluginEvent ignored.\n");
218 goto bail_out;
219 }
220
221 plugin_ctx_list = jcr->plugin_ctx_list;
222 event.eventType = eventType;
223
224 Dmsg2(debuglevel, "dir-plugin_ctx_list=%p JobId=%d\n", plugin_ctx_list,
225 jcr->JobId);
226
227 /*
228 * See if we need to trigger the loaded plugins in reverse order.
229 */
230 if (reverse) {
231 bpContext* ctx;
232
233 foreach_alist_rindex (i, ctx, plugin_ctx_list) {
234 if (trigger_plugin_event(jcr, eventType, &event, ctx, value,
235 plugin_ctx_list, &i, &rc)) {
236 break;
237 }
238 }
239 } else {
240 bpContext* ctx;
241
242 foreach_alist_index (i, ctx, plugin_ctx_list) {
243 if (trigger_plugin_event(jcr, eventType, &event, ctx, value,
244 plugin_ctx_list, &i, &rc)) {
245 break;
246 }
247 }
248 }
249
250 if (jcr->IsJobCanceled()) {
251 Dmsg0(debuglevel, "Cancel return from GeneratePluginEvent\n");
252 rc = bRC_Cancel;
253 }
254
255 bail_out:
256 return rc;
257 }
258
259 /**
260 * Print to file the plugin info.
261 */
DumpDirPlugin(Plugin * plugin,FILE * fp)262 void DumpDirPlugin(Plugin* plugin, FILE* fp)
263 {
264 genpInfo* info;
265
266 if (!plugin) { return; }
267
268 info = (genpInfo*)plugin->pinfo;
269 fprintf(fp, "\tversion=%d\n", info->version);
270 fprintf(fp, "\tdate=%s\n", NPRTB(info->plugin_date));
271 fprintf(fp, "\tmagic=%s\n", NPRTB(info->plugin_magic));
272 fprintf(fp, "\tauthor=%s\n", NPRTB(info->plugin_author));
273 fprintf(fp, "\tlicence=%s\n", NPRTB(info->plugin_license));
274 fprintf(fp, "\tversion=%s\n", NPRTB(info->plugin_version));
275 fprintf(fp, "\tdescription=%s\n", NPRTB(info->plugin_description));
276 }
277
DumpDirPlugins(FILE * fp)278 static void DumpDirPlugins(FILE* fp) { DumpPlugins(dird_plugin_list, fp); }
279
280 /**
281 * This entry point is called internally by BAREOS to ensure
282 * that the plugin IO calls come into this code.
283 */
LoadDirPlugins(const char * plugin_dir,alist * plugin_names)284 void LoadDirPlugins(const char* plugin_dir, alist* plugin_names)
285 {
286 Plugin* plugin;
287 int i;
288
289 Dmsg0(debuglevel, "Load dir plugins\n");
290 if (!plugin_dir) {
291 Dmsg0(debuglevel, "No dir plugin dir!\n");
292 return;
293 }
294
295 dird_plugin_list = new alist(10, not_owned_by_alist);
296 if (!LoadPlugins((void*)&binfo, (void*)&bfuncs, dird_plugin_list, plugin_dir,
297 plugin_names, plugin_type, IsPluginCompatible)) {
298 /* Either none found, or some error */
299 if (dird_plugin_list->size() == 0) {
300 delete dird_plugin_list;
301 dird_plugin_list = NULL;
302 Dmsg0(debuglevel, "No plugins loaded\n");
303 return;
304 }
305 }
306 /*
307 * Verify that the plugin is acceptable, and print information
308 * about it.
309 */
310 foreach_alist_index (i, plugin, dird_plugin_list) {
311 Dmsg1(debuglevel, "Loaded plugin: %s\n", plugin->file);
312 }
313
314 Dmsg1(debuglevel, "num plugins=%d\n", dird_plugin_list->size());
315 DbgPluginAddHook(DumpDirPlugin);
316 DbgPrintPluginAddHook(DumpDirPlugins);
317 }
318
UnloadDirPlugins(void)319 void UnloadDirPlugins(void)
320 {
321 UnloadPlugins(dird_plugin_list);
322 delete dird_plugin_list;
323 dird_plugin_list = NULL;
324 }
325
ListDirPlugins(PoolMem & msg)326 int ListDirPlugins(PoolMem& msg) { return ListPlugins(dird_plugin_list, msg); }
327
328 /**
329 * Check if a plugin is compatible. Called by the load_plugin function
330 * to allow us to verify the plugin.
331 */
IsPluginCompatible(Plugin * plugin)332 static bool IsPluginCompatible(Plugin* plugin)
333 {
334 genpInfo* info = (genpInfo*)plugin->pinfo;
335
336 Dmsg0(50, "IsPluginCompatible called\n");
337 if (debug_level >= 50) { DumpDirPlugin(plugin, stdin); }
338 if (!bstrcmp(info->plugin_magic, DIR_PLUGIN_MAGIC)) {
339 Jmsg(NULL, M_ERROR, 0,
340 _("Plugin magic wrong. Plugin=%s wanted=%s got=%s\n"), plugin->file,
341 DIR_PLUGIN_MAGIC, info->plugin_magic);
342 Dmsg3(50, "Plugin magic wrong. Plugin=%s wanted=%s got=%s\n", plugin->file,
343 DIR_PLUGIN_MAGIC, info->plugin_magic);
344
345 return false;
346 }
347 if (info->version != DIR_PLUGIN_INTERFACE_VERSION) {
348 Jmsg(NULL, M_ERROR, 0,
349 _("Plugin version incorrect. Plugin=%s wanted=%d got=%d\n"),
350 plugin->file, DIR_PLUGIN_INTERFACE_VERSION, info->version);
351 Dmsg3(50, "Plugin version incorrect. Plugin=%s wanted=%d got=%d\n",
352 plugin->file, DIR_PLUGIN_INTERFACE_VERSION, info->version);
353 return false;
354 }
355 if (!Bstrcasecmp(info->plugin_license, "Bareos AGPLv3") &&
356 !Bstrcasecmp(info->plugin_license, "AGPLv3")) {
357 Jmsg(NULL, M_ERROR, 0,
358 _("Plugin license incompatible. Plugin=%s license=%s\n"), plugin->file,
359 info->plugin_license);
360 Dmsg2(50, "Plugin license incompatible. Plugin=%s license=%s\n",
361 plugin->file, info->plugin_license);
362 return false;
363 }
364 if (info->size != sizeof(genpInfo)) {
365 Jmsg(NULL, M_ERROR, 0,
366 _("Plugin size incorrect. Plugin=%s wanted=%d got=%d\n"), plugin->file,
367 sizeof(genpInfo), info->size);
368 return false;
369 }
370
371 return true;
372 }
373
374 /**
375 * Instantiate a new plugin instance.
376 */
instantiate_plugin(JobControlRecord * jcr,Plugin * plugin,uint32_t instance)377 static inline bpContext* instantiate_plugin(JobControlRecord* jcr,
378 Plugin* plugin,
379 uint32_t instance)
380 {
381 bpContext* ctx;
382 b_plugin_ctx* b_ctx;
383
384 b_ctx = (b_plugin_ctx*)malloc(sizeof(b_plugin_ctx));
385 memset(b_ctx, 0, sizeof(b_plugin_ctx));
386 b_ctx->jcr = jcr;
387 b_ctx->plugin = plugin;
388
389 Dmsg2(debuglevel, "Instantiate dir-plugin_ctx_list=%p JobId=%d\n",
390 jcr->plugin_ctx_list, jcr->JobId);
391
392 ctx = (bpContext*)malloc(sizeof(bpContext));
393 ctx->instance = instance;
394 ctx->plugin = plugin;
395 ctx->bContext = (void*)b_ctx;
396 ctx->pContext = NULL;
397
398 jcr->plugin_ctx_list->append(ctx);
399
400 if (DirplugFunc(plugin)->newPlugin(ctx) != bRC_OK) { b_ctx->disabled = true; }
401
402 return ctx;
403 }
404
405 /**
406 * Send a bDirEventNewPluginOptions event to all plugins configured in
407 * jcr->impl_->res.Job.DirPluginOptions
408 */
DispatchNewPluginOptions(JobControlRecord * jcr)409 void DispatchNewPluginOptions(JobControlRecord* jcr)
410 {
411 int i, j, len;
412 Plugin* plugin;
413 bpContext* ctx = nullptr;
414 uint32_t instance;
415 bDirEvent event;
416 bDirEventType eventType;
417 char *bp, *plugin_name, *option;
418 const char* plugin_options;
419 PoolMem priv_plugin_options(PM_MESSAGE);
420
421 if (!dird_plugin_list || dird_plugin_list->empty()) { return; }
422
423 if (jcr->impl->res.job && jcr->impl->res.job->DirPluginOptions &&
424 jcr->impl->res.job->DirPluginOptions->size()) {
425 eventType = bDirEventNewPluginOptions;
426 event.eventType = eventType;
427
428 foreach_alist_index (i, plugin_options,
429 jcr->impl->res.job->DirPluginOptions) {
430 /*
431 * Make a private copy of plugin options.
432 */
433 PmStrcpy(priv_plugin_options, plugin_options);
434
435 plugin_name = priv_plugin_options.c_str();
436 if (!(bp = strchr(plugin_name, ':'))) {
437 Jmsg(NULL, M_ERROR, 0,
438 _("Illegal DIR plugin options encountered, %s skipping\n"),
439 priv_plugin_options.c_str());
440 continue;
441 }
442 *bp++ = '\0';
443
444 /*
445 * See if there is any instance named in the options string.
446 */
447 instance = 0;
448 option = bp;
449 while (option) {
450 bp = strchr(bp, ':');
451 if (bp) { *bp++ = '\0'; }
452
453 if (bstrncasecmp(option, "instance=", 9)) {
454 instance = str_to_int64(option + 9);
455 break;
456 }
457
458 option = bp;
459 }
460
461 if (instance < LOWEST_PLUGIN_INSTANCE ||
462 instance > HIGHEST_PLUGIN_INSTANCE) {
463 Jmsg(NULL, M_ERROR, 0,
464 _("Illegal DIR plugin options encountered, %s instance %d "
465 "skipping\n"),
466 plugin_options, instance);
467 continue;
468 }
469
470 len = strlen(plugin_name);
471
472 /*
473 * See if this plugin options are for an already instantiated plugin
474 * instance.
475 */
476 if (jcr->plugin_ctx_list) {
477 foreach_alist (ctx, jcr->plugin_ctx_list) {
478 if (ctx->instance == instance && ctx->plugin->file_len == len &&
479 bstrncasecmp(ctx->plugin->file, plugin_name, len)) {
480 break;
481 }
482 }
483
484 /*
485 * Found a context in the previous loop ?
486 */
487 if (!ctx) {
488 foreach_alist_index (j, plugin, dird_plugin_list) {
489 if (plugin->file_len == len &&
490 bstrncasecmp(plugin->file, plugin_name, len)) {
491 ctx = instantiate_plugin(jcr, plugin, instance);
492 break;
493 }
494 }
495 }
496
497 if (ctx) {
498 trigger_plugin_event(jcr, eventType, &event, ctx,
499 (void*)plugin_options, NULL, NULL, NULL);
500 }
501 }
502 }
503 }
504 }
505
506 /**
507 * Create a new instance of each plugin for this Job
508 */
NewPlugins(JobControlRecord * jcr)509 void NewPlugins(JobControlRecord* jcr)
510 {
511 int i, num;
512 Plugin* plugin;
513
514 Dmsg0(debuglevel, "=== enter NewPlugins ===\n");
515 if (!dird_plugin_list) {
516 Dmsg0(debuglevel, "No dir plugin list!\n");
517 return;
518 }
519 if (jcr->IsJobCanceled()) { return; }
520
521 num = dird_plugin_list->size();
522 Dmsg1(debuglevel, "dir-plugin-list size=%d\n", num);
523 if (num == 0) { return; }
524
525 jcr->plugin_ctx_list = new alist(10, owned_by_alist);
526 foreach_alist_index (i, plugin, dird_plugin_list) {
527 /*
528 * Start a new instance of each plugin
529 */
530 instantiate_plugin(jcr, plugin, 0);
531 }
532 }
533
534 /**
535 * Free the plugin instances for this Job
536 */
FreePlugins(JobControlRecord * jcr)537 void FreePlugins(JobControlRecord* jcr)
538 {
539 bpContext* ctx = nullptr;
540
541 if (!dird_plugin_list || !jcr->plugin_ctx_list) { return; }
542
543 Dmsg2(debuglevel, "Free instance dir-plugin_ctx_list=%p JobId=%d\n",
544 jcr->plugin_ctx_list, jcr->JobId);
545 foreach_alist (ctx, jcr->plugin_ctx_list) {
546 /*
547 * Free the plugin instance
548 */
549 DirplugFunc(ctx->plugin)->freePlugin(ctx);
550 free(ctx->bContext); /* Free BAREOS private context */
551 }
552
553 delete jcr->plugin_ctx_list;
554 jcr->plugin_ctx_list = NULL;
555 }
556
557 /**
558 *
559 * Callbacks from the plugin
560 *
561 */
bareosGetValue(bpContext * ctx,brDirVariable var,void * value)562 static bRC bareosGetValue(bpContext* ctx, brDirVariable var, void* value)
563 {
564 JobControlRecord* jcr = NULL;
565 bRC retval = bRC_OK;
566
567 if (!value) { return bRC_Error; }
568
569 switch (var) { /* General variables, no need of ctx */
570 case bDirVarPluginDir:
571 *((char**)value) = me->plugin_directory;
572 Dmsg1(debuglevel, "dir-plugin: return bDirVarPluginDir=%s\n",
573 NPRT(*((char**)value)));
574 break;
575 default:
576 if (!ctx) { return bRC_Error; }
577 jcr = ((b_plugin_ctx*)ctx->bContext)->jcr;
578 if (!jcr) { return bRC_Error; }
579 break;
580 }
581
582 if (jcr) {
583 switch (var) {
584 case bDirVarJobId:
585 *((int*)value) = jcr->JobId;
586 Dmsg1(debuglevel, "dir-plugin: return bDirVarJobId=%d\n", jcr->JobId);
587 break;
588 case bDirVarJobName:
589 *((char**)value) = jcr->Job;
590 Dmsg1(debuglevel, "dir-plugin: return Job name=%s\n",
591 NPRT(*((char**)value)));
592 break;
593 case bDirVarJob:
594 *((char**)value) = jcr->impl->res.job->resource_name_;
595 Dmsg1(debuglevel, "dir-plugin: return bDirVarJob=%s\n",
596 NPRT(*((char**)value)));
597 break;
598 case bDirVarLevel:
599 *((int*)value) = jcr->getJobLevel();
600 Dmsg1(debuglevel, "dir-plugin: return bDirVarLevel=%c\n",
601 jcr->getJobLevel());
602 break;
603 case bDirVarType:
604 *((int*)value) = jcr->getJobType();
605 Dmsg1(debuglevel, "dir-plugin: return bDirVarType=%c\n",
606 jcr->getJobType());
607 break;
608 case bDirVarClient:
609 *((char**)value) = jcr->impl->res.client->resource_name_;
610 Dmsg1(debuglevel, "dir-plugin: return bDirVarClient=%s\n",
611 NPRT(*((char**)value)));
612 break;
613 case bDirVarNumVols: {
614 PoolDbRecord pr;
615
616 bstrncpy(pr.Name, jcr->impl->res.pool->resource_name_,
617 sizeof(pr.Name));
618 if (!jcr->db->GetPoolRecord(jcr, &pr)) { retval = bRC_Error; }
619 *((int*)value) = pr.NumVols;
620 Dmsg1(debuglevel, "dir-plugin: return bDirVarNumVols=%d\n", pr.NumVols);
621 break;
622 }
623 case bDirVarPool:
624 *((char**)value) = jcr->impl->res.pool->resource_name_;
625 Dmsg1(debuglevel, "dir-plugin: return bDirVarPool=%s\n",
626 NPRT(*((char**)value)));
627 break;
628 case bDirVarStorage:
629 if (jcr->impl->res.write_storage) {
630 *((char**)value) = jcr->impl->res.write_storage->resource_name_;
631 } else if (jcr->impl->res.read_storage) {
632 *((char**)value) = jcr->impl->res.read_storage->resource_name_;
633 } else {
634 *((char**)value) = NULL;
635 retval = bRC_Error;
636 }
637 Dmsg1(debuglevel, "dir-plugin: return bDirVarStorage=%s\n",
638 NPRT(*((char**)value)));
639 break;
640 case bDirVarWriteStorage:
641 if (jcr->impl->res.write_storage) {
642 *((char**)value) = jcr->impl->res.write_storage->resource_name_;
643 } else {
644 *((char**)value) = NULL;
645 retval = bRC_Error;
646 }
647 Dmsg1(debuglevel, "dir-plugin: return bDirVarWriteStorage=%s\n",
648 NPRT(*((char**)value)));
649 break;
650 case bDirVarReadStorage:
651 if (jcr->impl->res.read_storage) {
652 *((char**)value) = jcr->impl->res.read_storage->resource_name_;
653 } else {
654 *((char**)value) = NULL;
655 retval = bRC_Error;
656 }
657 Dmsg1(debuglevel, "dir-plugin: return bDirVarReadStorage=%s\n",
658 NPRT(*((char**)value)));
659 break;
660 case bDirVarCatalog:
661 *((char**)value) = jcr->impl->res.catalog->resource_name_;
662 Dmsg1(debuglevel, "dir-plugin: return bDirVarCatalog=%s\n",
663 NPRT(*((char**)value)));
664 break;
665 case bDirVarMediaType:
666 if (jcr->impl->res.write_storage) {
667 *((char**)value) = jcr->impl->res.write_storage->media_type;
668 } else if (jcr->impl->res.read_storage) {
669 *((char**)value) = jcr->impl->res.read_storage->media_type;
670 } else {
671 *((char**)value) = NULL;
672 retval = bRC_Error;
673 }
674 Dmsg1(debuglevel, "dir-plugin: return bDirVarMediaType=%s\n",
675 NPRT(*((char**)value)));
676 break;
677 case bDirVarJobStatus:
678 *((int*)value) = jcr->JobStatus;
679 Dmsg1(debuglevel, "dir-plugin: return bDirVarJobStatus=%c\n",
680 jcr->JobStatus);
681 break;
682 case bDirVarPriority:
683 *((int*)value) = jcr->JobPriority;
684 Dmsg1(debuglevel, "dir-plugin: return bDirVarPriority=%d\n",
685 jcr->JobPriority);
686 break;
687 case bDirVarVolumeName:
688 *((char**)value) = jcr->VolumeName;
689 Dmsg1(debuglevel, "dir-plugin: return bDirVarVolumeName=%s\n",
690 NPRT(*((char**)value)));
691 break;
692 case bDirVarCatalogRes:
693 retval = bRC_Error;
694 break;
695 case bDirVarJobErrors:
696 *((int*)value) = jcr->JobErrors;
697 Dmsg1(debuglevel, "dir-plugin: return bDirVarErrors=%d\n",
698 jcr->JobErrors);
699 break;
700 case bDirVarJobFiles:
701 *((int*)value) = jcr->JobFiles;
702 Dmsg1(debuglevel, "dir-plugin: return bDirVarFiles=%d\n",
703 jcr->JobFiles);
704 break;
705 case bDirVarSDJobFiles:
706 *((int*)value) = jcr->impl->SDJobFiles;
707 Dmsg1(debuglevel, "dir-plugin: return bDirVarSDFiles=%d\n",
708 jcr->impl->SDJobFiles);
709 break;
710 case bDirVarSDErrors:
711 *((int*)value) = jcr->impl->SDErrors;
712 Dmsg1(debuglevel, "dir-plugin: return bDirVarSDErrors=%d\n",
713 jcr->impl->SDErrors);
714 break;
715 case bDirVarFDJobStatus:
716 *((int*)value) = jcr->impl->FDJobStatus;
717 Dmsg1(debuglevel, "dir-plugin: return bDirVarFDJobStatus=%c\n",
718 jcr->impl->FDJobStatus);
719 break;
720 case bDirVarSDJobStatus:
721 *((int*)value) = jcr->impl->SDJobStatus;
722 Dmsg1(debuglevel, "dir-plugin: return bDirVarSDJobStatus=%c\n",
723 jcr->impl->SDJobStatus);
724 break;
725 case bDirVarLastRate:
726 *((int*)value) = jcr->LastRate;
727 Dmsg1(debuglevel, "dir-plugin: return bDirVarLastRate=%d\n",
728 jcr->LastRate);
729 break;
730 case bDirVarJobBytes:
731 *((uint64_t*)value) = jcr->JobBytes;
732 Dmsg1(debuglevel, "dir-plugin: return bDirVarJobBytes=%u\n",
733 jcr->JobBytes);
734 break;
735 case bDirVarReadBytes:
736 *((uint64_t*)value) = jcr->ReadBytes;
737 Dmsg1(debuglevel, "dir-plugin: return bDirVarReadBytes=%u\n",
738 jcr->ReadBytes);
739 break;
740 default:
741 break;
742 }
743 }
744
745 return retval;
746 }
747
bareosSetValue(bpContext * ctx,bwDirVariable var,void * value)748 static bRC bareosSetValue(bpContext* ctx, bwDirVariable var, void* value)
749 {
750 JobControlRecord* jcr;
751
752 if (!value || !ctx) { return bRC_Error; }
753
754 jcr = ((b_plugin_ctx*)ctx->bContext)->jcr;
755 if (!jcr) { return bRC_Error; }
756
757 Dmsg1(debuglevel, "dir-plugin: bareosSetValue var=%d\n", var);
758 switch (var) {
759 case bwDirVarVolumeName:
760 PmStrcpy(jcr->VolumeName, ((char*)value));
761 break;
762 case bwDirVarPriority:
763 jcr->JobPriority = *((int*)value);
764 break;
765 case bwDirVarJobLevel:
766 jcr->setJobLevel(*((int*)value));
767 break;
768 default:
769 break;
770 }
771
772 return bRC_OK;
773 }
774
bareosRegisterEvents(bpContext * ctx,int nr_events,...)775 static bRC bareosRegisterEvents(bpContext* ctx, int nr_events, ...)
776 {
777 int i;
778 va_list args;
779 uint32_t event;
780 b_plugin_ctx* b_ctx;
781
782 if (!ctx) { return bRC_Error; }
783 b_ctx = (b_plugin_ctx*)ctx->bContext;
784 va_start(args, nr_events);
785 for (i = 0; i < nr_events; i++) {
786 event = va_arg(args, uint32_t);
787 Dmsg1(debuglevel, "dir-plugin: Plugin registered event=%u\n", event);
788 SetBit(event, b_ctx->events);
789 }
790 va_end(args);
791
792 return bRC_OK;
793 }
794
bareosUnRegisterEvents(bpContext * ctx,int nr_events,...)795 static bRC bareosUnRegisterEvents(bpContext* ctx, int nr_events, ...)
796 {
797 int i;
798 va_list args;
799 uint32_t event;
800 b_plugin_ctx* b_ctx;
801
802 if (!ctx) { return bRC_Error; }
803 b_ctx = (b_plugin_ctx*)ctx->bContext;
804 va_start(args, nr_events);
805 for (i = 0; i < nr_events; i++) {
806 event = va_arg(args, uint32_t);
807 Dmsg1(debuglevel, "dir-plugin: Plugin unregistered event=%u\n", event);
808 ClearBit(event, b_ctx->events);
809 }
810 va_end(args);
811
812 return bRC_OK;
813 }
814
bareosGetInstanceCount(bpContext * ctx,int * ret)815 static bRC bareosGetInstanceCount(bpContext* ctx, int* ret)
816 {
817 int cnt;
818 JobControlRecord *jcr, *njcr;
819 bpContext* nctx;
820 b_plugin_ctx* bctx;
821 bRC retval = bRC_Error;
822
823 if (!IsCtxGood(ctx, jcr, bctx)) { goto bail_out; }
824
825 P(mutex);
826
827 cnt = 0;
828 foreach_jcr (njcr) {
829 if (jcr->plugin_ctx_list) {
830 foreach_alist (nctx, jcr->plugin_ctx_list) {
831 if (nctx->plugin == bctx->plugin) { cnt++; }
832 }
833 }
834 }
835 endeach_jcr(njcr);
836
837 V(mutex);
838
839 *ret = cnt;
840 retval = bRC_OK;
841
842 bail_out:
843 return retval;
844 }
845
bareosJobMsg(bpContext * ctx,const char * file,int line,int type,utime_t mtime,const char * fmt,...)846 static bRC bareosJobMsg(bpContext* ctx,
847 const char* file,
848 int line,
849 int type,
850 utime_t mtime,
851 const char* fmt,
852 ...)
853 {
854 JobControlRecord* jcr;
855 va_list arg_ptr;
856 PoolMem buffer(PM_MESSAGE);
857
858 if (ctx) {
859 jcr = ((b_plugin_ctx*)ctx->bContext)->jcr;
860 } else {
861 jcr = NULL;
862 }
863
864 va_start(arg_ptr, fmt);
865 buffer.Bvsprintf(fmt, arg_ptr);
866 va_end(arg_ptr);
867 Jmsg(jcr, type, mtime, "%s", buffer.c_str());
868
869 return bRC_OK;
870 }
871
bareosDebugMsg(bpContext * ctx,const char * file,int line,int level,const char * fmt,...)872 static bRC bareosDebugMsg(bpContext* ctx,
873 const char* file,
874 int line,
875 int level,
876 const char* fmt,
877 ...)
878 {
879 va_list arg_ptr;
880 PoolMem buffer(PM_MESSAGE);
881
882 va_start(arg_ptr, fmt);
883 buffer.Bvsprintf(fmt, arg_ptr);
884 va_end(arg_ptr);
885 d_msg(file, line, level, "%s", buffer.c_str());
886
887 return bRC_OK;
888 }
889 } /* namespace directordaemon */
890