]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/journalctl-misc.c
Merge pull request #31960 from YHNdnzj/capsule-followup
[thirdparty/systemd.git] / src / journal / journalctl-misc.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "dirent-util.h"
4 #include "fd-util.h"
5 #include "format-table.h"
6 #include "format-util.h"
7 #include "journal-internal.h"
8 #include "journal-verify.h"
9 #include "journalctl.h"
10 #include "journalctl-misc.h"
11 #include "journalctl-util.h"
12 #include "logs-show.h"
13 #include "syslog-util.h"
14
15 int action_print_header(void) {
16 _cleanup_(sd_journal_closep) sd_journal *j = NULL;
17 int r;
18
19 assert(arg_action == ACTION_PRINT_HEADER);
20
21 r = acquire_journal(&j);
22 if (r < 0)
23 return r;
24
25 journal_print_header(j);
26 return 0;
27 }
28
29 int action_verify(void) {
30 _cleanup_(sd_journal_closep) sd_journal *j = NULL;
31 int r;
32
33 assert(arg_action == ACTION_VERIFY);
34
35 r = acquire_journal(&j);
36 if (r < 0)
37 return r;
38
39 log_show_color(true);
40
41 JournalFile *f;
42 ORDERED_HASHMAP_FOREACH(f, j->files) {
43 int k;
44 usec_t first = 0, validated = 0, last = 0;
45
46 #if HAVE_GCRYPT
47 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
48 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
49 #endif
50
51 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, /* show_progress = */ !arg_quiet);
52 if (k == -EINVAL)
53 /* If the key was invalid give up right-away. */
54 return k;
55 if (k < 0)
56 r = log_warning_errno(k, "FAIL: %s (%m)", f->path);
57 else {
58 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
59 log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "PASS: %s", f->path);
60
61 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
62 if (validated > 0) {
63 log_full(arg_quiet ? LOG_DEBUG : LOG_INFO,
64 "=> Validated from %s to %s, final %s entries not sealed.",
65 format_timestamp_maybe_utc(a, sizeof(a), first),
66 format_timestamp_maybe_utc(b, sizeof(b), validated),
67 FORMAT_TIMESPAN(last > validated ? last - validated : 0, 0));
68 } else if (last > 0)
69 log_full(arg_quiet ? LOG_DEBUG : LOG_INFO,
70 "=> No sealing yet, %s of entries not sealed.",
71 FORMAT_TIMESPAN(last - first, 0));
72 else
73 log_full(arg_quiet ? LOG_DEBUG : LOG_INFO,
74 "=> No sealing yet, no entries in file.");
75 }
76 }
77 }
78
79 return r;
80 }
81
82 int action_disk_usage(void) {
83 _cleanup_(sd_journal_closep) sd_journal *j = NULL;
84 uint64_t bytes = 0;
85 int r;
86
87 assert(arg_action == ACTION_DISK_USAGE);
88
89 r = acquire_journal(&j);
90 if (r < 0)
91 return r;
92
93 r = sd_journal_get_usage(j, &bytes);
94 if (r < 0)
95 return log_error_errno(r, "Failed to get disk usage: %m");
96
97 printf("Archived and active journals take up %s in the file system.\n", FORMAT_BYTES(bytes));
98 return 0;
99 }
100
101 int action_list_boots(void) {
102 _cleanup_(sd_journal_closep) sd_journal *j = NULL;
103 _cleanup_(table_unrefp) Table *table = NULL;
104 _cleanup_free_ BootId *boots = NULL;
105 size_t n_boots;
106 int r;
107
108 assert(arg_action == ACTION_LIST_BOOTS);
109
110 r = acquire_journal(&j);
111 if (r < 0)
112 return r;
113
114 r = journal_get_boots(j, &boots, &n_boots);
115 if (r < 0)
116 return log_error_errno(r, "Failed to determine boots: %m");
117 if (r == 0)
118 return 0;
119
120 table = table_new("idx", "boot id", "first entry", "last entry");
121 if (!table)
122 return log_oom();
123
124 if (arg_full)
125 table_set_width(table, 0);
126
127 r = table_set_json_field_name(table, 0, "index");
128 if (r < 0)
129 return log_error_errno(r, "Failed to set JSON field name of column 0: %m");
130
131 (void) table_set_sort(table, (size_t) 0);
132 (void) table_set_reverse(table, 0, arg_reverse);
133
134 FOREACH_ARRAY(i, boots, n_boots) {
135 r = table_add_many(table,
136 TABLE_INT, (int)(i - boots) - (int) n_boots + 1,
137 TABLE_SET_ALIGN_PERCENT, 100,
138 TABLE_ID128, i->id,
139 TABLE_TIMESTAMP, i->first_usec,
140 TABLE_TIMESTAMP, i->last_usec);
141 if (r < 0)
142 return table_log_add_error(r);
143 }
144
145 r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, !arg_quiet);
146 if (r < 0)
147 return table_log_print_error(r);
148
149 return 0;
150 }
151
152 int action_list_fields(void) {
153 _cleanup_(sd_journal_closep) sd_journal *j = NULL;
154 int r, n_shown = 0;
155
156 assert(arg_action == ACTION_LIST_FIELDS);
157 assert(arg_field);
158
159 r = acquire_journal(&j);
160 if (r < 0)
161 return r;
162
163 if (!journal_boot_has_effect(j))
164 return 0;
165
166 r = sd_journal_set_data_threshold(j, 0);
167 if (r < 0)
168 return log_error_errno(r, "Failed to unset data size threshold: %m");
169
170 r = sd_journal_query_unique(j, arg_field);
171 if (r < 0)
172 return log_error_errno(r, "Failed to query unique data objects: %m");
173
174 const void *data;
175 size_t size;
176 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
177 const void *eq;
178
179 if (arg_lines >= 0 && n_shown >= arg_lines)
180 break;
181
182 eq = memchr(data, '=', size);
183 if (eq)
184 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
185 else
186 printf("%.*s\n", (int) size, (const char*) data);
187
188 n_shown++;
189 }
190
191 return 0;
192 }
193
194 int action_list_field_names(void) {
195 _cleanup_(sd_journal_closep) sd_journal *j = NULL;
196 int r;
197
198 assert(arg_action == ACTION_LIST_FIELD_NAMES);
199
200 r = acquire_journal(&j);
201 if (r < 0)
202 return r;
203
204 const char *field;
205 SD_JOURNAL_FOREACH_FIELD(j, field)
206 printf("%s\n", field);
207
208 return 0;
209 }
210
211 int action_list_namespaces(void) {
212 _cleanup_(table_unrefp) Table *table = NULL;
213 sd_id128_t machine;
214 char machine_id[SD_ID128_STRING_MAX];
215 int r;
216
217 assert(arg_action == ACTION_LIST_NAMESPACES);
218
219 r = sd_id128_get_machine(&machine);
220 if (r < 0)
221 return log_error_errno(r, "Failed to get machine ID: %m");
222
223 sd_id128_to_string(machine, machine_id);
224
225 table = table_new("namespace");
226 if (!table)
227 return log_oom();
228
229 (void) table_set_sort(table, (size_t) 0);
230
231 FOREACH_STRING(dir, "/var/log/journal", "/run/log/journal") {
232 _cleanup_free_ char *path = NULL;
233 _cleanup_closedir_ DIR *dirp = NULL;
234
235 path = path_join(arg_root, dir);
236 if (!path)
237 return log_oom();
238
239 dirp = opendir(path);
240 if (!dirp) {
241 log_debug_errno(errno, "Failed to open directory %s, ignoring: %m", path);
242 continue;
243 }
244
245 FOREACH_DIRENT(de, dirp, return log_error_errno(errno, "Failed to iterate through %s: %m", path)) {
246 char *dot;
247
248 if (!startswith(de->d_name, machine_id))
249 continue;
250
251 dot = strchr(de->d_name, '.');
252 if (!dot)
253 continue;
254
255 if (!log_namespace_name_valid(dot + 1))
256 continue;
257
258 r = table_add_cell(table, NULL, TABLE_STRING, dot + 1);
259 if (r < 0)
260 return table_log_add_error(r);
261 }
262 }
263
264 r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, !arg_quiet);
265 if (r < 0)
266 return table_log_print_error(r);
267
268 return 0;
269 }