2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation, which is
11 listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Main program to test loading and running Bacula plugins.
30 * Destined to become Bacula pluginloader, ...
32 * Kern Sibbald, October 2007
36 #include "plugin-sd.h"
39 #define NAMELEN(dirent) (strlen((dirent)->d_name))
41 #ifndef HAVE_READDIR_R
42 int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
52 t_bpShutdown p_bpShutdown;
57 /* All loaded plugins */
60 /* Forward referenced functions */
61 static Plugin *new_plugin();
62 bool load_plugins(const char *plugin_dir);
63 void unload_plugins();
64 static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value);
65 static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value);
67 int main(int argc, char *argv[])
69 char plugin_dir[1000];
74 plugin_list = New(alist(10, not_owned_by_alist));
78 getcwd(plugin_dir, sizeof(plugin_dir)-1);
79 load_plugins(plugin_dir);
81 foreach_alist(plugin, plugin_list) {
82 /* Start a new instance of the plugin */
83 plugin->pfuncs.pNew(&ctx);
84 event.eventType = bEventNewVolume;
85 plugin->pfuncs.pHandleEvent(&ctx, &event);
86 /* Destroy the instance */
87 plugin->pfuncs.pDestroy(&ctx);
89 /* Start a new instance of the plugin */
90 plugin->pfuncs.pNew(&ctx);
91 event.eventType = bEventNewVolume;
92 plugin->pfuncs.pHandleEvent(&ctx, &event);
93 /* Destroy the instance */
94 plugin->pfuncs.pDestroy(&ctx);
99 printf("bacula: OK ...\n");
105 * Create a new plugin "class" entry and enter it in the
106 * list of plugins. Note, this is not the same as
107 * an instance of the plugin.
109 static Plugin *new_plugin()
113 plugin = (Plugin *)malloc(sizeof(Plugin));
114 memset(plugin, 0, sizeof(Plugin));
115 plugin_list->append(plugin);
121 * Load all the plugins in the specified directory.
123 bool load_plugins(const char *plugin_dir)
125 t_bpInitialize p_bpInitialize;
130 struct dirent *entry, *result;
134 POOL_MEM fname(PM_FNAME);
135 bool need_slash = false;
138 /* Setup pointers to Bacula functions */
139 bfuncs.size = sizeof(bFuncs);
141 bfuncs.bGetValue = baculaGetValue;
142 bfuncs.bSetValue = baculaSetValue;
144 plugin = new_plugin();
146 name_max = pathconf(".", _PC_NAME_MAX);
147 if (name_max < 1024) {
151 if (!(dp = opendir(plugin_dir))) {
153 Dmsg2(29, "load_plugins: failed to open dir %s: ERR=%s\n",
154 plugin_dir, be.bstrerror());
158 len = strlen(plugin_dir);
160 need_slash = !IsPathSeparator(plugin_dir[len - 1]);
162 entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
164 if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
165 Dmsg1(129, "load_plugins: failed to find suitable file in dir %s\n",
169 if (strcmp(result->d_name, ".") == 0 ||
170 strcmp(result->d_name, "..") == 0) {
174 len = strlen(result->d_name);
175 if (len < 7 || strcmp(&result->d_name[len-6], "-sd.so") != 0) {
178 printf("Got: name=%s len=%d\n", result->d_name, len);
180 pm_strcpy(fname, plugin_dir);
182 pm_strcat(fname, "/");
184 pm_strcat(fname, result->d_name);
185 if (lstat(fname.c_str(), &statp) != 0 || !S_ISREG(statp.st_mode)) {
186 continue; /* ignore directories & special files */
189 plugin->file = bstrdup(result->d_name);
190 plugin->pHandle = dlopen(fname.c_str(), RTLD_NOW);
191 if (!plugin->pHandle) {
192 printf("dlopen of %s failed: ERR=%s\n", fname.c_str(), dlerror());
196 /* Get two global entry points */
197 p_bpInitialize = (t_bpInitialize)dlsym(plugin->pHandle, "bpInitialize");
198 if ((error=dlerror()) != NULL) {
199 printf("dlsym failed: ERR=%s\n", error);
202 plugin->p_bpShutdown = (t_bpShutdown)dlsym(plugin->pHandle, "bpShutdown");
203 if ((error=dlerror()) != NULL) {
204 printf("dlsym failed: ERR=%s\n", error);
208 /* Initialize the plugin */
209 p_bpInitialize(&bfuncs, &plugin->pfuncs);
210 printf("bacula: plugin_size=%d plugin_version=%d\n",
211 plugin->pfuncs.size, plugin->pfuncs.version);
213 found = true; /* found a plugin */
225 * Unload all the loaded plugins
227 void unload_plugins()
231 foreach_alist(plugin, plugin_list) {
232 /* Shut it down and unload it */
233 plugin->p_bpShutdown();
234 dlclose(plugin->pHandle);
244 static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value)
246 printf("bacula: GetValue var=%d\n", var);
248 *((int *)value) = 100;
253 static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value)
255 printf("baculaSetValue var=%d\n", var);