X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Ffiled%2Ffd_plugins.c;h=ef24d0520e718993d6150072e25e033d6a57f0fa;hb=f9201647d5ecc4a1b0a2d1de7ca339f50fc5d77b;hp=0d52728dddbe69af32ea83dd16db5fe3fed0640a;hpb=5a7079d36330f2008c68c981d505851b1aa5d62c;p=bacula%2Fbacula diff --git a/bacula/src/filed/fd_plugins.c b/bacula/src/filed/fd_plugins.c index 0d52728ddd..ef24d0520e 100644 --- a/bacula/src/filed/fd_plugins.c +++ b/bacula/src/filed/fd_plugins.c @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2007-2008 Free Software Foundation Europe e.V. + Copyright (C) 2007-2009 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -34,7 +34,7 @@ #include "bacula.h" #include "filed.h" -const int dbglvl = 50; +const int dbglvl = 150; #ifdef HAVE_WIN32 const char *plugin_type = "-fd.dll"; #else @@ -56,10 +56,18 @@ static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value); static bRC baculaSetValue(bpContext *ctx, bVariable var, void *value); static bRC baculaRegisterEvents(bpContext *ctx, ...); static bRC baculaJobMsg(bpContext *ctx, const char *file, int line, - int type, time_t mtime, const char *fmt, ...); + int type, utime_t mtime, const char *fmt, ...); static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line, int level, const char *fmt, ...); +static void *baculaMalloc(bpContext *ctx, const char *file, int line, + size_t size); +static void baculaFree(bpContext *ctx, const char *file, int line, void *mem); +static bool is_plugin_compatible(Plugin *plugin); +/* + * These will be plugged into the global pointer structure for + * the findlib. + */ static int my_plugin_bopen(BFILE *bfd, const char *fname, int flags, mode_t mode); static int my_plugin_bclose(BFILE *bfd); static ssize_t my_plugin_bread(BFILE *bfd, void *buf, size_t count); @@ -69,7 +77,7 @@ static boffset_t my_plugin_blseek(BFILE *bfd, boffset_t offset, int whence); /* Bacula info */ static bInfo binfo = { - sizeof(bFuncs), + sizeof(bInfo), FD_PLUGIN_INTERFACE_VERSION }; @@ -81,9 +89,30 @@ static bFuncs bfuncs = { baculaGetValue, baculaSetValue, baculaJobMsg, - baculaDebugMsg + baculaDebugMsg, + baculaMalloc, + baculaFree }; +/* + * Bacula private context + */ +struct bacula_ctx { + JCR *jcr; /* jcr for plugin */ + bRC rc; /* last return code */ + bool disabled; /* set if plugin disabled */ +}; + +static bool is_plugin_disabled(JCR *jcr) +{ + bacula_ctx *b_ctx; + if (!jcr->plugin_ctx) { + return true; + } + b_ctx = (bacula_ctx *)jcr->plugin_ctx->bContext; + return b_ctx->disabled; +} + /* * Create a plugin event @@ -94,7 +123,7 @@ void generate_plugin_event(JCR *jcr, bEventType eventType, void *value) Plugin *plugin; int i = 0; - if (!plugin_list || !jcr->plugin_ctx_list) { + if (!plugin_list || !jcr || !jcr->plugin_ctx_list || job_canceled(jcr)) { return; /* Return if no plugins loaded */ } @@ -106,15 +135,61 @@ void generate_plugin_event(JCR *jcr, bEventType eventType, void *value) /* Pass event to every plugin */ foreach_alist(plugin, plugin_list) { bRC rc; - rc = plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i++], &event, value); + jcr->plugin_ctx = &plugin_ctx_list[i++]; + jcr->plugin = plugin; + if (is_plugin_disabled(jcr)) { + continue; + } + rc = plug_func(plugin)->handlePluginEvent(jcr->plugin_ctx, &event, value); if (rc != bRC_OK) { break; } } + jcr->plugin = NULL; + jcr->plugin_ctx = NULL; return; } +/* + * Check if file was seen for accurate + */ +bool plugin_check_file(JCR *jcr, char *fname) +{ + Plugin *plugin; + int rc = bRC_OK; + int i = 0; + + if (!plugin_list || !jcr || !jcr->plugin_ctx_list || job_canceled(jcr)) { + return false; /* Return if no plugins loaded */ + } + + bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list; + + Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId); + + /* Pass event to every plugin */ + foreach_alist(plugin, plugin_list) { + jcr->plugin_ctx = &plugin_ctx_list[i++]; + jcr->plugin = plugin; + if (is_plugin_disabled(jcr)) { + continue; + } + if (plug_func(plugin)->checkFile == NULL) { + continue; + } + rc = plug_func(plugin)->checkFile(jcr->plugin_ctx, fname); + if (rc == bRC_Seen) { + break; + } + } + + jcr->plugin = NULL; + jcr->plugin_ctx = NULL; + return rc == bRC_Seen; +} + + /* * Sequence of calls for a backup: * 1. plugin_save() here is called with ff_pkt @@ -139,8 +214,10 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level) char *cmd = ff_pkt->top_fname; struct save_pkt sp; bEvent event; + POOL_MEM fname(PM_FNAME); + POOL_MEM link(PM_FNAME); - if (!plugin_list || !jcr->plugin_ctx_list) { + if (!plugin_list || !jcr->plugin_ctx_list || job_canceled(jcr)) { return 1; /* Return if no plugins loaded */ } @@ -159,15 +236,27 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level) goto bail_out; } + /* Note, we stop the loop on the first plugin that matches the name */ foreach_alist(plugin, plugin_list) { Dmsg3(dbglvl, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len); if (strncmp(plugin->file, cmd, len) != 0) { i++; continue; } + /* + * We put the current plugin pointer, and the plugin context + * into the jcr, because during save_file(), the plugin + * will be called many times and these values are needed. + */ + jcr->plugin_ctx = &plugin_ctx_list[i]; + jcr->plugin = plugin; + if (is_plugin_disabled(jcr)) { + goto bail_out; + } + Dmsg1(dbglvl, "Command plugin = %s\n", cmd); /* Send the backup command to the right plugin*/ - if (plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i], &event, cmd) != bRC_OK) { + if (plug_func(plugin)->handlePluginEvent(jcr->plugin_ctx, &event, cmd) != bRC_OK) { goto bail_out; } /* Loop getting filenames to backup then saving them */ @@ -180,7 +269,7 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level) Dmsg3(dbglvl, "startBackup st_size=%p st_blocks=%p sp=%p\n", &sp.statp.st_size, &sp.statp.st_blocks, &sp); /* Get the file save parameters */ - if (plug_func(plugin)->startBackupFile(&plugin_ctx_list[i], &sp) != bRC_OK) { + if (plug_func(plugin)->startBackupFile(jcr->plugin_ctx, &sp) != bRC_OK) { goto bail_out; } if (sp.type == 0 || sp.fname == NULL) { @@ -188,26 +277,37 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level) cmd); goto bail_out; } - jcr->plugin_ctx = &plugin_ctx_list[i]; - jcr->plugin = plugin; jcr->plugin_sp = &sp; ff_pkt = jcr->ff; - ff_pkt->fname = sp.fname; + /* + * Copy fname and link because save_file() zaps them. This + * avoids zaping the plugin's strings. + */ + pm_strcpy(fname, sp.fname); + pm_strcpy(link, sp.link); + ff_pkt->fname = fname.c_str(); + ff_pkt->link = link.c_str(); ff_pkt->type = sp.type; memcpy(&ff_pkt->statp, &sp.statp, sizeof(ff_pkt->statp)); - Dmsg1(dbglvl, "Save_file: file=%s\n", ff_pkt->fname); + Dmsg1(dbglvl, "Save_file: file=%s\n", fname.c_str()); save_file(jcr, ff_pkt, true); - bRC rc = plug_func(plugin)->endBackupFile(&plugin_ctx_list[i]); + bRC rc = plug_func(plugin)->endBackupFile(jcr->plugin_ctx); + if (rc == bRC_More || rc == bRC_OK) { + accurate_mark_file_as_seen(jcr, fname.c_str()); + } if (rc == bRC_More) { continue; } goto bail_out; } + goto bail_out; } Jmsg1(jcr, M_ERROR, 0, "Command plugin \"%s\" not found.\n", cmd); bail_out: jcr->cmd_plugin = false; + jcr->plugin = NULL; + jcr->plugin_ctx = NULL; return 1; } @@ -217,20 +317,32 @@ bail_out: bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start) { int stat; + int index = jcr->JobFiles; struct save_pkt *sp = (struct save_pkt *)jcr->plugin_sp; + + if (!sp) { + Jmsg0(jcr, M_FATAL, 0, _("Plugin save packet not found.\n")); + return false; + } + if (job_canceled(jcr)) { + return false; + } + if (start) { + index++; /* JobFiles not incremented yet */ + } Dmsg1(dbglvl, "send_plugin_name=%s\n", sp->cmd); /* Send stream header */ - if (!sd->fsend("%ld %d 0", jcr->JobFiles+1, STREAM_PLUGIN_NAME)) { + if (!sd->fsend("%ld %d 0", index, STREAM_PLUGIN_NAME)) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); return false; } - Dmsg1(000, "send: %s\n", sd->msg); + Dmsg1(50, "send: %s\n", sd->msg); if (start) { /* Send data -- not much */ - stat = sd->fsend("%ld 1 %d %s%c", jcr->JobFiles+1, sp->portable, sp->cmd, 0); + stat = sd->fsend("%ld 1 %d %s%c", index, sp->portable, sp->cmd, 0); } else { /* Send end of data */ stat = sd->fsend("0 0"); @@ -248,8 +360,11 @@ bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start) /* * Plugin name stream found during restore. The record passed in * argument name was generated in send_plugin_name() above. + * + * Returns: true if start of stream + * false if end of steam */ -void plugin_name_stream(JCR *jcr, char *name) +bool plugin_name_stream(JCR *jcr, char *name) { char *p = name; char *cmd; @@ -257,10 +372,7 @@ void plugin_name_stream(JCR *jcr, char *name) Plugin *plugin; int len; int i = 0; - bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list; - if (!plugin_ctx_list) { - goto bail_out; - } + bpContext *plugin_ctx_list = jcr->plugin_ctx_list; Dmsg1(dbglvl, "Read plugin stream string=%s\n", name); skip_nonspaces(&p); /* skip over jcr->JobFiles */ @@ -280,13 +392,15 @@ void plugin_name_stream(JCR *jcr, char *name) */ Dmsg2(dbglvl, "End plugin data plugin=%p ctx=%p\n", jcr->plugin, jcr->plugin_ctx); if (jcr->plugin) { - plugin = (Plugin *)jcr->plugin; - plug_func(plugin)->endRestoreFile((bpContext *)jcr->plugin_ctx); + plug_func(jcr->plugin)->endRestoreFile(jcr->plugin_ctx); } jcr->plugin_ctx = NULL; jcr->plugin = NULL; goto bail_out; } + if (!plugin_ctx_list) { + goto bail_out; + } /* * After this point, we are dealing with a restore start @@ -313,22 +427,30 @@ void plugin_name_stream(JCR *jcr, char *name) i++; continue; } + jcr->plugin_ctx = &plugin_ctx_list[i]; + jcr->plugin = plugin; + if (is_plugin_disabled(jcr)) { + goto bail_out; + } Dmsg1(dbglvl, "Restore Command plugin = %s\n", cmd); event.eventType = bEventRestoreCommand; - if (plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i], + if (plug_func(plugin)->handlePluginEvent(jcr->plugin_ctx, &event, cmd) != bRC_OK) { goto bail_out; } - jcr->plugin_ctx = &plugin_ctx_list[i]; - jcr->plugin = plugin; + /* ***FIXME**** check error code */ + plug_func(plugin)->startRestoreFile((bpContext *)jcr->plugin_ctx, cmd); goto bail_out; } + Jmsg1(jcr, M_WARNING, 0, _("Plugin=%s not found.\n"), cmd); + bail_out: - return; + return start; } /* * Tell the plugin to create the file. Return values are + * This is called only during Restore * * CF_ERROR -- error * CF_SKIP -- skip processing this file @@ -338,13 +460,13 @@ bail_out: */ int plugin_create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) { - bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx; - Plugin *plugin = (Plugin *)jcr->plugin; + bpContext *plugin_ctx = jcr->plugin_ctx; + Plugin *plugin = jcr->plugin; struct restore_pkt rp; int flags; int rc; - if (!set_cmd_plugin(bfd, jcr)) { + if (!plugin || !plugin_ctx || !set_cmd_plugin(bfd, jcr) || job_canceled(jcr)) { return CF_ERROR; } rp.pkt_size = sizeof(rp); @@ -379,16 +501,23 @@ int plugin_create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) if (rp.create_status == CF_CREATED) { return rp.create_status; /* yes, no need to bopen */ } + flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; Dmsg0(dbglvl, "call bopen\n"); - if ((bopen(bfd, attr->ofname, flags, S_IRUSR | S_IWUSR)) < 0) { + int stat = bopen(bfd, attr->ofname, flags, S_IRUSR | S_IWUSR); + Dmsg1(50, "bopen status=%d\n", stat); + if (stat < 0) { berrno be; be.set_errno(bfd->berrno); Qmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"), attr->ofname, be.bstrerror()); - Dmsg2(dbglvl,"Could not create %s: ERR=%s\n", attr->ofname, be.bstrerror()); + Dmsg2(dbglvl,"Could not bopen file %s: ERR=%s\n", attr->ofname, be.bstrerror()); return CF_ERROR; } + + if (!is_bopen(bfd)) { + Dmsg0(000, "===== BFD is not open!!!!\n"); + } return CF_EXTRACT; } @@ -396,13 +525,36 @@ int plugin_create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) * Reset the file attributes after all file I/O is done -- this allows * the previous access time/dates to be set properly, and it also allows * us to properly set directory permissions. + * Not currently Implemented. */ bool plugin_set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) { Dmsg0(dbglvl, "plugin_set_attributes\n"); + if (is_bopen(ofd)) { + bclose(ofd); + } + pm_strcpy(attr->ofname, "*none*"); return true; } +/* + * Print to file the plugin info. + */ +void dump_fd_plugin(Plugin *plugin, FILE *fp) +{ + if (!plugin) { + return ; + } + pInfo *info = (pInfo *)plugin->pinfo; + fprintf(fp, "\tversion=%d\n", info->version); + fprintf(fp, "\tdate=%s\n", NPRTB(info->plugin_date)); + fprintf(fp, "\tmagic=%s\n", NPRTB(info->plugin_magic)); + fprintf(fp, "\tauthor=%s\n", NPRTB(info->plugin_author)); + fprintf(fp, "\tlicence=%s\n", NPRTB(info->plugin_license)); + fprintf(fp, "\tversion=%s\n", NPRTB(info->plugin_version)); + fprintf(fp, "\tdescription=%s\n", NPRTB(info->plugin_description)); +} + /* * This entry point is called internally by Bacula to ensure * that the plugin IO calls come into this code. @@ -417,7 +569,8 @@ void load_fd_plugins(const char *plugin_dir) } plugin_list = New(alist(10, not_owned_by_alist)); - if (!load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type)) { + if (!load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type, + is_plugin_compatible)) { /* Either none found, or some error */ if (plugin_list->size() == 0) { delete plugin_list; @@ -433,13 +586,58 @@ void load_fd_plugins(const char *plugin_dir) plugin_bread = my_plugin_bread; plugin_bwrite = my_plugin_bwrite; plugin_blseek = my_plugin_blseek; + + /* + * Verify that the plugin is acceptable, and print information + * about it. + */ foreach_alist(plugin, plugin_list) { Jmsg(NULL, M_INFO, 0, _("Loaded plugin: %s\n"), plugin->file); Dmsg1(dbglvl, "Loaded plugin: %s\n", plugin->file); + } + + dbg_plugin_add_hook(dump_fd_plugin); +} +/* + * Check if a plugin is compatible. Called by the load_plugin function + * to allow us to verify the plugin. + */ +static bool is_plugin_compatible(Plugin *plugin) +{ + pInfo *info = (pInfo *)plugin->pinfo; + Dmsg0(50, "is_plugin_compatible called\n"); + if (debug_level >= 50) { + dump_fd_plugin(plugin, stdin); + } + if (strcmp(info->plugin_magic, FD_PLUGIN_MAGIC) != 0) { + Jmsg(NULL, M_ERROR, 0, _("Plugin magic wrong. Plugin=%s wanted=%s got=%s\n"), + plugin->file, FD_PLUGIN_MAGIC, info->plugin_magic); + Dmsg3(50, "Plugin magic wrong. Plugin=%s wanted=%s got=%s\n", + plugin->file, FD_PLUGIN_MAGIC, info->plugin_magic); + + return false; } + if (info->version != FD_PLUGIN_INTERFACE_VERSION) { + Jmsg(NULL, M_ERROR, 0, _("Plugin version incorrect. Plugin=%s wanted=%d got=%d\n"), + plugin->file, FD_PLUGIN_INTERFACE_VERSION, info->version); + Dmsg3(50, "Plugin version incorrect. Plugin=%s wanted=%d got=%d\n", + plugin->file, FD_PLUGIN_INTERFACE_VERSION, info->version); + return false; + } + if (strcmp(info->plugin_license, "Bacula GPLv2") != 0 && + strcmp(info->plugin_license, "GPLv2") != 0) { + Jmsg(NULL, M_ERROR, 0, _("Plugin license incompatible. Plugin=%s license=%s\n"), + plugin->file, info->plugin_license); + Dmsg2(50, "Plugin license incompatible. Plugin=%s license=%s\n", + plugin->file, info->plugin_license); + return false; + } + + return true; } + /* * Create a new instance of each plugin for this Job * Note, plugin_list can exist but jcr->plugin_ctx_list can @@ -454,6 +652,9 @@ void new_plugins(JCR *jcr) Dmsg0(dbglvl, "plugin list is NULL\n"); return; } + if (job_canceled(jcr)) { + return; + } int num = plugin_list->size(); @@ -462,15 +663,20 @@ void new_plugins(JCR *jcr) return; } - jcr->plugin_ctx_list = (void *)malloc(sizeof(bpContext) * num); + jcr->plugin_ctx_list = (bpContext *)malloc(sizeof(bpContext) * num); bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list; Dmsg2(dbglvl, "Instantiate plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId); foreach_alist(plugin, plugin_list) { /* Start a new instance of each plugin */ - plugin_ctx_list[i].bContext = (void *)jcr; + bacula_ctx *b_ctx = (bacula_ctx *)malloc(sizeof(bacula_ctx)); + memset(b_ctx, 0, sizeof(bacula_ctx)); + b_ctx->jcr = jcr; + plugin_ctx_list[i].bContext = (void *)b_ctx; /* Bacula private context */ plugin_ctx_list[i].pContext = NULL; - plug_func(plugin)->newPlugin(&plugin_ctx_list[i++]); + if (plug_func(plugin)->newPlugin(&plugin_ctx_list[i++]) != bRC_OK) { + b_ctx->disabled = true; + } } } @@ -488,9 +694,10 @@ void free_plugins(JCR *jcr) bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list; Dmsg2(dbglvl, "Free instance plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId); - foreach_alist(plugin, plugin_list) { + foreach_alist(plugin, plugin_list) { /* Free the plugin instance */ - plug_func(plugin)->freePlugin(&plugin_ctx_list[i++]); + plug_func(plugin)->freePlugin(&plugin_ctx_list[i]); + free(plugin_ctx_list[i++].bContext); /* free Bacula private context */ } free(plugin_ctx_list); jcr->plugin_ctx_list = NULL; @@ -500,9 +707,9 @@ static int my_plugin_bopen(BFILE *bfd, const char *fname, int flags, mode_t mode { JCR *jcr = bfd->jcr; Plugin *plugin = (Plugin *)jcr->plugin; - bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx; struct io_pkt io; - Dmsg0(dbglvl, "plugin_bopen\n"); + + Dmsg1(dbglvl, "plugin_bopen flags=%x\n", flags); io.pkt_size = sizeof(io); io.pkt_end = sizeof(io); io.func = IO_OPEN; @@ -513,7 +720,7 @@ static int my_plugin_bopen(BFILE *bfd, const char *fname, int flags, mode_t mode io.mode = mode; io.win32 = false; io.lerror = 0; - plug_func(plugin)->pluginIO(plugin_ctx, &io); + plug_func(plugin)->pluginIO(jcr->plugin_ctx, &io); bfd->berrno = io.io_errno; if (io.win32) { errno = b_errno_win32; @@ -521,6 +728,7 @@ static int my_plugin_bopen(BFILE *bfd, const char *fname, int flags, mode_t mode errno = io.io_errno; bfd->lerror = io.lerror; } + Dmsg1(50, "Return from plugin open status=%d\n", io.status); return io.status; } @@ -528,9 +736,8 @@ static int my_plugin_bclose(BFILE *bfd) { JCR *jcr = bfd->jcr; Plugin *plugin = (Plugin *)jcr->plugin; - bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx; struct io_pkt io; - Dmsg0(dbglvl, "plugin_bclose\n"); + Dmsg0(dbglvl, "===== plugin_bclose\n"); io.pkt_size = sizeof(io); io.pkt_end = sizeof(io); io.func = IO_CLOSE; @@ -538,7 +745,7 @@ static int my_plugin_bclose(BFILE *bfd) io.buf = NULL; io.win32 = false; io.lerror = 0; - plug_func(plugin)->pluginIO(plugin_ctx, &io); + plug_func(plugin)->pluginIO(jcr->plugin_ctx, &io); bfd->berrno = io.io_errno; if (io.win32) { errno = b_errno_win32; @@ -554,7 +761,6 @@ static ssize_t my_plugin_bread(BFILE *bfd, void *buf, size_t count) { JCR *jcr = bfd->jcr; Plugin *plugin = (Plugin *)jcr->plugin; - bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx; struct io_pkt io; Dmsg0(dbglvl, "plugin_bread\n"); io.pkt_size = sizeof(io); @@ -564,7 +770,7 @@ static ssize_t my_plugin_bread(BFILE *bfd, void *buf, size_t count) io.buf = (char *)buf; io.win32 = false; io.lerror = 0; - plug_func(plugin)->pluginIO(plugin_ctx, &io); + plug_func(plugin)->pluginIO(jcr->plugin_ctx, &io); bfd->berrno = io.io_errno; if (io.win32) { errno = b_errno_win32; @@ -579,7 +785,6 @@ static ssize_t my_plugin_bwrite(BFILE *bfd, void *buf, size_t count) { JCR *jcr = bfd->jcr; Plugin *plugin = (Plugin *)jcr->plugin; - bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx; struct io_pkt io; Dmsg0(dbglvl, "plugin_bwrite\n"); io.pkt_size = sizeof(io); @@ -589,7 +794,7 @@ static ssize_t my_plugin_bwrite(BFILE *bfd, void *buf, size_t count) io.buf = (char *)buf; io.win32 = false; io.lerror = 0; - plug_func(plugin)->pluginIO(plugin_ctx, &io); + plug_func(plugin)->pluginIO(jcr->plugin_ctx, &io); bfd->berrno = io.io_errno; if (io.win32) { errno = b_errno_win32; @@ -604,7 +809,6 @@ static boffset_t my_plugin_blseek(BFILE *bfd, boffset_t offset, int whence) { JCR *jcr = bfd->jcr; Plugin *plugin = (Plugin *)jcr->plugin; - bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx; struct io_pkt io; Dmsg0(dbglvl, "plugin_bseek\n"); io.pkt_size = sizeof(io); @@ -614,7 +818,7 @@ static boffset_t my_plugin_blseek(BFILE *bfd, boffset_t offset, int whence) io.whence = whence; io.win32 = false; io.lerror = 0; - plug_func(plugin)->pluginIO(plugin_ctx, &io); + plug_func(plugin)->pluginIO(jcr->plugin_ctx, &io); bfd->berrno = io.io_errno; if (io.win32) { errno = b_errno_win32; @@ -633,9 +837,14 @@ static boffset_t my_plugin_blseek(BFILE *bfd, boffset_t offset, int whence) */ static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value) { - JCR *jcr = (JCR *)(ctx->bContext); + JCR *jcr; + if (!value || !ctx) { + return bRC_Error; + } + jcr = ((bacula_ctx *)ctx->bContext)->jcr; // Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var); - if (!value) { + jcr = ((bacula_ctx *)ctx->bContext)->jcr; + if (!jcr) { return bRC_Error; } // Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr); @@ -649,19 +858,61 @@ static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value) Dmsg1(dbglvl, "Bacula: return my_name=%s\n", my_name); break; case bVarLevel: + *((int *)value) = jcr->get_JobLevel(); + Dmsg1(dbglvl, "Bacula: return bVarJobLevel=%d\n", jcr->get_JobLevel()); + break; case bVarType: + *((int *)value) = jcr->get_JobType(); + Dmsg1(dbglvl, "Bacula: return bVarJobType=%d\n", jcr->get_JobType()); + break; case bVarClient: + *((char **)value) = jcr->client_name; + Dmsg1(dbglvl, "Bacula: return Client_name=%s\n", jcr->client_name); + break; case bVarJobName: + *((char **)value) = jcr->Job; + Dmsg1(dbglvl, "Bacula: return Job name=%s\n", jcr->Job); + break; case bVarJobStatus: + *((int *)value) = jcr->JobStatus; + Dmsg1(dbglvl, "Bacula: return bVarJobStatus=%d\n", jcr->JobStatus); + break; case bVarSinceTime: + *((int *)value) = (int)jcr->mtime; + Dmsg1(dbglvl, "Bacula: return since=%d\n", (int)jcr->mtime); break; + case bVarAccurate: + *((int *)value) = (int)jcr->accurate; + Dmsg1(dbglvl, "Bacula: return accurate=%d\n", (int)jcr->accurate); + break; + case bVarFileSeen: + break; /* a write only variable, ignore read request */ } return bRC_OK; } static bRC baculaSetValue(bpContext *ctx, bVariable var, void *value) { - Dmsg1(dbglvl, "bacula: baculaSetValue var=%d\n", var); + JCR *jcr; + if (!value || !ctx) { + return bRC_Error; + } + jcr = ((bacula_ctx *)ctx->bContext)->jcr; +// Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var); + jcr = ((bacula_ctx *)ctx->bContext)->jcr; + if (!jcr) { + return bRC_Error; + } +// Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr); + switch (var) { + case bVarFileSeen: + if (!accurate_mark_file_as_seen(jcr, (char *)value)) { + return bRC_Error; + } + break; + default: + break; + } return bRC_OK; } @@ -670,6 +921,10 @@ static bRC baculaRegisterEvents(bpContext *ctx, ...) va_list args; uint32_t event; + if (!ctx) { + return bRC_Error; + } + va_start(args, ctx); while ((event = va_arg(args, uint32_t))) { Dmsg1(dbglvl, "Plugin wants event=%u\n", event); @@ -679,11 +934,17 @@ static bRC baculaRegisterEvents(bpContext *ctx, ...) } static bRC baculaJobMsg(bpContext *ctx, const char *file, int line, - int type, time_t mtime, const char *fmt, ...) + int type, utime_t mtime, const char *fmt, ...) { va_list arg_ptr; char buf[2000]; - JCR *jcr = (JCR *)(ctx->bContext); + JCR *jcr; + + if (ctx) { + jcr = ((bacula_ctx *)ctx->bContext)->jcr; + } else { + jcr = NULL; + } va_start(arg_ptr, fmt); bvsnprintf(buf, sizeof(buf), fmt, arg_ptr); @@ -705,6 +966,27 @@ static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line, return bRC_OK; } +static void *baculaMalloc(bpContext *ctx, const char *file, int line, + size_t size) +{ +#ifdef SMARTALLOC + return sm_malloc(file, line, size); +#else + return malloc(size); +#endif +} + +static void baculaFree(bpContext *ctx, const char *file, int line, void *mem) +{ +#ifdef SMARTALLOC + sm_free(file, line, mem); +#else + free(mem); +#endif +} + + + #ifdef TEST_PROGRAM int (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode) = NULL;