]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/sd_plugins.c
Pull files from Master
[bacula/bacula] / bacula / src / stored / sd_plugins.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2011 Free Software Foundation Europe e.V.
5
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.
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    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    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.
27 */
28 /*
29  * Main program to test loading and running Bacula plugins.
30  *   Destined to become Bacula pluginloader, ...
31  *
32  * Kern Sibbald, October 2007
33  */
34 #include "bacula.h"
35 #include "stored.h"
36 #include "sd_plugins.h"
37
38 const int dbglvl = 50;
39 const char *plugin_type = "-sd.so";
40
41
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
53
54 /* Bacula info */
55 static bsdInfo binfo = {
56    sizeof(bsdFuncs),
57    SD_PLUGIN_INTERFACE_VERSION
58 };
59
60 /* Bacula entry points */
61 static bsdFuncs bfuncs = {
62    sizeof(bsdFuncs),
63    SD_PLUGIN_INTERFACE_VERSION,
64    baculaRegisterEvents,
65    baculaGetValue,
66    baculaSetValue,
67    baculaJobMsg,
68    baculaDebugMsg,
69    baculaEditDeviceCodes
70 };
71
72 /* 
73  * Bacula private context
74  */
75 struct bacula_ctx {
76    JCR *jcr;                             /* jcr for plugin */
77    bRC  rc;                              /* last return code */
78    bool disabled;                        /* set if plugin disabled */
79 };
80
81 static bool is_plugin_disabled(bpContext *plugin_ctx)
82 {
83    bacula_ctx *b_ctx;
84    if (!plugin_ctx) {
85       return true;
86    }
87    b_ctx = (bacula_ctx *)plugin_ctx->bContext;
88    return b_ctx->disabled;
89 }
90
91 #ifdef needed
92 static bool is_plugin_disabled(JCR *jcr)
93 {
94    return is_plugin_disabled(jcr->plugin_ctx);
95 }
96 #endif
97
98 /*
99  * Create a plugin event 
100  */
101 int generate_plugin_event(JCR *jcr, bsdEventType eventType, void *value)
102 {
103    bpContext *plugin_ctx;
104    bsdEvent event;
105    Plugin *plugin;
106    int i = 0;
107    bRC rc = bRC_OK;
108
109    if (!bplugin_list || !jcr || !jcr->plugin_ctx_list) {
110       return bRC_OK;                  /* Return if no plugins loaded */
111    }
112    if (jcr->is_job_canceled()) {
113       return bRC_Cancel;
114    }
115
116    bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
117    event.eventType = eventType;
118
119    Dmsg2(dbglvl, "sd-plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
120
121    foreach_alist(plugin, bplugin_list) {
122       plugin_ctx = &plugin_ctx_list[i++];
123       if (is_plugin_disabled(plugin_ctx)) {
124          continue;
125       }
126       rc = sdplug_func(plugin)->handlePluginEvent(plugin_ctx, &event, value);
127       if (rc != bRC_OK) {
128          break;
129       }
130    }
131
132    return rc;
133 }
134
135 static void dump_sd_plugin(Plugin *plugin, FILE *fp)
136 {
137    if (!plugin) {
138       return ;
139    }
140    psdInfo *info = (psdInfo *) plugin->pinfo;
141    fprintf(fp, "\tversion=%d\n", info->version);
142    fprintf(fp, "\tdate=%s\n", NPRTB(info->plugin_date));
143    fprintf(fp, "\tmagic=%s\n", NPRTB(info->plugin_magic));
144    fprintf(fp, "\tauthor=%s\n", NPRTB(info->plugin_author));
145    fprintf(fp, "\tlicence=%s\n", NPRTB(info->plugin_license));
146    fprintf(fp, "\tversion=%s\n", NPRTB(info->plugin_version));
147    fprintf(fp, "\tdescription=%s\n", NPRTB(info->plugin_description));
148 }
149
150 void load_sd_plugins(const char *plugin_dir)
151 {
152    Dmsg0(dbglvl, "Load sd plugins\n");
153    if (!plugin_dir) {
154       Dmsg0(dbglvl, "No sd plugin dir!\n");
155       return;
156    }
157    bplugin_list = New(alist(10, not_owned_by_alist));
158    load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type, NULL);
159    Dmsg1(dbglvl, "num plugins=%d\n", bplugin_list->size());
160    dbg_plugin_add_hook(dump_sd_plugin);
161 }
162
163 /*
164  * Create a new instance of each plugin for this Job
165  */
166 void new_plugins(JCR *jcr)
167 {
168    Plugin *plugin;
169    int i = 0;
170
171    Dmsg0(dbglvl, "=== enter new_plugins ===\n");
172    if (!bplugin_list) {
173       Dmsg0(dbglvl, "No sd plugin list!\n");
174       return;
175    }
176    if (jcr->is_job_canceled()) {
177       return;
178    }
179
180    int num = bplugin_list->size();
181
182    Dmsg1(dbglvl, "sd-plugin-list size=%d\n", num);
183    if (num == 0) {
184       return;
185    }
186
187    jcr->plugin_ctx_list = (bpContext *)malloc(sizeof(bpContext) * num);
188
189    bpContext *plugin_ctx_list = jcr->plugin_ctx_list;
190    Dmsg2(dbglvl, "Instantiate sd-plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
191    foreach_alist(plugin, bplugin_list) {
192       /* Start a new instance of each plugin */
193       bacula_ctx *b_ctx = (bacula_ctx *)malloc(sizeof(bacula_ctx));
194       memset(b_ctx, 0, sizeof(bacula_ctx));
195       b_ctx->jcr = jcr;
196       plugin_ctx_list[i].bContext = (void *)b_ctx;
197       plugin_ctx_list[i].pContext = NULL;
198       if (sdplug_func(plugin)->newPlugin(&plugin_ctx_list[i++]) != bRC_OK) {
199          b_ctx->disabled = true;
200       }
201    }
202 }
203
204 /*
205  * Free the plugin instances for this Job
206  */
207 void free_plugins(JCR *jcr)
208 {
209    Plugin *plugin;
210    int i = 0;
211
212    if (!bplugin_list) {
213       return;
214    }
215
216    bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
217    Dmsg2(dbglvl, "Free instance sd-plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
218    foreach_alist(plugin, bplugin_list) {
219       /* Free the plugin instance */
220       sdplug_func(plugin)->freePlugin(&plugin_ctx_list[i++]);
221    }
222    free(plugin_ctx_list);
223    jcr->plugin_ctx_list = NULL;
224 }
225
226
227 /* ==============================================================
228  *
229  * Callbacks from the plugin
230  *
231  * ==============================================================
232  */
233 static bRC baculaGetValue(bpContext *ctx, bsdrVariable var, void *value)
234 {
235    JCR *jcr;
236    if (!ctx) {
237       return bRC_Error;
238    }
239    jcr = ((bacula_ctx *)ctx->bContext)->jcr;
240    if (!jcr) {
241       return bRC_Error;
242    }
243    if (!value) {
244       return bRC_Error;
245    }
246    switch (var) {
247    case bsdVarJobId:
248       *((int *)value) = jcr->JobId;
249       Dmsg1(dbglvl, "sd-plugin: return bVarJobId=%d\n", jcr->JobId);
250       break;
251    case bsdVarJobName:
252       *((char **)value) = jcr->Job;
253       Dmsg1(dbglvl, "Bacula: return Job name=%s\n", jcr->Job);
254       break;
255    default:
256       break;
257    }
258    return bRC_OK;
259 }
260
261 static bRC baculaSetValue(bpContext *ctx, bsdwVariable var, void *value)
262 {
263    JCR *jcr;   
264    if (!value || !ctx) {
265       return bRC_Error;
266    }
267 // Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var);
268    jcr = ((bacula_ctx *)ctx->bContext)->jcr;
269    if (!jcr) {
270       return bRC_Error;
271    }
272 // Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr); 
273    /* Nothing implemented yet */
274    Dmsg1(dbglvl, "sd-plugin: baculaSetValue var=%d\n", var);
275    return bRC_OK;
276 }
277
278 static bRC baculaRegisterEvents(bpContext *ctx, ...)
279 {
280    va_list args;
281    uint32_t event;
282
283    va_start(args, ctx);
284    while ((event = va_arg(args, uint32_t))) {
285       Dmsg1(dbglvl, "sd-Plugin wants event=%u\n", event);
286    }
287    va_end(args);
288    return bRC_OK;
289 }
290
291 static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
292   int type, utime_t mtime, const char *fmt, ...)
293 {
294    va_list arg_ptr;
295    char buf[2000];
296    JCR *jcr;
297
298    if (ctx) {
299       jcr = ((bacula_ctx *)ctx->bContext)->jcr;
300    } else {
301       jcr = NULL;
302    }
303
304    va_start(arg_ptr, fmt);
305    bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
306    va_end(arg_ptr);
307    Jmsg(jcr, type, mtime, "%s", buf);
308    return bRC_OK;
309 }
310
311 static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
312   int level, const char *fmt, ...)
313 {
314    va_list arg_ptr;
315    char buf[2000];
316
317    va_start(arg_ptr, fmt);
318    bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
319    va_end(arg_ptr);
320    d_msg(file, line, level, "%s", buf);
321    return bRC_OK;
322 }
323
324 static char *baculaEditDeviceCodes(DCR *dcr, char *omsg, 
325   const char *imsg, const char *cmd)
326 {
327    return edit_device_codes(dcr, omsg, imsg, cmd);
328 }
329
330 #ifdef TEST_PROGRAM
331
332 int main(int argc, char *argv[])
333 {
334    char plugin_dir[1000];
335    JCR mjcr1, mjcr2;
336    JCR *jcr1 = &mjcr1;
337    JCR *jcr2 = &mjcr2;
338
339    strcpy(my_name, "test-dir");
340     
341    getcwd(plugin_dir, sizeof(plugin_dir)-1);
342    load_sd_plugins(plugin_dir);
343
344    jcr1->JobId = 111;
345    new_plugins(jcr1);
346
347    jcr2->JobId = 222;
348    new_plugins(jcr2);
349
350    generate_plugin_event(jcr1, bsdEventJobStart, (void *)"Start Job 1");
351    generate_plugin_event(jcr1, bsdEventJobEnd);
352    generate_plugin_event(jcr2, bsdEventJobStart, (void *)"Start Job 1");
353    free_plugins(jcr1);
354    generate_plugin_event(jcr2, bsdEventJobEnd);
355    free_plugins(jcr2);
356
357    unload_plugins();
358
359    Dmsg0(dbglvl, "sd-plugin: OK ...\n");
360    close_memory_pool();
361    sm_dump(false);
362    return 0;
363 }
364
365 #endif /* TEST_PROGRAM */