From e209dab6d036fd194901ce36c1f525c6ffc48f83 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 4 Feb 2008 22:12:14 +0000 Subject: [PATCH] More plugin implementation git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6368 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/filed/backup.c | 6 +- bacula/src/filed/fd-plugins.c | 96 ++++++++++++++++++++++- bacula/src/filed/fd-plugins.h | 24 ++++++ bacula/src/filed/job.c | 16 +--- bacula/src/findlib/bfile.c | 60 +++++++------- bacula/src/findlib/bfile.h | 8 +- bacula/src/findlib/find.c | 10 +-- bacula/src/findlib/find.h | 9 +-- bacula/src/plugins/fd/example-plugin-fd.c | 2 + bacula/src/tools/testfind.c | 12 --- bacula/technotes-2.3 | 2 + 11 files changed, 166 insertions(+), 79 deletions(-) diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index 3620355675..5660fb8244 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -439,10 +439,8 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) 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; } } diff --git a/bacula/src/filed/fd-plugins.c b/bacula/src/filed/fd-plugins.c index c503da898d..72b4151573 100644 --- a/bacula/src/filed/fd-plugins.c +++ b/bacula/src/filed/fd-plugins.c @@ -38,6 +38,12 @@ 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); @@ -48,6 +54,11 @@ static bpError baculaJobMsg(bpContext *ctx, const char *file, int line, 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 = { @@ -66,6 +77,7 @@ static bFuncs bfuncs = { baculaDebugMsg }; + /* * Create a plugin event */ @@ -74,17 +86,44 @@ void generate_plugin_event(JCR *jcr, bEventType eventType, void *value) 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) @@ -95,6 +134,11 @@ 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; + } /* @@ -149,6 +193,46 @@ void free_plugins(JCR *jcr) 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; +} /* ============================================================== * @@ -221,6 +305,12 @@ static bpError baculaDebugMsg(bpContext *ctx, const char *file, int line, #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]; diff --git a/bacula/src/filed/fd-plugins.h b/bacula/src/filed/fd-plugins.h index dc608f557c..513739603d 100644 --- a/bacula/src/filed/fd-plugins.h +++ b/bacula/src/filed/fd-plugins.h @@ -42,7 +42,29 @@ #endif #include "bc_types.h" #include "lib/plugins.h" +#include +/* + * 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 */ +}; /**************************************************************************** * * @@ -146,6 +168,8 @@ typedef struct s_pluginFuncs { 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)) diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index 6965a863a7..5673a633cc 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -313,12 +313,6 @@ void *handle_client_request(void *dirp) 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(); @@ -846,12 +840,12 @@ static void add_fileset(JCR *jcr, const char *item) 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: @@ -905,12 +899,6 @@ static bool term_fileset(JCR *jcr) for (k=0; kdrivetype.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) { diff --git a/bacula/src/findlib/bfile.c b/bacula/src/findlib/bfile.c index 4597d42c94..8ee2ff7cd5 100644 --- a/bacula/src/findlib/bfile.c +++ b/bacula/src/findlib/bfile.c @@ -1,7 +1,7 @@ /* 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. @@ -45,6 +45,12 @@ int (*python_close)(BFILE *bfd) = NULL; 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 #endif @@ -287,6 +293,7 @@ void binit(BFILE *bfd) bfd->fid = -1; bfd->mode = BF_CLOSED; bfd->use_backup_api = have_win32_api(); + bfd->cmd_plugin = false; } /* @@ -310,11 +317,16 @@ bool set_portable_backup(BFILE *bfd) 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 @@ -567,6 +579,7 @@ int bclose(BFILE *bfd) } bfd->mode = BF_CLOSED; bfd->lpContext = NULL; + bfd->cmd_plugin = false; return stat; } @@ -705,22 +718,14 @@ bool is_portable_backup(BFILE *bfd) 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; } /* @@ -783,10 +788,8 @@ bool is_restore_stream_supported(int stream) 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 */ @@ -850,9 +853,8 @@ int bclose(BFILE *bfd) 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) { @@ -870,6 +872,7 @@ int bclose(BFILE *bfd) stat = close(bfd->fid); bfd->berrno = errno; bfd->fid = -1; + bfd->cmd_plugin = false; return stat; } @@ -877,9 +880,10 @@ ssize_t bread(BFILE *bfd, void *buf, size_t count) { 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; @@ -889,8 +893,8 @@ ssize_t bwrite(BFILE *bfd, void *buf, size_t count) { 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; diff --git a/bacula/src/findlib/bfile.h b/bacula/src/findlib/bfile.h index ed3f6c6d28..7d26775390 100644 --- a/bacula/src/findlib/bfile.h +++ b/bacula/src/findlib/bfile.h @@ -1,7 +1,7 @@ /* 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. @@ -98,12 +98,12 @@ struct BFILE { 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); @@ -122,12 +122,12 @@ struct BFILE { 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 @@ -136,7 +136,7 @@ void binit(BFILE *bfd); 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); diff --git a/bacula/src/findlib/find.c b/bacula/src/findlib/find.c index e9e1d94f25..e2f1c0cd75 100644 --- a/bacula/src/findlib/find.c +++ b/bacula/src/findlib/find.c @@ -148,11 +148,6 @@ get_win32_driveletters(FF_PKT *ff, char* szDrives) } /* - * 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 @@ -205,7 +200,9 @@ find_files(JCR *jcr, FF_PKT *ff, int callback(FF_PKT *ff_pkt, void *hpkt, bool t 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; } } } @@ -237,8 +234,6 @@ static bool accept_file(FF_PKT *ff) 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; @@ -398,7 +393,6 @@ static int our_callback(FF_PKT *ff, void *hpkt, bool top_level) 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); diff --git a/bacula/src/findlib/find.h b/bacula/src/findlib/find.h index 9860ff5369..8bedc7a687 100644 --- a/bacula/src/findlib/find.h +++ b/bacula/src/findlib/find.h @@ -68,7 +68,6 @@ struct utimbuf { int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); #endif - /* * Status codes returned by create_file() */ @@ -80,7 +79,8 @@ enum { }; -/* 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 */ @@ -156,8 +156,6 @@ struct findFOPTS { 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 */ }; @@ -221,8 +219,7 @@ struct FF_PKT { 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 */ diff --git a/bacula/src/plugins/fd/example-plugin-fd.c b/bacula/src/plugins/fd/example-plugin-fd.c index 7599c4d9c7..b87a448264 100644 --- a/bacula/src/plugins/fd/example-plugin-fd.c +++ b/bacula/src/plugins/fd/example-plugin-fd.c @@ -151,6 +151,8 @@ static bpError handlePluginEvent(bpContext *ctx, bEvent *event, void *value) 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); diff --git a/bacula/src/tools/testfind.c b/bacula/src/tools/testfind.c index c42a9043a3..57528e309d 100644 --- a/bacula/src/tools/testfind.c +++ b/bacula/src/tools/testfind.c @@ -191,12 +191,6 @@ main (int argc, char *const *argv) 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(); @@ -513,12 +507,6 @@ static bool copy_fileset(FF_PKT *ff, JCR *jcr) for (k=0; kdrivetype.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; jname_list.size(); j++) { diff --git a/bacula/technotes-2.3 b/bacula/technotes-2.3 index d7009b849d..f160f18952 100644 --- a/bacula/technotes-2.3 +++ b/bacula/technotes-2.3 @@ -21,6 +21,8 @@ kes Attempt to work around gcc FORTIFY_SOURCE bug that crashes the 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. -- 2.39.5