]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/filed/plugins/exchange-fd.c
a2e3fa40609381bf7313ee9c40771476aa43fbce
[bacula/bacula] / bacula / src / win32 / filed / plugins / exchange-fd.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2008-2008 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      "GPL"
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 DLLEXPORT
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 DLLEXPORT
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 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         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;
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;
209
210         switch (event->eventType) {
211         case bEventJobStart:
212                 _DebugMessage(0, "JobStart=%s\n", (char *)value);
213                 break;
214         case bEventJobEnd:
215                 _DebugMessage(0, "JobEnd\n");
216                 break;
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)
223                 {
224                 case 'F':
225                         if (context->notrunconfull_option) {
226                                 context->truncate_logs = false;
227                         } else {
228                                 context->truncate_logs = true;
229                         }
230                         break;
231                 case 'D':
232                         context->truncate_logs = false;
233                         break;
234                 case 'I':
235                         context->truncate_logs = false;
236                         break;
237                 default:
238                         _DebugMessage(0, "Invalid job level %c\n", context->job_level);
239                         return bRC_Error;
240                 }
241                 break;
242         case bEventEndBackupJob:
243                 _DebugMessage(0, "BackupEnd\n");
244                 break;
245         case bEventLevel:
246                 _DebugMessage(0, "JobLevel=%c %d\n", (int)value, (int)value);
247                 context->job_level = (int)value;
248                 break;
249         case bEventSince:
250                 _DebugMessage(0, "since=%d\n", (int)value);
251                 context->job_since = (time_t)value;
252                 break;
253         case bEventStartRestoreJob:
254                 _DebugMessage(0, "StartRestoreJob\n");
255                 context->job_type = JOB_TYPE_RESTORE;
256                 break;
257         case bEventEndRestoreJob:
258                 _DebugMessage(0, "EndRestoreJob\n");
259                 break;
260         
261         /* Plugin command e.g. plugin = <plugin-name>:<name-space>:command */
262         case bEventRestoreCommand:
263                 _DebugMessage(0, "restore\n"); // command=%s\n", (char *)value);
264                 break;
265
266         case bEventBackupCommand:
267                 {
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, ":");
273                 char *option;
274                 while ((option = strtok(NULL, ":")) != NULL)
275                 {
276                         _DebugMessage(100, "option %s\n", option);
277                         if (stricmp(option, "notrunconfull") == 0)
278                         {
279                                 context->notrunconfull_option = true;
280                         }
281                         else
282                         {
283                                 _JobMessage(M_WARNING, "Unknown plugin option '%s'\n", option);
284                         }
285                 }
286                 _DebugMessage(0, "name = %s\n", plugin_name);
287                 _DebugMessage(0, "path = %s\n", path);
288                 if (*path != '/')
289                 {
290                         _JobMessage(M_ERROR, "Path does not begin with a '/'\n");
291                         return bRC_Error;
292                 }
293
294                 for (i = 0; i < 6; i++)
295                         context->path_bits[i] = NULL;
296
297                 char *path_bit = strtok(path, "/");
298                 for (i = 0; path_bit != NULL && i < 6; i++)
299                 {
300                         context->path_bits[i] = new char[strlen(path_bit) + 1];
301                         strcpy(context->path_bits[i], path_bit);
302                         path_bit = strtok(NULL, "/");
303                 }
304
305                 if (i < 2 || i > 4)
306                 {
307                         _JobMessage(M_ERROR, "Invalid plugin backup path\n");
308                         return bRC_Error;
309                 }
310                 context->root_node = new root_node_t(context->path_bits[0]);
311                 context->current_node = context->root_node;
312
313                 }
314                 break;
315
316    default:
317            _JobMessage(M_ERROR, "unknown event=%d\n", event->eventType);
318    }
319    bfuncs->getBaculaValue(ctx, bVarFDName, (void *)&name);
320    return bRC_OK;
321 }
322
323 static bRC
324 startBackupFile(bpContext *ctx, struct save_pkt *sp)
325 {
326         bRC retval;
327         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
328         node_t *current_node;
329
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))
332         {
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);
334                 return bRC_Error;
335         }
336
337         //context->root_node = new root_node_t(PLUGIN_PATH_PREFIX_BASE);
338         //context->current_node = context->root_node;
339         do {
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);
344         return retval;
345 }
346
347 static bRC endBackupFile(bpContext *ctx)
348
349         bRC retval;
350         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
351         node_t *current_node;
352
353         _DebugMessage(100, "endBackupFile\n");
354
355         do {
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);
360         return retval;
361 }
362
363 /*
364  * Do actual I/O
365  */
366 static bRC pluginIO(bpContext *ctx, struct io_pkt *io)
367 {
368         bRC retval = bRC_OK;
369         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
370
371         if (io->pkt_size != sizeof(struct io_pkt) || io->pkt_end != sizeof(struct io_pkt))
372         {
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);
374         }
375
376         switch(io->func) {
377         case IO_OPEN:
378                 _DebugMessage(100, "IO_OPEN\n");
379                 retval = context->current_node->pluginIoOpen(context, io);
380                 break;
381         case IO_READ:
382                 //_DebugMessage(100, "IO_READ buf=%p len=%d\n", io->buf, io->count);
383                 retval = context->current_node->pluginIoRead(context, io);
384                 break;
385         case IO_WRITE:
386                 //_DebugMessage(100, "IO_WRITE buf=%p len=%d\n", io->buf, io->count);
387                 retval = context->current_node->pluginIoWrite(context, io);
388                 break;
389         case IO_CLOSE:
390                 _DebugMessage(100, "IO_CLOSE\n");
391                 retval = context->current_node->pluginIoClose(context, io);
392                 break;
393         }
394         return retval;
395 }
396
397 static bRC startRestoreFile(bpContext *ctx, const char *cmd)
398 {
399         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
400         _DebugMessage(100, "startRestoreFile\n");
401
402         return bRC_OK;
403 }
404
405 static bRC endRestoreFile(bpContext *ctx)
406 {
407         bRC retval;
408         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
409         node_t *current_node;
410
411         _DebugMessage(100, "endRestoreFile\n");
412
413         do {
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);
418         return retval;
419 }
420
421 static bRC createFile(bpContext *ctx, struct restore_pkt *rp)
422 {
423         bRC retval;
424         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
425         node_t *current_node;
426         char **path_bits;
427         int count;
428         int i;
429
430
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))
433         {
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);
435         }
436
437         for (i = 0; i < 6; i++)
438         {
439                 context->path_bits[i] = NULL;
440         }
441
442         path_bits = splitString((char *)rp->ofname, '/', 7, &count);
443
444         _DebugMessage(100, "count = %d\n", count);
445
446         for (i = 1; i < count; i++)
447         {
448                 _DebugMessage(150, "%d = '%s'\n", i, path_bits[i]);
449                 context->path_bits[i - 1] = path_bits[i];
450         }
451
452         if (context->current_node == NULL)
453         {
454                 context->root_node = new root_node_t(context->path_bits[0]);
455                 context->current_node = context->root_node;
456         }
457
458         do {
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);
463         return retval;
464 }
465
466 static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp)
467 {
468         exchange_fd_context_t *context = (exchange_fd_context_t *)ctx->pContext;
469         _DebugMessage(100, "setFileAttributes\n");
470         return bRC_OK;
471 }