tap-driver.sh: flush stdout after each test result
[babeltrace.git] / 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
0fbb9a9f 23#include <stdlib.h>
3fadfbc0
MJ
24#include <babeltrace2/babeltrace.h>
25#include <babeltrace2/common-internal.h>
ec2c5e50
MJ
26#include "babeltrace2-cfg.h"
27#include "babeltrace2-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) {
398454ed
PP
298 found_comp = comp;
299 bt_object_get_ref(found_comp);
ebba3338
PP
300 goto end;
301 }
302 }
303
304end:
305 return found_comp;
306}
307
308static struct bt_config_component *find_component(struct bt_config *cfg,
90de159b 309 const char *name)
ebba3338
PP
310{
311 struct bt_config_component *comp;
312
db0f160a 313 comp = find_component_in_array(cfg->cmd_data.run.sources, name);
ebba3338 314 if (comp) {
ebba3338
PP
315 goto end;
316 }
317
db0f160a 318 comp = find_component_in_array(cfg->cmd_data.run.filters, name);
ebba3338 319 if (comp) {
ebba3338
PP
320 goto end;
321 }
322
db0f160a 323 comp = find_component_in_array(cfg->cmd_data.run.sinks, name);
ebba3338 324 if (comp) {
ebba3338
PP
325 goto end;
326 }
327
328end:
329 return comp;
330}
331
332static int validate_all_endpoints_exist(struct bt_config *cfg, char *error_buf,
333 size_t error_buf_size)
334{
335 size_t i;
336 int ret = 0;
337
db0f160a 338 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 339 struct bt_config_connection *connection =
db0f160a 340 g_ptr_array_index(cfg->cmd_data.run.connections, i);
ebba3338 341 struct bt_config_component *comp;
ebba3338 342
9009cc24 343 comp = find_component(cfg, connection->upstream_comp_name->str);
65300d60 344 bt_object_put_ref(comp);
ebba3338 345 if (!comp) {
db0f160a
PP
346 snprintf(error_buf, error_buf_size,
347 "Invalid connection: cannot find upstream component `%s`:\n %s\n",
9009cc24 348 connection->upstream_comp_name->str,
db0f160a
PP
349 connection->arg->str);
350 ret = -1;
351 goto end;
352 }
353
9009cc24 354 comp = find_component(cfg, connection->downstream_comp_name->str);
65300d60 355 bt_object_put_ref(comp);
db0f160a
PP
356 if (!comp) {
357 snprintf(error_buf, error_buf_size,
358 "Invalid connection: cannot find downstream component `%s`:\n %s\n",
9009cc24 359 connection->downstream_comp_name->str,
db0f160a
PP
360 connection->arg->str);
361 ret = -1;
362 goto end;
ebba3338
PP
363 }
364 }
365
366end:
367 return ret;
368}
369
370static int validate_connection_directions(struct bt_config *cfg,
371 char *error_buf, size_t error_buf_size)
372{
373 size_t i;
374 int ret = 0;
375 struct bt_config_component *src_comp = NULL;
376 struct bt_config_component *dst_comp = NULL;
377
db0f160a 378 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 379 struct bt_config_connection *connection =
db0f160a 380 g_ptr_array_index(cfg->cmd_data.run.connections, i);
ebba3338
PP
381
382 src_comp = find_component(cfg,
9009cc24 383 connection->upstream_comp_name->str);
f6ccaed9 384 BT_ASSERT(src_comp);
ebba3338 385 dst_comp = find_component(cfg,
9009cc24 386 connection->downstream_comp_name->str);
f6ccaed9 387 BT_ASSERT(dst_comp);
ebba3338 388
90de159b
PP
389 if (src_comp->type == BT_COMPONENT_CLASS_TYPE_SOURCE) {
390 if (dst_comp->type != BT_COMPONENT_CLASS_TYPE_FILTER &&
391 dst_comp->type != BT_COMPONENT_CLASS_TYPE_SINK) {
ebba3338
PP
392 snprintf(error_buf, error_buf_size,
393 "Invalid connection: source component `%s` not connected to filter or sink component:\n %s\n",
9009cc24 394 connection->upstream_comp_name->str,
ebba3338
PP
395 connection->arg->str);
396 ret = -1;
397 goto end;
398 }
90de159b
PP
399 } else if (src_comp->type == BT_COMPONENT_CLASS_TYPE_FILTER) {
400 if (dst_comp->type != BT_COMPONENT_CLASS_TYPE_FILTER &&
401 dst_comp->type != BT_COMPONENT_CLASS_TYPE_SINK) {
ebba3338
PP
402 snprintf(error_buf, error_buf_size,
403 "Invalid connection: filter component `%s` not connected to filter or sink component:\n %s\n",
9009cc24 404 connection->upstream_comp_name->str,
ebba3338
PP
405 connection->arg->str);
406 ret = -1;
407 goto end;
408 }
409 } else {
410 snprintf(error_buf, error_buf_size,
411 "Invalid connection: cannot connect sink component `%s` to component `%s`:\n %s\n",
9009cc24
PP
412 connection->upstream_comp_name->str,
413 connection->downstream_comp_name->str,
ebba3338
PP
414 connection->arg->str);
415 ret = -1;
416 goto end;
417 }
418
65300d60
PP
419 BT_OBJECT_PUT_REF_AND_RESET(src_comp);
420 BT_OBJECT_PUT_REF_AND_RESET(dst_comp);
ebba3338
PP
421 }
422
423end:
65300d60
PP
424 bt_object_put_ref(src_comp);
425 bt_object_put_ref(dst_comp);
ebba3338
PP
426 return ret;
427}
428
db0f160a
PP
429static int validate_no_cycles_rec(struct bt_config *cfg, GPtrArray *path,
430 char *error_buf, size_t error_buf_size)
431{
432 int ret = 0;
433 size_t conn_i;
434 const char *src_comp_name;
435
f6ccaed9 436 BT_ASSERT(path && path->len > 0);
db0f160a
PP
437 src_comp_name = g_ptr_array_index(path, path->len - 1);
438
439 for (conn_i = 0; conn_i < cfg->cmd_data.run.connections->len; conn_i++) {
440 struct bt_config_connection *conn =
441 g_ptr_array_index(cfg->cmd_data.run.connections, conn_i);
442
9009cc24 443 if (strcmp(conn->upstream_comp_name->str, src_comp_name) == 0) {
db0f160a
PP
444 size_t path_i;
445
446 for (path_i = 0; path_i < path->len; path_i++) {
447 const char *comp_name =
448 g_ptr_array_index(path, path_i);
449
9009cc24 450 if (strcmp(comp_name, conn->downstream_comp_name->str) == 0) {
db0f160a
PP
451 snprintf(error_buf, error_buf_size,
452 "Invalid connection: connection forms a cycle:\n %s\n",
453 conn->arg->str);
454 ret = -1;
455 goto end;
456 }
457 }
458
9009cc24 459 g_ptr_array_add(path, conn->downstream_comp_name->str);
db0f160a
PP
460 ret = validate_no_cycles_rec(cfg, path, error_buf,
461 error_buf_size);
462 if (ret) {
463 goto end;
464 }
465
466 g_ptr_array_remove_index(path, path->len - 1);
467 }
468 }
469
470end:
471 return ret;
472}
473
474static int validate_no_cycles(struct bt_config *cfg, char *error_buf,
ebba3338
PP
475 size_t error_buf_size)
476{
477 size_t i;
478 int ret = 0;
db0f160a 479 GPtrArray *path;
ebba3338 480
db0f160a
PP
481 path = g_ptr_array_new();
482 if (!path) {
483 ret = -1;
484 goto end;
485 }
ebba3338 486
db0f160a
PP
487 g_ptr_array_add(path, NULL);
488
489 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
490 struct bt_config_connection *conn =
491 g_ptr_array_index(cfg->cmd_data.run.connections, i);
492
9009cc24 493 g_ptr_array_index(path, 0) = conn->upstream_comp_name->str;
db0f160a
PP
494 ret = validate_no_cycles_rec(cfg, path,
495 error_buf, error_buf_size);
496 if (ret) {
ebba3338
PP
497 goto end;
498 }
499 }
500
501end:
db0f160a
PP
502 if (path) {
503 g_ptr_array_free(path, TRUE);
504 }
505
ebba3338
PP
506 return ret;
507}
508
509static int validate_all_components_connected_in_array(GPtrArray *comps,
b19ff26f 510 const bt_value *connected_components,
ebba3338
PP
511 char *error_buf, size_t error_buf_size)
512{
513 int ret = 0;
514 size_t i;
515
516 for (i = 0; i < comps->len; i++) {
517 struct bt_config_component *comp = g_ptr_array_index(comps, i);
518
07208d85 519 if (!bt_value_map_has_entry(connected_components,
ebba3338
PP
520 comp->instance_name->str)) {
521 snprintf(error_buf, error_buf_size,
522 "Component `%s` is not connected\n",
523 comp->instance_name->str);
524 ret = -1;
525 goto end;
526 }
527 }
528
529end:
530 return ret;
531}
532
533static int validate_all_components_connected(struct bt_config *cfg,
534 char *error_buf, size_t error_buf_size)
535{
536 size_t i;
537 int ret = 0;
b19ff26f 538 bt_value *connected_components = bt_value_map_create();
ebba3338
PP
539
540 if (!connected_components) {
541 ret = -1;
542 goto end;
543 }
544
db0f160a 545 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 546 struct bt_config_connection *connection =
db0f160a 547 g_ptr_array_index(cfg->cmd_data.run.connections, i);
ebba3338 548
05e21286 549 ret = bt_value_map_insert_entry(connected_components,
9009cc24 550 connection->upstream_comp_name->str, bt_value_null);
ebba3338
PP
551 if (ret) {
552 goto end;
553 }
554
05e21286 555 ret = bt_value_map_insert_entry(connected_components,
9009cc24 556 connection->downstream_comp_name->str, bt_value_null);
ebba3338
PP
557 if (ret) {
558 goto end;
559 }
560 }
561
562 ret = validate_all_components_connected_in_array(
da91b29a 563 cfg->cmd_data.run.sources,
05e21286 564 connected_components,
ebba3338
PP
565 error_buf, error_buf_size);
566 if (ret) {
567 goto end;
568 }
569
570 ret = validate_all_components_connected_in_array(
da91b29a 571 cfg->cmd_data.run.filters,
05e21286 572 connected_components,
ebba3338
PP
573 error_buf, error_buf_size);
574 if (ret) {
575 goto end;
576 }
577
578 ret = validate_all_components_connected_in_array(
da91b29a 579 cfg->cmd_data.run.sinks,
05e21286 580 connected_components,
ebba3338
PP
581 error_buf, error_buf_size);
582 if (ret) {
583 goto end;
584 }
585
586end:
c5b9b441 587 bt_value_put_ref(connected_components);
ebba3338
PP
588 return ret;
589}
590
591static int validate_no_duplicate_connection(struct bt_config *cfg,
592 char *error_buf, size_t error_buf_size)
593{
594 size_t i;
595 int ret = 0;
b19ff26f 596 bt_value *flat_connection_names =
05e21286 597 bt_value_map_create();
ebba3338
PP
598 GString *flat_connection_name = NULL;
599
600 if (!flat_connection_names) {
601 ret = -1;
602 goto end;
603 }
604
605 flat_connection_name = g_string_new(NULL);
606 if (!flat_connection_name) {
607 ret = -1;
608 goto end;
609 }
610
db0f160a 611 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 612 struct bt_config_connection *connection =
db0f160a 613 g_ptr_array_index(cfg->cmd_data.run.connections, i);
ebba3338 614
db0f160a 615 g_string_printf(flat_connection_name, "%s\x01%s\x01%s\x01%s",
9009cc24
PP
616 connection->upstream_comp_name->str,
617 connection->upstream_port_glob->str,
618 connection->downstream_comp_name->str,
619 connection->downstream_port_glob->str);
ebba3338 620
05e21286
PP
621 if (bt_value_map_has_entry(flat_connection_names,
622 flat_connection_name->str)) {
ebba3338
PP
623 snprintf(error_buf, error_buf_size,
624 "Duplicate connection:\n %s\n",
625 connection->arg->str);
626 ret = -1;
627 goto end;
628 }
629
05e21286 630 ret = bt_value_map_insert_entry(flat_connection_names,
ebba3338
PP
631 flat_connection_name->str, bt_value_null);
632 if (ret) {
633 goto end;
634 }
635 }
636
637end:
c5b9b441 638 bt_value_put_ref(flat_connection_names);
ebba3338
PP
639
640 if (flat_connection_name) {
641 g_string_free(flat_connection_name, TRUE);
642 }
643
644 return ret;
645}
646
647static int validate_connections(struct bt_config *cfg, char *error_buf,
648 size_t error_buf_size)
649{
650 int ret;
651
652 ret = validate_all_endpoints_exist(cfg, error_buf, error_buf_size);
653 if (ret) {
654 goto end;
655 }
656
657 ret = validate_connection_directions(cfg, error_buf, error_buf_size);
658 if (ret) {
659 goto end;
660 }
661
ebba3338
PP
662 ret = validate_all_components_connected(cfg, error_buf, error_buf_size);
663 if (ret) {
664 goto end;
665 }
666
667 ret = validate_no_duplicate_connection(cfg, error_buf, error_buf_size);
668 if (ret) {
669 goto end;
670 }
671
db0f160a 672 ret = validate_no_cycles(cfg, error_buf, error_buf_size);
ebba3338
PP
673 if (ret) {
674 goto end;
675 }
676
ebba3338 677end:
ebba3338
PP
678 return ret;
679}
680
9009cc24 681int bt_config_cli_args_create_connections(struct bt_config *cfg,
b19ff26f 682 const bt_value *connection_args,
ebba3338
PP
683 char *error_buf, size_t error_buf_size)
684{
685 int ret;
686 size_t i;
687
db0f160a
PP
688 if (!all_named_and_printable(cfg)) {
689 snprintf(error_buf, error_buf_size,
690 "One or more components are unnamed (use --name) or contain a non-printable character\n");
ebba3338
PP
691 goto error;
692 }
693
07208d85 694 for (i = 0; i < bt_value_array_get_size(connection_args); i++) {
b19ff26f 695 const bt_value *arg_value =
05e21286 696 bt_value_array_borrow_element_by_index_const(
07208d85 697 connection_args, i);
ebba3338
PP
698 const char *arg;
699 struct bt_config_connection *cfg_connection;
700
601b0d3c 701 arg = bt_value_string_get(arg_value);
ebba3338
PP
702 cfg_connection = cfg_connection_from_arg(arg);
703 if (!cfg_connection) {
704 snprintf(error_buf, error_buf_size, "Cannot parse --connect option's argument:\n %s\n",
705 arg);
706 goto error;
707 }
708
db0f160a 709 g_ptr_array_add(cfg->cmd_data.run.connections,
ebba3338
PP
710 cfg_connection);
711 }
712
713
714 ret = validate_connections(cfg, error_buf, error_buf_size);
715 if (ret) {
716 goto error;
717 }
718
719 goto end;
720
721error:
722 ret = -1;
723
724end:
725 return ret;
726}
This page took 0.069873 seconds and 4 git commands to generate.