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