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