diff --git a/src/journal/journalctl-filter.c b/src/journal/journalctl-filter.c index ce2a6cb18c..01c82ca405 100644 --- a/src/journal/journalctl-filter.c +++ b/src/journal/journalctl-filter.c @@ -23,6 +23,25 @@ #include "strv.h" #include "unit-name.h" +bool field_list_has_scope_options(void) { + return + arg_boot_filter || + arg_invocation || + arg_dmesg || + arg_cursor || + arg_after_cursor || + arg_cursor_file || + !strv_isempty(arg_system_units) || + !strv_isempty(arg_user_units) || + !strv_isempty(arg_syslog_identifier) || + !strv_isempty(arg_exclude_identifier) || + arg_priorities != 0 || + !set_isempty(arg_facilities) || + arg_since_set || + arg_until_set || + arg_pattern; +} + static int add_invocation(sd_journal *j) { int r; diff --git a/src/journal/journalctl-filter.h b/src/journal/journalctl-filter.h index bf2f7b839c..f0ac453d3c 100644 --- a/src/journal/journalctl-filter.h +++ b/src/journal/journalctl-filter.h @@ -11,4 +11,5 @@ int journal_add_unit_matches( uid_t uid, char * const *user_units); +bool field_list_has_scope_options(void); int add_filters(sd_journal *j, char **matches); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index b407a77d97..4bc648ceff 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -17,6 +17,7 @@ #include "journalctl.h" #include "journalctl-authenticate.h" #include "journalctl-catalog.h" +#include "journalctl-filter.h" #include "journalctl-metrics.h" #include "journalctl-misc.h" #include "journalctl-show.h" @@ -70,6 +71,7 @@ bool arg_merge = false; int arg_boot = -1; /* tristate */ sd_id128_t arg_boot_id = {}; int arg_boot_offset = 0; +bool arg_boot_filter = false; bool arg_dmesg = false; bool arg_no_hostname = false; char *arg_cursor = NULL; @@ -532,6 +534,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { OPTION_LONG("this-boot", NULL, /* help= */ NULL): arg_boot = true; + arg_boot_filter = true; arg_boot_id = SD_ID128_NULL; arg_boot_offset = 0; break; @@ -539,6 +542,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { OPTION_FULL(OPTION_OPTIONAL_ARG, 'b', "boot", "ID", "Show current boot or the specified boot"): arg_boot = true; + arg_boot_filter = true; arg_boot_id = SD_ID128_NULL; arg_boot_offset = 0; @@ -548,6 +552,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { return log_error_errno(r, "Failed to parse boot descriptor '%s'", opts.arg); arg_boot = r; + arg_boot_filter = r > 0; } else { /* Hmm, no argument? Maybe the next word on the command line is supposed to @@ -558,6 +563,7 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { r = parse_id_descriptor(peek, &arg_boot_id, &arg_boot_offset); if (r >= 0) { arg_boot = r; + arg_boot_filter = r > 0; (void) option_parser_consume_next_arg(&opts); } } @@ -976,6 +982,10 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { "Extraneous arguments starting with '%s'", args[0]); + if (IN_SET(arg_action, ACTION_LIST_FIELDS, ACTION_LIST_FIELD_NAMES) && field_list_has_scope_options()) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "-F/--field= and -N/--fields cannot be combined with options that limit the journal."); + if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && arg_merge) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Using --boot or --list-boots with --merge is not supported."); diff --git a/src/journal/journalctl.h b/src/journal/journalctl.h index 59353253d4..23535ab0ce 100644 --- a/src/journal/journalctl.h +++ b/src/journal/journalctl.h @@ -45,6 +45,7 @@ extern bool arg_merge; extern int arg_boot; extern sd_id128_t arg_boot_id; extern int arg_boot_offset; +extern bool arg_boot_filter; extern bool arg_dmesg; extern bool arg_no_hostname; extern char *arg_cursor; diff --git a/test/units/TEST-04-JOURNAL.journal.sh b/test/units/TEST-04-JOURNAL.journal.sh index 03613b5805..403164016f 100755 --- a/test/units/TEST-04-JOURNAL.journal.sh +++ b/test/units/TEST-04-JOURNAL.journal.sh @@ -158,6 +158,10 @@ journalctl --root / | grep . >/dev/null journalctl --cursor "t=0;t=-1;t=0;t=0x0" | grep . >/dev/null journalctl --header | grep system.journal journalctl --field _EXE | grep . >/dev/null +journalctl --field _EXE --pager-end | grep . >/dev/null +(! journalctl -q --field _SYSTEMD_UNIT --unit "test-no-such-unit-$RANDOM.service" --no-pager) +(! journalctl -q --field _SYSTEMD_UNIT --since "9999-01-01" --no-pager) +(! journalctl -q --fields --unit "test-no-such-unit-$RANDOM.service" --no-pager) journalctl --no-hostname --utc --catalog | grep . >/dev/null # Exercise executable_is_script() and the related code, e.g. `journalctl -b /path/to/a/script.sh` should turn # into ((_EXE=/usr/bin/bash AND _COMM=script.sh) AND _BOOT_ID=c002e3683ba14fa8b6c1e12878386514)