Skip to content

Commit 7bd2e7b

Browse files
authored
Merge pull request bareos#2205
set environment vars in bpipe fd plugin
2 parents 674e765 + 6cebe15 commit 7bd2e7b

File tree

30 files changed

+460
-105
lines changed

30 files changed

+460
-105
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
110110
- ndmp-bareos: Introduce incremental loop, restore 2nd file explicitly [PR #2269]
111111
- systemtest: always incremental add one job with one removed file [PR #2329]
112112
- webui: add summary subscription report [PR #2340]
113+
- set environment vars in bpipe fd plugin [PR #2205]
113114

114115
[Issue #1965]: https://bugs.bareos.org/view.php?id=1965
115116
[PR #1697]: https://github.com/bareos/bareos/pull/1697
@@ -162,6 +163,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
162163
[PR #2194]: https://github.com/bareos/bareos/pull/2194
163164
[PR #2201]: https://github.com/bareos/bareos/pull/2201
164165
[PR #2202]: https://github.com/bareos/bareos/pull/2202
166+
[PR #2205]: https://github.com/bareos/bareos/pull/2205
165167
[PR #2207]: https://github.com/bareos/bareos/pull/2207
166168
[PR #2211]: https://github.com/bareos/bareos/pull/2211
167169
[PR #2213]: https://github.com/bareos/bareos/pull/2213

core/scripts/bareos-ctl-fd-win.in

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,20 @@ srv_libdir="$(dirname "$(readlink "${BAREOS_FILEDAEMON_BINARY}")")"
3333
case "$1" in
3434
start)
3535
exec 3>&1 4>&2 >/dev/null 2>&1
36-
nssm install $srv_name $(cygpath -w "${BAREOS_FILEDAEMON_BINARY}")
37-
nssm set $srv_name AppParameters "-d 1000 -v -c $(cygpath -w ${srv_configdir})"
38-
nssm set $srv_name AppDirectory "$(cygpath -w ${srv_rundir})"
39-
nssm set $srv_name AppStdout "$(cygpath -w ${srv_rundir})/log/${srv_name}.stdout.log"
40-
nssm set $srv_name AppStdErr "$(cygpath -w ${srv_rundir})/log/${srv_name}.stderr.log"
41-
nssm set $srv_name AppExit Default Restart
42-
nssm set $srv_name AppNoConsole 1
43-
nssm set $srv_name DisplayName $srv_name
44-
nssm set $srv_name ObjectName LocalSystem
45-
nssm set $srv_name Start SERVICE_DEMAND_START
46-
nssm set $srv_name Type SERVICE_WIN32_OWN_PROCESS
47-
nssm set $srv_name AppEnvironmentExtra PATH="$(cygpath -w ${srv_libdir});%PATH%"
36+
nssm install "${srv_name}" "$(cygpath -w "${BAREOS_FILEDAEMON_BINARY:?}")"
37+
nssm set "${srv_name}" AppParameters "-d 1000 -v -c $(cygpath -w "${srv_configdir}")"
38+
nssm set "${srv_name}" AppDirectory "$(cygpath -w "${srv_rundir}")"
39+
nssm set "${srv_name}" AppStdout "$(cygpath -w "${srv_rundir}")/log/${srv_name}.stdout.log"
40+
nssm set "${srv_name}" AppStdErr "$(cygpath -w "${srv_rundir}")/log/${srv_name}.stderr.log"
41+
nssm set "${srv_name}" AppExit Default Restart
42+
nssm set "${srv_name}" AppNoConsole 1
43+
nssm set "${srv_name}" DisplayName "${srv_name}"
44+
nssm set "${srv_name}" ObjectName LocalSystem
45+
nssm set "${srv_name}" Start SERVICE_DEMAND_START
46+
nssm set "${srv_name}" Type SERVICE_WIN32_OWN_PROCESS
47+
nssm set "${srv_name}" AppEnvironmentExtra my_env_variable="${my_env_variable:-default_unused}" PATH="$(cygpath -w "${srv_libdir}");%PATH%"
4848
exec 1>&3 2>&4
49-
nssm start $srv_name
49+
nssm start "${srv_name}"
5050
;;
5151

5252
stop)

core/src/plugins/filed/bpipe/bpipe-fd.cc

Lines changed: 91 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
BAREOS® - Backup Archiving REcovery Open Sourced
33
44
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
66
77
This program is Free Software; you can redistribute it and/or
88
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);
7070
static bRC getXattr(PluginContext* ctx, xattr_pkt* xp);
7171
static bRC setXattr(PluginContext* ctx, xattr_pkt* xp);
7272

73-
static char* apply_rp_codes(PluginContext* ctx);
73+
static std::string apply_rp_codes(PluginContext* ctx, const char* fmt);
7474
static bRC parse_plugin_definition(PluginContext* ctx, void* value);
7575
static bRC plugin_has_all_arguments(PluginContext* ctx);
7676

@@ -296,35 +296,64 @@ static bRC pluginIO(PluginContext* ctx, io_pkt* io)
296296
switch (io->func) {
297297
case IO_OPEN:
298298
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+
}
328357
}
329358
}
330359
sleep(1); /* let pipe connect */
@@ -458,77 +487,47 @@ static bRC setXattr(PluginContext*, xattr_pkt*) { return bRC_OK; }
458487
* 'ifolder' => 'o', chr(111)
459488
* 'never' => 'n', chr(110)
460489
*
461-
* This function will allocate the required amount of memory with malloc.
462-
* Need to be free()d manually.
463-
*
464490
* Inspired by edit_job_codes in lib/util.c
465491
*/
466-
static char* apply_rp_codes(PluginContext* ctx)
492+
static std::string apply_rp_codes(PluginContext* ctx, const char* fmt)
467493
{
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);
472495
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+
}
473519

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
489522
}
490-
}
491523

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
524526
} else {
525-
add[0] = *p;
526-
add[1] = 0;
527-
str = add;
527+
output += p[0];
528528
}
529-
strcat(omsg, str);
530529
}
531-
return omsg;
530+
return output;
532531
}
533532

534533
// Strip any backslashes in the string.

docs/manuals/source/TasksAndConcepts/Plugins/FileDaemonPlugins/BpipePlugin.rst.inc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,19 @@ Please note that the two items above describing the "reader" and "writer", these
6363
automatically create the path to the file. Either the path must exist, or you must explicitly do so with your command or in a shell script.
6464

6565
See the examples about :ref:`backup-postgresql` and :ref:`backup-mysql`.
66+
67+
Environment variables
68+
^^^^^^^^^^^^^^^^^^^^^
69+
70+
For both the readprogram and the writeprogram, the following environment variables are being set:
71+
72+
================ =================================================
73+
BareosClientName Client name of the current job
74+
BareosJobId Job id of the current job
75+
BareosJobLevel Job level of the current job
76+
BareosSinceTime Since time of the differential/incremental backup
77+
BareosJobType Job type of the current job
78+
================ =================================================
79+
80+
The BareosSinceTime is 0 during full backups and restores.
81+
The BareosjobLevel is the space character (" ") during restores.

systemtests/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ add_subdirectory(bareos-acl)
3232
add_subdirectory(bconsole-basic)
3333
add_subdirectory(bconsole-pam)
3434
add_subdirectory(block-size)
35+
add_subdirectory(bpipe-fd)
3536
add_subdirectory(bscan-bextract-bls-bcopy-btape)
3637
add_subdirectory(catalog)
3738
add_subdirectory(checkpoints)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# BAREOS® - Backup Archiving REcovery Open Sourced
2+
#
3+
# Copyright (C) 2025-2025 Bareos GmbH & Co. KG
4+
#
5+
# This program is Free Software; you can redistribute it and/or
6+
# modify it under the terms of version three of the GNU Affero General Public
7+
# License as published by the Free Software Foundation and included
8+
# in the file LICENSE.
9+
#
10+
# This program is distributed in the hope that it will be useful, but
11+
# WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
# Affero General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU Affero General Public License
16+
# along with this program; if not, write to the Free Software
17+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18+
# 02110-1301, USA.
19+
20+
get_filename_component(BASENAME ${CMAKE_CURRENT_BINARY_DIR} NAME)
21+
create_systemtest(${SYSTEMTEST_PREFIX} ${BASENAME})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# these should get overwritten in bpipe-fd
2+
export BareosClientName='-1'
3+
export BareosJobId='-1'
4+
export BareosJobLevel='-1'
5+
export BareosSinceTime='-1'
6+
export BareosJobType='-1'
7+
8+
# this should be preserved inside bpipe-fd
9+
export my_env_variable="still there"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Catalog {
2+
Name = MyCatalog
3+
dbname = "@db_name@"
4+
dbuser = "@db_user@"
5+
dbpassword = "@db_password@"
6+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Client {
2+
Name = bareos-fd
3+
Description = "Client resource of the Director itself."
4+
Address = @hostname@
5+
Password = "@fd_password@" # password for FileDaemon
6+
Port = @fd_port@
7+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Director { # define myself
2+
Name = bareos-dir
3+
QueryFile = "@scriptdir@/query.sql"
4+
Maximum Concurrent Jobs = 10
5+
Password = "@dir_password@" # Console password
6+
Messages = Daemon
7+
Auditing = yes
8+
Working Directory = "@working_dir@"
9+
DirPort = @dir_port@
10+
}

0 commit comments

Comments
 (0)