]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
metaplugin: Add local restore with Core functions.
authorRadosław Korzeniewski <radoslaw@korzeniewski.net>
Thu, 8 Apr 2021 13:02:12 +0000 (15:02 +0200)
committerEric Bollengier <eric@baculasystems.com>
Thu, 24 Mar 2022 08:03:01 +0000 (09:03 +0100)
bacula/src/plugins/fd/pluginlib/Makefile
bacula/src/plugins/fd/pluginlib/metaplugin.cpp
bacula/src/plugins/fd/pluginlib/metaplugin.h
bacula/src/plugins/fd/pluginlib/pluginlib.h
bacula/src/plugins/fd/pluginlib/pluginlib_test.cpp

index 812107c81564e1dba478eb837c49fbb7ccc57a1a..ec741f92a725b662dc3d0a78a6a3cc86f2d9218a 100644 (file)
@@ -77,6 +77,14 @@ test_metaplugin_backend.lo: $(TESTMETAPLUGINBACKENDSRC)
        @echo "Compiling backend $< ..."
        $(NO_ECHO)$(LIBTOOL_COMPILE) $(CXX) $(DEFS) $(DEBUG) $(CPPFLAGS) $(CFLAGS) -I${SRCDIR} -I${FDDIR} -DLOGDIR=\"$(DESTDIR)$(working_dir)\" -c $<
 
+test_metaplugin_backend_fd: $(TESTMETAPLUGINBACKENDOBJ) test_metaplugin_backend_fd.lo
+       @echo "Building $@ ..."
+       $(NO_ECHO)$(LIBTOOL_LINK) --silent $(CXX) $(LDFLAGS) test_metaplugin_backend_fd.lo $(TESTMETAPLUGINBACKENDOBJ) -o $@
+
+test_metaplugin-fd.la: $(PTCOMMOBJ) $(PLUGINLIBSOBJ) $(METAPLUGINOBJ) test_metaplugin-fd.lo
+       @echo "Linking $(@:.la=.so) ..."
+       $(NO_ECHO)$(LIBTOOL_LINK) --silent $(CXX) $(LDFLAGS) -shared $^ -o $@ -rpath $(plugindir) -module -export-dynamic -avoid-version
+
 pluginlib_test: $(PLUGINLIBSTESTOBJ) $(PLUGINLIBSTEST) $(UNITTESTSOBJ) $(LIBBACOBJ)
        @echo "Building $@ ..."
        $(NO_ECHO)$(LIBTOOL_LINK) --silent $(CXX) $(LDFLAGS) -L$(LIBDIR) -lbac $(PLUGINLIBSTESTOBJ) -o $@
index 852c48d2de2607856ace3b4840fa3492820afe9b..93e255e59061c7d2b937a3d3c7d73ba5ec4e9d7f 100644 (file)
@@ -17,7 +17,7 @@
    Bacula(R) is a registered trademark of Kern Sibbald.
  */
 /**
- * @file metaplugin.h
+ * @file metaplugin.cpp
  * @author Radosław Korzeniewski (radoslaw@korzeniewski.net)
  * @brief This is a Bacula metaplugin interface.
  * @version 2.1.0
@@ -2145,10 +2145,14 @@ bRC METAPLUGIN::endBackupFile(bpContext *ctx)
 }
 
 /*
- * The PLUGIN is not using this callback to handle restore.
+ * The PLUGIN is using this callback to handle Core restore.
  */
 bRC METAPLUGIN::startRestoreFile(bpContext *ctx, const char *cmd)
 {
+   if (CORELOCALRESTORE && islocalpath(where)){
+      DMSG0(ctx, DDEBUG, "Forwarding restore to Core\n");
+      return bRC_Core;
+   }
    return bRC_OK;
 }
 
@@ -2594,7 +2598,7 @@ static bRC startRestoreFile(bpContext *ctx, const char *cmd)
 {
    ASSERT_CTX;
 
-   DMSG0(ctx, D1, "startRestoreFile.\n");
+   DMSG1(ctx, D1, "startRestoreFile: %s\n", NPRT(cmd));
    METAPLUGIN *self = pluginclass(ctx);
    return self->startRestoreFile(ctx, cmd);
 }
index f17fcabf24874e1d9706ab1f41bbfea2c4845f8f..6ebeff31a0b40226439aca87305e1725cd8ecbdb 100644 (file)
 #define PLUGINLIB_METAPLUGIN_H
 
 
+// custom checkFile() callback
+typedef bRC (*checkFile_t)(bpContext *ctx, char *fname);
+
+// metadata handling map
+struct metadataTypeMap
+{
+   const char *command;
+   metadata_type type;
+};
+extern const metadataTypeMap plugin_metadata_map[];
+
 // Plugin Info definitions
 extern const char *PLUGIN_LICENSE;
 extern const char *PLUGIN_AUTHOR;
@@ -48,16 +59,17 @@ extern const char *PLUGIN_VERSION;
 extern const char *PLUGIN_DESCRIPTION;
 
 // Plugin linking time variables
-extern const char *PLUGINPREFIX;
-extern const char *PLUGINNAME;
-extern const char *PLUGINNAMESPACE;
-extern const bool CUSTOMNAMESPACE;
+extern const char *PLUGINPREFIX;       /// is used for prefixing every Job and Debug messages generted by a plugin
+extern const char *PLUGINNAME;         /// should match the backend $pluginname$ used for Handshake procedure
+extern const bool CUSTOMNAMESPACE;     /// defines if metaplugin should send `Namespace=...` backend plugin parameter using PLUGINNAMESPACE variable
+extern const char *PLUGINNAMESPACE;    /// custom backend plugin namespace used as file name prefix
 extern const char *PLUGINAPI;
 extern const char *BACKEND_CMD;
 
-// custom checkFile() callback
-typedef bRC (*checkFile_t)(bpContext *ctx, char *fname);
-extern checkFile_t checkFile;
+/// defines if metaplugin should handle local filesystem restore with Bacula Core functions
+/// `false` means metaplugin will redirect local restore to backend
+/// `true` means Bacula Core functions will handle local restore
+extern const bool CORELOCALRESTORE;
 
 // The list of restore options saved to the RestoreObject.
 extern struct ini_items plugin_items_dump[];
@@ -65,13 +77,8 @@ extern struct ini_items plugin_items_dump[];
 // the list of valid plugin options
 extern const char *valid_params[];
 
-struct metadataTypeMap
-{
-   const char *command;
-   metadata_type type;
-};
-
-extern const metadataTypeMap plugin_metadata_map[];
+// custom checkFile() callback
+extern checkFile_t checkFile;
 
 /*
  * This is a main plugin API class. It manages a plugin context.
index b13713a9ea900566a1e31c8e8a4bb832177f1c0b..871dad3c3539eff9467ab763a8f5b66ce06cdb41 100644 (file)
@@ -183,6 +183,25 @@ inline bool isourpluginfname(const char *pluginprefix, const char *fname)
 
 alist * plugutil_str_split_to_alist(const char * str, const char sep = '.');
 
+/**
+ * @brief Verifies if path is local except '/'
+ *
+ * @param path
+ * @return true
+ * @return false
+ */
+inline bool islocalpath(const char *path)
+{
+   bool result = path && strlen(path) > 1;
+   bool spath = path[0] == '/';
+#ifdef HAVE_WIN32
+   bool wpath = isalpha(path[0]) && path[1] == ':' ;   // simple drive letter
+#else
+   bool wpath = false;
+#endif
+   return result && (spath || wpath);
+}
+
 /* plugin parameters manipulation */
 bool render_param(POOLMEM **param, const char *pname, const char *fmt, const char *name, const char *value);
 bool render_param(POOLMEM **param, const char *pname, const char *fmt, const char *name, const int value);
index 7352fcd088a968ca8e12f79284b4e964a8c3f04b..c4f994b496045d5089d26306647e066204ba294b 100644 (file)
 bFuncs *bfuncs;
 bInfo *binfo;
 
+struct vectstruct
+{
+   const char *path;
+   bool result;
+   const char *descr;
+};
+
 int main()
 {
    Unittests pluglib_test("pluglib_test");
@@ -98,5 +105,27 @@ int main()
    ok(bstrcmp(param.c_str(), fname1) , "check scan parameter for char* str param");
    nok(scan_parameter_str(cmd2, "prefix", param), "check scan parameter for char* str not match");
 
+   const vectstruct testvect1[] = {
+      { "", false, "checking empty" },
+      { "/", false, "checking slash" },
+      { "other", false, "checking other" },
+      { "/tmp", true, "checking local" },
+      { "/tmp/restore", true, "checking local" },
+#ifdef HAVE_WIN32
+      { "c:", true, "checking local win32" },
+      { "d:/", true, "checking local win32" },
+      { "E:/", true, "checking local win32" },
+      { "F:/test", true, "checking local win32" },
+      { "g:/test/restore", true, "checking local win32" },
+#endif
+      { NULL, false, NULL },
+   };
+
+   for (int i = 0; testvect1[i].path != NULL; i++)
+   {
+      bool result = islocalpath(testvect1[i].path);
+      ok(result == testvect1[i].result, testvect1[i].descr);
+   }
+
    return report();
 }