if (ff_pkt->flags & FO_PORTABLE) {
set_portable_backup(&ff_pkt->bfd); /* disable Win32 BackupRead() */
}
- if (ff_pkt->reader) {
- if (!set_prog(&ff_pkt->bfd, ff_pkt->reader, jcr)) {
- Jmsg(jcr, M_FATAL, 0, _("Python reader program \"%s\" not found.\n"),
- ff_pkt->reader);
+ if (ff_pkt->cmd_plugin) {
+ if (!set_cmd_plugin(&ff_pkt->bfd, jcr)) {
goto bail_out;
}
}
const int dbglvl = 50;
const char *plugin_type = "-fd.so";
+/* External functions */
+extern int (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode);
+extern int (*plugin_bclose)(JCR *jcr);
+extern ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count);
+extern ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count);
+
/* Forward referenced functions */
static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value);
static bpError baculaDebugMsg(bpContext *ctx, const char *file, int line,
int level, const char *msg);
+static int my_plugin_bopen(JCR *jcr, const char *fname, int flags, mode_t mode);
+static int my_plugin_bclose(JCR *jcr);
+static ssize_t my_plugin_bread(JCR *jcr, void *buf, size_t count);
+static ssize_t my_plugin_bwrite(JCR *jcr, void *buf, size_t count);
+
/* Bacula info */
static bInfo binfo = {
baculaDebugMsg
};
+
/*
* Create a plugin event
*/
bEvent event;
Plugin *plugin;
int i = 0;
+ int len;
+ char *p;
+ char *cmd = (char *)value;
if (!plugin_list) {
return;
}
bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
- Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId);
event.eventType = eventType;
- foreach_alist(plugin, plugin_list) {
- plug_func(plugin)->handlePluginEvent(&plugin_ctx[i++], &event, value);
+
+ Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId);
+ if (eventType != bEventPluginCommand) {
+ /* Pass event to every plugin */
+ foreach_alist(plugin, plugin_list) {
+ plug_func(plugin)->handlePluginEvent(&plugin_ctx[i++], &event, value);
+ }
+ return;
}
+
+ /* Handle plugin command here (backup/restore of file) */
+ if (!(p = strchr(cmd, ':'))) {
+ Jmsg1(jcr, M_ERROR, 0, "Malformed plugin command: %s\n", cmd);
+ return;
+ }
+ len = p - cmd;
+ if (len > 0) {
+ foreach_alist(plugin, plugin_list) {
+ Dmsg3(000, "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);
+ plug_func(plugin)->handlePluginEvent(&plugin_ctx[i], &event, value);
+ return;
+ }
+ i++;
+ }
+ }
+
}
void load_fd_plugins(const char *plugin_dir)
plugin_list = New(alist(10, not_owned_by_alist));
load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type);
+ plugin_bopen = my_plugin_bopen;
+ plugin_bclose = my_plugin_bclose;
+ plugin_bread = my_plugin_bread;
+ plugin_bwrite = my_plugin_bwrite;
+
}
/*
jcr->plugin_ctx = NULL;
}
+static int my_plugin_bopen(JCR *jcr, const char *fname, int flags, mode_t mode)
+{
+ struct io_pkt io;
+ Dmsg0(000, "plugin_bopen\n");
+ io.func = IO_OPEN;
+ io.count = 0;
+ io.buf = NULL;
+
+ return 0;
+}
+
+static int my_plugin_bclose(JCR *jcr)
+{
+ struct io_pkt io;
+ Dmsg0(000, "plugin_bclose\n");
+ io.func = IO_CLOSE;
+ io.count = 0;
+ io.buf = NULL;
+ return 0;
+}
+
+static ssize_t my_plugin_bread(JCR *jcr, void *buf, size_t count)
+{
+ struct io_pkt io;
+ Dmsg0(000, "plugin_bread\n");
+ io.func = IO_READ;
+ io.count = count;
+ io.buf = (char *)buf;
+ return 0;
+}
+
+static ssize_t my_plugin_bwrite(JCR *jcr, void *buf, size_t count)
+{
+ struct io_pkt io;
+ Dmsg0(000, "plugin_bwrite\n");
+ io.func = IO_WRITE;
+ io.count = count;
+ io.buf = (char *)buf;
+ return 0;
+}
/* ==============================================================
*
#ifdef TEST_PROGRAM
+int (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode) = NULL;
+int (*plugin_bclose)(JCR *jcr) = NULL;
+ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count) = NULL;
+ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count) = NULL;
+
+
int main(int argc, char *argv[])
{
char plugin_dir[1000];
#endif
#include "bc_types.h"
#include "lib/plugins.h"
+#include <sys/stat.h>
+/*
+ * This packet is used for file save/restore info transfer */
+struct save_pkt {
+ char *fname; /* Full path and filename */
+ char *link; /* Link name if any */
+ struct stat statp; /* System stat() packet for file */
+ int type; /* FT_xx for this file */
+ uint32_t flags; /* Bacula internal flags */
+ bool portable; /* set if data format is portable */
+};
+
+#define IO_OPEN 1
+#define IO_READ 2
+#define IO_WRITE 3
+#define IO_CLOSE 4
+
+struct io_pkt {
+ int func; /* Function code */
+ int count; /* read/write count */
+ char *buf; /* read/write buffer */
+};
/****************************************************************************
* *
bpError (*getPluginValue)(bpContext *ctx, pVariable var, void *value);
bpError (*setPluginValue)(bpContext *ctx, pVariable var, void *value);
bpError (*handlePluginEvent)(bpContext *ctx, bEvent *event, void *value);
+ bpError (*startPluginBackup)(bpContext *ctx, struct save_pkt *sp);
+ bpError (*pluginIO)(bpContext *ctx, struct io_pkt *io);
} pFuncs;
#define plug_func(plugin) ((pFuncs *)(plugin->pfuncs))
fo->base.destroy();
fo->fstype.destroy();
fo->drivetype.destroy();
- if (fo->reader) {
- free(fo->reader);
- }
- if (fo->writer) {
- free(fo->writer);
- }
}
incexe->opts_list.destroy();
incexe->name_list.destroy();
break;
case 'D':
current_opts = start_options(ff);
- current_opts->reader = bstrdup(item);
+// current_opts->reader = bstrdup(item);
state = state_options;
break;
case 'T':
current_opts = start_options(ff);
- current_opts->writer = bstrdup(item);
+// current_opts->writer = bstrdup(item);
state = state_options;
break;
default:
for (k=0; k<fo->drivetype.size(); k++) {
Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
}
- if (fo->reader) {
- Dmsg1(400, "D %s\n", fo->reader);
- }
- if (fo->writer) {
- Dmsg1(400, "T %s\n", fo->writer);
- }
}
dlistString *node;
foreach_dlist(node, &incexe->name_list) {
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2003-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2003-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.
ssize_t (*python_read)(BFILE *bfd, void *buf, size_t count) = NULL;
ssize_t (*python_write)(BFILE *bfd, void *buf, size_t count) = NULL;
+int (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode) = NULL;
+int (*plugin_bclose)(JCR *jcr) = NULL;
+ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count) = NULL;
+ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count) = NULL;
+
+
#ifdef HAVE_DARWIN_OS
#include <sys/paths.h>
#endif
bfd->fid = -1;
bfd->mode = BF_CLOSED;
bfd->use_backup_api = have_win32_api();
+ bfd->cmd_plugin = false;
}
/*
bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
{
- bfd->prog = prog;
- bfd->jcr = jcr;
return false;
}
+bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
+{
+ bfd->cmd_plugin = true;
+ bfd->jcr = jcr;
+ return true;
+}
+
/*
* Return 1 if we are NOT using Win32 BackupWrite()
* return 0 if are
}
bfd->mode = BF_CLOSED;
bfd->lpContext = NULL;
+ bfd->cmd_plugin = false;
return stat;
}
bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
{
-#ifdef HAVE_PYTHON
- if (bfd->prog && strcmp(prog, bfd->prog) == 0) {
- return true; /* already setup */
- }
-
- if (python_set_prog(jcr, prog)) {
- Dmsg1(000, "Set prog=%s\n", prog);
- bfd->prog = prog;
- bfd->jcr = jcr;
- return true;
- }
-#endif
- Dmsg0(000, "No prog set\n");
- bfd->prog = NULL;
return false;
+}
+bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
+{
+ bfd->cmd_plugin = true;
+ bfd->jcr = jcr;
+ return true;
}
/*
int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
{
- /* Open reader/writer program */
- if (bfd->prog) {
- Dmsg1(000, "Open file %d\n", bfd->fid);
- return python_open(bfd, fname, flags, mode);
+ if (bfd->cmd_plugin && plugin_bopen) {
+ return plugin_bopen(bfd->jcr, fname, flags, mode);
}
/* Normal file open */
Dmsg1(400, "Close file %d\n", bfd->fid);
- /* Close reader/writer program */
- if (bfd->prog) {
- return python_close(bfd);
+ if (bfd->cmd_plugin && plugin_bclose) {
+ return plugin_bclose(bfd->jcr);
}
if (bfd->fid == -1) {
stat = close(bfd->fid);
bfd->berrno = errno;
bfd->fid = -1;
+ bfd->cmd_plugin = false;
return stat;
}
{
ssize_t stat;
- if (bfd->prog) {
- return python_read(bfd, buf, count);
+ if (bfd->cmd_plugin && plugin_bread) {
+ return plugin_bread(bfd->jcr, buf, count);
}
+
stat = read(bfd->fid, buf, count);
bfd->berrno = errno;
return stat;
{
ssize_t stat;
- if (bfd->prog) {
- return python_write(bfd, buf, count);
+ if (bfd->cmd_plugin && plugin_bwrite) {
+ return plugin_bwrite(bfd->jcr, buf, count);
}
stat = write(bfd->fid, buf, count);
bfd->berrno = errno;
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2003-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2003-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.
DWORD rw_bytes; /* Bytes read or written */
DWORD lerror; /* Last error code */
int berrno; /* errno */
- char *prog; /* reader/writer program if any */
JCR *jcr; /* jcr for editing job codes */
Python_IO pio; /* Python I/O routines */
PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT win32DecompContext; /* context for decomposition of win32 backup streams */
int use_backup_decomp; /* set if using BackupRead Stream Decomposition */
bool reparse_point; /* set if reparse point */
+ bool cmd_plugin; /* set if we have a command plugin */
};
HANDLE bget_handle(BFILE *bfd);
int fid; /* file id on Unix */
int m_flags; /* open flags */
int berrno;
- char *prog; /* reader/writer program if any */
JCR *jcr; /* jcr for editing job codes */
Python_IO pio; /* Python I/O routines */
PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT win32DecompContext; /* context for decomposition of win32 backup streams */
int use_backup_decomp; /* set if using BackupRead Stream Decomposition */
bool reparse_point; /* not used in Unix */
+ bool cmd_plugin; /* set if we have a command plugin */
};
#endif
bool is_bopen(BFILE *bfd);
bool set_win32_backup(BFILE *bfd);
bool set_portable_backup(BFILE *bfd);
-bool set_prog(BFILE *bfd, char *prog, JCR *jcr);
+bool set_cmd_plugin(BFILE *bfd, JCR *jcr);
bool have_win32_api();
bool is_portable_backup(BFILE *bfd);
bool is_restore_stream_supported(int stream);
}
/*
- * Find all specified files (determined by calls to name_add()
- * This routine calls the (handle_file) subroutine with all
- * sorts of good information for the final disposition of
- * the file.
- *
* Call this subroutine with a callback subroutine as the first
* argument and a packet as the second argument, this packet
* will be passed back to the callback subroutine as the last
char *fname = node->c_str();
Dmsg1(100, "P %s\n", fname);
ff->top_fname = fname;
+ ff->cmd_plugin = true;
generate_plugin_event(jcr, bEventPluginCommand, (void *)fname);
+ ff->cmd_plugin = false;
}
}
}
findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
ff->flags = fo->flags;
ff->GZIP_level = fo->GZIP_level;
- ff->reader = fo->reader;
- ff->writer = fo->writer;
ff->fstypes = fo->fstype;
ff->drivetypes = fo->drivetype;
case FT_SPEC:
case FT_DIRNOCHG:
if (accept_file(ff)) {
-// Dmsg2(000, "Accept file %s; reader=%s\n", ff->fname, NPRT(ff->reader));
return ff->callback(ff, hpkt, top_level);
} else {
Dmsg1(100, "Skip file %s\n", ff->fname);
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
#endif
-
/*
* Status codes returned by create_file()
*/
};
-/* Options saved int "options" of the include/exclude lists.
+/*
+ * Options saved int "options" of the include/exclude lists.
* They are directly jammed ito "flag" of ff packet
*/
#define FO_MD5 (1<<1) /* Do MD5 checksum */
alist base; /* list of base names */
alist fstype; /* file system type limitation */
alist drivetype; /* drive type limitation */
- char *reader; /* reader program */
- char *writer; /* writer program */
};
uint32_t flags; /* backup options */
int GZIP_level; /* compression level */
int strip_path; /* strip path count */
- char *reader; /* reader program */
- char *writer; /* writer program */
+ bool cmd_plugin; /* set if we have a command plugin */
alist fstypes; /* allowed file system types */
alist drivetypes; /* allowed drive types */
case bEventSince:
printf("plugin: since=%d\n", (int)value);
break;
+ default:
+ printf("plugin: unknown event=%d\n", event->eventType);
}
bfuncs->getBaculaValue(ctx, bVarFDName, (void *)&name);
// printf("FD Name=%s\n", name);
fo->wildbase.destroy();
fo->fstype.destroy();
fo->drivetype.destroy();
- if (fo->reader) {
- free(fo->reader);
- }
- if (fo->writer) {
- free(fo->writer);
- }
}
incexe->opts_list.destroy();
incexe->name_list.destroy();
for (k=0; k<fo->drivetype.size(); k++) {
current_opts->drivetype.append(bstrdup((const char *)fo->drivetype.get(k)));
}
- if (fo->reader) {
- current_opts->reader = bstrdup(fo->reader);
- }
- if (fo->writer) {
- current_opts->writer = bstrdup(fo->writer);
- }
}
for (j=0; j<ie->name_list.size(); j++) {
FD by using casting. Reported in bug #1042.
28Jan08
kes A bit of crypto cleanup. More later.
+
+Release Version 2.2.8
25Jan08
kes Apply patch from Martin to correct bug #1040, bscan sets existing
ClientId to zero.