1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
12 #include <sys/inotify.h>
17 #include "sd-device.h"
18 #include "sd-journal.h"
21 #include "alloc-util.h"
23 #include "bus-error.h"
24 #include "bus-locator.h"
28 #include "chattr-util.h"
29 #include "constants.h"
30 #include "devnum-util.h"
31 #include "dissect-image.h"
34 #include "format-table.h"
35 #include "format-util.h"
38 #include "glob-util.h"
39 #include "hostname-util.h"
40 #include "id128-print.h"
42 #include "journal-def.h"
43 #include "journal-internal.h"
44 #include "journal-util.h"
45 #include "journal-vacuum.h"
46 #include "journal-verify.h"
47 #include "locale-util.h"
49 #include "logs-show.h"
50 #include "main-func.h"
51 #include "memory-util.h"
52 #include "memstream-util.h"
53 #include "missing_sched.h"
55 #include "mount-util.h"
56 #include "mountpoint-util.h"
57 #include "nulstr-util.h"
59 #include "parse-argument.h"
60 #include "parse-util.h"
61 #include "path-util.h"
62 #include "pcre2-util.h"
63 #include "pretty-print.h"
64 #include "qrcode-util.h"
65 #include "random-util.h"
66 #include "rlimit-util.h"
69 #include "signal-util.h"
70 #include "static-destruct.h"
71 #include "stdio-util.h"
72 #include "string-table.h"
74 #include "syslog-util.h"
75 #include "terminal-util.h"
76 #include "tmpfile-util.h"
77 #include "unit-name.h"
78 #include "user-util.h"
81 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
82 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
85 /* Special values for arg_lines */
86 ARG_LINES_DEFAULT
= -2,
90 static OutputMode arg_output
= OUTPUT_SHORT
;
91 static JsonFormatFlags arg_json_format_flags
= JSON_FORMAT_OFF
;
92 static bool arg_utc
= false;
93 static bool arg_follow
= false;
94 static bool arg_full
= true;
95 static bool arg_all
= false;
96 static PagerFlags arg_pager_flags
= 0;
97 static int arg_lines
= ARG_LINES_DEFAULT
;
98 static bool arg_no_tail
= false;
99 static bool arg_truncate_newline
= false;
100 static bool arg_quiet
= false;
101 static bool arg_merge
= false;
102 static bool arg_boot
= false;
103 static sd_id128_t arg_boot_id
= {};
104 static int arg_boot_offset
= 0;
105 static bool arg_dmesg
= false;
106 static bool arg_no_hostname
= false;
107 static const char *arg_cursor
= NULL
;
108 static const char *arg_cursor_file
= NULL
;
109 static const char *arg_after_cursor
= NULL
;
110 static bool arg_show_cursor
= false;
111 static const char *arg_directory
= NULL
;
112 static char **arg_file
= NULL
;
113 static bool arg_file_stdin
= false;
114 static int arg_priorities
= 0xFF;
115 static Set
*arg_facilities
= NULL
;
116 static char *arg_verify_key
= NULL
;
118 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
119 static bool arg_force
= false;
121 static usec_t arg_since
= 0, arg_until
= 0;
122 static bool arg_since_set
= false, arg_until_set
= false;
123 static char **arg_syslog_identifier
= NULL
;
124 static char **arg_system_units
= NULL
;
125 static char **arg_user_units
= NULL
;
126 static const char *arg_field
= NULL
;
127 static bool arg_catalog
= false;
128 static bool arg_reverse
= false;
129 static int arg_journal_type
= 0;
130 static int arg_namespace_flags
= 0;
131 static char *arg_root
= NULL
;
132 static char *arg_image
= NULL
;
133 static const char *arg_machine
= NULL
;
134 static const char *arg_namespace
= NULL
;
135 static uint64_t arg_vacuum_size
= 0;
136 static uint64_t arg_vacuum_n_files
= 0;
137 static usec_t arg_vacuum_time
= 0;
138 static Set
*arg_output_fields
= NULL
;
139 static const char *arg_pattern
= NULL
;
140 static pcre2_code
*arg_compiled_pattern
= NULL
;
141 static PatternCompileCase arg_case
= PATTERN_COMPILE_CASE_AUTO
;
142 ImagePolicy
*arg_image_policy
= NULL
;
144 STATIC_DESTRUCTOR_REGISTER(arg_file
, strv_freep
);
145 STATIC_DESTRUCTOR_REGISTER(arg_facilities
, set_freep
);
146 STATIC_DESTRUCTOR_REGISTER(arg_verify_key
, freep
);
147 STATIC_DESTRUCTOR_REGISTER(arg_syslog_identifier
, strv_freep
);
148 STATIC_DESTRUCTOR_REGISTER(arg_system_units
, strv_freep
);
149 STATIC_DESTRUCTOR_REGISTER(arg_user_units
, strv_freep
);
150 STATIC_DESTRUCTOR_REGISTER(arg_root
, freep
);
151 STATIC_DESTRUCTOR_REGISTER(arg_image
, freep
);
152 STATIC_DESTRUCTOR_REGISTER(arg_output_fields
, set_freep
);
153 STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern
, pattern_freep
);
154 STATIC_DESTRUCTOR_REGISTER(arg_image_policy
, image_policy_freep
);
165 ACTION_UPDATE_CATALOG
,
168 ACTION_RELINQUISH_VAR
,
172 ACTION_ROTATE_AND_VACUUM
,
174 ACTION_LIST_FIELD_NAMES
,
175 } arg_action
= ACTION_SHOW
;
177 typedef struct BootId
{
183 static int add_matches_for_device(sd_journal
*j
, const char *devpath
) {
184 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
192 if (!path_startswith(devpath
, "/dev/"))
193 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
194 "Devpath does not start with /dev/");
196 if (stat(devpath
, &st
) < 0)
197 return log_error_errno(errno
, "Couldn't stat file: %m");
199 r
= sd_device_new_from_stat_rdev(&device
, &st
);
201 return log_error_errno(r
, "Failed to get device from devnum " DEVNUM_FORMAT_STR
": %m", DEVNUM_FORMAT_VAL(st
.st_rdev
));
203 for (d
= device
; d
; ) {
204 _cleanup_free_
char *match
= NULL
;
205 const char *subsys
, *sysname
, *devnode
;
208 r
= sd_device_get_subsystem(d
, &subsys
);
212 r
= sd_device_get_sysname(d
, &sysname
);
216 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
);
220 r
= sd_journal_add_match(j
, match
, 0);
222 return log_error_errno(r
, "Failed to add match: %m");
224 if (sd_device_get_devname(d
, &devnode
) >= 0) {
225 _cleanup_free_
char *match1
= NULL
;
227 r
= stat(devnode
, &st
);
229 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
231 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c" DEVNUM_FORMAT_STR
, S_ISBLK(st
.st_mode
) ? 'b' : 'c', DEVNUM_FORMAT_VAL(st
.st_rdev
));
235 r
= sd_journal_add_match(j
, match1
, 0);
237 return log_error_errno(r
, "Failed to add match: %m");
241 if (sd_device_get_parent(d
, &parent
) < 0)
247 r
= add_match_this_boot(j
, arg_machine
);
249 return log_error_errno(r
, "Failed to add match for the current boot: %m");
254 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
257 return format_timestamp_style(buf
, l
, t
, TIMESTAMP_UTC
);
259 return format_timestamp(buf
, l
, t
);
262 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
263 sd_id128_t id
= SD_ID128_NULL
;
266 if (streq(x
, "all")) {
267 *boot_id
= SD_ID128_NULL
;
270 } else if (strlen(x
) >= SD_ID128_STRING_MAX
- 1) {
273 t
= strndupa_safe(x
, SD_ID128_STRING_MAX
- 1);
274 r
= sd_id128_from_string(t
, &id
);
276 x
+= SD_ID128_STRING_MAX
- 1;
278 if (!IN_SET(*x
, 0, '-', '+'))
282 r
= safe_atoi(x
, &off
);
287 r
= safe_atoi(x
, &off
);
301 static int help_facilities(void) {
303 puts("Available facilities:");
305 for (int i
= 0; i
< LOG_NFACILITIES
; i
++) {
306 _cleanup_free_
char *t
= NULL
;
308 if (log_facility_unshifted_to_string_alloc(i
, &t
))
316 static int help(void) {
317 _cleanup_free_
char *link
= NULL
;
320 pager_open(arg_pager_flags
);
322 r
= terminal_urlify_man("journalctl", "1", &link
);
326 printf("%1$s [OPTIONS...] [MATCHES...]\n\n"
327 "%5$sQuery the journal.%6$s\n\n"
328 "%3$sSource Options:%4$s\n"
329 " --system Show the system journal\n"
330 " --user Show the user journal for the current user\n"
331 " -M --machine=CONTAINER Operate on local container\n"
332 " -m --merge Show entries from all available journals\n"
333 " -D --directory=PATH Show journal files from directory\n"
334 " --file=PATH Show journal file\n"
335 " --root=PATH Operate on an alternate filesystem root\n"
336 " --image=PATH Operate on disk image as filesystem root\n"
337 " --image-policy=POLICY Specify disk image dissection policy\n"
338 " --namespace=NAMESPACE Show journal data from specified journal namespace\n"
339 "\n%3$sFiltering Options:%4$s\n"
340 " -S --since=DATE Show entries not older than the specified date\n"
341 " -U --until=DATE Show entries not newer than the specified date\n"
342 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
343 " --after-cursor=CURSOR Show entries after the specified cursor\n"
344 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
345 " -b --boot[=ID] Show current boot or the specified boot\n"
346 " -u --unit=UNIT Show logs from the specified unit\n"
347 " --user-unit=UNIT Show logs from the specified user unit\n"
348 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
349 " -p --priority=RANGE Show entries with the specified priority\n"
350 " --facility=FACILITY... Show entries with the specified facilities\n"
351 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
352 " --case-sensitive[=BOOL] Force case sensitive or insensitive matching\n"
353 " -k --dmesg Show kernel message log from the current boot\n"
354 "\n%3$sOutput Control Options:%4$s\n"
355 " -o --output=STRING Change journal output mode (short, short-precise,\n"
356 " short-iso, short-iso-precise, short-full,\n"
357 " short-monotonic, short-unix, verbose, export,\n"
358 " json, json-pretty, json-sse, json-seq, cat,\n"
360 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
361 " -n --lines[=INTEGER] Number of journal entries to show\n"
362 " -r --reverse Show the newest entries first\n"
363 " --show-cursor Print the cursor after all the entries\n"
364 " --utc Express time in Coordinated Universal Time (UTC)\n"
365 " -x --catalog Add message explanations where available\n"
366 " --no-hostname Suppress output of hostname field\n"
367 " --no-full Ellipsize fields\n"
368 " -a --all Show all fields, including long and unprintable\n"
369 " -f --follow Follow the journal\n"
370 " --no-tail Show all lines, even in follow mode\n"
371 " --truncate-newline Truncate entries by first newline character\n"
372 " -q --quiet Do not show info messages and privilege warning\n"
373 "\n%3$sPager Control Options:%4$s\n"
374 " --no-pager Do not pipe output into a pager\n"
375 " -e --pager-end Immediately jump to the end in the pager\n"
376 "\n%3$sForward Secure Sealing (FSS) Options:%4$s\n"
377 " --interval=TIME Time interval for changing the FSS sealing key\n"
378 " --verify-key=KEY Specify FSS verification key\n"
379 " --force Override of the FSS key pair with --setup-keys\n"
380 "\n%3$sCommands:%4$s\n"
381 " -h --help Show this help text\n"
382 " --version Show package version\n"
383 " -N --fields List all field names currently used\n"
384 " -F --field=FIELD List all values that a specified field takes\n"
385 " --list-boots Show terse information about recorded boots\n"
386 " --disk-usage Show total disk usage of all journal files\n"
387 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
388 " --vacuum-files=INT Leave only the specified number of journal files\n"
389 " --vacuum-time=TIME Remove journal files older than specified time\n"
390 " --verify Verify journal file consistency\n"
391 " --sync Synchronize unwritten journal messages to disk\n"
392 " --relinquish-var Stop logging to disk, log to temporary file system\n"
393 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
394 " --flush Flush all journal data from /run into /var\n"
395 " --rotate Request immediate rotation of the journal files\n"
396 " --header Show journal header information\n"
397 " --list-catalog Show all message IDs in the catalog\n"
398 " --dump-catalog Show entries in the message catalog\n"
399 " --update-catalog Update the message catalog database\n"
400 " --setup-keys Generate a new FSS key pair\n"
401 "\nSee the %2$s for details.\n",
402 program_invocation_short_name
,
412 static int parse_argv(int argc
, char *argv
[]) {
448 ARG_SMART_RELINQUISH_VAR
,
450 ARG_TRUNCATE_NEWLINE
,
459 static const struct option options
[] = {
460 { "help", no_argument
, NULL
, 'h' },
461 { "version" , no_argument
, NULL
, ARG_VERSION
},
462 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
463 { "pager-end", no_argument
, NULL
, 'e' },
464 { "follow", no_argument
, NULL
, 'f' },
465 { "force", no_argument
, NULL
, ARG_FORCE
},
466 { "output", required_argument
, NULL
, 'o' },
467 { "all", no_argument
, NULL
, 'a' },
468 { "full", no_argument
, NULL
, 'l' },
469 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
470 { "lines", optional_argument
, NULL
, 'n' },
471 { "truncate-newline", no_argument
, NULL
, ARG_TRUNCATE_NEWLINE
},
472 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
473 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
}, /* deprecated */
474 { "quiet", no_argument
, NULL
, 'q' },
475 { "merge", no_argument
, NULL
, 'm' },
476 { "this-boot", no_argument
, NULL
, ARG_THIS_BOOT
}, /* deprecated */
477 { "boot", optional_argument
, NULL
, 'b' },
478 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
479 { "dmesg", no_argument
, NULL
, 'k' },
480 { "system", no_argument
, NULL
, ARG_SYSTEM
},
481 { "user", no_argument
, NULL
, ARG_USER
},
482 { "directory", required_argument
, NULL
, 'D' },
483 { "file", required_argument
, NULL
, ARG_FILE
},
484 { "root", required_argument
, NULL
, ARG_ROOT
},
485 { "image", required_argument
, NULL
, ARG_IMAGE
},
486 { "image-policy", required_argument
, NULL
, ARG_IMAGE_POLICY
},
487 { "header", no_argument
, NULL
, ARG_HEADER
},
488 { "identifier", required_argument
, NULL
, 't' },
489 { "priority", required_argument
, NULL
, 'p' },
490 { "facility", required_argument
, NULL
, ARG_FACILITY
},
491 { "grep", required_argument
, NULL
, 'g' },
492 { "case-sensitive", optional_argument
, NULL
, ARG_CASE_SENSITIVE
},
493 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
494 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
495 { "verify", no_argument
, NULL
, ARG_VERIFY
},
496 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
497 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
498 { "cursor", required_argument
, NULL
, 'c' },
499 { "cursor-file", required_argument
, NULL
, ARG_CURSOR_FILE
},
500 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
501 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
502 { "since", required_argument
, NULL
, 'S' },
503 { "until", required_argument
, NULL
, 'U' },
504 { "unit", required_argument
, NULL
, 'u' },
505 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
506 { "field", required_argument
, NULL
, 'F' },
507 { "fields", no_argument
, NULL
, 'N' },
508 { "catalog", no_argument
, NULL
, 'x' },
509 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
510 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
511 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
512 { "reverse", no_argument
, NULL
, 'r' },
513 { "machine", required_argument
, NULL
, 'M' },
514 { "utc", no_argument
, NULL
, ARG_UTC
},
515 { "flush", no_argument
, NULL
, ARG_FLUSH
},
516 { "relinquish-var", no_argument
, NULL
, ARG_RELINQUISH_VAR
},
517 { "smart-relinquish-var", no_argument
, NULL
, ARG_SMART_RELINQUISH_VAR
},
518 { "sync", no_argument
, NULL
, ARG_SYNC
},
519 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
520 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
521 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
522 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
523 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
524 { "output-fields", required_argument
, NULL
, ARG_OUTPUT_FIELDS
},
525 { "namespace", required_argument
, NULL
, ARG_NAMESPACE
},
534 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:", options
, NULL
)) >= 0)
545 arg_pager_flags
|= PAGER_DISABLE
;
549 arg_pager_flags
|= PAGER_JUMP_TO_END
;
551 if (arg_lines
== ARG_LINES_DEFAULT
)
563 if (streq(optarg
, "help")) {
564 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
568 arg_output
= output_mode_from_string(optarg
);
570 return log_error_errno(arg_output
, "Unknown output format '%s'.", optarg
);
572 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
575 if (OUTPUT_MODE_IS_JSON(arg_output
))
576 arg_json_format_flags
= output_mode_to_json_format_flags(arg_output
) | JSON_FORMAT_COLOR_AUTO
;
578 arg_json_format_flags
= JSON_FORMAT_OFF
;
596 if (streq(optarg
, "all"))
597 arg_lines
= ARG_LINES_ALL
;
599 r
= safe_atoi(optarg
, &arg_lines
);
600 if (r
< 0 || arg_lines
< 0)
601 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to parse lines '%s'", optarg
);
606 /* Hmm, no argument? Maybe the next
607 * word on the command line is
608 * supposed to be the argument? Let's
609 * see if there is one, and is
613 if (streq(argv
[optind
], "all")) {
614 arg_lines
= ARG_LINES_ALL
;
616 } else if (safe_atoi(argv
[optind
], &n
) >= 0 && n
>= 0) {
629 case ARG_TRUNCATE_NEWLINE
:
630 arg_truncate_newline
= true;
634 arg_action
= ACTION_NEW_ID128
;
647 arg_boot_id
= SD_ID128_NULL
;
653 arg_boot_id
= SD_ID128_NULL
;
657 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
659 return log_error_errno(r
, "Failed to parse boot descriptor '%s'", optarg
);
663 /* Hmm, no argument? Maybe the next
664 * word on the command line is
665 * supposed to be the argument? Let's
666 * see if there is one and is parsable
667 * as a boot descriptor... */
668 } else if (optind
< argc
) {
669 r
= parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
);
678 arg_action
= ACTION_LIST_BOOTS
;
682 arg_boot
= arg_dmesg
= true;
686 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
690 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
694 arg_machine
= optarg
;
698 if (streq(optarg
, "*")) {
699 arg_namespace_flags
= SD_JOURNAL_ALL_NAMESPACES
;
700 arg_namespace
= NULL
;
701 } else if (startswith(optarg
, "+")) {
702 arg_namespace_flags
= SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE
;
703 arg_namespace
= optarg
+ 1;
704 } else if (isempty(optarg
)) {
705 arg_namespace_flags
= 0;
706 arg_namespace
= NULL
;
708 arg_namespace_flags
= 0;
709 arg_namespace
= optarg
;
715 arg_directory
= optarg
;
719 if (streq(optarg
, "-"))
720 /* An undocumented feature: we can read journal files from STDIN. We don't document
721 * this though, since after all we only support this for mmap-able, seekable files, and
722 * not for example pipes which are probably the primary usecase for reading things from
723 * STDIN. To avoid confusion we hence don't document this feature. */
724 arg_file_stdin
= true;
726 r
= glob_extend(&arg_file
, optarg
, GLOB_NOCHECK
);
728 return log_error_errno(r
, "Failed to add paths: %m");
733 r
= parse_path_argument(optarg
, /* suppress_root= */ true, &arg_root
);
739 r
= parse_path_argument(optarg
, /* suppress_root= */ false, &arg_image
);
744 case ARG_IMAGE_POLICY
:
745 r
= parse_image_policy_argument(optarg
, &arg_image_policy
);
754 case ARG_CURSOR_FILE
:
755 arg_cursor_file
= optarg
;
758 case ARG_AFTER_CURSOR
:
759 arg_after_cursor
= optarg
;
762 case ARG_SHOW_CURSOR
:
763 arg_show_cursor
= true;
767 arg_action
= ACTION_PRINT_HEADER
;
771 arg_action
= ACTION_VERIFY
;
775 arg_action
= ACTION_DISK_USAGE
;
778 case ARG_VACUUM_SIZE
:
779 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
781 return log_error_errno(r
, "Failed to parse vacuum size: %s", optarg
);
783 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
786 case ARG_VACUUM_FILES
:
787 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
789 return log_error_errno(r
, "Failed to parse vacuum files: %s", optarg
);
791 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
794 case ARG_VACUUM_TIME
:
795 r
= parse_sec(optarg
, &arg_vacuum_time
);
797 return log_error_errno(r
, "Failed to parse vacuum time: %s", optarg
);
799 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
808 arg_action
= ACTION_SETUP_KEYS
;
812 r
= free_and_strdup(&arg_verify_key
, optarg
);
815 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
816 * in ps or htop output. */
817 memset(optarg
, 'x', strlen(optarg
));
819 arg_action
= ACTION_VERIFY
;
824 r
= parse_sec(optarg
, &arg_interval
);
825 if (r
< 0 || arg_interval
<= 0)
826 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
827 "Failed to parse sealing key change interval: %s", optarg
);
834 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
835 "Compiled without forward-secure sealing support.");
841 dots
= strstr(optarg
, "..");
843 _cleanup_free_
char *a
= NULL
;
847 a
= strndup(optarg
, dots
- optarg
);
851 from
= log_level_from_string(a
);
852 to
= log_level_from_string(dots
+ 2);
854 if (from
< 0 || to
< 0)
855 return log_error_errno(from
< 0 ? from
: to
,
856 "Failed to parse log level range %s", optarg
);
861 for (i
= from
; i
<= to
; i
++)
862 arg_priorities
|= 1 << i
;
864 for (i
= to
; i
<= from
; i
++)
865 arg_priorities
|= 1 << i
;
871 p
= log_level_from_string(optarg
);
873 return log_error_errno(p
, "Unknown log level %s", optarg
);
877 for (i
= 0; i
<= p
; i
++)
878 arg_priorities
|= 1 << i
;
888 _cleanup_free_
char *fac
= NULL
;
891 r
= extract_first_word(&p
, &fac
, ",", 0);
893 return log_error_errno(r
, "Failed to parse facilities: %s", optarg
);
897 if (streq(fac
, "help")) {
902 num
= log_facility_unshifted_from_string(fac
);
904 return log_error_errno(num
, "Bad --facility= argument \"%s\".", fac
);
906 if (set_ensure_put(&arg_facilities
, NULL
, INT_TO_PTR(num
)) < 0)
914 arg_pattern
= optarg
;
917 case ARG_CASE_SENSITIVE
:
919 r
= parse_boolean(optarg
);
921 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
922 arg_case
= r
? PATTERN_COMPILE_CASE_SENSITIVE
: PATTERN_COMPILE_CASE_INSENSITIVE
;
924 arg_case
= PATTERN_COMPILE_CASE_SENSITIVE
;
929 r
= parse_timestamp(optarg
, &arg_since
);
931 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
932 "Failed to parse timestamp: %s", optarg
);
933 arg_since_set
= true;
937 r
= parse_timestamp(optarg
, &arg_until
);
939 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
940 "Failed to parse timestamp: %s", optarg
);
941 arg_until_set
= true;
945 r
= strv_extend(&arg_syslog_identifier
, optarg
);
951 r
= strv_extend(&arg_system_units
, optarg
);
957 r
= strv_extend(&arg_user_units
, optarg
);
963 arg_action
= ACTION_LIST_FIELDS
;
968 arg_action
= ACTION_LIST_FIELD_NAMES
;
971 case ARG_NO_HOSTNAME
:
972 arg_no_hostname
= true;
979 case ARG_LIST_CATALOG
:
980 arg_action
= ACTION_LIST_CATALOG
;
983 case ARG_DUMP_CATALOG
:
984 arg_action
= ACTION_DUMP_CATALOG
;
987 case ARG_UPDATE_CATALOG
:
988 arg_action
= ACTION_UPDATE_CATALOG
;
1000 arg_action
= ACTION_FLUSH
;
1003 case ARG_SMART_RELINQUISH_VAR
: {
1004 int root_mnt_id
, log_mnt_id
;
1006 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
1007 * if it's on the same mount as the root file system there's no point in
1008 * relinquishing access and we can leave journald write to it until the very last
1011 r
= path_get_mnt_id("/", &root_mnt_id
);
1013 log_debug_errno(r
, "Failed to get root mount ID, ignoring: %m");
1015 r
= path_get_mnt_id("/var/log/journal/", &log_mnt_id
);
1017 log_debug_errno(r
, "Failed to get journal directory mount ID, ignoring: %m");
1018 else if (root_mnt_id
== log_mnt_id
) {
1019 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
1022 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
1028 case ARG_RELINQUISH_VAR
:
1029 arg_action
= ACTION_RELINQUISH_VAR
;
1033 arg_action
= arg_action
== ACTION_VACUUM
? ACTION_ROTATE_AND_VACUUM
: ACTION_ROTATE
;
1037 arg_action
= ACTION_SYNC
;
1040 case ARG_OUTPUT_FIELDS
: {
1041 _cleanup_strv_free_
char **v
= NULL
;
1043 v
= strv_split(optarg
, ",");
1047 r
= set_put_strdupv(&arg_output_fields
, v
);
1057 assert_not_reached();
1061 arg_lines
= ARG_LINES_ALL
;
1063 if (arg_follow
&& !arg_since_set
&& arg_lines
== ARG_LINES_DEFAULT
)
1066 if (arg_follow
&& !arg_merge
&& !arg_boot
) {
1068 arg_boot_id
= SD_ID128_NULL
;
1069 arg_boot_offset
= 0;
1072 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
+ !!arg_image
> 1)
1073 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1074 "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
1076 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
)
1077 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1078 "--since= must be before --until=.");
1080 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1)
1081 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1082 "Please specify only one of --since=, --cursor=, and --after-cursor=.");
1084 if (arg_follow
&& arg_reverse
)
1085 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1086 "Please specify either --reverse= or --follow=, not both.");
1088 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
)
1089 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1090 "Extraneous arguments starting with '%s'",
1093 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
)
1094 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1095 "Using --boot or --list-boots with --merge is not supported.");
1097 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
1098 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1099 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1100 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1101 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
1105 arg_system_units
= strv_free(arg_system_units
);
1109 r
= pattern_compile_and_log(arg_pattern
, arg_case
, &arg_compiled_pattern
);
1113 /* When --grep is used along with --lines, we don't know how many lines we can print.
1114 * So we search backwards and count until enough lines have been printed or we hit the head.
1115 * An exception is that --follow might set arg_lines, so let's not imply --reverse
1116 * if that is specified. */
1117 if (arg_lines
>= 0 && !arg_follow
)
1124 static int add_matches(sd_journal
*j
, char **args
) {
1125 bool have_term
= false;
1129 STRV_FOREACH(i
, args
) {
1132 if (streq(*i
, "+")) {
1135 r
= sd_journal_add_disjunction(j
);
1138 } else if (path_is_absolute(*i
)) {
1139 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1142 r
= chase(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
, NULL
);
1144 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1146 if (lstat(p
, &st
) < 0)
1147 return log_error_errno(errno
, "Couldn't stat file: %m");
1149 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1150 if (executable_is_script(p
, &interpreter
) > 0) {
1151 _cleanup_free_
char *comm
= NULL
;
1153 r
= path_extract_filename(p
, &comm
);
1155 return log_error_errno(r
, "Failed to extract filename of '%s': %m", p
);
1157 t
= strjoin("_COMM=", strshorten(comm
, TASK_COMM_LEN
-1));
1161 /* Append _EXE only if the interpreter is not a link.
1162 Otherwise, it might be outdated often. */
1163 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1164 t2
= strjoin("_EXE=", interpreter
);
1169 t
= strjoin("_EXE=", p
);
1174 r
= sd_journal_add_match(j
, t
, 0);
1177 r
= sd_journal_add_match(j
, t2
, 0);
1179 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1180 r
= add_matches_for_device(j
, p
);
1184 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1185 "File is neither a device node, nor regular file, nor executable: %s",
1190 r
= sd_journal_add_match(j
, *i
, 0);
1195 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1198 if (!strv_isempty(args
) && !have_term
)
1199 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1200 "\"+\" can only be used between terms");
1205 static int discover_next_boot(
1207 sd_id128_t previous_boot_id
,
1217 /* We expect the journal to be on the last position of a boot
1218 * (in relation to the direction we are going), so that the next
1219 * invocation of sd_journal_next/previous will be from a different
1220 * boot. We then collect any information we desire and then jump
1221 * to the last location of the new boot by using a _BOOT_ID match
1222 * coming from the other journal direction. */
1224 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1225 * we can actually advance to a *different* boot. */
1226 sd_journal_flush_matches(j
);
1230 r
= sd_journal_previous(j
);
1232 r
= sd_journal_next(j
);
1237 return 0; /* End of journal, yay. */
1240 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot
.id
);
1244 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1245 * normally, this will only require a single iteration, as we moved to the last entry of the previous
1246 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1247 * complete than the main entry array, and hence might reference an entry that's not actually the last
1248 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1249 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1252 } while (sd_id128_equal(boot
.id
, previous_boot_id
));
1254 r
= sd_journal_get_realtime_usec(j
, &boot
.first_usec
);
1258 /* Now seek to the last occurrence of this boot ID. */
1259 r
= add_match_boot_id(j
, boot
.id
);
1264 r
= sd_journal_seek_head(j
);
1266 r
= sd_journal_seek_tail(j
);
1271 r
= sd_journal_next(j
);
1273 r
= sd_journal_previous(j
);
1277 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA
),
1278 "Whoopsie! We found a boot ID but can't read its last entry."); /* This shouldn't happen. We just came from this very boot ID. */
1280 r
= sd_journal_get_realtime_usec(j
, &boot
.last_usec
);
1284 sd_journal_flush_matches(j
);
1289 static int find_boot_by_id(sd_journal
*j
) {
1294 sd_journal_flush_matches(j
);
1296 r
= add_match_boot_id(j
, arg_boot_id
);
1300 r
= sd_journal_seek_head(j
); /* seek to oldest */
1304 r
= sd_journal_next(j
); /* read the oldest entry */
1308 /* At this point the read pointer is positioned at the oldest occurrence of the reference boot ID.
1309 * After flushing the matches, one more invocation of _previous() will hence place us at the
1310 * following entry, which must then have an older boot ID */
1312 sd_journal_flush_matches(j
);
1316 static int find_boot_by_offset(sd_journal
*j
) {
1317 bool advance_older
, skip_once
;
1320 /* Adjust for the asymmetry that offset 0 is the last (and current) boot, while 1 is considered the
1321 * (chronological) first boot in the journal. */
1322 advance_older
= skip_once
= arg_boot_offset
<= 0;
1325 r
= sd_journal_seek_tail(j
); /* seek to newest */
1327 r
= sd_journal_seek_head(j
); /* seek to oldest */
1331 /* No sd_journal_next()/_previous() here.
1333 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1334 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1337 int offset
= arg_boot_offset
;
1338 sd_id128_t previous_boot_id
= SD_ID128_NULL
;
1342 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, &boot
);
1346 previous_boot_id
= boot
.id
;
1349 offset
+= advance_older
? 1 : -1;
1353 arg_boot_id
= boot
.id
;
1359 static int get_boots(sd_journal
*j
, BootId
**ret_boots
, size_t *ret_n_boots
) {
1360 _cleanup_free_ BootId
*boots
= NULL
;
1366 assert(ret_n_boots
);
1368 r
= sd_journal_seek_head(j
); /* seek to oldest */
1372 /* No sd_journal_next()/_previous() here.
1374 * At this point the read pointer is positioned before the oldest entry in the whole journal. The
1375 * next invocation of _next() will hence position us at the oldest entry we have. */
1377 sd_id128_t previous_boot_id
= SD_ID128_NULL
;
1381 r
= discover_next_boot(j
, previous_boot_id
, /* advance_older = */ false, &boot
);
1387 previous_boot_id
= boot
.id
;
1389 FOREACH_ARRAY(i
, boots
, n_boots
)
1390 if (sd_id128_equal(i
->id
, boot
.id
))
1391 /* The boot id is already stored, something wrong with the journal files.
1392 * Exiting as otherwise this problem would cause an infinite loop. */
1395 if (!GREEDY_REALLOC(boots
, n_boots
+ 1))
1398 boots
[n_boots
++] = boot
;
1401 *ret_boots
= TAKE_PTR(boots
);
1402 *ret_n_boots
= n_boots
;
1406 static int list_boots(sd_journal
*j
) {
1407 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1408 _cleanup_free_ BootId
*boots
= NULL
;
1414 r
= get_boots(j
, &boots
, &n_boots
);
1416 return log_error_errno(r
, "Failed to determine boots: %m");
1420 table
= table_new("idx", "boot id", "first entry", "last entry");
1425 table_set_width(table
, 0);
1427 r
= table_set_json_field_name(table
, 0, "index");
1429 return log_error_errno(r
, "Failed to set JSON field name of column 0: %m");
1431 (void) table_set_sort(table
, (size_t) 0);
1432 (void) table_set_reverse(table
, 0, arg_reverse
);
1434 FOREACH_ARRAY(i
, boots
, n_boots
) {
1435 r
= table_add_many(table
,
1436 TABLE_INT
, (int)(i
- boots
) - (int) n_boots
+ 1,
1437 TABLE_SET_ALIGN_PERCENT
, 100,
1439 TABLE_TIMESTAMP
, i
->first_usec
,
1440 TABLE_TIMESTAMP
, i
->last_usec
);
1442 return table_log_add_error(r
);
1445 r
= table_print_with_pager(table
, arg_json_format_flags
, arg_pager_flags
, !arg_quiet
);
1447 return table_log_print_error(r
);
1452 static int add_boot(sd_journal
*j
) {
1460 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1461 * We can do this only when we logs are coming from the current machine,
1462 * so take the slow path if log location is specified. */
1463 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1464 !arg_directory
&& !arg_file
&& !arg_root
)
1465 return add_match_this_boot(j
, arg_machine
);
1467 if (sd_id128_is_null(arg_boot_id
)) {
1468 r
= find_boot_by_offset(j
);
1470 return log_error_errno(r
, "Failed to find journal entry from the specified boot offset (%+i): %m",
1473 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1474 "No journal boot entry found from the specified boot offset (%+i).",
1477 r
= find_boot_by_id(j
);
1479 return log_error_errno(r
, "Failed to find journal entry from the specified boot ID (%s): %m",
1480 SD_ID128_TO_STRING(arg_boot_id
));
1482 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1483 "No journal boot entry found from the specified boot ID (%s).",
1484 SD_ID128_TO_STRING(arg_boot_id
));
1487 r
= add_match_boot_id(j
, arg_boot_id
);
1489 return log_error_errno(r
, "Failed to add match: %m");
1491 r
= sd_journal_add_conjunction(j
);
1493 return log_error_errno(r
, "Failed to add conjunction: %m");
1498 static int add_dmesg(sd_journal
*j
) {
1505 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1506 STRLEN("_TRANSPORT=kernel"));
1508 return log_error_errno(r
, "Failed to add match: %m");
1510 r
= sd_journal_add_conjunction(j
);
1512 return log_error_errno(r
, "Failed to add conjunction: %m");
1517 static int get_possible_units(
1523 _cleanup_set_free_free_ Set
*found
= NULL
;
1526 found
= set_new(&string_hash_ops
);
1530 NULSTR_FOREACH(field
, fields
) {
1534 r
= sd_journal_query_unique(j
, field
);
1538 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1541 _cleanup_free_
char *u
= NULL
;
1543 eq
= memchr(data
, '=', size
);
1545 prefix
= eq
- (char*) data
+ 1;
1549 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1553 STRV_FOREACH(pattern
, patterns
)
1554 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1555 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1557 r
= set_consume(found
, u
);
1559 if (r
< 0 && r
!= -EEXIST
)
1567 *units
= TAKE_PTR(found
);
1572 /* This list is supposed to return the superset of unit names
1573 * possibly matched by rules added with add_matches_for_unit... */
1574 #define SYSTEM_UNITS \
1578 "OBJECT_SYSTEMD_UNIT\0" \
1581 /* ... and add_matches_for_user_unit */
1582 #define USER_UNITS \
1583 "_SYSTEMD_USER_UNIT\0" \
1585 "COREDUMP_USER_UNIT\0" \
1586 "OBJECT_SYSTEMD_USER_UNIT\0" \
1587 "_SYSTEMD_USER_SLICE\0"
1589 static int add_units(sd_journal
*j
) {
1590 _cleanup_strv_free_
char **patterns
= NULL
;
1595 STRV_FOREACH(i
, arg_system_units
) {
1596 _cleanup_free_
char *u
= NULL
;
1598 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1602 if (string_is_glob(u
)) {
1603 r
= strv_push(&patterns
, u
);
1608 r
= add_matches_for_unit(j
, u
);
1611 r
= sd_journal_add_disjunction(j
);
1618 if (!strv_isempty(patterns
)) {
1619 _cleanup_set_free_free_ Set
*units
= NULL
;
1622 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1626 SET_FOREACH(u
, units
) {
1627 r
= add_matches_for_unit(j
, u
);
1630 r
= sd_journal_add_disjunction(j
);
1637 patterns
= strv_free(patterns
);
1639 STRV_FOREACH(i
, arg_user_units
) {
1640 _cleanup_free_
char *u
= NULL
;
1642 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1646 if (string_is_glob(u
)) {
1647 r
= strv_push(&patterns
, u
);
1652 r
= add_matches_for_user_unit(j
, u
, getuid());
1655 r
= sd_journal_add_disjunction(j
);
1662 if (!strv_isempty(patterns
)) {
1663 _cleanup_set_free_free_ Set
*units
= NULL
;
1666 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1670 SET_FOREACH(u
, units
) {
1671 r
= add_matches_for_user_unit(j
, u
, getuid());
1674 r
= sd_journal_add_disjunction(j
);
1681 /* Complain if the user request matches but nothing whatsoever was
1682 * found, since otherwise everything would be matched. */
1683 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1686 r
= sd_journal_add_conjunction(j
);
1693 static int add_priorities(sd_journal
*j
) {
1694 char match
[] = "PRIORITY=0";
1698 if (arg_priorities
== 0xFF)
1701 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1702 if (arg_priorities
& (1 << i
)) {
1703 match
[sizeof(match
)-2] = '0' + i
;
1705 r
= sd_journal_add_match(j
, match
, strlen(match
));
1707 return log_error_errno(r
, "Failed to add match: %m");
1710 r
= sd_journal_add_conjunction(j
);
1712 return log_error_errno(r
, "Failed to add conjunction: %m");
1717 static int add_facilities(sd_journal
*j
) {
1721 SET_FOREACH(p
, arg_facilities
) {
1722 char match
[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
1724 xsprintf(match
, "SYSLOG_FACILITY=%d", PTR_TO_INT(p
));
1726 r
= sd_journal_add_match(j
, match
, strlen(match
));
1728 return log_error_errno(r
, "Failed to add match: %m");
1734 static int add_syslog_identifier(sd_journal
*j
) {
1739 STRV_FOREACH(i
, arg_syslog_identifier
) {
1740 _cleanup_free_
char *u
= NULL
;
1742 u
= strjoin("SYSLOG_IDENTIFIER=", *i
);
1745 r
= sd_journal_add_match(j
, u
, 0);
1748 r
= sd_journal_add_disjunction(j
);
1753 r
= sd_journal_add_conjunction(j
);
1761 static int format_journal_url(
1771 _cleanup_(memstream_done
) MemStream m
= {};
1775 assert(seed_size
> 0);
1777 f
= memstream_init(&m
);
1784 for (size_t i
= 0; i
< seed_size
; i
++) {
1785 if (i
> 0 && i
% 3 == 0)
1787 fprintf(f
, "%02x", ((uint8_t*) seed
)[i
]);
1790 fprintf(f
, "/%"PRIx64
"-%"PRIx64
, start
, interval
);
1793 fprintf(f
, "?machine=" SD_ID128_FORMAT_STR
, SD_ID128_FORMAT_VAL(machine
));
1795 fprintf(f
, ";hostname=%s", hn
);
1798 return memstream_finalize(&m
, ret_url
, NULL
);
1802 static int setup_keys(void) {
1804 size_t mpk_size
, seed_size
, state_size
;
1805 _cleanup_(unlink_and_freep
) char *k
= NULL
;
1806 _cleanup_free_
char *p
= NULL
;
1807 uint8_t *mpk
, *seed
, *state
;
1808 _cleanup_close_
int fd
= -EBADF
;
1809 sd_id128_t machine
, boot
;
1814 r
= stat("/var/log/journal", &st
);
1815 if (r
< 0 && !IN_SET(errno
, ENOENT
, ENOTDIR
))
1816 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1818 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1819 log_error("%s is not a directory, must be using persistent logging for FSS.",
1820 "/var/log/journal");
1821 return r
< 0 ? -errno
: -ENOTDIR
;
1824 r
= sd_id128_get_machine(&machine
);
1826 return log_error_errno(r
, "Failed to get machine ID: %m");
1828 r
= sd_id128_get_boot(&boot
);
1830 return log_error_errno(r
, "Failed to get boot ID: %m");
1832 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1833 SD_ID128_FORMAT_VAL(machine
)) < 0)
1838 if (r
< 0 && errno
!= ENOENT
)
1839 return log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1840 } else if (access(p
, F_OK
) >= 0)
1841 return log_error_errno(SYNTHETIC_ERRNO(EEXIST
),
1842 "Sealing key file %s exists already. Use --force to recreate.", p
);
1844 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1845 SD_ID128_FORMAT_VAL(machine
)) < 0)
1848 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1849 mpk
= alloca_safe(mpk_size
);
1851 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1852 seed
= alloca_safe(seed_size
);
1854 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1855 state
= alloca_safe(state_size
);
1857 log_info("Generating seed...");
1858 r
= crypto_random_bytes(seed
, seed_size
);
1860 return log_error_errno(r
, "Failed to acquire random seed: %m");
1862 log_info("Generating key pair...");
1863 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1865 log_info("Generating sealing key...");
1866 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1868 assert(arg_interval
> 0);
1870 n
= now(CLOCK_REALTIME
);
1874 fd
= mkostemp_safe(k
);
1876 return log_error_errno(fd
, "Failed to open %s: %m", k
);
1878 r
= chattr_secret(fd
, CHATTR_WARN_UNSUPPORTED_FLAGS
);
1880 log_full_errno(ERRNO_IS_NOT_SUPPORTED(r
) ? LOG_DEBUG
: LOG_WARNING
,
1881 r
, "Failed to set file attributes on '%s', ignoring: %m", k
);
1883 struct FSSHeader h
= {
1884 .signature
= { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' },
1885 .machine_id
= machine
,
1887 .header_size
= htole64(sizeof(h
)),
1888 .start_usec
= htole64(n
* arg_interval
),
1889 .interval_usec
= htole64(arg_interval
),
1890 .fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
),
1891 .fsprg_state_size
= htole64(state_size
),
1894 r
= loop_write(fd
, &h
, sizeof(h
), false);
1896 return log_error_errno(r
, "Failed to write header: %m");
1898 r
= loop_write(fd
, state
, state_size
, false);
1900 return log_error_errno(r
, "Failed to write state: %m");
1902 if (rename(k
, p
) < 0)
1903 return log_error_errno(errno
, "Failed to link file: %m");
1907 _cleanup_free_
char *hn
= NULL
, *key
= NULL
;
1909 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, false, &key
);
1914 hn
= gethostname_malloc();
1916 hostname_cleanup(hn
);
1919 "\nNew keys have been generated for host %s%s" SD_ID128_FORMAT_STR
".\n"
1921 "The %ssecret sealing key%s has been written to the following local file.\n"
1922 "This key file is automatically updated when the sealing key is advanced.\n"
1923 "It should not be used on multiple hosts.\n"
1927 "The sealing key is automatically changed every %s.\n"
1929 "Please write down the following %ssecret verification key%s. It should be stored\n"
1930 "in a safe location and should not be saved locally on disk.\n"
1932 strempty(hn
), hn
? "/" : "",
1933 SD_ID128_FORMAT_VAL(machine
),
1934 ansi_highlight(), ansi_normal(),
1936 FORMAT_TIMESPAN(arg_interval
, 0),
1937 ansi_highlight(), ansi_normal(),
1938 ansi_highlight_red());
1945 fprintf(stderr
, "%s", ansi_normal());
1947 _cleanup_free_
char *url
= NULL
;
1948 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, true, &url
);
1952 (void) print_qrcode(stderr
,
1953 "To transfer the verification key to your phone scan the QR code below",
1960 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1961 "Forward-secure sealing not available.");
1965 static int verify(sd_journal
*j
, bool verbose
) {
1971 log_show_color(true);
1973 ORDERED_HASHMAP_FOREACH(f
, j
->files
) {
1975 usec_t first
= 0, validated
= 0, last
= 0;
1978 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1979 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1982 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, verbose
);
1984 /* If the key was invalid give up right-away. */
1987 r
= log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
1989 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
1990 log_full(verbose
? LOG_INFO
: LOG_DEBUG
, "PASS: %s", f
->path
);
1992 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
1993 if (validated
> 0) {
1994 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1995 "=> Validated from %s to %s, final %s entries not sealed.",
1996 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
1997 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
1998 FORMAT_TIMESPAN(last
> validated
? last
- validated
: 0, 0));
1999 } else if (last
> 0)
2000 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2001 "=> No sealing yet, %s of entries not sealed.",
2002 FORMAT_TIMESPAN(last
- first
, 0));
2004 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2005 "=> No sealing yet, no entries in file.");
2013 static int simple_varlink_call(const char *option
, const char *method
) {
2014 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
2015 const char *error
, *fn
;
2019 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "%s is not supported in conjunction with --machine=.", option
);
2021 fn
= arg_namespace
?
2022 strjoina("/run/systemd/journal.", arg_namespace
, "/io.systemd.journal") :
2023 "/run/systemd/journal/io.systemd.journal";
2025 r
= varlink_connect_address(&link
, fn
);
2027 return log_error_errno(r
, "Failed to connect to %s: %m", fn
);
2029 (void) varlink_set_description(link
, "journal");
2030 (void) varlink_set_relative_timeout(link
, USEC_INFINITY
);
2032 r
= varlink_call(link
, method
, NULL
, NULL
, &error
, NULL
);
2034 return log_error_errno(r
, "Failed to execute varlink call: %m");
2036 return log_error_errno(SYNTHETIC_ERRNO(ENOANO
),
2037 "Failed to execute varlink call: %s", error
);
2042 static int flush_to_var(void) {
2043 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
2044 return 0; /* Already flushed, no need to contact journald */
2045 if (errno
!= ENOENT
)
2046 return log_error_errno(errno
, "Unable to check for existence of /run/systemd/journal/flushed: %m");
2048 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
2051 static int relinquish_var(void) {
2052 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
2055 static int rotate(void) {
2056 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
2059 static int sync_journal(void) {
2060 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
2063 static int action_list_fields(sd_journal
*j
) {
2070 r
= sd_journal_set_data_threshold(j
, 0);
2072 return log_error_errno(r
, "Failed to unset data size threshold: %m");
2074 r
= sd_journal_query_unique(j
, arg_field
);
2076 return log_error_errno(r
, "Failed to query unique data objects: %m");
2078 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2081 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2084 eq
= memchr(data
, '=', size
);
2086 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2088 printf("%.*s\n", (int) size
, (const char*) data
);
2096 static int update_cursor(sd_journal
*j
) {
2097 _cleanup_free_
char *cursor
= NULL
;
2102 if (!arg_show_cursor
&& !arg_cursor_file
)
2105 r
= sd_journal_get_cursor(j
, &cursor
);
2106 if (r
== -EADDRNOTAVAIL
)
2109 return log_error_errno(r
, "Failed to get cursor: %m");
2111 if (arg_show_cursor
)
2112 printf("-- cursor: %s\n", cursor
);
2114 if (arg_cursor_file
) {
2115 r
= write_string_file(arg_cursor_file
, cursor
, WRITE_STRING_FILE_CREATE
| WRITE_STRING_FILE_ATOMIC
);
2117 return log_error_errno(r
, "Failed to write new cursor to %s: %m", arg_cursor_file
);
2123 typedef struct Context
{
2124 sd_journal
*journal
;
2128 bool previous_boot_id_valid
;
2129 sd_id128_t previous_boot_id
;
2130 sd_id128_t previous_boot_id_output
;
2131 dual_timestamp previous_ts_output
;
2134 static int show(Context
*c
) {
2140 j
= ASSERT_PTR(c
->journal
);
2142 while (arg_lines
< 0 || n_shown
< arg_lines
|| arg_follow
) {
2144 size_t highlight
[2] = {};
2147 r
= sd_journal_step_one(j
, !arg_reverse
);
2149 return log_error_errno(r
, "Failed to iterate through journal: %m");
2154 if (arg_until_set
&& !arg_reverse
&& (arg_lines
< 0 || arg_since_set
)) {
2155 /* If --lines= is set, we usually rely on the n_shown to tell us
2156 * when to stop. However, if --since= is set too, we may end up
2157 * having less than --lines= to output. In this case let's also
2158 * check if the entry is in range. */
2162 r
= sd_journal_get_realtime_usec(j
, &usec
);
2164 return log_error_errno(r
, "Failed to determine timestamp: %m");
2165 if (usec
> arg_until
)
2169 if (arg_since_set
&& (arg_reverse
|| !c
->since_seeked
)) {
2172 r
= sd_journal_get_realtime_usec(j
, &usec
);
2174 return log_error_errno(r
, "Failed to determine timestamp: %m");
2176 if (usec
< arg_since
) {
2178 break; /* Reached the earliest entry */
2180 /* arg_lines >= 0 (!since_seeked):
2181 * We jumped arg_lines back and it seems to be too much */
2182 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2184 return log_error_errno(r
, "Failed to seek to date: %m");
2185 c
->since_seeked
= true;
2187 c
->need_seek
= true;
2190 c
->since_seeked
= true; /* We're surely within the range of --since now */
2193 if (!arg_merge
&& !arg_quiet
) {
2196 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2198 if (c
->previous_boot_id_valid
&&
2199 !sd_id128_equal(boot_id
, c
->previous_boot_id
))
2200 printf("%s-- Boot "SD_ID128_FORMAT_STR
" --%s\n",
2201 ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id
), ansi_normal());
2203 c
->previous_boot_id
= boot_id
;
2204 c
->previous_boot_id_valid
= true;
2208 if (arg_compiled_pattern
) {
2209 const void *message
;
2212 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2215 c
->need_seek
= true;
2219 return log_error_errno(r
, "Failed to get MESSAGE field: %m");
2222 assert_se(message
= startswith(message
, "MESSAGE="));
2224 r
= pattern_matches_and_log(arg_compiled_pattern
, message
,
2225 len
- strlen("MESSAGE="), highlight
);
2229 c
->need_seek
= true;
2235 arg_all
* OUTPUT_SHOW_ALL
|
2236 arg_full
* OUTPUT_FULL_WIDTH
|
2237 colors_enabled() * OUTPUT_COLOR
|
2238 arg_catalog
* OUTPUT_CATALOG
|
2239 arg_utc
* OUTPUT_UTC
|
2240 arg_truncate_newline
* OUTPUT_TRUNCATE_NEWLINE
|
2241 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2243 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2244 arg_output_fields
, highlight
, &c
->ellipsized
,
2245 &c
->previous_ts_output
, &c
->previous_boot_id_output
);
2246 c
->need_seek
= true;
2247 if (r
== -EADDRNOTAVAIL
)
2254 /* If journalctl take a long time to process messages, and during that time journal file
2255 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2256 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2257 * in the "following" case. By periodically calling sd_journal_process() during the processing
2258 * loop we shrink the window of time a client instance has open file descriptors for rotated
2259 * (deleted) journal files. */
2260 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2261 r
= sd_journal_process(j
);
2263 return log_error_errno(r
, "Failed to process inotify events: %m");
2270 static int show_and_fflush(Context
*c
, sd_event_source
*s
) {
2278 return sd_event_exit(sd_event_source_get_event(s
), r
);
2284 static int on_journal_event(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
2285 Context
*c
= ASSERT_PTR(userdata
);
2290 r
= sd_journal_process(c
->journal
);
2292 log_error_errno(r
, "Failed to process journal events: %m");
2293 return sd_event_exit(sd_event_source_get_event(s
), r
);
2296 return show_and_fflush(c
, s
);
2299 static int on_first_event(sd_event_source
*s
, void *userdata
) {
2300 return show_and_fflush(userdata
, s
);
2303 static int on_signal(sd_event_source
*s
, const struct signalfd_siginfo
*si
, void *userdata
) {
2306 assert(IN_SET(si
->ssi_signo
, SIGTERM
, SIGINT
));
2308 return sd_event_exit(sd_event_source_get_event(s
), si
->ssi_signo
);
2311 static int setup_event(Context
*c
, int fd
, sd_event
**ret
) {
2312 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
2320 r
= sd_event_default(&e
);
2322 return log_error_errno(r
, "Failed to allocate sd_event object: %m");
2324 (void) sd_event_add_signal(e
, NULL
, SIGTERM
| SD_EVENT_SIGNAL_PROCMASK
, on_signal
, NULL
);
2325 (void) sd_event_add_signal(e
, NULL
, SIGINT
| SD_EVENT_SIGNAL_PROCMASK
, on_signal
, NULL
);
2327 r
= sd_event_add_io(e
, NULL
, fd
, EPOLLIN
, &on_journal_event
, c
);
2329 return log_error_errno(r
, "Failed to add io event source for journal: %m");
2331 /* Also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that, i.e. when it is closed. */
2332 r
= sd_event_add_io(e
, NULL
, STDOUT_FILENO
, EPOLLHUP
|EPOLLERR
, NULL
, INT_TO_PTR(-ECANCELED
));
2334 return log_error_errno(r
, "Failed to add io event source for stdout: %m");
2336 if (arg_lines
!= 0 || arg_since_set
) {
2337 r
= sd_event_add_defer(e
, NULL
, on_first_event
, c
);
2339 return log_error_errno(r
, "Failed to add defer event source: %m");
2346 static int run(int argc
, char *argv
[]) {
2347 bool need_seek
= false, since_seeked
= false, use_cursor
= false, after_cursor
= false;
2348 _cleanup_(loop_device_unrefp
) LoopDevice
*loop_device
= NULL
;
2349 _cleanup_(umount_and_freep
) char *mounted_dir
= NULL
;
2350 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2351 int n_shown
, r
, poll_fd
= -EBADF
;
2353 setlocale(LC_ALL
, "");
2356 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2357 * split up into many files. */
2358 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE
);
2360 r
= parse_argv(argc
, argv
);
2367 r
= mount_image_privately_interactively(
2370 DISSECT_IMAGE_GENERIC_ROOT
|
2371 DISSECT_IMAGE_REQUIRE_ROOT
|
2372 DISSECT_IMAGE_VALIDATE_OS
|
2373 DISSECT_IMAGE_RELAX_VAR_CHECK
|
2374 (arg_action
== ACTION_UPDATE_CATALOG
? DISSECT_IMAGE_FSCK
|DISSECT_IMAGE_GROWFS
: DISSECT_IMAGE_READ_ONLY
),
2376 /* ret_dir_fd= */ NULL
,
2381 arg_root
= strdup(mounted_dir
);
2386 signal(SIGWINCH
, columns_lines_cache_reset
);
2389 switch (arg_action
) {
2391 case ACTION_NEW_ID128
:
2392 return id128_print_new(ID128_PRINT_PRETTY
);
2394 case ACTION_SETUP_KEYS
:
2395 return setup_keys();
2397 case ACTION_LIST_CATALOG
:
2398 case ACTION_DUMP_CATALOG
:
2399 case ACTION_UPDATE_CATALOG
: {
2400 _cleanup_free_
char *database
= NULL
;
2402 database
= path_join(arg_root
, secure_getenv("SYSTEMD_CATALOG") ?: CATALOG_DATABASE
);
2406 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2409 e
= secure_getenv("SYSTEMD_CATALOG_SOURCES");
2414 e
? (const char* const*) STRV_MAKE(e
) : catalog_file_dirs
);
2416 return log_error_errno(r
, "Failed to list catalog: %m");
2418 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2420 pager_open(arg_pager_flags
);
2423 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2425 r
= catalog_list(stdout
, database
, oneline
);
2427 return log_error_errno(r
, "Failed to list catalog: %m");
2434 return flush_to_var();
2436 case ACTION_RELINQUISH_VAR
:
2437 return relinquish_var();
2440 return sync_journal();
2446 case ACTION_PRINT_HEADER
:
2448 case ACTION_DISK_USAGE
:
2449 case ACTION_LIST_BOOTS
:
2451 case ACTION_ROTATE_AND_VACUUM
:
2452 case ACTION_LIST_FIELDS
:
2453 case ACTION_LIST_FIELD_NAMES
:
2454 /* These ones require access to the journal files, continue below. */
2458 assert_not_reached();
2462 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2464 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| SD_JOURNAL_OS_ROOT
);
2465 else if (arg_file_stdin
)
2466 r
= sd_journal_open_files_fd(&j
, (int[]) { STDIN_FILENO
}, 1, 0);
2468 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2469 else if (arg_machine
)
2470 r
= journal_open_machine(&j
, arg_machine
);
2472 r
= sd_journal_open_namespace(
2475 (arg_merge
? 0 : SD_JOURNAL_LOCAL_ONLY
) |
2476 arg_namespace_flags
| arg_journal_type
);
2478 return log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2480 r
= journal_access_check_and_warn(j
, arg_quiet
,
2481 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2485 switch (arg_action
) {
2487 case ACTION_NEW_ID128
:
2488 case ACTION_SETUP_KEYS
:
2489 case ACTION_LIST_CATALOG
:
2490 case ACTION_DUMP_CATALOG
:
2491 case ACTION_UPDATE_CATALOG
:
2495 assert_not_reached();
2497 case ACTION_PRINT_HEADER
:
2498 journal_print_header(j
);
2502 return verify(j
, !arg_quiet
);
2504 case ACTION_DISK_USAGE
: {
2507 r
= sd_journal_get_usage(j
, &bytes
);
2511 printf("Archived and active journals take up %s in the file system.\n",
2512 FORMAT_BYTES(bytes
));
2517 case ACTION_LIST_BOOTS
:
2518 return list_boots(j
);
2520 case ACTION_ROTATE_AND_VACUUM
:
2528 case ACTION_VACUUM
: {
2532 HASHMAP_FOREACH(d
, j
->directories_by_path
) {
2533 r
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2535 log_error_errno(r
, "Failed to vacuum %s: %m", d
->path
);
2544 case ACTION_LIST_FIELD_NAMES
: {
2547 SD_JOURNAL_FOREACH_FIELD(j
, field
)
2548 printf("%s\n", field
);
2554 case ACTION_LIST_FIELDS
:
2558 assert_not_reached();
2561 if (arg_boot_offset
!= 0 &&
2562 sd_journal_has_runtime_files(j
) > 0 &&
2563 sd_journal_has_persistent_files(j
) == 0) {
2564 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2566 if (arg_action
== ACTION_SHOW
&& arg_compiled_pattern
)
2571 /* add_boot() must be called first!
2572 * It may need to seek the journal to find parent boot IDs. */
2583 return log_error_errno(r
, "Failed to add filter for units: %m");
2585 r
= add_syslog_identifier(j
);
2587 return log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2589 r
= add_priorities(j
);
2593 r
= add_facilities(j
);
2597 r
= add_matches(j
, argv
+ optind
);
2601 if (DEBUG_LOGGING
) {
2602 _cleanup_free_
char *filter
= NULL
;
2604 filter
= journal_make_match_string(j
);
2608 log_debug("Journal filter: %s", filter
);
2611 if (arg_action
== ACTION_LIST_FIELDS
)
2612 return action_list_fields(j
);
2614 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2616 poll_fd
= sd_journal_get_fd(j
);
2617 if (poll_fd
== -EMFILE
) {
2618 log_warning_errno(poll_fd
, "Insufficient watch descriptors available. Reverting to -n.");
2620 } else if (poll_fd
== -EMEDIUMTYPE
)
2621 return log_error_errno(poll_fd
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2622 else if (poll_fd
< 0)
2623 return log_error_errno(poll_fd
, "Failed to get journal fd: %m");
2626 if (arg_cursor
|| arg_after_cursor
|| arg_cursor_file
) {
2627 _cleanup_free_
char *cursor_from_file
= NULL
;
2628 const char *cursor
= arg_cursor
?: arg_after_cursor
;
2630 if (arg_cursor_file
) {
2631 r
= read_one_line_file(arg_cursor_file
, &cursor_from_file
);
2632 if (r
< 0 && r
!= -ENOENT
)
2633 return log_error_errno(r
, "Failed to read cursor file %s: %m", arg_cursor_file
);
2636 cursor
= cursor_from_file
;
2637 after_cursor
= true;
2640 after_cursor
= arg_after_cursor
;
2643 r
= sd_journal_seek_cursor(j
, cursor
);
2645 return log_error_errno(r
, "Failed to seek to cursor: %m");
2653 r
= sd_journal_next_skip(j
, 1 + after_cursor
);
2655 r
= sd_journal_previous_skip(j
, 1 + after_cursor
);
2657 if (after_cursor
&& r
< 2) {
2658 /* We couldn't find the next entry after the cursor. */
2665 } else if (arg_until_set
&& (arg_reverse
|| arg_lines
>= 0)) {
2666 /* If both --until and any of --reverse and --lines is specified, things get
2667 * a little tricky. We seek to the place of --until first. If only --reverse or
2668 * --reverse and --lines is specified, we search backwards and let the output
2669 * counter handle --lines for us. If only --lines is used, we just jump backwards
2670 * arg_lines and search afterwards from there. */
2672 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2674 return log_error_errno(r
, "Failed to seek to date: %m");
2677 r
= sd_journal_previous(j
);
2678 else /* arg_lines >= 0 */
2679 r
= sd_journal_previous_skip(j
, arg_lines
);
2681 } else if (arg_reverse
) {
2682 r
= sd_journal_seek_tail(j
);
2684 return log_error_errno(r
, "Failed to seek to tail: %m");
2686 r
= sd_journal_previous(j
);
2688 } else if (arg_lines
>= 0) {
2689 r
= sd_journal_seek_tail(j
);
2691 return log_error_errno(r
, "Failed to seek to tail: %m");
2693 r
= sd_journal_previous_skip(j
, arg_lines
);
2695 } else if (arg_since_set
) {
2696 /* This is placed after arg_reverse and arg_lines. If --since is used without
2697 * both, we seek to the place of --since and search afterwards from there.
2698 * If used with --reverse or --lines, we seek to the tail first and check if
2699 * the entry is within the range of --since later. */
2701 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2703 return log_error_errno(r
, "Failed to seek to date: %m");
2704 since_seeked
= true;
2706 r
= sd_journal_next(j
);
2709 r
= sd_journal_seek_head(j
);
2711 return log_error_errno(r
, "Failed to seek to head: %m");
2713 r
= sd_journal_next(j
);
2716 return log_error_errno(r
, "Failed to iterate through journal: %m");
2721 pager_open(arg_pager_flags
);
2723 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
) && DEBUG_LOGGING
) {
2725 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2727 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2729 return log_error_errno(r
, "Failed to get cutoff: %m");
2732 printf("-- Journal begins at %s. --\n",
2733 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2735 printf("-- Journal begins at %s, ends at %s. --\n",
2736 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2737 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2743 .need_seek
= need_seek
,
2744 .since_seeked
= since_seeked
,
2748 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
2751 assert(poll_fd
>= 0);
2753 r
= setup_event(&c
, poll_fd
, &e
);
2757 r
= sd_event_loop(e
);
2762 /* unref signal event sources. */
2763 e
= sd_event_unref(e
);
2765 r
= update_cursor(j
);
2769 /* re-send the original signal. */
2770 assert(SIGNAL_VALID(sig
));
2772 log_error("Failed to raise the original signal SIG%s, ignoring: %m", signal_to_string(sig
));
2782 if (n_shown
== 0 && !arg_quiet
)
2783 printf("-- No entries --\n");
2785 r
= update_cursor(j
);
2789 if (arg_compiled_pattern
&& n_shown
== 0)
2790 /* --grep was used, no error was thrown, but the pattern didn't
2791 * match anything. Let's mimic grep's behavior here and return
2792 * a non-zero exit code, so journalctl --grep can be used
2793 * in scripts and such */
2799 DEFINE_MAIN_FUNCTION(run
);