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