]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/journal/journalctl.c
networkd-test: stop varlink socket before setting up runtime directories
[thirdparty/systemd.git] / src / journal / journalctl.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
87d2c1ff 2
3f6fd1ba 3#include <getopt.h>
eea9eb1f 4#include <locale.h>
ade2db83 5
3f6fd1ba
LP
6#include "sd-journal.h"
7
d6b4d1c7 8#include "build.h"
eea9eb1f
DDM
9#include "dissect-image.h"
10#include "extract-word.h"
7d50b32a 11#include "glob-util.h"
ff7dad48 12#include "id128-print.h"
8aa304d3 13#include "image-policy.h"
ade2db83
YW
14#include "journalctl.h"
15#include "journalctl-authenticate.h"
16#include "journalctl-catalog.h"
17#include "journalctl-misc.h"
18#include "journalctl-show.h"
19#include "journalctl-varlink.h"
eea9eb1f
DDM
20#include "log.h"
21#include "loop-util.h"
9556e79b 22#include "main-func.h"
cc171228 23#include "mount-util.h"
c0dfcb31 24#include "mountpoint-util.h"
eea9eb1f
DDM
25#include "output-mode.h"
26#include "pager.h"
614b022c 27#include "parse-argument.h"
c94f6ab1 28#include "parse-util.h"
eea9eb1f 29#include "pcre2-util.h"
294bf0c3 30#include "pretty-print.h"
eea9eb1f 31#include "set.h"
2e64b27a 32#include "static-destruct.h"
5c828e66 33#include "string-table.h"
eea9eb1f
DDM
34#include "string-util.h"
35#include "strv.h"
7ccbd1ae 36#include "syslog-util.h"
eea9eb1f 37#include "time-util.h"
7560fffc 38
baed47c3 39#define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
ec316d19 40
97e1cc8b
LP
41enum {
42 /* Special values for arg_lines */
43 ARG_LINES_DEFAULT = -2,
44 ARG_LINES_ALL = -1,
45};
46
ade2db83
YW
47JournalctlAction arg_action = ACTION_SHOW;
48OutputMode arg_output = OUTPUT_SHORT;
309a747f 49sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
ade2db83
YW
50PagerFlags arg_pager_flags = 0;
51bool arg_utc = false;
52bool arg_follow = false;
53bool arg_full = true;
54bool arg_all = false;
55int arg_lines = ARG_LINES_DEFAULT;
56bool arg_lines_oldest = false;
57bool arg_no_tail = false;
58bool arg_truncate_newline = false;
59bool arg_quiet = false;
60bool arg_merge = false;
f8bfe16b 61int arg_boot = -1; /* tristate */
ade2db83
YW
62sd_id128_t arg_boot_id = {};
63int arg_boot_offset = 0;
64bool arg_dmesg = false;
65bool arg_no_hostname = false;
ce2b92e8
YW
66char *arg_cursor = NULL;
67char *arg_cursor_file = NULL;
68char *arg_after_cursor = NULL;
ade2db83 69bool arg_show_cursor = false;
ce2b92e8 70char *arg_directory = NULL;
ade2db83
YW
71char **arg_file = NULL;
72bool arg_file_stdin = false;
22f2b556 73int arg_priorities = 0;
ade2db83
YW
74Set *arg_facilities = NULL;
75char *arg_verify_key = NULL;
349cc4a5 76#if HAVE_GCRYPT
ade2db83
YW
77usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
78bool arg_force = false;
feb12d3e 79#endif
ade2db83
YW
80usec_t arg_since = 0;
81usec_t arg_until = 0;
82bool arg_since_set = false;
83bool arg_until_set = false;
84char **arg_syslog_identifier = NULL;
85char **arg_exclude_identifier = NULL;
86char **arg_system_units = NULL;
87char **arg_user_units = NULL;
7d3ae6b2
YW
88bool arg_invocation = false;
89sd_id128_t arg_invocation_id = SD_ID128_NULL;
90int arg_invocation_offset = 0;
ce2b92e8 91char *arg_field = NULL;
ade2db83
YW
92bool arg_catalog = false;
93bool arg_reverse = false;
94int arg_journal_type = 0;
95int arg_journal_additional_open_flags = 0;
96int arg_namespace_flags = 0;
97char *arg_root = NULL;
98char *arg_image = NULL;
ce2b92e8
YW
99char *arg_machine = NULL;
100char *arg_namespace = NULL;
ade2db83
YW
101uint64_t arg_vacuum_size = 0;
102uint64_t arg_vacuum_n_files = 0;
103usec_t arg_vacuum_time = 0;
104Set *arg_output_fields = NULL;
ce2b92e8 105char *arg_pattern = NULL;
ade2db83
YW
106pcre2_code *arg_compiled_pattern = NULL;
107PatternCompileCase arg_case = PATTERN_COMPILE_CASE_AUTO;
5be930db 108ImagePolicy *arg_image_policy = NULL;
d2f45c76 109bool arg_synchronize_on_exit = false;
6becf48c 110
ce2b92e8
YW
111STATIC_DESTRUCTOR_REGISTER(arg_cursor, freep);
112STATIC_DESTRUCTOR_REGISTER(arg_cursor_file, freep);
113STATIC_DESTRUCTOR_REGISTER(arg_after_cursor, freep);
114STATIC_DESTRUCTOR_REGISTER(arg_directory, freep);
2e64b27a
DDM
115STATIC_DESTRUCTOR_REGISTER(arg_file, strv_freep);
116STATIC_DESTRUCTOR_REGISTER(arg_facilities, set_freep);
d0ad4e88 117STATIC_DESTRUCTOR_REGISTER(arg_verify_key, erase_and_freep);
2e64b27a 118STATIC_DESTRUCTOR_REGISTER(arg_syslog_identifier, strv_freep);
25aa35d4 119STATIC_DESTRUCTOR_REGISTER(arg_exclude_identifier, strv_freep);
2e64b27a
DDM
120STATIC_DESTRUCTOR_REGISTER(arg_system_units, strv_freep);
121STATIC_DESTRUCTOR_REGISTER(arg_user_units, strv_freep);
ce2b92e8 122STATIC_DESTRUCTOR_REGISTER(arg_field, freep);
2e64b27a
DDM
123STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
124STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
ce2b92e8
YW
125STATIC_DESTRUCTOR_REGISTER(arg_machine, freep);
126STATIC_DESTRUCTOR_REGISTER(arg_namespace, freep);
c5da14cd 127STATIC_DESTRUCTOR_REGISTER(arg_output_fields, set_freep);
ce2b92e8 128STATIC_DESTRUCTOR_REGISTER(arg_pattern, freep);
75db32dc 129STATIC_DESTRUCTOR_REGISTER(arg_compiled_pattern, pattern_freep);
84be0c71 130STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
2e64b27a 131
fdd325fb 132static int parse_id_descriptor(const char *x, sd_id128_t *ret_id, int *ret_offset) {
442e2def
LP
133 sd_id128_t id = SD_ID128_NULL;
134 int off = 0, r;
135
fdd325fb
YW
136 assert(x);
137 assert(ret_id);
138 assert(ret_offset);
139
48904825 140 if (streq(x, "all")) {
fdd325fb
YW
141 *ret_id = SD_ID128_NULL;
142 *ret_offset = 0;
48904825 143 return 0;
fdd325fb
YW
144 }
145
146 if (strlen(x) >= SD_ID128_STRING_MAX - 1) {
442e2def
LP
147 char *t;
148
2f82562b 149 t = strndupa_safe(x, SD_ID128_STRING_MAX - 1);
442e2def
LP
150 r = sd_id128_from_string(t, &id);
151 if (r >= 0)
0d5765f7 152 x += SD_ID128_STRING_MAX - 1;
442e2def 153
4c701096 154 if (!IN_SET(*x, 0, '-', '+'))
442e2def
LP
155 return -EINVAL;
156
157 if (*x != 0) {
158 r = safe_atoi(x, &off);
159 if (r < 0)
160 return r;
161 }
162 } else {
163 r = safe_atoi(x, &off);
164 if (r < 0)
165 return r;
166 }
167
fdd325fb
YW
168 *ret_id = id;
169 *ret_offset = off;
48904825 170 return 1;
442e2def
LP
171}
172
8d6791d2
MY
173static int parse_lines(const char *arg, bool graceful) {
174 const char *l;
175 int n, r;
176
177 assert(arg || graceful);
178
179 if (!arg)
180 goto default_noarg;
181
182 if (streq(arg, "all")) {
183 arg_lines = ARG_LINES_ALL;
184 return 1;
185 }
186
187 l = startswith(arg, "+");
188
189 r = safe_atoi(l ?: arg, &n);
190 if (r < 0 || n < 0) {
191 if (graceful)
192 goto default_noarg;
193
194 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse --lines='%s'.", arg);
195 }
196
197 arg_lines = n;
c8ccd444 198 arg_lines_oldest = l;
8d6791d2
MY
199
200 return 1;
201
202default_noarg:
203 arg_lines = 10;
7b5ff439 204 arg_lines_oldest = false;
8d6791d2
MY
205 return 0;
206}
207
196dedd5
ZJS
208static int help_facilities(void) {
209 if (!arg_quiet)
210 puts("Available facilities:");
211
212 for (int i = 0; i < LOG_NFACILITIES; i++) {
213 _cleanup_free_ char *t = NULL;
214
d4423350 215 if (log_facility_unshifted_to_string_alloc(i, &t) < 0)
196dedd5
ZJS
216 return log_oom();
217 puts(t);
218 }
219
220 return 0;
221}
222
37ec0fdd
LP
223static int help(void) {
224 _cleanup_free_ char *link = NULL;
225 int r;
0d43c694 226
384c2c32 227 pager_open(arg_pager_flags);
faf5077f 228
37ec0fdd
LP
229 r = terminal_urlify_man("journalctl", "1", &link);
230 if (r < 0)
231 return log_oom();
232
23d8c560
LP
233 printf("%1$s [OPTIONS...] [MATCHES...]\n\n"
234 "%5$sQuery the journal.%6$s\n\n"
74962351 235 "%3$sSource Options:%4$s\n"
61c5f8a1
ZJS
236 " --system Show the system journal\n"
237 " --user Show the user journal for the current user\n"
238 " -M --machine=CONTAINER Operate on local container\n"
74962351
LP
239 " -m --merge Show entries from all available journals\n"
240 " -D --directory=PATH Show journal files from directory\n"
dde54b8a 241 " -i --file=PATH Show journal file\n"
84be0c71
LP
242 " --root=PATH Operate on an alternate filesystem root\n"
243 " --image=PATH Operate on disk image as filesystem root\n"
244 " --image-policy=POLICY Specify disk image dissection policy\n"
74962351
LP
245 " --namespace=NAMESPACE Show journal data from specified journal namespace\n"
246 "\n%3$sFiltering Options:%4$s\n"
61c5f8a1
ZJS
247 " -S --since=DATE Show entries not older than the specified date\n"
248 " -U --until=DATE Show entries not newer than the specified date\n"
249 " -c --cursor=CURSOR Show entries starting at the specified cursor\n"
250 " --after-cursor=CURSOR Show entries after the specified cursor\n"
d9e15cbd 251 " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n"
61c5f8a1 252 " -b --boot[=ID] Show current boot or the specified boot\n"
61c5f8a1
ZJS
253 " -u --unit=UNIT Show logs from the specified unit\n"
254 " --user-unit=UNIT Show logs from the specified user unit\n"
7d3ae6b2
YW
255 " --invocation=ID Show logs from the matching invocation ID\n"
256 " -I Show logs from the latest invocation of unit\n"
61c5f8a1 257 " -t --identifier=STRING Show entries with the specified syslog identifier\n"
25aa35d4
SZ
258 " -T --exclude-identifier=STRING\n"
259 " Hide entries with the specified syslog identifier\n"
ad938537 260 " -p --priority=RANGE Show entries within the specified priority range\n"
196dedd5 261 " --facility=FACILITY... Show entries with the specified facilities\n"
fabf4dae 262 " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n"
86b52a39 263 " --case-sensitive[=BOOL] Force case sensitive or insensitive matching\n"
74962351
LP
264 " -k --dmesg Show kernel message log from the current boot\n"
265 "\n%3$sOutput Control Options:%4$s\n"
61c5f8a1
ZJS
266 " -o --output=STRING Change journal output mode (short, short-precise,\n"
267 " short-iso, short-iso-precise, short-full,\n"
268 " short-monotonic, short-unix, verbose, export,\n"
8e044443
LP
269 " json, json-pretty, json-sse, json-seq, cat,\n"
270 " with-unit)\n"
61c5f8a1 271 " --output-fields=LIST Select fields to print in verbose/export/json modes\n"
8d6791d2 272 " -n --lines[=[+]INTEGER] Number of journal entries to show\n"
74962351
LP
273 " -r --reverse Show the newest entries first\n"
274 " --show-cursor Print the cursor after all the entries\n"
61c5f8a1
ZJS
275 " --utc Express time in Coordinated Universal Time (UTC)\n"
276 " -x --catalog Add message explanations where available\n"
74962351 277 " --no-hostname Suppress output of hostname field\n"
61c5f8a1
ZJS
278 " --no-full Ellipsize fields\n"
279 " -a --all Show all fields, including long and unprintable\n"
74962351
LP
280 " -f --follow Follow the journal\n"
281 " --no-tail Show all lines, even in follow mode\n"
61cecfa0 282 " --truncate-newline Truncate entries by first newline character\n"
61c5f8a1 283 " -q --quiet Do not show info messages and privilege warning\n"
d2f45c76
LP
284 " --synchronize-on-exit=BOOL\n"
285 " Wait for Journal synchronization before exiting\n"
74962351 286 "\n%3$sPager Control Options:%4$s\n"
61c5f8a1 287 " --no-pager Do not pipe output into a pager\n"
74962351
LP
288 " -e --pager-end Immediately jump to the end in the pager\n"
289 "\n%3$sForward Secure Sealing (FSS) Options:%4$s\n"
61c5f8a1
ZJS
290 " --interval=TIME Time interval for changing the FSS sealing key\n"
291 " --verify-key=KEY Specify FSS verification key\n"
292 " --force Override of the FSS key pair with --setup-keys\n"
23d8c560 293 "\n%3$sCommands:%4$s\n"
61c5f8a1
ZJS
294 " -h --help Show this help text\n"
295 " --version Show package version\n"
296 " -N --fields List all field names currently used\n"
297 " -F --field=FIELD List all values that a specified field takes\n"
74962351 298 " --list-boots Show terse information about recorded boots\n"
7d3ae6b2 299 " --list-invocations Show invocation IDs of specified unit\n"
edd2b336 300 " --list-namespaces Show list of journal namespaces\n"
61c5f8a1
ZJS
301 " --disk-usage Show total disk usage of all journal files\n"
302 " --vacuum-size=BYTES Reduce disk usage below specified size\n"
303 " --vacuum-files=INT Leave only the specified number of journal files\n"
304 " --vacuum-time=TIME Remove journal files older than specified time\n"
305 " --verify Verify journal file consistency\n"
306 " --sync Synchronize unwritten journal messages to disk\n"
c0dfcb31
LP
307 " --relinquish-var Stop logging to disk, log to temporary file system\n"
308 " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n"
61c5f8a1
ZJS
309 " --flush Flush all journal data from /run into /var\n"
310 " --rotate Request immediate rotation of the journal files\n"
311 " --header Show journal header information\n"
312 " --list-catalog Show all message IDs in the catalog\n"
313 " --dump-catalog Show entries in the message catalog\n"
314 " --update-catalog Update the message catalog database\n"
61c5f8a1 315 " --setup-keys Generate a new FSS key pair\n"
bc556335
DDM
316 "\nSee the %2$s for details.\n",
317 program_invocation_short_name,
318 link,
319 ansi_underline(),
320 ansi_normal(),
321 ansi_highlight(),
322 ansi_normal());
37ec0fdd
LP
323
324 return 0;
0d43c694
LP
325}
326
327static int parse_argv(int argc, char *argv[]) {
328
329 enum {
330 ARG_VERSION = 0x100,
e91af489 331 ARG_NO_PAGER,
2b8f6883 332 ARG_NO_FULL,
55ee336c 333 ARG_NO_TAIL,
dca6219e 334 ARG_NEW_ID128,
8453f062 335 ARG_THIS_BOOT,
f1188074 336 ARG_LIST_BOOTS,
7d3ae6b2 337 ARG_LIST_INVOCATIONS,
3f3a438f
ZJS
338 ARG_USER,
339 ARG_SYSTEM,
13cbf3a5 340 ARG_ROOT,
cc171228 341 ARG_IMAGE,
06e78680 342 ARG_IMAGE_POLICY,
7560fffc 343 ARG_HEADER,
196dedd5 344 ARG_FACILITY,
beec0085 345 ARG_SETUP_KEYS,
baed47c3 346 ARG_INTERVAL,
4da416aa 347 ARG_VERIFY,
a1a03e30 348 ARG_VERIFY_KEY,
cfbc22ab 349 ARG_DISK_USAGE,
248fc619 350 ARG_AFTER_CURSOR,
d9e15cbd 351 ARG_CURSOR_FILE,
248fc619 352 ARG_SHOW_CURSOR,
ffa7cd15 353 ARG_USER_UNIT,
7d3ae6b2 354 ARG_INVOCATION,
d4205751 355 ARG_LIST_CATALOG,
54b7254c 356 ARG_DUMP_CATALOG,
3f3a438f 357 ARG_UPDATE_CATALOG,
b8547c10 358 ARG_FORCE,
61c5f8a1 359 ARG_CASE_SENSITIVE,
9fd29044 360 ARG_UTC,
94b65516 361 ARG_SYNC,
74055aa7 362 ARG_FLUSH,
c0dfcb31
LP
363 ARG_RELINQUISH_VAR,
364 ARG_SMART_RELINQUISH_VAR,
e3fdfb49 365 ARG_ROTATE,
61cecfa0 366 ARG_TRUNCATE_NEWLINE,
dbd2a83f 367 ARG_VACUUM_SIZE,
8580d1f7 368 ARG_VACUUM_FILES,
dbd2a83f 369 ARG_VACUUM_TIME,
991e274b 370 ARG_NO_HOSTNAME,
cc25a67e 371 ARG_OUTPUT_FIELDS,
6b25db87 372 ARG_NAMESPACE,
68f66a17 373 ARG_LIST_NAMESPACES,
d2f45c76 374 ARG_SYNCHRONIZE_ON_EXIT,
0d43c694
LP
375 };
376
377 static const struct option options[] = {
c0dfcb31
LP
378 { "help", no_argument, NULL, 'h' },
379 { "version" , no_argument, NULL, ARG_VERSION },
380 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
381 { "pager-end", no_argument, NULL, 'e' },
382 { "follow", no_argument, NULL, 'f' },
383 { "force", no_argument, NULL, ARG_FORCE },
384 { "output", required_argument, NULL, 'o' },
385 { "all", no_argument, NULL, 'a' },
386 { "full", no_argument, NULL, 'l' },
387 { "no-full", no_argument, NULL, ARG_NO_FULL },
388 { "lines", optional_argument, NULL, 'n' },
61cecfa0 389 { "truncate-newline", no_argument, NULL, ARG_TRUNCATE_NEWLINE },
c0dfcb31
LP
390 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
391 { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, /* deprecated */
392 { "quiet", no_argument, NULL, 'q' },
393 { "merge", no_argument, NULL, 'm' },
394 { "this-boot", no_argument, NULL, ARG_THIS_BOOT }, /* deprecated */
395 { "boot", optional_argument, NULL, 'b' },
396 { "list-boots", no_argument, NULL, ARG_LIST_BOOTS },
7d3ae6b2 397 { "list-invocations", no_argument, NULL, ARG_LIST_INVOCATIONS },
c0dfcb31
LP
398 { "dmesg", no_argument, NULL, 'k' },
399 { "system", no_argument, NULL, ARG_SYSTEM },
400 { "user", no_argument, NULL, ARG_USER },
401 { "directory", required_argument, NULL, 'D' },
dde54b8a 402 { "file", required_argument, NULL, 'i' },
c0dfcb31 403 { "root", required_argument, NULL, ARG_ROOT },
cc171228 404 { "image", required_argument, NULL, ARG_IMAGE },
06e78680 405 { "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
c0dfcb31
LP
406 { "header", no_argument, NULL, ARG_HEADER },
407 { "identifier", required_argument, NULL, 't' },
25aa35d4 408 { "exclude-identifier", required_argument, NULL, 'T' },
c0dfcb31 409 { "priority", required_argument, NULL, 'p' },
196dedd5 410 { "facility", required_argument, NULL, ARG_FACILITY },
c0dfcb31
LP
411 { "grep", required_argument, NULL, 'g' },
412 { "case-sensitive", optional_argument, NULL, ARG_CASE_SENSITIVE },
413 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
414 { "interval", required_argument, NULL, ARG_INTERVAL },
415 { "verify", no_argument, NULL, ARG_VERIFY },
416 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
417 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
418 { "cursor", required_argument, NULL, 'c' },
419 { "cursor-file", required_argument, NULL, ARG_CURSOR_FILE },
420 { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR },
421 { "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR },
422 { "since", required_argument, NULL, 'S' },
423 { "until", required_argument, NULL, 'U' },
424 { "unit", required_argument, NULL, 'u' },
425 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
7d3ae6b2 426 { "invocation", required_argument, NULL, ARG_INVOCATION },
c0dfcb31
LP
427 { "field", required_argument, NULL, 'F' },
428 { "fields", no_argument, NULL, 'N' },
429 { "catalog", no_argument, NULL, 'x' },
430 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
431 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
432 { "update-catalog", no_argument, NULL, ARG_UPDATE_CATALOG },
433 { "reverse", no_argument, NULL, 'r' },
434 { "machine", required_argument, NULL, 'M' },
435 { "utc", no_argument, NULL, ARG_UTC },
436 { "flush", no_argument, NULL, ARG_FLUSH },
437 { "relinquish-var", no_argument, NULL, ARG_RELINQUISH_VAR },
438 { "smart-relinquish-var", no_argument, NULL, ARG_SMART_RELINQUISH_VAR },
439 { "sync", no_argument, NULL, ARG_SYNC },
440 { "rotate", no_argument, NULL, ARG_ROTATE },
441 { "vacuum-size", required_argument, NULL, ARG_VACUUM_SIZE },
442 { "vacuum-files", required_argument, NULL, ARG_VACUUM_FILES },
443 { "vacuum-time", required_argument, NULL, ARG_VACUUM_TIME },
444 { "no-hostname", no_argument, NULL, ARG_NO_HOSTNAME },
445 { "output-fields", required_argument, NULL, ARG_OUTPUT_FIELDS },
6b25db87 446 { "namespace", required_argument, NULL, ARG_NAMESPACE },
68f66a17 447 { "list-namespaces", no_argument, NULL, ARG_LIST_NAMESPACES },
d2f45c76 448 { "synchronize-on-exit", required_argument, NULL, ARG_SYNCHRONIZE_ON_EXIT },
eb9da376 449 {}
0d43c694
LP
450 };
451
2100675e 452 int c, r;
0d43c694
LP
453
454 assert(argc >= 0);
455 assert(argv);
456
7d3ae6b2 457 while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:g:c:S:U:t:T:u:INF:xrM:i:", options, NULL)) >= 0)
0d43c694
LP
458
459 switch (c) {
460
461 case 'h':
37ec0fdd 462 return help();
0d43c694
LP
463
464 case ARG_VERSION:
3f6fd1ba 465 return version();
0d43c694
LP
466
467 case ARG_NO_PAGER:
0221d68a 468 arg_pager_flags |= PAGER_DISABLE;
0d43c694
LP
469 break;
470
1b12a7b5 471 case 'e':
0221d68a 472 arg_pager_flags |= PAGER_JUMP_TO_END;
1b12a7b5
HH
473 break;
474
0d43c694
LP
475 case 'f':
476 arg_follow = true;
477 break;
478
479 case 'o':
5c828e66
LP
480 if (streq(optarg, "help")) {
481 DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
482 return 0;
483 }
484
1705594f 485 arg_output = output_mode_from_string(optarg);
0491150b 486 if (arg_output < 0)
7211c853 487 return log_error_errno(arg_output, "Unknown output format '%s'.", optarg);
df50185b 488
8e044443 489 if (IN_SET(arg_output, OUTPUT_EXPORT, OUTPUT_JSON, OUTPUT_JSON_PRETTY, OUTPUT_JSON_SSE, OUTPUT_JSON_SEQ, OUTPUT_CAT))
edfb521a
ZJS
490 arg_quiet = true;
491
5a1355d8 492 if (OUTPUT_MODE_IS_JSON(arg_output))
309a747f 493 arg_json_format_flags = output_mode_to_json_format_flags(arg_output) | SD_JSON_FORMAT_COLOR_AUTO;
faf20d4c 494 else
309a747f 495 arg_json_format_flags = SD_JSON_FORMAT_OFF;
faf20d4c 496
0d43c694
LP
497 break;
498
98a6e132 499 case 'l':
e3657ecd
ZJS
500 arg_full = true;
501 break;
502
2b8f6883
ZJS
503 case ARG_NO_FULL:
504 arg_full = false;
505 break;
506
0d43c694 507 case 'a':
cd4b13e0 508 arg_all = true;
0d43c694
LP
509 break;
510
2100675e 511 case 'n':
f2e2c93d 512 r = parse_lines(optarg ?: argv[optind], !optarg);
8d6791d2
MY
513 if (r < 0)
514 return r;
515 if (r > 0 && !optarg)
516 optind++;
1705594f 517
2100675e
LP
518 break;
519
e91af489
LP
520 case ARG_NO_TAIL:
521 arg_no_tail = true;
522 break;
523
61cecfa0 524 case ARG_TRUNCATE_NEWLINE:
525 arg_truncate_newline = true;
526 break;
527
39f7f5c1 528 case ARG_NEW_ID128:
7560fffc 529 arg_action = ACTION_NEW_ID128;
55ee336c
LP
530 break;
531
43673799
LP
532 case 'q':
533 arg_quiet = true;
490e567d 534 break;
43673799 535
9e8a535f
LP
536 case 'm':
537 arg_merge = true;
2bd3c38a
LP
538 break;
539
8453f062
ZJS
540 case ARG_THIS_BOOT:
541 arg_boot = true;
48904825 542 arg_boot_id = SD_ID128_NULL;
543 arg_boot_offset = 0;
8453f062
ZJS
544 break;
545
59cea26a 546 case 'b':
d121b396 547 arg_boot = true;
48904825 548 arg_boot_id = SD_ID128_NULL;
549 arg_boot_offset = 0;
6cebe83c 550
442e2def 551 if (optarg) {
fdd325fb 552 r = parse_id_descriptor(optarg, &arg_boot_id, &arg_boot_offset);
48904825 553 if (r < 0)
554 return log_error_errno(r, "Failed to parse boot descriptor '%s'", optarg);
555
556 arg_boot = r;
557
48904825 558 } else if (optind < argc) {
fdd325fb
YW
559 /* Hmm, no argument? Maybe the next word on the command line is supposed to be the
560 * argument? Let's see if there is one and is parsable as a boot descriptor... */
561 r = parse_id_descriptor(argv[optind], &arg_boot_id, &arg_boot_offset);
48904825 562 if (r >= 0) {
563 arg_boot = r;
6cebe83c 564 optind++;
48904825 565 }
6cebe83c 566 }
59cea26a
LP
567 break;
568
f1188074
ZJS
569 case ARG_LIST_BOOTS:
570 arg_action = ACTION_LIST_BOOTS;
571 break;
572
7d3ae6b2
YW
573 case ARG_LIST_INVOCATIONS:
574 arg_action = ACTION_LIST_INVOCATIONS;
575 break;
576
99271804 577 case 'k':
f8bfe16b 578 arg_dmesg = true;
99271804
ZJS
579 break;
580
3f3a438f
ZJS
581 case ARG_SYSTEM:
582 arg_journal_type |= SD_JOURNAL_SYSTEM;
583 break;
584
585 case ARG_USER:
586 arg_journal_type |= SD_JOURNAL_CURRENT_USER;
587 break;
588
b6741478 589 case 'M':
ce2b92e8
YW
590 r = free_and_strdup_warn(&arg_machine, optarg);
591 if (r < 0)
592 return r;
b6741478
LP
593 break;
594
6b25db87
LP
595 case ARG_NAMESPACE:
596 if (streq(optarg, "*")) {
597 arg_namespace_flags = SD_JOURNAL_ALL_NAMESPACES;
ce2b92e8 598 arg_namespace = mfree(arg_namespace);
6b25db87
LP
599 } else if (startswith(optarg, "+")) {
600 arg_namespace_flags = SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE;
ce2b92e8
YW
601 r = free_and_strdup_warn(&arg_namespace, optarg + 1);
602 if (r < 0)
603 return r;
6b25db87
LP
604 } else if (isempty(optarg)) {
605 arg_namespace_flags = 0;
ce2b92e8 606 arg_namespace = mfree(arg_namespace);
6b25db87
LP
607 } else {
608 arg_namespace_flags = 0;
ce2b92e8
YW
609 r = free_and_strdup_warn(&arg_namespace, optarg);
610 if (r < 0)
611 return r;
6b25db87 612 }
6b25db87
LP
613 break;
614
68f66a17
FS
615 case ARG_LIST_NAMESPACES:
616 arg_action = ACTION_LIST_NAMESPACES;
617 break;
618
a963990f 619 case 'D':
ce2b92e8
YW
620 r = free_and_strdup_warn(&arg_directory, optarg);
621 if (r < 0)
622 return r;
a963990f
LP
623 break;
624
dde54b8a 625 case 'i':
5d1ce257
LP
626 if (streq(optarg, "-"))
627 /* An undocumented feature: we can read journal files from STDIN. We don't document
628 * this though, since after all we only support this for mmap-able, seekable files, and
7227dd81 629 * not for example pipes which are probably the primary use case for reading things from
5d1ce257
LP
630 * STDIN. To avoid confusion we hence don't document this feature. */
631 arg_file_stdin = true;
632 else {
544e146b 633 r = glob_extend(&arg_file, optarg, GLOB_NOCHECK);
5d1ce257
LP
634 if (r < 0)
635 return log_error_errno(r, "Failed to add paths: %m");
636 }
8d98da3f
ZJS
637 break;
638
13cbf3a5 639 case ARG_ROOT:
614b022c 640 r = parse_path_argument(optarg, /* suppress_root= */ true, &arg_root);
cc171228
LP
641 if (r < 0)
642 return r;
643 break;
644
645 case ARG_IMAGE:
614b022c 646 r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
0f03c2a4
LP
647 if (r < 0)
648 return r;
13cbf3a5
ZJS
649 break;
650
06e78680
YW
651 case ARG_IMAGE_POLICY:
652 r = parse_image_policy_argument(optarg, &arg_image_policy);
653 if (r < 0)
654 return r;
655 break;
656
8f14c832 657 case 'c':
ce2b92e8
YW
658 r = free_and_strdup_warn(&arg_cursor, optarg);
659 if (r < 0)
660 return r;
8f14c832
LP
661 break;
662
d9e15cbd 663 case ARG_CURSOR_FILE:
ce2b92e8
YW
664 r = free_and_strdup_warn(&arg_cursor_file, optarg);
665 if (r < 0)
666 return r;
d9e15cbd
JS
667 break;
668
248fc619 669 case ARG_AFTER_CURSOR:
ce2b92e8
YW
670 r = free_and_strdup_warn(&arg_after_cursor, optarg);
671 if (r < 0)
672 return r;
248fc619
ZJS
673 break;
674
675 case ARG_SHOW_CURSOR:
676 arg_show_cursor = true;
677 break;
678
dca6219e 679 case ARG_HEADER:
7560fffc
LP
680 arg_action = ACTION_PRINT_HEADER;
681 break;
682
feb12d3e
LP
683 case ARG_VERIFY:
684 arg_action = ACTION_VERIFY;
685 break;
686
a1a03e30
LP
687 case ARG_DISK_USAGE:
688 arg_action = ACTION_DISK_USAGE;
689 break;
690
dbd2a83f
LP
691 case ARG_VACUUM_SIZE:
692 r = parse_size(optarg, 1024, &arg_vacuum_size);
0491150b
LP
693 if (r < 0)
694 return log_error_errno(r, "Failed to parse vacuum size: %s", optarg);
dbd2a83f 695
8df64fd0 696 arg_action = arg_action == ACTION_ROTATE ? ACTION_ROTATE_AND_VACUUM : ACTION_VACUUM;
dbd2a83f
LP
697 break;
698
8580d1f7
LP
699 case ARG_VACUUM_FILES:
700 r = safe_atou64(optarg, &arg_vacuum_n_files);
0491150b
LP
701 if (r < 0)
702 return log_error_errno(r, "Failed to parse vacuum files: %s", optarg);
8580d1f7 703
8df64fd0 704 arg_action = arg_action == ACTION_ROTATE ? ACTION_ROTATE_AND_VACUUM : ACTION_VACUUM;
8580d1f7
LP
705 break;
706
dbd2a83f
LP
707 case ARG_VACUUM_TIME:
708 r = parse_sec(optarg, &arg_vacuum_time);
0491150b
LP
709 if (r < 0)
710 return log_error_errno(r, "Failed to parse vacuum time: %s", optarg);
dbd2a83f 711
8df64fd0 712 arg_action = arg_action == ACTION_ROTATE ? ACTION_ROTATE_AND_VACUUM : ACTION_VACUUM;
dbd2a83f
LP
713 break;
714
349cc4a5 715#if HAVE_GCRYPT
b8547c10
SL
716 case ARG_FORCE:
717 arg_force = true;
718 break;
719
7560fffc
LP
720 case ARG_SETUP_KEYS:
721 arg_action = ACTION_SETUP_KEYS;
dca6219e
LP
722 break;
723
baed47c3 724 case ARG_VERIFY_KEY:
d0ad4e88
YW
725 erase_and_free(arg_verify_key);
726 arg_verify_key = strdup(optarg);
727 if (!arg_verify_key)
728 return log_oom();
729
309c6b19 730 /* Use memset not explicit_bzero() or similar so this doesn't look confusing
1075122f
ZJS
731 * in ps or htop output. */
732 memset(optarg, 'x', strlen(optarg));
e50412ef 733
0491150b 734 arg_action = ACTION_VERIFY;
e50412ef 735 arg_merge = false;
4da416aa
LP
736 break;
737
baed47c3 738 case ARG_INTERVAL:
7f602784 739 r = parse_sec(optarg, &arg_interval);
0491150b
LP
740 if (r < 0 || arg_interval <= 0)
741 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
742 "Failed to parse sealing key change interval: %s", optarg);
14d10188 743 break;
feb12d3e
LP
744#else
745 case ARG_SETUP_KEYS:
746 case ARG_VERIFY_KEY:
747 case ARG_INTERVAL:
b8547c10 748 case ARG_FORCE:
0491150b
LP
749 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
750 "Compiled without forward-secure sealing support.");
feb12d3e 751#endif
14d10188 752
941e990d
LP
753 case 'p': {
754 const char *dots;
755
756 dots = strstr(optarg, "..");
757 if (dots) {
e7238caf 758 _cleanup_free_ char *a = NULL;
941e990d
LP
759 int from, to, i;
760
761 /* a range */
762 a = strndup(optarg, dots - optarg);
763 if (!a)
764 return log_oom();
765
766 from = log_level_from_string(a);
767 to = log_level_from_string(dots + 2);
941e990d 768
0491150b 769 if (from < 0 || to < 0)
7211c853 770 return log_error_errno(from < 0 ? from : to,
0491150b 771 "Failed to parse log level range %s", optarg);
941e990d
LP
772
773 arg_priorities = 0;
774
775 if (from < to) {
776 for (i = from; i <= to; i++)
777 arg_priorities |= 1 << i;
778 } else {
779 for (i = to; i <= from; i++)
780 arg_priorities |= 1 << i;
781 }
782
783 } else {
784 int p, i;
785
786 p = log_level_from_string(optarg);
0491150b 787 if (p < 0)
7211c853 788 return log_error_errno(p, "Unknown log level %s", optarg);
941e990d
LP
789
790 arg_priorities = 0;
791
792 for (i = 0; i <= p; i++)
793 arg_priorities |= 1 << i;
794 }
795
796 break;
797 }
798
196dedd5
ZJS
799 case ARG_FACILITY: {
800 const char *p;
801
802 for (p = optarg;;) {
803 _cleanup_free_ char *fac = NULL;
804 int num;
805
806 r = extract_first_word(&p, &fac, ",", 0);
807 if (r < 0)
808 return log_error_errno(r, "Failed to parse facilities: %s", optarg);
809 if (r == 0)
810 break;
811
812 if (streq(fac, "help")) {
813 help_facilities();
814 return 0;
815 }
816
817 num = log_facility_unshifted_from_string(fac);
818 if (num < 0)
7211c853 819 return log_error_errno(num, "Bad --facility= argument \"%s\".", fac);
196dedd5 820
de7fef4b 821 if (set_ensure_put(&arg_facilities, NULL, INT_TO_PTR(num)) < 0)
196dedd5
ZJS
822 return log_oom();
823 }
824
825 break;
826 }
827
61c5f8a1 828 case 'g':
ce2b92e8
YW
829 r = free_and_strdup_warn(&arg_pattern, optarg);
830 if (r < 0)
831 return r;
6becf48c 832 break;
6becf48c 833
61c5f8a1
ZJS
834 case ARG_CASE_SENSITIVE:
835 if (optarg) {
836 r = parse_boolean(optarg);
837 if (r < 0)
838 return log_error_errno(r, "Bad --case-sensitive= argument \"%s\": %m", optarg);
75db32dc 839 arg_case = r ? PATTERN_COMPILE_CASE_SENSITIVE : PATTERN_COMPILE_CASE_INSENSITIVE;
61c5f8a1 840 } else
75db32dc 841 arg_case = PATTERN_COMPILE_CASE_SENSITIVE;
61c5f8a1
ZJS
842
843 break;
6becf48c 844
66f52924 845 case 'S':
cfbc22ab 846 r = parse_timestamp(optarg, &arg_since);
0491150b
LP
847 if (r < 0)
848 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
849 "Failed to parse timestamp: %s", optarg);
cfbc22ab
LP
850 arg_since_set = true;
851 break;
852
66f52924 853 case 'U':
cfbc22ab 854 r = parse_timestamp(optarg, &arg_until);
0491150b
LP
855 if (r < 0)
856 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
857 "Failed to parse timestamp: %s", optarg);
cfbc22ab
LP
858 arg_until_set = true;
859 break;
860
73083640
HH
861 case 't':
862 r = strv_extend(&arg_syslog_identifier, optarg);
863 if (r < 0)
864 return log_oom();
865 break;
866
25aa35d4
SZ
867 case 'T':
868 r = strv_extend(&arg_exclude_identifier, optarg);
869 if (r < 0)
870 return log_oom();
871 break;
872
7199aa96 873 case 'u':
b9e40524
HH
874 r = strv_extend(&arg_system_units, optarg);
875 if (r < 0)
876 return log_oom();
ffa7cd15
DW
877 break;
878
7199aa96 879 case ARG_USER_UNIT:
b9e40524
HH
880 r = strv_extend(&arg_user_units, optarg);
881 if (r < 0)
882 return log_oom();
c3f60ec5
LP
883 break;
884
7d3ae6b2
YW
885 case ARG_INVOCATION:
886 r = parse_id_descriptor(optarg, &arg_invocation_id, &arg_invocation_offset);
887 if (r < 0)
888 return log_error_errno(r, "Failed to parse invocation descriptor: %s", optarg);
889 arg_invocation = r;
890 break;
891
892 case 'I':
893 /* Equivalent to --invocation=0 */
894 arg_invocation = true;
895 arg_invocation_id = SD_ID128_NULL;
896 arg_invocation_offset = 0;
897 break;
898
15119c16 899 case 'F':
69e714f3 900 arg_action = ACTION_LIST_FIELDS;
ce2b92e8
YW
901 r = free_and_strdup_warn(&arg_field, optarg);
902 if (r < 0)
903 return r;
15119c16
LP
904 break;
905
69e714f3
LP
906 case 'N':
907 arg_action = ACTION_LIST_FIELD_NAMES;
908 break;
909
991e274b
LP
910 case ARG_NO_HOSTNAME:
911 arg_no_hostname = true;
912 break;
913
d4205751
LP
914 case 'x':
915 arg_catalog = true;
916 break;
917
918 case ARG_LIST_CATALOG:
919 arg_action = ACTION_LIST_CATALOG;
920 break;
921
54b7254c
ZJS
922 case ARG_DUMP_CATALOG:
923 arg_action = ACTION_DUMP_CATALOG;
924 break;
925
d4205751
LP
926 case ARG_UPDATE_CATALOG:
927 arg_action = ACTION_UPDATE_CATALOG;
928 break;
929
d89d6c86
LN
930 case 'r':
931 arg_reverse = true;
932 break;
933
9fd29044
JS
934 case ARG_UTC:
935 arg_utc = true;
936 break;
937
74055aa7
LP
938 case ARG_FLUSH:
939 arg_action = ACTION_FLUSH;
940 break;
941
c0dfcb31
LP
942 case ARG_SMART_RELINQUISH_VAR: {
943 int root_mnt_id, log_mnt_id;
944
945 /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
946 * if it's on the same mount as the root file system there's no point in
947 * relinquishing access and we can leave journald write to it until the very last
948 * moment. */
949
950 r = path_get_mnt_id("/", &root_mnt_id);
951 if (r < 0)
952 log_debug_errno(r, "Failed to get root mount ID, ignoring: %m");
953 else {
954 r = path_get_mnt_id("/var/log/journal/", &log_mnt_id);
955 if (r < 0)
956 log_debug_errno(r, "Failed to get journal directory mount ID, ignoring: %m");
957 else if (root_mnt_id == log_mnt_id) {
958 log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
959 return 0;
960 } else
961 log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
962 }
963
964 _fallthrough_;
965 }
966
967 case ARG_RELINQUISH_VAR:
968 arg_action = ACTION_RELINQUISH_VAR;
969 break;
970
e3fdfb49 971 case ARG_ROTATE:
8df64fd0 972 arg_action = arg_action == ACTION_VACUUM ? ACTION_ROTATE_AND_VACUUM : ACTION_ROTATE;
e3fdfb49
EV
973 break;
974
94b65516
LP
975 case ARG_SYNC:
976 arg_action = ACTION_SYNC;
977 break;
978
cc25a67e
LK
979 case ARG_OUTPUT_FIELDS: {
980 _cleanup_strv_free_ char **v = NULL;
981
982 v = strv_split(optarg, ",");
983 if (!v)
984 return log_oom();
985
c5da14cd
LP
986 r = set_put_strdupv(&arg_output_fields, v);
987 if (r < 0)
988 return log_oom();
989
cc25a67e
LK
990 break;
991 }
d2f45c76
LP
992
993 case ARG_SYNCHRONIZE_ON_EXIT:
994 r = parse_boolean_argument("--synchronize-on-exit", optarg, &arg_synchronize_on_exit);
995 if (r < 0)
996 return r;
997
998 break;
999
eb9da376 1000 case '?':
0d43c694 1001 return -EINVAL;
eb9da376
LP
1002
1003 default:
04499a70 1004 assert_not_reached();
0d43c694 1005 }
0d43c694 1006
3f2203f6
YW
1007 if (arg_no_tail)
1008 arg_lines = ARG_LINES_ALL;
1009
f8bfe16b
YW
1010 if (arg_lines == ARG_LINES_DEFAULT) {
1011 if (arg_follow && !arg_since_set)
1012 arg_lines = 10;
1013 else if (FLAGS_SET(arg_pager_flags, PAGER_JUMP_TO_END))
1014 arg_lines = 1000;
1015 }
e91af489 1016
f8bfe16b
YW
1017 if (arg_boot < 0)
1018 /* Show the current boot if -f/--follow, -k/--dmesg, or -e/--pager-end is specified unless
1019 * -m/--merge is specified. */
1020 arg_boot = !arg_merge && (arg_follow || arg_dmesg || FLAGS_SET(arg_pager_flags, PAGER_JUMP_TO_END));
1021 if (!arg_boot) {
1022 /* Clear the boot ID and offset if -b/--boot is unspecified for safety. */
e47622a6
FS
1023 arg_boot_id = SD_ID128_NULL;
1024 arg_boot_offset = 0;
1025 }
1026
821bf13b 1027 if (!!arg_directory + !!arg_file + arg_file_stdin + !!arg_machine + !!arg_root + !!arg_image > 1)
d7a0f1f4
FS
1028 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1029 "Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=.");
8d98da3f 1030
d7a0f1f4
FS
1031 if (arg_since_set && arg_until_set && arg_since > arg_until)
1032 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1033 "--since= must be before --until=.");
cfbc22ab 1034
159d1e26 1035 if (!!arg_cursor + !!arg_after_cursor + !!arg_cursor_file + !!arg_since_set > 1)
d7a0f1f4 1036 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
159d1e26 1037 "Please specify only one of --since=, --cursor=, --cursor-file=, and --after-cursor=.");
cfbc22ab 1038
d7a0f1f4
FS
1039 if (arg_follow && arg_reverse)
1040 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
8d6791d2
MY
1041 "Please specify either --reverse or --follow, not both.");
1042
d0936a72 1043 if (arg_action == ACTION_SHOW && arg_lines >= 0 && arg_lines_oldest && (arg_reverse || arg_follow))
8d6791d2
MY
1044 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1045 "--lines=+N is unsupported when --reverse or --follow is specified.");
d89d6c86 1046
d7a0f1f4
FS
1047 if (!IN_SET(arg_action, ACTION_SHOW, ACTION_DUMP_CATALOG, ACTION_LIST_CATALOG) && optind < argc)
1048 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1049 "Extraneous arguments starting with '%s'",
1050 argv[optind]);
0b6b7c20 1051
d7a0f1f4
FS
1052 if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && arg_merge)
1053 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1054 "Using --boot or --list-boots with --merge is not supported.");
596a2329 1055
e79d0b59 1056 if (!strv_isempty(arg_system_units) && arg_journal_type == SD_JOURNAL_CURRENT_USER) {
52051dd8
LP
1057 /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user
1058 * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice
1059 * to users, and automatically turn --unit= into --user-unit= if combined with --user. */
1060 r = strv_extend_strv(&arg_user_units, arg_system_units, true);
1061 if (r < 0)
e50412ef 1062 return r;
52051dd8
LP
1063
1064 arg_system_units = strv_free(arg_system_units);
1065 }
1066
61c5f8a1 1067 if (arg_pattern) {
75db32dc 1068 r = pattern_compile_and_log(arg_pattern, arg_case, &arg_compiled_pattern);
61c5f8a1
ZJS
1069 if (r < 0)
1070 return r;
db469196 1071
8d6791d2
MY
1072 /* When --grep is used along with --lines without '+', i.e. when we start from the end of the
1073 * journal, we don't know how many lines we can print. So we search backwards and count until
1074 * enough lines have been printed or we hit the head.
c673fd52
MY
1075 * An exception is that --follow might set arg_lines, so let's not imply --reverse
1076 * if that is specified. */
8d6791d2 1077 if (arg_lines_needs_seek_end() && !arg_follow)
db469196 1078 arg_reverse = true;
61c5f8a1 1079 }
61c5f8a1 1080
f7f062bf
YW
1081 if (!arg_follow)
1082 arg_journal_additional_open_flags = SD_JOURNAL_ASSUME_IMMUTABLE;
1083
0d43c694
LP
1084 return 1;
1085}
1086
ade2db83
YW
1087static int run(int argc, char *argv[]) {
1088 _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
1089 _cleanup_(umount_and_freep) char *mounted_dir = NULL;
ce2b92e8 1090 _cleanup_strv_free_ char **args = NULL;
c3f60ec5 1091 int r;
ea18a4b5 1092
ade2db83
YW
1093 setlocale(LC_ALL, "");
1094 log_setup();
ea18a4b5 1095
ade2db83
YW
1096 r = parse_argv(argc, argv);
1097 if (r <= 0)
1098 return r;
ea18a4b5 1099
ce2b92e8
YW
1100 r = strv_copy_unless_empty(strv_skip(argv, optind), &args);
1101 if (r < 0)
1102 return log_oom();
ea18a4b5 1103
ade2db83
YW
1104 if (arg_image) {
1105 assert(!arg_root);
ea18a4b5 1106
ade2db83
YW
1107 r = mount_image_privately_interactively(
1108 arg_image,
1109 arg_image_policy,
1110 DISSECT_IMAGE_GENERIC_ROOT |
1111 DISSECT_IMAGE_REQUIRE_ROOT |
1112 DISSECT_IMAGE_VALIDATE_OS |
1113 DISSECT_IMAGE_RELAX_VAR_CHECK |
1114 (arg_action == ACTION_UPDATE_CATALOG ? DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS : DISSECT_IMAGE_READ_ONLY) |
1115 DISSECT_IMAGE_ALLOW_USERSPACE_VERITY,
1116 &mounted_dir,
1117 /* ret_dir_fd= */ NULL,
1118 &loop_device);
b9e40524
HH
1119 if (r < 0)
1120 return r;
ea18a4b5 1121
ade2db83
YW
1122 arg_root = strdup(mounted_dir);
1123 if (!arg_root)
1124 return log_oom();
b9e40524 1125 }
c3f60ec5 1126
ade2db83 1127 switch (arg_action) {
ea18a4b5 1128
ade2db83
YW
1129 case ACTION_SHOW:
1130 return action_show(args);
ea18a4b5 1131
ade2db83
YW
1132 case ACTION_NEW_ID128:
1133 return id128_print_new(ID128_PRINT_PRETTY);
c3f60ec5 1134
ade2db83
YW
1135 case ACTION_SETUP_KEYS:
1136 return action_setup_keys();
ea18a4b5 1137
ade2db83
YW
1138 case ACTION_LIST_CATALOG:
1139 case ACTION_DUMP_CATALOG:
1140 return action_list_catalog(args);
b9e40524 1141
ade2db83
YW
1142 case ACTION_UPDATE_CATALOG:
1143 return action_update_catalog();
b9e40524 1144
ade2db83
YW
1145 case ACTION_PRINT_HEADER:
1146 return action_print_header();
c3f60ec5 1147
ade2db83
YW
1148 case ACTION_VERIFY:
1149 return action_verify();
ea18a4b5 1150
ade2db83
YW
1151 case ACTION_DISK_USAGE:
1152 return action_disk_usage();
cd34b3c6 1153
ade2db83
YW
1154 case ACTION_LIST_BOOTS:
1155 return action_list_boots();
c3f60ec5 1156
ade2db83
YW
1157 case ACTION_LIST_FIELDS:
1158 return action_list_fields();
941e990d 1159
ade2db83
YW
1160 case ACTION_LIST_FIELD_NAMES:
1161 return action_list_field_names();
941e990d 1162
7d3ae6b2
YW
1163 case ACTION_LIST_INVOCATIONS:
1164 return action_list_invocations();
1165
ade2db83
YW
1166 case ACTION_LIST_NAMESPACES:
1167 return action_list_namespaces();
941e990d 1168
ade2db83
YW
1169 case ACTION_FLUSH:
1170 return action_flush_to_var();
941e990d 1171
ade2db83
YW
1172 case ACTION_RELINQUISH_VAR:
1173 return action_relinquish_var();
cd34b3c6 1174
ade2db83
YW
1175 case ACTION_SYNC:
1176 return action_sync();
941e990d 1177
ade2db83
YW
1178 case ACTION_ROTATE:
1179 return action_rotate();
196dedd5 1180
ade2db83
YW
1181 case ACTION_VACUUM:
1182 return action_vacuum();
196dedd5 1183
ade2db83
YW
1184 case ACTION_ROTATE_AND_VACUUM:
1185 return action_rotate_and_vacuum();
196dedd5 1186
ade2db83
YW
1187 default:
1188 assert_not_reached();
196dedd5 1189 }
87d2c1ff 1190}
9556e79b 1191
64347b97 1192DEFINE_MAIN_FUNCTION_WITH_POSITIVE_SIGNAL(run);