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