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