Fix: missing memset 0 and NULL byte in string
[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>
28#include <common/config/config-session-internal.h>
29#include <common/utils.h>
30#include <common/runas.h>
31#include <lttng/save-internal.h>
32
33#include "save.h"
34#include "session.h"
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;
262 default:
263 context_type_string = NULL;
264 }
265
266 return context_type_string;
267}
268
269static
270const char *get_buffer_type_string(
271 enum lttng_buffer_type buffer_type)
272{
273 const char *buffer_type_string;
274
275 switch (buffer_type) {
276 case LTTNG_BUFFER_PER_PID:
277 buffer_type_string = config_buffer_type_per_pid;
278 break;
279 case LTTNG_BUFFER_PER_UID:
280 buffer_type_string = config_buffer_type_per_uid;
281 break;
282 case LTTNG_BUFFER_GLOBAL:
283 buffer_type_string = config_buffer_type_global;
284 break;
285 default:
286 buffer_type_string = NULL;
287 }
288
289 return buffer_type_string;
290}
291
292static
293const char *get_loglevel_type_string(
294 enum lttng_ust_loglevel_type loglevel_type)
295{
296 const char *loglevel_type_string;
297
298 switch (loglevel_type) {
299 case LTTNG_UST_LOGLEVEL_ALL:
300 loglevel_type_string = config_loglevel_type_all;
301 break;
302 case LTTNG_UST_LOGLEVEL_RANGE:
303 loglevel_type_string = config_loglevel_type_range;
304 break;
305 case LTTNG_UST_LOGLEVEL_SINGLE:
306 loglevel_type_string = config_loglevel_type_single;
307 break;
308 default:
309 loglevel_type_string = NULL;
310 }
311
312 return loglevel_type_string;
313}
314
315static
316int save_kernel_event(struct config_writer *writer,
317 struct ltt_kernel_event *event)
318{
319 int ret;
320 const char *instrumentation_type;
321
322 ret = config_writer_open_element(writer, config_element_event);
323 if (ret) {
324 ret = LTTNG_ERR_SAVE_IO_FAIL;
325 goto end;
326 }
327
328 if (event->event->name[0]) {
329 ret = config_writer_write_element_string(writer,
330 config_element_name, event->event->name);
331 if (ret) {
332 ret = LTTNG_ERR_SAVE_IO_FAIL;
333 goto end;
334 }
335 }
336
337 ret = config_writer_write_element_bool(writer, config_element_enabled,
338 event->enabled);
339 if (ret) {
340 ret = LTTNG_ERR_SAVE_IO_FAIL;
341 goto end;
342 }
343
344 instrumentation_type = get_kernel_instrumentation_string(
345 event->event->instrumentation);
346 if (!instrumentation_type) {
347 ret = LTTNG_ERR_INVALID;
348 goto end;
349 }
350
351 ret = config_writer_write_element_string(writer, config_element_type,
352 instrumentation_type);
353 if (ret) {
354 ret = LTTNG_ERR_SAVE_IO_FAIL;
355 goto end;
356 }
357
358 if (event->event->instrumentation == LTTNG_KERNEL_FUNCTION ||
359 event->event->instrumentation == LTTNG_KERNEL_KPROBE ||
360 event->event->instrumentation == LTTNG_KERNEL_KRETPROBE) {
361
362 ret = config_writer_open_element(writer,
363 config_element_attributes);
364 if (ret) {
365 ret = LTTNG_ERR_SAVE_IO_FAIL;
366 goto end;
367 }
368
369 switch (event->event->instrumentation) {
370 case LTTNG_KERNEL_FUNCTION:
371 ret = config_writer_open_element(writer,
372 config_element_function_attributes);
373 if (ret) {
374 ret = LTTNG_ERR_SAVE_IO_FAIL;
375 goto end;
376 }
377
378 ret = config_writer_write_element_string(writer,
379 config_element_name,
380 event->event->u.ftrace.symbol_name);
381 if (ret) {
382 ret = LTTNG_ERR_SAVE_IO_FAIL;
383 goto end;
384 }
385
386 /* /function attributes */
387 ret = config_writer_close_element(writer);
388 if (ret) {
389 ret = LTTNG_ERR_SAVE_IO_FAIL;
390 goto end;
391 }
392 break;
393 case LTTNG_KERNEL_KPROBE:
394 case LTTNG_KERNEL_KRETPROBE:
395 {
396 const char *symbol_name;
397 uint64_t addr;
398 uint64_t offset;
399
400 if (event->event->instrumentation ==
401 LTTNG_KERNEL_KPROBE) {
402 /*
403 * Comments in lttng-kernel.h mention that
404 * either addr or symbol_name are set, not both.
405 */
406 addr = event->event->u.kprobe.addr;
407 offset = event->event->u.kprobe.offset;
408 symbol_name = addr ? NULL :
409 event->event->u.kprobe.symbol_name;
410 } else {
411 symbol_name =
412 event->event->u.kretprobe.symbol_name;
413 addr = event->event->u.kretprobe.addr;
414 offset = event->event->u.kretprobe.offset;
415 }
416
417 ret = config_writer_open_element(writer,
418 config_element_probe_attributes);
419 if (ret) {
420 ret = LTTNG_ERR_SAVE_IO_FAIL;
421 goto end;
422 }
423
424 if (symbol_name) {
425 ret = config_writer_write_element_string(writer,
426 config_element_symbol_name,
427 symbol_name);
428 if (ret) {
429 ret = LTTNG_ERR_SAVE_IO_FAIL;
430 goto end;
431 }
432 }
433
434 if (addr) {
435 ret = config_writer_write_element_unsigned_int(
436 writer, config_element_address, addr);
437 if (ret) {
438 ret = LTTNG_ERR_SAVE_IO_FAIL;
439 goto end;
440 }
441 }
442
443 if (offset) {
444 ret = config_writer_write_element_unsigned_int(
445 writer, config_element_offset, offset);
446 if (ret) {
447 ret = LTTNG_ERR_SAVE_IO_FAIL;
448 goto end;
449 }
450 }
451
452 ret = config_writer_close_element(writer);
453 if (ret) {
454 ret = LTTNG_ERR_SAVE_IO_FAIL;
455 goto end;
456 }
457 break;
458 }
459 default:
460 ERR("Unsupported kernel instrumentation type.");
461 ret = LTTNG_ERR_INVALID;
462 goto end;
463 }
464
465 /* /attributes */
466 ret = config_writer_close_element(writer);
467 if (ret) {
468 ret = LTTNG_ERR_SAVE_IO_FAIL;
469 goto end;
470 }
471 }
472
473 /* /event */
474 ret = config_writer_close_element(writer);
475 if (ret) {
476 ret = LTTNG_ERR_SAVE_IO_FAIL;
477 goto end;
478 }
479end:
480 return ret;
481}
482
483static
484int save_kernel_events(struct config_writer *writer,
485 struct ltt_kernel_event_list *event_list)
486{
487 int ret;
488 struct ltt_kernel_event *event;
489
490 ret = config_writer_open_element(writer, config_element_events);
491 if (ret) {
492 ret = LTTNG_ERR_SAVE_IO_FAIL;
493 goto end;
494 }
495
496 cds_list_for_each_entry(event, &event_list->head, list) {
497 ret = save_kernel_event(writer, event);
498 if (ret) {
499 goto end;
500 }
501 }
502
503 /* /events */
504 ret = config_writer_close_element(writer);
505 if (ret) {
506 ret = LTTNG_ERR_SAVE_IO_FAIL;
507 goto end;
508 }
509end:
510 return ret;
511}
512
513static
514int save_ust_event(struct config_writer *writer,
515 struct ltt_ust_event *event)
516{
517 int ret;
518 const char *loglevel_type_string;
519
520 ret = config_writer_open_element(writer, config_element_event);
521 if (ret) {
522 ret = LTTNG_ERR_SAVE_IO_FAIL;
523 goto end;
524 }
525
526 if (event->attr.name[0]) {
527 ret = config_writer_write_element_string(writer,
528 config_element_name, event->attr.name);
529 if (ret) {
530 ret = LTTNG_ERR_SAVE_IO_FAIL;
531 goto end;
532 }
533 }
534
535 ret = config_writer_write_element_bool(writer, config_element_enabled,
536 event->enabled);
537 if (ret) {
538 ret = LTTNG_ERR_SAVE_IO_FAIL;
539 goto end;
540 }
541
542 if (event->attr.instrumentation != LTTNG_UST_TRACEPOINT) {
543 ERR("Unsupported UST instrumentation type.");
544 ret = LTTNG_ERR_INVALID;
545 goto end;
546 }
547 ret = config_writer_write_element_string(writer, config_element_type,
548 config_event_type_tracepoint);
549 if (ret) {
550 ret = LTTNG_ERR_SAVE_IO_FAIL;
551 goto end;
552 }
553
554 loglevel_type_string = get_loglevel_type_string(
555 event->attr.loglevel_type);
556 if (!loglevel_type_string) {
557 ERR("Unsupported UST loglevel type.");
558 ret = LTTNG_ERR_INVALID;
559 goto end;
560 }
561
562 ret = config_writer_write_element_string(writer,
563 config_element_loglevel_type, loglevel_type_string);
564 if (ret) {
565 ret = LTTNG_ERR_SAVE_IO_FAIL;
566 goto end;
567 }
568
569 ret = config_writer_write_element_signed_int(writer,
570 config_element_loglevel, event->attr.loglevel);
571 if (ret) {
572 ret = LTTNG_ERR_SAVE_IO_FAIL;
573 goto end;
574 }
575
576 if (event->filter_expression) {
577 ret = config_writer_write_element_string(writer,
578 config_element_filter, event->filter_expression);
579 if (ret) {
580 ret = LTTNG_ERR_SAVE_IO_FAIL;
581 goto end;
582 }
583 }
584
585 if (event->exclusion && event->exclusion->count) {
586 uint32_t i;
587
588 ret = config_writer_open_element(writer,
589 config_element_exclusions);
590 if (ret) {
591 ret = LTTNG_ERR_SAVE_IO_FAIL;
592 goto end;
593 }
594
595 for (i = 0; i < event->exclusion->count; i++) {
596 ret = config_writer_write_element_string(writer,
597 config_element_exclusion,
598 &event->exclusion->names[0][i]);
599 if (ret) {
600 ret = LTTNG_ERR_SAVE_IO_FAIL;
601 goto end;
602 }
603 }
604
605 /* /exclusions */
606 ret = config_writer_close_element(writer);
607 if (ret) {
608 ret = LTTNG_ERR_SAVE_IO_FAIL;
609 goto end;
610 }
611 }
612
613 /* /event */
614 ret = config_writer_close_element(writer);
615 if (ret) {
616 ret = LTTNG_ERR_SAVE_IO_FAIL;
617 goto end;
618 }
619end:
620 return ret;
621}
622
623static
624int save_ust_events(struct config_writer *writer,
625 struct lttng_ht *events)
626{
627 int ret;
628 struct ltt_ust_event *event;
629 struct lttng_ht_node_str *node;
630 struct lttng_ht_iter iter;
631
632 ret = config_writer_open_element(writer, config_element_events);
633 if (ret) {
634 ret = LTTNG_ERR_SAVE_IO_FAIL;
635 goto end;
636 }
637
638 rcu_read_lock();
639 cds_lfht_for_each_entry(events->ht, &iter.iter, node, node) {
640 event = caa_container_of(node, struct ltt_ust_event, node);
641
642 ret = save_ust_event(writer, event);
643 if (ret) {
644 rcu_read_unlock();
645 goto end;
646 }
647 }
648 rcu_read_unlock();
649
650 /* /events */
651 ret = config_writer_close_element(writer);
652 if (ret) {
653 ret = LTTNG_ERR_SAVE_IO_FAIL;
654 goto end;
655 }
656end:
657 return ret;
658}
659
660static
661int save_kernel_context(struct config_writer *writer,
662 struct lttng_kernel_context *ctx)
663{
664 int ret = 0;
665
666 if (!ctx) {
667 goto end;
668 }
669
670 ret = config_writer_open_element(writer, config_element_contexts);
671 if (ret) {
672 ret = LTTNG_ERR_SAVE_IO_FAIL;
673 goto end;
674 }
675
676 ret = config_writer_open_element(writer, config_element_context);
677 if (ret) {
678 ret = LTTNG_ERR_SAVE_IO_FAIL;
679 goto end;
680 }
681
682 if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_COUNTER) {
683 ret = config_writer_open_element(writer, config_element_perf);
684 if (ret) {
685 ret = LTTNG_ERR_SAVE_IO_FAIL;
686 goto end;
687 }
688
689 ret = config_writer_write_element_unsigned_int(writer,
690 config_element_type, ctx->u.perf_counter.type);
691 if (ret) {
692 ret = LTTNG_ERR_SAVE_IO_FAIL;
693 goto end;
694 }
695
696 ret = config_writer_write_element_unsigned_int(writer,
697 config_element_config, ctx->u.perf_counter.config);
698 if (ret) {
699 ret = LTTNG_ERR_SAVE_IO_FAIL;
700 goto end;
701 }
702
703 ret = config_writer_write_element_string(writer,
704 config_element_name, ctx->u.perf_counter.name);
705 if (ret) {
706 ret = LTTNG_ERR_SAVE_IO_FAIL;
707 goto end;
708 }
709
710 /* /perf */
711 ret = config_writer_close_element(writer);
712 if (ret) {
713 ret = LTTNG_ERR_SAVE_IO_FAIL;
714 goto end;
715 }
716 } else {
717 const char *context_type_string =
718 get_kernel_context_type_string(ctx->ctx);
719
720 if (!context_type_string) {
721 ERR("Unsupported kernel context type.");
722 ret = LTTNG_ERR_INVALID;
723 goto end;
724 }
725
726 ret = config_writer_write_element_string(writer,
727 config_element_type, context_type_string);
728 if (ret) {
729 ret = LTTNG_ERR_SAVE_IO_FAIL;
730 goto end;
731 }
732 }
733
734 /* /context */
735 ret = config_writer_close_element(writer);
736 if (ret) {
737 ret = LTTNG_ERR_SAVE_IO_FAIL;
738 goto end;
739 }
740
741 /* /contexts */
742 ret = config_writer_close_element(writer);
743 if (ret) {
744 ret = LTTNG_ERR_SAVE_IO_FAIL;
745 goto end;
746 }
747end:
748 return ret;
749}
750
751static
752int save_ust_context(struct config_writer *writer,
753 struct cds_list_head *ctx_list)
754{
755 int ret;
756 struct ltt_ust_context *ctx;
757
758 assert(writer);
759 assert(ctx_list);
760
761 ret = config_writer_open_element(writer, config_element_contexts);
762 if (ret) {
763 ret = LTTNG_ERR_SAVE_IO_FAIL;
764 goto end;
765 }
766
767 cds_list_for_each_entry(ctx, ctx_list, list) {
768 const char *context_type_string;
769
770 context_type_string = get_ust_context_type_string(ctx->ctx.ctx);
771 if (!context_type_string) {
772 ERR("Unsupported UST context type.")
773 ret = LTTNG_ERR_INVALID;
774 goto end;
775 }
776
777 ret = config_writer_open_element(writer,
778 config_element_context);
779 if (ret) {
780 ret = LTTNG_ERR_SAVE_IO_FAIL;
781 goto end;
782 }
783
784 ret = config_writer_write_element_string(writer,
785 config_element_type, context_type_string);
786 if (ret) {
787 ret = LTTNG_ERR_SAVE_IO_FAIL;
788 goto end;
789 }
790
791 /* /context */
792 ret = config_writer_close_element(writer);
793 if (ret) {
794 ret = LTTNG_ERR_SAVE_IO_FAIL;
795 goto end;
796 }
797 }
798
799 /* /contexts */
800 ret = config_writer_close_element(writer);
801 if (ret) {
802 ret = LTTNG_ERR_SAVE_IO_FAIL;
803 goto end;
804 }
805end:
806 return ret;
807}
808
809static
810int save_kernel_channel(struct config_writer *writer,
811 struct ltt_kernel_channel *kchan)
812{
813 int ret;
814
815 assert(writer);
816 assert(kchan);
817
818 ret = config_writer_open_element(writer, config_element_channel);
819 if (ret) {
820 ret = LTTNG_ERR_SAVE_IO_FAIL;
821 goto end;
822 }
823
824 ret = config_writer_write_element_string(writer, config_element_name,
825 kchan->channel->name);
826 if (ret) {
827 ret = LTTNG_ERR_SAVE_IO_FAIL;
828 goto end;
829 }
830
831 ret = config_writer_write_element_bool(writer, config_element_enabled,
832 kchan->channel->enabled);
833 if (ret) {
834 ret = LTTNG_ERR_SAVE_IO_FAIL;
835 goto end;
836 }
837
838 ret = save_kernel_channel_attributes(writer, &kchan->channel->attr);
839 if (ret) {
840 goto end;
841 }
842
843 ret = save_kernel_events(writer, &kchan->events_list);
844 if (ret) {
845 goto end;
846 }
847
848 ret = save_kernel_context(writer, kchan->ctx);
849 if (ret) {
850 goto end;
851 }
852
853 /* /channel */
854 ret = config_writer_close_element(writer);
855 if (ret) {
856 ret = LTTNG_ERR_SAVE_IO_FAIL;
857 goto end;
858 }
859end:
860 return ret;
861}
862
863static
864int save_ust_channel(struct config_writer *writer,
865 struct ltt_ust_channel *ust_chan,
866 struct ltt_ust_session *session)
867{
868 int ret;
869
870 assert(writer);
871 assert(ust_chan);
872 assert(session);
873
874 ret = config_writer_open_element(writer, config_element_channel);
875 if (ret) {
876 ret = LTTNG_ERR_SAVE_IO_FAIL;
877 goto end;
878 }
879
880 ret = config_writer_write_element_string(writer, config_element_name,
881 ust_chan->name);
882 if (ret) {
883 ret = LTTNG_ERR_SAVE_IO_FAIL;
884 goto end;
885 }
886
887 ret = config_writer_write_element_bool(writer, config_element_enabled,
888 ust_chan->enabled);
889 if (ret) {
890 ret = LTTNG_ERR_SAVE_IO_FAIL;
891 goto end;
892 }
893
894 ret = save_ust_channel_attributes(writer, &ust_chan->attr);
895 if (ret) {
896 goto end;
897 }
898
899 ret = config_writer_write_element_unsigned_int(writer,
900 config_element_tracefile_size, ust_chan->tracefile_size);
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_tracefile_count, ust_chan->tracefile_count);
908 if (ret) {
909 ret = LTTNG_ERR_SAVE_IO_FAIL;
910 goto end;
911 }
912
913 ret = config_writer_write_element_unsigned_int(writer,
914 config_element_live_timer_interval,
915 session->live_timer_interval);
916 if (ret) {
917 ret = LTTNG_ERR_SAVE_IO_FAIL;
918 goto end;
919 }
920
921 ret = save_ust_events(writer, ust_chan->events);
922 if (ret) {
923 ret = LTTNG_ERR_SAVE_IO_FAIL;
924 goto end;
925 }
926
927 ret = save_ust_context(writer, &ust_chan->ctx_list);
928 if (ret) {
929 goto end;
930 }
931
932 /* /channel */
933 ret = config_writer_close_element(writer);
934 if (ret) {
935 ret = LTTNG_ERR_SAVE_IO_FAIL;
936 goto end;
937 }
938end:
939 return ret;
940}
941
942static
943int save_kernel_session(struct config_writer *writer,
944 struct ltt_session *session)
945{
946 int ret;
947 struct ltt_kernel_channel *kchan;
948
949 assert(writer);
950 assert(session);
951
952 ret = config_writer_write_element_string(writer, config_element_type,
953 config_domain_type_kernel);
954 if (ret) {
955 ret = LTTNG_ERR_SAVE_IO_FAIL;
956 goto end;
957 }
958
959 ret = config_writer_write_element_string(writer,
960 config_element_buffer_type, config_buffer_type_global);
961 if (ret) {
962 ret = LTTNG_ERR_SAVE_IO_FAIL;
963 goto end;
964 }
965
966 ret = config_writer_open_element(writer,
967 config_element_channels);
968 if (ret) {
969 ret = LTTNG_ERR_SAVE_IO_FAIL;
970 goto end;
971 }
972
973 cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head,
974 list) {
975 ret = save_kernel_channel(writer, kchan);
976 if (ret) {
977 goto end;
978 }
979 }
980
981 /* /channels */
982 ret = config_writer_close_element(writer);
983 if (ret) {
984 ret = LTTNG_ERR_SAVE_IO_FAIL;
985 goto end;
986 }
987end:
988 return ret;
989}
990
991static
992int save_ust_session(struct config_writer *writer,
993 struct ltt_session *session, int save_jul)
994{
995 int ret;
996 struct ltt_ust_channel *ust_chan;
997 const char *buffer_type_string;
998 struct lttng_ht_node_str *node;
999 struct lttng_ht_iter iter;
1000
1001 assert(writer);
1002 assert(session);
1003
1004 ret = config_writer_write_element_string(writer, config_element_type,
1005 save_jul ? config_domain_type_jul : config_domain_type_ust);
1006 if (ret) {
1007 ret = LTTNG_ERR_SAVE_IO_FAIL;
1008 goto end;
1009 }
1010
1011 buffer_type_string = get_buffer_type_string(
1012 session->ust_session->buffer_type);
1013 if (!buffer_type_string) {
1014 ERR("Unsupported buffer type.");
1015 ret = LTTNG_ERR_INVALID;
1016 goto end;
1017 }
1018
1019 ret = config_writer_write_element_string(writer,
1020 config_element_buffer_type, buffer_type_string);
1021 if (ret) {
1022 ret = LTTNG_ERR_SAVE_IO_FAIL;
1023 goto end;
1024 }
1025
1026 ret = config_writer_open_element(writer, config_element_channels);
1027 if (ret) {
1028 ret = LTTNG_ERR_SAVE_IO_FAIL;
1029 goto end;
1030 }
1031
1032 rcu_read_lock();
1033 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
1034 &iter.iter, node, node) {
1035 int jul_channel;
1036
1037 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
1038 jul_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name);
1039 if (!(save_jul ^ jul_channel)) {
1040 ret = save_ust_channel(writer, ust_chan, session->ust_session);
1041 if (ret) {
1042 rcu_read_unlock();
1043 goto end;
1044 }
1045 }
1046 }
1047 rcu_read_unlock();
1048
1049 /* /channels */
1050 ret = config_writer_close_element(writer);
1051 if (ret) {
1052 ret = LTTNG_ERR_SAVE_IO_FAIL;
1053 goto end;
1054 }
1055end:
1056 return ret;
1057}
1058
1059static
1060int save_domains(struct config_writer *writer, struct ltt_session *session)
1061{
1062 int ret = 0;
1063
1064 assert(writer);
1065 assert(session);
1066
1067 if (!session->kernel_session && !session->ust_session) {
1068 goto end;
1069 }
1070
1071 ret = config_writer_open_element(writer, config_element_domains);
1072 if (ret) {
1073 ret = LTTNG_ERR_SAVE_IO_FAIL;
1074 goto end;
1075 }
1076
1077
1078 if (session->kernel_session) {
1079 ret = config_writer_open_element(writer,
1080 config_element_domain);
1081 if (ret) {
1082 ret = LTTNG_ERR_SAVE_IO_FAIL;
1083 goto end;
1084 }
1085
1086 ret = save_kernel_session(writer, session);
1087 if (ret) {
1088 goto end;
1089 }
1090
1091 /* /domain */
1092 ret = config_writer_close_element(writer);
1093 if (ret) {
1094 ret = LTTNG_ERR_SAVE_IO_FAIL;
1095 goto end;
1096 }
1097 }
1098
1099 if (session->ust_session) {
1100 ret = config_writer_open_element(writer,
1101 config_element_domain);
1102 if (ret) {
1103 ret = LTTNG_ERR_SAVE_IO_FAIL;
1104 goto end;
1105 }
1106
1107 ret = save_ust_session(writer, session, 0);
1108 if (ret) {
1109 goto end;
1110 }
1111
1112 /* /domain */
1113 ret = config_writer_close_element(writer);
1114 if (ret) {
1115 ret = LTTNG_ERR_SAVE_IO_FAIL;
1116 goto end;
1117 }
1118 }
1119
1120 if (session->ust_session &&
1121 session->ust_session->domain_jul.being_used) {
1122 ret = config_writer_open_element(writer,
1123 config_element_domain);
1124 if (ret) {
1125 ret = LTTNG_ERR_SAVE_IO_FAIL;
1126 goto end;
1127 }
1128
1129 ret = save_ust_session(writer, session, 1);
1130 if (ret) {
1131 goto end;
1132 }
1133
1134 /* /domain */
1135 ret = config_writer_close_element(writer);
1136 if (ret) {
1137 ret = LTTNG_ERR_SAVE_IO_FAIL;
1138 goto end;
1139 }
1140 }
1141
1142 /* /domains */
1143 ret = config_writer_close_element(writer);
1144 if (ret) {
1145 ret = LTTNG_ERR_SAVE_IO_FAIL;
1146 goto end;
1147 }
1148end:
1149 return ret;
1150}
1151
1152static
1153int save_consumer_output(struct config_writer *writer,
1154 struct consumer_output *output)
1155{
1156 int ret;
1157
1158 assert(writer);
1159 assert(output);
1160
1161 ret = config_writer_open_element(writer, config_element_consumer_output);
1162 if (ret) {
1163 ret = LTTNG_ERR_SAVE_IO_FAIL;
1164 goto end;
1165 }
1166
1167 ret = config_writer_write_element_bool(writer, config_element_enabled,
1168 output->enabled);
1169 if (ret) {
1170 ret = LTTNG_ERR_SAVE_IO_FAIL;
1171 goto end;
1172 }
1173
1174 ret = config_writer_open_element(writer, config_element_destination);
1175 if (ret) {
1176 ret = LTTNG_ERR_SAVE_IO_FAIL;
1177 goto end;
1178 }
1179
1180 switch (output->type) {
1181 case CONSUMER_DST_LOCAL:
1182 ret = config_writer_write_element_string(writer,
1183 config_element_path, output->dst.trace_path);
1184 if (ret) {
1185 ret = LTTNG_ERR_SAVE_IO_FAIL;
1186 goto end;
1187 }
1188 break;
1189 case CONSUMER_DST_NET:
1190 {
1191 char *uri;
1192
1193 uri = zmalloc(PATH_MAX);
1194 if (!uri) {
1195 ret = LTTNG_ERR_NOMEM;
1196 goto end;
1197 }
1198
1199 ret = config_writer_open_element(writer, config_element_net_output);
1200 if (ret) {
1201 ret = LTTNG_ERR_SAVE_IO_FAIL;
1202 goto end_net_output;
1203 }
1204
1205 if (output->dst.net.control_isset &&
1206 output->dst.net.data_isset) {
1207 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1208 if (ret < 0) {
1209 ret = LTTNG_ERR_INVALID;
1210 goto end_net_output;
1211 }
1212
1213 ret = config_writer_write_element_string(writer,
1214 config_element_control_uri, uri);
1215 if (ret) {
1216 ret = LTTNG_ERR_SAVE_IO_FAIL;
1217 goto end_net_output;
1218 }
1219
1220 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1221 if (ret < 0) {
1222 ret = LTTNG_ERR_INVALID;
1223 goto end_net_output;
1224 }
1225
1226 ret = config_writer_write_element_string(writer,
1227 config_element_data_uri, uri);
1228 if (ret) {
1229 ret = LTTNG_ERR_SAVE_IO_FAIL;
1230 goto end_net_output;
1231 }
1232
1233end_net_output:
1234 free(uri);
1235 if (ret) {
1236 goto end;
1237 }
1238 } else {
1239 ret = !output->dst.net.control_isset ?
1240 LTTNG_ERR_URL_CTRL_MISS :
1241 LTTNG_ERR_URL_DATA_MISS;
c39270e5 1242 free(uri);
fb198a11
JG
1243 goto end;
1244 }
1245
1246 ret = config_writer_close_element(writer);
1247 if (ret) {
1248 ret = LTTNG_ERR_SAVE_IO_FAIL;
1249 goto end;
1250 }
1251 break;
1252 }
1253 default:
1254 ERR("Unsupported consumer output type.");
1255 ret = LTTNG_ERR_INVALID;
1256 goto end;
1257 }
1258
1259 /* /destination */
1260 ret = config_writer_close_element(writer);
1261 if (ret) {
1262 ret = LTTNG_ERR_SAVE_IO_FAIL;
1263 goto end;
1264 }
1265
1266 /* /consumer_output */
1267 ret = config_writer_close_element(writer);
1268 if (ret) {
1269 ret = LTTNG_ERR_SAVE_IO_FAIL;
1270 goto end;
1271 }
1272end:
1273 return ret;
1274}
1275
1276static
1277int save_snapshot_outputs(struct config_writer *writer,
1278 struct snapshot *snapshot)
1279{
1280 int ret;
1281 struct lttng_ht_iter iter;
1282 struct snapshot_output *output;
1283
1284 assert(writer);
1285 assert(snapshot);
1286
1287 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1288 if (ret) {
1289 ret = LTTNG_ERR_SAVE_IO_FAIL;
1290 goto end;
1291 }
1292
1293 rcu_read_lock();
1294 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1295 node.node) {
1296 ret = config_writer_open_element(writer,
1297 config_element_output);
1298 if (ret) {
1299 ret = LTTNG_ERR_SAVE_IO_FAIL;
1300 goto end_unlock;
1301 }
1302
1303 ret = config_writer_write_element_string(writer,
1304 config_element_name, output->name);
1305 if (ret) {
1306 ret = LTTNG_ERR_SAVE_IO_FAIL;
1307 goto end_unlock;
1308 }
1309
1310 ret = config_writer_write_element_unsigned_int(writer,
1311 config_element_max_size, output->max_size);
1312 if (ret) {
1313 ret = LTTNG_ERR_SAVE_IO_FAIL;
1314 goto end_unlock;
1315 }
1316
1317 ret = save_consumer_output(writer, output->consumer);
1318 if (ret) {
1319 goto end_unlock;
1320 }
1321
1322 /* /output */
1323 ret = config_writer_close_element(writer);
1324 if (ret) {
1325 ret = LTTNG_ERR_SAVE_IO_FAIL;
1326 goto end_unlock;
1327 }
1328 }
1329 rcu_read_unlock();
1330
1331 /* /snapshot_outputs */
1332 ret = config_writer_close_element(writer);
1333 if (ret) {
1334 ret = LTTNG_ERR_SAVE_IO_FAIL;
1335 goto end;
1336 }
1337
1338end:
1339 return ret;
1340end_unlock:
1341 rcu_read_unlock();
1342 return ret;
1343}
1344
1345static
1346int save_session_output(struct config_writer *writer,
1347 struct ltt_session *session)
1348{
1349 int ret;
1350
1351 assert(writer);
1352 assert(session);
1353
1354 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
1355 (!session->snapshot_mode && !session->consumer)) {
1356 /* Session is in no output mode */
1357 ret = 0;
1358 goto end;
1359 }
1360
1361 ret = config_writer_open_element(writer, config_element_output);
1362 if (ret) {
1363 ret = LTTNG_ERR_SAVE_IO_FAIL;
1364 goto end;
1365 }
1366
1367 if (session->snapshot_mode) {
1368 ret = save_snapshot_outputs(writer, &session->snapshot);
1369 if (ret) {
1370 goto end;
1371 }
1372 } else {
1373 if (session->consumer) {
1374 ret = save_consumer_output(writer, session->consumer);
1375 if (ret) {
1376 goto end;
1377 }
1378 }
1379 }
1380
1381 /* /output */
1382 ret = config_writer_close_element(writer);
1383 if (ret) {
1384 ret = LTTNG_ERR_SAVE_IO_FAIL;
1385 goto end;
1386 }
1387end:
1388 return ret;
1389}
1390
1391/*
1392 * Save the given session.
1393 *
1394 * Return 0 on success else a LTTNG_ERR* code.
1395 */
1396static
1397int save_session(struct ltt_session *session,
1398 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1399{
1400 int ret, fd;
db471218 1401 unsigned int file_opened = 0; /* Indicate if the file has been opened */
fb198a11
JG
1402 char config_file_path[PATH_MAX];
1403 size_t len;
1404 struct config_writer *writer = NULL;
1405 size_t session_name_len;
1406 const char *provided_path;
1407
1408 assert(session);
1409 assert(attr);
1410 assert(creds);
1411
1412 session_name_len = strlen(session->name);
95a29ab8 1413 memset(config_file_path, 0, sizeof(config_file_path));
fb198a11
JG
1414
1415 if (!session_access_ok(session,
1416 LTTNG_SOCK_GET_UID_CRED(creds),
1417 LTTNG_SOCK_GET_GID_CRED(creds))) {
1418 ret = LTTNG_ERR_EPERM;
1419 goto end;
1420 }
1421
1422 provided_path = lttng_save_session_attr_get_output_url(attr);
1423 if (provided_path) {
95a29ab8 1424 DBG3("Save session in provided path %s", provided_path);
fb198a11 1425 len = strlen(provided_path);
d2992717 1426 if (len >= sizeof(config_file_path)) {
fb198a11
JG
1427 ret = LTTNG_ERR_SET_URL;
1428 goto end;
1429 }
1430 strncpy(config_file_path, provided_path, len);
1431 } else {
7e078ad1 1432 ssize_t ret_len;
fb198a11
JG
1433 char *home_dir = utils_get_user_home_dir(
1434 LTTNG_SOCK_GET_UID_CRED(creds));
1435 if (!home_dir) {
1436 ret = LTTNG_ERR_SET_URL;
1437 goto end;
1438 }
1439
d2992717 1440 ret_len = snprintf(config_file_path, sizeof(config_file_path),
fb198a11
JG
1441 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1442 free(home_dir);
7e078ad1 1443 if (ret_len < 0) {
fb198a11
JG
1444 PERROR("snprintf save session");
1445 ret = LTTNG_ERR_SET_URL;
1446 goto end;
1447 }
7e078ad1 1448 len = ret_len;
fb198a11
JG
1449 }
1450
1451 /*
d2992717
DG
1452 * Check the path fits in the config file path dst including the '/'
1453 * followed by trailing .lttng extension and the NULL terminated string.
fb198a11 1454 */
d2992717
DG
1455 if ((len + session_name_len + 2 +
1456 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1457 > sizeof(config_file_path)) {
fb198a11
JG
1458 ret = LTTNG_ERR_SET_URL;
1459 goto end;
1460 }
1461
1462 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1463 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1464 if (ret) {
1465 ret = LTTNG_ERR_SET_URL;
1466 goto end;
1467 }
1468
d2992717
DG
1469 /*
1470 * At this point, we know that everything fits in the buffer. Validation
1471 * was done just above.
1472 */
fb198a11
JG
1473 config_file_path[len++] = '/';
1474 strncpy(config_file_path + len, session->name, session_name_len);
1475 len += session_name_len;
1476 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
95a29ab8
DG
1477 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1478 config_file_path[len] = '\0';
fb198a11
JG
1479
1480 if (!access(config_file_path, F_OK) && !attr->overwrite) {
1481 /* A file with the same name already exists, skip */
1482 goto end;
1483 }
1484
1485 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1486 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1487 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1488 if (fd < 0) {
1489 PERROR("Could not create configuration file");
1490 ret = LTTNG_ERR_SAVE_IO_FAIL;
1491 goto end;
1492 }
db471218 1493 file_opened = 1;
fb198a11
JG
1494
1495 writer = config_writer_create(fd);
1496 if (!writer) {
1497 ret = LTTNG_ERR_NOMEM;
1498 goto end;
1499 }
1500
1501 ret = config_writer_open_element(writer, config_element_sessions);
1502 if (ret) {
1503 ret = LTTNG_ERR_SAVE_IO_FAIL;
1504 goto end;
1505 }
1506
1507 ret = config_writer_open_element(writer, config_element_session);
1508 if (ret) {
1509 ret = LTTNG_ERR_SAVE_IO_FAIL;
1510 goto end;
1511 }
1512
1513 ret = config_writer_write_element_string(writer, config_element_name,
1514 session->name);
1515 if (ret) {
1516 ret = LTTNG_ERR_SAVE_IO_FAIL;
1517 goto end;
1518 }
1519
1520 ret = save_domains(writer, session);
1521 if (ret) {
1522 goto end;
1523 }
1524
1525 ret = config_writer_write_element_bool(writer, config_element_started,
1526 session->enabled);
1527 if (ret) {
1528 ret = LTTNG_ERR_SAVE_IO_FAIL;
1529 goto end;
1530 }
1531
1532 if (session->snapshot_mode || session->live_timer) {
1533 ret = config_writer_open_element(writer, config_element_attributes);
1534 if (ret) {
1535 ret = LTTNG_ERR_SAVE_IO_FAIL;
1536 goto end;
1537 }
1538
1539 if (session->snapshot_mode) {
1540 ret = config_writer_write_element_bool(writer,
1541 config_element_snapshot_mode, 1);
1542 if (ret) {
1543 ret = LTTNG_ERR_SAVE_IO_FAIL;
1544 goto end;
1545 }
1546 } else {
1547 ret = config_writer_write_element_signed_int(writer,
1548 config_element_live_timer_interval, session->live_timer);
1549 if (ret) {
1550 ret = LTTNG_ERR_SAVE_IO_FAIL;
1551 goto end;
1552 }
1553 }
1554
1555 /* /attributes */
1556 ret = config_writer_close_element(writer);
1557 if (ret) {
1558 ret = LTTNG_ERR_SAVE_IO_FAIL;
1559 goto end;
1560 }
1561 }
1562
1563 ret = save_session_output(writer, session);
1564 if (ret) {
1565 goto end;
1566 }
1567
1568 /* /session */
1569 ret = config_writer_close_element(writer);
1570 if (ret) {
1571 ret = LTTNG_ERR_SAVE_IO_FAIL;
1572 goto end;
1573 }
1574
1575 /* /sessions */
1576 ret = config_writer_close_element(writer);
1577 if (ret) {
1578 ret = LTTNG_ERR_SAVE_IO_FAIL;
1579 goto end;
1580 }
1581end:
1582 if (writer && config_writer_destroy(writer)) {
1583 /* Preserve the original error code */
1584 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
1585 }
1586 if (ret) {
1587 /* Delete file in case of error */
db471218 1588 if (file_opened && unlink(config_file_path)) {
fb198a11
JG
1589 PERROR("Unlinking XML session configuration.");
1590 }
1591 }
1592
1593 return ret;
1594}
1595
1596int cmd_save_sessions(struct lttng_save_session_attr *attr,
1597 lttng_sock_cred *creds)
1598{
1599 int ret;
1600 const char *session_name;
1601 struct ltt_session *session;
1602
1603 session_lock_list();
1604
1605 session_name = lttng_save_session_attr_get_session_name(attr);
1606 if (session_name) {
1607 session = session_find_by_name(session_name);
1608 if (!session) {
1609 ret = LTTNG_ERR_SESS_NOT_FOUND;
1610 goto end;
1611 }
1612
1613 session_lock(session);
1614 ret = save_session(session, attr, creds);
1615 session_unlock(session);
1616 if (ret) {
1617 goto end;
1618 }
1619 } else {
1620 struct ltt_session_list *list = session_get_list();
1621
1622 cds_list_for_each_entry(session, &list->head, list) {
1623 session_lock(session);
1624 ret = save_session(session, attr, creds);
1625 session_unlock(session);
1626
1627 /* Don't abort if we don't have the required permissions. */
1628 if (ret && ret != LTTNG_ERR_EPERM) {
1629 goto end;
1630 }
1631 }
1632 }
1633 ret = LTTNG_OK;
1634
1635end:
1636 session_unlock_list();
1637 return ret;
1638}
This page took 0.081092 seconds and 4 git commands to generate.