From 7c1006b22def05a77f4f1da03f7689f2b69144f7 Mon Sep 17 00:00:00 2001 From: Marco van Wieringen Date: Sat, 13 Jul 2013 17:29:43 +0200 Subject: [PATCH] Implement plugin options passing. Implement a new feature to pass plugin option as part of the restore process. Most of the plugin options input was already implemented but for the restore the options were never pushed to the file daemon. We should pass it to the filed and raise a bEventPluginCommand event. This way a user can pass in extra hints to the plugin for the restore process. Currently the plugin only gets passed in the plugin options that were defined at the moment the backup was made. The options defined by the user at restore time are passed before the actual options saved at backup time are passed so the plugin should take care to ignore any of the options passed in as part of the backup stream being restored when it already got a override at restore time. We increased the FD protocol number to 52 to be able to detect if the file daemon understand the new protocol keyword. Along the way we tweaked the layout of fileset traversal code somewhat. Added some spaces and fixed the scoping of the variables somewhat. So you understand what is going on. And fixed the comments in the filed plugin code. Fixes #207: Implement plugin options passing. --- src/dird/dird.h | 1 + src/dird/fd_cmds.c | 122 +++++++++++++------ src/dird/protos.h | 1 + src/dird/restore.c | 11 ++ src/dird/ua_run.c | 2 - src/filed/authenticate.c | 3 +- src/filed/dir_cmd.c | 36 ++++++ src/filed/fd_plugins.c | 256 ++++++++++++++++++++++++++------------- 8 files changed, 311 insertions(+), 121 deletions(-) diff --git a/src/dird/dird.h b/src/dird/dird.h index ec954126c10..ecebf75f6ee 100644 --- a/src/dird/dird.h +++ b/src/dird/dird.h @@ -120,5 +120,6 @@ typedef struct s_vol_list { #define FD_VERSION_4 4 #define FD_VERSION_5 5 #define FD_VERSION_51 51 +#define FD_VERSION_52 52 #include "protos.h" diff --git a/src/dird/fd_cmds.c b/src/dird/fd_cmds.c index 6d7d87e55c0..9a6255b6482 100644 --- a/src/dird/fd_cmds.c +++ b/src/dird/fd_cmds.c @@ -46,12 +46,16 @@ static char jobcmd[] = /* Note, mtime_only is not used here -- implemented as file option */ static char levelcmd[] = "level = %s%s%s mtime_only=%d %s%s\n"; -static char runscript[] = +static char runscriptcmd[] = "Run OnSuccess=%u OnFailure=%u AbortOnError=%u When=%u Command=%s\n"; -static char runbeforenow[] = +static char runbeforenowcmd[] = "RunBeforeNow\n"; +static char restoreobjectendcmd[] = + "restoreobject end\n"; static char bandwidthcmd[] = "setbandwidth=%lld Job=%s\n"; +static char pluginoptionscmd[] = + "pluginoptions %s\n"; /* Responses received from File daemon */ static char OKinc[] = @@ -68,6 +72,8 @@ static char OKRestoreObject[] = "2000 OK ObjectRestored\n"; static char OKBandwidth[] = "2000 OK Bandwidth\n"; +static char OKPluginOptions[] = + "2000 OK PluginOptions\n"; /* Forward referenced functions */ static bool send_list_item(JCR *jcr, const char *code, char *item, BSOCK *fd); @@ -251,16 +257,15 @@ static bool send_fileset(JCR *jcr) int num; bool include = true; - for ( ;; ) { + while (1) { if (include) { num = fileset->num_includes; } else { num = fileset->num_excludes; } - for (int i=0; iinclude_items[i]; @@ -269,98 +274,124 @@ static bool send_fileset(JCR *jcr) ie = fileset->exclude_items[i]; fd->fsend("E\n"); } + if (ie->ignoredir) { fd->fsend("Z %s\n", ie->ignoredir); } - for (j=0; jnum_opts; j++) { - FOPTS *fo = ie->opts_list[j]; + for (int j = 0; j < ie->num_opts; j++) { + FOPTS *fo = ie->opts_list[j]; bool enhanced_wild = false; - for (k=0; fo->opts[k]!='\0'; k++) { + + for (int k = 0; fo->opts[k] != '\0'; k++) { if (fo->opts[k]=='W') { enhanced_wild = true; break; } } - /* Strip out compression option Zn if disallowed for this Storage */ + /* + * Strip out compression option Zn if disallowed for this Storage + */ if (store && !store->AllowCompress) { char newopts[MAX_FOPTS]; bool done=false; /* print warning only if compression enabled in FS */ - int j = 0; - for (k=0; fo->opts[k]!='\0'; k++) { - /* Z compress option is followed by the single-digit compress level or 'o' */ + int l = 0; + + for (int k = 0; fo->opts[k] != '\0'; k++) { + /* + * Z compress option is followed by the single-digit compress level or 'o' + */ if (fo->opts[k]=='Z') { - done=true; + done = true; k++; /* skip option and level */ } else { - newopts[j] = fo->opts[k]; - j++; + newopts[l] = fo->opts[k]; + l++; } } - newopts[j] = '\0'; + newopts[l] = '\0'; if (done) { Jmsg(jcr, M_INFO, 0, - _("FD compression disabled for this Job because AllowCompress=No in Storage resource.\n") ); + _("FD compression disabled for this Job because AllowCompress=No in Storage resource.\n") ); } - /* Send the new trimmed option set without overwriting fo->opts */ + + /* + * Send the new trimmed option set without overwriting fo->opts + */ fd->fsend("O %s\n", newopts); } else { - /* Send the original options */ + /* + * Send the original options + */ fd->fsend("O %s\n", fo->opts); } - for (k=0; kregex.size(); k++) { + for (int k = 0; k < fo->regex.size(); k++) { fd->fsend("R %s\n", fo->regex.get(k)); } - for (k=0; kregexdir.size(); k++) { + + for (int k = 0; k < fo->regexdir.size(); k++) { fd->fsend("RD %s\n", fo->regexdir.get(k)); } - for (k=0; kregexfile.size(); k++) { + + for (int k = 0; k < fo->regexfile.size(); k++) { fd->fsend("RF %s\n", fo->regexfile.get(k)); } - for (k=0; kwild.size(); k++) { + + for (int k = 0; kwild.size(); k++) { fd->fsend("W %s\n", fo->wild.get(k)); } - for (k=0; kwilddir.size(); k++) { + + for (int k = 0; k < fo->wilddir.size(); k++) { fd->fsend("WD %s\n", fo->wilddir.get(k)); } - for (k=0; kwildfile.size(); k++) { + + for (int k = 0; k < fo->wildfile.size(); k++) { fd->fsend("WF %s\n", fo->wildfile.get(k)); } - for (k=0; kwildbase.size(); k++) { + + for (int k = 0; k < fo->wildbase.size(); k++) { fd->fsend("W%c %s\n", enhanced_wild ? 'B' : 'F', fo->wildbase.get(k)); } - for (k=0; kbase.size(); k++) { + + for (int k = 0; k < fo->base.size(); k++) { fd->fsend("B %s\n", fo->base.get(k)); } - for (k=0; kfstype.size(); k++) { + + for (int k = 0; k < fo->fstype.size(); k++) { fd->fsend("X %s\n", fo->fstype.get(k)); } - for (k=0; kdrivetype.size(); k++) { + + for (int k = 0; k < fo->drivetype.size(); k++) { fd->fsend("XD %s\n", fo->drivetype.get(k)); } + if (fo->plugin) { fd->fsend("G %s\n", fo->plugin); } + if (fo->reader) { fd->fsend("D %s\n", fo->reader); } + if (fo->writer) { fd->fsend("T %s\n", fo->writer); } + fd->fsend("N\n"); } - for (j=0; jname_list.size(); j++) { + for (int j = 0; j < ie->name_list.size(); j++) { item = (char *)ie->name_list.get(j); if (!send_list_item(jcr, "F ", item, fd)) { goto bail_out; } } fd->fsend("N\n"); - for (j=0; jplugin_list.size(); j++) { + + for (int j = 0; j < ie->plugin_list.size(); j++) { item = (char *)ie->plugin_list.get(j); if (!send_list_item(jcr, "P ", item, fd)) { goto bail_out; @@ -368,9 +399,11 @@ static bool send_fileset(JCR *jcr) } fd->fsend("N\n"); } + if (!include) { /* If we just did excludes */ break; /* all done */ } + include = false; /* Now do excludes */ } @@ -540,7 +573,7 @@ int send_runscripts_commands(JCR *jcr) Dmsg1(120, "bdird: sending runscripts to fd '%s'\n", cmd->command); - fd->fsend(runscript, + fd->fsend(runscriptcmd, cmd->on_success, cmd->on_failure, cmd->fail_on_error, @@ -573,7 +606,7 @@ int send_runscripts_commands(JCR *jcr) * Tell the FD to execute the ClientRunBeforeJob */ if (has_before_jobs) { - fd->fsend(runbeforenow); + fd->fsend(runbeforenowcmd); if (!response(jcr, fd, OKRunBeforeNow, "RunBeforeNow", DISPLAY_ERROR)) { goto bail_out; } @@ -652,6 +685,27 @@ static int restore_object_handler(void *ctx, int num_fields, char **row) return 0; } +bool send_plugin_options(JCR *jcr) +{ + BSOCK *fd = jcr->file_bsock; + POOLMEM *msg; + + if (jcr->plugin_options) { + msg = get_pool_memory(PM_FNAME); + pm_strcpy(msg, jcr->plugin_options); + bash_spaces(msg); + + fd->fsend(pluginoptionscmd, msg); + free_pool_memory(msg); + + if (!response(jcr, fd, OKPluginOptions, "PluginOptions", DISPLAY_ERROR)) { + Jmsg(jcr, M_FATAL, 0, _("Plugin options failed.\n")); + return false; + } + } + return true; +} + bool send_restore_objects(JCR *jcr) { char ed1[50]; @@ -682,7 +736,7 @@ bool send_restore_objects(JCR *jcr) */ if (octx.count > 0) { fd = jcr->file_bsock; - fd->fsend("restoreobject end\n"); + fd->fsend(restoreobjectendcmd); if (!response(jcr, fd, OKRestoreObject, "RestoreObject", DISPLAY_ERROR)) { Jmsg(jcr, M_FATAL, 0, _("RestoreObject failed.\n")); return false; diff --git a/src/dird/protos.h b/src/dird/protos.h index 0c4ad3a7d52..30518488416 100644 --- a/src/dird/protos.h +++ b/src/dird/protos.h @@ -101,6 +101,7 @@ void get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId); int put_file_into_catalog(JCR *jcr, long file_index, char *fname, char *link, char *attr, int stream); int send_runscripts_commands(JCR *jcr); +bool send_plugin_options(JCR *jcr); bool send_restore_objects(JCR *jcr); bool cancel_file_daemon_job(UAContext *ua, JCR *jcr); void do_native_client_status(UAContext *ua, CLIENTRES *client, char *cmd); diff --git a/src/dird/restore.c b/src/dird/restore.c index dc1f61be6ab..0c25c176e68 100644 --- a/src/dird/restore.c +++ b/src/dird/restore.c @@ -315,10 +315,21 @@ static inline bool do_native_restore_bootstrap(JCR *jcr) if (!send_runscripts_commands(jcr)) { goto bail_out; } + if (!send_restore_objects(jcr)) { Dmsg0(000, "FAIL: Send restore objects\n"); goto bail_out; } + + /* + * Only FD version 52 and later understand the sending of plugin options. + */ + if (jcr->FDVersion >= FD_VERSION_52) { + if (!send_plugin_options(jcr)) { + Dmsg0(000, "FAIL: Send plugin options\n"); + goto bail_out; + } + } } fd->fsend("%s", restore_cmd.c_str()); diff --git a/src/dird/ua_run.c b/src/dird/ua_run.c index 1f98fee807e..e67f6b0f368 100644 --- a/src/dird/ua_run.c +++ b/src/dird/ua_run.c @@ -1820,8 +1820,6 @@ static bool scan_command_line_arguments(UAContext *ua, RUN_CTX &rc) kw_ok = true; break; case 26: /* pluginoptions */ - ua->send_msg(_("Plugin Options not yet implemented.\n")); - return false; if (rc.plugin_options) { ua->send_msg(_("Plugin Options specified twice.\n")); return false; diff --git a/src/filed/authenticate.c b/src/filed/authenticate.c index b54f8d21897..cc67d5f3a43 100644 --- a/src/filed/authenticate.c +++ b/src/filed/authenticate.c @@ -40,11 +40,12 @@ const int dbglvl = 50; * 5 24Nov11 - Added new restore object command format (pluginname) 6.0 * * 51 21Mar13 - Added reverse datachannel initialization + * 52 13Jul13 - Added plugin options */ static char OK_hello_compat[] = "2000 OK Hello 5\n"; static char OK_hello[] = - "2000 OK Hello 51\n"; + "2000 OK Hello 52\n"; static char Dir_sorry[] = "2999 Authentication failed.\n"; diff --git a/src/filed/dir_cmd.c b/src/filed/dir_cmd.c index afbbfa8765f..4b8c34ccd92 100644 --- a/src/filed/dir_cmd.c +++ b/src/filed/dir_cmd.c @@ -74,6 +74,7 @@ static bool exit_cmd(JCR *jcr); static bool fileset_cmd(JCR *jcr); static bool job_cmd(JCR *jcr); static bool level_cmd(JCR *jcr); +static bool pluginoptions_cmd(JCR *jcr); static bool runafter_cmd(JCR *jcr); static bool runbeforenow_cmd(JCR *jcr); static bool runbefore_cmd(JCR *jcr); @@ -119,6 +120,7 @@ static struct s_cmds cmds[] = { { "fileset", fileset_cmd, false }, { "JobId=", job_cmd, false }, { "level = ", level_cmd, false }, + { "pluginoptions", pluginoptions_cmd, false }, { "RunAfterJob", runafter_cmd, false }, { "RunBeforeNow", runbeforenow_cmd, false }, { "RunBeforeJob", runbefore_cmd, false }, @@ -166,6 +168,8 @@ static char restoreobjcmd1[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d\n"; static char endrestoreobjectcmd[] = "restoreobject end\n"; +static char pluginoptionscmd[] = + "pluginoptions %s"; static char verifycmd[] = "verify level=%30s"; static char estimatecmd[] = @@ -235,6 +239,10 @@ static char BADcmd[] = "2902 Bad %s\n"; static char OKRestoreObject[] = "2000 OK ObjectRestored\n"; +static char OKPluginOptions[] = + "2000 OK PluginOptions\n"; +static char BadPluginOptions[] = + "2905 Bad PluginOptions command.\n"; /* * Responses received from Storage Daemon @@ -924,6 +932,30 @@ static bool runscript_cmd(JCR *jcr) return dir->fsend(OKRunScript); } +/* + * This passes plugin specific options. + */ +static bool pluginoptions_cmd(JCR *jcr) +{ + BSOCK *dir = jcr->dir_bsock; + POOLMEM *msg; + + msg = get_memory(dir->msglen + 1); + if (sscanf(dir->msg, pluginoptionscmd, msg) != 1) { + pm_strcpy(jcr->errmsg, dir->msg); + Jmsg1(jcr, M_FATAL, 0, _("Bad Plugin Options command: %s\n"), jcr->errmsg); + dir->fsend(BadPluginOptions); + free_memory(msg); + return false; + } + + unbash_spaces(msg); + generate_plugin_event(jcr, bEventPluginCommand, (void *)msg); + free_memory(msg); + + return dir->fsend(OKPluginOptions); +} + /* * This reads data sent from the Director from the * RestoreObject table that allows us to get objects @@ -2036,6 +2068,10 @@ static void filed_free_jcr(JCR *jcr) free_pool_memory(jcr->last_fname); } + if (jcr->plugin_options) { + free(jcr->plugin_options); + } + free_bootstrap(jcr); free_runscripts(jcr->RunScripts); delete jcr->RunScripts; diff --git a/src/filed/fd_plugins.c b/src/filed/fd_plugins.c index a7894ddd42f..8d5c04afbca 100644 --- a/src/filed/fd_plugins.c +++ b/src/filed/fd_plugins.c @@ -156,7 +156,7 @@ static inline bool is_plugin_disabled(bpContext *ctx) return b_ctx->disabled; } -/* +/** * Test if event is for this plugin */ static bool for_this_plugin(Plugin *plugin, char *name, int len) @@ -165,34 +165,47 @@ static bool for_this_plugin(Plugin *plugin, char *name, int len) if (!name) { /* if no plugin name, all plugins get it */ return true; } - /* Return global VSS job metadata to all plugins */ + + /* + * Return global VSS job metadata to all plugins + */ if (bstrcmp("job", name)) { /* old V4.0 name for VSS job metadata */ return true; } + if (bstrcmp("*all*", name)) { /* new v6.0 name for VSS job metadata */ return true; } - /* Check if this is the correct plugin */ + + /* + * Check if this is the correct plugin + */ if (len == plugin->file_len && bstrncmp(plugin->file, name, len)) { return true; } + return false; } +/** + * Test if plugin is disabled. + */ bool is_plugin_disabled(JCR *jcr) { return is_plugin_disabled(jcr->plugin_ctx); } +/** + * Raise a certain plugin event. + */ static inline void trigger_plugin_event(JCR *jcr, bEventType eventType, bEvent *event, Plugin *plugin, bpContext *plugin_ctx_list, int index, void *value) { bpContext *ctx; /* - * Note, at this point do not change - * jcr->plugin or jcr->plugin_ctx + * Note, at this point do not change jcr->plugin or jcr->plugin_ctx */ Dsm_check(999); ctx = &plugin_ctx_list[index]; @@ -221,8 +234,7 @@ static inline void trigger_plugin_event(JCR *jcr, bEventType eventType, bEvent * } /** - * Create a plugin event When receiving bEventCancelCommand, this function is - * called by an other thread. + * Create a plugin event When receiving bEventCancelCommand, this function is called by an other thread. */ void generate_plugin_event(JCR *jcr, bEventType eventType, void *value, bool reverse) { @@ -240,8 +252,7 @@ void generate_plugin_event(JCR *jcr, bEventType eventType, void *value, bool rev } /* - * Some events are sent to only a particular plugin or must be - * called even if the job is canceled. + * Some events are sent to only a particular plugin or must be called even if the job is canceled. */ switch(eventType) { case bEventPluginCommand: @@ -265,7 +276,6 @@ void generate_plugin_event(JCR *jcr, bEventType eventType, void *value, bool rev get_plugin_name(jcr, name, &len); } } - break; case bEventEndBackupJob: case bEventEndVerifyJob: @@ -297,9 +307,8 @@ void generate_plugin_event(JCR *jcr, bEventType eventType, void *value, bool rev Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId); /* - * Pass event to every plugin that has requested this event type - * (except if name is set). If name is set, we pass it only to - * the plugin with that name. + * Pass event to every plugin that has requested this event type (except if name is set). + * If name is set, we pass it only to the plugin with that name. * * See if we need to trigger the loaded plugins in reverse order. */ @@ -346,7 +355,9 @@ bool plugin_check_file(JCR *jcr, char *fname) Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId); - /* Pass event to every plugin */ + /* + * Pass event to every plugin + */ foreach_alist_index(i, plugin, fd_plugin_list) { jcr->plugin_ctx = &plugin_ctx_list[i]; jcr->plugin = plugin; @@ -368,7 +379,7 @@ bool plugin_check_file(JCR *jcr, char *fname) return rc == bRC_Seen; } -/* +/** * Get the first part of the the plugin command * systemstate:/@SYSTEMSTATE/ * => ret = 11 @@ -386,7 +397,10 @@ static bool get_plugin_name(JCR *jcr, char *cmd, int *ret) if (!cmd || (*cmd == '\0')) { return false; } - /* Handle plugin command here backup */ + + /* + * Handle plugin command here backup + */ Dmsg1(dbglvl, "plugin cmd=%s\n", cmd); if ((p = strchr(cmd, ':')) == NULL) { if (strchr(cmd, ' ') == NULL) { /* we have just the plugin name */ @@ -411,6 +425,7 @@ static void update_ff_pkt(FF_PKT *ff_pkt, struct save_pkt *sp) Dsm_check(999); ff_pkt->no_read = sp->no_read; ff_pkt->delta_seq = sp->delta_seq; + if (sp->flags & FO_DELTA) { ff_pkt->flags |= FO_DELTA; ff_pkt->delta_seq++; /* make new delta sequence number */ @@ -424,7 +439,9 @@ static void update_ff_pkt(FF_PKT *ff_pkt, struct save_pkt *sp) } else { ff_pkt->flags &= ~FO_OFFSETS; } - /* Sparse code doesn't work with plugins + + /* + * Sparse code doesn't work with plugins * that use FIFO or STDOUT/IN to communicate */ if (sp->flags & FO_SPARSE) { @@ -432,16 +449,18 @@ static void update_ff_pkt(FF_PKT *ff_pkt, struct save_pkt *sp) } else { ff_pkt->flags &= ~FO_SPARSE; } + if (sp->flags & FO_PORTABLE_DATA) { ff_pkt->flags |= FO_PORTABLE_DATA; } else { ff_pkt->flags &= ~FO_PORTABLE_DATA; } + ff_pkt->flags |= FO_PLUGIN; /* data from plugin */ Dsm_check(999); } -/* +/** * Ask to a Option Plugin what to do with the current file */ bRC plugin_option_handle_file(JCR *jcr, FF_PKT *ff_pkt, struct save_pkt *sp) @@ -476,7 +495,9 @@ bRC plugin_option_handle_file(JCR *jcr, FF_PKT *ff_pkt, struct save_pkt *sp) goto bail_out; } - /* Note, we stop the loop on the first plugin that matches the name */ + /* + * Note, we stop the loop on the first plugin that matches the name + */ foreach_alist_index(i, plugin, fd_plugin_list) { Dmsg4(dbglvl, "plugin=%s plen=%d cmd=%s len=%d\n", plugin->file, plugin->file_len, cmd, len); if (!for_this_plugin(plugin, cmd, len)) { @@ -491,10 +512,11 @@ bRC plugin_option_handle_file(JCR *jcr, FF_PKT *ff_pkt, struct save_pkt *sp) jcr->plugin_ctx = &plugin_ctx_list[i]; jcr->plugin = plugin; - ret = plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i], - &event, sp); + ret = plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i], &event, sp); - /* TODO: would be better to set this in save_file() */ + /* + * TODO: would be better to set this in save_file() + */ if (ret == bRC_OK) { jcr->opt_plugin = true; jcr->plugin = plugin; @@ -502,9 +524,10 @@ bRC plugin_option_handle_file(JCR *jcr, FF_PKT *ff_pkt, struct save_pkt *sp) jcr->plugin_ctx = &plugin_ctx_list[i]; update_ff_pkt(ff_pkt, sp); - - /* reset plugin in JCR if not used this time */ } else { + /* + * Reset plugin in JCR if not used this time + */ jcr->plugin_ctx = NULL; jcr->plugin = NULL; } @@ -556,16 +579,18 @@ 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 */ + /* + * Note, we stop the loop on the first plugin that matches the name + */ foreach_alist_index(i, plugin, fd_plugin_list) { Dmsg4(dbglvl, "plugin=%s plen=%d cmd=%s len=%d\n", plugin->file, plugin->file_len, cmd, len); if (!for_this_plugin(plugin, cmd, len)) { 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. + * 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. */ Dsm_check(999); jcr->plugin_ctx = &plugin_ctx_list[i]; @@ -574,12 +599,17 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level) goto bail_out; } + /* + * Send the backup command to the right plugin + */ Dmsg1(dbglvl, "Command plugin = %s\n", cmd); - /* Send the backup command to the right plugin*/ if (plug_func(plugin)->handlePluginEvent(jcr->plugin_ctx, &event, cmd) != bRC_OK) { goto bail_out; } - /* Loop getting filenames to backup then saving them */ + + /* + * Loop getting filenames to backup then saving them + */ while (!jcr->is_job_canceled()) { memset(&sp, 0, sizeof(sp)); sp.pkt_size = sizeof(sp); @@ -591,7 +621,10 @@ 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); Dsm_check(999); - /* Get the file save parameters. I.e. the stat pkt ... */ + + /* + * Get the file save parameters. I.e. the stat pkt ... + */ if (plug_func(plugin)->startBackupFile(jcr->plugin_ctx, &sp) != bRC_OK) { goto bail_out; } @@ -602,9 +635,9 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level) } jcr->plugin_sp = &sp; ff_pkt = jcr->ff; + /* - * Copy fname and link because save_file() zaps them. This - * avoids zaping the plugin's strings. + * Copy fname and link because save_file() zaps them. This avoids zaping the plugin's strings. */ ff_pkt->type = sp.type; if (IS_FT_OBJECT(sp.type)) { @@ -640,7 +673,10 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level) if (sp.object) { Dmsg2(dbglvl, "index=%d object=%s\n", sp.index, sp.object); } - /* Call Bareos core code to backup the plugin's file */ + + /* + * Call Bareos core code to backup the plugin's file + */ save_file(jcr, ff_pkt, true); bRC rc = plug_func(plugin)->endBackupFile(jcr->plugin_ctx); if (rc == bRC_More || rc == bRC_OK) { @@ -708,10 +744,10 @@ int plugin_estimate(JCR *jcr, FF_PKT *ff_pkt, bool top_level) if (!for_this_plugin(plugin, cmd, len)) { 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. + * 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. */ Dsm_check(999); jcr->plugin_ctx = &plugin_ctx_list[i]; @@ -720,13 +756,14 @@ int plugin_estimate(JCR *jcr, FF_PKT *ff_pkt, bool top_level) goto bail_out; } - Dmsg1(dbglvl, "Command plugin = %s\n", cmd); /* * Send the backup command to the right plugin */ + Dmsg1(dbglvl, "Command plugin = %s\n", cmd); if (plug_func(plugin)->handlePluginEvent(jcr->plugin_ctx, &event, cmd) != bRC_OK) { goto bail_out; } + /* * Loop getting filenames to backup then saving them */ @@ -738,12 +775,16 @@ int plugin_estimate(JCR *jcr, FF_PKT *ff_pkt, bool top_level) sp.portable = true; sp.flags = 0; sp.cmd = cmd; - 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. I.e. the stat pkt ... */ + 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. I.e. the stat pkt ... + */ if (plug_func(plugin)->startBackupFile(jcr->plugin_ctx, &sp) != bRC_OK) { goto bail_out; } + if (sp.type == 0) { Jmsg1(jcr, M_FATAL, 0, _("Command plugin \"%s\": no type in startBackupFile packet.\n"), cmd); @@ -757,7 +798,9 @@ int plugin_estimate(JCR *jcr, FF_PKT *ff_pkt, bool top_level) goto bail_out; } - /* Count only files backed up */ + /* + * Count only files backed up + */ switch (sp.type) { case FT_REGE: case FT_REG: @@ -837,7 +880,10 @@ bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start) index++; /* JobFiles not incremented yet */ } Dmsg1(dbglvl, "send_plugin_name=%s\n", sp->cmd); - /* Send stream header */ + + /* + * Send stream header + */ Dsm_check(999); if (!sd->fsend("%ld %d 0", index, STREAM_PLUGIN_NAME)) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), @@ -848,10 +894,14 @@ bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start) Dsm_check(999); if (start) { - /* Send data -- not much */ + /* + * Send data -- not much + */ status = sd->fsend("%ld 1 %d %s%c", index, sp->portable, sp->cmd, 0); } else { - /* Send end of data */ + /* + * Send end of data + */ status = sd->fsend("%ld 0", jcr->JobFiles); } Dsm_check(999); @@ -867,8 +917,8 @@ 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. + * 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 @@ -889,7 +939,9 @@ bool plugin_name_stream(JCR *jcr, char *name) skip_spaces(&p); start = *p == '1'; if (start) { - /* Start of plugin data */ + /* + * Start of plugin data + */ skip_nonspaces(&p); /* skip start/end flag */ skip_spaces(&p); // portable = *p == '1'; @@ -975,13 +1027,13 @@ bool plugin_name_stream(JCR *jcr, char *name) } /** - * Tell the plugin to create the file. Return values are - * This is called only during Restore + * Tell the plugin to create the file. this is called only during Restore. + * Return values are: * - * CF_ERROR -- error - * CF_SKIP -- skip processing this file - * CF_EXTRACT -- extract the file (i.e.call i/o routines) - * CF_CREATED -- created, but no content to extract (typically directories) + * CF_ERROR -> error + * CF_SKIP -> skip processing this file + * CF_EXTRACT -> extract the file (i.e.call i/o routines) + * CF_CREATED -> created, but no content to extract (typically directories) * */ int plugin_create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) @@ -1046,7 +1098,9 @@ int plugin_create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) return CF_CORE; /* Let Bareos core handle the file creation */ } - /* Created link or directory? */ + /* + * Created link or directory? + */ if (rp.create_status == CF_CREATED) { return rp.create_status; /* yes, no need to bopen */ } @@ -1074,10 +1128,10 @@ 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. + * 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) { @@ -1123,7 +1177,7 @@ bool plugin_set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) return true; } -/* +/** * Print to file the plugin info. */ static void dump_fd_plugin(Plugin *plugin, FILE *fp) @@ -1147,8 +1201,7 @@ static void dump_fd_plugins(FILE *fp) } /** - * This entry point is called internally by Bareos to ensure - * that the plugin IO calls come into this code. + * This entry point is called internally by Bareos to ensure that the plugin IO calls come into this code. */ void load_fd_plugins(const char *plugin_dir, const char *plugin_names) { @@ -1210,8 +1263,7 @@ int list_fd_plugins(POOL_MEM &msg) } /** - * Check if a plugin is compatible. Called by the load_plugin function - * to allow us to verify the 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) { @@ -1258,8 +1310,8 @@ static bool is_plugin_compatible(Plugin *plugin) /** * Create a new instance of each plugin for this Job - * Note, fd_plugin_list can exist but jcr->plugin_ctx_list can - * be NULL if no plugins were loaded. + * + * Note, fd_plugin_list can exist but jcr->plugin_ctx_list can be NULL if no plugins were loaded. */ void new_plugins(JCR *jcr) { @@ -1288,7 +1340,9 @@ void new_plugins(JCR *jcr) Dmsg2(dbglvl, "Instantiate plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId); foreach_alist_index(i, plugin, fd_plugin_list) { Dsm_check(999); - /* Start a new instance of each plugin */ + /* + * Start a new instance of each plugin + */ b_plugin_ctx *b_ctx = (b_plugin_ctx *)malloc(sizeof(b_plugin_ctx)); memset(b_ctx, 0, sizeof(b_plugin_ctx)); b_ctx->jcr = jcr; @@ -1321,7 +1375,9 @@ 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_index(i, plugin, fd_plugin_list) { - /* Free the plugin instance */ + /* + * Free the plugin instance + */ plug_func(plugin)->freePlugin(&plugin_ctx_list[i]); free(plugin_ctx_list[i].bContext); /* free Bareos private context */ Dsm_check(999); @@ -1331,6 +1387,9 @@ void free_plugins(JCR *jcr) jcr->plugin_ctx_list = NULL; } +/** + * Entry point for opening the file this is a wrapper around the pluginIO entry point in the plugin. + */ static int my_plugin_bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) { JCR *jcr = bfd->jcr; @@ -1365,6 +1424,9 @@ static int my_plugin_bopen(BFILE *bfd, const char *fname, int flags, mode_t mode return io.status; } +/** + * Entry point for closing the file this is a wrapper around the pluginIO entry point in the plugin. + */ static int my_plugin_bclose(BFILE *bfd) { JCR *jcr = bfd->jcr; @@ -1396,6 +1458,9 @@ static int my_plugin_bclose(BFILE *bfd) return io.status; } +/** + * Entry point for reading from the file this is a wrapper around the pluginIO entry point in the plugin. + */ static ssize_t my_plugin_bread(BFILE *bfd, void *buf, size_t count) { JCR *jcr = bfd->jcr; @@ -1428,6 +1493,9 @@ static ssize_t my_plugin_bread(BFILE *bfd, void *buf, size_t count) return (ssize_t)io.status; } +/** + * Entry point for writing to the file this is a wrapper around the pluginIO entry point in the plugin. + */ static ssize_t my_plugin_bwrite(BFILE *bfd, void *buf, size_t count) { JCR *jcr = bfd->jcr; @@ -1459,6 +1527,9 @@ static ssize_t my_plugin_bwrite(BFILE *bfd, void *buf, size_t count) return (ssize_t)io.status; } +/** + * Entry point for seeking in the file this is a wrapper around the pluginIO entry point in the plugin. + */ static boffset_t my_plugin_blseek(BFILE *bfd, boffset_t offset, int whence) { JCR *jcr = bfd->jcr; @@ -1731,8 +1802,7 @@ static bool is_ctx_good(bpContext *ctx, JCR *&jcr, b_plugin_ctx *&bctx) } /** - * Let the plugin define files/directories to be excluded - * from the main backup. + * Let the plugin define files/directories to be excluded from the main backup. */ static bRC bareosAddExclude(bpContext *ctx, const char *file) { @@ -1747,10 +1817,14 @@ static bRC bareosAddExclude(bpContext *ctx, const char *file) return bRC_Error; } - /* Save the include context */ + /* + * Save the include context + */ old = get_incexe(jcr); - /* Not right time to add exlude */ + /* + * Not right time to add exlude + */ if (!old) { return bRC_Error; } @@ -1759,12 +1833,16 @@ static bRC bareosAddExclude(bpContext *ctx, const char *file) bctx->exclude = new_exclude(jcr); } - /* Set the Exclude context */ + /* + * Set the Exclude context + */ set_incexe(jcr, bctx->exclude); add_file_to_fileset(jcr, file, true); - /* Restore the current context */ + /* + * Restore the current context + */ set_incexe(jcr, old); Dmsg1(100, "Add exclude file=%s\n", file); @@ -1773,8 +1851,7 @@ static bRC bareosAddExclude(bpContext *ctx, const char *file) } /** - * Let the plugin define files/directories to be excluded - * from the main backup. + * Let the plugin define files/directories to be excluded from the main backup. */ static bRC bareosAddInclude(bpContext *ctx, const char *file) { @@ -1786,17 +1863,23 @@ static bRC bareosAddInclude(bpContext *ctx, const char *file) if (!is_ctx_good(ctx, jcr, bctx)) { return bRC_Error; } + if (!file) { return bRC_Error; } - /* Save the include context */ + /* + * Save the include context + */ old = get_incexe(jcr); - /* Not right time to add include */ + /* + * Not right time to add include + */ if (!old) { return bRC_Error; } + if (!bctx->include) { bctx->include = old; } @@ -1804,7 +1887,9 @@ static bRC bareosAddInclude(bpContext *ctx, const char *file) set_incexe(jcr, bctx->include); add_file_to_fileset(jcr, file, true); - /* Restore the current context */ + /* + * Restore the current context + */ set_incexe(jcr, old); Dmsg1(100, "Add include file=%s\n", file); @@ -1906,7 +1991,7 @@ static bRC bareosNewPreInclude(bpContext *ctx) return bRC_OK; } -/* +/** * Check if a file have to be backuped using Accurate code */ static bRC bareosCheckChanges(bpContext *ctx, struct save_pkt *sp) @@ -1920,14 +2005,15 @@ static bRC bareosCheckChanges(bpContext *ctx, struct save_pkt *sp) if (!is_ctx_good(ctx, jcr, bctx)) { goto bail_out; } + if (!sp) { goto bail_out; } ff_pkt = jcr->ff; /* - * Copy fname and link because save_file() zaps them. This - * avoids zaping the plugin's strings. + * Copy fname and link because save_file() zaps them. + * This avoids zaping the plugin's strings. */ ff_pkt->type = sp->type; if (!sp->fname) { @@ -1957,7 +2043,7 @@ static bRC bareosCheckChanges(bpContext *ctx, struct save_pkt *sp) return ret; } -/* +/** * Check if a file would be saved using current Include/Exclude code */ static bRC bareosAcceptFile(bpContext *ctx, struct save_pkt *sp) @@ -1980,7 +2066,9 @@ static bRC bareosAcceptFile(bpContext *ctx, struct save_pkt *sp) ff_pkt = jcr->ff; - /* Probably not needed, but keep a copy */ + /* + * TODO: Probably not needed, but keep a copy + */ old = ff_pkt->fname; oldstat = ff_pkt->statp;