Switzerland, email:ftf@fsfeurope.org.
*/
/*
- * Sample Plugin program
+ * A simple pipe plugin for Bacula
*
* Kern Sibbald, October 2007
*
*/
-#include <stdio.h>
#include "fd-plugins.h"
+#undef malloc
+#undef free
+#undef strdup
+
#ifdef __cplusplus
extern "C" {
#endif
pluginIO
};
+struct plugin_ctx {
+ 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("plugin: 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("plugin: Unloaded\n");
+// printf("bpipe-fd: Unloaded\n");
return bRC_OK;
}
static bRC newPlugin(bpContext *ctx)
{
- int JobId = 0;
- bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId);
-// printf("plugin: newPlugin JobId=%d\n", JobId);
- bfuncs->registerBaculaEvents(ctx, 1, 2, 0);
+ struct plugin_ctx *p_ctx = (struct plugin_ctx *)malloc(sizeof(struct plugin_ctx));
+ 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)
{
- int JobId = 0;
- bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId);
-// printf("plugin: freePlugin JobId=%d\n", JobId);
+ 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 getPluginValue(bpContext *ctx, pVariable var, void *value)
{
-// printf("plugin: getPluginValue var=%d\n", var);
return bRC_OK;
}
static bRC setPluginValue(bpContext *ctx, pVariable var, void *value)
{
-// printf("plugin: setPluginValue var=%d\n", var);
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("plugin: JobStart=%s\n", (char *)value);
+// printf("bpipe-fd: JobStart=%s\n", (char *)value);
break;
case bEventJobEnd:
- printf("plugin: JobEnd\n");
+// printf("bpipe-fd: JobEnd\n");
break;
case bEventBackupStart:
- printf("plugin: BackupStart\n");
+// printf("bpipe-fd: BackupStart\n");
break;
case bEventBackupEnd:
- printf("plugin: BackupEnd\n");
+// printf("bpipe-fd: BackupEnd\n");
break;
case bEventLevel:
- printf("plugin: JobLevel=%c %d\n", (int)value, (int)value);
+// printf("bpipe-fd: JobLevel=%c %d\n", (int)value, (int)value);
break;
case bEventSince:
- printf("plugin: since=%d\n", (int)value);
+// printf("bpipe-fd: since=%d\n", (int)value);
+ break;
+
+ case bEventRestoreStart:
+// printf("bpipe-fd: RestoreStart\n");
+ break;
+ case bEventRestoreEnd:
+// printf("bpipe-fd: RestoreEnd\n");
break;
/* Plugin command e.g. plugin = <plugin-name>:<name-space>:command */
case bEventPluginCommand:
- printf("plugin: 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:
- printf("plugin: unknown event=%d\n", event->eventType);
+ printf("bpipe-fd: unknown event=%d\n", event->eventType);
}
bfuncs->getBaculaValue(ctx, bVarFDName, (void *)&name);
// printf("FD Name=%s\n", name);
static bRC startPluginBackup(bpContext *ctx, struct save_pkt *sp)
{
+ struct plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;
+ time_t now = time(NULL);
+ 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;
+ 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:
- printf("plugin: 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("plugin: IO_READ buf=%p len=%d\n", io->buf, io->count);
+ 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;
+ }
+ printf("status=%d\n", io->status);
break;
+
case IO_WRITE:
- printf("plugin: IO_WRITE buf=%p len=%d\n", io->buf, io->count);
+ printf("bpipe-fd: IO_WRITE buf=%p len=%d\n", io->buf, io->count);
break;
+
case IO_CLOSE:
- printf("plugin: IO_CLOSE\n");
+ io->status = pclose(p_ctx->fd);
+ printf("bpipe-fd: IO_CLOSE\n");
+ break;
+
+ case IO_SEEK:
+ io->offset = p_ctx->offset;
break;
}
return bRC_OK;