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