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