2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2018 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Written by James Harper, July 2010
22 * Used only in "old Exchange plugin" now deprecated.
25 #include "exchange-fd.h"
27 /* Pointers to Bacula functions */
28 bFuncs *bfuncs = NULL;
31 #define PLUGIN_LICENSE "Bacula"
32 #define PLUGIN_AUTHOR "James Harper"
33 #define PLUGIN_DATE "September 2008"
34 #define PLUGIN_VERSION "1"
35 #define PLUGIN_DESCRIPTION "Exchange Plugin"
37 static pInfo pluginInfo = {
39 FD_PLUGIN_INTERFACE_VERSION,
48 /* Forward referenced functions */
49 static bRC newPlugin(bpContext *ctx);
50 static bRC freePlugin(bpContext *ctx);
51 static bRC getPluginValue(bpContext *ctx, pVariable var, void *value);
52 static bRC setPluginValue(bpContext *ctx, pVariable var, void *value);
53 static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value);
54 static bRC startBackupFile(bpContext *ctx, struct save_pkt *sp);
55 static bRC endBackupFile(bpContext *ctx);
56 static bRC pluginIO(bpContext *ctx, struct io_pkt *io);
57 static bRC startRestoreFile(bpContext *ctx, const char *cmd);
58 static bRC endRestoreFile(bpContext *ctx);
59 static bRC createFile(bpContext *ctx, struct restore_pkt *rp);
60 static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp);
61 static bRC checkFile(bpContext *ctx, char *fname);
63 static pFuncs pluginFuncs = {
65 FD_PLUGIN_INTERFACE_VERSION,
67 /* Entry points into plugin */
68 newPlugin, /* new plugin instance */
69 freePlugin, /* free plugin instance */
81 NULL /* No ACL/XATTR */
87 splitString(char *string, char split, int maxParts, int *count)
93 //KdPrint((__DRIVER_NAME " a\n"));
97 RetVal = (char **)malloc((maxParts + 1) * sizeof(char *));
101 if (*count == maxParts)
104 for (last = first; *last != '\0' && *last != split; last++);
105 RetVal[*count] = (char *)malloc(last - first + 1);
106 strncpy(RetVal[*count], first, last - first);
107 RetVal[*count][last - first] = 0;
111 } while (*last != 0);
112 RetVal[*count] = NULL;
117 loadPlugin(bInfo *lbinfo, bFuncs *lbfuncs, pInfo **pinfo, pFuncs **pfuncs)
120 bfuncs = lbfuncs; /* set Bacula funct pointers */
122 *pinfo = &pluginInfo;
123 *pfuncs = &pluginFuncs;
124 retval = loadExchangeApi();
125 if (retval != bRC_OK) {
126 printf("Cannot load Exchange DLL\n");
141 b_malloc(const char *file, int lone, size_t size)
147 sm_malloc(const char *file, int lone, size_t size)
153 static bRC newPlugin(bpContext *ctx)
155 exchange_fd_context_t *context;
160 ctx->pContext = new exchange_fd_context_t;
161 context = (exchange_fd_context_t *)ctx->pContext;
162 context->bpContext = ctx;
163 context->job_since = 0;
164 context->notrunconfull_option = false;
165 context->plugin_active = false;
166 bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId);
167 _DebugMessage(0, "newPlugin JobId=%d\n", JobId);
168 bfuncs->registerBaculaEvents(ctx, 1, 2, 0);
169 size = MAX_COMPUTERNAME_LENGTH + 1;
170 context->computer_name = new WCHAR[size];
172 GetComputerNameW(context->computer_name, &size);
174 GetComputerNameExW(ComputerNameNetBIOS, 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;
213 switch (event->eventType) {
215 _DebugMessage(0, "JobStart=%s\n", (char *)value);
216 context->plugin_active = false;
219 _DebugMessage(0, "JobEnd\n");
221 case bEventPluginCommand:
222 _DebugMessage(0, "bEventPluginCommand %s\n", value);
223 command = bstrdup((char *)value);
224 /* this isn't really unused */
225 plugin_name = strtok((char *)command, ":");
226 if (strcmp(plugin_name, "exchange") != 0) {
227 context->plugin_active = false;
229 context->plugin_active = true;
233 case bEventStartBackupJob:
234 if (!context->plugin_active) {
237 _DebugMessage(0, "BackupStart\n");
238 bfuncs->getBaculaValue(ctx, bVarAccurate, (void *)&accurate);
239 context->accurate = accurate;
240 context->job_type = JOB_TYPE_BACKUP;
241 // level should have been specified by now - check it
242 // if level is D or I, since should have been specified too
243 switch (context->job_level) {
245 if (context->notrunconfull_option) {
246 context->truncate_logs = false;
248 context->truncate_logs = true;
252 context->truncate_logs = false;
255 context->truncate_logs = false;
258 _DebugMessage(0, "Invalid job level %c\n", context->job_level);
262 case bEventEndBackupJob:
263 _DebugMessage(0, "BackupEnd\n");
264 if (!context->plugin_active) {
269 /* We don't know if the plugin is active here yet */
270 intval = (intptr_t)value;
271 _DebugMessage(0, "JobLevel=%c %d\n", intval, intval);
272 context->job_level = intval;
275 /* We don't know if the plugin is active here yet */
276 intval = (intptr_t)value;
277 _DebugMessage(0, "since=%d\n", intval);
278 context->job_since = (time_t)value;
280 case bEventStartRestoreJob:
281 _DebugMessage(0, "StartRestoreJob\n");
282 context->job_type = JOB_TYPE_RESTORE;
283 context->plugin_active = true;
285 case bEventEndRestoreJob:
286 if (!context->plugin_active) {
289 _DebugMessage(0, "EndRestoreJob\n");
290 context->plugin_active = false;
293 /* Plugin command e.g. plugin = <plugin-name>:<name-space>:command */
294 case bEventRestoreCommand:
295 _DebugMessage(0, "restore\n"); // command=%s\n", (char *)value);
296 if (!context->plugin_active) {
301 case bEventBackupCommand:
302 if (!context->plugin_active) {
306 _DebugMessage(0, "backup command=%s\n", (char *)value);
307 char *command = new char[strlen((char *)value) + 1];
308 strcpy(command, (char *)value);
309 char *plugin_name = strtok((char *)command, ":");
310 char *path = strtok(NULL, ":");
312 while ((option = strtok(NULL, ":")) != NULL) {
313 _DebugMessage(100, "option %s\n", option);
314 if (stricmp(option, "notrunconfull") == 0) {
315 context->notrunconfull_option = true;
317 _JobMessage(M_WARNING, "Unknown plugin option '%s'\n", option);
320 _DebugMessage(0, "name = %s\n", plugin_name);
321 _DebugMessage(0, "path = %s\n", path);
323 _JobMessage(M_FATAL, "Path does not begin with a '/'\n");
327 for (i = 0; i < 6; i++) {
328 context->path_bits[i] = NULL;
331 char *path_bit = strtok(path, "/");
332 for (i = 0; path_bit != NULL && i < 6; i++) {
333 context->path_bits[i] = new char[strlen(path_bit) + 1];
334 strcpy(context->path_bits[i], path_bit);
335 path_bit = strtok(NULL, "/");
338 if (i < 2 || i > 4) {
339 _JobMessage(M_FATAL, "Invalid plugin backup path\n");
342 context->root_node = new root_node_t(context->path_bits[0]);
343 context->current_node = context->root_node;
348 case bEventVssBeforeCloseRestore:
350 case bEventComponentInfo:
354 _DebugMessage(0, "Ignored event=%d\n", event->eventType);
357 bfuncs->getBaculaValue(ctx, bVarFDName, (void *)&name);
362 startBackupFile(bpContext *ctx, struct save_pkt *sp)
365 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
366 node_t *current_node;
368 _DebugMessage(100, "startBackupFile, cmd = %s\n", sp->cmd);
369 if (sp->pkt_size != sizeof(struct save_pkt) || sp->pkt_end != sizeof(struct save_pkt)) {
370 _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);
374 //context->root_node = new root_node_t(PLUGIN_PATH_PREFIX_BASE);
375 //context->current_node = context->root_node;
377 current_node = context->current_node;
378 retval = current_node->startBackupFile(context, sp);
379 if (retval == bRC_Seen)
381 } while (current_node != context->current_node);
382 _DebugMessage(100, "startBackupFile done - type = %d, fname = %s, retval = %d\n", sp->type, sp->fname, retval);
386 static bRC endBackupFile(bpContext *ctx)
389 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
390 node_t *current_node;
392 _DebugMessage(100, "endBackupFile\n");
395 current_node = context->current_node;
396 retval = current_node->endBackupFile(context);
397 } while (current_node != context->current_node);
398 _DebugMessage(100, "endBackupFile done - retval = %d\n", retval);
405 static bRC pluginIO(bpContext *ctx, struct io_pkt *io)
408 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
410 if (io->pkt_size != sizeof(struct io_pkt) || io->pkt_end != sizeof(struct io_pkt))
412 _JobMessage(M_FATAL, "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);
417 _DebugMessage(100, "IO_OPEN\n");
418 retval = context->current_node->pluginIoOpen(context, io);
421 //_DebugMessage(100, "IO_READ buf=%p len=%d\n", io->buf, io->count);
422 retval = context->current_node->pluginIoRead(context, io);
425 //_DebugMessage(100, "IO_WRITE buf=%p len=%d\n", io->buf, io->count);
426 retval = context->current_node->pluginIoWrite(context, io);
429 _DebugMessage(100, "IO_CLOSE\n");
430 retval = context->current_node->pluginIoClose(context, io);
436 static bRC startRestoreFile(bpContext *ctx, const char *cmd)
438 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
439 _DebugMessage(100, "startRestoreFile\n");
444 static bRC endRestoreFile(bpContext *ctx)
447 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
448 node_t *current_node;
450 _DebugMessage(100, "endRestoreFile\n");
453 current_node = context->current_node;
454 retval = current_node->endRestoreFile(context);
455 } while (current_node != context->current_node);
456 _DebugMessage(100, "endRestoreFile done - retval = %d\n", retval);
460 static bRC createFile(bpContext *ctx, struct restore_pkt *rp)
463 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
464 node_t *current_node;
470 _DebugMessage(100, "createFile - type = %d, ofname = %s\n", rp->type, rp->ofname);
471 if (rp->pkt_size != sizeof(struct restore_pkt) || rp->pkt_end != sizeof(struct restore_pkt))
473 _JobMessage(M_FATAL, "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);
477 for (i = 0; i < 6; i++)
479 context->path_bits[i] = NULL;
482 path_bits = splitString((char *)rp->ofname, '/', 7, &count);
484 _DebugMessage(100, "count = %d\n", count);
486 for (i = 1; i < count; i++)
488 _DebugMessage(150, "%d = '%s'\n", i, path_bits[i]);
489 context->path_bits[i - 1] = path_bits[i];
492 if (context->current_node == NULL)
494 context->root_node = new root_node_t(context->path_bits[0]);
495 context->current_node = context->root_node;
499 current_node = context->current_node;
500 retval = current_node->createFile(context, rp);
501 } while (current_node != context->current_node);
502 _DebugMessage(100, "createFile done - retval = %d\n", retval);
506 static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp)
508 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
509 _DebugMessage(100, "setFileAttributes\n");
514 * At the end of the job, the accurate code loops over all files
515 * that are in the accurate list but not marked as seen during the
516 * backup. Unless the checkFile routine returns bRC_Seen,
517 * these files look to be deleted and hence will not be
518 * returned during a restore.
520 static bRC checkFile(bpContext *ctx, char *fname)
522 exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
523 if (context->plugin_active) {
524 _DebugMessage(100, "marked as seen %s\n", fname);