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