2 Bacula® - The Network Backup Solution
4 Copyright (C) 2008-2008 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 Kern Sibbald.
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 * Written by James Harper, October 2008
32 #include "exchange-fd.h"
34 /* Pointers to Bacula functions */
35 bFuncs *bfuncs = NULL;
38 #define PLUGIN_LICENSE "GPL"
39 #define PLUGIN_AUTHOR "James Harper"
40 #define PLUGIN_DATE "September 2008"
41 #define PLUGIN_VERSION "1"
42 #define PLUGIN_DESCRIPTION "Exchange Plugin"
44 static pInfo pluginInfo = {
46 FD_PLUGIN_INTERFACE_VERSION,
55 /* Forward referenced functions */
56 static bRC newPlugin(bpContext *ctx);
57 static bRC freePlugin(bpContext *ctx);
58 static bRC getPluginValue(bpContext *ctx, pVariable var, void *value);
59 static bRC setPluginValue(bpContext *ctx, pVariable var, void *value);
60 static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value);
61 static bRC startBackupFile(bpContext *ctx, struct save_pkt *sp);
62 static bRC endBackupFile(bpContext *ctx);
63 static bRC pluginIO(bpContext *ctx, struct io_pkt *io);
64 static bRC startRestoreFile(bpContext *ctx, const char *cmd);
65 static bRC endRestoreFile(bpContext *ctx);
66 static bRC createFile(bpContext *ctx, struct restore_pkt *rp);
67 static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp);
69 static pFuncs pluginFuncs = {
71 FD_PLUGIN_INTERFACE_VERSION,
73 /* Entry points into plugin */
74 newPlugin, /* new plugin instance */
75 freePlugin, /* free plugin instance */
91 splitString(char *string, char split, int maxParts, int *count)
97 //KdPrint((__DRIVER_NAME " a\n"));
101 RetVal = (char **)malloc((maxParts + 1) * sizeof(char *));
105 if (*count == maxParts)
108 for (last = first; *last != '\0' && *last != split; last++);
109 RetVal[*count] = (char *)malloc(last - first + 1);
110 strncpy(RetVal[*count], first, last - first);
111 RetVal[*count][last - first] = 0;
115 } while (*last != 0);
116 RetVal[*count] = NULL;
121 loadPlugin(bInfo *lbinfo, bFuncs *lbfuncs, pInfo **pinfo, pFuncs **pfuncs)
124 bfuncs = lbfuncs; /* set Bacula funct pointers */
126 *pinfo = &pluginInfo;
127 *pfuncs = &pluginFuncs;
128 retval = loadExchangeApi();
129 if (retval != bRC_OK)
131 printf("Cannot load Exchange DLL\n");
146 b_malloc(const char *file, int lone, size_t size)
152 sm_malloc(const char *file, int lone, size_t size)
157 static bRC newPlugin(bpContext *ctx)
159 exchange_fd_context_t *context;
164 ctx->pContext = new exchange_fd_context_t;
165 context = (exchange_fd_context_t *)ctx->pContext;
166 context->bpContext = ctx;
167 context->job_since = 0;
168 context->notrunconfull_option = false;
169 bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId);
170 _DebugMessage(0, "newPlugin JobId=%d\n", JobId);
171 bfuncs->registerBaculaEvents(ctx, 1, 2, 0);
172 size = MAX_COMPUTERNAME_LENGTH + 1;
173 context->computer_name = new WCHAR[size];
174 GetComputerNameW(context->computer_name, &size);
175 context->current_node = NULL;
176 context->root_node = NULL;
180 static bRC freePlugin(bpContext *ctx)
182 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
184 bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId);
185 _DebugMessage(100, "freePlugin JobId=%d\n", JobId);
190 static bRC getPluginValue(bpContext *ctx, pVariable var, void *value)
192 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
193 _DebugMessage(100, "getPluginValue var=%d\n", var);
197 static bRC setPluginValue(bpContext *ctx, pVariable var, void *value)
199 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
200 _DebugMessage(100, "setPluginValue var=%d\n", var);
204 static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value)
206 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
210 switch (event->eventType) {
212 _DebugMessage(0, "JobStart=%s\n", (char *)value);
215 _DebugMessage(0, "JobEnd\n");
217 case bEventStartBackupJob:
218 _DebugMessage(0, "BackupStart\n");
219 context->job_type = JOB_TYPE_BACKUP;
220 // level should have been specified by now - check it
221 // if level is D or I, since should have been specified too
222 switch (context->job_level)
225 if (context->notrunconfull_option) {
226 context->truncate_logs = false;
228 context->truncate_logs = true;
232 context->truncate_logs = false;
235 context->truncate_logs = false;
238 _DebugMessage(0, "Invalid job level %c\n", context->job_level);
242 case bEventEndBackupJob:
243 _DebugMessage(0, "BackupEnd\n");
246 _DebugMessage(0, "JobLevel=%c %d\n", (int)value, (int)value);
247 context->job_level = (int)value;
250 _DebugMessage(0, "since=%d\n", (int)value);
251 context->job_since = (time_t)value;
253 case bEventStartRestoreJob:
254 _DebugMessage(0, "StartRestoreJob\n");
255 context->job_type = JOB_TYPE_RESTORE;
257 case bEventEndRestoreJob:
258 _DebugMessage(0, "EndRestoreJob\n");
261 /* Plugin command e.g. plugin = <plugin-name>:<name-space>:command */
262 case bEventRestoreCommand:
263 _DebugMessage(0, "restore\n"); // command=%s\n", (char *)value);
266 case bEventBackupCommand:
268 _DebugMessage(0, "backup command=%s\n", (char *)value);
269 char *command = new char[strlen((char *)value)];
270 strcpy(command, (char *)value);
271 char *plugin_name = strtok((char *)command, ":");
272 char *path = strtok(NULL, ":");
274 while ((option = strtok(NULL, ":")) != NULL)
276 _DebugMessage(100, "option %s\n", option);
277 if (stricmp(option, "notrunconfull") == 0)
279 context->notrunconfull_option = true;
283 _JobMessage(M_WARNING, "Unknown plugin option '%s'\n", option);
286 _DebugMessage(0, "name = %s\n", plugin_name);
287 _DebugMessage(0, "path = %s\n", path);
290 _JobMessage(M_ERROR, "Path does not begin with a '/'\n");
294 for (i = 0; i < 6; i++)
295 context->path_bits[i] = NULL;
297 char *path_bit = strtok(path, "/");
298 for (i = 0; path_bit != NULL && i < 6; i++)
300 context->path_bits[i] = new char[strlen(path_bit) + 1];
301 strcpy(context->path_bits[i], path_bit);
302 path_bit = strtok(NULL, "/");
307 _JobMessage(M_ERROR, "Invalid plugin backup path\n");
310 context->root_node = new root_node_t(context->path_bits[0]);
311 context->current_node = context->root_node;
317 _JobMessage(M_ERROR, "unknown event=%d\n", event->eventType);
319 bfuncs->getBaculaValue(ctx, bVarFDName, (void *)&name);
324 startBackupFile(bpContext *ctx, struct save_pkt *sp)
327 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
328 node_t *current_node;
330 _DebugMessage(100, "startBackupFile, cmd = %s\n", sp->cmd);
331 if (sp->pkt_size != sizeof(struct save_pkt) || sp->pkt_end != sizeof(struct save_pkt))
333 _JobMessage(M_FATAL, "save_pkt size mismatch - sizeof(struct save_pkt) = %d, pkt_size = %d, pkt_end = %d\n", sizeof(struct save_pkt), sp->pkt_size, sp->pkt_end);
337 //context->root_node = new root_node_t(PLUGIN_PATH_PREFIX_BASE);
338 //context->current_node = context->root_node;
340 current_node = context->current_node;
341 retval = current_node->startBackupFile(context, sp);
342 } while (current_node != context->current_node);
343 _DebugMessage(100, "startBackupFile done - type = %d, fname = %s, retval = %d\n", sp->type, sp->fname, retval);
347 static bRC endBackupFile(bpContext *ctx)
350 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
351 node_t *current_node;
353 _DebugMessage(100, "endBackupFile\n");
356 current_node = context->current_node;
357 retval = current_node->endBackupFile(context);
358 } while (current_node != context->current_node);
359 _DebugMessage(100, "endBackupFile done - retval = %d\n", retval);
366 static bRC pluginIO(bpContext *ctx, struct io_pkt *io)
369 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
371 if (io->pkt_size != sizeof(struct io_pkt) || io->pkt_end != sizeof(struct io_pkt))
373 _JobMessage(M_ERROR, "io_pkt size mismatch - sizeof(struct io_pkt) = %d, pkt_size = %d, pkt_end = %d\n", sizeof(struct io_pkt), io->pkt_size, io->pkt_end);
378 _DebugMessage(100, "IO_OPEN\n");
379 retval = context->current_node->pluginIoOpen(context, io);
382 //_DebugMessage(100, "IO_READ buf=%p len=%d\n", io->buf, io->count);
383 retval = context->current_node->pluginIoRead(context, io);
386 //_DebugMessage(100, "IO_WRITE buf=%p len=%d\n", io->buf, io->count);
387 retval = context->current_node->pluginIoWrite(context, io);
390 _DebugMessage(100, "IO_CLOSE\n");
391 retval = context->current_node->pluginIoClose(context, io);
397 static bRC startRestoreFile(bpContext *ctx, const char *cmd)
399 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
400 _DebugMessage(100, "startRestoreFile\n");
405 static bRC endRestoreFile(bpContext *ctx)
408 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
409 node_t *current_node;
411 _DebugMessage(100, "endRestoreFile\n");
414 current_node = context->current_node;
415 retval = current_node->endRestoreFile(context);
416 } while (current_node != context->current_node);
417 _DebugMessage(100, "endRestoreFile done - retval = %d\n", retval);
421 static bRC createFile(bpContext *ctx, struct restore_pkt *rp)
424 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
425 node_t *current_node;
431 _DebugMessage(100, "createFile - type = %d, ofname = %s\n", rp->type, rp->ofname);
432 if (rp->pkt_size != sizeof(struct restore_pkt) || rp->pkt_end != sizeof(struct restore_pkt))
434 _JobMessage(M_ERROR, "restore_pkt size mismatch - sizeof(struct restore_pkt) = %d, pkt_size = %d, pkt_end = %d\n", sizeof(struct restore_pkt), rp->pkt_size, rp->pkt_end);
437 for (i = 0; i < 6; i++)
439 context->path_bits[i] = NULL;
442 path_bits = splitString((char *)rp->ofname, '/', 7, &count);
444 _DebugMessage(100, "count = %d\n", count);
446 for (i = 1; i < count; i++)
448 _DebugMessage(150, "%d = '%s'\n", i, path_bits[i]);
449 context->path_bits[i - 1] = path_bits[i];
452 if (context->current_node == NULL)
454 context->root_node = new root_node_t(context->path_bits[0]);
455 context->current_node = context->root_node;
459 current_node = context->current_node;
460 retval = current_node->createFile(context, rp);
461 } while (current_node != context->current_node);
462 _DebugMessage(100, "createFile done - retval = %d\n", retval);
466 static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp)
468 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
469 _DebugMessage(100, "setFileAttributes\n");