]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/journal/journalctl.c
Merge pull request #2706 from whot/hwdb-updates
[thirdparty/systemd.git] / src / journal / journalctl.c
... / ...
CommitLineData
1/***
2 This file is part of systemd.
3
4 Copyright 2011 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
20#include <errno.h>
21#include <fcntl.h>
22#include <fnmatch.h>
23#include <getopt.h>
24#include <linux/fs.h>
25#include <locale.h>
26#include <poll.h>
27#include <signal.h>
28#include <stddef.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <sys/inotify.h>
33#include <sys/stat.h>
34#include <unistd.h>
35
36#include "sd-bus.h"
37#include "sd-journal.h"
38
39#include "acl-util.h"
40#include "alloc-util.h"
41#include "bus-error.h"
42#include "bus-util.h"
43#include "catalog.h"
44#include "chattr-util.h"
45#include "fd-util.h"
46#include "fileio.h"
47#include "fs-util.h"
48#include "fsprg.h"
49#include "glob-util.h"
50#include "hostname-util.h"
51#include "io-util.h"
52#include "journal-def.h"
53#include "journal-internal.h"
54#include "journal-qrcode.h"
55#include "journal-vacuum.h"
56#include "journal-verify.h"
57#include "locale-util.h"
58#include "log.h"
59#include "logs-show.h"
60#include "mkdir.h"
61#include "pager.h"
62#include "parse-util.h"
63#include "path-util.h"
64#include "rlimit-util.h"
65#include "set.h"
66#include "sigbus.h"
67#include "strv.h"
68#include "syslog-util.h"
69#include "terminal-util.h"
70#include "udev.h"
71#include "udev-util.h"
72#include "unit-name.h"
73#include "user-util.h"
74
75#define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
76
77enum {
78 /* Special values for arg_lines */
79 ARG_LINES_DEFAULT = -2,
80 ARG_LINES_ALL = -1,
81};
82
83static OutputMode arg_output = OUTPUT_SHORT;
84static bool arg_utc = false;
85static bool arg_pager_end = false;
86static bool arg_follow = false;
87static bool arg_full = true;
88static bool arg_all = false;
89static bool arg_no_pager = false;
90static int arg_lines = ARG_LINES_DEFAULT;
91static bool arg_no_tail = false;
92static bool arg_quiet = false;
93static bool arg_merge = false;
94static bool arg_boot = false;
95static sd_id128_t arg_boot_id = {};
96static int arg_boot_offset = 0;
97static bool arg_dmesg = false;
98static const char *arg_cursor = NULL;
99static const char *arg_after_cursor = NULL;
100static bool arg_show_cursor = false;
101static const char *arg_directory = NULL;
102static char **arg_file = NULL;
103static int arg_priorities = 0xFF;
104static const char *arg_verify_key = NULL;
105#ifdef HAVE_GCRYPT
106static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
107static bool arg_force = false;
108#endif
109static usec_t arg_since, arg_until;
110static bool arg_since_set = false, arg_until_set = false;
111static char **arg_syslog_identifier = NULL;
112static char **arg_system_units = NULL;
113static char **arg_user_units = NULL;
114static const char *arg_field = NULL;
115static bool arg_catalog = false;
116static bool arg_reverse = false;
117static int arg_journal_type = 0;
118static char *arg_root = NULL;
119static const char *arg_machine = NULL;
120static uint64_t arg_vacuum_size = 0;
121static uint64_t arg_vacuum_n_files = 0;
122static usec_t arg_vacuum_time = 0;
123
124static enum {
125 ACTION_SHOW,
126 ACTION_NEW_ID128,
127 ACTION_PRINT_HEADER,
128 ACTION_SETUP_KEYS,
129 ACTION_VERIFY,
130 ACTION_DISK_USAGE,
131 ACTION_LIST_CATALOG,
132 ACTION_DUMP_CATALOG,
133 ACTION_UPDATE_CATALOG,
134 ACTION_LIST_BOOTS,
135 ACTION_FLUSH,
136 ACTION_SYNC,
137 ACTION_ROTATE,
138 ACTION_VACUUM,
139 ACTION_LIST_FIELDS,
140 ACTION_LIST_FIELD_NAMES,
141} arg_action = ACTION_SHOW;
142
143typedef struct BootId {
144 sd_id128_t id;
145 uint64_t first;
146 uint64_t last;
147 LIST_FIELDS(struct BootId, boot_list);
148} BootId;
149
150static int add_matches_for_device(sd_journal *j, const char *devpath) {
151 int r;
152 _cleanup_udev_unref_ struct udev *udev = NULL;
153 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
154 struct udev_device *d = NULL;
155 struct stat st;
156
157 assert(j);
158 assert(devpath);
159
160 if (!path_startswith(devpath, "/dev/")) {
161 log_error("Devpath does not start with /dev/");
162 return -EINVAL;
163 }
164
165 udev = udev_new();
166 if (!udev)
167 return log_oom();
168
169 r = stat(devpath, &st);
170 if (r < 0)
171 log_error_errno(errno, "Couldn't stat file: %m");
172
173 d = device = udev_device_new_from_devnum(udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev);
174 if (!device)
175 return log_error_errno(errno, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
176
177 while (d) {
178 _cleanup_free_ char *match = NULL;
179 const char *subsys, *sysname, *devnode;
180
181 subsys = udev_device_get_subsystem(d);
182 if (!subsys) {
183 d = udev_device_get_parent(d);
184 continue;
185 }
186
187 sysname = udev_device_get_sysname(d);
188 if (!sysname) {
189 d = udev_device_get_parent(d);
190 continue;
191 }
192
193 match = strjoin("_KERNEL_DEVICE=+", subsys, ":", sysname, NULL);
194 if (!match)
195 return log_oom();
196
197 r = sd_journal_add_match(j, match, 0);
198 if (r < 0)
199 return log_error_errno(r, "Failed to add match: %m");
200
201 devnode = udev_device_get_devnode(d);
202 if (devnode) {
203 _cleanup_free_ char *match1 = NULL;
204
205 r = stat(devnode, &st);
206 if (r < 0)
207 return log_error_errno(r, "Failed to stat() device node \"%s\": %m", devnode);
208
209 r = asprintf(&match1, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st.st_mode) ? 'b' : 'c', major(st.st_rdev), minor(st.st_rdev));
210 if (r < 0)
211 return log_oom();
212
213 r = sd_journal_add_match(j, match1, 0);
214 if (r < 0)
215 return log_error_errno(r, "Failed to add match: %m");
216 }
217
218 d = udev_device_get_parent(d);
219 }
220
221 r = add_match_this_boot(j, arg_machine);
222 if (r < 0)
223 return log_error_errno(r, "Failed to add match for the current boot: %m");
224
225 return 0;
226}
227
228static void pager_open_if_enabled(void) {
229
230 if (arg_no_pager)
231 return;
232
233 pager_open(arg_pager_end);
234}
235
236static char *format_timestamp_maybe_utc(char *buf, size_t l, usec_t t) {
237
238 if (arg_utc)
239 return format_timestamp_utc(buf, l, t);
240
241 return format_timestamp(buf, l, t);
242}
243
244static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset) {
245 sd_id128_t id = SD_ID128_NULL;
246 int off = 0, r;
247
248 if (strlen(x) >= 32) {
249 char *t;
250
251 t = strndupa(x, 32);
252 r = sd_id128_from_string(t, &id);
253 if (r >= 0)
254 x += 32;
255
256 if (*x != '-' && *x != '+' && *x != 0)
257 return -EINVAL;
258
259 if (*x != 0) {
260 r = safe_atoi(x, &off);
261 if (r < 0)
262 return r;
263 }
264 } else {
265 r = safe_atoi(x, &off);
266 if (r < 0)
267 return r;
268 }
269
270 if (boot_id)
271 *boot_id = id;
272
273 if (offset)
274 *offset = off;
275
276 return 0;
277}
278
279static void help(void) {
280
281 pager_open_if_enabled();
282
283 printf("%s [OPTIONS...] [MATCHES...]\n\n"
284 "Query the journal.\n\n"
285 "Options:\n"
286 " --system Show the system journal\n"
287 " --user Show the user journal for the current user\n"
288 " -M --machine=CONTAINER Operate on local container\n"
289 " -S --since=DATE Show entries not older than the specified date\n"
290 " -U --until=DATE Show entries not newer than the specified date\n"
291 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
292 " --after-cursor=CURSOR Show entries after the specified cursor\n"
293 " --show-cursor Print the cursor after all the entries\n"
294 " -b --boot[=ID] Show current boot or the specified boot\n"
295 " --list-boots Show terse information about recorded boots\n"
296 " -k --dmesg Show kernel message log from the current boot\n"
297 " -u --unit=UNIT Show logs from the specified unit\n"
298 " --user-unit=UNIT Show logs from the specified user unit\n"
299 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
300 " -p --priority=RANGE Show entries with the specified priority\n"
301 " -e --pager-end Immediately jump to the end in the pager\n"
302 " -f --follow Follow the journal\n"
303 " -n --lines[=INTEGER] Number of journal entries to show\n"
304 " --no-tail Show all lines, even in follow mode\n"
305 " -r --reverse Show the newest entries first\n"
306 " -o --output=STRING Change journal output mode (short, short-iso,\n"
307 " short-precise, short-monotonic, verbose,\n"
308 " export, json, json-pretty, json-sse, cat)\n"
309 " --utc Express time in Coordinated Universal Time (UTC)\n"
310 " -x --catalog Add message explanations where available\n"
311 " --no-full Ellipsize fields\n"
312 " -a --all Show all fields, including long and unprintable\n"
313 " -q --quiet Do not show info messages and privilege warning\n"
314 " --no-pager Do not pipe output into a pager\n"
315 " -m --merge Show entries from all available journals\n"
316 " -D --directory=PATH Show journal files from directory\n"
317 " --file=PATH Show journal file\n"
318 " --root=ROOT Operate on catalog files below a root directory\n"
319#ifdef HAVE_GCRYPT
320 " --interval=TIME Time interval for changing the FSS sealing key\n"
321 " --verify-key=KEY Specify FSS verification key\n"
322 " --force Override of the FSS key pair with --setup-keys\n"
323#endif
324 "\nCommands:\n"
325 " -h --help Show this help text\n"
326 " --version Show package version\n"
327 " -N --fields List all field names currently used\n"
328 " -F --field=FIELD List all values that a specified field takes\n"
329 " --disk-usage Show total disk usage of all journal files\n"
330 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
331 " --vacuum-files=INT Leave only the specified number of journal files\n"
332 " --vacuum-time=TIME Remove journal files older than specified time\n"
333 " --verify Verify journal file consistency\n"
334 " --sync Synchronize unwritten journal messages to disk\n"
335 " --flush Flush all journal data from /run into /var\n"
336 " --rotate Request immediate rotation of the journal files\n"
337 " --header Show journal header information\n"
338 " --list-catalog Show all message IDs in the catalog\n"
339 " --dump-catalog Show entries in the message catalog\n"
340 " --update-catalog Update the message catalog database\n"
341 " --new-id128 Generate a new 128-bit ID\n"
342#ifdef HAVE_GCRYPT
343 " --setup-keys Generate a new FSS key pair\n"
344#endif
345 , program_invocation_short_name);
346}
347
348static int parse_argv(int argc, char *argv[]) {
349
350 enum {
351 ARG_VERSION = 0x100,
352 ARG_NO_PAGER,
353 ARG_NO_FULL,
354 ARG_NO_TAIL,
355 ARG_NEW_ID128,
356 ARG_LIST_BOOTS,
357 ARG_USER,
358 ARG_SYSTEM,
359 ARG_ROOT,
360 ARG_HEADER,
361 ARG_SETUP_KEYS,
362 ARG_FILE,
363 ARG_INTERVAL,
364 ARG_VERIFY,
365 ARG_VERIFY_KEY,
366 ARG_DISK_USAGE,
367 ARG_AFTER_CURSOR,
368 ARG_SHOW_CURSOR,
369 ARG_USER_UNIT,
370 ARG_LIST_CATALOG,
371 ARG_DUMP_CATALOG,
372 ARG_UPDATE_CATALOG,
373 ARG_FORCE,
374 ARG_UTC,
375 ARG_SYNC,
376 ARG_FLUSH,
377 ARG_ROTATE,
378 ARG_VACUUM_SIZE,
379 ARG_VACUUM_FILES,
380 ARG_VACUUM_TIME,
381 };
382
383 static const struct option options[] = {
384 { "help", no_argument, NULL, 'h' },
385 { "version" , no_argument, NULL, ARG_VERSION },
386 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
387 { "pager-end", no_argument, NULL, 'e' },
388 { "follow", no_argument, NULL, 'f' },
389 { "force", no_argument, NULL, ARG_FORCE },
390 { "output", required_argument, NULL, 'o' },
391 { "all", no_argument, NULL, 'a' },
392 { "full", no_argument, NULL, 'l' },
393 { "no-full", no_argument, NULL, ARG_NO_FULL },
394 { "lines", optional_argument, NULL, 'n' },
395 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
396 { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
397 { "quiet", no_argument, NULL, 'q' },
398 { "merge", no_argument, NULL, 'm' },
399 { "boot", optional_argument, NULL, 'b' },
400 { "list-boots", no_argument, NULL, ARG_LIST_BOOTS },
401 { "this-boot", optional_argument, NULL, 'b' }, /* deprecated */
402 { "dmesg", no_argument, NULL, 'k' },
403 { "system", no_argument, NULL, ARG_SYSTEM },
404 { "user", no_argument, NULL, ARG_USER },
405 { "directory", required_argument, NULL, 'D' },
406 { "file", required_argument, NULL, ARG_FILE },
407 { "root", required_argument, NULL, ARG_ROOT },
408 { "header", no_argument, NULL, ARG_HEADER },
409 { "identifier", required_argument, NULL, 't' },
410 { "priority", required_argument, NULL, 'p' },
411 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
412 { "interval", required_argument, NULL, ARG_INTERVAL },
413 { "verify", no_argument, NULL, ARG_VERIFY },
414 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
415 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
416 { "cursor", required_argument, NULL, 'c' },
417 { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR },
418 { "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR },
419 { "since", required_argument, NULL, 'S' },
420 { "until", required_argument, NULL, 'U' },
421 { "unit", required_argument, NULL, 'u' },
422 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
423 { "field", required_argument, NULL, 'F' },
424 { "fields", no_argument, NULL, 'N' },
425 { "catalog", no_argument, NULL, 'x' },
426 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
427 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
428 { "update-catalog", no_argument, NULL, ARG_UPDATE_CATALOG },
429 { "reverse", no_argument, NULL, 'r' },
430 { "machine", required_argument, NULL, 'M' },
431 { "utc", no_argument, NULL, ARG_UTC },
432 { "flush", no_argument, NULL, ARG_FLUSH },
433 { "sync", no_argument, NULL, ARG_SYNC },
434 { "rotate", no_argument, NULL, ARG_ROTATE },
435 { "vacuum-size", required_argument, NULL, ARG_VACUUM_SIZE },
436 { "vacuum-files", required_argument, NULL, ARG_VACUUM_FILES },
437 { "vacuum-time", required_argument, NULL, ARG_VACUUM_TIME },
438 {}
439 };
440
441 int c, r;
442
443 assert(argc >= 0);
444 assert(argv);
445
446 while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:S:U:t:u:NF:xrM:", options, NULL)) >= 0)
447
448 switch (c) {
449
450 case 'h':
451 help();
452 return 0;
453
454 case ARG_VERSION:
455 return version();
456
457 case ARG_NO_PAGER:
458 arg_no_pager = true;
459 break;
460
461 case 'e':
462 arg_pager_end = true;
463
464 if (arg_lines == ARG_LINES_DEFAULT)
465 arg_lines = 1000;
466
467 break;
468
469 case 'f':
470 arg_follow = true;
471 break;
472
473 case 'o':
474 arg_output = output_mode_from_string(optarg);
475 if (arg_output < 0) {
476 log_error("Unknown output format '%s'.", optarg);
477 return -EINVAL;
478 }
479
480 if (arg_output == OUTPUT_EXPORT ||
481 arg_output == OUTPUT_JSON ||
482 arg_output == OUTPUT_JSON_PRETTY ||
483 arg_output == OUTPUT_JSON_SSE ||
484 arg_output == OUTPUT_CAT)
485 arg_quiet = true;
486
487 break;
488
489 case 'l':
490 arg_full = true;
491 break;
492
493 case ARG_NO_FULL:
494 arg_full = false;
495 break;
496
497 case 'a':
498 arg_all = true;
499 break;
500
501 case 'n':
502 if (optarg) {
503 if (streq(optarg, "all"))
504 arg_lines = ARG_LINES_ALL;
505 else {
506 r = safe_atoi(optarg, &arg_lines);
507 if (r < 0 || arg_lines < 0) {
508 log_error("Failed to parse lines '%s'", optarg);
509 return -EINVAL;
510 }
511 }
512 } else {
513 arg_lines = 10;
514
515 /* Hmm, no argument? Maybe the next
516 * word on the command line is
517 * supposed to be the argument? Let's
518 * see if there is one, and is
519 * parsable. */
520 if (optind < argc) {
521 int n;
522 if (streq(argv[optind], "all")) {
523 arg_lines = ARG_LINES_ALL;
524 optind++;
525 } else if (safe_atoi(argv[optind], &n) >= 0 && n >= 0) {
526 arg_lines = n;
527 optind++;
528 }
529 }
530 }
531
532 break;
533
534 case ARG_NO_TAIL:
535 arg_no_tail = true;
536 break;
537
538 case ARG_NEW_ID128:
539 arg_action = ACTION_NEW_ID128;
540 break;
541
542 case 'q':
543 arg_quiet = true;
544 break;
545
546 case 'm':
547 arg_merge = true;
548 break;
549
550 case 'b':
551 arg_boot = true;
552
553 if (optarg) {
554 r = parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset);
555 if (r < 0) {
556 log_error("Failed to parse boot descriptor '%s'", optarg);
557 return -EINVAL;
558 }
559 } else {
560
561 /* Hmm, no argument? Maybe the next
562 * word on the command line is
563 * supposed to be the argument? Let's
564 * see if there is one and is parsable
565 * as a boot descriptor... */
566
567 if (optind < argc &&
568 parse_boot_descriptor(argv[optind], &arg_boot_id, &arg_boot_offset) >= 0)
569 optind++;
570 }
571
572 break;
573
574 case ARG_LIST_BOOTS:
575 arg_action = ACTION_LIST_BOOTS;
576 break;
577
578 case 'k':
579 arg_boot = arg_dmesg = true;
580 break;
581
582 case ARG_SYSTEM:
583 arg_journal_type |= SD_JOURNAL_SYSTEM;
584 break;
585
586 case ARG_USER:
587 arg_journal_type |= SD_JOURNAL_CURRENT_USER;
588 break;
589
590 case 'M':
591 arg_machine = optarg;
592 break;
593
594 case 'D':
595 arg_directory = optarg;
596 break;
597
598 case ARG_FILE:
599 r = glob_extend(&arg_file, optarg);
600 if (r < 0)
601 return log_error_errno(r, "Failed to add paths: %m");
602 break;
603
604 case ARG_ROOT:
605 r = parse_path_argument_and_warn(optarg, true, &arg_root);
606 if (r < 0)
607 return r;
608 break;
609
610 case 'c':
611 arg_cursor = optarg;
612 break;
613
614 case ARG_AFTER_CURSOR:
615 arg_after_cursor = optarg;
616 break;
617
618 case ARG_SHOW_CURSOR:
619 arg_show_cursor = true;
620 break;
621
622 case ARG_HEADER:
623 arg_action = ACTION_PRINT_HEADER;
624 break;
625
626 case ARG_VERIFY:
627 arg_action = ACTION_VERIFY;
628 break;
629
630 case ARG_DISK_USAGE:
631 arg_action = ACTION_DISK_USAGE;
632 break;
633
634 case ARG_VACUUM_SIZE:
635 r = parse_size(optarg, 1024, &arg_vacuum_size);
636 if (r < 0) {
637 log_error("Failed to parse vacuum size: %s", optarg);
638 return r;
639 }
640
641 arg_action = ACTION_VACUUM;
642 break;
643
644 case ARG_VACUUM_FILES:
645 r = safe_atou64(optarg, &arg_vacuum_n_files);
646 if (r < 0) {
647 log_error("Failed to parse vacuum files: %s", optarg);
648 return r;
649 }
650
651 arg_action = ACTION_VACUUM;
652 break;
653
654 case ARG_VACUUM_TIME:
655 r = parse_sec(optarg, &arg_vacuum_time);
656 if (r < 0) {
657 log_error("Failed to parse vacuum time: %s", optarg);
658 return r;
659 }
660
661 arg_action = ACTION_VACUUM;
662 break;
663
664#ifdef HAVE_GCRYPT
665 case ARG_FORCE:
666 arg_force = true;
667 break;
668
669 case ARG_SETUP_KEYS:
670 arg_action = ACTION_SETUP_KEYS;
671 break;
672
673
674 case ARG_VERIFY_KEY:
675 arg_action = ACTION_VERIFY;
676 arg_verify_key = optarg;
677 arg_merge = false;
678 break;
679
680 case ARG_INTERVAL:
681 r = parse_sec(optarg, &arg_interval);
682 if (r < 0 || arg_interval <= 0) {
683 log_error("Failed to parse sealing key change interval: %s", optarg);
684 return -EINVAL;
685 }
686 break;
687#else
688 case ARG_SETUP_KEYS:
689 case ARG_VERIFY_KEY:
690 case ARG_INTERVAL:
691 case ARG_FORCE:
692 log_error("Forward-secure sealing not available.");
693 return -EOPNOTSUPP;
694#endif
695
696 case 'p': {
697 const char *dots;
698
699 dots = strstr(optarg, "..");
700 if (dots) {
701 char *a;
702 int from, to, i;
703
704 /* a range */
705 a = strndup(optarg, dots - optarg);
706 if (!a)
707 return log_oom();
708
709 from = log_level_from_string(a);
710 to = log_level_from_string(dots + 2);
711 free(a);
712
713 if (from < 0 || to < 0) {
714 log_error("Failed to parse log level range %s", optarg);
715 return -EINVAL;
716 }
717
718 arg_priorities = 0;
719
720 if (from < to) {
721 for (i = from; i <= to; i++)
722 arg_priorities |= 1 << i;
723 } else {
724 for (i = to; i <= from; i++)
725 arg_priorities |= 1 << i;
726 }
727
728 } else {
729 int p, i;
730
731 p = log_level_from_string(optarg);
732 if (p < 0) {
733 log_error("Unknown log level %s", optarg);
734 return -EINVAL;
735 }
736
737 arg_priorities = 0;
738
739 for (i = 0; i <= p; i++)
740 arg_priorities |= 1 << i;
741 }
742
743 break;
744 }
745
746 case 'S':
747 r = parse_timestamp(optarg, &arg_since);
748 if (r < 0) {
749 log_error("Failed to parse timestamp: %s", optarg);
750 return -EINVAL;
751 }
752 arg_since_set = true;
753 break;
754
755 case 'U':
756 r = parse_timestamp(optarg, &arg_until);
757 if (r < 0) {
758 log_error("Failed to parse timestamp: %s", optarg);
759 return -EINVAL;
760 }
761 arg_until_set = true;
762 break;
763
764 case 't':
765 r = strv_extend(&arg_syslog_identifier, optarg);
766 if (r < 0)
767 return log_oom();
768 break;
769
770 case 'u':
771 r = strv_extend(&arg_system_units, optarg);
772 if (r < 0)
773 return log_oom();
774 break;
775
776 case ARG_USER_UNIT:
777 r = strv_extend(&arg_user_units, optarg);
778 if (r < 0)
779 return log_oom();
780 break;
781
782 case 'F':
783 arg_action = ACTION_LIST_FIELDS;
784 arg_field = optarg;
785 break;
786
787 case 'N':
788 arg_action = ACTION_LIST_FIELD_NAMES;
789 break;
790
791 case 'x':
792 arg_catalog = true;
793 break;
794
795 case ARG_LIST_CATALOG:
796 arg_action = ACTION_LIST_CATALOG;
797 break;
798
799 case ARG_DUMP_CATALOG:
800 arg_action = ACTION_DUMP_CATALOG;
801 break;
802
803 case ARG_UPDATE_CATALOG:
804 arg_action = ACTION_UPDATE_CATALOG;
805 break;
806
807 case 'r':
808 arg_reverse = true;
809 break;
810
811 case ARG_UTC:
812 arg_utc = true;
813 break;
814
815 case ARG_FLUSH:
816 arg_action = ACTION_FLUSH;
817 break;
818
819 case ARG_ROTATE:
820 arg_action = ACTION_ROTATE;
821 break;
822
823 case ARG_SYNC:
824 arg_action = ACTION_SYNC;
825 break;
826
827 case '?':
828 return -EINVAL;
829
830 default:
831 assert_not_reached("Unhandled option");
832 }
833
834 if (arg_follow && !arg_no_tail && !arg_since && arg_lines == ARG_LINES_DEFAULT)
835 arg_lines = 10;
836
837 if (!!arg_directory + !!arg_file + !!arg_machine > 1) {
838 log_error("Please specify either -D/--directory= or --file= or -M/--machine=, not more than one.");
839 return -EINVAL;
840 }
841
842 if (arg_since_set && arg_until_set && arg_since > arg_until) {
843 log_error("--since= must be before --until=.");
844 return -EINVAL;
845 }
846
847 if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1) {
848 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
849 return -EINVAL;
850 }
851
852 if (arg_follow && arg_reverse) {
853 log_error("Please specify either --reverse= or --follow=, not both.");
854 return -EINVAL;
855 }
856
857 if (!IN_SET(arg_action, ACTION_SHOW, ACTION_DUMP_CATALOG, ACTION_LIST_CATALOG) && optind < argc) {
858 log_error("Extraneous arguments starting with '%s'", argv[optind]);
859 return -EINVAL;
860 }
861
862 if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && (arg_file || arg_directory || arg_merge)) {
863 log_error("Using --boot or --list-boots with --file, --directory or --merge is not supported.");
864 return -EINVAL;
865 }
866
867 return 1;
868}
869
870static int generate_new_id128(void) {
871 sd_id128_t id;
872 int r;
873 unsigned i;
874
875 r = sd_id128_randomize(&id);
876 if (r < 0)
877 return log_error_errno(r, "Failed to generate ID: %m");
878
879 printf("As string:\n"
880 SD_ID128_FORMAT_STR "\n\n"
881 "As UUID:\n"
882 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
883 "As macro:\n"
884 "#define MESSAGE_XYZ SD_ID128_MAKE(",
885 SD_ID128_FORMAT_VAL(id),
886 SD_ID128_FORMAT_VAL(id));
887 for (i = 0; i < 16; i++)
888 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
889 fputs(")\n\n", stdout);
890
891 printf("As Python constant:\n"
892 ">>> import uuid\n"
893 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
894 SD_ID128_FORMAT_VAL(id));
895
896 return 0;
897}
898
899static int add_matches(sd_journal *j, char **args) {
900 char **i;
901 bool have_term = false;
902
903 assert(j);
904
905 STRV_FOREACH(i, args) {
906 int r;
907
908 if (streq(*i, "+")) {
909 if (!have_term)
910 break;
911 r = sd_journal_add_disjunction(j);
912 have_term = false;
913
914 } else if (path_is_absolute(*i)) {
915 _cleanup_free_ char *p, *t = NULL, *t2 = NULL, *interpreter = NULL;
916 const char *path;
917 struct stat st;
918
919 p = canonicalize_file_name(*i);
920 path = p ?: *i;
921
922 if (lstat(path, &st) < 0)
923 return log_error_errno(errno, "Couldn't stat file: %m");
924
925 if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
926 if (executable_is_script(path, &interpreter) > 0) {
927 _cleanup_free_ char *comm;
928
929 comm = strndup(basename(path), 15);
930 if (!comm)
931 return log_oom();
932
933 t = strappend("_COMM=", comm);
934 if (!t)
935 return log_oom();
936
937 /* Append _EXE only if the interpreter is not a link.
938 Otherwise, it might be outdated often. */
939 if (lstat(interpreter, &st) == 0 && !S_ISLNK(st.st_mode)) {
940 t2 = strappend("_EXE=", interpreter);
941 if (!t2)
942 return log_oom();
943 }
944 } else {
945 t = strappend("_EXE=", path);
946 if (!t)
947 return log_oom();
948 }
949
950 r = sd_journal_add_match(j, t, 0);
951
952 if (r >=0 && t2)
953 r = sd_journal_add_match(j, t2, 0);
954
955 } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
956 r = add_matches_for_device(j, path);
957 if (r < 0)
958 return r;
959 } else {
960 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
961 return -EINVAL;
962 }
963
964 have_term = true;
965 } else {
966 r = sd_journal_add_match(j, *i, 0);
967 have_term = true;
968 }
969
970 if (r < 0)
971 return log_error_errno(r, "Failed to add match '%s': %m", *i);
972 }
973
974 if (!strv_isempty(args) && !have_term) {
975 log_error("\"+\" can only be used between terms");
976 return -EINVAL;
977 }
978
979 return 0;
980}
981
982static void boot_id_free_all(BootId *l) {
983
984 while (l) {
985 BootId *i = l;
986 LIST_REMOVE(boot_list, l, i);
987 free(i);
988 }
989}
990
991static int discover_next_boot(
992 sd_journal *j,
993 BootId **boot,
994 bool advance_older,
995 bool read_realtime) {
996
997 int r;
998 char match[9+32+1] = "_BOOT_ID=";
999 _cleanup_free_ BootId *next_boot = NULL;
1000
1001 assert(j);
1002 assert(boot);
1003
1004 /* We expect the journal to be on the last position of a boot
1005 * (in relation to the direction we are going), so that the next
1006 * invocation of sd_journal_next/previous will be from a different
1007 * boot. We then collect any information we desire and then jump
1008 * to the last location of the new boot by using a _BOOT_ID match
1009 * coming from the other journal direction. */
1010
1011 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1012 * we can actually advance to a *different* boot. */
1013 sd_journal_flush_matches(j);
1014
1015 if (advance_older)
1016 r = sd_journal_previous(j);
1017 else
1018 r = sd_journal_next(j);
1019 if (r < 0)
1020 return r;
1021 else if (r == 0)
1022 return 0; /* End of journal, yay. */
1023
1024 next_boot = new0(BootId, 1);
1025 if (!next_boot)
1026 return -ENOMEM;
1027
1028 r = sd_journal_get_monotonic_usec(j, NULL, &next_boot->id);
1029 if (r < 0)
1030 return r;
1031
1032 if (read_realtime) {
1033 r = sd_journal_get_realtime_usec(j, &next_boot->first);
1034 if (r < 0)
1035 return r;
1036 }
1037
1038 /* Now seek to the last occurrence of this boot ID. */
1039 sd_id128_to_string(next_boot->id, match + 9);
1040 r = sd_journal_add_match(j, match, sizeof(match) - 1);
1041 if (r < 0)
1042 return r;
1043
1044 if (advance_older)
1045 r = sd_journal_seek_head(j);
1046 else
1047 r = sd_journal_seek_tail(j);
1048 if (r < 0)
1049 return r;
1050
1051 if (advance_older)
1052 r = sd_journal_next(j);
1053 else
1054 r = sd_journal_previous(j);
1055 if (r < 0)
1056 return r;
1057 else if (r == 0)
1058 return -ENODATA; /* This shouldn't happen. We just came from this very boot ID. */
1059
1060 if (read_realtime) {
1061 r = sd_journal_get_realtime_usec(j, &next_boot->last);
1062 if (r < 0)
1063 return r;
1064 }
1065
1066 *boot = next_boot;
1067 next_boot = NULL;
1068
1069 return 0;
1070}
1071
1072static int get_boots(
1073 sd_journal *j,
1074 BootId **boots,
1075 BootId *query_ref_boot,
1076 int ref_boot_offset) {
1077
1078 bool skip_once;
1079 int r, count = 0;
1080 BootId *head = NULL, *tail = NULL;
1081 const bool advance_older = query_ref_boot && ref_boot_offset <= 0;
1082
1083 assert(j);
1084
1085 /* Adjust for the asymmetry that offset 0 is
1086 * the last (and current) boot, while 1 is considered the
1087 * (chronological) first boot in the journal. */
1088 skip_once = query_ref_boot && sd_id128_is_null(query_ref_boot->id) && ref_boot_offset < 0;
1089
1090 /* Advance to the earliest/latest occurrence of our reference
1091 * boot ID (taking our lookup direction into account), so that
1092 * discover_next_boot() can do its job.
1093 * If no reference is given, the journal head/tail will do,
1094 * they're "virtual" boots after all. */
1095 if (query_ref_boot && !sd_id128_is_null(query_ref_boot->id)) {
1096 char match[9+32+1] = "_BOOT_ID=";
1097
1098 sd_journal_flush_matches(j);
1099
1100 sd_id128_to_string(query_ref_boot->id, match + 9);
1101 r = sd_journal_add_match(j, match, sizeof(match) - 1);
1102 if (r < 0)
1103 return r;
1104
1105 if (advance_older)
1106 r = sd_journal_seek_head(j);
1107 else
1108 r = sd_journal_seek_tail(j);
1109 if (r < 0)
1110 return r;
1111
1112 if (advance_older)
1113 r = sd_journal_next(j);
1114 else
1115 r = sd_journal_previous(j);
1116 if (r < 0)
1117 return r;
1118 else if (r == 0)
1119 goto finish;
1120 else if (ref_boot_offset == 0) {
1121 count = 1;
1122 goto finish;
1123 }
1124 } else {
1125 if (advance_older)
1126 r = sd_journal_seek_tail(j);
1127 else
1128 r = sd_journal_seek_head(j);
1129 if (r < 0)
1130 return r;
1131
1132 /* No sd_journal_next/previous here. */
1133 }
1134
1135 for (;;) {
1136 _cleanup_free_ BootId *current = NULL;
1137
1138 r = discover_next_boot(j, &current, advance_older, !query_ref_boot);
1139 if (r < 0) {
1140 boot_id_free_all(head);
1141 return r;
1142 }
1143
1144 if (!current)
1145 break;
1146
1147 if (query_ref_boot) {
1148 if (!skip_once)
1149 ref_boot_offset += advance_older ? 1 : -1;
1150 skip_once = false;
1151
1152 if (ref_boot_offset == 0) {
1153 count = 1;
1154 query_ref_boot->id = current->id;
1155 break;
1156 }
1157 } else {
1158 LIST_INSERT_AFTER(boot_list, head, tail, current);
1159 tail = current;
1160 current = NULL;
1161 count++;
1162 }
1163 }
1164
1165finish:
1166 if (boots)
1167 *boots = head;
1168
1169 sd_journal_flush_matches(j);
1170
1171 return count;
1172}
1173
1174static int list_boots(sd_journal *j) {
1175 int w, i, count;
1176 BootId *id, *all_ids;
1177
1178 assert(j);
1179
1180 count = get_boots(j, &all_ids, NULL, 0);
1181 if (count < 0)
1182 return log_error_errno(count, "Failed to determine boots: %m");
1183 if (count == 0)
1184 return count;
1185
1186 pager_open_if_enabled();
1187
1188 /* numbers are one less, but we need an extra char for the sign */
1189 w = DECIMAL_STR_WIDTH(count - 1) + 1;
1190
1191 i = 0;
1192 LIST_FOREACH(boot_list, id, all_ids) {
1193 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
1194
1195 printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
1196 w, i - count + 1,
1197 SD_ID128_FORMAT_VAL(id->id),
1198 format_timestamp_maybe_utc(a, sizeof(a), id->first),
1199 format_timestamp_maybe_utc(b, sizeof(b), id->last));
1200 i++;
1201 }
1202
1203 boot_id_free_all(all_ids);
1204
1205 return 0;
1206}
1207
1208static int add_boot(sd_journal *j) {
1209 char match[9+32+1] = "_BOOT_ID=";
1210 int r;
1211 BootId ref_boot_id = {};
1212
1213 assert(j);
1214
1215 if (!arg_boot)
1216 return 0;
1217
1218 if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL))
1219 return add_match_this_boot(j, arg_machine);
1220
1221 ref_boot_id.id = arg_boot_id;
1222 r = get_boots(j, NULL, &ref_boot_id, arg_boot_offset);
1223 assert(r <= 1);
1224 if (r <= 0) {
1225 const char *reason = (r == 0) ? "No such boot ID in journal" : strerror(-r);
1226
1227 if (sd_id128_is_null(arg_boot_id))
1228 log_error("Data from the specified boot (%+i) is not available: %s",
1229 arg_boot_offset, reason);
1230 else
1231 log_error("Data from the specified boot ("SD_ID128_FORMAT_STR") is not available: %s",
1232 SD_ID128_FORMAT_VAL(arg_boot_id), reason);
1233
1234 return r == 0 ? -ENODATA : r;
1235 }
1236
1237 sd_id128_to_string(ref_boot_id.id, match + 9);
1238
1239 r = sd_journal_add_match(j, match, sizeof(match) - 1);
1240 if (r < 0)
1241 return log_error_errno(r, "Failed to add match: %m");
1242
1243 r = sd_journal_add_conjunction(j);
1244 if (r < 0)
1245 return log_error_errno(r, "Failed to add conjunction: %m");
1246
1247 return 0;
1248}
1249
1250static int add_dmesg(sd_journal *j) {
1251 int r;
1252 assert(j);
1253
1254 if (!arg_dmesg)
1255 return 0;
1256
1257 r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
1258 if (r < 0)
1259 return log_error_errno(r, "Failed to add match: %m");
1260
1261 r = sd_journal_add_conjunction(j);
1262 if (r < 0)
1263 return log_error_errno(r, "Failed to add conjunction: %m");
1264
1265 return 0;
1266}
1267
1268static int get_possible_units(
1269 sd_journal *j,
1270 const char *fields,
1271 char **patterns,
1272 Set **units) {
1273
1274 _cleanup_set_free_free_ Set *found;
1275 const char *field;
1276 int r;
1277
1278 found = set_new(&string_hash_ops);
1279 if (!found)
1280 return -ENOMEM;
1281
1282 NULSTR_FOREACH(field, fields) {
1283 const void *data;
1284 size_t size;
1285
1286 r = sd_journal_query_unique(j, field);
1287 if (r < 0)
1288 return r;
1289
1290 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1291 char **pattern, *eq;
1292 size_t prefix;
1293 _cleanup_free_ char *u = NULL;
1294
1295 eq = memchr(data, '=', size);
1296 if (eq)
1297 prefix = eq - (char*) data + 1;
1298 else
1299 prefix = 0;
1300
1301 u = strndup((char*) data + prefix, size - prefix);
1302 if (!u)
1303 return -ENOMEM;
1304
1305 STRV_FOREACH(pattern, patterns)
1306 if (fnmatch(*pattern, u, FNM_NOESCAPE) == 0) {
1307 log_debug("Matched %s with pattern %s=%s", u, field, *pattern);
1308
1309 r = set_consume(found, u);
1310 u = NULL;
1311 if (r < 0 && r != -EEXIST)
1312 return r;
1313
1314 break;
1315 }
1316 }
1317 }
1318
1319 *units = found;
1320 found = NULL;
1321 return 0;
1322}
1323
1324/* This list is supposed to return the superset of unit names
1325 * possibly matched by rules added with add_matches_for_unit... */
1326#define SYSTEM_UNITS \
1327 "_SYSTEMD_UNIT\0" \
1328 "COREDUMP_UNIT\0" \
1329 "UNIT\0" \
1330 "OBJECT_SYSTEMD_UNIT\0" \
1331 "_SYSTEMD_SLICE\0"
1332
1333/* ... and add_matches_for_user_unit */
1334#define USER_UNITS \
1335 "_SYSTEMD_USER_UNIT\0" \
1336 "USER_UNIT\0" \
1337 "COREDUMP_USER_UNIT\0" \
1338 "OBJECT_SYSTEMD_USER_UNIT\0"
1339
1340static int add_units(sd_journal *j) {
1341 _cleanup_strv_free_ char **patterns = NULL;
1342 int r, count = 0;
1343 char **i;
1344
1345 assert(j);
1346
1347 STRV_FOREACH(i, arg_system_units) {
1348 _cleanup_free_ char *u = NULL;
1349
1350 r = unit_name_mangle(*i, UNIT_NAME_GLOB, &u);
1351 if (r < 0)
1352 return r;
1353
1354 if (string_is_glob(u)) {
1355 r = strv_push(&patterns, u);
1356 if (r < 0)
1357 return r;
1358 u = NULL;
1359 } else {
1360 r = add_matches_for_unit(j, u);
1361 if (r < 0)
1362 return r;
1363 r = sd_journal_add_disjunction(j);
1364 if (r < 0)
1365 return r;
1366 count ++;
1367 }
1368 }
1369
1370 if (!strv_isempty(patterns)) {
1371 _cleanup_set_free_free_ Set *units = NULL;
1372 Iterator it;
1373 char *u;
1374
1375 r = get_possible_units(j, SYSTEM_UNITS, patterns, &units);
1376 if (r < 0)
1377 return r;
1378
1379 SET_FOREACH(u, units, it) {
1380 r = add_matches_for_unit(j, u);
1381 if (r < 0)
1382 return r;
1383 r = sd_journal_add_disjunction(j);
1384 if (r < 0)
1385 return r;
1386 count ++;
1387 }
1388 }
1389
1390 patterns = strv_free(patterns);
1391
1392 STRV_FOREACH(i, arg_user_units) {
1393 _cleanup_free_ char *u = NULL;
1394
1395 r = unit_name_mangle(*i, UNIT_NAME_GLOB, &u);
1396 if (r < 0)
1397 return r;
1398
1399 if (string_is_glob(u)) {
1400 r = strv_push(&patterns, u);
1401 if (r < 0)
1402 return r;
1403 u = NULL;
1404 } else {
1405 r = add_matches_for_user_unit(j, u, getuid());
1406 if (r < 0)
1407 return r;
1408 r = sd_journal_add_disjunction(j);
1409 if (r < 0)
1410 return r;
1411 count ++;
1412 }
1413 }
1414
1415 if (!strv_isempty(patterns)) {
1416 _cleanup_set_free_free_ Set *units = NULL;
1417 Iterator it;
1418 char *u;
1419
1420 r = get_possible_units(j, USER_UNITS, patterns, &units);
1421 if (r < 0)
1422 return r;
1423
1424 SET_FOREACH(u, units, it) {
1425 r = add_matches_for_user_unit(j, u, getuid());
1426 if (r < 0)
1427 return r;
1428 r = sd_journal_add_disjunction(j);
1429 if (r < 0)
1430 return r;
1431 count ++;
1432 }
1433 }
1434
1435 /* Complain if the user request matches but nothing whatsoever was
1436 * found, since otherwise everything would be matched. */
1437 if (!(strv_isempty(arg_system_units) && strv_isempty(arg_user_units)) && count == 0)
1438 return -ENODATA;
1439
1440 r = sd_journal_add_conjunction(j);
1441 if (r < 0)
1442 return r;
1443
1444 return 0;
1445}
1446
1447static int add_priorities(sd_journal *j) {
1448 char match[] = "PRIORITY=0";
1449 int i, r;
1450 assert(j);
1451
1452 if (arg_priorities == 0xFF)
1453 return 0;
1454
1455 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
1456 if (arg_priorities & (1 << i)) {
1457 match[sizeof(match)-2] = '0' + i;
1458
1459 r = sd_journal_add_match(j, match, strlen(match));
1460 if (r < 0)
1461 return log_error_errno(r, "Failed to add match: %m");
1462 }
1463
1464 r = sd_journal_add_conjunction(j);
1465 if (r < 0)
1466 return log_error_errno(r, "Failed to add conjunction: %m");
1467
1468 return 0;
1469}
1470
1471
1472static int add_syslog_identifier(sd_journal *j) {
1473 int r;
1474 char **i;
1475
1476 assert(j);
1477
1478 STRV_FOREACH(i, arg_syslog_identifier) {
1479 char *u;
1480
1481 u = strjoina("SYSLOG_IDENTIFIER=", *i);
1482 r = sd_journal_add_match(j, u, 0);
1483 if (r < 0)
1484 return r;
1485 r = sd_journal_add_disjunction(j);
1486 if (r < 0)
1487 return r;
1488 }
1489
1490 r = sd_journal_add_conjunction(j);
1491 if (r < 0)
1492 return r;
1493
1494 return 0;
1495}
1496
1497static int setup_keys(void) {
1498#ifdef HAVE_GCRYPT
1499 size_t mpk_size, seed_size, state_size, i;
1500 uint8_t *mpk, *seed, *state;
1501 int fd = -1, r;
1502 sd_id128_t machine, boot;
1503 char *p = NULL, *k = NULL;
1504 struct FSSHeader h;
1505 uint64_t n;
1506 struct stat st;
1507
1508 r = stat("/var/log/journal", &st);
1509 if (r < 0 && errno != ENOENT && errno != ENOTDIR)
1510 return log_error_errno(errno, "stat(\"%s\") failed: %m", "/var/log/journal");
1511
1512 if (r < 0 || !S_ISDIR(st.st_mode)) {
1513 log_error("%s is not a directory, must be using persistent logging for FSS.",
1514 "/var/log/journal");
1515 return r < 0 ? -errno : -ENOTDIR;
1516 }
1517
1518 r = sd_id128_get_machine(&machine);
1519 if (r < 0)
1520 return log_error_errno(r, "Failed to get machine ID: %m");
1521
1522 r = sd_id128_get_boot(&boot);
1523 if (r < 0)
1524 return log_error_errno(r, "Failed to get boot ID: %m");
1525
1526 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
1527 SD_ID128_FORMAT_VAL(machine)) < 0)
1528 return log_oom();
1529
1530 if (arg_force) {
1531 r = unlink(p);
1532 if (r < 0 && errno != ENOENT) {
1533 r = log_error_errno(errno, "unlink(\"%s\") failed: %m", p);
1534 goto finish;
1535 }
1536 } else if (access(p, F_OK) >= 0) {
1537 log_error("Sealing key file %s exists already. Use --force to recreate.", p);
1538 r = -EEXIST;
1539 goto finish;
1540 }
1541
1542 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
1543 SD_ID128_FORMAT_VAL(machine)) < 0) {
1544 r = log_oom();
1545 goto finish;
1546 }
1547
1548 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
1549 mpk = alloca(mpk_size);
1550
1551 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
1552 seed = alloca(seed_size);
1553
1554 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
1555 state = alloca(state_size);
1556
1557 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1558 if (fd < 0) {
1559 r = log_error_errno(errno, "Failed to open /dev/random: %m");
1560 goto finish;
1561 }
1562
1563 log_info("Generating seed...");
1564 r = loop_read_exact(fd, seed, seed_size, true);
1565 if (r < 0) {
1566 log_error_errno(r, "Failed to read random seed: %m");
1567 goto finish;
1568 }
1569
1570 log_info("Generating key pair...");
1571 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
1572
1573 log_info("Generating sealing key...");
1574 FSPRG_GenState0(state, mpk, seed, seed_size);
1575
1576 assert(arg_interval > 0);
1577
1578 n = now(CLOCK_REALTIME);
1579 n /= arg_interval;
1580
1581 safe_close(fd);
1582 fd = mkostemp_safe(k, O_WRONLY|O_CLOEXEC);
1583 if (fd < 0) {
1584 r = log_error_errno(fd, "Failed to open %s: %m", k);
1585 goto finish;
1586 }
1587
1588 /* Enable secure remove, exclusion from dump, synchronous
1589 * writing and in-place updating */
1590 r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL);
1591 if (r < 0)
1592 log_warning_errno(r, "Failed to set file attributes: %m");
1593
1594 zero(h);
1595 memcpy(h.signature, "KSHHRHLP", 8);
1596 h.machine_id = machine;
1597 h.boot_id = boot;
1598 h.header_size = htole64(sizeof(h));
1599 h.start_usec = htole64(n * arg_interval);
1600 h.interval_usec = htole64(arg_interval);
1601 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
1602 h.fsprg_state_size = htole64(state_size);
1603
1604 r = loop_write(fd, &h, sizeof(h), false);
1605 if (r < 0) {
1606 log_error_errno(r, "Failed to write header: %m");
1607 goto finish;
1608 }
1609
1610 r = loop_write(fd, state, state_size, false);
1611 if (r < 0) {
1612 log_error_errno(r, "Failed to write state: %m");
1613 goto finish;
1614 }
1615
1616 if (link(k, p) < 0) {
1617 r = log_error_errno(errno, "Failed to link file: %m");
1618 goto finish;
1619 }
1620
1621 if (on_tty()) {
1622 fprintf(stderr,
1623 "\n"
1624 "The new key pair has been generated. The " ANSI_HIGHLIGHT "secret sealing key" ANSI_NORMAL " has been written to\n"
1625 "the following local file. This key file is automatically updated when the\n"
1626 "sealing key is advanced. It should not be used on multiple hosts.\n"
1627 "\n"
1628 "\t%s\n"
1629 "\n"
1630 "Please write down the following " ANSI_HIGHLIGHT "secret verification key" ANSI_NORMAL ". It should be stored\n"
1631 "at a safe location and should not be saved locally on disk.\n"
1632 "\n\t" ANSI_HIGHLIGHT_RED, p);
1633 fflush(stderr);
1634 }
1635 for (i = 0; i < seed_size; i++) {
1636 if (i > 0 && i % 3 == 0)
1637 putchar('-');
1638 printf("%02x", ((uint8_t*) seed)[i]);
1639 }
1640
1641 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
1642
1643 if (on_tty()) {
1644 char tsb[FORMAT_TIMESPAN_MAX], *hn;
1645
1646 fprintf(stderr,
1647 ANSI_NORMAL "\n"
1648 "The sealing key is automatically changed every %s.\n",
1649 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
1650
1651 hn = gethostname_malloc();
1652
1653 if (hn) {
1654 hostname_cleanup(hn);
1655 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
1656 } else
1657 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
1658
1659#ifdef HAVE_QRENCODE
1660 /* If this is not an UTF-8 system don't print any QR codes */
1661 if (is_locale_utf8()) {
1662 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
1663 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
1664 }
1665#endif
1666 free(hn);
1667 }
1668
1669 r = 0;
1670
1671finish:
1672 safe_close(fd);
1673
1674 if (k) {
1675 unlink(k);
1676 free(k);
1677 }
1678
1679 free(p);
1680
1681 return r;
1682#else
1683 log_error("Forward-secure sealing not available.");
1684 return -EOPNOTSUPP;
1685#endif
1686}
1687
1688static int verify(sd_journal *j) {
1689 int r = 0;
1690 Iterator i;
1691 JournalFile *f;
1692
1693 assert(j);
1694
1695 log_show_color(true);
1696
1697 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
1698 int k;
1699 usec_t first = 0, validated = 0, last = 0;
1700
1701#ifdef HAVE_GCRYPT
1702 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
1703 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
1704#endif
1705
1706 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
1707 if (k == -EINVAL) {
1708 /* If the key was invalid give up right-away. */
1709 return k;
1710 } else if (k < 0) {
1711 log_warning_errno(k, "FAIL: %s (%m)", f->path);
1712 r = k;
1713 } else {
1714 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
1715 log_info("PASS: %s", f->path);
1716
1717 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
1718 if (validated > 0) {
1719 log_info("=> Validated from %s to %s, final %s entries not sealed.",
1720 format_timestamp_maybe_utc(a, sizeof(a), first),
1721 format_timestamp_maybe_utc(b, sizeof(b), validated),
1722 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
1723 } else if (last > 0)
1724 log_info("=> No sealing yet, %s of entries not sealed.",
1725 format_timespan(c, sizeof(c), last - first, 0));
1726 else
1727 log_info("=> No sealing yet, no entries in file.");
1728 }
1729 }
1730 }
1731
1732 return r;
1733}
1734
1735static int access_check_var_log_journal(sd_journal *j) {
1736#ifdef HAVE_ACL
1737 _cleanup_strv_free_ char **g = NULL;
1738 const char* dir;
1739#endif
1740 int r;
1741
1742 assert(j);
1743
1744 if (arg_quiet)
1745 return 0;
1746
1747 /* If we are root, we should have access, don't warn. */
1748 if (getuid() == 0)
1749 return 0;
1750
1751 /* If we are in the 'systemd-journal' group, we should have
1752 * access too. */
1753 r = in_group("systemd-journal");
1754 if (r < 0)
1755 return log_error_errno(r, "Failed to check if we are in the 'systemd-journal' group: %m");
1756 if (r > 0)
1757 return 0;
1758
1759#ifdef HAVE_ACL
1760 if (laccess("/run/log/journal", F_OK) >= 0)
1761 dir = "/run/log/journal";
1762 else
1763 dir = "/var/log/journal";
1764
1765 /* If we are in any of the groups listed in the journal ACLs,
1766 * then all is good, too. Let's enumerate all groups from the
1767 * default ACL of the directory, which generally should allow
1768 * access to most journal files too. */
1769 r = acl_search_groups(dir, &g);
1770 if (r < 0)
1771 return log_error_errno(r, "Failed to search journal ACL: %m");
1772 if (r > 0)
1773 return 0;
1774
1775 /* Print a pretty list, if there were ACLs set. */
1776 if (!strv_isempty(g)) {
1777 _cleanup_free_ char *s = NULL;
1778
1779 /* Thre are groups in the ACL, let's list them */
1780 r = strv_extend(&g, "systemd-journal");
1781 if (r < 0)
1782 return log_oom();
1783
1784 strv_sort(g);
1785 strv_uniq(g);
1786
1787 s = strv_join(g, "', '");
1788 if (!s)
1789 return log_oom();
1790
1791 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1792 " Users in groups '%s' can see all messages.\n"
1793 " Pass -q to turn off this notice.", s);
1794 return 1;
1795 }
1796#endif
1797
1798 /* If no ACLs were found, print a short version of the message. */
1799 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1800 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1801 " turn off this notice.");
1802
1803 return 1;
1804}
1805
1806static int access_check(sd_journal *j) {
1807 Iterator it;
1808 void *code;
1809 char *path;
1810 int r = 0;
1811
1812 assert(j);
1813
1814 if (hashmap_isempty(j->errors)) {
1815 if (ordered_hashmap_isempty(j->files))
1816 log_notice("No journal files were found.");
1817
1818 return 0;
1819 }
1820
1821 if (hashmap_contains(j->errors, INT_TO_PTR(-EACCES))) {
1822 (void) access_check_var_log_journal(j);
1823
1824 if (ordered_hashmap_isempty(j->files))
1825 r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions.");
1826 }
1827
1828 HASHMAP_FOREACH_KEY(path, code, j->errors, it) {
1829 int err;
1830
1831 err = abs(PTR_TO_INT(code));
1832
1833 switch (err) {
1834 case EACCES:
1835 continue;
1836
1837 case ENODATA:
1838 log_warning_errno(err, "Journal file %s is truncated, ignoring file.", path);
1839 break;
1840
1841 case EPROTONOSUPPORT:
1842 log_warning_errno(err, "Journal file %s uses an unsupported feature, ignoring file.", path);
1843 break;
1844
1845 case EBADMSG:
1846 log_warning_errno(err, "Journal file %s corrupted, ignoring file.", path);
1847 break;
1848
1849 default:
1850 log_warning_errno(err, "An error was encountered while opening journal file %s, ignoring file.", path);
1851 break;
1852 }
1853 }
1854
1855 return r;
1856}
1857
1858static int flush_to_var(void) {
1859 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1860 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
1861 _cleanup_close_ int watch_fd = -1;
1862 int r;
1863
1864 if (arg_machine) {
1865 log_error("--flush is not supported in conjunction with --machine=.");
1866 return -EOPNOTSUPP;
1867 }
1868
1869 /* Quick exit */
1870 if (access("/run/systemd/journal/flushed", F_OK) >= 0)
1871 return 0;
1872
1873 /* OK, let's actually do the full logic, send SIGUSR1 to the
1874 * daemon and set up inotify to wait for the flushed file to appear */
1875 r = bus_connect_system_systemd(&bus);
1876 if (r < 0)
1877 return log_error_errno(r, "Failed to get D-Bus connection: %m");
1878
1879 r = sd_bus_call_method(
1880 bus,
1881 "org.freedesktop.systemd1",
1882 "/org/freedesktop/systemd1",
1883 "org.freedesktop.systemd1.Manager",
1884 "KillUnit",
1885 &error,
1886 NULL,
1887 "ssi", "systemd-journald.service", "main", SIGUSR1);
1888 if (r < 0)
1889 return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r));
1890
1891 mkdir_p("/run/systemd/journal", 0755);
1892
1893 watch_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
1894 if (watch_fd < 0)
1895 return log_error_errno(errno, "Failed to create inotify watch: %m");
1896
1897 r = inotify_add_watch(watch_fd, "/run/systemd/journal", IN_CREATE|IN_DONT_FOLLOW|IN_ONLYDIR);
1898 if (r < 0)
1899 return log_error_errno(errno, "Failed to watch journal directory: %m");
1900
1901 for (;;) {
1902 if (access("/run/systemd/journal/flushed", F_OK) >= 0)
1903 break;
1904
1905 if (errno != ENOENT)
1906 return log_error_errno(errno, "Failed to check for existence of /run/systemd/journal/flushed: %m");
1907
1908 r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY);
1909 if (r < 0)
1910 return log_error_errno(r, "Failed to wait for event: %m");
1911
1912 r = flush_fd(watch_fd);
1913 if (r < 0)
1914 return log_error_errno(r, "Failed to flush inotify events: %m");
1915 }
1916
1917 return 0;
1918}
1919
1920static int send_signal_and_wait(int sig, const char *watch_path) {
1921 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
1922 _cleanup_close_ int watch_fd = -1;
1923 usec_t start;
1924 int r;
1925
1926 if (arg_machine) {
1927 log_error("--sync and --rotate are not supported in conjunction with --machine=.");
1928 return -EOPNOTSUPP;
1929 }
1930
1931 start = now(CLOCK_MONOTONIC);
1932
1933 /* This call sends the specified signal to journald, and waits
1934 * for acknowledgment by watching the mtime of the specified
1935 * flag file. This is used to trigger syncing or rotation and
1936 * then wait for the operation to complete. */
1937
1938 for (;;) {
1939 usec_t tstamp;
1940
1941 /* See if a sync happened by now. */
1942 r = read_timestamp_file(watch_path, &tstamp);
1943 if (r < 0 && r != -ENOENT)
1944 return log_error_errno(errno, "Failed to read %s: %m", watch_path);
1945 if (r >= 0 && tstamp >= start)
1946 return 0;
1947
1948 /* Let's ask for a sync, but only once. */
1949 if (!bus) {
1950 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1951
1952 r = bus_connect_system_systemd(&bus);
1953 if (r < 0)
1954 return log_error_errno(r, "Failed to get D-Bus connection: %m");
1955
1956 r = sd_bus_call_method(
1957 bus,
1958 "org.freedesktop.systemd1",
1959 "/org/freedesktop/systemd1",
1960 "org.freedesktop.systemd1.Manager",
1961 "KillUnit",
1962 &error,
1963 NULL,
1964 "ssi", "systemd-journald.service", "main", sig);
1965 if (r < 0)
1966 return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r));
1967
1968 continue;
1969 }
1970
1971 /* Let's install the inotify watch, if we didn't do that yet. */
1972 if (watch_fd < 0) {
1973
1974 mkdir_p("/run/systemd/journal", 0755);
1975
1976 watch_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
1977 if (watch_fd < 0)
1978 return log_error_errno(errno, "Failed to create inotify watch: %m");
1979
1980 r = inotify_add_watch(watch_fd, "/run/systemd/journal", IN_MOVED_TO|IN_DONT_FOLLOW|IN_ONLYDIR);
1981 if (r < 0)
1982 return log_error_errno(errno, "Failed to watch journal directory: %m");
1983
1984 /* Recheck the flag file immediately, so that we don't miss any event since the last check. */
1985 continue;
1986 }
1987
1988 /* OK, all preparatory steps done, let's wait until
1989 * inotify reports an event. */
1990
1991 r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY);
1992 if (r < 0)
1993 return log_error_errno(r, "Failed to wait for event: %m");
1994
1995 r = flush_fd(watch_fd);
1996 if (r < 0)
1997 return log_error_errno(r, "Failed to flush inotify events: %m");
1998 }
1999
2000 return 0;
2001}
2002
2003static int rotate(void) {
2004 return send_signal_and_wait(SIGUSR2, "/run/systemd/journal/rotated");
2005}
2006
2007static int sync_journal(void) {
2008 return send_signal_and_wait(SIGRTMIN+1, "/run/systemd/journal/synced");
2009}
2010
2011int main(int argc, char *argv[]) {
2012 int r;
2013 _cleanup_(sd_journal_closep) sd_journal *j = NULL;
2014 bool need_seek = false;
2015 sd_id128_t previous_boot_id;
2016 bool previous_boot_id_valid = false, first_line = true;
2017 int n_shown = 0;
2018 bool ellipsized = false;
2019
2020 setlocale(LC_ALL, "");
2021 log_parse_environment();
2022 log_open();
2023
2024 r = parse_argv(argc, argv);
2025 if (r <= 0)
2026 goto finish;
2027
2028 signal(SIGWINCH, columns_lines_cache_reset);
2029 sigbus_install();
2030
2031 /* Increase max number of open files to 16K if we can, we
2032 * might needs this when browsing journal files, which might
2033 * be split up into many files. */
2034 setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
2035
2036 switch (arg_action) {
2037
2038 case ACTION_NEW_ID128:
2039 r = generate_new_id128();
2040 goto finish;
2041
2042 case ACTION_SETUP_KEYS:
2043 r = setup_keys();
2044 goto finish;
2045
2046 case ACTION_LIST_CATALOG:
2047 case ACTION_DUMP_CATALOG:
2048 case ACTION_UPDATE_CATALOG: {
2049 _cleanup_free_ char *database;
2050
2051 database = path_join(arg_root, CATALOG_DATABASE, NULL);
2052 if (!database) {
2053 r = log_oom();
2054 goto finish;
2055 }
2056
2057 if (arg_action == ACTION_UPDATE_CATALOG) {
2058 r = catalog_update(database, arg_root, catalog_file_dirs);
2059 if (r < 0)
2060 log_error_errno(r, "Failed to list catalog: %m");
2061 } else {
2062 bool oneline = arg_action == ACTION_LIST_CATALOG;
2063
2064 pager_open_if_enabled();
2065
2066 if (optind < argc)
2067 r = catalog_list_items(stdout, database, oneline, argv + optind);
2068 else
2069 r = catalog_list(stdout, database, oneline);
2070 if (r < 0)
2071 log_error_errno(r, "Failed to list catalog: %m");
2072 }
2073
2074 goto finish;
2075 }
2076
2077 case ACTION_FLUSH:
2078 r = flush_to_var();
2079 goto finish;
2080
2081 case ACTION_SYNC:
2082 r = sync_journal();
2083 goto finish;
2084
2085 case ACTION_ROTATE:
2086 r = rotate();
2087 goto finish;
2088
2089 case ACTION_SHOW:
2090 case ACTION_PRINT_HEADER:
2091 case ACTION_VERIFY:
2092 case ACTION_DISK_USAGE:
2093 case ACTION_LIST_BOOTS:
2094 case ACTION_VACUUM:
2095 case ACTION_LIST_FIELDS:
2096 case ACTION_LIST_FIELD_NAMES:
2097 /* These ones require access to the journal files, continue below. */
2098 break;
2099
2100 default:
2101 assert_not_reached("Unknown action");
2102 }
2103
2104 if (arg_directory)
2105 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
2106 else if (arg_file)
2107 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
2108 else if (arg_machine)
2109 r = sd_journal_open_container(&j, arg_machine, 0);
2110 else
2111 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
2112 if (r < 0) {
2113 log_error_errno(r, "Failed to open %s: %m", arg_directory ?: arg_file ? "files" : "journal");
2114 goto finish;
2115 }
2116
2117 r = access_check(j);
2118 if (r < 0)
2119 goto finish;
2120
2121 switch (arg_action) {
2122
2123 case ACTION_NEW_ID128:
2124 case ACTION_SETUP_KEYS:
2125 case ACTION_LIST_CATALOG:
2126 case ACTION_DUMP_CATALOG:
2127 case ACTION_UPDATE_CATALOG:
2128 case ACTION_FLUSH:
2129 case ACTION_SYNC:
2130 case ACTION_ROTATE:
2131 assert_not_reached("Unexpected action.");
2132
2133 case ACTION_PRINT_HEADER:
2134 journal_print_header(j);
2135 r = 0;
2136 goto finish;
2137
2138 case ACTION_VERIFY:
2139 r = verify(j);
2140 goto finish;
2141
2142 case ACTION_DISK_USAGE: {
2143 uint64_t bytes = 0;
2144 char sbytes[FORMAT_BYTES_MAX];
2145
2146 r = sd_journal_get_usage(j, &bytes);
2147 if (r < 0)
2148 goto finish;
2149
2150 printf("Archived and active journals take up %s on disk.\n",
2151 format_bytes(sbytes, sizeof(sbytes), bytes));
2152 goto finish;
2153 }
2154
2155 case ACTION_LIST_BOOTS:
2156 r = list_boots(j);
2157 goto finish;
2158
2159 case ACTION_VACUUM: {
2160 Directory *d;
2161 Iterator i;
2162
2163 HASHMAP_FOREACH(d, j->directories_by_path, i) {
2164 int q;
2165
2166 if (d->is_root)
2167 continue;
2168
2169 q = journal_directory_vacuum(d->path, arg_vacuum_size, arg_vacuum_n_files, arg_vacuum_time, NULL, true);
2170 if (q < 0) {
2171 log_error_errno(q, "Failed to vacuum %s: %m", d->path);
2172 r = q;
2173 }
2174 }
2175
2176 goto finish;
2177 }
2178
2179 case ACTION_LIST_FIELD_NAMES: {
2180 const char *field;
2181
2182 SD_JOURNAL_FOREACH_FIELD(j, field) {
2183 printf("%s\n", field);
2184 n_shown ++;
2185 }
2186
2187 r = 0;
2188 goto finish;
2189 }
2190
2191 case ACTION_SHOW:
2192 case ACTION_LIST_FIELDS:
2193 break;
2194
2195 default:
2196 assert_not_reached("Unknown action");
2197 }
2198
2199 if (arg_boot_offset != 0 &&
2200 sd_journal_has_runtime_files(j) > 0 &&
2201 sd_journal_has_persistent_files(j) == 0) {
2202 log_info("Specifying boot ID has no effect, no persistent journal was found");
2203 r = 0;
2204 goto finish;
2205 }
2206 /* add_boot() must be called first!
2207 * It may need to seek the journal to find parent boot IDs. */
2208 r = add_boot(j);
2209 if (r < 0)
2210 goto finish;
2211
2212 r = add_dmesg(j);
2213 if (r < 0)
2214 goto finish;
2215
2216 r = add_units(j);
2217 if (r < 0) {
2218 log_error_errno(r, "Failed to add filter for units: %m");
2219 goto finish;
2220 }
2221
2222 r = add_syslog_identifier(j);
2223 if (r < 0) {
2224 log_error_errno(r, "Failed to add filter for syslog identifiers: %m");
2225 goto finish;
2226 }
2227
2228 r = add_priorities(j);
2229 if (r < 0)
2230 goto finish;
2231
2232 r = add_matches(j, argv + optind);
2233 if (r < 0)
2234 goto finish;
2235
2236 if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
2237 _cleanup_free_ char *filter;
2238
2239 filter = journal_make_match_string(j);
2240 if (!filter)
2241 return log_oom();
2242
2243 log_debug("Journal filter: %s", filter);
2244 }
2245
2246 if (arg_action == ACTION_LIST_FIELDS) {
2247 const void *data;
2248 size_t size;
2249
2250 assert(arg_field);
2251
2252 r = sd_journal_set_data_threshold(j, 0);
2253 if (r < 0) {
2254 log_error_errno(r, "Failed to unset data size threshold: %m");
2255 goto finish;
2256 }
2257
2258 r = sd_journal_query_unique(j, arg_field);
2259 if (r < 0) {
2260 log_error_errno(r, "Failed to query unique data objects: %m");
2261 goto finish;
2262 }
2263
2264 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
2265 const void *eq;
2266
2267 if (arg_lines >= 0 && n_shown >= arg_lines)
2268 break;
2269
2270 eq = memchr(data, '=', size);
2271 if (eq)
2272 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
2273 else
2274 printf("%.*s\n", (int) size, (const char*) data);
2275
2276 n_shown ++;
2277 }
2278
2279 r = 0;
2280 goto finish;
2281 }
2282
2283 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2284 if (arg_follow) {
2285 r = sd_journal_get_fd(j);
2286 if (r < 0) {
2287 log_error_errno(r, "Failed to get journal fd: %m");
2288 goto finish;
2289 }
2290 }
2291
2292 if (arg_cursor || arg_after_cursor) {
2293 r = sd_journal_seek_cursor(j, arg_cursor ?: arg_after_cursor);
2294 if (r < 0) {
2295 log_error_errno(r, "Failed to seek to cursor: %m");
2296 goto finish;
2297 }
2298
2299 if (!arg_reverse)
2300 r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
2301 else
2302 r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor);
2303
2304 if (arg_after_cursor && r < 2) {
2305 /* We couldn't find the next entry after the cursor. */
2306 if (arg_follow)
2307 need_seek = true;
2308 else
2309 arg_lines = 0;
2310 }
2311
2312 } else if (arg_since_set && !arg_reverse) {
2313 r = sd_journal_seek_realtime_usec(j, arg_since);
2314 if (r < 0) {
2315 log_error_errno(r, "Failed to seek to date: %m");
2316 goto finish;
2317 }
2318 r = sd_journal_next(j);
2319
2320 } else if (arg_until_set && arg_reverse) {
2321 r = sd_journal_seek_realtime_usec(j, arg_until);
2322 if (r < 0) {
2323 log_error_errno(r, "Failed to seek to date: %m");
2324 goto finish;
2325 }
2326 r = sd_journal_previous(j);
2327
2328 } else if (arg_lines >= 0) {
2329 r = sd_journal_seek_tail(j);
2330 if (r < 0) {
2331 log_error_errno(r, "Failed to seek to tail: %m");
2332 goto finish;
2333 }
2334
2335 r = sd_journal_previous_skip(j, arg_lines);
2336
2337 } else if (arg_reverse) {
2338 r = sd_journal_seek_tail(j);
2339 if (r < 0) {
2340 log_error_errno(r, "Failed to seek to tail: %m");
2341 goto finish;
2342 }
2343
2344 r = sd_journal_previous(j);
2345
2346 } else {
2347 r = sd_journal_seek_head(j);
2348 if (r < 0) {
2349 log_error_errno(r, "Failed to seek to head: %m");
2350 goto finish;
2351 }
2352
2353 r = sd_journal_next(j);
2354 }
2355
2356 if (r < 0) {
2357 log_error_errno(r, "Failed to iterate through journal: %m");
2358 goto finish;
2359 }
2360 if (r == 0) {
2361 if (arg_follow)
2362 need_seek = true;
2363 else {
2364 if (!arg_quiet)
2365 printf("-- No entries --\n");
2366 goto finish;
2367 }
2368 }
2369
2370 if (!arg_follow)
2371 pager_open_if_enabled();
2372
2373 if (!arg_quiet) {
2374 usec_t start, end;
2375 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
2376
2377 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
2378 if (r < 0) {
2379 log_error_errno(r, "Failed to get cutoff: %m");
2380 goto finish;
2381 }
2382
2383 if (r > 0) {
2384 if (arg_follow)
2385 printf("-- Logs begin at %s. --\n",
2386 format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start));
2387 else
2388 printf("-- Logs begin at %s, end at %s. --\n",
2389 format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start),
2390 format_timestamp_maybe_utc(end_buf, sizeof(end_buf), end));
2391 }
2392 }
2393
2394 for (;;) {
2395 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
2396 int flags;
2397
2398 if (need_seek) {
2399 if (!arg_reverse)
2400 r = sd_journal_next(j);
2401 else
2402 r = sd_journal_previous(j);
2403 if (r < 0) {
2404 log_error_errno(r, "Failed to iterate through journal: %m");
2405 goto finish;
2406 }
2407 if (r == 0)
2408 break;
2409 }
2410
2411 if (arg_until_set && !arg_reverse) {
2412 usec_t usec;
2413
2414 r = sd_journal_get_realtime_usec(j, &usec);
2415 if (r < 0) {
2416 log_error_errno(r, "Failed to determine timestamp: %m");
2417 goto finish;
2418 }
2419 if (usec > arg_until)
2420 goto finish;
2421 }
2422
2423 if (arg_since_set && arg_reverse) {
2424 usec_t usec;
2425
2426 r = sd_journal_get_realtime_usec(j, &usec);
2427 if (r < 0) {
2428 log_error_errno(r, "Failed to determine timestamp: %m");
2429 goto finish;
2430 }
2431 if (usec < arg_since)
2432 goto finish;
2433 }
2434
2435 if (!arg_merge && !arg_quiet) {
2436 sd_id128_t boot_id;
2437
2438 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
2439 if (r >= 0) {
2440 if (previous_boot_id_valid &&
2441 !sd_id128_equal(boot_id, previous_boot_id))
2442 printf("%s-- Reboot --%s\n",
2443 ansi_highlight(), ansi_normal());
2444
2445 previous_boot_id = boot_id;
2446 previous_boot_id_valid = true;
2447 }
2448 }
2449
2450 flags =
2451 arg_all * OUTPUT_SHOW_ALL |
2452 arg_full * OUTPUT_FULL_WIDTH |
2453 colors_enabled() * OUTPUT_COLOR |
2454 arg_catalog * OUTPUT_CATALOG |
2455 arg_utc * OUTPUT_UTC;
2456
2457 r = output_journal(stdout, j, arg_output, 0, flags, &ellipsized);
2458 need_seek = true;
2459 if (r == -EADDRNOTAVAIL)
2460 break;
2461 else if (r < 0 || ferror(stdout))
2462 goto finish;
2463
2464 n_shown++;
2465 }
2466
2467 if (!arg_follow) {
2468 if (arg_show_cursor) {
2469 _cleanup_free_ char *cursor = NULL;
2470
2471 r = sd_journal_get_cursor(j, &cursor);
2472 if (r < 0 && r != -EADDRNOTAVAIL)
2473 log_error_errno(r, "Failed to get cursor: %m");
2474 else if (r >= 0)
2475 printf("-- cursor: %s\n", cursor);
2476 }
2477
2478 break;
2479 }
2480
2481 r = sd_journal_wait(j, (uint64_t) -1);
2482 if (r < 0) {
2483 log_error_errno(r, "Couldn't wait for journal event: %m");
2484 goto finish;
2485 }
2486
2487 first_line = false;
2488 }
2489
2490finish:
2491 pager_close();
2492
2493 strv_free(arg_file);
2494
2495 strv_free(arg_syslog_identifier);
2496 strv_free(arg_system_units);
2497 strv_free(arg_user_units);
2498
2499 free(arg_root);
2500
2501 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2502}