2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Written by: Eric Bollengier, December MMXIII
23 #define OUTPUT_C /* control dll export in output.h */
27 /* use new output (lowercase, no special char) */
28 #define OF_USE_NEW_OUTPUT 1
30 void OutputWriter::parse_options(const char *options)
33 const char *p = options;
40 set_time_format(OW_DEFAULT_TIMEFORMAT);
41 set_separator(OW_DEFAULT_SEPARATOR);
44 case 'S': /* object separator */
45 while(isdigit(*(p+1))) {
46 nb = nb*10 + (*(++p) - '0');
49 set_object_separator((char) nb);
54 flags |= OF_USE_NEW_OUTPUT; /* lowercase and only isalpha */
57 case 't': /* Time format */
58 if (isdigit(*(p+1))) {
60 set_time_format((OutputTimeType) nb);
64 case 's': /* Separator */
65 while(isdigit(*(p+1))) {
66 nb = nb*10 + (*(++p) - '0');
69 set_separator((char) nb);
79 char *OutputWriter::get_options(char *dest)
83 if (separator != OW_DEFAULT_SEPARATOR) {
84 snprintf(dest, 50, "s%d", (int)separator);
86 if (object_separator) {
87 snprintf(ed1, sizeof(ed1), "S%d", (int) object_separator);
88 bstrncat(dest, ed1, sizeof(ed1));
90 if (timeformat != OW_DEFAULT_TIMEFORMAT) {
91 snprintf(ed1, sizeof(ed1), "t%d", (int) timeformat);
92 bstrncat(dest, ed1, sizeof(ed1));
94 if (flags & OF_USE_NEW_OUTPUT) {
95 bstrncat(dest, "o", 1);
100 void OutputWriter::get_buf(bool append)
103 buf = get_pool_memory(PM_MESSAGE);
106 } else if (!append) {
111 char *OutputWriter::start_group(const char *name, bool append)
114 pm_strcat(buf, name);
115 pm_strcat(buf, ":\n");
119 char *OutputWriter::end_group(bool append)
122 pm_strcat(buf, "\n");
127 char *OutputWriter::start_list(const char *name, bool append)
130 pm_strcat(buf, name);
131 pm_strcat(buf, ": [\n");
135 char *OutputWriter::end_list(bool append)
138 pm_strcat(buf, "]\n");
145 * OT_STRING, "name", "value",
146 * OT_PINT32, "age", 10,
147 * OT_TIME, "birth-date", 1120202002,
148 * OT_PINT64, "weight", 100,
152 * "name=value\nage=10\nbirt-date=2012-01-12 10:20:00\nweight=100\n"
155 char *OutputWriter::get_output(OutputType first, ...)
160 get_buf(true); /* Append to the current string */
162 va_start(arg_ptr, first);
163 ret = get_output(arg_ptr, &buf, first);
171 * OT_STRING, "name", "value",
172 * OT_PINT32, "age", 10,
173 * OT_TIME, "birth-date", 1120202002,
174 * OT_PINT64, "weight", 100,
178 * "name=value\nage=10\nbirt-date=2012-01-12 10:20:00\nweight=100\n"
181 char *OutputWriter::get_output(POOLMEM **out, OutputType first, ...)
186 va_start(arg_ptr, first);
187 ret = get_output(arg_ptr, out, first);
193 char *OutputWriter::get_output(va_list ap, POOLMEM **out, OutputType first)
195 char ed1[MAX_TIME_LENGTH];
202 char *s = NULL, *k = NULL;
205 POOLMEM *tmp2 = get_pool_memory(PM_FNAME);
206 POOLMEM *tmp = get_pool_memory(PM_FNAME);
207 OutputType val = first;
209 while (val != OT_END) {
213 /* Some arguments are not using a keyword */
222 k = va_arg(ap, char *); /* Get the variable name */
224 /* If requested, we can put the keyword in lowercase */
225 if (flags & OF_USE_NEW_OUTPUT) {
226 tmp2 = check_pool_memory_size(tmp2, strlen(k)+1);
227 for (i = 0; k[i] ; i++) {
229 tmp2[i] = tolower(k[i]);
239 //Dmsg2(000, "%d - %s\n", val, k);
243 lst = va_arg(ap, alist *);
247 foreach_alist(s, lst) {
254 pm_strcat(tmp, separator_str);
257 lst = va_arg(ap, alist *);
259 pm_strcpy(tmp, "plugins=");
261 foreach_alist(plug, lst) {
265 pm_strcat(tmp, plug->file);
268 pm_strcat(tmp, separator_str);
271 d = va_arg(ap, double);
272 Mmsg(tmp, "%s=%.2f%c", k, d, separator);
276 s = va_arg(ap, char *);
277 Mmsg(tmp, "%s=%s%c", k, NPRTB(s), separator) ;
281 i32 = va_arg(ap, int32_t);
282 Mmsg(tmp, "%s=%d%c", k, i32, separator);
287 if (val == OT_UTIME) {
288 bt = va_arg(ap, utime_t);
290 bt = va_arg(ap, btime_t);
292 switch (timeformat) {
293 case OTT_TIME_NC: /* Formatted time for user display: dd-Mon hh:mm */
294 bstrftime_ny(ed1, sizeof(ed1), bt);
297 case OTT_TIME_UNIX: /* unix timestamp */
298 bsnprintf(ed1, sizeof(ed1), "%lld", bt);
302 /* wanted fallback */
304 bstrutime(ed1, sizeof(ed1), bt);
306 Mmsg(tmp, "%s_epoch=%lld%c%s=%s%c", k, bt, separator, k, ed1, separator);
311 i64 = va_arg(ap, int64_t);
312 Mmsg(tmp, "%s=%lld%c", k, i64, separator);
316 u64 = va_arg(ap, uint64_t);
317 Mmsg(tmp, "%s=%llu%c", k, u64, separator);
321 i64 = va_arg(ap, int);
322 Mmsg(tmp, "%s=%lld%c", k, i64, separator);
328 i32 = va_arg(ap, int32_t);
329 Mmsg(tmp, "%s=%c%c", k, (char) i32, separator);
337 pm_strcpy(tmp, "\n");
342 if (object_separator) {
343 for(; i < 32 ; i++) {
344 tmp[i] = object_separator;
352 /* wanted fallback */
359 val = (OutputType) va_arg(ap, int); /* OutputType is promoted to int when using ... */
363 free_pool_memory(tmp);
364 free_pool_memory(tmp2);
365 //Dmsg1(000, "%s", *out);
372 void _ok(const char *file, int l, const char *op, int value, const char *label)
377 printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
379 printf("OK %.30s\n", label);
383 #define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
385 void _nok(const char *file, int l, const char *op, int value, const char *label)
390 printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
392 printf("OK %.30s\n", label);
396 #define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
400 printf("Result %i/%i OK\n", nb - err, nb);
404 int main(int argc, char **argv)
408 POOLMEM *tmp = get_pool_memory(PM_FNAME);
412 const char *ptr = "my value";
413 char *str = bstrdup("ptr");
416 btime_t t = time(NULL);
418 ok(strcmp(wt.get_options(ed1), "") == 0, "Default options");
420 Pmsg1(000, "%s", wt.start_group("test"));
422 wt.get_output(&tmp, OT_CLEAR,
423 OT_STRING, "test", "my value",
424 OT_STRING, "test2", ptr,
425 OT_STRING, "test3", str,
427 OT_INT32, "nb32", nb32,
428 OT_INT64, "nb64", nb64,
432 Pmsg1(000, "%s", tmp);
434 free_pool_memory(tmp);
438 wt.get_output(OT_CLEAR,
440 OT_STRING, "test", "my value",
441 OT_STRING, "test2", ptr,
442 OT_STRING, "test3", str,
444 OT_INT32, "nb32", nb32,
445 OT_INT64, "nb64", nb64,
450 wt.set_time_format(OTT_TIME_UNIX);
451 ok(strcmp("t1", wt.get_options(ed1)) == 0, "Check unix time format");
454 wt.get_output(OT_CLEAR,
458 wt.set_time_format(OTT_TIME_NC);
459 ok(strcmp("t2", wt.get_options(ed1)) == 0, "Check NC time format");
462 wt.get_output(OT_CLEAR,
466 Pmsg1(000, "%s", wt.end_group(false));
468 wt.parse_options("s43t1O");
469 ok(strcmp(wt.get_options(ed1), "s43t1") == 0, "Check options after parsing");
472 wt.get_output(OT_CLEAR,
474 OT_STRING, "brazil", "test",
476 "+brazil=test+") != NULL,
479 wt.parse_options("CS35");
480 ok(strcmp(wt.get_options(ed1), "S35") == 0, "Check options after parsing");
483 wt.get_output(OT_CLEAR,
485 OT_STRING, "test", "my value",
486 OT_STRING, "test2", ptr,
489 OT_STRING, "test", "my value",
490 OT_STRING, "test2", ptr,