common: session load: use session descriptor for session creation
[lttng-tools.git] / src / common / config / session-config.cpp
CommitLineData
1501a7f3 1/*
ab5be9fa 2 * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
1501a7f3 3 *
c922647d 4 * SPDX-License-Identifier: LGPL-2.1-only
1501a7f3 5 *
1501a7f3
JG
6 */
7
159b042f 8#include "lttng/tracker.h"
6c1c0768 9#define _LGPL_SOURCE
1501a7f3 10#include <ctype.h>
1501a7f3
JG
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
36f2332b 14#include <inttypes.h>
dcf266c0
JG
15#include <dirent.h>
16#include <unistd.h>
17#include <sys/types.h>
18#include <sys/stat.h>
6c66fa0f 19#include <stdbool.h>
1501a7f3 20
c9e313bc
SM
21#include <common/defaults.hpp>
22#include <common/error.hpp>
23#include <common/macros.hpp>
24#include <common/utils.hpp>
25#include <common/dynamic-buffer.hpp>
26#include <common/compat/getenv.hpp>
fb198a11
JG
27#include <lttng/lttng-error.h>
28#include <libxml/parser.h>
29#include <libxml/valid.h>
30#include <libxml/xmlschemas.h>
dcf266c0
JG
31#include <libxml/tree.h>
32#include <lttng/lttng.h>
33#include <lttng/snapshot.h>
259c2674 34#include <lttng/rotation.h>
c1e83fb4 35#include <lttng/userspace-probe.h>
1501a7f3 36
c9e313bc
SM
37#include "session-config.hpp"
38#include "config-internal.hpp"
1501a7f3 39
c1e83fb4
FD
40#define CONFIG_USERSPACE_PROBE_LOOKUP_METHOD_NAME_MAX_LEN 7
41
f1494934 42namespace {
dcf266c0
JG
43struct session_config_validation_ctx {
44 xmlSchemaParserCtxtPtr parser_ctx;
45 xmlSchemaPtr schema;
46 xmlSchemaValidCtxtPtr schema_validation_ctx;
47};
f1494934 48} /* namespace */
dcf266c0 49
ca806b0b 50const char * const config_element_all = "all";
3afa94ae
SM
51LTTNG_EXPORT const char *config_xml_encoding = "UTF-8";
52LTTNG_EXPORT size_t config_xml_encoding_bytes_per_char = 2; /* Size of the encoding's largest character */
53LTTNG_EXPORT const char *config_xml_indent_string = "\t";
54LTTNG_EXPORT const char *config_xml_true = "true";
55LTTNG_EXPORT const char *config_xml_false = "false";
1501a7f3 56
fb198a11
JG
57const char * const config_element_channel = "channel";
58const char * const config_element_channels = "channels";
59const char * const config_element_domain = "domain";
60const char * const config_element_domains = "domains";
61const char * const config_element_event = "event";
62const char * const config_element_events = "events";
63const char * const config_element_context = "context";
64const char * const config_element_contexts = "contexts";
65const char * const config_element_attributes = "attributes";
66const char * const config_element_exclusion = "exclusion";
67const char * const config_element_exclusions = "exclusions";
68const char * const config_element_function_attributes = "function_attributes";
69const char * const config_element_probe_attributes = "probe_attributes";
70const char * const config_element_symbol_name = "symbol_name";
71const char * const config_element_address = "address";
72const char * const config_element_offset = "offset";
c1e83fb4 73
ca806b0b
SM
74const char * const config_element_userspace_probe_lookup = "lookup_method";
75const char * const config_element_userspace_probe_lookup_function_default = "DEFAULT";
76const char * const config_element_userspace_probe_lookup_function_elf = "ELF";
77const char * const config_element_userspace_probe_lookup_tracepoint_sdt = "SDT";
78const char * const config_element_userspace_probe_location_binary_path = "binary_path";
79const char * const config_element_userspace_probe_function_attributes = "userspace_probe_function_attributes";
80const char * const config_element_userspace_probe_function_location_function_name = "function_name";
81const char * const config_element_userspace_probe_tracepoint_attributes = "userspace_probe_tracepoint_attributes";
82const char * const config_element_userspace_probe_tracepoint_location_provider_name = "provider_name";
83const char * const config_element_userspace_probe_tracepoint_location_probe_name = "probe_name";
c1e83fb4 84
fb198a11
JG
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";
ca806b0b
SM
92const char * const config_element_monitor_timer_interval = "monitor_timer_interval";
93const char * const config_element_blocking_timeout = "blocking_timeout";
fb198a11
JG
94const char * const config_element_output = "output";
95const char * const config_element_output_type = "output_type";
96const char * const config_element_tracefile_size = "tracefile_size";
97const char * const config_element_tracefile_count = "tracefile_count";
98const char * const config_element_live_timer_interval = "live_timer_interval";
ca806b0b
SM
99const char * const config_element_discarded_events = "discarded_events";
100const char * const config_element_lost_packets = "lost_packets";
fb198a11
JG
101const char * const config_element_type = "type";
102const char * const config_element_buffer_type = "buffer_type";
103const char * const config_element_session = "session";
104const char * const config_element_sessions = "sessions";
ca806b0b
SM
105const char * const config_element_context_perf = "perf";
106const char * const config_element_context_app = "app";
107const char * const config_element_context_app_provider_name = "provider_name";
108const char * const config_element_context_app_ctx_name = "ctx_name";
fb198a11
JG
109const char * const config_element_config = "config";
110const char * const config_element_started = "started";
111const char * const config_element_snapshot_mode = "snapshot_mode";
112const char * const config_element_loglevel = "loglevel";
113const char * const config_element_loglevel_type = "loglevel_type";
114const char * const config_element_filter = "filter";
ca806b0b 115const char * const config_element_filter_expression = "filter_expression";
fb198a11
JG
116const char * const config_element_snapshot_outputs = "snapshot_outputs";
117const char * const config_element_consumer_output = "consumer_output";
118const char * const config_element_destination = "destination";
119const char * const config_element_path = "path";
120const char * const config_element_net_output = "net_output";
121const char * const config_element_control_uri = "control_uri";
122const char * const config_element_data_uri = "data_uri";
123const char * const config_element_max_size = "max_size";
ccf10263
MD
124const char * const config_element_pid = "pid";
125const char * const config_element_pids = "pids";
9e7c9f56 126const char * const config_element_shared_memory_path = "shared_memory_path";
159b042f 127
ca806b0b
SM
128const char * const config_element_process_attr_id = "id";
129const char * const config_element_process_attr_tracker_pid = "pid_process_attr_tracker";
130const char * const config_element_process_attr_tracker_vpid = "vpid_process_attr_tracker";
131const char * const config_element_process_attr_tracker_uid = "uid_process_attr_tracker";
132const char * const config_element_process_attr_tracker_vuid = "vuid_process_attr_tracker";
133const char * const config_element_process_attr_tracker_gid = "gid_process_attr_tracker";
134const char * const config_element_process_attr_tracker_vgid = "vgid_process_attr_tracker";
135const char * const config_element_process_attr_trackers = "process_attr_trackers";
136const char * const config_element_process_attr_values = "process_attr_values";
137const char * const config_element_process_attr_value_type = "process_attr_value_type";
138const char * const config_element_process_attr_pid_value = "pid";
139const char * const config_element_process_attr_vpid_value = "vpid";
140const char * const config_element_process_attr_uid_value = "uid";
141const char * const config_element_process_attr_vuid_value = "vuid";
142const char * const config_element_process_attr_gid_value = "gid";
143const char * const config_element_process_attr_vgid_value = "vgid";
144const char * const config_element_process_attr_tracker_type = "process_attr_tracker_type";
fb198a11 145
f7af9a72 146/* Used for support of legacy tracker serialization (< 2.12). */
ca806b0b
SM
147const char * const config_element_trackers_legacy = "trackers";
148const char * const config_element_pid_tracker_legacy = "pid_tracker";
149const char * const config_element_tracker_targets_legacy = "targets";
ca806b0b
SM
150const char * const config_element_tracker_pid_legacy = "pid";
151
152const char * const config_element_rotation_schedules = "rotation_schedules";
153const char * const config_element_rotation_schedule_periodic = "periodic";
154const char * const config_element_rotation_schedule_periodic_time_us = "time_us";
155const char * const config_element_rotation_schedule_size_threshold = "size_threshold";
156const char * const config_element_rotation_schedule_size_threshold_bytes = "bytes";
259c2674 157
fb198a11
JG
158const char * const config_domain_type_kernel = "KERNEL";
159const char * const config_domain_type_ust = "UST";
160const char * const config_domain_type_jul = "JUL";
5cdb6027 161const char * const config_domain_type_log4j = "LOG4J";
0e115563 162const char * const config_domain_type_python = "PYTHON";
fb198a11
JG
163
164const char * const config_buffer_type_per_pid = "PER_PID";
165const char * const config_buffer_type_per_uid = "PER_UID";
166const char * const config_buffer_type_global = "GLOBAL";
167
168const char * const config_overwrite_mode_discard = "DISCARD";
169const char * const config_overwrite_mode_overwrite = "OVERWRITE";
170
171const char * const config_output_type_splice = "SPLICE";
172const char * const config_output_type_mmap = "MMAP";
173
174const char * const config_loglevel_type_all = "ALL";
175const char * const config_loglevel_type_range = "RANGE";
176const char * const config_loglevel_type_single = "SINGLE";
177
178const char * const config_event_type_all = "ALL";
179const char * const config_event_type_tracepoint = "TRACEPOINT";
180const char * const config_event_type_probe = "PROBE";
ca806b0b 181const char * const config_event_type_userspace_probe = "USERSPACE_PROBE";
fb198a11
JG
182const char * const config_event_type_function = "FUNCTION";
183const char * const config_event_type_function_entry = "FUNCTION_ENTRY";
184const char * const config_event_type_noop = "NOOP";
185const char * const config_event_type_syscall = "SYSCALL";
186const char * const config_event_type_kprobe = "KPROBE";
187const char * const config_event_type_kretprobe = "KRETPROBE";
188
189const char * const config_event_context_pid = "PID";
190const char * const config_event_context_procname = "PROCNAME";
191const char * const config_event_context_prio = "PRIO";
192const char * const config_event_context_nice = "NICE";
193const char * const config_event_context_vpid = "VPID";
194const char * const config_event_context_tid = "TID";
195const char * const config_event_context_vtid = "VTID";
196const char * const config_event_context_ppid = "PPID";
197const char * const config_event_context_vppid = "VPPID";
198const char * const config_event_context_pthread_id = "PTHREAD_ID";
199const char * const config_event_context_hostname = "HOSTNAME";
200const char * const config_event_context_ip = "IP";
e885a367 201const char * const config_event_context_perf_thread_counter = "PERF_THREAD_COUNTER";
ca806b0b
SM
202const char * const config_event_context_app = "APP";
203const char * const config_event_context_interruptible = "INTERRUPTIBLE";
204const char * const config_event_context_preemptible = "PREEMPTIBLE";
205const char * const config_event_context_need_reschedule = "NEED_RESCHEDULE";
206const char * const config_event_context_migratable = "MIGRATABLE";
207const char * const config_event_context_callstack_user= "CALLSTACK_USER";
208const char * const config_event_context_callstack_kernel = "CALLSTACK_KERNEL";
209const char * const config_event_context_cgroup_ns = "CGROUP_NS";
210const char * const config_event_context_ipc_ns = "IPC_NS";
211const char * const config_event_context_mnt_ns = "MNT_NS";
212const char * const config_event_context_net_ns = "NET_NS";
213const char * const config_event_context_pid_ns = "PID_NS";
214const char * const config_event_context_time_ns = "TIME_NS";
215const char * const config_event_context_user_ns = "USER_NS";
216const char * const config_event_context_uts_ns = "UTS_NS";
217const char * const config_event_context_uid = "UID";
218const char * const config_event_context_euid = "EUID";
219const char * const config_event_context_suid = "SUID";
220const char * const config_event_context_gid = "GID";
221const char * const config_event_context_egid = "EGID";
222const char * const config_event_context_sgid = "SGID";
223const char * const config_event_context_vuid = "VUID";
224const char * const config_event_context_veuid = "VEUID";
225const char * const config_event_context_vsuid = "VSUID";
226const char * const config_event_context_vgid = "VGID";
227const char * const config_event_context_vegid = "VEGID";
228const char * const config_event_context_vsgid = "VSGID";
fb198a11 229
fbd987c9 230/* Deprecated symbols */
3afa94ae 231LTTNG_EXPORT const char *config_element_perf;
fbd987c9 232
d7b645e2
JR
233enum process_event_node_phase {
234 CREATION = 0,
235 ENABLE = 1,
236};
237
f1494934 238namespace {
dcf266c0
JG
239struct consumer_output {
240 int enabled;
241 char *path;
242 char *control_uri;
243 char *data_uri;
244};
f1494934 245} /* namespace */
dcf266c0 246
36f2332b
JG
247/*
248 * Returns a xmlChar string which must be released using xmlFree().
249 */
250static xmlChar *encode_string(const char *in_str)
251{
252 xmlChar *out_str = NULL;
253 xmlCharEncodingHandlerPtr handler;
254 int out_len, ret, in_len;
255
a0377dfe 256 LTTNG_ASSERT(in_str);
36f2332b
JG
257
258 handler = xmlFindCharEncodingHandler(config_xml_encoding);
259 if (!handler) {
260 ERR("xmlFindCharEncodingHandler return NULL!. Configure issue!");
261 goto end;
262 }
263
264 in_len = strlen(in_str);
265 /*
f76d886f
JG
266 * Add 1 byte for the NULL terminted character. The factor 4 here is
267 * used because UTF-8 characters can take up to 4 bytes.
36f2332b 268 */
f76d886f 269 out_len = (in_len * 4) + 1;
3afa94ae 270 out_str = (xmlChar *) xmlMalloc(out_len);
36f2332b
JG
271 if (!out_str) {
272 goto end;
273 }
274
275 ret = handler->input(out_str, &out_len, (const xmlChar *) in_str, &in_len);
276 if (ret < 0) {
277 xmlFree(out_str);
278 out_str = NULL;
279 goto end;
280 }
281
282 /* out_len is now the size of out_str */
283 out_str[out_len] = '\0';
284end:
285 return out_str;
286}
287
705bb62f 288struct config_writer *config_writer_create(int fd_output, int indent)
36f2332b
JG
289{
290 int ret;
291 struct config_writer *writer;
292 xmlOutputBufferPtr buffer;
293
64803277 294 writer = zmalloc<config_writer>();
36f2332b
JG
295 if (!writer) {
296 PERROR("zmalloc config_writer_create");
297 goto end;
298 }
299
300 buffer = xmlOutputBufferCreateFd(fd_output, NULL);
301 if (!buffer) {
302 goto error_destroy;
303 }
304
305 writer->writer = xmlNewTextWriter(buffer);
306 ret = xmlTextWriterStartDocument(writer->writer, NULL,
307 config_xml_encoding, NULL);
308 if (ret < 0) {
309 goto error_destroy;
310 }
311
312 ret = xmlTextWriterSetIndentString(writer->writer,
313 BAD_CAST config_xml_indent_string);
705bb62f 314 if (ret) {
36f2332b
JG
315 goto error_destroy;
316 }
317
705bb62f
JRJ
318 ret = xmlTextWriterSetIndent(writer->writer, indent);
319 if (ret) {
36f2332b
JG
320 goto error_destroy;
321 }
322
323end:
324 return writer;
325error_destroy:
326 config_writer_destroy(writer);
327 return NULL;
328}
329
36f2332b
JG
330int config_writer_destroy(struct config_writer *writer)
331{
332 int ret = 0;
333
334 if (!writer) {
335 ret = -EINVAL;
336 goto end;
337 }
338
339 if (xmlTextWriterEndDocument(writer->writer) < 0) {
340 WARN("Could not close XML document");
341 ret = -EIO;
342 }
343
344 if (writer->writer) {
345 xmlFreeTextWriter(writer->writer);
346 }
347
348 free(writer);
349end:
350 return ret;
351}
352
36f2332b
JG
353int config_writer_open_element(struct config_writer *writer,
354 const char *element_name)
355{
356 int ret;
357 xmlChar *encoded_element_name;
358
359 if (!writer || !writer->writer || !element_name || !element_name[0]) {
360 ret = -1;
361 goto end;
362 }
363
364 encoded_element_name = encode_string(element_name);
365 if (!encoded_element_name) {
366 ret = -1;
367 goto end;
368 }
369
370 ret = xmlTextWriterStartElement(writer->writer, encoded_element_name);
371 xmlFree(encoded_element_name);
372end:
28676a1d 373 return ret >= 0 ? 0 : ret;
36f2332b
JG
374}
375
e10b6a1c
JG
376int config_writer_write_attribute(struct config_writer *writer,
377 const char *name, const char *value)
378{
379 int ret;
380 xmlChar *encoded_name = NULL;
381 xmlChar *encoded_value = NULL;
382
383 if (!writer || !writer->writer || !name || !name[0]) {
384 ret = -1;
385 goto end;
386 }
387
388 encoded_name = encode_string(name);
389 if (!encoded_name) {
390 ret = -1;
391 goto end;
392 }
393
394 encoded_value = encode_string(value);
395 if (!encoded_value) {
396 ret = -1;
397 goto end;
398 }
399
400 ret = xmlTextWriterWriteAttribute(writer->writer, encoded_name,
401 encoded_value);
402end:
403 xmlFree(encoded_name);
404 xmlFree(encoded_value);
405 return ret >= 0 ? 0 : ret;
406}
407
36f2332b
JG
408int config_writer_close_element(struct config_writer *writer)
409{
410 int ret;
411
412 if (!writer || !writer->writer) {
413 ret = -1;
414 goto end;
415 }
416
417 ret = xmlTextWriterEndElement(writer->writer);
418end:
28676a1d 419 return ret >= 0 ? 0 : ret;
36f2332b
JG
420}
421
36f2332b
JG
422int config_writer_write_element_unsigned_int(struct config_writer *writer,
423 const char *element_name, uint64_t value)
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 = xmlTextWriterWriteFormatElement(writer->writer,
440 encoded_element_name, "%" PRIu64, value);
441 xmlFree(encoded_element_name);
442end:
28676a1d 443 return ret >= 0 ? 0 : ret;
36f2332b
JG
444}
445
36f2332b
JG
446int config_writer_write_element_signed_int(struct config_writer *writer,
447 const char *element_name, int64_t value)
448{
449 int ret;
450 xmlChar *encoded_element_name;
451
452 if (!writer || !writer->writer || !element_name || !element_name[0]) {
453 ret = -1;
454 goto end;
455 }
456
457 encoded_element_name = encode_string(element_name);
458 if (!encoded_element_name) {
459 ret = -1;
460 goto end;
461 }
462
463 ret = xmlTextWriterWriteFormatElement(writer->writer,
464 encoded_element_name, "%" PRIi64, value);
465 xmlFree(encoded_element_name);
466end:
28676a1d 467 return ret >= 0 ? 0 : ret;
36f2332b
JG
468}
469
36f2332b
JG
470int config_writer_write_element_bool(struct config_writer *writer,
471 const char *element_name, int value)
472{
473 return config_writer_write_element_string(writer, element_name,
474 value ? config_xml_true : config_xml_false);
475}
476
2b166400
JR
477int config_writer_write_element_double(struct config_writer *writer,
478 const char *element_name,
479 double value)
480{
481 int ret;
482 xmlChar *encoded_element_name;
483
484 if (!writer || !writer->writer || !element_name || !element_name[0]) {
485 ret = -1;
486 goto end;
487 }
488
489 encoded_element_name = encode_string(element_name);
490 if (!encoded_element_name) {
491 ret = -1;
492 goto end;
493 }
494
495 ret = xmlTextWriterWriteFormatElement(
496 writer->writer, encoded_element_name, "%f", value);
497 xmlFree(encoded_element_name);
498end:
499 return ret >= 0 ? 0 : ret;
500}
501
36f2332b
JG
502int config_writer_write_element_string(struct config_writer *writer,
503 const char *element_name, const char *value)
504{
505 int ret;
506 xmlChar *encoded_element_name = NULL;
507 xmlChar *encoded_value = NULL;
508
509 if (!writer || !writer->writer || !element_name || !element_name[0] ||
510 !value) {
511 ret = -1;
512 goto end;
513 }
514
515 encoded_element_name = encode_string(element_name);
516 if (!encoded_element_name) {
517 ret = -1;
518 goto end;
519 }
520
521 encoded_value = encode_string(value);
522 if (!encoded_value) {
523 ret = -1;
524 goto end;
525 }
526
527 ret = xmlTextWriterWriteElement(writer->writer, encoded_element_name,
dcf266c0 528 encoded_value);
36f2332b
JG
529end:
530 xmlFree(encoded_element_name);
531 xmlFree(encoded_value);
28676a1d 532 return ret >= 0 ? 0 : ret;
36f2332b 533}
dcf266c0 534
d22ad5f8 535static ATTR_FORMAT_PRINTF(2, 3)
f46376a1 536void xml_error_handler(void *ctx __attribute__((unused)), const char *format, ...)
dcf266c0
JG
537{
538 char *errMsg;
539 va_list args;
540 int ret;
541
542 va_start(args, format);
543 ret = vasprintf(&errMsg, format, args);
6c043b48 544 va_end(args);
dcf266c0
JG
545 if (ret == -1) {
546 ERR("String allocation failed in xml error handler");
547 return;
548 }
dcf266c0
JG
549
550 fprintf(stderr, "XML Error: %s", errMsg);
551 free(errMsg);
552}
553
554static
555void fini_session_config_validation_ctx(
556 struct session_config_validation_ctx *ctx)
557{
558 if (ctx->parser_ctx) {
559 xmlSchemaFreeParserCtxt(ctx->parser_ctx);
560 }
561
562 if (ctx->schema) {
563 xmlSchemaFree(ctx->schema);
564 }
565
566 if (ctx->schema_validation_ctx) {
567 xmlSchemaFreeValidCtxt(ctx->schema_validation_ctx);
568 }
569
570 memset(ctx, 0, sizeof(struct session_config_validation_ctx));
571}
572
54e399cb 573static
a3ecaea8 574char *get_session_config_xsd_path(void)
54e399cb
JG
575{
576 char *xsd_path;
e8fa9fb0 577 const char *base_path = lttng_secure_getenv(DEFAULT_SESSION_CONFIG_XSD_PATH_ENV);
54e399cb
JG
578 size_t base_path_len;
579 size_t max_path_len;
580
581 if (!base_path) {
582 base_path = DEFAULT_SESSION_CONFIG_XSD_PATH;
583 }
584
585 base_path_len = strlen(base_path);
586 max_path_len = base_path_len +
587 sizeof(DEFAULT_SESSION_CONFIG_XSD_FILENAME) + 1;
64803277 588 xsd_path = zmalloc<char>(max_path_len);
54e399cb
JG
589 if (!xsd_path) {
590 goto end;
591 }
592
00a7f6f8 593 strcpy(xsd_path, base_path);
54e399cb
JG
594 if (xsd_path[base_path_len - 1] != '/') {
595 xsd_path[base_path_len++] = '/';
596 }
597
00a7f6f8 598 strcpy(xsd_path + base_path_len, DEFAULT_SESSION_CONFIG_XSD_FILENAME);
54e399cb
JG
599end:
600 return xsd_path;
601}
602
dcf266c0
JG
603static
604int init_session_config_validation_ctx(
605 struct session_config_validation_ctx *ctx)
606{
607 int ret;
54e399cb
JG
608 char *xsd_path = get_session_config_xsd_path();
609
610 if (!xsd_path) {
611 ret = -LTTNG_ERR_NOMEM;
612 goto end;
613 }
dcf266c0 614
54e399cb 615 ctx->parser_ctx = xmlSchemaNewParserCtxt(xsd_path);
dcf266c0
JG
616 if (!ctx->parser_ctx) {
617 ERR("XSD parser context creation failed");
618 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
619 goto end;
620 }
621 xmlSchemaSetParserErrors(ctx->parser_ctx, xml_error_handler,
622 xml_error_handler, NULL);
623
624 ctx->schema = xmlSchemaParse(ctx->parser_ctx);
625 if (!ctx->schema) {
626 ERR("XSD parsing failed");
627 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
628 goto end;
629 }
630
631 ctx->schema_validation_ctx = xmlSchemaNewValidCtxt(ctx->schema);
632 if (!ctx->schema_validation_ctx) {
633 ERR("XSD validation context creation failed");
634 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
635 goto end;
636 }
637
638 xmlSchemaSetValidErrors(ctx->schema_validation_ctx, xml_error_handler,
639 xml_error_handler, NULL);
640 ret = 0;
641
642end:
643 if (ret) {
644 fini_session_config_validation_ctx(ctx);
645 }
646
54e399cb 647 free(xsd_path);
dcf266c0
JG
648 return ret;
649}
650
651static
652int parse_uint(xmlChar *str, uint64_t *val)
653{
654 int ret;
655 char *endptr;
656
657 if (!str || !val) {
658 ret = -1;
659 goto end;
660 }
661
662 *val = strtoull((const char *) str, &endptr, 10);
663 if (!endptr || *endptr) {
664 ret = -1;
665 } else {
666 ret = 0;
667 }
668
669end:
670 return ret;
671}
672
673static
674int parse_int(xmlChar *str, int64_t *val)
675{
676 int ret;
677 char *endptr;
678
679 if (!str || !val) {
680 ret = -1;
681 goto end;
682 }
683
684 *val = strtoll((const char *) str, &endptr, 10);
685 if (!endptr || *endptr) {
686 ret = -1;
687 } else {
688 ret = 0;
689 }
690
691end:
692 return ret;
693}
694
695static
696int parse_bool(xmlChar *str, int *val)
697{
698 int ret = 0;
699
700 if (!str || !val) {
701 ret = -1;
702 goto end;
703 }
704
47945b17
SM
705 if (!strcmp((const char *) str, config_xml_true) ||
706 !strcmp((const char *) str, "1")) {
dcf266c0 707 *val = 1;
47945b17
SM
708 } else if (!strcmp((const char *) str, config_xml_false) ||
709 !strcmp((const char *) str, "0")) {
dcf266c0
JG
710 *val = 0;
711 } else {
a22a57cb 712 WARN("Invalid boolean value encountered (%s).",
dcf266c0
JG
713 (const char *) str);
714 ret = -1;
715 }
716end:
717 return ret;
718}
719
720static
721int get_domain_type(xmlChar *domain)
722{
723 int ret;
724
725 if (!domain) {
726 goto error;
727 }
728
729 if (!strcmp((char *) domain, config_domain_type_kernel)) {
730 ret = LTTNG_DOMAIN_KERNEL;
731 } else if (!strcmp((char *) domain, config_domain_type_ust)) {
732 ret = LTTNG_DOMAIN_UST;
733 } else if (!strcmp((char *) domain, config_domain_type_jul)) {
734 ret = LTTNG_DOMAIN_JUL;
5cdb6027
DG
735 } else if (!strcmp((char *) domain, config_domain_type_log4j)) {
736 ret = LTTNG_DOMAIN_LOG4J;
0e115563
DG
737 } else if (!strcmp((char *) domain, config_domain_type_python)) {
738 ret = LTTNG_DOMAIN_PYTHON;
dcf266c0
JG
739 } else {
740 goto error;
741 }
742
743 return ret;
744error:
745 return -1;
746}
747
748static
749int get_buffer_type(xmlChar *buffer_type)
750{
751 int ret;
752
753 if (!buffer_type) {
754 goto error;
755 }
756
757 if (!strcmp((char *) buffer_type, config_buffer_type_global)) {
758 ret = LTTNG_BUFFER_GLOBAL;
759 } else if (!strcmp((char *) buffer_type, config_buffer_type_per_uid)) {
760 ret = LTTNG_BUFFER_PER_UID;
761 } else if (!strcmp((char *) buffer_type, config_buffer_type_per_pid)) {
762 ret = LTTNG_BUFFER_PER_PID;
763 } else {
764 goto error;
765 }
766
767 return ret;
768error:
769 return -1;
770}
771
772static
773int get_overwrite_mode(xmlChar *overwrite_mode)
774{
775 int ret;
776
777 if (!overwrite_mode) {
778 goto error;
779 }
780
781 if (!strcmp((char *) overwrite_mode, config_overwrite_mode_overwrite)) {
782 ret = 1;
783 } else if (!strcmp((char *) overwrite_mode,
784 config_overwrite_mode_discard)) {
785 ret = 0;
786 } else {
787 goto error;
788 }
789
790 return ret;
791error:
792 return -1;
793}
794
795static
796int get_output_type(xmlChar *output_type)
797{
798 int ret;
799
800 if (!output_type) {
801 goto error;
802 }
803
804 if (!strcmp((char *) output_type, config_output_type_mmap)) {
805 ret = LTTNG_EVENT_MMAP;
806 } else if (!strcmp((char *) output_type, config_output_type_splice)) {
807 ret = LTTNG_EVENT_SPLICE;
808 } else {
809 goto error;
810 }
811
812 return ret;
813error:
814 return -1;
815}
816
817static
818int get_event_type(xmlChar *event_type)
819{
820 int ret;
821
822 if (!event_type) {
823 goto error;
824 }
825
826 if (!strcmp((char *) event_type, config_event_type_all)) {
827 ret = LTTNG_EVENT_ALL;
828 } else if (!strcmp((char *) event_type, config_event_type_tracepoint)) {
829 ret = LTTNG_EVENT_TRACEPOINT;
830 } else if (!strcmp((char *) event_type, config_event_type_probe)) {
831 ret = LTTNG_EVENT_PROBE;
c1e83fb4
FD
832 } else if (!strcmp((char *) event_type,
833 config_event_type_userspace_probe)) {
834 ret = LTTNG_EVENT_USERSPACE_PROBE;
dcf266c0
JG
835 } else if (!strcmp((char *) event_type, config_event_type_function)) {
836 ret = LTTNG_EVENT_FUNCTION;
837 } else if (!strcmp((char *) event_type,
c1e83fb4 838 config_event_type_function_entry)) {
dcf266c0
JG
839 ret = LTTNG_EVENT_FUNCTION_ENTRY;
840 } else if (!strcmp((char *) event_type, config_event_type_noop)) {
841 ret = LTTNG_EVENT_NOOP;
842 } else if (!strcmp((char *) event_type, config_event_type_syscall)) {
843 ret = LTTNG_EVENT_SYSCALL;
844 } else {
845 goto error;
846 }
847
848 return ret;
849error:
850 return -1;
851}
852
853static
854int get_loglevel_type(xmlChar *loglevel_type)
855{
856 int ret;
857
858 if (!loglevel_type) {
859 goto error;
860 }
861
862 if (!strcmp((char *) loglevel_type, config_loglevel_type_all)) {
863 ret = LTTNG_EVENT_LOGLEVEL_ALL;
864 } else if (!strcmp((char *) loglevel_type,
865 config_loglevel_type_range)) {
866 ret = LTTNG_EVENT_LOGLEVEL_RANGE;
867 } else if (!strcmp((char *) loglevel_type,
868 config_loglevel_type_single)) {
869 ret = LTTNG_EVENT_LOGLEVEL_SINGLE;
870 } else {
871 goto error;
872 }
873
874 return ret;
875error:
876 return -1;
877}
878
879/*
880 * Return the context type or -1 on error.
881 */
882static
883int get_context_type(xmlChar *context_type)
884{
885 int ret;
886
887 if (!context_type) {
888 goto error;
889 }
890
891 if (!strcmp((char *) context_type, config_event_context_pid)) {
892 ret = LTTNG_EVENT_CONTEXT_PID;
893 } else if (!strcmp((char *) context_type,
894 config_event_context_procname)) {
895 ret = LTTNG_EVENT_CONTEXT_PROCNAME;
896 } else if (!strcmp((char *) context_type,
897 config_event_context_prio)) {
898 ret = LTTNG_EVENT_CONTEXT_PRIO;
899 } else if (!strcmp((char *) context_type,
900 config_event_context_nice)) {
901 ret = LTTNG_EVENT_CONTEXT_NICE;
902 } else if (!strcmp((char *) context_type,
903 config_event_context_vpid)) {
904 ret = LTTNG_EVENT_CONTEXT_VPID;
905 } else if (!strcmp((char *) context_type,
906 config_event_context_tid)) {
907 ret = LTTNG_EVENT_CONTEXT_TID;
908 } else if (!strcmp((char *) context_type,
909 config_event_context_vtid)) {
910 ret = LTTNG_EVENT_CONTEXT_VTID;
911 } else if (!strcmp((char *) context_type,
912 config_event_context_ppid)) {
913 ret = LTTNG_EVENT_CONTEXT_PPID;
914 } else if (!strcmp((char *) context_type,
915 config_event_context_vppid)) {
916 ret = LTTNG_EVENT_CONTEXT_VPPID;
917 } else if (!strcmp((char *) context_type,
918 config_event_context_pthread_id)) {
919 ret = LTTNG_EVENT_CONTEXT_PTHREAD_ID;
920 } else if (!strcmp((char *) context_type,
921 config_event_context_hostname)) {
922 ret = LTTNG_EVENT_CONTEXT_HOSTNAME;
923 } else if (!strcmp((char *) context_type,
924 config_event_context_ip)) {
925 ret = LTTNG_EVENT_CONTEXT_IP;
1ae5e83e
JD
926 } else if (!strcmp((char *) context_type,
927 config_event_context_interruptible)) {
928 ret = LTTNG_EVENT_CONTEXT_INTERRUPTIBLE;
929 } else if (!strcmp((char *) context_type,
930 config_event_context_preemptible)) {
931 ret = LTTNG_EVENT_CONTEXT_PREEMPTIBLE;
932 } else if (!strcmp((char *) context_type,
933 config_event_context_need_reschedule)) {
934 ret = LTTNG_EVENT_CONTEXT_NEED_RESCHEDULE;
935 } else if (!strcmp((char *) context_type,
936 config_event_context_migratable)) {
937 ret = LTTNG_EVENT_CONTEXT_MIGRATABLE;
16c4c991
FD
938 } else if (!strcmp((char *) context_type,
939 config_event_context_callstack_user)) {
940 ret = LTTNG_EVENT_CONTEXT_CALLSTACK_USER;
941 } else if (!strcmp((char *) context_type,
942 config_event_context_callstack_kernel)) {
943 ret = LTTNG_EVENT_CONTEXT_CALLSTACK_KERNEL;
40e14884
MJ
944 } else if (!strcmp((char *) context_type,
945 config_event_context_cgroup_ns)) {
946 ret = LTTNG_EVENT_CONTEXT_CGROUP_NS;
947 } else if (!strcmp((char *) context_type,
948 config_event_context_ipc_ns)) {
949 ret = LTTNG_EVENT_CONTEXT_IPC_NS;
950 } else if (!strcmp((char *) context_type,
951 config_event_context_mnt_ns)) {
952 ret = LTTNG_EVENT_CONTEXT_MNT_NS;
953 } else if (!strcmp((char *) context_type,
954 config_event_context_net_ns)) {
955 ret = LTTNG_EVENT_CONTEXT_NET_NS;
956 } else if (!strcmp((char *) context_type,
957 config_event_context_pid_ns)) {
958 ret = LTTNG_EVENT_CONTEXT_PID_NS;
d37ac3cd
MJ
959 } else if (!strcmp((char *) context_type,
960 config_event_context_time_ns)) {
961 ret = LTTNG_EVENT_CONTEXT_TIME_NS;
40e14884
MJ
962 } else if (!strcmp((char *) context_type,
963 config_event_context_user_ns)) {
964 ret = LTTNG_EVENT_CONTEXT_USER_NS;
965 } else if (!strcmp((char *) context_type,
966 config_event_context_uts_ns)) {
967 ret = LTTNG_EVENT_CONTEXT_UTS_NS;
499cbfa1
MJ
968 } else if (!strcmp((char *) context_type,
969 config_event_context_uid)) {
970 ret = LTTNG_EVENT_CONTEXT_UID;
971 } else if (!strcmp((char *) context_type,
972 config_event_context_euid)) {
973 ret = LTTNG_EVENT_CONTEXT_EUID;
974 } else if (!strcmp((char *) context_type,
975 config_event_context_suid)) {
976 ret = LTTNG_EVENT_CONTEXT_SUID;
977 } else if (!strcmp((char *) context_type,
978 config_event_context_gid)) {
979 ret = LTTNG_EVENT_CONTEXT_GID;
980 } else if (!strcmp((char *) context_type,
981 config_event_context_egid)) {
982 ret = LTTNG_EVENT_CONTEXT_EGID;
983 } else if (!strcmp((char *) context_type,
984 config_event_context_sgid)) {
985 ret = LTTNG_EVENT_CONTEXT_SGID;
986 } else if (!strcmp((char *) context_type,
987 config_event_context_vuid)) {
988 ret = LTTNG_EVENT_CONTEXT_VUID;
989 } else if (!strcmp((char *) context_type,
990 config_event_context_veuid)) {
991 ret = LTTNG_EVENT_CONTEXT_VEUID;
992 } else if (!strcmp((char *) context_type,
993 config_event_context_vsuid)) {
994 ret = LTTNG_EVENT_CONTEXT_VSUID;
995 } else if (!strcmp((char *) context_type,
996 config_event_context_vgid)) {
997 ret = LTTNG_EVENT_CONTEXT_VGID;
998 } else if (!strcmp((char *) context_type,
999 config_event_context_vegid)) {
1000 ret = LTTNG_EVENT_CONTEXT_VEGID;
1001 } else if (!strcmp((char *) context_type,
1002 config_event_context_vsgid)) {
1003 ret = LTTNG_EVENT_CONTEXT_VSGID;
dcf266c0
JG
1004 } else {
1005 goto error;
1006 }
1007
1008 return ret;
1009error:
1010 return -1;
1011}
1012
1013static
1014int init_domain(xmlNodePtr domain_node, struct lttng_domain *domain)
1015{
1016 int ret;
1017 xmlNodePtr node;
1018
1019 for (node = xmlFirstElementChild(domain_node); node;
1020 node = xmlNextElementSibling(node)) {
1021 if (!strcmp((const char *) node->name, config_element_type)) {
1022 /* domain type */
1023 xmlChar *node_content = xmlNodeGetContent(node);
1024 if (!node_content) {
1025 ret = -LTTNG_ERR_NOMEM;
1026 goto end;
1027 }
1028
1029 ret = get_domain_type(node_content);
1030 free(node_content);
1031 if (ret < 0) {
1032 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1033 goto end;
1034 }
1035
3afa94ae 1036 domain->type = (lttng_domain_type) ret;
dcf266c0
JG
1037 } else if (!strcmp((const char *) node->name,
1038 config_element_buffer_type)) {
1039 /* buffer type */
1040 xmlChar *node_content = xmlNodeGetContent(node);
1041 if (!node_content) {
1042 ret = -LTTNG_ERR_NOMEM;
1043 goto end;
1044 }
1045
1046 ret = get_buffer_type(node_content);
1047 free(node_content);
1048 if (ret < 0) {
1049 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1050 goto end;
1051 }
1052
3afa94ae 1053 domain->buf_type = (lttng_buffer_type) ret;
dcf266c0
JG
1054 }
1055 }
1056 ret = 0;
1057end:
1058 return ret;
1059}
1060
1061static
1062int get_net_output_uris(xmlNodePtr net_output_node, char **control_uri,
1063 char **data_uri)
1064{
1065 xmlNodePtr node;
1066
1067 for (node = xmlFirstElementChild(net_output_node); node;
1068 node = xmlNextElementSibling(node)) {
1069 if (!strcmp((const char *) node->name, config_element_control_uri)) {
1070 /* control_uri */
1071 *control_uri = (char *) xmlNodeGetContent(node);
1072 if (!*control_uri) {
1073 break;
1074 }
1075 } else {
1076 /* data_uri */
1077 *data_uri = (char *) xmlNodeGetContent(node);
1078 if (!*data_uri) {
1079 break;
1080 }
1081 }
1082 }
1083
1084 return *control_uri || *data_uri ? 0 : -LTTNG_ERR_LOAD_INVALID_CONFIG;
1085}
1086
1087static
1088int process_consumer_output(xmlNodePtr consumer_output_node,
1089 struct consumer_output *output)
1090{
1091 int ret;
1092 xmlNodePtr node;
1093
a0377dfe 1094 LTTNG_ASSERT(output);
dcf266c0
JG
1095
1096 for (node = xmlFirstElementChild(consumer_output_node); node;
1097 node = xmlNextElementSibling(node)) {
1098 if (!strcmp((const char *) node->name, config_element_enabled)) {
1099 xmlChar *enabled_str = xmlNodeGetContent(node);
1100
1101 /* enabled */
1102 if (!enabled_str) {
1103 ret = -LTTNG_ERR_NOMEM;
1104 goto end;
1105 }
1106
1107 ret = parse_bool(enabled_str, &output->enabled);
1108 free(enabled_str);
1109 if (ret) {
1110 goto end;
1111 }
1112 } else {
1113 xmlNodePtr output_type_node;
1114
1115 /* destination */
1116 output_type_node = xmlFirstElementChild(node);
1117 if (!output_type_node) {
1118 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1119 goto end;
1120 }
1121
1122 if (!strcmp((const char *) output_type_node->name,
1123 config_element_path)) {
1124 /* path */
1125 output->path = (char *) xmlNodeGetContent(output_type_node);
1126 if (!output->path) {
1127 ret = -LTTNG_ERR_NOMEM;
1128 goto end;
1129 }
1130 } else {
1131 /* net_output */
1132 ret = get_net_output_uris(output_type_node,
1133 &output->control_uri, &output->data_uri);
1134 if (ret) {
1135 goto end;
1136 }
1137 }
1138 }
1139 }
1140 ret = 0;
1141
1142end:
1143 if (ret) {
1144 free(output->path);
1145 free(output->control_uri);
1146 free(output->data_uri);
1147 memset(output, 0, sizeof(struct consumer_output));
1148 }
1149 return ret;
1150}
1151
dcf266c0 1152static
1b08cbce
JR
1153int create_snapshot_session(const char *session_name, xmlNodePtr output_node,
1154 const struct config_load_session_override_attr *overrides)
dcf266c0
JG
1155{
1156 int ret;
fbc3f258 1157 enum lttng_error_code ret_code;
dcf266c0
JG
1158 xmlNodePtr node = NULL;
1159 xmlNodePtr snapshot_output_list_node;
1160 xmlNodePtr snapshot_output_node;
fbc3f258 1161 struct lttng_session_descriptor *session_descriptor = nullptr;
dcf266c0 1162
a0377dfe 1163 LTTNG_ASSERT(session_name);
fbc3f258 1164 LTTNG_ASSERT(output_node);
dcf266c0 1165
fbc3f258
JR
1166 /*
1167 * Use a descriptor without output since consumer output size is not
1168 * exposed by the session descriptor api.
1169 */
1170 session_descriptor = lttng_session_descriptor_snapshot_create(session_name);
1171 if (session_descriptor == nullptr) {
1172 ret = -LTTNG_ERR_NOMEM;
dcf266c0
JG
1173 goto end;
1174 }
1175
fbc3f258
JR
1176 ret_code = lttng_create_session_ext(session_descriptor);
1177 if (ret_code != LTTNG_OK) {
1178 ret = -ret_code;
dcf266c0
JG
1179 goto end;
1180 }
1181
1182 snapshot_output_list_node = xmlFirstElementChild(output_node);
1183
1184 /* Parse and create snapshot outputs */
dcf266c0
JG
1185 for (snapshot_output_node =
1186 xmlFirstElementChild(snapshot_output_list_node);
1187 snapshot_output_node; snapshot_output_node =
1188 xmlNextElementSibling(snapshot_output_node)) {
1189 char *name = NULL;
1190 uint64_t max_size = UINT64_MAX;
1c9a0b0e 1191 struct consumer_output output = {};
dcf266c0 1192 struct lttng_snapshot_output *snapshot_output = NULL;
1b08cbce
JR
1193 const char *control_uri = NULL;
1194 const char *data_uri = NULL;
1195 const char *path = NULL;
dcf266c0
JG
1196
1197 for (node = xmlFirstElementChild(snapshot_output_node); node;
1198 node = xmlNextElementSibling(node)) {
1199 if (!strcmp((const char *) node->name,
1200 config_element_name)) {
1201 /* name */
1202 name = (char *) xmlNodeGetContent(node);
1203 if (!name) {
1204 ret = -LTTNG_ERR_NOMEM;
1205 goto error_snapshot_output;
1206 }
1207 } else if (!strcmp((const char *) node->name,
1208 config_element_max_size)) {
1209 xmlChar *content = xmlNodeGetContent(node);
1210
1211 /* max_size */
1212 if (!content) {
1213 ret = -LTTNG_ERR_NOMEM;
1214 goto error_snapshot_output;
1215 }
1216 ret = parse_uint(content, &max_size);
1217 free(content);
1218 if (ret) {
1219 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1220 goto error_snapshot_output;
1221 }
1222 } else {
1223 /* consumer_output */
1224 ret = process_consumer_output(node, &output);
1225 if (ret) {
1226 goto error_snapshot_output;
1227 }
1228 }
1229 }
1230
21a3f144
JR
1231 control_uri = output.control_uri;
1232 data_uri = output.data_uri;
1233 path = output.path;
1234
1b08cbce
JR
1235 if (overrides) {
1236 if (overrides->path_url) {
1b08cbce 1237 path = overrides->path_url;
21a3f144
JR
1238 /* Control/data_uri are null */
1239 control_uri = NULL;
1240 data_uri = NULL;
1b08cbce
JR
1241 } else {
1242 if (overrides->ctrl_url) {
1b08cbce 1243 control_uri = overrides->ctrl_url;
21a3f144
JR
1244 /* path is null */
1245 path = NULL;
1b08cbce
JR
1246 }
1247 if (overrides->data_url) {
1b08cbce 1248 data_uri = overrides->data_url;
21a3f144
JR
1249 /* path is null */
1250 path = NULL;
1b08cbce
JR
1251 }
1252 }
1b08cbce
JR
1253 }
1254
dcf266c0
JG
1255 snapshot_output = lttng_snapshot_output_create();
1256 if (!snapshot_output) {
1257 ret = -LTTNG_ERR_NOMEM;
1258 goto error_snapshot_output;
1259 }
1260
1261 ret = lttng_snapshot_output_set_name(name, snapshot_output);
1262 if (ret) {
1263 goto error_snapshot_output;
1264 }
1265
1266 ret = lttng_snapshot_output_set_size(max_size, snapshot_output);
1267 if (ret) {
1268 goto error_snapshot_output;
1269 }
1270
1b08cbce
JR
1271 if (path) {
1272 ret = lttng_snapshot_output_set_ctrl_url(path,
dcf266c0
JG
1273 snapshot_output);
1274 if (ret) {
1275 goto error_snapshot_output;
1276 }
1277 } else {
1b08cbce
JR
1278 if (control_uri) {
1279 ret = lttng_snapshot_output_set_ctrl_url(control_uri,
dcf266c0
JG
1280 snapshot_output);
1281 if (ret) {
1282 goto error_snapshot_output;
1283 }
1284 }
1285
1b08cbce
JR
1286 if (data_uri) {
1287 ret = lttng_snapshot_output_set_data_url(data_uri,
dcf266c0
JG
1288 snapshot_output);
1289 if (ret) {
1290 goto error_snapshot_output;
1291 }
1292 }
1293 }
1294
1295 ret = lttng_snapshot_add_output(session_name, snapshot_output);
1296error_snapshot_output:
1297 free(name);
1298 free(output.path);
1299 free(output.control_uri);
1300 free(output.data_uri);
1301 lttng_snapshot_output_destroy(snapshot_output);
1302 if (ret) {
1303 goto end;
1304 }
1305 }
1306end:
fbc3f258 1307 lttng_session_descriptor_destroy(session_descriptor);
dcf266c0
JG
1308 return ret;
1309}
1310
1311static
1312int create_session(const char *name,
dcf266c0 1313 xmlNodePtr output_node,
1b08cbce
JR
1314 uint64_t live_timer_interval,
1315 const struct config_load_session_override_attr *overrides)
dcf266c0 1316{
fbc3f258
JR
1317 int ret = 0;
1318 enum lttng_error_code ret_code;
1c9a0b0e 1319 struct consumer_output output = {};
dcf266c0 1320 xmlNodePtr consumer_output_node;
1b08cbce
JR
1321 const char *control_uri = NULL;
1322 const char *data_uri = NULL;
1323 const char *path = NULL;
fbc3f258 1324 struct lttng_session_descriptor *session_descriptor = nullptr;
dcf266c0 1325
a0377dfe 1326 LTTNG_ASSERT(name);
dcf266c0
JG
1327
1328 if (output_node) {
1329 consumer_output_node = xmlFirstElementChild(output_node);
1330 if (!consumer_output_node) {
1331 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1332 goto end;
1333 }
1334
1335 if (strcmp((const char *) consumer_output_node->name,
1336 config_element_consumer_output)) {
1337 WARN("Invalid output type, expected %s node",
1338 config_element_consumer_output);
1339 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1340 goto end;
1341 }
1342
1343 ret = process_consumer_output(consumer_output_node, &output);
1344 if (ret) {
1345 goto end;
1346 }
1347 }
1348
21a3f144
JR
1349 control_uri = output.control_uri;
1350 data_uri = output.data_uri;
1351 path = output.path;
1352
1b08cbce
JR
1353 /* Check for override and apply them */
1354 if (overrides) {
1355 if (overrides->path_url) {
1b08cbce 1356 path = overrides->path_url;
21a3f144
JR
1357 /* control/data_uri are null */;
1358 control_uri = NULL;
1359 data_uri = NULL;
1b08cbce
JR
1360 } else {
1361 if (overrides->ctrl_url) {
1b08cbce 1362 control_uri = overrides->ctrl_url;
21a3f144
JR
1363 /* path is null */
1364 path = NULL;
1b08cbce
JR
1365 }
1366 if (overrides->data_url) {
1b08cbce 1367 data_uri = overrides->data_url;
21a3f144
JR
1368 /* path is null */
1369 path = NULL;
1b08cbce
JR
1370 }
1371 }
1b08cbce
JR
1372 }
1373
1374 if (live_timer_interval != UINT64_MAX && !control_uri && !data_uri) {
dcf266c0
JG
1375 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1376 goto end;
1377 }
1378
1b08cbce 1379 if (control_uri || data_uri) {
dcf266c0
JG
1380 /* network destination */
1381 if (live_timer_interval && live_timer_interval != UINT64_MAX) {
b664f89a
DG
1382 /*
1383 * URLs are provided for sure since the test above make sure that
1384 * with a live timer the data and control URIs are provided. So,
1385 * NULL is passed here and will be set right after.
1386 */
fbc3f258
JR
1387 session_descriptor = lttng_session_descriptor_live_network_create(
1388 name, control_uri, data_uri, live_timer_interval);
dcf266c0 1389 } else {
fbc3f258
JR
1390 session_descriptor = lttng_session_descriptor_network_create(
1391 name, control_uri, data_uri);
dcf266c0 1392 }
95681498 1393
fbc3f258
JR
1394 } else if (path != nullptr) {
1395 session_descriptor = lttng_session_descriptor_local_create(name, path);
dcf266c0 1396 } else {
fbc3f258
JR
1397 /* No output */
1398 session_descriptor = lttng_session_descriptor_create(name);
1399 }
1400
1401 if (session_descriptor == nullptr) {
1402 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1403 goto end;
dcf266c0 1404 }
fbc3f258
JR
1405
1406 ret_code = lttng_create_session_ext(session_descriptor);
1407 if (ret_code != LTTNG_OK) {
1408 ret = -ret_code;
1409 goto end;
1410 }
1411
dcf266c0
JG
1412end:
1413 free(output.path);
1414 free(output.control_uri);
1415 free(output.data_uri);
fbc3f258 1416 lttng_session_descriptor_destroy(session_descriptor);
dcf266c0
JG
1417 return ret;
1418}
c1e83fb4
FD
1419
1420static
1421struct lttng_userspace_probe_location *
1422process_userspace_probe_function_attribute_node(
1423 xmlNodePtr attribute_node)
1424{
c1e83fb4 1425 xmlNodePtr function_attribute_node;
717d2dba 1426 char *function_name = NULL, *binary_path = NULL;
c1e83fb4
FD
1427 struct lttng_userspace_probe_location *location = NULL;
1428 struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
1429
1430 /*
1431 * Process userspace probe location function attributes. The order of
1432 * the fields are not guaranteed so we need to iterate over all fields
1433 * and check at the end if everything we need for this location type is
1434 * there.
1435 */
1436 for (function_attribute_node =
1437 xmlFirstElementChild(attribute_node);
1438 function_attribute_node;
1439 function_attribute_node = xmlNextElementSibling(
1440 function_attribute_node)) {
1441 /* Handle function name, binary path and lookup method. */
1442 if (!strcmp((const char *) function_attribute_node->name,
1443 config_element_userspace_probe_function_location_function_name)) {
717d2dba 1444 function_name = (char *) xmlNodeGetContent(function_attribute_node);
c1e83fb4 1445 if (!function_name) {
c1e83fb4
FD
1446 goto error;
1447 }
1448 } else if (!strcmp((const char *) function_attribute_node->name,
1449 config_element_userspace_probe_location_binary_path)) {
717d2dba 1450 binary_path = (char *) xmlNodeGetContent(function_attribute_node);
c1e83fb4 1451 if (!binary_path) {
c1e83fb4
FD
1452 goto error;
1453 }
1454 } else if (!strcmp((const char *) function_attribute_node->name,
1455 config_element_userspace_probe_lookup)) {
717d2dba 1456 char *lookup_method_name;
c1e83fb4 1457
717d2dba
JG
1458 lookup_method_name = (char *) xmlNodeGetContent(
1459 function_attribute_node);
c1e83fb4 1460 if (!lookup_method_name) {
c1e83fb4
FD
1461 goto error;
1462 }
1463
1464 /*
1465 * function_default lookup method defaults to
1466 * function_elf lookup method at the moment.
1467 */
1468 if (!strcmp(lookup_method_name, config_element_userspace_probe_lookup_function_elf)
1469 || !strcmp(lookup_method_name, config_element_userspace_probe_lookup_function_default)) {
1470 lookup_method = lttng_userspace_probe_location_lookup_method_function_elf_create();
1471 if (!lookup_method) {
1472 PERROR("Error creating function default/ELF lookup method");
c1e83fb4
FD
1473 }
1474 } else {
717d2dba
JG
1475 WARN("Unknown function lookup method");
1476 }
1477
1478 free(lookup_method_name);
1479 if (!lookup_method) {
c1e83fb4
FD
1480 goto error;
1481 }
1482 } else {
1483 goto error;
1484 }
1485
1486 /* Check if all the necessary fields were found. */
1487 if (binary_path && function_name && lookup_method) {
717d2dba 1488 /* Ownership of lookup_method is transferred. */
c1e83fb4
FD
1489 location =
1490 lttng_userspace_probe_location_function_create(
1491 binary_path, function_name,
1492 lookup_method);
717d2dba
JG
1493 lookup_method = NULL;
1494 goto error;
c1e83fb4
FD
1495 }
1496 }
1497error:
717d2dba 1498 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
c1e83fb4
FD
1499 free(binary_path);
1500 free(function_name);
c1e83fb4
FD
1501 return location;
1502}
1503
1504static
1505struct lttng_userspace_probe_location *
1506process_userspace_probe_tracepoint_attribute_node(
1507 xmlNodePtr attribute_node)
1508{
c1e83fb4 1509 xmlNodePtr tracepoint_attribute_node;
c1e83fb4
FD
1510 char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
1511 struct lttng_userspace_probe_location *location = NULL;
1512 struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
1513
1514 /*
1515 * Process userspace probe location tracepoint attributes. The order of
1516 * the fields are not guaranteed so we need to iterate over all fields
1517 * and check at the end if everything we need for this location type is
1518 * there.
1519 */
1520 for (tracepoint_attribute_node =
1521 xmlFirstElementChild(attribute_node); tracepoint_attribute_node;
1522 tracepoint_attribute_node = xmlNextElementSibling(
1523 tracepoint_attribute_node)) {
1524 if (!strcmp((const char *) tracepoint_attribute_node->name,
1525 config_element_userspace_probe_tracepoint_location_probe_name)) {
717d2dba 1526 probe_name = (char *) xmlNodeGetContent(tracepoint_attribute_node);
c1e83fb4 1527 if (!probe_name) {
c1e83fb4
FD
1528 goto error;
1529 }
1530 } else if (!strcmp((const char *) tracepoint_attribute_node->name,
1531 config_element_userspace_probe_tracepoint_location_provider_name)) {
717d2dba 1532 provider_name = (char *) xmlNodeGetContent(tracepoint_attribute_node);
c1e83fb4 1533 if (!provider_name) {
c1e83fb4
FD
1534 goto error;
1535 }
1536 } else if (!strcmp((const char *) tracepoint_attribute_node->name,
1537 config_element_userspace_probe_location_binary_path)) {
717d2dba 1538 binary_path = (char *) xmlNodeGetContent(tracepoint_attribute_node);
c1e83fb4 1539 if (!binary_path) {
c1e83fb4
FD
1540 goto error;
1541 }
1542 } else if (!strcmp((const char *) tracepoint_attribute_node->name,
1543 config_element_userspace_probe_lookup)) {
717d2dba 1544 char *lookup_method_name;
c1e83fb4 1545
717d2dba
JG
1546 lookup_method_name = (char *) xmlNodeGetContent(
1547 tracepoint_attribute_node);
c1e83fb4 1548 if (!lookup_method_name) {
c1e83fb4
FD
1549 goto error;
1550 }
1551
1552 if (!strcmp(lookup_method_name,
1553 config_element_userspace_probe_lookup_tracepoint_sdt)) {
1554 lookup_method =
1555 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1556 if (!lookup_method) {
1557 PERROR("Error creating tracepoint SDT lookup method");
c1e83fb4
FD
1558 }
1559 } else {
717d2dba
JG
1560 WARN("Unknown tracepoint lookup method");
1561 }
1562
1563 free(lookup_method_name);
1564 if (!lookup_method) {
c1e83fb4
FD
1565 goto error;
1566 }
1567 } else {
717d2dba 1568 WARN("Unknown tracepoint attribute");
c1e83fb4
FD
1569 goto error;
1570 }
1571
1572 /* Check if all the necessary fields were found. */
1573 if (binary_path && provider_name && probe_name && lookup_method) {
717d2dba 1574 /* Ownership of lookup_method is transferred. */
c1e83fb4
FD
1575 location =
1576 lttng_userspace_probe_location_tracepoint_create(
1577 binary_path, provider_name,
1578 probe_name, lookup_method);
6bd61b96 1579 lookup_method = NULL;
717d2dba 1580 goto error;
c1e83fb4
FD
1581 }
1582 }
1583error:
717d2dba 1584 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
c1e83fb4 1585 free(binary_path);
c1e83fb4 1586 free(provider_name);
717d2dba 1587 free(probe_name);
c1e83fb4
FD
1588 return location;
1589}
1590
dcf266c0
JG
1591static
1592int process_probe_attribute_node(xmlNodePtr probe_attribute_node,
1593 struct lttng_event_probe_attr *attr)
1594{
1595 int ret;
1596
a0377dfe
FD
1597 LTTNG_ASSERT(probe_attribute_node);
1598 LTTNG_ASSERT(attr);
dcf266c0
JG
1599
1600 if (!strcmp((const char *) probe_attribute_node->name,
1601 config_element_address)) {
1602 xmlChar *content;
1603 uint64_t addr = 0;
1604
1605 /* addr */
1606 content = xmlNodeGetContent(probe_attribute_node);
1607 if (!content) {
1608 ret = -LTTNG_ERR_NOMEM;
1609 goto end;
1610 }
1611
1612 ret = parse_uint(content, &addr);
1613 free(content);
1614 if (ret) {
1615 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1616 goto end;
1617 }
1618
1619 attr->addr = addr;
1620 } else if (!strcmp((const char *) probe_attribute_node->name,
1621 config_element_offset)) {
1622 xmlChar *content;
1623 uint64_t offset = 0;
1624
1625 /* offset */
1626 content = xmlNodeGetContent(probe_attribute_node);
1627 if (!content) {
1628 ret = -LTTNG_ERR_NOMEM;
1629 goto end;
1630 }
1631
1632 ret = parse_uint(content, &offset);
1633 free(content);
1634 if (ret) {
1635 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1636 goto end;
1637 }
1638
1639 attr->offset = offset;
1640 } else if (!strcmp((const char *) probe_attribute_node->name,
1641 config_element_symbol_name)) {
1642 xmlChar *content;
dcf266c0
JG
1643
1644 /* symbol_name */
1645 content = xmlNodeGetContent(probe_attribute_node);
1646 if (!content) {
1647 ret = -LTTNG_ERR_NOMEM;
1648 goto end;
1649 }
1650
d2e67842
JG
1651 ret = lttng_strncpy(attr->symbol_name,
1652 (const char *) content,
1653 LTTNG_SYMBOL_NAME_LEN);
1654 if (ret == -1) {
1655 ERR("symbol name \"%s\"'s length (%zu) exceeds the maximal permitted length (%d) in session configuration",
1656 (const char *) content,
1657 strlen((const char *) content),
1658 LTTNG_SYMBOL_NAME_LEN);
dcf266c0
JG
1659 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1660 free(content);
1661 goto end;
1662 }
dcf266c0
JG
1663 free(content);
1664 }
1665 ret = 0;
1666end:
1667 return ret;
1668}
1669
1670static
1671int process_event_node(xmlNodePtr event_node, struct lttng_handle *handle,
d7b645e2 1672 const char *channel_name, const enum process_event_node_phase phase)
dcf266c0 1673{
d7b645e2 1674 int ret = 0, i;
dcf266c0 1675 xmlNodePtr node;
91744e14 1676 struct lttng_event *event;
dcf266c0
JG
1677 char **exclusions = NULL;
1678 unsigned long exclusion_count = 0;
1679 char *filter_expression = NULL;
1680
a0377dfe
FD
1681 LTTNG_ASSERT(event_node);
1682 LTTNG_ASSERT(handle);
1683 LTTNG_ASSERT(channel_name);
dcf266c0 1684
91744e14
FD
1685 event = lttng_event_create();
1686 if (!event) {
1687 ret = -LTTNG_ERR_NOMEM;
1688 goto end;
1689 }
dcf266c0 1690
f40eba3d
JG
1691 /* Initialize default log level which varies by domain */
1692 switch (handle->domain.type)
1693 {
1694 case LTTNG_DOMAIN_JUL:
91744e14 1695 event->loglevel = LTTNG_LOGLEVEL_JUL_ALL;
f40eba3d
JG
1696 break;
1697 case LTTNG_DOMAIN_LOG4J:
91744e14 1698 event->loglevel = LTTNG_LOGLEVEL_LOG4J_ALL;
f40eba3d
JG
1699 break;
1700 case LTTNG_DOMAIN_PYTHON:
91744e14 1701 event->loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
f40eba3d
JG
1702 break;
1703 case LTTNG_DOMAIN_UST:
1704 case LTTNG_DOMAIN_KERNEL:
91744e14 1705 event->loglevel = LTTNG_LOGLEVEL_DEBUG;
f40eba3d
JG
1706 break;
1707 default:
a0377dfe 1708 abort();
f40eba3d
JG
1709 }
1710
dcf266c0
JG
1711 for (node = xmlFirstElementChild(event_node); node;
1712 node = xmlNextElementSibling(node)) {
1713 if (!strcmp((const char *) node->name, config_element_name)) {
1714 xmlChar *content;
dcf266c0
JG
1715
1716 /* name */
1717 content = xmlNodeGetContent(node);
1718 if (!content) {
1719 ret = -LTTNG_ERR_NOMEM;
1720 goto end;
1721 }
1722
91744e14 1723 ret = lttng_strncpy(event->name,
d2e67842
JG
1724 (const char *) content,
1725 LTTNG_SYMBOL_NAME_LEN);
1726 if (ret == -1) {
1727 WARN("Event \"%s\"'s name length (%zu) exceeds the maximal permitted length (%d) in session configuration",
1728 (const char *) content,
1729 strlen((const char *) content),
1730 LTTNG_SYMBOL_NAME_LEN);
dcf266c0
JG
1731 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1732 free(content);
1733 goto end;
1734 }
dcf266c0
JG
1735 free(content);
1736 } else if (!strcmp((const char *) node->name,
1737 config_element_enabled)) {
1738 xmlChar *content = xmlNodeGetContent(node);
1739
1740 /* enabled */
1741 if (!content) {
1742 ret = -LTTNG_ERR_NOMEM;
1743 goto end;
1744 }
1745
91744e14 1746 ret = parse_bool(content, &event->enabled);
dcf266c0
JG
1747 free(content);
1748 if (ret) {
1749 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1750 goto end;
1751 }
1752 } else if (!strcmp((const char *) node->name,
1753 config_element_type)) {
1754 xmlChar *content = xmlNodeGetContent(node);
1755
1756 /* type */
1757 if (!content) {
1758 ret = -LTTNG_ERR_NOMEM;
1759 goto end;
1760 }
1761
1762 ret = get_event_type(content);
1763 free(content);
1764 if (ret < 0) {
1765 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1766 goto end;
1767 }
1768
3afa94ae 1769 event->type = (lttng_event_type) ret;
dcf266c0
JG
1770 } else if (!strcmp((const char *) node->name,
1771 config_element_loglevel_type)) {
1772 xmlChar *content = xmlNodeGetContent(node);
1773
1774 /* loglevel_type */
1775 if (!content) {
1776 ret = -LTTNG_ERR_NOMEM;
1777 goto end;
1778 }
1779
1780 ret = get_loglevel_type(content);
1781 free(content);
1782 if (ret < 0) {
1783 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1784 goto end;
1785 }
1786
3afa94ae 1787 event->loglevel_type = (lttng_loglevel_type) ret;
dcf266c0
JG
1788 } else if (!strcmp((const char *) node->name,
1789 config_element_loglevel)) {
1790 xmlChar *content;
1791 int64_t loglevel = 0;
1792
1793 /* loglevel */
1794 content = xmlNodeGetContent(node);
1795 if (!content) {
1796 ret = -LTTNG_ERR_NOMEM;
1797 goto end;
1798 }
1799
1800 ret = parse_int(content, &loglevel);
1801 free(content);
1802 if (ret) {
1803 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1804 goto end;
1805 }
1806
1807 if (loglevel > INT_MAX || loglevel < INT_MIN) {
1808 WARN("loglevel out of range.");
1809 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1810 goto end;
1811 }
1812
91744e14 1813 event->loglevel = loglevel;
dcf266c0
JG
1814 } else if (!strcmp((const char *) node->name,
1815 config_element_filter)) {
1816 xmlChar *content =
1817 xmlNodeGetContent(node);
1818
1819 /* filter */
1820 if (!content) {
1821 ret = -LTTNG_ERR_NOMEM;
1822 goto end;
1823 }
1824
02d8ac3d 1825 free(filter_expression);
dcf266c0
JG
1826 filter_expression = strdup((char *) content);
1827 free(content);
1828 if (!filter_expression) {
1829 ret = -LTTNG_ERR_NOMEM;
1830 goto end;
1831 }
1832 } else if (!strcmp((const char *) node->name,
1833 config_element_exclusions)) {
1834 xmlNodePtr exclusion_node;
1835 int exclusion_index = 0;
1836
1837 /* exclusions */
1838 if (exclusions) {
1839 /*
1840 * Exclusions has already been initialized,
1841 * invalid file.
1842 */
1843 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1844 goto end;
1845 }
1846
1847 exclusion_count = xmlChildElementCount(node);
1848 if (!exclusion_count) {
1849 continue;
1850 }
1851
64803277 1852 exclusions = calloc<char *>(exclusion_count);
dcf266c0
JG
1853 if (!exclusions) {
1854 exclusion_count = 0;
1855 ret = -LTTNG_ERR_NOMEM;
1856 goto end;
1857 }
1858
1859 for (exclusion_node = xmlFirstElementChild(node); exclusion_node;
1860 exclusion_node = xmlNextElementSibling(exclusion_node)) {
1861 xmlChar *content =
1862 xmlNodeGetContent(exclusion_node);
1863
1864 if (!content) {
1865 ret = -LTTNG_ERR_NOMEM;
1866 goto end;
1867 }
1868
1869 exclusions[exclusion_index] = strdup((const char *) content);
1870 free(content);
1871 if (!exclusions[exclusion_index]) {
1872 ret = -LTTNG_ERR_NOMEM;
1873 goto end;
1874 }
1875 exclusion_index++;
1876 }
1877
91744e14 1878 event->exclusion = 1;
dcf266c0
JG
1879 } else if (!strcmp((const char *) node->name,
1880 config_element_attributes)) {
1881 xmlNodePtr attribute_node = xmlFirstElementChild(node);
1882
1883 /* attributes */
1884 if (!attribute_node) {
1885 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1886 goto end;
1887 }
1888
c1e83fb4 1889 if (!strcmp((const char *) attribute_node->name,
dcf266c0
JG
1890 config_element_probe_attributes)) {
1891 xmlNodePtr probe_attribute_node;
1892
1893 /* probe_attributes */
1894 for (probe_attribute_node =
1895 xmlFirstElementChild(attribute_node); probe_attribute_node;
1896 probe_attribute_node = xmlNextElementSibling(
1897 probe_attribute_node)) {
1898
1899 ret = process_probe_attribute_node(probe_attribute_node,
91744e14 1900 &event->attr.probe);
dcf266c0
JG
1901 if (ret) {
1902 goto end;
1903 }
1904 }
c1e83fb4
FD
1905 } else if (!strcmp((const char *) attribute_node->name,
1906 config_element_function_attributes)) {
dcf266c0
JG
1907 size_t sym_len;
1908 xmlChar *content;
1909 xmlNodePtr symbol_node = xmlFirstElementChild(attribute_node);
1910
1911 /* function_attributes */
1912 content = xmlNodeGetContent(symbol_node);
1913 if (!content) {
1914 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1915 goto end;
1916 }
1917
1918 sym_len = strlen((char *) content);
1919 if (sym_len >= LTTNG_SYMBOL_NAME_LEN) {
1920 WARN("Function name too long.");
1921 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1922 free(content);
1923 goto end;
1924 }
1925
d2e67842 1926 ret = lttng_strncpy(
91744e14 1927 event->attr.ftrace.symbol_name,
d2e67842
JG
1928 (char *) content, sym_len);
1929 if (ret == -1) {
1930 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1931 free(content);
1932 goto end;
1933 }
dcf266c0 1934 free(content);
c1e83fb4
FD
1935 } else if (!strcmp((const char *) attribute_node->name,
1936 config_element_userspace_probe_tracepoint_attributes)) {
1937 struct lttng_userspace_probe_location *location;
1938
1939 location = process_userspace_probe_tracepoint_attribute_node(attribute_node);
1940 if (!location) {
1941 WARN("Error processing userspace probe tracepoint attribute");
1942 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1943 goto end;
1944 }
1945 ret = lttng_event_set_userspace_probe_location(
1946 event, location);
1947 if (ret) {
1948 WARN("Error setting userspace probe location field");
1949 lttng_userspace_probe_location_destroy(
1950 location);
1951 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1952 goto end;
1953 }
1954 } else if (!strcmp((const char *) attribute_node->name,
1955 config_element_userspace_probe_function_attributes)) {
1956 struct lttng_userspace_probe_location *location;
1957
1958 location =
1959 process_userspace_probe_function_attribute_node(
1960 attribute_node);
1961 if (!location) {
1962 WARN("Error processing userspace probe function attribute");
1963 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1964 goto end;
1965 }
1966
1967 ret = lttng_event_set_userspace_probe_location(
1968 event, location);
1969 if (ret) {
1970 WARN("Error setting userspace probe location field");
1971 lttng_userspace_probe_location_destroy(
1972 location);
1973 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1974 goto end;
1975 }
1976 } else {
1977 /* Unknown event attribute. */
1978 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1979 goto end;
dcf266c0
JG
1980 }
1981 }
1982 }
1983
91744e14
FD
1984 if ((event->enabled && phase == ENABLE) || phase == CREATION) {
1985 ret = lttng_enable_event_with_exclusions(handle, event, channel_name,
d7b645e2
JR
1986 filter_expression, exclusion_count, exclusions);
1987 if (ret < 0) {
91744e14 1988 WARN("Enabling event (name:%s) on load failed.", event->name);
d7b645e2
JR
1989 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1990 goto end;
1991 }
065321e9 1992 }
d2e67842 1993 ret = 0;
dcf266c0
JG
1994end:
1995 for (i = 0; i < exclusion_count; i++) {
1996 free(exclusions[i]);
1997 }
1998
b33f872b 1999 lttng_event_destroy(event);
dcf266c0
JG
2000 free(exclusions);
2001 free(filter_expression);
2002 return ret;
2003}
2004
2005static
2006int process_events_node(xmlNodePtr events_node, struct lttng_handle *handle,
2007 const char *channel_name)
2008{
2009 int ret = 0;
d7b645e2 2010 struct lttng_event event;
dcf266c0
JG
2011 xmlNodePtr node;
2012
a0377dfe
FD
2013 LTTNG_ASSERT(events_node);
2014 LTTNG_ASSERT(handle);
2015 LTTNG_ASSERT(channel_name);
dcf266c0
JG
2016
2017 for (node = xmlFirstElementChild(events_node); node;
2018 node = xmlNextElementSibling(node)) {
d7b645e2 2019 ret = process_event_node(node, handle, channel_name, CREATION);
dcf266c0
JG
2020 if (ret) {
2021 goto end;
2022 }
2023 }
d7b645e2
JR
2024
2025 /*
2026 * Disable all events to enable only the necessary events.
2027 * Limitations regarding lttng_disable_events and tuple descriptor
2028 * force this approach.
2029 */
2030 memset(&event, 0, sizeof(event));
2031 event.loglevel = -1;
2032 event.type = LTTNG_EVENT_ALL;
2033 ret = lttng_disable_event_ext(handle, &event, channel_name, NULL);
2034 if (ret) {
2035 goto end;
2036 }
2037
2038 for (node = xmlFirstElementChild(events_node); node;
2039 node = xmlNextElementSibling(node)) {
2040 ret = process_event_node(node, handle, channel_name, ENABLE);
2041 if (ret) {
2042 goto end;
2043 }
2044 }
2045
dcf266c0
JG
2046end:
2047 return ret;
2048}
2049
2050static
2051int process_channel_attr_node(xmlNodePtr attr_node,
2052 struct lttng_channel *channel, xmlNodePtr *contexts_node,
2053 xmlNodePtr *events_node)
2054{
2055 int ret;
2056
a0377dfe
FD
2057 LTTNG_ASSERT(attr_node);
2058 LTTNG_ASSERT(channel);
2059 LTTNG_ASSERT(contexts_node);
2060 LTTNG_ASSERT(events_node);
dcf266c0
JG
2061
2062 if (!strcmp((const char *) attr_node->name, config_element_name)) {
2063 xmlChar *content;
dcf266c0
JG
2064
2065 /* name */
2066 content = xmlNodeGetContent(attr_node);
2067 if (!content) {
2068 ret = -LTTNG_ERR_NOMEM;
2069 goto end;
2070 }
2071
d2e67842
JG
2072 ret = lttng_strncpy(channel->name,
2073 (const char *) content,
2074 LTTNG_SYMBOL_NAME_LEN);
2075 if (ret == -1) {
2076 WARN("Channel \"%s\"'s name length (%zu) exceeds the maximal permitted length (%d) in session configuration",
2077 (const char *) content,
2078 strlen((const char *) content),
2079 LTTNG_SYMBOL_NAME_LEN);
dcf266c0
JG
2080 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2081 free(content);
2082 goto end;
2083 }
dcf266c0
JG
2084 free(content);
2085 } else if (!strcmp((const char *) attr_node->name,
2086 config_element_enabled)) {
2087 xmlChar *content;
2088 int enabled;
2089
2090 /* enabled */
2091 content = xmlNodeGetContent(attr_node);
2092 if (!content) {
2093 ret = -LTTNG_ERR_NOMEM;
2094 goto end;
2095 }
2096
2097 ret = parse_bool(content, &enabled);
2098 free(content);
2099 if (ret) {
2100 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2101 goto end;
2102 }
2103
2104 channel->enabled = enabled;
2105 } else if (!strcmp((const char *) attr_node->name,
2106 config_element_overwrite_mode)) {
2107 xmlChar *content;
2108
2109 /* overwrite_mode */
2110 content = xmlNodeGetContent(attr_node);
2111 if (!content) {
2112 ret = -LTTNG_ERR_NOMEM;
2113 goto end;
2114 }
2115
2116 ret = get_overwrite_mode(content);
2117 free(content);
2118 if (ret < 0) {
2119 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2120 goto end;
2121 }
2122
2123 channel->attr.overwrite = ret;
2124 } else if (!strcmp((const char *) attr_node->name,
2125 config_element_subbuf_size)) {
2126 xmlChar *content;
2127
2128 /* subbuffer_size */
2129 content = xmlNodeGetContent(attr_node);
2130 if (!content) {
2131 ret = -LTTNG_ERR_NOMEM;
2132 goto end;
2133 }
2134
2135 ret = parse_uint(content, &channel->attr.subbuf_size);
2136 free(content);
2137 if (ret) {
2138 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2139 goto end;
2140 }
2141 } else if (!strcmp((const char *) attr_node->name,
2142 config_element_num_subbuf)) {
2143 xmlChar *content;
2144
2145 /* subbuffer_count */
2146 content = xmlNodeGetContent(attr_node);
2147 if (!content) {
2148 ret = -LTTNG_ERR_NOMEM;
2149 goto end;
2150 }
2151
2152 ret = parse_uint(content, &channel->attr.num_subbuf);
2153 free(content);
2154 if (ret) {
2155 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2156 goto end;
2157 }
2158 } else if (!strcmp((const char *) attr_node->name,
2159 config_element_switch_timer_interval)) {
2160 xmlChar *content;
2161 uint64_t switch_timer_interval = 0;
2162
2163 /* switch_timer_interval */
2164 content = xmlNodeGetContent(attr_node);
2165 if (!content) {
2166 ret = -LTTNG_ERR_NOMEM;
2167 goto end;
2168 }
2169
2170 ret = parse_uint(content, &switch_timer_interval);
2171 free(content);
2172 if (ret) {
2173 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2174 goto end;
2175 }
2176
2177 if (switch_timer_interval > UINT_MAX) {
2178 WARN("switch_timer_interval out of range.");
2179 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2180 goto end;
2181 }
2182
2183 channel->attr.switch_timer_interval =
2184 switch_timer_interval;
2185 } else if (!strcmp((const char *) attr_node->name,
2186 config_element_read_timer_interval)) {
2187 xmlChar *content;
2188 uint64_t read_timer_interval = 0;
2189
2190 /* read_timer_interval */
2191 content = xmlNodeGetContent(attr_node);
2192 if (!content) {
2193 ret = -LTTNG_ERR_NOMEM;
2194 goto end;
2195 }
2196
2197 ret = parse_uint(content, &read_timer_interval);
2198 free(content);
2199 if (ret) {
2200 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2201 goto end;
2202 }
2203
2204 if (read_timer_interval > UINT_MAX) {
2205 WARN("read_timer_interval out of range.");
2206 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2207 goto end;
2208 }
2209
2210 channel->attr.read_timer_interval =
2211 read_timer_interval;
2212 } else if (!strcmp((const char *) attr_node->name,
2213 config_element_output_type)) {
2214 xmlChar *content;
2215
2216 /* output_type */
2217 content = xmlNodeGetContent(attr_node);
2218 if (!content) {
2219 ret = -LTTNG_ERR_NOMEM;
2220 goto end;
2221 }
2222
2223 ret = get_output_type(content);
2224 free(content);
2225 if (ret < 0) {
2226 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2227 goto end;
2228 }
2229
3afa94ae 2230 channel->attr.output = (lttng_event_output) ret;
dcf266c0
JG
2231 } else if (!strcmp((const char *) attr_node->name,
2232 config_element_tracefile_size)) {
2233 xmlChar *content;
2234
2235 /* tracefile_size */
2236 content = xmlNodeGetContent(attr_node);
2237 if (!content) {
2238 ret = -LTTNG_ERR_NOMEM;
2239 goto end;
2240 }
2241
2242 ret = parse_uint(content, &channel->attr.tracefile_size);
2243 free(content);
2244 if (ret) {
2245 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2246 goto end;
2247 }
2248 } else if (!strcmp((const char *) attr_node->name,
2249 config_element_tracefile_count)) {
2250 xmlChar *content;
2251
2252 /* tracefile_count */
2253 content = xmlNodeGetContent(attr_node);
2254 if (!content) {
2255 ret = -LTTNG_ERR_NOMEM;
2256 goto end;
2257 }
2258
2259 ret = parse_uint(content, &channel->attr.tracefile_count);
2260 free(content);
2261 if (ret) {
2262 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2263 goto end;
2264 }
2265 } else if (!strcmp((const char *) attr_node->name,
2266 config_element_live_timer_interval)) {
2267 xmlChar *content;
2268 uint64_t live_timer_interval = 0;
2269
2270 /* live_timer_interval */
2271 content = xmlNodeGetContent(attr_node);
2272 if (!content) {
2273 ret = -LTTNG_ERR_NOMEM;
2274 goto end;
2275 }
2276
2277 ret = parse_uint(content, &live_timer_interval);
2278 free(content);
2279 if (ret) {
2280 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2281 goto end;
2282 }
2283
2284 if (live_timer_interval > UINT_MAX) {
2285 WARN("live_timer_interval out of range.");
2286 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2287 goto end;
2288 }
2289
2290 channel->attr.live_timer_interval =
2291 live_timer_interval;
4fc2b126
JR
2292 } else if (!strcmp((const char *) attr_node->name,
2293 config_element_monitor_timer_interval)) {
2294 xmlChar *content;
2295 uint64_t monitor_timer_interval = 0;
2296
2297 /* monitor_timer_interval */
2298 content = xmlNodeGetContent(attr_node);
2299 if (!content) {
2300 ret = -LTTNG_ERR_NOMEM;
2301 goto end;
2302 }
2303
2304 ret = parse_uint(content, &monitor_timer_interval);
2305 free(content);
2306 if (ret) {
2307 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2308 goto end;
2309 }
2310
2311 ret = lttng_channel_set_monitor_timer_interval(channel,
2312 monitor_timer_interval);
2313 if (ret) {
2314 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2315 goto end;
2316 }
275472aa
JR
2317 } else if (!strcmp((const char *) attr_node->name,
2318 config_element_blocking_timeout)) {
2319 xmlChar *content;
2320 int64_t blocking_timeout = 0;
2321
2322 /* blocking_timeout */
2323 content = xmlNodeGetContent(attr_node);
2324 if (!content) {
2325 ret = -LTTNG_ERR_NOMEM;
2326 goto end;
2327 }
2328
2329 ret = parse_int(content, &blocking_timeout);
2330 free(content);
2331 if (ret) {
2332 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2333 goto end;
2334 }
2335
2336 ret = lttng_channel_set_blocking_timeout(channel,
2337 blocking_timeout);
2338 if (ret) {
2339 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2340 goto end;
2341 }
dcf266c0
JG
2342 } else if (!strcmp((const char *) attr_node->name,
2343 config_element_events)) {
2344 /* events */
2345 *events_node = attr_node;
2346 } else {
2347 /* contexts */
2348 *contexts_node = attr_node;
2349 }
2350 ret = 0;
2351end:
2352 return ret;
2353}
2354
2355static
2356int process_context_node(xmlNodePtr context_node,
2357 struct lttng_handle *handle, const char *channel_name)
2358{
2359 int ret;
2360 struct lttng_event_context context;
2361 xmlNodePtr context_child_node = xmlFirstElementChild(context_node);
2362
a0377dfe
FD
2363 LTTNG_ASSERT(handle);
2364 LTTNG_ASSERT(channel_name);
dcf266c0
JG
2365
2366 if (!context_child_node) {
2367 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2368 goto end;
2369 }
2370
2371 memset(&context, 0, sizeof(context));
2372
2373 if (!strcmp((const char *) context_child_node->name,
2374 config_element_type)) {
2375 /* type */
2376 xmlChar *content = xmlNodeGetContent(context_child_node);
045fc617 2377
dcf266c0
JG
2378 if (!content) {
2379 ret = -LTTNG_ERR_NOMEM;
2380 goto end;
2381 }
2382
2383 ret = get_context_type(content);
2384 free(content);
2385 if (ret < 0) {
2386 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2387 goto end;
2388 }
2389
3afa94ae 2390 context.ctx = (lttng_event_context_type) ret;
045fc617
JG
2391 } else if (!strcmp((const char *) context_child_node->name,
2392 config_element_context_perf)) {
2393 /* perf */
dcf266c0
JG
2394 xmlNodePtr perf_attr_node;
2395
14ce5bd8
JG
2396 context.ctx = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
2397 LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER :
2398 LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER;
dcf266c0
JG
2399 for (perf_attr_node = xmlFirstElementChild(context_child_node);
2400 perf_attr_node; perf_attr_node =
2401 xmlNextElementSibling(perf_attr_node)) {
2402 if (!strcmp((const char *) perf_attr_node->name,
2403 config_element_type)) {
2404 xmlChar *content;
2405 uint64_t type = 0;
2406
2407 /* type */
2408 content = xmlNodeGetContent(perf_attr_node);
2409 if (!content) {
2410 ret = -LTTNG_ERR_NOMEM;
2411 goto end;
2412 }
2413
2414 ret = parse_uint(content, &type);
2415 free(content);
2416 if (ret) {
2417 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2418 goto end;
2419 }
2420
2421 if (type > UINT32_MAX) {
2422 WARN("perf context type out of range.");
2423 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2424 goto end;
2425 }
2426
2427 context.u.perf_counter.type = type;
2428 } else if (!strcmp((const char *) perf_attr_node->name,
2429 config_element_config)) {
2430 xmlChar *content;
2431 uint64_t config = 0;
2432
2433 /* config */
2434 content = xmlNodeGetContent(perf_attr_node);
2435 if (!content) {
2436 ret = -LTTNG_ERR_NOMEM;
2437 goto end;
2438 }
2439
2440 ret = parse_uint(content, &config);
2441 free(content);
2442 if (ret) {
2443 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2444 goto end;
2445 }
2446
2447 context.u.perf_counter.config = config;
2448 } else if (!strcmp((const char *) perf_attr_node->name,
2449 config_element_name)) {
2450 xmlChar *content;
dcf266c0
JG
2451
2452 /* name */
2453 content = xmlNodeGetContent(perf_attr_node);
2454 if (!content) {
2455 ret = -LTTNG_ERR_NOMEM;
2456 goto end;
2457 }
2458
d2e67842
JG
2459 ret = lttng_strncpy(context.u.perf_counter.name,
2460 (const char *) content,
2461 LTTNG_SYMBOL_NAME_LEN);
2462 if (ret == -1) {
2463 WARN("Perf counter \"%s\"'s name length (%zu) exceeds the maximal permitted length (%d) in session configuration",
2464 (const char *) content,
2465 strlen((const char *) content),
2466 LTTNG_SYMBOL_NAME_LEN);
dcf266c0
JG
2467 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2468 free(content);
2469 goto end;
2470 }
dcf266c0
JG
2471 free(content);
2472 }
2473 }
045fc617
JG
2474 } else if (!strcmp((const char *) context_child_node->name,
2475 config_element_context_app)) {
2476 /* application context */
2477 xmlNodePtr app_ctx_node;
2478
2479 context.ctx = LTTNG_EVENT_CONTEXT_APP_CONTEXT;
2480 for (app_ctx_node = xmlFirstElementChild(context_child_node);
2481 app_ctx_node; app_ctx_node =
2482 xmlNextElementSibling(app_ctx_node)) {
2483 xmlChar *content;
2484 char **target = strcmp(
2485 (const char *) app_ctx_node->name,
2486 config_element_context_app_provider_name) == 0 ?
2487 &context.u.app_ctx.provider_name :
2488 &context.u.app_ctx.ctx_name;
2489
2490 content = xmlNodeGetContent(app_ctx_node);
2491 if (!content) {
2492 ret = -LTTNG_ERR_NOMEM;
2493 goto end;
2494 }
2495
2496 *target = (char *) content;
2497 }
2498 } else {
2499 /* Unrecognized context type */
2500 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2501 goto end;
dcf266c0
JG
2502 }
2503
2504 ret = lttng_add_context(handle, &context, NULL, channel_name);
045fc617
JG
2505 if (context.ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
2506 free(context.u.app_ctx.provider_name);
2507 free(context.u.app_ctx.ctx_name);
2508 }
dcf266c0
JG
2509end:
2510 return ret;
2511}
2512
2513static
2514int process_contexts_node(xmlNodePtr contexts_node,
2515 struct lttng_handle *handle, const char *channel_name)
2516{
2517 int ret = 0;
2518 xmlNodePtr context_node;
2519
2520 for (context_node = xmlFirstElementChild(contexts_node); context_node;
2521 context_node = xmlNextElementSibling(context_node)) {
2522 ret = process_context_node(context_node, handle, channel_name);
2523 if (ret) {
2524 goto end;
2525 }
2526 }
2527end:
2528 return ret;
2529}
2530
159b042f 2531static int get_tracker_elements(enum lttng_process_attr process_attr,
55c9e7ca 2532 const char **element_id_tracker,
159b042f
JG
2533 const char **element_value_type,
2534 const char **element_value,
2535 const char **element_value_alias,
55c9e7ca
JR
2536 const char **element_name)
2537{
2538 int ret = 0;
2539
159b042f
JG
2540 switch (process_attr) {
2541 case LTTNG_PROCESS_ATTR_PROCESS_ID:
2542 *element_id_tracker = config_element_process_attr_tracker_pid;
2543 *element_value_type = config_element_process_attr_pid_value;
2544 *element_value = config_element_process_attr_id;
2545 *element_value_alias = config_element_process_attr_id;
55c9e7ca
JR
2546 *element_name = NULL;
2547 break;
159b042f
JG
2548 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
2549 *element_id_tracker = config_element_process_attr_tracker_vpid;
2550 *element_value_type = config_element_process_attr_vpid_value;
2551 *element_value = config_element_process_attr_id;
2552 *element_value_alias = NULL;
55c9e7ca
JR
2553 *element_name = NULL;
2554 break;
159b042f
JG
2555 case LTTNG_PROCESS_ATTR_USER_ID:
2556 *element_id_tracker = config_element_process_attr_tracker_uid;
2557 *element_value_type = config_element_process_attr_uid_value;
2558 *element_value = config_element_process_attr_id;
2559 *element_value_alias = NULL;
55c9e7ca
JR
2560 *element_name = config_element_name;
2561 break;
159b042f
JG
2562 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
2563 *element_id_tracker = config_element_process_attr_tracker_vuid;
2564 *element_value_type = config_element_process_attr_vuid_value;
2565 *element_value = config_element_process_attr_id;
2566 *element_value_alias = NULL;
55c9e7ca
JR
2567 *element_name = config_element_name;
2568 break;
159b042f
JG
2569 case LTTNG_PROCESS_ATTR_GROUP_ID:
2570 *element_id_tracker = config_element_process_attr_tracker_gid;
2571 *element_value_type = config_element_process_attr_gid_value;
2572 *element_value = config_element_process_attr_id;
2573 *element_value_alias = NULL;
55c9e7ca
JR
2574 *element_name = config_element_name;
2575 break;
159b042f
JG
2576 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
2577 *element_id_tracker = config_element_process_attr_tracker_vgid;
2578 *element_value_type = config_element_process_attr_vgid_value;
2579 *element_value = config_element_process_attr_id;
2580 *element_value_alias = NULL;
55c9e7ca
JR
2581 *element_name = config_element_name;
2582 break;
2583 default:
2584 ret = LTTNG_ERR_INVALID;
2585 }
2586 return ret;
2587}
2588
f7af9a72
JG
2589static int process_legacy_pid_tracker_node(
2590 xmlNodePtr trackers_node, struct lttng_handle *handle)
2591{
2592 int ret = 0, child_count;
2593 xmlNodePtr targets_node = NULL;
2594 xmlNodePtr node;
2595 const char *element_id_tracker;
2596 const char *element_target_id;
2597 const char *element_id;
2598 const char *element_id_alias;
2599 const char *element_name;
2600 enum lttng_error_code tracker_handle_ret_code;
2601 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
2602 enum lttng_process_attr_tracker_handle_status status;
2603 const enum lttng_process_attr process_attr =
2604 handle->domain.type == LTTNG_DOMAIN_UST ?
2605 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID :
2606 LTTNG_PROCESS_ATTR_PROCESS_ID;
2607
a0377dfe 2608 LTTNG_ASSERT(handle);
f7af9a72
JG
2609
2610 tracker_handle_ret_code = lttng_session_get_tracker_handle(
2611 handle->session_name, handle->domain.type,
2612 process_attr,
2613 &tracker_handle);
2614 if (tracker_handle_ret_code != LTTNG_OK) {
2615 ret = LTTNG_ERR_INVALID;
2616 goto end;
2617 }
2618
2619 ret = get_tracker_elements(process_attr, &element_id_tracker,
2620 &element_target_id, &element_id, &element_id_alias,
2621 &element_name);
2622 if (ret) {
2623 goto end;
2624 }
2625
2626 /* Get the targets node */
2627 for (node = xmlFirstElementChild(trackers_node); node;
2628 node = xmlNextElementSibling(node)) {
2629 if (!strcmp((const char *) node->name,
2630 config_element_tracker_targets_legacy)) {
2631 targets_node = node;
2632 break;
2633 }
3afa94ae 2634 }
f7af9a72
JG
2635
2636 if (!targets_node) {
2637 ret = LTTNG_ERR_INVALID;
2638 goto end;
2639 }
2640
2641 /* Go through all id target node */
2642 child_count = xmlChildElementCount(targets_node);
2643 status = lttng_process_attr_tracker_handle_set_tracking_policy(
2644 tracker_handle,
2645 child_count == 0 ? LTTNG_TRACKING_POLICY_EXCLUDE_ALL :
2646 LTTNG_TRACKING_POLICY_INCLUDE_SET);
2647 if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
2648 ret = LTTNG_ERR_UNK;
2649 goto end;
2650 }
2651
2652 /* Add all tracked values. */
2653 for (node = xmlFirstElementChild(targets_node); node;
2654 node = xmlNextElementSibling(node)) {
2655 xmlNodePtr pid_target_node = node;
2656
2657 /* get pid_target node and track it */
2658 for (node = xmlFirstElementChild(pid_target_node); node;
2659 node = xmlNextElementSibling(node)) {
2660 if (!strcmp((const char *) node->name,
2661 config_element_tracker_pid_legacy)) {
2662 int64_t id;
2663 xmlChar *content = xmlNodeGetContent(node);
2664
2665 if (!content) {
2666 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2667 goto end;
2668 }
2669
2670 ret = parse_int(content, &id);
2671 free(content);
2672 if (ret) {
2673 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2674 goto end;
2675 }
2676
2677 switch (process_attr) {
2678 case LTTNG_PROCESS_ATTR_PROCESS_ID:
2679 status = lttng_process_attr_process_id_tracker_handle_add_pid(
2680 tracker_handle,
2681 (pid_t) id);
2682 break;
2683 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
2684 status = lttng_process_attr_virtual_process_id_tracker_handle_add_pid(
2685 tracker_handle,
2686 (pid_t) id);
2687 break;
2688 default:
2689 ret = LTTNG_ERR_INVALID;
2690 goto end;
2691 }
2692 }
2693 switch (status) {
2694 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
2695 continue;
2696 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID:
2697 ret = LTTNG_ERR_INVALID;
2698 break;
2699 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS:
2700 ret = LTTNG_ERR_PROCESS_ATTR_EXISTS;
2701 break;
2702 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING:
2703 ret = LTTNG_ERR_PROCESS_ATTR_MISSING;
2704 break;
2705 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR:
2706 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
2707 default:
2708 ret = LTTNG_ERR_UNK;
2709 goto end;
2710 }
2711 }
2712 node = pid_target_node;
2713 }
2714
2715end:
2716 lttng_process_attr_tracker_handle_destroy(tracker_handle);
2717 return ret;
2718 }
2719
55c9e7ca
JR
2720static int process_id_tracker_node(xmlNodePtr id_tracker_node,
2721 struct lttng_handle *handle,
159b042f 2722 enum lttng_process_attr process_attr)
847a5916 2723{
159b042f 2724 int ret = 0, child_count;
f7af9a72 2725 xmlNodePtr values_node = NULL;
847a5916 2726 xmlNodePtr node;
55c9e7ca
JR
2727 const char *element_id_tracker;
2728 const char *element_target_id;
2729 const char *element_id;
2730 const char *element_id_alias;
2731 const char *element_name;
159b042f
JG
2732 enum lttng_error_code tracker_handle_ret_code;
2733 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
2734 enum lttng_process_attr_tracker_handle_status status;
847a5916 2735
a0377dfe
FD
2736 LTTNG_ASSERT(handle);
2737 LTTNG_ASSERT(id_tracker_node);
55c9e7ca 2738
159b042f
JG
2739 tracker_handle_ret_code = lttng_session_get_tracker_handle(
2740 handle->session_name, handle->domain.type, process_attr,
2741 &tracker_handle);
2742 if (tracker_handle_ret_code != LTTNG_OK) {
2743 ret = LTTNG_ERR_INVALID;
2744 goto end;
2745 }
2746
2747 ret = get_tracker_elements(process_attr, &element_id_tracker,
55c9e7ca
JR
2748 &element_target_id, &element_id, &element_id_alias,
2749 &element_name);
2750 if (ret) {
159b042f 2751 goto end;
55c9e7ca
JR
2752 }
2753
f7af9a72 2754 /* get the values node */
55c9e7ca
JR
2755 for (node = xmlFirstElementChild(id_tracker_node); node;
2756 node = xmlNextElementSibling(node)) {
847a5916 2757 if (!strcmp((const char *) node->name,
159b042f 2758 config_element_process_attr_values)) {
f7af9a72 2759 values_node = node;
847a5916
JR
2760 break;
2761 }
2762 }
2763
f7af9a72 2764 if (!values_node) {
847a5916
JR
2765 ret = LTTNG_ERR_INVALID;
2766 goto end;
2767 }
2768
55c9e7ca 2769 /* Go through all id target node */
f7af9a72 2770 child_count = xmlChildElementCount(values_node);
159b042f
JG
2771 status = lttng_process_attr_tracker_handle_set_tracking_policy(
2772 tracker_handle,
2773 child_count == 0 ? LTTNG_TRACKING_POLICY_EXCLUDE_ALL :
2774 LTTNG_TRACKING_POLICY_INCLUDE_SET);
2775 if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
2776 ret = LTTNG_ERR_UNK;
2777 goto end;
847a5916 2778 }
159b042f
JG
2779
2780 /* Add all tracked values. */
f7af9a72 2781 for (node = xmlFirstElementChild(values_node); node;
847a5916 2782 node = xmlNextElementSibling(node)) {
55c9e7ca 2783 xmlNodePtr id_target_node = node;
847a5916 2784
55c9e7ca
JR
2785 /* get id node and track it */
2786 for (node = xmlFirstElementChild(id_target_node); node;
2787 node = xmlNextElementSibling(node)) {
2788 if (!strcmp((const char *) node->name, element_id) ||
2789 (element_id_alias &&
2790 !strcmp((const char *) node->name,
2791 element_id_alias))) {
2792 int64_t id;
159b042f 2793 xmlChar *content = xmlNodeGetContent(node);
847a5916 2794
847a5916
JR
2795 if (!content) {
2796 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2797 goto end;
2798 }
2799
55c9e7ca 2800 ret = parse_int(content, &id);
847a5916
JR
2801 free(content);
2802 if (ret) {
2803 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2804 goto end;
2805 }
2806
159b042f
JG
2807 switch (process_attr) {
2808 case LTTNG_PROCESS_ATTR_PROCESS_ID:
2809 status = lttng_process_attr_process_id_tracker_handle_add_pid(
2810 tracker_handle,
2811 (pid_t) id);
2812 break;
2813 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
2814 status = lttng_process_attr_virtual_process_id_tracker_handle_add_pid(
2815 tracker_handle,
2816 (pid_t) id);
2817 break;
2818 case LTTNG_PROCESS_ATTR_USER_ID:
2819 status = lttng_process_attr_user_id_tracker_handle_add_uid(
2820 tracker_handle,
2821 (uid_t) id);
2822 break;
2823 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
2824 status = lttng_process_attr_virtual_user_id_tracker_handle_add_uid(
2825 tracker_handle,
2826 (uid_t) id);
2827 break;
2828 case LTTNG_PROCESS_ATTR_GROUP_ID:
2829 status = lttng_process_attr_group_id_tracker_handle_add_gid(
2830 tracker_handle,
2831 (gid_t) id);
2832 break;
2833 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
2834 status = lttng_process_attr_virtual_group_id_tracker_handle_add_gid(
2835 tracker_handle,
2836 (gid_t) id);
2837 break;
2838 default:
2839 ret = LTTNG_ERR_INVALID;
55c9e7ca
JR
2840 goto end;
2841 }
159b042f
JG
2842 } else if (element_name &&
2843 !strcmp((const char *) node->name,
2844 element_name)) {
2845 xmlChar *content = xmlNodeGetContent(node);
55c9e7ca 2846
55c9e7ca
JR
2847 if (!content) {
2848 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2849 goto end;
2850 }
2d97a006 2851
159b042f
JG
2852 switch (process_attr) {
2853 case LTTNG_PROCESS_ATTR_USER_ID:
2854 status = lttng_process_attr_user_id_tracker_handle_add_user_name(
2855 tracker_handle,
2856 (const char *) content);
2857 break;
2858 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
2859 status = lttng_process_attr_virtual_user_id_tracker_handle_add_user_name(
2860 tracker_handle,
2861 (const char *) content);
2862 break;
2863 case LTTNG_PROCESS_ATTR_GROUP_ID:
2864 status = lttng_process_attr_group_id_tracker_handle_add_group_name(
2865 tracker_handle,
2866 (const char *) content);
2867 break;
2868 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
2869 status = lttng_process_attr_virtual_group_id_tracker_handle_add_group_name(
2870 tracker_handle,
2871 (const char *) content);
2872 break;
2873 default:
2874 free(content);
2875 ret = LTTNG_ERR_INVALID;
2d97a006
JR
2876 goto end;
2877 }
55c9e7ca 2878 free(content);
159b042f
JG
2879 }
2880 switch (status) {
2881 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
2882 continue;
2883 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID:
2884 ret = LTTNG_ERR_INVALID;
2885 break;
2886 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS:
2887 ret = LTTNG_ERR_PROCESS_ATTR_EXISTS;
2888 break;
2889 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING:
2890 ret = LTTNG_ERR_PROCESS_ATTR_MISSING;
2891 break;
2892 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR:
2893 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
2894 default:
2895 ret = LTTNG_ERR_UNK;
2896 goto end;
847a5916
JR
2897 }
2898 }
55c9e7ca 2899 node = id_target_node;
847a5916
JR
2900 }
2901
2902end:
159b042f 2903 lttng_process_attr_tracker_handle_destroy(tracker_handle);
847a5916
JR
2904 return ret;
2905}
2906
dcf266c0
JG
2907static
2908int process_domain_node(xmlNodePtr domain_node, const char *session_name)
2909{
2910 int ret;
3afa94ae 2911 struct lttng_domain domain {};
dcf266c0 2912 struct lttng_handle *handle = NULL;
4fc2b126 2913 struct lttng_channel *channel = NULL;
dcf266c0 2914 xmlNodePtr channels_node = NULL;
847a5916
JR
2915 xmlNodePtr trackers_node = NULL;
2916 xmlNodePtr pid_tracker_node = NULL;
55c9e7ca
JR
2917 xmlNodePtr vpid_tracker_node = NULL;
2918 xmlNodePtr uid_tracker_node = NULL;
2919 xmlNodePtr vuid_tracker_node = NULL;
2920 xmlNodePtr gid_tracker_node = NULL;
2921 xmlNodePtr vgid_tracker_node = NULL;
dcf266c0
JG
2922 xmlNodePtr node;
2923
a0377dfe 2924 LTTNG_ASSERT(session_name);
dcf266c0
JG
2925
2926 ret = init_domain(domain_node, &domain);
2927 if (ret) {
2928 goto end;
2929 }
2930
2931 handle = lttng_create_handle(session_name, &domain);
2932 if (!handle) {
2933 ret = -LTTNG_ERR_NOMEM;
2934 goto end;
2935 }
2936
2937 /* get the channels node */
2938 for (node = xmlFirstElementChild(domain_node); node;
2939 node = xmlNextElementSibling(node)) {
2940 if (!strcmp((const char *) node->name,
2941 config_element_channels)) {
2942 channels_node = node;
2943 break;
2944 }
2945 }
2946
2947 if (!channels_node) {
2948 goto end;
2949 }
2950
2951 /* create all channels */
2952 for (node = xmlFirstElementChild(channels_node); node;
2953 node = xmlNextElementSibling(node)) {
36d1687c 2954 const enum lttng_domain_type original_domain = domain.type;
dcf266c0
JG
2955 xmlNodePtr contexts_node = NULL;
2956 xmlNodePtr events_node = NULL;
2957 xmlNodePtr channel_attr_node;
2958
36d1687c
JG
2959 /*
2960 * Channels of the "agent" types cannot be created directly.
2961 * They are meant to be created implicitly through the
2962 * activation of events in their domain. However, a user
2963 * can override the default channel configuration attributes
2964 * by creating the underlying UST channel _before_ enabling
2965 * an agent domain event.
2966 *
2967 * Hence, the channel's type is substituted before the creation
2968 * and restored by the time the events are created.
2969 */
2970 switch (domain.type) {
2971 case LTTNG_DOMAIN_JUL:
2972 case LTTNG_DOMAIN_LOG4J:
2973 case LTTNG_DOMAIN_PYTHON:
2974 domain.type = LTTNG_DOMAIN_UST;
2975 default:
2976 break;
2977 }
2978
4fc2b126
JR
2979 channel = lttng_channel_create(&domain);
2980 if (!channel) {
2981 ret = -1;
2982 goto end;
2983 }
dcf266c0
JG
2984
2985 for (channel_attr_node = xmlFirstElementChild(node);
2986 channel_attr_node; channel_attr_node =
2987 xmlNextElementSibling(channel_attr_node)) {
2988 ret = process_channel_attr_node(channel_attr_node,
4fc2b126 2989 channel, &contexts_node, &events_node);
dcf266c0
JG
2990 if (ret) {
2991 goto end;
2992 }
2993 }
2994
4fc2b126 2995 ret = lttng_enable_channel(handle, channel);
dcf266c0
JG
2996 if (ret < 0) {
2997 goto end;
2998 }
2999
36d1687c
JG
3000 /* Restore the original channel domain. */
3001 domain.type = original_domain;
3002
4fc2b126 3003 ret = process_events_node(events_node, handle, channel->name);
dcf266c0
JG
3004 if (ret) {
3005 goto end;
3006 }
3007
3008 ret = process_contexts_node(contexts_node, handle,
4fc2b126 3009 channel->name);
dcf266c0
JG
3010 if (ret) {
3011 goto end;
3012 }
4fc2b126
JR
3013
3014 lttng_channel_destroy(channel);
dcf266c0 3015 }
4fc2b126 3016 channel = NULL;
847a5916
JR
3017
3018 /* get the trackers node */
3019 for (node = xmlFirstElementChild(domain_node); node;
3020 node = xmlNextElementSibling(node)) {
3021 if (!strcmp((const char *) node->name,
f7af9a72
JG
3022 config_element_process_attr_trackers) ||
3023 !strcmp((const char *) node->name,
3024 config_element_trackers_legacy)) {
3025 if (trackers_node) {
3026 ERR("Only one instance of `%s` or `%s` is allowed in a session configuration",
3027 config_element_process_attr_trackers,
3028 config_element_trackers_legacy);
3029 ret = -1;
3030 goto end;
3031 }
847a5916
JR
3032 trackers_node = node;
3033 break;
3034 }
3035 }
3036
3037 if (!trackers_node) {
3038 goto end;
3039 }
3040
3041 for (node = xmlFirstElementChild(trackers_node); node;
3042 node = xmlNextElementSibling(node)) {
55c9e7ca 3043 if (!strcmp((const char *) node->name,
159b042f 3044 config_element_process_attr_tracker_pid)) {
847a5916 3045 pid_tracker_node = node;
55c9e7ca 3046 ret = process_id_tracker_node(pid_tracker_node, handle,
159b042f 3047 LTTNG_PROCESS_ATTR_PROCESS_ID);
55c9e7ca
JR
3048 if (ret) {
3049 goto end;
3050 }
3051 }
3052 if (!strcmp((const char *) node->name,
159b042f 3053 config_element_process_attr_tracker_vpid)) {
55c9e7ca
JR
3054 vpid_tracker_node = node;
3055 ret = process_id_tracker_node(vpid_tracker_node, handle,
159b042f 3056 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
55c9e7ca
JR
3057 if (ret) {
3058 goto end;
3059 }
3060 }
3061 if (!strcmp((const char *) node->name,
159b042f 3062 config_element_process_attr_tracker_uid)) {
55c9e7ca
JR
3063 uid_tracker_node = node;
3064 ret = process_id_tracker_node(uid_tracker_node, handle,
159b042f 3065 LTTNG_PROCESS_ATTR_USER_ID);
55c9e7ca
JR
3066 if (ret) {
3067 goto end;
3068 }
3069 }
3070 if (!strcmp((const char *) node->name,
159b042f 3071 config_element_process_attr_tracker_vuid)) {
55c9e7ca
JR
3072 vuid_tracker_node = node;
3073 ret = process_id_tracker_node(vuid_tracker_node, handle,
159b042f 3074 LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
55c9e7ca
JR
3075 if (ret) {
3076 goto end;
3077 }
3078 }
3079 if (!strcmp((const char *) node->name,
159b042f 3080 config_element_process_attr_tracker_gid)) {
55c9e7ca
JR
3081 gid_tracker_node = node;
3082 ret = process_id_tracker_node(gid_tracker_node, handle,
159b042f 3083 LTTNG_PROCESS_ATTR_GROUP_ID);
55c9e7ca
JR
3084 if (ret) {
3085 goto end;
3086 }
3087 }
3088 if (!strcmp((const char *) node->name,
159b042f 3089 config_element_process_attr_tracker_vgid)) {
55c9e7ca
JR
3090 vgid_tracker_node = node;
3091 ret = process_id_tracker_node(vgid_tracker_node, handle,
159b042f 3092 LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
847a5916
JR
3093 if (ret) {
3094 goto end;
3095 }
3096 }
f7af9a72
JG
3097 if (!strcmp((const char *) node->name,
3098 config_element_pid_tracker_legacy)) {
3099 ret = process_legacy_pid_tracker_node(node, handle);
3100 if (ret) {
3101 goto end;
3102 }
3103 }
847a5916
JR
3104 }
3105
dcf266c0 3106end:
4fc2b126 3107 lttng_channel_destroy(channel);
dcf266c0
JG
3108 lttng_destroy_handle(handle);
3109 return ret;
3110}
3111
66ea93b1
JG
3112static
3113int add_periodic_rotation(const char *name, uint64_t time_us)
3114{
3115 int ret;
3116 enum lttng_rotation_status status;
3117 struct lttng_rotation_schedule *periodic =
3118 lttng_rotation_schedule_periodic_create();
3119
3120 if (!periodic) {
3121 ret = -LTTNG_ERR_NOMEM;
3122 goto error;
3123 }
3124
3125 status = lttng_rotation_schedule_periodic_set_period(periodic,
3126 time_us);
3127 if (status != LTTNG_ROTATION_STATUS_OK) {
3128 ret = -LTTNG_ERR_INVALID;
3129 goto error;
3130 }
3131
3132 status = lttng_session_add_rotation_schedule(name, periodic);
3133 switch (status) {
3134 case LTTNG_ROTATION_STATUS_OK:
ce6176f2 3135 ret = 0;
66ea93b1
JG
3136 break;
3137 case LTTNG_ROTATION_STATUS_SCHEDULE_ALREADY_SET:
3138 case LTTNG_ROTATION_STATUS_INVALID:
3139 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3140 break;
3141 default:
3142 ret = -LTTNG_ERR_UNK;
3143 break;
3144 }
3145error:
3146 lttng_rotation_schedule_destroy(periodic);
3147 return ret;
3148}
3149
3150static
3151int add_size_rotation(const char *name, uint64_t size_bytes)
3152{
3153 int ret;
3154 enum lttng_rotation_status status;
3155 struct lttng_rotation_schedule *size =
3156 lttng_rotation_schedule_size_threshold_create();
3157
3158 if (!size) {
3159 ret = -LTTNG_ERR_NOMEM;
3160 goto error;
3161 }
3162
3163 status = lttng_rotation_schedule_size_threshold_set_threshold(size,
3164 size_bytes);
3165 if (status != LTTNG_ROTATION_STATUS_OK) {
3166 ret = -LTTNG_ERR_INVALID;
3167 goto error;
3168 }
3169
3170 status = lttng_session_add_rotation_schedule(name, size);
3171 switch (status) {
3172 case LTTNG_ROTATION_STATUS_OK:
ce6176f2 3173 ret = 0;
66ea93b1
JG
3174 break;
3175 case LTTNG_ROTATION_STATUS_SCHEDULE_ALREADY_SET:
3176 case LTTNG_ROTATION_STATUS_INVALID:
3177 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3178 break;
3179 default:
3180 ret = -LTTNG_ERR_UNK;
3181 break;
3182 }
3183error:
3184 lttng_rotation_schedule_destroy(size);
3185 return ret;
3186}
3187
ce6176f2
JG
3188static
3189int process_session_rotation_schedules_node(
3190 xmlNodePtr schedules_node,
3191 uint64_t *rotation_timer_interval,
3192 uint64_t *rotation_size)
3193{
3194 int ret = 0;
3195 xmlNodePtr child;
3196
3197 for (child = xmlFirstElementChild(schedules_node);
3198 child;
3199 child = xmlNextElementSibling(child)) {
3200 if (!strcmp((const char *) child->name,
3201 config_element_rotation_schedule_periodic)) {
3202 xmlChar *content;
3203 xmlNodePtr time_us_node;
3204
3205 /* periodic rotation schedule */
3206 time_us_node = xmlFirstElementChild(child);
3207 if (!time_us_node ||
3208 strcmp((const char *) time_us_node->name,
3209 config_element_rotation_schedule_periodic_time_us)) {
3210 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3211 goto end;
3212 }
3213
3214 /* time_us child */
3215 content = xmlNodeGetContent(time_us_node);
3216 if (!content) {
3217 ret = -LTTNG_ERR_NOMEM;
3218 goto end;
3219 }
3220 ret = parse_uint(content, rotation_timer_interval);
3221 free(content);
3222 if (ret) {
3223 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3224 goto end;
3225 }
3226 } else if (!strcmp((const char *) child->name,
3227 config_element_rotation_schedule_size_threshold)) {
3228 xmlChar *content;
3229 xmlNodePtr bytes_node;
3230
3231 /* size_threshold rotation schedule */
3232 bytes_node = xmlFirstElementChild(child);
3233 if (!bytes_node ||
3234 strcmp((const char *) bytes_node->name,
3235 config_element_rotation_schedule_size_threshold_bytes)) {
3236 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3237 goto end;
3238 }
3239
3240 /* bytes child */
3241 content = xmlNodeGetContent(bytes_node);
3242 if (!content) {
3243 ret = -LTTNG_ERR_NOMEM;
3244 goto end;
3245 }
3246 ret = parse_uint(content, rotation_size);
3247 free(content);
3248 if (ret) {
3249 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3250 goto end;
3251 }
3252 }
3253 }
3254
3255end:
3256 return ret;
3257}
3258
dcf266c0
JG
3259static
3260int process_session_node(xmlNodePtr session_node, const char *session_name,
1b08cbce
JR
3261 int overwrite,
3262 const struct config_load_session_override_attr *overrides)
dcf266c0
JG
3263{
3264 int ret, started = -1, snapshot_mode = -1;
259c2674 3265 uint64_t live_timer_interval = UINT64_MAX,
90936dcf
JD
3266 rotation_timer_interval = 0,
3267 rotation_size = 0;
d324faf7 3268 xmlChar *name = NULL;
9e7c9f56 3269 xmlChar *shm_path = NULL;
dcf266c0
JG
3270 xmlNodePtr domains_node = NULL;
3271 xmlNodePtr output_node = NULL;
3272 xmlNodePtr node;
90936dcf 3273 xmlNodePtr attributes_child;
dcf266c0
JG
3274 struct lttng_domain *kernel_domain = NULL;
3275 struct lttng_domain *ust_domain = NULL;
3276 struct lttng_domain *jul_domain = NULL;
5cdb6027 3277 struct lttng_domain *log4j_domain = NULL;
0e115563 3278 struct lttng_domain *python_domain = NULL;
dcf266c0
JG
3279
3280 for (node = xmlFirstElementChild(session_node); node;
3281 node = xmlNextElementSibling(node)) {
3282 if (!name && !strcmp((const char *) node->name,
3283 config_element_name)) {
3284 /* name */
3285 xmlChar *node_content = xmlNodeGetContent(node);
3286 if (!node_content) {
3287 ret = -LTTNG_ERR_NOMEM;
c2da8cde 3288 goto error;
dcf266c0
JG
3289 }
3290
d324faf7 3291 name = node_content;
dcf266c0
JG
3292 } else if (!domains_node && !strcmp((const char *) node->name,
3293 config_element_domains)) {
3294 /* domains */
3295 domains_node = node;
3296 } else if (started == -1 && !strcmp((const char *) node->name,
3297 config_element_started)) {
3298 /* started */
3299 xmlChar *node_content = xmlNodeGetContent(node);
3300 if (!node_content) {
3301 ret = -LTTNG_ERR_NOMEM;
c2da8cde 3302 goto error;
dcf266c0
JG
3303 }
3304
3305 ret = parse_bool(node_content, &started);
3306 free(node_content);
3307 if (ret) {
3308 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
c2da8cde 3309 goto error;
dcf266c0
JG
3310 }
3311 } else if (!output_node && !strcmp((const char *) node->name,
3312 config_element_output)) {
3313 /* output */
3314 output_node = node;
9e7c9f56
JR
3315 } else if (!shm_path && !strcmp((const char *) node->name,
3316 config_element_shared_memory_path)) {
3317 /* shared memory path */
3318 xmlChar *node_content = xmlNodeGetContent(node);
3319 if (!node_content) {
3320 ret = -LTTNG_ERR_NOMEM;
3321 goto error;
3322 }
3323
3324 shm_path = node_content;
dcf266c0 3325 } else {
259c2674
JD
3326 /*
3327 * attributes, snapshot_mode, live_timer_interval, rotation_size,
90936dcf
JD
3328 * rotation_timer_interval.
3329 */
3330 for (attributes_child = xmlFirstElementChild(node); attributes_child;
3331 attributes_child = xmlNextElementSibling(attributes_child)) {
3332 if (!strcmp((const char *) attributes_child->name,
3333 config_element_snapshot_mode)) {
3334 /* snapshot_mode */
3335 xmlChar *snapshot_mode_content =
3336 xmlNodeGetContent(attributes_child);
3337 if (!snapshot_mode_content) {
3338 ret = -LTTNG_ERR_NOMEM;
3339 goto error;
3340 }
dcf266c0 3341
90936dcf
JD
3342 ret = parse_bool(snapshot_mode_content, &snapshot_mode);
3343 free(snapshot_mode_content);
3344 if (ret) {
3345 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3346 goto error;
3347 }
3348 } else if (!strcmp((const char *) attributes_child->name,
3349 config_element_live_timer_interval)) {
3350 /* live_timer_interval */
3351 xmlChar *timer_interval_content =
3352 xmlNodeGetContent(attributes_child);
3353 if (!timer_interval_content) {
3354 ret = -LTTNG_ERR_NOMEM;
3355 goto error;
3356 }
dcf266c0 3357
90936dcf
JD
3358 ret = parse_uint(timer_interval_content, &live_timer_interval);
3359 free(timer_interval_content);
3360 if (ret) {
3361 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3362 goto error;
3363 }
ce6176f2
JG
3364 } else if (!strcmp((const char *) attributes_child->name,
3365 config_element_rotation_schedules)) {
3366 ret = process_session_rotation_schedules_node(
3367 attributes_child,
3368 &rotation_timer_interval,
3369 &rotation_size);
90936dcf
JD
3370 if (ret) {
3371 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3372 goto error;
3373 }
259c2674 3374
259c2674
JD
3375 }
3376 }
dcf266c0
JG
3377 }
3378 }
3379
3380 if (!name) {
3381 /* Mandatory attribute, as defined in the session XSD */
3382 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
c2da8cde 3383 goto error;
dcf266c0
JG
3384 }
3385
d324faf7 3386 if (session_name && strcmp((char *) name, session_name)) {
dcf266c0 3387 /* This is not the session we are looking for */
c2da8cde
DG
3388 ret = -LTTNG_ERR_NO_SESSION;
3389 goto error;
dcf266c0
JG
3390 }
3391
3392 /* Init domains to create the session handles */
3393 for (node = xmlFirstElementChild(domains_node); node;
3394 node = xmlNextElementSibling(node)) {
64803277 3395 lttng_domain *domain = zmalloc<lttng_domain>();
dcf266c0 3396
dcf266c0
JG
3397 if (!domain) {
3398 ret = -LTTNG_ERR_NOMEM;
c2da8cde 3399 goto error;
dcf266c0
JG
3400 }
3401
3402 ret = init_domain(node, domain);
3403 if (ret) {
3404 goto domain_init_error;
3405 }
3406
3407 switch (domain->type) {
3408 case LTTNG_DOMAIN_KERNEL:
c33e6729
DG
3409 if (kernel_domain) {
3410 /* Same domain seen twice, invalid! */
3411 goto domain_init_error;
3412 }
dcf266c0
JG
3413 kernel_domain = domain;
3414 break;
3415 case LTTNG_DOMAIN_UST:
c33e6729
DG
3416 if (ust_domain) {
3417 /* Same domain seen twice, invalid! */
3418 goto domain_init_error;
3419 }
dcf266c0
JG
3420 ust_domain = domain;
3421 break;
3422 case LTTNG_DOMAIN_JUL:
c33e6729
DG
3423 if (jul_domain) {
3424 /* Same domain seen twice, invalid! */
3425 goto domain_init_error;
3426 }
dcf266c0
JG
3427 jul_domain = domain;
3428 break;
5cdb6027
DG
3429 case LTTNG_DOMAIN_LOG4J:
3430 if (log4j_domain) {
3431 /* Same domain seen twice, invalid! */
3432 goto domain_init_error;
3433 }
3434 log4j_domain = domain;
3435 break;
0e115563
DG
3436 case LTTNG_DOMAIN_PYTHON:
3437 if (python_domain) {
3438 /* Same domain seen twice, invalid! */
3439 goto domain_init_error;
3440 }
3441 python_domain = domain;
3442 break;
dcf266c0
JG
3443 default:
3444 WARN("Invalid domain type");
3445 goto domain_init_error;
3446 }
3447 continue;
3448domain_init_error:
3449 free(domain);
3450 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
c2da8cde 3451 goto error;
dcf266c0
JG
3452 }
3453
2aaf5fc7
JR
3454 /* Apply overrides */
3455 if (overrides) {
3456 if (overrides->session_name) {
3457 xmlChar *name_override = xmlStrdup(BAD_CAST(overrides->session_name));
3458 if (!name_override) {
3459 ret = -LTTNG_ERR_NOMEM;
3460 goto error;
3461 }
3462
3463 /* Overrides the session name to the provided name */
3464 xmlFree(name);
3465 name = name_override;
3466 }
3467 }
3468
40b4155f 3469 if (overwrite) {
dcf266c0 3470 /* Destroy session if it exists */
d324faf7 3471 ret = lttng_destroy_session((const char *) name);
dcf266c0
JG
3472 if (ret && ret != -LTTNG_ERR_SESS_NOT_FOUND) {
3473 ERR("Failed to destroy existing session.");
c2da8cde 3474 goto error;
dcf266c0
JG
3475 }
3476 }
3477
3478 /* Create session type depending on output type */
3479 if (snapshot_mode && snapshot_mode != -1) {
1b08cbce
JR
3480 ret = create_snapshot_session((const char *) name, output_node,
3481 overrides);
dcf266c0
JG
3482 } else if (live_timer_interval &&
3483 live_timer_interval != UINT64_MAX) {
194dfca0 3484 ret = create_session((const char *) name,
1b08cbce 3485 output_node, live_timer_interval, overrides);
dcf266c0
JG
3486 } else {
3487 /* regular session */
194dfca0 3488 ret = create_session((const char *) name,
1b08cbce 3489 output_node, UINT64_MAX, overrides);
dcf266c0 3490 }
dcf266c0 3491 if (ret) {
c2da8cde 3492 goto error;
dcf266c0
JG
3493 }
3494
9e7c9f56
JR
3495 if (shm_path) {
3496 ret = lttng_set_session_shm_path((const char *) name,
d324faf7 3497 (const char *) shm_path);
9e7c9f56
JR
3498 if (ret) {
3499 goto error;
3500 }
3501 }
3502
dcf266c0
JG
3503 for (node = xmlFirstElementChild(domains_node); node;
3504 node = xmlNextElementSibling(node)) {
d324faf7 3505 ret = process_domain_node(node, (const char *) name);
dcf266c0
JG
3506 if (ret) {
3507 goto end;
3508 }
3509 }
3510
66ea93b1
JG
3511 if (rotation_timer_interval) {
3512 ret = add_periodic_rotation((const char *) name,
3513 rotation_timer_interval);
3514 if (ret < 0) {
259c2674
JD
3515 goto error;
3516 }
66ea93b1
JG
3517 }
3518 if (rotation_size) {
3519 ret = add_size_rotation((const char *) name,
dbd512ea 3520 rotation_size);
66ea93b1 3521 if (ret < 0) {
259c2674
JD
3522 goto error;
3523 }
3524 }
3525
dcf266c0 3526 if (started) {
d324faf7 3527 ret = lttng_start_tracing((const char *) name);
dcf266c0
JG
3528 if (ret) {
3529 goto end;
3530 }
3531 }
c2da8cde 3532
dcf266c0 3533end:
b2579dc1 3534 if (ret < 0) {
d324faf7
JG
3535 ERR("Failed to load session %s: %s", (const char *) name,
3536 lttng_strerror(ret));
3537 lttng_destroy_session((const char *) name);
b2579dc1
JG
3538 }
3539
c2da8cde 3540error:
dcf266c0
JG
3541 free(kernel_domain);
3542 free(ust_domain);
3543 free(jul_domain);
5cdb6027 3544 free(log4j_domain);
135a3893 3545 free(python_domain);
d324faf7 3546 xmlFree(name);
9e7c9f56 3547 xmlFree(shm_path);
dcf266c0
JG
3548 return ret;
3549}
3550
cf53c06d
DG
3551/*
3552 * Return 1 if the given path is readable by the current UID or 0 if not.
3553 * Return -1 if the path is EPERM.
3554 */
3555static int validate_file_read_creds(const char *path)
3556{
3557 int ret;
3558
a0377dfe 3559 LTTNG_ASSERT(path);
cf53c06d
DG
3560
3561 /* Can we read the file. */
3562 ret = access(path, R_OK);
3563 if (!ret) {
3564 goto valid;
3565 }
3566 if (errno == EACCES) {
3567 return -1;
3568 } else {
3569 /* Invalid. */
3570 return 0;
3571 }
3572valid:
3573 return 1;
3574}
3575
dcf266c0
JG
3576static
3577int load_session_from_file(const char *path, const char *session_name,
1b08cbce
JR
3578 struct session_config_validation_ctx *validation_ctx, int overwrite,
3579 const struct config_load_session_override_attr *overrides)
dcf266c0
JG
3580{
3581 int ret, session_found = !session_name;
3582 xmlDocPtr doc = NULL;
3583 xmlNodePtr sessions_node;
3584 xmlNodePtr session_node;
dcf266c0 3585
a0377dfe
FD
3586 LTTNG_ASSERT(path);
3587 LTTNG_ASSERT(validation_ctx);
dcf266c0 3588
cf53c06d
DG
3589 ret = validate_file_read_creds(path);
3590 if (ret != 1) {
3591 if (ret == -1) {
3592 ret = -LTTNG_ERR_EPERM;
3593 } else {
3594 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
3595 }
dcf266c0
JG
3596 goto end;
3597 }
3598
3599 doc = xmlParseFile(path);
3600 if (!doc) {
3601 ret = -LTTNG_ERR_LOAD_IO_FAIL;
3602 goto end;
3603 }
3604
3605 ret = xmlSchemaValidateDoc(validation_ctx->schema_validation_ctx, doc);
3606 if (ret) {
3607 ERR("Session configuration file validation failed");
3608 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3609 goto end;
3610 }
3611
3612 sessions_node = xmlDocGetRootElement(doc);
3613 if (!sessions_node) {
55c9e7ca 3614 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
dcf266c0
JG
3615 goto end;
3616 }
3617
3618 for (session_node = xmlFirstElementChild(sessions_node);
3619 session_node; session_node =
3620 xmlNextElementSibling(session_node)) {
3621 ret = process_session_node(session_node,
1b08cbce 3622 session_name, overwrite, overrides);
317ea246
JG
3623 if (!session_name && ret) {
3624 /* Loading error occurred. */
3625 goto end;
3626 } else if (session_name) {
3627 if (ret == 0) {
3628 /* Target session found and loaded */
3629 session_found = 1;
3630 break;
3631 } else if (ret == -LTTNG_ERR_NO_SESSION) {
3632 /*
3633 * Ignore this error, we are looking for a
3634 * specific session.
3635 */
3636 ret = 0;
3637 } else {
3638 /* Loading error occurred. */
3639 goto end;
3640 }
dcf266c0
JG
3641 }
3642 }
3643end:
3644 xmlFreeDoc(doc);
3645 if (!ret) {
a96bc65d 3646 ret = session_found ? 0 : -LTTNG_ERR_LOAD_SESSION_NOENT;
dcf266c0
JG
3647 }
3648 return ret;
3649}
3650
3651static
3652int load_session_from_path(const char *path, const char *session_name,
1b08cbce
JR
3653 struct session_config_validation_ctx *validation_ctx, int overwrite,
3654 const struct config_load_session_override_attr *overrides)
dcf266c0
JG
3655{
3656 int ret, session_found = !session_name;
dcf266c0 3657 DIR *directory = NULL;
cce35f91
JG
3658 struct lttng_dynamic_buffer file_path;
3659 size_t path_len;
dcf266c0 3660
a0377dfe
FD
3661 LTTNG_ASSERT(path);
3662 LTTNG_ASSERT(validation_ctx);
cce35f91
JG
3663 path_len = strlen(path);
3664 lttng_dynamic_buffer_init(&file_path);
3665 if (path_len >= LTTNG_PATH_MAX) {
3666 ERR("Session configuration load path \"%s\" length (%zu) exceeds the maximal length allowed (%d)",
3667 path, path_len, LTTNG_PATH_MAX);
3668 ret = -LTTNG_ERR_INVALID;
3669 goto end;
3670 }
dcf266c0 3671
4af16958
DG
3672 directory = opendir(path);
3673 if (!directory) {
11143783
DG
3674 switch (errno) {
3675 case ENOTDIR:
0f0a81b5
DG
3676 /* Try the file loading. */
3677 break;
11143783
DG
3678 case ENOENT:
3679 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
3680 goto end;
3681 default:
0f0a81b5
DG
3682 ret = -LTTNG_ERR_LOAD_IO_FAIL;
3683 goto end;
4af16958 3684 }
dcf266c0 3685 }
4af16958 3686 if (directory) {
cce35f91 3687 size_t file_path_root_len;
dcf266c0 3688
cce35f91
JG
3689 ret = lttng_dynamic_buffer_set_capacity(&file_path,
3690 LTTNG_PATH_MAX);
3691 if (ret) {
3692 ret = -LTTNG_ERR_NOMEM;
dcf266c0
JG
3693 goto end;
3694 }
3695
cce35f91
JG
3696 ret = lttng_dynamic_buffer_append(&file_path, path, path_len);
3697 if (ret) {
dcf266c0 3698 ret = -LTTNG_ERR_NOMEM;
dcf266c0
JG
3699 goto end;
3700 }
3701
cce35f91
JG
3702 if (file_path.data[file_path.size - 1] != '/') {
3703 ret = lttng_dynamic_buffer_append(&file_path, "/", 1);
3704 if (ret) {
3705 ret = -LTTNG_ERR_NOMEM;
3706 goto end;
3707 }
dcf266c0 3708 }
cce35f91 3709 file_path_root_len = file_path.size;
dcf266c0
JG
3710
3711 /* Search for *.lttng files */
9a2df626
MJ
3712 for (;;) {
3713 size_t file_name_len;
3714 struct dirent *result;
3715
3716 /*
3717 * When the end of the directory stream is reached, NULL
3718 * is returned and errno is kept unchanged. When an
3719 * error occurs, NULL is returned and errno is set
3720 * accordingly. To distinguish between the two, set
3721 * errno to zero before calling readdir().
3722 *
3723 * On success, readdir() returns a pointer to a dirent
3724 * structure. This structure may be statically
3725 * allocated, do not attempt to free(3) it.
3726 */
3727 errno = 0;
3728 result = readdir(directory);
3729
ff86d8d0 3730 /* Reached end of dir stream or error out. */
9a2df626
MJ
3731 if (!result) {
3732 if (errno) {
3733 PERROR("Failed to enumerate the contents of path \"%s\" while loading session, readdir returned", path);
3734 ret = -LTTNG_ERR_LOAD_IO_FAIL;
3735 goto end;
3736 }
3737 break;
3738 }
3739
3740 file_name_len = strlen(result->d_name);
dcf266c0
JG
3741
3742 if (file_name_len <=
3743 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION)) {
3744 continue;
3745 }
3746
cce35f91
JG
3747 if (file_path.size + file_name_len >= LTTNG_PATH_MAX) {
3748 WARN("Ignoring file \"%s\" since the path's length (%zu) would exceed the maximal permitted size (%d)",
3749 result->d_name,
3750 /* +1 to account for NULL terminator. */
3751 file_path.size + file_name_len + 1,
3752 LTTNG_PATH_MAX);
dcf266c0
JG
3753 continue;
3754 }
3755
cce35f91 3756 /* Does the file end with .lttng? */
dcf266c0 3757 if (strcmp(DEFAULT_SESSION_CONFIG_FILE_EXTENSION,
cce35f91
JG
3758 result->d_name + file_name_len - sizeof(
3759 DEFAULT_SESSION_CONFIG_FILE_EXTENSION) + 1)) {
dcf266c0
JG
3760 continue;
3761 }
3762
cce35f91
JG
3763 ret = lttng_dynamic_buffer_append(&file_path, result->d_name,
3764 file_name_len + 1);
3765 if (ret) {
3766 ret = -LTTNG_ERR_NOMEM;
3767 goto end;
3768 }
dcf266c0 3769
cce35f91 3770 ret = load_session_from_file(file_path.data, session_name,
1b08cbce 3771 validation_ctx, overwrite, overrides);
55c9e7ca
JR
3772 if (session_name &&
3773 (!ret || ret != -LTTNG_ERR_LOAD_SESSION_NOENT)) {
dcf266c0
JG
3774 session_found = 1;
3775 break;
3776 }
55c9e7ca
JR
3777 if (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT) {
3778 goto end;
3779 }
cce35f91
JG
3780 /*
3781 * Reset the buffer's size to the location of the
3782 * path's trailing '/'.
3783 */
3784 ret = lttng_dynamic_buffer_set_size(&file_path,
3785 file_path_root_len);
3786 if (ret) {
3787 ret = -LTTNG_ERR_UNK;
3788 goto end;
3789 }
dcf266c0 3790 }
dcf266c0
JG
3791 } else {
3792 ret = load_session_from_file(path, session_name,
1b08cbce 3793 validation_ctx, overwrite, overrides);
dcf266c0
JG
3794 if (ret) {
3795 goto end;
dcf266c0 3796 }
55c9e7ca 3797 session_found = 1;
dcf266c0
JG
3798 }
3799
55c9e7ca 3800 ret = 0;
dcf266c0
JG
3801end:
3802 if (directory) {
3803 if (closedir(directory)) {
3804 PERROR("closedir");
3805 }
3806 }
55c9e7ca
JR
3807 if (!ret && !session_found) {
3808 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
dcf266c0 3809 }
cce35f91 3810 lttng_dynamic_buffer_reset(&file_path);
dcf266c0
JG
3811 return ret;
3812}
3813
ab38c13f
DG
3814/*
3815 * Validate that the given path's credentials and the current process have the
cf53c06d 3816 * same UID. If so, return 1 else return 0 if it does NOT match.
ab38c13f
DG
3817 */
3818static int validate_path_creds(const char *path)
3819{
3820 int ret, uid = getuid();
3821 struct stat buf;
3822
a0377dfe 3823 LTTNG_ASSERT(path);
ab38c13f 3824
cf53c06d 3825 if (uid == 0) {
ab38c13f
DG
3826 goto valid;
3827 }
3828
3829 ret = stat(path, &buf);
3830 if (ret < 0) {
3831 if (errno != ENOENT) {
3832 PERROR("stat");
3833 }
ab38c13f
DG
3834 goto valid;
3835 }
3836
3837 if (buf.st_uid != uid) {
3838 goto invalid;
3839 }
3840
3841valid:
ab38c13f 3842 return 1;
cf53c06d
DG
3843invalid:
3844 return 0;
ab38c13f
DG
3845}
3846
dcf266c0 3847int config_load_session(const char *path, const char *session_name,
1b08cbce
JR
3848 int overwrite, unsigned int autoload,
3849 const struct config_load_session_override_attr *overrides)
dcf266c0
JG
3850{
3851 int ret;
6c66fa0f 3852 bool session_loaded = false;
cf53c06d 3853 const char *path_ptr = NULL;
1c9a0b0e 3854 struct session_config_validation_ctx validation_ctx = {};
dcf266c0
JG
3855
3856 ret = init_session_config_validation_ctx(&validation_ctx);
3857 if (ret) {
3858 goto end;
3859 }
3860
3861 if (!path) {
4f00620d 3862 const char *home_path;
ab38c13f
DG
3863 const char *sys_path;
3864
dcf266c0 3865 /* Try home path */
ab38c13f 3866 home_path = utils_get_home_dir();
dcf266c0 3867 if (home_path) {
db8196db 3868 char path_buf[PATH_MAX];
dcf266c0 3869
d4fcf703
DG
3870 /*
3871 * Try user session configuration path. Ignore error here so we can
3872 * continue loading the system wide sessions.
3873 */
ab38c13f 3874 if (autoload) {
db8196db
SM
3875 ret = snprintf(path_buf, sizeof(path_buf),
3876 DEFAULT_SESSION_HOME_CONFIGPATH
3877 "/" DEFAULT_SESSION_CONFIG_AUTOLOAD,
3878 home_path);
cf53c06d
DG
3879 if (ret < 0) {
3880 PERROR("snprintf session autoload home config path");
55c9e7ca 3881 ret = -LTTNG_ERR_INVALID;
cf53c06d
DG
3882 goto end;
3883 }
3884
3885 /*
3886 * Credentials are only validated for the autoload in order to
3887 * avoid any user session daemon to try to load kernel sessions
3888 * automatically and failing all the times.
3889 */
db8196db 3890 ret = validate_path_creds(path_buf);
cf53c06d 3891 if (ret) {
db8196db 3892 path_ptr = path_buf;
cf53c06d 3893 }
ab38c13f 3894 } else {
db8196db
SM
3895 ret = snprintf(path_buf, sizeof(path_buf),
3896 DEFAULT_SESSION_HOME_CONFIGPATH,
3897 home_path);
cf53c06d
DG
3898 if (ret < 0) {
3899 PERROR("snprintf session home config path");
55c9e7ca 3900 ret = -LTTNG_ERR_INVALID;
cf53c06d
DG
3901 goto end;
3902 }
db8196db 3903 path_ptr = path_buf;
ab38c13f 3904 }
cf53c06d
DG
3905 if (path_ptr) {
3906 ret = load_session_from_path(path_ptr, session_name,
1b08cbce 3907 &validation_ctx, overwrite, overrides);
d4fcf703
DG
3908 if (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT) {
3909 goto end;
3910 }
3911 /*
3912 * Continue even if the session was found since we have to try
3913 * the system wide sessions.
3914 */
6c66fa0f 3915 session_loaded = true;
ab38c13f 3916 }
d4fcf703 3917 }
ab38c13f 3918
cf53c06d
DG
3919 /* Reset path pointer for the system wide dir. */
3920 path_ptr = NULL;
3921
d4fcf703
DG
3922 /* Try system wide configuration directory. */
3923 if (autoload) {
3924 sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH "/"
3925 DEFAULT_SESSION_CONFIG_AUTOLOAD;
cf53c06d
DG
3926 ret = validate_path_creds(sys_path);
3927 if (ret) {
3928 path_ptr = sys_path;
3929 }
d4fcf703 3930 } else {
cf53c06d
DG
3931 sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH;
3932 path_ptr = sys_path;
d4fcf703
DG
3933 }
3934
cf53c06d
DG
3935 if (path_ptr) {
3936 ret = load_session_from_path(path_ptr, session_name,
1b08cbce 3937 &validation_ctx, overwrite, overrides);
6c66fa0f
JG
3938 if (!ret) {
3939 session_loaded = true;
3940 }
55c9e7ca
JR
3941 } else {
3942 ret = 0;
dcf266c0
JG
3943 }
3944 } else {
3945 ret = access(path, F_OK);
3946 if (ret < 0) {
3947 PERROR("access");
3948 switch (errno) {
3949 case ENOENT:
3950 ret = -LTTNG_ERR_INVALID;
3951 WARN("Session configuration path does not exist.");
3952 break;
3953 case EACCES:
3954 ret = -LTTNG_ERR_EPERM;
3955 break;
3956 default:
3957 ret = -LTTNG_ERR_UNK;
3958 break;
3959 }
3960 goto end;
3961 }
3962
3963 ret = load_session_from_path(path, session_name,
1b08cbce 3964 &validation_ctx, overwrite, overrides);
dcf266c0
JG
3965 }
3966end:
3967 fini_session_config_validation_ctx(&validation_ctx);
d2b6efff
JG
3968 if (ret == -LTTNG_ERR_LOAD_SESSION_NOENT && !session_name && !path) {
3969 /*
3970 * Don't report an error if no sessions are found when called
3971 * without a session_name or a search path.
3972 */
3973 ret = 0;
3974 }
6c66fa0f
JG
3975
3976 if (session_loaded && ret == -LTTNG_ERR_LOAD_SESSION_NOENT) {
3977 /* A matching session was found in one of the search paths. */
3978 ret = 0;
3979 }
dcf266c0
JG
3980 return ret;
3981}
56766c75
JG
3982
3983static
3984void __attribute__((destructor)) session_config_exit(void)
3985{
3986 xmlCleanupParser();
3987}
This page took 0.257829 seconds and 4 git commands to generate.