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