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