/* Forward referenced functions */
int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level);
-static int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level);
static void strip_path(FF_PKT *ff_pkt);
static void unstrip_path(FF_PKT *ff_pkt);
static int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest, DIGEST *signature_digest);
return true;
}
-int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
-{
- generate_plugin_event(jcr, bEventPluginCommand, (void *)ff_pkt->top_fname);
- return 1;
-}
/*
* Called here by find() for each file included.
baculaDebugMsg
};
+
+/*
+ * Create a plugin event
+ */
+void generate_plugin_event(JCR *jcr, bEventType eventType, void *value)
+{
+ bEvent event;
+ Plugin *plugin;
+ int i = 0;
+
+ if (!plugin_list) {
+ return; /* Return if no plugins loaded */
+ }
+
+ bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+ event.eventType = eventType;
+
+ Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
+
+ /* Pass event to every plugin */
+ foreach_alist(plugin, plugin_list) {
+ bRC rc;
+ rc = plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i++], &event, value);
+ if (rc != bRC_OK) {
+ break;
+ }
+ }
+
+ return;
+}
+
/*
* Sequence of calls for a backup:
- * 1. generate_plugin_event called with bEventPluginCommand
- * the command string is passed as an argument.
+ * 1. plugin_save() here is called with ff_pkt
* 2. we find the plugin requested on the command string
- * 3. we generate a bEventPluginCommand event to the specified plugin
+ * 3. we generate a bEventBackupCommand event to the specified plugin
+ * and pass it the command string.
* 4. we make a startPluginBackup call to the plugin, which gives
* us the data we need in save_pkt
* 5. we call Bacula's save_file() subroutine to save the specified
* Sequence of calls for restore:
* See subroutine plugin_name_stream() below.
*/
-
-/*
- * Create a plugin event
- */
-void generate_plugin_event(JCR *jcr, bEventType eventType, void *value)
+int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
{
- bEvent event;
Plugin *plugin;
int i = 0;
int len;
char *p;
- char *cmd = (char *)value;
+ char *cmd = ff_pkt->top_fname;
struct save_pkt sp;
- FF_PKT *ff_pkt;
+ bEvent event;
+
+ bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+ event.eventType = bEventBackupCommand;
if (!plugin_list) {
- return;
+ return 1; /* Return if no plugins loaded */
}
- bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
- event.eventType = eventType;
+ /* Handle plugin command here backup */
+ Dmsg1(100, "plugin cmd=%s\n", cmd);
+ if (!(p = strchr(cmd, ':'))) {
+ Jmsg1(jcr, M_ERROR, 0, "Malformed plugin command: %s\n", cmd);
+ goto bail_out;
+ }
+ len = p - cmd;
+ if (len <= 0) {
+ goto bail_out;
+ }
- Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
- switch (eventType) {
- case bEventPluginCommand:
- /* Handle plugin command here backup */
- Dmsg1(100, "plugin cmd=%s\n", cmd);
- if (!(p = strchr(cmd, ':'))) {
- Jmsg1(jcr, M_ERROR, 0, "Malformed plugin command: %s\n", cmd);
- goto bail_out;
+ foreach_alist(plugin, plugin_list) {
+ Dmsg3(100, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
+ if (strncmp(plugin->file, cmd, len) != 0) {
+ i++;
+ continue;
}
- len = p - cmd;
- if (len <= 0) {
+ Dmsg1(100, "Command plugin = %s\n", cmd);
+ /* Send the backup command */
+ if (plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i], &event, cmd) != bRC_OK) {
goto bail_out;
}
-
- foreach_alist(plugin, plugin_list) {
- Dmsg3(100, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
- if (strncmp(plugin->file, cmd, len) != 0) {
- i++;
- continue;
- }
- while (!job_canceled(jcr)) {
- Dmsg1(100, "Command plugin = %s\n", cmd);
- if (plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i], &event, value) != bRC_OK) {
- goto bail_out;
- }
- memset(&sp, 0, sizeof(sp));
- sp.type = FT_REG;
- sp.portable = true;
- sp.cmd = cmd;
- Dmsg3(000, "startBackup st_size=%p st_blocks=%p sp=%p\n", &sp.statp.st_size, &sp.statp.st_blocks,
- &sp);
- if (plug_func(plugin)->startPluginBackup(&plugin_ctx_list[i], &sp) != bRC_OK) {
- 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;
- ff_pkt->type = sp.type;
- memcpy(&ff_pkt->statp, &sp.statp, sizeof(ff_pkt->statp));
- Dmsg1(000, "Save_file: file=%s\n", ff_pkt->fname);
- save_file(jcr, ff_pkt, true);
- /* ***FIXME***/
- /* add call to endPluginBackup() and loop on bRC_MORE */
+ /* Loop getting filenames to backup then saving them */
+ while (!job_canceled(jcr)) {
+ memset(&sp, 0, sizeof(sp));
+ sp.type = FT_REG;
+ sp.portable = true;
+ sp.cmd = cmd;
+ Dmsg3(000, "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) {
goto bail_out;
}
- }
- Jmsg1(jcr, M_ERROR, 0, "Command plugin \"%s\" not found.\n", cmd);
- break;
-
- default:
- /* Pass event to every plugin */
- foreach_alist(plugin, plugin_list) {
- bRC rc;
- rc = plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i++], &event, value);
- if (rc != bRC_OK) {
- break;
+ jcr->plugin_ctx = &plugin_ctx_list[i];
+ jcr->plugin = plugin;
+ jcr->plugin_sp = &sp;
+ ff_pkt = jcr->ff;
+ ff_pkt->fname = sp.fname;
+ ff_pkt->type = sp.type;
+ memcpy(&ff_pkt->statp, &sp.statp, sizeof(ff_pkt->statp));
+ Dmsg1(000, "Save_file: file=%s\n", ff_pkt->fname);
+ save_file(jcr, ff_pkt, true);
+ if (plug_func(plugin)->endBackupFile(&plugin_ctx_list[i]) != bRC_More) {
+ goto bail_out;
}
}
- break;
}
+ Jmsg1(jcr, M_ERROR, 0, "Command plugin \"%s\" not found.\n", cmd);
-
bail_out:
- return;
+ return 1;
}
/*
int stat;
struct save_pkt *sp = (struct save_pkt *)jcr->plugin_sp;
- if (!sd->fsend("%ld %d %d", jcr->JobFiles, STREAM_PLUGIN_NAME, start)) {
+ Dmsg1(000, "send_plugin_name=%s\n", sp->cmd);
+ if (!sd->fsend("%ld %d 0", jcr->JobFiles, STREAM_PLUGIN_NAME)) {
Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
sd->bstrerror());
return false;
}
- stat = sd->fsend("%ld %d %d %s%c", jcr->JobFiles, start, sp->portable, sp->cmd, 0);
+ Dmsg1(000, "send: %s\n", sd->msg);
+
+ if (start) {
+ stat = sd->fsend("%ld 1 %d %s%c", jcr->JobFiles, sp->portable, sp->cmd, 0);
+ } else {
+ stat = sd->fsend("%ld 0");
+ }
if (!stat) {
Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
sd->bstrerror());
return false;
}
+ Dmsg1(000, "send: %s\n", sd->msg);
sd->signal(BNET_EOD); /* indicate end of plugin name data */
return true;
}
/*
- * Plugin name stream found during restore. This is the record
- * that 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.
*/
void plugin_name_stream(JCR *jcr, char *name)
{
char *p = name;
char *cmd;
bool start, portable;
- bEvent event;
Plugin *plugin;
int len;
int i = 0;
- bpContext *plugin_ctx_list;
+ bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
- Dmsg1(000, "plugin stream string=%s\n", name);
+ Dmsg1(000, "Read plugin stream string=%s\n", name);
skip_nonspaces(&p); /* skip over jcr->JobFiles */
skip_spaces(&p);
start = *p == '1';
skip_nonspaces(&p); /* skip portable flag */
skip_spaces(&p);
cmd = p;
- event.eventType = start ? bEventRestoreStart : bEventRestoreEnd;
/* Check for restore end */
if (!start) {
* If end of restore, notify plugin, then clear flags
*/
plugin = (Plugin *)jcr->plugin;
- plug_func(plugin)->handlePluginEvent((bpContext *)jcr->plugin_ctx, &event, cmd);
+ plug_func(plugin)->endRestoreFile(&plugin_ctx_list[i]);
jcr->plugin_ctx = NULL;
jcr->plugin = NULL;
goto bail_out;
goto bail_out;
}
-
- plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+ /*
+ * Search for correct plugin as specified on the command
+ */
foreach_alist(plugin, plugin_list) {
- Dmsg3(100, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
+ bEvent event;
+ Dmsg3(000, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
if (strncmp(plugin->file, cmd, len) != 0) {
i++;
continue;
}
- Dmsg1(100, "Command plugin = %s\n", cmd);
+ Dmsg1(000, "Restore Command plugin = %s\n", cmd);
+ event.eventType = bEventRestoreCommand;
if (plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i],
- &event, (void *)name) != bRC_OK) {
+ &event, cmd) != bRC_OK) {
goto bail_out;
}
jcr->plugin_ctx = &plugin_ctx_list[i];
} bVariable;
typedef enum {
- bEventJobStart = 1,
- bEventJobEnd = 2,
- bEventBackupStart = 3,
- bEventBackupEnd = 4,
- bEventRestoreStart = 5,
- bEventRestoreEnd = 6,
- bEventVerifyStart = 7,
- bEventVerifyEnd = 8,
- bEventPluginCommand = 9,
- bEventPluginFile = 10,
- bEventLevel = 11,
- bEventSince = 12,
+ bEventJobStart = 1,
+ bEventJobEnd = 2,
+ bEventStartBackupJob = 3,
+ bEventEndBackupJob = 4,
+ bEventStartRestoreJob = 5,
+ bEventEndRestoreJob = 6,
+ bEventStartVerifyJob = 7,
+ bEventEndVerifyJob = 8,
+ bEventBackupCommand = 9,
+ bEventRestoreCommand = 10,
+ bEventLevel = 11,
+ bEventSince = 12,
} bEventType;
typedef struct s_bEvent {
/* Bacula Core Routines -- not used by plugins */
struct BFILE; /* forward referenced */
+struct FF_PKT;
void load_fd_plugins(const char *plugin_dir);
void new_plugins(JCR *jcr);
void free_plugins(JCR *jcr);
void plugin_name_stream(JCR *jcr, char *name);
int plugin_create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace);
bool plugin_set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd);
+int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level);
#ifdef __cplusplus
extern "C" {
bRC (*getPluginValue)(bpContext *ctx, pVariable var, void *value);
bRC (*setPluginValue)(bpContext *ctx, pVariable var, void *value);
bRC (*handlePluginEvent)(bpContext *ctx, bEvent *event, void *value);
- bRC (*startPluginBackup)(bpContext *ctx, struct save_pkt *sp);
- bRC (*endPluginBackup)(bpContext *ctx);
+ bRC (*startBackupFile)(bpContext *ctx, struct save_pkt *sp);
+ bRC (*endBackupFile)(bpContext *ctx);
bRC (*startRestoreFile)(bpContext *ctx, const char *cmd);
bRC (*endRestoreFile)(bpContext *ctx);
bRC (*pluginIO)(bpContext *ctx, struct io_pkt *io);
}
generate_daemon_event(jcr, "JobStart");
- generate_plugin_event(jcr, bEventBackupStart);
+ generate_plugin_event(jcr, bEventStartBackupJob);
#if defined(WIN32_VSS)
/* START VSS ON WIN32 */
}
#endif
- generate_plugin_event(jcr, bEventBackupEnd);
+ generate_plugin_event(jcr, bEventEndBackupJob);
return 0; /* return and stop command loop */
}
generate_daemon_event(jcr, "JobStart");
generate_plugin_event(jcr, bEventLevel, (void *)jcr->JobLevel);
- generate_plugin_event(jcr, bEventVerifyStart);
+ generate_plugin_event(jcr, bEventStartVerifyJob);
Dmsg1(110, "bfiled>dird: %s", dir->msg);
}
dir->signal(BNET_EOD);
- generate_plugin_event(jcr, bEventVerifyEnd);
+ generate_plugin_event(jcr, bEventEndVerifyJob);
return 0; /* return and terminate command loop */
}
*/
start_dir_heartbeat(jcr);
generate_daemon_event(jcr, "JobStart");
- generate_plugin_event(jcr, bEventRestoreStart);
+ generate_plugin_event(jcr, bEventStartRestoreJob);
do_restore(jcr);
stop_dir_heartbeat(jcr);
}
Dmsg0(130, "Done in job.c\n");
- generate_plugin_event(jcr, bEventRestoreEnd);
+ generate_plugin_event(jcr, bEventEndRestoreJob);
return 0; /* return and terminate command loop */
}
break;
case STREAM_PLUGIN_NAME:
+ Dmsg1(000, "stream_plugin_name=%s\n", sd->msg);
plugin_name_stream(jcr, sd->msg);
break;
.c.o:
$(CC) -I${SRCDIR} -I${FDDOR} -DTEST_PROGRAM -c $<
-all: main example-plugin-fd.so bpipe-fd.so
+all: main bpipe-fd.so
fd-plugins.o: ${FDDIR}/fd-plugins.h ${FDDIR}/fd-plugins.c
$(CC) -I${SRCDIR} -I${FDDIR} -DTEST_PROGRAM -c ${FDDIR}/fd-plugins.c
static bRC getPluginValue(bpContext *ctx, pVariable var, void *value);
static bRC setPluginValue(bpContext *ctx, pVariable var, void *value);
static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value);
-static bRC startPluginBackup(bpContext *ctx, struct save_pkt *sp);
-static bRC endPluginBackup(bpContext *ctx);
+static bRC startBackupFile(bpContext *ctx, struct save_pkt *sp);
+static bRC endBackupFile(bpContext *ctx);
static bRC pluginIO(bpContext *ctx, struct io_pkt *io);
static bRC startRestoreFile(bpContext *ctx, const char *cmd);
static bRC endRestoreFile(bpContext *ctx);
getPluginValue,
setPluginValue,
handlePluginEvent,
- startPluginBackup,
- endPluginBackup,
+ startBackupFile,
+ endBackupFile,
startRestoreFile,
endRestoreFile,
pluginIO,
case bEventJobEnd:
// printf("bpipe-fd: JobEnd\n");
break;
- case bEventBackupStart:
+ case bEventStartBackupJob:
// printf("bpipe-fd: BackupStart\n");
break;
- case bEventBackupEnd:
+ case bEventEndBackupJob:
// printf("bpipe-fd: BackupEnd\n");
break;
case bEventLevel:
// printf("bpipe-fd: since=%d\n", (int)value);
break;
- case bEventRestoreStart:
-// printf("bpipe-fd: RestoreStart\n");
+ case bEventStartRestoreJob:
+ printf("bpipe-fd: StartRestoreJob\n");
break;
- case bEventRestoreEnd:
-// printf("bpipe-fd: RestoreEnd\n");
+
+ case bEventEndRestoreJob:
+ printf("bpipe-fd: EndRestoreJob\n");
break;
- /* Plugin command e.g. plugin = <plugin-name>:<name-space>:command */
- case bEventPluginCommand:
+ /* Plugin command e.g. plugin = <plugin-name>:<name-space>:read command:write command */
+ case bEventRestoreCommand:
+ printf("bpipe-fd: EventRestoreCommand cmd=%s\n", (char *)value);
+ case bEventBackupCommand:
char *p;
-// printf("bpipe-fd: pluginEvent cmd=%s\n", (char *)value);
+ printf("bpipe-fd: pluginEvent cmd=%s\n", (char *)value);
p_ctx->cmd = strdup((char *)value);
p = strchr(p_ctx->cmd, ':');
if (!p) {
return bRC_OK;
}
-static bRC startPluginBackup(bpContext *ctx, struct save_pkt *sp)
+static bRC startBackupFile(bpContext *ctx, struct save_pkt *sp)
{
struct plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;
time_t now = time(NULL);
sp->statp.st_blksize = 4096;
sp->statp.st_blocks = 1;
p_ctx->backup = true;
-// printf("bpipe-fd: startPluginBackup\n");
+// printf("bpipe-fd: startBackupFile\n");
return bRC_OK;
}
-static bRC endPluginBackup(bpContext *ctx)
+static bRC endBackupFile(bpContext *ctx)
{
+ /*
+ * We would return bRC_More if we wanted startBackupFile to be
+ * called again to backup another file
+ */
+// printf("bpipe-fd: endBackupFile\n");
return bRC_OK;
}
if (!p_ctx->fd) {
io->io_errno = errno;
snprintf(msg, sizeof(msg), "bpipe-fd: reader=%s failed: ERR=%d\n", p_ctx->reader, errno);
- bfuncs->JobMessage(ctx, __FILE__, __LINE__, 1, 0, msg);
+ bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, msg);
printf("%s", msg);
return bRC_Error;
}
break;
case IO_READ:
+ if (!p_ctx->fd) {
+ bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, "NULL FD\n");
+ return bRC_Error;
+ }
io->status = fread(io->buf, 1, io->count, p_ctx->fd);
printf("bpipe-fd: IO_READ buf=%p len=%d\n", io->buf, io->status);
if (io->status == 0 && ferror(p_ctx->fd)) {
+ bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, "Pipe I/O error\n");
printf("Error reading pipe\n");
return bRC_Error;
}
break;
case IO_CLOSE:
+ if (!p_ctx->fd) {
+ bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, "NULL FD\n");
+ return bRC_Error;
+ }
io->status = pclose(p_ctx->fd);
printf("bpipe-fd: IO_CLOSE\n");
break;
static bRC startRestoreFile(bpContext *ctx, const char *cmd)
{
+ printf("bpipe-fd: startRestoreFile cmd=%s\n", cmd);
return bRC_OK;
}
static bRC endRestoreFile(bpContext *ctx)
{
+ printf("bpipe-fd: endRestoreFile\n");
return bRC_OK;
}
static bRC createFile(bpContext *ctx, struct restore_pkt *rp)
{
+ printf("bpipe-fd: createFile\n");
return bRC_OK;
}
static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp)
{
+ printf("bpipe-fd: setFileAttributes\n");
return bRC_OK;
}
static bRC getPluginValue(bpContext *ctx, pVariable var, void *value);
static bRC setPluginValue(bpContext *ctx, pVariable var, void *value);
static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value);
-static bRC startPluginBackup(bpContext *ctx, struct save_pkt *sp);
-static bRC endPluginBackup(bpContext *ctx);
+static bRC startBackupFile(bpContext *ctx, struct save_pkt *sp);
+static bRC endBackupFile(bpContext *ctx);
static bRC pluginIO(bpContext *ctx, struct io_pkt *io);
static bRC startRestoreFile(bpContext *ctx, const char *cmd);
static bRC endRestoreFile(bpContext *ctx);
getPluginValue,
setPluginValue,
handlePluginEvent,
- startPluginBackup,
- endPluginBackup,
+ startBackupFile,
+ endBackupFile,
startRestoreFile,
endRestoreFile,
pluginIO,
case bEventJobEnd:
printf("plugin: JobEnd\n");
break;
- case bEventBackupStart:
+ case bEventStartBackupJob:
printf("plugin: BackupStart\n");
break;
- case bEventBackupEnd:
+ case bEventEndBackupJob:
printf("plugin: BackupEnd\n");
break;
case bEventLevel:
case bEventSince:
printf("plugin: since=%d\n", (int)value);
break;
- case bEventRestoreStart:
- printf("bpipe-fd: RestoreStart\n");
+ case bEventStartRestoreJob:
+ printf("plugin: StartRestoreJob\n");
break;
- case bEventRestoreEnd:
- printf("bpipe-fd: RestoreEnd\n");
+ case bEventEndRestoreJob:
+ printf("plugin: EndRestoreJob\");
break;
/* Plugin command e.g. plugin = <plugin-name>:<name-space>:command */
- case bEventPluginCommand:
- printf("plugin: command=%s\n", (char *)value);
+ case bEventRestoreCommand:
+ printf("plugin: backup command=%s\n", (char *)value);
+ break;
+
+ case bEventBackupCommand:
+ printf("plugin: backup command=%s\n", (char *)value);
break;
default:
return bRC_OK;
}
-static bRC startPluginBackup(bpContext *ctx, struct save_pkt *sp)
+static bRC startBackupFile(bpContext *ctx, struct save_pkt *sp)
{
return bRC_OK;
}
-static bRC endPluginBackup(bpContext *ctx)
+static bRC endBackupFile(bpContext *ctx)
{
return bRC_OK;
}
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2008 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.
return "PROG-NAMES";
case STREAM_PROGRAM_DATA:
return "PROG-DATA";
+ case STREAM_PLUGIN_NAME:
+ return "PLUGIN-NAME";
case STREAM_MACOS_FORK_DATA:
return "MACOS-RSRC";
case STREAM_HFSPLUS_ATTRIBUTES:
return "contENCRYPTED-WIN32-GZIP";
case -STREAM_ENCRYPTED_MACOS_FORK_DATA:
return "contENCRYPTED-MACOS-RSRC";
+ case -STREAM_PLUGIN_NAME:
+ return "contPLUGIN-NAME";
+
default:
sprintf(buf, "%d", stream);
return buf;