}
/* Handle plugin command here (backup/restore of file) */
- Dmsg1(000, "plugin cmd=%s\n", cmd);
+ 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(000, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
+ Dmsg3(100, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
if (strncmp(plugin->file, cmd, len) == 0) {
- Dmsg1(000, "Command plugin = %s\n", cmd);
+ Dmsg1(100, "Command plugin = %s\n", cmd);
if (plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i], &event, value) != bRC_OK) {
goto bail_out;
}
sp.type = FT_REG;
sp.portable = true;
sp.cmd = cmd;
- Dmsg0(000, "Plugin startBackup\n");
- printf("st_size=%p st_blocks=%p sp=%p\n", &sp.statp.st_size, &sp.statp.st_blocks,
+ 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;
}
i++;
}
+ Jmsg1(jcr, M_ERROR, 0, "Command plugin \"%s\" not found.\n", cmd);
bail_out:
return;
Switzerland, email:ftf@fsfeurope.org.
*/
/*
- * Sample Plugin program
+ * A simple pipe plugin for Bacula
*
* Kern Sibbald, October 2007
*
#undef malloc
#undef free
+#undef strdup
#ifdef __cplusplus
extern "C" {
};
struct plugin_ctx {
- int record;
boffset_t offset;
+ FILE *fd;
+ bool backup;
+ char *cmd;
+ char *fname;
+ char *reader;
+ char *writer;
};
bRC loadPlugin(bInfo *lbinfo, bFuncs *lbfuncs, pInfo **pinfo, pFuncs **pfuncs)
{
bfuncs = lbfuncs; /* set Bacula funct pointers */
binfo = lbinfo;
- printf("bpipe-fd: Loaded: size=%d version=%d\n", bfuncs->size, bfuncs->version);
+// printf("bpipe-fd: Loaded: size=%d version=%d\n", bfuncs->size, bfuncs->version);
*pinfo = &pluginInfo; /* return pointer to our info */
*pfuncs = &pluginFuncs; /* return pointer to our functions */
bRC unloadPlugin()
{
- printf("bpipe-fd: Unloaded\n");
+// printf("bpipe-fd: Unloaded\n");
return bRC_OK;
}
static bRC newPlugin(bpContext *ctx)
{
struct plugin_ctx *p_ctx = (struct plugin_ctx *)malloc(sizeof(struct plugin_ctx));
-
- p_ctx->record = -1;
+ memset(p_ctx, 0, sizeof(struct plugin_ctx));
ctx->pContext = (void *)p_ctx; /* set our context pointer */
return bRC_OK;
}
static bRC freePlugin(bpContext *ctx)
{
struct plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;
+ if (p_ctx->cmd) {
+ free(p_ctx->cmd);
+ }
free(p_ctx);
return bRC_OK;
}
static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value)
{
+ struct plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;
char *name;
switch (event->eventType) {
case bEventJobStart:
- printf("bpipe-fd: JobStart=%s\n", (char *)value);
+// printf("bpipe-fd: JobStart=%s\n", (char *)value);
break;
case bEventJobEnd:
- printf("bpipe-fd: JobEnd\n");
+// printf("bpipe-fd: JobEnd\n");
break;
case bEventBackupStart:
- printf("bpipe-fd: BackupStart\n");
+// printf("bpipe-fd: BackupStart\n");
break;
case bEventBackupEnd:
- printf("bpipe-fd: BackupEnd\n");
+// printf("bpipe-fd: BackupEnd\n");
break;
case bEventLevel:
- printf("bpipe-fd: JobLevel=%c %d\n", (int)value, (int)value);
+// printf("bpipe-fd: JobLevel=%c %d\n", (int)value, (int)value);
break;
case bEventSince:
- printf("bpipe-fd: since=%d\n", (int)value);
+// printf("bpipe-fd: since=%d\n", (int)value);
break;
case bEventRestoreStart:
- printf("bpipe-fd: RestoreStart\n");
+// printf("bpipe-fd: RestoreStart\n");
break;
case bEventRestoreEnd:
- printf("bpipe-fd: RestoreEnd\n");
+// printf("bpipe-fd: RestoreEnd\n");
break;
/* Plugin command e.g. plugin = <plugin-name>:<name-space>:command */
case bEventPluginCommand:
- printf("bpipe-fd: command=%s\n", (char *)value);
+ char *p;
+// printf("bpipe-fd: pluginEvent cmd=%s\n", (char *)value);
+ p_ctx->cmd = strdup((char *)value);
+ p = strchr(p_ctx->cmd, ':');
+ if (!p) {
+ printf("Plugin terminator not found: %s\n", (char *)value);
+ return bRC_Error;
+ }
+ *p++ = 0; /* terminate plugin */
+ p_ctx->fname = p;
+ p = strchr(p, ':');
+ if (!p) {
+ printf("File terminator not found: %s\n", (char *)value);
+ return bRC_Error;
+ }
+ *p++ = 0; /* terminate file */
+ p_ctx->reader = p;
+ p = strchr(p, ':');
+ if (!p) {
+ printf("Reader terminator not found: %s\n", (char *)value);
+ return bRC_Error;
+ }
+ *p++ = 0; /* terminate reader string */
+ p_ctx->writer = p;
+ printf("bpipe-fd: plugin=%s fname=%s reader=%s writer=%s\n",
+ p_ctx->cmd, p_ctx->fname, p_ctx->reader, p_ctx->writer);
break;
default:
static bRC startPluginBackup(bpContext *ctx, struct save_pkt *sp)
{
- static char *fname = (char *)"/@BPIPE/test.txt";
+ struct plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;
time_t now = time(NULL);
- sp->fname = fname;
- sp->statp.st_mode = 0700;
+ sp->fname = p_ctx->fname;
+ sp->statp.st_mode = 0700 | S_IFREG;
sp->statp.st_ctime = now;
sp->statp.st_mtime = now;
sp->statp.st_atime = now;
sp->statp.st_size = -1;
sp->statp.st_blksize = 4096;
sp->statp.st_blocks = 1;
- printf("bpipe: st_size=%p st_blocks=%p sp=%p\n", &sp->statp.st_size, &sp->statp.st_blocks,
- sp);
-
- printf("bpipe-fd: startPluginBackup\n");
+ p_ctx->backup = true;
+// printf("bpipe-fd: startPluginBackup\n");
return bRC_OK;
}
static bRC pluginIO(bpContext *ctx, struct io_pkt *io)
{
struct plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;
+ char msg[200];
io->status = 0;
io->io_errno = 0;
switch(io->func) {
case IO_OPEN:
- p_ctx->record = 0;
- printf("bpipe-fd: IO_OPEN\n");
+ p_ctx->fd = popen(p_ctx->reader, "r");
+ 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);
+ printf("%s", msg);
+ return bRC_Error;
+ }
+ printf("bpipe-fd: IO_OPEN reader=%s fd=%p\n", p_ctx->reader, p_ctx->fd);
+ sleep(1); /* let pipe connect */
break;
+
case IO_READ:
- printf("bpipe-fd: IO_READ buf=%p len=%d\n", io->buf, io->count);
- if (p_ctx->record == 0) {
- strcpy(io->buf, "This is a test string.\n");
- io->status = strlen(io->buf);
- p_ctx->offset = io->status;
- p_ctx->record = 1;
- return bRC_OK;
+ 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)) {
+ printf("Error reading pipe\n");
+ return bRC_Error;
}
- io->status = 0;
+ printf("status=%d\n", io->status);
break;
+
case IO_WRITE:
printf("bpipe-fd: IO_WRITE buf=%p len=%d\n", io->buf, io->count);
break;
+
case IO_CLOSE:
+ io->status = pclose(p_ctx->fd);
printf("bpipe-fd: IO_CLOSE\n");
break;
+
case IO_SEEK:
io->offset = p_ctx->offset;
break;