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