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