]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/tools/bpluginfo.c
Change copyright as per agreement with FSFE + update copyright year
[bacula/bacula] / bacula / src / tools / bpluginfo.c
1 /*
2  * Contributed in 2012 by Inteos sp. z o.o.
3  *
4  * Utility tool display various information about Bacula plugin,
5  * including but not limited to:
6  * - Name and Author of the plugin
7  * - Plugin License
8  * - Description
9  * - API version
10  * - Enabled functions, etc.
11  */
12 /*
13    Bacula(R) - The Network Backup Solution
14
15    Copyright (C) 2012-2016 Kern Sibbald
16
17    The original author of Bacula is Kern Sibbald, with contributions
18    from many others, a complete list can be found in the file AUTHORS.
19
20    You may use this file and others of this release according to the
21    license defined in the LICENSE file, which includes the Affero General
22    Public License, v3.0 ("AGPLv3") and some additional permissions and
23    terms pursuant to its AGPLv3 Section 7.
24
25    This notice must be preserved when any source code is 
26    conveyed and/or propagated.
27
28    Bacula(R) is a registered trademark of Kern Sibbald.
29 */
30
31 #ifdef working /* currently will not compile KES 21 Nov 2015 */
32
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <limits.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <stdint.h>
39 #ifndef __WIN32__
40 #include <dlfcn.h>
41 #endif
42 #include "bacula.h"
43 #include "../filed/fd_plugins.h"
44 #include "../dird/dir_plugins.h"
45 // I can't include sd_plugins.h here ...
46 #include "../stored/stored.h"
47 #include "assert_macro.h"
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 enum plugintype {
56    DIRPLUGIN,
57    FDPLUGIN,
58    SDPLUGIN,
59    ERRORPLUGIN,
60 };
61
62 /*
63  * pDirInfo
64  * pInfo
65  * psdInfo
66  */
67 typedef union _pluginfo pluginfo;
68 union _pluginfo {
69    pDirInfo pdirinfo;
70    pInfo pfdinfo;
71    psdInfo psdinfo;
72 };
73
74 /*
75  * pDirFuncs
76  * pFuncs
77  * psdFuncs
78  */
79 typedef union _plugfuncs plugfuncs;
80 union _plugfuncs {
81    pDirFuncs pdirfuncs;
82    pFuncs pfdfuncs;
83    psdFuncs psdfuncs;
84 };
85
86 /*
87  * bDirFuncs
88  * bFuncs
89  * bsdFuncs
90  */
91 /*
92  * TODO: change to union
93  *
94 typedef union _baculafuncs baculafuncs;
95 union _baculafuncs {
96    bDirFuncs bdirfuncs;
97    bFuncs bfdfuncs;
98    bsdFuncs bsdfuncs;
99 };
100 */
101 typedef struct _baculafuncs baculafuncs;
102 struct _baculafuncs {
103    uint32_t size;
104    uint32_t version;
105    int (*registerBaculaEvents) (void *ctx, ...);
106    int (*getBaculaValue) (void *ctx, int var, void *value);
107    int (*setBaculaValue) (void *ctx, int var, void *value);
108    int (*JobMessage) (void *ctx, const char *file, int line, int type, int64_t mtime,
109             const char *fmt, ...);
110    int (*DebugMessage) (void *ctx, const char *file, int line, int level,
111          const char *fmt, ...);
112    void *(*baculaMalloc) (void *ctx, const char *file, int line, size_t size);
113    void (*baculaFree) (void *ctx, const char *file, int line, void *mem);
114 };
115
116 /*
117  * bDirInfo
118  * bInfo
119  * bsdInfo
120  */
121 typedef union _baculainfos baculainfos;
122 union _baculainfos {
123    bDirInfo bdirinfo;
124    bInfo bfdinfo;
125    bsdInfo bsdinfo;
126 };
127
128 /*
129 typedef struct _baculainfos baculainfos;
130 struct _baculainfos {
131    uint32_t size;
132    uint32_t version;
133 };
134 */
135
136 typedef struct _progdata progdata;
137 struct _progdata {
138    int verbose;
139    int listinfo;
140    int listfunc;
141    char *pluginfile;
142    void *pluginhandle;
143    int bapiversion;
144    int bplugtype;
145    pluginfo *pinfo;
146    plugfuncs *pfuncs;
147 };
148
149 /* memory allocation/deallocation */
150 #define MALLOC(size) \
151    (char *) bmalloc ( size );
152
153 #define ASSERT_MEMORY(m) \
154    if ( m == NULL ){ \
155       printf ( "Error: memory allocation error!\n" ); \
156       exit (10); \
157    }
158
159 #define FREE(ptr) \
160    if ( ptr != NULL ){ \
161       bfree ( ptr ); \
162       ptr = NULL; \
163    }
164
165 int registerBaculaEvents(void *ctx, ...)
166 {
167    return 0;
168 };
169
170 int getBaculaValue(void *ctx, int var, void *value)
171 {
172    return 0;
173 };
174
175 int setBaculaValue(void *ctx, int var, void *value)
176 {
177    return 0;
178 };
179
180 int DebugMessage(void *ctx, const char *file, int line, int level, const char *fmt, ...)
181 {
182 #ifdef DEBUGMSG
183    printf("DG: %s:%d %s\n", file, line, fmt);
184 #endif
185    return 0;
186 };
187
188 int JobMessage(void *ctx, const char *file, int line, int type, int64_t mtime,
189           const char *fmt, ...)
190 {
191 #ifdef DEBUGMSG
192    printf("JM: %s:%d <%d> %s\n", file, line, type, fmt);
193 #endif
194    return 0;
195 };
196
197 void *baculaMalloc(void *ctx, const char *file, int line, size_t size)
198 {
199    return MALLOC(size);
200 };
201
202 void baculaFree(void *ctx, const char *file, int line, void *mem)
203 {
204    FREE(mem);
205 };
206
207 /*
208  * displays a short help
209  */
210 void print_help(int argc, char *argv[])
211 {
212
213    printf("\n"
214      "Usage: bpluginfo [options] <plugin_file.so>\n"
215      "       -v          verbose\n"
216      "       -i          list plugin header information only (default)\n"
217      "       -f          list plugin functions information only\n"
218      "       -a <api>    bacula api version (default %d)\n"
219      "       -h          help screen\n" "\n", DEFAULT_API_VERSION);
220 }
221
222 /* allocates and resets a main program data variable */
223 progdata *allocpdata(void)
224 {
225
226    progdata *pdata;
227
228    pdata = (progdata *) bmalloc(sizeof(progdata));
229    ASSERT_MEMORY(pdata);
230    memset(pdata, 0, sizeof(progdata));
231
232    return pdata;
233 }
234
235 /* releases all allocated program data resources */
236 void freepdata(progdata * pdata)
237 {
238
239    if (pdata->pluginfile) {
240       FREE(pdata->pluginfile);
241    }
242    FREE(pdata);
243 }
244
245 /*
246  * parse execution arguments and fills required pdata structure fields
247  *
248  * input:
249  *    pdata - pointer to program data structure
250  *    argc, argv - execution envinroment variables
251  * output:
252  *    pdata - required structure fields
253  *
254  * supported options:
255  * -v    verbose flag
256  * -i    list plugin header info only (default)
257  * -f    list implemented functions only
258  * -a    bacula api version (default 1)
259  * -h    help screen
260  */
261 void parse_args(progdata * pdata, int argc, char *argv[])
262 {
263
264    int i;
265    char *dirtmp;
266    char *progdir;
267    int api;
268    int s;
269
270    if (argc < 2) {
271       /* TODO - add a real help screen */
272       printf("\nNot enough parameters!\n");
273       print_help(argc, argv);
274       exit(1);
275    }
276
277    if (argc > 5) {
278       /* TODO - add a real help screen */
279       printf("\nToo many parameters!\n");
280       print_help(argc, argv);
281       exit(1);
282    }
283
284    for (i = 1; i < argc; i++) {
285       if (strcmp(argv[i], "-h") == 0) {
286          /* help screen */
287          print_help(argc, argv);
288          exit(0);
289       }
290       if (strcmp(argv[i], "-v") == 0) {
291           /* verbose option */
292           pdata->verbose = 1;
293           continue;
294       }
295       if (strcmp(argv[i], "-f") == 0) {
296          /* functions list */
297          pdata->listfunc = 1;
298          continue;
299       }
300       if (strcmp(argv[i], "-i") == 0) {
301          /* header list */
302          pdata->listinfo = 1;
303          continue;
304       }
305       if (strcmp(argv[i], "-a") == 0) {
306          /* bacula api version */
307          if (i < argc - 1) {
308             s = sscanf(argv[i + 1], "%d", &api);
309             if (s == 1) {
310                pdata->bapiversion = api;
311                i++;
312                continue;
313             }
314          }
315          printf("\nAPI version number required!\n");
316          print_help(argc, argv);
317          exit(1);
318       }
319       if (!pdata->pluginfile) {
320           if (argv[i][0] != '/') {
321              dirtmp = MALLOC(PATH_MAX);
322              ASSERT_MEMORY(dirtmp);
323              progdir = MALLOC(PATH_MAX);
324              ASSERT_MEMORY(progdir);
325              dirtmp = getcwd(dirtmp, PATH_MAX);
326
327              strcat(dirtmp, "/");
328              strcat(dirtmp, argv[i]);
329
330              if (realpath(dirtmp, progdir) == NULL) {
331                 /* error in resolving path */
332                 FREE(progdir);
333                 progdir = bstrdup(argv[i]);
334              }
335              pdata->pluginfile = bstrdup(progdir);
336              FREE(dirtmp);
337              FREE(progdir);
338           } else {
339              pdata->pluginfile = bstrdup(argv[i]);
340           }
341     continue;
342       }
343    }
344 }
345
346 /*
347  * checks a plugin type based on a plugin magic string
348  *
349  * input:
350  *    pdata - program data with plugin info structure
351  * output:
352  *    int - enum plugintype
353  */
354 int getplugintype(progdata * pdata)
355 {
356
357    ASSERT_NVAL_RET_V(pdata, ERRORPLUGIN);
358
359    pluginfo *pinfo = pdata->pinfo;
360
361    ASSERT_NVAL_RET_V(pinfo, ERRORPLUGIN);
362
363    if (pinfo->pdirinfo.plugin_magic &&
364        strcmp(pinfo->pdirinfo.plugin_magic, DIR_PLUGIN_MAGIC) == 0) {
365       return DIRPLUGIN;
366    } else
367       if (pinfo->pfdinfo.plugin_magic &&
368      strcmp(pinfo->pfdinfo.plugin_magic, FD_PLUGIN_MAGIC) == 0) {
369       return FDPLUGIN;
370    } else
371       if (pinfo->psdinfo.plugin_magic &&
372      strcmp(pinfo->psdinfo.plugin_magic, SD_PLUGIN_MAGIC) == 0) {
373       return SDPLUGIN;
374    } else {
375       return ERRORPLUGIN;
376    }
377 }
378
379 /*
380  * prints any available information about a plugin
381  *
382  * input:
383  *    pdata - program data with plugin info structure
384  * output:
385  *    printed info
386  */
387 void dump_pluginfo(progdata * pdata)
388 {
389
390    ASSERT_NVAL_RET(pdata);
391
392    pluginfo *pinfo = pdata->pinfo;
393
394    ASSERT_NVAL_RET(pinfo);
395
396    plugfuncs *pfuncs = pdata->pfuncs;
397
398    ASSERT_NVAL_RET(pfuncs);
399
400    switch (pdata->bplugtype) {
401    case DIRPLUGIN:
402       printf("\nPlugin type:\t\tBacula Director plugin\n");
403       if (pdata->verbose) {
404          printf("Plugin magic:\t\t%s\n", NPRT(pinfo->pdirinfo.plugin_magic));
405       }
406       printf("Plugin version:\t\t%s\n", pinfo->pdirinfo.plugin_version);
407       printf("Plugin release date:\t%s\n", NPRT(pinfo->pdirinfo.plugin_date));
408       printf("Plugin author:\t\t%s\n", NPRT(pinfo->pdirinfo.plugin_author));
409       printf("Plugin licence:\t\t%s\n", NPRT(pinfo->pdirinfo.plugin_license));
410       printf("Plugin description:\t%s\n", NPRT(pinfo->pdirinfo.plugin_description));
411       printf("Plugin API version:\t%d\n", pinfo->pdirinfo.version);
412       break;
413    case FDPLUGIN:
414       printf("\nPlugin type:\t\tFile Daemon plugin\n");
415       if (pdata->verbose) {
416          printf("Plugin magic:\t\t%s\n", NPRT(pinfo->pfdinfo.plugin_magic));
417       }
418       printf("Plugin version:\t\t%s\n", pinfo->pfdinfo.plugin_version);
419       printf("Plugin release date:\t%s\n", NPRT(pinfo->pfdinfo.plugin_date));
420       printf("Plugin author:\t\t%s\n", NPRT(pinfo->pfdinfo.plugin_author));
421       printf("Plugin licence:\t\t%s\n", NPRT(pinfo->pfdinfo.plugin_license));
422       printf("Plugin description:\t%s\n", NPRT(pinfo->pfdinfo.plugin_description));
423       printf("Plugin API version:\t%d\n", pinfo->pfdinfo.version);
424       break;
425    case SDPLUGIN:
426       printf("\nPlugin type:\t\tBacula Storage plugin\n");
427       if (pdata->verbose) {
428          printf("Plugin magic:\t\t%s\n", NPRT(pinfo->psdinfo.plugin_magic));
429       }
430       printf("Plugin version:\t\t%s\n", pinfo->psdinfo.plugin_version);
431       printf("Plugin release date:\t%s\n", NPRT(pinfo->psdinfo.plugin_date));
432       printf("Plugin author:\t\t%s\n", NPRT(pinfo->psdinfo.plugin_author));
433       printf("Plugin licence:\t\t%s\n", NPRT(pinfo->psdinfo.plugin_license));
434       printf("Plugin description:\t%s\n", NPRT(pinfo->psdinfo.plugin_description));
435       printf("Plugin API version:\t%d\n", pinfo->psdinfo.version);
436       break;
437    default:
438       printf("\nUnknown plugin type or other Error\n\n");
439    }
440 }
441
442 /*
443  * prints any available information about plugin' functions
444  *
445  * input:
446  *    pdata - program data with plugin info structure
447  * output:
448  *    printed info
449  */
450 void dump_plugfuncs(progdata * pdata)
451 {
452
453    ASSERT_NVAL_RET(pdata);
454
455    plugfuncs *pfuncs = pdata->pfuncs;
456
457    ASSERT_NVAL_RET(pfuncs);
458
459    printf("\nPlugin functions:\n");
460
461    switch (pdata->bplugtype) {
462    case DIRPLUGIN:
463       if (pdata->verbose) {
464           if (pfuncs->pdirfuncs.newPlugin) {
465              printf(" newPlugin()\n");
466           }
467           if (pfuncs->pdirfuncs.freePlugin) {
468              printf(" freePlugin()\n");
469           }
470       }
471       if (pfuncs->pdirfuncs.getPluginValue) {
472          printf(" getPluginValue()\n");
473       }
474       if (pfuncs->pdirfuncs.setPluginValue) {
475          printf(" setPluginValue()\n");
476       }
477       if (pfuncs->pdirfuncs.handlePluginEvent) {
478          printf(" handlePluginEvent()\n");
479       }
480       break;
481    case FDPLUGIN:
482       if (pdata->verbose) {
483           if (pfuncs->pfdfuncs.newPlugin) {
484              printf(" newPlugin()\n");
485           }
486           if (pfuncs->pfdfuncs.freePlugin) {
487              printf(" freePlugin()\n");
488           }
489       }
490       if (pfuncs->pfdfuncs.getPluginValue) {
491          printf(" getPluginValue()\n");
492       }
493       if (pfuncs->pfdfuncs.setPluginValue) {
494          printf(" setPluginValue()\n");
495       }
496       if (pfuncs->pfdfuncs.handlePluginEvent) {
497          printf(" handlePluginEvent()\n");
498       }
499       if (pfuncs->pfdfuncs.startBackupFile) {
500          printf(" startBackupFile()\n");
501       }
502       if (pfuncs->pfdfuncs.endBackupFile) {
503          printf(" endBackupFile()\n");
504       }
505       if (pfuncs->pfdfuncs.startRestoreFile) {
506          printf(" startRestoreFile()\n");
507       }
508       if (pfuncs->pfdfuncs.endRestoreFile) {
509          printf(" endRestoreFile()\n");
510       }
511       if (pfuncs->pfdfuncs.pluginIO) {
512          printf(" pluginIO()\n");
513       }
514       if (pfuncs->pfdfuncs.createFile) {
515          printf(" createFile()\n");
516       }
517       if (pfuncs->pfdfuncs.setFileAttributes) {
518          printf(" setFileAttributes()\n");
519       }
520       if (pfuncs->pfdfuncs.checkFile) {
521          printf(" checkFile()\n");
522       }
523       break;
524    case SDPLUGIN:
525       if (pdata->verbose) {
526           if (pfuncs->psdfuncs.newPlugin) {
527              printf(" newPlugin()\n");
528           }
529           if (pfuncs->psdfuncs.freePlugin) {
530              printf(" freePlugin()\n");
531           }
532       }
533       if (pfuncs->psdfuncs.getPluginValue) {
534          printf(" getPluginValue()\n");
535       }
536       if (pfuncs->psdfuncs.setPluginValue) {
537          printf(" setPluginValue()\n");
538       }
539       if (pfuncs->psdfuncs.handlePluginEvent) {
540          printf(" handlePluginEvent()\n");
541       }
542       break;
543    default:
544       printf("\nUnknown plugin type or other Error\n\n");
545    }
546 }
547
548 /*
549  * input parameters:
550  *    argv[0] [options] <plugin_filename.so>
551  *
552  * exit codes:
553  *    0 - success
554  *    1 - cannot load a plugin
555  *    2 - cannot find a loadPlugin function
556  *    3 - cannot find an unloadPlugin function
557  *    10 - not enough memory
558  */
559 int main(int argc, char *argv[])
560 {
561
562    progdata *pdata;
563    loadPlugin loadplugfunc;
564    unloadPlugin unloadplugfunc;
565    baculafuncs bfuncs = {
566       sizeof(bfuncs),
567       1,
568       registerBaculaEvents,
569       getBaculaValue,
570       setBaculaValue,
571       JobMessage,
572       DebugMessage,
573       baculaMalloc,
574       baculaFree,
575    };
576    baculainfos binfos;
577
578    pdata = allocpdata();
579    parse_args(pdata, argc, argv);
580
581    binfos.bfdinfo.size = sizeof(binfos);
582    binfos.bfdinfo.version = DEFAULT_API_VERSION;
583
584    pdata->pluginhandle = dlopen(pdata->pluginfile, RTLD_LAZY);
585    if (pdata->pluginhandle == NULL) {
586       printf("\nCannot load a plugin: %s\n\n", dlerror());
587       freepdata(pdata);
588       exit(1);
589    }
590
591    loadplugfunc = (loadPlugin) dlsym(pdata->pluginhandle, "loadPlugin");
592    if (loadplugfunc == NULL) {
593       printf("\nCannot find loadPlugin function: %s\n", dlerror());
594       printf("\nWhether the file is a really Bacula plugin?\n\n");
595       freepdata(pdata);
596       exit(2);
597    }
598
599    unloadplugfunc = (unloadPlugin) dlsym(pdata->pluginhandle, "unloadPlugin");
600    if (unloadplugfunc == NULL) {
601       printf("\nCannot find unloadPlugin function: %s\n", dlerror());
602       printf("\nWhether the file is a really Bacula plugin?\n\n");
603       freepdata(pdata);
604       exit(3);
605    }
606
607    if (pdata->bapiversion > 0) {
608       binfos.bdirinfo.version = pdata->bapiversion;
609    }
610
611    loadplugfunc(&binfos, &bfuncs, (void **)&pdata->pinfo, (void **)&pdata->pfuncs);
612
613    pdata->bplugtype = getplugintype(pdata);
614
615    if (!pdata->listfunc) {
616       dump_pluginfo(pdata);
617    }
618    if ((!pdata->listinfo && pdata->listfunc) || pdata->verbose) {
619       dump_plugfuncs(pdata);
620    }
621    printf("\n");
622
623    unloadplugfunc();
624
625    dlclose(pdata->pluginhandle);
626
627    freepdata(pdata);
628
629    return 0;
630 }
631
632 #endif /* working */