]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/filed/plugins/exchange-fd.c
Restore win32 dir from Branch-5.2 and update it
[bacula/bacula] / bacula / src / win32 / filed / plugins / exchange-fd.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2018 Kern Sibbald
5
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.
8
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.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /* 
20  *  Written by James Harper, July 2010
21  *  
22  *  Used only in "old Exchange plugin" now deprecated.
23  */
24
25 #include "exchange-fd.h"
26
27 /* Pointers to Bacula functions */
28 bFuncs *bfuncs = NULL;
29 bInfo  *binfo = NULL;
30
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"
36
37 static pInfo pluginInfo = {
38    sizeof(pluginInfo),
39    FD_PLUGIN_INTERFACE_VERSION,
40    FD_PLUGIN_MAGIC,
41    PLUGIN_LICENSE,
42    PLUGIN_AUTHOR,
43    PLUGIN_DATE,
44    PLUGIN_VERSION,
45    PLUGIN_DESCRIPTION
46 };
47
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);
62
63 static pFuncs pluginFuncs = {
64    sizeof(pluginFuncs),
65    FD_PLUGIN_INTERFACE_VERSION,
66
67    /* Entry points into plugin */
68    newPlugin,          /* new plugin instance */
69    freePlugin,         /* free plugin instance */
70    getPluginValue,
71    setPluginValue,
72    handlePluginEvent,
73    startBackupFile,
74    endBackupFile,
75    startRestoreFile,
76    endRestoreFile,
77    pluginIO,
78    createFile,
79    setFileAttributes,
80    checkFile,
81    NULL                        /* No ACL/XATTR */
82 };
83
84 extern "C" {
85
86 static char **
87 splitString(char *string, char split, int maxParts, int *count)
88 {
89   char **RetVal;
90   char *first;
91   char *last;
92
93   //KdPrint((__DRIVER_NAME "     a\n"));
94
95   *count = 0;
96
97   RetVal = (char **)malloc((maxParts + 1) * sizeof(char *));
98   last = string;
99   do
100   {
101     if (*count == maxParts)
102       break;
103     first = last;
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;
108     (*count)++;
109     if (*last == split)
110       last++;
111   } while (*last != 0);
112   RetVal[*count] = NULL;
113   return RetVal;
114 }
115
116 bRC DLL_IMP_EXP
117 loadPlugin(bInfo *lbinfo, bFuncs *lbfuncs, pInfo **pinfo, pFuncs **pfuncs)
118 {
119    bRC retval;
120    bfuncs = lbfuncs;        /* set Bacula funct pointers */
121    binfo  = lbinfo;
122    *pinfo = &pluginInfo;
123    *pfuncs = &pluginFuncs;
124    retval = loadExchangeApi();
125    if (retval != bRC_OK) {
126       printf("Cannot load Exchange DLL\n");
127       return retval;
128    }
129    return retval;
130 }
131
132 bRC DLL_IMP_EXP
133 unloadPlugin()
134 {
135    return bRC_OK;
136 }
137
138 }
139 /*
140 void *
141 b_malloc(const char *file, int lone, size_t size)
142 {
143    return NULL;
144 }
145
146 void *
147 sm_malloc(const char *file, int lone, size_t size)
148 {
149    return NULL;
150 }
151 */
152
153 static bRC newPlugin(bpContext *ctx)
154 {
155    exchange_fd_context_t *context;
156    bRC retval = bRC_OK;
157    DWORD size;
158
159    int JobId = 0;
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];
171    /*
172    GetComputerNameW(context->computer_name, &size);
173    */
174    GetComputerNameExW(ComputerNameNetBIOS, context->computer_name, &size);
175    context->current_node = NULL;
176    context->root_node = NULL;
177    return retval;
178 }
179
180 static bRC freePlugin(bpContext *ctx)
181 {
182    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
183    int JobId = 0;
184    bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId);
185    _DebugMessage(100, "freePlugin JobId=%d\n", JobId);
186    delete context;
187    return bRC_OK;
188 }
189
190 static bRC getPluginValue(bpContext *ctx, pVariable var, void *value) 
191 {
192    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
193    _DebugMessage(100, "getPluginValue var=%d\n", var);
194    return bRC_OK;
195 }
196
197 static bRC setPluginValue(bpContext *ctx, pVariable var, void *value) 
198 {
199    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
200    _DebugMessage(100, "setPluginValue var=%d\n", var);
201    return bRC_OK;
202 }
203
204 static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value)
205 {
206    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
207    char *name;
208    int i, intval;
209    int accurate;
210    char *command;
211    char *plugin_name;
212
213    switch (event->eventType) {
214    case bEventJobStart:
215       _DebugMessage(0, "JobStart=%s\n", (char *)value);
216       context->plugin_active = false;
217       break;
218    case bEventJobEnd:
219       _DebugMessage(0, "JobEnd\n");
220       break;
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;
228       } else {
229          context->plugin_active = true;
230       }
231       free(command);
232       break;
233    case bEventStartBackupJob:
234       if (!context->plugin_active) {
235          break;
236       }
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) {
244       case 'F':
245          if (context->notrunconfull_option) {
246             context->truncate_logs = false;
247          } else {
248             context->truncate_logs = true;
249          }
250          break;
251       case 'D':
252          context->truncate_logs = false;
253          break;
254       case 'I':
255          context->truncate_logs = false;
256          break;
257       default:
258          _DebugMessage(0, "Invalid job level %c\n", context->job_level);
259          return bRC_Error;
260       }
261       break;
262    case bEventEndBackupJob:
263       _DebugMessage(0, "BackupEnd\n");
264       if (!context->plugin_active) {
265          break;
266       }
267       break;
268    case bEventLevel:
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;
273       break;
274    case bEventSince:
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;
279       break;
280    case bEventStartRestoreJob:
281       _DebugMessage(0, "StartRestoreJob\n");
282       context->job_type = JOB_TYPE_RESTORE;
283       context->plugin_active = true;
284       break;
285    case bEventEndRestoreJob:
286       if (!context->plugin_active) {
287          break;
288       }
289       _DebugMessage(0, "EndRestoreJob\n");
290       context->plugin_active = false;
291       break;
292    
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) {
297          break;
298       }
299       break;
300
301    case bEventBackupCommand:
302       if (!context->plugin_active) {
303          break;
304       }
305       {
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, ":");
311       char *option;
312       while ((option = strtok(NULL, ":")) != NULL) {
313          _DebugMessage(100, "option %s\n", option);
314          if (stricmp(option, "notrunconfull") == 0) {
315             context->notrunconfull_option = true;
316          } else {
317             _JobMessage(M_WARNING, "Unknown plugin option '%s'\n", option);
318          }
319       }
320       _DebugMessage(0, "name = %s\n", plugin_name);
321       _DebugMessage(0, "path = %s\n", path);
322       if (*path != '/') {
323          _JobMessage(M_FATAL, "Path does not begin with a '/'\n");
324          return bRC_Error;
325       }
326
327       for (i = 0; i < 6; i++) {
328          context->path_bits[i] = NULL;
329       }
330
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, "/");
336       }
337
338       if (i < 2 || i > 4) {
339          _JobMessage(M_FATAL, "Invalid plugin backup path\n");
340          return bRC_Error;
341       }
342       context->root_node = new root_node_t(context->path_bits[0]);
343       context->current_node = context->root_node;
344
345       }
346       break;
347
348    case bEventVssBeforeCloseRestore:
349       break;
350    case bEventComponentInfo:
351       break;
352
353    default:
354       _DebugMessage(0, "Ignored event=%d\n", event->eventType);
355       break;
356    }
357    bfuncs->getBaculaValue(ctx, bVarFDName, (void *)&name);
358    return bRC_OK;
359 }
360
361 static bRC
362 startBackupFile(bpContext *ctx, struct save_pkt *sp)
363 {
364    bRC retval;
365    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
366    node_t *current_node;
367
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);
371       return bRC_Error;
372    }
373
374    //context->root_node = new root_node_t(PLUGIN_PATH_PREFIX_BASE);
375    //context->current_node = context->root_node;
376    do {
377       current_node  = context->current_node;
378       retval = current_node->startBackupFile(context, sp);
379       if (retval == bRC_Seen)
380          endBackupFile(ctx);
381    } while (current_node != context->current_node);
382    _DebugMessage(100, "startBackupFile done - type = %d, fname = %s, retval = %d\n", sp->type, sp->fname, retval);
383    return retval;
384 }
385
386 static bRC endBackupFile(bpContext *ctx)
387
388    bRC retval;
389    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
390    node_t *current_node;
391
392    _DebugMessage(100, "endBackupFile\n");
393
394    do {
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);
399    return retval;
400 }
401
402 /*
403  * Do actual I/O
404  */
405 static bRC pluginIO(bpContext *ctx, struct io_pkt *io)
406 {
407    bRC retval = bRC_OK;
408    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
409
410    if (io->pkt_size != sizeof(struct io_pkt) || io->pkt_end != sizeof(struct io_pkt))
411    {
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);
413    }
414
415    switch(io->func) {
416    case IO_OPEN:
417       _DebugMessage(100, "IO_OPEN\n");
418       retval = context->current_node->pluginIoOpen(context, io);
419       break;
420    case IO_READ:
421       //_DebugMessage(100, "IO_READ buf=%p len=%d\n", io->buf, io->count);
422       retval = context->current_node->pluginIoRead(context, io);
423       break;
424    case IO_WRITE:
425       //_DebugMessage(100, "IO_WRITE buf=%p len=%d\n", io->buf, io->count);
426       retval = context->current_node->pluginIoWrite(context, io);
427       break;
428    case IO_CLOSE:
429       _DebugMessage(100, "IO_CLOSE\n");
430       retval = context->current_node->pluginIoClose(context, io);
431       break;
432    }
433    return retval;
434 }
435
436 static bRC startRestoreFile(bpContext *ctx, const char *cmd)
437 {
438    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
439    _DebugMessage(100, "startRestoreFile\n");
440
441    return bRC_OK;
442 }
443
444 static bRC endRestoreFile(bpContext *ctx)
445 {
446    bRC retval;
447    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
448    node_t *current_node;
449
450    _DebugMessage(100, "endRestoreFile\n");
451
452    do {
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);
457    return retval;
458 }
459
460 static bRC createFile(bpContext *ctx, struct restore_pkt *rp)
461 {
462    bRC retval;
463    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
464    node_t *current_node;
465    char **path_bits;
466    int count;
467    int i;
468
469
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))
472    {
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);
474       return bRC_Error;
475    }
476
477    for (i = 0; i < 6; i++)
478    {
479       context->path_bits[i] = NULL;
480    }
481
482    path_bits = splitString((char *)rp->ofname, '/', 7, &count);
483
484    _DebugMessage(100, "count = %d\n", count);
485
486    for (i = 1; i < count; i++)
487    {
488       _DebugMessage(150, "%d = '%s'\n", i, path_bits[i]);
489       context->path_bits[i - 1] = path_bits[i];
490    }
491
492    if (context->current_node == NULL)
493    {
494       context->root_node = new root_node_t(context->path_bits[0]);
495       context->current_node = context->root_node;
496    }
497
498    do {
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);
503    return retval;
504 }
505
506 static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp)
507 {
508    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
509    _DebugMessage(100, "setFileAttributes\n");
510    return bRC_OK;
511 }
512
513 /*
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. 
519  */
520 static bRC checkFile(bpContext *ctx, char *fname)
521 {
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);
525       return bRC_Seen;
526    }
527    return bRC_OK;
528 }