]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/filed/plugins/exchange-fd.c
Add checks on the plugin version and the plugin license. Currently
[bacula/bacula] / bacula / src / win32 / filed / plugins / exchange-fd.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2008-2009 Free Software Foundation Europe e.V.
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 two of the GNU 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 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 GPLv2"
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         {
131                 printf("Cannot load Exchange DLL\n");
132                 return retval;
133         }
134         return retval;
135 }
136
137 bRC DLL_IMP_EXP
138 unloadPlugin()
139 {
140         return bRC_OK;
141 }
142
143 }
144 /*
145 void *
146 b_malloc(const char *file, int lone, size_t size)
147 {
148         return NULL;
149 }
150
151 void *
152 sm_malloc(const char *file, int lone, size_t size)
153 {
154         return NULL;
155 }
156 */
157
158 static bRC newPlugin(bpContext *ctx)
159 {
160         exchange_fd_context_t *context;
161         bRC retval = bRC_OK;
162         DWORD size;
163
164         int JobId = 0;
165         ctx->pContext = new exchange_fd_context_t;
166         context = (exchange_fd_context_t *)ctx->pContext;
167         context->bpContext = ctx;
168         context->job_since = 0;
169         context->notrunconfull_option = 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         GetComputerNameW(context->computer_name, &size);
176         context->current_node = NULL;
177         context->root_node = NULL;
178         return retval;
179 }
180
181 static bRC freePlugin(bpContext *ctx)
182 {
183         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
184         int JobId = 0;
185         bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId);
186         _DebugMessage(100, "freePlugin JobId=%d\n", JobId);
187         delete context;
188         return bRC_OK;
189 }
190
191 static bRC getPluginValue(bpContext *ctx, pVariable var, void *value) 
192 {
193         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
194         _DebugMessage(100, "getPluginValue var=%d\n", var);
195         return bRC_OK;
196 }
197
198 static bRC setPluginValue(bpContext *ctx, pVariable var, void *value) 
199 {
200         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
201         _DebugMessage(100, "setPluginValue var=%d\n", var);
202         return bRC_OK;
203 }
204
205 static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value)
206 {
207         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
208         char *name;
209         int i, intval;
210
211         switch (event->eventType) {
212         case bEventJobStart:
213                 _DebugMessage(0, "JobStart=%s\n", (char *)value);
214                 break;
215         case bEventJobEnd:
216                 _DebugMessage(0, "JobEnd\n");
217                 break;
218         case bEventStartBackupJob:
219                 _DebugMessage(0, "BackupStart\n");
220                 context->job_type = JOB_TYPE_BACKUP;
221                 // level should have been specified by now - check it
222                 // if level is D or I, since should have been specified too
223                 switch (context->job_level)
224                 {
225                 case 'F':
226                         if (context->notrunconfull_option) {
227                                 context->truncate_logs = false;
228                         } else {
229                                 context->truncate_logs = true;
230                         }
231                         break;
232                 case 'D':
233                         context->truncate_logs = false;
234                         break;
235                 case 'I':
236                         context->truncate_logs = false;
237                         break;
238                 default:
239                         _DebugMessage(0, "Invalid job level %c\n", context->job_level);
240                         return bRC_Error;
241                 }
242                 break;
243         case bEventEndBackupJob:
244                 _DebugMessage(0, "BackupEnd\n");
245                 break;
246         case bEventLevel:
247                 intval = (intptr_t)value;
248                 _DebugMessage(0, "JobLevel=%c %d\n", intval, intval);
249                 context->job_level = intval;
250                 break;
251         case bEventSince:
252                 intval = (intptr_t)value;
253                 _DebugMessage(0, "since=%d\n", intval);
254                 context->job_since = (time_t)value;
255                 break;
256         case bEventStartRestoreJob:
257                 _DebugMessage(0, "StartRestoreJob\n");
258                 context->job_type = JOB_TYPE_RESTORE;
259                 break;
260         case bEventEndRestoreJob:
261                 _DebugMessage(0, "EndRestoreJob\n");
262                 break;
263         
264         /* Plugin command e.g. plugin = <plugin-name>:<name-space>:command */
265         case bEventRestoreCommand:
266                 _DebugMessage(0, "restore\n"); // command=%s\n", (char *)value);
267                 break;
268
269         case bEventBackupCommand:
270                 {
271                 _DebugMessage(0, "backup command=%s\n", (char *)value);         
272                 char *command = new char[strlen((char *)value)];
273                 strcpy(command, (char *)value);
274                 char *plugin_name = strtok((char *)command, ":");
275                 char *path = strtok(NULL, ":");
276                 char *option;
277                 while ((option = strtok(NULL, ":")) != NULL)
278                 {
279                         _DebugMessage(100, "option %s\n", option);
280                         if (stricmp(option, "notrunconfull") == 0)
281                         {
282                                 context->notrunconfull_option = true;
283                         }
284                         else
285                         {
286                                 _JobMessage(M_WARNING, "Unknown plugin option '%s'\n", option);
287                         }
288                 }
289                 _DebugMessage(0, "name = %s\n", plugin_name);
290                 _DebugMessage(0, "path = %s\n", path);
291                 if (*path != '/')
292                 {
293                         _JobMessage(M_ERROR, "Path does not begin with a '/'\n");
294                         return bRC_Error;
295                 }
296
297                 for (i = 0; i < 6; i++)
298                         context->path_bits[i] = NULL;
299
300                 char *path_bit = strtok(path, "/");
301                 for (i = 0; path_bit != NULL && i < 6; i++)
302                 {
303                         context->path_bits[i] = new char[strlen(path_bit) + 1];
304                         strcpy(context->path_bits[i], path_bit);
305                         path_bit = strtok(NULL, "/");
306                 }
307
308                 if (i < 2 || i > 4)
309                 {
310                         _JobMessage(M_ERROR, "Invalid plugin backup path\n");
311                         return bRC_Error;
312                 }
313                 context->root_node = new root_node_t(context->path_bits[0]);
314                 context->current_node = context->root_node;
315
316                 }
317                 break;
318
319    default:
320            _JobMessage(M_ERROR, "unknown event=%d\n", event->eventType);
321    }
322    bfuncs->getBaculaValue(ctx, bVarFDName, (void *)&name);
323    return bRC_OK;
324 }
325
326 static bRC
327 startBackupFile(bpContext *ctx, struct save_pkt *sp)
328 {
329         bRC retval;
330         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
331         node_t *current_node;
332
333         _DebugMessage(100, "startBackupFile, cmd = %s\n", sp->cmd);
334         if (sp->pkt_size != sizeof(struct save_pkt) || sp->pkt_end != sizeof(struct save_pkt))
335         {
336                 _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                 return bRC_Error;
338         }
339
340         //context->root_node = new root_node_t(PLUGIN_PATH_PREFIX_BASE);
341         //context->current_node = context->root_node;
342         do {
343                 current_node  = context->current_node;
344                 retval = current_node->startBackupFile(context, sp);
345         } while (current_node != context->current_node);
346         _DebugMessage(100, "startBackupFile done - type = %d, fname = %s, retval = %d\n", sp->type, sp->fname, retval);
347         return retval;
348 }
349
350 static bRC endBackupFile(bpContext *ctx)
351
352         bRC retval;
353         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
354         node_t *current_node;
355
356         _DebugMessage(100, "endBackupFile\n");
357
358         do {
359                 current_node  = context->current_node;
360                 retval = current_node->endBackupFile(context);
361         } while (current_node != context->current_node);
362         _DebugMessage(100, "endBackupFile done - retval = %d\n", retval);
363         return retval;
364 }
365
366 /*
367  * Do actual I/O
368  */
369 static bRC pluginIO(bpContext *ctx, struct io_pkt *io)
370 {
371         bRC retval = bRC_OK;
372         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
373
374         if (io->pkt_size != sizeof(struct io_pkt) || io->pkt_end != sizeof(struct io_pkt))
375         {
376                 _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);
377         }
378
379         switch(io->func) {
380         case IO_OPEN:
381                 _DebugMessage(100, "IO_OPEN\n");
382                 retval = context->current_node->pluginIoOpen(context, io);
383                 break;
384         case IO_READ:
385                 //_DebugMessage(100, "IO_READ buf=%p len=%d\n", io->buf, io->count);
386                 retval = context->current_node->pluginIoRead(context, io);
387                 break;
388         case IO_WRITE:
389                 //_DebugMessage(100, "IO_WRITE buf=%p len=%d\n", io->buf, io->count);
390                 retval = context->current_node->pluginIoWrite(context, io);
391                 break;
392         case IO_CLOSE:
393                 _DebugMessage(100, "IO_CLOSE\n");
394                 retval = context->current_node->pluginIoClose(context, io);
395                 break;
396         }
397         return retval;
398 }
399
400 static bRC startRestoreFile(bpContext *ctx, const char *cmd)
401 {
402         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
403         _DebugMessage(100, "startRestoreFile\n");
404
405         return bRC_OK;
406 }
407
408 static bRC endRestoreFile(bpContext *ctx)
409 {
410         bRC retval;
411         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
412         node_t *current_node;
413
414         _DebugMessage(100, "endRestoreFile\n");
415
416         do {
417                 current_node  = context->current_node;
418                 retval = current_node->endRestoreFile(context);
419         } while (current_node != context->current_node);
420         _DebugMessage(100, "endRestoreFile done - retval = %d\n", retval);
421         return retval;
422 }
423
424 static bRC createFile(bpContext *ctx, struct restore_pkt *rp)
425 {
426         bRC retval;
427         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
428         node_t *current_node;
429         char **path_bits;
430         int count;
431         int i;
432
433
434         _DebugMessage(100, "createFile - type = %d, ofname = %s\n", rp->type, rp->ofname);
435         if (rp->pkt_size != sizeof(struct restore_pkt) || rp->pkt_end != sizeof(struct restore_pkt))
436         {
437                 _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);
438         }
439
440         for (i = 0; i < 6; i++)
441         {
442                 context->path_bits[i] = NULL;
443         }
444
445         path_bits = splitString((char *)rp->ofname, '/', 7, &count);
446
447         _DebugMessage(100, "count = %d\n", count);
448
449         for (i = 1; i < count; i++)
450         {
451                 _DebugMessage(150, "%d = '%s'\n", i, path_bits[i]);
452                 context->path_bits[i - 1] = path_bits[i];
453         }
454
455         if (context->current_node == NULL)
456         {
457                 context->root_node = new root_node_t(context->path_bits[0]);
458                 context->current_node = context->root_node;
459         }
460
461         do {
462                 current_node  = context->current_node;
463                 retval = current_node->createFile(context, rp);
464         } while (current_node != context->current_node);
465         _DebugMessage(100, "createFile done - retval = %d\n", retval);
466         return retval;
467 }
468
469 static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp)
470 {
471         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
472         _DebugMessage(100, "setFileAttributes\n");
473         return bRC_OK;
474 }