Fix: wrong casting of return value
[lttng-tools.git] / src / common / config / config.c
CommitLineData
1501a7f3
JG
1/*
2 * Copyright (C) 2013 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18#define _GNU_SOURCE
19#include <assert.h>
1501a7f3 20#include <ctype.h>
1501a7f3
JG
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
36f2332b 24#include <inttypes.h>
dcf266c0
JG
25#include <dirent.h>
26#include <unistd.h>
27#include <sys/types.h>
28#include <sys/stat.h>
1501a7f3
JG
29
30#include <common/defaults.h>
31#include <common/error.h>
32#include <common/macros.h>
33#include <common/utils.h>
fb198a11
JG
34#include <lttng/lttng-error.h>
35#include <libxml/parser.h>
36#include <libxml/valid.h>
37#include <libxml/xmlschemas.h>
dcf266c0
JG
38#include <libxml/tree.h>
39#include <lttng/lttng.h>
40#include <lttng/snapshot.h>
1501a7f3
JG
41
42#include "config.h"
36f2332b 43#include "config-internal.h"
1501a7f3
JG
44
45struct handler_filter_args {
46 const char* section;
47 config_entry_handler_cb handler;
48 void *user_data;
49};
50
dcf266c0
JG
51struct session_config_validation_ctx {
52 xmlSchemaParserCtxtPtr parser_ctx;
53 xmlSchemaPtr schema;
54 xmlSchemaValidCtxtPtr schema_validation_ctx;
55};
56
1501a7f3
JG
57const char * const config_str_yes = "yes";
58const char * const config_str_true = "true";
59const char * const config_str_on = "on";
60const char * const config_str_no = "no";
61const char * const config_str_false = "false";
62const char * const config_str_off = "off";
36f2332b 63const char * const config_xml_encoding = "UTF-8";
fb198a11 64const size_t config_xml_encoding_bytes_per_char = 2; /* Size of the encoding's largest character */
36f2332b
JG
65const char * const config_xml_indent_string = "\t";
66const char * const config_xml_true = "true";
67const char * const config_xml_false = "false";
1501a7f3 68
fb198a11
JG
69const char * const config_element_channel = "channel";
70const char * const config_element_channels = "channels";
71const char * const config_element_domain = "domain";
72const char * const config_element_domains = "domains";
73const char * const config_element_event = "event";
74const char * const config_element_events = "events";
75const char * const config_element_context = "context";
76const char * const config_element_contexts = "contexts";
77const char * const config_element_attributes = "attributes";
78const char * const config_element_exclusion = "exclusion";
79const char * const config_element_exclusions = "exclusions";
80const char * const config_element_function_attributes = "function_attributes";
81const char * const config_element_probe_attributes = "probe_attributes";
82const char * const config_element_symbol_name = "symbol_name";
83const char * const config_element_address = "address";
84const char * const config_element_offset = "offset";
85const char * const config_element_name = "name";
86const char * const config_element_enabled = "enabled";
87const char * const config_element_overwrite_mode = "overwrite_mode";
88const char * const config_element_subbuf_size = "subbuffer_size";
89const char * const config_element_num_subbuf = "subbuffer_count";
90const char * const config_element_switch_timer_interval = "switch_timer_interval";
91const char * const config_element_read_timer_interval = "read_timer_interval";
92const char * const config_element_output = "output";
93const char * const config_element_output_type = "output_type";
94const char * const config_element_tracefile_size = "tracefile_size";
95const char * const config_element_tracefile_count = "tracefile_count";
96const char * const config_element_live_timer_interval = "live_timer_interval";
97const char * const config_element_type = "type";
98const char * const config_element_buffer_type = "buffer_type";
99const char * const config_element_session = "session";
100const char * const config_element_sessions = "sessions";
101const char * const config_element_perf = "perf";
102const char * const config_element_config = "config";
103const char * const config_element_started = "started";
104const char * const config_element_snapshot_mode = "snapshot_mode";
105const char * const config_element_loglevel = "loglevel";
106const char * const config_element_loglevel_type = "loglevel_type";
107const char * const config_element_filter = "filter";
108const char * const config_element_snapshot_outputs = "snapshot_outputs";
109const char * const config_element_consumer_output = "consumer_output";
110const char * const config_element_destination = "destination";
111const char * const config_element_path = "path";
112const char * const config_element_net_output = "net_output";
113const char * const config_element_control_uri = "control_uri";
114const char * const config_element_data_uri = "data_uri";
115const char * const config_element_max_size = "max_size";
116
117const char * const config_domain_type_kernel = "KERNEL";
118const char * const config_domain_type_ust = "UST";
119const char * const config_domain_type_jul = "JUL";
120
121const char * const config_buffer_type_per_pid = "PER_PID";
122const char * const config_buffer_type_per_uid = "PER_UID";
123const char * const config_buffer_type_global = "GLOBAL";
124
125const char * const config_overwrite_mode_discard = "DISCARD";
126const char * const config_overwrite_mode_overwrite = "OVERWRITE";
127
128const char * const config_output_type_splice = "SPLICE";
129const char * const config_output_type_mmap = "MMAP";
130
131const char * const config_loglevel_type_all = "ALL";
132const char * const config_loglevel_type_range = "RANGE";
133const char * const config_loglevel_type_single = "SINGLE";
134
135const char * const config_event_type_all = "ALL";
136const char * const config_event_type_tracepoint = "TRACEPOINT";
137const char * const config_event_type_probe = "PROBE";
138const char * const config_event_type_function = "FUNCTION";
139const char * const config_event_type_function_entry = "FUNCTION_ENTRY";
140const char * const config_event_type_noop = "NOOP";
141const char * const config_event_type_syscall = "SYSCALL";
142const char * const config_event_type_kprobe = "KPROBE";
143const char * const config_event_type_kretprobe = "KRETPROBE";
144
145const char * const config_event_context_pid = "PID";
146const char * const config_event_context_procname = "PROCNAME";
147const char * const config_event_context_prio = "PRIO";
148const char * const config_event_context_nice = "NICE";
149const char * const config_event_context_vpid = "VPID";
150const char * const config_event_context_tid = "TID";
151const char * const config_event_context_vtid = "VTID";
152const char * const config_event_context_ppid = "PPID";
153const char * const config_event_context_vppid = "VPPID";
154const char * const config_event_context_pthread_id = "PTHREAD_ID";
155const char * const config_event_context_hostname = "HOSTNAME";
156const char * const config_event_context_ip = "IP";
157
dcf266c0
JG
158struct consumer_output {
159 int enabled;
160 char *path;
161 char *control_uri;
162 char *data_uri;
163};
164
1501a7f3
JG
165static int config_entry_handler_filter(struct handler_filter_args *args,
166 const char *section, const char *name, const char *value)
167{
168 int ret = 0;
169 struct config_entry entry = { section, name, value };
170
171 assert(args);
172
173 if (!section || !name || !value) {
174 ret = -EIO;
175 goto end;
176 }
177
178 if (args->section) {
179 if (strcmp(args->section, section)) {
180 goto end;
181 }
182 }
183
184 ret = args->handler(&entry, args->user_data);
185end:
186 return ret;
187}
188
189LTTNG_HIDDEN
190int config_get_section_entries(const char *override_path, const char *section,
191 config_entry_handler_cb handler, void *user_data)
192{
193 int ret = 0;
7ab02a27 194 char *path;
1501a7f3
JG
195 FILE *config_file = NULL;
196 struct handler_filter_args filter = { section, handler, user_data };
197
7ab02a27
DG
198 /* First, try system-wide conf. file. */
199 path = DEFAULT_DAEMON_SYSTEM_CONFIGPATH;
200
201 config_file = fopen(path, "r");
202 if (config_file) {
203 DBG("Loading daemon conf file at %s", path);
204 /*
205 * Return value is not very important here since error or not, we
206 * continue and try the next possible conf. file.
207 */
208 (void) ini_parse_file(config_file,
209 (ini_entry_handler) config_entry_handler_filter,
210 (void *) &filter);
211 fclose(config_file);
212 }
213
214 /* Second is the user local configuration. */
215 path = utils_get_home_dir();
216 if (path) {
217 char fullpath[PATH_MAX];
218
219 ret = snprintf(fullpath, sizeof(fullpath),
220 DEFAULT_DAEMON_HOME_CONFIGPATH, path);
221 if (ret < 0) {
222 PERROR("snprintf user conf. path");
223 goto error;
224 }
225
226 config_file = fopen(fullpath, "r");
227 if (config_file) {
228 DBG("Loading daemon user conf file at %s", path);
229 /*
230 * Return value is not very important here since error or not, we
231 * continue and try the next possible conf. file.
232 */
233 (void) ini_parse_file(config_file,
234 (ini_entry_handler) config_entry_handler_filter,
235 (void *) &filter);
236 fclose(config_file);
237 }
238 }
239
240 /* Final path is the one that the user might have provided. */
1501a7f3
JG
241 if (override_path) {
242 config_file = fopen(override_path, "r");
243 if (config_file) {
7ab02a27
DG
244 DBG("Loading daemon command line conf file at %s", override_path);
245 (void) ini_parse_file(config_file,
246 (ini_entry_handler) config_entry_handler_filter,
247 (void *) &filter);
248 fclose(config_file);
1501a7f3
JG
249 } else {
250 ERR("Failed to open daemon configuration file at %s",
251 override_path);
252 ret = -ENOENT;
7ab02a27 253 goto error;
1501a7f3
JG
254 }
255 }
256
7ab02a27
DG
257 /* Everything went well. */
258 ret = 0;
1501a7f3 259
7ab02a27 260error:
1501a7f3
JG
261 return ret;
262}
263
264LTTNG_HIDDEN
265int config_parse_value(const char *value)
266{
267 int i, ret = 0;
268 char *endptr, *lower_str;
269 size_t len;
270 unsigned long v;
271
272 len = strlen(value);
273 if (!len) {
274 ret = -1;
275 goto end;
276 }
277
278 v = strtoul(value, &endptr, 10);
279 if (endptr != value) {
280 ret = v;
281 goto end;
282 }
283
284 lower_str = zmalloc(len + 1);
285 if (!lower_str) {
286 PERROR("zmalloc");
287 ret = -errno;
288 goto end;
289 }
290
291 for (i = 0; i < len; i++) {
292 lower_str[i] = tolower(value[i]);
293 }
294
295 if (!strcmp(lower_str, config_str_yes) ||
296 !strcmp(lower_str, config_str_true) ||
297 !strcmp(lower_str, config_str_on)) {
298 ret = 1;
299 } else if (!strcmp(lower_str, config_str_no) ||
300 !strcmp(lower_str, config_str_false) ||
301 !strcmp(lower_str, config_str_off)) {
302 ret = 0;
303 } else {
304 ret = -1;
305 }
306
307 free(lower_str);
308end:
309 return ret;
310}
36f2332b
JG
311
312/*
313 * Returns a xmlChar string which must be released using xmlFree().
314 */
315static xmlChar *encode_string(const char *in_str)
316{
317 xmlChar *out_str = NULL;
318 xmlCharEncodingHandlerPtr handler;
319 int out_len, ret, in_len;
320
321 assert(in_str);
322
323 handler = xmlFindCharEncodingHandler(config_xml_encoding);
324 if (!handler) {
325 ERR("xmlFindCharEncodingHandler return NULL!. Configure issue!");
326 goto end;
327 }
328
329 in_len = strlen(in_str);
330 /*
331 * Add 1 byte for the NULL terminted character. The factor 2 here is
332 * because UTF-8 can be on two bytes so this fits the worst case for each
333 * bytes.
334 */
335 out_len = (in_len * 2) + 1;
336 out_str = xmlMalloc(out_len);
337 if (!out_str) {
338 goto end;
339 }
340
341 ret = handler->input(out_str, &out_len, (const xmlChar *) in_str, &in_len);
342 if (ret < 0) {
343 xmlFree(out_str);
344 out_str = NULL;
345 goto end;
346 }
347
348 /* out_len is now the size of out_str */
349 out_str[out_len] = '\0';
350end:
351 return out_str;
352}
353
354LTTNG_HIDDEN
355struct config_writer *config_writer_create(int fd_output)
356{
357 int ret;
358 struct config_writer *writer;
359 xmlOutputBufferPtr buffer;
360
361 writer = zmalloc(sizeof(struct config_writer));
362 if (!writer) {
363 PERROR("zmalloc config_writer_create");
364 goto end;
365 }
366
367 buffer = xmlOutputBufferCreateFd(fd_output, NULL);
368 if (!buffer) {
369 goto error_destroy;
370 }
371
372 writer->writer = xmlNewTextWriter(buffer);
373 ret = xmlTextWriterStartDocument(writer->writer, NULL,
374 config_xml_encoding, NULL);
375 if (ret < 0) {
376 goto error_destroy;
377 }
378
379 ret = xmlTextWriterSetIndentString(writer->writer,
380 BAD_CAST config_xml_indent_string);
381 if (ret) {
382 goto error_destroy;
383 }
384
385 ret = xmlTextWriterSetIndent(writer->writer, 1);
386 if (ret) {
387 goto error_destroy;
388 }
389
390end:
391 return writer;
392error_destroy:
393 config_writer_destroy(writer);
394 return NULL;
395}
396
397LTTNG_HIDDEN
398int config_writer_destroy(struct config_writer *writer)
399{
400 int ret = 0;
401
402 if (!writer) {
403 ret = -EINVAL;
404 goto end;
405 }
406
407 if (xmlTextWriterEndDocument(writer->writer) < 0) {
408 WARN("Could not close XML document");
409 ret = -EIO;
410 }
411
412 if (writer->writer) {
413 xmlFreeTextWriter(writer->writer);
414 }
415
416 free(writer);
417end:
418 return ret;
419}
420
421LTTNG_HIDDEN
422int config_writer_open_element(struct config_writer *writer,
423 const char *element_name)
424{
425 int ret;
426 xmlChar *encoded_element_name;
427
428 if (!writer || !writer->writer || !element_name || !element_name[0]) {
429 ret = -1;
430 goto end;
431 }
432
433 encoded_element_name = encode_string(element_name);
434 if (!encoded_element_name) {
435 ret = -1;
436 goto end;
437 }
438
439 ret = xmlTextWriterStartElement(writer->writer, encoded_element_name);
440 xmlFree(encoded_element_name);
441end:
442 return ret > 0 ? 0 : ret;
443}
444
445LTTNG_HIDDEN
446int config_writer_close_element(struct config_writer *writer)
447{
448 int ret;
449
450 if (!writer || !writer->writer) {
451 ret = -1;
452 goto end;
453 }
454
455 ret = xmlTextWriterEndElement(writer->writer);
456end:
457 return ret > 0 ? 0 : ret;
458}
459
460LTTNG_HIDDEN
461int config_writer_write_element_unsigned_int(struct config_writer *writer,
462 const char *element_name, uint64_t value)
463{
464 int ret;
465 xmlChar *encoded_element_name;
466
467 if (!writer || !writer->writer || !element_name || !element_name[0]) {
468 ret = -1;
469 goto end;
470 }
471
472 encoded_element_name = encode_string(element_name);
473 if (!encoded_element_name) {
474 ret = -1;
475 goto end;
476 }
477
478 ret = xmlTextWriterWriteFormatElement(writer->writer,
479 encoded_element_name, "%" PRIu64, value);
480 xmlFree(encoded_element_name);
481end:
482 return ret > 0 ? 0 : ret;
483}
484
485LTTNG_HIDDEN
486int config_writer_write_element_signed_int(struct config_writer *writer,
487 const char *element_name, int64_t value)
488{
489 int ret;
490 xmlChar *encoded_element_name;
491
492 if (!writer || !writer->writer || !element_name || !element_name[0]) {
493 ret = -1;
494 goto end;
495 }
496
497 encoded_element_name = encode_string(element_name);
498 if (!encoded_element_name) {
499 ret = -1;
500 goto end;
501 }
502
503 ret = xmlTextWriterWriteFormatElement(writer->writer,
504 encoded_element_name, "%" PRIi64, value);
505 xmlFree(encoded_element_name);
506end:
507 return ret > 0 ? 0 : ret;
508}
509
510LTTNG_HIDDEN
511int config_writer_write_element_bool(struct config_writer *writer,
512 const char *element_name, int value)
513{
514 return config_writer_write_element_string(writer, element_name,
515 value ? config_xml_true : config_xml_false);
516}
517
518LTTNG_HIDDEN
519int config_writer_write_element_string(struct config_writer *writer,
520 const char *element_name, const char *value)
521{
522 int ret;
523 xmlChar *encoded_element_name = NULL;
524 xmlChar *encoded_value = NULL;
525
526 if (!writer || !writer->writer || !element_name || !element_name[0] ||
527 !value) {
528 ret = -1;
529 goto end;
530 }
531
532 encoded_element_name = encode_string(element_name);
533 if (!encoded_element_name) {
534 ret = -1;
535 goto end;
536 }
537
538 encoded_value = encode_string(value);
539 if (!encoded_value) {
540 ret = -1;
541 goto end;
542 }
543
544 ret = xmlTextWriterWriteElement(writer->writer, encoded_element_name,
dcf266c0 545 encoded_value);
36f2332b
JG
546end:
547 xmlFree(encoded_element_name);
548 xmlFree(encoded_value);
549 return ret > 0 ? 0 : ret;
550}
dcf266c0
JG
551
552static
553void xml_error_handler(void *ctx, const char *format, ...)
554{
555 char *errMsg;
556 va_list args;
557 int ret;
558
559 va_start(args, format);
560 ret = vasprintf(&errMsg, format, args);
6c043b48 561 va_end(args);
dcf266c0
JG
562 if (ret == -1) {
563 ERR("String allocation failed in xml error handler");
564 return;
565 }
dcf266c0
JG
566
567 fprintf(stderr, "XML Error: %s", errMsg);
568 free(errMsg);
569}
570
571static
572void fini_session_config_validation_ctx(
573 struct session_config_validation_ctx *ctx)
574{
575 if (ctx->parser_ctx) {
576 xmlSchemaFreeParserCtxt(ctx->parser_ctx);
577 }
578
579 if (ctx->schema) {
580 xmlSchemaFree(ctx->schema);
581 }
582
583 if (ctx->schema_validation_ctx) {
584 xmlSchemaFreeValidCtxt(ctx->schema_validation_ctx);
585 }
586
587 memset(ctx, 0, sizeof(struct session_config_validation_ctx));
588}
589
54e399cb
JG
590static
591char *get_session_config_xsd_path()
592{
593 char *xsd_path;
594 const char *base_path = getenv(DEFAULT_SESSION_CONFIG_XSD_PATH_ENV);
595 size_t base_path_len;
596 size_t max_path_len;
597
598 if (!base_path) {
599 base_path = DEFAULT_SESSION_CONFIG_XSD_PATH;
600 }
601
602 base_path_len = strlen(base_path);
603 max_path_len = base_path_len +
604 sizeof(DEFAULT_SESSION_CONFIG_XSD_FILENAME) + 1;
605 xsd_path = zmalloc(max_path_len);
606 if (!xsd_path) {
607 goto end;
608 }
609
610 strncpy(xsd_path, base_path, max_path_len);
611 if (xsd_path[base_path_len - 1] != '/') {
612 xsd_path[base_path_len++] = '/';
613 }
614
615 strncpy(xsd_path + base_path_len, DEFAULT_SESSION_CONFIG_XSD_FILENAME,
616 max_path_len - base_path_len);
617end:
618 return xsd_path;
619}
620
dcf266c0
JG
621static
622int init_session_config_validation_ctx(
623 struct session_config_validation_ctx *ctx)
624{
625 int ret;
54e399cb
JG
626 char *xsd_path = get_session_config_xsd_path();
627
628 if (!xsd_path) {
629 ret = -LTTNG_ERR_NOMEM;
630 goto end;
631 }
dcf266c0 632
54e399cb 633 ctx->parser_ctx = xmlSchemaNewParserCtxt(xsd_path);
dcf266c0
JG
634 if (!ctx->parser_ctx) {
635 ERR("XSD parser context creation failed");
636 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
637 goto end;
638 }
639 xmlSchemaSetParserErrors(ctx->parser_ctx, xml_error_handler,
640 xml_error_handler, NULL);
641
642 ctx->schema = xmlSchemaParse(ctx->parser_ctx);
643 if (!ctx->schema) {
644 ERR("XSD parsing failed");
645 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
646 goto end;
647 }
648
649 ctx->schema_validation_ctx = xmlSchemaNewValidCtxt(ctx->schema);
650 if (!ctx->schema_validation_ctx) {
651 ERR("XSD validation context creation failed");
652 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
653 goto end;
654 }
655
656 xmlSchemaSetValidErrors(ctx->schema_validation_ctx, xml_error_handler,
657 xml_error_handler, NULL);
658 ret = 0;
659
660end:
661 if (ret) {
662 fini_session_config_validation_ctx(ctx);
663 }
664
54e399cb 665 free(xsd_path);
dcf266c0
JG
666 return ret;
667}
668
669static
670int parse_uint(xmlChar *str, uint64_t *val)
671{
672 int ret;
673 char *endptr;
674
675 if (!str || !val) {
676 ret = -1;
677 goto end;
678 }
679
680 *val = strtoull((const char *) str, &endptr, 10);
681 if (!endptr || *endptr) {
682 ret = -1;
683 } else {
684 ret = 0;
685 }
686
687end:
688 return ret;
689}
690
691static
692int parse_int(xmlChar *str, int64_t *val)
693{
694 int ret;
695 char *endptr;
696
697 if (!str || !val) {
698 ret = -1;
699 goto end;
700 }
701
702 *val = strtoll((const char *) str, &endptr, 10);
703 if (!endptr || *endptr) {
704 ret = -1;
705 } else {
706 ret = 0;
707 }
708
709end:
710 return ret;
711}
712
713static
714int parse_bool(xmlChar *str, int *val)
715{
716 int ret = 0;
717
718 if (!str || !val) {
719 ret = -1;
720 goto end;
721 }
722
723 if (!strcmp((const char *) str, config_xml_true)) {
724 *val = 1;
725 } else if (!strcmp((const char *) str, config_xml_false)) {
726 *val = 0;
727 } else {
728 WARN("Invalid boolean value encoutered (%s).",
729 (const char *) str);
730 ret = -1;
731 }
732end:
733 return ret;
734}
735
736static
737int get_domain_type(xmlChar *domain)
738{
739 int ret;
740
741 if (!domain) {
742 goto error;
743 }
744
745 if (!strcmp((char *) domain, config_domain_type_kernel)) {
746 ret = LTTNG_DOMAIN_KERNEL;
747 } else if (!strcmp((char *) domain, config_domain_type_ust)) {
748 ret = LTTNG_DOMAIN_UST;
749 } else if (!strcmp((char *) domain, config_domain_type_jul)) {
750 ret = LTTNG_DOMAIN_JUL;
751 } else {
752 goto error;
753 }
754
755 return ret;
756error:
757 return -1;
758}
759
760static
761int get_buffer_type(xmlChar *buffer_type)
762{
763 int ret;
764
765 if (!buffer_type) {
766 goto error;
767 }
768
769 if (!strcmp((char *) buffer_type, config_buffer_type_global)) {
770 ret = LTTNG_BUFFER_GLOBAL;
771 } else if (!strcmp((char *) buffer_type, config_buffer_type_per_uid)) {
772 ret = LTTNG_BUFFER_PER_UID;
773 } else if (!strcmp((char *) buffer_type, config_buffer_type_per_pid)) {
774 ret = LTTNG_BUFFER_PER_PID;
775 } else {
776 goto error;
777 }
778
779 return ret;
780error:
781 return -1;
782}
783
784static
785int get_overwrite_mode(xmlChar *overwrite_mode)
786{
787 int ret;
788
789 if (!overwrite_mode) {
790 goto error;
791 }
792
793 if (!strcmp((char *) overwrite_mode, config_overwrite_mode_overwrite)) {
794 ret = 1;
795 } else if (!strcmp((char *) overwrite_mode,
796 config_overwrite_mode_discard)) {
797 ret = 0;
798 } else {
799 goto error;
800 }
801
802 return ret;
803error:
804 return -1;
805}
806
807static
808int get_output_type(xmlChar *output_type)
809{
810 int ret;
811
812 if (!output_type) {
813 goto error;
814 }
815
816 if (!strcmp((char *) output_type, config_output_type_mmap)) {
817 ret = LTTNG_EVENT_MMAP;
818 } else if (!strcmp((char *) output_type, config_output_type_splice)) {
819 ret = LTTNG_EVENT_SPLICE;
820 } else {
821 goto error;
822 }
823
824 return ret;
825error:
826 return -1;
827}
828
829static
830int get_event_type(xmlChar *event_type)
831{
832 int ret;
833
834 if (!event_type) {
835 goto error;
836 }
837
838 if (!strcmp((char *) event_type, config_event_type_all)) {
839 ret = LTTNG_EVENT_ALL;
840 } else if (!strcmp((char *) event_type, config_event_type_tracepoint)) {
841 ret = LTTNG_EVENT_TRACEPOINT;
842 } else if (!strcmp((char *) event_type, config_event_type_probe)) {
843 ret = LTTNG_EVENT_PROBE;
844 } else if (!strcmp((char *) event_type, config_event_type_function)) {
845 ret = LTTNG_EVENT_FUNCTION;
846 } else if (!strcmp((char *) event_type,
847 config_event_type_function_entry)) {
848 ret = LTTNG_EVENT_FUNCTION_ENTRY;
849 } else if (!strcmp((char *) event_type, config_event_type_noop)) {
850 ret = LTTNG_EVENT_NOOP;
851 } else if (!strcmp((char *) event_type, config_event_type_syscall)) {
852 ret = LTTNG_EVENT_SYSCALL;
853 } else {
854 goto error;
855 }
856
857 return ret;
858error:
859 return -1;
860}
861
862static
863int get_loglevel_type(xmlChar *loglevel_type)
864{
865 int ret;
866
867 if (!loglevel_type) {
868 goto error;
869 }
870
871 if (!strcmp((char *) loglevel_type, config_loglevel_type_all)) {
872 ret = LTTNG_EVENT_LOGLEVEL_ALL;
873 } else if (!strcmp((char *) loglevel_type,
874 config_loglevel_type_range)) {
875 ret = LTTNG_EVENT_LOGLEVEL_RANGE;
876 } else if (!strcmp((char *) loglevel_type,
877 config_loglevel_type_single)) {
878 ret = LTTNG_EVENT_LOGLEVEL_SINGLE;
879 } else {
880 goto error;
881 }
882
883 return ret;
884error:
885 return -1;
886}
887
888/*
889 * Return the context type or -1 on error.
890 */
891static
892int get_context_type(xmlChar *context_type)
893{
894 int ret;
895
896 if (!context_type) {
897 goto error;
898 }
899
900 if (!strcmp((char *) context_type, config_event_context_pid)) {
901 ret = LTTNG_EVENT_CONTEXT_PID;
902 } else if (!strcmp((char *) context_type,
903 config_event_context_procname)) {
904 ret = LTTNG_EVENT_CONTEXT_PROCNAME;
905 } else if (!strcmp((char *) context_type,
906 config_event_context_prio)) {
907 ret = LTTNG_EVENT_CONTEXT_PRIO;
908 } else if (!strcmp((char *) context_type,
909 config_event_context_nice)) {
910 ret = LTTNG_EVENT_CONTEXT_NICE;
911 } else if (!strcmp((char *) context_type,
912 config_event_context_vpid)) {
913 ret = LTTNG_EVENT_CONTEXT_VPID;
914 } else if (!strcmp((char *) context_type,
915 config_event_context_tid)) {
916 ret = LTTNG_EVENT_CONTEXT_TID;
917 } else if (!strcmp((char *) context_type,
918 config_event_context_vtid)) {
919 ret = LTTNG_EVENT_CONTEXT_VTID;
920 } else if (!strcmp((char *) context_type,
921 config_event_context_ppid)) {
922 ret = LTTNG_EVENT_CONTEXT_PPID;
923 } else if (!strcmp((char *) context_type,
924 config_event_context_vppid)) {
925 ret = LTTNG_EVENT_CONTEXT_VPPID;
926 } else if (!strcmp((char *) context_type,
927 config_event_context_pthread_id)) {
928 ret = LTTNG_EVENT_CONTEXT_PTHREAD_ID;
929 } else if (!strcmp((char *) context_type,
930 config_event_context_hostname)) {
931 ret = LTTNG_EVENT_CONTEXT_HOSTNAME;
932 } else if (!strcmp((char *) context_type,
933 config_event_context_ip)) {
934 ret = LTTNG_EVENT_CONTEXT_IP;
935 } else {
936 goto error;
937 }
938
939 return ret;
940error:
941 return -1;
942}
943
944static
945int init_domain(xmlNodePtr domain_node, struct lttng_domain *domain)
946{
947 int ret;
948 xmlNodePtr node;
949
950 for (node = xmlFirstElementChild(domain_node); node;
951 node = xmlNextElementSibling(node)) {
952 if (!strcmp((const char *) node->name, config_element_type)) {
953 /* domain type */
954 xmlChar *node_content = xmlNodeGetContent(node);
955 if (!node_content) {
956 ret = -LTTNG_ERR_NOMEM;
957 goto end;
958 }
959
960 ret = get_domain_type(node_content);
961 free(node_content);
962 if (ret < 0) {
963 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
964 goto end;
965 }
966
967 domain->type = ret;
968 } else if (!strcmp((const char *) node->name,
969 config_element_buffer_type)) {
970 /* buffer type */
971 xmlChar *node_content = xmlNodeGetContent(node);
972 if (!node_content) {
973 ret = -LTTNG_ERR_NOMEM;
974 goto end;
975 }
976
977 ret = get_buffer_type(node_content);
978 free(node_content);
979 if (ret < 0) {
980 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
981 goto end;
982 }
983
984 domain->buf_type = ret;
985 }
986 }
987 ret = 0;
988end:
989 return ret;
990}
991
992static
993int get_net_output_uris(xmlNodePtr net_output_node, char **control_uri,
994 char **data_uri)
995{
996 xmlNodePtr node;
997
998 for (node = xmlFirstElementChild(net_output_node); node;
999 node = xmlNextElementSibling(node)) {
1000 if (!strcmp((const char *) node->name, config_element_control_uri)) {
1001 /* control_uri */
1002 *control_uri = (char *) xmlNodeGetContent(node);
1003 if (!*control_uri) {
1004 break;
1005 }
1006 } else {
1007 /* data_uri */
1008 *data_uri = (char *) xmlNodeGetContent(node);
1009 if (!*data_uri) {
1010 break;
1011 }
1012 }
1013 }
1014
1015 return *control_uri || *data_uri ? 0 : -LTTNG_ERR_LOAD_INVALID_CONFIG;
1016}
1017
1018static
1019int process_consumer_output(xmlNodePtr consumer_output_node,
1020 struct consumer_output *output)
1021{
1022 int ret;
1023 xmlNodePtr node;
1024
1025 assert(output);
1026
1027 for (node = xmlFirstElementChild(consumer_output_node); node;
1028 node = xmlNextElementSibling(node)) {
1029 if (!strcmp((const char *) node->name, config_element_enabled)) {
1030 xmlChar *enabled_str = xmlNodeGetContent(node);
1031
1032 /* enabled */
1033 if (!enabled_str) {
1034 ret = -LTTNG_ERR_NOMEM;
1035 goto end;
1036 }
1037
1038 ret = parse_bool(enabled_str, &output->enabled);
1039 free(enabled_str);
1040 if (ret) {
1041 goto end;
1042 }
1043 } else {
1044 xmlNodePtr output_type_node;
1045
1046 /* destination */
1047 output_type_node = xmlFirstElementChild(node);
1048 if (!output_type_node) {
1049 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1050 goto end;
1051 }
1052
1053 if (!strcmp((const char *) output_type_node->name,
1054 config_element_path)) {
1055 /* path */
1056 output->path = (char *) xmlNodeGetContent(output_type_node);
1057 if (!output->path) {
1058 ret = -LTTNG_ERR_NOMEM;
1059 goto end;
1060 }
1061 } else {
1062 /* net_output */
1063 ret = get_net_output_uris(output_type_node,
1064 &output->control_uri, &output->data_uri);
1065 if (ret) {
1066 goto end;
1067 }
1068 }
1069 }
1070 }
1071 ret = 0;
1072
1073end:
1074 if (ret) {
1075 free(output->path);
1076 free(output->control_uri);
1077 free(output->data_uri);
1078 memset(output, 0, sizeof(struct consumer_output));
1079 }
1080 return ret;
1081}
1082
1083static
1084int create_session_net_output(const char *name, struct lttng_domain *domain,
1085 const char *control_uri, const char *data_uri)
1086{
1087 int ret;
1088 struct lttng_handle *handle;
1089 const char *uri = NULL;
1090
1091 assert(name);
1092 assert(domain);
1093
1094 handle = lttng_create_handle(name, domain);
1095 if (!handle) {
1096 ret = -LTTNG_ERR_NOMEM;
1097 goto end;
1098 }
1099
1100 if (!control_uri || !data_uri) {
1101 uri = control_uri ? control_uri : data_uri;
1102 control_uri = uri;
1103 data_uri = uri;
1104 }
1105
1106 ret = lttng_set_consumer_url(handle, control_uri, data_uri);
1107 lttng_destroy_handle(handle);
1108end:
1109 return ret;
1110}
1111
1112static
1113int create_snapshot_session(const char *session_name, xmlNodePtr output_node)
1114{
1115 int ret;
1116 xmlNodePtr node = NULL;
1117 xmlNodePtr snapshot_output_list_node;
1118 xmlNodePtr snapshot_output_node;
1119
1120 assert(session_name);
1121
1122 ret = lttng_create_session_snapshot(session_name, NULL);
1123 if (ret) {
1124 goto end;
1125 }
1126
1127 if (!output_node) {
1128 goto end;
1129 }
1130
1131 snapshot_output_list_node = xmlFirstElementChild(output_node);
1132
1133 /* Parse and create snapshot outputs */
1134
1135 for (snapshot_output_node =
1136 xmlFirstElementChild(snapshot_output_list_node);
1137 snapshot_output_node; snapshot_output_node =
1138 xmlNextElementSibling(snapshot_output_node)) {
1139 char *name = NULL;
1140 uint64_t max_size = UINT64_MAX;
1141 struct consumer_output output = { 0 };
1142 struct lttng_snapshot_output *snapshot_output = NULL;
1143
1144 for (node = xmlFirstElementChild(snapshot_output_node); node;
1145 node = xmlNextElementSibling(node)) {
1146 if (!strcmp((const char *) node->name,
1147 config_element_name)) {
1148 /* name */
1149 name = (char *) xmlNodeGetContent(node);
1150 if (!name) {
1151 ret = -LTTNG_ERR_NOMEM;
1152 goto error_snapshot_output;
1153 }
1154 } else if (!strcmp((const char *) node->name,
1155 config_element_max_size)) {
1156 xmlChar *content = xmlNodeGetContent(node);
1157
1158 /* max_size */
1159 if (!content) {
1160 ret = -LTTNG_ERR_NOMEM;
1161 goto error_snapshot_output;
1162 }
1163 ret = parse_uint(content, &max_size);
1164 free(content);
1165 if (ret) {
1166 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1167 goto error_snapshot_output;
1168 }
1169 } else {
1170 /* consumer_output */
1171 ret = process_consumer_output(node, &output);
1172 if (ret) {
1173 goto error_snapshot_output;
1174 }
1175 }
1176 }
1177
1178 snapshot_output = lttng_snapshot_output_create();
1179 if (!snapshot_output) {
1180 ret = -LTTNG_ERR_NOMEM;
1181 goto error_snapshot_output;
1182 }
1183
1184 ret = lttng_snapshot_output_set_name(name, snapshot_output);
1185 if (ret) {
1186 goto error_snapshot_output;
1187 }
1188
1189 ret = lttng_snapshot_output_set_size(max_size, snapshot_output);
1190 if (ret) {
1191 goto error_snapshot_output;
1192 }
1193
1194 if (output.path) {
1195 ret = lttng_snapshot_output_set_ctrl_url(output.path,
1196 snapshot_output);
1197 if (ret) {
1198 goto error_snapshot_output;
1199 }
1200 } else {
1201 if (output.control_uri) {
1202 ret = lttng_snapshot_output_set_ctrl_url(output.control_uri,
1203 snapshot_output);
1204 if (ret) {
1205 goto error_snapshot_output;
1206 }
1207 }
1208
1209 if (output.data_uri) {
1210 ret = lttng_snapshot_output_set_data_url(output.data_uri,
1211 snapshot_output);
1212 if (ret) {
1213 goto error_snapshot_output;
1214 }
1215 }
1216 }
1217
1218 ret = lttng_snapshot_add_output(session_name, snapshot_output);
1219error_snapshot_output:
1220 free(name);
1221 free(output.path);
1222 free(output.control_uri);
1223 free(output.data_uri);
1224 lttng_snapshot_output_destroy(snapshot_output);
1225 if (ret) {
1226 goto end;
1227 }
1228 }
1229end:
1230 return ret;
1231}
1232
1233static
1234int create_session(const char *name,
1235 struct lttng_domain *kernel_domain,
1236 struct lttng_domain *ust_domain,
1237 struct lttng_domain *jul_domain,
1238 xmlNodePtr output_node,
1239 uint64_t live_timer_interval)
1240{
1241 int ret;
1242 struct consumer_output output = { 0 };
1243 xmlNodePtr consumer_output_node;
1244
1245 assert(name);
dcf266c0
JG
1246
1247 if (output_node) {
1248 consumer_output_node = xmlFirstElementChild(output_node);
1249 if (!consumer_output_node) {
1250 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1251 goto end;
1252 }
1253
1254 if (strcmp((const char *) consumer_output_node->name,
1255 config_element_consumer_output)) {
1256 WARN("Invalid output type, expected %s node",
1257 config_element_consumer_output);
1258 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1259 goto end;
1260 }
1261
1262 ret = process_consumer_output(consumer_output_node, &output);
1263 if (ret) {
1264 goto end;
1265 }
1266 }
1267
1268 if (live_timer_interval != UINT64_MAX &&
1269 !output.control_uri && !output.data_uri) {
1270 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1271 goto end;
1272 }
1273
1274 if (output.control_uri || output.data_uri) {
1275 int i;
1276 struct lttng_domain *domain;
1277 struct lttng_domain *domains[] =
1278 { kernel_domain, ust_domain, jul_domain };
1279
1280 /* network destination */
1281 if (live_timer_interval && live_timer_interval != UINT64_MAX) {
b664f89a
DG
1282 /*
1283 * URLs are provided for sure since the test above make sure that
1284 * with a live timer the data and control URIs are provided. So,
1285 * NULL is passed here and will be set right after.
1286 */
1287 ret = lttng_create_session_live(name, NULL, live_timer_interval);
dcf266c0
JG
1288 } else {
1289 ret = lttng_create_session(name, NULL);
1290 }
1291 if (ret) {
1292 goto end;
1293 }
1294
301423df 1295 for (i = 0; i < (sizeof(domains) / sizeof(domains[0])); i++) {
dcf266c0
JG
1296 domain = domains[i];
1297 if (!domain) {
1298 continue;
1299 }
1300
1301 ret = create_session_net_output(name, domain, output.control_uri,
1302 output.data_uri);
1303 if (ret) {
1304 goto end;
1305 }
1306 }
1307 } else {
1308 /* either local output or no output */
1309 ret = lttng_create_session(name, output.path);
1310 if (ret) {
1311 goto end;
1312 }
1313 }
1314end:
1315 free(output.path);
1316 free(output.control_uri);
1317 free(output.data_uri);
1318 return ret;
1319}
1320static
1321int process_probe_attribute_node(xmlNodePtr probe_attribute_node,
1322 struct lttng_event_probe_attr *attr)
1323{
1324 int ret;
1325
1326 assert(probe_attribute_node);
1327 assert(attr);
1328
1329 if (!strcmp((const char *) probe_attribute_node->name,
1330 config_element_address)) {
1331 xmlChar *content;
1332 uint64_t addr = 0;
1333
1334 /* addr */
1335 content = xmlNodeGetContent(probe_attribute_node);
1336 if (!content) {
1337 ret = -LTTNG_ERR_NOMEM;
1338 goto end;
1339 }
1340
1341 ret = parse_uint(content, &addr);
1342 free(content);
1343 if (ret) {
1344 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1345 goto end;
1346 }
1347
1348 attr->addr = addr;
1349 } else if (!strcmp((const char *) probe_attribute_node->name,
1350 config_element_offset)) {
1351 xmlChar *content;
1352 uint64_t offset = 0;
1353
1354 /* offset */
1355 content = xmlNodeGetContent(probe_attribute_node);
1356 if (!content) {
1357 ret = -LTTNG_ERR_NOMEM;
1358 goto end;
1359 }
1360
1361 ret = parse_uint(content, &offset);
1362 free(content);
1363 if (ret) {
1364 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1365 goto end;
1366 }
1367
1368 attr->offset = offset;
1369 } else if (!strcmp((const char *) probe_attribute_node->name,
1370 config_element_symbol_name)) {
1371 xmlChar *content;
1372 size_t name_len;
1373
1374 /* symbol_name */
1375 content = xmlNodeGetContent(probe_attribute_node);
1376 if (!content) {
1377 ret = -LTTNG_ERR_NOMEM;
1378 goto end;
1379 }
1380
1381 name_len = strlen((char *) content);
1382 if (name_len >= LTTNG_SYMBOL_NAME_LEN) {
1383 WARN("symbol_name too long.");
1384 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1385 free(content);
1386 goto end;
1387 }
1388
1389 strncpy(attr->symbol_name, (const char *) content, name_len);
1390 free(content);
1391 }
1392 ret = 0;
1393end:
1394 return ret;
1395}
1396
1397static
1398int process_event_node(xmlNodePtr event_node, struct lttng_handle *handle,
1399 const char *channel_name)
1400{
1401 int ret, i;
1402 xmlNodePtr node;
1403 struct lttng_event event;
1404 char **exclusions = NULL;
1405 unsigned long exclusion_count = 0;
1406 char *filter_expression = NULL;
1407
1408 assert(event_node);
1409 assert(handle);
1410 assert(channel_name);
1411
1412 memset(&event, 0, sizeof(event));
1413
1414 for (node = xmlFirstElementChild(event_node); node;
1415 node = xmlNextElementSibling(node)) {
1416 if (!strcmp((const char *) node->name, config_element_name)) {
1417 xmlChar *content;
1418 size_t name_len;
1419
1420 /* name */
1421 content = xmlNodeGetContent(node);
1422 if (!content) {
1423 ret = -LTTNG_ERR_NOMEM;
1424 goto end;
1425 }
1426
1427 name_len = strlen((char *) content);
1428 if (name_len >= LTTNG_SYMBOL_NAME_LEN) {
1429 WARN("Channel name too long.");
1430 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1431 free(content);
1432 goto end;
1433 }
1434
1435 strncpy(event.name, (const char *) content, name_len);
1436 free(content);
1437 } else if (!strcmp((const char *) node->name,
1438 config_element_enabled)) {
1439 xmlChar *content = xmlNodeGetContent(node);
1440
1441 /* enabled */
1442 if (!content) {
1443 ret = -LTTNG_ERR_NOMEM;
1444 goto end;
1445 }
1446
1447 ret = parse_bool(content, &event.enabled);
1448 free(content);
1449 if (ret) {
1450 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1451 goto end;
1452 }
1453 } else if (!strcmp((const char *) node->name,
1454 config_element_type)) {
1455 xmlChar *content = xmlNodeGetContent(node);
1456
1457 /* type */
1458 if (!content) {
1459 ret = -LTTNG_ERR_NOMEM;
1460 goto end;
1461 }
1462
1463 ret = get_event_type(content);
1464 free(content);
1465 if (ret < 0) {
1466 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1467 goto end;
1468 }
1469
1470 event.type = ret;
1471 } else if (!strcmp((const char *) node->name,
1472 config_element_loglevel_type)) {
1473 xmlChar *content = xmlNodeGetContent(node);
1474
1475 /* loglevel_type */
1476 if (!content) {
1477 ret = -LTTNG_ERR_NOMEM;
1478 goto end;
1479 }
1480
1481 ret = get_loglevel_type(content);
1482 free(content);
1483 if (ret < 0) {
1484 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1485 goto end;
1486 }
1487
1488 event.loglevel_type = ret;
1489 } else if (!strcmp((const char *) node->name,
1490 config_element_loglevel)) {
1491 xmlChar *content;
1492 int64_t loglevel = 0;
1493
1494 /* loglevel */
1495 content = xmlNodeGetContent(node);
1496 if (!content) {
1497 ret = -LTTNG_ERR_NOMEM;
1498 goto end;
1499 }
1500
1501 ret = parse_int(content, &loglevel);
1502 free(content);
1503 if (ret) {
1504 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1505 goto end;
1506 }
1507
1508 if (loglevel > INT_MAX || loglevel < INT_MIN) {
1509 WARN("loglevel out of range.");
1510 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1511 goto end;
1512 }
1513
1514 event.loglevel = loglevel;
1515 } else if (!strcmp((const char *) node->name,
1516 config_element_filter)) {
1517 xmlChar *content =
1518 xmlNodeGetContent(node);
1519
1520 /* filter */
1521 if (!content) {
1522 ret = -LTTNG_ERR_NOMEM;
1523 goto end;
1524 }
1525
1526 filter_expression = strdup((char *) content);
1527 free(content);
1528 if (!filter_expression) {
1529 ret = -LTTNG_ERR_NOMEM;
1530 goto end;
1531 }
1532 } else if (!strcmp((const char *) node->name,
1533 config_element_exclusions)) {
1534 xmlNodePtr exclusion_node;
1535 int exclusion_index = 0;
1536
1537 /* exclusions */
1538 if (exclusions) {
1539 /*
1540 * Exclusions has already been initialized,
1541 * invalid file.
1542 */
1543 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1544 goto end;
1545 }
1546
1547 exclusion_count = xmlChildElementCount(node);
1548 if (!exclusion_count) {
1549 continue;
1550 }
1551
1552 exclusions = zmalloc(exclusion_count * sizeof(char *));
1553 if (!exclusions) {
1554 exclusion_count = 0;
1555 ret = -LTTNG_ERR_NOMEM;
1556 goto end;
1557 }
1558
1559 for (exclusion_node = xmlFirstElementChild(node); exclusion_node;
1560 exclusion_node = xmlNextElementSibling(exclusion_node)) {
1561 xmlChar *content =
1562 xmlNodeGetContent(exclusion_node);
1563
1564 if (!content) {
1565 ret = -LTTNG_ERR_NOMEM;
1566 goto end;
1567 }
1568
1569 exclusions[exclusion_index] = strdup((const char *) content);
1570 free(content);
1571 if (!exclusions[exclusion_index]) {
1572 ret = -LTTNG_ERR_NOMEM;
1573 goto end;
1574 }
1575 exclusion_index++;
1576 }
1577
1578 event.exclusion = 1;
1579 } else if (!strcmp((const char *) node->name,
1580 config_element_attributes)) {
1581 xmlNodePtr attribute_node = xmlFirstElementChild(node);
1582
1583 /* attributes */
1584 if (!attribute_node) {
1585 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1586 goto end;
1587 }
1588
1589 if (!strcmp((const char *) node->name,
1590 config_element_probe_attributes)) {
1591 xmlNodePtr probe_attribute_node;
1592
1593 /* probe_attributes */
1594 for (probe_attribute_node =
1595 xmlFirstElementChild(attribute_node); probe_attribute_node;
1596 probe_attribute_node = xmlNextElementSibling(
1597 probe_attribute_node)) {
1598
1599 ret = process_probe_attribute_node(probe_attribute_node,
1600 &event.attr.probe);
1601 if (ret) {
1602 goto end;
1603 }
1604 }
1605 } else {
1606 size_t sym_len;
1607 xmlChar *content;
1608 xmlNodePtr symbol_node = xmlFirstElementChild(attribute_node);
1609
1610 /* function_attributes */
1611 content = xmlNodeGetContent(symbol_node);
1612 if (!content) {
1613 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1614 goto end;
1615 }
1616
1617 sym_len = strlen((char *) content);
1618 if (sym_len >= LTTNG_SYMBOL_NAME_LEN) {
1619 WARN("Function name too long.");
1620 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1621 free(content);
1622 goto end;
1623 }
1624
1625 strncpy(event.attr.ftrace.symbol_name, (char *) content,
1626 sym_len);
1627 free(content);
1628 }
1629 }
1630 }
1631
1632 ret = lttng_enable_event_with_exclusions(handle, &event, channel_name,
1633 filter_expression, exclusion_count, exclusions);
1634end:
1635 for (i = 0; i < exclusion_count; i++) {
1636 free(exclusions[i]);
1637 }
1638
1639 free(exclusions);
1640 free(filter_expression);
1641 return ret;
1642}
1643
1644static
1645int process_events_node(xmlNodePtr events_node, struct lttng_handle *handle,
1646 const char *channel_name)
1647{
1648 int ret = 0;
1649 xmlNodePtr node;
1650
1651 assert(events_node);
1652 assert(handle);
1653 assert(channel_name);
1654
1655 for (node = xmlFirstElementChild(events_node); node;
1656 node = xmlNextElementSibling(node)) {
1657 ret = process_event_node(node, handle, channel_name);
1658 if (ret) {
1659 goto end;
1660 }
1661 }
1662end:
1663 return ret;
1664}
1665
1666static
1667int process_channel_attr_node(xmlNodePtr attr_node,
1668 struct lttng_channel *channel, xmlNodePtr *contexts_node,
1669 xmlNodePtr *events_node)
1670{
1671 int ret;
1672
1673 assert(attr_node);
1674 assert(channel);
1675 assert(contexts_node);
1676 assert(events_node);
1677
1678 if (!strcmp((const char *) attr_node->name, config_element_name)) {
1679 xmlChar *content;
1680 size_t name_len;
1681
1682 /* name */
1683 content = xmlNodeGetContent(attr_node);
1684 if (!content) {
1685 ret = -LTTNG_ERR_NOMEM;
1686 goto end;
1687 }
1688
1689 name_len = strlen((char *) content);
1690 if (name_len >= LTTNG_SYMBOL_NAME_LEN) {
1691 WARN("Channel name too long.");
1692 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1693 free(content);
1694 goto end;
1695 }
1696
1697 strncpy(channel->name, (const char *) content, name_len);
1698 free(content);
1699 } else if (!strcmp((const char *) attr_node->name,
1700 config_element_enabled)) {
1701 xmlChar *content;
1702 int enabled;
1703
1704 /* enabled */
1705 content = xmlNodeGetContent(attr_node);
1706 if (!content) {
1707 ret = -LTTNG_ERR_NOMEM;
1708 goto end;
1709 }
1710
1711 ret = parse_bool(content, &enabled);
1712 free(content);
1713 if (ret) {
1714 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1715 goto end;
1716 }
1717
1718 channel->enabled = enabled;
1719 } else if (!strcmp((const char *) attr_node->name,
1720 config_element_overwrite_mode)) {
1721 xmlChar *content;
1722
1723 /* overwrite_mode */
1724 content = xmlNodeGetContent(attr_node);
1725 if (!content) {
1726 ret = -LTTNG_ERR_NOMEM;
1727 goto end;
1728 }
1729
1730 ret = get_overwrite_mode(content);
1731 free(content);
1732 if (ret < 0) {
1733 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1734 goto end;
1735 }
1736
1737 channel->attr.overwrite = ret;
1738 } else if (!strcmp((const char *) attr_node->name,
1739 config_element_subbuf_size)) {
1740 xmlChar *content;
1741
1742 /* subbuffer_size */
1743 content = xmlNodeGetContent(attr_node);
1744 if (!content) {
1745 ret = -LTTNG_ERR_NOMEM;
1746 goto end;
1747 }
1748
1749 ret = parse_uint(content, &channel->attr.subbuf_size);
1750 free(content);
1751 if (ret) {
1752 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1753 goto end;
1754 }
1755 } else if (!strcmp((const char *) attr_node->name,
1756 config_element_num_subbuf)) {
1757 xmlChar *content;
1758
1759 /* subbuffer_count */
1760 content = xmlNodeGetContent(attr_node);
1761 if (!content) {
1762 ret = -LTTNG_ERR_NOMEM;
1763 goto end;
1764 }
1765
1766 ret = parse_uint(content, &channel->attr.num_subbuf);
1767 free(content);
1768 if (ret) {
1769 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1770 goto end;
1771 }
1772 } else if (!strcmp((const char *) attr_node->name,
1773 config_element_switch_timer_interval)) {
1774 xmlChar *content;
1775 uint64_t switch_timer_interval = 0;
1776
1777 /* switch_timer_interval */
1778 content = xmlNodeGetContent(attr_node);
1779 if (!content) {
1780 ret = -LTTNG_ERR_NOMEM;
1781 goto end;
1782 }
1783
1784 ret = parse_uint(content, &switch_timer_interval);
1785 free(content);
1786 if (ret) {
1787 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1788 goto end;
1789 }
1790
1791 if (switch_timer_interval > UINT_MAX) {
1792 WARN("switch_timer_interval out of range.");
1793 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1794 goto end;
1795 }
1796
1797 channel->attr.switch_timer_interval =
1798 switch_timer_interval;
1799 } else if (!strcmp((const char *) attr_node->name,
1800 config_element_read_timer_interval)) {
1801 xmlChar *content;
1802 uint64_t read_timer_interval = 0;
1803
1804 /* read_timer_interval */
1805 content = xmlNodeGetContent(attr_node);
1806 if (!content) {
1807 ret = -LTTNG_ERR_NOMEM;
1808 goto end;
1809 }
1810
1811 ret = parse_uint(content, &read_timer_interval);
1812 free(content);
1813 if (ret) {
1814 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1815 goto end;
1816 }
1817
1818 if (read_timer_interval > UINT_MAX) {
1819 WARN("read_timer_interval out of range.");
1820 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1821 goto end;
1822 }
1823
1824 channel->attr.read_timer_interval =
1825 read_timer_interval;
1826 } else if (!strcmp((const char *) attr_node->name,
1827 config_element_output_type)) {
1828 xmlChar *content;
1829
1830 /* output_type */
1831 content = xmlNodeGetContent(attr_node);
1832 if (!content) {
1833 ret = -LTTNG_ERR_NOMEM;
1834 goto end;
1835 }
1836
1837 ret = get_output_type(content);
1838 free(content);
1839 if (ret < 0) {
1840 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1841 goto end;
1842 }
1843
1844 channel->attr.output = ret;
1845 } else if (!strcmp((const char *) attr_node->name,
1846 config_element_tracefile_size)) {
1847 xmlChar *content;
1848
1849 /* tracefile_size */
1850 content = xmlNodeGetContent(attr_node);
1851 if (!content) {
1852 ret = -LTTNG_ERR_NOMEM;
1853 goto end;
1854 }
1855
1856 ret = parse_uint(content, &channel->attr.tracefile_size);
1857 free(content);
1858 if (ret) {
1859 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1860 goto end;
1861 }
1862 } else if (!strcmp((const char *) attr_node->name,
1863 config_element_tracefile_count)) {
1864 xmlChar *content;
1865
1866 /* tracefile_count */
1867 content = xmlNodeGetContent(attr_node);
1868 if (!content) {
1869 ret = -LTTNG_ERR_NOMEM;
1870 goto end;
1871 }
1872
1873 ret = parse_uint(content, &channel->attr.tracefile_count);
1874 free(content);
1875 if (ret) {
1876 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1877 goto end;
1878 }
1879 } else if (!strcmp((const char *) attr_node->name,
1880 config_element_live_timer_interval)) {
1881 xmlChar *content;
1882 uint64_t live_timer_interval = 0;
1883
1884 /* live_timer_interval */
1885 content = xmlNodeGetContent(attr_node);
1886 if (!content) {
1887 ret = -LTTNG_ERR_NOMEM;
1888 goto end;
1889 }
1890
1891 ret = parse_uint(content, &live_timer_interval);
1892 free(content);
1893 if (ret) {
1894 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1895 goto end;
1896 }
1897
1898 if (live_timer_interval > UINT_MAX) {
1899 WARN("live_timer_interval out of range.");
1900 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1901 goto end;
1902 }
1903
1904 channel->attr.live_timer_interval =
1905 live_timer_interval;
1906 } else if (!strcmp((const char *) attr_node->name,
1907 config_element_events)) {
1908 /* events */
1909 *events_node = attr_node;
1910 } else {
1911 /* contexts */
1912 *contexts_node = attr_node;
1913 }
1914 ret = 0;
1915end:
1916 return ret;
1917}
1918
1919static
1920int process_context_node(xmlNodePtr context_node,
1921 struct lttng_handle *handle, const char *channel_name)
1922{
1923 int ret;
1924 struct lttng_event_context context;
1925 xmlNodePtr context_child_node = xmlFirstElementChild(context_node);
1926
1927 assert(handle);
1928 assert(channel_name);
1929
1930 if (!context_child_node) {
1931 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1932 goto end;
1933 }
1934
1935 memset(&context, 0, sizeof(context));
1936
1937 if (!strcmp((const char *) context_child_node->name,
1938 config_element_type)) {
1939 /* type */
1940 xmlChar *content = xmlNodeGetContent(context_child_node);
1941 if (!content) {
1942 ret = -LTTNG_ERR_NOMEM;
1943 goto end;
1944 }
1945
1946 ret = get_context_type(content);
1947 free(content);
1948 if (ret < 0) {
1949 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1950 goto end;
1951 }
1952
1953 context.ctx = ret;
1954 } else {
1955 xmlNodePtr perf_attr_node;
1956
1957 /* perf */
1958 context.ctx = LTTNG_EVENT_CONTEXT_PERF_COUNTER;
1959 for (perf_attr_node = xmlFirstElementChild(context_child_node);
1960 perf_attr_node; perf_attr_node =
1961 xmlNextElementSibling(perf_attr_node)) {
1962 if (!strcmp((const char *) perf_attr_node->name,
1963 config_element_type)) {
1964 xmlChar *content;
1965 uint64_t type = 0;
1966
1967 /* type */
1968 content = xmlNodeGetContent(perf_attr_node);
1969 if (!content) {
1970 ret = -LTTNG_ERR_NOMEM;
1971 goto end;
1972 }
1973
1974 ret = parse_uint(content, &type);
1975 free(content);
1976 if (ret) {
1977 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1978 goto end;
1979 }
1980
1981 if (type > UINT32_MAX) {
1982 WARN("perf context type out of range.");
1983 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1984 goto end;
1985 }
1986
1987 context.u.perf_counter.type = type;
1988 } else if (!strcmp((const char *) perf_attr_node->name,
1989 config_element_config)) {
1990 xmlChar *content;
1991 uint64_t config = 0;
1992
1993 /* config */
1994 content = xmlNodeGetContent(perf_attr_node);
1995 if (!content) {
1996 ret = -LTTNG_ERR_NOMEM;
1997 goto end;
1998 }
1999
2000 ret = parse_uint(content, &config);
2001 free(content);
2002 if (ret) {
2003 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2004 goto end;
2005 }
2006
2007 context.u.perf_counter.config = config;
2008 } else if (!strcmp((const char *) perf_attr_node->name,
2009 config_element_name)) {
2010 xmlChar *content;
2011 size_t name_len;
2012
2013 /* name */
2014 content = xmlNodeGetContent(perf_attr_node);
2015 if (!content) {
2016 ret = -LTTNG_ERR_NOMEM;
2017 goto end;
2018 }
2019
2020 name_len = strlen((char *) content);
2021 if (name_len >= LTTNG_SYMBOL_NAME_LEN) {
2022 WARN("perf context name too long.");
2023 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2024 free(content);
2025 goto end;
2026 }
2027
2028 strncpy(context.u.perf_counter.name, (const char *) content,
2029 name_len);
2030 free(content);
2031 }
2032 }
2033 }
2034
2035 ret = lttng_add_context(handle, &context, NULL, channel_name);
2036end:
2037 return ret;
2038}
2039
2040static
2041int process_contexts_node(xmlNodePtr contexts_node,
2042 struct lttng_handle *handle, const char *channel_name)
2043{
2044 int ret = 0;
2045 xmlNodePtr context_node;
2046
2047 for (context_node = xmlFirstElementChild(contexts_node); context_node;
2048 context_node = xmlNextElementSibling(context_node)) {
2049 ret = process_context_node(context_node, handle, channel_name);
2050 if (ret) {
2051 goto end;
2052 }
2053 }
2054end:
2055 return ret;
2056}
2057
2058static
2059int process_domain_node(xmlNodePtr domain_node, const char *session_name)
2060{
2061 int ret;
2062 struct lttng_domain domain = { 0 };
2063 struct lttng_handle *handle = NULL;
2064 xmlNodePtr channels_node = NULL;
2065 xmlNodePtr node;
2066
2067 assert(session_name);
2068
2069 ret = init_domain(domain_node, &domain);
2070 if (ret) {
2071 goto end;
2072 }
2073
2074 handle = lttng_create_handle(session_name, &domain);
2075 if (!handle) {
2076 ret = -LTTNG_ERR_NOMEM;
2077 goto end;
2078 }
2079
2080 /* get the channels node */
2081 for (node = xmlFirstElementChild(domain_node); node;
2082 node = xmlNextElementSibling(node)) {
2083 if (!strcmp((const char *) node->name,
2084 config_element_channels)) {
2085 channels_node = node;
2086 break;
2087 }
2088 }
2089
2090 if (!channels_node) {
2091 goto end;
2092 }
2093
2094 /* create all channels */
2095 for (node = xmlFirstElementChild(channels_node); node;
2096 node = xmlNextElementSibling(node)) {
2097 struct lttng_channel channel;
2098 xmlNodePtr contexts_node = NULL;
2099 xmlNodePtr events_node = NULL;
2100 xmlNodePtr channel_attr_node;
2101
2102 memset(&channel, 0, sizeof(channel));
2103 lttng_channel_set_default_attr(&domain, &channel.attr);
2104
2105 for (channel_attr_node = xmlFirstElementChild(node);
2106 channel_attr_node; channel_attr_node =
2107 xmlNextElementSibling(channel_attr_node)) {
2108 ret = process_channel_attr_node(channel_attr_node,
2109 &channel, &contexts_node, &events_node);
2110 if (ret) {
2111 goto end;
2112 }
2113 }
2114
2115 ret = lttng_enable_channel(handle, &channel);
2116 if (ret < 0) {
2117 goto end;
2118 }
2119
2120 ret = process_events_node(events_node, handle, channel.name);
2121 if (ret) {
2122 goto end;
2123 }
2124
2125 ret = process_contexts_node(contexts_node, handle,
2126 channel.name);
2127 if (ret) {
2128 goto end;
2129 }
2130 }
2131end:
2132 lttng_destroy_handle(handle);
2133 return ret;
2134}
2135
2136static
2137int process_session_node(xmlNodePtr session_node, const char *session_name,
2138 int override)
2139{
2140 int ret, started = -1, snapshot_mode = -1;
2141 uint64_t live_timer_interval = UINT64_MAX;
2142 char *name = NULL;
2143 xmlNodePtr domains_node = NULL;
2144 xmlNodePtr output_node = NULL;
2145 xmlNodePtr node;
2146 struct lttng_domain *kernel_domain = NULL;
2147 struct lttng_domain *ust_domain = NULL;
2148 struct lttng_domain *jul_domain = NULL;
2149
2150 for (node = xmlFirstElementChild(session_node); node;
2151 node = xmlNextElementSibling(node)) {
2152 if (!name && !strcmp((const char *) node->name,
2153 config_element_name)) {
2154 /* name */
2155 xmlChar *node_content = xmlNodeGetContent(node);
2156 if (!node_content) {
2157 ret = -LTTNG_ERR_NOMEM;
2158 goto end;
2159 }
2160
2161 name = (char *) node_content;
2162 } else if (!domains_node && !strcmp((const char *) node->name,
2163 config_element_domains)) {
2164 /* domains */
2165 domains_node = node;
2166 } else if (started == -1 && !strcmp((const char *) node->name,
2167 config_element_started)) {
2168 /* started */
2169 xmlChar *node_content = xmlNodeGetContent(node);
2170 if (!node_content) {
2171 ret = -LTTNG_ERR_NOMEM;
2172 goto end;
2173 }
2174
2175 ret = parse_bool(node_content, &started);
2176 free(node_content);
2177 if (ret) {
2178 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2179 goto end;
2180 }
2181 } else if (!output_node && !strcmp((const char *) node->name,
2182 config_element_output)) {
2183 /* output */
2184 output_node = node;
2185 } else {
2186 /* attributes, snapshot_mode or live_timer_interval */
2187 xmlNodePtr attributes_child =
2188 xmlFirstElementChild(node);
2189
2190 if (!strcmp((const char *) attributes_child->name,
2191 config_element_snapshot_mode)) {
2192 /* snapshot_mode */
2193 xmlChar *snapshot_mode_content =
2194 xmlNodeGetContent(attributes_child);
2195 if (!snapshot_mode_content) {
2196 ret = -LTTNG_ERR_NOMEM;
2197 goto end;
2198 }
2199
2200 ret = parse_bool(snapshot_mode_content, &snapshot_mode);
2201 free(snapshot_mode_content);
2202 if (ret) {
2203 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2204 goto end;
2205 }
2206 } else {
2207 /* live_timer_interval */
2208 xmlChar *timer_interval_content =
2209 xmlNodeGetContent(attributes_child);
2210 if (!timer_interval_content) {
2211 ret = -LTTNG_ERR_NOMEM;
2212 goto end;
2213 }
2214
2215 ret = parse_uint(timer_interval_content, &live_timer_interval);
2216 free(timer_interval_content);
2217 if (ret) {
2218 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2219 goto end;
2220 }
2221 }
2222 }
2223 }
2224
2225 if (!name) {
2226 /* Mandatory attribute, as defined in the session XSD */
2227 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2228 goto end;
2229 }
2230
2231 if (session_name && strcmp(name, session_name)) {
2232 /* This is not the session we are looking for */
a96bc65d 2233 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
dcf266c0
JG
2234 goto end;
2235 }
2236
2237 /* Init domains to create the session handles */
2238 for (node = xmlFirstElementChild(domains_node); node;
2239 node = xmlNextElementSibling(node)) {
2240 struct lttng_domain *domain;
2241
2242 domain = zmalloc(sizeof(*domain));
2243 if (!domain) {
2244 ret = -LTTNG_ERR_NOMEM;
2245 goto end;
2246 }
2247
2248 ret = init_domain(node, domain);
2249 if (ret) {
2250 goto domain_init_error;
2251 }
2252
2253 switch (domain->type) {
2254 case LTTNG_DOMAIN_KERNEL:
c33e6729
DG
2255 if (kernel_domain) {
2256 /* Same domain seen twice, invalid! */
2257 goto domain_init_error;
2258 }
dcf266c0
JG
2259 kernel_domain = domain;
2260 break;
2261 case LTTNG_DOMAIN_UST:
c33e6729
DG
2262 if (ust_domain) {
2263 /* Same domain seen twice, invalid! */
2264 goto domain_init_error;
2265 }
dcf266c0
JG
2266 ust_domain = domain;
2267 break;
2268 case LTTNG_DOMAIN_JUL:
c33e6729
DG
2269 if (jul_domain) {
2270 /* Same domain seen twice, invalid! */
2271 goto domain_init_error;
2272 }
dcf266c0
JG
2273 jul_domain = domain;
2274 break;
2275 default:
2276 WARN("Invalid domain type");
2277 goto domain_init_error;
2278 }
2279 continue;
2280domain_init_error:
2281 free(domain);
2282 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2283 goto end;
2284 }
2285
2286 if (override) {
2287 /* Destroy session if it exists */
2288 ret = lttng_destroy_session(name);
2289 if (ret && ret != -LTTNG_ERR_SESS_NOT_FOUND) {
2290 ERR("Failed to destroy existing session.");
2291 goto end;
2292 }
2293 }
2294
2295 /* Create session type depending on output type */
2296 if (snapshot_mode && snapshot_mode != -1) {
2297 ret = create_snapshot_session(name, output_node);
2298 } else if (live_timer_interval &&
2299 live_timer_interval != UINT64_MAX) {
2300 ret = create_session(name, kernel_domain, ust_domain, jul_domain,
2301 output_node, live_timer_interval);
2302 } else {
2303 /* regular session */
2304 ret = create_session(name, kernel_domain, ust_domain, jul_domain,
2305 output_node, UINT64_MAX);
2306 }
2307
2308 if (ret) {
2309 goto end;
2310 }
2311
2312 for (node = xmlFirstElementChild(domains_node); node;
2313 node = xmlNextElementSibling(node)) {
2314 ret = process_domain_node(node, name);
2315 if (ret) {
2316 goto end;
2317 }
2318 }
2319
2320 if (started) {
2321 ret = lttng_start_tracing(name);
2322 if (ret) {
2323 goto end;
2324 }
2325 }
2326end:
b2579dc1
JG
2327 if (ret < 0) {
2328 ERR("Failed to load session %s: %s", name, lttng_strerror(ret));
2329 lttng_destroy_session(name);
2330 }
2331
dcf266c0
JG
2332 free(kernel_domain);
2333 free(ust_domain);
2334 free(jul_domain);
2335 free(name);
2336 return ret;
2337}
2338
2339static
2340int load_session_from_file(const char *path, const char *session_name,
2341 struct session_config_validation_ctx *validation_ctx, int override)
2342{
2343 int ret, session_found = !session_name;
2344 xmlDocPtr doc = NULL;
2345 xmlNodePtr sessions_node;
2346 xmlNodePtr session_node;
2347 struct stat sb;
2348
2349 assert(path);
2350 assert(validation_ctx);
2351
2352 ret = stat(path, &sb);
2353 if (ret) {
2354 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
2355 goto end;
2356 }
2357
2358 doc = xmlParseFile(path);
2359 if (!doc) {
2360 ret = -LTTNG_ERR_LOAD_IO_FAIL;
2361 goto end;
2362 }
2363
2364 ret = xmlSchemaValidateDoc(validation_ctx->schema_validation_ctx, doc);
2365 if (ret) {
2366 ERR("Session configuration file validation failed");
2367 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2368 goto end;
2369 }
2370
2371 sessions_node = xmlDocGetRootElement(doc);
2372 if (!sessions_node) {
2373 goto end;
2374 }
2375
2376 for (session_node = xmlFirstElementChild(sessions_node);
2377 session_node; session_node =
2378 xmlNextElementSibling(session_node)) {
2379 ret = process_session_node(session_node,
2380 session_name, override);
2381 if (session_name && ret == 0) {
2382 /* Target session found and loaded */
2383 session_found = 1;
2384 break;
2385 }
2386 }
2387end:
2388 xmlFreeDoc(doc);
2389 if (!ret) {
a96bc65d 2390 ret = session_found ? 0 : -LTTNG_ERR_LOAD_SESSION_NOENT;
dcf266c0
JG
2391 }
2392 return ret;
2393}
2394
2395static
2396int load_session_from_path(const char *path, const char *session_name,
2397 struct session_config_validation_ctx *validation_ctx, int override)
2398{
2399 int ret, session_found = !session_name;
dcf266c0
JG
2400 DIR *directory = NULL;
2401
2402 assert(path);
2403 assert(validation_ctx);
2404
4af16958
DG
2405 directory = opendir(path);
2406 if (!directory) {
11143783
DG
2407 switch (errno) {
2408 case ENOTDIR:
0f0a81b5
DG
2409 /* Try the file loading. */
2410 break;
11143783
DG
2411 case ENOENT:
2412 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
2413 goto end;
2414 default:
0f0a81b5
DG
2415 ret = -LTTNG_ERR_LOAD_IO_FAIL;
2416 goto end;
4af16958 2417 }
dcf266c0 2418 }
4af16958 2419 if (directory) {
dcf266c0
JG
2420 struct dirent *entry;
2421 struct dirent *result;
2422 char *file_path = NULL;
2423 size_t path_len = strlen(path);
2424
2425 if (path_len >= PATH_MAX) {
2426 ret = -LTTNG_ERR_INVALID;
2427 goto end;
2428 }
2429
2430 entry = zmalloc(sizeof(*entry));
2431 if (!entry) {
2432 ret = -LTTNG_ERR_NOMEM;
2433 goto end;
2434 }
2435
dcf266c0
JG
2436 file_path = zmalloc(PATH_MAX);
2437 if (!file_path) {
2438 ret = -LTTNG_ERR_NOMEM;
2439 free(entry);
2440 goto end;
2441 }
2442
2443 strncpy(file_path, path, path_len);
2444 if (file_path[path_len - 1] != '/') {
2445 file_path[path_len++] = '/';
2446 }
2447
4af16958 2448 ret = 0;
dcf266c0
JG
2449 /* Search for *.lttng files */
2450 while (!readdir_r(directory, entry, &result) && result) {
2451 size_t file_name_len = strlen(result->d_name);
2452
2453 if (file_name_len <=
2454 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION)) {
2455 continue;
2456 }
2457
431f702e 2458 if (path_len + file_name_len >= PATH_MAX) {
dcf266c0
JG
2459 continue;
2460 }
2461
2462 if (strcmp(DEFAULT_SESSION_CONFIG_FILE_EXTENSION,
2463 result->d_name + file_name_len - sizeof(
2464 DEFAULT_SESSION_CONFIG_FILE_EXTENSION) + 1)) {
2465 continue;
2466 }
2467
2468 strncpy(file_path + path_len, result->d_name, file_name_len);
2469 file_path[path_len + file_name_len] = '\0';
2470
2471 ret = load_session_from_file(file_path, session_name,
2472 validation_ctx, override);
2473 if (session_name && !ret) {
2474 session_found = 1;
2475 break;
2476 }
2477 }
2478
2479 free(entry);
2480 free(file_path);
2481 } else {
2482 ret = load_session_from_file(path, session_name,
2483 validation_ctx, override);
2484 if (ret) {
2485 goto end;
2486 } else {
2487 session_found = 1;
2488 }
2489 }
2490
2491end:
2492 if (directory) {
2493 if (closedir(directory)) {
2494 PERROR("closedir");
2495 }
2496 }
2497
2498 if (!session_found) {
a96bc65d 2499 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
dcf266c0
JG
2500 }
2501
2502 return ret;
2503}
2504
2505LTTNG_HIDDEN
2506int config_load_session(const char *path, const char *session_name,
2507 int override)
2508{
2509 int ret;
2510 struct session_config_validation_ctx validation_ctx = { 0 };
2511
2512 ret = init_session_config_validation_ctx(&validation_ctx);
2513 if (ret) {
2514 goto end;
2515 }
2516
2517 if (!path) {
2518 /* Try home path */
2519 char *home_path = utils_get_home_dir();
2520 if (home_path) {
2521 char *path;
2522
2523 ret = asprintf(&path, DEFAULT_SESSION_HOME_CONFIGPATH,
2524 home_path);
2525 if (ret < 0) {
2526 goto end;
2527 }
2528
883d970a 2529 ret = load_session_from_path(path, session_name,
dcf266c0 2530 &validation_ctx, 0);
5a8f54da
JG
2531 if (!ret || (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT)) {
2532 /* Session found or an error occured */
dcf266c0
JG
2533 free(path);
2534 goto end;
2535 }
2536
2537 free(path);
2538 }
2539
2540 /* Try system session configuration path */
883d970a
JG
2541 ret = load_session_from_path(DEFAULT_SESSION_SYSTEM_CONFIGPATH,
2542 session_name, &validation_ctx, 0);
5a8f54da
JG
2543 if (!ret || (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT)) {
2544 /* Session found or an error occured */
dcf266c0
JG
2545 goto end;
2546 }
2547 } else {
2548 ret = access(path, F_OK);
2549 if (ret < 0) {
2550 PERROR("access");
2551 switch (errno) {
2552 case ENOENT:
2553 ret = -LTTNG_ERR_INVALID;
2554 WARN("Session configuration path does not exist.");
2555 break;
2556 case EACCES:
2557 ret = -LTTNG_ERR_EPERM;
2558 break;
2559 default:
2560 ret = -LTTNG_ERR_UNK;
2561 break;
2562 }
2563 goto end;
2564 }
2565
2566 ret = load_session_from_path(path, session_name,
2567 &validation_ctx, override);
2568 }
2569end:
2570 fini_session_config_validation_ctx(&validation_ctx);
d2b6efff
JG
2571 if (ret == -LTTNG_ERR_LOAD_SESSION_NOENT && !session_name && !path) {
2572 /*
2573 * Don't report an error if no sessions are found when called
2574 * without a session_name or a search path.
2575 */
2576 ret = 0;
2577 }
dcf266c0
JG
2578 return ret;
2579}
This page took 0.123947 seconds and 4 git commands to generate.