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