clang-tidy: add Chrome-inspired checks
[lttng-tools.git] / src / bin / lttng / commands / list.cpp
CommitLineData
f3ed775e 1/*
21cf9b6b 2 * Copyright (C) 2011 EfficiOS Inc.
159b042f 3 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
f3ed775e 4 *
ab5be9fa 5 * SPDX-License-Identifier: GPL-2.0-only
f3ed775e 6 *
f3ed775e
DG
7 */
8
159b042f 9#include <stdint.h>
6c1c0768 10#define _LGPL_SOURCE
28ab034a 11#include "../command.hpp"
f3ed775e 12
c9e313bc
SM
13#include <common/mi-lttng.hpp>
14#include <common/time.hpp>
15#include <common/tracker.hpp>
28ab034a 16
c9e313bc 17#include <lttng/domain-internal.hpp>
050dd639 18#include <lttng/lttng.h>
fb14d0d8 19
28ab034a
JG
20#include <inttypes.h>
21#include <popt.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
f3ed775e 25
9f19cc17
DG
26static int opt_userspace;
27static int opt_kernel;
3c6a091f 28static int opt_jul;
5cdb6027 29static int opt_log4j;
0e115563 30static int opt_python;
9f19cc17
DG
31static char *opt_channel;
32static int opt_domain;
f37d259d 33static int opt_fields;
834978fd 34static int opt_syscall;
9f19cc17
DG
35
36const char *indent4 = " ";
37const char *indent6 = " ";
38const char *indent8 = " ";
f3ed775e 39
4fc83d94
PP
40#ifdef LTTNG_EMBED_HELP
41static const char help_msg[] =
42#include <lttng-list.1.h>
28ab034a 43 ;
4fc83d94
PP
44#endif
45
f3ed775e
DG
46enum {
47 OPT_HELP = 1,
eeac7d46 48 OPT_USERSPACE,
679b4943 49 OPT_LIST_OPTIONS,
f3ed775e
DG
50};
51
41493f4a
SM
52static struct lttng_handle *the_handle;
53static struct mi_writer *the_writer;
cd80958d 54
e50e81d3 55/* Only set when listing a single session. */
41493f4a 56static struct lttng_session the_listed_session;
e50e81d3 57
f3ed775e
DG
58static struct poptOption long_options[] = {
59 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
cd9adb8b
JG
60 { "help", 'h', POPT_ARG_NONE, nullptr, OPT_HELP, nullptr, nullptr },
61 { "kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, nullptr, nullptr },
62 { "jul", 'j', POPT_ARG_VAL, &opt_jul, 1, nullptr, nullptr },
63 { "log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, nullptr, nullptr },
64 { "python", 'p', POPT_ARG_VAL, &opt_python, 1, nullptr, nullptr },
65 { "userspace", 'u', POPT_ARG_NONE, nullptr, OPT_USERSPACE, nullptr, nullptr },
66 { "channel", 'c', POPT_ARG_STRING, &opt_channel, 0, nullptr, nullptr },
67 { "domain", 'd', POPT_ARG_VAL, &opt_domain, 1, nullptr, nullptr },
68 { "fields", 'f', POPT_ARG_VAL, &opt_fields, 1, nullptr, nullptr },
69 { "syscall", 'S', POPT_ARG_VAL, &opt_syscall, 1, nullptr, nullptr },
70 { "list-options", 0, POPT_ARG_NONE, nullptr, OPT_LIST_OPTIONS, nullptr, nullptr },
71 { nullptr, 0, 0, nullptr, 0, nullptr, nullptr }
f3ed775e
DG
72};
73
f3ed775e 74/*
9f19cc17 75 * Get command line from /proc for a specific pid.
f3ed775e 76 *
9f19cc17
DG
77 * On success, return an allocated string pointer to the proc cmdline.
78 * On error, return NULL.
f3ed775e
DG
79 */
80static char *get_cmdline_by_pid(pid_t pid)
81{
82 int ret;
cd9adb8b
JG
83 FILE *fp = nullptr;
84 char *cmdline = nullptr;
fae9a062
JG
85 /* Can't go bigger than /proc/LTTNG_MAX_PID/cmdline */
86 char path[sizeof("/proc//cmdline") + sizeof(LTTNG_MAX_PID_STR) - 1];
f3ed775e
DG
87
88 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
89 fp = fopen(path, "r");
cd9adb8b 90 if (fp == nullptr) {
f3ed775e
DG
91 goto end;
92 }
93
94 /* Caller must free() *cmdline */
64803277 95 cmdline = zmalloc<char>(PATH_MAX);
f6962219 96 if (!cmdline) {
6f04ed72 97 PERROR("malloc cmdline");
f6962219
JG
98 goto end;
99 }
64803277 100
f3ed775e 101 ret = fread(cmdline, 1, PATH_MAX, fp);
f40799e8 102 if (ret < 0) {
6f04ed72 103 PERROR("fread proc list");
f40799e8 104 }
f3ed775e
DG
105
106end:
1ad31aec
DG
107 if (fp) {
108 fclose(fp);
109 }
f3ed775e
DG
110 return cmdline;
111}
b551a063 112
28ab034a 113static const char *active_string(int value)
464dd62d
MD
114{
115 switch (value) {
28ab034a
JG
116 case 0:
117 return "inactive";
118 case 1:
119 return "active";
120 case -1:
121 return "";
122 default:
cd9adb8b 123 return nullptr;
464dd62d
MD
124 }
125}
126
2cbf8fed
DG
127static const char *snapshot_string(int value)
128{
129 switch (value) {
130 case 1:
131 return " snapshot";
132 default:
133 return "";
134 }
135}
136
28ab034a 137static const char *enabled_string(int value)
464dd62d
MD
138{
139 switch (value) {
28ab034a
JG
140 case 0:
141 return " [disabled]";
142 case 1:
143 return " [enabled]";
144 case -1:
145 return "";
146 default:
cd9adb8b 147 return nullptr;
464dd62d
MD
148 }
149}
150
28ab034a 151static const char *safe_string(const char *str)
fceb65df 152{
7b4a95b1 153 return str ? str : "";
4634f12e
JI
154}
155
1f0e17de
DG
156static const char *logleveltype_string(enum lttng_loglevel_type value)
157{
158 switch (value) {
af6bce80
DG
159 case LTTNG_EVENT_LOGLEVEL_ALL:
160 return ":";
1f0e17de 161 case LTTNG_EVENT_LOGLEVEL_RANGE:
af6bce80 162 return " <=";
1f0e17de 163 case LTTNG_EVENT_LOGLEVEL_SINGLE:
af6bce80 164 return " ==";
1f0e17de 165 default:
af6bce80 166 return " <<TYPE UNKN>>";
1f0e17de
DG
167 }
168}
169
834978fd
DG
170static const char *bitness_event(enum lttng_event_flag flags)
171{
172 if (flags & LTTNG_EVENT_FLAG_SYSCALL_32) {
173 if (flags & LTTNG_EVENT_FLAG_SYSCALL_64) {
174 return " [32/64-bit]";
175 } else {
176 return " [32-bit]";
177 }
178 } else if (flags & LTTNG_EVENT_FLAG_SYSCALL_64) {
179 return " [64-bit]";
180 } else {
181 return "";
182 }
183}
184
7b4a95b1
PP
185/*
186 * Get exclusion names message for a single event.
187 *
188 * Returned pointer must be freed by caller. Returns NULL on error.
189 */
190static char *get_exclusion_names_msg(struct lttng_event *event)
191{
192 int ret;
193 int exclusion_count;
cd9adb8b 194 char *exclusion_msg = nullptr;
7b4a95b1 195 char *at;
7b4a95b1 196 size_t i;
28ab034a 197 const char *const exclusion_fmt = " [exclusions: ";
19ed7632 198 const size_t exclusion_fmt_len = strlen(exclusion_fmt);
7b4a95b1
PP
199
200 exclusion_count = lttng_event_get_exclusion_name_count(event);
201 if (exclusion_count < 0) {
202 goto end;
203 } else if (exclusion_count == 0) {
204 /*
205 * No exclusions: return copy of empty string so that
206 * it can be freed by caller.
207 */
208 exclusion_msg = strdup("");
209 goto end;
210 }
211
212 /*
213 * exclusion_msg's size is bounded by the exclusion_fmt string,
214 * a comma per entry, the entry count (fixed-size), a closing
215 * bracket, and a trailing \0.
216 */
28ab034a
JG
217 exclusion_msg = (char *) malloc(exclusion_count + exclusion_count * LTTNG_SYMBOL_NAME_LEN +
218 exclusion_fmt_len + 1);
7b4a95b1
PP
219 if (!exclusion_msg) {
220 goto end;
221 }
222
19ed7632 223 at = strcpy(exclusion_msg, exclusion_fmt) + exclusion_fmt_len;
7b4a95b1
PP
224 for (i = 0; i < exclusion_count; ++i) {
225 const char *name;
226
227 /* Append comma between exclusion names */
228 if (i > 0) {
229 *at = ',';
230 at++;
231 }
232
233 ret = lttng_event_get_exclusion_name(event, i, &name);
234 if (ret) {
235 /* Prints '?' on local error; should never happen */
236 *at = '?';
237 at++;
238 continue;
239 }
240
241 /* Append exclusion name */
31e40170 242 at += sprintf(at, "%s", name);
7b4a95b1
PP
243 }
244
245 /* This also puts a final '\0' at the end of exclusion_msg */
19ed7632 246 strcpy(at, "]");
7b4a95b1
PP
247
248end:
249 return exclusion_msg;
250}
251
b955b4d4
FD
252static void print_userspace_probe_location(struct lttng_event *event)
253{
87597c2c
JG
254 const struct lttng_userspace_probe_location *location;
255 const struct lttng_userspace_probe_location_lookup_method *lookup_method;
b955b4d4
FD
256 enum lttng_userspace_probe_location_lookup_method_type lookup_type;
257
258 location = lttng_event_get_userspace_probe_location(event);
259 if (!location) {
260 MSG("Event has no userspace probe location");
261 return;
262 }
263
264 lookup_method = lttng_userspace_probe_location_get_lookup_method(location);
265 if (!lookup_method) {
266 MSG("Event has no userspace probe location lookup method");
267 return;
268 }
269
270 MSG("%s%s (type: userspace-probe)%s", indent6, event->name, enabled_string(event->enabled));
271
272 lookup_type = lttng_userspace_probe_location_lookup_method_get_type(lookup_method);
273
274 switch (lttng_userspace_probe_location_get_type(location)) {
275 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN:
276 MSG("%sType: Unknown", indent8);
277 break;
278 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
279 {
280 const char *function_name;
4df1f2d4 281 char *binary_path;
b955b4d4
FD
282
283 MSG("%sType: Function", indent8);
284 function_name = lttng_userspace_probe_location_function_get_function_name(location);
28ab034a 285 binary_path = realpath(
cd9adb8b 286 lttng_userspace_probe_location_function_get_binary_path(location), nullptr);
b955b4d4
FD
287
288 MSG("%sBinary path: %s", indent8, binary_path ? binary_path : "NULL");
289 MSG("%sFunction: %s()", indent8, function_name ? function_name : "NULL");
290 switch (lookup_type) {
291 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
292 MSG("%sLookup method: ELF", indent8);
293 break;
294 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
295 MSG("%sLookup method: default", indent8);
296 break;
297 default:
298 MSG("%sLookup method: INVALID LOOKUP TYPE ENCOUNTERED", indent8);
299 break;
300 }
4df1f2d4
JG
301
302 free(binary_path);
b955b4d4
FD
303 break;
304 }
305 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
306 {
307 const char *probe_name, *provider_name;
4df1f2d4 308 char *binary_path;
b955b4d4
FD
309
310 MSG("%sType: Tracepoint", indent8);
311 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(location);
28ab034a
JG
312 provider_name =
313 lttng_userspace_probe_location_tracepoint_get_provider_name(location);
314 binary_path = realpath(
cd9adb8b
JG
315 lttng_userspace_probe_location_tracepoint_get_binary_path(location),
316 nullptr);
b955b4d4 317 MSG("%sBinary path: %s", indent8, binary_path ? binary_path : "NULL");
28ab034a
JG
318 MSG("%sTracepoint: %s:%s",
319 indent8,
320 provider_name ? provider_name : "NULL",
321 probe_name ? probe_name : "NULL");
b955b4d4
FD
322 switch (lookup_type) {
323 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
324 MSG("%sLookup method: SDT", indent8);
325 break;
326 default:
327 MSG("%sLookup method: INVALID LOOKUP TYPE ENCOUNTERED", indent8);
328 break;
329 }
4df1f2d4
JG
330
331 free(binary_path);
b955b4d4
FD
332 break;
333 }
334 default:
335 ERR("Invalid probe type encountered");
336 }
337}
338
b551a063
DG
339/*
340 * Pretty print single event.
341 */
342static void print_events(struct lttng_event *event)
343{
4adbcc72
PP
344 int ret;
345 const char *filter_str;
cd9adb8b
JG
346 char *filter_msg = nullptr;
347 char *exclusion_msg = nullptr;
4adbcc72 348
134e72ed 349 ret = lttng_event_get_filter_expression(event, &filter_str);
4adbcc72
PP
350
351 if (ret) {
352 filter_msg = strdup(" [failed to retrieve filter]");
353 } else if (filter_str) {
411b3154 354 if (asprintf(&filter_msg, " [filter: '%s']", filter_str) == -1) {
cd9adb8b 355 filter_msg = nullptr;
4adbcc72
PP
356 }
357 }
358
7b4a95b1
PP
359 exclusion_msg = get_exclusion_names_msg(event);
360 if (!exclusion_msg) {
361 exclusion_msg = strdup(" [failed to retrieve exclusions]");
362 }
363
b551a063
DG
364 switch (event->type) {
365 case LTTNG_EVENT_TRACEPOINT:
e4baff1e 366 {
8b703175 367 if (event->loglevel != -1) {
af6bce80 368 MSG("%s%s (loglevel%s %s (%d)) (type: tracepoint)%s%s%s",
28ab034a
JG
369 indent6,
370 event->name,
371 logleveltype_string(event->loglevel_type),
372 mi_lttng_loglevel_string(event->loglevel, the_handle->domain.type),
373 event->loglevel,
374 enabled_string(event->enabled),
375 safe_string(exclusion_msg),
376 safe_string(filter_msg));
8b703175 377 } else {
4634f12e 378 MSG("%s%s (type: tracepoint)%s%s%s",
28ab034a
JG
379 indent6,
380 event->name,
381 enabled_string(event->enabled),
382 safe_string(exclusion_msg),
383 safe_string(filter_msg));
8b703175 384 }
b551a063 385 break;
e4baff1e 386 }
1896972b 387 case LTTNG_EVENT_FUNCTION:
28ab034a
JG
388 MSG("%s%s (type: function)%s%s",
389 indent6,
390 event->name,
391 enabled_string(event->enabled),
392 safe_string(filter_msg));
1896972b
DG
393 if (event->attr.probe.addr != 0) {
394 MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr);
395 } else {
396 MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
397 MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
398 }
399 break;
b551a063 400 case LTTNG_EVENT_PROBE:
28ab034a
JG
401 MSG("%s%s (type: probe)%s%s",
402 indent6,
403 event->name,
404 enabled_string(event->enabled),
405 safe_string(filter_msg));
b551a063
DG
406 if (event->attr.probe.addr != 0) {
407 MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr);
408 } else {
409 MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
410 MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
411 }
412 break;
b955b4d4
FD
413 case LTTNG_EVENT_USERSPACE_PROBE:
414 print_userspace_probe_location(event);
415 break;
b551a063 416 case LTTNG_EVENT_FUNCTION_ENTRY:
28ab034a
JG
417 MSG("%s%s (type: function)%s%s",
418 indent6,
419 event->name,
420 enabled_string(event->enabled),
421 safe_string(filter_msg));
b551a063
DG
422 MSG("%ssymbol: \"%s\"", indent8, event->attr.ftrace.symbol_name);
423 break;
424 case LTTNG_EVENT_SYSCALL:
28ab034a
JG
425 MSG("%s%s%s%s%s%s",
426 indent6,
427 event->name,
428 (opt_syscall ? "" : " (type:syscall)"),
429 enabled_string(event->enabled),
430 bitness_event(event->flags),
431 safe_string(filter_msg));
b551a063
DG
432 break;
433 case LTTNG_EVENT_NOOP:
28ab034a
JG
434 MSG("%s (type: noop)%s%s",
435 indent6,
436 enabled_string(event->enabled),
437 safe_string(filter_msg));
b551a063
DG
438 break;
439 case LTTNG_EVENT_ALL:
410b78a0
FD
440 /* Fall-through. */
441 default:
b551a063 442 /* We should never have "all" events in list. */
a0377dfe 443 abort();
b551a063
DG
444 break;
445 }
4adbcc72
PP
446
447 free(filter_msg);
7b4a95b1 448 free(exclusion_msg);
b551a063
DG
449}
450
f37d259d
MD
451static const char *field_type(struct lttng_event_field *field)
452{
28ab034a 453 switch (field->type) {
f37d259d
MD
454 case LTTNG_EVENT_FIELD_INTEGER:
455 return "integer";
456 case LTTNG_EVENT_FIELD_ENUM:
457 return "enum";
458 case LTTNG_EVENT_FIELD_FLOAT:
459 return "float";
460 case LTTNG_EVENT_FIELD_STRING:
461 return "string";
462 case LTTNG_EVENT_FIELD_OTHER:
28ab034a 463 default: /* fall-through */
f37d259d
MD
464 return "unknown";
465 }
466}
467
468/*
469 * Pretty print single event fields.
470 */
471static void print_event_field(struct lttng_event_field *field)
472{
473 if (!field->field_name[0]) {
474 return;
475 }
28ab034a
JG
476 MSG("%sfield: %s (%s)%s",
477 indent8,
478 field->field_name,
479 field_type(field),
480 field->nowrite ? " [no write]" : "");
f37d259d
MD
481}
482
fb14d0d8
JR
483/*
484 * Machine interface
485 * Jul and ust event listing
486 */
28ab034a
JG
487static int
488mi_list_agent_ust_events(struct lttng_event *events, int count, struct lttng_domain *domain)
fb14d0d8
JR
489{
490 int ret, i;
491 pid_t cur_pid = 0;
cd9adb8b 492 char *cmdline = nullptr;
fb14d0d8
JR
493 int pid_element_open = 0;
494
495 /* Open domains element */
41493f4a 496 ret = mi_lttng_domains_open(the_writer);
fb14d0d8
JR
497 if (ret) {
498 goto end;
499 }
500
501 /* Write domain */
41493f4a 502 ret = mi_lttng_domain(the_writer, domain, 1);
fb14d0d8
JR
503 if (ret) {
504 goto end;
505 }
506
bf239d4c 507 /* Open pids element element */
41493f4a 508 ret = mi_lttng_pids_open(the_writer);
fb14d0d8
JR
509 if (ret) {
510 goto end;
511 }
512
513 for (i = 0; i < count; i++) {
514 if (cur_pid != events[i].pid) {
515 if (pid_element_open) {
2e9aecb9 516 /* Close the previous events and pid element */
28ab034a 517 ret = mi_lttng_close_multi_element(the_writer, 2);
fb14d0d8
JR
518 if (ret) {
519 goto end;
520 }
521 pid_element_open = 0;
522 }
523
524 cur_pid = events[i].pid;
525 cmdline = get_cmdline_by_pid(cur_pid);
526 if (!cmdline) {
527 ret = CMD_ERROR;
528 goto end;
529 }
530
531 if (!pid_element_open) {
532 /* Open and write a pid element */
28ab034a 533 ret = mi_lttng_pid(the_writer, cur_pid, cmdline, 1);
fb14d0d8
JR
534 if (ret) {
535 goto error;
536 }
537
538 /* Open events element */
41493f4a 539 ret = mi_lttng_events_open(the_writer);
fb14d0d8
JR
540 if (ret) {
541 goto error;
542 }
543
544 pid_element_open = 1;
545 }
546 free(cmdline);
547 }
548
549 /* Write an event */
28ab034a 550 ret = mi_lttng_event(the_writer, &events[i], 0, the_handle->domain.type);
fb14d0d8
JR
551 if (ret) {
552 goto end;
553 }
554 }
555
bf239d4c 556 /* Close pids */
41493f4a 557 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
558 if (ret) {
559 goto end;
560 }
561
562 /* Close domain, domains */
41493f4a 563 ret = mi_lttng_close_multi_element(the_writer, 2);
fb14d0d8
JR
564end:
565 return ret;
566error:
567 free(cmdline);
568 return ret;
569}
570
cd9adb8b 571static int list_agent_events()
3c6a091f 572{
fb14d0d8 573 int i, size, ret = CMD_SUCCESS;
3c6a091f 574 struct lttng_domain domain;
cd9adb8b
JG
575 struct lttng_handle *handle = nullptr;
576 struct lttng_event *event_list = nullptr;
3c6a091f 577 pid_t cur_pid = 0;
cd9adb8b 578 char *cmdline = nullptr;
5cdb6027 579 const char *agent_domain_str;
3c6a091f
DG
580
581 memset(&domain, 0, sizeof(domain));
5cdb6027
DG
582 if (opt_jul) {
583 domain.type = LTTNG_DOMAIN_JUL;
584 } else if (opt_log4j) {
585 domain.type = LTTNG_DOMAIN_LOG4J;
0e115563
DG
586 } else if (opt_python) {
587 domain.type = LTTNG_DOMAIN_PYTHON;
26c610c9
JG
588 } else {
589 ERR("Invalid agent domain selected.");
590 ret = CMD_ERROR;
591 goto error;
5cdb6027
DG
592 }
593
1004b719 594 agent_domain_str = lttng_domain_type_str(domain.type);
5cdb6027
DG
595
596 DBG("Getting %s tracing events", agent_domain_str);
3c6a091f 597
cd9adb8b
JG
598 handle = lttng_create_handle(nullptr, &domain);
599 if (handle == nullptr) {
fb14d0d8
JR
600 ret = CMD_ERROR;
601 goto end;
3c6a091f
DG
602 }
603
604 size = lttng_list_tracepoints(handle, &event_list);
605 if (size < 0) {
28ab034a 606 ERR("Unable to list %s events: %s", agent_domain_str, lttng_strerror(size));
fb14d0d8
JR
607 ret = CMD_ERROR;
608 goto end;
3c6a091f
DG
609 }
610
fb14d0d8
JR
611 if (lttng_opt_mi) {
612 /* Mi print */
5cdb6027 613 ret = mi_list_agent_ust_events(event_list, size, &domain);
fb14d0d8
JR
614 if (ret) {
615 ret = CMD_ERROR;
616 goto error;
3c6a091f 617 }
fb14d0d8
JR
618 } else {
619 /* Pretty print */
28ab034a 620 MSG("%s events (Logger name):\n-------------------------", agent_domain_str);
3c6a091f 621
fb14d0d8
JR
622 if (size == 0) {
623 MSG("None");
624 }
3c6a091f 625
fb14d0d8
JR
626 for (i = 0; i < size; i++) {
627 if (cur_pid != event_list[i].pid) {
628 cur_pid = event_list[i].pid;
629 cmdline = get_cmdline_by_pid(cur_pid);
cd9adb8b 630 if (cmdline == nullptr) {
fb14d0d8
JR
631 ret = CMD_ERROR;
632 goto error;
633 }
634 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
635 free(cmdline);
636 }
637 MSG("%s- %s", indent6, event_list[i].name);
638 }
3c6a091f 639
fb14d0d8
JR
640 MSG("");
641 }
3c6a091f
DG
642
643error:
fb14d0d8
JR
644 free(event_list);
645end:
3c6a091f 646 lttng_destroy_handle(handle);
fb14d0d8 647 return ret;
3c6a091f
DG
648}
649
b551a063
DG
650/*
651 * Ask session daemon for all user space tracepoints available.
652 */
cd9adb8b 653static int list_ust_events()
b551a063 654{
fb14d0d8 655 int i, size, ret = CMD_SUCCESS;
b551a063
DG
656 struct lttng_domain domain;
657 struct lttng_handle *handle;
cd9adb8b 658 struct lttng_event *event_list = nullptr;
b551a063 659 pid_t cur_pid = 0;
cd9adb8b 660 char *cmdline = nullptr;
b551a063 661
441c16a7
MD
662 memset(&domain, 0, sizeof(domain));
663
b551a063
DG
664 DBG("Getting UST tracing events");
665
666 domain.type = LTTNG_DOMAIN_UST;
667
cd9adb8b
JG
668 handle = lttng_create_handle(nullptr, &domain);
669 if (handle == nullptr) {
fb14d0d8
JR
670 ret = CMD_ERROR;
671 goto end;
b551a063
DG
672 }
673
674 size = lttng_list_tracepoints(handle, &event_list);
675 if (size < 0) {
60e835ca 676 ERR("Unable to list UST events: %s", lttng_strerror(size));
fb14d0d8
JR
677 ret = CMD_ERROR;
678 goto error;
b551a063
DG
679 }
680
fb14d0d8
JR
681 if (lttng_opt_mi) {
682 /* Mi print */
5cdb6027 683 ret = mi_list_agent_ust_events(event_list, size, &domain);
fb14d0d8
JR
684 } else {
685 /* Pretty print */
686 MSG("UST events:\n-------------");
687
688 if (size == 0) {
689 MSG("None");
690 }
691
692 for (i = 0; i < size; i++) {
693 if (cur_pid != event_list[i].pid) {
694 cur_pid = event_list[i].pid;
695 cmdline = get_cmdline_by_pid(cur_pid);
cd9adb8b 696 if (cmdline == nullptr) {
fb14d0d8
JR
697 ret = CMD_ERROR;
698 goto error;
699 }
700 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
701 free(cmdline);
702 }
703 print_events(&event_list[i]);
704 }
b551a063 705
fb14d0d8 706 MSG("");
b551a063
DG
707 }
708
fb14d0d8
JR
709error:
710 free(event_list);
711end:
712 lttng_destroy_handle(handle);
713 return ret;
714}
715
716/*
717 * Machine interface
718 * List all ust event with their fields
719 */
28ab034a
JG
720static int
721mi_list_ust_event_fields(struct lttng_event_field *fields, int count, struct lttng_domain *domain)
fb14d0d8
JR
722{
723 int ret, i;
724 pid_t cur_pid = 0;
cd9adb8b 725 char *cmdline = nullptr;
fb14d0d8
JR
726 int pid_element_open = 0;
727 int event_element_open = 0;
728 struct lttng_event cur_event;
729
d113fbc8
JR
730 memset(&cur_event, 0, sizeof(cur_event));
731
fb14d0d8 732 /* Open domains element */
41493f4a 733 ret = mi_lttng_domains_open(the_writer);
fb14d0d8
JR
734 if (ret) {
735 goto end;
736 }
737
738 /* Write domain */
41493f4a 739 ret = mi_lttng_domain(the_writer, domain, 1);
fb14d0d8
JR
740 if (ret) {
741 goto end;
742 }
743
bf239d4c 744 /* Open pids element */
41493f4a 745 ret = mi_lttng_pids_open(the_writer);
fb14d0d8
JR
746 if (ret) {
747 goto end;
748 }
749
750 for (i = 0; i < count; i++) {
751 if (cur_pid != fields[i].event.pid) {
752 if (pid_element_open) {
753 if (event_element_open) {
485ca16f 754 /* Close the previous field element and event. */
28ab034a 755 ret = mi_lttng_close_multi_element(the_writer, 2);
fb14d0d8
JR
756 if (ret) {
757 goto end;
758 }
759 event_element_open = 0;
760 }
761 /* Close the previous events, pid element */
28ab034a 762 ret = mi_lttng_close_multi_element(the_writer, 2);
fb14d0d8
JR
763 if (ret) {
764 goto end;
765 }
766 pid_element_open = 0;
767 }
768
769 cur_pid = fields[i].event.pid;
ea5cbc00 770 cmdline = get_cmdline_by_pid(cur_pid);
fb14d0d8 771 if (!pid_element_open) {
bf239d4c 772 /* Open and write a pid element */
28ab034a 773 ret = mi_lttng_pid(the_writer, cur_pid, cmdline, 1);
fb14d0d8
JR
774 if (ret) {
775 goto error;
776 }
777
778 /* Open events element */
41493f4a 779 ret = mi_lttng_events_open(the_writer);
fb14d0d8
JR
780 if (ret) {
781 goto error;
782 }
783 pid_element_open = 1;
784 }
ea5cbc00 785 free(cmdline);
fb14d0d8
JR
786 /* Wipe current event since we are about to print a new PID. */
787 memset(&cur_event, 0, sizeof(cur_event));
b551a063 788 }
b551a063 789
fb14d0d8
JR
790 if (strcmp(cur_event.name, fields[i].event.name) != 0) {
791 if (event_element_open) {
792 /* Close the previous fields element and the previous event */
28ab034a 793 ret = mi_lttng_close_multi_element(the_writer, 2);
fb14d0d8
JR
794 if (ret) {
795 goto end;
796 }
797 event_element_open = 0;
798 }
799
28ab034a 800 memcpy(&cur_event, &fields[i].event, sizeof(cur_event));
b551a063 801
fb14d0d8
JR
802 if (!event_element_open) {
803 /* Open and write the event */
28ab034a
JG
804 ret = mi_lttng_event(
805 the_writer, &cur_event, 1, the_handle->domain.type);
fb14d0d8
JR
806 if (ret) {
807 goto end;
808 }
809
810 /* Open a fields element */
41493f4a 811 ret = mi_lttng_event_fields_open(the_writer);
fb14d0d8
JR
812 if (ret) {
813 goto end;
814 }
815 event_element_open = 1;
816 }
817 }
b551a063 818
fb14d0d8 819 /* Print the event_field */
41493f4a 820 ret = mi_lttng_event_field(the_writer, &fields[i]);
fb14d0d8
JR
821 if (ret) {
822 goto end;
823 }
824 }
b551a063 825
83d6d6c4 826 /* Close pids, domain, domains */
41493f4a 827 ret = mi_lttng_close_multi_element(the_writer, 3);
fb14d0d8
JR
828end:
829 return ret;
b551a063 830error:
fb14d0d8
JR
831 free(cmdline);
832 return ret;
b551a063 833}
f3ed775e 834
f37d259d
MD
835/*
836 * Ask session daemon for all user space tracepoint fields available.
837 */
cd9adb8b 838static int list_ust_event_fields()
f37d259d 839{
fb14d0d8 840 int i, size, ret = CMD_SUCCESS;
f37d259d
MD
841 struct lttng_domain domain;
842 struct lttng_handle *handle;
843 struct lttng_event_field *event_field_list;
844 pid_t cur_pid = 0;
cd9adb8b 845 char *cmdline = nullptr;
ea5cbc00 846
f37d259d
MD
847 struct lttng_event cur_event;
848
849 memset(&domain, 0, sizeof(domain));
850 memset(&cur_event, 0, sizeof(cur_event));
851
852 DBG("Getting UST tracing event fields");
853
854 domain.type = LTTNG_DOMAIN_UST;
855
cd9adb8b
JG
856 handle = lttng_create_handle(nullptr, &domain);
857 if (handle == nullptr) {
fb14d0d8
JR
858 ret = CMD_ERROR;
859 goto end;
f37d259d
MD
860 }
861
862 size = lttng_list_tracepoint_fields(handle, &event_field_list);
863 if (size < 0) {
60e835ca 864 ERR("Unable to list UST event fields: %s", lttng_strerror(size));
fb14d0d8
JR
865 ret = CMD_ERROR;
866 goto end;
f37d259d
MD
867 }
868
fb14d0d8
JR
869 if (lttng_opt_mi) {
870 /* Mi print */
871 ret = mi_list_ust_event_fields(event_field_list, size, &domain);
872 if (ret) {
873 ret = CMD_ERROR;
874 goto error;
875 }
876 } else {
877 /* Pretty print */
878 MSG("UST events:\n-------------");
f37d259d 879
fb14d0d8
JR
880 if (size == 0) {
881 MSG("None");
f37d259d 882 }
fb14d0d8
JR
883
884 for (i = 0; i < size; i++) {
885 if (cur_pid != event_field_list[i].event.pid) {
886 cur_pid = event_field_list[i].event.pid;
887 cmdline = get_cmdline_by_pid(cur_pid);
cd9adb8b 888 if (cmdline == nullptr) {
fb14d0d8
JR
889 ret = CMD_ERROR;
890 goto error;
891 }
892 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
893 free(cmdline);
894 /* Wipe current event since we are about to print a new PID. */
895 memset(&cur_event, 0, sizeof(cur_event));
896 }
897 if (strcmp(cur_event.name, event_field_list[i].event.name) != 0) {
898 print_events(&event_field_list[i].event);
28ab034a 899 memcpy(&cur_event, &event_field_list[i].event, sizeof(cur_event));
fb14d0d8
JR
900 }
901 print_event_field(&event_field_list[i]);
f37d259d 902 }
f37d259d 903
fb14d0d8
JR
904 MSG("");
905 }
f37d259d 906
fb14d0d8 907error:
f37d259d 908 free(event_field_list);
fb14d0d8 909end:
f37d259d 910 lttng_destroy_handle(handle);
fb14d0d8
JR
911 return ret;
912}
f37d259d 913
fb14d0d8
JR
914/*
915 * Machine interface
916 * Print a list of kernel events
917 */
28ab034a 918static int mi_list_kernel_events(struct lttng_event *events, int count, struct lttng_domain *domain)
fb14d0d8
JR
919{
920 int ret, i;
f37d259d 921
fb14d0d8 922 /* Open domains element */
41493f4a 923 ret = mi_lttng_domains_open(the_writer);
fb14d0d8
JR
924 if (ret) {
925 goto end;
926 }
927
928 /* Write domain */
41493f4a 929 ret = mi_lttng_domain(the_writer, domain, 1);
fb14d0d8
JR
930 if (ret) {
931 goto end;
932 }
933
934 /* Open events */
41493f4a 935 ret = mi_lttng_events_open(the_writer);
fb14d0d8
JR
936 if (ret) {
937 goto end;
938 }
939
940 for (i = 0; i < count; i++) {
28ab034a 941 ret = mi_lttng_event(the_writer, &events[i], 0, the_handle->domain.type);
fb14d0d8
JR
942 if (ret) {
943 goto end;
944 }
945 }
946
947 /* close events, domain and domains */
41493f4a 948 ret = mi_lttng_close_multi_element(the_writer, 3);
fb14d0d8
JR
949 if (ret) {
950 goto end;
951 }
952
953end:
954 return ret;
f37d259d
MD
955}
956
f3ed775e 957/*
fb14d0d8 958 * Ask for all trace events in the kernel
f3ed775e 959 */
cd9adb8b 960static int list_kernel_events()
f3ed775e 961{
fb14d0d8 962 int i, size, ret = CMD_SUCCESS;
b551a063
DG
963 struct lttng_domain domain;
964 struct lttng_handle *handle;
9f19cc17 965 struct lttng_event *event_list;
f3ed775e 966
441c16a7
MD
967 memset(&domain, 0, sizeof(domain));
968
b551a063
DG
969 DBG("Getting kernel tracing events");
970
971 domain.type = LTTNG_DOMAIN_KERNEL;
972
cd9adb8b
JG
973 handle = lttng_create_handle(nullptr, &domain);
974 if (handle == nullptr) {
fb14d0d8 975 ret = CMD_ERROR;
b551a063
DG
976 goto error;
977 }
f3ed775e 978
cd80958d 979 size = lttng_list_tracepoints(handle, &event_list);
9f19cc17 980 if (size < 0) {
60e835ca 981 ERR("Unable to list kernel events: %s", lttng_strerror(size));
ef021732 982 lttng_destroy_handle(handle);
fb14d0d8 983 return CMD_ERROR;
f3ed775e
DG
984 }
985
fb14d0d8
JR
986 if (lttng_opt_mi) {
987 /* Mi print */
988 ret = mi_list_kernel_events(event_list, size, &domain);
989 if (ret) {
990 ret = CMD_ERROR;
991 goto end;
992 }
993 } else {
994 MSG("Kernel events:\n-------------");
f3ed775e 995
fb14d0d8
JR
996 for (i = 0; i < size; i++) {
997 print_events(&event_list[i]);
998 }
f3ed775e 999
fb14d0d8
JR
1000 MSG("");
1001 }
b551a063 1002
fb14d0d8 1003end:
f3ed775e
DG
1004 free(event_list);
1005
ef021732 1006 lttng_destroy_handle(handle);
fb14d0d8 1007 return ret;
b551a063
DG
1008
1009error:
ef021732 1010 lttng_destroy_handle(handle);
fb14d0d8
JR
1011 return ret;
1012}
1013
834978fd
DG
1014/*
1015 * Machine interface
1016 * Print a list of system calls.
1017 */
1018static int mi_list_syscalls(struct lttng_event *events, int count)
1019{
1020 int ret, i;
1021
1022 /* Open events */
41493f4a 1023 ret = mi_lttng_events_open(the_writer);
834978fd
DG
1024 if (ret) {
1025 goto end;
1026 }
1027
1028 for (i = 0; i < count; i++) {
28ab034a 1029 ret = mi_lttng_event(the_writer, &events[i], 0, the_handle->domain.type);
834978fd
DG
1030 if (ret) {
1031 goto end;
1032 }
1033 }
1034
1035 /* Close events. */
41493f4a 1036 ret = mi_lttng_writer_close_element(the_writer);
834978fd
DG
1037 if (ret) {
1038 goto end;
1039 }
1040
1041end:
1042 return ret;
1043}
1044
1045/*
1046 * Ask for kernel system calls.
1047 */
cd9adb8b 1048static int list_syscalls()
834978fd
DG
1049{
1050 int i, size, ret = CMD_SUCCESS;
1051 struct lttng_event *event_list;
1052
1053 DBG("Getting kernel system call events");
1054
1055 size = lttng_list_syscalls(&event_list);
1056 if (size < 0) {
1057 ERR("Unable to list system calls: %s", lttng_strerror(size));
1058 ret = CMD_ERROR;
1059 goto error;
1060 }
1061
1062 if (lttng_opt_mi) {
1063 /* Mi print */
1064 ret = mi_list_syscalls(event_list, size);
1065 if (ret) {
1066 ret = CMD_ERROR;
1067 goto end;
1068 }
1069 } else {
1070 MSG("System calls:\n-------------");
1071
1072 for (i = 0; i < size; i++) {
1073 print_events(&event_list[i]);
1074 }
1075
1076 MSG("");
1077 }
1078
1079end:
1080 free(event_list);
1081 return ret;
1082
1083error:
1084 return ret;
1085}
1086
fb14d0d8
JR
1087/*
1088 * Machine Interface
5cdb6027 1089 * Print a list of agent events
fb14d0d8 1090 */
5cdb6027 1091static int mi_list_session_agent_events(struct lttng_event *events, int count)
fb14d0d8
JR
1092{
1093 int ret, i;
1094
1095 /* Open events element */
41493f4a 1096 ret = mi_lttng_events_open(the_writer);
fb14d0d8
JR
1097 if (ret) {
1098 goto end;
1099 }
1100
1101 for (i = 0; i < count; i++) {
28ab034a 1102 ret = mi_lttng_event(the_writer, &events[i], 0, the_handle->domain.type);
fb14d0d8
JR
1103 if (ret) {
1104 goto end;
1105 }
1106 }
1107
1108 /* Close events element */
41493f4a 1109 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
1110
1111end:
1112 return ret;
f3ed775e
DG
1113}
1114
3c6a091f 1115/*
5cdb6027 1116 * List agent events for a specific session using the handle.
3c6a091f
DG
1117 *
1118 * Return CMD_SUCCESS on success else a negative value.
1119 */
cd9adb8b 1120static int list_session_agent_events()
3c6a091f 1121{
fb14d0d8 1122 int ret = CMD_SUCCESS, count, i;
cd9adb8b 1123 struct lttng_event *events = nullptr;
3c6a091f 1124
41493f4a 1125 count = lttng_list_events(the_handle, "", &events);
3c6a091f 1126 if (count < 0) {
fb14d0d8
JR
1127 ret = CMD_ERROR;
1128 ERR("%s", lttng_strerror(count));
3c6a091f
DG
1129 goto error;
1130 }
1131
fb14d0d8
JR
1132 if (lttng_opt_mi) {
1133 /* Mi print */
5cdb6027 1134 ret = mi_list_session_agent_events(events, count);
fb14d0d8
JR
1135 if (ret) {
1136 ret = CMD_ERROR;
1137 goto end;
1138 }
1139 } else {
1140 /* Pretty print */
1141 MSG("Events (Logger name):\n---------------------");
1142 if (count == 0) {
1143 MSG("%sNone\n", indent6);
1144 goto end;
1145 }
1146
1147 for (i = 0; i < count; i++) {
9a890ce8 1148 const char *filter_str;
cd9adb8b 1149 char *filter_msg = nullptr;
9a890ce8
JG
1150 struct lttng_event *event = &events[i];
1151
28ab034a 1152 ret = lttng_event_get_filter_expression(event, &filter_str);
9a890ce8
JG
1153 if (ret) {
1154 filter_msg = strdup(" [failed to retrieve filter]");
1155 } else if (filter_str) {
411b3154 1156 if (asprintf(&filter_msg, " [filter: '%s']", filter_str) == -1) {
cd9adb8b 1157 filter_msg = nullptr;
9a890ce8
JG
1158 }
1159 }
1160
28ab034a
JG
1161 if (event->loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
1162 MSG("%s- %s%s (loglevel%s %s)%s",
1163 indent4,
1164 event->name,
1165 enabled_string(event->enabled),
1166 logleveltype_string(event->loglevel_type),
1167 mi_lttng_loglevel_string(event->loglevel,
1168 the_handle->domain.type),
1169 safe_string(filter_msg));
755066c2 1170 } else {
28ab034a
JG
1171 MSG("%s- %s%s%s",
1172 indent4,
1173 event->name,
1174 enabled_string(event->enabled),
1175 safe_string(filter_msg));
755066c2 1176 }
9a890ce8 1177 free(filter_msg);
fb14d0d8
JR
1178 }
1179
1180 MSG("");
1181 }
1182
1183end:
1184 free(events);
1185error:
1186 return ret;
1187}
1188
1189/*
1190 * Machine interface
1191 * print a list of event
1192 */
1193static int mi_list_events(struct lttng_event *events, int count)
1194{
1195 int ret, i;
1196
1197 /* Open events element */
41493f4a 1198 ret = mi_lttng_events_open(the_writer);
fb14d0d8 1199 if (ret) {
3c6a091f
DG
1200 goto end;
1201 }
1202
1203 for (i = 0; i < count; i++) {
28ab034a 1204 ret = mi_lttng_event(the_writer, &events[i], 0, the_handle->domain.type);
fb14d0d8
JR
1205 if (ret) {
1206 goto end;
1207 }
3c6a091f
DG
1208 }
1209
fb14d0d8 1210 /* Close events element */
41493f4a 1211 ret = mi_lttng_writer_close_element(the_writer);
3c6a091f
DG
1212
1213end:
3c6a091f
DG
1214 return ret;
1215}
1216
f3ed775e 1217/*
9f19cc17 1218 * List events of channel of session and domain.
f3ed775e 1219 */
cd80958d 1220static int list_events(const char *channel_name)
f3ed775e 1221{
fb14d0d8 1222 int ret = CMD_SUCCESS, count, i;
cd9adb8b 1223 struct lttng_event *events = nullptr;
f3ed775e 1224
41493f4a 1225 count = lttng_list_events(the_handle, channel_name, &events);
f3ed775e 1226 if (count < 0) {
fb14d0d8
JR
1227 ret = CMD_ERROR;
1228 ERR("%s", lttng_strerror(count));
f3ed775e
DG
1229 goto error;
1230 }
1231
fb14d0d8
JR
1232 if (lttng_opt_mi) {
1233 /* Mi print */
1234 ret = mi_list_events(events, count);
1235 if (ret) {
1236 ret = CMD_ERROR;
1237 goto end;
1238 }
1239 } else {
1240 /* Pretty print */
484b2a0c 1241 MSG("\n%sRecording event rules:", indent4);
fb14d0d8
JR
1242 if (count == 0) {
1243 MSG("%sNone\n", indent6);
1244 goto end;
1245 }
f3ed775e 1246
fb14d0d8
JR
1247 for (i = 0; i < count; i++) {
1248 print_events(&events[i]);
1249 }
f3ed775e 1250
fb14d0d8
JR
1251 MSG("");
1252 }
9f19cc17 1253end:
0e428499 1254 free(events);
f3ed775e
DG
1255error:
1256 return ret;
1257}
1258
28ab034a 1259static void print_timer(const char *timer_name, uint32_t space_count, int64_t value)
f3b3a67b
JG
1260{
1261 uint32_t i;
1262
1263 _MSG("%s%s:", indent6, timer_name);
1264 for (i = 0; i < space_count; i++) {
1265 _MSG(" ");
1266 }
1267
1268 if (value) {
2a1135fa 1269 MSG("%" PRId64 " %s", value, USEC_UNIT);
f3b3a67b
JG
1270 } else {
1271 MSG("inactive");
1272 }
1273}
1274
f3ed775e 1275/*
9f19cc17
DG
1276 * Pretty print channel
1277 */
1278static void print_channel(struct lttng_channel *channel)
1279{
fb83fe64 1280 int ret;
cf0bcb51 1281 uint64_t discarded_events, lost_packets, monitor_timer_interval;
491d1539 1282 int64_t blocking_timeout;
fb83fe64 1283
28ab034a 1284 ret = lttng_channel_get_discarded_event_count(channel, &discarded_events);
fb83fe64
JD
1285 if (ret) {
1286 ERR("Failed to retrieve discarded event count of channel");
1287 return;
1288 }
1289
28ab034a 1290 ret = lttng_channel_get_lost_packet_count(channel, &lost_packets);
fb83fe64
JD
1291 if (ret) {
1292 ERR("Failed to retrieve lost packet count of channel");
1293 return;
1294 }
1295
28ab034a 1296 ret = lttng_channel_get_monitor_timer_interval(channel, &monitor_timer_interval);
cf0bcb51
JG
1297 if (ret) {
1298 ERR("Failed to retrieve monitor interval of channel");
1299 return;
1300 }
1301
28ab034a 1302 ret = lttng_channel_get_blocking_timeout(channel, &blocking_timeout);
491d1539
MD
1303 if (ret) {
1304 ERR("Failed to retrieve blocking timeout of channel");
1305 return;
1306 }
1307
464dd62d 1308 MSG("- %s:%s\n", channel->name, enabled_string(channel->enabled));
9f19cc17 1309 MSG("%sAttributes:", indent4);
f3b3a67b
JG
1310 MSG("%sEvent-loss mode: %s", indent6, channel->attr.overwrite ? "overwrite" : "discard");
1311 MSG("%sSub-buffer size: %" PRIu64 " bytes", indent6, channel->attr.subbuf_size);
1312 MSG("%sSub-buffer count: %" PRIu64, indent6, channel->attr.num_subbuf);
1313
1314 print_timer("Switch timer", 5, channel->attr.switch_timer_interval);
28ab034a 1315 print_timer("Read timer", 7, channel->attr.read_timer_interval);
f3b3a67b
JG
1316 print_timer("Monitor timer", 4, monitor_timer_interval);
1317
1318 if (!channel->attr.overwrite) {
1319 if (blocking_timeout == -1) {
1320 MSG("%sBlocking timeout: infinite", indent6);
1321 } else {
28ab034a
JG
1322 MSG("%sBlocking timeout: %" PRId64 " %s",
1323 indent6,
1324 blocking_timeout,
1325 USEC_UNIT);
f3b3a67b
JG
1326 }
1327 }
1328
28ab034a
JG
1329 MSG("%sTrace file count: %" PRIu64 " per stream",
1330 indent6,
1331 channel->attr.tracefile_count == 0 ? 1 : channel->attr.tracefile_count);
1332 if (channel->attr.tracefile_size != 0) {
1333 MSG("%sTrace file size: %" PRIu64 " bytes", indent6, channel->attr.tracefile_size);
f3b3a67b
JG
1334 } else {
1335 MSG("%sTrace file size: %s", indent6, "unlimited");
1336 }
9f19cc17 1337 switch (channel->attr.output) {
28ab034a
JG
1338 case LTTNG_EVENT_SPLICE:
1339 MSG("%sOutput mode: splice", indent6);
1340 break;
1341 case LTTNG_EVENT_MMAP:
1342 MSG("%sOutput mode: mmap", indent6);
1343 break;
9f19cc17 1344 }
e50e81d3 1345
f3b3a67b 1346 MSG("\n%sStatistics:", indent4);
41493f4a 1347 if (the_listed_session.snapshot_mode) {
e50e81d3
JG
1348 /*
1349 * The lost packet count is omitted for sessions in snapshot
1350 * mode as it is misleading: it would indicate the number of
1351 * packets that the consumer could not extract during the
1352 * course of recording the snapshot. It does not have the
1353 * same meaning as the "regular" lost packet count that
1354 * would result from the consumer not keeping up with
1355 * event production in an overwrite-mode channel.
1356 *
1357 * A more interesting statistic would be the number of
1358 * packets lost between the first and last extracted
1359 * packets of a given snapshot (which prevents most analyses).
1360 */
f3b3a67b 1361 MSG("%sNone", indent6);
e50e81d3
JG
1362 goto skip_stats_printing;
1363 }
1364
1365 if (!channel->attr.overwrite) {
f3b3a67b 1366 MSG("%sDiscarded events: %" PRIu64, indent6, discarded_events);
e50e81d3 1367 } else {
f3b3a67b 1368 MSG("%sLost packets: %" PRIu64, indent6, lost_packets);
e50e81d3
JG
1369 }
1370skip_stats_printing:
1371 return;
9f19cc17
DG
1372}
1373
fb14d0d8
JR
1374/*
1375 * Machine interface
1376 * Print a list of channel
1377 *
1378 */
28ab034a 1379static int mi_list_channels(struct lttng_channel *channels, int count, const char *channel_name)
fb14d0d8
JR
1380{
1381 int i, ret;
1382 unsigned int chan_found = 0;
1383
1384 /* Open channels element */
41493f4a 1385 ret = mi_lttng_channels_open(the_writer);
fb14d0d8
JR
1386 if (ret) {
1387 goto error;
1388 }
1389
1390 for (i = 0; i < count; i++) {
cd9adb8b 1391 if (channel_name != nullptr) {
fb14d0d8
JR
1392 if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
1393 chan_found = 1;
1394 } else {
1395 continue;
1396 }
1397 }
1398
1399 /* Write channel element and leave it open */
41493f4a 1400 ret = mi_lttng_channel(the_writer, &channels[i], 1);
fb14d0d8
JR
1401 if (ret) {
1402 goto error;
1403 }
1404
1405 /* Listing events per channel */
1406 ret = list_events(channels[i].name);
1407 if (ret) {
1408 goto error;
1409 }
1410
1411 /* Closing the channel element we opened earlier */
41493f4a 1412 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
1413 if (ret) {
1414 goto error;
1415 }
1416
1417 if (chan_found) {
1418 break;
1419 }
1420 }
1421
1422 /* Close channels element */
41493f4a 1423 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
1424 if (ret) {
1425 goto error;
1426 }
1427
1428error:
1429 return ret;
1430}
1431
9f19cc17
DG
1432/*
1433 * List channel(s) of session and domain.
f3ed775e 1434 *
9f19cc17 1435 * If channel_name is NULL, all channels are listed.
f3ed775e 1436 */
cd80958d 1437static int list_channels(const char *channel_name)
f3ed775e 1438{
9f19cc17
DG
1439 int count, i, ret = CMD_SUCCESS;
1440 unsigned int chan_found = 0;
cd9adb8b 1441 struct lttng_channel *channels = nullptr;
f3ed775e 1442
28ab034a 1443 DBG("Listing channel(s) (%s)", channel_name ?: "<all>");
9f19cc17 1444
41493f4a 1445 count = lttng_list_channels(the_handle, &channels);
f3ed775e 1446 if (count < 0) {
c7d620a2
DG
1447 switch (-count) {
1448 case LTTNG_ERR_KERN_CHAN_NOT_FOUND:
fb14d0d8
JR
1449 if (lttng_opt_mi) {
1450 /* When printing mi this is not an error
1451 * but an empty channels element */
1452 count = 0;
1453 } else {
1454 ret = CMD_SUCCESS;
fb14d0d8
JR
1455 goto error_channels;
1456 }
c7d620a2
DG
1457 break;
1458 default:
1459 /* We had a real error */
fb14d0d8
JR
1460 ret = CMD_ERROR;
1461 ERR("%s", lttng_strerror(count));
1462 goto error_channels;
60e835ca 1463 break;
c7d620a2 1464 }
f3ed775e
DG
1465 }
1466
fb14d0d8
JR
1467 if (lttng_opt_mi) {
1468 /* Mi print */
1469 ret = mi_list_channels(channels, count, channel_name);
1470 if (ret) {
1471 ret = CMD_ERROR;
1472 goto error;
1473 }
1474 } else {
1475 /* Pretty print */
ade7ce52 1476 if (count) {
fb14d0d8
JR
1477 MSG("Channels:\n-------------");
1478 }
9f19cc17 1479
fb14d0d8 1480 for (i = 0; i < count; i++) {
cd9adb8b 1481 if (channel_name != nullptr) {
fb14d0d8
JR
1482 if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
1483 chan_found = 1;
1484 } else {
1485 continue;
1486 }
1487 }
1488 print_channel(&channels[i]);
1489
1490 /* Listing events per channel */
1491 ret = list_events(channels[i].name);
1492 if (ret) {
1493 goto error;
1494 }
1495
1496 if (chan_found) {
1497 break;
9f19cc17
DG
1498 }
1499 }
9f19cc17 1500
cd9adb8b 1501 if (!chan_found && channel_name != nullptr) {
fb14d0d8
JR
1502 ret = CMD_ERROR;
1503 ERR("Channel %s not found", channel_name);
1504 goto error;
9f19cc17 1505 }
fb14d0d8
JR
1506 }
1507error:
1508 free(channels);
9f19cc17 1509
fb14d0d8
JR
1510error_channels:
1511 return ret;
1512}
1513
159b042f 1514static const char *get_capitalized_process_attr_str(enum lttng_process_attr process_attr)
83d6d6c4 1515{
159b042f
JG
1516 switch (process_attr) {
1517 case LTTNG_PROCESS_ATTR_PROCESS_ID:
1518 return "Process ID";
1519 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
1520 return "Virtual process ID";
1521 case LTTNG_PROCESS_ATTR_USER_ID:
1522 return "User ID";
1523 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
1524 return "Virtual user ID";
1525 case LTTNG_PROCESS_ATTR_GROUP_ID:
1526 return "Group ID";
1527 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
1528 return "Virtual group ID";
1529 default:
1530 return "Unknown";
83d6d6c4 1531 }
cd9adb8b 1532 return nullptr;
83d6d6c4
JR
1533}
1534
159b042f 1535static int handle_process_attr_status(enum lttng_process_attr process_attr,
28ab034a 1536 enum lttng_process_attr_tracker_handle_status status)
159b042f
JG
1537{
1538 int ret = CMD_SUCCESS;
1539
1540 switch (status) {
1541 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY:
1542 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
1543 /* Carry on. */
1544 break;
1545 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
1546 ERR("Communication occurred while fetching %s tracker",
28ab034a 1547 lttng_process_attr_to_string(process_attr));
159b042f
JG
1548 ret = CMD_ERROR;
1549 break;
1550 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
1551 ERR("Failed to get the inclusion set of the %s tracker: session `%s` no longer exists",
28ab034a
JG
1552 lttng_process_attr_to_string(process_attr),
1553 the_handle->session_name);
159b042f
JG
1554 ret = CMD_ERROR;
1555 break;
1556 default:
1557 ERR("Unknown error occurred while fetching the inclusion set of the %s tracker",
28ab034a 1558 lttng_process_attr_to_string(process_attr));
159b042f
JG
1559 ret = CMD_ERROR;
1560 break;
1561 }
1562
1563 return ret;
1564}
1565
1566static int mi_output_empty_tracker(enum lttng_process_attr process_attr)
1567{
1568 int ret;
1569
41493f4a 1570 ret = mi_lttng_process_attribute_tracker_open(the_writer, process_attr);
159b042f
JG
1571 if (ret) {
1572 goto end;
1573 }
1574
41493f4a 1575 ret = mi_lttng_close_multi_element(the_writer, 2);
159b042f
JG
1576end:
1577 return ret;
1578}
1579
28ab034a 1580static inline bool is_value_type_name(enum lttng_process_attr_value_type value_type)
159b042f
JG
1581{
1582 return value_type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME ||
28ab034a 1583 value_type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME;
159b042f
JG
1584}
1585
a5dfbb9d 1586/*
159b042f 1587 * List a process attribute tracker for a session and domain tuple.
a5dfbb9d 1588 */
159b042f 1589static int list_process_attr_tracker(enum lttng_process_attr process_attr)
a5dfbb9d 1590{
ebbf5ab7 1591 int ret = 0;
159b042f
JG
1592 unsigned int count, i;
1593 enum lttng_tracking_policy policy;
1594 enum lttng_error_code ret_code;
1595 enum lttng_process_attr_tracker_handle_status handle_status;
1596 enum lttng_process_attr_values_status values_status;
1597 const struct lttng_process_attr_values *values;
cd9adb8b 1598 struct lttng_process_attr_tracker_handle *tracker_handle = nullptr;
159b042f 1599
28ab034a
JG
1600 ret_code = lttng_session_get_tracker_handle(
1601 the_handle->session_name, the_handle->domain.type, process_attr, &tracker_handle);
159b042f 1602 if (ret_code != LTTNG_OK) {
28ab034a 1603 ERR("Failed to get process attribute tracker handle: %s", lttng_strerror(ret_code));
159b042f
JG
1604 ret = CMD_ERROR;
1605 goto end;
1606 }
a5dfbb9d 1607
28ab034a
JG
1608 handle_status =
1609 lttng_process_attr_tracker_handle_get_inclusion_set(tracker_handle, &values);
159b042f
JG
1610 ret = handle_process_attr_status(process_attr, handle_status);
1611 if (ret != CMD_SUCCESS) {
1612 goto end;
a5dfbb9d 1613 }
a7a533cd 1614
28ab034a
JG
1615 handle_status =
1616 lttng_process_attr_tracker_handle_get_tracking_policy(tracker_handle, &policy);
159b042f
JG
1617 ret = handle_process_attr_status(process_attr, handle_status);
1618 if (ret != CMD_SUCCESS) {
e283e4a0
JR
1619 goto end;
1620 }
1621
159b042f
JG
1622 {
1623 char *process_attr_name;
28ab034a
JG
1624 const int print_ret = asprintf(
1625 &process_attr_name, "%ss:", get_capitalized_process_attr_str(process_attr));
159b042f
JG
1626
1627 if (print_ret == -1) {
1628 ret = CMD_FATAL;
1629 goto end;
a7a533cd 1630 }
159b042f
JG
1631 _MSG(" %-22s", process_attr_name);
1632 free(process_attr_name);
1633 }
1634 switch (policy) {
1635 case LTTNG_TRACKING_POLICY_INCLUDE_SET:
1636 break;
1637 case LTTNG_TRACKING_POLICY_EXCLUDE_ALL:
41493f4a 1638 if (the_writer) {
159b042f
JG
1639 mi_output_empty_tracker(process_attr);
1640 }
1641 MSG("none");
1642 ret = CMD_SUCCESS;
1643 goto end;
1644 case LTTNG_TRACKING_POLICY_INCLUDE_ALL:
1645 MSG("all");
1646 ret = CMD_SUCCESS;
1647 goto end;
1648 default:
1649 ERR("Unknown tracking policy encoutered while listing the %s process attribute tracker of session `%s`",
28ab034a
JG
1650 lttng_process_attr_to_string(process_attr),
1651 the_handle->session_name);
159b042f
JG
1652 ret = CMD_FATAL;
1653 goto end;
83d6d6c4 1654 }
a7a533cd 1655
159b042f
JG
1656 values_status = lttng_process_attr_values_get_count(values, &count);
1657 if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
1658 ERR("Failed to get the count of values in the inclusion set of the %s process attribute tracker of session `%s`",
28ab034a
JG
1659 lttng_process_attr_to_string(process_attr),
1660 the_handle->session_name);
159b042f
JG
1661 ret = CMD_FATAL;
1662 goto end;
1663 }
a5dfbb9d 1664
159b042f
JG
1665 if (count == 0) {
1666 /* Functionally equivalent to the 'exclude all' policy. */
41493f4a 1667 if (the_writer) {
159b042f 1668 mi_output_empty_tracker(process_attr);
ebbf5ab7 1669 }
159b042f
JG
1670 MSG("none");
1671 ret = CMD_SUCCESS;
1672 goto end;
1673 }
ebbf5ab7 1674
159b042f 1675 /* Mi tracker_id element */
41493f4a 1676 if (the_writer) {
159b042f 1677 /* Open tracker_id and targets elements */
28ab034a 1678 ret = mi_lttng_process_attribute_tracker_open(the_writer, process_attr);
159b042f
JG
1679 if (ret) {
1680 goto end;
1681 }
1682 }
2d97a006 1683
159b042f
JG
1684 for (i = 0; i < count; i++) {
1685 const enum lttng_process_attr_value_type value_type =
28ab034a 1686 lttng_process_attr_values_get_type_at_index(values, i);
159b042f
JG
1687 int64_t integral_value = INT64_MAX;
1688 const char *name = "error";
1689
1690 if (i >= 1) {
1691 _MSG(", ");
1692 }
1693 switch (value_type) {
1694 case LTTNG_PROCESS_ATTR_VALUE_TYPE_PID:
1695 {
1696 pid_t pid;
1697
28ab034a 1698 values_status = lttng_process_attr_values_get_pid_at_index(values, i, &pid);
159b042f
JG
1699 integral_value = (int64_t) pid;
1700 break;
1701 }
1702 case LTTNG_PROCESS_ATTR_VALUE_TYPE_UID:
1703 {
1704 uid_t uid;
a7a533cd 1705
28ab034a 1706 values_status = lttng_process_attr_values_get_uid_at_index(values, i, &uid);
159b042f
JG
1707 integral_value = (int64_t) uid;
1708 break;
1709 }
1710 case LTTNG_PROCESS_ATTR_VALUE_TYPE_GID:
1711 {
1712 gid_t gid;
2d97a006 1713
28ab034a 1714 values_status = lttng_process_attr_values_get_gid_at_index(values, i, &gid);
159b042f
JG
1715 integral_value = (int64_t) gid;
1716 break;
1717 }
1718 case LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME:
28ab034a
JG
1719 values_status =
1720 lttng_process_attr_values_get_user_name_at_index(values, i, &name);
159b042f
JG
1721 break;
1722 case LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME:
28ab034a
JG
1723 values_status =
1724 lttng_process_attr_values_get_group_name_at_index(values, i, &name);
159b042f
JG
1725 break;
1726 default:
1727 ret = CMD_ERROR;
1728 goto end;
1729 }
83d6d6c4 1730
159b042f
JG
1731 if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
1732 /*
1733 * Not possible given the current liblttng-ctl
1734 * implementation.
1735 */
1736 ERR("Unknown error occurred while fetching process attribute value in inclusion list");
1737 ret = CMD_FATAL;
1738 goto end;
1739 }
ebbf5ab7 1740
159b042f
JG
1741 if (is_value_type_name(value_type)) {
1742 _MSG("`%s`", name);
1743 } else {
1744 _MSG("%" PRIi64, integral_value);
a5dfbb9d 1745 }
ebbf5ab7 1746
159b042f 1747 /* Mi */
41493f4a 1748 if (the_writer) {
159b042f 1749 ret = is_value_type_name(value_type) ?
28ab034a
JG
1750 mi_lttng_string_process_attribute_value(
1751 the_writer, process_attr, name, false) :
1752 mi_lttng_integral_process_attribute_value(
1753 the_writer, process_attr, integral_value, false);
ebbf5ab7
JR
1754 if (ret) {
1755 goto end;
1756 }
1757 }
a5dfbb9d 1758 }
159b042f
JG
1759 MSG("");
1760
1761 /* Mi close tracker_id and targets */
41493f4a
SM
1762 if (the_writer) {
1763 ret = mi_lttng_close_multi_element(the_writer, 2);
159b042f
JG
1764 if (ret) {
1765 goto end;
1766 }
1767 }
ebbf5ab7 1768end:
159b042f 1769 lttng_process_attr_tracker_handle_destroy(tracker_handle);
ebbf5ab7 1770 return ret;
ebbf5ab7
JR
1771}
1772
1773/*
83d6d6c4 1774 * List all trackers of a domain
ebbf5ab7 1775 */
83d6d6c4 1776static int list_trackers(const struct lttng_domain *domain)
ebbf5ab7 1777{
0dda6728 1778 int ret = 0;
ebbf5ab7 1779
159b042f 1780 MSG("Tracked process attributes");
ebbf5ab7
JR
1781 /* Trackers listing */
1782 if (lttng_opt_mi) {
41493f4a 1783 ret = mi_lttng_trackers_open(the_writer);
ebbf5ab7
JR
1784 if (ret) {
1785 goto end;
1786 }
1787 }
1788
83d6d6c4
JR
1789 switch (domain->type) {
1790 case LTTNG_DOMAIN_KERNEL:
1791 /* pid tracker */
159b042f 1792 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_PROCESS_ID);
83d6d6c4
JR
1793 if (ret) {
1794 goto end;
1795 }
1796 /* vpid tracker */
28ab034a 1797 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
83d6d6c4
JR
1798 if (ret) {
1799 goto end;
1800 }
1801 /* uid tracker */
159b042f 1802 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_USER_ID);
83d6d6c4
JR
1803 if (ret) {
1804 goto end;
1805 }
1806 /* vuid tracker */
28ab034a 1807 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
83d6d6c4
JR
1808 if (ret) {
1809 goto end;
1810 }
1811 /* gid tracker */
159b042f 1812 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_GROUP_ID);
83d6d6c4
JR
1813 if (ret) {
1814 goto end;
1815 }
1816 /* vgid tracker */
28ab034a 1817 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
83d6d6c4
JR
1818 if (ret) {
1819 goto end;
1820 }
1821 break;
1822 case LTTNG_DOMAIN_UST:
1823 /* vpid tracker */
28ab034a 1824 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
83d6d6c4
JR
1825 if (ret) {
1826 goto end;
1827 }
1828 /* vuid tracker */
28ab034a 1829 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
83d6d6c4
JR
1830 if (ret) {
1831 goto end;
1832 }
1833 /* vgid tracker */
28ab034a 1834 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
83d6d6c4
JR
1835 if (ret) {
1836 goto end;
1837 }
1838 break;
1839 default:
1840 break;
ebbf5ab7 1841 }
159b042f 1842 MSG();
ebbf5ab7
JR
1843 if (lttng_opt_mi) {
1844 /* Close trackers element */
41493f4a 1845 ret = mi_lttng_writer_close_element(the_writer);
ebbf5ab7
JR
1846 if (ret) {
1847 goto end;
1848 }
1849 }
1850
1851end:
1852 return ret;
a5dfbb9d
MD
1853}
1854
28ab034a
JG
1855static enum cmd_error_code
1856print_periodic_rotation_schedule(const struct lttng_rotation_schedule *schedule)
66ea93b1
JG
1857{
1858 enum cmd_error_code ret;
1859 enum lttng_rotation_status status;
1860 uint64_t value;
1861
28ab034a 1862 status = lttng_rotation_schedule_periodic_get_period(schedule, &value);
66ea93b1
JG
1863 if (status != LTTNG_ROTATION_STATUS_OK) {
1864 ERR("Failed to retrieve period parameter from periodic rotation schedule.");
1865 ret = CMD_ERROR;
1866 goto end;
1867 }
1868
28ab034a 1869 MSG(" timer period: %" PRIu64 " %s", value, USEC_UNIT);
66ea93b1
JG
1870 ret = CMD_SUCCESS;
1871end:
1872 return ret;
1873}
1874
28ab034a
JG
1875static enum cmd_error_code
1876print_size_threshold_rotation_schedule(const struct lttng_rotation_schedule *schedule)
66ea93b1
JG
1877{
1878 enum cmd_error_code ret;
1879 enum lttng_rotation_status status;
1880 uint64_t value;
1881
28ab034a 1882 status = lttng_rotation_schedule_size_threshold_get_threshold(schedule, &value);
66ea93b1
JG
1883 if (status != LTTNG_ROTATION_STATUS_OK) {
1884 ERR("Failed to retrieve size parameter from size-based rotation schedule.");
1885 ret = CMD_ERROR;
1886 goto end;
1887 }
1888
28ab034a 1889 MSG(" size threshold: %" PRIu64 " bytes", value);
66ea93b1
JG
1890 ret = CMD_SUCCESS;
1891end:
1892 return ret;
1893}
1894
28ab034a 1895static enum cmd_error_code print_rotation_schedule(const struct lttng_rotation_schedule *schedule)
66ea93b1
JG
1896{
1897 enum cmd_error_code ret;
1898
1899 switch (lttng_rotation_schedule_get_type(schedule)) {
1900 case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
1901 ret = print_size_threshold_rotation_schedule(schedule);
1902 break;
1903 case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
1904 ret = print_periodic_rotation_schedule(schedule);
1905 break;
1906 default:
1907 ret = CMD_ERROR;
1908 }
1909 return ret;
1910}
1911
329f3443 1912/*
66ea93b1 1913 * List the automatic rotation settings.
329f3443 1914 */
66ea93b1 1915static enum cmd_error_code list_rotate_settings(const char *session_name)
329f3443
JD
1916{
1917 int ret;
66ea93b1
JG
1918 enum cmd_error_code cmd_ret = CMD_SUCCESS;
1919 unsigned int count, i;
cd9adb8b 1920 struct lttng_rotation_schedules *schedules = nullptr;
66ea93b1
JG
1921 enum lttng_rotation_status status;
1922
1923 ret = lttng_session_list_rotation_schedules(session_name, &schedules);
1924 if (ret != LTTNG_OK) {
1925 ERR("Failed to list session rotation schedules: %s", lttng_strerror(ret));
1926 cmd_ret = CMD_ERROR;
329f3443
JD
1927 goto end;
1928 }
1929
66ea93b1
JG
1930 status = lttng_rotation_schedules_get_count(schedules, &count);
1931 if (status != LTTNG_ROTATION_STATUS_OK) {
1932 ERR("Failed to retrieve the number of session rotation schedules.");
1933 cmd_ret = CMD_ERROR;
329f3443
JD
1934 goto end;
1935 }
1936
66ea93b1
JG
1937 if (count == 0) {
1938 cmd_ret = CMD_SUCCESS;
329f3443
JD
1939 goto end;
1940 }
1941
66ea93b1
JG
1942 MSG("Automatic rotation schedules:");
1943 if (lttng_opt_mi) {
28ab034a 1944 ret = mi_lttng_writer_open_element(the_writer, mi_lttng_element_rotation_schedules);
66ea93b1
JG
1945 if (ret) {
1946 cmd_ret = CMD_ERROR;
1947 goto end;
329f3443
JD
1948 }
1949 }
66ea93b1
JG
1950
1951 for (i = 0; i < count; i++) {
1952 enum cmd_error_code tmp_ret = CMD_SUCCESS;
1953 const struct lttng_rotation_schedule *schedule;
1954
1955 schedule = lttng_rotation_schedules_get_at_index(schedules, i);
1956 if (!schedule) {
1957 ERR("Failed to retrieve session rotation schedule.");
1958 cmd_ret = CMD_ERROR;
1959 goto end;
1960 }
1961
329f3443 1962 if (lttng_opt_mi) {
41493f4a 1963 ret = mi_lttng_rotation_schedule(the_writer, schedule);
329f3443 1964 if (ret) {
66ea93b1 1965 tmp_ret = CMD_ERROR;
329f3443 1966 }
66ea93b1
JG
1967 } else {
1968 tmp_ret = print_rotation_schedule(schedule);
329f3443 1969 }
66ea93b1
JG
1970
1971 /*
1972 * Report an error if the serialization of any of the
1973 * descriptors failed.
1974 */
1975 cmd_ret = cmd_ret ? cmd_ret : tmp_ret;
329f3443 1976 }
329f3443 1977
66ea93b1
JG
1978 _MSG("\n");
1979 if (lttng_opt_mi) {
1980 /* Close the rotation_schedules element. */
41493f4a 1981 ret = mi_lttng_writer_close_element(the_writer);
66ea93b1
JG
1982 if (ret) {
1983 cmd_ret = CMD_ERROR;
1984 goto end;
1985 }
1986 }
329f3443 1987end:
66ea93b1
JG
1988 lttng_rotation_schedules_destroy(schedules);
1989 return cmd_ret;
329f3443
JD
1990}
1991
fb14d0d8
JR
1992/*
1993 * Machine interface
1994 * Find the session with session_name as name
1995 * and print his informations.
1996 */
28ab034a 1997static int mi_list_session(const char *session_name, struct lttng_session *sessions, int count)
fb14d0d8
JR
1998{
1999 int ret, i;
2000 unsigned int session_found = 0;
2001
cd9adb8b 2002 if (session_name == nullptr) {
fb14d0d8
JR
2003 ret = -LTTNG_ERR_SESS_NOT_FOUND;
2004 goto end;
2005 }
2006
2007 for (i = 0; i < count; i++) {
2008 if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
2009 /* We need to leave it open to append other informations
2010 * like domain, channel, events etc.*/
2011 session_found = 1;
41493f4a 2012 ret = mi_lttng_session(the_writer, &sessions[i], 1);
fb14d0d8
JR
2013 if (ret) {
2014 goto end;
2015 }
9f19cc17 2016 break;
f3ed775e 2017 }
f3ed775e
DG
2018 }
2019
fb14d0d8
JR
2020 if (!session_found) {
2021 ERR("Session '%s' not found", session_name);
2022 ret = -LTTNG_ERR_SESS_NOT_FOUND;
2023 goto end;
9f19cc17 2024 }
f3ed775e 2025
fb14d0d8
JR
2026end:
2027 return ret;
2028}
f3ed775e 2029
fb14d0d8
JR
2030/*
2031 * Machine interface
2032 * List all availables session
2033 */
2034static int mi_list_sessions(struct lttng_session *sessions, int count)
2035{
2036 int ret, i;
ae856491 2037
fb14d0d8 2038 /* Opening sessions element */
41493f4a 2039 ret = mi_lttng_sessions_open(the_writer);
fb14d0d8
JR
2040 if (ret) {
2041 goto end;
2042 }
2043
2044 /* Listing sessions */
2045 for (i = 0; i < count; i++) {
41493f4a 2046 ret = mi_lttng_session(the_writer, &sessions[i], 0);
fb14d0d8
JR
2047 if (ret) {
2048 goto end;
2049 }
2050 }
2051
2052 /* Closing sessions element */
41493f4a 2053 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
2054 if (ret) {
2055 goto end;
2056 }
2057
2058end:
f3ed775e
DG
2059 return ret;
2060}
2061
2062/*
9f19cc17 2063 * List available tracing session. List only basic information.
f3ed775e 2064 *
9f19cc17 2065 * If session_name is NULL, all sessions are listed.
f3ed775e 2066 */
9f19cc17 2067static int list_sessions(const char *session_name)
f3ed775e 2068{
fb14d0d8
JR
2069 int ret = CMD_SUCCESS;
2070 int count, i;
9f19cc17 2071 unsigned int session_found = 0;
cd9adb8b 2072 struct lttng_session *sessions = nullptr;
9f19cc17
DG
2073
2074 count = lttng_list_sessions(&sessions);
2075 DBG("Session count %d", count);
2076 if (count < 0) {
fb14d0d8
JR
2077 ret = CMD_ERROR;
2078 ERR("%s", lttng_strerror(count));
d32fb093 2079 goto end;
9f19cc17
DG
2080 }
2081
fb14d0d8
JR
2082 if (lttng_opt_mi) {
2083 /* Mi */
cd9adb8b 2084 if (session_name == nullptr) {
aff0fa72 2085 /* List all sessions */
fb14d0d8
JR
2086 ret = mi_list_sessions(sessions, count);
2087 } else {
2088 /* Note : this return an open session element */
2089 ret = mi_list_session(session_name, sessions, count);
2090 }
2091 if (ret) {
2092 ret = CMD_ERROR;
aff0fa72 2093 goto end;
fb14d0d8
JR
2094 }
2095 } else {
2096 /* Pretty print */
2097 if (count == 0) {
e9711845 2098 MSG("Currently no available recording session");
fb14d0d8
JR
2099 goto end;
2100 }
9f19cc17 2101
cd9adb8b 2102 if (session_name == nullptr) {
e9711845 2103 MSG("Available recording sessions:");
fb14d0d8
JR
2104 }
2105
fb14d0d8 2106 for (i = 0; i < count; i++) {
cd9adb8b 2107 if (session_name != nullptr) {
fb14d0d8
JR
2108 if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
2109 session_found = 1;
28ab034a
JG
2110 MSG("Recording session %s: [%s%s]",
2111 session_name,
2112 active_string(sessions[i].enabled),
2113 snapshot_string(sessions[i].snapshot_mode));
5b89fc92 2114 if (*sessions[i].path) {
28ab034a
JG
2115 MSG("%sTrace output: %s\n",
2116 indent4,
2117 sessions[i].path);
5b89fc92 2118 }
41493f4a 2119 memcpy(&the_listed_session,
28ab034a
JG
2120 &sessions[i],
2121 sizeof(the_listed_session));
fb14d0d8
JR
2122 break;
2123 }
2124 } else {
28ab034a
JG
2125 MSG(" %d) %s [%s%s]",
2126 i + 1,
2127 sessions[i].name,
2128 active_string(sessions[i].enabled),
2129 snapshot_string(sessions[i].snapshot_mode));
5b89fc92
JG
2130 if (*sessions[i].path) {
2131 MSG("%sTrace output: %s", indent4, sessions[i].path);
2132 }
fcbc96a2 2133 if (sessions[i].live_timer_interval != 0) {
28ab034a
JG
2134 MSG("%sLive timer interval: %u %s",
2135 indent4,
2136 sessions[i].live_timer_interval,
2137 USEC_UNIT);
fcbc96a2
JG
2138 }
2139 MSG("");
9f19cc17 2140 }
fb14d0d8
JR
2141 }
2142
cd9adb8b 2143 if (!session_found && session_name != nullptr) {
fb14d0d8
JR
2144 ERR("Session '%s' not found", session_name);
2145 ret = CMD_ERROR;
aff0fa72 2146 goto end;
fb14d0d8
JR
2147 }
2148
cd9adb8b 2149 if (session_name == nullptr) {
fb14d0d8 2150 MSG("\nUse lttng list <session_name> for more details");
9f19cc17
DG
2151 }
2152 }
2153
fb14d0d8 2154end:
aff0fa72 2155 free(sessions);
fb14d0d8
JR
2156 return ret;
2157}
9f19cc17 2158
fb14d0d8
JR
2159/*
2160 * Machine Interface
2161 * list available domain(s) for a session.
2162 */
2163static int mi_list_domains(struct lttng_domain *domains, int count)
2164{
2165 int i, ret;
2166 /* Open domains element */
41493f4a 2167 ret = mi_lttng_domains_open(the_writer);
fb14d0d8
JR
2168 if (ret) {
2169 goto end;
9f19cc17
DG
2170 }
2171
fb14d0d8 2172 for (i = 0; i < count; i++) {
41493f4a 2173 ret = mi_lttng_domain(the_writer, &domains[i], 0);
fb14d0d8
JR
2174 if (ret) {
2175 goto end;
2176 }
9f19cc17 2177 }
f3ed775e 2178
fb14d0d8 2179 /* Closing domains element */
41493f4a 2180 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
2181 if (ret) {
2182 goto end;
2183 }
d32fb093 2184end:
f3ed775e
DG
2185 return ret;
2186}
f3ed775e
DG
2187
2188/*
9f19cc17 2189 * List available domain(s) for a session.
f3ed775e 2190 */
330be774 2191static int list_domains(const char *session_name)
f3ed775e 2192{
9f19cc17 2193 int i, count, ret = CMD_SUCCESS;
cd9adb8b 2194 struct lttng_domain *domains = nullptr;
9f19cc17 2195
330be774 2196 count = lttng_list_domains(session_name, &domains);
9f19cc17 2197 if (count < 0) {
fb14d0d8
JR
2198 ret = CMD_ERROR;
2199 ERR("%s", lttng_strerror(count));
9f19cc17
DG
2200 goto end;
2201 }
2202
fb14d0d8
JR
2203 if (lttng_opt_mi) {
2204 /* Mi output */
2205 ret = mi_list_domains(domains, count);
2206 if (ret) {
2207 ret = CMD_ERROR;
2208 goto error;
2209 }
2210 } else {
2211 /* Pretty print */
2212 MSG("Domains:\n-------------");
2213 if (count == 0) {
2214 MSG(" None");
2215 goto end;
2216 }
2217
2218 for (i = 0; i < count; i++) {
2219 switch (domains[i].type) {
2220 case LTTNG_DOMAIN_KERNEL:
2221 MSG(" - Kernel");
2222 break;
2223 case LTTNG_DOMAIN_UST:
2224 MSG(" - UST global");
2225 break;
2226 case LTTNG_DOMAIN_JUL:
2227 MSG(" - JUL (Java Util Logging)");
2228 break;
5cdb6027
DG
2229 case LTTNG_DOMAIN_LOG4J:
2230 MSG(" - LOG4j (Logging for Java)");
2231 break;
0e115563
DG
2232 case LTTNG_DOMAIN_PYTHON:
2233 MSG(" - Python (logging)");
2234 break;
fb14d0d8
JR
2235 default:
2236 break;
2237 }
9f19cc17
DG
2238 }
2239 }
2240
fb14d0d8 2241error:
9f19cc17
DG
2242 free(domains);
2243
fb14d0d8 2244end:
9f19cc17 2245 return ret;
f3ed775e 2246}
f3ed775e
DG
2247
2248/*
9f19cc17 2249 * The 'list <options>' first level command
f3ed775e
DG
2250 */
2251int cmd_list(int argc, const char **argv)
2252{
c617c0c6 2253 int opt, ret = CMD_SUCCESS;
cd9adb8b 2254 const char *arg_session_name, *leftover = nullptr;
f3ed775e 2255 static poptContext pc;
9f19cc17 2256 struct lttng_domain domain;
cd9adb8b 2257 struct lttng_domain *domains = nullptr;
f3ed775e 2258
441c16a7
MD
2259 memset(&domain, 0, sizeof(domain));
2260
9f19cc17 2261 if (argc < 1) {
ca1c3607 2262 ret = CMD_ERROR;
f3ed775e
DG
2263 goto end;
2264 }
2265
cd9adb8b 2266 pc = poptGetContext(nullptr, argc, argv, long_options, 0);
f3ed775e
DG
2267 poptReadDefaultConfig(pc, 0);
2268
2269 while ((opt = poptGetNextOpt(pc)) != -1) {
2270 switch (opt) {
2271 case OPT_HELP:
4ba92f18 2272 SHOW_HELP();
f3ed775e 2273 goto end;
eeac7d46
MD
2274 case OPT_USERSPACE:
2275 opt_userspace = 1;
eeac7d46 2276 break;
679b4943
SM
2277 case OPT_LIST_OPTIONS:
2278 list_cmd_options(stdout, long_options);
679b4943 2279 goto end;
f3ed775e 2280 default:
f3ed775e
DG
2281 ret = CMD_UNDEFINED;
2282 goto end;
2283 }
2284 }
2285
fb14d0d8
JR
2286 /* Mi check */
2287 if (lttng_opt_mi) {
28ab034a 2288 the_writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
41493f4a 2289 if (!the_writer) {
fb14d0d8
JR
2290 ret = CMD_ERROR;
2291 goto end;
2292 }
2293
2294 /* Open command element */
28ab034a 2295 ret = mi_lttng_writer_command_open(the_writer, mi_lttng_element_command_list);
fb14d0d8
JR
2296 if (ret) {
2297 ret = CMD_ERROR;
2298 goto end;
2299 }
2300
2301 /* Open output element */
28ab034a 2302 ret = mi_lttng_writer_open_element(the_writer, mi_lttng_element_command_output);
fb14d0d8
JR
2303 if (ret) {
2304 ret = CMD_ERROR;
2305 goto end;
2306 }
2307 }
2308
9f19cc17 2309 /* Get session name (trailing argument) */
5b915816
MJ
2310 arg_session_name = poptGetArg(pc);
2311 DBG2("Session name: %s", arg_session_name);
9f19cc17 2312
68c7f6e5
JD
2313 leftover = poptGetArg(pc);
2314 if (leftover) {
2315 ERR("Unknown argument: %s", leftover);
2316 ret = CMD_ERROR;
2317 goto end;
2318 }
2319
cd80958d
DG
2320 if (opt_kernel) {
2321 domain.type = LTTNG_DOMAIN_KERNEL;
b551a063
DG
2322 } else if (opt_userspace) {
2323 DBG2("Listing userspace global domain");
2324 domain.type = LTTNG_DOMAIN_UST;
3c6a091f
DG
2325 } else if (opt_jul) {
2326 DBG2("Listing JUL domain");
2327 domain.type = LTTNG_DOMAIN_JUL;
edf60534 2328 } else if (opt_log4j) {
5cdb6027 2329 domain.type = LTTNG_DOMAIN_LOG4J;
0e115563
DG
2330 } else if (opt_python) {
2331 domain.type = LTTNG_DOMAIN_PYTHON;
cd80958d
DG
2332 }
2333
834978fd
DG
2334 if (!opt_kernel && opt_syscall) {
2335 WARN("--syscall will only work with the Kernel domain (-k)");
2336 ret = CMD_ERROR;
2337 goto end;
2338 }
2339
0e115563 2340 if (opt_kernel || opt_userspace || opt_jul || opt_log4j || opt_python) {
5b915816 2341 the_handle = lttng_create_handle(arg_session_name, &domain);
cd9adb8b 2342 if (the_handle == nullptr) {
aa5de748
MD
2343 ret = CMD_FATAL;
2344 goto end;
2345 }
cd80958d
DG
2346 }
2347
cd9adb8b 2348 if (arg_session_name == nullptr) {
28ab034a 2349 if (!opt_kernel && !opt_userspace && !opt_jul && !opt_log4j && !opt_python) {
cd9adb8b 2350 ret = list_sessions(nullptr);
fb14d0d8 2351 if (ret) {
b551a063
DG
2352 goto end;
2353 }
2354 }
9f19cc17 2355 if (opt_kernel) {
834978fd
DG
2356 if (opt_syscall) {
2357 ret = list_syscalls();
2358 if (ret) {
2359 goto end;
2360 }
2361 } else {
2362 ret = list_kernel_events();
2363 if (ret) {
2364 goto end;
2365 }
9f19cc17 2366 }
b551a063
DG
2367 }
2368 if (opt_userspace) {
f37d259d
MD
2369 if (opt_fields) {
2370 ret = list_ust_event_fields();
2371 } else {
2372 ret = list_ust_events();
2373 }
fb14d0d8 2374 if (ret) {
9f19cc17
DG
2375 goto end;
2376 }
2377 }
0e115563 2378 if (opt_jul || opt_log4j || opt_python) {
5cdb6027 2379 ret = list_agent_events();
fb14d0d8 2380 if (ret) {
3c6a091f
DG
2381 goto end;
2382 }
2383 }
9f19cc17
DG
2384 } else {
2385 /* List session attributes */
fb14d0d8
JR
2386 if (lttng_opt_mi) {
2387 /* Open element sessions
2388 * Present for xml consistency */
41493f4a 2389 ret = mi_lttng_sessions_open(the_writer);
fb14d0d8
JR
2390 if (ret) {
2391 goto end;
2392 }
2393 }
2394 /* MI: the ouptut of list_sessions is an unclosed session element */
5b915816 2395 ret = list_sessions(arg_session_name);
fb14d0d8 2396 if (ret) {
9f19cc17
DG
2397 goto end;
2398 }
2399
5b915816 2400 ret = list_rotate_settings(arg_session_name);
329f3443
JD
2401 if (ret) {
2402 goto end;
2403 }
2404
9f19cc17
DG
2405 /* Domain listing */
2406 if (opt_domain) {
5b915816 2407 ret = list_domains(arg_session_name);
9f19cc17
DG
2408 goto end;
2409 }
2410
fb14d0d8 2411 /* Channel listing */
1c3de747 2412 if (opt_kernel || opt_userspace) {
fb14d0d8
JR
2413 if (lttng_opt_mi) {
2414 /* Add of domains and domain element for xml
2415 * consistency and validation
2416 */
41493f4a 2417 ret = mi_lttng_domains_open(the_writer);
fb14d0d8
JR
2418 if (ret) {
2419 goto end;
2420 }
2421
2422 /* Open domain and leave it open for
2423 * nested channels printing */
41493f4a 2424 ret = mi_lttng_domain(the_writer, &domain, 1);
fb14d0d8
JR
2425 if (ret) {
2426 goto end;
2427 }
fb14d0d8
JR
2428 }
2429
ebbf5ab7 2430 /* Trackers */
83d6d6c4 2431 ret = list_trackers(&domain);
a5dfbb9d
MD
2432 if (ret) {
2433 goto end;
2434 }
2435
ebbf5ab7 2436 /* Channels */
cd80958d 2437 ret = list_channels(opt_channel);
fb14d0d8
JR
2438 if (ret) {
2439 goto end;
2440 }
2441
2442 if (lttng_opt_mi) {
2443 /* Close domain and domain element */
28ab034a 2444 ret = mi_lttng_close_multi_element(the_writer, 2);
fb14d0d8
JR
2445 }
2446 if (ret) {
9f19cc17
DG
2447 goto end;
2448 }
fb14d0d8 2449
9f19cc17 2450 } else {
c617c0c6
MD
2451 int i, nb_domain;
2452
9f19cc17 2453 /* We want all domain(s) */
5b915816 2454 nb_domain = lttng_list_domains(arg_session_name, &domains);
b551a063 2455 if (nb_domain < 0) {
fb14d0d8
JR
2456 ret = CMD_ERROR;
2457 ERR("%s", lttng_strerror(nb_domain));
9f19cc17
DG
2458 goto end;
2459 }
2460
fb14d0d8 2461 if (lttng_opt_mi) {
41493f4a 2462 ret = mi_lttng_domains_open(the_writer);
fb14d0d8
JR
2463 if (ret) {
2464 ret = CMD_ERROR;
2465 goto end;
2466 }
2467 }
2468
b551a063 2469 for (i = 0; i < nb_domain; i++) {
9f19cc17
DG
2470 switch (domains[i].type) {
2471 case LTTNG_DOMAIN_KERNEL:
ac41e67e 2472 MSG("=== Domain: Linux kernel ===\n");
9f19cc17 2473 break;
b551a063 2474 case LTTNG_DOMAIN_UST:
ac41e67e 2475 MSG("=== Domain: User space ===\n");
74707e6e 2476 MSG("Buffering scheme: %s\n",
28ab034a
JG
2477 domains[i].buf_type == LTTNG_BUFFER_PER_PID ?
2478 "per-process" :
2479 "per-user");
b551a063 2480 break;
3c6a091f 2481 case LTTNG_DOMAIN_JUL:
ac41e67e 2482 MSG("=== Domain: java.util.logging (JUL) ===\n");
3c6a091f 2483 break;
5cdb6027 2484 case LTTNG_DOMAIN_LOG4J:
ac41e67e 2485 MSG("=== Domain: log4j ===\n");
5cdb6027 2486 break;
0e115563 2487 case LTTNG_DOMAIN_PYTHON:
ac41e67e 2488 MSG("=== Domain: Python logging ===\n");
0e115563 2489 break;
9f19cc17
DG
2490 default:
2491 MSG("=== Domain: Unimplemented ===\n");
2492 break;
2493 }
2494
fb14d0d8 2495 if (lttng_opt_mi) {
28ab034a 2496 ret = mi_lttng_domain(the_writer, &domains[i], 1);
fb14d0d8
JR
2497 if (ret) {
2498 ret = CMD_ERROR;
2499 goto end;
2500 }
2501 }
2502
cd80958d 2503 /* Clean handle before creating a new one */
41493f4a
SM
2504 if (the_handle) {
2505 lttng_destroy_handle(the_handle);
aa5de748 2506 }
cd80958d 2507
28ab034a 2508 the_handle = lttng_create_handle(arg_session_name, &domains[i]);
cd9adb8b 2509 if (the_handle == nullptr) {
ca1c3607 2510 ret = CMD_FATAL;
cd80958d
DG
2511 goto end;
2512 }
2513
5cdb6027 2514 if (domains[i].type == LTTNG_DOMAIN_JUL ||
28ab034a
JG
2515 domains[i].type == LTTNG_DOMAIN_LOG4J ||
2516 domains[i].type == LTTNG_DOMAIN_PYTHON) {
5cdb6027 2517 ret = list_session_agent_events();
fb14d0d8 2518 if (ret) {
3c6a091f
DG
2519 goto end;
2520 }
cd7b2927
PP
2521
2522 goto next_domain;
3c6a091f 2523 }
a5dfbb9d
MD
2524
2525 switch (domains[i].type) {
2526 case LTTNG_DOMAIN_KERNEL:
2527 case LTTNG_DOMAIN_UST:
83d6d6c4 2528 ret = list_trackers(&domains[i]);
a5dfbb9d
MD
2529 if (ret) {
2530 goto end;
2531 }
2532 break;
2533 default:
2534 break;
2535 }
3c6a091f 2536
cd80958d 2537 ret = list_channels(opt_channel);
fb14d0d8
JR
2538 if (ret) {
2539 goto end;
2540 }
2541
28ab034a 2542 next_domain:
fb14d0d8
JR
2543 if (lttng_opt_mi) {
2544 /* Close domain element */
28ab034a 2545 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
2546 if (ret) {
2547 ret = CMD_ERROR;
2548 goto end;
2549 }
2550 }
fb14d0d8
JR
2551 }
2552 if (lttng_opt_mi) {
2553 /* Close the domains, session and sessions element */
28ab034a 2554 ret = mi_lttng_close_multi_element(the_writer, 3);
fb14d0d8
JR
2555 if (ret) {
2556 ret = CMD_ERROR;
9f19cc17
DG
2557 goto end;
2558 }
2559 }
2560 }
f3ed775e
DG
2561 }
2562
fb14d0d8
JR
2563 /* Mi closing */
2564 if (lttng_opt_mi) {
2565 /* Close output element */
41493f4a 2566 ret = mi_lttng_writer_close_element(the_writer);
fb14d0d8
JR
2567 if (ret) {
2568 ret = CMD_ERROR;
2569 goto end;
2570 }
2571
2572 /* Command element close */
41493f4a 2573 ret = mi_lttng_writer_command_close(the_writer);
fb14d0d8
JR
2574 if (ret) {
2575 ret = CMD_ERROR;
2576 goto end;
2577 }
2578 }
f3ed775e 2579end:
fb14d0d8 2580 /* Mi clean-up */
41493f4a 2581 if (the_writer && mi_lttng_writer_destroy(the_writer)) {
fb14d0d8
JR
2582 /* Preserve original error code */
2583 ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL;
2584 }
2585
0e428499 2586 free(domains);
41493f4a
SM
2587 if (the_handle) {
2588 lttng_destroy_handle(the_handle);
aa5de748 2589 }
cd80958d 2590
ca1c3607 2591 poptFreeContext(pc);
f3ed775e
DG
2592 return ret;
2593}
This page took 0.21131 seconds and 4 git commands to generate.