homectl: add interface for controlling storage for negative machine ID matches

This commit is contained in:
Lennart Poettering
2025-02-19 21:56:54 +01:00
parent c7a4216509
commit 0e1ede4b4b
4 changed files with 175 additions and 68 deletions

View File

@@ -774,14 +774,23 @@ If any of the specified IDs match the system's local machine ID
(As a special case, if only a single machine ID is listed this field may be a single
string rather than an array of strings.)
`matchNotMachineId` → Similar to `matchMachineId` but implements the inverse
match: this section only applies if the local machine ID does *not* match any
of the listed IDs.
`matchHostname` → An array of strings that are valid hostnames.
If any of the specified hostnames match the system's local hostname, the fields in this object are honored.
If both `matchHostname` and `matchMachineId` are used within the same array entry, the object is honored when either match succeeds,
i.e. the two match types are combined in OR, not in AND.
(As a special case, if only a single hostname is listed this field may be a single string rather than an array of strings.)
These two are the only two fields specific to this section.
All other fields that may be used in this section are identical to the equally named ones in the
`matchNotHostname` → Similar to `matchHostname`, but implement the inverse
match, as above.
If any of these four fields are used within the same array entry, the object is
honored when either match succeeds, i.e. the match types are combined in OR,
not in AND.
These four are the only fields specific to this section. All other fields that
may be used in this section are identical to the equally named ones in the
`regular` section (i.e. at the top-level object). Specifically, these are:
`blobDirectory`, `blobManifest`, `iconName`, `location`, `shell`, `umask`,

View File

@@ -205,6 +205,40 @@
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--match=</option></term>
<term><option>-A</option></term>
<term><option>-N</option></term>
<term><option>-T</option></term>
<listitem><para>Takes one of <literal>this</literal>, <literal>other</literal>,
<literal>any</literal> or <literal>auto</literal>. Some user record settings can be defined to match
only specific machines, or all machines but one, or all machines. With this switch it is possibly to
control to which machines to apply the settings appearing on the command line after it. If
<literal>this</literal> is specified the setting will only apply to the local system (positive
match), if <literal>other</literal> it will apply to all but the local system (negative match), if
<literal>any</literal> it will apply to all systems (unless there's a matching positive or negative
per-machine setting). If <literal>auto</literal> returns to the default logic: whether a setting
applies by default to the local system or all systems depends on the option in question.</para>
<para>Note that only some user record settings can be conditioned like this. This option has no
effect on the others and is ignored there. This option may appear multiple times in a single command
line to apply settings conditioned by different matches to the same user record. See <ulink
url="https://systemd.io/USER_RECORD">JSON User Records</ulink> for details on which settings may be
used with such per-machine matching and which ones may not.</para>
<para><option>-A</option> is a shortcut for <option>--match=any</option>, <option>-T</option> is
short for <option>--match=this</option> and <option>-N</option> is short for
<option>--match=other</option>.</para>
<para>Here's an example call that sets the storage field to <literal>luks</literal> on the local
system, but to <literal>cifs</literal> on all others:</para>
<programlisting># homectl update lennart -T --storage=luks -N --storage=cifs</programlisting>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<xi:include href="user-system-options.xml" xpointer="host" />
<xi:include href="user-system-options.xml" xpointer="machine" />

View File

@@ -41,7 +41,7 @@ _homectl() {
local -A OPTS=(
[STANDALONE]='-h --help --version
--no-pager --no-legend --no-ask-password
-j -E -P'
-j -E -P -A -N -T'
[ARG]=' -H --host
-M --machine
--identity
@@ -114,7 +114,8 @@ _homectl() {
--session-launcher
--session-type
--key-name
--seize'
--seize
--match'
)
if __contains_word "$prev" ${OPTS[ARG]}; then

View File

@@ -70,6 +70,7 @@ static const char *arg_identity = NULL;
static sd_json_variant *arg_identity_extra = NULL;
static sd_json_variant *arg_identity_extra_privileged = NULL;
static sd_json_variant *arg_identity_extra_this_machine = NULL;
static sd_json_variant *arg_identity_extra_other_machines = NULL;
static sd_json_variant *arg_identity_extra_rlimits = NULL;
static char **arg_identity_filter = NULL; /* this one is also applied to 'privileged' and 'thisMachine' subobjects */
static char **arg_identity_filter_rlimits = NULL;
@@ -104,6 +105,7 @@ static bool arg_seize = true;
STATIC_DESTRUCTOR_REGISTER(arg_identity_extra, sd_json_variant_unrefp);
STATIC_DESTRUCTOR_REGISTER(arg_identity_extra_this_machine, sd_json_variant_unrefp);
STATIC_DESTRUCTOR_REGISTER(arg_identity_extra_other_machines, sd_json_variant_unrefp);
STATIC_DESTRUCTOR_REGISTER(arg_identity_extra_privileged, sd_json_variant_unrefp);
STATIC_DESTRUCTOR_REGISTER(arg_identity_extra_rlimits, sd_json_variant_unrefp);
STATIC_DESTRUCTOR_REGISTER(arg_identity_filter, strv_freep);
@@ -122,6 +124,7 @@ static bool identity_properties_specified(void) {
!sd_json_variant_is_blank_object(arg_identity_extra) ||
!sd_json_variant_is_blank_object(arg_identity_extra_privileged) ||
!sd_json_variant_is_blank_object(arg_identity_extra_this_machine) ||
!sd_json_variant_is_blank_object(arg_identity_extra_other_machines) ||
!sd_json_variant_is_blank_object(arg_identity_extra_rlimits) ||
!strv_isempty(arg_identity_filter) ||
!strv_isempty(arg_identity_filter_rlimits) ||
@@ -932,7 +935,7 @@ static int apply_identity_changes(sd_json_variant **_v) {
if (r < 0)
return log_error_errno(r, "Failed to merge identities: %m");
if (arg_identity_extra_this_machine || !strv_isempty(arg_identity_filter)) {
if (arg_identity_extra_this_machine || arg_identity_extra_other_machines || !strv_isempty(arg_identity_filter)) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *per_machine = NULL, *mmid = NULL;
sd_id128_t mid;
@@ -946,7 +949,7 @@ static int apply_identity_changes(sd_json_variant **_v) {
per_machine = sd_json_variant_ref(sd_json_variant_by_key(v, "perMachine"));
if (per_machine) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *npm = NULL, *add = NULL;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *npm = NULL, *positive = NULL, *negative = NULL;
_cleanup_free_ sd_json_variant **array = NULL;
sd_json_variant *z;
size_t i = 0;
@@ -954,7 +957,7 @@ static int apply_identity_changes(sd_json_variant **_v) {
if (!sd_json_variant_is_array(per_machine))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "perMachine field is not an array, refusing.");
array = new(sd_json_variant*, sd_json_variant_elements(per_machine) + 1);
array = new(sd_json_variant*, sd_json_variant_elements(per_machine) + 2);
if (!array)
return log_oom();
@@ -967,31 +970,41 @@ static int apply_identity_changes(sd_json_variant **_v) {
array[i++] = z;
u = sd_json_variant_by_key(z, "matchMachineId");
if (!u)
continue;
if (u && sd_json_variant_equal(u, mmid))
r = sd_json_variant_merge_object(&positive, z);
else {
u = sd_json_variant_by_key(z, "matchNotMachineId");
if (!u || !sd_json_variant_equal(u, mmid))
continue;
if (!sd_json_variant_equal(u, mmid))
continue;
r = sd_json_variant_merge_object(&add, z);
r = sd_json_variant_merge_object(&negative, z);
}
if (r < 0)
return log_error_errno(r, "Failed to merge perMachine entry: %m");
i--;
}
r = sd_json_variant_filter(&add, arg_identity_filter);
r = sd_json_variant_filter(&positive, arg_identity_filter);
if (r < 0)
return log_error_errno(r, "Failed to filter perMachine: %m");
r = sd_json_variant_merge_object(&add, arg_identity_extra_this_machine);
r = sd_json_variant_filter(&negative, arg_identity_filter);
if (r < 0)
return log_error_errno(r, "Failed to filter perMachine: %m");
r = sd_json_variant_merge_object(&positive, arg_identity_extra_this_machine);
if (r < 0)
return log_error_errno(r, "Failed to merge in perMachine fields: %m");
r = sd_json_variant_merge_object(&negative, arg_identity_extra_other_machines);
if (r < 0)
return log_error_errno(r, "Failed to merge in perMachine fields: %m");
if (arg_identity_filter_rlimits || arg_identity_extra_rlimits) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *rlv = NULL;
rlv = sd_json_variant_ref(sd_json_variant_by_key(add, "resourceLimits"));
rlv = sd_json_variant_ref(sd_json_variant_by_key(positive, "resourceLimits"));
r = sd_json_variant_filter(&rlv, arg_identity_filter_rlimits);
if (r < 0)
@@ -1002,22 +1015,30 @@ static int apply_identity_changes(sd_json_variant **_v) {
return log_error_errno(r, "Failed to set resource limits: %m");
if (sd_json_variant_is_blank_object(rlv)) {
r = sd_json_variant_filter(&add, STRV_MAKE("resourceLimits"));
r = sd_json_variant_filter(&positive, STRV_MAKE("resourceLimits"));
if (r < 0)
return log_error_errno(r, "Failed to drop resource limits field from identity: %m");
} else {
r = sd_json_variant_set_field(&add, "resourceLimits", rlv);
r = sd_json_variant_set_field(&positive, "resourceLimits", rlv);
if (r < 0)
return log_error_errno(r, "Failed to update resource limits of identity: %m");
}
}
if (!sd_json_variant_is_blank_object(add)) {
r = sd_json_variant_set_field(&add, "matchMachineId", mmid);
if (!sd_json_variant_is_blank_object(positive)) {
r = sd_json_variant_set_field(&positive, "matchMachineId", mmid);
if (r < 0)
return log_error_errno(r, "Failed to set matchMachineId field: %m");
array[i++] = add;
array[i++] = positive;
}
if (!sd_json_variant_is_blank_object(negative)) {
r = sd_json_variant_set_field(&negative, "matchNotMachineId", mmid);
if (r < 0)
return log_error_errno(r, "Failed to set matchNotMachineId field: %m");
array[i++] = negative;
}
r = sd_json_variant_new_array(&npm, array, i);
@@ -1027,21 +1048,34 @@ static int apply_identity_changes(sd_json_variant **_v) {
sd_json_variant_unref(per_machine);
per_machine = TAKE_PTR(npm);
} else {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *item = sd_json_variant_ref(arg_identity_extra_this_machine);
_cleanup_(sd_json_variant_unrefp) sd_json_variant *positive = sd_json_variant_ref(arg_identity_extra_this_machine),
*negative = sd_json_variant_ref(arg_identity_extra_other_machines);
if (arg_identity_extra_rlimits) {
r = sd_json_variant_set_field(&item, "resourceLimits", arg_identity_extra_rlimits);
r = sd_json_variant_set_field(&positive, "resourceLimits", arg_identity_extra_rlimits);
if (r < 0)
return log_error_errno(r, "Failed to update resource limits of identity: %m");
}
r = sd_json_variant_set_field(&item, "matchMachineId", mmid);
if (r < 0)
return log_error_errno(r, "Failed to set matchMachineId field: %m");
if (positive) {
r = sd_json_variant_set_field(&positive, "matchMachineId", mmid);
if (r < 0)
return log_error_errno(r, "Failed to set matchMachineId field: %m");
r = sd_json_variant_append_array(&per_machine, item);
if (r < 0)
return log_error_errno(r, "Failed to append to perMachine array: %m");
r = sd_json_variant_append_array(&per_machine, positive);
if (r < 0)
return log_error_errno(r, "Failed to append to perMachine array: %m");
}
if (negative) {
r = sd_json_variant_set_field(&negative, "matchNotMachineId", mmid);
if (r < 0)
return log_error_errno(r, "Failed to set matchNotMachineId field: %m");
r = sd_json_variant_append_array(&per_machine, negative);
if (r < 0)
return log_error_errno(r, "Failed to append to perMachine array: %m");
}
}
r = sd_json_variant_set_field(&v, "perMachine", per_machine);
@@ -3239,6 +3273,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_DEFAULT_AREA,
ARG_KEY_NAME,
ARG_SEIZE,
ARG_MATCH,
};
static const struct option options[] = {
@@ -3344,11 +3379,17 @@ static int parse_argv(int argc, char *argv[]) {
{ "default-area", required_argument, NULL, ARG_DEFAULT_AREA },
{ "key-name", required_argument, NULL, ARG_KEY_NAME },
{ "seize", required_argument, NULL, ARG_SEIZE },
{ "match", required_argument, NULL, ARG_MATCH },
{}
};
int r;
/* This points to one of arg_identity_extra, arg_identity_extra_this_machine,
* arg_identity_extra_other_machines, in order to redirect changes on the next property being set to
* this part of the identity, instead of the default. */
sd_json_variant **match_identity = NULL;
assert(argc >= 0);
assert(argv);
@@ -3362,7 +3403,7 @@ static int parse_argv(int argc, char *argv[]) {
for (;;) {
int c;
c = getopt_long(argc, argv, "hH:M:I:c:d:u:G:k:s:e:b:jPE", options, NULL);
c = getopt_long(argc, argv, "hH:M:I:c:d:u:G:k:s:e:b:jPENAT", options, NULL);
if (c < 0)
break;
@@ -3416,7 +3457,7 @@ static int parse_argv(int argc, char *argv[]) {
if (!valid_gecos(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Real name '%s' not a valid GECOS field.", optarg);
r = sd_json_variant_set_field_string(&arg_identity_extra, "realName", optarg);
r = sd_json_variant_set_field_string(match_identity ?: &arg_identity_extra, "realName", optarg);
if (r < 0)
return log_error_errno(r, "Failed to set realName field: %m");
@@ -3546,7 +3587,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
r = sd_json_variant_set_field_string(&arg_identity_extra, field, optarg);
r = sd_json_variant_set_field_string(match_identity ?: &arg_identity_extra, field, optarg);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);
@@ -3566,7 +3607,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to validate CIFS service name: %s", optarg);
r = sd_json_variant_set_field_string(&arg_identity_extra, "cifsService", optarg);
r = sd_json_variant_set_field_string(match_identity ?: &arg_identity_extra, "cifsService", optarg);
if (r < 0)
return log_error_errno(r, "Failed to set cifsService field: %m");
@@ -3602,7 +3643,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse nice level: %s", optarg);
r = sd_json_variant_set_field_integer(&arg_identity_extra, "niceLevel", nc);
r = sd_json_variant_set_field_integer(match_identity ?: &arg_identity_extra, "niceLevel", nc);
if (r < 0)
return log_error_errno(r, "Failed to set niceLevel field: %m");
@@ -3726,7 +3767,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return r;
r = sd_json_variant_set_field_string(&arg_identity_extra_this_machine, field, v);
r = sd_json_variant_set_field_string(match_identity ?: &arg_identity_extra_this_machine, field, v);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", v);
@@ -3745,7 +3786,7 @@ static int parse_argv(int argc, char *argv[]) {
if (!valid_shell(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Shell '%s' not valid.", optarg);
r = sd_json_variant_set_field_string(&arg_identity_extra, "shell", optarg);
r = sd_json_variant_set_field_string(match_identity ?: &arg_identity_extra, "shell", optarg);
if (r < 0)
return log_error_errno(r, "Failed to set shell field: %m");
@@ -3764,7 +3805,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
e = sd_json_variant_by_key(arg_identity_extra, "environment");
e = sd_json_variant_by_key(match_identity ? *match_identity: arg_identity_extra, "environment");
if (e) {
r = sd_json_variant_strv(e, &l);
if (r < 0)
@@ -3781,7 +3822,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to allocate environment list JSON: %m");
r = sd_json_variant_set_field(&arg_identity_extra, "environment", ne);
r = sd_json_variant_set_field(match_identity ?: &arg_identity_extra, "environment", ne);
if (r < 0)
return log_error_errno(r, "Failed to set environment list: %m");
@@ -3789,7 +3830,6 @@ static int parse_argv(int argc, char *argv[]) {
}
case ARG_TIMEZONE:
if (isempty(optarg)) {
r = drop_from_identity("timeZone");
if (r < 0)
@@ -3801,7 +3841,7 @@ static int parse_argv(int argc, char *argv[]) {
if (!timezone_is_valid(optarg, LOG_DEBUG))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Timezone '%s' is not valid.", optarg);
r = sd_json_variant_set_field_string(&arg_identity_extra, "timeZone", optarg);
r = sd_json_variant_set_field_string(match_identity ?: &arg_identity_extra, "timeZone", optarg);
if (r < 0)
return log_error_errno(r, "Failed to set timezone field: %m");
@@ -3881,7 +3921,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse %s boolean: %m", field);
r = sd_json_variant_set_field_boolean(&arg_identity_extra, field, r > 0);
r = sd_json_variant_set_field_boolean(match_identity ?: &arg_identity_extra, field, r > 0);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);
@@ -3917,7 +3957,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return r;
r = sd_json_variant_set_field_unsigned(&arg_identity_extra_this_machine, "diskSize", arg_disk_size);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra_this_machine, "diskSize", arg_disk_size);
if (r < 0)
return log_error_errno(r, "Failed to set diskSize field: %m");
@@ -3930,7 +3970,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return r;
r = sd_json_variant_set_field_unsigned(&arg_identity_extra_this_machine, "diskSizeRelative", arg_disk_size_relative);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra_this_machine, "diskSizeRelative", arg_disk_size_relative);
if (r < 0)
return log_error_errno(r, "Failed to set diskSizeRelative field: %m");
@@ -3938,7 +3978,7 @@ static int parse_argv(int argc, char *argv[]) {
}
/* Automatically turn off the rebalance logic if user configured a size explicitly */
r = sd_json_variant_set_field_unsigned(&arg_identity_extra_this_machine, "rebalanceWeight", REBALANCE_WEIGHT_OFF);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra_this_machine, "rebalanceWeight", REBALANCE_WEIGHT_OFF);
if (r < 0)
return log_error_errno(r, "Failed to set rebalanceWeight field: %m");
@@ -3979,7 +4019,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse --luks-discard= parameter: %s", optarg);
r = sd_json_variant_set_field_boolean(&arg_identity_extra, "luksDiscard", r);
r = sd_json_variant_set_field_boolean(match_identity ?: &arg_identity_extra, "luksDiscard", r);
if (r < 0)
return log_error_errno(r, "Failed to set discard field: %m");
@@ -3998,7 +4038,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse --luks-offline-discard= parameter: %s", optarg);
r = sd_json_variant_set_field_boolean(&arg_identity_extra, "luksOfflineDiscard", r);
r = sd_json_variant_set_field_boolean(match_identity ?: &arg_identity_extra, "luksOfflineDiscard", r);
if (r < 0)
return log_error_errno(r, "Failed to set offline discard field: %m");
@@ -4027,7 +4067,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse %s parameter: %s", field, optarg);
r = sd_json_variant_set_field_unsigned(&arg_identity_extra, field, n);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra, field, n);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);
@@ -4049,7 +4089,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return r;
r = sd_json_variant_set_field_unsigned(&arg_identity_extra, "luksSectorSize", ss);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra, "luksSectorSize", ss);
if (r < 0)
return log_error_errno(r, "Failed to set sector size field: %m");
@@ -4071,7 +4111,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse umask: %m");
r = sd_json_variant_set_field_integer(&arg_identity_extra, "umask", m);
r = sd_json_variant_set_field_integer(match_identity ?: &arg_identity_extra, "umask", m);
if (r < 0)
return log_error_errno(r, "Failed to set umask field: %m");
@@ -4183,7 +4223,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse %s parameter: %m", field);
r = sd_json_variant_set_field_unsigned(&arg_identity_extra, field, n);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra, field, n);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);
break;
@@ -4216,7 +4256,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse %s parameter: %m", field);
r = sd_json_variant_set_field_unsigned(&arg_identity_extra, field, n);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra, field, n);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);
break;
@@ -4251,9 +4291,9 @@ static int parse_argv(int argc, char *argv[]) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parameter for %s field not valid: %s", field, optarg);
r = sd_json_variant_set_field_string(
IN_SET(c, ARG_STORAGE, ARG_FS_TYPE) ?
&arg_identity_extra_this_machine :
&arg_identity_extra, field, optarg);
match_identity ?: (IN_SET(c, ARG_STORAGE, ARG_FS_TYPE) ?
&arg_identity_extra_this_machine :
&arg_identity_extra), field, optarg);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);
@@ -4284,7 +4324,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse %s field: %s", field, optarg);
r = sd_json_variant_set_field_unsigned(&arg_identity_extra, field, t);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra, field, t);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);
@@ -4333,7 +4373,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to create group list JSON: %m");
r = sd_json_variant_set_field(&arg_identity_extra, "memberOf", mo);
r = sd_json_variant_set_field(match_identity ?: &arg_identity_extra, "memberOf", mo);
if (r < 0)
return log_error_errno(r, "Failed to update group list: %m");
}
@@ -4355,7 +4395,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse --tasks-max= parameter: %s", optarg);
r = sd_json_variant_set_field_unsigned(&arg_identity_extra, "tasksMax", u);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra, "tasksMax", u);
if (r < 0)
return log_error_errno(r, "Failed to set tasksMax field: %m");
@@ -4385,7 +4425,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse %s parameter: %s", field, optarg);
r = sd_json_variant_set_field_unsigned(&arg_identity_extra_this_machine, field, u);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra_this_machine, field, u);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);
@@ -4414,7 +4454,7 @@ static int parse_argv(int argc, char *argv[]) {
if (!CGROUP_WEIGHT_IS_OK(u))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Weight %" PRIu64 " is out of valid weight range.", u);
r = sd_json_variant_set_field_unsigned(&arg_identity_extra, field, u);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra, field, u);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);
@@ -4545,7 +4585,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse --auto-resize-mode= argument: %s", optarg);
r = sd_json_variant_set_field_string(&arg_identity_extra, "autoResizeMode", auto_resize_mode_to_string(r));
r = sd_json_variant_set_field_string(match_identity ?: &arg_identity_extra, "autoResizeMode", auto_resize_mode_to_string(r));
if (r < 0)
return log_error_errno(r, "Failed to set autoResizeMode field: %m");
@@ -4579,7 +4619,7 @@ static int parse_argv(int argc, char *argv[]) {
return r;
/* Add to main identity */
r = sd_json_variant_set_field_unsigned(&arg_identity_extra, "rebalanceWeight", u);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra, "rebalanceWeight", u);
if (r < 0)
return log_error_errno(r, "Failed to set rebalanceWeight field: %m");
@@ -4646,7 +4686,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return r;
r = sd_json_variant_set_field_boolean(&arg_identity_extra, "dropCaches", r);
r = sd_json_variant_set_field_boolean(match_identity ?: &arg_identity_extra, "dropCaches", r);
if (r < 0)
return log_error_errno(r, "Failed to set drop caches field: %m");
@@ -4700,7 +4740,7 @@ static int parse_argv(int argc, char *argv[]) {
if (capability_set_to_strv(updated, &l) < 0)
return log_oom();
r = sd_json_variant_set_field_strv(&arg_identity_extra, field, l);
r = sd_json_variant_set_field_strv(match_identity ?: &arg_identity_extra, field, l);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);
@@ -4814,7 +4854,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to parse %s/%s parameter: %s", field, field_scale, optarg);
r = sd_json_variant_set_field_unsigned(&arg_identity_extra, field, u);
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra, field, u);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);
@@ -4822,7 +4862,7 @@ static int parse_argv(int argc, char *argv[]) {
if (r < 0)
return r;
} else {
r = sd_json_variant_set_field_unsigned(&arg_identity_extra, field_scale, UINT32_SCALE_FROM_PERMYRIAD(r));
r = sd_json_variant_set_field_unsigned(match_identity ?: &arg_identity_extra, field_scale, UINT32_SCALE_FROM_PERMYRIAD(r));
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field_scale);
@@ -4846,7 +4886,7 @@ static int parse_argv(int argc, char *argv[]) {
if (!filename_is_valid(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parameter for default area field not valid: %s", optarg);
r = sd_json_variant_set_field_string(&arg_identity_extra, "defaultArea", optarg);
r = sd_json_variant_set_field_string(match_identity ?: &arg_identity_extra, "defaultArea", optarg);
if (r < 0)
return log_error_errno(r, "Failed to set default area field: %m");
@@ -4873,6 +4913,29 @@ static int parse_argv(int argc, char *argv[]) {
return r;
break;
case ARG_MATCH:
if (streq(optarg, "any"))
match_identity = &arg_identity_extra;
else if (streq(optarg, "this"))
match_identity = &arg_identity_extra_this_machine;
else if (streq(optarg, "other"))
match_identity = &arg_identity_extra_other_machines;
else if (streq(optarg, "auto"))
match_identity = NULL;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--machine= argument not understood. Refusing.");
break;
case 'A':
match_identity = &arg_identity_extra;
break;
case 'T':
match_identity = &arg_identity_extra_this_machine;
break;
case 'N':
match_identity = &arg_identity_extra_other_machines;
break;
case '?':
return -EINVAL;