]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/journalctl.c
Merge pull request #12806 from yuwata/networkctl-ethtool-12657
[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 string_erase 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(-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 char *u;
1683
1684 u = strjoina("SYSLOG_IDENTIFIER=", *i);
1685 r = sd_journal_add_match(j, u, 0);
1686 if (r < 0)
1687 return r;
1688 r = sd_journal_add_disjunction(j);
1689 if (r < 0)
1690 return r;
1691 }
1692
1693 r = sd_journal_add_conjunction(j);
1694 if (r < 0)
1695 return r;
1696
1697 return 0;
1698 }
1699
1700 static int setup_keys(void) {
1701 #if HAVE_GCRYPT
1702 size_t mpk_size, seed_size, state_size, i;
1703 uint8_t *mpk, *seed, *state;
1704 int fd = -1, r;
1705 sd_id128_t machine, boot;
1706 char *p = NULL, *k = NULL;
1707 struct FSSHeader h;
1708 uint64_t n;
1709 struct stat st;
1710
1711 r = stat("/var/log/journal", &st);
1712 if (r < 0 && !IN_SET(errno, ENOENT, ENOTDIR))
1713 return log_error_errno(errno, "stat(\"%s\") failed: %m", "/var/log/journal");
1714
1715 if (r < 0 || !S_ISDIR(st.st_mode)) {
1716 log_error("%s is not a directory, must be using persistent logging for FSS.",
1717 "/var/log/journal");
1718 return r < 0 ? -errno : -ENOTDIR;
1719 }
1720
1721 r = sd_id128_get_machine(&machine);
1722 if (r < 0)
1723 return log_error_errno(r, "Failed to get machine ID: %m");
1724
1725 r = sd_id128_get_boot(&boot);
1726 if (r < 0)
1727 return log_error_errno(r, "Failed to get boot ID: %m");
1728
1729 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
1730 SD_ID128_FORMAT_VAL(machine)) < 0)
1731 return log_oom();
1732
1733 if (arg_force) {
1734 r = unlink(p);
1735 if (r < 0 && errno != ENOENT) {
1736 r = log_error_errno(errno, "unlink(\"%s\") failed: %m", p);
1737 goto finish;
1738 }
1739 } else if (access(p, F_OK) >= 0) {
1740 log_error("Sealing key file %s exists already. Use --force to recreate.", p);
1741 r = -EEXIST;
1742 goto finish;
1743 }
1744
1745 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
1746 SD_ID128_FORMAT_VAL(machine)) < 0) {
1747 r = log_oom();
1748 goto finish;
1749 }
1750
1751 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
1752 mpk = alloca(mpk_size);
1753
1754 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
1755 seed = alloca(seed_size);
1756
1757 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
1758 state = alloca(state_size);
1759
1760 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1761 if (fd < 0) {
1762 r = log_error_errno(errno, "Failed to open /dev/random: %m");
1763 goto finish;
1764 }
1765
1766 log_info("Generating seed...");
1767 r = loop_read_exact(fd, seed, seed_size, true);
1768 if (r < 0) {
1769 log_error_errno(r, "Failed to read random seed: %m");
1770 goto finish;
1771 }
1772
1773 log_info("Generating key pair...");
1774 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
1775
1776 log_info("Generating sealing key...");
1777 FSPRG_GenState0(state, mpk, seed, seed_size);
1778
1779 assert(arg_interval > 0);
1780
1781 n = now(CLOCK_REALTIME);
1782 n /= arg_interval;
1783
1784 safe_close(fd);
1785 fd = mkostemp_safe(k);
1786 if (fd < 0) {
1787 r = log_error_errno(fd, "Failed to open %s: %m", k);
1788 goto finish;
1789 }
1790
1791 /* Enable secure remove, exclusion from dump, synchronous
1792 * writing and in-place updating */
1793 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);
1794 if (r < 0)
1795 log_warning_errno(r, "Failed to set file attributes: %m");
1796
1797 zero(h);
1798 memcpy(h.signature, "KSHHRHLP", 8);
1799 h.machine_id = machine;
1800 h.boot_id = boot;
1801 h.header_size = htole64(sizeof(h));
1802 h.start_usec = htole64(n * arg_interval);
1803 h.interval_usec = htole64(arg_interval);
1804 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
1805 h.fsprg_state_size = htole64(state_size);
1806
1807 r = loop_write(fd, &h, sizeof(h), false);
1808 if (r < 0) {
1809 log_error_errno(r, "Failed to write header: %m");
1810 goto finish;
1811 }
1812
1813 r = loop_write(fd, state, state_size, false);
1814 if (r < 0) {
1815 log_error_errno(r, "Failed to write state: %m");
1816 goto finish;
1817 }
1818
1819 if (link(k, p) < 0) {
1820 r = log_error_errno(errno, "Failed to link file: %m");
1821 goto finish;
1822 }
1823
1824 if (on_tty()) {
1825 fprintf(stderr,
1826 "\n"
1827 "The new key pair has been generated. The %ssecret sealing key%s has been written to\n"
1828 "the following local file. This key file is automatically updated when the\n"
1829 "sealing key is advanced. It should not be used on multiple hosts.\n"
1830 "\n"
1831 "\t%s\n"
1832 "\n"
1833 "Please write down the following %ssecret verification key%s. It should be stored\n"
1834 "at a safe location and should not be saved locally on disk.\n"
1835 "\n\t%s",
1836 ansi_highlight(), ansi_normal(),
1837 p,
1838 ansi_highlight(), ansi_normal(),
1839 ansi_highlight_red());
1840 fflush(stderr);
1841 }
1842 for (i = 0; i < seed_size; i++) {
1843 if (i > 0 && i % 3 == 0)
1844 putchar('-');
1845 printf("%02x", ((uint8_t*) seed)[i]);
1846 }
1847
1848 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
1849
1850 if (on_tty()) {
1851 char tsb[FORMAT_TIMESPAN_MAX], *hn;
1852
1853 fprintf(stderr,
1854 "%s\n"
1855 "The sealing key is automatically changed every %s.\n",
1856 ansi_normal(),
1857 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
1858
1859 hn = gethostname_malloc();
1860
1861 if (hn) {
1862 hostname_cleanup(hn);
1863 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
1864 } else
1865 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
1866
1867 #if HAVE_QRENCODE
1868 /* If this is not an UTF-8 system don't print any QR codes */
1869 if (is_locale_utf8()) {
1870 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
1871 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
1872 }
1873 #endif
1874 free(hn);
1875 }
1876
1877 r = 0;
1878
1879 finish:
1880 safe_close(fd);
1881
1882 if (k) {
1883 (void) unlink(k);
1884 free(k);
1885 }
1886
1887 free(p);
1888
1889 return r;
1890 #else
1891 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1892 "Forward-secure sealing not available.");
1893 #endif
1894 }
1895
1896 static int verify(sd_journal *j) {
1897 int r = 0;
1898 Iterator i;
1899 JournalFile *f;
1900
1901 assert(j);
1902
1903 log_show_color(true);
1904
1905 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
1906 int k;
1907 usec_t first = 0, validated = 0, last = 0;
1908
1909 #if HAVE_GCRYPT
1910 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
1911 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
1912 #endif
1913
1914 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
1915 if (k == -EINVAL) {
1916 /* If the key was invalid give up right-away. */
1917 return k;
1918 } else if (k < 0) {
1919 log_warning_errno(k, "FAIL: %s (%m)", f->path);
1920 r = k;
1921 } else {
1922 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
1923 log_info("PASS: %s", f->path);
1924
1925 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
1926 if (validated > 0) {
1927 log_info("=> Validated from %s to %s, final %s entries not sealed.",
1928 format_timestamp_maybe_utc(a, sizeof(a), first),
1929 format_timestamp_maybe_utc(b, sizeof(b), validated),
1930 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
1931 } else if (last > 0)
1932 log_info("=> No sealing yet, %s of entries not sealed.",
1933 format_timespan(c, sizeof(c), last - first, 0));
1934 else
1935 log_info("=> No sealing yet, no entries in file.");
1936 }
1937 }
1938 }
1939
1940 return r;
1941 }
1942
1943 static int simple_varlink_call(const char *option, const char *method) {
1944 _cleanup_(varlink_flush_close_unrefp) Varlink *link = NULL;
1945 const char *error;
1946 int r;
1947
1948 if (arg_machine)
1949 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "%s is not supported in conjunction with --machine=.", option);
1950
1951 r = varlink_connect_address(&link, "/run/systemd/journal/io.systemd.journal");
1952 if (r < 0)
1953 return log_error_errno(r, "Failed to connect to /run/systemd/journal/io.systemd.journal: %m");
1954
1955 (void) varlink_set_description(link, "journal");
1956 (void) varlink_set_relative_timeout(link, USEC_INFINITY);
1957
1958 r = varlink_call(link, method, NULL, NULL, &error, NULL);
1959 if (r < 0)
1960 return log_error_errno(r, "Failed to execute varlink call: %m");
1961 if (error)
1962 return log_error_errno(SYNTHETIC_ERRNO(ENOANO),
1963 "Failed to execute varlink call: %s", error);
1964
1965 return 0;
1966 }
1967
1968 static int flush_to_var(void) {
1969 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
1970 }
1971
1972 static int relinquish_var(void) {
1973 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
1974 }
1975
1976 static int rotate(void) {
1977 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
1978 }
1979
1980 static int sync_journal(void) {
1981 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
1982 }
1983
1984 static int wait_for_change(sd_journal *j, int poll_fd) {
1985 struct pollfd pollfds[] = {
1986 { .fd = poll_fd, .events = POLLIN },
1987 { .fd = STDOUT_FILENO },
1988 };
1989
1990 struct timespec ts;
1991 usec_t timeout;
1992 int r;
1993
1994 assert(j);
1995 assert(poll_fd >= 0);
1996
1997 /* Much like sd_journal_wait() but also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that,
1998 * i.e. when it is closed. */
1999
2000 r = sd_journal_get_timeout(j, &timeout);
2001 if (r < 0)
2002 return log_error_errno(r, "Failed to determine journal waiting time: %m");
2003
2004 if (ppoll(pollfds, ELEMENTSOF(pollfds),
2005 timeout == USEC_INFINITY ? NULL : timespec_store(&ts, timeout), NULL) < 0) {
2006 if (errno == EINTR)
2007 return 0;
2008
2009 return log_error_errno(errno, "Couldn't wait for journal event: %m");
2010 }
2011
2012 if (pollfds[1].revents & (POLLHUP|POLLERR)) /* STDOUT has been closed? */
2013 return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED),
2014 "Standard output has been closed.");
2015
2016 r = sd_journal_process(j);
2017 if (r < 0)
2018 return log_error_errno(r, "Failed to process journal events: %m");
2019
2020 return 0;
2021 }
2022
2023 int main(int argc, char *argv[]) {
2024 bool previous_boot_id_valid = false, first_line = true, ellipsized = false, need_seek = false;
2025 bool use_cursor = false, after_cursor = false;
2026 _cleanup_(sd_journal_closep) sd_journal *j = NULL;
2027 sd_id128_t previous_boot_id;
2028 int n_shown = 0, r, poll_fd = -1;
2029
2030 setlocale(LC_ALL, "");
2031 log_show_color(true);
2032 log_parse_environment();
2033 log_open();
2034
2035 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2036 * split up into many files. */
2037 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
2038
2039 r = parse_argv(argc, argv);
2040 if (r <= 0)
2041 goto finish;
2042
2043 signal(SIGWINCH, columns_lines_cache_reset);
2044 sigbus_install();
2045
2046 switch (arg_action) {
2047
2048 case ACTION_NEW_ID128:
2049 r = id128_print_new(true);
2050 goto finish;
2051
2052 case ACTION_SETUP_KEYS:
2053 r = setup_keys();
2054 goto finish;
2055
2056 case ACTION_LIST_CATALOG:
2057 case ACTION_DUMP_CATALOG:
2058 case ACTION_UPDATE_CATALOG: {
2059 _cleanup_free_ char *database;
2060
2061 database = path_join(arg_root, CATALOG_DATABASE);
2062 if (!database) {
2063 r = log_oom();
2064 goto finish;
2065 }
2066
2067 if (arg_action == ACTION_UPDATE_CATALOG) {
2068 r = catalog_update(database, arg_root, catalog_file_dirs);
2069 if (r < 0)
2070 log_error_errno(r, "Failed to list catalog: %m");
2071 } else {
2072 bool oneline = arg_action == ACTION_LIST_CATALOG;
2073
2074 (void) pager_open(arg_pager_flags);
2075
2076 if (optind < argc)
2077 r = catalog_list_items(stdout, database, oneline, argv + optind);
2078 else
2079 r = catalog_list(stdout, database, oneline);
2080 if (r < 0)
2081 log_error_errno(r, "Failed to list catalog: %m");
2082 }
2083
2084 goto finish;
2085 }
2086
2087 case ACTION_FLUSH:
2088 r = flush_to_var();
2089 goto finish;
2090
2091 case ACTION_RELINQUISH_VAR:
2092 r = relinquish_var();
2093 goto finish;
2094
2095 case ACTION_SYNC:
2096 r = sync_journal();
2097 goto finish;
2098
2099 case ACTION_ROTATE:
2100 r = rotate();
2101 goto finish;
2102
2103 case ACTION_SHOW:
2104 case ACTION_PRINT_HEADER:
2105 case ACTION_VERIFY:
2106 case ACTION_DISK_USAGE:
2107 case ACTION_LIST_BOOTS:
2108 case ACTION_VACUUM:
2109 case ACTION_ROTATE_AND_VACUUM:
2110 case ACTION_LIST_FIELDS:
2111 case ACTION_LIST_FIELD_NAMES:
2112 /* These ones require access to the journal files, continue below. */
2113 break;
2114
2115 default:
2116 assert_not_reached("Unknown action");
2117 }
2118
2119 if (arg_directory)
2120 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
2121 else if (arg_root)
2122 r = sd_journal_open_directory(&j, arg_root, arg_journal_type | SD_JOURNAL_OS_ROOT);
2123 else if (arg_file_stdin) {
2124 int ifd = STDIN_FILENO;
2125 r = sd_journal_open_files_fd(&j, &ifd, 1, 0);
2126 } else if (arg_file)
2127 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
2128 else if (arg_machine) {
2129 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2130 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2131 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
2132 int fd;
2133
2134 if (geteuid() != 0) {
2135 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2136 * the container, thus we need root privileges to override them. */
2137 log_error("Using the --machine= switch requires root privileges.");
2138 r = -EPERM;
2139 goto finish;
2140 }
2141
2142 r = sd_bus_open_system(&bus);
2143 if (r < 0) {
2144 log_error_errno(r, "Failed to open system bus: %m");
2145 goto finish;
2146 }
2147
2148 r = sd_bus_call_method(
2149 bus,
2150 "org.freedesktop.machine1",
2151 "/org/freedesktop/machine1",
2152 "org.freedesktop.machine1.Manager",
2153 "OpenMachineRootDirectory",
2154 &error,
2155 &reply,
2156 "s", arg_machine);
2157 if (r < 0) {
2158 log_error_errno(r, "Failed to open root directory: %s", bus_error_message(&error, r));
2159 goto finish;
2160 }
2161
2162 r = sd_bus_message_read(reply, "h", &fd);
2163 if (r < 0) {
2164 bus_log_parse_error(r);
2165 goto finish;
2166 }
2167
2168 fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
2169 if (fd < 0) {
2170 r = log_error_errno(errno, "Failed to duplicate file descriptor: %m");
2171 goto finish;
2172 }
2173
2174 r = sd_journal_open_directory_fd(&j, fd, SD_JOURNAL_OS_ROOT);
2175 if (r < 0)
2176 safe_close(fd);
2177 } else
2178 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
2179 if (r < 0) {
2180 log_error_errno(r, "Failed to open %s: %m", arg_directory ?: arg_file ? "files" : "journal");
2181 goto finish;
2182 }
2183
2184 r = journal_access_check_and_warn(j, arg_quiet,
2185 !(arg_journal_type == SD_JOURNAL_CURRENT_USER || arg_user_units));
2186 if (r < 0)
2187 goto finish;
2188
2189 switch (arg_action) {
2190
2191 case ACTION_NEW_ID128:
2192 case ACTION_SETUP_KEYS:
2193 case ACTION_LIST_CATALOG:
2194 case ACTION_DUMP_CATALOG:
2195 case ACTION_UPDATE_CATALOG:
2196 case ACTION_FLUSH:
2197 case ACTION_SYNC:
2198 case ACTION_ROTATE:
2199 assert_not_reached("Unexpected action.");
2200
2201 case ACTION_PRINT_HEADER:
2202 journal_print_header(j);
2203 r = 0;
2204 goto finish;
2205
2206 case ACTION_VERIFY:
2207 r = verify(j);
2208 goto finish;
2209
2210 case ACTION_DISK_USAGE: {
2211 uint64_t bytes = 0;
2212 char sbytes[FORMAT_BYTES_MAX];
2213
2214 r = sd_journal_get_usage(j, &bytes);
2215 if (r < 0)
2216 goto finish;
2217
2218 printf("Archived and active journals take up %s in the file system.\n",
2219 format_bytes(sbytes, sizeof(sbytes), bytes));
2220 goto finish;
2221 }
2222
2223 case ACTION_LIST_BOOTS:
2224 r = list_boots(j);
2225 goto finish;
2226
2227 case ACTION_ROTATE_AND_VACUUM:
2228
2229 r = rotate();
2230 if (r < 0)
2231 goto finish;
2232
2233 _fallthrough_;
2234
2235 case ACTION_VACUUM: {
2236 Directory *d;
2237 Iterator i;
2238
2239 HASHMAP_FOREACH(d, j->directories_by_path, i) {
2240 int q;
2241
2242 if (d->is_root)
2243 continue;
2244
2245 q = journal_directory_vacuum(d->path, arg_vacuum_size, arg_vacuum_n_files, arg_vacuum_time, NULL, !arg_quiet);
2246 if (q < 0) {
2247 log_error_errno(q, "Failed to vacuum %s: %m", d->path);
2248 r = q;
2249 }
2250 }
2251
2252 goto finish;
2253 }
2254
2255 case ACTION_LIST_FIELD_NAMES: {
2256 const char *field;
2257
2258 SD_JOURNAL_FOREACH_FIELD(j, field) {
2259 printf("%s\n", field);
2260 n_shown++;
2261 }
2262
2263 r = 0;
2264 goto finish;
2265 }
2266
2267 case ACTION_SHOW:
2268 case ACTION_LIST_FIELDS:
2269 break;
2270
2271 default:
2272 assert_not_reached("Unknown action");
2273 }
2274
2275 if (arg_boot_offset != 0 &&
2276 sd_journal_has_runtime_files(j) > 0 &&
2277 sd_journal_has_persistent_files(j) == 0) {
2278 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2279 r = 0;
2280 goto finish;
2281 }
2282 /* add_boot() must be called first!
2283 * It may need to seek the journal to find parent boot IDs. */
2284 r = add_boot(j);
2285 if (r < 0)
2286 goto finish;
2287
2288 r = add_dmesg(j);
2289 if (r < 0)
2290 goto finish;
2291
2292 r = add_units(j);
2293 if (r < 0) {
2294 log_error_errno(r, "Failed to add filter for units: %m");
2295 goto finish;
2296 }
2297
2298 r = add_syslog_identifier(j);
2299 if (r < 0) {
2300 log_error_errno(r, "Failed to add filter for syslog identifiers: %m");
2301 goto finish;
2302 }
2303
2304 r = add_priorities(j);
2305 if (r < 0)
2306 goto finish;
2307
2308 r = add_matches(j, argv + optind);
2309 if (r < 0)
2310 goto finish;
2311
2312 if (DEBUG_LOGGING) {
2313 _cleanup_free_ char *filter;
2314
2315 filter = journal_make_match_string(j);
2316 if (!filter)
2317 return log_oom();
2318
2319 log_debug("Journal filter: %s", filter);
2320 }
2321
2322 if (arg_action == ACTION_LIST_FIELDS) {
2323 const void *data;
2324 size_t size;
2325
2326 assert(arg_field);
2327
2328 r = sd_journal_set_data_threshold(j, 0);
2329 if (r < 0) {
2330 log_error_errno(r, "Failed to unset data size threshold: %m");
2331 goto finish;
2332 }
2333
2334 r = sd_journal_query_unique(j, arg_field);
2335 if (r < 0) {
2336 log_error_errno(r, "Failed to query unique data objects: %m");
2337 goto finish;
2338 }
2339
2340 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
2341 const void *eq;
2342
2343 if (arg_lines >= 0 && n_shown >= arg_lines)
2344 break;
2345
2346 eq = memchr(data, '=', size);
2347 if (eq)
2348 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
2349 else
2350 printf("%.*s\n", (int) size, (const char*) data);
2351
2352 n_shown++;
2353 }
2354
2355 r = 0;
2356 goto finish;
2357 }
2358
2359 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2360 if (arg_follow) {
2361 poll_fd = sd_journal_get_fd(j);
2362 if (poll_fd == -EMFILE) {
2363 log_warning_errno(poll_fd, "Insufficient watch descriptors available. Reverting to -n.");
2364 arg_follow = false;
2365 } else if (poll_fd == -EMEDIUMTYPE) {
2366 log_error_errno(poll_fd, "The --follow switch is not supported in conjunction with reading from STDIN.");
2367 goto finish;
2368 } else if (poll_fd < 0) {
2369 log_error_errno(poll_fd, "Failed to get journal fd: %m");
2370 goto finish;
2371 }
2372 }
2373
2374 if (arg_cursor || arg_after_cursor || arg_cursor_file) {
2375 _cleanup_free_ char *cursor_from_file = NULL;
2376 const char *cursor = arg_cursor ?: arg_after_cursor;
2377
2378 if (arg_cursor_file) {
2379 r = read_one_line_file(arg_cursor_file, &cursor_from_file);
2380 if (r < 0 && r != -ENOENT) {
2381 log_error_errno(r, "Failed to read cursor file %s: %m", arg_cursor_file);
2382 goto finish;
2383 }
2384
2385 if (r > 0) {
2386 cursor = cursor_from_file;
2387 after_cursor = true;
2388 }
2389 } else
2390 after_cursor = !!arg_after_cursor;
2391
2392 if (cursor) {
2393 r = sd_journal_seek_cursor(j, cursor);
2394 if (r < 0) {
2395 log_error_errno(r, "Failed to seek to cursor: %m");
2396 goto finish;
2397 }
2398 use_cursor = true;
2399 }
2400 }
2401
2402 if (use_cursor) {
2403 if (!arg_reverse)
2404 r = sd_journal_next_skip(j, 1 + after_cursor);
2405 else
2406 r = sd_journal_previous_skip(j, 1 + after_cursor);
2407
2408 if (after_cursor && r < 2) {
2409 /* We couldn't find the next entry after the cursor. */
2410 if (arg_follow)
2411 need_seek = true;
2412 else
2413 arg_lines = 0;
2414 }
2415
2416 } else if (arg_since_set && !arg_reverse) {
2417 r = sd_journal_seek_realtime_usec(j, arg_since);
2418 if (r < 0) {
2419 log_error_errno(r, "Failed to seek to date: %m");
2420 goto finish;
2421 }
2422 r = sd_journal_next(j);
2423
2424 } else if (arg_until_set && arg_reverse) {
2425 r = sd_journal_seek_realtime_usec(j, arg_until);
2426 if (r < 0) {
2427 log_error_errno(r, "Failed to seek to date: %m");
2428 goto finish;
2429 }
2430 r = sd_journal_previous(j);
2431
2432 } else if (arg_lines >= 0) {
2433 r = sd_journal_seek_tail(j);
2434 if (r < 0) {
2435 log_error_errno(r, "Failed to seek to tail: %m");
2436 goto finish;
2437 }
2438
2439 r = sd_journal_previous_skip(j, arg_lines);
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 {
2451 r = sd_journal_seek_head(j);
2452 if (r < 0) {
2453 log_error_errno(r, "Failed to seek to head: %m");
2454 goto finish;
2455 }
2456
2457 r = sd_journal_next(j);
2458 }
2459
2460 if (r < 0) {
2461 log_error_errno(r, "Failed to iterate through journal: %m");
2462 goto finish;
2463 }
2464 if (r == 0)
2465 need_seek = true;
2466
2467 if (!arg_follow)
2468 (void) pager_open(arg_pager_flags);
2469
2470 if (!arg_quiet && (arg_lines != 0 || arg_follow)) {
2471 usec_t start, end;
2472 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
2473
2474 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
2475 if (r < 0) {
2476 log_error_errno(r, "Failed to get cutoff: %m");
2477 goto finish;
2478 }
2479
2480 if (r > 0) {
2481 if (arg_follow)
2482 printf("-- Logs begin at %s. --\n",
2483 format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start));
2484 else
2485 printf("-- Logs begin at %s, end at %s. --\n",
2486 format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start),
2487 format_timestamp_maybe_utc(end_buf, sizeof(end_buf), end));
2488 }
2489 }
2490
2491 for (;;) {
2492 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
2493 int flags;
2494 size_t highlight[2] = {};
2495
2496 if (need_seek) {
2497 if (!arg_reverse)
2498 r = sd_journal_next(j);
2499 else
2500 r = sd_journal_previous(j);
2501 if (r < 0) {
2502 log_error_errno(r, "Failed to iterate through journal: %m");
2503 goto finish;
2504 }
2505 if (r == 0)
2506 break;
2507 }
2508
2509 if (arg_until_set && !arg_reverse) {
2510 usec_t usec;
2511
2512 r = sd_journal_get_realtime_usec(j, &usec);
2513 if (r < 0) {
2514 log_error_errno(r, "Failed to determine timestamp: %m");
2515 goto finish;
2516 }
2517 if (usec > arg_until)
2518 goto finish;
2519 }
2520
2521 if (arg_since_set && arg_reverse) {
2522 usec_t usec;
2523
2524 r = sd_journal_get_realtime_usec(j, &usec);
2525 if (r < 0) {
2526 log_error_errno(r, "Failed to determine timestamp: %m");
2527 goto finish;
2528 }
2529 if (usec < arg_since)
2530 goto finish;
2531 }
2532
2533 if (!arg_merge && !arg_quiet) {
2534 sd_id128_t boot_id;
2535
2536 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
2537 if (r >= 0) {
2538 if (previous_boot_id_valid &&
2539 !sd_id128_equal(boot_id, previous_boot_id))
2540 printf("%s-- Reboot --%s\n",
2541 ansi_highlight(), ansi_normal());
2542
2543 previous_boot_id = boot_id;
2544 previous_boot_id_valid = true;
2545 }
2546 }
2547
2548 #if HAVE_PCRE2
2549 if (arg_compiled_pattern) {
2550 _cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL;
2551 const void *message;
2552 size_t len;
2553 PCRE2_SIZE *ovec;
2554
2555 md = pcre2_match_data_create(1, NULL);
2556 if (!md)
2557 return log_oom();
2558
2559 r = sd_journal_get_data(j, "MESSAGE", &message, &len);
2560 if (r < 0) {
2561 if (r == -ENOENT) {
2562 need_seek = true;
2563 continue;
2564 }
2565
2566 log_error_errno(r, "Failed to get MESSAGE field: %m");
2567 goto finish;
2568 }
2569
2570 assert_se(message = startswith(message, "MESSAGE="));
2571
2572 r = pcre2_match(arg_compiled_pattern,
2573 message,
2574 len - strlen("MESSAGE="),
2575 0, /* start at offset 0 in the subject */
2576 0, /* default options */
2577 md,
2578 NULL);
2579 if (r == PCRE2_ERROR_NOMATCH) {
2580 need_seek = true;
2581 continue;
2582 }
2583 if (r < 0) {
2584 unsigned char buf[LINE_MAX];
2585 int r2;
2586
2587 r2 = pcre2_get_error_message(r, buf, sizeof buf);
2588 log_error("Pattern matching failed: %s",
2589 r2 < 0 ? "unknown error" : (char*) buf);
2590 r = -EINVAL;
2591 goto finish;
2592 }
2593
2594 ovec = pcre2_get_ovector_pointer(md);
2595 highlight[0] = ovec[0];
2596 highlight[1] = ovec[1];
2597 }
2598 #endif
2599
2600 flags =
2601 arg_all * OUTPUT_SHOW_ALL |
2602 arg_full * OUTPUT_FULL_WIDTH |
2603 colors_enabled() * OUTPUT_COLOR |
2604 arg_catalog * OUTPUT_CATALOG |
2605 arg_utc * OUTPUT_UTC |
2606 arg_no_hostname * OUTPUT_NO_HOSTNAME;
2607
2608 r = show_journal_entry(stdout, j, arg_output, 0, flags,
2609 arg_output_fields, highlight, &ellipsized);
2610 need_seek = true;
2611 if (r == -EADDRNOTAVAIL)
2612 break;
2613 else if (r < 0)
2614 goto finish;
2615
2616 n_shown++;
2617
2618 /* If journalctl take a long time to process messages, and during that time journal file
2619 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2620 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2621 * in the "following" case. By periodically calling sd_journal_process() during the processing
2622 * loop we shrink the window of time a client instance has open file descriptors for rotated
2623 * (deleted) journal files. */
2624 if ((n_shown % PROCESS_INOTIFY_INTERVAL) == 0) {
2625 r = sd_journal_process(j);
2626 if (r < 0) {
2627 log_error_errno(r, "Failed to process inotify events: %m");
2628 goto finish;
2629 }
2630 }
2631 }
2632
2633 if (!arg_follow) {
2634 if (n_shown == 0 && !arg_quiet)
2635 printf("-- No entries --\n");
2636
2637 if (arg_show_cursor || arg_cursor_file) {
2638 _cleanup_free_ char *cursor = NULL;
2639
2640 r = sd_journal_get_cursor(j, &cursor);
2641 if (r < 0 && r != -EADDRNOTAVAIL)
2642 log_error_errno(r, "Failed to get cursor: %m");
2643 else if (r >= 0) {
2644 if (arg_show_cursor)
2645 printf("-- cursor: %s\n", cursor);
2646
2647 if (arg_cursor_file) {
2648 r = write_string_file(arg_cursor_file, cursor,
2649 WRITE_STRING_FILE_CREATE |
2650 WRITE_STRING_FILE_ATOMIC);
2651 if (r < 0)
2652 log_error_errno(r,
2653 "Failed to write new cursor to %s: %m",
2654 arg_cursor_file);
2655 }
2656 }
2657 }
2658
2659 break;
2660 }
2661
2662 fflush(stdout);
2663
2664 r = wait_for_change(j, poll_fd);
2665 if (r < 0)
2666 goto finish;
2667
2668 first_line = false;
2669 }
2670
2671 finish:
2672 fflush(stdout);
2673 pager_close();
2674
2675 strv_free(arg_file);
2676
2677 strv_free(arg_syslog_identifier);
2678 strv_free(arg_system_units);
2679 strv_free(arg_user_units);
2680 strv_free(arg_output_fields);
2681
2682 free(arg_root);
2683 free(arg_verify_key);
2684
2685 #if HAVE_PCRE2
2686 if (arg_compiled_pattern) {
2687 pcre2_code_free(arg_compiled_pattern);
2688
2689 /* --grep was used, no error was thrown, but the pattern didn't
2690 * match anything. Let's mimic grep's behavior here and return
2691 * a non-zero exit code, so journalctl --grep can be used
2692 * in scripts and such */
2693 if (r == 0 && n_shown == 0)
2694 r = -ENOENT;
2695 }
2696 #endif
2697
2698 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2699 }