Fix: UTF-8 characters may be stored on up to 4 bytes
[lttng-tools.git] / src / bin / lttng-sessiond / save.c
CommitLineData
fb198a11
JG
1/*
2 * Copyright (C) 2014 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18#define _GNU_SOURCE
6c1c0768 19#define _LGPL_SOURCE
fb198a11
JG
20#include <assert.h>
21#include <inttypes.h>
22#include <string.h>
23#include <urcu/uatomic.h>
24#include <unistd.h>
25
26#include <common/defaults.h>
27#include <common/error.h>
28#include <common/config/config.h>
fb198a11
JG
29#include <common/utils.h>
30#include <common/runas.h>
31#include <lttng/save-internal.h>
32
847a5916 33#include "kernel.h"
fb198a11
JG
34#include "save.h"
35#include "session.h"
0de3eda1 36#include "syscall.h"
fb198a11
JG
37#include "trace-ust.h"
38
39static
40int save_kernel_channel_attributes(struct config_writer *writer,
41 struct lttng_channel_attr *attr)
42{
43 int ret;
44
45 ret = config_writer_write_element_string(writer,
46 config_element_overwrite_mode,
47 attr->overwrite ? config_overwrite_mode_overwrite :
48 config_overwrite_mode_discard);
49 if (ret) {
50 goto end;
51 }
52
53 ret = config_writer_write_element_unsigned_int(writer,
54 config_element_subbuf_size, attr->subbuf_size);
55 if (ret) {
56 goto end;
57 }
58
59 ret = config_writer_write_element_unsigned_int(writer,
60 config_element_num_subbuf,
61 attr->num_subbuf);
62 if (ret) {
63 goto end;
64 }
65
66 ret = config_writer_write_element_unsigned_int(writer,
67 config_element_switch_timer_interval,
68 attr->switch_timer_interval);
69 if (ret) {
70 goto end;
71 }
72
73 ret = config_writer_write_element_unsigned_int(writer,
74 config_element_read_timer_interval,
75 attr->read_timer_interval);
76 if (ret) {
77 goto end;
78 }
79
80 ret = config_writer_write_element_string(writer,
81 config_element_output_type,
82 attr->output == LTTNG_EVENT_SPLICE ?
83 config_output_type_splice : config_output_type_mmap);
84 if (ret) {
85 goto end;
86 }
87
88 ret = config_writer_write_element_unsigned_int(writer,
89 config_element_tracefile_size, attr->tracefile_size);
90 if (ret) {
91 goto end;
92 }
93
94 ret = config_writer_write_element_unsigned_int(writer,
95 config_element_tracefile_count,
96 attr->tracefile_count);
97 if (ret) {
98 goto end;
99 }
100
101 ret = config_writer_write_element_unsigned_int(writer,
102 config_element_live_timer_interval,
103 attr->live_timer_interval);
104 if (ret) {
105 goto end;
106 }
107end:
108 return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0;
109}
110
111static
112int save_ust_channel_attributes(struct config_writer *writer,
113 struct lttng_ust_channel_attr *attr)
114{
115 int ret;
116
117 ret = config_writer_write_element_string(writer,
118 config_element_overwrite_mode,
119 attr->overwrite ? config_overwrite_mode_overwrite :
120 config_overwrite_mode_discard);
121 if (ret) {
122 goto end;
123 }
124
125 ret = config_writer_write_element_unsigned_int(writer,
126 config_element_subbuf_size, attr->subbuf_size);
127 if (ret) {
128 goto end;
129 }
130
131 ret = config_writer_write_element_unsigned_int(writer,
132 config_element_num_subbuf,
133 attr->num_subbuf);
134 if (ret) {
135 goto end;
136 }
137
138 ret = config_writer_write_element_unsigned_int(writer,
139 config_element_switch_timer_interval,
140 attr->switch_timer_interval);
141 if (ret) {
142 goto end;
143 }
144
145 ret = config_writer_write_element_unsigned_int(writer,
146 config_element_read_timer_interval,
147 attr->read_timer_interval);
148 if (ret) {
149 goto end;
150 }
151
152 ret = config_writer_write_element_string(writer,
153 config_element_output_type,
154 attr->output == LTTNG_UST_MMAP ?
155 config_output_type_mmap : config_output_type_splice);
156 if (ret) {
157 goto end;
158 }
159end:
160 return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0;
161}
162
163static
164const char *get_kernel_instrumentation_string(
165 enum lttng_kernel_instrumentation instrumentation)
166{
167 const char *instrumentation_string;
168
169 switch (instrumentation) {
170 case LTTNG_KERNEL_ALL:
171 instrumentation_string = config_event_type_all;
172 break;
173 case LTTNG_KERNEL_TRACEPOINT:
174 instrumentation_string = config_event_type_tracepoint;
175 break;
176 case LTTNG_KERNEL_KPROBE:
177 instrumentation_string = config_event_type_kprobe;
178 break;
179 case LTTNG_KERNEL_FUNCTION:
180 instrumentation_string = config_event_type_function;
181 break;
182 case LTTNG_KERNEL_KRETPROBE:
183 instrumentation_string = config_event_type_kretprobe;
184 break;
185 case LTTNG_KERNEL_NOOP:
186 instrumentation_string = config_event_type_noop;
187 break;
188 case LTTNG_KERNEL_SYSCALL:
189 instrumentation_string = config_event_type_syscall;
190 break;
191 default:
192 instrumentation_string = NULL;
193 }
194
195 return instrumentation_string;
196}
197
198static
199const char *get_kernel_context_type_string(
200 enum lttng_kernel_context_type context_type)
201{
202 const char *context_type_string;
203
204 switch (context_type) {
205 case LTTNG_KERNEL_CONTEXT_PID:
206 context_type_string = config_event_context_pid;
207 break;
208 case LTTNG_KERNEL_CONTEXT_PROCNAME:
209 context_type_string = config_event_context_procname;
210 break;
211 case LTTNG_KERNEL_CONTEXT_PRIO:
212 context_type_string = config_event_context_prio;
213 break;
214 case LTTNG_KERNEL_CONTEXT_NICE:
215 context_type_string = config_event_context_nice;
216 break;
217 case LTTNG_KERNEL_CONTEXT_VPID:
218 context_type_string = config_event_context_vpid;
219 break;
220 case LTTNG_KERNEL_CONTEXT_TID:
221 context_type_string = config_event_context_tid;
222 break;
223 case LTTNG_KERNEL_CONTEXT_VTID:
224 context_type_string = config_event_context_vtid;
225 break;
226 case LTTNG_KERNEL_CONTEXT_PPID:
227 context_type_string = config_event_context_ppid;
228 break;
229 case LTTNG_KERNEL_CONTEXT_VPPID:
230 context_type_string = config_event_context_vppid;
231 break;
232 case LTTNG_KERNEL_CONTEXT_HOSTNAME:
233 context_type_string = config_event_context_hostname;
234 break;
235 default:
236 context_type_string = NULL;
237 }
238
239 return context_type_string;
240}
241
242static
243const char *get_ust_context_type_string(
244 enum lttng_ust_context_type context_type)
245{
246 const char *context_type_string;
247
248 switch (context_type) {
249 case LTTNG_UST_CONTEXT_PROCNAME:
250 context_type_string = config_event_context_procname;
251 break;
252 case LTTNG_UST_CONTEXT_VPID:
253 context_type_string = config_event_context_vpid;
254 break;
255 case LTTNG_UST_CONTEXT_VTID:
256 context_type_string = config_event_context_vtid;
257 break;
258 case LTTNG_UST_CONTEXT_IP:
259 context_type_string = config_event_context_ip;
260 break;
261 case LTTNG_UST_CONTEXT_PTHREAD_ID:
262 context_type_string = config_event_context_pthread_id;
263 break;
e885a367 264 case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER:
14ce5bd8
JG
265 /*
266 * Error, should not be stored in the XML, perf contexts
267 * are stored as a node of type event_perf_context_type.
268 */
fb198a11
JG
269 default:
270 context_type_string = NULL;
e885a367 271 break;
fb198a11
JG
272 }
273
274 return context_type_string;
275}
276
277static
278const char *get_buffer_type_string(
279 enum lttng_buffer_type buffer_type)
280{
281 const char *buffer_type_string;
282
283 switch (buffer_type) {
284 case LTTNG_BUFFER_PER_PID:
285 buffer_type_string = config_buffer_type_per_pid;
286 break;
287 case LTTNG_BUFFER_PER_UID:
288 buffer_type_string = config_buffer_type_per_uid;
289 break;
290 case LTTNG_BUFFER_GLOBAL:
291 buffer_type_string = config_buffer_type_global;
292 break;
293 default:
294 buffer_type_string = NULL;
295 }
296
297 return buffer_type_string;
298}
299
300static
301const char *get_loglevel_type_string(
302 enum lttng_ust_loglevel_type loglevel_type)
303{
304 const char *loglevel_type_string;
305
306 switch (loglevel_type) {
307 case LTTNG_UST_LOGLEVEL_ALL:
308 loglevel_type_string = config_loglevel_type_all;
309 break;
310 case LTTNG_UST_LOGLEVEL_RANGE:
311 loglevel_type_string = config_loglevel_type_range;
312 break;
313 case LTTNG_UST_LOGLEVEL_SINGLE:
314 loglevel_type_string = config_loglevel_type_single;
315 break;
316 default:
317 loglevel_type_string = NULL;
318 }
319
320 return loglevel_type_string;
321}
322
323static
324int save_kernel_event(struct config_writer *writer,
325 struct ltt_kernel_event *event)
326{
327 int ret;
328 const char *instrumentation_type;
329
330 ret = config_writer_open_element(writer, config_element_event);
331 if (ret) {
332 ret = LTTNG_ERR_SAVE_IO_FAIL;
333 goto end;
334 }
335
336 if (event->event->name[0]) {
337 ret = config_writer_write_element_string(writer,
338 config_element_name, event->event->name);
339 if (ret) {
340 ret = LTTNG_ERR_SAVE_IO_FAIL;
341 goto end;
342 }
343 }
344
345 ret = config_writer_write_element_bool(writer, config_element_enabled,
346 event->enabled);
347 if (ret) {
348 ret = LTTNG_ERR_SAVE_IO_FAIL;
349 goto end;
350 }
351
352 instrumentation_type = get_kernel_instrumentation_string(
353 event->event->instrumentation);
354 if (!instrumentation_type) {
355 ret = LTTNG_ERR_INVALID;
356 goto end;
357 }
358
359 ret = config_writer_write_element_string(writer, config_element_type,
360 instrumentation_type);
361 if (ret) {
362 ret = LTTNG_ERR_SAVE_IO_FAIL;
363 goto end;
364 }
365
911d1560
JG
366 if (event->filter_expression) {
367 ret = config_writer_write_element_string(writer,
368 config_element_filter,
369 event->filter_expression);
370 if (ret) {
371 ret = LTTNG_ERR_SAVE_IO_FAIL;
372 goto end;
373 }
374 }
375
fb198a11
JG
376 if (event->event->instrumentation == LTTNG_KERNEL_FUNCTION ||
377 event->event->instrumentation == LTTNG_KERNEL_KPROBE ||
378 event->event->instrumentation == LTTNG_KERNEL_KRETPROBE) {
379
380 ret = config_writer_open_element(writer,
381 config_element_attributes);
382 if (ret) {
383 ret = LTTNG_ERR_SAVE_IO_FAIL;
384 goto end;
385 }
386
387 switch (event->event->instrumentation) {
0de3eda1 388 case LTTNG_KERNEL_SYSCALL:
fb198a11
JG
389 case LTTNG_KERNEL_FUNCTION:
390 ret = config_writer_open_element(writer,
391 config_element_function_attributes);
392 if (ret) {
393 ret = LTTNG_ERR_SAVE_IO_FAIL;
394 goto end;
395 }
396
397 ret = config_writer_write_element_string(writer,
398 config_element_name,
399 event->event->u.ftrace.symbol_name);
400 if (ret) {
401 ret = LTTNG_ERR_SAVE_IO_FAIL;
402 goto end;
403 }
404
405 /* /function attributes */
406 ret = config_writer_close_element(writer);
407 if (ret) {
408 ret = LTTNG_ERR_SAVE_IO_FAIL;
409 goto end;
410 }
411 break;
412 case LTTNG_KERNEL_KPROBE:
413 case LTTNG_KERNEL_KRETPROBE:
414 {
415 const char *symbol_name;
416 uint64_t addr;
417 uint64_t offset;
418
419 if (event->event->instrumentation ==
420 LTTNG_KERNEL_KPROBE) {
421 /*
422 * Comments in lttng-kernel.h mention that
423 * either addr or symbol_name are set, not both.
424 */
425 addr = event->event->u.kprobe.addr;
426 offset = event->event->u.kprobe.offset;
427 symbol_name = addr ? NULL :
428 event->event->u.kprobe.symbol_name;
429 } else {
430 symbol_name =
431 event->event->u.kretprobe.symbol_name;
432 addr = event->event->u.kretprobe.addr;
433 offset = event->event->u.kretprobe.offset;
434 }
435
436 ret = config_writer_open_element(writer,
437 config_element_probe_attributes);
438 if (ret) {
439 ret = LTTNG_ERR_SAVE_IO_FAIL;
440 goto end;
441 }
442
443 if (symbol_name) {
444 ret = config_writer_write_element_string(writer,
445 config_element_symbol_name,
446 symbol_name);
447 if (ret) {
448 ret = LTTNG_ERR_SAVE_IO_FAIL;
449 goto end;
450 }
451 }
452
453 if (addr) {
454 ret = config_writer_write_element_unsigned_int(
455 writer, config_element_address, addr);
456 if (ret) {
457 ret = LTTNG_ERR_SAVE_IO_FAIL;
458 goto end;
459 }
460 }
461
462 if (offset) {
463 ret = config_writer_write_element_unsigned_int(
464 writer, config_element_offset, offset);
465 if (ret) {
466 ret = LTTNG_ERR_SAVE_IO_FAIL;
467 goto end;
468 }
469 }
470
471 ret = config_writer_close_element(writer);
472 if (ret) {
473 ret = LTTNG_ERR_SAVE_IO_FAIL;
474 goto end;
475 }
476 break;
477 }
478 default:
479 ERR("Unsupported kernel instrumentation type.");
480 ret = LTTNG_ERR_INVALID;
481 goto end;
482 }
483
484 /* /attributes */
485 ret = config_writer_close_element(writer);
486 if (ret) {
487 ret = LTTNG_ERR_SAVE_IO_FAIL;
488 goto end;
489 }
490 }
491
492 /* /event */
493 ret = config_writer_close_element(writer);
494 if (ret) {
495 ret = LTTNG_ERR_SAVE_IO_FAIL;
496 goto end;
497 }
498end:
499 return ret;
500}
501
0de3eda1
DG
502static
503int save_kernel_syscall(struct config_writer *writer,
504 struct ltt_kernel_channel *kchan)
505{
506 int ret, i;
507 ssize_t count;
508 struct lttng_event *events = NULL;
509
510 assert(writer);
511 assert(kchan);
512
513 count = syscall_list_channel(kchan, &events, 0);
514 if (!count) {
515 /* No syscalls, just gracefully return. */
516 ret = 0;
517 goto end;
518 }
519
520 for (i = 0; i < count; i++) {
521 struct ltt_kernel_event *kevent;
522
523 /* Create a temporary kevent in order to save it. */
00a62084
MD
524 /*
525 * TODO: struct lttng_event does not really work for a filter,
526 * but unfortunately, it is exposed as external API (and used as
527 * internal representation. Using NULL meanwhile.
528 */
529 kevent = trace_kernel_create_event(&events[i],
530 NULL, NULL);
0de3eda1
DG
531 if (!kevent) {
532 ret = -ENOMEM;
533 goto end;
534 }
535 /* Init list in order so the destroy call can del the node. */
536 CDS_INIT_LIST_HEAD(&kevent->list);
537
538 ret = save_kernel_event(writer, kevent);
539 trace_kernel_destroy_event(kevent);
540 if (ret) {
541 goto end;
542 }
543 }
544
545 /* Everything went well */
546 ret = 0;
547
548end:
549 free(events);
550 return ret;
551}
552
fb198a11
JG
553static
554int save_kernel_events(struct config_writer *writer,
0de3eda1 555 struct ltt_kernel_channel *kchan)
fb198a11
JG
556{
557 int ret;
558 struct ltt_kernel_event *event;
559
560 ret = config_writer_open_element(writer, config_element_events);
561 if (ret) {
562 ret = LTTNG_ERR_SAVE_IO_FAIL;
563 goto end;
564 }
565
0de3eda1 566 cds_list_for_each_entry(event, &kchan->events_list.head, list) {
fb198a11
JG
567 ret = save_kernel_event(writer, event);
568 if (ret) {
569 goto end;
570 }
571 }
572
0de3eda1
DG
573 /* Save syscalls if any. */
574 ret = save_kernel_syscall(writer, kchan);
575 if (ret) {
576 goto end;
577 }
578
fb198a11
JG
579 /* /events */
580 ret = config_writer_close_element(writer);
581 if (ret) {
582 ret = LTTNG_ERR_SAVE_IO_FAIL;
583 goto end;
584 }
585end:
586 return ret;
587}
588
589static
590int save_ust_event(struct config_writer *writer,
591 struct ltt_ust_event *event)
592{
593 int ret;
594 const char *loglevel_type_string;
595
596 ret = config_writer_open_element(writer, config_element_event);
597 if (ret) {
598 ret = LTTNG_ERR_SAVE_IO_FAIL;
599 goto end;
600 }
601
602 if (event->attr.name[0]) {
603 ret = config_writer_write_element_string(writer,
604 config_element_name, event->attr.name);
605 if (ret) {
606 ret = LTTNG_ERR_SAVE_IO_FAIL;
607 goto end;
608 }
609 }
610
611 ret = config_writer_write_element_bool(writer, config_element_enabled,
612 event->enabled);
613 if (ret) {
614 ret = LTTNG_ERR_SAVE_IO_FAIL;
615 goto end;
616 }
617
618 if (event->attr.instrumentation != LTTNG_UST_TRACEPOINT) {
619 ERR("Unsupported UST instrumentation type.");
620 ret = LTTNG_ERR_INVALID;
621 goto end;
622 }
623 ret = config_writer_write_element_string(writer, config_element_type,
624 config_event_type_tracepoint);
625 if (ret) {
626 ret = LTTNG_ERR_SAVE_IO_FAIL;
627 goto end;
628 }
629
630 loglevel_type_string = get_loglevel_type_string(
631 event->attr.loglevel_type);
632 if (!loglevel_type_string) {
633 ERR("Unsupported UST loglevel type.");
634 ret = LTTNG_ERR_INVALID;
635 goto end;
636 }
637
638 ret = config_writer_write_element_string(writer,
639 config_element_loglevel_type, loglevel_type_string);
640 if (ret) {
641 ret = LTTNG_ERR_SAVE_IO_FAIL;
642 goto end;
643 }
644
1adbdb10
JG
645 /* The log level is irrelevant if no "filtering" is enabled */
646 if (event->attr.loglevel_type != LTTNG_UST_LOGLEVEL_ALL) {
647 ret = config_writer_write_element_signed_int(writer,
648 config_element_loglevel, event->attr.loglevel);
649 if (ret) {
650 ret = LTTNG_ERR_SAVE_IO_FAIL;
651 goto end;
652 }
fb198a11
JG
653 }
654
655 if (event->filter_expression) {
656 ret = config_writer_write_element_string(writer,
657 config_element_filter, event->filter_expression);
658 if (ret) {
659 ret = LTTNG_ERR_SAVE_IO_FAIL;
660 goto end;
661 }
662 }
663
664 if (event->exclusion && event->exclusion->count) {
665 uint32_t i;
666
667 ret = config_writer_open_element(writer,
668 config_element_exclusions);
669 if (ret) {
670 ret = LTTNG_ERR_SAVE_IO_FAIL;
671 goto end;
672 }
673
674 for (i = 0; i < event->exclusion->count; i++) {
675 ret = config_writer_write_element_string(writer,
676 config_element_exclusion,
677 &event->exclusion->names[0][i]);
678 if (ret) {
679 ret = LTTNG_ERR_SAVE_IO_FAIL;
680 goto end;
681 }
682 }
683
684 /* /exclusions */
685 ret = config_writer_close_element(writer);
686 if (ret) {
687 ret = LTTNG_ERR_SAVE_IO_FAIL;
688 goto end;
689 }
690 }
691
692 /* /event */
693 ret = config_writer_close_element(writer);
694 if (ret) {
695 ret = LTTNG_ERR_SAVE_IO_FAIL;
696 goto end;
697 }
698end:
699 return ret;
700}
701
702static
703int save_ust_events(struct config_writer *writer,
704 struct lttng_ht *events)
705{
706 int ret;
707 struct ltt_ust_event *event;
708 struct lttng_ht_node_str *node;
709 struct lttng_ht_iter iter;
710
711 ret = config_writer_open_element(writer, config_element_events);
712 if (ret) {
713 ret = LTTNG_ERR_SAVE_IO_FAIL;
714 goto end;
715 }
716
717 rcu_read_lock();
718 cds_lfht_for_each_entry(events->ht, &iter.iter, node, node) {
719 event = caa_container_of(node, struct ltt_ust_event, node);
720
af325ba1
JG
721 if (event->internal) {
722 /* Internal events must not be exposed to clients */
723 continue;
724 }
fb198a11
JG
725 ret = save_ust_event(writer, event);
726 if (ret) {
727 rcu_read_unlock();
728 goto end;
729 }
730 }
731 rcu_read_unlock();
732
733 /* /events */
734 ret = config_writer_close_element(writer);
735 if (ret) {
736 ret = LTTNG_ERR_SAVE_IO_FAIL;
737 goto end;
738 }
739end:
740 return ret;
741}
742
743static
744int save_kernel_context(struct config_writer *writer,
745 struct lttng_kernel_context *ctx)
746{
747 int ret = 0;
748
749 if (!ctx) {
750 goto end;
751 }
752
fb198a11
JG
753 ret = config_writer_open_element(writer, config_element_context);
754 if (ret) {
755 ret = LTTNG_ERR_SAVE_IO_FAIL;
756 goto end;
757 }
758
cba45eda 759 if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) {
fb198a11
JG
760 ret = config_writer_open_element(writer, config_element_perf);
761 if (ret) {
762 ret = LTTNG_ERR_SAVE_IO_FAIL;
763 goto end;
764 }
765
766 ret = config_writer_write_element_unsigned_int(writer,
767 config_element_type, ctx->u.perf_counter.type);
768 if (ret) {
769 ret = LTTNG_ERR_SAVE_IO_FAIL;
770 goto end;
771 }
772
773 ret = config_writer_write_element_unsigned_int(writer,
774 config_element_config, ctx->u.perf_counter.config);
775 if (ret) {
776 ret = LTTNG_ERR_SAVE_IO_FAIL;
777 goto end;
778 }
779
780 ret = config_writer_write_element_string(writer,
781 config_element_name, ctx->u.perf_counter.name);
782 if (ret) {
783 ret = LTTNG_ERR_SAVE_IO_FAIL;
784 goto end;
785 }
786
787 /* /perf */
788 ret = config_writer_close_element(writer);
789 if (ret) {
790 ret = LTTNG_ERR_SAVE_IO_FAIL;
791 goto end;
792 }
793 } else {
794 const char *context_type_string =
795 get_kernel_context_type_string(ctx->ctx);
796
797 if (!context_type_string) {
798 ERR("Unsupported kernel context type.");
799 ret = LTTNG_ERR_INVALID;
800 goto end;
801 }
802
803 ret = config_writer_write_element_string(writer,
804 config_element_type, context_type_string);
805 if (ret) {
806 ret = LTTNG_ERR_SAVE_IO_FAIL;
807 goto end;
808 }
809 }
810
811 /* /context */
812 ret = config_writer_close_element(writer);
813 if (ret) {
814 ret = LTTNG_ERR_SAVE_IO_FAIL;
815 goto end;
816 }
817
645328ae
DG
818end:
819 return ret;
820}
821
822static
823int save_kernel_contexts(struct config_writer *writer,
824 struct ltt_kernel_channel *kchan)
825{
826 int ret;
827 struct ltt_kernel_context *ctx;
828
2aa64052
JG
829 if (cds_list_empty(&kchan->ctx_list)) {
830 ret = 0;
831 goto end;
832 }
833
645328ae
DG
834 ret = config_writer_open_element(writer, config_element_contexts);
835 if (ret) {
836 ret = LTTNG_ERR_SAVE_IO_FAIL;
837 goto end;
838 }
839
840 cds_list_for_each_entry(ctx, &kchan->ctx_list, list) {
841 ret = save_kernel_context(writer, &ctx->ctx);
842 if (ret) {
843 goto end;
844 }
845 }
846
fb198a11
JG
847 /* /contexts */
848 ret = config_writer_close_element(writer);
849 if (ret) {
850 ret = LTTNG_ERR_SAVE_IO_FAIL;
851 goto end;
852 }
853end:
854 return ret;
855}
856
857static
858int save_ust_context(struct config_writer *writer,
859 struct cds_list_head *ctx_list)
860{
861 int ret;
862 struct ltt_ust_context *ctx;
863
864 assert(writer);
865 assert(ctx_list);
866
867 ret = config_writer_open_element(writer, config_element_contexts);
868 if (ret) {
869 ret = LTTNG_ERR_SAVE_IO_FAIL;
870 goto end;
871 }
872
873 cds_list_for_each_entry(ctx, ctx_list, list) {
874 const char *context_type_string;
875
fb198a11
JG
876
877 ret = config_writer_open_element(writer,
878 config_element_context);
879 if (ret) {
880 ret = LTTNG_ERR_SAVE_IO_FAIL;
881 goto end;
882 }
883
14ce5bd8
JG
884 if (ctx->ctx.ctx == LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER) {
885 /* Perf contexts are saved as event_perf_context_type */
886 ret = config_writer_open_element(writer,
887 config_element_perf);
888 if (ret) {
889 ret = LTTNG_ERR_SAVE_IO_FAIL;
890 goto end;
891 }
892
893 ret = config_writer_write_element_unsigned_int(writer,
894 config_element_type,
895 ctx->ctx.u.perf_counter.type);
896 if (ret) {
897 ret = LTTNG_ERR_SAVE_IO_FAIL;
898 goto end;
899 }
900
901 ret = config_writer_write_element_unsigned_int(writer,
902 config_element_config,
903 ctx->ctx.u.perf_counter.config);
904 if (ret) {
905 ret = LTTNG_ERR_SAVE_IO_FAIL;
906 goto end;
907 }
908
909 ret = config_writer_write_element_string(writer,
910 config_element_name,
911 ctx->ctx.u.perf_counter.name);
912 if (ret) {
913 ret = LTTNG_ERR_SAVE_IO_FAIL;
914 goto end;
915 }
916
917 /* /perf */
918 ret = config_writer_close_element(writer);
919 if (ret) {
920 ret = LTTNG_ERR_SAVE_IO_FAIL;
921 goto end;
922 }
923 } else {
924 /* Save context as event_context_type_type */
925 context_type_string = get_ust_context_type_string(
926 ctx->ctx.ctx);
927 if (!context_type_string) {
928 ERR("Unsupported UST context type.")
929 ret = LTTNG_ERR_INVALID;
930 goto end;
931 }
932
933 ret = config_writer_write_element_string(writer,
934 config_element_type, context_type_string);
935 if (ret) {
936 ret = LTTNG_ERR_SAVE_IO_FAIL;
937 goto end;
938 }
fb198a11
JG
939 }
940
941 /* /context */
942 ret = config_writer_close_element(writer);
943 if (ret) {
944 ret = LTTNG_ERR_SAVE_IO_FAIL;
945 goto end;
946 }
947 }
948
949 /* /contexts */
950 ret = config_writer_close_element(writer);
951 if (ret) {
952 ret = LTTNG_ERR_SAVE_IO_FAIL;
953 goto end;
954 }
955end:
956 return ret;
957}
958
959static
960int save_kernel_channel(struct config_writer *writer,
961 struct ltt_kernel_channel *kchan)
962{
963 int ret;
964
965 assert(writer);
966 assert(kchan);
967
968 ret = config_writer_open_element(writer, config_element_channel);
969 if (ret) {
970 ret = LTTNG_ERR_SAVE_IO_FAIL;
971 goto end;
972 }
973
974 ret = config_writer_write_element_string(writer, config_element_name,
975 kchan->channel->name);
976 if (ret) {
977 ret = LTTNG_ERR_SAVE_IO_FAIL;
978 goto end;
979 }
980
981 ret = config_writer_write_element_bool(writer, config_element_enabled,
982 kchan->channel->enabled);
983 if (ret) {
984 ret = LTTNG_ERR_SAVE_IO_FAIL;
985 goto end;
986 }
987
988 ret = save_kernel_channel_attributes(writer, &kchan->channel->attr);
989 if (ret) {
990 goto end;
991 }
992
0de3eda1 993 ret = save_kernel_events(writer, kchan);
fb198a11
JG
994 if (ret) {
995 goto end;
996 }
997
645328ae 998 ret = save_kernel_contexts(writer, kchan);
fb198a11
JG
999 if (ret) {
1000 goto end;
1001 }
1002
1003 /* /channel */
1004 ret = config_writer_close_element(writer);
1005 if (ret) {
1006 ret = LTTNG_ERR_SAVE_IO_FAIL;
1007 goto end;
1008 }
1009end:
1010 return ret;
1011}
1012
1013static
1014int save_ust_channel(struct config_writer *writer,
1015 struct ltt_ust_channel *ust_chan,
1016 struct ltt_ust_session *session)
1017{
1018 int ret;
1019
1020 assert(writer);
1021 assert(ust_chan);
1022 assert(session);
1023
1024 ret = config_writer_open_element(writer, config_element_channel);
1025 if (ret) {
1026 ret = LTTNG_ERR_SAVE_IO_FAIL;
1027 goto end;
1028 }
1029
1030 ret = config_writer_write_element_string(writer, config_element_name,
1031 ust_chan->name);
1032 if (ret) {
1033 ret = LTTNG_ERR_SAVE_IO_FAIL;
1034 goto end;
1035 }
1036
1037 ret = config_writer_write_element_bool(writer, config_element_enabled,
1038 ust_chan->enabled);
1039 if (ret) {
1040 ret = LTTNG_ERR_SAVE_IO_FAIL;
1041 goto end;
1042 }
1043
1044 ret = save_ust_channel_attributes(writer, &ust_chan->attr);
1045 if (ret) {
1046 goto end;
1047 }
1048
1049 ret = config_writer_write_element_unsigned_int(writer,
1050 config_element_tracefile_size, ust_chan->tracefile_size);
1051 if (ret) {
1052 ret = LTTNG_ERR_SAVE_IO_FAIL;
1053 goto end;
1054 }
1055
1056 ret = config_writer_write_element_unsigned_int(writer,
1057 config_element_tracefile_count, ust_chan->tracefile_count);
1058 if (ret) {
1059 ret = LTTNG_ERR_SAVE_IO_FAIL;
1060 goto end;
1061 }
1062
1063 ret = config_writer_write_element_unsigned_int(writer,
1064 config_element_live_timer_interval,
1065 session->live_timer_interval);
1066 if (ret) {
1067 ret = LTTNG_ERR_SAVE_IO_FAIL;
1068 goto end;
1069 }
1070
1071 ret = save_ust_events(writer, ust_chan->events);
1072 if (ret) {
1073 ret = LTTNG_ERR_SAVE_IO_FAIL;
1074 goto end;
1075 }
1076
1077 ret = save_ust_context(writer, &ust_chan->ctx_list);
1078 if (ret) {
1079 goto end;
1080 }
1081
1082 /* /channel */
1083 ret = config_writer_close_element(writer);
1084 if (ret) {
1085 ret = LTTNG_ERR_SAVE_IO_FAIL;
1086 goto end;
1087 }
1088end:
1089 return ret;
1090}
1091
1092static
1093int save_kernel_session(struct config_writer *writer,
1094 struct ltt_session *session)
1095{
1096 int ret;
1097 struct ltt_kernel_channel *kchan;
1098
1099 assert(writer);
1100 assert(session);
1101
1102 ret = config_writer_write_element_string(writer, config_element_type,
1103 config_domain_type_kernel);
1104 if (ret) {
1105 ret = LTTNG_ERR_SAVE_IO_FAIL;
1106 goto end;
1107 }
1108
1109 ret = config_writer_write_element_string(writer,
1110 config_element_buffer_type, config_buffer_type_global);
1111 if (ret) {
1112 ret = LTTNG_ERR_SAVE_IO_FAIL;
1113 goto end;
1114 }
1115
1116 ret = config_writer_open_element(writer,
1117 config_element_channels);
1118 if (ret) {
1119 ret = LTTNG_ERR_SAVE_IO_FAIL;
1120 goto end;
1121 }
1122
1123 cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head,
1124 list) {
1125 ret = save_kernel_channel(writer, kchan);
1126 if (ret) {
1127 goto end;
1128 }
1129 }
1130
1131 /* /channels */
1132 ret = config_writer_close_element(writer);
1133 if (ret) {
1134 ret = LTTNG_ERR_SAVE_IO_FAIL;
1135 goto end;
1136 }
1137end:
1138 return ret;
1139}
1140
1141static
1142int save_ust_session(struct config_writer *writer,
022d91ba 1143 struct ltt_session *session, int save_agent)
fb198a11
JG
1144{
1145 int ret;
1146 struct ltt_ust_channel *ust_chan;
1147 const char *buffer_type_string;
1148 struct lttng_ht_node_str *node;
1149 struct lttng_ht_iter iter;
1150
1151 assert(writer);
1152 assert(session);
1153
1154 ret = config_writer_write_element_string(writer, config_element_type,
022d91ba 1155 save_agent ? config_domain_type_jul : config_domain_type_ust);
fb198a11
JG
1156 if (ret) {
1157 ret = LTTNG_ERR_SAVE_IO_FAIL;
1158 goto end;
1159 }
1160
1161 buffer_type_string = get_buffer_type_string(
1162 session->ust_session->buffer_type);
1163 if (!buffer_type_string) {
1164 ERR("Unsupported buffer type.");
1165 ret = LTTNG_ERR_INVALID;
1166 goto end;
1167 }
1168
1169 ret = config_writer_write_element_string(writer,
1170 config_element_buffer_type, buffer_type_string);
1171 if (ret) {
1172 ret = LTTNG_ERR_SAVE_IO_FAIL;
1173 goto end;
1174 }
1175
1176 ret = config_writer_open_element(writer, config_element_channels);
1177 if (ret) {
1178 ret = LTTNG_ERR_SAVE_IO_FAIL;
1179 goto end;
1180 }
1181
1182 rcu_read_lock();
1183 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
1184 &iter.iter, node, node) {
022d91ba 1185 int agent_channel;
fb198a11
JG
1186
1187 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
da6c3a50 1188 agent_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name) ||
0e115563
DG
1189 !strcmp(DEFAULT_LOG4J_CHANNEL_NAME, ust_chan->name) ||
1190 !strcmp(DEFAULT_PYTHON_CHANNEL_NAME, ust_chan->name);
022d91ba 1191 if (!(save_agent ^ agent_channel)) {
fb198a11
JG
1192 ret = save_ust_channel(writer, ust_chan, session->ust_session);
1193 if (ret) {
1194 rcu_read_unlock();
1195 goto end;
1196 }
1197 }
1198 }
1199 rcu_read_unlock();
1200
1201 /* /channels */
1202 ret = config_writer_close_element(writer);
1203 if (ret) {
1204 ret = LTTNG_ERR_SAVE_IO_FAIL;
1205 goto end;
1206 }
1207end:
1208 return ret;
1209}
1210
847a5916
JR
1211static
1212int save_pid_tracker(struct config_writer *writer,
1213 struct ltt_session *sess, int domain)
1214{
1215 int ret = 0;
1216 ssize_t nr_pids = 0, i;
1217 int32_t *pids = NULL;
1218
1219 switch (domain) {
1220 case LTTNG_DOMAIN_KERNEL:
1221 {
1222 nr_pids = kernel_list_tracker_pids(sess->kernel_session, &pids);
1223 if (nr_pids < 0) {
1224 ret = LTTNG_ERR_KERN_LIST_FAIL;
1225 goto end;
1226 }
1227 break;
1228 }
1229 case LTTNG_DOMAIN_UST:
1230 {
1231 nr_pids = trace_ust_list_tracker_pids(sess->ust_session, &pids);
1232 if (nr_pids < 0) {
1233 ret = LTTNG_ERR_UST_LIST_FAIL;
1234 goto end;
1235 }
1236 break;
1237 }
1238 case LTTNG_DOMAIN_JUL:
1239 case LTTNG_DOMAIN_LOG4J:
1240 case LTTNG_DOMAIN_PYTHON:
1241 default:
1242 ret = LTTNG_ERR_UNKNOWN_DOMAIN;
1243 goto end;
1244 }
1245
1246 /* Only create a pid_tracker if enabled or untrack all */
1247 if (nr_pids != 1 || (nr_pids == 1 && pids[0] != -1)) {
1248 ret = config_writer_open_element(writer,
1249 config_element_pid_tracker);
1250 if (ret) {
1251 ret = LTTNG_ERR_SAVE_IO_FAIL;
1252 goto end;
1253 }
1254
1255 ret = config_writer_open_element(writer,
1256 config_element_targets);
1257 if (ret) {
1258 ret = LTTNG_ERR_SAVE_IO_FAIL;
1259 goto end;
1260 }
1261
1262 for (i = 0; i < nr_pids; i++) {
1263 ret = config_writer_open_element(writer,
1264 config_element_target_pid);
1265 if (ret) {
1266 ret = LTTNG_ERR_SAVE_IO_FAIL;
1267 goto end;
1268 }
1269
1270 ret = config_writer_write_element_unsigned_int(writer,
1271 config_element_pid, pids[i]);
1272 if (ret) {
1273 ret = LTTNG_ERR_SAVE_IO_FAIL;
1274 goto end;
1275 }
1276
1277 /* /pid_target */
1278 ret = config_writer_close_element(writer);
1279 if (ret) {
1280 ret = LTTNG_ERR_SAVE_IO_FAIL;
1281 goto end;
1282 }
1283 }
1284
1285 /* /targets */
1286 ret = config_writer_close_element(writer);
1287 if (ret) {
1288 ret = LTTNG_ERR_SAVE_IO_FAIL;
1289 goto end;
1290 }
1291
1292 /* /pid_tracker */
1293 ret = config_writer_close_element(writer);
1294 if (ret) {
1295 ret = LTTNG_ERR_SAVE_IO_FAIL;
1296 goto end;
1297 }
1298 }
1299end:
1300 free(pids);
1301 return ret;
1302}
1303
fb198a11
JG
1304static
1305int save_domains(struct config_writer *writer, struct ltt_session *session)
1306{
1307 int ret = 0;
1308
1309 assert(writer);
1310 assert(session);
1311
1312 if (!session->kernel_session && !session->ust_session) {
1313 goto end;
1314 }
1315
1316 ret = config_writer_open_element(writer, config_element_domains);
1317 if (ret) {
1318 ret = LTTNG_ERR_SAVE_IO_FAIL;
1319 goto end;
1320 }
1321
1322
1323 if (session->kernel_session) {
1324 ret = config_writer_open_element(writer,
1325 config_element_domain);
1326 if (ret) {
1327 ret = LTTNG_ERR_SAVE_IO_FAIL;
1328 goto end;
1329 }
1330
1331 ret = save_kernel_session(writer, session);
1332 if (ret) {
1333 goto end;
1334 }
1335
847a5916
JR
1336 ret = config_writer_open_element(writer,
1337 config_element_trackers);
1338 if (ret) {
1339 ret = LTTNG_ERR_SAVE_IO_FAIL;
1340 goto end;
1341 }
1342
1343 ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_KERNEL);
1344 if (ret) {
1345 goto end;
1346 }
1347
1348 /* /trackers */
1349 ret = config_writer_close_element(writer);
1350 if (ret) {
1351 ret = LTTNG_ERR_SAVE_IO_FAIL;
1352 goto end;
1353 }
fb198a11
JG
1354 /* /domain */
1355 ret = config_writer_close_element(writer);
1356 if (ret) {
1357 ret = LTTNG_ERR_SAVE_IO_FAIL;
1358 goto end;
1359 }
1360 }
1361
1362 if (session->ust_session) {
65d72c41
JG
1363 unsigned long agent_count;
1364
fb198a11
JG
1365 ret = config_writer_open_element(writer,
1366 config_element_domain);
1367 if (ret) {
1368 ret = LTTNG_ERR_SAVE_IO_FAIL;
1369 goto end;
1370 }
1371
1372 ret = save_ust_session(writer, session, 0);
1373 if (ret) {
1374 goto end;
1375 }
1376
847a5916
JR
1377 ret = config_writer_open_element(writer,
1378 config_element_trackers);
1379 if (ret) {
1380 ret = LTTNG_ERR_SAVE_IO_FAIL;
1381 goto end;
1382 }
1383
1384 ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_UST);
1385 if (ret) {
1386 goto end;
1387 }
1388
1389 /* /trackers */
1390 ret = config_writer_close_element(writer);
1391 if (ret) {
1392 ret = LTTNG_ERR_SAVE_IO_FAIL;
1393 goto end;
1394 }
fb198a11
JG
1395 /* /domain */
1396 ret = config_writer_close_element(writer);
1397 if (ret) {
1398 ret = LTTNG_ERR_SAVE_IO_FAIL;
1399 goto end;
1400 }
fb198a11 1401
22c34f48 1402 agent_count = lttng_ht_get_count(session->ust_session->agents);
65d72c41
JG
1403 if (agent_count > 0) {
1404 ret = config_writer_open_element(writer,
1405 config_element_domain);
1406 if (ret) {
1407 ret = LTTNG_ERR_SAVE_IO_FAIL;
1408 goto end;
1409 }
fb198a11 1410
65d72c41
JG
1411 ret = save_ust_session(writer, session, 1);
1412 if (ret) {
1413 goto end;
1414 }
1415
1416 /* /domain */
1417 ret = config_writer_close_element(writer);
1418 if (ret) {
1419 ret = LTTNG_ERR_SAVE_IO_FAIL;
1420 goto end;
1421 }
fb198a11
JG
1422 }
1423 }
1424
1425 /* /domains */
1426 ret = config_writer_close_element(writer);
1427 if (ret) {
1428 ret = LTTNG_ERR_SAVE_IO_FAIL;
1429 goto end;
1430 }
1431end:
1432 return ret;
1433}
1434
1435static
1436int save_consumer_output(struct config_writer *writer,
1437 struct consumer_output *output)
1438{
1439 int ret;
1440
1441 assert(writer);
1442 assert(output);
1443
1444 ret = config_writer_open_element(writer, config_element_consumer_output);
1445 if (ret) {
1446 ret = LTTNG_ERR_SAVE_IO_FAIL;
1447 goto end;
1448 }
1449
1450 ret = config_writer_write_element_bool(writer, config_element_enabled,
1451 output->enabled);
1452 if (ret) {
1453 ret = LTTNG_ERR_SAVE_IO_FAIL;
1454 goto end;
1455 }
1456
1457 ret = config_writer_open_element(writer, config_element_destination);
1458 if (ret) {
1459 ret = LTTNG_ERR_SAVE_IO_FAIL;
1460 goto end;
1461 }
1462
1463 switch (output->type) {
1464 case CONSUMER_DST_LOCAL:
1465 ret = config_writer_write_element_string(writer,
1466 config_element_path, output->dst.trace_path);
1467 if (ret) {
1468 ret = LTTNG_ERR_SAVE_IO_FAIL;
1469 goto end;
1470 }
1471 break;
1472 case CONSUMER_DST_NET:
1473 {
1474 char *uri;
1475
1476 uri = zmalloc(PATH_MAX);
1477 if (!uri) {
1478 ret = LTTNG_ERR_NOMEM;
1479 goto end;
1480 }
1481
1482 ret = config_writer_open_element(writer, config_element_net_output);
1483 if (ret) {
1484 ret = LTTNG_ERR_SAVE_IO_FAIL;
1485 goto end_net_output;
1486 }
1487
1488 if (output->dst.net.control_isset &&
1489 output->dst.net.data_isset) {
1490 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1491 if (ret < 0) {
1492 ret = LTTNG_ERR_INVALID;
1493 goto end_net_output;
1494 }
1495
1496 ret = config_writer_write_element_string(writer,
1497 config_element_control_uri, uri);
1498 if (ret) {
1499 ret = LTTNG_ERR_SAVE_IO_FAIL;
1500 goto end_net_output;
1501 }
1502
1503 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1504 if (ret < 0) {
1505 ret = LTTNG_ERR_INVALID;
1506 goto end_net_output;
1507 }
1508
1509 ret = config_writer_write_element_string(writer,
1510 config_element_data_uri, uri);
1511 if (ret) {
1512 ret = LTTNG_ERR_SAVE_IO_FAIL;
1513 goto end_net_output;
1514 }
1515
1516end_net_output:
1517 free(uri);
1518 if (ret) {
1519 goto end;
1520 }
1521 } else {
1522 ret = !output->dst.net.control_isset ?
1523 LTTNG_ERR_URL_CTRL_MISS :
1524 LTTNG_ERR_URL_DATA_MISS;
c39270e5 1525 free(uri);
fb198a11
JG
1526 goto end;
1527 }
1528
1529 ret = config_writer_close_element(writer);
1530 if (ret) {
1531 ret = LTTNG_ERR_SAVE_IO_FAIL;
1532 goto end;
1533 }
1534 break;
1535 }
1536 default:
1537 ERR("Unsupported consumer output type.");
1538 ret = LTTNG_ERR_INVALID;
1539 goto end;
1540 }
1541
1542 /* /destination */
1543 ret = config_writer_close_element(writer);
1544 if (ret) {
1545 ret = LTTNG_ERR_SAVE_IO_FAIL;
1546 goto end;
1547 }
1548
1549 /* /consumer_output */
1550 ret = config_writer_close_element(writer);
1551 if (ret) {
1552 ret = LTTNG_ERR_SAVE_IO_FAIL;
1553 goto end;
1554 }
1555end:
1556 return ret;
1557}
1558
1559static
1560int save_snapshot_outputs(struct config_writer *writer,
1561 struct snapshot *snapshot)
1562{
1563 int ret;
1564 struct lttng_ht_iter iter;
1565 struct snapshot_output *output;
1566
1567 assert(writer);
1568 assert(snapshot);
1569
1570 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1571 if (ret) {
1572 ret = LTTNG_ERR_SAVE_IO_FAIL;
1573 goto end;
1574 }
1575
1576 rcu_read_lock();
1577 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1578 node.node) {
1579 ret = config_writer_open_element(writer,
1580 config_element_output);
1581 if (ret) {
1582 ret = LTTNG_ERR_SAVE_IO_FAIL;
1583 goto end_unlock;
1584 }
1585
1586 ret = config_writer_write_element_string(writer,
1587 config_element_name, output->name);
1588 if (ret) {
1589 ret = LTTNG_ERR_SAVE_IO_FAIL;
1590 goto end_unlock;
1591 }
1592
1593 ret = config_writer_write_element_unsigned_int(writer,
1594 config_element_max_size, output->max_size);
1595 if (ret) {
1596 ret = LTTNG_ERR_SAVE_IO_FAIL;
1597 goto end_unlock;
1598 }
1599
1600 ret = save_consumer_output(writer, output->consumer);
1601 if (ret) {
1602 goto end_unlock;
1603 }
1604
1605 /* /output */
1606 ret = config_writer_close_element(writer);
1607 if (ret) {
1608 ret = LTTNG_ERR_SAVE_IO_FAIL;
1609 goto end_unlock;
1610 }
1611 }
1612 rcu_read_unlock();
1613
1614 /* /snapshot_outputs */
1615 ret = config_writer_close_element(writer);
1616 if (ret) {
1617 ret = LTTNG_ERR_SAVE_IO_FAIL;
1618 goto end;
1619 }
1620
1621end:
1622 return ret;
1623end_unlock:
1624 rcu_read_unlock();
1625 return ret;
1626}
1627
1628static
1629int save_session_output(struct config_writer *writer,
1630 struct ltt_session *session)
1631{
1632 int ret;
1633
1634 assert(writer);
1635 assert(session);
1636
1637 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
1638 (!session->snapshot_mode && !session->consumer)) {
1639 /* Session is in no output mode */
1640 ret = 0;
1641 goto end;
1642 }
1643
1644 ret = config_writer_open_element(writer, config_element_output);
1645 if (ret) {
1646 ret = LTTNG_ERR_SAVE_IO_FAIL;
1647 goto end;
1648 }
1649
1650 if (session->snapshot_mode) {
1651 ret = save_snapshot_outputs(writer, &session->snapshot);
1652 if (ret) {
1653 goto end;
1654 }
1655 } else {
1656 if (session->consumer) {
1657 ret = save_consumer_output(writer, session->consumer);
1658 if (ret) {
1659 goto end;
1660 }
1661 }
1662 }
1663
1664 /* /output */
1665 ret = config_writer_close_element(writer);
1666 if (ret) {
1667 ret = LTTNG_ERR_SAVE_IO_FAIL;
1668 goto end;
1669 }
1670end:
1671 return ret;
1672}
1673
1674/*
1675 * Save the given session.
1676 *
1677 * Return 0 on success else a LTTNG_ERR* code.
1678 */
1679static
1680int save_session(struct ltt_session *session,
1681 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1682{
1683 int ret, fd;
db471218 1684 unsigned int file_opened = 0; /* Indicate if the file has been opened */
fb198a11
JG
1685 char config_file_path[PATH_MAX];
1686 size_t len;
1687 struct config_writer *writer = NULL;
1688 size_t session_name_len;
1689 const char *provided_path;
1690
1691 assert(session);
1692 assert(attr);
1693 assert(creds);
1694
1695 session_name_len = strlen(session->name);
95a29ab8 1696 memset(config_file_path, 0, sizeof(config_file_path));
fb198a11
JG
1697
1698 if (!session_access_ok(session,
1699 LTTNG_SOCK_GET_UID_CRED(creds),
1700 LTTNG_SOCK_GET_GID_CRED(creds))) {
1701 ret = LTTNG_ERR_EPERM;
1702 goto end;
1703 }
1704
1705 provided_path = lttng_save_session_attr_get_output_url(attr);
1706 if (provided_path) {
95a29ab8 1707 DBG3("Save session in provided path %s", provided_path);
fb198a11 1708 len = strlen(provided_path);
d2992717 1709 if (len >= sizeof(config_file_path)) {
fb198a11
JG
1710 ret = LTTNG_ERR_SET_URL;
1711 goto end;
1712 }
1713 strncpy(config_file_path, provided_path, len);
1714 } else {
7e078ad1 1715 ssize_t ret_len;
fb198a11
JG
1716 char *home_dir = utils_get_user_home_dir(
1717 LTTNG_SOCK_GET_UID_CRED(creds));
1718 if (!home_dir) {
1719 ret = LTTNG_ERR_SET_URL;
1720 goto end;
1721 }
1722
d2992717 1723 ret_len = snprintf(config_file_path, sizeof(config_file_path),
fb198a11
JG
1724 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1725 free(home_dir);
7e078ad1 1726 if (ret_len < 0) {
fb198a11
JG
1727 PERROR("snprintf save session");
1728 ret = LTTNG_ERR_SET_URL;
1729 goto end;
1730 }
7e078ad1 1731 len = ret_len;
fb198a11
JG
1732 }
1733
1734 /*
d2992717
DG
1735 * Check the path fits in the config file path dst including the '/'
1736 * followed by trailing .lttng extension and the NULL terminated string.
fb198a11 1737 */
d2992717
DG
1738 if ((len + session_name_len + 2 +
1739 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1740 > sizeof(config_file_path)) {
fb198a11
JG
1741 ret = LTTNG_ERR_SET_URL;
1742 goto end;
1743 }
1744
1745 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1746 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1747 if (ret) {
1748 ret = LTTNG_ERR_SET_URL;
1749 goto end;
1750 }
1751
d2992717
DG
1752 /*
1753 * At this point, we know that everything fits in the buffer. Validation
1754 * was done just above.
1755 */
fb198a11
JG
1756 config_file_path[len++] = '/';
1757 strncpy(config_file_path + len, session->name, session_name_len);
1758 len += session_name_len;
1759 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
95a29ab8
DG
1760 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1761 config_file_path[len] = '\0';
fb198a11
JG
1762
1763 if (!access(config_file_path, F_OK) && !attr->overwrite) {
f9b57ab2
DG
1764 /* File exists, notify the user since the overwrite flag is off. */
1765 ret = LTTNG_ERR_SAVE_FILE_EXIST;
fb198a11
JG
1766 goto end;
1767 }
1768
1769 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1770 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1771 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1772 if (fd < 0) {
1773 PERROR("Could not create configuration file");
1774 ret = LTTNG_ERR_SAVE_IO_FAIL;
1775 goto end;
1776 }
db471218 1777 file_opened = 1;
fb198a11 1778
705bb62f 1779 writer = config_writer_create(fd, 1);
fb198a11
JG
1780 if (!writer) {
1781 ret = LTTNG_ERR_NOMEM;
1782 goto end;
1783 }
1784
1785 ret = config_writer_open_element(writer, config_element_sessions);
1786 if (ret) {
1787 ret = LTTNG_ERR_SAVE_IO_FAIL;
1788 goto end;
1789 }
1790
1791 ret = config_writer_open_element(writer, config_element_session);
1792 if (ret) {
1793 ret = LTTNG_ERR_SAVE_IO_FAIL;
1794 goto end;
1795 }
1796
1797 ret = config_writer_write_element_string(writer, config_element_name,
1798 session->name);
1799 if (ret) {
1800 ret = LTTNG_ERR_SAVE_IO_FAIL;
1801 goto end;
1802 }
1803
9e7c9f56
JR
1804 if(session->shm_path[0] != '\0') {
1805 ret = config_writer_write_element_string(writer,
1806 config_element_shared_memory_path,
1807 session->shm_path);
1808 if (ret) {
1809 ret = LTTNG_ERR_SAVE_IO_FAIL;
1810 goto end;
1811 }
1812 }
1813
fb198a11
JG
1814 ret = save_domains(writer, session);
1815 if (ret) {
1816 goto end;
1817 }
1818
1819 ret = config_writer_write_element_bool(writer, config_element_started,
8382cf6f 1820 session->active);
fb198a11
JG
1821 if (ret) {
1822 ret = LTTNG_ERR_SAVE_IO_FAIL;
1823 goto end;
1824 }
1825
1826 if (session->snapshot_mode || session->live_timer) {
1827 ret = config_writer_open_element(writer, config_element_attributes);
1828 if (ret) {
1829 ret = LTTNG_ERR_SAVE_IO_FAIL;
1830 goto end;
1831 }
1832
1833 if (session->snapshot_mode) {
1834 ret = config_writer_write_element_bool(writer,
1835 config_element_snapshot_mode, 1);
1836 if (ret) {
1837 ret = LTTNG_ERR_SAVE_IO_FAIL;
1838 goto end;
1839 }
1840 } else {
d98ad589 1841 ret = config_writer_write_element_unsigned_int(writer,
fb198a11
JG
1842 config_element_live_timer_interval, session->live_timer);
1843 if (ret) {
1844 ret = LTTNG_ERR_SAVE_IO_FAIL;
1845 goto end;
1846 }
1847 }
1848
1849 /* /attributes */
1850 ret = config_writer_close_element(writer);
1851 if (ret) {
1852 ret = LTTNG_ERR_SAVE_IO_FAIL;
1853 goto end;
1854 }
1855 }
1856
1857 ret = save_session_output(writer, session);
1858 if (ret) {
1859 goto end;
1860 }
1861
1862 /* /session */
1863 ret = config_writer_close_element(writer);
1864 if (ret) {
1865 ret = LTTNG_ERR_SAVE_IO_FAIL;
1866 goto end;
1867 }
1868
1869 /* /sessions */
1870 ret = config_writer_close_element(writer);
1871 if (ret) {
1872 ret = LTTNG_ERR_SAVE_IO_FAIL;
1873 goto end;
1874 }
1875end:
1876 if (writer && config_writer_destroy(writer)) {
1877 /* Preserve the original error code */
1878 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
1879 }
1880 if (ret) {
1881 /* Delete file in case of error */
db471218 1882 if (file_opened && unlink(config_file_path)) {
fb198a11
JG
1883 PERROR("Unlinking XML session configuration.");
1884 }
1885 }
1886
1887 return ret;
1888}
1889
1890int cmd_save_sessions(struct lttng_save_session_attr *attr,
1891 lttng_sock_cred *creds)
1892{
1893 int ret;
1894 const char *session_name;
1895 struct ltt_session *session;
1896
1897 session_lock_list();
1898
1899 session_name = lttng_save_session_attr_get_session_name(attr);
1900 if (session_name) {
1901 session = session_find_by_name(session_name);
1902 if (!session) {
1903 ret = LTTNG_ERR_SESS_NOT_FOUND;
1904 goto end;
1905 }
1906
1907 session_lock(session);
1908 ret = save_session(session, attr, creds);
1909 session_unlock(session);
1910 if (ret) {
1911 goto end;
1912 }
1913 } else {
1914 struct ltt_session_list *list = session_get_list();
1915
1916 cds_list_for_each_entry(session, &list->head, list) {
1917 session_lock(session);
1918 ret = save_session(session, attr, creds);
1919 session_unlock(session);
1920
1921 /* Don't abort if we don't have the required permissions. */
1922 if (ret && ret != LTTNG_ERR_EPERM) {
1923 goto end;
1924 }
1925 }
1926 }
1927 ret = LTTNG_OK;
1928
1929end:
1930 session_unlock_list();
1931 return ret;
1932}
This page took 0.174451 seconds and 4 git commands to generate.