Values API: standardize function names
[babeltrace.git] / cli / babeltrace-cfg-cli-args-connect.c
CommitLineData
ebba3338
PP
1/*
2 * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
0fbb9a9f 23#include <stdlib.h>
ebba3338 24#include <babeltrace/values.h>
db0f160a 25#include <babeltrace/common-internal.h>
ebba3338 26#include "babeltrace-cfg.h"
9009cc24 27#include "babeltrace-cfg-cli-args-connect.h"
ebba3338 28
db0f160a 29static bool all_named_and_printable_in_array(GPtrArray *comps)
ebba3338
PP
30{
31 size_t i;
db0f160a 32 bool all_named_and_printable = true;
ebba3338
PP
33
34 for (i = 0; i < comps->len; i++) {
35 struct bt_config_component *comp = g_ptr_array_index(comps, i);
36
37 if (comp->instance_name->len == 0) {
db0f160a
PP
38 all_named_and_printable = false;
39 goto end;
40 }
41
42 if (!bt_common_string_is_printable(comp->instance_name->str)) {
43 all_named_and_printable = false;
ebba3338
PP
44 goto end;
45 }
46 }
47
48end:
db0f160a 49 return all_named_and_printable;
ebba3338
PP
50}
51
db0f160a 52static bool all_named_and_printable(struct bt_config *cfg)
ebba3338 53{
db0f160a
PP
54 return all_named_and_printable_in_array(cfg->cmd_data.run.sources) &&
55 all_named_and_printable_in_array(cfg->cmd_data.run.filters) &&
56 all_named_and_printable_in_array(cfg->cmd_data.run.sinks);
ebba3338
PP
57}
58
ebba3338
PP
59static struct bt_config_connection *bt_config_connection_create(const char *arg)
60{
61 struct bt_config_connection *cfg_connection;
62
63 cfg_connection = g_new0(struct bt_config_connection, 1);
64 if (!cfg_connection) {
65 goto error;
66 }
67
9009cc24
PP
68 cfg_connection->upstream_comp_name = g_string_new(NULL);
69 if (!cfg_connection->upstream_comp_name) {
ebba3338
PP
70 goto error;
71 }
72
9009cc24
PP
73 cfg_connection->downstream_comp_name = g_string_new(NULL);
74 if (!cfg_connection->downstream_comp_name) {
ebba3338
PP
75 goto error;
76 }
77
9009cc24
PP
78 cfg_connection->upstream_port_glob = g_string_new("*");
79 if (!cfg_connection->upstream_port_glob) {
ebba3338
PP
80 goto error;
81 }
82
9009cc24
PP
83 cfg_connection->downstream_port_glob = g_string_new("*");
84 if (!cfg_connection->downstream_port_glob) {
ebba3338
PP
85 goto error;
86 }
87
88 cfg_connection->arg = g_string_new(arg);
89 if (!cfg_connection->arg) {
90 goto error;
91 }
92
93 goto end;
94
95error:
96 g_free(cfg_connection);
97 cfg_connection = NULL;
98
99end:
100 return cfg_connection;
101}
102
9009cc24
PP
103static bool validate_port_glob(const char *port_glob)
104{
105 bool is_valid = true;
106 const char *ch = port_glob;
107
f6ccaed9 108 BT_ASSERT(port_glob);
9009cc24
PP
109
110 while (*ch != '\0') {
111 switch (*ch) {
112 case '\\':
113 switch (ch[1]) {
114 case '\0':
115 goto end;
116 default:
117 ch += 2;
118 continue;
119 }
120 case '?':
121 case '[':
122 /*
123 * This is reserved for future use, to support
124 * full globbing patterns. Those characters must
125 * be escaped with `\`.
126 */
127 is_valid = false;
128 goto end;
129 default:
130 ch++;
131 break;
132 }
133 }
134
135end:
136 return is_valid;
137}
138
139static int normalize_glob_pattern(GString *glob_pattern_gs)
140{
141 int ret = 0;
142 char *glob_pattern = strdup(glob_pattern_gs->str);
143
144 if (!glob_pattern) {
145 ret = -1;
146 goto end;
147 }
148
149 bt_common_normalize_star_glob_pattern(glob_pattern);
150 g_string_assign(glob_pattern_gs, glob_pattern);
151 free(glob_pattern);
152
153end:
154 return ret;
155}
156
ebba3338
PP
157static struct bt_config_connection *cfg_connection_from_arg(const char *arg)
158{
db0f160a
PP
159 const char *at = arg;
160 size_t end_pos;
161 struct bt_config_connection *cfg_conn = NULL;
162 GString *gs = NULL;
ebba3338 163 enum {
9009cc24
PP
164 UPSTREAM_NAME,
165 DOWNSTREAM_NAME,
166 UPSTREAM_PORT_GLOB,
167 DOWNSTREAM_PORT_GLOB,
168 } state = UPSTREAM_NAME;
db0f160a
PP
169
170 if (!bt_common_string_is_printable(arg)) {
ebba3338
PP
171 goto error;
172 }
173
db0f160a
PP
174 cfg_conn = bt_config_connection_create(arg);
175 if (!cfg_conn) {
ebba3338
PP
176 goto error;
177 }
178
ebba3338 179 while (true) {
ebba3338 180 switch (state) {
9009cc24 181 case UPSTREAM_NAME:
db0f160a
PP
182 gs = bt_common_string_until(at, ".:\\", ".:", &end_pos);
183 if (!gs || gs->len == 0) {
ebba3338
PP
184 goto error;
185 }
186
9009cc24
PP
187 g_string_free(cfg_conn->upstream_comp_name, TRUE);
188 cfg_conn->upstream_comp_name = gs;
db0f160a 189 gs = NULL;
ebba3338 190
db0f160a 191 if (at[end_pos] == ':') {
9009cc24 192 state = DOWNSTREAM_NAME;
db0f160a 193 } else if (at[end_pos] == '.') {
9009cc24 194 state = UPSTREAM_PORT_GLOB;
db0f160a 195 } else {
ebba3338
PP
196 goto error;
197 }
198
db0f160a 199 at += end_pos + 1;
ebba3338 200 break;
9009cc24 201 case DOWNSTREAM_NAME:
db0f160a
PP
202 gs = bt_common_string_until(at, ".:\\", ".:", &end_pos);
203 if (!gs || gs->len == 0) {
ebba3338
PP
204 goto error;
205 }
206
9009cc24
PP
207 g_string_free(cfg_conn->downstream_comp_name, TRUE);
208 cfg_conn->downstream_comp_name = gs;
db0f160a
PP
209 gs = NULL;
210
211 if (at[end_pos] == '.') {
9009cc24 212 state = DOWNSTREAM_PORT_GLOB;
db0f160a
PP
213 } else if (at[end_pos] == '\0') {
214 goto end;
215 } else {
ebba3338
PP
216 goto error;
217 }
218
db0f160a 219 at += end_pos + 1;
ebba3338 220 break;
9009cc24
PP
221 case UPSTREAM_PORT_GLOB:
222 gs = bt_common_string_until(at, ".:", ".:", &end_pos);
db0f160a 223 if (!gs || gs->len == 0) {
ebba3338
PP
224 goto error;
225 }
226
9009cc24
PP
227 if (!validate_port_glob(gs->str)) {
228 goto error;
229 }
230
231 if (normalize_glob_pattern(gs)) {
232 goto error;
233 }
234
235 g_string_free(cfg_conn->upstream_port_glob, TRUE);
236 cfg_conn->upstream_port_glob = gs;
db0f160a
PP
237 gs = NULL;
238
239 if (at[end_pos] == ':') {
9009cc24 240 state = DOWNSTREAM_NAME;
db0f160a 241 } else {
ebba3338
PP
242 goto error;
243 }
244
db0f160a 245 at += end_pos + 1;
ebba3338 246 break;
9009cc24
PP
247 case DOWNSTREAM_PORT_GLOB:
248 gs = bt_common_string_until(at, ".:", ".:", &end_pos);
db0f160a 249 if (!gs || gs->len == 0) {
ebba3338
PP
250 goto error;
251 }
252
9009cc24
PP
253 if (!validate_port_glob(gs->str)) {
254 goto error;
255 }
256
257 if (normalize_glob_pattern(gs)) {
258 goto error;
259 }
260
261 g_string_free(cfg_conn->downstream_port_glob, TRUE);
262 cfg_conn->downstream_port_glob = gs;
db0f160a
PP
263 gs = NULL;
264
265 if (at[end_pos] == '\0') {
266 goto end;
267 } else {
268 goto error;
269 }
ebba3338
PP
270 break;
271 default:
0fbb9a9f 272 abort();
ebba3338
PP
273 }
274 }
275
ebba3338 276error:
db0f160a
PP
277 bt_config_connection_destroy(cfg_conn);
278 cfg_conn = NULL;
ebba3338
PP
279
280end:
db0f160a
PP
281 if (gs) {
282 g_string_free(gs, TRUE);
ebba3338
PP
283 }
284
db0f160a 285 return cfg_conn;
ebba3338
PP
286}
287
288static struct bt_config_component *find_component_in_array(GPtrArray *comps,
289 const char *name)
290{
291 size_t i;
292 struct bt_config_component *found_comp = NULL;
293
294 for (i = 0; i < comps->len; i++) {
295 struct bt_config_component *comp = g_ptr_array_index(comps, i);
296
297 if (strcmp(name, comp->instance_name->str) == 0) {
298 found_comp = bt_get(comp);
299 goto end;
300 }
301 }
302
303end:
304 return found_comp;
305}
306
307static struct bt_config_component *find_component(struct bt_config *cfg,
90de159b 308 const char *name)
ebba3338
PP
309{
310 struct bt_config_component *comp;
311
db0f160a 312 comp = find_component_in_array(cfg->cmd_data.run.sources, name);
ebba3338 313 if (comp) {
ebba3338
PP
314 goto end;
315 }
316
db0f160a 317 comp = find_component_in_array(cfg->cmd_data.run.filters, name);
ebba3338 318 if (comp) {
ebba3338
PP
319 goto end;
320 }
321
db0f160a 322 comp = find_component_in_array(cfg->cmd_data.run.sinks, name);
ebba3338 323 if (comp) {
ebba3338
PP
324 goto end;
325 }
326
327end:
328 return comp;
329}
330
331static int validate_all_endpoints_exist(struct bt_config *cfg, char *error_buf,
332 size_t error_buf_size)
333{
334 size_t i;
335 int ret = 0;
336
db0f160a 337 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 338 struct bt_config_connection *connection =
db0f160a 339 g_ptr_array_index(cfg->cmd_data.run.connections, i);
ebba3338 340 struct bt_config_component *comp;
ebba3338 341
9009cc24 342 comp = find_component(cfg, connection->upstream_comp_name->str);
ebba3338
PP
343 bt_put(comp);
344 if (!comp) {
db0f160a
PP
345 snprintf(error_buf, error_buf_size,
346 "Invalid connection: cannot find upstream component `%s`:\n %s\n",
9009cc24 347 connection->upstream_comp_name->str,
db0f160a
PP
348 connection->arg->str);
349 ret = -1;
350 goto end;
351 }
352
9009cc24 353 comp = find_component(cfg, connection->downstream_comp_name->str);
db0f160a
PP
354 bt_put(comp);
355 if (!comp) {
356 snprintf(error_buf, error_buf_size,
357 "Invalid connection: cannot find downstream component `%s`:\n %s\n",
9009cc24 358 connection->downstream_comp_name->str,
db0f160a
PP
359 connection->arg->str);
360 ret = -1;
361 goto end;
ebba3338
PP
362 }
363 }
364
365end:
366 return ret;
367}
368
369static int validate_connection_directions(struct bt_config *cfg,
370 char *error_buf, size_t error_buf_size)
371{
372 size_t i;
373 int ret = 0;
374 struct bt_config_component *src_comp = NULL;
375 struct bt_config_component *dst_comp = NULL;
376
db0f160a 377 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 378 struct bt_config_connection *connection =
db0f160a 379 g_ptr_array_index(cfg->cmd_data.run.connections, i);
ebba3338
PP
380
381 src_comp = find_component(cfg,
9009cc24 382 connection->upstream_comp_name->str);
f6ccaed9 383 BT_ASSERT(src_comp);
ebba3338 384 dst_comp = find_component(cfg,
9009cc24 385 connection->downstream_comp_name->str);
f6ccaed9 386 BT_ASSERT(dst_comp);
ebba3338 387
90de159b
PP
388 if (src_comp->type == BT_COMPONENT_CLASS_TYPE_SOURCE) {
389 if (dst_comp->type != BT_COMPONENT_CLASS_TYPE_FILTER &&
390 dst_comp->type != BT_COMPONENT_CLASS_TYPE_SINK) {
ebba3338
PP
391 snprintf(error_buf, error_buf_size,
392 "Invalid connection: source component `%s` not connected to filter or sink component:\n %s\n",
9009cc24 393 connection->upstream_comp_name->str,
ebba3338
PP
394 connection->arg->str);
395 ret = -1;
396 goto end;
397 }
90de159b
PP
398 } else if (src_comp->type == BT_COMPONENT_CLASS_TYPE_FILTER) {
399 if (dst_comp->type != BT_COMPONENT_CLASS_TYPE_FILTER &&
400 dst_comp->type != BT_COMPONENT_CLASS_TYPE_SINK) {
ebba3338
PP
401 snprintf(error_buf, error_buf_size,
402 "Invalid connection: filter component `%s` not connected to filter or sink component:\n %s\n",
9009cc24 403 connection->upstream_comp_name->str,
ebba3338
PP
404 connection->arg->str);
405 ret = -1;
406 goto end;
407 }
408 } else {
409 snprintf(error_buf, error_buf_size,
410 "Invalid connection: cannot connect sink component `%s` to component `%s`:\n %s\n",
9009cc24
PP
411 connection->upstream_comp_name->str,
412 connection->downstream_comp_name->str,
ebba3338
PP
413 connection->arg->str);
414 ret = -1;
415 goto end;
416 }
417
418 BT_PUT(src_comp);
419 BT_PUT(dst_comp);
420 }
421
422end:
423 bt_put(src_comp);
424 bt_put(dst_comp);
425 return ret;
426}
427
db0f160a
PP
428static int validate_no_cycles_rec(struct bt_config *cfg, GPtrArray *path,
429 char *error_buf, size_t error_buf_size)
430{
431 int ret = 0;
432 size_t conn_i;
433 const char *src_comp_name;
434
f6ccaed9 435 BT_ASSERT(path && path->len > 0);
db0f160a
PP
436 src_comp_name = g_ptr_array_index(path, path->len - 1);
437
438 for (conn_i = 0; conn_i < cfg->cmd_data.run.connections->len; conn_i++) {
439 struct bt_config_connection *conn =
440 g_ptr_array_index(cfg->cmd_data.run.connections, conn_i);
441
9009cc24 442 if (strcmp(conn->upstream_comp_name->str, src_comp_name) == 0) {
db0f160a
PP
443 size_t path_i;
444
445 for (path_i = 0; path_i < path->len; path_i++) {
446 const char *comp_name =
447 g_ptr_array_index(path, path_i);
448
9009cc24 449 if (strcmp(comp_name, conn->downstream_comp_name->str) == 0) {
db0f160a
PP
450 snprintf(error_buf, error_buf_size,
451 "Invalid connection: connection forms a cycle:\n %s\n",
452 conn->arg->str);
453 ret = -1;
454 goto end;
455 }
456 }
457
9009cc24 458 g_ptr_array_add(path, conn->downstream_comp_name->str);
db0f160a
PP
459 ret = validate_no_cycles_rec(cfg, path, error_buf,
460 error_buf_size);
461 if (ret) {
462 goto end;
463 }
464
465 g_ptr_array_remove_index(path, path->len - 1);
466 }
467 }
468
469end:
470 return ret;
471}
472
473static int validate_no_cycles(struct bt_config *cfg, char *error_buf,
ebba3338
PP
474 size_t error_buf_size)
475{
476 size_t i;
477 int ret = 0;
db0f160a 478 GPtrArray *path;
ebba3338 479
db0f160a
PP
480 path = g_ptr_array_new();
481 if (!path) {
482 ret = -1;
483 goto end;
484 }
ebba3338 485
db0f160a
PP
486 g_ptr_array_add(path, NULL);
487
488 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
489 struct bt_config_connection *conn =
490 g_ptr_array_index(cfg->cmd_data.run.connections, i);
491
9009cc24 492 g_ptr_array_index(path, 0) = conn->upstream_comp_name->str;
db0f160a
PP
493 ret = validate_no_cycles_rec(cfg, path,
494 error_buf, error_buf_size);
495 if (ret) {
ebba3338
PP
496 goto end;
497 }
498 }
499
500end:
db0f160a
PP
501 if (path) {
502 g_ptr_array_free(path, TRUE);
503 }
504
ebba3338
PP
505 return ret;
506}
507
508static int validate_all_components_connected_in_array(GPtrArray *comps,
509 struct bt_value *connected_components,
510 char *error_buf, size_t error_buf_size)
511{
512 int ret = 0;
513 size_t i;
514
515 for (i = 0; i < comps->len; i++) {
516 struct bt_config_component *comp = g_ptr_array_index(comps, i);
517
07208d85 518 if (!bt_value_map_has_entry(connected_components,
ebba3338
PP
519 comp->instance_name->str)) {
520 snprintf(error_buf, error_buf_size,
521 "Component `%s` is not connected\n",
522 comp->instance_name->str);
523 ret = -1;
524 goto end;
525 }
526 }
527
528end:
529 return ret;
530}
531
532static int validate_all_components_connected(struct bt_config *cfg,
533 char *error_buf, size_t error_buf_size)
534{
535 size_t i;
536 int ret = 0;
537 struct bt_value *connected_components = bt_value_map_create();
538
539 if (!connected_components) {
540 ret = -1;
541 goto end;
542 }
543
db0f160a 544 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 545 struct bt_config_connection *connection =
db0f160a 546 g_ptr_array_index(cfg->cmd_data.run.connections, i);
ebba3338 547
07208d85 548 ret = bt_value_map_insert_entry(connected_components,
9009cc24 549 connection->upstream_comp_name->str, bt_value_null);
ebba3338
PP
550 if (ret) {
551 goto end;
552 }
553
07208d85 554 ret = bt_value_map_insert_entry(connected_components,
9009cc24 555 connection->downstream_comp_name->str, bt_value_null);
ebba3338
PP
556 if (ret) {
557 goto end;
558 }
559 }
560
561 ret = validate_all_components_connected_in_array(
db0f160a 562 cfg->cmd_data.run.sources, connected_components,
ebba3338
PP
563 error_buf, error_buf_size);
564 if (ret) {
565 goto end;
566 }
567
568 ret = validate_all_components_connected_in_array(
db0f160a 569 cfg->cmd_data.run.filters, connected_components,
ebba3338
PP
570 error_buf, error_buf_size);
571 if (ret) {
572 goto end;
573 }
574
575 ret = validate_all_components_connected_in_array(
db0f160a 576 cfg->cmd_data.run.sinks, connected_components,
ebba3338
PP
577 error_buf, error_buf_size);
578 if (ret) {
579 goto end;
580 }
581
582end:
583 bt_put(connected_components);
584 return ret;
585}
586
587static int validate_no_duplicate_connection(struct bt_config *cfg,
588 char *error_buf, size_t error_buf_size)
589{
590 size_t i;
591 int ret = 0;
592 struct bt_value *flat_connection_names = bt_value_map_create();
593 GString *flat_connection_name = NULL;
594
595 if (!flat_connection_names) {
596 ret = -1;
597 goto end;
598 }
599
600 flat_connection_name = g_string_new(NULL);
601 if (!flat_connection_name) {
602 ret = -1;
603 goto end;
604 }
605
db0f160a 606 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 607 struct bt_config_connection *connection =
db0f160a 608 g_ptr_array_index(cfg->cmd_data.run.connections, i);
ebba3338 609
db0f160a 610 g_string_printf(flat_connection_name, "%s\x01%s\x01%s\x01%s",
9009cc24
PP
611 connection->upstream_comp_name->str,
612 connection->upstream_port_glob->str,
613 connection->downstream_comp_name->str,
614 connection->downstream_port_glob->str);
ebba3338 615
07208d85 616 if (bt_value_map_has_entry(flat_connection_names,
ebba3338
PP
617 flat_connection_name->str)) {
618 snprintf(error_buf, error_buf_size,
619 "Duplicate connection:\n %s\n",
620 connection->arg->str);
621 ret = -1;
622 goto end;
623 }
624
07208d85 625 ret = bt_value_map_insert_entry(flat_connection_names,
ebba3338
PP
626 flat_connection_name->str, bt_value_null);
627 if (ret) {
628 goto end;
629 }
630 }
631
632end:
633 bt_put(flat_connection_names);
634
635 if (flat_connection_name) {
636 g_string_free(flat_connection_name, TRUE);
637 }
638
639 return ret;
640}
641
642static int validate_connections(struct bt_config *cfg, char *error_buf,
643 size_t error_buf_size)
644{
645 int ret;
646
647 ret = validate_all_endpoints_exist(cfg, error_buf, error_buf_size);
648 if (ret) {
649 goto end;
650 }
651
652 ret = validate_connection_directions(cfg, error_buf, error_buf_size);
653 if (ret) {
654 goto end;
655 }
656
ebba3338
PP
657 ret = validate_all_components_connected(cfg, error_buf, error_buf_size);
658 if (ret) {
659 goto end;
660 }
661
662 ret = validate_no_duplicate_connection(cfg, error_buf, error_buf_size);
663 if (ret) {
664 goto end;
665 }
666
db0f160a 667 ret = validate_no_cycles(cfg, error_buf, error_buf_size);
ebba3338
PP
668 if (ret) {
669 goto end;
670 }
671
ebba3338 672end:
ebba3338
PP
673 return ret;
674}
675
9009cc24 676int bt_config_cli_args_create_connections(struct bt_config *cfg,
ebba3338
PP
677 struct bt_value *connection_args,
678 char *error_buf, size_t error_buf_size)
679{
680 int ret;
681 size_t i;
682
db0f160a
PP
683 if (!all_named_and_printable(cfg)) {
684 snprintf(error_buf, error_buf_size,
685 "One or more components are unnamed (use --name) or contain a non-printable character\n");
ebba3338
PP
686 goto error;
687 }
688
07208d85 689 for (i = 0; i < bt_value_array_get_size(connection_args); i++) {
ebba3338 690 struct bt_value *arg_value =
07208d85
PP
691 bt_value_array_borrow_element_by_index(
692 connection_args, i);
ebba3338
PP
693 const char *arg;
694 struct bt_config_connection *cfg_connection;
695
696 ret = bt_value_string_get(arg_value, &arg);
f6ccaed9 697 BT_ASSERT(ret == 0);
ebba3338
PP
698 cfg_connection = cfg_connection_from_arg(arg);
699 if (!cfg_connection) {
700 snprintf(error_buf, error_buf_size, "Cannot parse --connect option's argument:\n %s\n",
701 arg);
702 goto error;
703 }
704
db0f160a 705 g_ptr_array_add(cfg->cmd_data.run.connections,
ebba3338
PP
706 cfg_connection);
707 }
708
709
710 ret = validate_connections(cfg, error_buf, error_buf_size);
711 if (ret) {
712 goto error;
713 }
714
715 goto end;
716
717error:
718 ret = -1;
719
720end:
721 return ret;
722}
This page took 0.06203 seconds and 4 git commands to generate.