#
SVRSRCS = dird.c admin.c authenticate.c \
autoprune.c backup.c bsr.c \
- catreq.c dir-plugins.c dird_conf.c expand.c \
+ catreq.c dir_plugins.c dird_conf.c expand.c \
fd_cmds.c getmsg.c inc_conf.c job.c \
jobq.c migrate.c \
mountreq.c msgchan.c next_vol.c newvol.c \
ua_status.c ua_tree.c ua_update.c verify.c
SVROBJS = dird.o admin.o authenticate.o \
autoprune.o backup.o bsr.o \
- catreq.o dir-plugins.o dird_conf.o expand.o \
+ catreq.o dir_plugins.o dird_conf.o expand.o \
fd_cmds.o getmsg.o inc_conf.o job.o \
jobq.o migrate.o \
mountreq.o msgchan.o next_vol.o newvol.o \
+++ /dev/null
-/*
- Bacula® - The Network Backup Solution
-
- Copyright (C) 2007-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.
- This program is Free Software; you can redistribute it and/or
- modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation, which is
- listed in the file LICENSE.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Bacula® is a registered trademark of John Walker.
- The licensor of Bacula is the Free Software Foundation Europe
- (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
- Switzerland, email:ftf@fsfeurope.org.
-*/
-/*
- * Main program to test loading and running Bacula plugins.
- * Destined to become Bacula pluginloader, ...
- *
- * Kern Sibbald, October 2007
- */
-#include "bacula.h"
-#include "dird.h"
-
-const int dbglvl = 0;
-const char *plugin_type = "-dir.so";
-
-
-/* Forward referenced functions */
-static bRC baculaGetValue(bpContext *ctx, brVariable var, void *value);
-static bRC baculaSetValue(bpContext *ctx, bwVariable var, void *value);
-static bRC baculaRegisterEvents(bpContext *ctx, ...);
-static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
- int type, time_t mtime, const char *msg);
-static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
- int level, const char *msg);
-
-
-/* Bacula info */
-static bInfo binfo = {
- sizeof(bFuncs),
- DIR_PLUGIN_INTERFACE_VERSION,
-};
-
-/* Bacula entry points */
-static bFuncs bfuncs = {
- sizeof(bFuncs),
- DIR_PLUGIN_INTERFACE_VERSION,
- baculaRegisterEvents,
- baculaGetValue,
- baculaSetValue,
- baculaJobMsg,
- 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;
- }
-
- bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
- event.eventType = eventType;
-
- Dmsg2(dbglvl, "plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
-
- foreach_alist(plugin, plugin_list) {
- bRC rc;
- rc = plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i++], &event, value);
- if (rc != bRC_OK) {
- break;
- }
- }
-
- return;
-}
-
-void load_dir_plugins(const char *plugin_dir)
-{
- if (!plugin_dir) {
- return;
- }
-
- plugin_list = New(alist(10, not_owned_by_alist));
- load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type);
-}
-
-/*
- * Create a new instance of each plugin for this Job
- */
-void new_plugins(JCR *jcr)
-{
- Plugin *plugin;
- int i = 0;
-
- if (!plugin_list) {
- return;
- }
-
- int num = plugin_list->size();
-
- if (num == 0) {
- return;
- }
-
- jcr->plugin_ctx_list = (void *)malloc(sizeof(bpContext) * num);
-
- bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
- Dmsg2(dbglvl, "Instantiate plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
- foreach_alist(plugin, plugin_list) {
- /* Start a new instance of each plugin */
- plugin_ctx_list[i].bContext = (void *)jcr;
- plugin_ctx_list[i].pContext = NULL;
- plug_func(plugin)->newPlugin(&plugin_ctx_list[i++]);
- }
-}
-
-/*
- * Free the plugin instances for this Job
- */
-void free_plugins(JCR *jcr)
-{
- Plugin *plugin;
- int i = 0;
-
- if (!plugin_list) {
- return;
- }
-
- bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
- Dmsg2(dbglvl, "Free instance plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
- foreach_alist(plugin, plugin_list) {
- /* Free the plugin instance */
- plug_func(plugin)->freePlugin(&plugin_ctx_list[i++]);
- }
- free(plugin_ctx_list);
- jcr->plugin_ctx_list = NULL;
-}
-
-
-/* ==============================================================
- *
- * Callbacks from the plugin
- *
- * ==============================================================
- */
-static bRC baculaGetValue(bpContext *ctx, brVariable var, void *value)
-{
- JCR *jcr = (JCR *)(ctx->bContext);
-// Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var);
- if (!value) {
- return bRC_Error;
- }
-// Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr);
- switch (var) {
- case bVarJobId:
- *((int *)value) = jcr->JobId;
- Dmsg1(dbglvl, "Bacula: return bVarJobId=%d\n", jcr->JobId);
- break;
- default:
- break;
- }
- return bRC_OK;
-}
-
-static bRC baculaSetValue(bpContext *ctx, bwVariable var, void *value)
-{
- Dmsg1(dbglvl, "bacula: baculaSetValue var=%d\n", var);
- return bRC_OK;
-}
-
-static bRC baculaRegisterEvents(bpContext *ctx, ...)
-{
- va_list args;
- uint32_t event;
-
- va_start(args, ctx);
- while ((event = va_arg(args, uint32_t))) {
- Dmsg1(dbglvl, "Plugin wants event=%u\n", event);
- }
- va_end(args);
- return bRC_OK;
-}
-
-static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
- int type, time_t mtime, const char *msg)
-{
- Dmsg5(dbglvl, "Job message: %s:%d type=%d time=%ld msg=%s\n",
- file, line, type, mtime, msg);
- return bRC_OK;
-}
-
-static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
- int level, const char *msg)
-{
- Dmsg4(dbglvl, "Debug message: %s:%d level=%d msg=%s\n",
- file, line, level, msg);
- return bRC_OK;
-}
-
-#ifdef TEST_PROGRAM
-
-
-int main(int argc, char *argv[])
-{
- char plugin_dir[1000];
- JCR mjcr1, mjcr2;
- JCR *jcr1 = &mjcr1;
- JCR *jcr2 = &mjcr2;
-
- strcpy(my_name, "test-dir");
-
- getcwd(plugin_dir, sizeof(plugin_dir)-1);
- load_dir_plugins(plugin_dir);
-
- jcr1->JobId = 111;
- new_plugins(jcr1);
-
- jcr2->JobId = 222;
- new_plugins(jcr2);
-
- generate_plugin_event(jcr1, bEventJobStart, (void *)"Start Job 1");
- generate_plugin_event(jcr1, bEventJobEnd);
- generate_plugin_event(jcr2, bEventJobStart, (void *)"Start Job 1");
- free_plugins(jcr1);
- generate_plugin_event(jcr2, bEventJobEnd);
- free_plugins(jcr2);
-
- unload_plugins();
-
- Dmsg0(dbglvl, "bacula: OK ...\n");
- close_memory_pool();
- sm_dump(false);
- return 0;
-}
-
-#endif /* TEST_PROGRAM */
+++ /dev/null
-/*
- Bacula® - The Network Backup Solution
-
- Copyright (C) 2007-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.
- This program is Free Software; you can redistribute it and/or
- modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation, which is
- listed in the file LICENSE.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Bacula® is a registered trademark of John Walker.
- The licensor of Bacula is the Free Software Foundation Europe
- (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
- Switzerland, email:ftf@fsfeurope.org.
-*/
-/*
- * Interface definition for Bacula Plugins
- *
- * Kern Sibbald, October 2007
- *
- */
-
-#ifndef __FD_PLUGINS_H
-#define __FD_PLUGINS_H
-
-#ifndef _BACULA_H
-#ifdef __cplusplus
-/* Workaround for SGI IRIX 6.5 */
-#define _LANGUAGE_C_PLUS_PLUS 1
-#endif
-#define _REENTRANT 1
-#define _THREAD_SAFE 1
-#define _POSIX_PTHREAD_SEMANTICS 1
-#define _FILE_OFFSET_BITS 64
-#define _LARGEFILE_SOURCE 1
-#define _LARGE_FILES 1
-#endif
-
-#include <sys/types.h>
-#ifndef __CONFIG_H
-#define __CONFIG_H
-#include "config.h"
-#endif
-#include "bc_types.h"
-#include "lib/plugins.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-
-
-/****************************************************************************
- * *
- * Bacula definitions *
- * *
- ****************************************************************************/
-
-/* Bacula Variable Ids */
-typedef enum {
- bVarJob = 1,
- bVarLevel = 2,
- bVarType = 3,
- bVarJobId = 4,
- bVarClient = 5,
- bVarNumVols = 6,
- bVarPool = 7,
- bVarStorage = 8,
- bVarCatalog = 9,
- bVarMediaType = 10,
- bVarJobName = 11,
- bVarJobStatus = 12,
- bVarPriority = 13,
- bVarVolumeName = 14,
- bVarCatalogRes = 15,
- bVarJobErrors = 16,
- bVarJobFiles = 17,
- bVarSDJobFiles = 18,
- bVarSDErrors = 19,
- bVarFDJobStatus = 20,
- bVarSDJobStatus = 21
-} brVariable;
-
-typedef enum {
- bwVarJobReport = 1,
- bwVarVolumeName = 2,
- bwVarPriority = 3,
- bwVarJobLevel = 4,
-} bwVariable;
-
-
-typedef enum {
- bEventJobStart = 1,
- bEventJobEnd = 2,
-} bEventType;
-
-typedef struct s_bEvent {
- uint32_t eventType;
-} bEvent;
-
-typedef struct s_baculaInfo {
- uint32_t size;
- uint32_t version;
-} bInfo;
-
-/* Bacula interface version and function pointers */
-typedef struct s_baculaFuncs {
- uint32_t size;
- uint32_t version;
- bRC (*registerBaculaEvents)(bpContext *ctx, ...);
- bRC (*getBaculaValue)(bpContext *ctx, brVariable var, void *value);
- bRC (*setBaculaValue)(bpContext *ctx, bwVariable var, void *value);
- bRC (*JobMessage)(bpContext *ctx, const char *file, int line,
- int type, time_t mtime, const char *msg);
- bRC (*DebugMessage)(bpContext *ctx, const char *file, int line,
- int level, const char *msg);
-} bFuncs;
-
-/* Bacula Subroutines */
-void load_dir_plugins(const char *plugin_dir);
-void new_plugins(JCR *jcr);
-void free_plugins(JCR *jcr);
-void generate_plugin_event(JCR *jcr, bEventType event, void *value=NULL);
-
-
-
-/****************************************************************************
- * *
- * Plugin definitions *
- * *
- ****************************************************************************/
-
-typedef enum {
- pVarName = 1,
- pVarDescription = 2
-} pVariable;
-
-
-#define DIR_PLUGIN_MAGIC "*DirPluginData*"
-#define DIR_PLUGIN_INTERFACE_VERSION 1
-
-typedef struct s_pluginInfo {
- uint32_t size;
- uint32_t version;
- char *plugin_magic;
- char *plugin_license;
- char *plugin_author;
- char *plugin_date;
- char *plugin_version;
- char *plugin_description;
-} pInfo;
-
-typedef struct s_pluginFuncs {
- uint32_t size;
- uint32_t version;
- bRC (*newPlugin)(bpContext *ctx);
- bRC (*freePlugin)(bpContext *ctx);
- bRC (*getPluginValue)(bpContext *ctx, pVariable var, void *value);
- bRC (*setPluginValue)(bpContext *ctx, pVariable var, void *value);
- bRC (*handlePluginEvent)(bpContext *ctx, bEvent *event, void *value);
-} pFuncs;
-
-#define plug_func(plugin) ((pFuncs *)(plugin->pfuncs))
-#define plug_info(plugin) ((pInfo *)(plugin->pinfo))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __FD_PLUGINS_H */
--- /dev/null
+/*
+ Bacula® - The Network Backup Solution
+
+ Copyright (C) 2007-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.
+ This program is Free Software; you can redistribute it and/or
+ modify it under the terms of version two of the GNU General Public
+ License as published by the Free Software Foundation, which is
+ listed in the file LICENSE.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ Bacula® is a registered trademark of John Walker.
+ The licensor of Bacula is the Free Software Foundation Europe
+ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+ Switzerland, email:ftf@fsfeurope.org.
+*/
+/*
+ * Main program to test loading and running Bacula plugins.
+ * Destined to become Bacula pluginloader, ...
+ *
+ * Kern Sibbald, October 2007
+ */
+#include "bacula.h"
+#include "dird.h"
+
+const int dbglvl = 0;
+const char *plugin_type = "-dir.so";
+
+
+/* Forward referenced functions */
+static bRC baculaGetValue(bpContext *ctx, brVariable var, void *value);
+static bRC baculaSetValue(bpContext *ctx, bwVariable var, void *value);
+static bRC baculaRegisterEvents(bpContext *ctx, ...);
+static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
+ int type, time_t mtime, const char *msg);
+static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
+ int level, const char *msg);
+
+
+/* Bacula info */
+static bInfo binfo = {
+ sizeof(bFuncs),
+ DIR_PLUGIN_INTERFACE_VERSION,
+};
+
+/* Bacula entry points */
+static bFuncs bfuncs = {
+ sizeof(bFuncs),
+ DIR_PLUGIN_INTERFACE_VERSION,
+ baculaRegisterEvents,
+ baculaGetValue,
+ baculaSetValue,
+ baculaJobMsg,
+ 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;
+ }
+
+ bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+ event.eventType = eventType;
+
+ Dmsg2(dbglvl, "plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
+
+ foreach_alist(plugin, plugin_list) {
+ bRC rc;
+ rc = plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i++], &event, value);
+ if (rc != bRC_OK) {
+ break;
+ }
+ }
+
+ return;
+}
+
+void load_dir_plugins(const char *plugin_dir)
+{
+ if (!plugin_dir) {
+ return;
+ }
+
+ plugin_list = New(alist(10, not_owned_by_alist));
+ load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type);
+}
+
+/*
+ * Create a new instance of each plugin for this Job
+ */
+void new_plugins(JCR *jcr)
+{
+ Plugin *plugin;
+ int i = 0;
+
+ if (!plugin_list) {
+ return;
+ }
+
+ int num = plugin_list->size();
+
+ if (num == 0) {
+ return;
+ }
+
+ jcr->plugin_ctx_list = (void *)malloc(sizeof(bpContext) * num);
+
+ bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+ Dmsg2(dbglvl, "Instantiate plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
+ foreach_alist(plugin, plugin_list) {
+ /* Start a new instance of each plugin */
+ plugin_ctx_list[i].bContext = (void *)jcr;
+ plugin_ctx_list[i].pContext = NULL;
+ plug_func(plugin)->newPlugin(&plugin_ctx_list[i++]);
+ }
+}
+
+/*
+ * Free the plugin instances for this Job
+ */
+void free_plugins(JCR *jcr)
+{
+ Plugin *plugin;
+ int i = 0;
+
+ if (!plugin_list) {
+ return;
+ }
+
+ bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+ Dmsg2(dbglvl, "Free instance plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
+ foreach_alist(plugin, plugin_list) {
+ /* Free the plugin instance */
+ plug_func(plugin)->freePlugin(&plugin_ctx_list[i++]);
+ }
+ free(plugin_ctx_list);
+ jcr->plugin_ctx_list = NULL;
+}
+
+
+/* ==============================================================
+ *
+ * Callbacks from the plugin
+ *
+ * ==============================================================
+ */
+static bRC baculaGetValue(bpContext *ctx, brVariable var, void *value)
+{
+ JCR *jcr = (JCR *)(ctx->bContext);
+// Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var);
+ if (!value) {
+ return bRC_Error;
+ }
+// Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr);
+ switch (var) {
+ case bVarJobId:
+ *((int *)value) = jcr->JobId;
+ Dmsg1(dbglvl, "Bacula: return bVarJobId=%d\n", jcr->JobId);
+ break;
+ default:
+ break;
+ }
+ return bRC_OK;
+}
+
+static bRC baculaSetValue(bpContext *ctx, bwVariable var, void *value)
+{
+ Dmsg1(dbglvl, "bacula: baculaSetValue var=%d\n", var);
+ return bRC_OK;
+}
+
+static bRC baculaRegisterEvents(bpContext *ctx, ...)
+{
+ va_list args;
+ uint32_t event;
+
+ va_start(args, ctx);
+ while ((event = va_arg(args, uint32_t))) {
+ Dmsg1(dbglvl, "Plugin wants event=%u\n", event);
+ }
+ va_end(args);
+ return bRC_OK;
+}
+
+static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
+ int type, time_t mtime, const char *msg)
+{
+ Dmsg5(dbglvl, "Job message: %s:%d type=%d time=%ld msg=%s\n",
+ file, line, type, mtime, msg);
+ return bRC_OK;
+}
+
+static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
+ int level, const char *msg)
+{
+ Dmsg4(dbglvl, "Debug message: %s:%d level=%d msg=%s\n",
+ file, line, level, msg);
+ return bRC_OK;
+}
+
+#ifdef TEST_PROGRAM
+
+
+int main(int argc, char *argv[])
+{
+ char plugin_dir[1000];
+ JCR mjcr1, mjcr2;
+ JCR *jcr1 = &mjcr1;
+ JCR *jcr2 = &mjcr2;
+
+ strcpy(my_name, "test-dir");
+
+ getcwd(plugin_dir, sizeof(plugin_dir)-1);
+ load_dir_plugins(plugin_dir);
+
+ jcr1->JobId = 111;
+ new_plugins(jcr1);
+
+ jcr2->JobId = 222;
+ new_plugins(jcr2);
+
+ generate_plugin_event(jcr1, bEventJobStart, (void *)"Start Job 1");
+ generate_plugin_event(jcr1, bEventJobEnd);
+ generate_plugin_event(jcr2, bEventJobStart, (void *)"Start Job 1");
+ free_plugins(jcr1);
+ generate_plugin_event(jcr2, bEventJobEnd);
+ free_plugins(jcr2);
+
+ unload_plugins();
+
+ Dmsg0(dbglvl, "bacula: OK ...\n");
+ close_memory_pool();
+ sm_dump(false);
+ return 0;
+}
+
+#endif /* TEST_PROGRAM */
--- /dev/null
+/*
+ Bacula® - The Network Backup Solution
+
+ Copyright (C) 2007-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.
+ This program is Free Software; you can redistribute it and/or
+ modify it under the terms of version two of the GNU General Public
+ License as published by the Free Software Foundation, which is
+ listed in the file LICENSE.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ Bacula® is a registered trademark of John Walker.
+ The licensor of Bacula is the Free Software Foundation Europe
+ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+ Switzerland, email:ftf@fsfeurope.org.
+*/
+/*
+ * Interface definition for Bacula Plugins
+ *
+ * Kern Sibbald, October 2007
+ *
+ */
+
+#ifndef __FD_PLUGINS_H
+#define __FD_PLUGINS_H
+
+#ifndef _BACULA_H
+#ifdef __cplusplus
+/* Workaround for SGI IRIX 6.5 */
+#define _LANGUAGE_C_PLUS_PLUS 1
+#endif
+#define _REENTRANT 1
+#define _THREAD_SAFE 1
+#define _POSIX_PTHREAD_SEMANTICS 1
+#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE_SOURCE 1
+#define _LARGE_FILES 1
+#endif
+
+#include <sys/types.h>
+#ifndef __CONFIG_H
+#define __CONFIG_H
+#include "config.h"
+#endif
+#include "bc_types.h"
+#include "lib/plugins.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+
+/****************************************************************************
+ * *
+ * Bacula definitions *
+ * *
+ ****************************************************************************/
+
+/* Bacula Variable Ids */
+typedef enum {
+ bVarJob = 1,
+ bVarLevel = 2,
+ bVarType = 3,
+ bVarJobId = 4,
+ bVarClient = 5,
+ bVarNumVols = 6,
+ bVarPool = 7,
+ bVarStorage = 8,
+ bVarCatalog = 9,
+ bVarMediaType = 10,
+ bVarJobName = 11,
+ bVarJobStatus = 12,
+ bVarPriority = 13,
+ bVarVolumeName = 14,
+ bVarCatalogRes = 15,
+ bVarJobErrors = 16,
+ bVarJobFiles = 17,
+ bVarSDJobFiles = 18,
+ bVarSDErrors = 19,
+ bVarFDJobStatus = 20,
+ bVarSDJobStatus = 21
+} brVariable;
+
+typedef enum {
+ bwVarJobReport = 1,
+ bwVarVolumeName = 2,
+ bwVarPriority = 3,
+ bwVarJobLevel = 4,
+} bwVariable;
+
+
+typedef enum {
+ bEventJobStart = 1,
+ bEventJobEnd = 2,
+} bEventType;
+
+typedef struct s_bEvent {
+ uint32_t eventType;
+} bEvent;
+
+typedef struct s_baculaInfo {
+ uint32_t size;
+ uint32_t version;
+} bInfo;
+
+/* Bacula interface version and function pointers */
+typedef struct s_baculaFuncs {
+ uint32_t size;
+ uint32_t version;
+ bRC (*registerBaculaEvents)(bpContext *ctx, ...);
+ bRC (*getBaculaValue)(bpContext *ctx, brVariable var, void *value);
+ bRC (*setBaculaValue)(bpContext *ctx, bwVariable var, void *value);
+ bRC (*JobMessage)(bpContext *ctx, const char *file, int line,
+ int type, time_t mtime, const char *msg);
+ bRC (*DebugMessage)(bpContext *ctx, const char *file, int line,
+ int level, const char *msg);
+} bFuncs;
+
+/* Bacula Subroutines */
+void load_dir_plugins(const char *plugin_dir);
+void new_plugins(JCR *jcr);
+void free_plugins(JCR *jcr);
+void generate_plugin_event(JCR *jcr, bEventType event, void *value=NULL);
+
+
+
+/****************************************************************************
+ * *
+ * Plugin definitions *
+ * *
+ ****************************************************************************/
+
+typedef enum {
+ pVarName = 1,
+ pVarDescription = 2
+} pVariable;
+
+
+#define DIR_PLUGIN_MAGIC "*DirPluginData*"
+#define DIR_PLUGIN_INTERFACE_VERSION 1
+
+typedef struct s_pluginInfo {
+ uint32_t size;
+ uint32_t version;
+ char *plugin_magic;
+ char *plugin_license;
+ char *plugin_author;
+ char *plugin_date;
+ char *plugin_version;
+ char *plugin_description;
+} pInfo;
+
+typedef struct s_pluginFuncs {
+ uint32_t size;
+ uint32_t version;
+ bRC (*newPlugin)(bpContext *ctx);
+ bRC (*freePlugin)(bpContext *ctx);
+ bRC (*getPluginValue)(bpContext *ctx, pVariable var, void *value);
+ bRC (*setPluginValue)(bpContext *ctx, pVariable var, void *value);
+ bRC (*handlePluginEvent)(bpContext *ctx, bEvent *event, void *value);
+} pFuncs;
+
+#define plug_func(plugin) ((pFuncs *)(plugin->pfuncs))
+#define plug_info(plugin) ((pInfo *)(plugin->pinfo))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FD_PLUGINS_H */
#include "lib/runscript.h"
#include "lib/breg.h"
#include "dird_conf.h"
-#include "dir-plugins.h"
+#include "dir_plugins.h"
#define DIRECTOR_DAEMON 1
#
SVRSRCS = filed.c authenticate.c acl.c backup.c estimate.c \
- fd-plugins.c \
+ fd_plugins.c \
filed_conf.c heartbeat.c job.c pythonfd.c \
restore.c status.c verify.c verify_vol.c
SVROBJS = filed.o authenticate.o acl.o backup.o estimate.o \
- fd-plugins.o \
+ fd_plugins.o \
filed_conf.o heartbeat.o job.o pythonfd.o \
restore.o status.o verify.o verify_vol.o
+++ /dev/null
-/*
- Bacula® - The Network Backup Solution
-
- Copyright (C) 2007-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.
- This program is Free Software; you can redistribute it and/or
- modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation, which is
- listed in the file LICENSE.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Bacula® is a registered trademark of John Walker.
- The licensor of Bacula is the Free Software Foundation Europe
- (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
- Switzerland, email:ftf@fsfeurope.org.
-*/
-/*
- * Main program to test loading and running Bacula plugins.
- * Destined to become Bacula pluginloader, ...
- *
- * Kern Sibbald, October 2007
- */
-#include "bacula.h"
-#include "filed.h"
-
-const int dbglvl = 50;
-const char *plugin_type = "-fd.so";
-
-extern int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level);
-
-/* Function pointers to be set here */
-extern DLL_IMP_EXP int (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode);
-extern DLL_IMP_EXP int (*plugin_bclose)(JCR *jcr);
-extern DLL_IMP_EXP ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count);
-extern DLL_IMP_EXP ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count);
-extern DLL_IMP_EXP boffset_t (*plugin_blseek)(JCR *jcr, boffset_t offset, int whence);
-
-
-/* Forward referenced functions */
-static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value);
-static bRC baculaSetValue(bpContext *ctx, bVariable var, void *value);
-static bRC baculaRegisterEvents(bpContext *ctx, ...);
-static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
- int type, time_t mtime, const char *fmt, ...);
-static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
- int level, const char *fmt, ...);
-
-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);
-static boffset_t my_plugin_blseek(JCR *jcr, boffset_t offset, int whence);
-
-
-/* Bacula info */
-static bInfo binfo = {
- sizeof(bFuncs),
- FD_PLUGIN_INTERFACE_VERSION
-};
-
-/* Bacula entry points */
-static bFuncs bfuncs = {
- sizeof(bFuncs),
- FD_PLUGIN_INTERFACE_VERSION,
- baculaRegisterEvents,
- baculaGetValue,
- baculaSetValue,
- baculaJobMsg,
- 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. plugin_save() here is called with ff_pkt
- * 2. we find the plugin requested on the command string
- * 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
- * file. The plugin will be called at pluginIO() to supply the
- * file data.
- *
- * Sequence of calls for restore:
- * See subroutine plugin_name_stream() below.
- */
-int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
-{
- Plugin *plugin;
- int i = 0;
- int len;
- char *p;
- char *cmd = ff_pkt->top_fname;
- struct save_pkt sp;
- bEvent event;
-
- if (!plugin_list) {
- return 1; /* Return if no plugins loaded */
- }
-
- bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
- event.eventType = bEventBackupCommand;
-
- /* 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;
- }
-
- 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;
- }
- 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;
- }
- /* 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;
- }
- 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;
- }
- }
- }
- Jmsg1(jcr, M_ERROR, 0, "Command plugin \"%s\" not found.\n", cmd);
-
-bail_out:
- return 1;
-}
-
-/*
- * Send plugin name start/end record to SD
- */
-bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start)
-{
- int stat;
- struct save_pkt *sp = (struct save_pkt *)jcr->plugin_sp;
-
- Dmsg1(000, "send_plugin_name=%s\n", sp->cmd);
- if (!sd->fsend("%ld %d 0", jcr->JobFiles+1, STREAM_PLUGIN_NAME)) {
- Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
- sd->bstrerror());
- return false;
- }
- Dmsg1(000, "send: %s\n", sd->msg);
-
- if (start) {
- stat = sd->fsend("%ld 1 %d %s%c", jcr->JobFiles+1, 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. 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;
- Plugin *plugin;
- int len;
- int i = 0;
- bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
-
- Dmsg1(100, "Read plugin stream string=%s\n", name);
- skip_nonspaces(&p); /* skip over jcr->JobFiles */
- skip_spaces(&p);
- start = *p == '1';
- skip_nonspaces(&p); /* skip start/end flag */
- skip_spaces(&p);
- portable = *p == '1';
- skip_nonspaces(&p); /* skip portable flag */
- skip_spaces(&p);
- cmd = p;
-
- /* Check for restore end */
- if (!start) {
- /*
- * If end of restore, notify plugin, then clear flags
- */
- plugin = (Plugin *)jcr->plugin;
- plug_func(plugin)->endRestoreFile(&plugin_ctx_list[i]);
- jcr->plugin_ctx = NULL;
- jcr->plugin = NULL;
- goto bail_out;
- }
-
- /*
- * After this point, we are dealing with a restore start
- */
-
- Dmsg1(100, "plugin restore 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;
- }
-
- /*
- * Search for correct plugin as specified on the command
- */
- foreach_alist(plugin, plugin_list) {
- bEvent event;
- Dmsg3(100, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
- if (strncmp(plugin->file, cmd, len) != 0) {
- i++;
- continue;
- }
- Dmsg1(100, "Restore Command plugin = %s\n", cmd);
- event.eventType = bEventRestoreCommand;
- if (plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i],
- &event, cmd) != bRC_OK) {
- goto bail_out;
- }
- jcr->plugin_ctx = &plugin_ctx_list[i];
- jcr->plugin = plugin;
- goto bail_out;
- }
-bail_out:
- return;
-}
-
-/*
- * Tell the plugin to create the file. Return values are
- *
- * CF_ERROR -- error
- * CF_SKIP -- skip processing this file
- * CF_EXTRACT -- extract the file (i.e.call i/o routines)
- * CF_CREATED -- created, but no content to extract (typically directories)
- *
- */
-int plugin_create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace)
-{
- bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
- Plugin *plugin = (Plugin *)jcr->plugin;
- struct restore_pkt rp;
- struct io_pkt io;
-
- if (!set_cmd_plugin(bfd, jcr)) {
- return CF_ERROR;
- }
- rp.stream = attr->stream;
- rp.data_stream = attr->data_stream;
- rp.type = attr->type;
- rp.file_index = attr->file_index;
- rp.LinkFI = attr->LinkFI;
- rp.uid = attr->uid;
- rp.statp = attr->statp; /* structure assignment */
- rp.attrEx = attr->attrEx;
- rp.ofname = attr->ofname;
- rp.olname = attr->olname;
- rp.where = jcr->where;
- rp.RegexWhere = jcr->RegexWhere;
- rp.replace = jcr->replace;
- if (plug_func(plugin)->createFile(plugin_ctx, &rp) != bRC_OK) {
- return CF_ERROR;
- }
- io.func = IO_OPEN;
- io.count = 0;
- io.buf = NULL;
- io.mode = 0777 & attr->statp.st_mode;
- io.flags = O_WRONLY;
- if (plug_func(plugin)->pluginIO(plugin_ctx, &io) != bRC_OK) {
- return CF_ERROR;
- }
- return CF_EXTRACT;
-}
-
-/*
- * Reset the file attributes after all file I/O is done -- this allows
- * the previous access time/dates to be set properly, and it also allows
- * us to properly set directory permissions.
- */
-bool plugin_set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
-{
- return true;
-}
-
-void load_fd_plugins(const char *plugin_dir)
-{
- if (!plugin_dir) {
- return;
- }
-
- plugin_list = New(alist(10, not_owned_by_alist));
- load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type);
-
- /* Plug entry points called from findlib */
- plugin_bopen = my_plugin_bopen;
- plugin_bclose = my_plugin_bclose;
- plugin_bread = my_plugin_bread;
- plugin_bwrite = my_plugin_bwrite;
- plugin_blseek = my_plugin_blseek;
-
-}
-
-/*
- * Create a new instance of each plugin for this Job
- */
-void new_plugins(JCR *jcr)
-{
- Plugin *plugin;
- int i = 0;
-
- if (!plugin_list) {
- return;
- }
-
- int num = plugin_list->size();
-
- if (num == 0) {
- return;
- }
-
- jcr->plugin_ctx_list = (void *)malloc(sizeof(bpContext) * num);
-
- bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
- Dmsg2(dbglvl, "Instantiate plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId);
- foreach_alist(plugin, plugin_list) {
- /* Start a new instance of each plugin */
- plugin_ctx_list[i].bContext = (void *)jcr;
- plugin_ctx_list[i].pContext = NULL;
- plug_func(plugin)->newPlugin(&plugin_ctx_list[i++]);
- }
-}
-
-/*
- * Free the plugin instances for this Job
- */
-void free_plugins(JCR *jcr)
-{
- Plugin *plugin;
- int i = 0;
-
- if (!plugin_list) {
- return;
- }
-
- bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
- Dmsg2(dbglvl, "Free instance plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId);
- foreach_alist(plugin, plugin_list) {
- /* Free the plugin instance */
- plug_func(plugin)->freePlugin(&plugin_ctx_list[i++]);
- }
- free(plugin_ctx_list);
- jcr->plugin_ctx_list = NULL;
-}
-
-static int my_plugin_bopen(JCR *jcr, const char *fname, int flags, mode_t mode)
-{
- Plugin *plugin = (Plugin *)jcr->plugin;
- bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
- struct io_pkt io;
- Dmsg0(000, "plugin_bopen\n");
- io.func = IO_OPEN;
- io.count = 0;
- io.buf = NULL;
- io.mode = mode;
- io.flags = flags;
- plug_func(plugin)->pluginIO(plugin_ctx, &io);
- return io.status;
-}
-
-static int my_plugin_bclose(JCR *jcr)
-{
- Plugin *plugin = (Plugin *)jcr->plugin;
- bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
- struct io_pkt io;
- Dmsg0(000, "plugin_bclose\n");
- io.func = IO_CLOSE;
- io.count = 0;
- io.buf = NULL;
- plug_func(plugin)->pluginIO(plugin_ctx, &io);
- return io.status;
-}
-
-static ssize_t my_plugin_bread(JCR *jcr, void *buf, size_t count)
-{
- Plugin *plugin = (Plugin *)jcr->plugin;
- bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
- struct io_pkt io;
- Dmsg0(000, "plugin_bread\n");
- io.func = IO_READ;
- io.count = count;
- io.buf = (char *)buf;
- plug_func(plugin)->pluginIO(plugin_ctx, &io);
- return (ssize_t)io.status;
-}
-
-static ssize_t my_plugin_bwrite(JCR *jcr, void *buf, size_t count)
-{
- Plugin *plugin = (Plugin *)jcr->plugin;
- bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
- struct io_pkt io;
- Dmsg0(000, "plugin_bwrite\n");
- io.func = IO_WRITE;
- io.count = count;
- io.buf = (char *)buf;
- plug_func(plugin)->pluginIO(plugin_ctx, &io);
- return (ssize_t)io.status;
-}
-
-static boffset_t my_plugin_blseek(JCR *jcr, boffset_t offset, int whence)
-{
- Plugin *plugin = (Plugin *)jcr->plugin;
- bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
- struct io_pkt io;
- Dmsg0(000, "plugin_bseek\n");
- io.func = IO_SEEK;
- io.offset = offset;
- io.whence = whence;
- plug_func(plugin)->pluginIO(plugin_ctx, &io);
- return (boffset_t)io.offset;
-}
-
-/* ==============================================================
- *
- * Callbacks from the plugin
- *
- * ==============================================================
- */
-static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value)
-{
- JCR *jcr = (JCR *)(ctx->bContext);
-// Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var);
- if (!value) {
- return bRC_Error;
- }
-// Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr);
- switch (var) {
- case bVarJobId:
- *((int *)value) = jcr->JobId;
- Dmsg1(dbglvl, "Bacula: return bVarJobId=%d\n", jcr->JobId);
- break;
- case bVarFDName:
- *((char **)value) = my_name;
- Dmsg1(dbglvl, "Bacula: return my_name=%s\n", my_name);
- break;
- case bVarLevel:
- case bVarType:
- case bVarClient:
- case bVarJobName:
- case bVarJobStatus:
- case bVarSinceTime:
- break;
- }
- return bRC_OK;
-}
-
-static bRC baculaSetValue(bpContext *ctx, bVariable var, void *value)
-{
- Dmsg1(dbglvl, "bacula: baculaSetValue var=%d\n", var);
- return bRC_OK;
-}
-
-static bRC baculaRegisterEvents(bpContext *ctx, ...)
-{
- va_list args;
- uint32_t event;
-
- va_start(args, ctx);
- while ((event = va_arg(args, uint32_t))) {
- Dmsg1(dbglvl, "Plugin wants event=%u\n", event);
- }
- va_end(args);
- return bRC_OK;
-}
-
-static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
- int type, time_t mtime, const char *fmt, ...)
-{
- va_list arg_ptr;
- char buf[2000];
- JCR *jcr = (JCR *)(ctx->bContext);
-
- va_start(arg_ptr, fmt);
- bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
- va_end(arg_ptr);
- Jmsg(jcr, type, mtime, "%s", buf);
- return bRC_OK;
-}
-
-static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
- int level, const char *fmt, ...)
-{
- va_list arg_ptr;
- char buf[2000];
-
- va_start(arg_ptr, fmt);
- bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
- va_end(arg_ptr);
- d_msg(file, line, level, "%s", buf);
- return bRC_OK;
-}
-
-#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;
-boffset_t (*plugin_blseek)(JCR *jcr, boffset_t offset, int whence) = NULL;
-
-int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
-{
- return 0;
-}
-
-bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
-{
- return true;
-}
-
-int main(int argc, char *argv[])
-{
- char plugin_dir[1000];
- JCR mjcr1, mjcr2;
- JCR *jcr1 = &mjcr1;
- JCR *jcr2 = &mjcr2;
-
- strcpy(my_name, "test-fd");
-
- getcwd(plugin_dir, sizeof(plugin_dir)-1);
- load_fd_plugins(plugin_dir);
-
- jcr1->JobId = 111;
- new_plugins(jcr1);
-
- jcr2->JobId = 222;
- new_plugins(jcr2);
-
- generate_plugin_event(jcr1, bEventJobStart, (void *)"Start Job 1");
- generate_plugin_event(jcr1, bEventJobEnd);
- generate_plugin_event(jcr2, bEventJobStart, (void *)"Start Job 2");
- free_plugins(jcr1);
- generate_plugin_event(jcr2, bEventJobEnd);
- free_plugins(jcr2);
-
- unload_plugins();
-
- Dmsg0(dbglvl, "bacula: OK ...\n");
- close_memory_pool();
- sm_dump(false);
- return 0;
-}
-
-#endif /* TEST_PROGRAM */
+++ /dev/null
-/*
- Bacula® - The Network Backup Solution
-
- Copyright (C) 2007-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.
- This program is Free Software; you can redistribute it and/or
- modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation, which is
- listed in the file LICENSE.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Bacula® is a registered trademark of John Walker.
- The licensor of Bacula is the Free Software Foundation Europe
- (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
- Switzerland, email:ftf@fsfeurope.org.
-*/
-/*
- * Application Programming Interface (API) definition for Bacula Plugins
- *
- * Kern Sibbald, October 2007
- *
- */
-
-#ifndef __FD_PLUGINS_H
-#define __FD_PLUGINS_H
-
-#ifndef _BACULA_H
-#ifdef __cplusplus
-/* Workaround for SGI IRIX 6.5 */
-#define _LANGUAGE_C_PLUS_PLUS 1
-#endif
-#define _REENTRANT 1
-#define _THREAD_SAFE 1
-#define _POSIX_PTHREAD_SEMANTICS 1
-#define _FILE_OFFSET_BITS 64
-#define _LARGEFILE_SOURCE 1
-#define _LARGE_FILES 1
-#endif
-
-#include <sys/types.h>
-#ifndef __CONFIG_H
-#define __CONFIG_H
-#include "config.h"
-#endif
-#include "bc_types.h"
-#include "lib/plugins.h"
-#include <sys/stat.h>
-
-/*
- * This packet is used for file save 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 */
- int32_t type; /* FT_xx for this file */
- uint32_t flags; /* Bacula internal flags */
- bool portable; /* set if data format is portable */
- char *cmd; /* command */
-};
-
-/*
- * This packet is used for file restore info transfer.
-*/
-struct restore_pkt {
- int32_t stream; /* attribute stream id */
- int32_t data_stream; /* id of data stream to follow */
- int32_t type; /* file type FT */
- int32_t file_index; /* file index */
- int32_t LinkFI; /* file index to data if hard link */
- uid_t uid; /* userid */
- struct stat statp; /* decoded stat packet */
- const char *attrEx; /* extended attributes if any */
- const char *ofname; /* output filename */
- const char *olname; /* output link name */
- const char *where; /* where */
- const char *RegexWhere; /* regex where */
- int replace; /* replace flag */
-};
-
-enum {
- IO_OPEN = 1,
- IO_READ = 2,
- IO_WRITE = 3,
- IO_CLOSE = 4,
- IO_SEEK = 5
-};
-
-struct io_pkt {
- int32_t func; /* Function code */
- int32_t count; /* read/write count */
- mode_t mode; /* permissions for created files */
- int32_t flags; /* open flags (e.g. O_WRONLY ...) */
- char *buf; /* read/write buffer */
- int32_t status; /* return status */
- int32_t io_errno; /* errno code */
- int32_t whence;
- boffset_t offset;
-};
-
-/****************************************************************************
- * *
- * Bacula definitions *
- * *
- ****************************************************************************/
-
-/* Bacula Variable Ids */
-typedef enum {
- bVarJobId = 1,
- bVarFDName = 2,
- bVarLevel = 3,
- bVarType = 4,
- bVarClient = 5,
- bVarJobName = 6,
- bVarJobStatus = 7,
- bVarSinceTime = 8
-} bVariable;
-
-typedef enum {
- 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 {
- uint32_t eventType;
-} bEvent;
-
-typedef struct s_baculaInfo {
- uint32_t size;
- uint32_t version;
-} bInfo;
-
-/* 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 generate_plugin_event(JCR *jcr, bEventType event, void *value=NULL);
-bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start);
-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" {
-#endif
-
-/*
- * Bacula interface version and function pointers --
- * i.e. callbacks from the plugin to Bacula
- */
-typedef struct s_baculaFuncs {
- uint32_t size;
- uint32_t version;
- bRC (*registerBaculaEvents)(bpContext *ctx, ...);
- bRC (*getBaculaValue)(bpContext *ctx, bVariable var, void *value);
- bRC (*setBaculaValue)(bpContext *ctx, bVariable var, void *value);
- bRC (*JobMessage)(bpContext *ctx, const char *file, int line,
- int type, time_t mtime, const char *fmt, ...);
- bRC (*DebugMessage)(bpContext *ctx, const char *file, int line,
- int level, const char *fmt, ...);
-} bFuncs;
-
-
-
-
-/****************************************************************************
- * *
- * Plugin definitions *
- * *
- ****************************************************************************/
-
-typedef enum {
- pVarName = 1,
- pVarDescription = 2
-} pVariable;
-
-
-#define FD_PLUGIN_MAGIC "*FDPluginData*"
-#define FD_PLUGIN_INTERFACE_VERSION 1
-
-typedef struct s_pluginInfo {
- uint32_t size;
- uint32_t version;
- char *plugin_magic;
- char *plugin_license;
- char *plugin_author;
- char *plugin_date;
- char *plugin_version;
- char *plugin_description;
-} pInfo;
-
-/*
- * This is a set of function pointers that Bacula can call
- * within the plugin.
- */
-typedef struct s_pluginFuncs {
- uint32_t size;
- uint32_t version;
- bRC (*newPlugin)(bpContext *ctx);
- bRC (*freePlugin)(bpContext *ctx);
- 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 (*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);
- bRC (*createFile)(bpContext *ctx, struct restore_pkt *rp);
- bRC (*setFileAttributes)(bpContext *ctx, struct restore_pkt *rp);
-} pFuncs;
-
-#define plug_func(plugin) ((pFuncs *)(plugin->pfuncs))
-#define plug_info(plugin) ((pInfo *)(plugin->pinfo))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __FD_PLUGINS_H */
--- /dev/null
+/*
+ Bacula® - The Network Backup Solution
+
+ Copyright (C) 2007-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.
+ This program is Free Software; you can redistribute it and/or
+ modify it under the terms of version two of the GNU General Public
+ License as published by the Free Software Foundation, which is
+ listed in the file LICENSE.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ Bacula® is a registered trademark of John Walker.
+ The licensor of Bacula is the Free Software Foundation Europe
+ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+ Switzerland, email:ftf@fsfeurope.org.
+*/
+/*
+ * Main program to test loading and running Bacula plugins.
+ * Destined to become Bacula pluginloader, ...
+ *
+ * Kern Sibbald, October 2007
+ */
+#include "bacula.h"
+#include "filed.h"
+
+const int dbglvl = 50;
+const char *plugin_type = "-fd.so";
+
+extern int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level);
+
+/* Function pointers to be set here */
+extern DLL_IMP_EXP int (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode);
+extern DLL_IMP_EXP int (*plugin_bclose)(JCR *jcr);
+extern DLL_IMP_EXP ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count);
+extern DLL_IMP_EXP ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count);
+extern DLL_IMP_EXP boffset_t (*plugin_blseek)(JCR *jcr, boffset_t offset, int whence);
+
+
+/* Forward referenced functions */
+static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value);
+static bRC baculaSetValue(bpContext *ctx, bVariable var, void *value);
+static bRC baculaRegisterEvents(bpContext *ctx, ...);
+static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
+ int type, time_t mtime, const char *fmt, ...);
+static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
+ int level, const char *fmt, ...);
+
+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);
+static boffset_t my_plugin_blseek(JCR *jcr, boffset_t offset, int whence);
+
+
+/* Bacula info */
+static bInfo binfo = {
+ sizeof(bFuncs),
+ FD_PLUGIN_INTERFACE_VERSION
+};
+
+/* Bacula entry points */
+static bFuncs bfuncs = {
+ sizeof(bFuncs),
+ FD_PLUGIN_INTERFACE_VERSION,
+ baculaRegisterEvents,
+ baculaGetValue,
+ baculaSetValue,
+ baculaJobMsg,
+ 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. plugin_save() here is called with ff_pkt
+ * 2. we find the plugin requested on the command string
+ * 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
+ * file. The plugin will be called at pluginIO() to supply the
+ * file data.
+ *
+ * Sequence of calls for restore:
+ * See subroutine plugin_name_stream() below.
+ */
+int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
+{
+ Plugin *plugin;
+ int i = 0;
+ int len;
+ char *p;
+ char *cmd = ff_pkt->top_fname;
+ struct save_pkt sp;
+ bEvent event;
+
+ if (!plugin_list) {
+ return 1; /* Return if no plugins loaded */
+ }
+
+ bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+ event.eventType = bEventBackupCommand;
+
+ /* 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;
+ }
+
+ 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;
+ }
+ 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;
+ }
+ /* 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;
+ }
+ 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;
+ }
+ }
+ }
+ Jmsg1(jcr, M_ERROR, 0, "Command plugin \"%s\" not found.\n", cmd);
+
+bail_out:
+ return 1;
+}
+
+/*
+ * Send plugin name start/end record to SD
+ */
+bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start)
+{
+ int stat;
+ struct save_pkt *sp = (struct save_pkt *)jcr->plugin_sp;
+
+ Dmsg1(000, "send_plugin_name=%s\n", sp->cmd);
+ if (!sd->fsend("%ld %d 0", jcr->JobFiles+1, STREAM_PLUGIN_NAME)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ sd->bstrerror());
+ return false;
+ }
+ Dmsg1(000, "send: %s\n", sd->msg);
+
+ if (start) {
+ stat = sd->fsend("%ld 1 %d %s%c", jcr->JobFiles+1, 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. 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;
+ Plugin *plugin;
+ int len;
+ int i = 0;
+ bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+
+ Dmsg1(100, "Read plugin stream string=%s\n", name);
+ skip_nonspaces(&p); /* skip over jcr->JobFiles */
+ skip_spaces(&p);
+ start = *p == '1';
+ skip_nonspaces(&p); /* skip start/end flag */
+ skip_spaces(&p);
+ portable = *p == '1';
+ skip_nonspaces(&p); /* skip portable flag */
+ skip_spaces(&p);
+ cmd = p;
+
+ /* Check for restore end */
+ if (!start) {
+ /*
+ * If end of restore, notify plugin, then clear flags
+ */
+ plugin = (Plugin *)jcr->plugin;
+ plug_func(plugin)->endRestoreFile(&plugin_ctx_list[i]);
+ jcr->plugin_ctx = NULL;
+ jcr->plugin = NULL;
+ goto bail_out;
+ }
+
+ /*
+ * After this point, we are dealing with a restore start
+ */
+
+ Dmsg1(100, "plugin restore 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;
+ }
+
+ /*
+ * Search for correct plugin as specified on the command
+ */
+ foreach_alist(plugin, plugin_list) {
+ bEvent event;
+ Dmsg3(100, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
+ if (strncmp(plugin->file, cmd, len) != 0) {
+ i++;
+ continue;
+ }
+ Dmsg1(100, "Restore Command plugin = %s\n", cmd);
+ event.eventType = bEventRestoreCommand;
+ if (plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i],
+ &event, cmd) != bRC_OK) {
+ goto bail_out;
+ }
+ jcr->plugin_ctx = &plugin_ctx_list[i];
+ jcr->plugin = plugin;
+ goto bail_out;
+ }
+bail_out:
+ return;
+}
+
+/*
+ * Tell the plugin to create the file. Return values are
+ *
+ * CF_ERROR -- error
+ * CF_SKIP -- skip processing this file
+ * CF_EXTRACT -- extract the file (i.e.call i/o routines)
+ * CF_CREATED -- created, but no content to extract (typically directories)
+ *
+ */
+int plugin_create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace)
+{
+ bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
+ Plugin *plugin = (Plugin *)jcr->plugin;
+ struct restore_pkt rp;
+ struct io_pkt io;
+
+ if (!set_cmd_plugin(bfd, jcr)) {
+ return CF_ERROR;
+ }
+ rp.stream = attr->stream;
+ rp.data_stream = attr->data_stream;
+ rp.type = attr->type;
+ rp.file_index = attr->file_index;
+ rp.LinkFI = attr->LinkFI;
+ rp.uid = attr->uid;
+ rp.statp = attr->statp; /* structure assignment */
+ rp.attrEx = attr->attrEx;
+ rp.ofname = attr->ofname;
+ rp.olname = attr->olname;
+ rp.where = jcr->where;
+ rp.RegexWhere = jcr->RegexWhere;
+ rp.replace = jcr->replace;
+ if (plug_func(plugin)->createFile(plugin_ctx, &rp) != bRC_OK) {
+ return CF_ERROR;
+ }
+ io.func = IO_OPEN;
+ io.count = 0;
+ io.buf = NULL;
+ io.mode = 0777 & attr->statp.st_mode;
+ io.flags = O_WRONLY;
+ if (plug_func(plugin)->pluginIO(plugin_ctx, &io) != bRC_OK) {
+ return CF_ERROR;
+ }
+ return CF_EXTRACT;
+}
+
+/*
+ * Reset the file attributes after all file I/O is done -- this allows
+ * the previous access time/dates to be set properly, and it also allows
+ * us to properly set directory permissions.
+ */
+bool plugin_set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
+{
+ return true;
+}
+
+void load_fd_plugins(const char *plugin_dir)
+{
+ if (!plugin_dir) {
+ return;
+ }
+
+ plugin_list = New(alist(10, not_owned_by_alist));
+ load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type);
+
+ /* Plug entry points called from findlib */
+ plugin_bopen = my_plugin_bopen;
+ plugin_bclose = my_plugin_bclose;
+ plugin_bread = my_plugin_bread;
+ plugin_bwrite = my_plugin_bwrite;
+ plugin_blseek = my_plugin_blseek;
+
+}
+
+/*
+ * Create a new instance of each plugin for this Job
+ */
+void new_plugins(JCR *jcr)
+{
+ Plugin *plugin;
+ int i = 0;
+
+ if (!plugin_list) {
+ return;
+ }
+
+ int num = plugin_list->size();
+
+ if (num == 0) {
+ return;
+ }
+
+ jcr->plugin_ctx_list = (void *)malloc(sizeof(bpContext) * num);
+
+ bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+ Dmsg2(dbglvl, "Instantiate plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId);
+ foreach_alist(plugin, plugin_list) {
+ /* Start a new instance of each plugin */
+ plugin_ctx_list[i].bContext = (void *)jcr;
+ plugin_ctx_list[i].pContext = NULL;
+ plug_func(plugin)->newPlugin(&plugin_ctx_list[i++]);
+ }
+}
+
+/*
+ * Free the plugin instances for this Job
+ */
+void free_plugins(JCR *jcr)
+{
+ Plugin *plugin;
+ int i = 0;
+
+ if (!plugin_list) {
+ return;
+ }
+
+ bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+ Dmsg2(dbglvl, "Free instance plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId);
+ foreach_alist(plugin, plugin_list) {
+ /* Free the plugin instance */
+ plug_func(plugin)->freePlugin(&plugin_ctx_list[i++]);
+ }
+ free(plugin_ctx_list);
+ jcr->plugin_ctx_list = NULL;
+}
+
+static int my_plugin_bopen(JCR *jcr, const char *fname, int flags, mode_t mode)
+{
+ Plugin *plugin = (Plugin *)jcr->plugin;
+ bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
+ struct io_pkt io;
+ Dmsg0(000, "plugin_bopen\n");
+ io.func = IO_OPEN;
+ io.count = 0;
+ io.buf = NULL;
+ io.mode = mode;
+ io.flags = flags;
+ plug_func(plugin)->pluginIO(plugin_ctx, &io);
+ return io.status;
+}
+
+static int my_plugin_bclose(JCR *jcr)
+{
+ Plugin *plugin = (Plugin *)jcr->plugin;
+ bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
+ struct io_pkt io;
+ Dmsg0(000, "plugin_bclose\n");
+ io.func = IO_CLOSE;
+ io.count = 0;
+ io.buf = NULL;
+ plug_func(plugin)->pluginIO(plugin_ctx, &io);
+ return io.status;
+}
+
+static ssize_t my_plugin_bread(JCR *jcr, void *buf, size_t count)
+{
+ Plugin *plugin = (Plugin *)jcr->plugin;
+ bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
+ struct io_pkt io;
+ Dmsg0(000, "plugin_bread\n");
+ io.func = IO_READ;
+ io.count = count;
+ io.buf = (char *)buf;
+ plug_func(plugin)->pluginIO(plugin_ctx, &io);
+ return (ssize_t)io.status;
+}
+
+static ssize_t my_plugin_bwrite(JCR *jcr, void *buf, size_t count)
+{
+ Plugin *plugin = (Plugin *)jcr->plugin;
+ bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
+ struct io_pkt io;
+ Dmsg0(000, "plugin_bwrite\n");
+ io.func = IO_WRITE;
+ io.count = count;
+ io.buf = (char *)buf;
+ plug_func(plugin)->pluginIO(plugin_ctx, &io);
+ return (ssize_t)io.status;
+}
+
+static boffset_t my_plugin_blseek(JCR *jcr, boffset_t offset, int whence)
+{
+ Plugin *plugin = (Plugin *)jcr->plugin;
+ bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
+ struct io_pkt io;
+ Dmsg0(000, "plugin_bseek\n");
+ io.func = IO_SEEK;
+ io.offset = offset;
+ io.whence = whence;
+ plug_func(plugin)->pluginIO(plugin_ctx, &io);
+ return (boffset_t)io.offset;
+}
+
+/* ==============================================================
+ *
+ * Callbacks from the plugin
+ *
+ * ==============================================================
+ */
+static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value)
+{
+ JCR *jcr = (JCR *)(ctx->bContext);
+// Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var);
+ if (!value) {
+ return bRC_Error;
+ }
+// Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr);
+ switch (var) {
+ case bVarJobId:
+ *((int *)value) = jcr->JobId;
+ Dmsg1(dbglvl, "Bacula: return bVarJobId=%d\n", jcr->JobId);
+ break;
+ case bVarFDName:
+ *((char **)value) = my_name;
+ Dmsg1(dbglvl, "Bacula: return my_name=%s\n", my_name);
+ break;
+ case bVarLevel:
+ case bVarType:
+ case bVarClient:
+ case bVarJobName:
+ case bVarJobStatus:
+ case bVarSinceTime:
+ break;
+ }
+ return bRC_OK;
+}
+
+static bRC baculaSetValue(bpContext *ctx, bVariable var, void *value)
+{
+ Dmsg1(dbglvl, "bacula: baculaSetValue var=%d\n", var);
+ return bRC_OK;
+}
+
+static bRC baculaRegisterEvents(bpContext *ctx, ...)
+{
+ va_list args;
+ uint32_t event;
+
+ va_start(args, ctx);
+ while ((event = va_arg(args, uint32_t))) {
+ Dmsg1(dbglvl, "Plugin wants event=%u\n", event);
+ }
+ va_end(args);
+ return bRC_OK;
+}
+
+static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
+ int type, time_t mtime, const char *fmt, ...)
+{
+ va_list arg_ptr;
+ char buf[2000];
+ JCR *jcr = (JCR *)(ctx->bContext);
+
+ va_start(arg_ptr, fmt);
+ bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
+ va_end(arg_ptr);
+ Jmsg(jcr, type, mtime, "%s", buf);
+ return bRC_OK;
+}
+
+static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
+ int level, const char *fmt, ...)
+{
+ va_list arg_ptr;
+ char buf[2000];
+
+ va_start(arg_ptr, fmt);
+ bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
+ va_end(arg_ptr);
+ d_msg(file, line, level, "%s", buf);
+ return bRC_OK;
+}
+
+#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;
+boffset_t (*plugin_blseek)(JCR *jcr, boffset_t offset, int whence) = NULL;
+
+int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
+{
+ return 0;
+}
+
+bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
+{
+ return true;
+}
+
+int main(int argc, char *argv[])
+{
+ char plugin_dir[1000];
+ JCR mjcr1, mjcr2;
+ JCR *jcr1 = &mjcr1;
+ JCR *jcr2 = &mjcr2;
+
+ strcpy(my_name, "test-fd");
+
+ getcwd(plugin_dir, sizeof(plugin_dir)-1);
+ load_fd_plugins(plugin_dir);
+
+ jcr1->JobId = 111;
+ new_plugins(jcr1);
+
+ jcr2->JobId = 222;
+ new_plugins(jcr2);
+
+ generate_plugin_event(jcr1, bEventJobStart, (void *)"Start Job 1");
+ generate_plugin_event(jcr1, bEventJobEnd);
+ generate_plugin_event(jcr2, bEventJobStart, (void *)"Start Job 2");
+ free_plugins(jcr1);
+ generate_plugin_event(jcr2, bEventJobEnd);
+ free_plugins(jcr2);
+
+ unload_plugins();
+
+ Dmsg0(dbglvl, "bacula: OK ...\n");
+ close_memory_pool();
+ sm_dump(false);
+ return 0;
+}
+
+#endif /* TEST_PROGRAM */
--- /dev/null
+/*
+ Bacula® - The Network Backup Solution
+
+ Copyright (C) 2007-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.
+ This program is Free Software; you can redistribute it and/or
+ modify it under the terms of version two of the GNU General Public
+ License as published by the Free Software Foundation, which is
+ listed in the file LICENSE.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ Bacula® is a registered trademark of John Walker.
+ The licensor of Bacula is the Free Software Foundation Europe
+ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+ Switzerland, email:ftf@fsfeurope.org.
+*/
+/*
+ * Application Programming Interface (API) definition for Bacula Plugins
+ *
+ * Kern Sibbald, October 2007
+ *
+ */
+
+#ifndef __FD_PLUGINS_H
+#define __FD_PLUGINS_H
+
+#ifndef _BACULA_H
+#ifdef __cplusplus
+/* Workaround for SGI IRIX 6.5 */
+#define _LANGUAGE_C_PLUS_PLUS 1
+#endif
+#define _REENTRANT 1
+#define _THREAD_SAFE 1
+#define _POSIX_PTHREAD_SEMANTICS 1
+#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE_SOURCE 1
+#define _LARGE_FILES 1
+#endif
+
+#include <sys/types.h>
+#ifndef __CONFIG_H
+#define __CONFIG_H
+#include "config.h"
+#endif
+#include "bc_types.h"
+#include "lib/plugins.h"
+#include <sys/stat.h>
+
+/*
+ * This packet is used for file save 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 */
+ int32_t type; /* FT_xx for this file */
+ uint32_t flags; /* Bacula internal flags */
+ bool portable; /* set if data format is portable */
+ char *cmd; /* command */
+};
+
+/*
+ * This packet is used for file restore info transfer.
+*/
+struct restore_pkt {
+ int32_t stream; /* attribute stream id */
+ int32_t data_stream; /* id of data stream to follow */
+ int32_t type; /* file type FT */
+ int32_t file_index; /* file index */
+ int32_t LinkFI; /* file index to data if hard link */
+ uid_t uid; /* userid */
+ struct stat statp; /* decoded stat packet */
+ const char *attrEx; /* extended attributes if any */
+ const char *ofname; /* output filename */
+ const char *olname; /* output link name */
+ const char *where; /* where */
+ const char *RegexWhere; /* regex where */
+ int replace; /* replace flag */
+};
+
+enum {
+ IO_OPEN = 1,
+ IO_READ = 2,
+ IO_WRITE = 3,
+ IO_CLOSE = 4,
+ IO_SEEK = 5
+};
+
+struct io_pkt {
+ int32_t func; /* Function code */
+ int32_t count; /* read/write count */
+ mode_t mode; /* permissions for created files */
+ int32_t flags; /* open flags (e.g. O_WRONLY ...) */
+ char *buf; /* read/write buffer */
+ int32_t status; /* return status */
+ int32_t io_errno; /* errno code */
+ int32_t whence;
+ boffset_t offset;
+};
+
+/****************************************************************************
+ * *
+ * Bacula definitions *
+ * *
+ ****************************************************************************/
+
+/* Bacula Variable Ids */
+typedef enum {
+ bVarJobId = 1,
+ bVarFDName = 2,
+ bVarLevel = 3,
+ bVarType = 4,
+ bVarClient = 5,
+ bVarJobName = 6,
+ bVarJobStatus = 7,
+ bVarSinceTime = 8
+} bVariable;
+
+typedef enum {
+ 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 {
+ uint32_t eventType;
+} bEvent;
+
+typedef struct s_baculaInfo {
+ uint32_t size;
+ uint32_t version;
+} bInfo;
+
+/* 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 generate_plugin_event(JCR *jcr, bEventType event, void *value=NULL);
+bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start);
+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" {
+#endif
+
+/*
+ * Bacula interface version and function pointers --
+ * i.e. callbacks from the plugin to Bacula
+ */
+typedef struct s_baculaFuncs {
+ uint32_t size;
+ uint32_t version;
+ bRC (*registerBaculaEvents)(bpContext *ctx, ...);
+ bRC (*getBaculaValue)(bpContext *ctx, bVariable var, void *value);
+ bRC (*setBaculaValue)(bpContext *ctx, bVariable var, void *value);
+ bRC (*JobMessage)(bpContext *ctx, const char *file, int line,
+ int type, time_t mtime, const char *fmt, ...);
+ bRC (*DebugMessage)(bpContext *ctx, const char *file, int line,
+ int level, const char *fmt, ...);
+} bFuncs;
+
+
+
+
+/****************************************************************************
+ * *
+ * Plugin definitions *
+ * *
+ ****************************************************************************/
+
+typedef enum {
+ pVarName = 1,
+ pVarDescription = 2
+} pVariable;
+
+
+#define FD_PLUGIN_MAGIC "*FDPluginData*"
+#define FD_PLUGIN_INTERFACE_VERSION 1
+
+typedef struct s_pluginInfo {
+ uint32_t size;
+ uint32_t version;
+ char *plugin_magic;
+ char *plugin_license;
+ char *plugin_author;
+ char *plugin_date;
+ char *plugin_version;
+ char *plugin_description;
+} pInfo;
+
+/*
+ * This is a set of function pointers that Bacula can call
+ * within the plugin.
+ */
+typedef struct s_pluginFuncs {
+ uint32_t size;
+ uint32_t version;
+ bRC (*newPlugin)(bpContext *ctx);
+ bRC (*freePlugin)(bpContext *ctx);
+ 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 (*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);
+ bRC (*createFile)(bpContext *ctx, struct restore_pkt *rp);
+ bRC (*setFileAttributes)(bpContext *ctx, struct restore_pkt *rp);
+} pFuncs;
+
+#define plug_func(plugin) ((pFuncs *)(plugin->pfuncs))
+#define plug_info(plugin) ((pInfo *)(plugin->pinfo))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FD_PLUGINS_H */
#define FILE_DAEMON 1
#include "filed_conf.h"
-#include "fd-plugins.h"
+#include "fd_plugins.h"
#include "findlib/find.h"
#include "jcr.h"
#include "acl.h"
#include "jcr.h"
#include "bfile.h"
-#include "../filed/fd-plugins.h"
+#include "../filed/fd_plugins.h"
#ifdef HAVE_DIRENT_H
#include <dirent.h>
test: main example-plugin-dir.so
-dir-plugins.o: ${DIRDIR}/dir-plugins.h ${DIRDIR}/dir-plugins.c
- $(CC) -I${SRCDIR} -I${DIRDIR} -DTEST_PROGRAM -c ${DIRDIR}/dir-plugins.c
+dir_plugins.o: ${DIRDIR}/dir_plugins.h ${DIRDIR}/dir_plugins.c
+ $(CC) -I${SRCDIR} -I${DIRDIR} -DTEST_PROGRAM -c ${DIRDIR}/dir_plugins.c
-main: dir-plugins.o
- $(CC) -L${LIBDIR} dir-plugins.o -o main -lbac -lpthread -lssl -l crypto -ldl
+main: dir_plugins.o
+ $(CC) -L${LIBDIR} dir_plugins.o -o main -lbac -lpthread -lssl -l crypto -ldl
-example-plugin-dir.o: example-plugin-dir.c ${DIRDIR}/dir-plugins.h
+example-plugin-dir.o: example-plugin-dir.c ${DIRDIR}/dir_plugins.h
$(CC) -fPIC -I../.. -I${DIRDIR} -c example-plugin-dir.c
example-plugin-dir.so: example-plugin-dir.o
*
*/
#include <stdio.h>
-#include "dir-plugins.h"
+#include "dir_plugins.h"
#ifdef __cplusplus
extern "C" {
test: main example-plugin-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
+fd_plugins.o: ${FDDIR}/fd_plugins.h ${FDDIR}/fd_plugins.c
+ $(CC) -I${SRCDIR} -I${FDDIR} -DTEST_PROGRAM -c ${FDDIR}/fd_plugins.c
-main: fd-plugins.o
- $(CC) -L${LIBDIR} fd-plugins.o -o main -lbac -lpthread -lssl -l crypto -ldl
+main: fd_plugins.o
+ $(CC) -L${LIBDIR} fd_plugins.o -o main -lbac -lpthread -lssl -l crypto -ldl
-example-plugin-fd.o: example-plugin-fd.c ${FDDIR}/fd-plugins.h
+example-plugin-fd.o: example-plugin-fd.c ${FDDIR}/fd_plugins.h
$(CC) -fPIC -I../.. -I${FDDIR} -c example-plugin-fd.c
example-plugin-fd.so: example-plugin-fd.o
$(CC) -shared example-plugin-fd.o -o example-plugin-fd.so
-bpipe-fd.o: bpipe-fd.c ${FDDIR}/fd-plugins.h
+bpipe-fd.o: bpipe-fd.c ${FDDIR}/fd_plugins.h
$(CC) -fPIC -I../.. -I${FDDIR} -c bpipe-fd.c
bpipe-fd.so: bpipe-fd.o
* Kern Sibbald, October 2007
*
*/
-#include "fd-plugins.h"
+#include "fd_plugins.h"
#undef malloc
#undef free
*
*/
#include <stdio.h>
-#include "fd-plugins.h"
+#include "fd_plugins.h"
#ifdef __cplusplus
extern "C" {
General:
08Mar08
+kes Rename fd/dir plugin to use Bacula standard underscore.
kes Plugin work -- bring dir up to fd level.
kes Start implementation of VTL code
kes Fix Win32 build after adding new cats subroutine.