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