|
2 | 2 | BAREOS® - Backup Archiving REcovery Open Sourced |
3 | 3 |
|
4 | 4 | Copyright (C) 2007-2012 Free Software Foundation Europe e.V. |
5 | | - Copyright (C) 2014-2024 Bareos GmbH & Co. KG |
| 5 | + Copyright (C) 2014-2025 Bareos GmbH & Co. KG |
6 | 6 |
|
7 | 7 | This program is Free Software; you can redistribute it and/or |
8 | 8 | modify it under the terms of version three of the GNU Affero General Public |
@@ -70,7 +70,7 @@ static bRC setAcl(PluginContext* ctx, acl_pkt* ap); |
70 | 70 | static bRC getXattr(PluginContext* ctx, xattr_pkt* xp); |
71 | 71 | static bRC setXattr(PluginContext* ctx, xattr_pkt* xp); |
72 | 72 |
|
73 | | -static char* apply_rp_codes(PluginContext* ctx); |
| 73 | +static std::string apply_rp_codes(PluginContext* ctx, const char* fmt); |
74 | 74 | static bRC parse_plugin_definition(PluginContext* ctx, void* value); |
75 | 75 | static bRC plugin_has_all_arguments(PluginContext* ctx); |
76 | 76 |
|
@@ -296,35 +296,64 @@ static bRC pluginIO(PluginContext* ctx, io_pkt* io) |
296 | 296 | switch (io->func) { |
297 | 297 | case IO_OPEN: |
298 | 298 | Dmsg(ctx, debuglevel, "bpipe-fd: IO_OPEN\n"); |
299 | | - if (io->flags & (O_CREAT | O_WRONLY)) { |
300 | | - char* writer_codes = apply_rp_codes(ctx); |
301 | | - |
302 | | - p_ctx->pfd = OpenBpipe(writer_codes, 0, "w"); |
303 | | - Dmsg(ctx, debuglevel, "bpipe-fd: IO_OPEN fd=%p writer=%s\n", p_ctx->pfd, |
304 | | - writer_codes); |
305 | | - if (!p_ctx->pfd) { |
306 | | - io->io_errno = errno; |
307 | | - Jmsg(ctx, M_FATAL, "bpipe-fd: Open pipe writer=%s failed: ERR=%s\n", |
308 | | - writer_codes, strerror(io->io_errno)); |
309 | | - Dmsg(ctx, debuglevel, |
310 | | - "bpipe-fd: Open pipe writer=%s failed: ERR=%s\n", writer_codes, |
311 | | - strerror(io->io_errno)); |
312 | | - if (writer_codes) { free(writer_codes); } |
313 | | - return bRC_Error; |
314 | | - } |
315 | | - if (writer_codes) { free(writer_codes); } |
316 | | - } else { |
317 | | - p_ctx->pfd = OpenBpipe(p_ctx->reader, 0, "r", false); |
318 | | - Dmsg(ctx, debuglevel, "bpipe-fd: IO_OPEN fd=%p reader=%s\n", p_ctx->pfd, |
319 | | - p_ctx->reader); |
320 | | - if (!p_ctx->pfd) { |
321 | | - io->io_errno = errno; |
322 | | - Jmsg(ctx, M_FATAL, "bpipe-fd: Open pipe reader=%s failed: ERR=%s\n", |
323 | | - p_ctx->reader, strerror(io->io_errno)); |
324 | | - Dmsg(ctx, debuglevel, |
325 | | - "bpipe-fd: Open pipe reader=%s failed: ERR=%s\n", p_ctx->reader, |
326 | | - strerror(io->io_errno)); |
327 | | - return bRC_Error; |
| 299 | + { |
| 300 | + int env_job_id; |
| 301 | + bareos_core_functions->getBareosValue(ctx, bVarJobId, &env_job_id); |
| 302 | + char* env_client_name; |
| 303 | + bareos_core_functions->getBareosValue(ctx, bVarFDName, |
| 304 | + &env_client_name); |
| 305 | + int env_backup_level; |
| 306 | + bareos_core_functions->getBareosValue(ctx, bVarLevel, |
| 307 | + &env_backup_level); |
| 308 | + int env_job_type; |
| 309 | + bareos_core_functions->getBareosValue(ctx, bVarType, &env_job_type); |
| 310 | + int env_since_time; |
| 311 | + bareos_core_functions->getBareosValue(ctx, bVarSinceTime, |
| 312 | + &env_since_time); |
| 313 | + |
| 314 | + std::unordered_map<std::string, std::string> env{ |
| 315 | + {"BareosClientName", std::string{env_client_name}}, |
| 316 | + {"BareosJobId", std::to_string(env_job_id)}, |
| 317 | + {"BareosJobLevel", |
| 318 | + std::string{static_cast<char>(env_backup_level)}}, |
| 319 | + {"BareosSinceTime", std::to_string(env_since_time)}, |
| 320 | + {"BareosJobType", std::string{static_cast<char>(env_job_type)}}, |
| 321 | + }; |
| 322 | + |
| 323 | + if (io->flags & (O_CREAT | O_WRONLY)) { |
| 324 | + if (!p_ctx->writer) { |
| 325 | + // this shouldn't happen as we check for this on plugin creation! |
| 326 | + Jmsg(ctx, M_FATAL, "bpipe-fd: writer command is not set\n"); |
| 327 | + return bRC_Error; |
| 328 | + } |
| 329 | + |
| 330 | + std::string writer_codes = apply_rp_codes(ctx, p_ctx->writer); |
| 331 | + |
| 332 | + p_ctx->pfd = OpenBpipe(writer_codes.c_str(), 0, "w", true, env); |
| 333 | + Dmsg(ctx, debuglevel, "bpipe-fd: IO_OPEN fd=%p writer=%s\n", |
| 334 | + p_ctx->pfd, writer_codes.c_str()); |
| 335 | + if (!p_ctx->pfd) { |
| 336 | + io->io_errno = errno; |
| 337 | + Jmsg(ctx, M_FATAL, "bpipe-fd: Open pipe writer=%s failed: ERR=%s\n", |
| 338 | + writer_codes.c_str(), strerror(io->io_errno)); |
| 339 | + Dmsg(ctx, debuglevel, |
| 340 | + "bpipe-fd: Open pipe writer=%s failed: ERR=%s\n", |
| 341 | + writer_codes.c_str(), strerror(io->io_errno)); |
| 342 | + return bRC_Error; |
| 343 | + } |
| 344 | + } else { |
| 345 | + p_ctx->pfd = OpenBpipe(p_ctx->reader, 0, "r", false, env); |
| 346 | + Dmsg(ctx, debuglevel, "bpipe-fd: IO_OPEN fd=%p reader=%s\n", |
| 347 | + p_ctx->pfd, p_ctx->reader); |
| 348 | + if (!p_ctx->pfd) { |
| 349 | + io->io_errno = errno; |
| 350 | + Jmsg(ctx, M_FATAL, "bpipe-fd: Open pipe reader=%s failed: ERR=%s\n", |
| 351 | + p_ctx->reader, strerror(io->io_errno)); |
| 352 | + Dmsg(ctx, debuglevel, |
| 353 | + "bpipe-fd: Open pipe reader=%s failed: ERR=%s\n", |
| 354 | + p_ctx->reader, strerror(io->io_errno)); |
| 355 | + return bRC_Error; |
| 356 | + } |
328 | 357 | } |
329 | 358 | } |
330 | 359 | sleep(1); /* let pipe connect */ |
@@ -458,77 +487,47 @@ static bRC setXattr(PluginContext*, xattr_pkt*) { return bRC_OK; } |
458 | 487 | * 'ifolder' => 'o', chr(111) |
459 | 488 | * 'never' => 'n', chr(110) |
460 | 489 | * |
461 | | - * This function will allocate the required amount of memory with malloc. |
462 | | - * Need to be free()d manually. |
463 | | - * |
464 | 490 | * Inspired by edit_job_codes in lib/util.c |
465 | 491 | */ |
466 | | -static char* apply_rp_codes(PluginContext* ctx) |
| 492 | +static std::string apply_rp_codes(PluginContext* ctx, const char* fmt) |
467 | 493 | { |
468 | | - char add[10]; |
469 | | - const char* str; |
470 | | - char *p, *q, *omsg, *imsg; |
471 | | - int w_count = 0, r_count = 0; |
| 494 | + ASSERT(ctx); |
472 | 495 | struct plugin_ctx* p_ctx = (struct plugin_ctx*)ctx->plugin_private_context; |
| 496 | + ASSERT(p_ctx); |
| 497 | + |
| 498 | + ASSERT(fmt); |
| 499 | + |
| 500 | + std::string output; |
| 501 | + |
| 502 | + for (char const* p = fmt; *p; ++p) { |
| 503 | + bool parsed_specifier = false; |
| 504 | + if (p[0] == '%') { |
| 505 | + switch (p[1]) { |
| 506 | + case '%': { |
| 507 | + output += "%"; |
| 508 | + parsed_specifier = true; |
| 509 | + } break; |
| 510 | + case 'w': { |
| 511 | + output += (char const*)p_ctx->where; |
| 512 | + parsed_specifier = true; |
| 513 | + } break; |
| 514 | + case 'r': { |
| 515 | + output += (char)p_ctx->replace; |
| 516 | + parsed_specifier = true; |
| 517 | + } break; |
| 518 | + } |
473 | 519 |
|
474 | | - if (!p_ctx) { return NULL; } |
475 | | - |
476 | | - imsg = p_ctx->writer; |
477 | | - if (!imsg) { return NULL; } |
478 | | - |
479 | | - if ((p = imsg)) { |
480 | | - while ((q = strstr(p, "%w"))) { |
481 | | - w_count++; |
482 | | - p = q + 1; |
483 | | - } |
484 | | - |
485 | | - p = imsg; |
486 | | - while ((q = strstr(p, "%r"))) { |
487 | | - r_count++; |
488 | | - p = q + 1; |
| 520 | + // if % is not followed by a valid specifier, we simply treat it as a |
| 521 | + // normal character |
489 | 522 | } |
490 | | - } |
491 | 523 |
|
492 | | - /* Required mem: |
493 | | - * len(imsg) |
494 | | - * + number of "where" codes * (len(where)-2) |
495 | | - * - number of "replace" codes */ |
496 | | - omsg = (char*)malloc(strlen(imsg) + (w_count * (strlen(p_ctx->where) - 2)) |
497 | | - - r_count + 1); |
498 | | - if (!omsg) { |
499 | | - Jmsg(ctx, M_FATAL, "bpipe-fd: Out of memory."); |
500 | | - return NULL; |
501 | | - } |
502 | | - |
503 | | - *omsg = 0; |
504 | | - for (p = imsg; *p; p++) { |
505 | | - if (*p == '%') { |
506 | | - switch (*++p) { |
507 | | - case '%': |
508 | | - str = "%"; |
509 | | - break; |
510 | | - case 'w': |
511 | | - str = p_ctx->where; |
512 | | - break; |
513 | | - case 'r': |
514 | | - snprintf(add, 2, "%c", p_ctx->replace); |
515 | | - str = add; |
516 | | - break; |
517 | | - default: |
518 | | - add[0] = '%'; |
519 | | - add[1] = *p; |
520 | | - add[2] = 0; |
521 | | - str = add; |
522 | | - break; |
523 | | - } |
| 524 | + if (parsed_specifier) { |
| 525 | + p += 1; // skip both characters |
524 | 526 | } else { |
525 | | - add[0] = *p; |
526 | | - add[1] = 0; |
527 | | - str = add; |
| 527 | + output += p[0]; |
528 | 528 | } |
529 | | - strcat(omsg, str); |
530 | 529 | } |
531 | | - return omsg; |
| 530 | + return output; |
532 | 531 | } |
533 | 532 |
|
534 | 533 | // Strip any backslashes in the string. |
|
0 commit comments