]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/journalctl.c
journalctl: replace ppoll() loop with sd_event_loop()
[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 = 0, arg_until = 0;
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_no_tail)
1051 arg_lines = ARG_LINES_ALL;
1052
1053 if (arg_follow && !arg_since_set && arg_lines == ARG_LINES_DEFAULT)
1054 arg_lines = 10;
1055
1056 if (arg_follow && !arg_merge && !arg_boot) {
1057 arg_boot = true;
1058 arg_boot_id = SD_ID128_NULL;
1059 arg_boot_offset = 0;
1060 }
1061
1062 if (!!arg_directory + !!arg_file + !!arg_machine + !!arg_root + !!arg_image > 1)
1063 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1064 "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
1065
1066 if (arg_since_set && arg_until_set && arg_since > arg_until)
1067 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1068 "--since= must be before --until=.");
1069
1070 if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1)
1071 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1072 "Please specify only one of --since=, --cursor=, and --after-cursor=.");
1073
1074 if (arg_follow && arg_reverse)
1075 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1076 "Please specify either --reverse= or --follow=, not both.");
1077
1078 if (!IN_SET(arg_action, ACTION_SHOW, ACTION_DUMP_CATALOG, ACTION_LIST_CATALOG) && optind < argc)
1079 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1080 "Extraneous arguments starting with '%s'",
1081 argv[optind]);
1082
1083 if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && arg_merge)
1084 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1085 "Using --boot or --list-boots with --merge is not supported.");
1086
1087 if (!strv_isempty(arg_system_units) && arg_journal_type == SD_JOURNAL_CURRENT_USER) {
1088 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1089 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1090 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1091 r = strv_extend_strv(&arg_user_units, arg_system_units, true);
1092 if (r < 0)
1093 return r;
1094
1095 arg_system_units = strv_free(arg_system_units);
1096 }
1097
1098 if (arg_pattern) {
1099 r = pattern_compile_and_log(arg_pattern, arg_case, &arg_compiled_pattern);
1100 if (r < 0)
1101 return r;
1102
1103 /* When --grep is used along with --lines, we don't know how many lines we can print.
1104 * So we search backwards and count until enough lines have been printed or we hit the head.
1105 * An exception is that --follow might set arg_lines, so let's not imply --reverse
1106 * if that is specified. */
1107 if (arg_lines >= 0 && !arg_follow)
1108 arg_reverse = true;
1109 }
1110
1111 return 1;
1112 }
1113
1114 static int add_matches(sd_journal *j, char **args) {
1115 bool have_term = false;
1116
1117 assert(j);
1118
1119 STRV_FOREACH(i, args) {
1120 int r;
1121
1122 if (streq(*i, "+")) {
1123 if (!have_term)
1124 break;
1125 r = sd_journal_add_disjunction(j);
1126 have_term = false;
1127
1128 } else if (path_is_absolute(*i)) {
1129 _cleanup_free_ char *p = NULL, *t = NULL, *t2 = NULL, *interpreter = NULL;
1130 struct stat st;
1131
1132 r = chase(*i, NULL, CHASE_TRAIL_SLASH, &p, NULL);
1133 if (r < 0)
1134 return log_error_errno(r, "Couldn't canonicalize path: %m");
1135
1136 if (lstat(p, &st) < 0)
1137 return log_error_errno(errno, "Couldn't stat file: %m");
1138
1139 if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
1140 if (executable_is_script(p, &interpreter) > 0) {
1141 _cleanup_free_ char *comm = NULL;
1142
1143 r = path_extract_filename(p, &comm);
1144 if (r < 0)
1145 return log_error_errno(r, "Failed to extract filename of '%s': %m", p);
1146
1147 t = strjoin("_COMM=", strshorten(comm, TASK_COMM_LEN-1));
1148 if (!t)
1149 return log_oom();
1150
1151 /* Append _EXE only if the interpreter is not a link.
1152 Otherwise, it might be outdated often. */
1153 if (lstat(interpreter, &st) == 0 && !S_ISLNK(st.st_mode)) {
1154 t2 = strjoin("_EXE=", interpreter);
1155 if (!t2)
1156 return log_oom();
1157 }
1158 } else {
1159 t = strjoin("_EXE=", p);
1160 if (!t)
1161 return log_oom();
1162 }
1163
1164 r = sd_journal_add_match(j, t, 0);
1165
1166 if (r >=0 && t2)
1167 r = sd_journal_add_match(j, t2, 0);
1168
1169 } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
1170 r = add_matches_for_device(j, p);
1171 if (r < 0)
1172 return r;
1173 } else
1174 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1175 "File is neither a device node, nor regular file, nor executable: %s",
1176 *i);
1177
1178 have_term = true;
1179 } else {
1180 r = sd_journal_add_match(j, *i, 0);
1181 have_term = true;
1182 }
1183
1184 if (r < 0)
1185 return log_error_errno(r, "Failed to add match '%s': %m", *i);
1186 }
1187
1188 if (!strv_isempty(args) && !have_term)
1189 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1190 "\"+\" can only be used between terms");
1191
1192 return 0;
1193 }
1194
1195 static int discover_next_boot(
1196 sd_journal *j,
1197 sd_id128_t previous_boot_id,
1198 bool advance_older,
1199 BootId *ret) {
1200
1201 BootId boot;
1202 int r;
1203
1204 assert(j);
1205 assert(ret);
1206
1207 /* We expect the journal to be on the last position of a boot
1208 * (in relation to the direction we are going), so that the next
1209 * invocation of sd_journal_next/previous will be from a different
1210 * boot. We then collect any information we desire and then jump
1211 * to the last location of the new boot by using a _BOOT_ID match
1212 * coming from the other journal direction. */
1213
1214 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1215 * we can actually advance to a *different* boot. */
1216 sd_journal_flush_matches(j);
1217
1218 do {
1219 if (advance_older)
1220 r = sd_journal_previous(j);
1221 else
1222 r = sd_journal_next(j);
1223 if (r < 0)
1224 return r;
1225 else if (r == 0) {
1226 *ret = (BootId) {};
1227 return 0; /* End of journal, yay. */
1228 }
1229
1230 r = sd_journal_get_monotonic_usec(j, NULL, &boot.id);
1231 if (r < 0)
1232 return r;
1233
1234 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1235 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1236 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1237 * complete than the main entry array, and hence might reference an entry that's not actually the last
1238 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1239 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1240 * necessary. */
1241
1242 } while (sd_id128_equal(boot.id, previous_boot_id));
1243
1244 r = sd_journal_get_realtime_usec(j, &boot.first_usec);
1245 if (r < 0)
1246 return r;
1247
1248 /* Now seek to the last occurrence of this boot ID. */
1249 r = add_match_boot_id(j, boot.id);
1250 if (r < 0)
1251 return r;
1252
1253 if (advance_older)
1254 r = sd_journal_seek_head(j);
1255 else
1256 r = sd_journal_seek_tail(j);
1257 if (r < 0)
1258 return r;
1259
1260 if (advance_older)
1261 r = sd_journal_next(j);
1262 else
1263 r = sd_journal_previous(j);
1264 if (r < 0)
1265 return r;
1266 else if (r == 0)
1267 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA),
1268 "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. */
1269
1270 r = sd_journal_get_realtime_usec(j, &boot.last_usec);
1271 if (r < 0)
1272 return r;
1273
1274 sd_journal_flush_matches(j);
1275 *ret = boot;
1276 return 1;
1277 }
1278
1279 static int find_boot_by_id(sd_journal *j) {
1280 int r;
1281
1282 assert(j);
1283
1284 sd_journal_flush_matches(j);
1285
1286 r = add_match_boot_id(j, arg_boot_id);
1287 if (r < 0)
1288 return r;
1289
1290 r = sd_journal_seek_head(j); /* seek to oldest */
1291 if (r < 0)
1292 return r;
1293
1294 r = sd_journal_next(j); /* read the oldest entry */
1295 if (r < 0)
1296 return r;
1297
1298 /* At this point the read pointer is positioned at the oldest occurrence of the reference boot ID.
1299 * After flushing the matches, one more invocation of _previous() will hence place us at the
1300 * following entry, which must then have an older boot ID */
1301
1302 sd_journal_flush_matches(j);
1303 return r > 0;
1304 }
1305
1306 static int find_boot_by_offset(sd_journal *j) {
1307 bool advance_older, skip_once;
1308 int r;
1309
1310 /* Adjust for the asymmetry that offset 0 is the last (and current) boot, while 1 is considered the
1311 * (chronological) first boot in the journal. */
1312 advance_older = skip_once = arg_boot_offset <= 0;
1313
1314 if (advance_older)
1315 r = sd_journal_seek_tail(j); /* seek to newest */
1316 else
1317 r = sd_journal_seek_head(j); /* seek to oldest */
1318 if (r < 0)
1319 return r;
1320
1321 /* No sd_journal_next()/_previous() here.
1322 *
1323 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1324 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1325 * entry we have. */
1326
1327 int offset = arg_boot_offset;
1328 sd_id128_t previous_boot_id = SD_ID128_NULL;
1329 for (;;) {
1330 BootId boot;
1331
1332 r = discover_next_boot(j, previous_boot_id, advance_older, &boot);
1333 if (r <= 0)
1334 return r;
1335
1336 previous_boot_id = boot.id;
1337
1338 if (!skip_once)
1339 offset += advance_older ? 1 : -1;
1340 skip_once = false;
1341
1342 if (offset == 0) {
1343 arg_boot_id = boot.id;
1344 return true;
1345 }
1346 }
1347 }
1348
1349 static int get_boots(sd_journal *j, BootId **ret_boots, size_t *ret_n_boots) {
1350 _cleanup_free_ BootId *boots = NULL;
1351 size_t n_boots = 0;
1352 int r;
1353
1354 assert(j);
1355 assert(ret_boots);
1356 assert(ret_n_boots);
1357
1358 r = sd_journal_seek_head(j); /* seek to oldest */
1359 if (r < 0)
1360 return r;
1361
1362 /* No sd_journal_next()/_previous() here.
1363 *
1364 * At this point the read pointer is positioned before the oldest entry in the whole journal. The
1365 * next invocation of _next() will hence position us at the oldest entry we have. */
1366
1367 sd_id128_t previous_boot_id = SD_ID128_NULL;
1368 for (;;) {
1369 BootId boot;
1370
1371 r = discover_next_boot(j, previous_boot_id, /* advance_older = */ false, &boot);
1372 if (r < 0)
1373 return r;
1374 if (r == 0)
1375 break;
1376
1377 previous_boot_id = boot.id;
1378
1379 FOREACH_ARRAY(i, boots, n_boots)
1380 if (sd_id128_equal(i->id, boot.id))
1381 /* The boot id is already stored, something wrong with the journal files.
1382 * Exiting as otherwise this problem would cause an infinite loop. */
1383 break;
1384
1385 if (!GREEDY_REALLOC(boots, n_boots + 1))
1386 return -ENOMEM;
1387
1388 boots[n_boots++] = boot;
1389 }
1390
1391 *ret_boots = TAKE_PTR(boots);
1392 *ret_n_boots = n_boots;
1393 return n_boots > 0;
1394 }
1395
1396 static int list_boots(sd_journal *j) {
1397 _cleanup_(table_unrefp) Table *table = NULL;
1398 _cleanup_free_ BootId *boots = NULL;
1399 size_t n_boots;
1400 int r;
1401
1402 assert(j);
1403
1404 r = get_boots(j, &boots, &n_boots);
1405 if (r < 0)
1406 return log_error_errno(r, "Failed to determine boots: %m");
1407 if (r == 0)
1408 return 0;
1409
1410 table = table_new("idx", "boot id", "first entry", "last entry");
1411 if (!table)
1412 return log_oom();
1413
1414 if (arg_full)
1415 table_set_width(table, 0);
1416
1417 r = table_set_json_field_name(table, 0, "index");
1418 if (r < 0)
1419 return log_error_errno(r, "Failed to set JSON field name of column 0: %m");
1420
1421 (void) table_set_sort(table, (size_t) 0);
1422 (void) table_set_reverse(table, 0, arg_reverse);
1423
1424 FOREACH_ARRAY(i, boots, n_boots) {
1425 r = table_add_many(table,
1426 TABLE_INT, (int)(i - boots) - (int) n_boots + 1,
1427 TABLE_SET_ALIGN_PERCENT, 100,
1428 TABLE_ID128, i->id,
1429 TABLE_TIMESTAMP, i->first_usec,
1430 TABLE_TIMESTAMP, i->last_usec);
1431 if (r < 0)
1432 return table_log_add_error(r);
1433 }
1434
1435 r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, !arg_quiet);
1436 if (r < 0)
1437 return table_log_print_error(r);
1438
1439 return 0;
1440 }
1441
1442 static int add_boot(sd_journal *j) {
1443 int r;
1444
1445 assert(j);
1446
1447 if (!arg_boot)
1448 return 0;
1449
1450 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1451 * We can do this only when we logs are coming from the current machine,
1452 * so take the slow path if log location is specified. */
1453 if (arg_boot_offset == 0 && sd_id128_is_null(arg_boot_id) &&
1454 !arg_directory && !arg_file && !arg_root)
1455 return add_match_this_boot(j, arg_machine);
1456
1457 if (sd_id128_is_null(arg_boot_id)) {
1458 r = find_boot_by_offset(j);
1459 if (r < 0)
1460 return log_error_errno(r, "Failed to find journal entry from the specified boot offset (%+i): %m",
1461 arg_boot_offset);
1462 if (r == 0)
1463 return log_error_errno(SYNTHETIC_ERRNO(ENODATA),
1464 "No journal boot entry found from the specified boot offset (%+i).",
1465 arg_boot_offset);
1466 } else {
1467 r = find_boot_by_id(j);
1468 if (r < 0)
1469 return log_error_errno(r, "Failed to find journal entry from the specified boot ID (%s): %m",
1470 SD_ID128_TO_STRING(arg_boot_id));
1471 if (r == 0)
1472 return log_error_errno(SYNTHETIC_ERRNO(ENODATA),
1473 "No journal boot entry found from the specified boot ID (%s).",
1474 SD_ID128_TO_STRING(arg_boot_id));
1475 }
1476
1477 r = add_match_boot_id(j, arg_boot_id);
1478 if (r < 0)
1479 return log_error_errno(r, "Failed to add match: %m");
1480
1481 r = sd_journal_add_conjunction(j);
1482 if (r < 0)
1483 return log_error_errno(r, "Failed to add conjunction: %m");
1484
1485 return 0;
1486 }
1487
1488 static int add_dmesg(sd_journal *j) {
1489 int r;
1490 assert(j);
1491
1492 if (!arg_dmesg)
1493 return 0;
1494
1495 r = sd_journal_add_match(j, "_TRANSPORT=kernel",
1496 STRLEN("_TRANSPORT=kernel"));
1497 if (r < 0)
1498 return log_error_errno(r, "Failed to add match: %m");
1499
1500 r = sd_journal_add_conjunction(j);
1501 if (r < 0)
1502 return log_error_errno(r, "Failed to add conjunction: %m");
1503
1504 return 0;
1505 }
1506
1507 static int get_possible_units(
1508 sd_journal *j,
1509 const char *fields,
1510 char **patterns,
1511 Set **units) {
1512
1513 _cleanup_set_free_free_ Set *found = NULL;
1514 int r;
1515
1516 found = set_new(&string_hash_ops);
1517 if (!found)
1518 return -ENOMEM;
1519
1520 NULSTR_FOREACH(field, fields) {
1521 const void *data;
1522 size_t size;
1523
1524 r = sd_journal_query_unique(j, field);
1525 if (r < 0)
1526 return r;
1527
1528 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1529 char *eq;
1530 size_t prefix;
1531 _cleanup_free_ char *u = NULL;
1532
1533 eq = memchr(data, '=', size);
1534 if (eq)
1535 prefix = eq - (char*) data + 1;
1536 else
1537 prefix = 0;
1538
1539 u = strndup((char*) data + prefix, size - prefix);
1540 if (!u)
1541 return -ENOMEM;
1542
1543 STRV_FOREACH(pattern, patterns)
1544 if (fnmatch(*pattern, u, FNM_NOESCAPE) == 0) {
1545 log_debug("Matched %s with pattern %s=%s", u, field, *pattern);
1546
1547 r = set_consume(found, u);
1548 u = NULL;
1549 if (r < 0 && r != -EEXIST)
1550 return r;
1551
1552 break;
1553 }
1554 }
1555 }
1556
1557 *units = TAKE_PTR(found);
1558
1559 return 0;
1560 }
1561
1562 /* This list is supposed to return the superset of unit names
1563 * possibly matched by rules added with add_matches_for_unit... */
1564 #define SYSTEM_UNITS \
1565 "_SYSTEMD_UNIT\0" \
1566 "COREDUMP_UNIT\0" \
1567 "UNIT\0" \
1568 "OBJECT_SYSTEMD_UNIT\0" \
1569 "_SYSTEMD_SLICE\0"
1570
1571 /* ... and add_matches_for_user_unit */
1572 #define USER_UNITS \
1573 "_SYSTEMD_USER_UNIT\0" \
1574 "USER_UNIT\0" \
1575 "COREDUMP_USER_UNIT\0" \
1576 "OBJECT_SYSTEMD_USER_UNIT\0" \
1577 "_SYSTEMD_USER_SLICE\0"
1578
1579 static int add_units(sd_journal *j) {
1580 _cleanup_strv_free_ char **patterns = NULL;
1581 int r, count = 0;
1582
1583 assert(j);
1584
1585 STRV_FOREACH(i, arg_system_units) {
1586 _cleanup_free_ char *u = NULL;
1587
1588 r = unit_name_mangle(*i, UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN), &u);
1589 if (r < 0)
1590 return r;
1591
1592 if (string_is_glob(u)) {
1593 r = strv_push(&patterns, u);
1594 if (r < 0)
1595 return r;
1596 u = NULL;
1597 } else {
1598 r = add_matches_for_unit(j, u);
1599 if (r < 0)
1600 return r;
1601 r = sd_journal_add_disjunction(j);
1602 if (r < 0)
1603 return r;
1604 count++;
1605 }
1606 }
1607
1608 if (!strv_isempty(patterns)) {
1609 _cleanup_set_free_free_ Set *units = NULL;
1610 char *u;
1611
1612 r = get_possible_units(j, SYSTEM_UNITS, patterns, &units);
1613 if (r < 0)
1614 return r;
1615
1616 SET_FOREACH(u, units) {
1617 r = add_matches_for_unit(j, u);
1618 if (r < 0)
1619 return r;
1620 r = sd_journal_add_disjunction(j);
1621 if (r < 0)
1622 return r;
1623 count++;
1624 }
1625 }
1626
1627 patterns = strv_free(patterns);
1628
1629 STRV_FOREACH(i, arg_user_units) {
1630 _cleanup_free_ char *u = NULL;
1631
1632 r = unit_name_mangle(*i, UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN), &u);
1633 if (r < 0)
1634 return r;
1635
1636 if (string_is_glob(u)) {
1637 r = strv_push(&patterns, u);
1638 if (r < 0)
1639 return r;
1640 u = NULL;
1641 } else {
1642 r = add_matches_for_user_unit(j, u, getuid());
1643 if (r < 0)
1644 return r;
1645 r = sd_journal_add_disjunction(j);
1646 if (r < 0)
1647 return r;
1648 count++;
1649 }
1650 }
1651
1652 if (!strv_isempty(patterns)) {
1653 _cleanup_set_free_free_ Set *units = NULL;
1654 char *u;
1655
1656 r = get_possible_units(j, USER_UNITS, patterns, &units);
1657 if (r < 0)
1658 return r;
1659
1660 SET_FOREACH(u, units) {
1661 r = add_matches_for_user_unit(j, u, getuid());
1662 if (r < 0)
1663 return r;
1664 r = sd_journal_add_disjunction(j);
1665 if (r < 0)
1666 return r;
1667 count++;
1668 }
1669 }
1670
1671 /* Complain if the user request matches but nothing whatsoever was
1672 * found, since otherwise everything would be matched. */
1673 if (!(strv_isempty(arg_system_units) && strv_isempty(arg_user_units)) && count == 0)
1674 return -ENODATA;
1675
1676 r = sd_journal_add_conjunction(j);
1677 if (r < 0)
1678 return r;
1679
1680 return 0;
1681 }
1682
1683 static int add_priorities(sd_journal *j) {
1684 char match[] = "PRIORITY=0";
1685 int i, r;
1686 assert(j);
1687
1688 if (arg_priorities == 0xFF)
1689 return 0;
1690
1691 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
1692 if (arg_priorities & (1 << i)) {
1693 match[sizeof(match)-2] = '0' + i;
1694
1695 r = sd_journal_add_match(j, match, strlen(match));
1696 if (r < 0)
1697 return log_error_errno(r, "Failed to add match: %m");
1698 }
1699
1700 r = sd_journal_add_conjunction(j);
1701 if (r < 0)
1702 return log_error_errno(r, "Failed to add conjunction: %m");
1703
1704 return 0;
1705 }
1706
1707 static int add_facilities(sd_journal *j) {
1708 void *p;
1709 int r;
1710
1711 SET_FOREACH(p, arg_facilities) {
1712 char match[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
1713
1714 xsprintf(match, "SYSLOG_FACILITY=%d", PTR_TO_INT(p));
1715
1716 r = sd_journal_add_match(j, match, strlen(match));
1717 if (r < 0)
1718 return log_error_errno(r, "Failed to add match: %m");
1719 }
1720
1721 return 0;
1722 }
1723
1724 static int add_syslog_identifier(sd_journal *j) {
1725 int r;
1726
1727 assert(j);
1728
1729 STRV_FOREACH(i, arg_syslog_identifier) {
1730 _cleanup_free_ char *u = NULL;
1731
1732 u = strjoin("SYSLOG_IDENTIFIER=", *i);
1733 if (!u)
1734 return -ENOMEM;
1735 r = sd_journal_add_match(j, u, 0);
1736 if (r < 0)
1737 return r;
1738 r = sd_journal_add_disjunction(j);
1739 if (r < 0)
1740 return r;
1741 }
1742
1743 r = sd_journal_add_conjunction(j);
1744 if (r < 0)
1745 return r;
1746
1747 return 0;
1748 }
1749
1750 #if HAVE_GCRYPT
1751 static int format_journal_url(
1752 const void *seed,
1753 size_t seed_size,
1754 uint64_t start,
1755 uint64_t interval,
1756 const char *hn,
1757 sd_id128_t machine,
1758 bool full,
1759 char **ret_url) {
1760 _cleanup_free_ char *url = NULL;
1761 _cleanup_fclose_ FILE *f = NULL;
1762 size_t url_size = 0;
1763 int r;
1764
1765 assert(seed);
1766 assert(seed_size > 0);
1767
1768 f = open_memstream_unlocked(&url, &url_size);
1769 if (!f)
1770 return -ENOMEM;
1771
1772 if (full)
1773 fputs("fss://", f);
1774
1775 for (size_t i = 0; i < seed_size; i++) {
1776 if (i > 0 && i % 3 == 0)
1777 fputc('-', f);
1778 fprintf(f, "%02x", ((uint8_t*) seed)[i]);
1779 }
1780
1781 fprintf(f, "/%"PRIx64"-%"PRIx64, start, interval);
1782
1783 if (full) {
1784 fprintf(f, "?machine=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(machine));
1785 if (hn)
1786 fprintf(f, ";hostname=%s", hn);
1787 }
1788
1789 r = fflush_and_check(f);
1790 if (r < 0)
1791 return r;
1792
1793 f = safe_fclose(f);
1794
1795 if (!url)
1796 return -ENOMEM;
1797
1798 *ret_url = TAKE_PTR(url);
1799 return 0;
1800 }
1801 #endif
1802
1803 static int setup_keys(void) {
1804 #if HAVE_GCRYPT
1805 size_t mpk_size, seed_size, state_size;
1806 _cleanup_(unlink_and_freep) char *k = NULL;
1807 _cleanup_free_ char *p = NULL;
1808 uint8_t *mpk, *seed, *state;
1809 _cleanup_close_ int fd = -EBADF;
1810 sd_id128_t machine, boot;
1811 struct stat st;
1812 uint64_t n;
1813 int r;
1814
1815 r = stat("/var/log/journal", &st);
1816 if (r < 0 && !IN_SET(errno, ENOENT, ENOTDIR))
1817 return log_error_errno(errno, "stat(\"%s\") failed: %m", "/var/log/journal");
1818
1819 if (r < 0 || !S_ISDIR(st.st_mode)) {
1820 log_error("%s is not a directory, must be using persistent logging for FSS.",
1821 "/var/log/journal");
1822 return r < 0 ? -errno : -ENOTDIR;
1823 }
1824
1825 r = sd_id128_get_machine(&machine);
1826 if (r < 0)
1827 return log_error_errno(r, "Failed to get machine ID: %m");
1828
1829 r = sd_id128_get_boot(&boot);
1830 if (r < 0)
1831 return log_error_errno(r, "Failed to get boot ID: %m");
1832
1833 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
1834 SD_ID128_FORMAT_VAL(machine)) < 0)
1835 return log_oom();
1836
1837 if (arg_force) {
1838 r = unlink(p);
1839 if (r < 0 && errno != ENOENT)
1840 return log_error_errno(errno, "unlink(\"%s\") failed: %m", p);
1841 } else if (access(p, F_OK) >= 0)
1842 return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
1843 "Sealing key file %s exists already. Use --force to recreate.", p);
1844
1845 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
1846 SD_ID128_FORMAT_VAL(machine)) < 0)
1847 return log_oom();
1848
1849 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
1850 mpk = alloca_safe(mpk_size);
1851
1852 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
1853 seed = alloca_safe(seed_size);
1854
1855 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
1856 state = alloca_safe(state_size);
1857
1858 log_info("Generating seed...");
1859 r = crypto_random_bytes(seed, seed_size);
1860 if (r < 0)
1861 return log_error_errno(r, "Failed to acquire random seed: %m");
1862
1863 log_info("Generating key pair...");
1864 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
1865
1866 log_info("Generating sealing key...");
1867 FSPRG_GenState0(state, mpk, seed, seed_size);
1868
1869 assert(arg_interval > 0);
1870
1871 n = now(CLOCK_REALTIME);
1872 n /= arg_interval;
1873
1874 safe_close(fd);
1875 fd = mkostemp_safe(k);
1876 if (fd < 0)
1877 return log_error_errno(fd, "Failed to open %s: %m", k);
1878
1879 r = chattr_secret(fd, CHATTR_WARN_UNSUPPORTED_FLAGS);
1880 if (r < 0)
1881 log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) ? LOG_DEBUG : LOG_WARNING,
1882 r, "Failed to set file attributes on '%s', ignoring: %m", k);
1883
1884 struct FSSHeader h = {
1885 .signature = { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' },
1886 .machine_id = machine,
1887 .boot_id = boot,
1888 .header_size = htole64(sizeof(h)),
1889 .start_usec = htole64(n * arg_interval),
1890 .interval_usec = htole64(arg_interval),
1891 .fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR),
1892 .fsprg_state_size = htole64(state_size),
1893 };
1894
1895 r = loop_write(fd, &h, sizeof(h), false);
1896 if (r < 0)
1897 return log_error_errno(r, "Failed to write header: %m");
1898
1899 r = loop_write(fd, state, state_size, false);
1900 if (r < 0)
1901 return log_error_errno(r, "Failed to write state: %m");
1902
1903 if (rename(k, p) < 0)
1904 return log_error_errno(errno, "Failed to link file: %m");
1905
1906 k = mfree(k);
1907
1908 _cleanup_free_ char *hn = NULL, *key = NULL;
1909
1910 r = format_journal_url(seed, seed_size, n, arg_interval, hn, machine, false, &key);
1911 if (r < 0)
1912 return r;
1913
1914 if (on_tty()) {
1915 hn = gethostname_malloc();
1916 if (hn)
1917 hostname_cleanup(hn);
1918
1919 fprintf(stderr,
1920 "\nNew keys have been generated for host %s%s" SD_ID128_FORMAT_STR ".\n"
1921 "\n"
1922 "The %ssecret sealing key%s has been written to the following local file.\n"
1923 "This key file is automatically updated when the sealing key is advanced.\n"
1924 "It should not be used on multiple hosts.\n"
1925 "\n"
1926 "\t%s\n"
1927 "\n"
1928 "The sealing key is automatically changed every %s.\n"
1929 "\n"
1930 "Please write down the following %ssecret verification key%s. It should be stored\n"
1931 "in a safe location and should not be saved locally on disk.\n"
1932 "\n\t%s",
1933 strempty(hn), hn ? "/" : "",
1934 SD_ID128_FORMAT_VAL(machine),
1935 ansi_highlight(), ansi_normal(),
1936 p,
1937 FORMAT_TIMESPAN(arg_interval, 0),
1938 ansi_highlight(), ansi_normal(),
1939 ansi_highlight_red());
1940 fflush(stderr);
1941 }
1942
1943 puts(key);
1944
1945 if (on_tty()) {
1946 fprintf(stderr, "%s", ansi_normal());
1947 #if HAVE_QRENCODE
1948 _cleanup_free_ char *url = NULL;
1949 r = format_journal_url(seed, seed_size, n, arg_interval, hn, machine, true, &url);
1950 if (r < 0)
1951 return r;
1952
1953 (void) print_qrcode(stderr,
1954 "To transfer the verification key to your phone scan the QR code below",
1955 url);
1956 #endif
1957 }
1958
1959 return 0;
1960 #else
1961 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1962 "Forward-secure sealing not available.");
1963 #endif
1964 }
1965
1966 static int verify(sd_journal *j, bool verbose) {
1967 int r = 0;
1968 JournalFile *f;
1969
1970 assert(j);
1971
1972 log_show_color(true);
1973
1974 ORDERED_HASHMAP_FOREACH(f, j->files) {
1975 int k;
1976 usec_t first = 0, validated = 0, last = 0;
1977
1978 #if HAVE_GCRYPT
1979 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
1980 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
1981 #endif
1982
1983 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, verbose);
1984 if (k == -EINVAL)
1985 /* If the key was invalid give up right-away. */
1986 return k;
1987 else if (k < 0)
1988 r = log_warning_errno(k, "FAIL: %s (%m)", f->path);
1989 else {
1990 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
1991 log_full(verbose ? LOG_INFO : LOG_DEBUG, "PASS: %s", f->path);
1992
1993 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
1994 if (validated > 0) {
1995 log_full(verbose ? LOG_INFO : LOG_DEBUG,
1996 "=> Validated from %s to %s, final %s entries not sealed.",
1997 format_timestamp_maybe_utc(a, sizeof(a), first),
1998 format_timestamp_maybe_utc(b, sizeof(b), validated),
1999 FORMAT_TIMESPAN(last > validated ? last - validated : 0, 0));
2000 } else if (last > 0)
2001 log_full(verbose ? LOG_INFO : LOG_DEBUG,
2002 "=> No sealing yet, %s of entries not sealed.",
2003 FORMAT_TIMESPAN(last - first, 0));
2004 else
2005 log_full(verbose ? LOG_INFO : LOG_DEBUG,
2006 "=> No sealing yet, no entries in file.");
2007 }
2008 }
2009 }
2010
2011 return r;
2012 }
2013
2014 static int simple_varlink_call(const char *option, const char *method) {
2015 _cleanup_(varlink_flush_close_unrefp) Varlink *link = NULL;
2016 const char *error, *fn;
2017 int r;
2018
2019 if (arg_machine)
2020 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "%s is not supported in conjunction with --machine=.", option);
2021
2022 fn = arg_namespace ?
2023 strjoina("/run/systemd/journal.", arg_namespace, "/io.systemd.journal") :
2024 "/run/systemd/journal/io.systemd.journal";
2025
2026 r = varlink_connect_address(&link, fn);
2027 if (r < 0)
2028 return log_error_errno(r, "Failed to connect to %s: %m", fn);
2029
2030 (void) varlink_set_description(link, "journal");
2031 (void) varlink_set_relative_timeout(link, USEC_INFINITY);
2032
2033 r = varlink_call(link, method, NULL, NULL, &error, NULL);
2034 if (r < 0)
2035 return log_error_errno(r, "Failed to execute varlink call: %m");
2036 if (error)
2037 return log_error_errno(SYNTHETIC_ERRNO(ENOANO),
2038 "Failed to execute varlink call: %s", error);
2039
2040 return 0;
2041 }
2042
2043 static int flush_to_var(void) {
2044 if (access("/run/systemd/journal/flushed", F_OK) >= 0)
2045 return 0; /* Already flushed, no need to contact journald */
2046 if (errno != ENOENT)
2047 return log_error_errno(errno, "Unable to check for existence of /run/systemd/journal/flushed: %m");
2048
2049 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
2050 }
2051
2052 static int relinquish_var(void) {
2053 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
2054 }
2055
2056 static int rotate(void) {
2057 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
2058 }
2059
2060 static int sync_journal(void) {
2061 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
2062 }
2063
2064 static int action_list_fields(sd_journal *j) {
2065 const void *data;
2066 size_t size;
2067 int r, n_shown = 0;
2068
2069 assert(arg_field);
2070
2071 r = sd_journal_set_data_threshold(j, 0);
2072 if (r < 0)
2073 return log_error_errno(r, "Failed to unset data size threshold: %m");
2074
2075 r = sd_journal_query_unique(j, arg_field);
2076 if (r < 0)
2077 return log_error_errno(r, "Failed to query unique data objects: %m");
2078
2079 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
2080 const void *eq;
2081
2082 if (arg_lines >= 0 && n_shown >= arg_lines)
2083 break;
2084
2085 eq = memchr(data, '=', size);
2086 if (eq)
2087 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
2088 else
2089 printf("%.*s\n", (int) size, (const char*) data);
2090
2091 n_shown++;
2092 }
2093
2094 return 0;
2095 }
2096
2097 static int update_cursor(sd_journal *j) {
2098 _cleanup_free_ char *cursor = NULL;
2099 int r;
2100
2101 assert(j);
2102
2103 if (!arg_show_cursor && !arg_cursor_file)
2104 return 0;
2105
2106 r = sd_journal_get_cursor(j, &cursor);
2107 if (r == -EADDRNOTAVAIL)
2108 return 0;
2109 if (r < 0)
2110 return log_error_errno(r, "Failed to get cursor: %m");
2111
2112 if (arg_show_cursor)
2113 printf("-- cursor: %s\n", cursor);
2114
2115 if (arg_cursor_file) {
2116 r = write_string_file(arg_cursor_file, cursor, WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_ATOMIC);
2117 if (r < 0)
2118 return log_error_errno(r, "Failed to write new cursor to %s: %m", arg_cursor_file);
2119 }
2120
2121 return 0;
2122 }
2123
2124 typedef struct Context {
2125 sd_journal *journal;
2126 bool need_seek;
2127 bool since_seeked;
2128 bool ellipsized;
2129 bool previous_boot_id_valid;
2130 sd_id128_t previous_boot_id;
2131 sd_id128_t previous_boot_id_output;
2132 dual_timestamp previous_ts_output;
2133 } Context;
2134
2135 static int show(Context *c) {
2136 sd_journal *j;
2137 int r, n_shown = 0;
2138
2139 assert(c);
2140
2141 j = ASSERT_PTR(c->journal);
2142
2143 while (arg_lines < 0 || n_shown < arg_lines || arg_follow) {
2144 int flags;
2145 size_t highlight[2] = {};
2146
2147 if (c->need_seek) {
2148 if (!arg_reverse)
2149 r = sd_journal_next(j);
2150 else
2151 r = sd_journal_previous(j);
2152 if (r < 0)
2153 return log_error_errno(r, "Failed to iterate through journal: %m");
2154 if (r == 0)
2155 break;
2156 }
2157
2158 if (arg_until_set && !arg_reverse && (arg_lines < 0 || arg_since_set)) {
2159 /* If --lines= is set, we usually rely on the n_shown to tell us
2160 * when to stop. However, if --since= is set too, we may end up
2161 * having less than --lines= to output. In this case let's also
2162 * check if the entry is in range. */
2163
2164 usec_t usec;
2165
2166 r = sd_journal_get_realtime_usec(j, &usec);
2167 if (r < 0)
2168 return log_error_errno(r, "Failed to determine timestamp: %m");
2169 if (usec > arg_until)
2170 break;
2171 }
2172
2173 if (arg_since_set && (arg_reverse || !c->since_seeked)) {
2174 usec_t usec;
2175
2176 r = sd_journal_get_realtime_usec(j, &usec);
2177 if (r < 0)
2178 return log_error_errno(r, "Failed to determine timestamp: %m");
2179
2180 if (usec < arg_since) {
2181 if (arg_reverse)
2182 break; /* Reached the earliest entry */
2183
2184 /* arg_lines >= 0 (!since_seeked):
2185 * We jumped arg_lines back and it seems to be too much */
2186 r = sd_journal_seek_realtime_usec(j, arg_since);
2187 if (r < 0)
2188 return log_error_errno(r, "Failed to seek to date: %m");
2189 c->since_seeked = true;
2190
2191 c->need_seek = true;
2192 continue;
2193 }
2194 c->since_seeked = true; /* We're surely within the range of --since now */
2195 }
2196
2197 if (!arg_merge && !arg_quiet) {
2198 sd_id128_t boot_id;
2199
2200 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
2201 if (r >= 0) {
2202 if (c->previous_boot_id_valid &&
2203 !sd_id128_equal(boot_id, c->previous_boot_id))
2204 printf("%s-- Boot "SD_ID128_FORMAT_STR" --%s\n",
2205 ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id), ansi_normal());
2206
2207 c->previous_boot_id = boot_id;
2208 c->previous_boot_id_valid = true;
2209 }
2210 }
2211
2212 if (arg_compiled_pattern) {
2213 const void *message;
2214 size_t len;
2215
2216 r = sd_journal_get_data(j, "MESSAGE", &message, &len);
2217 if (r < 0) {
2218 if (r == -ENOENT) {
2219 c->need_seek = true;
2220 continue;
2221 }
2222
2223 return log_error_errno(r, "Failed to get MESSAGE field: %m");
2224 }
2225
2226 assert_se(message = startswith(message, "MESSAGE="));
2227
2228 r = pattern_matches_and_log(arg_compiled_pattern, message,
2229 len - strlen("MESSAGE="), highlight);
2230 if (r < 0)
2231 return r;
2232 if (r == 0) {
2233 c->need_seek = true;
2234 continue;
2235 }
2236 }
2237
2238 flags =
2239 arg_all * OUTPUT_SHOW_ALL |
2240 arg_full * OUTPUT_FULL_WIDTH |
2241 colors_enabled() * OUTPUT_COLOR |
2242 arg_catalog * OUTPUT_CATALOG |
2243 arg_utc * OUTPUT_UTC |
2244 arg_no_hostname * OUTPUT_NO_HOSTNAME;
2245
2246 r = show_journal_entry(stdout, j, arg_output, 0, flags,
2247 arg_output_fields, highlight, &c->ellipsized,
2248 &c->previous_ts_output, &c->previous_boot_id_output);
2249 c->need_seek = true;
2250 if (r == -EADDRNOTAVAIL)
2251 break;
2252 if (r < 0)
2253 return r;
2254
2255 n_shown++;
2256
2257 /* If journalctl take a long time to process messages, and during that time journal file
2258 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2259 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2260 * in the "following" case. By periodically calling sd_journal_process() during the processing
2261 * loop we shrink the window of time a client instance has open file descriptors for rotated
2262 * (deleted) journal files. */
2263 if ((n_shown % PROCESS_INOTIFY_INTERVAL) == 0) {
2264 r = sd_journal_process(j);
2265 if (r < 0)
2266 return log_error_errno(r, "Failed to process inotify events: %m");
2267 }
2268 }
2269
2270 return n_shown;
2271 }
2272
2273 static int show_and_fflush(Context *c, sd_event_source *s) {
2274 int r;
2275
2276 assert(c);
2277 assert(s);
2278
2279 r = show(c);
2280 if (r < 0)
2281 return sd_event_exit(sd_event_source_get_event(s), r);
2282
2283 fflush(stdout);
2284 return 0;
2285 }
2286
2287 static int on_journal_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
2288 Context *c = ASSERT_PTR(userdata);
2289 int r;
2290
2291 assert(s);
2292
2293 r = sd_journal_process(c->journal);
2294 if (r < 0) {
2295 log_error_errno(r, "Failed to process journal events: %m");
2296 return sd_event_exit(sd_event_source_get_event(s), r);
2297 }
2298
2299 return show_and_fflush(c, s);
2300 }
2301
2302 static int on_first_event(sd_event_source *s, void *userdata) {
2303 return show_and_fflush(userdata, s);
2304 }
2305
2306 static int setup_event(Context *c, int fd, sd_event **ret) {
2307 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
2308 int r;
2309
2310 assert(arg_follow);
2311 assert(c);
2312 assert(fd >= 0);
2313 assert(ret);
2314
2315 r = sd_event_default(&e);
2316 if (r < 0)
2317 return log_error_errno(r, "Failed to allocate sd_event object: %m");
2318
2319 r = sd_event_add_io(e, NULL, fd, EPOLLIN, &on_journal_event, c);
2320 if (r < 0)
2321 return log_error_errno(r, "Failed to add io event source for journal: %m");
2322
2323 /* Also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that, i.e. when it is closed. */
2324 r = sd_event_add_io(e, NULL, STDOUT_FILENO, EPOLLHUP|EPOLLERR, NULL, INT_TO_PTR(-ECANCELED));
2325 if (r < 0)
2326 return log_error_errno(r, "Failed to add io event source for stdout: %m");
2327
2328 if (arg_lines != 0 || arg_since_set) {
2329 r = sd_event_add_defer(e, NULL, on_first_event, c);
2330 if (r < 0)
2331 return log_error_errno(r, "Failed to add defer event source: %m");
2332 }
2333
2334 *ret = TAKE_PTR(e);
2335 return 0;
2336 }
2337
2338 static int run(int argc, char *argv[]) {
2339 bool need_seek = false, since_seeked = false, use_cursor = false, after_cursor = false;
2340 _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
2341 _cleanup_(umount_and_freep) char *mounted_dir = NULL;
2342 _cleanup_(sd_journal_closep) sd_journal *j = NULL;
2343 _cleanup_close_ int machine_fd = -EBADF;
2344 int n_shown, r, poll_fd = -EBADF;
2345
2346 setlocale(LC_ALL, "");
2347 log_setup();
2348
2349 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2350 * split up into many files. */
2351 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
2352
2353 r = parse_argv(argc, argv);
2354 if (r <= 0)
2355 return r;
2356
2357 if (arg_image) {
2358 assert(!arg_root);
2359
2360 r = mount_image_privately_interactively(
2361 arg_image,
2362 arg_image_policy,
2363 DISSECT_IMAGE_GENERIC_ROOT |
2364 DISSECT_IMAGE_REQUIRE_ROOT |
2365 DISSECT_IMAGE_VALIDATE_OS |
2366 DISSECT_IMAGE_RELAX_VAR_CHECK |
2367 (arg_action == ACTION_UPDATE_CATALOG ? DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS : DISSECT_IMAGE_READ_ONLY),
2368 &mounted_dir,
2369 /* ret_dir_fd= */ NULL,
2370 &loop_device);
2371 if (r < 0)
2372 return r;
2373
2374 arg_root = strdup(mounted_dir);
2375 if (!arg_root)
2376 return log_oom();
2377 }
2378
2379 signal(SIGWINCH, columns_lines_cache_reset);
2380 sigbus_install();
2381
2382 switch (arg_action) {
2383
2384 case ACTION_NEW_ID128:
2385 return id128_print_new(ID128_PRINT_PRETTY);
2386
2387 case ACTION_SETUP_KEYS:
2388 return setup_keys();
2389
2390 case ACTION_LIST_CATALOG:
2391 case ACTION_DUMP_CATALOG:
2392 case ACTION_UPDATE_CATALOG: {
2393 _cleanup_free_ char *database = NULL;
2394
2395 database = path_join(arg_root, CATALOG_DATABASE);
2396 if (!database)
2397 return log_oom();
2398
2399 if (arg_action == ACTION_UPDATE_CATALOG) {
2400 r = catalog_update(database, arg_root, catalog_file_dirs);
2401 if (r < 0)
2402 return log_error_errno(r, "Failed to list catalog: %m");
2403 } else {
2404 bool oneline = arg_action == ACTION_LIST_CATALOG;
2405
2406 pager_open(arg_pager_flags);
2407
2408 if (optind < argc)
2409 r = catalog_list_items(stdout, database, oneline, argv + optind);
2410 else
2411 r = catalog_list(stdout, database, oneline);
2412 if (r < 0)
2413 return log_error_errno(r, "Failed to list catalog: %m");
2414 }
2415
2416 return 0;
2417 }
2418
2419 case ACTION_FLUSH:
2420 return flush_to_var();
2421
2422 case ACTION_RELINQUISH_VAR:
2423 return relinquish_var();
2424
2425 case ACTION_SYNC:
2426 return sync_journal();
2427
2428 case ACTION_ROTATE:
2429 return rotate();
2430
2431 case ACTION_SHOW:
2432 case ACTION_PRINT_HEADER:
2433 case ACTION_VERIFY:
2434 case ACTION_DISK_USAGE:
2435 case ACTION_LIST_BOOTS:
2436 case ACTION_VACUUM:
2437 case ACTION_ROTATE_AND_VACUUM:
2438 case ACTION_LIST_FIELDS:
2439 case ACTION_LIST_FIELD_NAMES:
2440 /* These ones require access to the journal files, continue below. */
2441 break;
2442
2443 default:
2444 assert_not_reached();
2445 }
2446
2447 if (arg_directory)
2448 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
2449 else if (arg_root)
2450 r = sd_journal_open_directory(&j, arg_root, arg_journal_type | SD_JOURNAL_OS_ROOT);
2451 else if (arg_file_stdin)
2452 r = sd_journal_open_files_fd(&j, (int[]) { STDIN_FILENO }, 1, 0);
2453 else if (arg_file)
2454 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
2455 else if (arg_machine) {
2456 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2457 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2458 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
2459 int fd;
2460
2461 if (geteuid() != 0)
2462 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2463 * the container, thus we need root privileges to override them. */
2464 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Using the --machine= switch requires root privileges.");
2465
2466 r = sd_bus_open_system(&bus);
2467 if (r < 0)
2468 return log_error_errno(r, "Failed to open system bus: %m");
2469
2470 r = bus_call_method(bus, bus_machine_mgr, "OpenMachineRootDirectory", &error, &reply, "s", arg_machine);
2471 if (r < 0)
2472 return log_error_errno(r, "Failed to open root directory: %s", bus_error_message(&error, r));
2473
2474 r = sd_bus_message_read(reply, "h", &fd);
2475 if (r < 0)
2476 return bus_log_parse_error(r);
2477
2478 machine_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
2479 if (machine_fd < 0)
2480 return log_error_errno(errno, "Failed to duplicate file descriptor: %m");
2481
2482 r = sd_journal_open_directory_fd(&j, machine_fd, SD_JOURNAL_OS_ROOT);
2483 } else
2484 r = sd_journal_open_namespace(
2485 &j,
2486 arg_namespace,
2487 (arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY) |
2488 arg_namespace_flags | arg_journal_type);
2489 if (r < 0)
2490 return log_error_errno(r, "Failed to open %s: %m", arg_directory ?: arg_file ? "files" : "journal");
2491
2492 r = journal_access_check_and_warn(j, arg_quiet,
2493 !(arg_journal_type == SD_JOURNAL_CURRENT_USER || arg_user_units));
2494 if (r < 0)
2495 return r;
2496
2497 switch (arg_action) {
2498
2499 case ACTION_NEW_ID128:
2500 case ACTION_SETUP_KEYS:
2501 case ACTION_LIST_CATALOG:
2502 case ACTION_DUMP_CATALOG:
2503 case ACTION_UPDATE_CATALOG:
2504 case ACTION_FLUSH:
2505 case ACTION_SYNC:
2506 case ACTION_ROTATE:
2507 assert_not_reached();
2508
2509 case ACTION_PRINT_HEADER:
2510 journal_print_header(j);
2511 return 0;
2512
2513 case ACTION_VERIFY:
2514 return verify(j, !arg_quiet);
2515
2516 case ACTION_DISK_USAGE: {
2517 uint64_t bytes = 0;
2518
2519 r = sd_journal_get_usage(j, &bytes);
2520 if (r < 0)
2521 return r;
2522
2523 printf("Archived and active journals take up %s in the file system.\n",
2524 FORMAT_BYTES(bytes));
2525
2526 return 0;
2527 }
2528
2529 case ACTION_LIST_BOOTS:
2530 return list_boots(j);
2531
2532 case ACTION_ROTATE_AND_VACUUM:
2533
2534 r = rotate();
2535 if (r < 0)
2536 return r;
2537
2538 _fallthrough_;
2539
2540 case ACTION_VACUUM: {
2541 Directory *d;
2542 int ret = 0;
2543
2544 HASHMAP_FOREACH(d, j->directories_by_path) {
2545 r = journal_directory_vacuum(d->path, arg_vacuum_size, arg_vacuum_n_files, arg_vacuum_time, NULL, !arg_quiet);
2546 if (r < 0) {
2547 log_error_errno(r, "Failed to vacuum %s: %m", d->path);
2548 if (ret >= 0)
2549 ret = r;
2550 }
2551 }
2552
2553 return ret;
2554 }
2555
2556 case ACTION_LIST_FIELD_NAMES: {
2557 const char *field;
2558
2559 SD_JOURNAL_FOREACH_FIELD(j, field)
2560 printf("%s\n", field);
2561
2562 return 0;
2563 }
2564
2565 case ACTION_SHOW:
2566 case ACTION_LIST_FIELDS:
2567 break;
2568
2569 default:
2570 assert_not_reached();
2571 }
2572
2573 if (arg_boot_offset != 0 &&
2574 sd_journal_has_runtime_files(j) > 0 &&
2575 sd_journal_has_persistent_files(j) == 0) {
2576 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2577
2578 if (arg_action == ACTION_SHOW && arg_compiled_pattern)
2579 return -ENOENT;
2580
2581 return 0;
2582 }
2583 /* add_boot() must be called first!
2584 * It may need to seek the journal to find parent boot IDs. */
2585 r = add_boot(j);
2586 if (r < 0)
2587 return r;
2588
2589 r = add_dmesg(j);
2590 if (r < 0)
2591 return r;
2592
2593 r = add_units(j);
2594 if (r < 0)
2595 return log_error_errno(r, "Failed to add filter for units: %m");
2596
2597 r = add_syslog_identifier(j);
2598 if (r < 0)
2599 return log_error_errno(r, "Failed to add filter for syslog identifiers: %m");
2600
2601 r = add_priorities(j);
2602 if (r < 0)
2603 return r;
2604
2605 r = add_facilities(j);
2606 if (r < 0)
2607 return r;
2608
2609 r = add_matches(j, argv + optind);
2610 if (r < 0)
2611 return r;
2612
2613 if (DEBUG_LOGGING) {
2614 _cleanup_free_ char *filter = NULL;
2615
2616 filter = journal_make_match_string(j);
2617 if (!filter)
2618 return log_oom();
2619
2620 log_debug("Journal filter: %s", filter);
2621 }
2622
2623 if (arg_action == ACTION_LIST_FIELDS)
2624 return action_list_fields(j);
2625
2626 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2627 if (arg_follow) {
2628 poll_fd = sd_journal_get_fd(j);
2629 if (poll_fd == -EMFILE) {
2630 log_warning_errno(poll_fd, "Insufficient watch descriptors available. Reverting to -n.");
2631 arg_follow = false;
2632 } else if (poll_fd == -EMEDIUMTYPE)
2633 return log_error_errno(poll_fd, "The --follow switch is not supported in conjunction with reading from STDIN.");
2634 else if (poll_fd < 0)
2635 return log_error_errno(poll_fd, "Failed to get journal fd: %m");
2636 }
2637
2638 if (arg_cursor || arg_after_cursor || arg_cursor_file) {
2639 _cleanup_free_ char *cursor_from_file = NULL;
2640 const char *cursor = arg_cursor ?: arg_after_cursor;
2641
2642 if (arg_cursor_file) {
2643 r = read_one_line_file(arg_cursor_file, &cursor_from_file);
2644 if (r < 0 && r != -ENOENT)
2645 return log_error_errno(r, "Failed to read cursor file %s: %m", arg_cursor_file);
2646
2647 if (r > 0) {
2648 cursor = cursor_from_file;
2649 after_cursor = true;
2650 }
2651 } else
2652 after_cursor = arg_after_cursor;
2653
2654 if (cursor) {
2655 r = sd_journal_seek_cursor(j, cursor);
2656 if (r < 0)
2657 return log_error_errno(r, "Failed to seek to cursor: %m");
2658
2659 use_cursor = true;
2660 }
2661 }
2662
2663 if (use_cursor) {
2664 if (!arg_reverse)
2665 r = sd_journal_next_skip(j, 1 + after_cursor);
2666 else
2667 r = sd_journal_previous_skip(j, 1 + after_cursor);
2668
2669 if (after_cursor && r < 2) {
2670 /* We couldn't find the next entry after the cursor. */
2671 if (arg_follow)
2672 need_seek = true;
2673 else
2674 arg_lines = 0;
2675 }
2676
2677 } else if (arg_until_set && (arg_reverse || arg_lines >= 0)) {
2678 /* If both --until and any of --reverse and --lines is specified, things get
2679 * a little tricky. We seek to the place of --until first. If only --reverse or
2680 * --reverse and --lines is specified, we search backwards and let the output
2681 * counter handle --lines for us. If only --lines is used, we just jump backwards
2682 * arg_lines and search afterwards from there. */
2683
2684 r = sd_journal_seek_realtime_usec(j, arg_until);
2685 if (r < 0)
2686 return log_error_errno(r, "Failed to seek to date: %m");
2687
2688 if (arg_reverse)
2689 r = sd_journal_previous(j);
2690 else /* arg_lines >= 0 */
2691 r = sd_journal_previous_skip(j, arg_lines);
2692
2693 } else if (arg_reverse) {
2694 r = sd_journal_seek_tail(j);
2695 if (r < 0)
2696 return log_error_errno(r, "Failed to seek to tail: %m");
2697
2698 r = sd_journal_previous(j);
2699
2700 } else if (arg_lines >= 0) {
2701 r = sd_journal_seek_tail(j);
2702 if (r < 0)
2703 return log_error_errno(r, "Failed to seek to tail: %m");
2704
2705 r = sd_journal_previous_skip(j, arg_lines);
2706
2707 } else if (arg_since_set) {
2708 /* This is placed after arg_reverse and arg_lines. If --since is used without
2709 * both, we seek to the place of --since and search afterwards from there.
2710 * If used with --reverse or --lines, we seek to the tail first and check if
2711 * the entry is within the range of --since later. */
2712
2713 r = sd_journal_seek_realtime_usec(j, arg_since);
2714 if (r < 0)
2715 return log_error_errno(r, "Failed to seek to date: %m");
2716 since_seeked = true;
2717
2718 r = sd_journal_next(j);
2719
2720 } else {
2721 r = sd_journal_seek_head(j);
2722 if (r < 0)
2723 return log_error_errno(r, "Failed to seek to head: %m");
2724
2725 r = sd_journal_next(j);
2726 }
2727 if (r < 0)
2728 return log_error_errno(r, "Failed to iterate through journal: %m");
2729 if (r == 0)
2730 need_seek = true;
2731
2732 if (!arg_follow)
2733 pager_open(arg_pager_flags);
2734
2735 if (!arg_quiet && (arg_lines != 0 || arg_follow) && DEBUG_LOGGING) {
2736 usec_t start, end;
2737 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
2738
2739 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
2740 if (r < 0)
2741 return log_error_errno(r, "Failed to get cutoff: %m");
2742 if (r > 0) {
2743 if (arg_follow)
2744 printf("-- Journal begins at %s. --\n",
2745 format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start));
2746 else
2747 printf("-- Journal begins at %s, ends at %s. --\n",
2748 format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start),
2749 format_timestamp_maybe_utc(end_buf, sizeof(end_buf), end));
2750 }
2751 }
2752
2753 Context c = {
2754 .journal = j,
2755 .need_seek = need_seek,
2756 .since_seeked = since_seeked,
2757 };
2758
2759 if (arg_follow) {
2760 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
2761
2762 assert(poll_fd >= 0);
2763
2764 r = setup_event(&c, poll_fd, &e);
2765 if (r < 0)
2766 return r;
2767
2768 return sd_event_loop(e);
2769 }
2770
2771 r = show(&c);
2772 if (r < 0)
2773 return r;
2774 n_shown = r;
2775
2776 if (n_shown == 0 && !arg_quiet)
2777 printf("-- No entries --\n");
2778
2779 r = update_cursor(j);
2780 if (r < 0)
2781 return r;
2782
2783 if (arg_compiled_pattern && n_shown == 0)
2784 /* --grep was used, no error was thrown, but the pattern didn't
2785 * match anything. Let's mimic grep's behavior here and return
2786 * a non-zero exit code, so journalctl --grep can be used
2787 * in scripts and such */
2788 return -ENOENT;
2789
2790 return 0;
2791 }
2792
2793 DEFINE_MAIN_FUNCTION(run);