1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2007-2011 Free Software Foundation Europe e.V.
5 Copyright (C) 2011-2012 Planets Communications B.V.
6 Copyright (C) 2013-2020 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
27 /**
28 * @file
29 * Bareos pluginloader
30 */
31 #include "include/bareos.h"
32 #include "stored/stored.h"
33 #include "stored/stored_globals.h"
34 #include "stored/device_control_record.h"
35 #include "stored/jcr_private.h"
36 #include "sd_plugins.h"
37 #include "lib/crypto_cache.h"
38 #include "stored/sd_stats.h"
39 #include "lib/edit.h"
40 #include "include/jcr.h"
41
42 namespace storagedaemon {
43
44 const int debuglevel = 250;
45 #ifdef HAVE_WIN32
46 const char* plugin_type = "-sd.dll";
47 #else
48 const char* plugin_type = "-sd.so";
49 #endif
50 static alist* sd_plugin_list = NULL;
51
52 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
53
54 /* Forward referenced functions */
55 static bRC bareosGetValue(PluginContext* ctx, bsdrVariable var, void* value);
56 static bRC bareosSetValue(PluginContext* ctx, bsdwVariable var, void* value);
57 static bRC bareosRegisterEvents(PluginContext* ctx, int nr_events, ...);
58 static bRC bareosUnRegisterEvents(PluginContext* ctx, int nr_events, ...);
59 static bRC bareosGetInstanceCount(PluginContext* ctx, int* ret);
60 static bRC bareosJobMsg(PluginContext* ctx,
61 const char* file,
62 int line,
63 int type,
64 utime_t mtime,
65 const char* fmt,
66 ...);
67 static bRC bareosDebugMsg(PluginContext* ctx,
68 const char* file,
69 int line,
70 int level,
71 const char* fmt,
72 ...);
73 static char* bareosEditDeviceCodes(DeviceControlRecord* dcr,
74 POOLMEM*& omsg,
75 const char* imsg,
76 const char* cmd);
77 static char* bareosLookupCryptoKey(const char* VolumeName);
78 static bool bareosUpdateVolumeInfo(DeviceControlRecord* dcr);
79 static void bareosUpdateTapeAlert(DeviceControlRecord* dcr, uint64_t flags);
80 static DeviceRecord* bareosNewRecord(bool with_data);
81 static void bareosCopyRecordState(DeviceRecord* dst, DeviceRecord* src);
82 static void bareosFreeRecord(DeviceRecord* rec);
83 static bool IsPluginCompatible(Plugin* plugin);
84
85 /* Bareos info */
86 static PluginApiDefinition bareos_plugin_interface_version
87 = {sizeof(PluginFunctions), SD_PLUGIN_INTERFACE_VERSION};
88
89 /* Bareos entry points */
90 static CoreFunctions bareos_core_functions
91 = {sizeof(CoreFunctions), SD_PLUGIN_INTERFACE_VERSION,
92 bareosRegisterEvents, bareosUnRegisterEvents,
93 bareosGetInstanceCount, bareosGetValue,
94 bareosSetValue, bareosJobMsg,
95 bareosDebugMsg, bareosEditDeviceCodes,
96 bareosLookupCryptoKey, bareosUpdateVolumeInfo,
97 bareosUpdateTapeAlert, bareosNewRecord,
98 bareosCopyRecordState, bareosFreeRecord};
99
100 /**
101 * Bareos private context
102 */
103 struct b_plugin_ctx {
104 JobControlRecord* jcr; /* jcr for plugin */
105 bRC rc; /* last return code */
106 bool disabled; /* set if plugin disabled */
107 char events[NbytesForBits(SD_NR_EVENTS + 1)]; /* enabled events bitmask */
108 Plugin* plugin; /* pointer to plugin of which this is an instance off */
109 };
110
IsEventEnabled(PluginContext * ctx,bSdEventType eventType)111 static inline bool IsEventEnabled(PluginContext* ctx, bSdEventType eventType)
112 {
113 b_plugin_ctx* b_ctx;
114 if (!ctx) { return false; }
115 b_ctx = (b_plugin_ctx*)ctx->core_private_context;
116 if (!b_ctx) { return false; }
117
118 return BitIsSet(eventType, b_ctx->events);
119 }
120
IsPluginDisabled(PluginContext * ctx)121 static inline bool IsPluginDisabled(PluginContext* ctx)
122 {
123 b_plugin_ctx* b_ctx;
124 if (!ctx) { return true; }
125 b_ctx = (b_plugin_ctx*)ctx->core_private_context;
126 if (!b_ctx) { return true; }
127 return b_ctx->disabled;
128 }
129
IsCtxGood(PluginContext * ctx,JobControlRecord * & jcr,b_plugin_ctx * & bctx)130 static bool IsCtxGood(PluginContext* ctx,
131 JobControlRecord*& jcr,
132 b_plugin_ctx*& bctx)
133 {
134 if (!ctx) { return false; }
135
136 bctx = (b_plugin_ctx*)ctx->core_private_context;
137 if (!bctx) { return false; }
138
139 jcr = bctx->jcr;
140 if (!jcr) { return false; }
141
142 return true;
143 }
144
145 /**
146 * Edit codes into ChangerCommand
147 * %% = %
148 * %a = Archive device name
149 * %c = Changer device name
150 * %D = Diagnostic device name
151 * %d = Changer drive index
152 * %f = Client's name
153 * %j = Job name
154 * %o = Command
155 * %s = Slot base 0
156 * %S = Slot base 1
157 * %v = Volume name
158 *
159 *
160 * omsg = edited output message
161 * imsg = input string containing edit codes (%x)
162 * cmd = command string (load, unload, ...)
163 */
edit_device_codes(DeviceControlRecord * dcr,POOLMEM * & omsg,const char * imsg,const char * cmd)164 char* edit_device_codes(DeviceControlRecord* dcr,
165 POOLMEM*& omsg,
166 const char* imsg,
167 const char* cmd)
168 {
169 const char* p;
170 const char* str;
171 char ed1[50];
172
173 *omsg = 0;
174 Dmsg1(1800, "edit_device_codes: %s\n", imsg);
175 for (p = imsg; *p; p++) {
176 if (*p == '%') {
177 switch (*++p) {
178 case '%':
179 str = "%";
180 break;
181 case 'a':
182 str = dcr->dev->archive_name();
183 break;
184 case 'c':
185 str = NPRT(dcr->device_resource->changer_name);
186 break;
187 case 'D':
188 str = NPRT(dcr->device_resource->diag_device_name);
189 break;
190 case 'd':
191 str = edit_int64(dcr->dev->drive_index, ed1);
192 break;
193 case 'o':
194 str = NPRT(cmd);
195 break;
196 case 's':
197 str = edit_int64(dcr->VolCatInfo.Slot - 1, ed1);
198 break;
199 case 'S':
200 str = edit_int64(dcr->VolCatInfo.Slot, ed1);
201 break;
202 case 'j': /* Job name */
203 str = dcr->jcr->Job;
204 break;
205 case 'v':
206 if (dcr->VolCatInfo.VolCatName[0]) {
207 str = dcr->VolCatInfo.VolCatName;
208 } else if (dcr->VolumeName[0]) {
209 str = dcr->VolumeName;
210 } else if (dcr->dev->vol && dcr->dev->vol->vol_name) {
211 str = dcr->dev->vol->vol_name;
212 } else {
213 str = dcr->dev->VolHdr.VolumeName;
214 }
215 break;
216 case 'f':
217 str = NPRT(dcr->jcr->client_name);
218 break;
219 default:
220 ed1[0] = '%';
221 ed1[1] = *p;
222 ed1[2] = 0;
223 str = ed1;
224 break;
225 }
226 } else {
227 ed1[0] = *p;
228 ed1[1] = 0;
229 str = ed1;
230 }
231 Dmsg1(1900, "add_str %s\n", str);
232 PmStrcat(omsg, (char*)str);
233 Dmsg1(1800, "omsg=%s\n", omsg);
234 }
235 Dmsg1(800, "omsg=%s\n", omsg);
236
237 return omsg;
238 }
239
trigger_plugin_event(JobControlRecord * jcr,bSdEventType eventType,bSdEvent * event,PluginContext * ctx,void * value,alist * plugin_ctx_list,int * index,bRC * rc)240 static inline bool trigger_plugin_event(JobControlRecord* jcr,
241 bSdEventType eventType,
242 bSdEvent* event,
243 PluginContext* ctx,
244 void* value,
245 alist* plugin_ctx_list,
246 int* index,
247 bRC* rc)
248 {
249 bool stop = false;
250
251 if (!IsEventEnabled(ctx, eventType)) {
252 Dmsg1(debuglevel, "Event %d disabled for this plugin.\n", eventType);
253 goto bail_out;
254 }
255
256 if (IsPluginDisabled(ctx)) {
257 Dmsg0(debuglevel, "Plugin disabled.\n");
258 goto bail_out;
259 }
260
261 /*
262 * See if we should care about the return code.
263 */
264 if (rc) {
265 *rc = SdplugFunc(ctx->plugin)->handlePluginEvent(ctx, event, value);
266 switch (*rc) {
267 case bRC_OK:
268 break;
269 case bRC_Stop:
270 case bRC_Error:
271 stop = true;
272 break;
273 case bRC_More:
274 break;
275 case bRC_Term:
276 /*
277 * Request to unload this plugin.
278 * As we remove the plugin from the list of plugins we decrement
279 * the running index value so the next plugin gets triggered as
280 * that moved back a position in the alist.
281 */
282 if (index) {
283 UnloadPlugin(plugin_ctx_list, ctx->plugin, *index);
284 *index = ((*index) - 1);
285 }
286 break;
287 case bRC_Seen:
288 break;
289 case bRC_Core:
290 break;
291 case bRC_Skip:
292 stop = true;
293 break;
294 case bRC_Cancel:
295 break;
296 default:
297 break;
298 }
299 } else {
300 SdplugFunc(ctx->plugin)->handlePluginEvent(ctx, event, value);
301 }
302
303 bail_out:
304 return stop;
305 }
306
307 /**
308 * Create a plugin event
309 */
GeneratePluginEvent(JobControlRecord * jcr,bSdEventType eventType,void * value,bool reverse)310 bRC GeneratePluginEvent(JobControlRecord* jcr,
311 bSdEventType eventType,
312 void* value,
313 bool reverse)
314 {
315 int i;
316 bSdEvent event;
317 alist* plugin_ctx_list;
318 bRC rc = bRC_OK;
319
320 if (!sd_plugin_list) {
321 Dmsg0(debuglevel, "No bplugin_list: GeneratePluginEvent ignored.\n");
322 goto bail_out;
323 }
324
325 if (!jcr) {
326 Dmsg0(debuglevel, "No jcr: GeneratePluginEvent ignored.\n");
327 goto bail_out;
328 }
329
330 /*
331 * Return if no plugins loaded
332 */
333 if (!jcr->plugin_ctx_list) {
334 Dmsg0(debuglevel, "No plugin_ctx_list: GeneratePluginEvent ignored.\n");
335 goto bail_out;
336 }
337
338 plugin_ctx_list = jcr->plugin_ctx_list;
339 event.eventType = eventType;
340
341 Dmsg2(debuglevel, "sd-plugin_ctx_list=%p JobId=%d\n", plugin_ctx_list,
342 jcr->JobId);
343
344 /*
345 * See if we need to trigger the loaded plugins in reverse order.
346 */
347 if (reverse) {
348 PluginContext* ctx;
349
350 foreach_alist_rindex (i, ctx, plugin_ctx_list) {
351 if (trigger_plugin_event(jcr, eventType, &event, ctx, value,
352 plugin_ctx_list, &i, &rc)) {
353 break;
354 }
355 }
356 } else {
357 PluginContext* ctx;
358
359 foreach_alist_index (i, ctx, plugin_ctx_list) {
360 if (trigger_plugin_event(jcr, eventType, &event, ctx, value,
361 plugin_ctx_list, &i, &rc)) {
362 break;
363 }
364 }
365 }
366
367 if (jcr->IsJobCanceled()) {
368 Dmsg0(debuglevel, "Cancel return from GeneratePluginEvent\n");
369 rc = bRC_Cancel;
370 }
371
372 bail_out:
373 return rc;
374 }
375
376 /**
377 * Print to file the plugin info.
378 */
DumpSdPlugin(Plugin * plugin,FILE * fp)379 void DumpSdPlugin(Plugin* plugin, FILE* fp)
380 {
381 PluginInformation* info;
382
383 if (!plugin) { return; }
384
385 info = (PluginInformation*)plugin->plugin_information;
386 fprintf(fp, "\tversion=%d\n", info->version);
387 fprintf(fp, "\tdate=%s\n", NPRTB(info->plugin_date));
388 fprintf(fp, "\tmagic=%s\n", NPRTB(info->plugin_magic));
389 fprintf(fp, "\tauthor=%s\n", NPRTB(info->plugin_author));
390 fprintf(fp, "\tlicence=%s\n", NPRTB(info->plugin_license));
391 fprintf(fp, "\tversion=%s\n", NPRTB(info->plugin_version));
392 fprintf(fp, "\tdescription=%s\n", NPRTB(info->plugin_description));
393 }
394
DumpSdPlugins(FILE * fp)395 static void DumpSdPlugins(FILE* fp) { DumpPlugins(sd_plugin_list, fp); }
396
397 /**
398 * This entry point is called internally by Bareos to ensure
399 * that the plugin IO calls come into this code.
400 */
LoadSdPlugins(const char * plugin_dir,alist * plugin_names)401 void LoadSdPlugins(const char* plugin_dir, alist* plugin_names)
402 {
403 Plugin* plugin;
404 int i;
405
406 Dmsg0(debuglevel, "Load sd plugins\n");
407 if (!plugin_dir) {
408 Dmsg0(debuglevel, "No sd plugin dir!\n");
409 return;
410 }
411 sd_plugin_list = new alist(10, not_owned_by_alist);
412 if (!LoadPlugins((void*)&bareos_plugin_interface_version,
413 (void*)&bareos_core_functions, sd_plugin_list, plugin_dir,
414 plugin_names, plugin_type, IsPluginCompatible)) {
415 /*
416 * Either none found, or some error
417 */
418 if (sd_plugin_list->size() == 0) {
419 delete sd_plugin_list;
420 sd_plugin_list = NULL;
421 Dmsg0(debuglevel, "No plugins loaded\n");
422 return;
423 }
424 }
425 /*
426 * Verify that the plugin is acceptable, and print information about it.
427 */
428 foreach_alist_index (i, plugin, sd_plugin_list) {
429 Dmsg1(debuglevel, "Loaded plugin: %s\n", plugin->file);
430 }
431
432 Dmsg1(debuglevel, "num plugins=%d\n", sd_plugin_list->size());
433 DbgPluginAddHook(DumpSdPlugin);
434 DbgPrintPluginAddHook(DumpSdPlugins);
435 }
436
UnloadSdPlugins(void)437 void UnloadSdPlugins(void)
438 {
439 UnloadPlugins(sd_plugin_list);
440 delete sd_plugin_list;
441 sd_plugin_list = NULL;
442 }
443
ListSdPlugins(PoolMem & msg)444 int ListSdPlugins(PoolMem& msg) { return ListPlugins(sd_plugin_list, msg); }
445
446 /**
447 * Check if a plugin is compatible. Called by the load_plugin function
448 * to allow us to verify the plugin.
449 */
IsPluginCompatible(Plugin * plugin)450 static bool IsPluginCompatible(Plugin* plugin)
451 {
452 PluginInformation* info = (PluginInformation*)plugin->plugin_information;
453 Dmsg0(50, "IsPluginCompatible called\n");
454 if (debug_level >= 50) { DumpSdPlugin(plugin, stdin); }
455 if (!bstrcmp(info->plugin_magic, SD_PLUGIN_MAGIC)) {
456 Jmsg(NULL, M_ERROR, 0,
457 _("Plugin magic wrong. Plugin=%s wanted=%s got=%s\n"), plugin->file,
458 SD_PLUGIN_MAGIC, info->plugin_magic);
459 Dmsg3(50, "Plugin magic wrong. Plugin=%s wanted=%s got=%s\n", plugin->file,
460 SD_PLUGIN_MAGIC, info->plugin_magic);
461
462 return false;
463 }
464 if (info->version != SD_PLUGIN_INTERFACE_VERSION) {
465 Jmsg(NULL, M_ERROR, 0,
466 _("Plugin version incorrect. Plugin=%s wanted=%d got=%d\n"),
467 plugin->file, SD_PLUGIN_INTERFACE_VERSION, info->version);
468 Dmsg3(50, "Plugin version incorrect. Plugin=%s wanted=%d got=%d\n",
469 plugin->file, SD_PLUGIN_INTERFACE_VERSION, info->version);
470 return false;
471 }
472 if (!Bstrcasecmp(info->plugin_license, "Bareos AGPLv3")
473 && !Bstrcasecmp(info->plugin_license, "AGPLv3")) {
474 Jmsg(NULL, M_ERROR, 0,
475 _("Plugin license incompatible. Plugin=%s license=%s\n"), plugin->file,
476 info->plugin_license);
477 Dmsg2(50, "Plugin license incompatible. Plugin=%s license=%s\n",
478 plugin->file, info->plugin_license);
479 return false;
480 }
481 if (info->size != sizeof(PluginInformation)) {
482 Jmsg(NULL, M_ERROR, 0,
483 _("Plugin size incorrect. Plugin=%s wanted=%d got=%d\n"), plugin->file,
484 sizeof(PluginInformation), info->size);
485 return false;
486 }
487
488 return true;
489 }
490
491 /**
492 * Instantiate a new plugin instance.
493 */
instantiate_plugin(JobControlRecord * jcr,Plugin * plugin,uint32_t instance)494 static inline PluginContext* instantiate_plugin(JobControlRecord* jcr,
495 Plugin* plugin,
496 uint32_t instance)
497 {
498 PluginContext* ctx;
499 b_plugin_ctx* b_ctx;
500
501 b_ctx = (b_plugin_ctx*)malloc(sizeof(b_plugin_ctx));
502 memset(b_ctx, 0, sizeof(b_plugin_ctx));
503 b_ctx->jcr = jcr;
504 b_ctx->plugin = plugin;
505
506 Dmsg2(debuglevel, "Instantiate dir-plugin_ctx_list=%p JobId=%d\n",
507 jcr->plugin_ctx_list, jcr->JobId);
508
509 ctx = (PluginContext*)malloc(sizeof(PluginContext));
510 ctx->instance = instance;
511 ctx->plugin = plugin;
512 ctx->core_private_context = (void*)b_ctx;
513 ctx->plugin_private_context = NULL;
514
515 jcr->plugin_ctx_list->append(ctx);
516
517 if (SdplugFunc(plugin)->newPlugin(ctx) != bRC_OK) { b_ctx->disabled = true; }
518
519 return ctx;
520 }
521
522 /**
523 * Send a bSdEventNewPluginOptions event to all plugins configured in
524 * jcr->impl_->plugin_options.
525 */
DispatchNewPluginOptions(JobControlRecord * jcr)526 void DispatchNewPluginOptions(JobControlRecord* jcr)
527 {
528 int i, j, len;
529 Plugin* plugin;
530 PluginContext* ctx = nullptr;
531 uint32_t instance;
532 bSdEvent event;
533 bSdEventType eventType;
534 char *bp, *plugin_name, *option;
535 const char* plugin_options;
536 PoolMem priv_plugin_options(PM_MESSAGE);
537
538 if (!sd_plugin_list || sd_plugin_list->empty()) { return; }
539
540 if (jcr->impl->plugin_options && jcr->impl->plugin_options->size()) {
541 eventType = bSdEventNewPluginOptions;
542 event.eventType = eventType;
543
544 foreach_alist_index (i, plugin_options, jcr->impl->plugin_options) {
545 /*
546 * Make a private copy of plugin options.
547 */
548 PmStrcpy(priv_plugin_options, plugin_options);
549
550 plugin_name = priv_plugin_options.c_str();
551 if (!(bp = strchr(plugin_name, ':'))) {
552 Jmsg(NULL, M_ERROR, 0,
553 _("Illegal SD plugin options encountered, %s skipping\n"),
554 priv_plugin_options.c_str());
555 continue;
556 }
557 *bp++ = '\0';
558
559 /*
560 * See if there is any instance named in the options string.
561 */
562 instance = 0;
563 option = bp;
564 while (option) {
565 bp = strchr(bp, ':');
566 if (bp) { *bp++ = '\0'; }
567
568 if (bstrncasecmp(option, "instance=", 9)) {
569 instance = str_to_int64(option + 9);
570 break;
571 }
572
573 option = bp;
574 }
575
576 if (instance < LOWEST_PLUGIN_INSTANCE
577 || instance > HIGHEST_PLUGIN_INSTANCE) {
578 Jmsg(NULL, M_ERROR, 0,
579 _("Illegal SD plugin options encountered, %s instance %d "
580 "skipping\n"),
581 plugin_options, instance);
582 continue;
583 }
584
585 len = strlen(plugin_name);
586
587 /*
588 * See if this plugin options are for an already instantiated plugin
589 * instance.
590 */
591 if (jcr->plugin_ctx_list) {
592 foreach_alist (ctx, jcr->plugin_ctx_list) {
593 if (ctx->instance == instance && ctx->plugin->file_len == len
594 && bstrncasecmp(ctx->plugin->file, plugin_name, len)) {
595 break;
596 }
597 }
598
599 /*
600 * Found a context in the previous loop ?
601 */
602 if (!ctx) {
603 foreach_alist_index (j, plugin, sd_plugin_list) {
604 if (plugin->file_len == len
605 && bstrncasecmp(plugin->file, plugin_name, len)) {
606 ctx = instantiate_plugin(jcr, plugin, instance);
607 break;
608 }
609 }
610 }
611
612 if (ctx) {
613 trigger_plugin_event(jcr, eventType, &event, ctx,
614 (void*)plugin_options, NULL, NULL, NULL);
615 }
616 }
617 }
618 }
619 }
620
621 /**
622 * Create a new instance of each plugin for this Job
623 */
NewPlugins(JobControlRecord * jcr)624 void NewPlugins(JobControlRecord* jcr)
625 {
626 Plugin* plugin;
627 int i, num;
628
629 Dmsg0(debuglevel, "=== enter NewPlugins ===\n");
630 if (!sd_plugin_list) {
631 Dmsg0(debuglevel, "No sd plugin list!\n");
632 return;
633 }
634 if (jcr->IsJobCanceled()) { return; }
635 /*
636 * If plugins already loaded, just return
637 */
638 if (jcr->plugin_ctx_list) { return; }
639
640 num = sd_plugin_list->size();
641 Dmsg1(debuglevel, "sd-plugin-list size=%d\n", num);
642 if (num == 0) { return; }
643
644 jcr->plugin_ctx_list = new alist(10, owned_by_alist);
645 foreach_alist_index (i, plugin, sd_plugin_list) {
646 /*
647 * Start a new instance of each plugin
648 */
649 instantiate_plugin(jcr, plugin, 0);
650 }
651 }
652
653 /**
654 * Free the plugin instances for this Job
655 */
FreePlugins(JobControlRecord * jcr)656 void FreePlugins(JobControlRecord* jcr)
657 {
658 PluginContext* ctx = nullptr;
659
660 if (!sd_plugin_list || !jcr->plugin_ctx_list) { return; }
661
662 Dmsg2(debuglevel, "Free instance dir-plugin_ctx_list=%p JobId=%d\n",
663 jcr->plugin_ctx_list, jcr->JobId);
664 foreach_alist (ctx, jcr->plugin_ctx_list) {
665 /*
666 * Free the plugin instance
667 */
668 SdplugFunc(ctx->plugin)->freePlugin(ctx);
669 free(ctx->core_private_context); /* Free BAREOS private context */
670 }
671
672 delete jcr->plugin_ctx_list;
673 jcr->plugin_ctx_list = NULL;
674 }
675
676 /* ==============================================================
677 *
678 * Callbacks from the plugin
679 *
680 * ==============================================================
681 */
bareosGetValue(PluginContext * ctx,bsdrVariable var,void * value)682 static bRC bareosGetValue(PluginContext* ctx, bsdrVariable var, void* value)
683 {
684 JobControlRecord* jcr = NULL;
685 bRC retval = bRC_OK;
686
687 if (!value) { return bRC_Error; }
688
689 switch (var) { /* General variables, no need of ctx */
690 case bsdVarCompatible:
691 *((bool*)value) = me->compatible;
692 Dmsg1(debuglevel, "sd-plugin: return bsdVarCompatible=%s\n",
693 (me->compatible) ? "true" : "false");
694 break;
695 case bsdVarPluginDir:
696 *((char**)value) = me->plugin_directory;
697 Dmsg1(debuglevel, "sd-plugin: return bsdVarPluginDir=%s\n",
698 me->plugin_directory);
699 break;
700 default:
701 if (!ctx) { return bRC_Error; }
702
703 jcr = ((b_plugin_ctx*)ctx->core_private_context)->jcr;
704 if (!jcr) { return bRC_Error; }
705 break;
706 }
707
708 if (jcr) {
709 switch (var) {
710 case bsdVarJob:
711 *((char**)value) = jcr->impl->job_name;
712 Dmsg1(debuglevel, "sd-plugin: return bsdVarJobName=%s\n",
713 NPRT(*((char**)value)));
714 break;
715 case bsdVarLevel:
716 *((int*)value) = jcr->getJobLevel();
717 Dmsg1(debuglevel, "sd-plugin: return bsdVarLevel=%c\n",
718 jcr->getJobLevel());
719 break;
720 case bsdVarType:
721 *((int*)value) = jcr->getJobType();
722 Dmsg1(debuglevel, "sd-plugin: return bsdVarType=%c\n",
723 jcr->getJobType());
724 break;
725 case bsdVarJobId:
726 *((int*)value) = jcr->JobId;
727 Dmsg1(debuglevel, "sd-plugin: return bsdVarJobId=%d\n", jcr->JobId);
728 break;
729 case bsdVarClient:
730 *((char**)value) = jcr->client_name;
731 Dmsg1(debuglevel, "sd-plugin: return bsdVarClient=%s\n",
732 NPRT(*((char**)value)));
733 break;
734 case bsdVarPool:
735 if (jcr->impl->dcr) {
736 *((char**)value) = jcr->impl->dcr->pool_name;
737 Dmsg1(debuglevel, "sd-plugin: return bsdVarPool=%s\n",
738 NPRT(*((char**)value)));
739 } else {
740 retval = bRC_Error;
741 }
742 break;
743 case bsdVarPoolType:
744 if (jcr->impl->dcr) {
745 *((char**)value) = jcr->impl->dcr->pool_type;
746 Dmsg1(debuglevel, "sd-plugin: return bsdVarPoolType=%s\n",
747 NPRT(*((char**)value)));
748 } else {
749 retval = bRC_Error;
750 }
751 break;
752 case bsdVarStorage:
753 if (jcr->impl->dcr && jcr->impl->dcr->device_resource) {
754 *((char**)value) = jcr->impl->dcr->device_resource->resource_name_;
755 Dmsg1(debuglevel, "sd-plugin: return bsdVarStorage=%s\n",
756 NPRT(*((char**)value)));
757 } else {
758 retval = bRC_Error;
759 }
760 break;
761 case bsdVarMediaType:
762 if (jcr->impl->dcr) {
763 *((char**)value) = jcr->impl->dcr->media_type;
764 Dmsg1(debuglevel, "sd-plugin: return bsdVarMediaType=%s\n",
765 NPRT(*((char**)value)));
766 } else {
767 retval = bRC_Error;
768 }
769 break;
770 case bsdVarJobName:
771 *((char**)value) = jcr->Job;
772 Dmsg1(debuglevel, "sd-plugin: return bsdVarJobName=%s\n",
773 NPRT(*((char**)value)));
774 break;
775 case bsdVarJobStatus:
776 *((int*)value) = jcr->JobStatus;
777 Dmsg1(debuglevel, "sd-plugin: return bsdVarJobStatus=%c\n",
778 jcr->JobStatus);
779 break;
780 case bsdVarVolumeName:
781 if (jcr->impl->dcr) {
782 *((char**)value) = jcr->impl->dcr->VolumeName;
783 Dmsg1(debuglevel, "sd-plugin: return bsdVarVolumeName=%s\n",
784 NPRT(*((char**)value)));
785 } else {
786 retval = bRC_Error;
787 }
788 Dmsg1(debuglevel, "sd-plugin: return bsdVarVolumeName=%s\n",
789 jcr->VolumeName);
790 break;
791 case bsdVarJobErrors:
792 *((int*)value) = jcr->JobErrors;
793 Dmsg1(debuglevel, "sd-plugin: return bsdVarJobErrors=%d\n",
794 jcr->JobErrors);
795 break;
796 case bsdVarJobFiles:
797 *((int*)value) = jcr->JobFiles;
798 Dmsg1(debuglevel, "sd-plugin: return bsdVarJobFiles=%d\n",
799 jcr->JobFiles);
800 break;
801 case bsdVarJobBytes:
802 *((uint64_t*)value) = jcr->JobBytes;
803 Dmsg1(debuglevel, "sd-plugin: return bsdVarJobBytes=%d\n",
804 jcr->JobBytes);
805 break;
806 default:
807 break;
808 }
809 }
810
811 return retval;
812 }
813
bareosSetValue(PluginContext * ctx,bsdwVariable var,void * value)814 static bRC bareosSetValue(PluginContext* ctx, bsdwVariable var, void* value)
815 {
816 JobControlRecord* jcr;
817 if (!value || !ctx) { return bRC_Error; }
818
819 jcr = ((b_plugin_ctx*)ctx->core_private_context)->jcr;
820 if (!jcr) { return bRC_Error; }
821
822 Dmsg1(debuglevel, "sd-plugin: bareosSetValue var=%d\n", var);
823 switch (var) {
824 case bsdwVarVolumeName:
825 PmStrcpy(jcr->VolumeName, ((char*)value));
826 break;
827 case bsdwVarPriority:
828 jcr->JobPriority = *((int*)value);
829 break;
830 case bsdwVarJobLevel:
831 jcr->setJobLevel(*((int*)value));
832 break;
833 default:
834 break;
835 }
836
837 return bRC_OK;
838 }
839
bareosRegisterEvents(PluginContext * ctx,int nr_events,...)840 static bRC bareosRegisterEvents(PluginContext* ctx, int nr_events, ...)
841 {
842 int i;
843 va_list args;
844 uint32_t event;
845 b_plugin_ctx* b_ctx;
846
847 if (!ctx) { return bRC_Error; }
848 b_ctx = (b_plugin_ctx*)ctx->core_private_context;
849 va_start(args, nr_events);
850 for (i = 0; i < nr_events; i++) {
851 event = va_arg(args, uint32_t);
852 Dmsg1(debuglevel, "sd-plugin: Plugin registered event=%u\n", event);
853 SetBit(event, b_ctx->events);
854 }
855 va_end(args);
856 return bRC_OK;
857 }
858
bareosUnRegisterEvents(PluginContext * ctx,int nr_events,...)859 static bRC bareosUnRegisterEvents(PluginContext* ctx, int nr_events, ...)
860 {
861 int i;
862 va_list args;
863 uint32_t event;
864 b_plugin_ctx* b_ctx;
865
866 if (!ctx) { return bRC_Error; }
867 b_ctx = (b_plugin_ctx*)ctx->core_private_context;
868 va_start(args, nr_events);
869 for (i = 0; i < nr_events; i++) {
870 event = va_arg(args, uint32_t);
871 Dmsg1(debuglevel, "sd-plugin: Plugin unregistered event=%u\n", event);
872 ClearBit(event, b_ctx->events);
873 }
874 va_end(args);
875 return bRC_OK;
876 }
877
bareosGetInstanceCount(PluginContext * ctx,int * ret)878 static bRC bareosGetInstanceCount(PluginContext* ctx, int* ret)
879 {
880 int cnt;
881 JobControlRecord *jcr, *njcr;
882 PluginContext* nctx;
883 b_plugin_ctx* bctx;
884 bRC retval = bRC_Error;
885
886 if (!IsCtxGood(ctx, jcr, bctx)) { goto bail_out; }
887
888 P(mutex);
889
890 cnt = 0;
891 foreach_jcr (njcr) {
892 if (jcr->plugin_ctx_list) {
893 foreach_alist (nctx, jcr->plugin_ctx_list) {
894 if (nctx->plugin == bctx->plugin) { cnt++; }
895 }
896 }
897 }
898 endeach_jcr(njcr);
899
900 V(mutex);
901
902 *ret = cnt;
903 retval = bRC_OK;
904
905 bail_out:
906 return retval;
907 }
908
bareosJobMsg(PluginContext * ctx,const char * file,int line,int type,utime_t mtime,const char * fmt,...)909 static bRC bareosJobMsg(PluginContext* ctx,
910 const char* file,
911 int line,
912 int type,
913 utime_t mtime,
914 const char* fmt,
915 ...)
916 {
917 JobControlRecord* jcr;
918 va_list arg_ptr;
919 PoolMem buffer(PM_MESSAGE);
920
921 if (ctx) {
922 jcr = ((b_plugin_ctx*)ctx->core_private_context)->jcr;
923 } else {
924 jcr = NULL;
925 }
926
927 va_start(arg_ptr, fmt);
928 buffer.Bvsprintf(fmt, arg_ptr);
929 va_end(arg_ptr);
930 Jmsg(jcr, type, mtime, "%s", buffer.c_str());
931
932 return bRC_OK;
933 }
934
bareosDebugMsg(PluginContext * ctx,const char * file,int line,int level,const char * fmt,...)935 static bRC bareosDebugMsg(PluginContext* ctx,
936 const char* file,
937 int line,
938 int level,
939 const char* fmt,
940 ...)
941 {
942 va_list arg_ptr;
943 PoolMem buffer(PM_MESSAGE);
944
945 va_start(arg_ptr, fmt);
946 buffer.Bvsprintf(fmt, arg_ptr);
947 va_end(arg_ptr);
948 d_msg(file, line, level, "%s", buffer.c_str());
949
950 return bRC_OK;
951 }
952
bareosEditDeviceCodes(DeviceControlRecord * dcr,POOLMEM * & omsg,const char * imsg,const char * cmd)953 static char* bareosEditDeviceCodes(DeviceControlRecord* dcr,
954 POOLMEM*& omsg,
955 const char* imsg,
956 const char* cmd)
957 {
958 return edit_device_codes(dcr, omsg, imsg, cmd);
959 }
960
bareosLookupCryptoKey(const char * VolumeName)961 static char* bareosLookupCryptoKey(const char* VolumeName)
962 {
963 return lookup_crypto_cache_entry(VolumeName);
964 }
965
bareosUpdateVolumeInfo(DeviceControlRecord * dcr)966 static bool bareosUpdateVolumeInfo(DeviceControlRecord* dcr)
967 {
968 return dcr->DirGetVolumeInfo(GET_VOL_INFO_FOR_READ);
969 }
970
bareosUpdateTapeAlert(DeviceControlRecord * dcr,uint64_t flags)971 static void bareosUpdateTapeAlert(DeviceControlRecord* dcr, uint64_t flags)
972 {
973 utime_t now;
974 now = (utime_t)time(NULL);
975
976 UpdateDeviceTapealert(dcr->device_resource->resource_name_, flags, now);
977 }
978
bareosNewRecord(bool with_data)979 static DeviceRecord* bareosNewRecord(bool with_data)
980 {
981 return new_record(with_data);
982 }
983
bareosCopyRecordState(DeviceRecord * dst,DeviceRecord * src)984 static void bareosCopyRecordState(DeviceRecord* dst, DeviceRecord* src)
985 {
986 CopyRecordState(dst, src);
987 }
988
bareosFreeRecord(DeviceRecord * rec)989 static void bareosFreeRecord(DeviceRecord* rec) { FreeRecord(rec); }
990
991 } /* namespace storagedaemon */
992