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