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