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