]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/filed/plugins/exchange-fd.c
Tweak add break to default
[bacula/bacula] / bacula / src / win32 / filed / plugins / exchange-fd.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2010-2011 Bacula Systems(R) SA
5
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 three of the GNU Affero General Public
10    License as published by the Free Software Foundation, which is 
11    listed in the file LICENSE.
12
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.
17
18    You should have received a copy of the GNU Affero 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
21    02110-1301, USA.
22
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.
27 */
28 /* 
29  *  Written by James Harper, October 2008
30  */
31
32 #include "exchange-fd.h"
33
34 /* Pointers to Bacula functions */
35 bFuncs *bfuncs = NULL;
36 bInfo  *binfo = NULL;
37
38 #define PLUGIN_LICENSE      "Bacula AGPLv3"
39 #define PLUGIN_AUTHOR       "James Harper"
40 #define PLUGIN_DATE    "September 2008"
41 #define PLUGIN_VERSION      "1"
42 #define PLUGIN_DESCRIPTION  "Exchange Plugin"
43
44 static pInfo pluginInfo = {
45    sizeof(pluginInfo),
46    FD_PLUGIN_INTERFACE_VERSION,
47    FD_PLUGIN_MAGIC,
48    PLUGIN_LICENSE,
49    PLUGIN_AUTHOR,
50    PLUGIN_DATE,
51    PLUGIN_VERSION,
52    PLUGIN_DESCRIPTION,
53 };
54
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);
68
69 static pFuncs pluginFuncs = {
70    sizeof(pluginFuncs),
71    FD_PLUGIN_INTERFACE_VERSION,
72
73    /* Entry points into plugin */
74    newPlugin,          /* new plugin instance */
75    freePlugin,         /* free plugin instance */
76    getPluginValue,
77    setPluginValue,
78    handlePluginEvent,
79    startBackupFile,
80    endBackupFile,
81    startRestoreFile,
82    endRestoreFile,
83    pluginIO,
84    createFile,
85    setFileAttributes
86 };
87
88 extern "C" {
89
90 static char **
91 splitString(char *string, char split, int maxParts, int *count)
92 {
93   char **RetVal;
94   char *first;
95   char *last;
96
97   //KdPrint((__DRIVER_NAME "     a\n"));
98
99   *count = 0;
100
101   RetVal = (char **)malloc((maxParts + 1) * sizeof(char *));
102   last = string;
103   do
104   {
105     if (*count == maxParts)
106       break;
107     first = last;
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;
112     (*count)++;
113     if (*last == split)
114       last++;
115   } while (*last != 0);
116   RetVal[*count] = NULL;
117   return RetVal;
118 }
119
120 bRC DLL_IMP_EXP
121 loadPlugin(bInfo *lbinfo, bFuncs *lbfuncs, pInfo **pinfo, pFuncs **pfuncs)
122 {
123    bRC retval;
124    bfuncs = lbfuncs;        /* set Bacula funct pointers */
125    binfo  = lbinfo;
126    *pinfo = &pluginInfo;
127    *pfuncs = &pluginFuncs;
128    retval = loadExchangeApi();
129    if (retval != bRC_OK) {
130       printf("Cannot load Exchange DLL\n");
131       return retval;
132    }
133    return retval;
134 }
135
136 bRC DLL_IMP_EXP
137 unloadPlugin()
138 {
139    return bRC_OK;
140 }
141
142 }
143 /*
144 void *
145 b_malloc(const char *file, int lone, size_t size)
146 {
147    return NULL;
148 }
149
150 void *
151 sm_malloc(const char *file, int lone, size_t size)
152 {
153    return NULL;
154 }
155 */
156
157 static bRC newPlugin(bpContext *ctx)
158 {
159    exchange_fd_context_t *context;
160    bRC retval = bRC_OK;
161    DWORD size;
162
163    int JobId = 0;
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    context->plugin_active = false;
170    bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId);
171    _DebugMessage(0, "newPlugin JobId=%d\n", JobId);
172    bfuncs->registerBaculaEvents(ctx, 1, 2, 0);
173    size = MAX_COMPUTERNAME_LENGTH + 1;
174    context->computer_name = new WCHAR[size];
175    /*
176    GetComputerNameW(context->computer_name, &size);
177    */
178    GetComputerNameExW(ComputerNameNetBIOS, context->computer_name, &size);
179    context->current_node = NULL;
180    context->root_node = NULL;
181    return retval;
182 }
183
184 static bRC freePlugin(bpContext *ctx)
185 {
186    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
187    int JobId = 0;
188    bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId);
189    _DebugMessage(100, "freePlugin JobId=%d\n", JobId);
190    delete context;
191    return bRC_OK;
192 }
193
194 static bRC getPluginValue(bpContext *ctx, pVariable var, void *value) 
195 {
196    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
197    _DebugMessage(100, "getPluginValue var=%d\n", var);
198    return bRC_OK;
199 }
200
201 static bRC setPluginValue(bpContext *ctx, pVariable var, void *value) 
202 {
203    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
204    _DebugMessage(100, "setPluginValue var=%d\n", var);
205    return bRC_OK;
206 }
207
208 static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value)
209 {
210    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
211    char *name;
212    int i, intval;
213    int accurate;
214    char *command;
215    char *plugin_name;
216
217    switch (event->eventType) {
218    case bEventJobStart:
219       _DebugMessage(0, "JobStart=%s\n", (char *)value);
220       context->plugin_active = false;
221       break;
222    case bEventJobEnd:
223       _DebugMessage(0, "JobEnd\n");
224       break;
225    case bEventPluginCommand:
226       _DebugMessage(0, "bEventPluginCommand %s\n", value);
227       command = bstrdup((char *)value);
228       /* this isn't really unused */
229       plugin_name = strtok((char *)command, ":");
230       if (strcmp(plugin_name, "exchange") != 0) {
231          context->plugin_active = false;
232       } else {
233          context->plugin_active = true;
234       }
235       free(command);
236       break;
237    case bEventStartBackupJob:
238       if (!context->plugin_active) {
239          break;
240       }
241       _DebugMessage(0, "BackupStart\n");
242       bfuncs->getBaculaValue(ctx, bVarAccurate, (void *)&accurate);
243       context->accurate = accurate;
244       context->job_type = JOB_TYPE_BACKUP;
245       // level should have been specified by now - check it
246       // if level is D or I, since should have been specified too
247       switch (context->job_level) {
248       case 'F':
249          if (context->notrunconfull_option) {
250             context->truncate_logs = false;
251          } else {
252             context->truncate_logs = true;
253          }
254          break;
255       case 'D':
256          context->truncate_logs = false;
257          break;
258       case 'I':
259          context->truncate_logs = false;
260          break;
261       default:
262          _DebugMessage(0, "Invalid job level %c\n", context->job_level);
263          return bRC_Error;
264       }
265       break;
266    case bEventEndBackupJob:
267       _DebugMessage(0, "BackupEnd\n");
268       if (!context->plugin_active) {
269          break;
270       }
271       break;
272    case bEventLevel:
273       if (!context->plugin_active) {
274          break;
275       }
276       intval = (intptr_t)value;
277       _DebugMessage(0, "JobLevel=%c %d\n", intval, intval);
278       context->job_level = intval;
279       break;
280    case bEventSince:
281       if (!context->plugin_active) {
282          break;
283       }
284       intval = (intptr_t)value;
285       _DebugMessage(0, "since=%d\n", intval);
286       context->job_since = (time_t)value;
287       break;
288    case bEventStartRestoreJob:
289       _DebugMessage(0, "StartRestoreJob\n");
290       context->job_type = JOB_TYPE_RESTORE;
291       context->plugin_active = true;
292       break;
293    case bEventEndRestoreJob:
294       if (!context->plugin_active) {
295          break;
296       }
297       _DebugMessage(0, "EndRestoreJob\n");
298       context->plugin_active = false;
299       break;
300    
301    /* Plugin command e.g. plugin = <plugin-name>:<name-space>:command */
302    case bEventRestoreCommand:
303       _DebugMessage(0, "restore\n"); // command=%s\n", (char *)value);
304       if (!context->plugin_active) {
305          break;
306       }
307       break;
308
309    case bEventBackupCommand:
310       if (!context->plugin_active) {
311          break;
312       }
313       {
314       _DebugMessage(0, "backup command=%s\n", (char *)value);    
315       char *command = new char[strlen((char *)value)];
316       strcpy(command, (char *)value);
317       char *plugin_name = strtok((char *)command, ":");
318       char *path = strtok(NULL, ":");
319       char *option;
320       while ((option = strtok(NULL, ":")) != NULL) {
321          _DebugMessage(100, "option %s\n", option);
322          if (stricmp(option, "notrunconfull") == 0) {
323             context->notrunconfull_option = true;
324          } else {
325             _JobMessage(M_WARNING, "Unknown plugin option '%s'\n", option);
326          }
327       }
328       _DebugMessage(0, "name = %s\n", plugin_name);
329       _DebugMessage(0, "path = %s\n", path);
330       if (*path != '/') {
331          _JobMessage(M_FATAL, "Path does not begin with a '/'\n");
332          return bRC_Error;
333       }
334
335       for (i = 0; i < 6; i++) {
336          context->path_bits[i] = NULL;
337       }
338
339       char *path_bit = strtok(path, "/");
340       for (i = 0; path_bit != NULL && i < 6; i++) {
341          context->path_bits[i] = new char[strlen(path_bit) + 1];
342          strcpy(context->path_bits[i], path_bit);
343          path_bit = strtok(NULL, "/");
344       }
345
346       if (i < 2 || i > 4) {
347          _JobMessage(M_FATAL, "Invalid plugin backup path\n");
348          return bRC_Error;
349       }
350       context->root_node = new root_node_t(context->path_bits[0]);
351       context->current_node = context->root_node;
352
353       }
354       break;
355
356    default:
357       _DebugMessage(0, "Ignored event=%d\n", event->eventType);
358       break;
359    }
360    bfuncs->getBaculaValue(ctx, bVarFDName, (void *)&name);
361    return bRC_OK;
362 }
363
364 static bRC
365 startBackupFile(bpContext *ctx, struct save_pkt *sp)
366 {
367    bRC retval;
368    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
369    node_t *current_node;
370
371    _DebugMessage(100, "startBackupFile, cmd = %s\n", sp->cmd);
372    if (sp->pkt_size != sizeof(struct save_pkt) || sp->pkt_end != sizeof(struct save_pkt)) {
373       _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       return bRC_Error;
375    }
376
377    //context->root_node = new root_node_t(PLUGIN_PATH_PREFIX_BASE);
378    //context->current_node = context->root_node;
379    do {
380       current_node  = context->current_node;
381       retval = current_node->startBackupFile(context, sp);
382       if (retval == bRC_Seen)
383          endBackupFile(ctx);
384    } while (current_node != context->current_node);
385    _DebugMessage(100, "startBackupFile done - type = %d, fname = %s, retval = %d\n", sp->type, sp->fname, retval);
386    return retval;
387 }
388
389 static bRC endBackupFile(bpContext *ctx)
390
391    bRC retval;
392    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
393    node_t *current_node;
394
395    _DebugMessage(100, "endBackupFile\n");
396
397    do {
398       current_node  = context->current_node;
399       retval = current_node->endBackupFile(context);
400    } while (current_node != context->current_node);
401    _DebugMessage(100, "endBackupFile done - retval = %d\n", retval);
402    return retval;
403 }
404
405 /*
406  * Do actual I/O
407  */
408 static bRC pluginIO(bpContext *ctx, struct io_pkt *io)
409 {
410    bRC retval = bRC_OK;
411    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
412
413    if (io->pkt_size != sizeof(struct io_pkt) || io->pkt_end != sizeof(struct io_pkt))
414    {
415       _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);
416    }
417
418    switch(io->func) {
419    case IO_OPEN:
420       _DebugMessage(100, "IO_OPEN\n");
421       retval = context->current_node->pluginIoOpen(context, io);
422       break;
423    case IO_READ:
424       //_DebugMessage(100, "IO_READ buf=%p len=%d\n", io->buf, io->count);
425       retval = context->current_node->pluginIoRead(context, io);
426       break;
427    case IO_WRITE:
428       //_DebugMessage(100, "IO_WRITE buf=%p len=%d\n", io->buf, io->count);
429       retval = context->current_node->pluginIoWrite(context, io);
430       break;
431    case IO_CLOSE:
432       _DebugMessage(100, "IO_CLOSE\n");
433       retval = context->current_node->pluginIoClose(context, io);
434       break;
435    }
436    return retval;
437 }
438
439 static bRC startRestoreFile(bpContext *ctx, const char *cmd)
440 {
441    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
442    _DebugMessage(100, "startRestoreFile\n");
443
444    return bRC_OK;
445 }
446
447 static bRC endRestoreFile(bpContext *ctx)
448 {
449    bRC retval;
450    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
451    node_t *current_node;
452
453    _DebugMessage(100, "endRestoreFile\n");
454
455    do {
456       current_node  = context->current_node;
457       retval = current_node->endRestoreFile(context);
458    } while (current_node != context->current_node);
459    _DebugMessage(100, "endRestoreFile done - retval = %d\n", retval);
460    return retval;
461 }
462
463 static bRC createFile(bpContext *ctx, struct restore_pkt *rp)
464 {
465    bRC retval;
466    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
467    node_t *current_node;
468    char **path_bits;
469    int count;
470    int i;
471
472
473    _DebugMessage(100, "createFile - type = %d, ofname = %s\n", rp->type, rp->ofname);
474    if (rp->pkt_size != sizeof(struct restore_pkt) || rp->pkt_end != sizeof(struct restore_pkt))
475    {
476       _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       return bRC_Error;
478    }
479
480    for (i = 0; i < 6; i++)
481    {
482       context->path_bits[i] = NULL;
483    }
484
485    path_bits = splitString((char *)rp->ofname, '/', 7, &count);
486
487    _DebugMessage(100, "count = %d\n", count);
488
489    for (i = 1; i < count; i++)
490    {
491       _DebugMessage(150, "%d = '%s'\n", i, path_bits[i]);
492       context->path_bits[i - 1] = path_bits[i];
493    }
494
495    if (context->current_node == NULL)
496    {
497       context->root_node = new root_node_t(context->path_bits[0]);
498       context->current_node = context->root_node;
499    }
500
501    do {
502       current_node  = context->current_node;
503       retval = current_node->createFile(context, rp);
504    } while (current_node != context->current_node);
505    _DebugMessage(100, "createFile done - retval = %d\n", retval);
506    return retval;
507 }
508
509 static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp)
510 {
511    exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
512    _DebugMessage(100, "setFileAttributes\n");
513    return bRC_OK;
514 }