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