2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2011 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
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.
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 General Public License for more details.
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
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Main program to test loading and running Bacula plugins.
30 * Destined to become Bacula pluginloader, ...
32 * Kern Sibbald, October 2007
36 #include "sd_plugins.h"
38 const int dbglvl = 50;
39 const char *plugin_type = "-sd.so";
42 /* Forward referenced functions */
43 static bRC baculaGetValue(bpContext *ctx, bsdrVariable var, void *value);
44 static bRC baculaSetValue(bpContext *ctx, bsdwVariable var, void *value);
45 static bRC baculaRegisterEvents(bpContext *ctx, ...);
46 static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
47 int type, utime_t mtime, const char *fmt, ...);
48 static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
49 int level, const char *fmt, ...);
50 static char *baculaEditDeviceCodes(DCR *dcr, char *omsg,
51 const char *imsg, const char *cmd);
52 static bool is_plugin_compatible(Plugin *plugin);
56 static bsdInfo binfo = {
58 SD_PLUGIN_INTERFACE_VERSION
61 /* Bacula entry points */
62 static bsdFuncs bfuncs = {
64 SD_PLUGIN_INTERFACE_VERSION,
74 * Bacula private context
77 JCR *jcr; /* jcr for plugin */
78 bRC rc; /* last return code */
79 bool disabled; /* set if plugin disabled */
82 static bool is_plugin_disabled(bpContext *plugin_ctx)
88 b_ctx = (bacula_ctx *)plugin_ctx->bContext;
89 return b_ctx->disabled;
93 static bool is_plugin_disabled(JCR *jcr)
95 return is_plugin_disabled(jcr->plugin_ctx);
100 * Create a plugin event
102 int generate_plugin_event(JCR *jcr, bsdEventType eventType, void *value)
104 bpContext *plugin_ctx;
110 if (!bplugin_list || !jcr || !jcr->plugin_ctx_list) {
111 return bRC_OK; /* Return if no plugins loaded */
113 if (jcr->is_job_canceled()) {
117 bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
118 event.eventType = eventType;
120 Dmsg2(dbglvl, "sd-plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
122 foreach_alist(plugin, bplugin_list) {
123 plugin_ctx = &plugin_ctx_list[i++];
124 if (is_plugin_disabled(plugin_ctx)) {
127 rc = sdplug_func(plugin)->handlePluginEvent(plugin_ctx, &event, value);
137 * Print to file the plugin info.
139 void dump_sd_plugin(Plugin *plugin, FILE *fp)
144 psdInfo *info = (psdInfo *) plugin->pinfo;
145 fprintf(fp, "\tversion=%d\n", info->version);
146 fprintf(fp, "\tdate=%s\n", NPRTB(info->plugin_date));
147 fprintf(fp, "\tmagic=%s\n", NPRTB(info->plugin_magic));
148 fprintf(fp, "\tauthor=%s\n", NPRTB(info->plugin_author));
149 fprintf(fp, "\tlicence=%s\n", NPRTB(info->plugin_license));
150 fprintf(fp, "\tversion=%s\n", NPRTB(info->plugin_version));
151 fprintf(fp, "\tdescription=%s\n", NPRTB(info->plugin_description));
155 * This entry point is called internally by Bacula to ensure
156 * that the plugin IO calls come into this code.
158 void load_sd_plugins(const char *plugin_dir)
162 Dmsg0(dbglvl, "Load sd plugins\n");
164 Dmsg0(dbglvl, "No sd plugin dir!\n");
167 bplugin_list = New(alist(10, not_owned_by_alist));
168 if (!load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type,
169 is_plugin_compatible)) {
170 /* Either none found, or some error */
171 if (bplugin_list->size() == 0) {
174 Dmsg0(dbglvl, "No plugins loaded\n");
179 * Verify that the plugin is acceptable, and print information
182 foreach_alist(plugin, bplugin_list) {
183 Jmsg(NULL, M_INFO, 0, _("Loaded plugin: %s\n"), plugin->file);
184 Dmsg1(dbglvl, "Loaded plugin: %s\n", plugin->file);
187 Dmsg1(dbglvl, "num plugins=%d\n", bplugin_list->size());
188 dbg_plugin_add_hook(dump_sd_plugin);
192 * Check if a plugin is compatible. Called by the load_plugin function
193 * to allow us to verify the plugin.
195 static bool is_plugin_compatible(Plugin *plugin)
197 psdInfo *info = (psdInfo *)plugin->pinfo;
198 Dmsg0(50, "is_plugin_compatible called\n");
199 if (debug_level >= 50) {
200 dump_sd_plugin(plugin, stdin);
202 if (strcmp(info->plugin_magic, SD_PLUGIN_MAGIC) != 0) {
203 Jmsg(NULL, M_ERROR, 0, _("Plugin magic wrong. Plugin=%s wanted=%s got=%s\n"),
204 plugin->file, SD_PLUGIN_MAGIC, info->plugin_magic);
205 Dmsg3(50, "Plugin magic wrong. Plugin=%s wanted=%s got=%s\n",
206 plugin->file, SD_PLUGIN_MAGIC, info->plugin_magic);
210 if (info->version != SD_PLUGIN_INTERFACE_VERSION) {
211 Jmsg(NULL, M_ERROR, 0, _("Plugin version incorrect. Plugin=%s wanted=%d got=%d\n"),
212 plugin->file, SD_PLUGIN_INTERFACE_VERSION, info->version);
213 Dmsg3(50, "Plugin version incorrect. Plugin=%s wanted=%d got=%d\n",
214 plugin->file, SD_PLUGIN_INTERFACE_VERSION, info->version);
217 if (strcmp(info->plugin_license, "Bacula AGPLv3") != 0 &&
218 strcmp(info->plugin_license, "AGPLv3") != 0 &&
219 strcmp(info->plugin_license, "Bacula Systems(R) SA") != 0) {
220 Jmsg(NULL, M_ERROR, 0, _("Plugin license incompatible. Plugin=%s license=%s\n"),
221 plugin->file, info->plugin_license);
222 Dmsg2(50, "Plugin license incompatible. Plugin=%s license=%s\n",
223 plugin->file, info->plugin_license);
226 if (info->size != sizeof(psdInfo)) {
227 Jmsg(NULL, M_ERROR, 0,
228 _("Plugin size incorrect. Plugin=%s wanted=%d got=%d\n"),
229 plugin->file, sizeof(psdInfo), info->size);
238 * Create a new instance of each plugin for this Job
240 void new_plugins(JCR *jcr)
245 Dmsg0(dbglvl, "=== enter new_plugins ===\n");
247 Dmsg0(dbglvl, "No sd plugin list!\n");
250 if (jcr->is_job_canceled()) {
254 int num = bplugin_list->size();
256 Dmsg1(dbglvl, "sd-plugin-list size=%d\n", num);
261 jcr->plugin_ctx_list = (bpContext *)malloc(sizeof(bpContext) * num);
263 bpContext *plugin_ctx_list = jcr->plugin_ctx_list;
264 Dmsg2(dbglvl, "Instantiate sd-plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
265 foreach_alist(plugin, bplugin_list) {
266 /* Start a new instance of each plugin */
267 bacula_ctx *b_ctx = (bacula_ctx *)malloc(sizeof(bacula_ctx));
268 memset(b_ctx, 0, sizeof(bacula_ctx));
270 plugin_ctx_list[i].bContext = (void *)b_ctx;
271 plugin_ctx_list[i].pContext = NULL;
272 if (sdplug_func(plugin)->newPlugin(&plugin_ctx_list[i++]) != bRC_OK) {
273 b_ctx->disabled = true;
279 * Free the plugin instances for this Job
281 void free_plugins(JCR *jcr)
286 if (!bplugin_list || !jcr->plugin_ctx_list) {
290 bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
291 Dmsg2(dbglvl, "Free instance sd-plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
292 foreach_alist(plugin, bplugin_list) {
293 /* Free the plugin instance */
294 sdplug_func(plugin)->freePlugin(&plugin_ctx_list[i]);
295 free(plugin_ctx_list[i++].bContext); /* free Bacula private context */
297 free(plugin_ctx_list);
298 jcr->plugin_ctx_list = NULL;
302 /* ==============================================================
304 * Callbacks from the plugin
306 * ==============================================================
308 static bRC baculaGetValue(bpContext *ctx, bsdrVariable var, void *value)
314 jcr = ((bacula_ctx *)ctx->bContext)->jcr;
323 *((int *)value) = jcr->JobId;
324 Dmsg1(dbglvl, "sd-plugin: return bVarJobId=%d\n", jcr->JobId);
327 *((char **)value) = jcr->Job;
328 Dmsg1(dbglvl, "Bacula: return Job name=%s\n", jcr->Job);
336 static bRC baculaSetValue(bpContext *ctx, bsdwVariable var, void *value)
339 if (!value || !ctx) {
342 // Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var);
343 jcr = ((bacula_ctx *)ctx->bContext)->jcr;
347 // Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr);
348 /* Nothing implemented yet */
349 Dmsg1(dbglvl, "sd-plugin: baculaSetValue var=%d\n", var);
353 static bRC baculaRegisterEvents(bpContext *ctx, ...)
359 while ((event = va_arg(args, uint32_t))) {
360 Dmsg1(dbglvl, "sd-Plugin wants event=%u\n", event);
366 static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
367 int type, utime_t mtime, const char *fmt, ...)
374 jcr = ((bacula_ctx *)ctx->bContext)->jcr;
379 va_start(arg_ptr, fmt);
380 bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
382 Jmsg(jcr, type, mtime, "%s", buf);
386 static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
387 int level, const char *fmt, ...)
392 va_start(arg_ptr, fmt);
393 bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
395 d_msg(file, line, level, "%s", buf);
399 static char *baculaEditDeviceCodes(DCR *dcr, char *omsg,
400 const char *imsg, const char *cmd)
402 return edit_device_codes(dcr, omsg, imsg, cmd);
407 int main(int argc, char *argv[])
409 char plugin_dir[1000];
414 strcpy(my_name, "test-dir");
416 getcwd(plugin_dir, sizeof(plugin_dir)-1);
417 load_sd_plugins(plugin_dir);
425 generate_plugin_event(jcr1, bsdEventJobStart, (void *)"Start Job 1");
426 generate_plugin_event(jcr1, bsdEventJobEnd);
427 generate_plugin_event(jcr2, bsdEventJobStart, (void *)"Start Job 1");
429 generate_plugin_event(jcr2, bsdEventJobEnd);
434 Dmsg0(dbglvl, "sd-plugin: OK ...\n");
440 #endif /* TEST_PROGRAM */