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.
21 * Bacula Json library routines
23 * Kern Sibbald, September MMXII
30 extern s_kw msg_types[];
31 extern RES_TABLE resources[];
39 extern "C" { // work around visual compiler mangling variables
48 /* default { { "Director": { "Name": aa, ...} }, { "Job": {..} */
49 bool do_list; /* [ {}, {}, ..] or { "aa": {}, "bb": {}, ...} */
50 bool do_one; /* { "Name": "aa", "Description": "test, ... } */
51 bool do_only_data; /* [ {}, {}, {}, ] */
54 regex_t directive_reg;
57 static void sendit(void *sock, const char *fmt, ...)
62 va_start(arg_ptr, fmt);
63 bvsnprintf(buf, sizeof(buf), (char *)fmt, arg_ptr);
69 void init_hpkt(HPKT &hpkt)
71 memset(&hpkt, 0, sizeof(hpkt));
72 hpkt.edbuf = get_pool_memory(PM_EMSG);
73 hpkt.edbuf2 = get_pool_memory(PM_EMSG);
75 hpkt.hfunc = HF_DISPLAY;
79 void term_hpkt(HPKT &hpkt)
81 free_pool_memory(hpkt.edbuf);
82 free_pool_memory(hpkt.edbuf2);
83 memset(&hpkt, 0, sizeof(hpkt));
87 * Strip long options out of fo->opts string so that
88 * they will not give us false matches for regular
89 * 1 or 2 character options.
91 void strip_long_opts(char *out, const char *in)
96 /* V, C, J, and P are long options, skip them */
102 p++; /* skip to after : */
105 /* Copy everything else */
111 *out = 0; /* terminate string */
114 void edit_alist(HPKT &hpkt)
119 pm_strcpy(hpkt.edbuf, " [");
120 foreach_alist(citem, hpkt.list) {
122 pm_strcat(hpkt.edbuf, ", ");
124 pm_strcat(hpkt.edbuf, quote_string(hpkt.edbuf2, citem));
127 pm_strcat(hpkt.edbuf, "]");
130 void edit_msg_types(HPKT &hpkt, DEST *dest)
133 bool first_type = true;
136 pm_strcpy(hpkt.edbuf, "[");
137 for (i=1; i<M_MAX; i++) {
138 if (bit_is_set(i, dest->msg_types)) {
140 if (!first_type) pm_strcat(hpkt.edbuf, ",");
142 for (j=0; msg_types[j].name; j++) {
143 if ((int)msg_types[j].token == i) {
144 pm_strcat(hpkt.edbuf, "\"");
145 pm_strcat(hpkt.edbuf, msg_types[j].name);
146 pm_strcat(hpkt.edbuf, "\"");
152 sendit(NULL, "No find for type=%d\n", i);
158 * Note, if we have more than half of the total items,
159 * redo using All and !item, which will give fewer items
162 if (count > M_MAX/2) {
163 pm_strcpy(hpkt.edbuf, "[\"All\"");
164 for (i=1; i<M_MAX; i++) {
165 if (!bit_is_set(i, dest->msg_types)) {
167 pm_strcat(hpkt.edbuf, ",");
168 for (j=0; msg_types[j].name; j++) {
169 if ((int)msg_types[j].token == i) {
170 pm_strcat(hpkt.edbuf, "\"!");
171 pm_strcat(hpkt.edbuf, msg_types[j].name);
172 pm_strcat(hpkt.edbuf, "\"");
178 sendit(NULL, "No find for type=%d in second loop\n", i);
180 } else if (i == M_SAVED) {
181 /* Saved is not set by default, users must explicitly use it
182 * on the configuration line
184 pm_strcat(hpkt.edbuf, ",\"Saved\"");
188 pm_strcat(hpkt.edbuf, "]");
191 bool display_global_item(HPKT &hpkt)
195 if (hpkt.ritem->handler == store_res) {
197 } else if (hpkt.ritem->handler == store_str ||
198 hpkt.ritem->handler == store_name ||
199 hpkt.ritem->handler == store_password ||
200 hpkt.ritem->handler == store_strname ||
201 hpkt.ritem->handler == store_dir) {
202 display_string_pair(hpkt);
203 } else if (hpkt.ritem->handler == store_int32 ||
204 hpkt.ritem->handler == store_pint32 ||
205 hpkt.ritem->handler == store_size32) {
206 display_int32_pair(hpkt);
207 } else if (hpkt.ritem->handler == store_size64 ||
208 hpkt.ritem->handler == store_int64 ||
209 hpkt.ritem->handler == store_time ||
210 hpkt.ritem->handler == store_speed) {
211 display_int64_pair(hpkt);
212 } else if (hpkt.ritem->handler == store_bool) {
213 display_bool_pair(hpkt);
214 } else if (hpkt.ritem->handler == store_msgs) {
216 } else if (hpkt.ritem->handler == store_bit) {
217 display_bit_pair(hpkt);
218 } else if (hpkt.ritem->handler == store_alist_res) {
219 found = display_alist_res(hpkt); /* In some cases, the list is null... */
220 } else if (hpkt.ritem->handler == store_alist_str) {
221 found = display_alist_str(hpkt); /* In some cases, the list is null... */
230 * Called here for each store_msgs resource
232 void display_msgs(HPKT &hpkt)
234 MSGS *msgs = (MSGS *)hpkt.ritem->value; /* Message res */
235 DEST *dest; /* destination chain */
238 if (!hpkt.in_store_msg) {
239 hpkt.in_store_msg = true;
240 sendit(NULL, "\n \"Destinations\": [");
242 for (dest=msgs->dest_chain; dest; dest=dest->next) {
243 if (dest->dest_code == hpkt.ritem->code) {
244 if (!first) sendit(NULL, ",");
246 edit_msg_types(hpkt, dest);
247 switch (hpkt.ritem->code) {
248 /* Output only message types */
254 sendit(NULL, "\n {\n \"Type\": \"%s\","
255 "\n \"MsgTypes\": %s\n }",
256 hpkt.ritem->name, hpkt.edbuf);
258 /* Output MsgTypes, Where */
262 sendit(NULL, "\n {\n \"Type\": \"%s\","
263 "\n \"MsgTypes\": %s,\n",
264 hpkt.ritem->name, hpkt.edbuf);
265 sendit(NULL, " \"Where\": [%s]\n }",
266 quote_where(hpkt.edbuf, dest->where));
268 /* Now we edit MsgTypes, Where, and Command */
271 case MD_MAIL_ON_ERROR:
272 case MD_MAIL_ON_SUCCESS:
273 sendit(NULL, "\n {\n \"Type\": \"%s\","
274 "\n \"MsgTypes\": %s,\n",
275 hpkt.ritem->name, hpkt.edbuf);
276 sendit(NULL, " \"Where\": [%s],\n",
277 quote_where(hpkt.edbuf, dest->where));
278 sendit(NULL, " \"Command\": %s\n }",
279 quote_string(hpkt.edbuf, dest->mail_cmd));
287 * Called here if the ITEM_LAST is set in flags,
288 * that means there are no more items to examine
289 * for this resource and that we can close any
292 void display_last(HPKT &hpkt)
294 if (hpkt.in_store_msg) {
295 hpkt.in_store_msg = false;
296 sendit(NULL, "\n ]");
300 void display_alist(HPKT &hpkt)
303 sendit(NULL, "%s", hpkt.edbuf);
306 bool display_alist_str(HPKT &hpkt)
308 hpkt.list = (alist *)(*(hpkt.ritem->value));
312 sendit(NULL, "\n \"%s\":", hpkt.ritem->name);
317 bool display_alist_res(HPKT &hpkt)
323 list = (alist *)(*(hpkt.ritem->value));
327 sendit(NULL, "\n \"%s\":", hpkt.ritem->name);
329 foreach_alist(res, list) {
333 sendit(NULL, "%s", quote_string(hpkt.edbuf, res->name));
340 void display_res(HPKT &hpkt)
344 res = (RES *)*hpkt.ritem->value;
345 sendit(NULL, "\n \"%s\": %s", hpkt.ritem->name,
346 quote_string(hpkt.edbuf, res->name));
349 void display_string_pair(HPKT &hpkt)
351 sendit(NULL, "\n \"%s\": %s", hpkt.ritem->name,
352 quote_string(hpkt.edbuf, *hpkt.ritem->value));
355 void display_int32_pair(HPKT &hpkt)
358 sendit(NULL, "\n \"%s\": %s", hpkt.ritem->name,
359 edit_int64(*(int32_t *)hpkt.ritem->value, ed1));
362 void display_int64_pair(HPKT &hpkt)
365 sendit(NULL, "\n \"%s\": %s", hpkt.ritem->name,
366 edit_int64(*(int64_t *)hpkt.ritem->value, ed1));
369 void display_bool_pair(HPKT &hpkt)
371 sendit(NULL, "\n \"%s\": %s", hpkt.ritem->name,
372 ((*(bool *)(hpkt.ritem->value)) == 0)?"false":"true");
375 void display_bit_pair(HPKT &hpkt)
377 sendit(NULL, "\n \"%s\": %s", hpkt.ritem->name,
378 ((*(uint32_t *)(hpkt.ritem->value) & hpkt.ritem->code)
379 == 0)?"false":"true");
382 bool byte_is_set(char *byte, int num)
386 for (i=0; i<num; i++) {
395 void display_bit_array(char *array, int num)
400 for (i=0; i<num; i++) {
401 if (bit_is_set(i, array)) {
402 if (!first) sendit(NULL, ", ");
404 sendit(NULL, "%d", i);