trackers: update lttng-sessiond
[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
6c1c0768 18#define _LGPL_SOURCE
fb198a11
JG
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>
f40ef1d5 27#include <common/config/session-config.h>
fb198a11
JG
28#include <common/utils.h>
29#include <common/runas.h>
30#include <lttng/save-internal.h>
31
847a5916 32#include "kernel.h"
fb198a11
JG
33#include "save.h"
34#include "session.h"
0dbc2034 35#include "lttng-syscall.h"
fb198a11 36#include "trace-ust.h"
51755dc8 37#include "agent.h"
fb198a11 38
a24248b3 39/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
40static
41int save_kernel_channel_attributes(struct config_writer *writer,
42 struct lttng_channel_attr *attr)
43{
44 int ret;
45
46 ret = config_writer_write_element_string(writer,
47 config_element_overwrite_mode,
48 attr->overwrite ? config_overwrite_mode_overwrite :
49 config_overwrite_mode_discard);
50 if (ret) {
a24248b3 51 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
52 goto end;
53 }
54
55 ret = config_writer_write_element_unsigned_int(writer,
56 config_element_subbuf_size, attr->subbuf_size);
57 if (ret) {
a24248b3 58 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
59 goto end;
60 }
61
62 ret = config_writer_write_element_unsigned_int(writer,
63 config_element_num_subbuf,
64 attr->num_subbuf);
65 if (ret) {
a24248b3 66 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
67 goto end;
68 }
69
70 ret = config_writer_write_element_unsigned_int(writer,
71 config_element_switch_timer_interval,
72 attr->switch_timer_interval);
73 if (ret) {
a24248b3 74 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
75 goto end;
76 }
77
78 ret = config_writer_write_element_unsigned_int(writer,
79 config_element_read_timer_interval,
80 attr->read_timer_interval);
81 if (ret) {
a24248b3 82 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
83 goto end;
84 }
85
86 ret = config_writer_write_element_string(writer,
87 config_element_output_type,
88 attr->output == LTTNG_EVENT_SPLICE ?
89 config_output_type_splice : config_output_type_mmap);
90 if (ret) {
a24248b3 91 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
92 goto end;
93 }
94
95 ret = config_writer_write_element_unsigned_int(writer,
96 config_element_tracefile_size, attr->tracefile_size);
97 if (ret) {
a24248b3 98 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
99 goto end;
100 }
101
102 ret = config_writer_write_element_unsigned_int(writer,
103 config_element_tracefile_count,
104 attr->tracefile_count);
105 if (ret) {
a24248b3 106 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
107 goto end;
108 }
109
110 ret = config_writer_write_element_unsigned_int(writer,
111 config_element_live_timer_interval,
112 attr->live_timer_interval);
113 if (ret) {
a24248b3 114 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
115 goto end;
116 }
4fc2b126
JR
117
118 if (attr->extended.ptr) {
119 struct lttng_channel_extended *ext = NULL;
120
121 ext = (struct lttng_channel_extended *) attr->extended.ptr;
122 ret = config_writer_write_element_unsigned_int(writer,
123 config_element_monitor_timer_interval,
124 ext->monitor_timer_interval);
125 if (ret) {
a24248b3 126 ret = LTTNG_ERR_SAVE_IO_FAIL;
4fc2b126
JR
127 goto end;
128 }
275472aa
JR
129
130 ret = config_writer_write_element_signed_int(writer,
131 config_element_blocking_timeout,
132 ext->blocking_timeout);
133 if (ret) {
a24248b3 134 ret = LTTNG_ERR_SAVE_IO_FAIL;
275472aa
JR
135 goto end;
136 }
4fc2b126
JR
137 }
138
a24248b3 139 ret = LTTNG_OK;
fb198a11 140end:
a24248b3 141 return ret;
fb198a11
JG
142}
143
a24248b3 144/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
145static
146int save_ust_channel_attributes(struct config_writer *writer,
147 struct lttng_ust_channel_attr *attr)
148{
149 int ret;
4fc2b126 150 struct ltt_ust_channel *channel = NULL;
fb198a11
JG
151
152 ret = config_writer_write_element_string(writer,
153 config_element_overwrite_mode,
154 attr->overwrite ? config_overwrite_mode_overwrite :
155 config_overwrite_mode_discard);
156 if (ret) {
a24248b3 157 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
158 goto end;
159 }
160
161 ret = config_writer_write_element_unsigned_int(writer,
162 config_element_subbuf_size, attr->subbuf_size);
163 if (ret) {
a24248b3 164 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
165 goto end;
166 }
167
168 ret = config_writer_write_element_unsigned_int(writer,
169 config_element_num_subbuf,
170 attr->num_subbuf);
171 if (ret) {
a24248b3 172 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
173 goto end;
174 }
175
176 ret = config_writer_write_element_unsigned_int(writer,
177 config_element_switch_timer_interval,
178 attr->switch_timer_interval);
179 if (ret) {
a24248b3 180 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
181 goto end;
182 }
183
184 ret = config_writer_write_element_unsigned_int(writer,
185 config_element_read_timer_interval,
186 attr->read_timer_interval);
187 if (ret) {
a24248b3 188 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
189 goto end;
190 }
191
192 ret = config_writer_write_element_string(writer,
193 config_element_output_type,
194 attr->output == LTTNG_UST_MMAP ?
195 config_output_type_mmap : config_output_type_splice);
196 if (ret) {
a24248b3 197 ret = LTTNG_ERR_SAVE_IO_FAIL;
fb198a11
JG
198 goto end;
199 }
4fc2b126 200
275472aa
JR
201 ret = config_writer_write_element_signed_int(writer,
202 config_element_blocking_timeout,
203 attr->u.s.blocking_timeout);
204 if (ret) {
a24248b3 205 ret = LTTNG_ERR_SAVE_IO_FAIL;
275472aa
JR
206 goto end;
207 }
208
4fc2b126
JR
209 /*
210 * Fetch the monitor timer which is located in the parent of
211 * lttng_ust_channel_attr
212 */
213 channel = caa_container_of(attr, struct ltt_ust_channel, attr);
214 ret = config_writer_write_element_unsigned_int(writer,
215 config_element_monitor_timer_interval,
216 channel->monitor_timer_interval);
217 if (ret) {
a24248b3 218 ret = LTTNG_ERR_SAVE_IO_FAIL;
4fc2b126
JR
219 goto end;
220 }
221
a24248b3 222 ret = LTTNG_OK;
fb198a11 223end:
a24248b3 224 return ret;
fb198a11
JG
225}
226
227static
228const char *get_kernel_instrumentation_string(
229 enum lttng_kernel_instrumentation instrumentation)
230{
231 const char *instrumentation_string;
232
233 switch (instrumentation) {
234 case LTTNG_KERNEL_ALL:
235 instrumentation_string = config_event_type_all;
236 break;
237 case LTTNG_KERNEL_TRACEPOINT:
238 instrumentation_string = config_event_type_tracepoint;
239 break;
240 case LTTNG_KERNEL_KPROBE:
241 instrumentation_string = config_event_type_kprobe;
242 break;
243 case LTTNG_KERNEL_FUNCTION:
244 instrumentation_string = config_event_type_function;
245 break;
246 case LTTNG_KERNEL_KRETPROBE:
247 instrumentation_string = config_event_type_kretprobe;
248 break;
249 case LTTNG_KERNEL_NOOP:
250 instrumentation_string = config_event_type_noop;
251 break;
252 case LTTNG_KERNEL_SYSCALL:
253 instrumentation_string = config_event_type_syscall;
254 break;
255 default:
256 instrumentation_string = NULL;
257 }
258
259 return instrumentation_string;
260}
261
262static
263const char *get_kernel_context_type_string(
264 enum lttng_kernel_context_type context_type)
265{
266 const char *context_type_string;
267
268 switch (context_type) {
269 case LTTNG_KERNEL_CONTEXT_PID:
270 context_type_string = config_event_context_pid;
271 break;
272 case LTTNG_KERNEL_CONTEXT_PROCNAME:
273 context_type_string = config_event_context_procname;
274 break;
275 case LTTNG_KERNEL_CONTEXT_PRIO:
276 context_type_string = config_event_context_prio;
277 break;
278 case LTTNG_KERNEL_CONTEXT_NICE:
279 context_type_string = config_event_context_nice;
280 break;
281 case LTTNG_KERNEL_CONTEXT_VPID:
282 context_type_string = config_event_context_vpid;
283 break;
284 case LTTNG_KERNEL_CONTEXT_TID:
285 context_type_string = config_event_context_tid;
286 break;
287 case LTTNG_KERNEL_CONTEXT_VTID:
288 context_type_string = config_event_context_vtid;
289 break;
290 case LTTNG_KERNEL_CONTEXT_PPID:
291 context_type_string = config_event_context_ppid;
292 break;
293 case LTTNG_KERNEL_CONTEXT_VPPID:
294 context_type_string = config_event_context_vppid;
295 break;
296 case LTTNG_KERNEL_CONTEXT_HOSTNAME:
297 context_type_string = config_event_context_hostname;
298 break;
1ae5e83e
JD
299 case LTTNG_KERNEL_CONTEXT_INTERRUPTIBLE:
300 context_type_string = config_event_context_interruptible;
301 break;
302 case LTTNG_KERNEL_CONTEXT_PREEMPTIBLE:
303 context_type_string = config_event_context_preemptible;
304 break;
305 case LTTNG_KERNEL_CONTEXT_NEED_RESCHEDULE:
306 context_type_string = config_event_context_need_reschedule;
307 break;
308 case LTTNG_KERNEL_CONTEXT_MIGRATABLE:
309 context_type_string = config_event_context_migratable;
310 break;
fb198a11
JG
311 default:
312 context_type_string = NULL;
313 }
314
315 return context_type_string;
316}
317
318static
319const char *get_ust_context_type_string(
320 enum lttng_ust_context_type context_type)
321{
322 const char *context_type_string;
323
324 switch (context_type) {
325 case LTTNG_UST_CONTEXT_PROCNAME:
326 context_type_string = config_event_context_procname;
327 break;
328 case LTTNG_UST_CONTEXT_VPID:
329 context_type_string = config_event_context_vpid;
330 break;
331 case LTTNG_UST_CONTEXT_VTID:
332 context_type_string = config_event_context_vtid;
333 break;
334 case LTTNG_UST_CONTEXT_IP:
335 context_type_string = config_event_context_ip;
336 break;
337 case LTTNG_UST_CONTEXT_PTHREAD_ID:
338 context_type_string = config_event_context_pthread_id;
339 break;
045fc617
JG
340 case LTTNG_UST_CONTEXT_APP_CONTEXT:
341 context_type_string = config_event_context_app;
342 break;
e885a367 343 case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER:
14ce5bd8
JG
344 /*
345 * Error, should not be stored in the XML, perf contexts
346 * are stored as a node of type event_perf_context_type.
347 */
fb198a11
JG
348 default:
349 context_type_string = NULL;
e885a367 350 break;
fb198a11
JG
351 }
352
353 return context_type_string;
354}
355
356static
357const char *get_buffer_type_string(
358 enum lttng_buffer_type buffer_type)
359{
360 const char *buffer_type_string;
361
362 switch (buffer_type) {
363 case LTTNG_BUFFER_PER_PID:
364 buffer_type_string = config_buffer_type_per_pid;
365 break;
366 case LTTNG_BUFFER_PER_UID:
367 buffer_type_string = config_buffer_type_per_uid;
368 break;
369 case LTTNG_BUFFER_GLOBAL:
370 buffer_type_string = config_buffer_type_global;
371 break;
372 default:
373 buffer_type_string = NULL;
374 }
375
376 return buffer_type_string;
377}
378
379static
380const char *get_loglevel_type_string(
381 enum lttng_ust_loglevel_type loglevel_type)
382{
383 const char *loglevel_type_string;
384
385 switch (loglevel_type) {
386 case LTTNG_UST_LOGLEVEL_ALL:
387 loglevel_type_string = config_loglevel_type_all;
388 break;
389 case LTTNG_UST_LOGLEVEL_RANGE:
390 loglevel_type_string = config_loglevel_type_range;
391 break;
392 case LTTNG_UST_LOGLEVEL_SINGLE:
393 loglevel_type_string = config_loglevel_type_single;
394 break;
395 default:
396 loglevel_type_string = NULL;
397 }
398
399 return loglevel_type_string;
400}
401
a24248b3 402/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
403static
404int save_kernel_event(struct config_writer *writer,
405 struct ltt_kernel_event *event)
406{
407 int ret;
408 const char *instrumentation_type;
409
410 ret = config_writer_open_element(writer, config_element_event);
411 if (ret) {
412 ret = LTTNG_ERR_SAVE_IO_FAIL;
413 goto end;
414 }
415
416 if (event->event->name[0]) {
417 ret = config_writer_write_element_string(writer,
418 config_element_name, event->event->name);
419 if (ret) {
420 ret = LTTNG_ERR_SAVE_IO_FAIL;
421 goto end;
422 }
423 }
424
425 ret = config_writer_write_element_bool(writer, config_element_enabled,
426 event->enabled);
427 if (ret) {
428 ret = LTTNG_ERR_SAVE_IO_FAIL;
429 goto end;
430 }
431
432 instrumentation_type = get_kernel_instrumentation_string(
433 event->event->instrumentation);
434 if (!instrumentation_type) {
435 ret = LTTNG_ERR_INVALID;
436 goto end;
437 }
438
439 ret = config_writer_write_element_string(writer, config_element_type,
440 instrumentation_type);
441 if (ret) {
442 ret = LTTNG_ERR_SAVE_IO_FAIL;
443 goto end;
444 }
445
911d1560
JG
446 if (event->filter_expression) {
447 ret = config_writer_write_element_string(writer,
448 config_element_filter,
449 event->filter_expression);
450 if (ret) {
451 ret = LTTNG_ERR_SAVE_IO_FAIL;
452 goto end;
453 }
454 }
455
fb198a11
JG
456 if (event->event->instrumentation == LTTNG_KERNEL_FUNCTION ||
457 event->event->instrumentation == LTTNG_KERNEL_KPROBE ||
458 event->event->instrumentation == LTTNG_KERNEL_KRETPROBE) {
459
460 ret = config_writer_open_element(writer,
461 config_element_attributes);
462 if (ret) {
463 ret = LTTNG_ERR_SAVE_IO_FAIL;
464 goto end;
465 }
466
467 switch (event->event->instrumentation) {
0de3eda1 468 case LTTNG_KERNEL_SYSCALL:
fb198a11
JG
469 case LTTNG_KERNEL_FUNCTION:
470 ret = config_writer_open_element(writer,
471 config_element_function_attributes);
472 if (ret) {
473 ret = LTTNG_ERR_SAVE_IO_FAIL;
474 goto end;
475 }
476
477 ret = config_writer_write_element_string(writer,
478 config_element_name,
479 event->event->u.ftrace.symbol_name);
480 if (ret) {
481 ret = LTTNG_ERR_SAVE_IO_FAIL;
482 goto end;
483 }
484
485 /* /function attributes */
486 ret = config_writer_close_element(writer);
487 if (ret) {
488 ret = LTTNG_ERR_SAVE_IO_FAIL;
489 goto end;
490 }
491 break;
492 case LTTNG_KERNEL_KPROBE:
493 case LTTNG_KERNEL_KRETPROBE:
494 {
495 const char *symbol_name;
496 uint64_t addr;
497 uint64_t offset;
498
499 if (event->event->instrumentation ==
500 LTTNG_KERNEL_KPROBE) {
501 /*
502 * Comments in lttng-kernel.h mention that
503 * either addr or symbol_name are set, not both.
504 */
505 addr = event->event->u.kprobe.addr;
506 offset = event->event->u.kprobe.offset;
507 symbol_name = addr ? NULL :
508 event->event->u.kprobe.symbol_name;
509 } else {
510 symbol_name =
511 event->event->u.kretprobe.symbol_name;
512 addr = event->event->u.kretprobe.addr;
513 offset = event->event->u.kretprobe.offset;
514 }
515
516 ret = config_writer_open_element(writer,
517 config_element_probe_attributes);
518 if (ret) {
519 ret = LTTNG_ERR_SAVE_IO_FAIL;
520 goto end;
521 }
522
523 if (symbol_name) {
524 ret = config_writer_write_element_string(writer,
525 config_element_symbol_name,
526 symbol_name);
527 if (ret) {
528 ret = LTTNG_ERR_SAVE_IO_FAIL;
529 goto end;
530 }
531 }
532
533 if (addr) {
534 ret = config_writer_write_element_unsigned_int(
535 writer, config_element_address, addr);
536 if (ret) {
537 ret = LTTNG_ERR_SAVE_IO_FAIL;
538 goto end;
539 }
540 }
541
542 if (offset) {
543 ret = config_writer_write_element_unsigned_int(
544 writer, config_element_offset, offset);
545 if (ret) {
546 ret = LTTNG_ERR_SAVE_IO_FAIL;
547 goto end;
548 }
549 }
550
551 ret = config_writer_close_element(writer);
552 if (ret) {
553 ret = LTTNG_ERR_SAVE_IO_FAIL;
554 goto end;
555 }
556 break;
557 }
558 default:
559 ERR("Unsupported kernel instrumentation type.");
560 ret = LTTNG_ERR_INVALID;
561 goto end;
562 }
563
564 /* /attributes */
565 ret = config_writer_close_element(writer);
566 if (ret) {
567 ret = LTTNG_ERR_SAVE_IO_FAIL;
568 goto end;
569 }
570 }
571
572 /* /event */
573 ret = config_writer_close_element(writer);
574 if (ret) {
575 ret = LTTNG_ERR_SAVE_IO_FAIL;
576 goto end;
577 }
a24248b3
MD
578
579 ret = LTTNG_OK;
fb198a11
JG
580end:
581 return ret;
582}
583
a24248b3 584/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
585static
586int save_kernel_events(struct config_writer *writer,
0de3eda1 587 struct ltt_kernel_channel *kchan)
fb198a11
JG
588{
589 int ret;
590 struct ltt_kernel_event *event;
591
592 ret = config_writer_open_element(writer, config_element_events);
593 if (ret) {
594 ret = LTTNG_ERR_SAVE_IO_FAIL;
595 goto end;
596 }
597
0de3eda1 598 cds_list_for_each_entry(event, &kchan->events_list.head, list) {
fb198a11 599 ret = save_kernel_event(writer, event);
a24248b3 600 if (ret != LTTNG_OK) {
fb198a11
JG
601 goto end;
602 }
603 }
604
605 /* /events */
606 ret = config_writer_close_element(writer);
607 if (ret) {
608 ret = LTTNG_ERR_SAVE_IO_FAIL;
609 goto end;
610 }
a24248b3
MD
611
612 ret = LTTNG_OK;
fb198a11
JG
613end:
614 return ret;
615}
616
a24248b3 617/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
618static
619int save_ust_event(struct config_writer *writer,
620 struct ltt_ust_event *event)
621{
622 int ret;
623 const char *loglevel_type_string;
624
625 ret = config_writer_open_element(writer, config_element_event);
626 if (ret) {
627 ret = LTTNG_ERR_SAVE_IO_FAIL;
628 goto end;
629 }
630
631 if (event->attr.name[0]) {
632 ret = config_writer_write_element_string(writer,
633 config_element_name, event->attr.name);
634 if (ret) {
635 ret = LTTNG_ERR_SAVE_IO_FAIL;
636 goto end;
637 }
638 }
639
640 ret = config_writer_write_element_bool(writer, config_element_enabled,
641 event->enabled);
642 if (ret) {
643 ret = LTTNG_ERR_SAVE_IO_FAIL;
644 goto end;
645 }
646
647 if (event->attr.instrumentation != LTTNG_UST_TRACEPOINT) {
648 ERR("Unsupported UST instrumentation type.");
649 ret = LTTNG_ERR_INVALID;
650 goto end;
651 }
652 ret = config_writer_write_element_string(writer, config_element_type,
653 config_event_type_tracepoint);
654 if (ret) {
655 ret = LTTNG_ERR_SAVE_IO_FAIL;
656 goto end;
657 }
658
659 loglevel_type_string = get_loglevel_type_string(
660 event->attr.loglevel_type);
661 if (!loglevel_type_string) {
662 ERR("Unsupported UST loglevel type.");
663 ret = LTTNG_ERR_INVALID;
664 goto end;
665 }
666
667 ret = config_writer_write_element_string(writer,
668 config_element_loglevel_type, loglevel_type_string);
669 if (ret) {
670 ret = LTTNG_ERR_SAVE_IO_FAIL;
671 goto end;
672 }
673
1adbdb10
JG
674 /* The log level is irrelevant if no "filtering" is enabled */
675 if (event->attr.loglevel_type != LTTNG_UST_LOGLEVEL_ALL) {
676 ret = config_writer_write_element_signed_int(writer,
677 config_element_loglevel, event->attr.loglevel);
678 if (ret) {
679 ret = LTTNG_ERR_SAVE_IO_FAIL;
680 goto end;
681 }
fb198a11
JG
682 }
683
684 if (event->filter_expression) {
685 ret = config_writer_write_element_string(writer,
686 config_element_filter, event->filter_expression);
687 if (ret) {
688 ret = LTTNG_ERR_SAVE_IO_FAIL;
689 goto end;
690 }
691 }
692
693 if (event->exclusion && event->exclusion->count) {
694 uint32_t i;
695
696 ret = config_writer_open_element(writer,
697 config_element_exclusions);
698 if (ret) {
699 ret = LTTNG_ERR_SAVE_IO_FAIL;
700 goto end;
701 }
702
703 for (i = 0; i < event->exclusion->count; i++) {
704 ret = config_writer_write_element_string(writer,
705 config_element_exclusion,
d7af3565
PP
706 LTTNG_EVENT_EXCLUSION_NAME_AT(
707 event->exclusion, i));
fb198a11
JG
708 if (ret) {
709 ret = LTTNG_ERR_SAVE_IO_FAIL;
710 goto end;
711 }
712 }
713
714 /* /exclusions */
715 ret = config_writer_close_element(writer);
716 if (ret) {
717 ret = LTTNG_ERR_SAVE_IO_FAIL;
718 goto end;
719 }
720 }
721
722 /* /event */
723 ret = config_writer_close_element(writer);
724 if (ret) {
725 ret = LTTNG_ERR_SAVE_IO_FAIL;
726 goto end;
727 }
a24248b3
MD
728
729 ret = LTTNG_OK;
fb198a11
JG
730end:
731 return ret;
732}
733
a24248b3 734/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
735static
736int save_ust_events(struct config_writer *writer,
737 struct lttng_ht *events)
738{
739 int ret;
740 struct ltt_ust_event *event;
741 struct lttng_ht_node_str *node;
742 struct lttng_ht_iter iter;
743
744 ret = config_writer_open_element(writer, config_element_events);
745 if (ret) {
746 ret = LTTNG_ERR_SAVE_IO_FAIL;
747 goto end;
748 }
749
750 rcu_read_lock();
751 cds_lfht_for_each_entry(events->ht, &iter.iter, node, node) {
752 event = caa_container_of(node, struct ltt_ust_event, node);
753
af325ba1
JG
754 if (event->internal) {
755 /* Internal events must not be exposed to clients */
756 continue;
757 }
fb198a11 758 ret = save_ust_event(writer, event);
a24248b3 759 if (ret != LTTNG_OK) {
fb198a11
JG
760 rcu_read_unlock();
761 goto end;
762 }
763 }
764 rcu_read_unlock();
765
766 /* /events */
767 ret = config_writer_close_element(writer);
768 if (ret) {
769 ret = LTTNG_ERR_SAVE_IO_FAIL;
770 goto end;
771 }
a24248b3
MD
772
773 ret = LTTNG_OK;
fb198a11
JG
774end:
775 return ret;
776}
777
a24248b3 778/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
51755dc8 779static
0b35b846 780int init_ust_event_from_agent_event(struct ltt_ust_event *ust_event,
51755dc8
JG
781 struct agent_event *agent_event)
782{
a24248b3 783 int ret;
0b35b846
JG
784 enum lttng_ust_loglevel_type ust_loglevel_type;
785
51755dc8
JG
786 ust_event->enabled = agent_event->enabled;
787 ust_event->attr.instrumentation = LTTNG_UST_TRACEPOINT;
d333bdaa
MD
788 if (lttng_strncpy(ust_event->attr.name, agent_event->name,
789 LTTNG_SYMBOL_NAME_LEN)) {
a24248b3 790 ret = LTTNG_ERR_INVALID;
d333bdaa
MD
791 goto end;
792 }
0b35b846
JG
793 switch (agent_event->loglevel_type) {
794 case LTTNG_EVENT_LOGLEVEL_ALL:
795 ust_loglevel_type = LTTNG_UST_LOGLEVEL_ALL;
796 break;
797 case LTTNG_EVENT_LOGLEVEL_SINGLE:
798 ust_loglevel_type = LTTNG_UST_LOGLEVEL_SINGLE;
799 break;
800 case LTTNG_EVENT_LOGLEVEL_RANGE:
801 ust_loglevel_type = LTTNG_UST_LOGLEVEL_RANGE;
802 break;
803 default:
804 ERR("Invalid agent_event loglevel_type.");
a24248b3 805 ret = LTTNG_ERR_INVALID;
0b35b846
JG
806 goto end;
807 }
808
809 ust_event->attr.loglevel_type = ust_loglevel_type;
2106efa0 810 ust_event->attr.loglevel = agent_event->loglevel_value;
51755dc8
JG
811 ust_event->filter_expression = agent_event->filter_expression;
812 ust_event->exclusion = agent_event->exclusion;
a24248b3
MD
813
814 ret = LTTNG_OK;
0b35b846
JG
815end:
816 return ret;
51755dc8
JG
817}
818
a24248b3 819/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
51755dc8
JG
820static
821int save_agent_events(struct config_writer *writer,
51755dc8
JG
822 struct agent *agent)
823{
824 int ret;
825 struct lttng_ht_iter iter;
826 struct lttng_ht_node_str *node;
827
828 ret = config_writer_open_element(writer, config_element_events);
829 if (ret) {
830 ret = LTTNG_ERR_SAVE_IO_FAIL;
831 goto end;
832 }
833
834 rcu_read_lock();
835 cds_lfht_for_each_entry(agent->events->ht, &iter.iter, node, node) {
836 int ret;
837 struct agent_event *agent_event;
838 struct ltt_ust_event fake_event;
839
840 memset(&fake_event, 0, sizeof(fake_event));
841 agent_event = caa_container_of(node, struct agent_event, node);
842
843 /*
844 * Initialize a fake ust event to reuse the same serialization
845 * function since UST and agent events contain the same info
846 * (and one could wonder why they don't reuse the same
847 * structures...).
848 */
0b35b846 849 ret = init_ust_event_from_agent_event(&fake_event, agent_event);
a24248b3 850 if (ret != LTTNG_OK) {
0b35b846
JG
851 rcu_read_unlock();
852 goto end;
853 }
51755dc8 854 ret = save_ust_event(writer, &fake_event);
a24248b3 855 if (ret != LTTNG_OK) {
51755dc8
JG
856 rcu_read_unlock();
857 goto end;
858 }
859 }
860 rcu_read_unlock();
861
862 /* /events */
863 ret = config_writer_close_element(writer);
864 if (ret) {
865 ret = LTTNG_ERR_SAVE_IO_FAIL;
866 goto end;
867 }
a24248b3
MD
868
869 ret = LTTNG_OK;
51755dc8
JG
870end:
871 return ret;
872}
873
a24248b3 874/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
875static
876int save_kernel_context(struct config_writer *writer,
877 struct lttng_kernel_context *ctx)
878{
a24248b3 879 int ret = LTTNG_OK;
fb198a11
JG
880
881 if (!ctx) {
882 goto end;
883 }
884
fb198a11
JG
885 ret = config_writer_open_element(writer, config_element_context);
886 if (ret) {
887 ret = LTTNG_ERR_SAVE_IO_FAIL;
888 goto end;
889 }
890
cba45eda 891 if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) {
045fc617
JG
892 ret = config_writer_open_element(writer,
893 config_element_context_perf);
fb198a11
JG
894 if (ret) {
895 ret = LTTNG_ERR_SAVE_IO_FAIL;
896 goto end;
897 }
898
899 ret = config_writer_write_element_unsigned_int(writer,
900 config_element_type, ctx->u.perf_counter.type);
901 if (ret) {
902 ret = LTTNG_ERR_SAVE_IO_FAIL;
903 goto end;
904 }
905
906 ret = config_writer_write_element_unsigned_int(writer,
907 config_element_config, ctx->u.perf_counter.config);
908 if (ret) {
909 ret = LTTNG_ERR_SAVE_IO_FAIL;
910 goto end;
911 }
912
913 ret = config_writer_write_element_string(writer,
914 config_element_name, ctx->u.perf_counter.name);
915 if (ret) {
916 ret = LTTNG_ERR_SAVE_IO_FAIL;
917 goto end;
918 }
919
920 /* /perf */
921 ret = config_writer_close_element(writer);
922 if (ret) {
923 ret = LTTNG_ERR_SAVE_IO_FAIL;
924 goto end;
925 }
926 } else {
927 const char *context_type_string =
928 get_kernel_context_type_string(ctx->ctx);
929
930 if (!context_type_string) {
931 ERR("Unsupported kernel context type.");
932 ret = LTTNG_ERR_INVALID;
933 goto end;
934 }
935
936 ret = config_writer_write_element_string(writer,
937 config_element_type, context_type_string);
938 if (ret) {
939 ret = LTTNG_ERR_SAVE_IO_FAIL;
940 goto end;
941 }
942 }
943
944 /* /context */
945 ret = config_writer_close_element(writer);
946 if (ret) {
947 ret = LTTNG_ERR_SAVE_IO_FAIL;
948 goto end;
949 }
950
a24248b3 951 ret = LTTNG_OK;
645328ae
DG
952end:
953 return ret;
954}
955
a24248b3 956/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
645328ae
DG
957static
958int save_kernel_contexts(struct config_writer *writer,
959 struct ltt_kernel_channel *kchan)
960{
961 int ret;
962 struct ltt_kernel_context *ctx;
963
2aa64052 964 if (cds_list_empty(&kchan->ctx_list)) {
a24248b3 965 ret = LTTNG_OK;
2aa64052
JG
966 goto end;
967 }
968
645328ae
DG
969 ret = config_writer_open_element(writer, config_element_contexts);
970 if (ret) {
971 ret = LTTNG_ERR_SAVE_IO_FAIL;
972 goto end;
973 }
974
975 cds_list_for_each_entry(ctx, &kchan->ctx_list, list) {
976 ret = save_kernel_context(writer, &ctx->ctx);
a24248b3 977 if (ret != LTTNG_OK) {
645328ae
DG
978 goto end;
979 }
980 }
981
fb198a11
JG
982 /* /contexts */
983 ret = config_writer_close_element(writer);
984 if (ret) {
985 ret = LTTNG_ERR_SAVE_IO_FAIL;
986 goto end;
987 }
a24248b3
MD
988
989 ret = LTTNG_OK;
fb198a11
JG
990end:
991 return ret;
992}
993
a24248b3 994/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
045fc617
JG
995static
996int save_ust_context_perf_thread_counter(struct config_writer *writer,
997 struct ltt_ust_context *ctx)
998{
999 int ret;
1000
1001 assert(writer);
1002 assert(ctx);
1003
1004 /* Perf contexts are saved as event_perf_context_type */
1005 ret = config_writer_open_element(writer, config_element_context_perf);
1006 if (ret) {
1007 ret = LTTNG_ERR_SAVE_IO_FAIL;
1008 goto end;
1009 }
1010
1011 ret = config_writer_write_element_unsigned_int(writer,
1012 config_element_type, ctx->ctx.u.perf_counter.type);
1013 if (ret) {
1014 ret = LTTNG_ERR_SAVE_IO_FAIL;
1015 goto end;
1016 }
1017
1018 ret = config_writer_write_element_unsigned_int(writer,
1019 config_element_config, ctx->ctx.u.perf_counter.config);
1020 if (ret) {
1021 ret = LTTNG_ERR_SAVE_IO_FAIL;
1022 goto end;
1023 }
1024
1025 ret = config_writer_write_element_string(writer, config_element_name,
1026 ctx->ctx.u.perf_counter.name);
1027 if (ret) {
1028 ret = LTTNG_ERR_SAVE_IO_FAIL;
1029 goto end;
1030 }
1031
1032 /* /perf */
1033 ret = config_writer_close_element(writer);
1034 if (ret) {
1035 ret = LTTNG_ERR_SAVE_IO_FAIL;
1036 goto end;
1037 }
a24248b3
MD
1038
1039 ret = LTTNG_OK;
045fc617
JG
1040end:
1041 return ret;
1042}
1043
a24248b3 1044/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
045fc617
JG
1045static
1046int save_ust_context_app_ctx(struct config_writer *writer,
1047 struct ltt_ust_context *ctx)
1048{
1049 int ret;
1050
1051 assert(writer);
1052 assert(ctx);
1053
1054 /* Application contexts are saved as application_context_type */
1055 ret = config_writer_open_element(writer, config_element_context_app);
1056 if (ret) {
1057 ret = LTTNG_ERR_SAVE_IO_FAIL;
1058 goto end;
1059 }
1060
1061 ret = config_writer_write_element_string(writer,
1062 config_element_context_app_provider_name,
1063 ctx->ctx.u.app_ctx.provider_name);
1064 if (ret) {
1065 ret = LTTNG_ERR_SAVE_IO_FAIL;
1066 goto end;
1067 }
1068
1069 ret = config_writer_write_element_string(writer,
1070 config_element_context_app_ctx_name,
1071 ctx->ctx.u.app_ctx.ctx_name);
1072 if (ret) {
1073 ret = LTTNG_ERR_SAVE_IO_FAIL;
1074 goto end;
1075 }
1076
1077 /* /app */
1078 ret = config_writer_close_element(writer);
1079 if (ret) {
1080 ret = LTTNG_ERR_SAVE_IO_FAIL;
1081 goto end;
1082 }
a24248b3
MD
1083
1084 ret = LTTNG_OK;
045fc617
JG
1085end:
1086 return ret;
1087}
1088
a24248b3 1089/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
045fc617
JG
1090static
1091int save_ust_context_generic(struct config_writer *writer,
1092 struct ltt_ust_context *ctx)
1093{
1094 int ret;
1095 const char *context_type_string;
1096
1097 assert(writer);
1098 assert(ctx);
1099
1100 /* Save context as event_context_type_type */
1101 context_type_string = get_ust_context_type_string(
1102 ctx->ctx.ctx);
1103 if (!context_type_string) {
1104 ERR("Unsupported UST context type.");
1105 ret = LTTNG_ERR_SAVE_IO_FAIL;
1106 goto end;
1107 }
1108
1109 ret = config_writer_write_element_string(writer,
1110 config_element_type, context_type_string);
1111 if (ret) {
1112 ret = LTTNG_ERR_SAVE_IO_FAIL;
1113 goto end;
1114 }
a24248b3
MD
1115
1116 ret = LTTNG_OK;
045fc617
JG
1117end:
1118 return ret;
1119}
1120
a24248b3 1121/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
1122static
1123int save_ust_context(struct config_writer *writer,
1124 struct cds_list_head *ctx_list)
1125{
1126 int ret;
1127 struct ltt_ust_context *ctx;
1128
1129 assert(writer);
1130 assert(ctx_list);
1131
1132 ret = config_writer_open_element(writer, config_element_contexts);
1133 if (ret) {
1134 ret = LTTNG_ERR_SAVE_IO_FAIL;
1135 goto end;
1136 }
1137
1138 cds_list_for_each_entry(ctx, ctx_list, list) {
fb198a11
JG
1139 ret = config_writer_open_element(writer,
1140 config_element_context);
1141 if (ret) {
1142 ret = LTTNG_ERR_SAVE_IO_FAIL;
1143 goto end;
1144 }
1145
045fc617
JG
1146 switch (ctx->ctx.ctx) {
1147 case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER:
1148 ret = save_ust_context_perf_thread_counter(writer, ctx);
1149 break;
1150 case LTTNG_UST_CONTEXT_APP_CONTEXT:
1151 ret = save_ust_context_app_ctx(writer, ctx);
1152 break;
1153 default:
1154 /* Save generic context. */
1155 ret = save_ust_context_generic(writer, ctx);
1156 }
a24248b3 1157 if (ret != LTTNG_OK) {
045fc617 1158 goto end;
fb198a11
JG
1159 }
1160
1161 /* /context */
1162 ret = config_writer_close_element(writer);
1163 if (ret) {
1164 ret = LTTNG_ERR_SAVE_IO_FAIL;
1165 goto end;
1166 }
1167 }
1168
1169 /* /contexts */
1170 ret = config_writer_close_element(writer);
1171 if (ret) {
1172 ret = LTTNG_ERR_SAVE_IO_FAIL;
1173 goto end;
1174 }
a24248b3
MD
1175
1176 ret = LTTNG_OK;
fb198a11
JG
1177end:
1178 return ret;
1179}
1180
a24248b3 1181/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
1182static
1183int save_kernel_channel(struct config_writer *writer,
1184 struct ltt_kernel_channel *kchan)
1185{
1186 int ret;
1187
1188 assert(writer);
1189 assert(kchan);
1190
1191 ret = config_writer_open_element(writer, config_element_channel);
1192 if (ret) {
1193 ret = LTTNG_ERR_SAVE_IO_FAIL;
1194 goto end;
1195 }
1196
1197 ret = config_writer_write_element_string(writer, config_element_name,
1198 kchan->channel->name);
1199 if (ret) {
1200 ret = LTTNG_ERR_SAVE_IO_FAIL;
1201 goto end;
1202 }
1203
1204 ret = config_writer_write_element_bool(writer, config_element_enabled,
1205 kchan->channel->enabled);
1206 if (ret) {
1207 ret = LTTNG_ERR_SAVE_IO_FAIL;
1208 goto end;
1209 }
1210
1211 ret = save_kernel_channel_attributes(writer, &kchan->channel->attr);
a24248b3 1212 if (ret != LTTNG_OK) {
fb198a11
JG
1213 goto end;
1214 }
1215
0de3eda1 1216 ret = save_kernel_events(writer, kchan);
a24248b3 1217 if (ret != LTTNG_OK) {
fb198a11
JG
1218 goto end;
1219 }
1220
645328ae 1221 ret = save_kernel_contexts(writer, kchan);
a24248b3 1222 if (ret != LTTNG_OK) {
fb198a11
JG
1223 goto end;
1224 }
1225
1226 /* /channel */
1227 ret = config_writer_close_element(writer);
1228 if (ret) {
1229 ret = LTTNG_ERR_SAVE_IO_FAIL;
1230 goto end;
1231 }
a24248b3
MD
1232
1233 ret = LTTNG_OK;
fb198a11
JG
1234end:
1235 return ret;
1236}
1237
a24248b3 1238/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
1239static
1240int save_ust_channel(struct config_writer *writer,
1241 struct ltt_ust_channel *ust_chan,
1242 struct ltt_ust_session *session)
1243{
1244 int ret;
1245
1246 assert(writer);
1247 assert(ust_chan);
1248 assert(session);
1249
1250 ret = config_writer_open_element(writer, config_element_channel);
1251 if (ret) {
1252 ret = LTTNG_ERR_SAVE_IO_FAIL;
1253 goto end;
1254 }
1255
1256 ret = config_writer_write_element_string(writer, config_element_name,
1257 ust_chan->name);
1258 if (ret) {
1259 ret = LTTNG_ERR_SAVE_IO_FAIL;
1260 goto end;
1261 }
1262
1263 ret = config_writer_write_element_bool(writer, config_element_enabled,
1264 ust_chan->enabled);
1265 if (ret) {
1266 ret = LTTNG_ERR_SAVE_IO_FAIL;
1267 goto end;
1268 }
1269
1270 ret = save_ust_channel_attributes(writer, &ust_chan->attr);
a24248b3 1271 if (ret != LTTNG_OK) {
fb198a11
JG
1272 goto end;
1273 }
1274
1275 ret = config_writer_write_element_unsigned_int(writer,
1276 config_element_tracefile_size, ust_chan->tracefile_size);
1277 if (ret) {
1278 ret = LTTNG_ERR_SAVE_IO_FAIL;
1279 goto end;
1280 }
1281
1282 ret = config_writer_write_element_unsigned_int(writer,
1283 config_element_tracefile_count, ust_chan->tracefile_count);
1284 if (ret) {
1285 ret = LTTNG_ERR_SAVE_IO_FAIL;
1286 goto end;
1287 }
1288
1289 ret = config_writer_write_element_unsigned_int(writer,
1290 config_element_live_timer_interval,
1291 session->live_timer_interval);
1292 if (ret) {
1293 ret = LTTNG_ERR_SAVE_IO_FAIL;
1294 goto end;
1295 }
1296
51755dc8
JG
1297 if (ust_chan->domain == LTTNG_DOMAIN_UST) {
1298 ret = save_ust_events(writer, ust_chan->events);
a24248b3 1299 if (ret != LTTNG_OK) {
51755dc8
JG
1300 goto end;
1301 }
1302 } else {
1303 struct agent *agent = NULL;
1304
1305 agent = trace_ust_find_agent(session, ust_chan->domain);
1306 if (!agent) {
1307 ret = LTTNG_ERR_SAVE_IO_FAIL;
1308 ERR("Could not find agent associated to UST subdomain");
1309 goto end;
1310 }
1311
1312 /*
1313 * Channels associated with a UST sub-domain (such as JUL, Log4j
1314 * or Python) don't have any non-internal events. We retrieve
1315 * the "agent" events associated with this channel and serialize
1316 * them.
1317 */
8cd0a98d 1318 ret = save_agent_events(writer, agent);
a24248b3 1319 if (ret != LTTNG_OK) {
51755dc8
JG
1320 goto end;
1321 }
fb198a11
JG
1322 }
1323
1324 ret = save_ust_context(writer, &ust_chan->ctx_list);
a24248b3 1325 if (ret != LTTNG_OK) {
fb198a11
JG
1326 goto end;
1327 }
1328
1329 /* /channel */
1330 ret = config_writer_close_element(writer);
1331 if (ret) {
1332 ret = LTTNG_ERR_SAVE_IO_FAIL;
1333 goto end;
1334 }
a24248b3
MD
1335
1336 ret = LTTNG_OK;
fb198a11
JG
1337end:
1338 return ret;
1339}
1340
a24248b3 1341/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
1342static
1343int save_kernel_session(struct config_writer *writer,
1344 struct ltt_session *session)
1345{
1346 int ret;
1347 struct ltt_kernel_channel *kchan;
1348
1349 assert(writer);
1350 assert(session);
1351
1352 ret = config_writer_write_element_string(writer, config_element_type,
1353 config_domain_type_kernel);
1354 if (ret) {
1355 ret = LTTNG_ERR_SAVE_IO_FAIL;
1356 goto end;
1357 }
1358
1359 ret = config_writer_write_element_string(writer,
1360 config_element_buffer_type, config_buffer_type_global);
1361 if (ret) {
1362 ret = LTTNG_ERR_SAVE_IO_FAIL;
1363 goto end;
1364 }
1365
1366 ret = config_writer_open_element(writer,
1367 config_element_channels);
1368 if (ret) {
1369 ret = LTTNG_ERR_SAVE_IO_FAIL;
1370 goto end;
1371 }
1372
1373 cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head,
1374 list) {
1375 ret = save_kernel_channel(writer, kchan);
a24248b3 1376 if (ret != LTTNG_OK) {
fb198a11
JG
1377 goto end;
1378 }
1379 }
1380
1381 /* /channels */
1382 ret = config_writer_close_element(writer);
1383 if (ret) {
1384 ret = LTTNG_ERR_SAVE_IO_FAIL;
1385 goto end;
1386 }
a24248b3
MD
1387
1388 ret = LTTNG_OK;
fb198a11
JG
1389end:
1390 return ret;
1391}
1392
1393static
51755dc8
JG
1394const char *get_config_domain_str(enum lttng_domain_type domain)
1395{
1396 const char *str_dom;
1397
1398 switch (domain) {
1399 case LTTNG_DOMAIN_KERNEL:
1400 str_dom = config_domain_type_kernel;
1401 break;
1402 case LTTNG_DOMAIN_UST:
1403 str_dom = config_domain_type_ust;
1404 break;
1405 case LTTNG_DOMAIN_JUL:
1406 str_dom = config_domain_type_jul;
1407 break;
1408 case LTTNG_DOMAIN_LOG4J:
1409 str_dom = config_domain_type_log4j;
1410 break;
1411 case LTTNG_DOMAIN_PYTHON:
1412 str_dom = config_domain_type_python;
1413 break;
1414 default:
1415 assert(0);
1416 }
1417
1418 return str_dom;
1419}
1420
a24248b3 1421/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
e8fcabef 1422static
a24248b3
MD
1423int save_id_tracker(struct config_writer *writer,
1424 struct ltt_session *sess, int domain,
1425 enum lttng_tracker_type tracker_type)
e8fcabef 1426{
a24248b3
MD
1427 int ret = LTTNG_OK;
1428 ssize_t nr_ids = 0, i;
1429 struct lttng_tracker_id *ids = NULL;
1430 const char *element_id_tracker, *element_target_id, *element_id;
1431
1432 switch (tracker_type) {
1433 case LTTNG_TRACKER_PID:
1434 element_id_tracker = config_element_pid_tracker;
1435 element_target_id = config_element_target_pid;
1436 element_id = config_element_pid;
1437 break;
1438 case LTTNG_TRACKER_VPID:
1439 element_id_tracker = config_element_vpid_tracker;
1440 element_target_id = config_element_target_vpid;
1441 element_id = config_element_id;
1442 break;
1443 case LTTNG_TRACKER_UID:
1444 element_id_tracker = config_element_uid_tracker;
1445 element_target_id = config_element_target_uid;
1446 element_id = config_element_id;
1447 break;
1448 case LTTNG_TRACKER_VUID:
1449 element_id_tracker = config_element_vuid_tracker;
1450 element_target_id = config_element_target_vuid;
1451 element_id = config_element_id;
1452 break;
1453 case LTTNG_TRACKER_GID:
1454 element_id_tracker = config_element_gid_tracker;
1455 element_target_id = config_element_target_gid;
1456 element_id = config_element_id;
1457 break;
1458 case LTTNG_TRACKER_VGID:
1459 element_id_tracker = config_element_vgid_tracker;
1460 element_target_id = config_element_target_vgid;
1461 element_id = config_element_id;
1462 break;
1463 default:
1464 ret = LTTNG_ERR_SAVE_IO_FAIL;
1465 goto end;
1466 }
e8fcabef
JG
1467
1468 switch (domain) {
1469 case LTTNG_DOMAIN_KERNEL:
1470 {
a24248b3
MD
1471 nr_ids = kernel_list_tracker_ids(tracker_type, sess->kernel_session, &ids);
1472 if (nr_ids < 0) {
e8fcabef
JG
1473 ret = LTTNG_ERR_KERN_LIST_FAIL;
1474 goto end;
1475 }
1476 break;
1477 }
1478 case LTTNG_DOMAIN_UST:
1479 {
a24248b3
MD
1480 nr_ids = trace_ust_list_tracker_ids(tracker_type, sess->ust_session, &ids);
1481 if (nr_ids < 0) {
e8fcabef
JG
1482 ret = LTTNG_ERR_UST_LIST_FAIL;
1483 goto end;
1484 }
1485 break;
1486 }
1487 case LTTNG_DOMAIN_JUL:
1488 case LTTNG_DOMAIN_LOG4J:
1489 case LTTNG_DOMAIN_PYTHON:
1490 default:
1491 ret = LTTNG_ERR_UNKNOWN_DOMAIN;
1492 goto end;
1493 }
1494
a24248b3
MD
1495
1496 if (nr_ids == 1 && ids[0].type == LTTNG_ID_ALL) {
1497 /* Tracking all, nothing to output. */
1498 ret = LTTNG_OK;
1499 goto end;
1500 }
1501
1502 ret = config_writer_open_element(writer, element_id_tracker);
1503 if (ret) {
1504 ret = LTTNG_ERR_SAVE_IO_FAIL;
1505 goto end;
1506 }
1507
1508 ret = config_writer_open_element(writer,
1509 config_element_targets);
1510 if (ret) {
1511 ret = LTTNG_ERR_SAVE_IO_FAIL;
1512 goto end;
1513 }
1514
1515 if (nr_ids == 0) {
1516 /* Tracking none: empty list. */
e8fcabef 1517 ret = config_writer_open_element(writer,
a24248b3 1518 element_target_id);
e8fcabef
JG
1519 if (ret) {
1520 ret = LTTNG_ERR_SAVE_IO_FAIL;
1521 goto end;
1522 }
1523
a24248b3
MD
1524 /* /$element_target_id */
1525 ret = config_writer_close_element(writer);
e8fcabef
JG
1526 if (ret) {
1527 ret = LTTNG_ERR_SAVE_IO_FAIL;
1528 goto end;
1529 }
a24248b3
MD
1530 } else {
1531 /* Tracking list. */
1532 for (i = 0; i < nr_ids; i++) {
1533 switch (ids[i].type) {
1534 case LTTNG_ID_VALUE:
1535 ret = config_writer_open_element(writer,
1536 element_target_id);
1537 if (ret) {
1538 ret = LTTNG_ERR_SAVE_IO_FAIL;
1539 goto end;
1540 }
1541 ret = config_writer_write_element_unsigned_int(writer,
1542 element_id, ids[i].value);
1543 break;
1544 case LTTNG_ID_STRING:
1545 ret = config_writer_open_element(writer,
1546 element_target_id);
1547 if (ret) {
1548 ret = LTTNG_ERR_SAVE_IO_FAIL;
1549 goto end;
1550 }
1551 ret = config_writer_write_element_string(writer,
1552 config_element_name, ids[i].string);
1553 break;
1554 default:
1555 /* Unexpected. */
e8fcabef
JG
1556 ret = LTTNG_ERR_SAVE_IO_FAIL;
1557 goto end;
1558 }
e8fcabef
JG
1559 if (ret) {
1560 ret = LTTNG_ERR_SAVE_IO_FAIL;
1561 goto end;
1562 }
1563
a24248b3 1564 /* /$element_target_id */
e8fcabef
JG
1565 ret = config_writer_close_element(writer);
1566 if (ret) {
1567 ret = LTTNG_ERR_SAVE_IO_FAIL;
1568 goto end;
1569 }
1570 }
a24248b3 1571 }
e8fcabef 1572
a24248b3
MD
1573 /* /targets */
1574 ret = config_writer_close_element(writer);
1575 if (ret) {
1576 ret = LTTNG_ERR_SAVE_IO_FAIL;
1577 goto end;
1578 }
e8fcabef 1579
a24248b3
MD
1580 /* /$element_id_tracker */
1581 ret = config_writer_close_element(writer);
1582 if (ret) {
1583 ret = LTTNG_ERR_SAVE_IO_FAIL;
1584 goto end;
e8fcabef 1585 }
a24248b3
MD
1586
1587 ret = LTTNG_OK;
e8fcabef 1588end:
a24248b3 1589 free(ids);
e8fcabef
JG
1590 return ret;
1591}
1592
a24248b3
MD
1593/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
1594static
1595int save_id_trackers(struct config_writer *writer,
1596 struct ltt_session *sess, int domain)
1597{
1598 int ret;
1599
1600 switch (domain) {
1601 case LTTNG_DOMAIN_KERNEL:
1602 ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_PID);
1603 if (ret != LTTNG_OK)
1604 return ret;
1605 ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VPID);
1606 if (ret != LTTNG_OK)
1607 return ret;
1608 ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_UID);
1609 if (ret != LTTNG_OK)
1610 return ret;
1611 ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VUID);
1612 if (ret != LTTNG_OK)
1613 return ret;
1614 ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_GID);
1615 if (ret != LTTNG_OK)
1616 return ret;
1617 ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VGID);
1618 if (ret != LTTNG_OK)
1619 return ret;
1620 break;
1621 case LTTNG_DOMAIN_UST:
1622 ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VPID);
1623 if (ret != LTTNG_OK)
1624 return ret;
1625 ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VUID);
1626 if (ret != LTTNG_OK)
1627 return ret;
1628 ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VGID);
1629 if (ret != LTTNG_OK)
1630 return ret;
1631 break;
1632 default:
1633 return LTTNG_ERR_INVALID;
1634 }
1635 return LTTNG_OK;
1636}
1637
1638/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
51755dc8
JG
1639static
1640int save_ust_domain(struct config_writer *writer,
1641 struct ltt_session *session, enum lttng_domain_type domain)
fb198a11
JG
1642{
1643 int ret;
1644 struct ltt_ust_channel *ust_chan;
1645 const char *buffer_type_string;
1646 struct lttng_ht_node_str *node;
1647 struct lttng_ht_iter iter;
51755dc8 1648 const char *config_domain_name;
fb198a11
JG
1649
1650 assert(writer);
1651 assert(session);
1652
51755dc8
JG
1653 ret = config_writer_open_element(writer,
1654 config_element_domain);
1655 if (ret) {
1656 ret = LTTNG_ERR_SAVE_IO_FAIL;
1657 goto end;
1658 }
1659
1660 config_domain_name = get_config_domain_str(domain);
1661 if (!config_domain_name) {
1662 ret = LTTNG_ERR_INVALID;
1663 goto end;
1664 }
1665
1666 ret = config_writer_write_element_string(writer,
1667 config_element_type, config_domain_name);
fb198a11
JG
1668 if (ret) {
1669 ret = LTTNG_ERR_SAVE_IO_FAIL;
1670 goto end;
1671 }
1672
1673 buffer_type_string = get_buffer_type_string(
1674 session->ust_session->buffer_type);
1675 if (!buffer_type_string) {
1676 ERR("Unsupported buffer type.");
1677 ret = LTTNG_ERR_INVALID;
1678 goto end;
1679 }
1680
1681 ret = config_writer_write_element_string(writer,
1682 config_element_buffer_type, buffer_type_string);
1683 if (ret) {
1684 ret = LTTNG_ERR_SAVE_IO_FAIL;
1685 goto end;
1686 }
1687
1688 ret = config_writer_open_element(writer, config_element_channels);
1689 if (ret) {
1690 ret = LTTNG_ERR_SAVE_IO_FAIL;
1691 goto end;
1692 }
1693
1694 rcu_read_lock();
1695 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
1696 &iter.iter, node, node) {
fb198a11 1697 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
51755dc8 1698 if (domain == ust_chan->domain) {
fb198a11 1699 ret = save_ust_channel(writer, ust_chan, session->ust_session);
a24248b3 1700 if (ret != LTTNG_OK) {
fb198a11
JG
1701 rcu_read_unlock();
1702 goto end;
1703 }
1704 }
1705 }
1706 rcu_read_unlock();
1707
1708 /* /channels */
1709 ret = config_writer_close_element(writer);
1710 if (ret) {
1711 ret = LTTNG_ERR_SAVE_IO_FAIL;
1712 goto end;
1713 }
51755dc8 1714
e8fcabef 1715 if (domain == LTTNG_DOMAIN_UST) {
847a5916 1716 ret = config_writer_open_element(writer,
e8fcabef 1717 config_element_trackers);
847a5916
JR
1718 if (ret) {
1719 ret = LTTNG_ERR_SAVE_IO_FAIL;
1720 goto end;
1721 }
1722
a24248b3
MD
1723 ret = save_id_trackers(writer, session, LTTNG_DOMAIN_UST);
1724 if (ret != LTTNG_OK) {
847a5916
JR
1725 goto end;
1726 }
1727
e8fcabef 1728 /* /trackers */
847a5916
JR
1729 ret = config_writer_close_element(writer);
1730 if (ret) {
a24248b3 1731 ret = LTTNG_ERR_SAVE_IO_FAIL;
847a5916
JR
1732 goto end;
1733 }
e8fcabef 1734 }
847a5916 1735
e8fcabef
JG
1736 /* /domain */
1737 ret = config_writer_close_element(writer);
1738 if (ret) {
1739 ret = LTTNG_ERR_SAVE_IO_FAIL;
1740 goto end;
847a5916 1741 }
e8fcabef 1742
a24248b3 1743 ret = LTTNG_OK;
847a5916 1744end:
847a5916
JR
1745 return ret;
1746}
1747
a24248b3 1748/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
1749static
1750int save_domains(struct config_writer *writer, struct ltt_session *session)
1751{
a24248b3 1752 int ret = LTTNG_OK;
fb198a11
JG
1753
1754 assert(writer);
1755 assert(session);
1756
1757 if (!session->kernel_session && !session->ust_session) {
1758 goto end;
1759 }
1760
1761 ret = config_writer_open_element(writer, config_element_domains);
1762 if (ret) {
1763 ret = LTTNG_ERR_SAVE_IO_FAIL;
1764 goto end;
1765 }
1766
fb198a11
JG
1767 if (session->kernel_session) {
1768 ret = config_writer_open_element(writer,
1769 config_element_domain);
1770 if (ret) {
1771 ret = LTTNG_ERR_SAVE_IO_FAIL;
1772 goto end;
1773 }
1774
1775 ret = save_kernel_session(writer, session);
a24248b3 1776 if (ret != LTTNG_OK) {
fb198a11
JG
1777 goto end;
1778 }
1779
847a5916
JR
1780 ret = config_writer_open_element(writer,
1781 config_element_trackers);
1782 if (ret) {
1783 ret = LTTNG_ERR_SAVE_IO_FAIL;
1784 goto end;
1785 }
1786
a24248b3
MD
1787 ret = save_id_trackers(writer, session, LTTNG_DOMAIN_KERNEL);
1788 if (ret != LTTNG_OK) {
847a5916
JR
1789 goto end;
1790 }
1791
1792 /* /trackers */
1793 ret = config_writer_close_element(writer);
1794 if (ret) {
1795 ret = LTTNG_ERR_SAVE_IO_FAIL;
1796 goto end;
1797 }
fb198a11
JG
1798 /* /domain */
1799 ret = config_writer_close_element(writer);
1800 if (ret) {
1801 ret = LTTNG_ERR_SAVE_IO_FAIL;
1802 goto end;
1803 }
1804 }
1805
1806 if (session->ust_session) {
51755dc8 1807 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_UST);
a24248b3 1808 if (ret != LTTNG_OK) {
fb198a11
JG
1809 goto end;
1810 }
1811
51755dc8 1812 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_JUL);
a24248b3 1813 if (ret != LTTNG_OK) {
fb198a11
JG
1814 goto end;
1815 }
fb198a11 1816
51755dc8 1817 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_LOG4J);
a24248b3 1818 if (ret != LTTNG_OK) {
51755dc8
JG
1819 goto end;
1820 }
65d72c41 1821
51755dc8 1822 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_PYTHON);
a24248b3 1823 if (ret != LTTNG_OK) {
51755dc8 1824 goto end;
fb198a11
JG
1825 }
1826 }
1827
1828 /* /domains */
1829 ret = config_writer_close_element(writer);
1830 if (ret) {
1831 ret = LTTNG_ERR_SAVE_IO_FAIL;
1832 goto end;
1833 }
a24248b3
MD
1834
1835 ret = LTTNG_OK;
fb198a11
JG
1836end:
1837 return ret;
1838}
1839
a24248b3 1840/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
1841static
1842int save_consumer_output(struct config_writer *writer,
1843 struct consumer_output *output)
1844{
1845 int ret;
1846
1847 assert(writer);
1848 assert(output);
1849
1850 ret = config_writer_open_element(writer, config_element_consumer_output);
1851 if (ret) {
1852 ret = LTTNG_ERR_SAVE_IO_FAIL;
1853 goto end;
1854 }
1855
1856 ret = config_writer_write_element_bool(writer, config_element_enabled,
1857 output->enabled);
1858 if (ret) {
1859 ret = LTTNG_ERR_SAVE_IO_FAIL;
1860 goto end;
1861 }
1862
1863 ret = config_writer_open_element(writer, config_element_destination);
1864 if (ret) {
1865 ret = LTTNG_ERR_SAVE_IO_FAIL;
1866 goto end;
1867 }
1868
1869 switch (output->type) {
1870 case CONSUMER_DST_LOCAL:
1871 ret = config_writer_write_element_string(writer,
366a9222 1872 config_element_path, output->dst.session_root_path);
fb198a11
JG
1873 if (ret) {
1874 ret = LTTNG_ERR_SAVE_IO_FAIL;
1875 goto end;
1876 }
1877 break;
1878 case CONSUMER_DST_NET:
1879 {
1880 char *uri;
1881
1882 uri = zmalloc(PATH_MAX);
1883 if (!uri) {
1884 ret = LTTNG_ERR_NOMEM;
1885 goto end;
1886 }
1887
1888 ret = config_writer_open_element(writer, config_element_net_output);
1889 if (ret) {
1890 ret = LTTNG_ERR_SAVE_IO_FAIL;
1891 goto end_net_output;
1892 }
1893
1894 if (output->dst.net.control_isset &&
1895 output->dst.net.data_isset) {
1896 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1897 if (ret < 0) {
1898 ret = LTTNG_ERR_INVALID;
1899 goto end_net_output;
1900 }
1901
1902 ret = config_writer_write_element_string(writer,
1903 config_element_control_uri, uri);
1904 if (ret) {
1905 ret = LTTNG_ERR_SAVE_IO_FAIL;
1906 goto end_net_output;
1907 }
1908
1909 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1910 if (ret < 0) {
1911 ret = LTTNG_ERR_INVALID;
1912 goto end_net_output;
1913 }
1914
1915 ret = config_writer_write_element_string(writer,
1916 config_element_data_uri, uri);
1917 if (ret) {
1918 ret = LTTNG_ERR_SAVE_IO_FAIL;
1919 goto end_net_output;
1920 }
a24248b3 1921 ret = LTTNG_OK;
fb198a11
JG
1922end_net_output:
1923 free(uri);
a24248b3 1924 if (ret != LTTNG_OK) {
fb198a11
JG
1925 goto end;
1926 }
1927 } else {
1928 ret = !output->dst.net.control_isset ?
1929 LTTNG_ERR_URL_CTRL_MISS :
1930 LTTNG_ERR_URL_DATA_MISS;
c39270e5 1931 free(uri);
fb198a11
JG
1932 goto end;
1933 }
1934
1935 ret = config_writer_close_element(writer);
1936 if (ret) {
1937 ret = LTTNG_ERR_SAVE_IO_FAIL;
1938 goto end;
1939 }
1940 break;
1941 }
1942 default:
1943 ERR("Unsupported consumer output type.");
1944 ret = LTTNG_ERR_INVALID;
1945 goto end;
1946 }
1947
1948 /* /destination */
1949 ret = config_writer_close_element(writer);
1950 if (ret) {
1951 ret = LTTNG_ERR_SAVE_IO_FAIL;
1952 goto end;
1953 }
1954
1955 /* /consumer_output */
1956 ret = config_writer_close_element(writer);
1957 if (ret) {
1958 ret = LTTNG_ERR_SAVE_IO_FAIL;
1959 goto end;
1960 }
a24248b3
MD
1961
1962 ret = LTTNG_OK;
fb198a11
JG
1963end:
1964 return ret;
1965}
1966
a24248b3 1967/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
1968static
1969int save_snapshot_outputs(struct config_writer *writer,
1970 struct snapshot *snapshot)
1971{
1972 int ret;
1973 struct lttng_ht_iter iter;
1974 struct snapshot_output *output;
1975
1976 assert(writer);
1977 assert(snapshot);
1978
1979 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1980 if (ret) {
1981 ret = LTTNG_ERR_SAVE_IO_FAIL;
1982 goto end;
1983 }
1984
1985 rcu_read_lock();
1986 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1987 node.node) {
1988 ret = config_writer_open_element(writer,
1989 config_element_output);
1990 if (ret) {
1991 ret = LTTNG_ERR_SAVE_IO_FAIL;
1992 goto end_unlock;
1993 }
1994
1995 ret = config_writer_write_element_string(writer,
1996 config_element_name, output->name);
1997 if (ret) {
1998 ret = LTTNG_ERR_SAVE_IO_FAIL;
1999 goto end_unlock;
2000 }
2001
2002 ret = config_writer_write_element_unsigned_int(writer,
2003 config_element_max_size, output->max_size);
2004 if (ret) {
2005 ret = LTTNG_ERR_SAVE_IO_FAIL;
2006 goto end_unlock;
2007 }
2008
2009 ret = save_consumer_output(writer, output->consumer);
a24248b3 2010 if (ret != LTTNG_OK) {
fb198a11
JG
2011 goto end_unlock;
2012 }
2013
2014 /* /output */
2015 ret = config_writer_close_element(writer);
2016 if (ret) {
2017 ret = LTTNG_ERR_SAVE_IO_FAIL;
2018 goto end_unlock;
2019 }
2020 }
2021 rcu_read_unlock();
2022
2023 /* /snapshot_outputs */
2024 ret = config_writer_close_element(writer);
2025 if (ret) {
2026 ret = LTTNG_ERR_SAVE_IO_FAIL;
2027 goto end;
2028 }
2029
a24248b3 2030 ret = LTTNG_OK;
fb198a11
JG
2031end:
2032 return ret;
2033end_unlock:
2034 rcu_read_unlock();
2035 return ret;
2036}
2037
a24248b3 2038/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
2039static
2040int save_session_output(struct config_writer *writer,
2041 struct ltt_session *session)
2042{
2043 int ret;
2044
2045 assert(writer);
2046 assert(session);
2047
2048 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
2049 (!session->snapshot_mode && !session->consumer)) {
2050 /* Session is in no output mode */
a24248b3 2051 ret = LTTNG_OK;
fb198a11
JG
2052 goto end;
2053 }
2054
2055 ret = config_writer_open_element(writer, config_element_output);
2056 if (ret) {
2057 ret = LTTNG_ERR_SAVE_IO_FAIL;
2058 goto end;
2059 }
2060
2061 if (session->snapshot_mode) {
2062 ret = save_snapshot_outputs(writer, &session->snapshot);
a24248b3 2063 if (ret != LTTNG_OK) {
fb198a11
JG
2064 goto end;
2065 }
2066 } else {
2067 if (session->consumer) {
2068 ret = save_consumer_output(writer, session->consumer);
a24248b3 2069 if (ret != LTTNG_OK) {
fb198a11
JG
2070 goto end;
2071 }
2072 }
2073 }
2074
2075 /* /output */
2076 ret = config_writer_close_element(writer);
2077 if (ret) {
2078 ret = LTTNG_ERR_SAVE_IO_FAIL;
2079 goto end;
2080 }
a24248b3 2081 ret = LTTNG_OK;
fb198a11
JG
2082end:
2083 return ret;
2084}
2085
2086/*
2087 * Save the given session.
2088 *
a24248b3 2089 * Return LTTNG_OK on success else a LTTNG_ERR* code.
fb198a11
JG
2090 */
2091static
2092int save_session(struct ltt_session *session,
2093 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
2094{
2095 int ret, fd;
db471218 2096 unsigned int file_opened = 0; /* Indicate if the file has been opened */
fb198a11
JG
2097 char config_file_path[PATH_MAX];
2098 size_t len;
2099 struct config_writer *writer = NULL;
2100 size_t session_name_len;
2101 const char *provided_path;
2102
2103 assert(session);
2104 assert(attr);
2105 assert(creds);
2106
2107 session_name_len = strlen(session->name);
95a29ab8 2108 memset(config_file_path, 0, sizeof(config_file_path));
fb198a11
JG
2109
2110 if (!session_access_ok(session,
2111 LTTNG_SOCK_GET_UID_CRED(creds),
2112 LTTNG_SOCK_GET_GID_CRED(creds))) {
2113 ret = LTTNG_ERR_EPERM;
2114 goto end;
2115 }
2116
2117 provided_path = lttng_save_session_attr_get_output_url(attr);
2118 if (provided_path) {
95a29ab8 2119 DBG3("Save session in provided path %s", provided_path);
fb198a11 2120 len = strlen(provided_path);
d2992717 2121 if (len >= sizeof(config_file_path)) {
fb198a11
JG
2122 ret = LTTNG_ERR_SET_URL;
2123 goto end;
2124 }
2125 strncpy(config_file_path, provided_path, len);
2126 } else {
7e078ad1 2127 ssize_t ret_len;
fb198a11
JG
2128 char *home_dir = utils_get_user_home_dir(
2129 LTTNG_SOCK_GET_UID_CRED(creds));
2130 if (!home_dir) {
2131 ret = LTTNG_ERR_SET_URL;
2132 goto end;
2133 }
2134
d2992717 2135 ret_len = snprintf(config_file_path, sizeof(config_file_path),
fb198a11
JG
2136 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
2137 free(home_dir);
7e078ad1 2138 if (ret_len < 0) {
fb198a11
JG
2139 PERROR("snprintf save session");
2140 ret = LTTNG_ERR_SET_URL;
2141 goto end;
2142 }
7e078ad1 2143 len = ret_len;
fb198a11
JG
2144 }
2145
2146 /*
d2992717
DG
2147 * Check the path fits in the config file path dst including the '/'
2148 * followed by trailing .lttng extension and the NULL terminated string.
fb198a11 2149 */
d2992717
DG
2150 if ((len + session_name_len + 2 +
2151 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
2152 > sizeof(config_file_path)) {
fb198a11
JG
2153 ret = LTTNG_ERR_SET_URL;
2154 goto end;
2155 }
2156
2157 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
2158 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
2159 if (ret) {
2160 ret = LTTNG_ERR_SET_URL;
2161 goto end;
2162 }
2163
d2992717
DG
2164 /*
2165 * At this point, we know that everything fits in the buffer. Validation
2166 * was done just above.
2167 */
fb198a11
JG
2168 config_file_path[len++] = '/';
2169 strncpy(config_file_path + len, session->name, session_name_len);
2170 len += session_name_len;
2171 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
95a29ab8
DG
2172 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
2173 config_file_path[len] = '\0';
fb198a11
JG
2174
2175 if (!access(config_file_path, F_OK) && !attr->overwrite) {
f9b57ab2
DG
2176 /* File exists, notify the user since the overwrite flag is off. */
2177 ret = LTTNG_ERR_SAVE_FILE_EXIST;
fb198a11
JG
2178 goto end;
2179 }
2180
2181 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
2182 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
2183 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
2184 if (fd < 0) {
2185 PERROR("Could not create configuration file");
2186 ret = LTTNG_ERR_SAVE_IO_FAIL;
2187 goto end;
2188 }
db471218 2189 file_opened = 1;
fb198a11 2190
705bb62f 2191 writer = config_writer_create(fd, 1);
fb198a11
JG
2192 if (!writer) {
2193 ret = LTTNG_ERR_NOMEM;
2194 goto end;
2195 }
2196
2197 ret = config_writer_open_element(writer, config_element_sessions);
2198 if (ret) {
2199 ret = LTTNG_ERR_SAVE_IO_FAIL;
2200 goto end;
2201 }
2202
2203 ret = config_writer_open_element(writer, config_element_session);
2204 if (ret) {
2205 ret = LTTNG_ERR_SAVE_IO_FAIL;
2206 goto end;
2207 }
2208
2209 ret = config_writer_write_element_string(writer, config_element_name,
2210 session->name);
2211 if (ret) {
2212 ret = LTTNG_ERR_SAVE_IO_FAIL;
2213 goto end;
2214 }
2215
a24248b3 2216 if (session->shm_path[0] != '\0') {
9e7c9f56
JR
2217 ret = config_writer_write_element_string(writer,
2218 config_element_shared_memory_path,
2219 session->shm_path);
2220 if (ret) {
2221 ret = LTTNG_ERR_SAVE_IO_FAIL;
2222 goto end;
2223 }
2224 }
2225
fb198a11 2226 ret = save_domains(writer, session);
a24248b3 2227 if (ret != LTTNG_OK) {
fb198a11
JG
2228 goto end;
2229 }
2230
2231 ret = config_writer_write_element_bool(writer, config_element_started,
8382cf6f 2232 session->active);
fb198a11
JG
2233 if (ret) {
2234 ret = LTTNG_ERR_SAVE_IO_FAIL;
2235 goto end;
2236 }
2237
329f3443
JD
2238 if (session->snapshot_mode || session->live_timer ||
2239 session->rotate_timer_period || session->rotate_size) {
fb198a11
JG
2240 ret = config_writer_open_element(writer, config_element_attributes);
2241 if (ret) {
2242 ret = LTTNG_ERR_SAVE_IO_FAIL;
2243 goto end;
2244 }
2245
2246 if (session->snapshot_mode) {
2247 ret = config_writer_write_element_bool(writer,
2248 config_element_snapshot_mode, 1);
2249 if (ret) {
2250 ret = LTTNG_ERR_SAVE_IO_FAIL;
2251 goto end;
2252 }
329f3443 2253 } else if (session->live_timer) {
d98ad589 2254 ret = config_writer_write_element_unsigned_int(writer,
fb198a11
JG
2255 config_element_live_timer_interval, session->live_timer);
2256 if (ret) {
2257 ret = LTTNG_ERR_SAVE_IO_FAIL;
2258 goto end;
2259 }
2260 }
329f3443
JD
2261 if (session->rotate_timer_period) {
2262 ret = config_writer_write_element_unsigned_int(writer,
2263 config_element_rotation_timer_interval,
2264 session->rotate_timer_period);
2265 if (ret) {
2266 ret = LTTNG_ERR_SAVE_IO_FAIL;
2267 goto end;
2268 }
2269 }
2270
2271 if (session->rotate_size) {
2272 ret = config_writer_write_element_unsigned_int(writer,
2273 config_element_rotation_size,
2274 session->rotate_size);
2275 if (ret) {
2276 ret = LTTNG_ERR_SAVE_IO_FAIL;
2277 goto end;
2278 }
2279 }
fb198a11
JG
2280
2281 /* /attributes */
2282 ret = config_writer_close_element(writer);
2283 if (ret) {
2284 ret = LTTNG_ERR_SAVE_IO_FAIL;
2285 goto end;
2286 }
2287 }
2288
2289 ret = save_session_output(writer, session);
a24248b3 2290 if (ret != LTTNG_OK) {
fb198a11
JG
2291 goto end;
2292 }
2293
2294 /* /session */
2295 ret = config_writer_close_element(writer);
2296 if (ret) {
2297 ret = LTTNG_ERR_SAVE_IO_FAIL;
2298 goto end;
2299 }
2300
2301 /* /sessions */
2302 ret = config_writer_close_element(writer);
2303 if (ret) {
2304 ret = LTTNG_ERR_SAVE_IO_FAIL;
2305 goto end;
2306 }
a24248b3
MD
2307
2308 ret = LTTNG_OK;
fb198a11
JG
2309end:
2310 if (writer && config_writer_destroy(writer)) {
2311 /* Preserve the original error code */
a24248b3 2312 ret = ret != LTTNG_OK ? ret : LTTNG_ERR_SAVE_IO_FAIL;
fb198a11 2313 }
a24248b3 2314 if (ret != LTTNG_OK) {
fb198a11 2315 /* Delete file in case of error */
db471218 2316 if (file_opened && unlink(config_file_path)) {
fb198a11
JG
2317 PERROR("Unlinking XML session configuration.");
2318 }
2319 }
2320
1d12100d 2321 if (file_opened) {
a24248b3
MD
2322 int closeret;
2323
2324 closeret = close(fd);
2325 if (closeret) {
1d12100d
JR
2326 PERROR("Closing XML session configuration");
2327 }
2328 }
2329
fb198a11
JG
2330 return ret;
2331}
2332
2333int cmd_save_sessions(struct lttng_save_session_attr *attr,
2334 lttng_sock_cred *creds)
2335{
2336 int ret;
2337 const char *session_name;
2338 struct ltt_session *session;
2339
2340 session_lock_list();
2341
2342 session_name = lttng_save_session_attr_get_session_name(attr);
2343 if (session_name) {
2344 session = session_find_by_name(session_name);
2345 if (!session) {
2346 ret = LTTNG_ERR_SESS_NOT_FOUND;
2347 goto end;
2348 }
2349
2350 session_lock(session);
2351 ret = save_session(session, attr, creds);
2352 session_unlock(session);
a24248b3 2353 if (ret != LTTNG_OK) {
fb198a11
JG
2354 goto end;
2355 }
2356 } else {
2357 struct ltt_session_list *list = session_get_list();
2358
2359 cds_list_for_each_entry(session, &list->head, list) {
2360 session_lock(session);
2361 ret = save_session(session, attr, creds);
2362 session_unlock(session);
2363
2364 /* Don't abort if we don't have the required permissions. */
a24248b3 2365 if (ret != LTTNG_OK && ret != LTTNG_ERR_EPERM) {
fb198a11
JG
2366 goto end;
2367 }
2368 }
2369 }
2370 ret = LTTNG_OK;
2371
2372end:
2373 session_unlock_list();
2374 return ret;
2375}
This page took 0.151982 seconds and 5 git commands to generate.