X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=bacula%2Fsrc%2Ffiled%2Ffd_plugins.c;h=5f4084fee1d15ef8b45410b651c31d57b8170686;hb=ebcac6d33874b4db1defa15fe9fb9ff19948b77c;hp=f75b51d7b937f3aebad638d95260fc62d8d71711;hpb=dbe749ea4435b75ef3afc327381218f24b69b890;p=bacula%2Fbacula diff --git a/bacula/src/filed/fd_plugins.c b/bacula/src/filed/fd_plugins.c index f75b51d7b9..5f4084fee1 100644 --- a/bacula/src/filed/fd_plugins.c +++ b/bacula/src/filed/fd_plugins.c @@ -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,17 @@ 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); +/* + * 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 +76,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 +88,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 +122,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) { return; /* Return if no plugins loaded */ } @@ -106,12 +134,19 @@ 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; } @@ -159,15 +194,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 +227,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,8 +235,6 @@ 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; @@ -198,17 +243,20 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level) memcpy(&ff_pkt->statp, &sp.statp, sizeof(ff_pkt->statp)); Dmsg1(dbglvl, "Save_file: file=%s\n", ff_pkt->fname); 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) { 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; } @@ -218,11 +266,20 @@ 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 (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; @@ -231,7 +288,7 @@ bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start) 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"); @@ -261,7 +318,7 @@ bool plugin_name_stream(JCR *jcr, char *name) Plugin *plugin; int len; int i = 0; - bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list; + bpContext *plugin_ctx_list = jcr->plugin_ctx_list; Dmsg1(dbglvl, "Read plugin stream string=%s\n", name); skip_nonspaces(&p); /* skip over jcr->JobFiles */ @@ -281,8 +338,7 @@ bool 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; @@ -317,17 +373,23 @@ bool 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 start; } @@ -343,13 +405,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)) { return CF_ERROR; } rp.pkt_size = sizeof(rp); @@ -419,6 +481,21 @@ bool plugin_set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) return true; } +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. @@ -454,6 +531,8 @@ void load_fd_plugins(const char *plugin_dir) Dmsg1(dbglvl, "Loaded plugin: %s\n", plugin->file); } + + dbg_plugin_add_hook(dump_fd_plugin); } /* @@ -478,15 +557,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; + } } } @@ -504,9 +588,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; @@ -516,8 +601,8 @@ 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; + Dmsg1(dbglvl, "plugin_bopen flags=%x\n", flags); io.pkt_size = sizeof(io); io.pkt_end = sizeof(io); @@ -529,7 +614,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; @@ -545,7 +630,6 @@ 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"); io.pkt_size = sizeof(io); @@ -555,7 +639,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; @@ -571,7 +655,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); @@ -581,7 +664,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; @@ -596,7 +679,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); @@ -606,7 +688,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; @@ -621,7 +703,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); @@ -631,7 +712,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; @@ -650,9 +731,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; + jcr = ((bacula_ctx *)ctx->bContext)->jcr; // Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var); - if (!value) { + if (!value || !ctx) { + return bRC_Error; + } + jcr = ((bacula_ctx *)ctx->bContext)->jcr; + if (!jcr) { return bRC_Error; } // Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr); @@ -678,6 +764,9 @@ static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value) static bRC baculaSetValue(bpContext *ctx, bVariable var, void *value) { + if (!value || !ctx) { + return bRC_Error; + } Dmsg1(dbglvl, "bacula: baculaSetValue var=%d\n", var); return bRC_OK; } @@ -687,6 +776,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); @@ -696,11 +789,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); @@ -722,6 +821,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;