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