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