Values API: split into private and public APIs
[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>
da91b29a 25#include <babeltrace/private-values.h>
db0f160a 26#include <babeltrace/common-internal.h>
ebba3338 27#include "babeltrace-cfg.h"
9009cc24 28#include "babeltrace-cfg-cli-args-connect.h"
ebba3338 29
db0f160a 30static bool all_named_and_printable_in_array(GPtrArray *comps)
ebba3338
PP
31{
32 size_t i;
db0f160a 33 bool all_named_and_printable = true;
ebba3338
PP
34
35 for (i = 0; i < comps->len; i++) {
36 struct bt_config_component *comp = g_ptr_array_index(comps, i);
37
38 if (comp->instance_name->len == 0) {
db0f160a
PP
39 all_named_and_printable = false;
40 goto end;
41 }
42
43 if (!bt_common_string_is_printable(comp->instance_name->str)) {
44 all_named_and_printable = false;
ebba3338
PP
45 goto end;
46 }
47 }
48
49end:
db0f160a 50 return all_named_and_printable;
ebba3338
PP
51}
52
db0f160a 53static bool all_named_and_printable(struct bt_config *cfg)
ebba3338 54{
db0f160a
PP
55 return all_named_and_printable_in_array(cfg->cmd_data.run.sources) &&
56 all_named_and_printable_in_array(cfg->cmd_data.run.filters) &&
57 all_named_and_printable_in_array(cfg->cmd_data.run.sinks);
ebba3338
PP
58}
59
ebba3338
PP
60static struct bt_config_connection *bt_config_connection_create(const char *arg)
61{
62 struct bt_config_connection *cfg_connection;
63
64 cfg_connection = g_new0(struct bt_config_connection, 1);
65 if (!cfg_connection) {
66 goto error;
67 }
68
9009cc24
PP
69 cfg_connection->upstream_comp_name = g_string_new(NULL);
70 if (!cfg_connection->upstream_comp_name) {
ebba3338
PP
71 goto error;
72 }
73
9009cc24
PP
74 cfg_connection->downstream_comp_name = g_string_new(NULL);
75 if (!cfg_connection->downstream_comp_name) {
ebba3338
PP
76 goto error;
77 }
78
9009cc24
PP
79 cfg_connection->upstream_port_glob = g_string_new("*");
80 if (!cfg_connection->upstream_port_glob) {
ebba3338
PP
81 goto error;
82 }
83
9009cc24
PP
84 cfg_connection->downstream_port_glob = g_string_new("*");
85 if (!cfg_connection->downstream_port_glob) {
ebba3338
PP
86 goto error;
87 }
88
89 cfg_connection->arg = g_string_new(arg);
90 if (!cfg_connection->arg) {
91 goto error;
92 }
93
94 goto end;
95
96error:
97 g_free(cfg_connection);
98 cfg_connection = NULL;
99
100end:
101 return cfg_connection;
102}
103
9009cc24
PP
104static bool validate_port_glob(const char *port_glob)
105{
106 bool is_valid = true;
107 const char *ch = port_glob;
108
f6ccaed9 109 BT_ASSERT(port_glob);
9009cc24
PP
110
111 while (*ch != '\0') {
112 switch (*ch) {
113 case '\\':
114 switch (ch[1]) {
115 case '\0':
116 goto end;
117 default:
118 ch += 2;
119 continue;
120 }
121 case '?':
122 case '[':
123 /*
124 * This is reserved for future use, to support
125 * full globbing patterns. Those characters must
126 * be escaped with `\`.
127 */
128 is_valid = false;
129 goto end;
130 default:
131 ch++;
132 break;
133 }
134 }
135
136end:
137 return is_valid;
138}
139
140static int normalize_glob_pattern(GString *glob_pattern_gs)
141{
142 int ret = 0;
143 char *glob_pattern = strdup(glob_pattern_gs->str);
144
145 if (!glob_pattern) {
146 ret = -1;
147 goto end;
148 }
149
150 bt_common_normalize_star_glob_pattern(glob_pattern);
151 g_string_assign(glob_pattern_gs, glob_pattern);
152 free(glob_pattern);
153
154end:
155 return ret;
156}
157
ebba3338
PP
158static struct bt_config_connection *cfg_connection_from_arg(const char *arg)
159{
db0f160a
PP
160 const char *at = arg;
161 size_t end_pos;
162 struct bt_config_connection *cfg_conn = NULL;
163 GString *gs = NULL;
ebba3338 164 enum {
9009cc24
PP
165 UPSTREAM_NAME,
166 DOWNSTREAM_NAME,
167 UPSTREAM_PORT_GLOB,
168 DOWNSTREAM_PORT_GLOB,
169 } state = UPSTREAM_NAME;
db0f160a
PP
170
171 if (!bt_common_string_is_printable(arg)) {
ebba3338
PP
172 goto error;
173 }
174
db0f160a
PP
175 cfg_conn = bt_config_connection_create(arg);
176 if (!cfg_conn) {
ebba3338
PP
177 goto error;
178 }
179
ebba3338 180 while (true) {
ebba3338 181 switch (state) {
9009cc24 182 case UPSTREAM_NAME:
db0f160a
PP
183 gs = bt_common_string_until(at, ".:\\", ".:", &end_pos);
184 if (!gs || gs->len == 0) {
ebba3338
PP
185 goto error;
186 }
187
9009cc24
PP
188 g_string_free(cfg_conn->upstream_comp_name, TRUE);
189 cfg_conn->upstream_comp_name = gs;
db0f160a 190 gs = NULL;
ebba3338 191
db0f160a 192 if (at[end_pos] == ':') {
9009cc24 193 state = DOWNSTREAM_NAME;
db0f160a 194 } else if (at[end_pos] == '.') {
9009cc24 195 state = UPSTREAM_PORT_GLOB;
db0f160a 196 } else {
ebba3338
PP
197 goto error;
198 }
199
db0f160a 200 at += end_pos + 1;
ebba3338 201 break;
9009cc24 202 case DOWNSTREAM_NAME:
db0f160a
PP
203 gs = bt_common_string_until(at, ".:\\", ".:", &end_pos);
204 if (!gs || gs->len == 0) {
ebba3338
PP
205 goto error;
206 }
207
9009cc24
PP
208 g_string_free(cfg_conn->downstream_comp_name, TRUE);
209 cfg_conn->downstream_comp_name = gs;
db0f160a
PP
210 gs = NULL;
211
212 if (at[end_pos] == '.') {
9009cc24 213 state = DOWNSTREAM_PORT_GLOB;
db0f160a
PP
214 } else if (at[end_pos] == '\0') {
215 goto end;
216 } else {
ebba3338
PP
217 goto error;
218 }
219
db0f160a 220 at += end_pos + 1;
ebba3338 221 break;
9009cc24
PP
222 case UPSTREAM_PORT_GLOB:
223 gs = bt_common_string_until(at, ".:", ".:", &end_pos);
db0f160a 224 if (!gs || gs->len == 0) {
ebba3338
PP
225 goto error;
226 }
227
9009cc24
PP
228 if (!validate_port_glob(gs->str)) {
229 goto error;
230 }
231
232 if (normalize_glob_pattern(gs)) {
233 goto error;
234 }
235
236 g_string_free(cfg_conn->upstream_port_glob, TRUE);
237 cfg_conn->upstream_port_glob = gs;
db0f160a
PP
238 gs = NULL;
239
240 if (at[end_pos] == ':') {
9009cc24 241 state = DOWNSTREAM_NAME;
db0f160a 242 } else {
ebba3338
PP
243 goto error;
244 }
245
db0f160a 246 at += end_pos + 1;
ebba3338 247 break;
9009cc24
PP
248 case DOWNSTREAM_PORT_GLOB:
249 gs = bt_common_string_until(at, ".:", ".:", &end_pos);
db0f160a 250 if (!gs || gs->len == 0) {
ebba3338
PP
251 goto error;
252 }
253
9009cc24
PP
254 if (!validate_port_glob(gs->str)) {
255 goto error;
256 }
257
258 if (normalize_glob_pattern(gs)) {
259 goto error;
260 }
261
262 g_string_free(cfg_conn->downstream_port_glob, TRUE);
263 cfg_conn->downstream_port_glob = gs;
db0f160a
PP
264 gs = NULL;
265
266 if (at[end_pos] == '\0') {
267 goto end;
268 } else {
269 goto error;
270 }
ebba3338
PP
271 break;
272 default:
0fbb9a9f 273 abort();
ebba3338
PP
274 }
275 }
276
ebba3338 277error:
db0f160a
PP
278 bt_config_connection_destroy(cfg_conn);
279 cfg_conn = NULL;
ebba3338
PP
280
281end:
db0f160a
PP
282 if (gs) {
283 g_string_free(gs, TRUE);
ebba3338
PP
284 }
285
db0f160a 286 return cfg_conn;
ebba3338
PP
287}
288
289static struct bt_config_component *find_component_in_array(GPtrArray *comps,
290 const char *name)
291{
292 size_t i;
293 struct bt_config_component *found_comp = NULL;
294
295 for (i = 0; i < comps->len; i++) {
296 struct bt_config_component *comp = g_ptr_array_index(comps, i);
297
298 if (strcmp(name, comp->instance_name->str) == 0) {
65300d60 299 found_comp = bt_object_get_ref(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,
510 struct bt_value *connected_components,
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;
da91b29a
PP
538 struct bt_private_value *connected_components =
539 bt_private_value_map_create();
ebba3338
PP
540
541 if (!connected_components) {
542 ret = -1;
543 goto end;
544 }
545
db0f160a 546 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 547 struct bt_config_connection *connection =
db0f160a 548 g_ptr_array_index(cfg->cmd_data.run.connections, i);
ebba3338 549
da91b29a 550 ret = bt_private_value_map_insert_entry(connected_components,
9009cc24 551 connection->upstream_comp_name->str, bt_value_null);
ebba3338
PP
552 if (ret) {
553 goto end;
554 }
555
da91b29a 556 ret = bt_private_value_map_insert_entry(connected_components,
9009cc24 557 connection->downstream_comp_name->str, bt_value_null);
ebba3338
PP
558 if (ret) {
559 goto end;
560 }
561 }
562
563 ret = validate_all_components_connected_in_array(
da91b29a
PP
564 cfg->cmd_data.run.sources,
565 bt_value_borrow_from_private(connected_components),
ebba3338
PP
566 error_buf, error_buf_size);
567 if (ret) {
568 goto end;
569 }
570
571 ret = validate_all_components_connected_in_array(
da91b29a
PP
572 cfg->cmd_data.run.filters,
573 bt_value_borrow_from_private(connected_components),
ebba3338
PP
574 error_buf, error_buf_size);
575 if (ret) {
576 goto end;
577 }
578
579 ret = validate_all_components_connected_in_array(
da91b29a
PP
580 cfg->cmd_data.run.sinks,
581 bt_value_borrow_from_private(connected_components),
ebba3338
PP
582 error_buf, error_buf_size);
583 if (ret) {
584 goto end;
585 }
586
587end:
65300d60 588 bt_object_put_ref(connected_components);
ebba3338
PP
589 return ret;
590}
591
592static int validate_no_duplicate_connection(struct bt_config *cfg,
593 char *error_buf, size_t error_buf_size)
594{
595 size_t i;
596 int ret = 0;
da91b29a
PP
597 struct bt_private_value *flat_connection_names =
598 bt_private_value_map_create();
ebba3338
PP
599 GString *flat_connection_name = NULL;
600
601 if (!flat_connection_names) {
602 ret = -1;
603 goto end;
604 }
605
606 flat_connection_name = g_string_new(NULL);
607 if (!flat_connection_name) {
608 ret = -1;
609 goto end;
610 }
611
db0f160a 612 for (i = 0; i < cfg->cmd_data.run.connections->len; i++) {
ebba3338 613 struct bt_config_connection *connection =
db0f160a 614 g_ptr_array_index(cfg->cmd_data.run.connections, i);
ebba3338 615
db0f160a 616 g_string_printf(flat_connection_name, "%s\x01%s\x01%s\x01%s",
9009cc24
PP
617 connection->upstream_comp_name->str,
618 connection->upstream_port_glob->str,
619 connection->downstream_comp_name->str,
620 connection->downstream_port_glob->str);
ebba3338 621
da91b29a
PP
622 if (bt_value_map_has_entry(bt_value_borrow_from_private(
623 flat_connection_names),
ebba3338
PP
624 flat_connection_name->str)) {
625 snprintf(error_buf, error_buf_size,
626 "Duplicate connection:\n %s\n",
627 connection->arg->str);
628 ret = -1;
629 goto end;
630 }
631
da91b29a 632 ret = bt_private_value_map_insert_entry(flat_connection_names,
ebba3338
PP
633 flat_connection_name->str, bt_value_null);
634 if (ret) {
635 goto end;
636 }
637 }
638
639end:
65300d60 640 bt_object_put_ref(flat_connection_names);
ebba3338
PP
641
642 if (flat_connection_name) {
643 g_string_free(flat_connection_name, TRUE);
644 }
645
646 return ret;
647}
648
649static int validate_connections(struct bt_config *cfg, char *error_buf,
650 size_t error_buf_size)
651{
652 int ret;
653
654 ret = validate_all_endpoints_exist(cfg, error_buf, error_buf_size);
655 if (ret) {
656 goto end;
657 }
658
659 ret = validate_connection_directions(cfg, error_buf, error_buf_size);
660 if (ret) {
661 goto end;
662 }
663
ebba3338
PP
664 ret = validate_all_components_connected(cfg, error_buf, error_buf_size);
665 if (ret) {
666 goto end;
667 }
668
669 ret = validate_no_duplicate_connection(cfg, error_buf, error_buf_size);
670 if (ret) {
671 goto end;
672 }
673
db0f160a 674 ret = validate_no_cycles(cfg, error_buf, error_buf_size);
ebba3338
PP
675 if (ret) {
676 goto end;
677 }
678
ebba3338 679end:
ebba3338
PP
680 return ret;
681}
682
9009cc24 683int bt_config_cli_args_create_connections(struct bt_config *cfg,
ebba3338
PP
684 struct bt_value *connection_args,
685 char *error_buf, size_t error_buf_size)
686{
687 int ret;
688 size_t i;
689
db0f160a
PP
690 if (!all_named_and_printable(cfg)) {
691 snprintf(error_buf, error_buf_size,
692 "One or more components are unnamed (use --name) or contain a non-printable character\n");
ebba3338
PP
693 goto error;
694 }
695
07208d85 696 for (i = 0; i < bt_value_array_get_size(connection_args); i++) {
ebba3338 697 struct bt_value *arg_value =
07208d85
PP
698 bt_value_array_borrow_element_by_index(
699 connection_args, i);
ebba3338
PP
700 const char *arg;
701 struct bt_config_connection *cfg_connection;
702
703 ret = bt_value_string_get(arg_value, &arg);
f6ccaed9 704 BT_ASSERT(ret == 0);
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.065597 seconds and 4 git commands to generate.