1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2020-2020 Bareos GmbH & Co. KG
5
6 This program is Free Software; you can redistribute it and/or
7 modify it under the terms of version three of the GNU Affero General Public
8 License as published by the Free Software Foundation, which is
9 listed in the file LICENSE.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Affero General Public License for more details.
15
16 You should have received a copy of the GNU Affero General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA.
20 */
21 /**
22 * @file
23 * Python module for the Bareos filedaemon plugin
24 */
25 #define PY_SSIZE_T_CLEAN
26 #define BUILD_PLUGIN
27
28 #if defined(HAVE_WIN32)
29 # include "include/bareos.h"
30 # include <Python.h>
31 #else
32 # include <Python.h>
33 # include "include/bareos.h"
34 #endif
35
36 #include "include/version_hex.h"
37
38 #if PY_VERSION_HEX < VERSION_HEX(3, 0, 0)
39 # define LOGPREFIX "python-fd-mod: "
40 #else
41 # define LOGPREFIX "python3-fd-mod: "
42 #endif
43
44
45 #include "filed/fd_plugins.h"
46
47 #include "plugins/include/python3compat.h"
48
49 #define BAREOSFD_MODULE
50 #include "bareosfd.h"
51 #include "plugins/include/python3compat.h"
52 #include "lib/edit.h"
53
54 namespace filedaemon {
55
56 static const int debuglevel = 150;
57
58 static bRC set_bareos_core_functions(CoreFunctions* new_bareos_core_functions);
59 static bRC set_plugin_context(PluginContext* new_plugin_context);
60 static bRC PyParsePluginDefinition(PluginContext* plugin_ctx, void* value);
61
62 static bRC PyGetPluginValue(PluginContext* plugin_ctx,
63 pVariable var,
64 void* value);
65 static bRC PySetPluginValue(PluginContext* plugin_ctx,
66 pVariable var,
67 void* value);
68 static bRC PyHandlePluginEvent(PluginContext* plugin_ctx,
69 bEvent* event,
70 void* value);
71 static bRC PyStartBackupFile(PluginContext* plugin_ctx, struct save_pkt* sp);
72 static bRC PyEndBackupFile(PluginContext* plugin_ctx);
73 static bRC PyPluginIO(PluginContext* plugin_ctx, struct io_pkt* io);
74 static bRC PyStartRestoreFile(PluginContext* plugin_ctx, const char* cmd);
75 static bRC PyEndRestoreFile(PluginContext* plugin_ctx);
76 static bRC PyCreateFile(PluginContext* plugin_ctx, struct restore_pkt* rp);
77 static bRC PySetFileAttributes(PluginContext* plugin_ctx,
78 struct restore_pkt* rp);
79 static bRC PyCheckFile(PluginContext* plugin_ctx, char* fname);
80 static bRC PyGetAcl(PluginContext* plugin_ctx, acl_pkt* ap);
81 static bRC PySetAcl(PluginContext* plugin_ctx, acl_pkt* ap);
82 static bRC PyGetXattr(PluginContext* plugin_ctx, xattr_pkt* xp);
83 static bRC PySetXattr(PluginContext* plugin_ctx, xattr_pkt* xp);
84 static bRC PyRestoreObjectData(PluginContext* plugin_ctx,
85 struct restore_object_pkt* rop);
86 static bRC PyHandleBackupFile(PluginContext* plugin_ctx, struct save_pkt* sp);
87
88 /* Pointers to Bareos functions */
89 static CoreFunctions* bareos_core_functions = NULL;
90
91 #include "plugins/filed/python/plugin_private_context.h"
92
93 #define NOPLUGINSETGETVALUE 1
94 /* functions common to all plugins */
95 #include "plugins/include/python_plugins_common.inc"
96
97
98 /* set the bareos_core_functions pointer to the given value */
set_bareos_core_functions(CoreFunctions * new_bareos_core_functions)99 static bRC set_bareos_core_functions(CoreFunctions* new_bareos_core_functions)
100 {
101 bareos_core_functions = new_bareos_core_functions;
102 return bRC_OK;
103 }
104
105 /* set the plugin context pointer to the given value */
set_plugin_context(PluginContext * new_plugin_context)106 static bRC set_plugin_context(PluginContext* new_plugin_context)
107 {
108 plugin_context = new_plugin_context;
109 return bRC_OK;
110 }
111
112 /**
113 * Any plugin options which are passed in are dispatched here to a Python
114 * method and it can parse the plugin options. This function is also called
115 * after PyLoadModule() has loaded the Python module and made sure things are
116 * operational. Normally you would only get one set of plugin options but for
117 * a restore overrides can be passed in before the actual plugin options are
118 * restored as part of the restore stream handling.
119 */
PyParsePluginDefinition(PluginContext * plugin_ctx,void * value)120 static bRC PyParsePluginDefinition(PluginContext* plugin_ctx, void* value)
121 {
122 bRC retval = bRC_Error;
123 struct plugin_private_context* plugin_priv_ctx
124 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
125 PyObject* pFunc;
126
127 /*
128 * Lookup the parse_plugin_definition() function in the python module.
129 */
130 pFunc = PyDict_GetItemString(
131 plugin_priv_ctx->pyModuleFunctionsDict,
132 "parse_plugin_definition"); /* Borrowed reference */
133 if (pFunc && PyCallable_Check(pFunc)) {
134 PyObject *pPluginDefinition, *pRetVal;
135
136 pPluginDefinition = PyUnicode_FromString((char*)value);
137 if (!pPluginDefinition) { goto bail_out; }
138
139 pRetVal = PyObject_CallFunctionObjArgs(pFunc, pPluginDefinition, NULL);
140 Py_DECREF(pPluginDefinition);
141
142 if (!pRetVal) {
143 goto bail_out;
144 } else {
145 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
146 Py_DECREF(pRetVal);
147 }
148
149 return retval;
150 } else {
151 Dmsg(plugin_ctx, debuglevel,
152 LOGPREFIX
153 "Failed to find function named "
154 "parse_plugin_definition()\n");
155 return bRC_Error;
156 }
157
158 bail_out:
159 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
160
161 return retval;
162 }
163
PyGetPluginValue(PluginContext * plugin_ctx,pVariable var,void * value)164 static bRC PyGetPluginValue(PluginContext* plugin_ctx,
165 pVariable var,
166 void* value)
167 {
168 return bRC_OK;
169 }
170
PySetPluginValue(PluginContext * plugin_ctx,pVariable var,void * value)171 static bRC PySetPluginValue(PluginContext* plugin_ctx,
172 pVariable var,
173 void* value)
174 {
175 return bRC_OK;
176 }
177
PyHandlePluginEvent(PluginContext * plugin_ctx,bEvent * event,void * value)178 static bRC PyHandlePluginEvent(PluginContext* plugin_ctx,
179 bEvent* event,
180 void* value)
181 {
182 bRC retval = bRC_Error;
183 plugin_private_context* plugin_priv_ctx
184 = (plugin_private_context*)plugin_ctx->plugin_private_context;
185 PyObject* pFunc;
186
187 /*
188 * Lookup the handle_plugin_event() function in the python module.
189 */
190 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
191 "handle_plugin_event"); /* Borrowed reference */
192 if (pFunc && PyCallable_Check(pFunc)) {
193 PyObject *pEventType, *pRetVal;
194
195 pEventType = PyLong_FromLong(event->eventType);
196
197 pRetVal = PyObject_CallFunctionObjArgs(pFunc, pEventType, NULL);
198 Py_DECREF(pEventType);
199
200 if (!pRetVal) {
201 goto bail_out;
202 } else {
203 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
204 Py_DECREF(pRetVal);
205 }
206 } else {
207 Dmsg(plugin_ctx, debuglevel,
208 LOGPREFIX "Failed to find function named handle_plugin_event()\n");
209 }
210
211 return retval;
212
213 bail_out:
214 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
215
216 return retval;
217 }
218
NativeToPyStatPacket(struct stat * statp)219 static inline PyStatPacket* NativeToPyStatPacket(struct stat* statp)
220 {
221 PyStatPacket* pStatp = PyObject_New(PyStatPacket, &PyStatPacketType);
222
223 if (pStatp) {
224 pStatp->dev = statp->st_dev;
225 pStatp->ino = statp->st_ino;
226 pStatp->mode = statp->st_mode;
227 pStatp->nlink = statp->st_nlink;
228 pStatp->uid = statp->st_uid;
229 pStatp->gid = statp->st_gid;
230 pStatp->rdev = statp->st_rdev;
231 pStatp->size = statp->st_size;
232 pStatp->atime = statp->st_atime;
233 pStatp->mtime = statp->st_mtime;
234 pStatp->ctime = statp->st_ctime;
235 pStatp->blksize = statp->st_blksize;
236 pStatp->blocks = statp->st_blocks;
237 }
238
239 return pStatp;
240 }
241
PyStatPacketToNative(PyStatPacket * pStatp,struct stat * statp)242 static inline void PyStatPacketToNative(PyStatPacket* pStatp,
243 struct stat* statp)
244 {
245 statp->st_dev = pStatp->dev;
246 statp->st_ino = pStatp->ino;
247 statp->st_mode = pStatp->mode;
248 statp->st_nlink = pStatp->nlink;
249 statp->st_uid = pStatp->uid;
250 statp->st_gid = pStatp->gid;
251 statp->st_rdev = pStatp->rdev;
252 statp->st_size = pStatp->size;
253 statp->st_atime = pStatp->atime;
254 statp->st_mtime = pStatp->mtime;
255 statp->st_ctime = pStatp->ctime;
256 statp->st_blksize = pStatp->blksize;
257 statp->st_blocks = pStatp->blocks;
258 }
259
NativeToPySavePacket(struct save_pkt * sp)260 static inline PySavePacket* NativeToPySavePacket(struct save_pkt* sp)
261 {
262 PySavePacket* pSavePkt = PyObject_New(PySavePacket, &PySavePacketType);
263
264 if (pSavePkt) {
265 pSavePkt->fname = PyUnicode_FromString(sp->fname ? sp->fname : "");
266 pSavePkt->link = PyUnicode_FromString(sp->link ? sp->link : "");
267 if (sp->statp.st_mode) {
268 pSavePkt->statp = (PyObject*)NativeToPyStatPacket(&sp->statp);
269 } else {
270 pSavePkt->statp = NULL;
271 }
272
273 pSavePkt->type = sp->type;
274 pSavePkt->flags
275 = PyByteArray_FromStringAndSize(sp->flags, sizeof(sp->flags));
276 pSavePkt->no_read = sp->no_read;
277 pSavePkt->portable = sp->portable;
278 pSavePkt->accurate_found = sp->accurate_found;
279 pSavePkt->cmd = sp->cmd;
280 pSavePkt->save_time = sp->save_time;
281 pSavePkt->delta_seq = sp->delta_seq;
282 pSavePkt->object_name = NULL;
283 pSavePkt->object = NULL;
284 pSavePkt->object_len = sp->object_len;
285 pSavePkt->object_index = sp->index;
286 }
287
288 return pSavePkt;
289 } // namespace filedaemon
290
PySavePacketToNative(PySavePacket * pSavePkt,struct save_pkt * sp,struct plugin_private_context * plugin_priv_ctx,bool is_options_plugin)291 static inline bool PySavePacketToNative(
292 PySavePacket* pSavePkt,
293 struct save_pkt* sp,
294 struct plugin_private_context* plugin_priv_ctx,
295 bool is_options_plugin)
296 {
297 /*
298 * See if this is for an Options Plugin.
299 */
300 if (!is_options_plugin) {
301 /*
302 * Only copy back the arguments that are allowed to change.
303 */
304 if (pSavePkt->fname) {
305 /*
306 * As this has to linger as long as the backup is running we save it in
307 * our plugin context.
308 */
309 if (PyUnicode_Check(pSavePkt->fname)) {
310 if (plugin_priv_ctx->fname) { free(plugin_priv_ctx->fname); }
311 plugin_priv_ctx->fname = strdup(PyUnicode_AsUTF8(pSavePkt->fname));
312 sp->fname = plugin_priv_ctx->fname;
313 }
314 } else {
315 goto bail_out;
316 }
317
318 /*
319 * Optional field.
320 */
321 if (pSavePkt->link) {
322 /*
323 * As this has to linger as long as the backup is running we save it in
324 * our plugin context.
325 */
326 if (PyUnicode_Check(pSavePkt->link)) {
327 if (plugin_priv_ctx->link) { free(plugin_priv_ctx->link); }
328 plugin_priv_ctx->link = strdup(PyUnicode_AsUTF8(pSavePkt->link));
329 sp->link = plugin_priv_ctx->link;
330 }
331 }
332
333 /*
334 * Handle the stat structure.
335 */
336 if (pSavePkt->statp) {
337 PyStatPacketToNative((PyStatPacket*)pSavePkt->statp, &sp->statp);
338 } else {
339 goto bail_out;
340 }
341
342 sp->type = pSavePkt->type;
343
344 if (PyByteArray_Check(pSavePkt->flags)) {
345 char* flags;
346
347 if (PyByteArray_Size(pSavePkt->flags) != sizeof(sp->flags)) {
348 goto bail_out;
349 }
350
351 if ((flags = PyByteArray_AsString(pSavePkt->flags))) {
352 memcpy(sp->flags, flags, sizeof(sp->flags));
353 } else {
354 goto bail_out;
355 }
356 } else {
357 goto bail_out;
358 }
359
360 /*
361 * Special code for handling restore objects.
362 */
363 if (IS_FT_OBJECT(sp->type)) {
364 /*
365 * See if a proper restore object was created.
366 */
367 if (pSavePkt->object_len > 0) {
368 /*
369 * As this has to linger as long as the backup is running we save it
370 * in our plugin context.
371 */
372 if (pSavePkt->object_name && pSavePkt->object
373 && PyUnicode_Check(pSavePkt->object_name)
374 && PyByteArray_Check(pSavePkt->object)) {
375 char* buf;
376
377 if (plugin_priv_ctx->object_name) {
378 free(plugin_priv_ctx->object_name);
379 }
380 plugin_priv_ctx->object_name
381 = strdup(PyUnicode_AsUTF8(pSavePkt->object_name));
382 sp->object_name = plugin_priv_ctx->object_name;
383
384 sp->object_len = pSavePkt->object_len;
385 sp->index = pSavePkt->object_index;
386
387 if ((buf = PyByteArray_AsString(pSavePkt->object))) {
388 if (plugin_priv_ctx->object) { free(plugin_priv_ctx->object); }
389 plugin_priv_ctx->object = (char*)malloc(pSavePkt->object_len);
390 memcpy(plugin_priv_ctx->object, buf, pSavePkt->object_len);
391 sp->object = plugin_priv_ctx->object;
392 } else {
393 goto bail_out;
394 }
395 } else {
396 goto bail_out;
397 }
398 } else {
399 goto bail_out;
400 }
401 } else {
402 sp->no_read = pSavePkt->no_read;
403 sp->delta_seq = pSavePkt->delta_seq;
404 }
405 } else {
406 sp->no_read = pSavePkt->no_read;
407 sp->delta_seq = pSavePkt->delta_seq;
408
409 if (PyByteArray_Check(pSavePkt->flags)) {
410 char* flags;
411
412 if (PyByteArray_Size(pSavePkt->flags) != sizeof(sp->flags)) {
413 goto bail_out;
414 }
415
416 if ((flags = PyByteArray_AsString(pSavePkt->flags))) {
417 memcpy(sp->flags, flags, sizeof(sp->flags));
418 } else {
419 goto bail_out;
420 }
421 } else {
422 goto bail_out;
423 }
424 }
425
426 return true;
427
428 bail_out:
429 return false;
430 }
431
432 /**
433 * Called when starting to backup a file. Here the plugin must
434 * return the "stat" packet for the directory/file and provide
435 * certain information so that Bareos knows what the file is.
436 * The plugin can create "Virtual" files by giving them a
437 * name that is not normally found on the file system.
438 */
PyStartBackupFile(PluginContext * plugin_ctx,struct save_pkt * sp)439 static bRC PyStartBackupFile(PluginContext* plugin_ctx, struct save_pkt* sp)
440 {
441 bRC retval = bRC_Error;
442 struct plugin_private_context* plugin_priv_ctx
443 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
444 PyObject* pFunc;
445
446 /*
447 * Lookup the start_backup_file() function in the python module.
448 */
449 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
450 "start_backup_file"); /* Borrowed reference */
451 if (pFunc && PyCallable_Check(pFunc)) {
452 PySavePacket* pSavePkt;
453 PyObject* pRetVal;
454
455 pSavePkt = NativeToPySavePacket(sp);
456 if (!pSavePkt) { goto bail_out; }
457
458 pRetVal = PyObject_CallFunctionObjArgs(pFunc, (PyObject*)pSavePkt, NULL);
459 if (!pRetVal) {
460 Py_DECREF((PyObject*)pSavePkt);
461 goto bail_out;
462 } else {
463 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
464 Py_DECREF(pRetVal);
465
466 if (!PySavePacketToNative(pSavePkt, sp, plugin_priv_ctx, false)) {
467 Py_DECREF((PyObject*)pSavePkt);
468 goto bail_out;
469 }
470 Py_DECREF((PyObject*)pSavePkt);
471 }
472 } else {
473 Dmsg(plugin_ctx, debuglevel,
474 LOGPREFIX "Failed to find function named start_backup_file()\n");
475 }
476
477 return retval;
478
479 bail_out:
480 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
481
482 return retval;
483 }
484
485 /**
486 * Called at the end of backing up a file for a command plugin.
487 * If the plugin's work is done, it should return bRC_OK.
488 * If the plugin wishes to create another file and back it up,
489 * then it must return bRC_More (not yet implemented).
490 */
PyEndBackupFile(PluginContext * plugin_ctx)491 static bRC PyEndBackupFile(PluginContext* plugin_ctx)
492 {
493 bRC retval = bRC_Error;
494 struct plugin_private_context* plugin_priv_ctx
495 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
496 PyObject* pFunc;
497
498 /*
499 * Lookup the end_backup_file() function in the python module.
500 */
501 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
502 "end_backup_file"); /* Borrowed reference */
503 if (pFunc && PyCallable_Check(pFunc)) {
504 PyObject* pRetVal;
505
506 pRetVal = PyObject_CallFunctionObjArgs(pFunc, NULL);
507 if (!pRetVal) {
508 goto bail_out;
509 } else {
510 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
511 }
512 } else {
513 Dmsg(plugin_ctx, debuglevel,
514 LOGPREFIX "Failed to find function named end_backup_file()\n");
515 }
516
517 return retval;
518
519 bail_out:
520 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
521
522 return retval;
523 }
524
NativeToPyIoPacket(struct io_pkt * io)525 static inline PyIoPacket* NativeToPyIoPacket(struct io_pkt* io)
526 {
527 PyIoPacket* pIoPkt = PyObject_New(PyIoPacket, &PyIoPacketType);
528
529 if (pIoPkt) {
530 /*
531 * Initialize the Python IoPkt with the data we got passed in.
532 */
533 pIoPkt->func = io->func;
534 pIoPkt->count = io->count;
535 pIoPkt->flags = io->flags;
536 pIoPkt->mode = io->mode;
537 pIoPkt->fname = io->fname;
538 pIoPkt->whence = io->whence;
539 pIoPkt->offset = io->offset;
540 if (io->func == IO_WRITE && io->count > 0) {
541 /*
542 * Only initialize the buffer with read data when we are writing and
543 * there is data.
544 */
545 pIoPkt->buf = PyByteArray_FromStringAndSize(io->buf, io->count);
546 if (!pIoPkt->buf) {
547 Py_DECREF((PyObject*)pIoPkt);
548 return (PyIoPacket*)NULL;
549 }
550 } else {
551 pIoPkt->buf = NULL;
552 }
553
554 /*
555 * These must be set by the Python function but we initialize them to zero
556 * to be sure they have some valid setting an not random data.
557 */
558 pIoPkt->io_errno = 0;
559 pIoPkt->lerror = 0;
560 pIoPkt->win32 = false;
561 pIoPkt->status = 0;
562 }
563
564 return pIoPkt;
565 }
566
PyIoPacketToNative(PyIoPacket * pIoPkt,struct io_pkt * io)567 static inline bool PyIoPacketToNative(PyIoPacket* pIoPkt, struct io_pkt* io)
568 {
569 /*
570 * Only copy back the arguments that are allowed to change.
571 */
572 io->io_errno = pIoPkt->io_errno;
573 io->lerror = pIoPkt->lerror;
574 io->win32 = pIoPkt->win32;
575 io->status = pIoPkt->status;
576 if (io->func == IO_READ && io->status > 0) {
577 /*
578 * Only copy back the data when doing a read and there is data.
579 */
580 if (PyByteArray_Check(pIoPkt->buf)) {
581 char* buf;
582
583 if (PyByteArray_Size(pIoPkt->buf) > io->count || io->status > io->count) {
584 return false;
585 }
586
587 if (!(buf = PyByteArray_AsString(pIoPkt->buf))) { return false; }
588 memcpy(io->buf, buf, io->status);
589 }
590 }
591
592 return true;
593 }
594
595 /**
596 * Do actual I/O. Bareos calls this after startBackupFile
597 * or after startRestoreFile to do the actual file
598 * input or output.
599 */
PyPluginIO(PluginContext * plugin_ctx,struct io_pkt * io)600 static bRC PyPluginIO(PluginContext* plugin_ctx, struct io_pkt* io)
601 {
602 bRC retval = bRC_Error;
603 struct plugin_private_context* plugin_priv_ctx
604 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
605 PyObject* pFunc;
606
607 /*
608 * Lookup the plugin_io() function in the python module.
609 */
610 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
611 "plugin_io"); /* Borrowed reference */
612 if (pFunc && PyCallable_Check(pFunc)) {
613 PyIoPacket* pIoPkt;
614 PyObject* pRetVal;
615
616 pIoPkt = NativeToPyIoPacket(io);
617 if (!pIoPkt) { goto bail_out; }
618
619 pRetVal = PyObject_CallFunctionObjArgs(pFunc, (PyObject*)pIoPkt, NULL);
620 if (!pRetVal) {
621 Py_DECREF((PyObject*)pIoPkt);
622 goto bail_out;
623 } else {
624 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
625 Py_DECREF(pRetVal);
626
627 if (!PyIoPacketToNative(pIoPkt, io)) {
628 Py_DECREF((PyObject*)pIoPkt);
629 goto bail_out;
630 }
631 }
632 Py_DECREF((PyObject*)pIoPkt);
633 } else {
634 Dmsg(plugin_ctx, debuglevel,
635 LOGPREFIX "Failed to find function named plugin_io()\n");
636 }
637
638 return retval;
639
640 bail_out:
641 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
642
643 io->status = -1;
644
645 return retval;
646 }
647
648 /**
649 * Called when the first record is read from the Volume that was previously
650 * written by the command plugin.
651 */
PyStartRestoreFile(PluginContext * plugin_ctx,const char * cmd)652 static bRC PyStartRestoreFile(PluginContext* plugin_ctx, const char* cmd)
653 {
654 bRC retval = bRC_Error;
655 struct plugin_private_context* plugin_priv_ctx
656 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
657 PyObject* pFunc;
658
659 /*
660 * Lookup the start_restore_file() function in the python module.
661 */
662 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
663 "start_restore_file"); /* Borrowed reference */
664 if (pFunc && PyCallable_Check(pFunc)) {
665 PyObject *pCmd, *pRetVal;
666
667 pCmd = PyUnicode_FromString(cmd);
668 if (!pCmd) { goto bail_out; }
669
670 pRetVal = PyObject_CallFunctionObjArgs(pFunc, pCmd, NULL);
671 Py_DECREF(pCmd);
672
673 if (!pRetVal) {
674 goto bail_out;
675 } else {
676 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
677 Py_DECREF(pRetVal);
678 }
679 } else {
680 Dmsg(plugin_ctx, debuglevel,
681 LOGPREFIX "Failed to find function named start_restore_file()\n");
682 }
683
684 return retval;
685
686 bail_out:
687 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
688
689 return retval;
690 }
691
692 /**
693 * Called when a command plugin is done restoring a file.
694 */
PyEndRestoreFile(PluginContext * plugin_ctx)695 static bRC PyEndRestoreFile(PluginContext* plugin_ctx)
696 {
697 bRC retval = bRC_Error;
698 struct plugin_private_context* plugin_priv_ctx
699 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
700 PyObject* pFunc;
701
702 /*
703 * Lookup the end_restore_file() function in the python module.
704 */
705 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
706 "end_restore_file"); /* Borrowed reference */
707 if (pFunc && PyCallable_Check(pFunc)) {
708 PyObject* pRetVal;
709
710 pRetVal = PyObject_CallFunctionObjArgs(pFunc, NULL);
711 if (!pRetVal) {
712 goto bail_out;
713 } else {
714 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
715 }
716 } else {
717 Dmsg(plugin_ctx, debuglevel,
718 LOGPREFIX "Failed to find function named end_restore_file()\n");
719 }
720
721 return retval;
722
723 bail_out:
724 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
725
726 return retval;
727 }
728
NativeToPyRestorePacket(struct restore_pkt * rp)729 static inline PyRestorePacket* NativeToPyRestorePacket(struct restore_pkt* rp)
730 {
731 PyRestorePacket* pRestorePacket
732 = PyObject_New(PyRestorePacket, &PyRestorePacketType);
733
734 if (pRestorePacket) {
735 pRestorePacket->stream = rp->stream;
736 pRestorePacket->data_stream = rp->data_stream;
737 pRestorePacket->type = rp->type;
738 pRestorePacket->file_index = rp->file_index;
739 pRestorePacket->LinkFI = rp->LinkFI;
740 pRestorePacket->uid = rp->uid;
741 pRestorePacket->statp = (PyObject*)NativeToPyStatPacket(&rp->statp);
742 pRestorePacket->attrEx = rp->attrEx;
743 pRestorePacket->ofname = rp->ofname;
744 pRestorePacket->olname = rp->olname;
745 pRestorePacket->where = rp->where;
746 pRestorePacket->RegexWhere = rp->RegexWhere;
747 pRestorePacket->replace = rp->replace;
748 pRestorePacket->create_status = rp->create_status;
749 }
750
751 return pRestorePacket;
752 }
753
PyRestorePacketToNative(PyRestorePacket * pRestorePacket,struct restore_pkt * rp)754 static inline void PyRestorePacketToNative(PyRestorePacket* pRestorePacket,
755 struct restore_pkt* rp)
756 {
757 /*
758 * Only copy back the fields that are allowed to be changed.
759 */
760 rp->create_status = pRestorePacket->create_status;
761 }
762
763 /**
764 * Called for a command plugin to create a file during a Restore job before
765 * restoring the data. This entry point is called before any I/O is done on
766 * the file. After this call, Bareos will call pluginIO() to open the file for
767 * write.
768 *
769 * We must return in rp->create_status:
770 *
771 * CF_ERROR -- error
772 * CF_SKIP -- skip processing this file
773 * CF_EXTRACT -- extract the file (i.e.call i/o routines)
774 * CF_CREATED -- created, but no content to extract (typically directories)
775 */
PyCreateFile(PluginContext * plugin_ctx,struct restore_pkt * rp)776 static bRC PyCreateFile(PluginContext* plugin_ctx, struct restore_pkt* rp)
777 {
778 bRC retval = bRC_Error;
779 struct plugin_private_context* plugin_priv_ctx
780 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
781 PyObject* pFunc;
782
783 if (!rp) { return bRC_Error; }
784
785 /*
786 * Lookup the create_file() function in the python module.
787 */
788 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
789 "create_file"); /* Borrowed reference */
790 if (pFunc && PyCallable_Check(pFunc)) {
791 PyRestorePacket* pRestorePacket;
792 PyObject* pRetVal;
793
794 pRestorePacket = NativeToPyRestorePacket(rp);
795 if (!pRestorePacket) { goto bail_out; }
796
797 pRetVal = PyObject_CallFunctionObjArgs(pFunc, pRestorePacket, NULL);
798 if (!pRetVal) {
799 Py_DECREF(pRestorePacket);
800 goto bail_out;
801 } else {
802 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
803 Py_DECREF(pRetVal);
804
805 PyRestorePacketToNative(pRestorePacket, rp);
806 Py_DECREF(pRestorePacket);
807 }
808 } else {
809 Dmsg(plugin_ctx, debuglevel,
810 LOGPREFIX "Failed to find function named create_file()\n");
811 }
812
813 return retval;
814
815 bail_out:
816 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
817
818 return retval;
819 }
820
PySetFileAttributes(PluginContext * plugin_ctx,struct restore_pkt * rp)821 static bRC PySetFileAttributes(PluginContext* plugin_ctx,
822 struct restore_pkt* rp)
823 {
824 bRC retval = bRC_Error;
825 struct plugin_private_context* plugin_priv_ctx
826 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
827 PyObject* pFunc;
828
829 if (!rp) { return bRC_Error; }
830
831 /*
832 * Lookup the set_file_attributes() function in the python module.
833 */
834 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
835 "set_file_attributes"); /* Borrowed reference */
836 if (pFunc && PyCallable_Check(pFunc)) {
837 PyRestorePacket* pRestorePacket;
838 PyObject* pRetVal;
839
840 pRestorePacket = NativeToPyRestorePacket(rp);
841 if (!pRestorePacket) { goto bail_out; }
842
843 pRetVal = PyObject_CallFunctionObjArgs(pFunc, pRestorePacket, NULL);
844 if (!pRetVal) {
845 Py_DECREF(pRestorePacket);
846 goto bail_out;
847 } else {
848 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
849 Py_DECREF(pRetVal);
850 Py_DECREF(pRestorePacket);
851 }
852 } else {
853 Dmsg(plugin_ctx, debuglevel,
854 LOGPREFIX "Failed to find function named set_file_attributes()\n");
855 }
856
857 return retval;
858
859 bail_out:
860 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
861
862 return retval;
863 }
864
PyCheckFile(PluginContext * plugin_ctx,char * fname)865 static bRC PyCheckFile(PluginContext* plugin_ctx, char* fname)
866 {
867 bRC retval = bRC_Error;
868 struct plugin_private_context* plugin_priv_ctx
869 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
870 PyObject* pFunc;
871
872 if (!fname) { return bRC_Error; }
873
874 /*
875 * Lookup the check_file() function in the python module.
876 */
877 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
878 "check_file"); /* Borrowed reference */
879 if (pFunc && PyCallable_Check(pFunc)) {
880 PyObject *pFname, *pRetVal;
881
882 pFname = PyUnicode_FromString(fname);
883 pRetVal = PyObject_CallFunctionObjArgs(pFunc, pFname, NULL);
884 Py_DECREF(pFname);
885
886 if (!pRetVal) {
887 goto bail_out;
888 } else {
889 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
890 Py_DECREF(pRetVal);
891 }
892 } else {
893 Dmsg(plugin_ctx, debuglevel,
894 LOGPREFIX "Failed to find function named check_file()\n");
895 }
896
897 return retval;
898
899 bail_out:
900 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
901
902 return retval;
903 }
904
NativeToPyAclPacket(struct acl_pkt * ap)905 static inline PyAclPacket* NativeToPyAclPacket(struct acl_pkt* ap)
906 {
907 PyAclPacket* pAclPacket = PyObject_New(PyAclPacket, &PyAclPacketType);
908
909 if (pAclPacket) {
910 pAclPacket->fname = ap->fname;
911
912 if (ap->content_length && ap->content) {
913 pAclPacket->content
914 = PyByteArray_FromStringAndSize(ap->content, ap->content_length);
915 } else {
916 pAclPacket->content = NULL;
917 }
918 }
919
920 return pAclPacket;
921 }
922
PyAclPacketToNative(PyAclPacket * pAclPacket,struct acl_pkt * ap)923 static inline bool PyAclPacketToNative(PyAclPacket* pAclPacket,
924 struct acl_pkt* ap)
925 {
926 if (!pAclPacket->content) { return true; }
927
928 if (PyByteArray_Check(pAclPacket->content)) {
929 char* buf;
930
931 ap->content_length = PyByteArray_Size(pAclPacket->content);
932 if (ap->content_length <= 0
933 || !(buf = PyByteArray_AsString(pAclPacket->content))) {
934 return false;
935 }
936
937 if (ap->content) { free(ap->content); }
938 ap->content = (char*)malloc(ap->content_length);
939 memcpy(ap->content, buf, ap->content_length);
940 }
941
942 return true;
943 }
944
PyGetAcl(PluginContext * plugin_ctx,acl_pkt * ap)945 static bRC PyGetAcl(PluginContext* plugin_ctx, acl_pkt* ap)
946 {
947 bRC retval = bRC_Error;
948 struct plugin_private_context* plugin_priv_ctx
949 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
950 PyObject* pFunc;
951
952 if (!ap) { return bRC_Error; }
953
954 /*
955 * Lookup the get_acl() function in the python module.
956 */
957 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
958 "get_acl"); /* Borrowed reference */
959 if (pFunc && PyCallable_Check(pFunc)) {
960 PyAclPacket* pAclPkt;
961 PyObject* pRetVal;
962
963 pAclPkt = NativeToPyAclPacket(ap);
964 if (!pAclPkt) { goto bail_out; }
965
966 pRetVal = PyObject_CallFunctionObjArgs(pFunc, pAclPkt, NULL);
967 if (!pRetVal) {
968 Py_DECREF((PyObject*)pAclPkt);
969 goto bail_out;
970 } else {
971 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
972 Py_DECREF(pRetVal);
973
974 if (!PyAclPacketToNative(pAclPkt, ap)) {
975 Py_DECREF((PyObject*)pAclPkt);
976 goto bail_out;
977 }
978 Py_DECREF(pAclPkt);
979 }
980 } else {
981 Dmsg(plugin_ctx, debuglevel,
982 LOGPREFIX "Failed to find function named get_acl()\n");
983 }
984
985 return retval;
986
987 bail_out:
988 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
989
990 return retval;
991 }
992
PySetAcl(PluginContext * plugin_ctx,acl_pkt * ap)993 static bRC PySetAcl(PluginContext* plugin_ctx, acl_pkt* ap)
994 {
995 bRC retval = bRC_Error;
996 struct plugin_private_context* plugin_priv_ctx
997 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
998 PyObject* pFunc;
999
1000 if (!ap) { return bRC_Error; }
1001
1002 /*
1003 * Lookup the set_acl() function in the python module.
1004 */
1005 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
1006 "set_acl"); /* Borrowed reference */
1007 if (pFunc && PyCallable_Check(pFunc)) {
1008 PyAclPacket* pAclPkt;
1009 PyObject* pRetVal;
1010
1011 pAclPkt = NativeToPyAclPacket(ap);
1012 if (!pAclPkt) { goto bail_out; }
1013
1014 pRetVal = PyObject_CallFunctionObjArgs(pFunc, pAclPkt, NULL);
1015 Py_DECREF(pAclPkt);
1016
1017 if (!pRetVal) {
1018 goto bail_out;
1019 } else {
1020 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
1021 Py_DECREF(pRetVal);
1022 }
1023 } else {
1024 Dmsg(plugin_ctx, debuglevel,
1025 LOGPREFIX "Failed to find function named set_acl()\n");
1026 }
1027
1028 return retval;
1029
1030 bail_out:
1031 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
1032
1033 return retval;
1034 }
1035
NativeToPyXattrPacket(struct xattr_pkt * xp)1036 static inline PyXattrPacket* NativeToPyXattrPacket(struct xattr_pkt* xp)
1037 {
1038 PyXattrPacket* pXattrPacket = PyObject_New(PyXattrPacket, &PyXattrPacketType);
1039
1040 if (pXattrPacket) {
1041 pXattrPacket->fname = xp->fname;
1042
1043 if (xp->name_length && xp->name) {
1044 pXattrPacket->name
1045 = PyByteArray_FromStringAndSize(xp->name, xp->name_length);
1046 } else {
1047 pXattrPacket->name = NULL;
1048 }
1049 if (xp->value_length && xp->value) {
1050 pXattrPacket->value
1051 = PyByteArray_FromStringAndSize(xp->value, xp->value_length);
1052 } else {
1053 pXattrPacket->value = NULL;
1054 }
1055 }
1056
1057 return pXattrPacket;
1058 }
1059
PyXattrPacketToNative(PyXattrPacket * pXattrPacket,struct xattr_pkt * xp)1060 static inline bool PyXattrPacketToNative(PyXattrPacket* pXattrPacket,
1061 struct xattr_pkt* xp)
1062 {
1063 if (!pXattrPacket->name) { return true; }
1064
1065 if (PyByteArray_Check(pXattrPacket->name)) {
1066 char* buf;
1067
1068 xp->name_length = PyByteArray_Size(pXattrPacket->name);
1069 if (xp->name_length <= 0
1070 || !(buf = PyByteArray_AsString(pXattrPacket->name))) {
1071 return false;
1072 }
1073
1074 if (xp->name) { free(xp->name); }
1075 xp->name = (char*)malloc(xp->name_length);
1076 memcpy(xp->name, buf, xp->name_length);
1077 }
1078
1079 if (pXattrPacket->value && PyByteArray_Check(pXattrPacket->value)) {
1080 char* buf;
1081
1082 xp->value_length = PyByteArray_Size(pXattrPacket->value);
1083 if (xp->name_length <= 0
1084 || !(buf = PyByteArray_AsString(pXattrPacket->name))) {
1085 return false;
1086 }
1087
1088 if (xp->value) { free(xp->value); }
1089 xp->value = (char*)malloc(xp->value_length);
1090 memcpy(xp->value, buf, xp->value_length);
1091 } else {
1092 if (xp->value) { free(xp->value); }
1093 xp->value = NULL;
1094 }
1095
1096 return true;
1097 }
1098
PyGetXattr(PluginContext * plugin_ctx,xattr_pkt * xp)1099 static bRC PyGetXattr(PluginContext* plugin_ctx, xattr_pkt* xp)
1100 {
1101 bRC retval = bRC_Error;
1102 struct plugin_private_context* plugin_priv_ctx
1103 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
1104 PyObject* pFunc;
1105
1106 if (!xp) { return bRC_Error; }
1107
1108 /*
1109 * Lookup the get_xattr() function in the python module.
1110 */
1111 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
1112 "get_xattr"); /* Borrowed reference */
1113 if (pFunc && PyCallable_Check(pFunc)) {
1114 PyXattrPacket* pXattrPkt;
1115 PyObject* pRetVal;
1116
1117 pXattrPkt = NativeToPyXattrPacket(xp);
1118 if (!pXattrPkt) { goto bail_out; }
1119
1120 pRetVal = PyObject_CallFunctionObjArgs(pFunc, pXattrPkt, NULL);
1121 if (!pRetVal) {
1122 Py_DECREF((PyObject*)pXattrPkt);
1123 goto bail_out;
1124 } else {
1125 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
1126 Py_DECREF(pRetVal);
1127
1128 if (!PyXattrPacketToNative(pXattrPkt, xp)) {
1129 Py_DECREF((PyObject*)pXattrPkt);
1130 goto bail_out;
1131 }
1132 Py_DECREF(pXattrPkt);
1133 }
1134 } else {
1135 Dmsg(plugin_ctx, debuglevel,
1136 LOGPREFIX "Failed to find function named get_xattr()\n");
1137 }
1138
1139 return retval;
1140
1141 bail_out:
1142 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
1143
1144 return retval;
1145 }
1146
PySetXattr(PluginContext * plugin_ctx,xattr_pkt * xp)1147 static bRC PySetXattr(PluginContext* plugin_ctx, xattr_pkt* xp)
1148 {
1149 bRC retval = bRC_Error;
1150 struct plugin_private_context* plugin_priv_ctx
1151 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
1152 PyObject* pFunc;
1153
1154 if (!xp) { return bRC_Error; }
1155
1156 /*
1157 * Lookup the set_acl() function in the python module.
1158 */
1159 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
1160 "set_xattr"); /* Borrowed reference */
1161 if (pFunc && PyCallable_Check(pFunc)) {
1162 PyXattrPacket* pXattrPkt;
1163 PyObject* pRetVal;
1164
1165 pXattrPkt = NativeToPyXattrPacket(xp);
1166 if (!pXattrPkt) { goto bail_out; }
1167
1168 pRetVal = PyObject_CallFunctionObjArgs(pFunc, pXattrPkt, NULL);
1169 Py_DECREF(pXattrPkt);
1170
1171 if (!pRetVal) {
1172 goto bail_out;
1173 } else {
1174 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
1175 Py_DECREF(pRetVal);
1176 }
1177 } else {
1178 Dmsg(plugin_ctx, debuglevel,
1179 LOGPREFIX "Failed to find function named set_xattr()\n");
1180 }
1181
1182 return retval;
1183 bail_out:
1184 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
1185
1186 return retval;
1187 }
1188
NativeToPyRestoreObject(struct restore_object_pkt * rop)1189 static inline PyRestoreObject* NativeToPyRestoreObject(
1190 struct restore_object_pkt* rop)
1191 {
1192 PyRestoreObject* pRestoreObject
1193 = PyObject_New(PyRestoreObject, &PyRestoreObjectType);
1194
1195 if (pRestoreObject) {
1196 pRestoreObject->object_name = PyUnicode_FromString(rop->object_name);
1197 pRestoreObject->object
1198 = PyByteArray_FromStringAndSize(rop->object, rop->object_len);
1199 pRestoreObject->plugin_name = rop->plugin_name;
1200 pRestoreObject->object_type = rop->object_type;
1201 pRestoreObject->object_len = rop->object_len;
1202 pRestoreObject->object_full_len = rop->object_full_len;
1203 pRestoreObject->object_index = rop->object_index;
1204 pRestoreObject->object_compression = rop->object_compression;
1205 pRestoreObject->stream = rop->stream;
1206 pRestoreObject->JobId = rop->JobId;
1207 }
1208
1209 return pRestoreObject;
1210 }
1211
PyRestoreObjectData(PluginContext * plugin_ctx,struct restore_object_pkt * rop)1212 static bRC PyRestoreObjectData(PluginContext* plugin_ctx,
1213 struct restore_object_pkt* rop)
1214 {
1215 bRC retval = bRC_Error;
1216 struct plugin_private_context* plugin_priv_ctx
1217 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
1218 PyObject* pFunc;
1219
1220 if (!rop) { return bRC_OK; }
1221
1222 /*
1223 * Lookup the restore_object_data() function in the python module.
1224 */
1225 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
1226 "restore_object_data"); /* Borrowed reference */
1227 if (pFunc && PyCallable_Check(pFunc)) {
1228 PyRestoreObject* pRestoreObject;
1229 PyObject* pRetVal;
1230
1231 pRestoreObject = NativeToPyRestoreObject(rop);
1232 if (!pRestoreObject) { goto bail_out; }
1233
1234 pRetVal = PyObject_CallFunctionObjArgs(pFunc, pRestoreObject, NULL);
1235 Py_DECREF(pRestoreObject);
1236
1237 if (!pRetVal) {
1238 goto bail_out;
1239 } else {
1240 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
1241 Py_DECREF(pRetVal);
1242 }
1243 } else {
1244 Dmsg(plugin_ctx, debuglevel,
1245 LOGPREFIX "Failed to find function named start_restore_file()\n");
1246 }
1247
1248 return retval;
1249
1250 bail_out:
1251 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
1252
1253 return retval;
1254 }
1255
PyHandleBackupFile(PluginContext * plugin_ctx,struct save_pkt * sp)1256 static bRC PyHandleBackupFile(PluginContext* plugin_ctx, struct save_pkt* sp)
1257 {
1258 bRC retval = bRC_Error;
1259 struct plugin_private_context* plugin_priv_ctx
1260 = (struct plugin_private_context*)plugin_ctx->plugin_private_context;
1261 PyObject* pFunc;
1262
1263 if (!sp) { return bRC_Error; }
1264
1265 /*
1266 * Lookup the handle_backup_file() function in the python module.
1267 */
1268 pFunc = PyDict_GetItemString(plugin_priv_ctx->pyModuleFunctionsDict,
1269 "handle_backup_file"); /* Borrowed reference */
1270 if (pFunc && PyCallable_Check(pFunc)) {
1271 PySavePacket* pSavePkt;
1272 PyObject* pRetVal;
1273
1274 pSavePkt = NativeToPySavePacket(sp);
1275 if (!pSavePkt) { goto bail_out; }
1276
1277 pRetVal = PyObject_CallFunctionObjArgs(pFunc, pSavePkt, NULL);
1278 if (!pRetVal) {
1279 Py_DECREF((PyObject*)pSavePkt);
1280 goto bail_out;
1281 } else {
1282 retval = ConvertPythonRetvalTobRCRetval(pRetVal);
1283 Py_DECREF(pRetVal);
1284
1285 if (!PySavePacketToNative(pSavePkt, sp, plugin_priv_ctx, true)) {
1286 Py_DECREF((PyObject*)pSavePkt);
1287 goto bail_out;
1288 }
1289 Py_DECREF(pSavePkt);
1290 }
1291 } else {
1292 Dmsg(plugin_ctx, debuglevel,
1293 LOGPREFIX "Failed to find function named handle_backup_file()\n");
1294 }
1295
1296 return retval;
1297
1298 bail_out:
1299 if (PyErr_Occurred()) { PyErrorHandler(plugin_ctx, M_FATAL); }
1300
1301 return retval;
1302 }
1303
1304 /**
1305 * Callback function which is exposed as a part of the additional methods
1306 * which allow a Python plugin to get certain internal values of the current
1307 * Job.
1308 */
PyBareosGetValue(PyObject * self,PyObject * args)1309 static PyObject* PyBareosGetValue(PyObject* self, PyObject* args)
1310 {
1311 int var;
1312 PluginContext* plugin_ctx = plugin_context;
1313 PyObject* pRetVal = NULL;
1314
1315 if (!PyArg_ParseTuple(args, "i:BareosGetValue", &var)) { return NULL; }
1316 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1317
1318 switch (var) {
1319 case bVarFDName:
1320 case bVarWorkingDir:
1321 case bVarExePath:
1322 case bVarVersion:
1323 case bVarDistName: {
1324 char* value = NULL;
1325
1326 if (bareos_core_functions->getBareosValue(plugin_ctx, (bVariable)var,
1327 &value)
1328 == bRC_OK) {
1329 if (value) { pRetVal = PyUnicode_FromString(value); }
1330 }
1331 break;
1332 }
1333 case bVarJobId:
1334 case bVarLevel:
1335 case bVarType:
1336 case bVarJobStatus:
1337 case bVarSinceTime:
1338 case bVarAccurate:
1339 case bVarPrefixLinks: {
1340 int value = 0;
1341
1342 if (bareos_core_functions->getBareosValue(plugin_ctx, (bVariable)var,
1343 &value)
1344 == bRC_OK) {
1345 pRetVal = PyLong_FromLong(value);
1346 }
1347 break;
1348 }
1349 case bVarClient:
1350 case bVarJobName:
1351 case bVarPrevJobName:
1352 case bVarWhere:
1353 case bVarRegexWhere: {
1354 char* value = NULL;
1355
1356 if (bareos_core_functions->getBareosValue(plugin_ctx, (bVariable)var,
1357 &value)
1358 == bRC_OK) {
1359 if (value) { pRetVal = PyUnicode_FromString(value); }
1360 }
1361 break;
1362 }
1363 case bVarFileSeen:
1364 break; /* a write only variable, ignore read request */
1365 default:
1366 Dmsg(plugin_ctx, debuglevel,
1367 LOGPREFIX "PyBareosGetValue unknown variable requested %d\n", var);
1368 break;
1369 }
1370
1371 if (!pRetVal) { Py_RETURN_NONE; }
1372
1373 return pRetVal;
1374 }
1375
1376 /**
1377 * Callback function which is exposed as a part of the additional methods
1378 * which allow a Python plugin to get certain internal values of the current
1379 * Job.
1380 */
PyBareosSetValue(PyObject * self,PyObject * args)1381 static PyObject* PyBareosSetValue(PyObject* self, PyObject* args)
1382 {
1383 int var;
1384 PluginContext* plugin_ctx = plugin_context;
1385 bRC retval = bRC_Error;
1386 PyObject* pyValue;
1387
1388 if (!PyArg_ParseTuple(args, "iO:BareosSetValue", &var, &pyValue)) {
1389 goto bail_out;
1390 }
1391 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1392
1393 switch (var) {
1394 case bVarLevel: {
1395 int value = 0;
1396
1397 value = PyLong_AsLong(pyValue);
1398 if (value) {
1399 retval = bareos_core_functions->setBareosValue(plugin_ctx,
1400 (bVariable)var, &value);
1401 }
1402 break;
1403 }
1404 case bVarFileSeen: {
1405 const char* value = PyUnicode_AsUTF8(pyValue);
1406 if (value) {
1407 retval = bareos_core_functions->setBareosValue(
1408 plugin_ctx, (bVariable)var,
1409 static_cast<void*>(const_cast<char*>(value)));
1410 }
1411 break;
1412 }
1413 default:
1414 Dmsg(plugin_ctx, debuglevel,
1415 LOGPREFIX "PyBareosSetValue unknown variable requested %d\n", var);
1416 break;
1417 }
1418
1419 bail_out:
1420 return ConvertbRCRetvalToPythonRetval(retval);
1421 }
1422
1423 /**
1424 * Callback function which is exposed as a part of the additional methods
1425 * which allow a Python plugin to issue debug messages using the Bareos debug
1426 * message facility.
1427 */
PyBareosDebugMessage(PyObject * self,PyObject * args)1428 static PyObject* PyBareosDebugMessage(PyObject* self, PyObject* args)
1429 {
1430 int level;
1431 char* dbgmsg = NULL;
1432 PluginContext* plugin_ctx = plugin_context;
1433 /* plugin_private_context* ppc = */
1434 /* (plugin_private_context*)plugin_ctx->plugin_private_context;
1435 */
1436
1437 if (!PyArg_ParseTuple(args, "i|z:BareosDebugMessage", &level, &dbgmsg)) {
1438 return NULL;
1439 }
1440 RETURN_RUNTIME_ERROR_IF_BAREOS_PLUGIN_CTX_UNSET()
1441
1442 if (dbgmsg) { Dmsg(plugin_ctx, level, LOGPREFIX "%s", dbgmsg); }
1443
1444 Py_RETURN_NONE;
1445 }
1446
1447 /**
1448 * Callback function which is exposed as a part of the additional methods
1449 * which allow a Python plugin to issue Job messages using the Bareos Job
1450 * message facility.
1451 */
PyBareosJobMessage(PyObject * self,PyObject * args)1452 static PyObject* PyBareosJobMessage(PyObject* self, PyObject* args)
1453 {
1454 int level;
1455 char* jobmsg = NULL;
1456 PluginContext* plugin_ctx = plugin_context;
1457
1458 if (!PyArg_ParseTuple(args, "i|z:BareosJobMessage", &level, &jobmsg)) {
1459 return NULL;
1460 }
1461 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1462
1463 if (jobmsg) { Jmsg(plugin_ctx, level, LOGPREFIX "%s", jobmsg); }
1464
1465 Py_RETURN_NONE;
1466 }
1467
1468 /**
1469 * Callback function which is exposed as a part of the additional methods
1470 * which allow a Python plugin to issue a Register Event to register
1471 * additional events it wants to receive.
1472 */
PyBareosRegisterEvents(PyObject * self,PyObject * args)1473 static PyObject* PyBareosRegisterEvents(PyObject* self, PyObject* args)
1474 {
1475 int len, event;
1476 PluginContext* plugin_ctx = plugin_context;
1477 bRC retval = bRC_Error;
1478 PyObject *pyEvents, *pySeq, *pyEvent;
1479
1480 if (!PyArg_ParseTuple(args, "O:BareosRegisterEvents", &pyEvents)) {
1481 goto bail_out;
1482 }
1483 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1484
1485 pySeq = PySequence_Fast(pyEvents, "Expected a sequence of events");
1486 if (!pySeq) { goto bail_out; }
1487 len = PySequence_Fast_GET_SIZE(pySeq);
1488
1489 for (int i = 0; i < len; i++) {
1490 pyEvent = PySequence_Fast_GET_ITEM(pySeq, i);
1491 event = PyLong_AsLong(pyEvent);
1492
1493 if (event >= bEventJobStart && event <= FD_NR_EVENTS) {
1494 Dmsg(plugin_ctx, debuglevel,
1495 LOGPREFIX "PyBareosRegisterEvents registering event %d\n", event);
1496 retval
1497 = bareos_core_functions->registerBareosEvents(plugin_ctx, 1, event);
1498
1499 if (retval != bRC_OK) { break; }
1500 }
1501 }
1502
1503 Py_DECREF(pySeq);
1504
1505 bail_out:
1506 return ConvertbRCRetvalToPythonRetval(retval);
1507 }
1508
1509 /**
1510 * Callback function which is exposed as a part of the additional methods
1511 * which allow a Python plugin to issue an Unregister Event to unregister
1512 * events it doesn't want to receive anymore.
1513 */
PyBareosUnRegisterEvents(PyObject * self,PyObject * args)1514 static PyObject* PyBareosUnRegisterEvents(PyObject* self, PyObject* args)
1515 {
1516 int len, event;
1517 PluginContext* plugin_ctx = plugin_context;
1518 bRC retval = bRC_Error;
1519 PyObject *pyEvents, *pySeq, *pyEvent;
1520
1521 if (!PyArg_ParseTuple(args, "O:BareosUnRegisterEvents", &pyEvents)) {
1522 goto bail_out;
1523 }
1524 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1525
1526 pySeq = PySequence_Fast(pyEvents, "Expected a sequence of events");
1527 if (!pySeq) { goto bail_out; }
1528
1529 len = PySequence_Fast_GET_SIZE(pySeq);
1530 for (int i = 0; i < len; i++) {
1531 pyEvent = PySequence_Fast_GET_ITEM(pySeq, i);
1532 event = PyLong_AsLong(pyEvent);
1533
1534 if (event >= bEventJobStart && event <= FD_NR_EVENTS) {
1535 Dmsg(plugin_ctx, debuglevel,
1536 "PyBareosUnRegisterEvents: unregistering event %d\n", event);
1537 retval
1538 = bareos_core_functions->unregisterBareosEvents(plugin_ctx, 1, event);
1539 }
1540 }
1541
1542 Py_DECREF(pySeq);
1543
1544 bail_out:
1545 return ConvertbRCRetvalToPythonRetval(retval);
1546 }
1547
1548 /**
1549 * Callback function which is exposed as a part of the additional methods
1550 * which allow a Python plugin to issue a GetInstanceCount to retrieve the
1551 * number of instances of the current plugin being loaded into the daemon.
1552 */
PyBareosGetInstanceCount(PyObject * self,PyObject * args)1553 static PyObject* PyBareosGetInstanceCount(PyObject* self, PyObject* args)
1554 {
1555 int value;
1556 PluginContext* plugin_ctx = plugin_context;
1557 PyObject* pRetVal = NULL;
1558
1559 if (!PyArg_ParseTuple(args, ":BareosGetInstanceCount")) { return NULL; }
1560 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1561
1562 if (bareos_core_functions->getInstanceCount(plugin_ctx, &value) == bRC_OK) {
1563 pRetVal = PyLong_FromLong(value);
1564 }
1565
1566 if (!pRetVal) { Py_RETURN_NONE; }
1567
1568 return pRetVal;
1569 }
1570
1571 /**
1572 * Callback function which is exposed as a part of the additional methods
1573 * which allow a Python plugin to issue a Add Exclude pattern to the fileset.
1574 */
PyBareosAddExclude(PyObject * self,PyObject * args)1575 static PyObject* PyBareosAddExclude(PyObject* self, PyObject* args)
1576 {
1577 char* file = NULL;
1578 bRC retval = bRC_Error;
1579 PluginContext* plugin_ctx = plugin_context;
1580
1581 if (!PyArg_ParseTuple(args, "|z:BareosAddExclude", &file)) { goto bail_out; }
1582 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1583
1584 if (file) { retval = bareos_core_functions->AddExclude(plugin_ctx, file); }
1585
1586 bail_out:
1587 return ConvertbRCRetvalToPythonRetval(retval);
1588 }
1589
1590 /**
1591 * Callback function which is exposed as a part of the additional methods
1592 * which allow a Python plugin to issue a Add Include pattern to the fileset.
1593 */
PyBareosAddInclude(PyObject * self,PyObject * args)1594 static PyObject* PyBareosAddInclude(PyObject* self, PyObject* args)
1595 {
1596 char* file = NULL;
1597 bRC retval = bRC_Error;
1598 PluginContext* plugin_ctx = plugin_context;
1599
1600 if (!PyArg_ParseTuple(args, "|z:BareosAddInclude", &file)) { goto bail_out; }
1601 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1602
1603 if (file) { retval = bareos_core_functions->AddInclude(plugin_ctx, file); }
1604
1605 bail_out:
1606 return ConvertbRCRetvalToPythonRetval(retval);
1607 }
1608
1609 /**
1610 * Callback function which is exposed as a part of the additional methods
1611 * which allow a Python plugin to issue a Add Include Options to the fileset.
1612 */
PyBareosAddOptions(PyObject * self,PyObject * args)1613 static PyObject* PyBareosAddOptions(PyObject* self, PyObject* args)
1614 {
1615 char* opts = NULL;
1616 bRC retval = bRC_Error;
1617 PluginContext* plugin_ctx = plugin_context;
1618
1619 if (!PyArg_ParseTuple(args, "|z:BareosAddOptions", &opts)) { goto bail_out; }
1620 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1621
1622 if (opts) { retval = bareos_core_functions->AddOptions(plugin_ctx, opts); }
1623
1624 bail_out:
1625 return ConvertbRCRetvalToPythonRetval(retval);
1626 }
1627
1628 /**
1629 * Callback function which is exposed as a part of the additional methods
1630 * which allow a Python plugin to issue a Add Regex to the fileset.
1631 */
PyBareosAddRegex(PyObject * self,PyObject * args)1632 static PyObject* PyBareosAddRegex(PyObject* self, PyObject* args)
1633 {
1634 int type;
1635 char* item = NULL;
1636 bRC retval = bRC_Error;
1637 PluginContext* plugin_ctx = plugin_context;
1638 if (!PyArg_ParseTuple(args, "|zi:BareosAddRegex", &item, &type)) {
1639 goto bail_out;
1640 }
1641 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1642
1643 if (item) {
1644 retval = bareos_core_functions->AddRegex(plugin_ctx, item, type);
1645 }
1646
1647 bail_out:
1648 return ConvertbRCRetvalToPythonRetval(retval);
1649 }
1650
1651 /**
1652 * Callback function which is exposed as a part of the additional methods
1653 * which allow a Python plugin to issue a Add Wildcard to the fileset.
1654 */
PyBareosAddWild(PyObject * self,PyObject * args)1655 static PyObject* PyBareosAddWild(PyObject* self, PyObject* args)
1656 {
1657 int type;
1658 char* item = NULL;
1659 bRC retval = bRC_Error;
1660 PluginContext* plugin_ctx = plugin_context;
1661
1662 if (!PyArg_ParseTuple(args, "|zi:BareosAddWild", &item, &type)) {
1663 goto bail_out;
1664 }
1665 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1666
1667 if (item) { retval = bareos_core_functions->AddWild(plugin_ctx, item, type); }
1668
1669 bail_out:
1670 return ConvertbRCRetvalToPythonRetval(retval);
1671 }
1672
1673 /**
1674 * Callback function which is exposed as a part of the additional methods
1675 * which allow a Python plugin to issue a Add New Option block.
1676 */
PyBareosNewOptions(PyObject * self,PyObject * args)1677 static PyObject* PyBareosNewOptions(PyObject* self, PyObject* args)
1678 {
1679 PluginContext* plugin_ctx = plugin_context;
1680 bRC retval = bRC_Error;
1681
1682 if (!PyArg_ParseTuple(args, ":BareosNewOptions")) { goto bail_out; }
1683 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1684
1685 retval = bareos_core_functions->NewOptions(plugin_ctx);
1686
1687 bail_out:
1688 return ConvertbRCRetvalToPythonRetval(retval);
1689 }
1690
1691 /**
1692 * Callback function which is exposed as a part of the additional methods
1693 * which allow a Python plugin to issue a Add New Include block.
1694 */
PyBareosNewInclude(PyObject * self,PyObject * args)1695 static PyObject* PyBareosNewInclude(PyObject* self, PyObject* args)
1696 {
1697 PluginContext* plugin_ctx = plugin_context;
1698 bRC retval = bRC_Error;
1699
1700 if (!PyArg_ParseTuple(args, ":BareosNewInclude")) { goto bail_out; }
1701 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1702
1703 retval = bareos_core_functions->NewInclude(plugin_ctx);
1704
1705 bail_out:
1706 return ConvertbRCRetvalToPythonRetval(retval);
1707 }
1708
1709 /**
1710 * Callback function which is exposed as a part of the additional methods
1711 * which allow a Python plugin to issue a Add New Pre Include block.
1712 */
PyBareosNewPreInclude(PyObject * self,PyObject * args)1713 static PyObject* PyBareosNewPreInclude(PyObject* self, PyObject* args)
1714 {
1715 PluginContext* plugin_ctx = plugin_context;
1716 bRC retval = bRC_Error;
1717
1718 if (!PyArg_ParseTuple(args, ":BareosNewPreInclude")) { goto bail_out; }
1719 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1720
1721 retval = bareos_core_functions->NewPreInclude(plugin_ctx);
1722
1723 bail_out:
1724 return ConvertbRCRetvalToPythonRetval(retval);
1725 }
1726
1727 /**
1728 * Callback function which is exposed as a part of the additional methods
1729 * which allow a Python plugin to issue a check if a file have to be backed up
1730 * using Accurate code.
1731 */
PyBareosCheckChanges(PyObject * self,PyObject * args)1732 static PyObject* PyBareosCheckChanges(PyObject* self, PyObject* args)
1733 {
1734 PluginContext* plugin_ctx = plugin_context;
1735
1736 struct save_pkt sp;
1737 bRC retval = bRC_Error;
1738 PySavePacket* pSavePkt;
1739
1740 if (!PyArg_ParseTuple(args, "O:BareosCheckChanges", &pSavePkt)) {
1741 goto bail_out;
1742 }
1743 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1744
1745
1746 /*
1747 * CheckFile only has a need for a limited version of the PySavePacket so we
1748 * handle that here separately and don't call PySavePacketToNative().
1749 */
1750 sp.type = pSavePkt->type;
1751 if (pSavePkt->fname) {
1752 if (PyUnicode_Check(pSavePkt->fname)) {
1753 sp.fname = const_cast<char*>(PyUnicode_AsUTF8(pSavePkt->fname));
1754 } else {
1755 goto bail_out;
1756 }
1757 } else {
1758 goto bail_out;
1759 }
1760 if (pSavePkt->link) {
1761 if (PyUnicode_Check(pSavePkt->link)) {
1762 sp.link = const_cast<char*>(PyUnicode_AsUTF8(pSavePkt->link));
1763 } else {
1764 goto bail_out;
1765 }
1766 }
1767 sp.save_time = pSavePkt->save_time;
1768
1769 retval = bareos_core_functions->checkChanges(plugin_ctx, &sp);
1770
1771 /*
1772 * Copy back the two fields that are changed by checkChanges().
1773 */
1774 pSavePkt->delta_seq = sp.delta_seq;
1775 pSavePkt->accurate_found = sp.accurate_found;
1776
1777 bail_out:
1778 return ConvertbRCRetvalToPythonRetval(retval);
1779 }
1780
1781 /**
1782 * Callback function which is exposed as a part of the additional methods
1783 * which allow a Python plugin to issue a check if a file would be saved using
1784 * current Include/Exclude code.
1785 */
PyBareosAcceptFile(PyObject * self,PyObject * args)1786 static PyObject* PyBareosAcceptFile(PyObject* self, PyObject* args)
1787 {
1788 PluginContext* plugin_ctx = plugin_context;
1789 struct save_pkt sp;
1790 bRC retval = bRC_Error;
1791 PySavePacket* pSavePkt;
1792
1793 if (!PyArg_ParseTuple(args, "O:BareosAcceptFile", &pSavePkt)) {
1794 goto bail_out;
1795 }
1796 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1797
1798 /*
1799 * Acceptfile only needs fname and statp from PySavePacket so we handle
1800 * that here separately and don't call PySavePacketToNative().
1801 */
1802 if (pSavePkt->fname) {
1803 if (PyUnicode_Check(pSavePkt->fname)) {
1804 sp.fname = const_cast<char*>(PyUnicode_AsUTF8(pSavePkt->fname));
1805 } else {
1806 goto bail_out;
1807 }
1808 } else {
1809 goto bail_out;
1810 }
1811
1812 if (pSavePkt->statp) {
1813 PyStatPacketToNative((PyStatPacket*)pSavePkt->statp, &sp.statp);
1814 } else {
1815 goto bail_out;
1816 }
1817
1818 retval = bareos_core_functions->AcceptFile(plugin_ctx, &sp);
1819
1820 bail_out:
1821 return ConvertbRCRetvalToPythonRetval(retval);
1822 }
1823
1824 /**
1825 * Callback function which is exposed as a part of the additional methods
1826 * which allow a Python plugin to issue a Set bit in the Accurate Seen bitmap.
1827 */
PyBareosSetSeenBitmap(PyObject * self,PyObject * args)1828 static PyObject* PyBareosSetSeenBitmap(PyObject* self, PyObject* args)
1829 {
1830 bool all;
1831 PluginContext* plugin_ctx = plugin_context;
1832 char* fname = NULL;
1833 bRC retval = bRC_Error;
1834 PyObject* pyBool;
1835
1836 if (!PyArg_ParseTuple(args, "O|s:BareosSetSeenBitmap", &pyBool, &fname)) {
1837 goto bail_out;
1838 }
1839 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1840
1841 all = PyObject_IsTrue(pyBool);
1842 retval = bareos_core_functions->SetSeenBitmap(plugin_ctx, all, fname);
1843
1844 bail_out:
1845 return ConvertbRCRetvalToPythonRetval(retval);
1846 }
1847
1848 /**
1849 * Callback function which is exposed as a part of the additional methods
1850 * which allow a Python plugin to issue a Clear bit in the Accurate Seen
1851 * bitmap.
1852 */
PyBareosClearSeenBitmap(PyObject * self,PyObject * args)1853 static PyObject* PyBareosClearSeenBitmap(PyObject* self, PyObject* args)
1854 {
1855 bool all;
1856 PluginContext* plugin_ctx = plugin_context;
1857 char* fname = NULL;
1858 bRC retval = bRC_Error;
1859 PyObject* pyBool;
1860
1861 if (!PyArg_ParseTuple(args, "O|s:BareosClearSeenBitmap", &pyBool, &fname)) {
1862 goto bail_out;
1863 }
1864 RETURN_RUNTIME_ERROR_IF_BFUNC_OR_BAREOS_PLUGIN_CTX_UNSET()
1865
1866 all = PyObject_IsTrue(pyBool);
1867 retval = bareos_core_functions->ClearSeenBitmap(plugin_ctx, all, fname);
1868
1869 bail_out:
1870 return ConvertbRCRetvalToPythonRetval(retval);
1871 }
1872
1873 /**
1874 * Some helper functions.
1875 */
PyGetStringValue(PyObject * object)1876 static inline char* PyGetStringValue(PyObject* object)
1877 {
1878 if (!object || !PyUnicode_Check(object)) { return (char*)""; }
1879
1880 return const_cast<char*>(PyUnicode_AsUTF8(object));
1881 }
1882
PyGetByteArrayValue(PyObject * object)1883 static inline char* PyGetByteArrayValue(PyObject* object)
1884 {
1885 if (!object || !PyByteArray_Check(object)) { return (char*)""; }
1886
1887 return PyByteArray_AsString(object);
1888 }
1889
1890 /**
1891 * Python specific handlers for PyRestoreObject structure mapping.
1892 */
1893
1894 /**
1895 * Representation.
1896 */
PyRestoreObject_repr(PyRestoreObject * self)1897 static PyObject* PyRestoreObject_repr(PyRestoreObject* self)
1898 {
1899 PyObject* s;
1900 PoolMem buf(PM_MESSAGE);
1901
1902 Mmsg(buf,
1903 "RestoreObject(object_name=\"%s\", object=\"%s\", plugin_name=\"%s\", "
1904 "object_type=%d, object_len=%d, object_full_len=%d, "
1905 "object_index=%d, object_compression=%d, stream=%d, jobid=%u)",
1906 PyGetStringValue(self->object_name), PyGetByteArrayValue(self->object),
1907 self->plugin_name, self->object_type, self->object_len,
1908 self->object_full_len, self->object_index, self->object_compression,
1909 self->stream, self->JobId);
1910 s = PyUnicode_FromString(buf.c_str());
1911
1912 return s;
1913 }
1914
1915 /**
1916 * Initialization.
1917 */
PyRestoreObject_init(PyRestoreObject * self,PyObject * args,PyObject * kwds)1918 static int PyRestoreObject_init(PyRestoreObject* self,
1919 PyObject* args,
1920 PyObject* kwds)
1921 {
1922 static char* kwlist[] = {(char*)"object_name",
1923 (char*)"object",
1924 (char*)"plugin_name",
1925 (char*)"object_type",
1926 (char*)"object_len",
1927 (char*)"object_full_len",
1928 (char*)"object_index",
1929 (char*)"object_compression",
1930 (char*)"stream",
1931 (char*)"jobid",
1932 NULL};
1933
1934 self->object_name = NULL;
1935 self->object = NULL;
1936 self->plugin_name = NULL;
1937 self->object_type = 0;
1938 self->object_len = 0;
1939 self->object_full_len = 0;
1940 self->object_index = 0;
1941 self->object_compression = 0;
1942 self->stream = 0;
1943 self->JobId = 0;
1944
1945 if (!PyArg_ParseTupleAndKeywords(
1946 args, kwds, "|oosiiiiiiI", kwlist, &self->object_name, &self->object,
1947 &self->plugin_name, &self->object_type, &self->object_len,
1948 &self->object_full_len, &self->object_index,
1949 &self->object_compression, &self->stream, &self->JobId)) {
1950 return -1;
1951 }
1952
1953 return 0;
1954 }
1955
1956 /**
1957 * Destructor.
1958 */
PyRestoreObject_dealloc(PyRestoreObject * self)1959 static void PyRestoreObject_dealloc(PyRestoreObject* self)
1960 {
1961 if (self->object_name) { Py_XDECREF(self->object_name); }
1962 if (self->object) { Py_XDECREF(self->object); }
1963 PyObject_Del(self);
1964 }
1965
1966 /**
1967 * Python specific handlers for PyStatPacket structure mapping.
1968 */
1969
1970 /**
1971 * Representation.
1972 */
PyStatPacket_repr(PyStatPacket * self)1973 static PyObject* PyStatPacket_repr(PyStatPacket* self)
1974 {
1975 PyObject* s;
1976 PoolMem buf(PM_MESSAGE);
1977
1978 Mmsg(buf,
1979 "StatPacket(dev=%ld, ino=%lld, mode=%04o, nlink=%d, "
1980 "uid=%ld, gid=%ld, rdev=%ld, size=%lld, "
1981 "atime=%ld, mtime=%ld, ctime=%ld, blksize=%ld, blocks=%lld)",
1982 self->dev, self->ino, (self->mode & ~S_IFMT), self->nlink, self->uid,
1983 self->gid, self->rdev, self->size, self->atime, self->mtime, self->ctime,
1984 self->blksize, self->blocks);
1985
1986 s = PyUnicode_FromString(buf.c_str());
1987
1988 return s;
1989 }
1990
1991 /**
1992 * Initialization.
1993 */
PyStatPacket_init(PyStatPacket * self,PyObject * args,PyObject * kwds)1994 static int PyStatPacket_init(PyStatPacket* self, PyObject* args, PyObject* kwds)
1995 {
1996 time_t now;
1997 static char* kwlist[] = {(char*)"dev", (char*)"ino",
1998 (char*)"mode", (char*)"nlink",
1999 (char*)"uid", (char*)"gid",
2000 (char*)"rdev", (char*)"size",
2001 (char*)"atime", (char*)"mtime",
2002 (char*)"ctime", (char*)"blksize",
2003 (char*)"blocks", NULL};
2004
2005 now = time(NULL);
2006 self->dev = 0;
2007 self->ino = 0;
2008 self->mode = 0700 | S_IFREG;
2009 self->nlink = 0;
2010 self->uid = 0;
2011 self->gid = 0;
2012 self->rdev = 0;
2013 self->size = -1;
2014 self->atime = now;
2015 self->mtime = now;
2016 self->ctime = now;
2017 self->blksize = 4096;
2018 self->blocks = 1;
2019
2020 if (!PyArg_ParseTupleAndKeywords(
2021 args, kwds, "|IKHHIIILIIIIK", kwlist, &self->dev, &self->ino,
2022 &self->mode, &self->nlink, &self->uid, &self->gid, &self->rdev,
2023 &self->size, &self->atime, &self->mtime, &self->ctime, &self->blksize,
2024 &self->blocks)) {
2025 return -1;
2026 }
2027
2028 return 0;
2029 }
2030
2031 /**
2032 * Destructor.
2033 */
PyStatPacket_dealloc(PyStatPacket * self)2034 static void PyStatPacket_dealloc(PyStatPacket* self) { PyObject_Del(self); }
2035
2036 /**
2037 * Python specific handlers for PySavePacket structure mapping.
2038 */
2039
2040 /**
2041 * Representation.
2042 */
print_flags_bitmap(PyObject * bitmap)2043 static inline const char* print_flags_bitmap(PyObject* bitmap)
2044 {
2045 static char visual_bitmap[FO_MAX + 1];
2046 if (!bitmap) { return "<NULL>"; }
2047 if (PyByteArray_Check(bitmap)) {
2048 int cnt;
2049 char* flags;
2050
2051 if (PyByteArray_Size(bitmap) == FOPTS_BYTES) {
2052 if ((flags = PyByteArray_AsString(bitmap))) {
2053 memset(visual_bitmap, 0, sizeof(visual_bitmap));
2054 for (cnt = 0; cnt <= FO_MAX; cnt++) {
2055 if (BitIsSet(cnt, flags)) {
2056 visual_bitmap[cnt] = '1';
2057 } else {
2058 visual_bitmap[cnt] = '0';
2059 }
2060 }
2061
2062 return visual_bitmap;
2063 }
2064 }
2065 }
2066
2067 return "Unknown";
2068 }
2069
PySavePacket_repr(PySavePacket * self)2070 static PyObject* PySavePacket_repr(PySavePacket* self)
2071 {
2072 PyObject* s;
2073 PoolMem buf(PM_MESSAGE);
2074
2075 Mmsg(buf,
2076 "SavePacket(fname=\"%s\", link=\"%s\", type=%ld, flags=%s, "
2077 "no_read=%d, portable=%d, accurate_found=%d, "
2078 "cmd=\"%s\", save_time=%ld, delta_seq=%ld, object_name=\"%s\", "
2079 "object=\"%s\", object_len=%ld, object_index=%ld)",
2080 PyGetStringValue(self->fname), PyGetStringValue(self->link), self->type,
2081 print_flags_bitmap(self->flags), self->no_read, self->portable,
2082 self->accurate_found, self->cmd, self->save_time, self->delta_seq,
2083 PyGetStringValue(self->object_name), PyGetByteArrayValue(self->object),
2084 self->object_len, self->object_index);
2085
2086 s = PyUnicode_FromString(buf.c_str());
2087
2088 return s;
2089 }
2090
2091 /**
2092 * Initialization.
2093 */
PySavePacket_init(PySavePacket * self,PyObject * args,PyObject * kwds)2094 static int PySavePacket_init(PySavePacket* self, PyObject* args, PyObject* kwds)
2095 {
2096 static char* kwlist[]
2097 = {(char*)"fname", (char*)"link", (char*)"type",
2098 (char*)"flags", (char*)"no_read", (char*)"portable",
2099 (char*)"accurate_found", (char*)"cmd", (char*)"save_time",
2100 (char*)"delta_seq", (char*)"object_name", (char*)"object",
2101 (char*)"object_len", (char*)"object_index", NULL};
2102 self->fname = NULL;
2103 self->link = NULL;
2104 self->type = 0;
2105 self->flags = NULL;
2106 self->no_read = false;
2107 self->portable = false;
2108 self->accurate_found = false;
2109 self->cmd = NULL;
2110 self->save_time = 0;
2111 self->delta_seq = 0;
2112 self->object_name = NULL;
2113 self->object = NULL;
2114 self->object_len = 0;
2115 self->object_index = 0;
2116
2117 if (!PyArg_ParseTupleAndKeywords(
2118 args, kwds, "|OOiOpppsiiOOii", kwlist, &self->fname, &self->link,
2119 &self->type, &self->flags, &self->no_read, &self->portable,
2120 &self->accurate_found, &self->cmd, &self->save_time, &self->delta_seq,
2121 &self->object_name, &self->object, &self->object_len,
2122 &self->object_index)) {
2123 return -1;
2124 }
2125 return 0;
2126 }
2127
2128 /**
2129 * Destructor.
2130 */
PySavePacket_dealloc(PySavePacket * self)2131 static void PySavePacket_dealloc(PySavePacket* self)
2132 {
2133 if (self->fname) { Py_XDECREF(self->fname); }
2134 if (self->link) { Py_XDECREF(self->link); }
2135 if (self->flags) { Py_XDECREF(self->flags); }
2136 if (self->object_name) { Py_XDECREF(self->object_name); }
2137 if (self->object) { Py_XDECREF(self->object); }
2138 if (self->statp) { Py_XDECREF(self->statp); }
2139 PyObject_Del(self);
2140 }
2141
2142 /**
2143 * Python specific handlers for PyRestorePacket structure mapping.
2144 */
2145
2146 /**
2147 * Representation.
2148 */
PyRestorePacket_repr(PyRestorePacket * self)2149 static PyObject* PyRestorePacket_repr(PyRestorePacket* self)
2150 {
2151 PyObject *stat_repr, *s;
2152 PoolMem buf(PM_MESSAGE);
2153
2154 stat_repr = PyObject_Repr(self->statp);
2155 Mmsg(buf,
2156 "RestorePacket(stream=%d, data_stream=%ld, type=%ld, file_index=%ld, "
2157 "linkFI=%ld, uid=%ld, statp=\"%s\", attrEx=\"%s\", ofname=\"%s\", "
2158 "olname=\"%s\", where=\"%s\", RegexWhere=\"%s\", replace=%d, "
2159 "create_status=%d)",
2160 self->stream, self->data_stream, self->type, self->file_index,
2161 self->LinkFI, self->uid, PyGetStringValue(stat_repr), self->attrEx,
2162 self->ofname, self->olname, self->where, self->RegexWhere, self->replace,
2163 self->create_status);
2164
2165 s = PyUnicode_FromString(buf.c_str());
2166 Py_DECREF(stat_repr);
2167
2168 return s;
2169 }
2170
2171 /**
2172 * Initialization.
2173 */
PyRestorePacket_init(PyRestorePacket * self,PyObject * args,PyObject * kwds)2174 static int PyRestorePacket_init(PyRestorePacket* self,
2175 PyObject* args,
2176 PyObject* kwds)
2177 {
2178 static char* kwlist[]
2179 = {(char*)"stream", (char*)"data_stream", (char*)"type",
2180 (char*)"file_index", (char*)"linkFI", (char*)"uid",
2181 (char*)"statp", (char*)"attrEX", (char*)"ofname",
2182 (char*)"olname", (char*)"where", (char*)"regexwhere",
2183 (char*)"replace", (char*)"create_status", NULL};
2184
2185 self->stream = 0;
2186 self->data_stream = 0;
2187 self->type = 0;
2188 self->file_index = 0;
2189 self->LinkFI = 0;
2190 self->uid = 0;
2191 self->statp = NULL;
2192 self->attrEx = NULL;
2193 self->ofname = NULL;
2194 self->olname = NULL;
2195 self->where = NULL;
2196 self->RegexWhere = NULL;
2197 self->replace = 0;
2198 self->create_status = 0;
2199
2200 if (!PyArg_ParseTupleAndKeywords(
2201 args, kwds, "|iiiiiIosssssii", kwlist, &self->stream,
2202 &self->data_stream, &self->type, &self->file_index, &self->LinkFI,
2203 &self->uid, &self->statp, &self->attrEx, &self->ofname, &self->olname,
2204 &self->where, &self->RegexWhere, &self->replace,
2205 &self->create_status)) {
2206 return -1;
2207 }
2208
2209 return 0;
2210 }
2211
2212 /**
2213 * Destructor.
2214 */
PyRestorePacket_dealloc(PyRestorePacket * self)2215 static void PyRestorePacket_dealloc(PyRestorePacket* self)
2216 {
2217 PyObject_Del(self);
2218 }
2219
2220 /**
2221 * Python specific handlers for PyIoPacket structure mapping.
2222 */
2223
2224 /**
2225 * Representation.
2226 */
PyIoPacket_repr(PyIoPacket * self)2227 static PyObject* PyIoPacket_repr(PyIoPacket* self)
2228 {
2229 PyObject* s;
2230 PoolMem buf(PM_MESSAGE);
2231
2232 Mmsg(buf,
2233 "IoPacket(func=%d, count=%ld, flags=%ld, mode=%04o, "
2234 "buf=\"%s\", fname=\"%s\", status=%ld, io_errno=%ld, lerror=%ld, "
2235 "whence=%ld, offset=%lld, win32=%d)",
2236 self->func, self->count, self->flags, (self->mode & ~S_IFMT),
2237 PyGetByteArrayValue(self->buf), self->fname, self->status,
2238 self->io_errno, self->lerror, self->whence, self->offset, self->win32);
2239 s = PyUnicode_FromString(buf.c_str());
2240
2241 return s;
2242 }
2243
2244 /**
2245 * Initialization.
2246 */
PyIoPacket_init(PyIoPacket * self,PyObject * args,PyObject * kwds)2247 static int PyIoPacket_init(PyIoPacket* self, PyObject* args, PyObject* kwds)
2248 {
2249 static char* kwlist[] = {(char*)"func",
2250 (char*)"count",
2251 (char*)"flags",
2252 (char*)"mode",
2253 (char*)"buf",
2254 (char*)"fname",
2255 (char*)"status",
2256 (char*)"io_errno",
2257 (char*)"lerror",
2258 (char*)"whence",
2259 (char*)"offset",
2260 (char*)"win32",
2261 NULL};
2262
2263 self->func = 0;
2264 self->count = 0;
2265 self->flags = 0;
2266 self->mode = 0;
2267 self->buf = NULL;
2268 self->fname = NULL;
2269 self->status = 0;
2270 self->io_errno = 0;
2271 self->lerror = 0;
2272 self->whence = 0;
2273 self->offset = 0;
2274 self->win32 = false;
2275
2276 if (!PyArg_ParseTupleAndKeywords(
2277 args, kwds, "|Hiiiosiiiilc", kwlist, &self->func, &self->count,
2278 &self->flags, &self->mode, &self->buf, &self->fname, &self->status,
2279 &self->io_errno, &self->lerror, &self->whence, &self->offset,
2280 &self->win32)) {
2281 return -1;
2282 }
2283
2284 return 0;
2285 }
2286
2287 /**
2288 * Destructor.
2289 */
PyIoPacket_dealloc(PyIoPacket * self)2290 static void PyIoPacket_dealloc(PyIoPacket* self)
2291 {
2292 if (self->buf) { Py_XDECREF(self->buf); }
2293 PyObject_Del(self);
2294 }
2295
2296 /**
2297 * Python specific handlers for PyAclPacket structure mapping.
2298 */
2299
2300 /**
2301 * Representation.
2302 */
PyAclPacket_repr(PyAclPacket * self)2303 static PyObject* PyAclPacket_repr(PyAclPacket* self)
2304 {
2305 PyObject* s;
2306 PoolMem buf(PM_MESSAGE);
2307
2308 Mmsg(buf, "AclPacket(fname=\"%s\", content=\"%s\")", self->fname,
2309 PyGetByteArrayValue(self->content));
2310 s = PyUnicode_FromString(buf.c_str());
2311
2312 return s;
2313 }
2314
2315 /**
2316 * Initialization.
2317 */
PyAclPacket_init(PyAclPacket * self,PyObject * args,PyObject * kwds)2318 static int PyAclPacket_init(PyAclPacket* self, PyObject* args, PyObject* kwds)
2319 {
2320 static char* kwlist[] = {(char*)"fname", (char*)"content", NULL};
2321
2322 self->fname = NULL;
2323 self->content = NULL;
2324
2325 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|so", kwlist, &self->fname,
2326 &self->content)) {
2327 return -1;
2328 }
2329
2330 return 0;
2331 }
2332
2333 /**
2334 * Destructor.
2335 */
PyAclPacket_dealloc(PyAclPacket * self)2336 static void PyAclPacket_dealloc(PyAclPacket* self)
2337 {
2338 if (self->content) { Py_XDECREF(self->content); }
2339 PyObject_Del(self);
2340 }
2341
2342 /**
2343 * Python specific handlers for PyIOPacket structure mapping.
2344 */
2345
2346 /**
2347 * Representation.
2348 */
PyXattrPacket_repr(PyXattrPacket * self)2349 static PyObject* PyXattrPacket_repr(PyXattrPacket* self)
2350 {
2351 PyObject* s;
2352 PoolMem buf(PM_MESSAGE);
2353
2354 Mmsg(buf, "XattrPacket(fname=\"%s\", name=\"%s\", value=\"%s\")", self->fname,
2355 PyGetByteArrayValue(self->name), PyGetByteArrayValue(self->value));
2356 s = PyUnicode_FromString(buf.c_str());
2357
2358 return s;
2359 }
2360
2361 /**
2362 * Initialization.
2363 */
PyXattrPacket_init(PyXattrPacket * self,PyObject * args,PyObject * kwds)2364 static int PyXattrPacket_init(PyXattrPacket* self,
2365 PyObject* args,
2366 PyObject* kwds)
2367 {
2368 static char* kwlist[] = {(char*)"fname", (char*)"name", (char*)"value", NULL};
2369
2370 self->fname = NULL;
2371 self->name = NULL;
2372 self->value = NULL;
2373
2374 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|soo", kwlist, &self->fname,
2375 &self->name, &self->value)) {
2376 return -1;
2377 }
2378
2379 return 0;
2380 }
2381
2382 /**
2383 * Destructor.
2384 */
PyXattrPacket_dealloc(PyXattrPacket * self)2385 static void PyXattrPacket_dealloc(PyXattrPacket* self)
2386 {
2387 if (self->value) { Py_XDECREF(self->value); }
2388 if (self->name) { Py_XDECREF(self->name); }
2389 PyObject_Del(self);
2390 }
2391
2392 } /* namespace filedaemon */
2393