]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/journalctl.c
4e2a8f6d1184ebac1499ec129412c8aed8fd9521
[thirdparty/systemd.git] / src / journal / journalctl.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <fnmatch.h>
6 #include <getopt.h>
7 #include <linux/fs.h>
8 #include <poll.h>
9 #include <signal.h>
10 #include <stddef.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <sys/inotify.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
16
17 #if HAVE_PCRE2
18 # define PCRE2_CODE_UNIT_WIDTH 8
19 # include <pcre2.h>
20 #endif
21
22 #include "sd-bus.h"
23 #include "sd-device.h"
24 #include "sd-journal.h"
25
26 #include "acl-util.h"
27 #include "alloc-util.h"
28 #include "bus-error.h"
29 #include "bus-util.h"
30 #include "catalog.h"
31 #include "chattr-util.h"
32 #include "def.h"
33 #include "device-private.h"
34 #include "fd-util.h"
35 #include "fileio.h"
36 #include "format-util.h"
37 #include "fs-util.h"
38 #include "fsprg.h"
39 #include "glob-util.h"
40 #include "hostname-util.h"
41 #include "id128-print.h"
42 #include "io-util.h"
43 #include "journal-def.h"
44 #include "journal-internal.h"
45 #include "journal-qrcode.h"
46 #include "journal-util.h"
47 #include "journal-vacuum.h"
48 #include "journal-verify.h"
49 #include "locale-util.h"
50 #include "log.h"
51 #include "logs-show.h"
52 #include "memory-util.h"
53 #include "mkdir.h"
54 #include "mountpoint-util.h"
55 #include "nulstr-util.h"
56 #include "pager.h"
57 #include "parse-util.h"
58 #include "path-util.h"
59 #include "pretty-print.h"
60 #include "rlimit-util.h"
61 #include "set.h"
62 #include "sigbus.h"
63 #include "string-table.h"
64 #include "strv.h"
65 #include "syslog-util.h"
66 #include "terminal-util.h"
67 #include "tmpfile-util.h"
68 #include "unit-name.h"
69 #include "user-util.h"
70 #include "varlink.h"
71
72 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
73 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
74
75 enum {
76 /* Special values for arg_lines */
77 ARG_LINES_DEFAULT = -2,
78 ARG_LINES_ALL = -1,
79 };
80
81 static OutputMode arg_output = OUTPUT_SHORT;
82 static bool arg_utc = false;
83 static bool arg_follow = false;
84 static bool arg_full = true;
85 static bool arg_all = false;
86 static PagerFlags arg_pager_flags = 0;
87 static int arg_lines = ARG_LINES_DEFAULT;
88 static bool arg_no_tail = false;
89 static bool arg_quiet = false;
90 static bool arg_merge = false;
91 static bool arg_boot = false;
92 static sd_id128_t arg_boot_id = {};
93 static int arg_boot_offset = 0;
94 static bool arg_dmesg = false;
95 static bool arg_no_hostname = false;
96 static const char *arg_cursor = NULL;
97 static const char *arg_cursor_file = NULL;
98 static const char *arg_after_cursor = NULL;
99 static bool arg_show_cursor = false;
100 static const char *arg_directory = NULL;
101 static char **arg_file = NULL;
102 static bool arg_file_stdin = false;
103 static int arg_priorities = 0xFF;
104 static char *arg_verify_key = NULL;
105 #if HAVE_GCRYPT
106 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
107 static bool arg_force = false;
108 #endif
109 static usec_t arg_since, arg_until;
110 static bool arg_since_set = false, arg_until_set = false;
111 static char **arg_syslog_identifier = NULL;
112 static char **arg_system_units = NULL;
113 static char **arg_user_units = NULL;
114 static const char *arg_field = NULL;
115 static bool arg_catalog = false;
116 static bool arg_reverse = false;
117 static int arg_journal_type = 0;
118 static int arg_namespace_flags = 0;
119 static char *arg_root = NULL;
120 static const char *arg_machine = NULL;
121 static const char *arg_namespace = NULL;
122 static uint64_t arg_vacuum_size = 0;
123 static uint64_t arg_vacuum_n_files = 0;
124 static usec_t arg_vacuum_time = 0;
125 static char **arg_output_fields = NULL;
126 #if HAVE_PCRE2
127 static const char *arg_pattern = NULL;
128 static pcre2_code *arg_compiled_pattern = NULL;
129 static int arg_case_sensitive = -1; /* -1 means be smart */
130 #endif
131
132 static enum {
133 ACTION_SHOW,
134 ACTION_NEW_ID128,
135 ACTION_PRINT_HEADER,
136 ACTION_SETUP_KEYS,
137 ACTION_VERIFY,
138 ACTION_DISK_USAGE,
139 ACTION_LIST_CATALOG,
140 ACTION_DUMP_CATALOG,
141 ACTION_UPDATE_CATALOG,
142 ACTION_LIST_BOOTS,
143 ACTION_FLUSH,
144 ACTION_RELINQUISH_VAR,
145 ACTION_SYNC,
146 ACTION_ROTATE,
147 ACTION_VACUUM,
148 ACTION_ROTATE_AND_VACUUM,
149 ACTION_LIST_FIELDS,
150 ACTION_LIST_FIELD_NAMES,
151 } arg_action = ACTION_SHOW;
152
153 typedef struct BootId {
154 sd_id128_t id;
155 uint64_t first;
156 uint64_t last;
157 LIST_FIELDS(struct BootId, boot_list);
158 } BootId;
159
160 #if HAVE_PCRE2
161 DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data*, pcre2_match_data_free);
162 DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code*, pcre2_code_free);
163
164 static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out) {
165 int errorcode, r;
166 PCRE2_SIZE erroroffset;
167 pcre2_code *p;
168
169 p = pcre2_compile((PCRE2_SPTR8) pattern,
170 PCRE2_ZERO_TERMINATED, flags, &errorcode, &erroroffset, NULL);
171 if (!p) {
172 unsigned char buf[LINE_MAX];
173
174 r = pcre2_get_error_message(errorcode, buf, sizeof buf);
175
176 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
177 "Bad pattern \"%s\": %s", pattern,
178 r < 0 ? "unknown error" : (char *)buf);
179 }
180
181 *out = p;
182 return 0;
183 }
184
185 #endif
186
187 static int add_matches_for_device(sd_journal *j, const char *devpath) {
188 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
189 sd_device *d = NULL;
190 struct stat st;
191 int r;
192
193 assert(j);
194 assert(devpath);
195
196 if (!path_startswith(devpath, "/dev/")) {
197 log_error("Devpath does not start with /dev/");
198 return -EINVAL;
199 }
200
201 if (stat(devpath, &st) < 0)
202 return log_error_errno(errno, "Couldn't stat file: %m");
203
204 r = device_new_from_stat_rdev(&device, &st);
205 if (r < 0)
206 return log_error_errno(r, "Failed to get device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
207
208 for (d = device; d; ) {
209 _cleanup_free_ char *match = NULL;
210 const char *subsys, *sysname, *devnode;
211 sd_device *parent;
212
213 r = sd_device_get_subsystem(d, &subsys);
214 if (r < 0)
215 goto get_parent;
216
217 r = sd_device_get_sysname(d, &sysname);
218 if (r < 0)
219 goto get_parent;
220
221 match = strjoin("_KERNEL_DEVICE=+", subsys, ":", sysname);
222 if (!match)
223 return log_oom();
224
225 r = sd_journal_add_match(j, match, 0);
226 if (r < 0)
227 return log_error_errno(r, "Failed to add match: %m");
228
229 if (sd_device_get_devname(d, &devnode) >= 0) {
230 _cleanup_free_ char *match1 = NULL;
231
232 r = stat(devnode, &st);
233 if (r < 0)
234 return log_error_errno(r, "Failed to stat() device node \"%s\": %m", devnode);
235
236 r = asprintf(&match1, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st.st_mode) ? 'b' : 'c', major(st.st_rdev), minor(st.st_rdev));
237 if (r < 0)
238 return log_oom();
239
240 r = sd_journal_add_match(j, match1, 0);
241 if (r < 0)
242 return log_error_errno(r, "Failed to add match: %m");
243 }
244
245 get_parent:
246 if (sd_device_get_parent(d, &parent) < 0)
247 break;
248
249 d = parent;
250 }
251
252 r = add_match_this_boot(j, arg_machine);
253 if (r < 0)
254 return log_error_errno(r, "Failed to add match for the current boot: %m");
255
256 return 0;
257 }
258
259 static char *format_timestamp_maybe_utc(char *buf, size_t l, usec_t t) {
260
261 if (arg_utc)
262 return format_timestamp_utc(buf, l, t);
263
264 return format_timestamp(buf, l, t);
265 }
266
267 static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset) {
268 sd_id128_t id = SD_ID128_NULL;
269 int off = 0, r;
270
271 if (streq(x, "all")) {
272 *boot_id = SD_ID128_NULL;
273 *offset = 0;
274 return 0;
275 } else if (strlen(x) >= 32) {
276 char *t;
277
278 t = strndupa(x, 32);
279 r = sd_id128_from_string(t, &id);
280 if (r >= 0)
281 x += 32;
282
283 if (!IN_SET(*x, 0, '-', '+'))
284 return -EINVAL;
285
286 if (*x != 0) {
287 r = safe_atoi(x, &off);
288 if (r < 0)
289 return r;
290 }
291 } else {
292 r = safe_atoi(x, &off);
293 if (r < 0)
294 return r;
295 }
296
297 if (boot_id)
298 *boot_id = id;
299
300 if (offset)
301 *offset = off;
302
303 return 1;
304 }
305
306 static int help(void) {
307 _cleanup_free_ char *link = NULL;
308 int r;
309
310 (void) pager_open(arg_pager_flags);
311
312 r = terminal_urlify_man("journalctl", "1", &link);
313 if (r < 0)
314 return log_oom();
315
316 printf("%1$s [OPTIONS...] [MATCHES...]\n\n"
317 "%5$sQuery the journal.%6$s\n\n"
318 "%3$sOptions:%4$s\n"
319 " --system Show the system journal\n"
320 " --user Show the user journal for the current user\n"
321 " -M --machine=CONTAINER Operate on local container\n"
322 " -S --since=DATE Show entries not older than the specified date\n"
323 " -U --until=DATE Show entries not newer than the specified date\n"
324 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
325 " --after-cursor=CURSOR Show entries after the specified cursor\n"
326 " --show-cursor Print the cursor after all the entries\n"
327 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
328 " -b --boot[=ID] Show current boot or the specified boot\n"
329 " --list-boots Show terse information about recorded boots\n"
330 " -k --dmesg Show kernel message log from the current boot\n"
331 " -u --unit=UNIT Show logs from the specified unit\n"
332 " --user-unit=UNIT Show logs from the specified user unit\n"
333 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
334 " -p --priority=RANGE Show entries with the specified priority\n"
335 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
336 " --case-sensitive[=BOOL] Force case sensitive or insenstive matching\n"
337 " -e --pager-end Immediately jump to the end in the pager\n"
338 " -f --follow Follow the journal\n"
339 " -n --lines[=INTEGER] Number of journal entries to show\n"
340 " --no-tail Show all lines, even in follow mode\n"
341 " -r --reverse Show the newest entries first\n"
342 " -o --output=STRING Change journal output mode (short, short-precise,\n"
343 " short-iso, short-iso-precise, short-full,\n"
344 " short-monotonic, short-unix, verbose, export,\n"
345 " json, json-pretty, json-sse, json-seq, cat,\n"
346 " with-unit)\n"
347 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
348 " --utc Express time in Coordinated Universal Time (UTC)\n"
349 " -x --catalog Add message explanations where available\n"
350 " --no-full Ellipsize fields\n"
351 " -a --all Show all fields, including long and unprintable\n"
352 " -q --quiet Do not show info messages and privilege warning\n"
353 " --no-pager Do not pipe output into a pager\n"
354 " --no-hostname Suppress output of hostname field\n"
355 " -m --merge Show entries from all available journals\n"
356 " -D --directory=PATH Show journal files from directory\n"
357 " --file=PATH Show journal file\n"
358 " --root=ROOT Operate on files below a root directory\n"
359 " --namespace=NAMESPACE Show journal data from specified namespace\n"
360 " --interval=TIME Time interval for changing the FSS sealing key\n"
361 " --verify-key=KEY Specify FSS verification key\n"
362 " --force Override of the FSS key pair with --setup-keys\n"
363 "\n%3$sCommands:%4$s\n"
364 " -h --help Show this help text\n"
365 " --version Show package version\n"
366 " -N --fields List all field names currently used\n"
367 " -F --field=FIELD List all values that a specified field takes\n"
368 " --disk-usage Show total disk usage of all journal files\n"
369 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
370 " --vacuum-files=INT Leave only the specified number of journal files\n"
371 " --vacuum-time=TIME Remove journal files older than specified time\n"
372 " --verify Verify journal file consistency\n"
373 " --sync Synchronize unwritten journal messages to disk\n"
374 " --relinquish-var Stop logging to disk, log to temporary file system\n"
375 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
376 " --flush Flush all journal data from /run into /var\n"
377 " --rotate Request immediate rotation of the journal files\n"
378 " --header Show journal header information\n"
379 " --list-catalog Show all message IDs in the catalog\n"
380 " --dump-catalog Show entries in the message catalog\n"
381 " --update-catalog Update the message catalog database\n"
382 " --setup-keys Generate a new FSS key pair\n"
383 "\nSee the %2$s for details.\n"
384 , program_invocation_short_name
385 , link
386 , ansi_underline(), ansi_normal()
387 , ansi_highlight(), ansi_normal()
388 );
389
390 return 0;
391 }
392
393 static int parse_argv(int argc, char *argv[]) {
394
395 enum {
396 ARG_VERSION = 0x100,
397 ARG_NO_PAGER,
398 ARG_NO_FULL,
399 ARG_NO_TAIL,
400 ARG_NEW_ID128,
401 ARG_THIS_BOOT,
402 ARG_LIST_BOOTS,
403 ARG_USER,
404 ARG_SYSTEM,
405 ARG_ROOT,
406 ARG_HEADER,
407 ARG_SETUP_KEYS,
408 ARG_FILE,
409 ARG_INTERVAL,
410 ARG_VERIFY,
411 ARG_VERIFY_KEY,
412 ARG_DISK_USAGE,
413 ARG_AFTER_CURSOR,
414 ARG_CURSOR_FILE,
415 ARG_SHOW_CURSOR,
416 ARG_USER_UNIT,
417 ARG_LIST_CATALOG,
418 ARG_DUMP_CATALOG,
419 ARG_UPDATE_CATALOG,
420 ARG_FORCE,
421 ARG_CASE_SENSITIVE,
422 ARG_UTC,
423 ARG_SYNC,
424 ARG_FLUSH,
425 ARG_RELINQUISH_VAR,
426 ARG_SMART_RELINQUISH_VAR,
427 ARG_ROTATE,
428 ARG_VACUUM_SIZE,
429 ARG_VACUUM_FILES,
430 ARG_VACUUM_TIME,
431 ARG_NO_HOSTNAME,
432 ARG_OUTPUT_FIELDS,
433 ARG_NAMESPACE,
434 };
435
436 static const struct option options[] = {
437 { "help", no_argument, NULL, 'h' },
438 { "version" , no_argument, NULL, ARG_VERSION },
439 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
440 { "pager-end", no_argument, NULL, 'e' },
441 { "follow", no_argument, NULL, 'f' },
442 { "force", no_argument, NULL, ARG_FORCE },
443 { "output", required_argument, NULL, 'o' },
444 { "all", no_argument, NULL, 'a' },
445 { "full", no_argument, NULL, 'l' },
446 { "no-full", no_argument, NULL, ARG_NO_FULL },
447 { "lines", optional_argument, NULL, 'n' },
448 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
449 { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, /* deprecated */
450 { "quiet", no_argument, NULL, 'q' },
451 { "merge", no_argument, NULL, 'm' },
452 { "this-boot", no_argument, NULL, ARG_THIS_BOOT }, /* deprecated */
453 { "boot", optional_argument, NULL, 'b' },
454 { "list-boots", no_argument, NULL, ARG_LIST_BOOTS },
455 { "dmesg", no_argument, NULL, 'k' },
456 { "system", no_argument, NULL, ARG_SYSTEM },
457 { "user", no_argument, NULL, ARG_USER },
458 { "directory", required_argument, NULL, 'D' },
459 { "file", required_argument, NULL, ARG_FILE },
460 { "root", required_argument, NULL, ARG_ROOT },
461 { "header", no_argument, NULL, ARG_HEADER },
462 { "identifier", required_argument, NULL, 't' },
463 { "priority", required_argument, NULL, 'p' },
464 { "grep", required_argument, NULL, 'g' },
465 { "case-sensitive", optional_argument, NULL, ARG_CASE_SENSITIVE },
466 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
467 { "interval", required_argument, NULL, ARG_INTERVAL },
468 { "verify", no_argument, NULL, ARG_VERIFY },
469 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
470 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
471 { "cursor", required_argument, NULL, 'c' },
472 { "cursor-file", required_argument, NULL, ARG_CURSOR_FILE },
473 { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR },
474 { "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR },
475 { "since", required_argument, NULL, 'S' },
476 { "until", required_argument, NULL, 'U' },
477 { "unit", required_argument, NULL, 'u' },
478 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
479 { "field", required_argument, NULL, 'F' },
480 { "fields", no_argument, NULL, 'N' },
481 { "catalog", no_argument, NULL, 'x' },
482 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
483 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
484 { "update-catalog", no_argument, NULL, ARG_UPDATE_CATALOG },
485 { "reverse", no_argument, NULL, 'r' },
486 { "machine", required_argument, NULL, 'M' },
487 { "utc", no_argument, NULL, ARG_UTC },
488 { "flush", no_argument, NULL, ARG_FLUSH },
489 { "relinquish-var", no_argument, NULL, ARG_RELINQUISH_VAR },
490 { "smart-relinquish-var", no_argument, NULL, ARG_SMART_RELINQUISH_VAR },
491 { "sync", no_argument, NULL, ARG_SYNC },
492 { "rotate", no_argument, NULL, ARG_ROTATE },
493 { "vacuum-size", required_argument, NULL, ARG_VACUUM_SIZE },
494 { "vacuum-files", required_argument, NULL, ARG_VACUUM_FILES },
495 { "vacuum-time", required_argument, NULL, ARG_VACUUM_TIME },
496 { "no-hostname", no_argument, NULL, ARG_NO_HOSTNAME },
497 { "output-fields", required_argument, NULL, ARG_OUTPUT_FIELDS },
498 { "namespace", required_argument, NULL, ARG_NAMESPACE },
499 {}
500 };
501
502 int c, r;
503
504 assert(argc >= 0);
505 assert(argv);
506
507 while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:", options, NULL)) >= 0)
508
509 switch (c) {
510
511 case 'h':
512 return help();
513
514 case ARG_VERSION:
515 return version();
516
517 case ARG_NO_PAGER:
518 arg_pager_flags |= PAGER_DISABLE;
519 break;
520
521 case 'e':
522 arg_pager_flags |= PAGER_JUMP_TO_END;
523
524 if (arg_lines == ARG_LINES_DEFAULT)
525 arg_lines = 1000;
526
527 break;
528
529 case 'f':
530 arg_follow = true;
531 break;
532
533 case 'o':
534 if (streq(optarg, "help")) {
535 DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
536 return 0;
537 }
538
539 arg_output = output_mode_from_string(optarg);
540 if (arg_output < 0)
541 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown output format '%s'.", optarg);
542
543 if (IN_SET(arg_output, OUTPUT_EXPORT, OUTPUT_JSON, OUTPUT_JSON_PRETTY, OUTPUT_JSON_SSE, OUTPUT_JSON_SEQ, OUTPUT_CAT))
544 arg_quiet = true;
545
546 break;
547
548 case 'l':
549 arg_full = true;
550 break;
551
552 case ARG_NO_FULL:
553 arg_full = false;
554 break;
555
556 case 'a':
557 arg_all = true;
558 break;
559
560 case 'n':
561 if (optarg) {
562 if (streq(optarg, "all"))
563 arg_lines = ARG_LINES_ALL;
564 else {
565 r = safe_atoi(optarg, &arg_lines);
566 if (r < 0 || arg_lines < 0)
567 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse lines '%s'", optarg);
568 }
569 } else {
570 arg_lines = 10;
571
572 /* Hmm, no argument? Maybe the next
573 * word on the command line is
574 * supposed to be the argument? Let's
575 * see if there is one, and is
576 * parsable. */
577 if (optind < argc) {
578 int n;
579 if (streq(argv[optind], "all")) {
580 arg_lines = ARG_LINES_ALL;
581 optind++;
582 } else if (safe_atoi(argv[optind], &n) >= 0 && n >= 0) {
583 arg_lines = n;
584 optind++;
585 }
586 }
587 }
588
589 break;
590
591 case ARG_NO_TAIL:
592 arg_no_tail = true;
593 break;
594
595 case ARG_NEW_ID128:
596 arg_action = ACTION_NEW_ID128;
597 break;
598
599 case 'q':
600 arg_quiet = true;
601 break;
602
603 case 'm':
604 arg_merge = true;
605 break;
606
607 case ARG_THIS_BOOT:
608 arg_boot = true;
609 arg_boot_id = SD_ID128_NULL;
610 arg_boot_offset = 0;
611 break;
612
613 case 'b':
614 arg_boot = true;
615 arg_boot_id = SD_ID128_NULL;
616 arg_boot_offset = 0;
617
618 if (optarg) {
619 r = parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset);
620 if (r < 0)
621 return log_error_errno(r, "Failed to parse boot descriptor '%s'", optarg);
622
623 arg_boot = r;
624
625 /* Hmm, no argument? Maybe the next
626 * word on the command line is
627 * supposed to be the argument? Let's
628 * see if there is one and is parsable
629 * as a boot descriptor... */
630 } else if (optind < argc) {
631 r = parse_boot_descriptor(argv[optind], &arg_boot_id, &arg_boot_offset);
632 if (r >= 0) {
633 arg_boot = r;
634 optind++;
635 }
636 }
637 break;
638
639 case ARG_LIST_BOOTS:
640 arg_action = ACTION_LIST_BOOTS;
641 break;
642
643 case 'k':
644 arg_boot = arg_dmesg = true;
645 break;
646
647 case ARG_SYSTEM:
648 arg_journal_type |= SD_JOURNAL_SYSTEM;
649 break;
650
651 case ARG_USER:
652 arg_journal_type |= SD_JOURNAL_CURRENT_USER;
653 break;
654
655 case 'M':
656 arg_machine = optarg;
657 break;
658
659 case ARG_NAMESPACE:
660 if (streq(optarg, "*")) {
661 arg_namespace_flags = SD_JOURNAL_ALL_NAMESPACES;
662 arg_namespace = NULL;
663 } else if (startswith(optarg, "+")) {
664 arg_namespace_flags = SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE;
665 arg_namespace = optarg + 1;
666 } else if (isempty(optarg)) {
667 arg_namespace_flags = 0;
668 arg_namespace = NULL;
669 } else {
670 arg_namespace_flags = 0;
671 arg_namespace = optarg;
672 }
673
674 break;
675
676 case 'D':
677 arg_directory = optarg;
678 break;
679
680 case ARG_FILE:
681 if (streq(optarg, "-"))
682 /* An undocumented feature: we can read journal files from STDIN. We don't document
683 * this though, since after all we only support this for mmap-able, seekable files, and
684 * not for example pipes which are probably the primary usecase for reading things from
685 * STDIN. To avoid confusion we hence don't document this feature. */
686 arg_file_stdin = true;
687 else {
688 r = glob_extend(&arg_file, optarg);
689 if (r < 0)
690 return log_error_errno(r, "Failed to add paths: %m");
691 }
692 break;
693
694 case ARG_ROOT:
695 r = parse_path_argument_and_warn(optarg, true, &arg_root);
696 if (r < 0)
697 return r;
698 break;
699
700 case 'c':
701 arg_cursor = optarg;
702 break;
703
704 case ARG_CURSOR_FILE:
705 arg_cursor_file = optarg;
706 break;
707
708 case ARG_AFTER_CURSOR:
709 arg_after_cursor = optarg;
710 break;
711
712 case ARG_SHOW_CURSOR:
713 arg_show_cursor = true;
714 break;
715
716 case ARG_HEADER:
717 arg_action = ACTION_PRINT_HEADER;
718 break;
719
720 case ARG_VERIFY:
721 arg_action = ACTION_VERIFY;
722 break;
723
724 case ARG_DISK_USAGE:
725 arg_action = ACTION_DISK_USAGE;
726 break;
727
728 case ARG_VACUUM_SIZE:
729 r = parse_size(optarg, 1024, &arg_vacuum_size);
730 if (r < 0)
731 return log_error_errno(r, "Failed to parse vacuum size: %s", optarg);
732
733 arg_action = arg_action == ACTION_ROTATE ? ACTION_ROTATE_AND_VACUUM : ACTION_VACUUM;
734 break;
735
736 case ARG_VACUUM_FILES:
737 r = safe_atou64(optarg, &arg_vacuum_n_files);
738 if (r < 0)
739 return log_error_errno(r, "Failed to parse vacuum files: %s", optarg);
740
741 arg_action = arg_action == ACTION_ROTATE ? ACTION_ROTATE_AND_VACUUM : ACTION_VACUUM;
742 break;
743
744 case ARG_VACUUM_TIME:
745 r = parse_sec(optarg, &arg_vacuum_time);
746 if (r < 0)
747 return log_error_errno(r, "Failed to parse vacuum time: %s", optarg);
748
749 arg_action = arg_action == ACTION_ROTATE ? ACTION_ROTATE_AND_VACUUM : ACTION_VACUUM;
750 break;
751
752 #if HAVE_GCRYPT
753 case ARG_FORCE:
754 arg_force = true;
755 break;
756
757 case ARG_SETUP_KEYS:
758 arg_action = ACTION_SETUP_KEYS;
759 break;
760
761 case ARG_VERIFY_KEY:
762 r = free_and_strdup(&arg_verify_key, optarg);
763 if (r < 0)
764 return r;
765 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
766 * in ps or htop output. */
767 memset(optarg, 'x', strlen(optarg));
768
769 arg_action = ACTION_VERIFY;
770 arg_merge = false;
771 break;
772
773 case ARG_INTERVAL:
774 r = parse_sec(optarg, &arg_interval);
775 if (r < 0 || arg_interval <= 0)
776 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
777 "Failed to parse sealing key change interval: %s", optarg);
778 break;
779 #else
780 case ARG_SETUP_KEYS:
781 case ARG_VERIFY_KEY:
782 case ARG_INTERVAL:
783 case ARG_FORCE:
784 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
785 "Compiled without forward-secure sealing support.");
786 #endif
787
788 case 'p': {
789 const char *dots;
790
791 dots = strstr(optarg, "..");
792 if (dots) {
793 _cleanup_free_ char *a = NULL;
794 int from, to, i;
795
796 /* a range */
797 a = strndup(optarg, dots - optarg);
798 if (!a)
799 return log_oom();
800
801 from = log_level_from_string(a);
802 to = log_level_from_string(dots + 2);
803
804 if (from < 0 || to < 0)
805 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
806 "Failed to parse log level range %s", optarg);
807
808 arg_priorities = 0;
809
810 if (from < to) {
811 for (i = from; i <= to; i++)
812 arg_priorities |= 1 << i;
813 } else {
814 for (i = to; i <= from; i++)
815 arg_priorities |= 1 << i;
816 }
817
818 } else {
819 int p, i;
820
821 p = log_level_from_string(optarg);
822 if (p < 0)
823 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
824 "Unknown log level %s", optarg);
825
826 arg_priorities = 0;
827
828 for (i = 0; i <= p; i++)
829 arg_priorities |= 1 << i;
830 }
831
832 break;
833 }
834
835 #if HAVE_PCRE2
836 case 'g':
837 arg_pattern = optarg;
838 break;
839
840 case ARG_CASE_SENSITIVE:
841 if (optarg) {
842 r = parse_boolean(optarg);
843 if (r < 0)
844 return log_error_errno(r, "Bad --case-sensitive= argument \"%s\": %m", optarg);
845 arg_case_sensitive = r;
846 } else
847 arg_case_sensitive = true;
848
849 break;
850 #else
851 case 'g':
852 case ARG_CASE_SENSITIVE:
853 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Compiled without pattern matching support");
854 #endif
855
856 case 'S':
857 r = parse_timestamp(optarg, &arg_since);
858 if (r < 0)
859 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
860 "Failed to parse timestamp: %s", optarg);
861 arg_since_set = true;
862 break;
863
864 case 'U':
865 r = parse_timestamp(optarg, &arg_until);
866 if (r < 0)
867 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
868 "Failed to parse timestamp: %s", optarg);
869 arg_until_set = true;
870 break;
871
872 case 't':
873 r = strv_extend(&arg_syslog_identifier, optarg);
874 if (r < 0)
875 return log_oom();
876 break;
877
878 case 'u':
879 r = strv_extend(&arg_system_units, optarg);
880 if (r < 0)
881 return log_oom();
882 break;
883
884 case ARG_USER_UNIT:
885 r = strv_extend(&arg_user_units, optarg);
886 if (r < 0)
887 return log_oom();
888 break;
889
890 case 'F':
891 arg_action = ACTION_LIST_FIELDS;
892 arg_field = optarg;
893 break;
894
895 case 'N':
896 arg_action = ACTION_LIST_FIELD_NAMES;
897 break;
898
899 case ARG_NO_HOSTNAME:
900 arg_no_hostname = true;
901 break;
902
903 case 'x':
904 arg_catalog = true;
905 break;
906
907 case ARG_LIST_CATALOG:
908 arg_action = ACTION_LIST_CATALOG;
909 break;
910
911 case ARG_DUMP_CATALOG:
912 arg_action = ACTION_DUMP_CATALOG;
913 break;
914
915 case ARG_UPDATE_CATALOG:
916 arg_action = ACTION_UPDATE_CATALOG;
917 break;
918
919 case 'r':
920 arg_reverse = true;
921 break;
922
923 case ARG_UTC:
924 arg_utc = true;
925 break;
926
927 case ARG_FLUSH:
928 arg_action = ACTION_FLUSH;
929 break;
930
931 case ARG_SMART_RELINQUISH_VAR: {
932 int root_mnt_id, log_mnt_id;
933
934 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
935 * if it's on the same mount as the root file system there's no point in
936 * relinquishing access and we can leave journald write to it until the very last
937 * moment. */
938
939 r = path_get_mnt_id("/", &root_mnt_id);
940 if (r < 0)
941 log_debug_errno(r, "Failed to get root mount ID, ignoring: %m");
942 else {
943 r = path_get_mnt_id("/var/log/journal/", &log_mnt_id);
944 if (r < 0)
945 log_debug_errno(r, "Failed to get journal directory mount ID, ignoring: %m");
946 else if (root_mnt_id == log_mnt_id) {
947 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
948 return 0;
949 } else
950 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
951 }
952
953 _fallthrough_;
954 }
955
956 case ARG_RELINQUISH_VAR:
957 arg_action = ACTION_RELINQUISH_VAR;
958 break;
959
960 case ARG_ROTATE:
961 arg_action = arg_action == ACTION_VACUUM ? ACTION_ROTATE_AND_VACUUM : ACTION_ROTATE;
962 break;
963
964 case ARG_SYNC:
965 arg_action = ACTION_SYNC;
966 break;
967
968 case ARG_OUTPUT_FIELDS: {
969 _cleanup_strv_free_ char **v = NULL;
970
971 v = strv_split(optarg, ",");
972 if (!v)
973 return log_oom();
974
975 if (!arg_output_fields)
976 arg_output_fields = TAKE_PTR(v);
977 else {
978 r = strv_extend_strv(&arg_output_fields, v, true);
979 if (r < 0)
980 return log_oom();
981 }
982 break;
983 }
984
985 case '?':
986 return -EINVAL;
987
988 default:
989 assert_not_reached("Unhandled option");
990 }
991
992 if (arg_follow && !arg_no_tail && !arg_since && arg_lines == ARG_LINES_DEFAULT)
993 arg_lines = 10;
994
995 if (!!arg_directory + !!arg_file + !!arg_machine + !!arg_root > 1) {
996 log_error("Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root.");
997 return -EINVAL;
998 }
999
1000 if (arg_since_set && arg_until_set && arg_since > arg_until) {
1001 log_error("--since= must be before --until=.");
1002 return -EINVAL;
1003 }
1004
1005 if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1) {
1006 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
1007 return -EINVAL;
1008 }
1009
1010 if (arg_follow && arg_reverse) {
1011 log_error("Please specify either --reverse= or --follow=, not both.");
1012 return -EINVAL;
1013 }
1014
1015 if (!IN_SET(arg_action, ACTION_SHOW, ACTION_DUMP_CATALOG, ACTION_LIST_CATALOG) && optind < argc) {
1016 log_error("Extraneous arguments starting with '%s'", argv[optind]);
1017 return -EINVAL;
1018 }
1019
1020 if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && arg_merge) {
1021 log_error("Using --boot or --list-boots with --merge is not supported.");
1022 return -EINVAL;
1023 }
1024
1025 if (!strv_isempty(arg_system_units) && arg_journal_type == SD_JOURNAL_CURRENT_USER) {
1026 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1027 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1028 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1029 r = strv_extend_strv(&arg_user_units, arg_system_units, true);
1030 if (r < 0)
1031 return r;
1032
1033 arg_system_units = strv_free(arg_system_units);
1034 }
1035
1036 #if HAVE_PCRE2
1037 if (arg_pattern) {
1038 unsigned flags;
1039
1040 if (arg_case_sensitive >= 0)
1041 flags = !arg_case_sensitive * PCRE2_CASELESS;
1042 else {
1043 _cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL;
1044 bool has_case;
1045 _cleanup_(pcre2_code_freep) pcre2_code *cs = NULL;
1046
1047 md = pcre2_match_data_create(1, NULL);
1048 if (!md)
1049 return log_oom();
1050
1051 r = pattern_compile("[[:upper:]]", 0, &cs);
1052 if (r < 0)
1053 return r;
1054
1055 r = pcre2_match(cs, (PCRE2_SPTR8) arg_pattern, PCRE2_ZERO_TERMINATED, 0, 0, md, NULL);
1056 has_case = r >= 0;
1057
1058 flags = !has_case * PCRE2_CASELESS;
1059 }
1060
1061 log_debug("Doing case %s matching based on %s",
1062 flags & PCRE2_CASELESS ? "insensitive" : "sensitive",
1063 arg_case_sensitive >= 0 ? "request" : "pattern casing");
1064
1065 r = pattern_compile(arg_pattern, flags, &arg_compiled_pattern);
1066 if (r < 0)
1067 return r;
1068 }
1069 #endif
1070
1071 return 1;
1072 }
1073
1074 static int add_matches(sd_journal *j, char **args) {
1075 char **i;
1076 bool have_term = false;
1077
1078 assert(j);
1079
1080 STRV_FOREACH(i, args) {
1081 int r;
1082
1083 if (streq(*i, "+")) {
1084 if (!have_term)
1085 break;
1086 r = sd_journal_add_disjunction(j);
1087 have_term = false;
1088
1089 } else if (path_is_absolute(*i)) {
1090 _cleanup_free_ char *p = NULL, *t = NULL, *t2 = NULL, *interpreter = NULL;
1091 struct stat st;
1092
1093 r = chase_symlinks(*i, NULL, CHASE_TRAIL_SLASH, &p, NULL);
1094 if (r < 0)
1095 return log_error_errno(r, "Couldn't canonicalize path: %m");
1096
1097 if (lstat(p, &st) < 0)
1098 return log_error_errno(errno, "Couldn't stat file: %m");
1099
1100 if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
1101 if (executable_is_script(p, &interpreter) > 0) {
1102 _cleanup_free_ char *comm;
1103
1104 comm = strndup(basename(p), 15);
1105 if (!comm)
1106 return log_oom();
1107
1108 t = strjoin("_COMM=", comm);
1109 if (!t)
1110 return log_oom();
1111
1112 /* Append _EXE only if the interpreter is not a link.
1113 Otherwise, it might be outdated often. */
1114 if (lstat(interpreter, &st) == 0 && !S_ISLNK(st.st_mode)) {
1115 t2 = strjoin("_EXE=", interpreter);
1116 if (!t2)
1117 return log_oom();
1118 }
1119 } else {
1120 t = strjoin("_EXE=", p);
1121 if (!t)
1122 return log_oom();
1123 }
1124
1125 r = sd_journal_add_match(j, t, 0);
1126
1127 if (r >=0 && t2)
1128 r = sd_journal_add_match(j, t2, 0);
1129
1130 } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
1131 r = add_matches_for_device(j, p);
1132 if (r < 0)
1133 return r;
1134 } else
1135 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1136 "File is neither a device node, nor regular file, nor executable: %s",
1137 *i);
1138
1139 have_term = true;
1140 } else {
1141 r = sd_journal_add_match(j, *i, 0);
1142 have_term = true;
1143 }
1144
1145 if (r < 0)
1146 return log_error_errno(r, "Failed to add match '%s': %m", *i);
1147 }
1148
1149 if (!strv_isempty(args) && !have_term)
1150 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1151 "\"+\" can only be used between terms");
1152
1153 return 0;
1154 }
1155
1156 static void boot_id_free_all(BootId *l) {
1157
1158 while (l) {
1159 BootId *i = l;
1160 LIST_REMOVE(boot_list, l, i);
1161 free(i);
1162 }
1163 }
1164
1165 static int discover_next_boot(sd_journal *j,
1166 sd_id128_t previous_boot_id,
1167 bool advance_older,
1168 BootId **ret) {
1169
1170 _cleanup_free_ BootId *next_boot = NULL;
1171 char match[9+32+1] = "_BOOT_ID=";
1172 sd_id128_t boot_id;
1173 int r;
1174
1175 assert(j);
1176 assert(ret);
1177
1178 /* We expect the journal to be on the last position of a boot
1179 * (in relation to the direction we are going), so that the next
1180 * invocation of sd_journal_next/previous will be from a different
1181 * boot. We then collect any information we desire and then jump
1182 * to the last location of the new boot by using a _BOOT_ID match
1183 * coming from the other journal direction. */
1184
1185 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1186 * we can actually advance to a *different* boot. */
1187 sd_journal_flush_matches(j);
1188
1189 do {
1190 if (advance_older)
1191 r = sd_journal_previous(j);
1192 else
1193 r = sd_journal_next(j);
1194 if (r < 0)
1195 return r;
1196 else if (r == 0)
1197 return 0; /* End of journal, yay. */
1198
1199 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1200 if (r < 0)
1201 return r;
1202
1203 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1204 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1205 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1206 * complete than the main entry array, and hence might reference an entry that's not actually the last
1207 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1208 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1209 * necessary. */
1210
1211 } while (sd_id128_equal(boot_id, previous_boot_id));
1212
1213 next_boot = new0(BootId, 1);
1214 if (!next_boot)
1215 return -ENOMEM;
1216
1217 next_boot->id = boot_id;
1218
1219 r = sd_journal_get_realtime_usec(j, &next_boot->first);
1220 if (r < 0)
1221 return r;
1222
1223 /* Now seek to the last occurrence of this boot ID. */
1224 sd_id128_to_string(next_boot->id, match + 9);
1225 r = sd_journal_add_match(j, match, sizeof(match) - 1);
1226 if (r < 0)
1227 return r;
1228
1229 if (advance_older)
1230 r = sd_journal_seek_head(j);
1231 else
1232 r = sd_journal_seek_tail(j);
1233 if (r < 0)
1234 return r;
1235
1236 if (advance_older)
1237 r = sd_journal_next(j);
1238 else
1239 r = sd_journal_previous(j);
1240 if (r < 0)
1241 return r;
1242 else if (r == 0)
1243 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA),
1244 "Whoopsie! We found a boot ID but can't read its last entry."); /* This shouldn't happen. We just came from this very boot ID. */
1245
1246 r = sd_journal_get_realtime_usec(j, &next_boot->last);
1247 if (r < 0)
1248 return r;
1249
1250 *ret = TAKE_PTR(next_boot);
1251
1252 return 0;
1253 }
1254
1255 static int get_boots(
1256 sd_journal *j,
1257 BootId **boots,
1258 sd_id128_t *boot_id,
1259 int offset) {
1260
1261 bool skip_once;
1262 int r, count = 0;
1263 BootId *head = NULL, *tail = NULL, *id;
1264 const bool advance_older = boot_id && offset <= 0;
1265 sd_id128_t previous_boot_id;
1266
1267 assert(j);
1268
1269 /* Adjust for the asymmetry that offset 0 is
1270 * the last (and current) boot, while 1 is considered the
1271 * (chronological) first boot in the journal. */
1272 skip_once = boot_id && sd_id128_is_null(*boot_id) && offset <= 0;
1273
1274 /* Advance to the earliest/latest occurrence of our reference
1275 * boot ID (taking our lookup direction into account), so that
1276 * discover_next_boot() can do its job.
1277 * If no reference is given, the journal head/tail will do,
1278 * they're "virtual" boots after all. */
1279 if (boot_id && !sd_id128_is_null(*boot_id)) {
1280 char match[9+32+1] = "_BOOT_ID=";
1281
1282 sd_journal_flush_matches(j);
1283
1284 sd_id128_to_string(*boot_id, match + 9);
1285 r = sd_journal_add_match(j, match, sizeof(match) - 1);
1286 if (r < 0)
1287 return r;
1288
1289 if (advance_older)
1290 r = sd_journal_seek_head(j); /* seek to oldest */
1291 else
1292 r = sd_journal_seek_tail(j); /* seek to newest */
1293 if (r < 0)
1294 return r;
1295
1296 if (advance_older)
1297 r = sd_journal_next(j); /* read the oldest entry */
1298 else
1299 r = sd_journal_previous(j); /* read the most recently added entry */
1300 if (r < 0)
1301 return r;
1302 else if (r == 0)
1303 goto finish;
1304 else if (offset == 0) {
1305 count = 1;
1306 goto finish;
1307 }
1308
1309 /* At this point the read pointer is positioned at the oldest/newest occurrence of the reference boot
1310 * ID. After flushing the matches, one more invocation of _previous()/_next() will hence place us at
1311 * the following entry, which must then have an older/newer boot ID */
1312 } else {
1313
1314 if (advance_older)
1315 r = sd_journal_seek_tail(j); /* seek to newest */
1316 else
1317 r = sd_journal_seek_head(j); /* seek to oldest */
1318 if (r < 0)
1319 return r;
1320
1321 /* No sd_journal_next()/_previous() here.
1322 *
1323 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1324 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1325 * entry we have. */
1326 }
1327
1328 previous_boot_id = SD_ID128_NULL;
1329 for (;;) {
1330 _cleanup_free_ BootId *current = NULL;
1331
1332 r = discover_next_boot(j, previous_boot_id, advance_older, &current);
1333 if (r < 0) {
1334 boot_id_free_all(head);
1335 return r;
1336 }
1337
1338 if (!current)
1339 break;
1340
1341 previous_boot_id = current->id;
1342
1343 if (boot_id) {
1344 if (!skip_once)
1345 offset += advance_older ? 1 : -1;
1346 skip_once = false;
1347
1348 if (offset == 0) {
1349 count = 1;
1350 *boot_id = current->id;
1351 break;
1352 }
1353 } else {
1354 LIST_FOREACH(boot_list, id, head) {
1355 if (sd_id128_equal(id->id, current->id)) {
1356 /* boot id already stored, something wrong with the journal files */
1357 /* exiting as otherwise this problem would cause forever loop */
1358 goto finish;
1359 }
1360 }
1361 LIST_INSERT_AFTER(boot_list, head, tail, current);
1362 tail = TAKE_PTR(current);
1363 count++;
1364 }
1365 }
1366
1367 finish:
1368 if (boots)
1369 *boots = head;
1370
1371 sd_journal_flush_matches(j);
1372
1373 return count;
1374 }
1375
1376 static int list_boots(sd_journal *j) {
1377 int w, i, count;
1378 BootId *id, *all_ids;
1379
1380 assert(j);
1381
1382 count = get_boots(j, &all_ids, NULL, 0);
1383 if (count < 0)
1384 return log_error_errno(count, "Failed to determine boots: %m");
1385 if (count == 0)
1386 return count;
1387
1388 (void) pager_open(arg_pager_flags);
1389
1390 /* numbers are one less, but we need an extra char for the sign */
1391 w = DECIMAL_STR_WIDTH(count - 1) + 1;
1392
1393 i = 0;
1394 LIST_FOREACH(boot_list, id, all_ids) {
1395 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
1396
1397 printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
1398 w, i - count + 1,
1399 SD_ID128_FORMAT_VAL(id->id),
1400 format_timestamp_maybe_utc(a, sizeof(a), id->first),
1401 format_timestamp_maybe_utc(b, sizeof(b), id->last));
1402 i++;
1403 }
1404
1405 boot_id_free_all(all_ids);
1406
1407 return 0;
1408 }
1409
1410 static int add_boot(sd_journal *j) {
1411 char match[9+32+1] = "_BOOT_ID=";
1412 sd_id128_t boot_id;
1413 int r;
1414
1415 assert(j);
1416
1417 if (!arg_boot)
1418 return 0;
1419
1420 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1421 * We can do this only when we logs are coming from the current machine,
1422 * so take the slow path if log location is specified. */
1423 if (arg_boot_offset == 0 && sd_id128_is_null(arg_boot_id) &&
1424 !arg_directory && !arg_file && !arg_root)
1425 return add_match_this_boot(j, arg_machine);
1426
1427 boot_id = arg_boot_id;
1428 r = get_boots(j, NULL, &boot_id, arg_boot_offset);
1429 assert(r <= 1);
1430 if (r <= 0) {
1431 const char *reason = (r == 0) ? "No such boot ID in journal" : strerror_safe(r);
1432
1433 if (sd_id128_is_null(arg_boot_id))
1434 log_error("Data from the specified boot (%+i) is not available: %s",
1435 arg_boot_offset, reason);
1436 else
1437 log_error("Data from the specified boot ("SD_ID128_FORMAT_STR") is not available: %s",
1438 SD_ID128_FORMAT_VAL(arg_boot_id), reason);
1439
1440 return r == 0 ? -ENODATA : r;
1441 }
1442
1443 sd_id128_to_string(boot_id, match + 9);
1444
1445 r = sd_journal_add_match(j, match, sizeof(match) - 1);
1446 if (r < 0)
1447 return log_error_errno(r, "Failed to add match: %m");
1448
1449 r = sd_journal_add_conjunction(j);
1450 if (r < 0)
1451 return log_error_errno(r, "Failed to add conjunction: %m");
1452
1453 return 0;
1454 }
1455
1456 static int add_dmesg(sd_journal *j) {
1457 int r;
1458 assert(j);
1459
1460 if (!arg_dmesg)
1461 return 0;
1462
1463 r = sd_journal_add_match(j, "_TRANSPORT=kernel",
1464 STRLEN("_TRANSPORT=kernel"));
1465 if (r < 0)
1466 return log_error_errno(r, "Failed to add match: %m");
1467
1468 r = sd_journal_add_conjunction(j);
1469 if (r < 0)
1470 return log_error_errno(r, "Failed to add conjunction: %m");
1471
1472 return 0;
1473 }
1474
1475 static int get_possible_units(
1476 sd_journal *j,
1477 const char *fields,
1478 char **patterns,
1479 Set **units) {
1480
1481 _cleanup_set_free_free_ Set *found;
1482 const char *field;
1483 int r;
1484
1485 found = set_new(&string_hash_ops);
1486 if (!found)
1487 return -ENOMEM;
1488
1489 NULSTR_FOREACH(field, fields) {
1490 const void *data;
1491 size_t size;
1492
1493 r = sd_journal_query_unique(j, field);
1494 if (r < 0)
1495 return r;
1496
1497 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1498 char **pattern, *eq;
1499 size_t prefix;
1500 _cleanup_free_ char *u = NULL;
1501
1502 eq = memchr(data, '=', size);
1503 if (eq)
1504 prefix = eq - (char*) data + 1;
1505 else
1506 prefix = 0;
1507
1508 u = strndup((char*) data + prefix, size - prefix);
1509 if (!u)
1510 return -ENOMEM;
1511
1512 STRV_FOREACH(pattern, patterns)
1513 if (fnmatch(*pattern, u, FNM_NOESCAPE) == 0) {
1514 log_debug("Matched %s with pattern %s=%s", u, field, *pattern);
1515
1516 r = set_consume(found, u);
1517 u = NULL;
1518 if (r < 0 && r != -EEXIST)
1519 return r;
1520
1521 break;
1522 }
1523 }
1524 }
1525
1526 *units = TAKE_PTR(found);
1527
1528 return 0;
1529 }
1530
1531 /* This list is supposed to return the superset of unit names
1532 * possibly matched by rules added with add_matches_for_unit... */
1533 #define SYSTEM_UNITS \
1534 "_SYSTEMD_UNIT\0" \
1535 "COREDUMP_UNIT\0" \
1536 "UNIT\0" \
1537 "OBJECT_SYSTEMD_UNIT\0" \
1538 "_SYSTEMD_SLICE\0"
1539
1540 /* ... and add_matches_for_user_unit */
1541 #define USER_UNITS \
1542 "_SYSTEMD_USER_UNIT\0" \
1543 "USER_UNIT\0" \
1544 "COREDUMP_USER_UNIT\0" \
1545 "OBJECT_SYSTEMD_USER_UNIT\0" \
1546 "_SYSTEMD_USER_SLICE\0"
1547
1548 static int add_units(sd_journal *j) {
1549 _cleanup_strv_free_ char **patterns = NULL;
1550 int r, count = 0;
1551 char **i;
1552
1553 assert(j);
1554
1555 STRV_FOREACH(i, arg_system_units) {
1556 _cleanup_free_ char *u = NULL;
1557
1558 r = unit_name_mangle(*i, UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN), &u);
1559 if (r < 0)
1560 return r;
1561
1562 if (string_is_glob(u)) {
1563 r = strv_push(&patterns, u);
1564 if (r < 0)
1565 return r;
1566 u = NULL;
1567 } else {
1568 r = add_matches_for_unit(j, u);
1569 if (r < 0)
1570 return r;
1571 r = sd_journal_add_disjunction(j);
1572 if (r < 0)
1573 return r;
1574 count++;
1575 }
1576 }
1577
1578 if (!strv_isempty(patterns)) {
1579 _cleanup_set_free_free_ Set *units = NULL;
1580 Iterator it;
1581 char *u;
1582
1583 r = get_possible_units(j, SYSTEM_UNITS, patterns, &units);
1584 if (r < 0)
1585 return r;
1586
1587 SET_FOREACH(u, units, it) {
1588 r = add_matches_for_unit(j, u);
1589 if (r < 0)
1590 return r;
1591 r = sd_journal_add_disjunction(j);
1592 if (r < 0)
1593 return r;
1594 count++;
1595 }
1596 }
1597
1598 patterns = strv_free(patterns);
1599
1600 STRV_FOREACH(i, arg_user_units) {
1601 _cleanup_free_ char *u = NULL;
1602
1603 r = unit_name_mangle(*i, UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN), &u);
1604 if (r < 0)
1605 return r;
1606
1607 if (string_is_glob(u)) {
1608 r = strv_push(&patterns, u);
1609 if (r < 0)
1610 return r;
1611 u = NULL;
1612 } else {
1613 r = add_matches_for_user_unit(j, u, getuid());
1614 if (r < 0)
1615 return r;
1616 r = sd_journal_add_disjunction(j);
1617 if (r < 0)
1618 return r;
1619 count++;
1620 }
1621 }
1622
1623 if (!strv_isempty(patterns)) {
1624 _cleanup_set_free_free_ Set *units = NULL;
1625 Iterator it;
1626 char *u;
1627
1628 r = get_possible_units(j, USER_UNITS, patterns, &units);
1629 if (r < 0)
1630 return r;
1631
1632 SET_FOREACH(u, units, it) {
1633 r = add_matches_for_user_unit(j, u, getuid());
1634 if (r < 0)
1635 return r;
1636 r = sd_journal_add_disjunction(j);
1637 if (r < 0)
1638 return r;
1639 count++;
1640 }
1641 }
1642
1643 /* Complain if the user request matches but nothing whatsoever was
1644 * found, since otherwise everything would be matched. */
1645 if (!(strv_isempty(arg_system_units) && strv_isempty(arg_user_units)) && count == 0)
1646 return -ENODATA;
1647
1648 r = sd_journal_add_conjunction(j);
1649 if (r < 0)
1650 return r;
1651
1652 return 0;
1653 }
1654
1655 static int add_priorities(sd_journal *j) {
1656 char match[] = "PRIORITY=0";
1657 int i, r;
1658 assert(j);
1659
1660 if (arg_priorities == 0xFF)
1661 return 0;
1662
1663 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
1664 if (arg_priorities & (1 << i)) {
1665 match[sizeof(match)-2] = '0' + i;
1666
1667 r = sd_journal_add_match(j, match, strlen(match));
1668 if (r < 0)
1669 return log_error_errno(r, "Failed to add match: %m");
1670 }
1671
1672 r = sd_journal_add_conjunction(j);
1673 if (r < 0)
1674 return log_error_errno(r, "Failed to add conjunction: %m");
1675
1676 return 0;
1677 }
1678
1679 static int add_syslog_identifier(sd_journal *j) {
1680 int r;
1681 char **i;
1682
1683 assert(j);
1684
1685 STRV_FOREACH(i, arg_syslog_identifier) {
1686 _cleanup_free_ char *u = NULL;
1687
1688 u = strjoin("SYSLOG_IDENTIFIER=", *i);
1689 if (!u)
1690 return -ENOMEM;
1691 r = sd_journal_add_match(j, u, 0);
1692 if (r < 0)
1693 return r;
1694 r = sd_journal_add_disjunction(j);
1695 if (r < 0)
1696 return r;
1697 }
1698
1699 r = sd_journal_add_conjunction(j);
1700 if (r < 0)
1701 return r;
1702
1703 return 0;
1704 }
1705
1706 static int setup_keys(void) {
1707 #if HAVE_GCRYPT
1708 size_t mpk_size, seed_size, state_size, i;
1709 uint8_t *mpk, *seed, *state;
1710 int fd = -1, r;
1711 sd_id128_t machine, boot;
1712 char *p = NULL, *k = NULL;
1713 struct FSSHeader h;
1714 uint64_t n;
1715 struct stat st;
1716
1717 r = stat("/var/log/journal", &st);
1718 if (r < 0 && !IN_SET(errno, ENOENT, ENOTDIR))
1719 return log_error_errno(errno, "stat(\"%s\") failed: %m", "/var/log/journal");
1720
1721 if (r < 0 || !S_ISDIR(st.st_mode)) {
1722 log_error("%s is not a directory, must be using persistent logging for FSS.",
1723 "/var/log/journal");
1724 return r < 0 ? -errno : -ENOTDIR;
1725 }
1726
1727 r = sd_id128_get_machine(&machine);
1728 if (r < 0)
1729 return log_error_errno(r, "Failed to get machine ID: %m");
1730
1731 r = sd_id128_get_boot(&boot);
1732 if (r < 0)
1733 return log_error_errno(r, "Failed to get boot ID: %m");
1734
1735 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
1736 SD_ID128_FORMAT_VAL(machine)) < 0)
1737 return log_oom();
1738
1739 if (arg_force) {
1740 r = unlink(p);
1741 if (r < 0 && errno != ENOENT) {
1742 r = log_error_errno(errno, "unlink(\"%s\") failed: %m", p);
1743 goto finish;
1744 }
1745 } else if (access(p, F_OK) >= 0) {
1746 log_error("Sealing key file %s exists already. Use --force to recreate.", p);
1747 r = -EEXIST;
1748 goto finish;
1749 }
1750
1751 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
1752 SD_ID128_FORMAT_VAL(machine)) < 0) {
1753 r = log_oom();
1754 goto finish;
1755 }
1756
1757 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
1758 mpk = alloca(mpk_size);
1759
1760 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
1761 seed = alloca(seed_size);
1762
1763 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
1764 state = alloca(state_size);
1765
1766 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1767 if (fd < 0) {
1768 r = log_error_errno(errno, "Failed to open /dev/random: %m");
1769 goto finish;
1770 }
1771
1772 log_info("Generating seed...");
1773 r = loop_read_exact(fd, seed, seed_size, true);
1774 if (r < 0) {
1775 log_error_errno(r, "Failed to read random seed: %m");
1776 goto finish;
1777 }
1778
1779 log_info("Generating key pair...");
1780 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
1781
1782 log_info("Generating sealing key...");
1783 FSPRG_GenState0(state, mpk, seed, seed_size);
1784
1785 assert(arg_interval > 0);
1786
1787 n = now(CLOCK_REALTIME);
1788 n /= arg_interval;
1789
1790 safe_close(fd);
1791 fd = mkostemp_safe(k);
1792 if (fd < 0) {
1793 r = log_error_errno(fd, "Failed to open %s: %m", k);
1794 goto finish;
1795 }
1796
1797 /* Enable secure remove, exclusion from dump, synchronous
1798 * writing and in-place updating */
1799 r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, NULL);
1800 if (r < 0)
1801 log_warning_errno(r, "Failed to set file attributes: %m");
1802
1803 zero(h);
1804 memcpy(h.signature, "KSHHRHLP", 8);
1805 h.machine_id = machine;
1806 h.boot_id = boot;
1807 h.header_size = htole64(sizeof(h));
1808 h.start_usec = htole64(n * arg_interval);
1809 h.interval_usec = htole64(arg_interval);
1810 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
1811 h.fsprg_state_size = htole64(state_size);
1812
1813 r = loop_write(fd, &h, sizeof(h), false);
1814 if (r < 0) {
1815 log_error_errno(r, "Failed to write header: %m");
1816 goto finish;
1817 }
1818
1819 r = loop_write(fd, state, state_size, false);
1820 if (r < 0) {
1821 log_error_errno(r, "Failed to write state: %m");
1822 goto finish;
1823 }
1824
1825 if (link(k, p) < 0) {
1826 r = log_error_errno(errno, "Failed to link file: %m");
1827 goto finish;
1828 }
1829
1830 if (on_tty()) {
1831 fprintf(stderr,
1832 "\n"
1833 "The new key pair has been generated. The %ssecret sealing key%s has been written to\n"
1834 "the following local file. This key file is automatically updated when the\n"
1835 "sealing key is advanced. It should not be used on multiple hosts.\n"
1836 "\n"
1837 "\t%s\n"
1838 "\n"
1839 "Please write down the following %ssecret verification key%s. It should be stored\n"
1840 "at a safe location and should not be saved locally on disk.\n"
1841 "\n\t%s",
1842 ansi_highlight(), ansi_normal(),
1843 p,
1844 ansi_highlight(), ansi_normal(),
1845 ansi_highlight_red());
1846 fflush(stderr);
1847 }
1848 for (i = 0; i < seed_size; i++) {
1849 if (i > 0 && i % 3 == 0)
1850 putchar('-');
1851 printf("%02x", ((uint8_t*) seed)[i]);
1852 }
1853
1854 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
1855
1856 if (on_tty()) {
1857 char tsb[FORMAT_TIMESPAN_MAX], *hn;
1858
1859 fprintf(stderr,
1860 "%s\n"
1861 "The sealing key is automatically changed every %s.\n",
1862 ansi_normal(),
1863 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
1864
1865 hn = gethostname_malloc();
1866
1867 if (hn) {
1868 hostname_cleanup(hn);
1869 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
1870 } else
1871 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
1872
1873 #if HAVE_QRENCODE
1874 /* If this is not an UTF-8 system don't print any QR codes */
1875 if (is_locale_utf8()) {
1876 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
1877 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
1878 }
1879 #endif
1880 free(hn);
1881 }
1882
1883 r = 0;
1884
1885 finish:
1886 safe_close(fd);
1887
1888 if (k) {
1889 (void) unlink(k);
1890 free(k);
1891 }
1892
1893 free(p);
1894
1895 return r;
1896 #else
1897 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1898 "Forward-secure sealing not available.");
1899 #endif
1900 }
1901
1902 static int verify(sd_journal *j) {
1903 int r = 0;
1904 Iterator i;
1905 JournalFile *f;
1906
1907 assert(j);
1908
1909 log_show_color(true);
1910
1911 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
1912 int k;
1913 usec_t first = 0, validated = 0, last = 0;
1914
1915 #if HAVE_GCRYPT
1916 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
1917 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
1918 #endif
1919
1920 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
1921 if (k == -EINVAL) {
1922 /* If the key was invalid give up right-away. */
1923 return k;
1924 } else if (k < 0) {
1925 log_warning_errno(k, "FAIL: %s (%m)", f->path);
1926 r = k;
1927 } else {
1928 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
1929 log_info("PASS: %s", f->path);
1930
1931 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
1932 if (validated > 0) {
1933 log_info("=> Validated from %s to %s, final %s entries not sealed.",
1934 format_timestamp_maybe_utc(a, sizeof(a), first),
1935 format_timestamp_maybe_utc(b, sizeof(b), validated),
1936 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
1937 } else if (last > 0)
1938 log_info("=> No sealing yet, %s of entries not sealed.",
1939 format_timespan(c, sizeof(c), last - first, 0));
1940 else
1941 log_info("=> No sealing yet, no entries in file.");
1942 }
1943 }
1944 }
1945
1946 return r;
1947 }
1948
1949 static int simple_varlink_call(const char *option, const char *method) {
1950 _cleanup_(varlink_flush_close_unrefp) Varlink *link = NULL;
1951 const char *error, *fn;
1952 int r;
1953
1954 if (arg_machine)
1955 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "%s is not supported in conjunction with --machine=.", option);
1956
1957 fn = arg_namespace ?
1958 strjoina("/run/systemd/journal.", arg_namespace, "/io.systemd.journal") :
1959 "/run/systemd/journal/io.systemd.journal";
1960
1961 r = varlink_connect_address(&link, fn);
1962 if (r < 0)
1963 return log_error_errno(r, "Failed to connect to %s: %m", fn);
1964
1965 (void) varlink_set_description(link, "journal");
1966 (void) varlink_set_relative_timeout(link, USEC_INFINITY);
1967
1968 r = varlink_call(link, method, NULL, NULL, &error, NULL);
1969 if (r < 0)
1970 return log_error_errno(r, "Failed to execute varlink call: %m");
1971 if (error)
1972 return log_error_errno(SYNTHETIC_ERRNO(ENOANO),
1973 "Failed to execute varlink call: %s", error);
1974
1975 return 0;
1976 }
1977
1978 static int flush_to_var(void) {
1979 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
1980 }
1981
1982 static int relinquish_var(void) {
1983 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
1984 }
1985
1986 static int rotate(void) {
1987 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
1988 }
1989
1990 static int sync_journal(void) {
1991 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
1992 }
1993
1994 static int wait_for_change(sd_journal *j, int poll_fd) {
1995 struct pollfd pollfds[] = {
1996 { .fd = poll_fd, .events = POLLIN },
1997 { .fd = STDOUT_FILENO },
1998 };
1999
2000 struct timespec ts;
2001 usec_t timeout;
2002 int r;
2003
2004 assert(j);
2005 assert(poll_fd >= 0);
2006
2007 /* Much like sd_journal_wait() but also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that,
2008 * i.e. when it is closed. */
2009
2010 r = sd_journal_get_timeout(j, &timeout);
2011 if (r < 0)
2012 return log_error_errno(r, "Failed to determine journal waiting time: %m");
2013
2014 if (ppoll(pollfds, ELEMENTSOF(pollfds),
2015 timeout == USEC_INFINITY ? NULL : timespec_store(&ts, timeout), NULL) < 0) {
2016 if (errno == EINTR)
2017 return 0;
2018
2019 return log_error_errno(errno, "Couldn't wait for journal event: %m");
2020 }
2021
2022 if (pollfds[1].revents & (POLLHUP|POLLERR)) /* STDOUT has been closed? */
2023 return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED),
2024 "Standard output has been closed.");
2025
2026 r = sd_journal_process(j);
2027 if (r < 0)
2028 return log_error_errno(r, "Failed to process journal events: %m");
2029
2030 return 0;
2031 }
2032
2033 int main(int argc, char *argv[]) {
2034 bool previous_boot_id_valid = false, first_line = true, ellipsized = false, need_seek = false;
2035 bool use_cursor = false, after_cursor = false;
2036 _cleanup_(sd_journal_closep) sd_journal *j = NULL;
2037 sd_id128_t previous_boot_id;
2038 int n_shown = 0, r, poll_fd = -1;
2039
2040 setlocale(LC_ALL, "");
2041 log_show_color(true);
2042 log_parse_environment();
2043 log_open();
2044
2045 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2046 * split up into many files. */
2047 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
2048
2049 r = parse_argv(argc, argv);
2050 if (r <= 0)
2051 goto finish;
2052
2053 signal(SIGWINCH, columns_lines_cache_reset);
2054 sigbus_install();
2055
2056 switch (arg_action) {
2057
2058 case ACTION_NEW_ID128:
2059 r = id128_print_new(ID128_PRINT_PRETTY);
2060 goto finish;
2061
2062 case ACTION_SETUP_KEYS:
2063 r = setup_keys();
2064 goto finish;
2065
2066 case ACTION_LIST_CATALOG:
2067 case ACTION_DUMP_CATALOG:
2068 case ACTION_UPDATE_CATALOG: {
2069 _cleanup_free_ char *database;
2070
2071 database = path_join(arg_root, CATALOG_DATABASE);
2072 if (!database) {
2073 r = log_oom();
2074 goto finish;
2075 }
2076
2077 if (arg_action == ACTION_UPDATE_CATALOG) {
2078 r = catalog_update(database, arg_root, catalog_file_dirs);
2079 if (r < 0)
2080 log_error_errno(r, "Failed to list catalog: %m");
2081 } else {
2082 bool oneline = arg_action == ACTION_LIST_CATALOG;
2083
2084 (void) pager_open(arg_pager_flags);
2085
2086 if (optind < argc)
2087 r = catalog_list_items(stdout, database, oneline, argv + optind);
2088 else
2089 r = catalog_list(stdout, database, oneline);
2090 if (r < 0)
2091 log_error_errno(r, "Failed to list catalog: %m");
2092 }
2093
2094 goto finish;
2095 }
2096
2097 case ACTION_FLUSH:
2098 r = flush_to_var();
2099 goto finish;
2100
2101 case ACTION_RELINQUISH_VAR:
2102 r = relinquish_var();
2103 goto finish;
2104
2105 case ACTION_SYNC:
2106 r = sync_journal();
2107 goto finish;
2108
2109 case ACTION_ROTATE:
2110 r = rotate();
2111 goto finish;
2112
2113 case ACTION_SHOW:
2114 case ACTION_PRINT_HEADER:
2115 case ACTION_VERIFY:
2116 case ACTION_DISK_USAGE:
2117 case ACTION_LIST_BOOTS:
2118 case ACTION_VACUUM:
2119 case ACTION_ROTATE_AND_VACUUM:
2120 case ACTION_LIST_FIELDS:
2121 case ACTION_LIST_FIELD_NAMES:
2122 /* These ones require access to the journal files, continue below. */
2123 break;
2124
2125 default:
2126 assert_not_reached("Unknown action");
2127 }
2128
2129 if (arg_directory)
2130 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
2131 else if (arg_root)
2132 r = sd_journal_open_directory(&j, arg_root, arg_journal_type | SD_JOURNAL_OS_ROOT);
2133 else if (arg_file_stdin)
2134 r = sd_journal_open_files_fd(&j, (int[]) { STDIN_FILENO }, 1, 0);
2135 else if (arg_file)
2136 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
2137 else if (arg_machine) {
2138 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2139 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2140 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
2141 int fd;
2142
2143 if (geteuid() != 0) {
2144 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2145 * the container, thus we need root privileges to override them. */
2146 r = log_error_errno(SYNTHETIC_ERRNO(EPERM), "Using the --machine= switch requires root privileges.");
2147 goto finish;
2148 }
2149
2150 r = sd_bus_open_system(&bus);
2151 if (r < 0) {
2152 log_error_errno(r, "Failed to open system bus: %m");
2153 goto finish;
2154 }
2155
2156 r = sd_bus_call_method(
2157 bus,
2158 "org.freedesktop.machine1",
2159 "/org/freedesktop/machine1",
2160 "org.freedesktop.machine1.Manager",
2161 "OpenMachineRootDirectory",
2162 &error,
2163 &reply,
2164 "s", arg_machine);
2165 if (r < 0) {
2166 log_error_errno(r, "Failed to open root directory: %s", bus_error_message(&error, r));
2167 goto finish;
2168 }
2169
2170 r = sd_bus_message_read(reply, "h", &fd);
2171 if (r < 0) {
2172 bus_log_parse_error(r);
2173 goto finish;
2174 }
2175
2176 fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
2177 if (fd < 0) {
2178 r = log_error_errno(errno, "Failed to duplicate file descriptor: %m");
2179 goto finish;
2180 }
2181
2182 r = sd_journal_open_directory_fd(&j, fd, SD_JOURNAL_OS_ROOT);
2183 if (r < 0)
2184 safe_close(fd);
2185 } else
2186 r = sd_journal_open_namespace(
2187 &j,
2188 arg_namespace,
2189 (arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY) |
2190 arg_namespace_flags | arg_journal_type);
2191 if (r < 0) {
2192 log_error_errno(r, "Failed to open %s: %m", arg_directory ?: arg_file ? "files" : "journal");
2193 goto finish;
2194 }
2195
2196 r = journal_access_check_and_warn(j, arg_quiet,
2197 !(arg_journal_type == SD_JOURNAL_CURRENT_USER || arg_user_units));
2198 if (r < 0)
2199 goto finish;
2200
2201 switch (arg_action) {
2202
2203 case ACTION_NEW_ID128:
2204 case ACTION_SETUP_KEYS:
2205 case ACTION_LIST_CATALOG:
2206 case ACTION_DUMP_CATALOG:
2207 case ACTION_UPDATE_CATALOG:
2208 case ACTION_FLUSH:
2209 case ACTION_SYNC:
2210 case ACTION_ROTATE:
2211 assert_not_reached("Unexpected action.");
2212
2213 case ACTION_PRINT_HEADER:
2214 journal_print_header(j);
2215 r = 0;
2216 goto finish;
2217
2218 case ACTION_VERIFY:
2219 r = verify(j);
2220 goto finish;
2221
2222 case ACTION_DISK_USAGE: {
2223 uint64_t bytes = 0;
2224 char sbytes[FORMAT_BYTES_MAX];
2225
2226 r = sd_journal_get_usage(j, &bytes);
2227 if (r < 0)
2228 goto finish;
2229
2230 printf("Archived and active journals take up %s in the file system.\n",
2231 format_bytes(sbytes, sizeof(sbytes), bytes));
2232 goto finish;
2233 }
2234
2235 case ACTION_LIST_BOOTS:
2236 r = list_boots(j);
2237 goto finish;
2238
2239 case ACTION_ROTATE_AND_VACUUM:
2240
2241 r = rotate();
2242 if (r < 0)
2243 goto finish;
2244
2245 _fallthrough_;
2246
2247 case ACTION_VACUUM: {
2248 Directory *d;
2249 Iterator i;
2250
2251 HASHMAP_FOREACH(d, j->directories_by_path, i) {
2252 int q;
2253
2254 q = journal_directory_vacuum(d->path, arg_vacuum_size, arg_vacuum_n_files, arg_vacuum_time, NULL, !arg_quiet);
2255 if (q < 0) {
2256 log_error_errno(q, "Failed to vacuum %s: %m", d->path);
2257 r = q;
2258 }
2259 }
2260
2261 goto finish;
2262 }
2263
2264 case ACTION_LIST_FIELD_NAMES: {
2265 const char *field;
2266
2267 SD_JOURNAL_FOREACH_FIELD(j, field) {
2268 printf("%s\n", field);
2269 n_shown++;
2270 }
2271
2272 r = 0;
2273 goto finish;
2274 }
2275
2276 case ACTION_SHOW:
2277 case ACTION_LIST_FIELDS:
2278 break;
2279
2280 default:
2281 assert_not_reached("Unknown action");
2282 }
2283
2284 if (arg_boot_offset != 0 &&
2285 sd_journal_has_runtime_files(j) > 0 &&
2286 sd_journal_has_persistent_files(j) == 0) {
2287 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2288 r = 0;
2289 goto finish;
2290 }
2291 /* add_boot() must be called first!
2292 * It may need to seek the journal to find parent boot IDs. */
2293 r = add_boot(j);
2294 if (r < 0)
2295 goto finish;
2296
2297 r = add_dmesg(j);
2298 if (r < 0)
2299 goto finish;
2300
2301 r = add_units(j);
2302 if (r < 0) {
2303 log_error_errno(r, "Failed to add filter for units: %m");
2304 goto finish;
2305 }
2306
2307 r = add_syslog_identifier(j);
2308 if (r < 0) {
2309 log_error_errno(r, "Failed to add filter for syslog identifiers: %m");
2310 goto finish;
2311 }
2312
2313 r = add_priorities(j);
2314 if (r < 0)
2315 goto finish;
2316
2317 r = add_matches(j, argv + optind);
2318 if (r < 0)
2319 goto finish;
2320
2321 if (DEBUG_LOGGING) {
2322 _cleanup_free_ char *filter;
2323
2324 filter = journal_make_match_string(j);
2325 if (!filter)
2326 return log_oom();
2327
2328 log_debug("Journal filter: %s", filter);
2329 }
2330
2331 if (arg_action == ACTION_LIST_FIELDS) {
2332 const void *data;
2333 size_t size;
2334
2335 assert(arg_field);
2336
2337 r = sd_journal_set_data_threshold(j, 0);
2338 if (r < 0) {
2339 log_error_errno(r, "Failed to unset data size threshold: %m");
2340 goto finish;
2341 }
2342
2343 r = sd_journal_query_unique(j, arg_field);
2344 if (r < 0) {
2345 log_error_errno(r, "Failed to query unique data objects: %m");
2346 goto finish;
2347 }
2348
2349 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
2350 const void *eq;
2351
2352 if (arg_lines >= 0 && n_shown >= arg_lines)
2353 break;
2354
2355 eq = memchr(data, '=', size);
2356 if (eq)
2357 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
2358 else
2359 printf("%.*s\n", (int) size, (const char*) data);
2360
2361 n_shown++;
2362 }
2363
2364 r = 0;
2365 goto finish;
2366 }
2367
2368 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2369 if (arg_follow) {
2370 poll_fd = sd_journal_get_fd(j);
2371 if (poll_fd == -EMFILE) {
2372 log_warning_errno(poll_fd, "Insufficient watch descriptors available. Reverting to -n.");
2373 arg_follow = false;
2374 } else if (poll_fd == -EMEDIUMTYPE) {
2375 log_error_errno(poll_fd, "The --follow switch is not supported in conjunction with reading from STDIN.");
2376 goto finish;
2377 } else if (poll_fd < 0) {
2378 log_error_errno(poll_fd, "Failed to get journal fd: %m");
2379 goto finish;
2380 }
2381 }
2382
2383 if (arg_cursor || arg_after_cursor || arg_cursor_file) {
2384 _cleanup_free_ char *cursor_from_file = NULL;
2385 const char *cursor = arg_cursor ?: arg_after_cursor;
2386
2387 if (arg_cursor_file) {
2388 r = read_one_line_file(arg_cursor_file, &cursor_from_file);
2389 if (r < 0 && r != -ENOENT) {
2390 log_error_errno(r, "Failed to read cursor file %s: %m", arg_cursor_file);
2391 goto finish;
2392 }
2393
2394 if (r > 0) {
2395 cursor = cursor_from_file;
2396 after_cursor = true;
2397 }
2398 } else
2399 after_cursor = !!arg_after_cursor;
2400
2401 if (cursor) {
2402 r = sd_journal_seek_cursor(j, cursor);
2403 if (r < 0) {
2404 log_error_errno(r, "Failed to seek to cursor: %m");
2405 goto finish;
2406 }
2407 use_cursor = true;
2408 }
2409 }
2410
2411 if (use_cursor) {
2412 if (!arg_reverse)
2413 r = sd_journal_next_skip(j, 1 + after_cursor);
2414 else
2415 r = sd_journal_previous_skip(j, 1 + after_cursor);
2416
2417 if (after_cursor && r < 2) {
2418 /* We couldn't find the next entry after the cursor. */
2419 if (arg_follow)
2420 need_seek = true;
2421 else
2422 arg_lines = 0;
2423 }
2424
2425 } else if (arg_since_set && !arg_reverse) {
2426 r = sd_journal_seek_realtime_usec(j, arg_since);
2427 if (r < 0) {
2428 log_error_errno(r, "Failed to seek to date: %m");
2429 goto finish;
2430 }
2431 r = sd_journal_next(j);
2432
2433 } else if (arg_until_set && arg_reverse) {
2434 r = sd_journal_seek_realtime_usec(j, arg_until);
2435 if (r < 0) {
2436 log_error_errno(r, "Failed to seek to date: %m");
2437 goto finish;
2438 }
2439 r = sd_journal_previous(j);
2440
2441 } else if (arg_reverse) {
2442 r = sd_journal_seek_tail(j);
2443 if (r < 0) {
2444 log_error_errno(r, "Failed to seek to tail: %m");
2445 goto finish;
2446 }
2447
2448 r = sd_journal_previous(j);
2449
2450 } else if (arg_lines >= 0) {
2451 r = sd_journal_seek_tail(j);
2452 if (r < 0) {
2453 log_error_errno(r, "Failed to seek to tail: %m");
2454 goto finish;
2455 }
2456
2457 r = sd_journal_previous_skip(j, arg_lines);
2458
2459 } else {
2460 r = sd_journal_seek_head(j);
2461 if (r < 0) {
2462 log_error_errno(r, "Failed to seek to head: %m");
2463 goto finish;
2464 }
2465
2466 r = sd_journal_next(j);
2467 }
2468
2469 if (r < 0) {
2470 log_error_errno(r, "Failed to iterate through journal: %m");
2471 goto finish;
2472 }
2473 if (r == 0)
2474 need_seek = true;
2475
2476 if (!arg_follow)
2477 (void) pager_open(arg_pager_flags);
2478
2479 if (!arg_quiet && (arg_lines != 0 || arg_follow)) {
2480 usec_t start, end;
2481 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
2482
2483 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
2484 if (r < 0) {
2485 log_error_errno(r, "Failed to get cutoff: %m");
2486 goto finish;
2487 }
2488
2489 if (r > 0) {
2490 if (arg_follow)
2491 printf("-- Logs begin at %s. --\n",
2492 format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start));
2493 else
2494 printf("-- Logs begin at %s, end at %s. --\n",
2495 format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start),
2496 format_timestamp_maybe_utc(end_buf, sizeof(end_buf), end));
2497 }
2498 }
2499
2500 for (;;) {
2501 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
2502 int flags;
2503 size_t highlight[2] = {};
2504
2505 if (need_seek) {
2506 if (!arg_reverse)
2507 r = sd_journal_next(j);
2508 else
2509 r = sd_journal_previous(j);
2510 if (r < 0) {
2511 log_error_errno(r, "Failed to iterate through journal: %m");
2512 goto finish;
2513 }
2514 if (r == 0)
2515 break;
2516 }
2517
2518 if (arg_until_set && !arg_reverse) {
2519 usec_t usec;
2520
2521 r = sd_journal_get_realtime_usec(j, &usec);
2522 if (r < 0) {
2523 log_error_errno(r, "Failed to determine timestamp: %m");
2524 goto finish;
2525 }
2526 if (usec > arg_until)
2527 break;
2528 }
2529
2530 if (arg_since_set && arg_reverse) {
2531 usec_t usec;
2532
2533 r = sd_journal_get_realtime_usec(j, &usec);
2534 if (r < 0) {
2535 log_error_errno(r, "Failed to determine timestamp: %m");
2536 goto finish;
2537 }
2538 if (usec < arg_since)
2539 break;
2540 }
2541
2542 if (!arg_merge && !arg_quiet) {
2543 sd_id128_t boot_id;
2544
2545 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
2546 if (r >= 0) {
2547 if (previous_boot_id_valid &&
2548 !sd_id128_equal(boot_id, previous_boot_id))
2549 printf("%s-- Reboot --%s\n",
2550 ansi_highlight(), ansi_normal());
2551
2552 previous_boot_id = boot_id;
2553 previous_boot_id_valid = true;
2554 }
2555 }
2556
2557 #if HAVE_PCRE2
2558 if (arg_compiled_pattern) {
2559 _cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL;
2560 const void *message;
2561 size_t len;
2562 PCRE2_SIZE *ovec;
2563
2564 md = pcre2_match_data_create(1, NULL);
2565 if (!md)
2566 return log_oom();
2567
2568 r = sd_journal_get_data(j, "MESSAGE", &message, &len);
2569 if (r < 0) {
2570 if (r == -ENOENT) {
2571 need_seek = true;
2572 continue;
2573 }
2574
2575 log_error_errno(r, "Failed to get MESSAGE field: %m");
2576 goto finish;
2577 }
2578
2579 assert_se(message = startswith(message, "MESSAGE="));
2580
2581 r = pcre2_match(arg_compiled_pattern,
2582 message,
2583 len - strlen("MESSAGE="),
2584 0, /* start at offset 0 in the subject */
2585 0, /* default options */
2586 md,
2587 NULL);
2588 if (r == PCRE2_ERROR_NOMATCH) {
2589 need_seek = true;
2590 continue;
2591 }
2592 if (r < 0) {
2593 unsigned char buf[LINE_MAX];
2594 int r2;
2595
2596 r2 = pcre2_get_error_message(r, buf, sizeof buf);
2597 log_error("Pattern matching failed: %s",
2598 r2 < 0 ? "unknown error" : (char*) buf);
2599 r = -EINVAL;
2600 goto finish;
2601 }
2602
2603 ovec = pcre2_get_ovector_pointer(md);
2604 highlight[0] = ovec[0];
2605 highlight[1] = ovec[1];
2606 }
2607 #endif
2608
2609 flags =
2610 arg_all * OUTPUT_SHOW_ALL |
2611 arg_full * OUTPUT_FULL_WIDTH |
2612 colors_enabled() * OUTPUT_COLOR |
2613 arg_catalog * OUTPUT_CATALOG |
2614 arg_utc * OUTPUT_UTC |
2615 arg_no_hostname * OUTPUT_NO_HOSTNAME;
2616
2617 r = show_journal_entry(stdout, j, arg_output, 0, flags,
2618 arg_output_fields, highlight, &ellipsized);
2619 need_seek = true;
2620 if (r == -EADDRNOTAVAIL)
2621 break;
2622 else if (r < 0)
2623 goto finish;
2624
2625 n_shown++;
2626
2627 /* If journalctl take a long time to process messages, and during that time journal file
2628 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2629 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2630 * in the "following" case. By periodically calling sd_journal_process() during the processing
2631 * loop we shrink the window of time a client instance has open file descriptors for rotated
2632 * (deleted) journal files. */
2633 if ((n_shown % PROCESS_INOTIFY_INTERVAL) == 0) {
2634 r = sd_journal_process(j);
2635 if (r < 0) {
2636 log_error_errno(r, "Failed to process inotify events: %m");
2637 goto finish;
2638 }
2639 }
2640 }
2641
2642 if (!arg_follow) {
2643 if (n_shown == 0 && !arg_quiet)
2644 printf("-- No entries --\n");
2645 break;
2646 }
2647
2648 fflush(stdout);
2649
2650 r = wait_for_change(j, poll_fd);
2651 if (r < 0)
2652 goto finish;
2653
2654 first_line = false;
2655 }
2656
2657 if (arg_show_cursor || arg_cursor_file) {
2658 _cleanup_free_ char *cursor = NULL;
2659
2660 r = sd_journal_get_cursor(j, &cursor);
2661 if (r < 0 && r != -EADDRNOTAVAIL)
2662 log_error_errno(r, "Failed to get cursor: %m");
2663 else if (r >= 0) {
2664 if (arg_show_cursor)
2665 printf("-- cursor: %s\n", cursor);
2666
2667 if (arg_cursor_file) {
2668 r = write_string_file(arg_cursor_file, cursor,
2669 WRITE_STRING_FILE_CREATE |
2670 WRITE_STRING_FILE_ATOMIC);
2671 if (r < 0)
2672 log_error_errno(r,
2673 "Failed to write new cursor to %s: %m",
2674 arg_cursor_file);
2675 }
2676 }
2677 }
2678
2679 finish:
2680 pager_close();
2681
2682 strv_free(arg_file);
2683
2684 strv_free(arg_syslog_identifier);
2685 strv_free(arg_system_units);
2686 strv_free(arg_user_units);
2687 strv_free(arg_output_fields);
2688
2689 free(arg_root);
2690 free(arg_verify_key);
2691
2692 #if HAVE_PCRE2
2693 if (arg_compiled_pattern) {
2694 pcre2_code_free(arg_compiled_pattern);
2695
2696 /* --grep was used, no error was thrown, but the pattern didn't
2697 * match anything. Let's mimic grep's behavior here and return
2698 * a non-zero exit code, so journalctl --grep can be used
2699 * in scripts and such */
2700 if (r == 0 && n_shown == 0)
2701 r = -ENOENT;
2702 }
2703 #endif
2704
2705 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2706 }