]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/filed/plugins/alldrives-fd.c
Restore win32 dir from Branch-5.2 and update it
[bacula/bacula] / bacula / src / win32 / filed / plugins / alldrives-fd.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2018 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19
20 #ifndef BUILDING_DLL
21 # define BUILDING_DLL
22 #endif
23 #define BUILD_PLUGIN
24
25 #include "bacula.h"
26 #include "fd_plugins.h"
27 #include "lib/mem_pool.h"
28
29 /* from lib/scan.c */
30 extern int parse_args(POOLMEM *cmd, POOLMEM **args, int *argc,
31                       char **argk, char **argv, int max_args);
32 #define Dmsg(context, level, message, ...) bfuncs->DebugMessage(context, __FILE__, __LINE__, level, message, ##__VA_ARGS__)
33
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37
38 #define PLUGIN_LICENSE      "Bacula"
39 #define PLUGIN_AUTHOR       "Eric Bollengier"
40 #define PLUGIN_DATE         "Oct 2013"
41 #define PLUGIN_VERSION      "1.2"
42 #define PLUGIN_DESCRIPTION  "Select all local drives"
43
44 /* Forward referenced functions */
45 static bRC newPlugin(bpContext *ctx);
46 static bRC freePlugin(bpContext *ctx);
47 static bRC getPluginValue(bpContext *ctx, pVariable var, void *value);
48 static bRC setPluginValue(bpContext *ctx, pVariable var, void *value);
49 static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value);
50 static bRC startBackupFile(bpContext *ctx, struct save_pkt *sp);
51 static bRC endBackupFile(bpContext *ctx);
52 static bRC pluginIO(bpContext *ctx, struct io_pkt *io);
53 static bRC startRestoreFile(bpContext *ctx, const char *cmd);
54 static bRC endRestoreFile(bpContext *ctx);
55 static bRC createFile(bpContext *ctx, struct restore_pkt *rp);
56 static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp);
57
58
59 /* Pointers to Bacula functions */
60 static bFuncs *bfuncs = NULL;
61 static bInfo  *binfo = NULL;
62
63 static pInfo pluginInfo = {
64    sizeof(pluginInfo),
65    FD_PLUGIN_INTERFACE_VERSION,
66    FD_PLUGIN_MAGIC,
67    PLUGIN_LICENSE,
68    PLUGIN_AUTHOR,
69    PLUGIN_DATE,
70    PLUGIN_VERSION,
71    PLUGIN_DESCRIPTION
72 };
73
74 static pFuncs pluginFuncs = {
75    sizeof(pluginFuncs),
76    FD_PLUGIN_INTERFACE_VERSION,
77
78    /* Entry points into plugin */
79    newPlugin,                         /* new plugin instance */
80    freePlugin,                        /* free plugin instance */
81    getPluginValue,
82    setPluginValue,
83    handlePluginEvent,
84    startBackupFile,
85    endBackupFile,
86    startRestoreFile,
87    endRestoreFile,
88    pluginIO,
89    createFile,
90    setFileAttributes,
91    NULL,                        /* No checkFiles */
92    NULL                         /* No ACL/XATTR */
93 };
94
95 /*
96  * Plugin called here when it is first loaded
97  */
98 bRC DLL_IMP_EXP 
99 loadPlugin(bInfo *lbinfo, bFuncs *lbfuncs, pInfo **pinfo, pFuncs **pfuncs)
100 {
101    bfuncs = lbfuncs;                  /* set Bacula funct pointers */
102    binfo  = lbinfo;
103
104    *pinfo  = &pluginInfo;             /* return pointer to our info */
105    *pfuncs = &pluginFuncs;            /* return pointer to our functions */
106
107    return bRC_OK;
108 }
109
110 /*
111  * Plugin called here when it is unloaded, normally when
112  *  Bacula is going to exit.
113  */
114 bRC DLL_IMP_EXP
115 unloadPlugin() 
116 {
117    return bRC_OK;
118 }
119
120 #define get_self(ctx) ((barg *)ctx->pContext)
121
122 class barg {
123 public:
124    POOLMEM *args;
125    POOLMEM *cmd;
126    char *argk[MAX_CMD_ARGS];    /* Argument keywords */
127    char *argv[MAX_CMD_ARGS];    /* Argument values */
128    int argc;   
129    char *exclude;
130    bool snapshot_only;
131
132    barg() {
133       args = cmd = NULL;
134       exclude = NULL;
135       argc = 0;
136       snapshot_only = false;
137    }
138
139    ~barg() {
140       free_and_null_pool_memory(args);
141       free_and_null_pool_memory(cmd);
142    }
143
144    /*
145     * Given a single keyword, find it in the argument list, but
146     *   it must have a value
147     * Returns: -1 if not found or no value
148     *           list index (base 0) on success
149     */
150    int find_arg_with_value(const char *keyword)
151    {
152       for (int i=0; i<argc; i++) {
153          if (strcasecmp(keyword, argk[i]) == 0) {
154             if (argv[i]) {
155                return i;
156             } else {
157                return -1;
158             }
159          }
160       }
161       return -1;
162    }
163
164    /* parse command line
165     *  search for exclude="A,B,C,D"
166     *  populate this->exclude with simple string "ABCD"
167     */
168    void parse(char *command) {
169       char *p;
170       char *q;
171       if ((p = strchr(command, ':')) == NULL) {
172          Dmsg(NULL, 10, "No options\n");
173          return;
174       }
175
176       args = get_pool_memory(PM_FNAME);
177       cmd = get_pool_memory(PM_FNAME);
178       
179       pm_strcpy(cmd, ++p);      /* copy string after : */
180       parse_args(cmd, &args, &argc, argk, argv, MAX_CMD_ARGS);
181       
182       for (int i=0; i < argc ; i++) {
183          if (strcmp(argk[i], "exclude") == 0) {
184             /* a,B,C d => ABCD */
185             q = p = exclude = argv[i];
186             for (; *p ; p++) {
187                if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z')) {
188                   *q = toupper(*p);
189                   q++;
190                }
191             }
192             *q = 0;
193             Dmsg(NULL, 50, "%s => %s\n", command, exclude);
194
195          } else if (strcmp(argk[i], "snapshot") == 0) {
196             Dmsg(NULL, 50, "Doing only snapshot\n");
197             snapshot_only = true;
198
199          } else {
200             Dmsg(NULL, 10, "Unknown keyword %s\n", argk[i]);
201          }
202       }
203    }
204 };
205
206 /*
207  * Called here to make a new instance of the plugin -- i.e. when
208  *  a new Job is started.  There can be multiple instances of
209  *  each plugin that are running at the same time.  Your
210  *  plugin instance must be thread safe and keep its own
211  *  local data.
212  */
213 static bRC newPlugin(bpContext *ctx)
214 {
215    barg *self = new barg();
216    ctx->pContext = (void *)self;        /* set our context pointer */
217    return bRC_OK;
218 }
219
220 /*
221  * Release everything concerning a particular instance of a 
222  *  plugin. Normally called when the Job terminates.
223  */
224 static bRC freePlugin(bpContext *ctx)
225 {
226    barg *self = get_self(ctx);
227    if (self) {
228       delete self;
229    }
230    return bRC_OK;
231 }
232
233 /*
234  * Called by core code to get a variable from the plugin.
235  *   Not currently used.
236  */
237 static bRC getPluginValue(bpContext *ctx, pVariable var, void *value) 
238 {
239 // printf("plugin: getPluginValue var=%d\n", var);
240    return bRC_OK;
241 }
242
243 /* 
244  * Called by core code to set a plugin variable.
245  *  Not currently used.
246  */
247 static bRC setPluginValue(bpContext *ctx, pVariable var, void *value) 
248 {
249 // printf("plugin: setPluginValue var=%d\n", var);
250    return bRC_OK;
251 }
252
253 /* TODO: use findlib/drivetype instead */
254 static bool drivetype(const char *fname, char *dt, int dtlen)
255 {
256    CHAR rootpath[4];
257    UINT type;
258
259    /* Copy Drive Letter, colon, and backslash to rootpath */
260    bstrncpy(rootpath, fname, 3);
261    rootpath[3] = '\0';
262
263    type = GetDriveType(rootpath);
264
265    switch (type) {
266    case DRIVE_REMOVABLE:   bstrncpy(dt, "removable", dtlen);   return true;
267    case DRIVE_FIXED:       bstrncpy(dt, "fixed", dtlen);       return true;
268    case DRIVE_REMOTE:      bstrncpy(dt, "remote", dtlen);      return true;
269    case DRIVE_CDROM:       bstrncpy(dt, "cdrom", dtlen);       return true;
270    case DRIVE_RAMDISK:     bstrncpy(dt, "ramdisk", dtlen);     return true;
271    case DRIVE_UNKNOWN:
272    case DRIVE_NO_ROOT_DIR:
273    default:
274       return false;
275    }
276 }
277
278 static void add_drives(bpContext *ctx, char *cmd)
279 {
280    char buf[32];
281    char dt[100];
282    char drive;
283    barg *arg = get_self(ctx);
284    arg->parse(cmd);
285
286    if (arg->snapshot_only) {
287       return;
288    }
289
290    for (drive = 'A'; drive <= 'Z'; drive++) {
291       if (arg->exclude && strchr(arg->exclude, drive)) {
292          Dmsg(ctx, 10, "%c is in exclude list\n", drive);
293          continue;
294       }
295       snprintf(buf, sizeof(buf), "%c:/", drive);
296       if (drivetype(buf, dt, sizeof(dt))) {
297          if (strcmp(dt, "fixed") == 0) {
298             Dmsg(ctx, 10, "Adding %c to include list\n", drive);
299             bfuncs->AddInclude(ctx, buf);
300             snprintf(buf, sizeof(buf), "%c:/pagefile.sys", drive);
301             bfuncs->AddExclude(ctx, buf);
302             snprintf(buf, sizeof(buf), "%c:/System Volume Information", drive);
303             bfuncs->AddExclude(ctx, buf);
304          } else {
305             Dmsg(ctx, 10, "Discarding %c from include list\n", drive);
306          }
307       }
308    }
309 }
310
311 static void add_snapshot(bpContext *ctx, char *ret)
312 {
313    char  buf[32];
314    char  dt[100];
315    char  drive;
316    char *p = ret;
317    barg *arg = get_self(ctx);
318
319    /* Start from blank */
320    *p = 0;
321
322    if (!arg->snapshot_only) {
323       return;
324    }
325
326    for (drive = 'A'; drive <= 'Z'; drive++) {
327       if (arg->exclude && strchr(arg->exclude, drive)) {
328          Dmsg(ctx, 10, "%c is in exclude list\n", drive);
329          continue;
330       }
331       
332       snprintf(buf, sizeof(buf), "%c:/", drive);
333       
334       if (drivetype(buf, dt, sizeof(dt))) {
335          if (strcmp(dt, "fixed") == 0) {
336             Dmsg(ctx, 10, "Adding %c to snapshot list\n", drive);
337             *p++ = drive;
338          } else {
339             Dmsg(ctx, 10, "Discarding %c from snapshot list\n", drive);
340          }
341       }
342    }
343    *p = 0;
344    Dmsg(ctx, 10, "ret = %s\n", ret);
345 }
346
347 /*
348  * Called by Bacula when there are certain events that the
349  *   plugin might want to know.  The value depends on the
350  *   event.
351  */
352 static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value)
353 {
354    barg arguments;
355
356    switch (event->eventType) {
357    case bEventPluginCommand:
358       add_drives(ctx, (char *)value); /* command line */
359       break;
360
361    case bEventVssPrepareSnapshot:
362       add_snapshot(ctx, (char *)value); /* snapshot list */
363       break;
364    default:
365       break;
366    }
367    
368    return bRC_OK;
369 }
370
371 /*
372  * Called when starting to backup a file.  Here the plugin must
373  *  return the "stat" packet for the directory/file and provide
374  *  certain information so that Bacula knows what the file is.
375  *  The plugin can create "Virtual" files by giving them a
376  *  name that is not normally found on the file system.
377  */
378 static bRC startBackupFile(bpContext *ctx, struct save_pkt *sp)
379 {
380    return bRC_Stop;
381 }
382
383 /*
384  * Done backing up a file.
385  */
386 static bRC endBackupFile(bpContext *ctx)
387
388    return bRC_Stop;
389 }
390
391 /*
392  * Do actual I/O.  Bacula calls this after startBackupFile
393  *   or after startRestoreFile to do the actual file 
394  *   input or output.
395  */
396 static bRC pluginIO(bpContext *ctx, struct io_pkt *io)
397 {
398    io->status = 0;
399    io->io_errno = 0;
400    return bRC_Error;
401 }
402
403 static bRC startRestoreFile(bpContext *ctx, const char *cmd)
404 {
405    return bRC_Error;
406 }
407
408 static bRC endRestoreFile(bpContext *ctx)
409 {
410    return bRC_Error;
411 }
412
413 /*
414  * Called here to give the plugin the information needed to
415  *  re-create the file on a restore.  It basically gets the
416  *  stat packet that was created during the backup phase.
417  *  This data is what is needed to create the file, but does
418  *  not contain actual file data.
419  */
420 static bRC createFile(bpContext *ctx, struct restore_pkt *rp)
421 {
422    return bRC_Error;
423 }
424
425 /*
426  * Called after the file has been restored. This can be used to
427  *  set directory permissions, ...
428  */
429 static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp)
430 {
431    return bRC_Error;
432 }
433
434
435 #ifdef __cplusplus
436 }
437 #endif