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