1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2006-2012 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 and included
11 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 /*
25 * Contributed in 2012 by Inteos sp. z o.o.
26 */
27
28 /**
29 * Utility tool display various information about Bareos plugin,
30 * including but not limited to:
31 * - Name and Author of the plugin
32 * - Plugin License
33 * - Description
34 * - API version
35 * - Enabled functions, etc.
36 */
37 #include "include/bareos.h"
38 #include "filed/fd_plugins.h"
39 #include "dird/dir_plugins.h"
40 #include "stored/sd_plugins.h"
41 #include "assert_macro.h"
42 #ifndef __WIN32__
43 # include <dlfcn.h>
44 #endif
45 #ifndef PATH_MAX
46 # define PATH_MAX 4096
47 #endif
48
49 extern "C" {
50 typedef int (*loadPlugin)(void* bareos_plugin_interface_version,
51 void* bareos_core_functions,
52 void** plugin_information,
53 void** plugin_functions);
54 typedef int (*unloadPlugin)(void);
55 }
56 #define DEFAULT_API_VERSION 1
57
58 enum plugintype
59 {
60 DIRPLUGIN,
61 FDPLUGIN,
62 SDPLUGIN,
63 ERRORPLUGIN
64 };
65
66 /*
67 * PluginFunctions
68 */
69 typedef union _plugfuncs plugfuncs;
70 union _plugfuncs {
71 directordaemon::PluginFunctions pdirfuncs;
72 filedaemon::PluginFunctions pfdfuncs;
73 storagedaemon::PluginFunctions psdfuncs;
74 };
75
76 /*
77 * CoreFunctions
78 */
79 typedef struct _bareosfuncs bareosfuncs;
80 struct _bareosfuncs {
81 uint32_t size;
82 uint32_t version;
83 int (*registerBareosEvents)(void* ctx, ...);
84 int (*getBareosValue)(void* ctx, int var, void* value);
85 int (*setBareosValue)(void* ctx, int var, void* value);
86 int (*JobMessage)(void* ctx,
87 const char* file,
88 int line,
89 int type,
90 int64_t mtime,
91 const char* fmt,
92 ...);
93 int (*DebugMessage)(void* ctx,
94 const char* file,
95 int line,
96 int level,
97 const char* fmt,
98 ...);
99 void* (*bareosMalloc)(void* ctx, const char* file, int line, size_t size);
100 void (*bareosFree)(void* ctx, const char* file, int line, void* mem);
101 };
102
103 /*
104 * PluginApiDefinition
105 */
106 typedef union _bareosinfos bareosinfos;
107 union _bareosinfos {
108 directordaemon::PluginApiDefinition bdirinfo;
109 filedaemon::PluginApiDefinition bfdinfo;
110 storagedaemon::PluginApiDefinition bsdinfo;
111 };
112
113 typedef struct _progdata progdata;
114 struct _progdata {
115 bool verbose;
116 bool listinfo;
117 bool listfunc;
118 char* pluginfile;
119 void* pluginhandle;
120 int bapiversion;
121 int bplugtype;
122 gen_pluginInfo* plugin_information;
123 plugfuncs* plugin_functions;
124 };
125
126 /* memory allocation/deallocation */
127 #define MALLOC(size) (char*)malloc(size);
128
129 #define ASSERT_MEMORY(m) \
130 if (m == NULL) { \
131 printf("Error: memory allocation error!\n"); \
132 exit(10); \
133 }
134
135 #define FREE(ptr) \
136 if (ptr != NULL) { \
137 free(ptr); \
138 ptr = NULL; \
139 }
140
registerBareosEvents(void * ctx,...)141 int registerBareosEvents(void* ctx, ...) { return 0; };
142
getBareosValue(void * ctx,int var,void * value)143 int getBareosValue(void* ctx, int var, void* value) { return 0; };
144
setBareosValue(void * ctx,int var,void * value)145 int setBareosValue(void* ctx, int var, void* value) { return 0; };
146
DebugMessage(void * ctx,const char * file,int line,int level,const char * fmt,...)147 int DebugMessage(void* ctx,
148 const char* file,
149 int line,
150 int level,
151 const char* fmt,
152 ...)
153 {
154 #ifdef DEBUGMSG
155 printf("DG: %s:%d %s\n", file, line, fmt);
156 #endif
157 return 0;
158 };
159
JobMessage(void * ctx,const char * file,int line,int type,int64_t mtime,const char * fmt,...)160 int JobMessage(void* ctx,
161 const char* file,
162 int line,
163 int type,
164 int64_t mtime,
165 const char* fmt,
166 ...)
167 {
168 #ifdef DEBUGMSG
169 printf("JM: %s:%d <%d> %s\n", file, line, type, fmt);
170 #endif
171 return 0;
172 };
173
bareosMalloc(void * ctx,const char * file,int line,size_t size)174 void* bareosMalloc(void* ctx, const char* file, int line, size_t size)
175 {
176 return MALLOC(size);
177 };
178
bareosFree(void * ctx,const char * file,int line,void * mem)179 void bareosFree(void* ctx, const char* file, int line, void* mem)
180 {
181 FREE(mem);
182 };
183
184 /*
185 * displays a short help
186 */
PrintHelp(int argc,char * argv[])187 void PrintHelp(int argc, char* argv[])
188 {
189 printf(
190 "\n"
191 "Usage: bpluginfo [options] <plugin_file.so>\n"
192 " -v verbose\n"
193 " -i list plugin header information only (default)\n"
194 " -f list plugin functions information only\n"
195 " -a <api> bareos api version (default %d)\n"
196 " -h help screen\n"
197 "\n",
198 DEFAULT_API_VERSION);
199 }
200
201 /* allocates and resets a main program data variable */
allocpdata(void)202 progdata* allocpdata(void)
203 {
204 progdata* pdata;
205
206 pdata = (progdata*)malloc(sizeof(progdata));
207 ASSERT_MEMORY(pdata);
208 memset(pdata, 0, sizeof(progdata));
209
210 return pdata;
211 }
212
213 /* releases all allocated program data resources */
Freepdata(progdata * pdata)214 void Freepdata(progdata* pdata)
215 {
216 if (pdata->pluginfile) { FREE(pdata->pluginfile); }
217 FREE(pdata);
218 }
219
220 /*
221 * parse execution arguments and fills required pdata structure fields
222 *
223 * input:
224 * pdata - pointer to program data structure
225 * argc, argv - execution envinroment variables
226 * output:
227 * pdata - required structure fields
228 *
229 * supported options:
230 * -v verbose flag
231 * -i list plugin header info only (default)
232 * -f list implemented functions only
233 * -a bareos api version (default 1)
234 * -h help screen
235 */
ParseArgs(progdata * pdata,int argc,char * argv[])236 void ParseArgs(progdata* pdata, int argc, char* argv[])
237 {
238 int ch;
239 char* dirtmp;
240 char* progdir;
241
242 while ((ch = getopt(argc, argv, "a:fiv")) != -1) {
243 switch (ch) {
244 case 'a':
245 pdata->bapiversion = atoi(optarg);
246 break;
247
248 case 'f':
249 pdata->listfunc = true;
250 break;
251
252 case 'i':
253 pdata->listinfo = true;
254 break;
255
256 case 'v':
257 pdata->verbose = true;
258 break;
259
260 case '?':
261 default:
262 PrintHelp(argc, argv);
263 exit(0);
264 }
265 }
266 argc -= optind;
267 argv += optind;
268
269 if (argc < 1) {
270 PrintHelp(argc, argv);
271 exit(0);
272 }
273
274 if (!pdata->pluginfile) {
275 if (argv[0][0] != '/') {
276 dirtmp = MALLOC(PATH_MAX);
277 ASSERT_MEMORY(dirtmp);
278 progdir = MALLOC(PATH_MAX);
279 ASSERT_MEMORY(progdir);
280 dirtmp = getcwd(dirtmp, PATH_MAX);
281
282 strcat(dirtmp, "/");
283 strcat(dirtmp, argv[0]);
284
285 if (realpath(dirtmp, progdir) == NULL) {
286 /*
287 * Error in resolving path
288 */
289 FREE(progdir);
290 progdir = strdup(argv[0]);
291 }
292 pdata->pluginfile = strdup(progdir);
293 FREE(dirtmp);
294 FREE(progdir);
295 } else {
296 pdata->pluginfile = strdup(argv[0]);
297 }
298 }
299 }
300
301 /*
302 * checks a plugin type based on a plugin magic string
303 *
304 * input:
305 * pdata - program data with plugin info structure
306 * output:
307 * int - enum plugintype
308 */
Getplugintype(progdata * pdata)309 int Getplugintype(progdata* pdata)
310 {
311 ASSERT_NVAL_RET_V(pdata, ERRORPLUGIN);
312
313 gen_pluginInfo* plugin_information = pdata->plugin_information;
314
315 ASSERT_NVAL_RET_V(plugin_information, ERRORPLUGIN);
316
317 if (plugin_information->plugin_magic
318 && bstrcmp(plugin_information->plugin_magic, DIR_PLUGIN_MAGIC)) {
319 return DIRPLUGIN;
320 } else {
321 if (plugin_information->plugin_magic
322 && bstrcmp(plugin_information->plugin_magic, FD_PLUGIN_MAGIC)) {
323 return FDPLUGIN;
324 } else {
325 if (plugin_information->plugin_magic
326 && bstrcmp(plugin_information->plugin_magic, SD_PLUGIN_MAGIC)) {
327 return SDPLUGIN;
328 } else {
329 return ERRORPLUGIN;
330 }
331 }
332 }
333 }
334
335 /*
336 * prints any available information about a plugin
337 *
338 * input:
339 * pdata - program data with plugin info structure
340 * output:
341 * printed info
342 */
DumpPluginfo(progdata * pdata)343 void DumpPluginfo(progdata* pdata)
344 {
345 ASSERT_NVAL_RET(pdata);
346
347 gen_pluginInfo* plugin_information = pdata->plugin_information;
348
349 ASSERT_NVAL_RET(plugin_information);
350
351 plugfuncs* plugin_functions = pdata->plugin_functions;
352
353 ASSERT_NVAL_RET(plugin_functions);
354
355 switch (pdata->bplugtype) {
356 case DIRPLUGIN:
357 printf("\nPlugin type:\t\tBareos Director plugin\n");
358 break;
359 case FDPLUGIN:
360 printf("\nPlugin type:\t\tBareos File Daemon plugin\n");
361 break;
362 case SDPLUGIN:
363 printf("\nPlugin type:\t\tBareos Storage plugin\n");
364 break;
365 default:
366 printf("\nUnknown plugin type or other Error\n\n");
367 return;
368 }
369
370 if (pdata->verbose) {
371 printf("Plugin magic:\t\t%s\n", NPRT(plugin_information->plugin_magic));
372 }
373 printf("Plugin version:\t\t%s\n", plugin_information->plugin_version);
374 printf("Plugin release date:\t%s\n", NPRT(plugin_information->plugin_date));
375 printf("Plugin author:\t\t%s\n", NPRT(plugin_information->plugin_author));
376 printf("Plugin licence:\t\t%s\n", NPRT(plugin_information->plugin_license));
377 printf("Plugin description:\t%s\n",
378 NPRT(plugin_information->plugin_description));
379 printf("Plugin API version:\t%d\n", plugin_information->version);
380 if (plugin_information->plugin_usage) {
381 printf("Plugin usage:\n%s\n", plugin_information->plugin_usage);
382 }
383 }
384
385 /*
386 * prints any available information about plugin' functions
387 *
388 * input:
389 * pdata - program data with plugin info structure
390 * output:
391 * printed info
392 */
DumpPlugfuncs(progdata * pdata)393 void DumpPlugfuncs(progdata* pdata)
394 {
395 ASSERT_NVAL_RET(pdata);
396
397 plugfuncs* plugin_functions = pdata->plugin_functions;
398
399 ASSERT_NVAL_RET(plugin_functions);
400
401 printf("\nPlugin functions:\n");
402
403 switch (pdata->bplugtype) {
404 case DIRPLUGIN:
405 if (pdata->verbose) {
406 if (plugin_functions->pdirfuncs.newPlugin) { printf(" newPlugin()\n"); }
407 if (plugin_functions->pdirfuncs.freePlugin) {
408 printf(" freePlugin()\n");
409 }
410 }
411 if (plugin_functions->pdirfuncs.getPluginValue) {
412 printf(" getPluginValue()\n");
413 }
414 if (plugin_functions->pdirfuncs.setPluginValue) {
415 printf(" setPluginValue()\n");
416 }
417 if (plugin_functions->pdirfuncs.handlePluginEvent) {
418 printf(" handlePluginEvent()\n");
419 }
420 break;
421 case FDPLUGIN:
422 if (pdata->verbose) {
423 if (plugin_functions->pfdfuncs.newPlugin) { printf(" newPlugin()\n"); }
424 if (plugin_functions->pfdfuncs.freePlugin) {
425 printf(" freePlugin()\n");
426 }
427 }
428 if (plugin_functions->pfdfuncs.getPluginValue) {
429 printf(" getPluginValue()\n");
430 }
431 if (plugin_functions->pfdfuncs.setPluginValue) {
432 printf(" setPluginValue()\n");
433 }
434 if (plugin_functions->pfdfuncs.handlePluginEvent) {
435 printf(" handlePluginEvent()\n");
436 }
437 if (plugin_functions->pfdfuncs.startBackupFile) {
438 printf(" startBackupFile()\n");
439 }
440 if (plugin_functions->pfdfuncs.endBackupFile) {
441 printf(" endBackupFile()\n");
442 }
443 if (plugin_functions->pfdfuncs.startRestoreFile) {
444 printf(" startRestoreFile()\n");
445 }
446 if (plugin_functions->pfdfuncs.endRestoreFile) {
447 printf(" endRestoreFile()\n");
448 }
449 if (plugin_functions->pfdfuncs.pluginIO) { printf(" pluginIO()\n"); }
450 if (plugin_functions->pfdfuncs.createFile) { printf(" createFile()\n"); }
451 if (plugin_functions->pfdfuncs.setFileAttributes) {
452 printf(" setFileAttributes()\n");
453 }
454 if (plugin_functions->pfdfuncs.checkFile) { printf(" checkFile()\n"); }
455 break;
456 case SDPLUGIN:
457 if (pdata->verbose) {
458 if (plugin_functions->psdfuncs.newPlugin) { printf(" newPlugin()\n"); }
459 if (plugin_functions->psdfuncs.freePlugin) {
460 printf(" freePlugin()\n");
461 }
462 }
463 if (plugin_functions->psdfuncs.getPluginValue) {
464 printf(" getPluginValue()\n");
465 }
466 if (plugin_functions->psdfuncs.setPluginValue) {
467 printf(" setPluginValue()\n");
468 }
469 if (plugin_functions->psdfuncs.handlePluginEvent) {
470 printf(" handlePluginEvent()\n");
471 }
472 break;
473 default:
474 printf("\nUnknown plugin type or other Error\n\n");
475 }
476 }
477
478 /*
479 * input parameters:
480 * argv[0] [options] <plugin_filename.so>
481 *
482 * exit codes:
483 * 0 - success
484 * 1 - cannot load a plugin
485 * 2 - cannot find a loadPlugin function
486 * 3 - cannot find an unloadPlugin function
487 * 10 - not enough memory
488 */
main(int argc,char * argv[])489 int main(int argc, char* argv[])
490 {
491 progdata* pdata;
492 loadPlugin loadplugfunc;
493 unloadPlugin unloadplugfunc;
494 bareosfuncs bareos_core_functions = {
495 sizeof(bareos_core_functions),
496 1,
497 registerBareosEvents,
498 getBareosValue,
499 setBareosValue,
500 JobMessage,
501 DebugMessage,
502 bareosMalloc,
503 bareosFree,
504 };
505 bareosinfos bareos_plugin_interface_version;
506
507 pdata = allocpdata();
508 ParseArgs(pdata, argc, argv);
509
510 bareos_plugin_interface_version.bfdinfo.size
511 = sizeof(bareos_plugin_interface_version);
512 bareos_plugin_interface_version.bfdinfo.version = DEFAULT_API_VERSION;
513
514 pdata->pluginhandle = dlopen(pdata->pluginfile, RTLD_LAZY);
515 if (pdata->pluginhandle == NULL) {
516 printf("\nCannot load a plugin: %s\n\n", dlerror());
517 Freepdata(pdata);
518 exit(1);
519 }
520
521 loadplugfunc = (loadPlugin)dlsym(pdata->pluginhandle, "loadPlugin");
522 if (loadplugfunc == NULL) {
523 printf("\nCannot find loadPlugin function: %s\n", dlerror());
524 printf("\nWhether the file is a really Bareos plugin?\n\n");
525 Freepdata(pdata);
526 exit(2);
527 }
528
529 unloadplugfunc = (unloadPlugin)dlsym(pdata->pluginhandle, "unloadPlugin");
530 if (unloadplugfunc == NULL) {
531 printf("\nCannot find unloadPlugin function: %s\n", dlerror());
532 printf("\nWhether the file is a really Bareos plugin?\n\n");
533 Freepdata(pdata);
534 exit(3);
535 }
536
537 if (pdata->bapiversion > 0) {
538 bareos_plugin_interface_version.bdirinfo.version = pdata->bapiversion;
539 }
540
541 loadplugfunc(&bareos_plugin_interface_version, &bareos_core_functions,
542 (void**)&pdata->plugin_information,
543 (void**)&pdata->plugin_functions);
544
545 pdata->bplugtype = Getplugintype(pdata);
546
547 if (!pdata->listfunc) { DumpPluginfo(pdata); }
548 if ((!pdata->listinfo && pdata->listfunc) || pdata->verbose) {
549 DumpPlugfuncs(pdata);
550 }
551 printf("\n");
552
553 unloadplugfunc();
554
555 dlclose(pdata->pluginhandle);
556
557 Freepdata(pdata);
558
559 return 0;
560 }
561