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