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