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 "missing_sched.h"
54 #include "mount-util.h"
55 #include "mountpoint-util.h"
56 #include "nulstr-util.h"
58 #include "parse-argument.h"
59 #include "parse-util.h"
60 #include "path-util.h"
61 #include "pcre2-util.h"
62 #include "pretty-print.h"
63 #include "qrcode-util.h"
64 #include "random-util.h"
65 #include "rlimit-util.h"
68 #include "static-destruct.h"
69 #include "stdio-util.h"
70 #include "string-table.h"
72 #include "syslog-util.h"
73 #include "terminal-util.h"
74 #include "tmpfile-util.h"
75 #include "unit-name.h"
76 #include "user-util.h"
79 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
80 #define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */
83 /* Special values for arg_lines */
84 ARG_LINES_DEFAULT
= -2,
88 static OutputMode arg_output
= OUTPUT_SHORT
;
89 static JsonFormatFlags arg_json_format_flags
= JSON_FORMAT_OFF
;
90 static bool arg_utc
= false;
91 static bool arg_follow
= false;
92 static bool arg_full
= true;
93 static bool arg_all
= false;
94 static PagerFlags arg_pager_flags
= 0;
95 static int arg_lines
= ARG_LINES_DEFAULT
;
96 static bool arg_no_tail
= false;
97 static bool arg_quiet
= false;
98 static bool arg_merge
= false;
99 static bool arg_boot
= false;
100 static sd_id128_t arg_boot_id
= {};
101 static int arg_boot_offset
= 0;
102 static bool arg_dmesg
= false;
103 static bool arg_no_hostname
= false;
104 static const char *arg_cursor
= NULL
;
105 static const char *arg_cursor_file
= NULL
;
106 static const char *arg_after_cursor
= NULL
;
107 static bool arg_show_cursor
= false;
108 static const char *arg_directory
= NULL
;
109 static char **arg_file
= NULL
;
110 static bool arg_file_stdin
= false;
111 static int arg_priorities
= 0xFF;
112 static Set
*arg_facilities
= NULL
;
113 static char *arg_verify_key
= NULL
;
115 static usec_t arg_interval
= DEFAULT_FSS_INTERVAL_USEC
;
116 static bool arg_force
= false;
118 static usec_t arg_since
= 0, arg_until
= 0;
119 static bool arg_since_set
= false, arg_until_set
= false;
120 static char **arg_syslog_identifier
= NULL
;
121 static char **arg_system_units
= NULL
;
122 static char **arg_user_units
= NULL
;
123 static const char *arg_field
= NULL
;
124 static bool arg_catalog
= false;
125 static bool arg_reverse
= false;
126 static int arg_journal_type
= 0;
127 static int arg_namespace_flags
= 0;
128 static char *arg_root
= NULL
;
129 static char *arg_image
= NULL
;
130 static const char *arg_machine
= NULL
;
131 static const char *arg_namespace
= NULL
;
132 static uint64_t arg_vacuum_size
= 0;
133 static uint64_t arg_vacuum_n_files
= 0;
134 static usec_t arg_vacuum_time
= 0;
135 static Set
*arg_output_fields
= NULL
;
136 static const char *arg_pattern
= NULL
;
137 static pcre2_code
*arg_compiled_pattern
= NULL
;
138 static PatternCompileCase arg_case
= PATTERN_COMPILE_CASE_AUTO
;
139 ImagePolicy
*arg_image_policy
= NULL
;
141 STATIC_DESTRUCTOR_REGISTER(arg_file
, strv_freep
);
142 STATIC_DESTRUCTOR_REGISTER(arg_facilities
, set_freep
);
143 STATIC_DESTRUCTOR_REGISTER(arg_verify_key
, freep
);
144 STATIC_DESTRUCTOR_REGISTER(arg_syslog_identifier
, strv_freep
);
145 STATIC_DESTRUCTOR_REGISTER(arg_system_units
, strv_freep
);
146 STATIC_DESTRUCTOR_REGISTER(arg_user_units
, strv_freep
);
147 STATIC_DESTRUCTOR_REGISTER(arg_root
, freep
);
148 STATIC_DESTRUCTOR_REGISTER(arg_image
, freep
);
149 STATIC_DESTRUCTOR_REGISTER(arg_output_fields
, set_freep
);
150 STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern
, pattern_freep
);
151 STATIC_DESTRUCTOR_REGISTER(arg_image_policy
, image_policy_freep
);
162 ACTION_UPDATE_CATALOG
,
165 ACTION_RELINQUISH_VAR
,
169 ACTION_ROTATE_AND_VACUUM
,
171 ACTION_LIST_FIELD_NAMES
,
172 } arg_action
= ACTION_SHOW
;
174 typedef struct BootId
{
180 static int add_matches_for_device(sd_journal
*j
, const char *devpath
) {
181 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
189 if (!path_startswith(devpath
, "/dev/"))
190 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
191 "Devpath does not start with /dev/");
193 if (stat(devpath
, &st
) < 0)
194 return log_error_errno(errno
, "Couldn't stat file: %m");
196 r
= sd_device_new_from_stat_rdev(&device
, &st
);
198 return log_error_errno(r
, "Failed to get device from devnum " DEVNUM_FORMAT_STR
": %m", DEVNUM_FORMAT_VAL(st
.st_rdev
));
200 for (d
= device
; d
; ) {
201 _cleanup_free_
char *match
= NULL
;
202 const char *subsys
, *sysname
, *devnode
;
205 r
= sd_device_get_subsystem(d
, &subsys
);
209 r
= sd_device_get_sysname(d
, &sysname
);
213 match
= strjoin("_KERNEL_DEVICE=+", subsys
, ":", sysname
);
217 r
= sd_journal_add_match(j
, match
, 0);
219 return log_error_errno(r
, "Failed to add match: %m");
221 if (sd_device_get_devname(d
, &devnode
) >= 0) {
222 _cleanup_free_
char *match1
= NULL
;
224 r
= stat(devnode
, &st
);
226 return log_error_errno(r
, "Failed to stat() device node \"%s\": %m", devnode
);
228 r
= asprintf(&match1
, "_KERNEL_DEVICE=%c" DEVNUM_FORMAT_STR
, S_ISBLK(st
.st_mode
) ? 'b' : 'c', DEVNUM_FORMAT_VAL(st
.st_rdev
));
232 r
= sd_journal_add_match(j
, match1
, 0);
234 return log_error_errno(r
, "Failed to add match: %m");
238 if (sd_device_get_parent(d
, &parent
) < 0)
244 r
= add_match_this_boot(j
, arg_machine
);
246 return log_error_errno(r
, "Failed to add match for the current boot: %m");
251 static char *format_timestamp_maybe_utc(char *buf
, size_t l
, usec_t t
) {
254 return format_timestamp_style(buf
, l
, t
, TIMESTAMP_UTC
);
256 return format_timestamp(buf
, l
, t
);
259 static int parse_boot_descriptor(const char *x
, sd_id128_t
*boot_id
, int *offset
) {
260 sd_id128_t id
= SD_ID128_NULL
;
263 if (streq(x
, "all")) {
264 *boot_id
= SD_ID128_NULL
;
267 } else if (strlen(x
) >= SD_ID128_STRING_MAX
- 1) {
270 t
= strndupa_safe(x
, SD_ID128_STRING_MAX
- 1);
271 r
= sd_id128_from_string(t
, &id
);
273 x
+= SD_ID128_STRING_MAX
- 1;
275 if (!IN_SET(*x
, 0, '-', '+'))
279 r
= safe_atoi(x
, &off
);
284 r
= safe_atoi(x
, &off
);
298 static int help_facilities(void) {
300 puts("Available facilities:");
302 for (int i
= 0; i
< LOG_NFACILITIES
; i
++) {
303 _cleanup_free_
char *t
= NULL
;
305 if (log_facility_unshifted_to_string_alloc(i
, &t
))
313 static int help(void) {
314 _cleanup_free_
char *link
= NULL
;
317 pager_open(arg_pager_flags
);
319 r
= terminal_urlify_man("journalctl", "1", &link
);
323 printf("%1$s [OPTIONS...] [MATCHES...]\n\n"
324 "%5$sQuery the journal.%6$s\n\n"
325 "%3$sSource Options:%4$s\n"
326 " --system Show the system journal\n"
327 " --user Show the user journal for the current user\n"
328 " -M --machine=CONTAINER Operate on local container\n"
329 " -m --merge Show entries from all available journals\n"
330 " -D --directory=PATH Show journal files from directory\n"
331 " --file=PATH Show journal file\n"
332 " --root=PATH Operate on an alternate filesystem root\n"
333 " --image=PATH Operate on disk image as filesystem root\n"
334 " --image-policy=POLICY Specify disk image dissection policy\n"
335 " --namespace=NAMESPACE Show journal data from specified journal namespace\n"
336 "\n%3$sFiltering Options:%4$s\n"
337 " -S --since=DATE Show entries not older than the specified date\n"
338 " -U --until=DATE Show entries not newer than the specified date\n"
339 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
340 " --after-cursor=CURSOR Show entries after the specified cursor\n"
341 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
342 " -b --boot[=ID] Show current boot or the specified boot\n"
343 " -u --unit=UNIT Show logs from the specified unit\n"
344 " --user-unit=UNIT Show logs from the specified user unit\n"
345 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
346 " -p --priority=RANGE Show entries with the specified priority\n"
347 " --facility=FACILITY... Show entries with the specified facilities\n"
348 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
349 " --case-sensitive[=BOOL] Force case sensitive or insensitive matching\n"
350 " -k --dmesg Show kernel message log from the current boot\n"
351 "\n%3$sOutput Control Options:%4$s\n"
352 " -o --output=STRING Change journal output mode (short, short-precise,\n"
353 " short-iso, short-iso-precise, short-full,\n"
354 " short-monotonic, short-unix, verbose, export,\n"
355 " json, json-pretty, json-sse, json-seq, cat,\n"
357 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
358 " -n --lines[=INTEGER] Number of journal entries to show\n"
359 " -r --reverse Show the newest entries first\n"
360 " --show-cursor Print the cursor after all the entries\n"
361 " --utc Express time in Coordinated Universal Time (UTC)\n"
362 " -x --catalog Add message explanations where available\n"
363 " --no-hostname Suppress output of hostname field\n"
364 " --no-full Ellipsize fields\n"
365 " -a --all Show all fields, including long and unprintable\n"
366 " -f --follow Follow the journal\n"
367 " --no-tail Show all lines, even in follow mode\n"
368 " -q --quiet Do not show info messages and privilege warning\n"
369 "\n%3$sPager Control Options:%4$s\n"
370 " --no-pager Do not pipe output into a pager\n"
371 " -e --pager-end Immediately jump to the end in the pager\n"
372 "\n%3$sForward Secure Sealing (FSS) Options:%4$s\n"
373 " --interval=TIME Time interval for changing the FSS sealing key\n"
374 " --verify-key=KEY Specify FSS verification key\n"
375 " --force Override of the FSS key pair with --setup-keys\n"
376 "\n%3$sCommands:%4$s\n"
377 " -h --help Show this help text\n"
378 " --version Show package version\n"
379 " -N --fields List all field names currently used\n"
380 " -F --field=FIELD List all values that a specified field takes\n"
381 " --list-boots Show terse information about recorded boots\n"
382 " --disk-usage Show total disk usage of all journal files\n"
383 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
384 " --vacuum-files=INT Leave only the specified number of journal files\n"
385 " --vacuum-time=TIME Remove journal files older than specified time\n"
386 " --verify Verify journal file consistency\n"
387 " --sync Synchronize unwritten journal messages to disk\n"
388 " --relinquish-var Stop logging to disk, log to temporary file system\n"
389 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
390 " --flush Flush all journal data from /run into /var\n"
391 " --rotate Request immediate rotation of the journal files\n"
392 " --header Show journal header information\n"
393 " --list-catalog Show all message IDs in the catalog\n"
394 " --dump-catalog Show entries in the message catalog\n"
395 " --update-catalog Update the message catalog database\n"
396 " --setup-keys Generate a new FSS key pair\n"
397 "\nSee the %2$s for details.\n",
398 program_invocation_short_name
,
408 static int parse_argv(int argc
, char *argv
[]) {
444 ARG_SMART_RELINQUISH_VAR
,
454 static const struct option options
[] = {
455 { "help", no_argument
, NULL
, 'h' },
456 { "version" , no_argument
, NULL
, ARG_VERSION
},
457 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
458 { "pager-end", no_argument
, NULL
, 'e' },
459 { "follow", no_argument
, NULL
, 'f' },
460 { "force", no_argument
, NULL
, ARG_FORCE
},
461 { "output", required_argument
, NULL
, 'o' },
462 { "all", no_argument
, NULL
, 'a' },
463 { "full", no_argument
, NULL
, 'l' },
464 { "no-full", no_argument
, NULL
, ARG_NO_FULL
},
465 { "lines", optional_argument
, NULL
, 'n' },
466 { "no-tail", no_argument
, NULL
, ARG_NO_TAIL
},
467 { "new-id128", no_argument
, NULL
, ARG_NEW_ID128
}, /* deprecated */
468 { "quiet", no_argument
, NULL
, 'q' },
469 { "merge", no_argument
, NULL
, 'm' },
470 { "this-boot", no_argument
, NULL
, ARG_THIS_BOOT
}, /* deprecated */
471 { "boot", optional_argument
, NULL
, 'b' },
472 { "list-boots", no_argument
, NULL
, ARG_LIST_BOOTS
},
473 { "dmesg", no_argument
, NULL
, 'k' },
474 { "system", no_argument
, NULL
, ARG_SYSTEM
},
475 { "user", no_argument
, NULL
, ARG_USER
},
476 { "directory", required_argument
, NULL
, 'D' },
477 { "file", required_argument
, NULL
, ARG_FILE
},
478 { "root", required_argument
, NULL
, ARG_ROOT
},
479 { "image", required_argument
, NULL
, ARG_IMAGE
},
480 { "image-policy", required_argument
, NULL
, ARG_IMAGE_POLICY
},
481 { "header", no_argument
, NULL
, ARG_HEADER
},
482 { "identifier", required_argument
, NULL
, 't' },
483 { "priority", required_argument
, NULL
, 'p' },
484 { "facility", required_argument
, NULL
, ARG_FACILITY
},
485 { "grep", required_argument
, NULL
, 'g' },
486 { "case-sensitive", optional_argument
, NULL
, ARG_CASE_SENSITIVE
},
487 { "setup-keys", no_argument
, NULL
, ARG_SETUP_KEYS
},
488 { "interval", required_argument
, NULL
, ARG_INTERVAL
},
489 { "verify", no_argument
, NULL
, ARG_VERIFY
},
490 { "verify-key", required_argument
, NULL
, ARG_VERIFY_KEY
},
491 { "disk-usage", no_argument
, NULL
, ARG_DISK_USAGE
},
492 { "cursor", required_argument
, NULL
, 'c' },
493 { "cursor-file", required_argument
, NULL
, ARG_CURSOR_FILE
},
494 { "after-cursor", required_argument
, NULL
, ARG_AFTER_CURSOR
},
495 { "show-cursor", no_argument
, NULL
, ARG_SHOW_CURSOR
},
496 { "since", required_argument
, NULL
, 'S' },
497 { "until", required_argument
, NULL
, 'U' },
498 { "unit", required_argument
, NULL
, 'u' },
499 { "user-unit", required_argument
, NULL
, ARG_USER_UNIT
},
500 { "field", required_argument
, NULL
, 'F' },
501 { "fields", no_argument
, NULL
, 'N' },
502 { "catalog", no_argument
, NULL
, 'x' },
503 { "list-catalog", no_argument
, NULL
, ARG_LIST_CATALOG
},
504 { "dump-catalog", no_argument
, NULL
, ARG_DUMP_CATALOG
},
505 { "update-catalog", no_argument
, NULL
, ARG_UPDATE_CATALOG
},
506 { "reverse", no_argument
, NULL
, 'r' },
507 { "machine", required_argument
, NULL
, 'M' },
508 { "utc", no_argument
, NULL
, ARG_UTC
},
509 { "flush", no_argument
, NULL
, ARG_FLUSH
},
510 { "relinquish-var", no_argument
, NULL
, ARG_RELINQUISH_VAR
},
511 { "smart-relinquish-var", no_argument
, NULL
, ARG_SMART_RELINQUISH_VAR
},
512 { "sync", no_argument
, NULL
, ARG_SYNC
},
513 { "rotate", no_argument
, NULL
, ARG_ROTATE
},
514 { "vacuum-size", required_argument
, NULL
, ARG_VACUUM_SIZE
},
515 { "vacuum-files", required_argument
, NULL
, ARG_VACUUM_FILES
},
516 { "vacuum-time", required_argument
, NULL
, ARG_VACUUM_TIME
},
517 { "no-hostname", no_argument
, NULL
, ARG_NO_HOSTNAME
},
518 { "output-fields", required_argument
, NULL
, ARG_OUTPUT_FIELDS
},
519 { "namespace", required_argument
, NULL
, ARG_NAMESPACE
},
528 while ((c
= getopt_long(argc
, argv
, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:", options
, NULL
)) >= 0)
539 arg_pager_flags
|= PAGER_DISABLE
;
543 arg_pager_flags
|= PAGER_JUMP_TO_END
;
545 if (arg_lines
== ARG_LINES_DEFAULT
)
557 if (streq(optarg
, "help")) {
558 DUMP_STRING_TABLE(output_mode
, OutputMode
, _OUTPUT_MODE_MAX
);
562 arg_output
= output_mode_from_string(optarg
);
564 return log_error_errno(arg_output
, "Unknown output format '%s'.", optarg
);
566 if (IN_SET(arg_output
, OUTPUT_EXPORT
, OUTPUT_JSON
, OUTPUT_JSON_PRETTY
, OUTPUT_JSON_SSE
, OUTPUT_JSON_SEQ
, OUTPUT_CAT
))
569 if (OUTPUT_MODE_IS_JSON(arg_output
))
570 arg_json_format_flags
= output_mode_to_json_format_flags(arg_output
) | JSON_FORMAT_COLOR_AUTO
;
572 arg_json_format_flags
= JSON_FORMAT_OFF
;
590 if (streq(optarg
, "all"))
591 arg_lines
= ARG_LINES_ALL
;
593 r
= safe_atoi(optarg
, &arg_lines
);
594 if (r
< 0 || arg_lines
< 0)
595 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to parse lines '%s'", optarg
);
600 /* Hmm, no argument? Maybe the next
601 * word on the command line is
602 * supposed to be the argument? Let's
603 * see if there is one, and is
607 if (streq(argv
[optind
], "all")) {
608 arg_lines
= ARG_LINES_ALL
;
610 } else if (safe_atoi(argv
[optind
], &n
) >= 0 && n
>= 0) {
624 arg_action
= ACTION_NEW_ID128
;
637 arg_boot_id
= SD_ID128_NULL
;
643 arg_boot_id
= SD_ID128_NULL
;
647 r
= parse_boot_descriptor(optarg
, &arg_boot_id
, &arg_boot_offset
);
649 return log_error_errno(r
, "Failed to parse boot descriptor '%s'", optarg
);
653 /* Hmm, no argument? Maybe the next
654 * word on the command line is
655 * supposed to be the argument? Let's
656 * see if there is one and is parsable
657 * as a boot descriptor... */
658 } else if (optind
< argc
) {
659 r
= parse_boot_descriptor(argv
[optind
], &arg_boot_id
, &arg_boot_offset
);
668 arg_action
= ACTION_LIST_BOOTS
;
672 arg_boot
= arg_dmesg
= true;
676 arg_journal_type
|= SD_JOURNAL_SYSTEM
;
680 arg_journal_type
|= SD_JOURNAL_CURRENT_USER
;
684 arg_machine
= optarg
;
688 if (streq(optarg
, "*")) {
689 arg_namespace_flags
= SD_JOURNAL_ALL_NAMESPACES
;
690 arg_namespace
= NULL
;
691 } else if (startswith(optarg
, "+")) {
692 arg_namespace_flags
= SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE
;
693 arg_namespace
= optarg
+ 1;
694 } else if (isempty(optarg
)) {
695 arg_namespace_flags
= 0;
696 arg_namespace
= NULL
;
698 arg_namespace_flags
= 0;
699 arg_namespace
= optarg
;
705 arg_directory
= optarg
;
709 if (streq(optarg
, "-"))
710 /* An undocumented feature: we can read journal files from STDIN. We don't document
711 * this though, since after all we only support this for mmap-able, seekable files, and
712 * not for example pipes which are probably the primary usecase for reading things from
713 * STDIN. To avoid confusion we hence don't document this feature. */
714 arg_file_stdin
= true;
716 r
= glob_extend(&arg_file
, optarg
, GLOB_NOCHECK
);
718 return log_error_errno(r
, "Failed to add paths: %m");
723 r
= parse_path_argument(optarg
, /* suppress_root= */ true, &arg_root
);
729 r
= parse_path_argument(optarg
, /* suppress_root= */ false, &arg_image
);
734 case ARG_IMAGE_POLICY
:
735 r
= parse_image_policy_argument(optarg
, &arg_image_policy
);
744 case ARG_CURSOR_FILE
:
745 arg_cursor_file
= optarg
;
748 case ARG_AFTER_CURSOR
:
749 arg_after_cursor
= optarg
;
752 case ARG_SHOW_CURSOR
:
753 arg_show_cursor
= true;
757 arg_action
= ACTION_PRINT_HEADER
;
761 arg_action
= ACTION_VERIFY
;
765 arg_action
= ACTION_DISK_USAGE
;
768 case ARG_VACUUM_SIZE
:
769 r
= parse_size(optarg
, 1024, &arg_vacuum_size
);
771 return log_error_errno(r
, "Failed to parse vacuum size: %s", optarg
);
773 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
776 case ARG_VACUUM_FILES
:
777 r
= safe_atou64(optarg
, &arg_vacuum_n_files
);
779 return log_error_errno(r
, "Failed to parse vacuum files: %s", optarg
);
781 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
784 case ARG_VACUUM_TIME
:
785 r
= parse_sec(optarg
, &arg_vacuum_time
);
787 return log_error_errno(r
, "Failed to parse vacuum time: %s", optarg
);
789 arg_action
= arg_action
== ACTION_ROTATE
? ACTION_ROTATE_AND_VACUUM
: ACTION_VACUUM
;
798 arg_action
= ACTION_SETUP_KEYS
;
802 r
= free_and_strdup(&arg_verify_key
, optarg
);
805 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
806 * in ps or htop output. */
807 memset(optarg
, 'x', strlen(optarg
));
809 arg_action
= ACTION_VERIFY
;
814 r
= parse_sec(optarg
, &arg_interval
);
815 if (r
< 0 || arg_interval
<= 0)
816 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
817 "Failed to parse sealing key change interval: %s", optarg
);
824 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
825 "Compiled without forward-secure sealing support.");
831 dots
= strstr(optarg
, "..");
833 _cleanup_free_
char *a
= NULL
;
837 a
= strndup(optarg
, dots
- optarg
);
841 from
= log_level_from_string(a
);
842 to
= log_level_from_string(dots
+ 2);
844 if (from
< 0 || to
< 0)
845 return log_error_errno(from
< 0 ? from
: to
,
846 "Failed to parse log level range %s", optarg
);
851 for (i
= from
; i
<= to
; i
++)
852 arg_priorities
|= 1 << i
;
854 for (i
= to
; i
<= from
; i
++)
855 arg_priorities
|= 1 << i
;
861 p
= log_level_from_string(optarg
);
863 return log_error_errno(p
, "Unknown log level %s", optarg
);
867 for (i
= 0; i
<= p
; i
++)
868 arg_priorities
|= 1 << i
;
878 _cleanup_free_
char *fac
= NULL
;
881 r
= extract_first_word(&p
, &fac
, ",", 0);
883 return log_error_errno(r
, "Failed to parse facilities: %s", optarg
);
887 if (streq(fac
, "help")) {
892 num
= log_facility_unshifted_from_string(fac
);
894 return log_error_errno(num
, "Bad --facility= argument \"%s\".", fac
);
896 if (set_ensure_put(&arg_facilities
, NULL
, INT_TO_PTR(num
)) < 0)
904 arg_pattern
= optarg
;
907 case ARG_CASE_SENSITIVE
:
909 r
= parse_boolean(optarg
);
911 return log_error_errno(r
, "Bad --case-sensitive= argument \"%s\": %m", optarg
);
912 arg_case
= r
? PATTERN_COMPILE_CASE_SENSITIVE
: PATTERN_COMPILE_CASE_INSENSITIVE
;
914 arg_case
= PATTERN_COMPILE_CASE_SENSITIVE
;
919 r
= parse_timestamp(optarg
, &arg_since
);
921 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
922 "Failed to parse timestamp: %s", optarg
);
923 arg_since_set
= true;
927 r
= parse_timestamp(optarg
, &arg_until
);
929 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
930 "Failed to parse timestamp: %s", optarg
);
931 arg_until_set
= true;
935 r
= strv_extend(&arg_syslog_identifier
, optarg
);
941 r
= strv_extend(&arg_system_units
, optarg
);
947 r
= strv_extend(&arg_user_units
, optarg
);
953 arg_action
= ACTION_LIST_FIELDS
;
958 arg_action
= ACTION_LIST_FIELD_NAMES
;
961 case ARG_NO_HOSTNAME
:
962 arg_no_hostname
= true;
969 case ARG_LIST_CATALOG
:
970 arg_action
= ACTION_LIST_CATALOG
;
973 case ARG_DUMP_CATALOG
:
974 arg_action
= ACTION_DUMP_CATALOG
;
977 case ARG_UPDATE_CATALOG
:
978 arg_action
= ACTION_UPDATE_CATALOG
;
990 arg_action
= ACTION_FLUSH
;
993 case ARG_SMART_RELINQUISH_VAR
: {
994 int root_mnt_id
, log_mnt_id
;
996 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
997 * if it's on the same mount as the root file system there's no point in
998 * relinquishing access and we can leave journald write to it until the very last
1001 r
= path_get_mnt_id("/", &root_mnt_id
);
1003 log_debug_errno(r
, "Failed to get root mount ID, ignoring: %m");
1005 r
= path_get_mnt_id("/var/log/journal/", &log_mnt_id
);
1007 log_debug_errno(r
, "Failed to get journal directory mount ID, ignoring: %m");
1008 else if (root_mnt_id
== log_mnt_id
) {
1009 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
1012 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
1018 case ARG_RELINQUISH_VAR
:
1019 arg_action
= ACTION_RELINQUISH_VAR
;
1023 arg_action
= arg_action
== ACTION_VACUUM
? ACTION_ROTATE_AND_VACUUM
: ACTION_ROTATE
;
1027 arg_action
= ACTION_SYNC
;
1030 case ARG_OUTPUT_FIELDS
: {
1031 _cleanup_strv_free_
char **v
= NULL
;
1033 v
= strv_split(optarg
, ",");
1037 r
= set_put_strdupv(&arg_output_fields
, v
);
1047 assert_not_reached();
1051 arg_lines
= ARG_LINES_ALL
;
1053 if (arg_follow
&& !arg_since_set
&& arg_lines
== ARG_LINES_DEFAULT
)
1056 if (arg_follow
&& !arg_merge
&& !arg_boot
) {
1058 arg_boot_id
= SD_ID128_NULL
;
1059 arg_boot_offset
= 0;
1062 if (!!arg_directory
+ !!arg_file
+ !!arg_machine
+ !!arg_root
+ !!arg_image
> 1)
1063 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1064 "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
1066 if (arg_since_set
&& arg_until_set
&& arg_since
> arg_until
)
1067 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1068 "--since= must be before --until=.");
1070 if (!!arg_cursor
+ !!arg_after_cursor
+ !!arg_since_set
> 1)
1071 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1072 "Please specify only one of --since=, --cursor=, and --after-cursor=.");
1074 if (arg_follow
&& arg_reverse
)
1075 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1076 "Please specify either --reverse= or --follow=, not both.");
1078 if (!IN_SET(arg_action
, ACTION_SHOW
, ACTION_DUMP_CATALOG
, ACTION_LIST_CATALOG
) && optind
< argc
)
1079 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1080 "Extraneous arguments starting with '%s'",
1083 if ((arg_boot
|| arg_action
== ACTION_LIST_BOOTS
) && arg_merge
)
1084 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1085 "Using --boot or --list-boots with --merge is not supported.");
1087 if (!strv_isempty(arg_system_units
) && arg_journal_type
== SD_JOURNAL_CURRENT_USER
) {
1088 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1089 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1090 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1091 r
= strv_extend_strv(&arg_user_units
, arg_system_units
, true);
1095 arg_system_units
= strv_free(arg_system_units
);
1099 r
= pattern_compile_and_log(arg_pattern
, arg_case
, &arg_compiled_pattern
);
1103 /* When --grep is used along with --lines, we don't know how many lines we can print.
1104 * So we search backwards and count until enough lines have been printed or we hit the head.
1105 * An exception is that --follow might set arg_lines, so let's not imply --reverse
1106 * if that is specified. */
1107 if (arg_lines
>= 0 && !arg_follow
)
1114 static int add_matches(sd_journal
*j
, char **args
) {
1115 bool have_term
= false;
1119 STRV_FOREACH(i
, args
) {
1122 if (streq(*i
, "+")) {
1125 r
= sd_journal_add_disjunction(j
);
1128 } else if (path_is_absolute(*i
)) {
1129 _cleanup_free_
char *p
= NULL
, *t
= NULL
, *t2
= NULL
, *interpreter
= NULL
;
1132 r
= chase(*i
, NULL
, CHASE_TRAIL_SLASH
, &p
, NULL
);
1134 return log_error_errno(r
, "Couldn't canonicalize path: %m");
1136 if (lstat(p
, &st
) < 0)
1137 return log_error_errno(errno
, "Couldn't stat file: %m");
1139 if (S_ISREG(st
.st_mode
) && (0111 & st
.st_mode
)) {
1140 if (executable_is_script(p
, &interpreter
) > 0) {
1141 _cleanup_free_
char *comm
= NULL
;
1143 r
= path_extract_filename(p
, &comm
);
1145 return log_error_errno(r
, "Failed to extract filename of '%s': %m", p
);
1147 t
= strjoin("_COMM=", strshorten(comm
, TASK_COMM_LEN
-1));
1151 /* Append _EXE only if the interpreter is not a link.
1152 Otherwise, it might be outdated often. */
1153 if (lstat(interpreter
, &st
) == 0 && !S_ISLNK(st
.st_mode
)) {
1154 t2
= strjoin("_EXE=", interpreter
);
1159 t
= strjoin("_EXE=", p
);
1164 r
= sd_journal_add_match(j
, t
, 0);
1167 r
= sd_journal_add_match(j
, t2
, 0);
1169 } else if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
1170 r
= add_matches_for_device(j
, p
);
1174 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1175 "File is neither a device node, nor regular file, nor executable: %s",
1180 r
= sd_journal_add_match(j
, *i
, 0);
1185 return log_error_errno(r
, "Failed to add match '%s': %m", *i
);
1188 if (!strv_isempty(args
) && !have_term
)
1189 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
1190 "\"+\" can only be used between terms");
1195 static int discover_next_boot(
1197 sd_id128_t previous_boot_id
,
1207 /* We expect the journal to be on the last position of a boot
1208 * (in relation to the direction we are going), so that the next
1209 * invocation of sd_journal_next/previous will be from a different
1210 * boot. We then collect any information we desire and then jump
1211 * to the last location of the new boot by using a _BOOT_ID match
1212 * coming from the other journal direction. */
1214 /* Make sure we aren't restricted by any _BOOT_ID matches, so that
1215 * we can actually advance to a *different* boot. */
1216 sd_journal_flush_matches(j
);
1220 r
= sd_journal_previous(j
);
1222 r
= sd_journal_next(j
);
1227 return 0; /* End of journal, yay. */
1230 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot
.id
);
1234 /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that
1235 * normally, this will only require a single iteration, as we seeked to the last entry of the previous
1236 * boot entry already. However, it might happen that the per-journal-field entry arrays are less
1237 * complete than the main entry array, and hence might reference an entry that's not actually the last
1238 * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to
1239 * speed things up, but let's not trust that it is complete, and hence, manually advance as
1242 } while (sd_id128_equal(boot
.id
, previous_boot_id
));
1244 r
= sd_journal_get_realtime_usec(j
, &boot
.first_usec
);
1248 /* Now seek to the last occurrence of this boot ID. */
1249 r
= add_match_boot_id(j
, boot
.id
);
1254 r
= sd_journal_seek_head(j
);
1256 r
= sd_journal_seek_tail(j
);
1261 r
= sd_journal_next(j
);
1263 r
= sd_journal_previous(j
);
1267 return log_debug_errno(SYNTHETIC_ERRNO(ENODATA
),
1268 "Whoopsie! We found a boot ID but can't read its last entry."); /* This shouldn't happen. We just came from this very boot ID. */
1270 r
= sd_journal_get_realtime_usec(j
, &boot
.last_usec
);
1274 sd_journal_flush_matches(j
);
1279 static int find_boot_by_id(sd_journal
*j
) {
1284 sd_journal_flush_matches(j
);
1286 r
= add_match_boot_id(j
, arg_boot_id
);
1290 r
= sd_journal_seek_head(j
); /* seek to oldest */
1294 r
= sd_journal_next(j
); /* read the oldest entry */
1298 /* At this point the read pointer is positioned at the oldest occurrence of the reference boot ID.
1299 * After flushing the matches, one more invocation of _previous() will hence place us at the
1300 * following entry, which must then have an older boot ID */
1302 sd_journal_flush_matches(j
);
1306 static int find_boot_by_offset(sd_journal
*j
) {
1307 bool advance_older
, skip_once
;
1310 /* Adjust for the asymmetry that offset 0 is the last (and current) boot, while 1 is considered the
1311 * (chronological) first boot in the journal. */
1312 advance_older
= skip_once
= arg_boot_offset
<= 0;
1315 r
= sd_journal_seek_tail(j
); /* seek to newest */
1317 r
= sd_journal_seek_head(j
); /* seek to oldest */
1321 /* No sd_journal_next()/_previous() here.
1323 * At this point the read pointer is positioned after the newest/before the oldest entry in the whole
1324 * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest
1327 int offset
= arg_boot_offset
;
1328 sd_id128_t previous_boot_id
= SD_ID128_NULL
;
1332 r
= discover_next_boot(j
, previous_boot_id
, advance_older
, &boot
);
1336 previous_boot_id
= boot
.id
;
1339 offset
+= advance_older
? 1 : -1;
1343 arg_boot_id
= boot
.id
;
1349 static int get_boots(sd_journal
*j
, BootId
**ret_boots
, size_t *ret_n_boots
) {
1350 _cleanup_free_ BootId
*boots
= NULL
;
1356 assert(ret_n_boots
);
1358 r
= sd_journal_seek_head(j
); /* seek to oldest */
1362 /* No sd_journal_next()/_previous() here.
1364 * At this point the read pointer is positioned before the oldest entry in the whole journal. The
1365 * next invocation of _next() will hence position us at the oldest entry we have. */
1367 sd_id128_t previous_boot_id
= SD_ID128_NULL
;
1371 r
= discover_next_boot(j
, previous_boot_id
, /* advance_older = */ false, &boot
);
1377 previous_boot_id
= boot
.id
;
1379 FOREACH_ARRAY(i
, boots
, n_boots
)
1380 if (sd_id128_equal(i
->id
, boot
.id
))
1381 /* The boot id is already stored, something wrong with the journal files.
1382 * Exiting as otherwise this problem would cause an infinite loop. */
1385 if (!GREEDY_REALLOC(boots
, n_boots
+ 1))
1388 boots
[n_boots
++] = boot
;
1391 *ret_boots
= TAKE_PTR(boots
);
1392 *ret_n_boots
= n_boots
;
1396 static int list_boots(sd_journal
*j
) {
1397 _cleanup_(table_unrefp
) Table
*table
= NULL
;
1398 _cleanup_free_ BootId
*boots
= NULL
;
1404 r
= get_boots(j
, &boots
, &n_boots
);
1406 return log_error_errno(r
, "Failed to determine boots: %m");
1410 table
= table_new("idx", "boot id", "first entry", "last entry");
1415 table_set_width(table
, 0);
1417 r
= table_set_json_field_name(table
, 0, "index");
1419 return log_error_errno(r
, "Failed to set JSON field name of column 0: %m");
1421 (void) table_set_sort(table
, (size_t) 0);
1422 (void) table_set_reverse(table
, 0, arg_reverse
);
1424 FOREACH_ARRAY(i
, boots
, n_boots
) {
1425 r
= table_add_many(table
,
1426 TABLE_INT
, (int)(i
- boots
) - (int) n_boots
+ 1,
1427 TABLE_SET_ALIGN_PERCENT
, 100,
1429 TABLE_TIMESTAMP
, i
->first_usec
,
1430 TABLE_TIMESTAMP
, i
->last_usec
);
1432 return table_log_add_error(r
);
1435 r
= table_print_with_pager(table
, arg_json_format_flags
, arg_pager_flags
, !arg_quiet
);
1437 return table_log_print_error(r
);
1442 static int add_boot(sd_journal
*j
) {
1450 /* Take a shortcut and use the current boot_id, which we can do very quickly.
1451 * We can do this only when we logs are coming from the current machine,
1452 * so take the slow path if log location is specified. */
1453 if (arg_boot_offset
== 0 && sd_id128_is_null(arg_boot_id
) &&
1454 !arg_directory
&& !arg_file
&& !arg_root
)
1455 return add_match_this_boot(j
, arg_machine
);
1457 if (sd_id128_is_null(arg_boot_id
)) {
1458 r
= find_boot_by_offset(j
);
1460 return log_error_errno(r
, "Failed to find journal entry from the specified boot offset (%+i): %m",
1463 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1464 "No journal boot entry found from the specified boot offset (%+i).",
1467 r
= find_boot_by_id(j
);
1469 return log_error_errno(r
, "Failed to find journal entry from the specified boot ID (%s): %m",
1470 SD_ID128_TO_STRING(arg_boot_id
));
1472 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
),
1473 "No journal boot entry found from the specified boot ID (%s).",
1474 SD_ID128_TO_STRING(arg_boot_id
));
1477 r
= add_match_boot_id(j
, arg_boot_id
);
1479 return log_error_errno(r
, "Failed to add match: %m");
1481 r
= sd_journal_add_conjunction(j
);
1483 return log_error_errno(r
, "Failed to add conjunction: %m");
1488 static int add_dmesg(sd_journal
*j
) {
1495 r
= sd_journal_add_match(j
, "_TRANSPORT=kernel",
1496 STRLEN("_TRANSPORT=kernel"));
1498 return log_error_errno(r
, "Failed to add match: %m");
1500 r
= sd_journal_add_conjunction(j
);
1502 return log_error_errno(r
, "Failed to add conjunction: %m");
1507 static int get_possible_units(
1513 _cleanup_set_free_free_ Set
*found
= NULL
;
1516 found
= set_new(&string_hash_ops
);
1520 NULSTR_FOREACH(field
, fields
) {
1524 r
= sd_journal_query_unique(j
, field
);
1528 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
1531 _cleanup_free_
char *u
= NULL
;
1533 eq
= memchr(data
, '=', size
);
1535 prefix
= eq
- (char*) data
+ 1;
1539 u
= strndup((char*) data
+ prefix
, size
- prefix
);
1543 STRV_FOREACH(pattern
, patterns
)
1544 if (fnmatch(*pattern
, u
, FNM_NOESCAPE
) == 0) {
1545 log_debug("Matched %s with pattern %s=%s", u
, field
, *pattern
);
1547 r
= set_consume(found
, u
);
1549 if (r
< 0 && r
!= -EEXIST
)
1557 *units
= TAKE_PTR(found
);
1562 /* This list is supposed to return the superset of unit names
1563 * possibly matched by rules added with add_matches_for_unit... */
1564 #define SYSTEM_UNITS \
1568 "OBJECT_SYSTEMD_UNIT\0" \
1571 /* ... and add_matches_for_user_unit */
1572 #define USER_UNITS \
1573 "_SYSTEMD_USER_UNIT\0" \
1575 "COREDUMP_USER_UNIT\0" \
1576 "OBJECT_SYSTEMD_USER_UNIT\0" \
1577 "_SYSTEMD_USER_SLICE\0"
1579 static int add_units(sd_journal
*j
) {
1580 _cleanup_strv_free_
char **patterns
= NULL
;
1585 STRV_FOREACH(i
, arg_system_units
) {
1586 _cleanup_free_
char *u
= NULL
;
1588 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1592 if (string_is_glob(u
)) {
1593 r
= strv_push(&patterns
, u
);
1598 r
= add_matches_for_unit(j
, u
);
1601 r
= sd_journal_add_disjunction(j
);
1608 if (!strv_isempty(patterns
)) {
1609 _cleanup_set_free_free_ Set
*units
= NULL
;
1612 r
= get_possible_units(j
, SYSTEM_UNITS
, patterns
, &units
);
1616 SET_FOREACH(u
, units
) {
1617 r
= add_matches_for_unit(j
, u
);
1620 r
= sd_journal_add_disjunction(j
);
1627 patterns
= strv_free(patterns
);
1629 STRV_FOREACH(i
, arg_user_units
) {
1630 _cleanup_free_
char *u
= NULL
;
1632 r
= unit_name_mangle(*i
, UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
), &u
);
1636 if (string_is_glob(u
)) {
1637 r
= strv_push(&patterns
, u
);
1642 r
= add_matches_for_user_unit(j
, u
, getuid());
1645 r
= sd_journal_add_disjunction(j
);
1652 if (!strv_isempty(patterns
)) {
1653 _cleanup_set_free_free_ Set
*units
= NULL
;
1656 r
= get_possible_units(j
, USER_UNITS
, patterns
, &units
);
1660 SET_FOREACH(u
, units
) {
1661 r
= add_matches_for_user_unit(j
, u
, getuid());
1664 r
= sd_journal_add_disjunction(j
);
1671 /* Complain if the user request matches but nothing whatsoever was
1672 * found, since otherwise everything would be matched. */
1673 if (!(strv_isempty(arg_system_units
) && strv_isempty(arg_user_units
)) && count
== 0)
1676 r
= sd_journal_add_conjunction(j
);
1683 static int add_priorities(sd_journal
*j
) {
1684 char match
[] = "PRIORITY=0";
1688 if (arg_priorities
== 0xFF)
1691 for (i
= LOG_EMERG
; i
<= LOG_DEBUG
; i
++)
1692 if (arg_priorities
& (1 << i
)) {
1693 match
[sizeof(match
)-2] = '0' + i
;
1695 r
= sd_journal_add_match(j
, match
, strlen(match
));
1697 return log_error_errno(r
, "Failed to add match: %m");
1700 r
= sd_journal_add_conjunction(j
);
1702 return log_error_errno(r
, "Failed to add conjunction: %m");
1707 static int add_facilities(sd_journal
*j
) {
1711 SET_FOREACH(p
, arg_facilities
) {
1712 char match
[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
1714 xsprintf(match
, "SYSLOG_FACILITY=%d", PTR_TO_INT(p
));
1716 r
= sd_journal_add_match(j
, match
, strlen(match
));
1718 return log_error_errno(r
, "Failed to add match: %m");
1724 static int add_syslog_identifier(sd_journal
*j
) {
1729 STRV_FOREACH(i
, arg_syslog_identifier
) {
1730 _cleanup_free_
char *u
= NULL
;
1732 u
= strjoin("SYSLOG_IDENTIFIER=", *i
);
1735 r
= sd_journal_add_match(j
, u
, 0);
1738 r
= sd_journal_add_disjunction(j
);
1743 r
= sd_journal_add_conjunction(j
);
1751 static int format_journal_url(
1760 _cleanup_free_
char *url
= NULL
;
1761 _cleanup_fclose_
FILE *f
= NULL
;
1762 size_t url_size
= 0;
1766 assert(seed_size
> 0);
1768 f
= open_memstream_unlocked(&url
, &url_size
);
1775 for (size_t i
= 0; i
< seed_size
; i
++) {
1776 if (i
> 0 && i
% 3 == 0)
1778 fprintf(f
, "%02x", ((uint8_t*) seed
)[i
]);
1781 fprintf(f
, "/%"PRIx64
"-%"PRIx64
, start
, interval
);
1784 fprintf(f
, "?machine=" SD_ID128_FORMAT_STR
, SD_ID128_FORMAT_VAL(machine
));
1786 fprintf(f
, ";hostname=%s", hn
);
1789 r
= fflush_and_check(f
);
1798 *ret_url
= TAKE_PTR(url
);
1803 static int setup_keys(void) {
1805 size_t mpk_size
, seed_size
, state_size
;
1806 _cleanup_(unlink_and_freep
) char *k
= NULL
;
1807 _cleanup_free_
char *p
= NULL
;
1808 uint8_t *mpk
, *seed
, *state
;
1809 _cleanup_close_
int fd
= -EBADF
;
1810 sd_id128_t machine
, boot
;
1815 r
= stat("/var/log/journal", &st
);
1816 if (r
< 0 && !IN_SET(errno
, ENOENT
, ENOTDIR
))
1817 return log_error_errno(errno
, "stat(\"%s\") failed: %m", "/var/log/journal");
1819 if (r
< 0 || !S_ISDIR(st
.st_mode
)) {
1820 log_error("%s is not a directory, must be using persistent logging for FSS.",
1821 "/var/log/journal");
1822 return r
< 0 ? -errno
: -ENOTDIR
;
1825 r
= sd_id128_get_machine(&machine
);
1827 return log_error_errno(r
, "Failed to get machine ID: %m");
1829 r
= sd_id128_get_boot(&boot
);
1831 return log_error_errno(r
, "Failed to get boot ID: %m");
1833 if (asprintf(&p
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss",
1834 SD_ID128_FORMAT_VAL(machine
)) < 0)
1839 if (r
< 0 && errno
!= ENOENT
)
1840 return log_error_errno(errno
, "unlink(\"%s\") failed: %m", p
);
1841 } else if (access(p
, F_OK
) >= 0)
1842 return log_error_errno(SYNTHETIC_ERRNO(EEXIST
),
1843 "Sealing key file %s exists already. Use --force to recreate.", p
);
1845 if (asprintf(&k
, "/var/log/journal/" SD_ID128_FORMAT_STR
"/fss.tmp.XXXXXX",
1846 SD_ID128_FORMAT_VAL(machine
)) < 0)
1849 mpk_size
= FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR
);
1850 mpk
= alloca_safe(mpk_size
);
1852 seed_size
= FSPRG_RECOMMENDED_SEEDLEN
;
1853 seed
= alloca_safe(seed_size
);
1855 state_size
= FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR
);
1856 state
= alloca_safe(state_size
);
1858 log_info("Generating seed...");
1859 r
= crypto_random_bytes(seed
, seed_size
);
1861 return log_error_errno(r
, "Failed to acquire random seed: %m");
1863 log_info("Generating key pair...");
1864 FSPRG_GenMK(NULL
, mpk
, seed
, seed_size
, FSPRG_RECOMMENDED_SECPAR
);
1866 log_info("Generating sealing key...");
1867 FSPRG_GenState0(state
, mpk
, seed
, seed_size
);
1869 assert(arg_interval
> 0);
1871 n
= now(CLOCK_REALTIME
);
1875 fd
= mkostemp_safe(k
);
1877 return log_error_errno(fd
, "Failed to open %s: %m", k
);
1879 r
= chattr_secret(fd
, CHATTR_WARN_UNSUPPORTED_FLAGS
);
1881 log_full_errno(ERRNO_IS_NOT_SUPPORTED(r
) ? LOG_DEBUG
: LOG_WARNING
,
1882 r
, "Failed to set file attributes on '%s', ignoring: %m", k
);
1884 struct FSSHeader h
= {
1885 .signature
= { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' },
1886 .machine_id
= machine
,
1888 .header_size
= htole64(sizeof(h
)),
1889 .start_usec
= htole64(n
* arg_interval
),
1890 .interval_usec
= htole64(arg_interval
),
1891 .fsprg_secpar
= htole16(FSPRG_RECOMMENDED_SECPAR
),
1892 .fsprg_state_size
= htole64(state_size
),
1895 r
= loop_write(fd
, &h
, sizeof(h
), false);
1897 return log_error_errno(r
, "Failed to write header: %m");
1899 r
= loop_write(fd
, state
, state_size
, false);
1901 return log_error_errno(r
, "Failed to write state: %m");
1903 if (rename(k
, p
) < 0)
1904 return log_error_errno(errno
, "Failed to link file: %m");
1908 _cleanup_free_
char *hn
= NULL
, *key
= NULL
;
1910 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, false, &key
);
1915 hn
= gethostname_malloc();
1917 hostname_cleanup(hn
);
1920 "\nNew keys have been generated for host %s%s" SD_ID128_FORMAT_STR
".\n"
1922 "The %ssecret sealing key%s has been written to the following local file.\n"
1923 "This key file is automatically updated when the sealing key is advanced.\n"
1924 "It should not be used on multiple hosts.\n"
1928 "The sealing key is automatically changed every %s.\n"
1930 "Please write down the following %ssecret verification key%s. It should be stored\n"
1931 "in a safe location and should not be saved locally on disk.\n"
1933 strempty(hn
), hn
? "/" : "",
1934 SD_ID128_FORMAT_VAL(machine
),
1935 ansi_highlight(), ansi_normal(),
1937 FORMAT_TIMESPAN(arg_interval
, 0),
1938 ansi_highlight(), ansi_normal(),
1939 ansi_highlight_red());
1946 fprintf(stderr
, "%s", ansi_normal());
1948 _cleanup_free_
char *url
= NULL
;
1949 r
= format_journal_url(seed
, seed_size
, n
, arg_interval
, hn
, machine
, true, &url
);
1953 (void) print_qrcode(stderr
,
1954 "To transfer the verification key to your phone scan the QR code below",
1961 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
1962 "Forward-secure sealing not available.");
1966 static int verify(sd_journal
*j
, bool verbose
) {
1972 log_show_color(true);
1974 ORDERED_HASHMAP_FOREACH(f
, j
->files
) {
1976 usec_t first
= 0, validated
= 0, last
= 0;
1979 if (!arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
))
1980 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f
->path
);
1983 k
= journal_file_verify(f
, arg_verify_key
, &first
, &validated
, &last
, verbose
);
1985 /* If the key was invalid give up right-away. */
1988 r
= log_warning_errno(k
, "FAIL: %s (%m)", f
->path
);
1990 char a
[FORMAT_TIMESTAMP_MAX
], b
[FORMAT_TIMESTAMP_MAX
];
1991 log_full(verbose
? LOG_INFO
: LOG_DEBUG
, "PASS: %s", f
->path
);
1993 if (arg_verify_key
&& JOURNAL_HEADER_SEALED(f
->header
)) {
1994 if (validated
> 0) {
1995 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
1996 "=> Validated from %s to %s, final %s entries not sealed.",
1997 format_timestamp_maybe_utc(a
, sizeof(a
), first
),
1998 format_timestamp_maybe_utc(b
, sizeof(b
), validated
),
1999 FORMAT_TIMESPAN(last
> validated
? last
- validated
: 0, 0));
2000 } else if (last
> 0)
2001 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2002 "=> No sealing yet, %s of entries not sealed.",
2003 FORMAT_TIMESPAN(last
- first
, 0));
2005 log_full(verbose
? LOG_INFO
: LOG_DEBUG
,
2006 "=> No sealing yet, no entries in file.");
2014 static int simple_varlink_call(const char *option
, const char *method
) {
2015 _cleanup_(varlink_flush_close_unrefp
) Varlink
*link
= NULL
;
2016 const char *error
, *fn
;
2020 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "%s is not supported in conjunction with --machine=.", option
);
2022 fn
= arg_namespace
?
2023 strjoina("/run/systemd/journal.", arg_namespace
, "/io.systemd.journal") :
2024 "/run/systemd/journal/io.systemd.journal";
2026 r
= varlink_connect_address(&link
, fn
);
2028 return log_error_errno(r
, "Failed to connect to %s: %m", fn
);
2030 (void) varlink_set_description(link
, "journal");
2031 (void) varlink_set_relative_timeout(link
, USEC_INFINITY
);
2033 r
= varlink_call(link
, method
, NULL
, NULL
, &error
, NULL
);
2035 return log_error_errno(r
, "Failed to execute varlink call: %m");
2037 return log_error_errno(SYNTHETIC_ERRNO(ENOANO
),
2038 "Failed to execute varlink call: %s", error
);
2043 static int flush_to_var(void) {
2044 if (access("/run/systemd/journal/flushed", F_OK
) >= 0)
2045 return 0; /* Already flushed, no need to contact journald */
2046 if (errno
!= ENOENT
)
2047 return log_error_errno(errno
, "Unable to check for existence of /run/systemd/journal/flushed: %m");
2049 return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
2052 static int relinquish_var(void) {
2053 return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar");
2056 static int rotate(void) {
2057 return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
2060 static int sync_journal(void) {
2061 return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
2064 static int action_list_fields(sd_journal
*j
) {
2071 r
= sd_journal_set_data_threshold(j
, 0);
2073 return log_error_errno(r
, "Failed to unset data size threshold: %m");
2075 r
= sd_journal_query_unique(j
, arg_field
);
2077 return log_error_errno(r
, "Failed to query unique data objects: %m");
2079 SD_JOURNAL_FOREACH_UNIQUE(j
, data
, size
) {
2082 if (arg_lines
>= 0 && n_shown
>= arg_lines
)
2085 eq
= memchr(data
, '=', size
);
2087 printf("%.*s\n", (int) (size
- ((const uint8_t*) eq
- (const uint8_t*) data
+ 1)), (const char*) eq
+ 1);
2089 printf("%.*s\n", (int) size
, (const char*) data
);
2097 static int update_cursor(sd_journal
*j
) {
2098 _cleanup_free_
char *cursor
= NULL
;
2103 if (!arg_show_cursor
&& !arg_cursor_file
)
2106 r
= sd_journal_get_cursor(j
, &cursor
);
2107 if (r
== -EADDRNOTAVAIL
)
2110 return log_error_errno(r
, "Failed to get cursor: %m");
2112 if (arg_show_cursor
)
2113 printf("-- cursor: %s\n", cursor
);
2115 if (arg_cursor_file
) {
2116 r
= write_string_file(arg_cursor_file
, cursor
, WRITE_STRING_FILE_CREATE
| WRITE_STRING_FILE_ATOMIC
);
2118 return log_error_errno(r
, "Failed to write new cursor to %s: %m", arg_cursor_file
);
2124 typedef struct Context
{
2125 sd_journal
*journal
;
2129 bool previous_boot_id_valid
;
2130 sd_id128_t previous_boot_id
;
2131 sd_id128_t previous_boot_id_output
;
2132 dual_timestamp previous_ts_output
;
2135 static int show(Context
*c
) {
2141 j
= ASSERT_PTR(c
->journal
);
2143 while (arg_lines
< 0 || n_shown
< arg_lines
|| arg_follow
) {
2145 size_t highlight
[2] = {};
2149 r
= sd_journal_next(j
);
2151 r
= sd_journal_previous(j
);
2153 return log_error_errno(r
, "Failed to iterate through journal: %m");
2158 if (arg_until_set
&& !arg_reverse
&& (arg_lines
< 0 || arg_since_set
)) {
2159 /* If --lines= is set, we usually rely on the n_shown to tell us
2160 * when to stop. However, if --since= is set too, we may end up
2161 * having less than --lines= to output. In this case let's also
2162 * check if the entry is in range. */
2166 r
= sd_journal_get_realtime_usec(j
, &usec
);
2168 return log_error_errno(r
, "Failed to determine timestamp: %m");
2169 if (usec
> arg_until
)
2173 if (arg_since_set
&& (arg_reverse
|| !c
->since_seeked
)) {
2176 r
= sd_journal_get_realtime_usec(j
, &usec
);
2178 return log_error_errno(r
, "Failed to determine timestamp: %m");
2180 if (usec
< arg_since
) {
2182 break; /* Reached the earliest entry */
2184 /* arg_lines >= 0 (!since_seeked):
2185 * We jumped arg_lines back and it seems to be too much */
2186 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2188 return log_error_errno(r
, "Failed to seek to date: %m");
2189 c
->since_seeked
= true;
2191 c
->need_seek
= true;
2194 c
->since_seeked
= true; /* We're surely within the range of --since now */
2197 if (!arg_merge
&& !arg_quiet
) {
2200 r
= sd_journal_get_monotonic_usec(j
, NULL
, &boot_id
);
2202 if (c
->previous_boot_id_valid
&&
2203 !sd_id128_equal(boot_id
, c
->previous_boot_id
))
2204 printf("%s-- Boot "SD_ID128_FORMAT_STR
" --%s\n",
2205 ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id
), ansi_normal());
2207 c
->previous_boot_id
= boot_id
;
2208 c
->previous_boot_id_valid
= true;
2212 if (arg_compiled_pattern
) {
2213 const void *message
;
2216 r
= sd_journal_get_data(j
, "MESSAGE", &message
, &len
);
2219 c
->need_seek
= true;
2223 return log_error_errno(r
, "Failed to get MESSAGE field: %m");
2226 assert_se(message
= startswith(message
, "MESSAGE="));
2228 r
= pattern_matches_and_log(arg_compiled_pattern
, message
,
2229 len
- strlen("MESSAGE="), highlight
);
2233 c
->need_seek
= true;
2239 arg_all
* OUTPUT_SHOW_ALL
|
2240 arg_full
* OUTPUT_FULL_WIDTH
|
2241 colors_enabled() * OUTPUT_COLOR
|
2242 arg_catalog
* OUTPUT_CATALOG
|
2243 arg_utc
* OUTPUT_UTC
|
2244 arg_no_hostname
* OUTPUT_NO_HOSTNAME
;
2246 r
= show_journal_entry(stdout
, j
, arg_output
, 0, flags
,
2247 arg_output_fields
, highlight
, &c
->ellipsized
,
2248 &c
->previous_ts_output
, &c
->previous_boot_id_output
);
2249 c
->need_seek
= true;
2250 if (r
== -EADDRNOTAVAIL
)
2257 /* If journalctl take a long time to process messages, and during that time journal file
2258 * rotation occurs, a journalctl client will keep those rotated files open until it calls
2259 * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below
2260 * in the "following" case. By periodically calling sd_journal_process() during the processing
2261 * loop we shrink the window of time a client instance has open file descriptors for rotated
2262 * (deleted) journal files. */
2263 if ((n_shown
% PROCESS_INOTIFY_INTERVAL
) == 0) {
2264 r
= sd_journal_process(j
);
2266 return log_error_errno(r
, "Failed to process inotify events: %m");
2273 static int show_and_fflush(Context
*c
, sd_event_source
*s
) {
2281 return sd_event_exit(sd_event_source_get_event(s
), r
);
2287 static int on_journal_event(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
2288 Context
*c
= ASSERT_PTR(userdata
);
2293 r
= sd_journal_process(c
->journal
);
2295 log_error_errno(r
, "Failed to process journal events: %m");
2296 return sd_event_exit(sd_event_source_get_event(s
), r
);
2299 return show_and_fflush(c
, s
);
2302 static int on_first_event(sd_event_source
*s
, void *userdata
) {
2303 return show_and_fflush(userdata
, s
);
2306 static int setup_event(Context
*c
, int fd
, sd_event
**ret
) {
2307 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
2315 r
= sd_event_default(&e
);
2317 return log_error_errno(r
, "Failed to allocate sd_event object: %m");
2319 r
= sd_event_add_io(e
, NULL
, fd
, EPOLLIN
, &on_journal_event
, c
);
2321 return log_error_errno(r
, "Failed to add io event source for journal: %m");
2323 /* Also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that, i.e. when it is closed. */
2324 r
= sd_event_add_io(e
, NULL
, STDOUT_FILENO
, EPOLLHUP
|EPOLLERR
, NULL
, INT_TO_PTR(-ECANCELED
));
2326 return log_error_errno(r
, "Failed to add io event source for stdout: %m");
2328 if (arg_lines
!= 0 || arg_since_set
) {
2329 r
= sd_event_add_defer(e
, NULL
, on_first_event
, c
);
2331 return log_error_errno(r
, "Failed to add defer event source: %m");
2338 static int run(int argc
, char *argv
[]) {
2339 bool need_seek
= false, since_seeked
= false, use_cursor
= false, after_cursor
= false;
2340 _cleanup_(loop_device_unrefp
) LoopDevice
*loop_device
= NULL
;
2341 _cleanup_(umount_and_freep
) char *mounted_dir
= NULL
;
2342 _cleanup_(sd_journal_closep
) sd_journal
*j
= NULL
;
2343 _cleanup_close_
int machine_fd
= -EBADF
;
2344 int n_shown
, r
, poll_fd
= -EBADF
;
2346 setlocale(LC_ALL
, "");
2349 /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be
2350 * split up into many files. */
2351 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE
);
2353 r
= parse_argv(argc
, argv
);
2360 r
= mount_image_privately_interactively(
2363 DISSECT_IMAGE_GENERIC_ROOT
|
2364 DISSECT_IMAGE_REQUIRE_ROOT
|
2365 DISSECT_IMAGE_VALIDATE_OS
|
2366 DISSECT_IMAGE_RELAX_VAR_CHECK
|
2367 (arg_action
== ACTION_UPDATE_CATALOG
? DISSECT_IMAGE_FSCK
|DISSECT_IMAGE_GROWFS
: DISSECT_IMAGE_READ_ONLY
),
2369 /* ret_dir_fd= */ NULL
,
2374 arg_root
= strdup(mounted_dir
);
2379 signal(SIGWINCH
, columns_lines_cache_reset
);
2382 switch (arg_action
) {
2384 case ACTION_NEW_ID128
:
2385 return id128_print_new(ID128_PRINT_PRETTY
);
2387 case ACTION_SETUP_KEYS
:
2388 return setup_keys();
2390 case ACTION_LIST_CATALOG
:
2391 case ACTION_DUMP_CATALOG
:
2392 case ACTION_UPDATE_CATALOG
: {
2393 _cleanup_free_
char *database
= NULL
;
2395 database
= path_join(arg_root
, CATALOG_DATABASE
);
2399 if (arg_action
== ACTION_UPDATE_CATALOG
) {
2400 r
= catalog_update(database
, arg_root
, catalog_file_dirs
);
2402 return log_error_errno(r
, "Failed to list catalog: %m");
2404 bool oneline
= arg_action
== ACTION_LIST_CATALOG
;
2406 pager_open(arg_pager_flags
);
2409 r
= catalog_list_items(stdout
, database
, oneline
, argv
+ optind
);
2411 r
= catalog_list(stdout
, database
, oneline
);
2413 return log_error_errno(r
, "Failed to list catalog: %m");
2420 return flush_to_var();
2422 case ACTION_RELINQUISH_VAR
:
2423 return relinquish_var();
2426 return sync_journal();
2432 case ACTION_PRINT_HEADER
:
2434 case ACTION_DISK_USAGE
:
2435 case ACTION_LIST_BOOTS
:
2437 case ACTION_ROTATE_AND_VACUUM
:
2438 case ACTION_LIST_FIELDS
:
2439 case ACTION_LIST_FIELD_NAMES
:
2440 /* These ones require access to the journal files, continue below. */
2444 assert_not_reached();
2448 r
= sd_journal_open_directory(&j
, arg_directory
, arg_journal_type
);
2450 r
= sd_journal_open_directory(&j
, arg_root
, arg_journal_type
| SD_JOURNAL_OS_ROOT
);
2451 else if (arg_file_stdin
)
2452 r
= sd_journal_open_files_fd(&j
, (int[]) { STDIN_FILENO
}, 1, 0);
2454 r
= sd_journal_open_files(&j
, (const char**) arg_file
, 0);
2455 else if (arg_machine
) {
2456 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2457 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2458 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
2462 /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of
2463 * the container, thus we need root privileges to override them. */
2464 return log_error_errno(SYNTHETIC_ERRNO(EPERM
), "Using the --machine= switch requires root privileges.");
2466 r
= sd_bus_open_system(&bus
);
2468 return log_error_errno(r
, "Failed to open system bus: %m");
2470 r
= bus_call_method(bus
, bus_machine_mgr
, "OpenMachineRootDirectory", &error
, &reply
, "s", arg_machine
);
2472 return log_error_errno(r
, "Failed to open root directory: %s", bus_error_message(&error
, r
));
2474 r
= sd_bus_message_read(reply
, "h", &fd
);
2476 return bus_log_parse_error(r
);
2478 machine_fd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
2480 return log_error_errno(errno
, "Failed to duplicate file descriptor: %m");
2482 r
= sd_journal_open_directory_fd(&j
, machine_fd
, SD_JOURNAL_OS_ROOT
);
2484 r
= sd_journal_open_namespace(
2487 (arg_merge
? 0 : SD_JOURNAL_LOCAL_ONLY
) |
2488 arg_namespace_flags
| arg_journal_type
);
2490 return log_error_errno(r
, "Failed to open %s: %m", arg_directory
?: arg_file
? "files" : "journal");
2492 r
= journal_access_check_and_warn(j
, arg_quiet
,
2493 !(arg_journal_type
== SD_JOURNAL_CURRENT_USER
|| arg_user_units
));
2497 switch (arg_action
) {
2499 case ACTION_NEW_ID128
:
2500 case ACTION_SETUP_KEYS
:
2501 case ACTION_LIST_CATALOG
:
2502 case ACTION_DUMP_CATALOG
:
2503 case ACTION_UPDATE_CATALOG
:
2507 assert_not_reached();
2509 case ACTION_PRINT_HEADER
:
2510 journal_print_header(j
);
2514 return verify(j
, !arg_quiet
);
2516 case ACTION_DISK_USAGE
: {
2519 r
= sd_journal_get_usage(j
, &bytes
);
2523 printf("Archived and active journals take up %s in the file system.\n",
2524 FORMAT_BYTES(bytes
));
2529 case ACTION_LIST_BOOTS
:
2530 return list_boots(j
);
2532 case ACTION_ROTATE_AND_VACUUM
:
2540 case ACTION_VACUUM
: {
2544 HASHMAP_FOREACH(d
, j
->directories_by_path
) {
2545 r
= journal_directory_vacuum(d
->path
, arg_vacuum_size
, arg_vacuum_n_files
, arg_vacuum_time
, NULL
, !arg_quiet
);
2547 log_error_errno(r
, "Failed to vacuum %s: %m", d
->path
);
2556 case ACTION_LIST_FIELD_NAMES
: {
2559 SD_JOURNAL_FOREACH_FIELD(j
, field
)
2560 printf("%s\n", field
);
2566 case ACTION_LIST_FIELDS
:
2570 assert_not_reached();
2573 if (arg_boot_offset
!= 0 &&
2574 sd_journal_has_runtime_files(j
) > 0 &&
2575 sd_journal_has_persistent_files(j
) == 0) {
2576 log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found.");
2578 if (arg_action
== ACTION_SHOW
&& arg_compiled_pattern
)
2583 /* add_boot() must be called first!
2584 * It may need to seek the journal to find parent boot IDs. */
2595 return log_error_errno(r
, "Failed to add filter for units: %m");
2597 r
= add_syslog_identifier(j
);
2599 return log_error_errno(r
, "Failed to add filter for syslog identifiers: %m");
2601 r
= add_priorities(j
);
2605 r
= add_facilities(j
);
2609 r
= add_matches(j
, argv
+ optind
);
2613 if (DEBUG_LOGGING
) {
2614 _cleanup_free_
char *filter
= NULL
;
2616 filter
= journal_make_match_string(j
);
2620 log_debug("Journal filter: %s", filter
);
2623 if (arg_action
== ACTION_LIST_FIELDS
)
2624 return action_list_fields(j
);
2626 /* Opening the fd now means the first sd_journal_wait() will actually wait */
2628 poll_fd
= sd_journal_get_fd(j
);
2629 if (poll_fd
== -EMFILE
) {
2630 log_warning_errno(poll_fd
, "Insufficient watch descriptors available. Reverting to -n.");
2632 } else if (poll_fd
== -EMEDIUMTYPE
)
2633 return log_error_errno(poll_fd
, "The --follow switch is not supported in conjunction with reading from STDIN.");
2634 else if (poll_fd
< 0)
2635 return log_error_errno(poll_fd
, "Failed to get journal fd: %m");
2638 if (arg_cursor
|| arg_after_cursor
|| arg_cursor_file
) {
2639 _cleanup_free_
char *cursor_from_file
= NULL
;
2640 const char *cursor
= arg_cursor
?: arg_after_cursor
;
2642 if (arg_cursor_file
) {
2643 r
= read_one_line_file(arg_cursor_file
, &cursor_from_file
);
2644 if (r
< 0 && r
!= -ENOENT
)
2645 return log_error_errno(r
, "Failed to read cursor file %s: %m", arg_cursor_file
);
2648 cursor
= cursor_from_file
;
2649 after_cursor
= true;
2652 after_cursor
= arg_after_cursor
;
2655 r
= sd_journal_seek_cursor(j
, cursor
);
2657 return log_error_errno(r
, "Failed to seek to cursor: %m");
2665 r
= sd_journal_next_skip(j
, 1 + after_cursor
);
2667 r
= sd_journal_previous_skip(j
, 1 + after_cursor
);
2669 if (after_cursor
&& r
< 2) {
2670 /* We couldn't find the next entry after the cursor. */
2677 } else if (arg_until_set
&& (arg_reverse
|| arg_lines
>= 0)) {
2678 /* If both --until and any of --reverse and --lines is specified, things get
2679 * a little tricky. We seek to the place of --until first. If only --reverse or
2680 * --reverse and --lines is specified, we search backwards and let the output
2681 * counter handle --lines for us. If only --lines is used, we just jump backwards
2682 * arg_lines and search afterwards from there. */
2684 r
= sd_journal_seek_realtime_usec(j
, arg_until
);
2686 return log_error_errno(r
, "Failed to seek to date: %m");
2689 r
= sd_journal_previous(j
);
2690 else /* arg_lines >= 0 */
2691 r
= sd_journal_previous_skip(j
, arg_lines
);
2693 } else if (arg_reverse
) {
2694 r
= sd_journal_seek_tail(j
);
2696 return log_error_errno(r
, "Failed to seek to tail: %m");
2698 r
= sd_journal_previous(j
);
2700 } else if (arg_lines
>= 0) {
2701 r
= sd_journal_seek_tail(j
);
2703 return log_error_errno(r
, "Failed to seek to tail: %m");
2705 r
= sd_journal_previous_skip(j
, arg_lines
);
2707 } else if (arg_since_set
) {
2708 /* This is placed after arg_reverse and arg_lines. If --since is used without
2709 * both, we seek to the place of --since and search afterwards from there.
2710 * If used with --reverse or --lines, we seek to the tail first and check if
2711 * the entry is within the range of --since later. */
2713 r
= sd_journal_seek_realtime_usec(j
, arg_since
);
2715 return log_error_errno(r
, "Failed to seek to date: %m");
2716 since_seeked
= true;
2718 r
= sd_journal_next(j
);
2721 r
= sd_journal_seek_head(j
);
2723 return log_error_errno(r
, "Failed to seek to head: %m");
2725 r
= sd_journal_next(j
);
2728 return log_error_errno(r
, "Failed to iterate through journal: %m");
2733 pager_open(arg_pager_flags
);
2735 if (!arg_quiet
&& (arg_lines
!= 0 || arg_follow
) && DEBUG_LOGGING
) {
2737 char start_buf
[FORMAT_TIMESTAMP_MAX
], end_buf
[FORMAT_TIMESTAMP_MAX
];
2739 r
= sd_journal_get_cutoff_realtime_usec(j
, &start
, &end
);
2741 return log_error_errno(r
, "Failed to get cutoff: %m");
2744 printf("-- Journal begins at %s. --\n",
2745 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
));
2747 printf("-- Journal begins at %s, ends at %s. --\n",
2748 format_timestamp_maybe_utc(start_buf
, sizeof(start_buf
), start
),
2749 format_timestamp_maybe_utc(end_buf
, sizeof(end_buf
), end
));
2755 .need_seek
= need_seek
,
2756 .since_seeked
= since_seeked
,
2760 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
2762 assert(poll_fd
>= 0);
2764 r
= setup_event(&c
, poll_fd
, &e
);
2768 return sd_event_loop(e
);
2776 if (n_shown
== 0 && !arg_quiet
)
2777 printf("-- No entries --\n");
2779 r
= update_cursor(j
);
2783 if (arg_compiled_pattern
&& n_shown
== 0)
2784 /* --grep was used, no error was thrown, but the pattern didn't
2785 * match anything. Let's mimic grep's behavior here and return
2786 * a non-zero exit code, so journalctl --grep can be used
2787 * in scripts and such */
2793 DEFINE_MAIN_FUNCTION(run
);