2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2008 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 two of the GNU 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 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 John Walker.
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
37 const int dbglvl = 50;
38 const char *plugin_type = "-fd.so";
40 extern int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level);
43 /* Function pointers to be set here */
44 extern int (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode);
45 extern int (*plugin_bclose)(JCR *jcr);
46 extern ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count);
47 extern ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count);
50 /* Forward referenced functions */
51 static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value);
52 static bRC baculaSetValue(bpContext *ctx, bVariable var, void *value);
53 static bRC baculaRegisterEvents(bpContext *ctx, ...);
54 static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
55 int type, time_t mtime, const char *msg);
56 static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
57 int level, const char *msg);
59 static int my_plugin_bopen(JCR *jcr, const char *fname, int flags, mode_t mode);
60 static int my_plugin_bclose(JCR *jcr);
61 static ssize_t my_plugin_bread(JCR *jcr, void *buf, size_t count);
62 static ssize_t my_plugin_bwrite(JCR *jcr, void *buf, size_t count);
66 static bInfo binfo = {
68 PLUGIN_INTERFACE_VERSION
71 /* Bacula entry points */
72 static bFuncs bfuncs = {
74 PLUGIN_INTERFACE_VERSION,
84 * Create a plugin event
86 void generate_plugin_event(JCR *jcr, bEventType eventType, void *value)
93 char *cmd = (char *)value;
99 bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
100 event.eventType = eventType;
102 Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
103 if (eventType != bEventPluginCommand) {
104 /* Pass event to every plugin */
105 foreach_alist(plugin, plugin_list) {
106 plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i++], &event, value);
111 /* Handle plugin command here (backup/restore of file) */
112 Dmsg1(000, "plugin cmd=%s\n", cmd);
113 if (!(p = strchr(cmd, ':'))) {
114 Jmsg1(jcr, M_ERROR, 0, "Malformed plugin command: %s\n", cmd);
122 foreach_alist(plugin, plugin_list) {
123 Dmsg3(000, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
124 if (strncmp(plugin->file, cmd, len) == 0) {
127 Dmsg1(000, "Command plugin = %s\n", cmd);
128 if (plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i], &event, value) != bRC_OK) {
131 memset(&sp, 0, sizeof(sp));
134 Dmsg0(000, "Plugin startBackup\n");
135 if (plug_func(plugin)->startPluginBackup(&plugin_ctx_list[i], &sp) != bRC_OK) {
138 jcr->plugin_ctx = &plugin_ctx_list[i];
139 jcr->plugin = plugin;
141 ff_pkt->fname = sp.fname;
142 ff_pkt->type = sp.type;
143 ff_pkt->statp = sp.statp; /* structure copy */
144 Dmsg1(000, "Save_file: file=%s\n", ff_pkt->fname);
145 save_file(ff_pkt, (void *)jcr, true);
155 void load_fd_plugins(const char *plugin_dir)
161 plugin_list = New(alist(10, not_owned_by_alist));
162 load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type);
163 plugin_bopen = my_plugin_bopen;
164 plugin_bclose = my_plugin_bclose;
165 plugin_bread = my_plugin_bread;
166 plugin_bwrite = my_plugin_bwrite;
171 * Create a new instance of each plugin for this Job
173 void new_plugins(JCR *jcr)
182 int num = plugin_list->size();
188 jcr->plugin_ctx_list = (void *)malloc(sizeof(bpContext) * num);
190 bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
191 Dmsg2(dbglvl, "Instantiate plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId);
192 foreach_alist(plugin, plugin_list) {
193 /* Start a new instance of each plugin */
194 plugin_ctx_list[i].bContext = (void *)jcr;
195 plugin_ctx_list[i].pContext = NULL;
196 plug_func(plugin)->newPlugin(&plugin_ctx_list[i++]);
201 * Free the plugin instances for this Job
203 void free_plugins(JCR *jcr)
212 bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
213 Dmsg2(dbglvl, "Free instance plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId);
214 foreach_alist(plugin, plugin_list) {
215 /* Free the plugin instance */
216 plug_func(plugin)->freePlugin(&plugin_ctx_list[i++]);
218 free(plugin_ctx_list);
219 jcr->plugin_ctx_list = NULL;
222 static int my_plugin_bopen(JCR *jcr, const char *fname, int flags, mode_t mode)
224 Plugin *plugin = (Plugin *)jcr->plugin;
225 bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
227 Dmsg0(000, "plugin_bopen\n");
231 plug_func(plugin)->pluginIO(plugin_ctx, &io);
235 static int my_plugin_bclose(JCR *jcr)
237 Plugin *plugin = (Plugin *)jcr->plugin;
238 bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
240 Dmsg0(000, "plugin_bclose\n");
244 plug_func(plugin)->pluginIO(plugin_ctx, &io);
248 static ssize_t my_plugin_bread(JCR *jcr, void *buf, size_t count)
250 Plugin *plugin = (Plugin *)jcr->plugin;
251 bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
253 Dmsg0(000, "plugin_bread\n");
256 io.buf = (char *)buf;
257 plug_func(plugin)->pluginIO(plugin_ctx, &io);
258 return (ssize_t)io.status;
261 static ssize_t my_plugin_bwrite(JCR *jcr, void *buf, size_t count)
263 Plugin *plugin = (Plugin *)jcr->plugin;
264 bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
266 Dmsg0(000, "plugin_bwrite\n");
269 io.buf = (char *)buf;
270 plug_func(plugin)->pluginIO(plugin_ctx, &io);
271 return (ssize_t)io.status;
274 /* ==============================================================
276 * Callbacks from the plugin
278 * ==============================================================
280 static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value)
282 JCR *jcr = (JCR *)(ctx->bContext);
283 // Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var);
287 // Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr);
290 *((int *)value) = jcr->JobId;
291 Dmsg1(dbglvl, "Bacula: return bVarJobId=%d\n", jcr->JobId);
294 *((char **)value) = my_name;
295 Dmsg1(dbglvl, "Bacula: return my_name=%s\n", my_name);
308 static bRC baculaSetValue(bpContext *ctx, bVariable var, void *value)
310 Dmsg1(dbglvl, "bacula: baculaSetValue var=%d\n", var);
314 static bRC baculaRegisterEvents(bpContext *ctx, ...)
320 while ((event = va_arg(args, uint32_t))) {
321 Dmsg1(dbglvl, "Plugin wants event=%u\n", event);
327 static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
328 int type, time_t mtime, const char *msg)
330 Dmsg5(dbglvl, "Job message: %s:%d type=%d time=%ld msg=%s\n",
331 file, line, type, mtime, msg);
335 static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
336 int level, const char *msg)
338 Dmsg4(dbglvl, "Debug message: %s:%d level=%d msg=%s\n",
339 file, line, level, msg);
345 int (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode) = NULL;
346 int (*plugin_bclose)(JCR *jcr) = NULL;
347 ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count) = NULL;
348 ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count) = NULL;
350 int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level)
355 int main(int argc, char *argv[])
357 char plugin_dir[1000];
362 strcpy(my_name, "test-fd");
364 getcwd(plugin_dir, sizeof(plugin_dir)-1);
365 load_fd_plugins(plugin_dir);
373 generate_plugin_event(jcr1, bEventJobStart);
374 generate_plugin_event(jcr1, bEventJobEnd);
375 generate_plugin_event(jcr2, bEventJobStart);
377 generate_plugin_event(jcr2, bEventJobEnd);
382 Dmsg0(dbglvl, "bacula: OK ...\n");
388 #endif /* TEST_PROGRAM */