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