sysupdate: add a "suggests" concept to features and components
Let's make it possible to "suggest" that certain features or components are enabled under some conditions. For this, both features and components gain two things: 1. A Suggested= field which takes a boolean. If true the feature/component will be suggested for installation, if false it will not. 2. A set of SuggestedOnXYZ= settings are modelled after ConditionXYZ= in unit files (and implement a subset of them), will suggest some component/feature under specific conditions. The result of the condition is shown in the various output tools.
This commit is contained in:
@@ -109,6 +109,53 @@
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Suggest=</varname></term>
|
||||
|
||||
<listitem><para>Takes a boolean argument. If true, this feature is suggested for enablement, if
|
||||
false it is not. This does not enable the feature on its own, but is a hint surfaced by the update
|
||||
tools (for example via the <option>--feature-suggested</option> switch of
|
||||
<citerefentry><refentrytitle>systemd-sysupdate</refentrytitle><manvolnum>8</manvolnum></citerefentry>)
|
||||
so that the system administrator or higher-level tooling may act on it.</para>
|
||||
|
||||
<para>If this setting is not specified, the <varname>SuggestOn…=</varname> conditions described below
|
||||
are evaluated instead to determine whether the feature is suggested. If neither this setting nor any
|
||||
<varname>SuggestOn…=</varname> condition is specified, the feature is not suggested.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v262"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>SuggestOnArchitecture=</varname></term>
|
||||
<term><varname>SuggestOnFirmware=</varname></term>
|
||||
<term><varname>SuggestOnVirtualization=</varname></term>
|
||||
<term><varname>SuggestOnHost=</varname></term>
|
||||
<term><varname>SuggestOnFraction=</varname></term>
|
||||
<term><varname>SuggestOnKernelCommandLine=</varname></term>
|
||||
<term><varname>SuggestOnVersion=</varname></term>
|
||||
<term><varname>SuggestOnCredential=</varname></term>
|
||||
<term><varname>SuggestOnSecurity=</varname></term>
|
||||
<term><varname>SuggestOnOSRelease=</varname></term>
|
||||
<term><varname>SuggestOnMachineTag=</varname></term>
|
||||
|
||||
<listitem><para>Suggest this feature for enablement depending on system properties. These settings
|
||||
take the same arguments and implement the same semantics — including the leading <literal>!</literal>
|
||||
for negation — as the identically-named
|
||||
<varname>ConditionArchitecture=</varname>, <varname>ConditionFirmware=</varname>,
|
||||
<varname>ConditionVirtualization=</varname>, <varname>ConditionHost=</varname>,
|
||||
<varname>ConditionFraction=</varname>, <varname>ConditionKernelCommandLine=</varname>,
|
||||
<varname>ConditionVersion=</varname>, <varname>ConditionCredential=</varname>,
|
||||
<varname>ConditionSecurity=</varname>, <varname>ConditionOSRelease=</varname> and
|
||||
<varname>ConditionMachineTag=</varname> settings for unit files, which are documented in
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
The feature is suggested if all specified conditions apply. As with the <varname>Condition…=</varname>
|
||||
settings, assigning an empty string to one of these resets the list.</para>
|
||||
|
||||
<para>These conditions are only evaluated if <varname>Suggest=</varname> is not specified.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v262"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ typedef enum BusPrintPropertyFlags BusPrintPropertyFlags;
|
||||
typedef enum BusTransport BusTransport;
|
||||
typedef enum CatFlags CatFlags;
|
||||
typedef enum CertificateSourceType CertificateSourceType;
|
||||
typedef enum ConditionType ConditionType;
|
||||
typedef enum DnsAnswerFlags DnsAnswerFlags;
|
||||
typedef enum DnsCacheMode DnsCacheMode;
|
||||
typedef enum DnsOverTlsMode DnsOverTlsMode;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "condition.h"
|
||||
#include "log.h"
|
||||
#include "specifier.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "sysupdate-config.h"
|
||||
@@ -48,6 +50,22 @@ int config_parse_url_specifiers(
|
||||
return free_and_replace(*s, resolved);
|
||||
}
|
||||
|
||||
static const char* const suggest_on_type_table[_CONDITION_TYPE_MAX] = {
|
||||
[CONDITION_ARCHITECTURE] = "SuggestOnArchitecture",
|
||||
[CONDITION_FIRMWARE] = "SuggestOnFirmware",
|
||||
[CONDITION_VIRTUALIZATION] = "SuggestOnVirtualization",
|
||||
[CONDITION_HOST] = "SuggestOnHost",
|
||||
[CONDITION_FRACTION] = "SuggestOnFraction",
|
||||
[CONDITION_KERNEL_COMMAND_LINE] = "SuggestOnKernelCommandLine",
|
||||
[CONDITION_VERSION] = "SuggestOnVersion",
|
||||
[CONDITION_CREDENTIAL] = "SuggestOnCredential",
|
||||
[CONDITION_SECURITY] = "SuggestOnSecurity",
|
||||
[CONDITION_OS_RELEASE] = "SuggestOnOSRelease",
|
||||
[CONDITION_MACHINE_TAG] = "SuggestOnMachineTag",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(suggest_on_type, ConditionType);
|
||||
|
||||
int config_parse_url_specifiers_many(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
@@ -90,3 +108,58 @@ int config_parse_url_specifiers_many(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_condition(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
const char *root = userdata;
|
||||
ConditionType cond = ltype;
|
||||
Condition **list = data, *c;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*list = condition_free_list_type(*list, cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool trigger = rvalue[0] == '|';
|
||||
if (trigger) {
|
||||
rvalue++;
|
||||
rvalue += strspn(rvalue, WHITESPACE);
|
||||
}
|
||||
|
||||
bool negate = rvalue[0] == '!';
|
||||
if (negate) {
|
||||
rvalue++;
|
||||
rvalue += strspn(rvalue, WHITESPACE);
|
||||
}
|
||||
|
||||
_cleanup_free_ char *resolved = NULL;
|
||||
r = specifier_printf(rvalue, SIZE_MAX, system_and_tmp_specifier_table, root, /* userdata= */ NULL, &resolved);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to expand specifiers in %s=, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = condition_new(cond, resolved, trigger, negate);
|
||||
if (!c)
|
||||
return log_oom();
|
||||
|
||||
LIST_PREPEND(conditions, *list, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "conf-parser-forward.h"
|
||||
#include "shared-forward.h"
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_url_specifiers);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_url_specifiers_many);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_condition);
|
||||
|
||||
DECLARE_STRING_TABLE_LOOKUP_TO_STRING(suggest_on_type, ConditionType);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "condition.h"
|
||||
#include "conf-parser.h"
|
||||
#include "hash-funcs.h"
|
||||
#include "path-util.h"
|
||||
@@ -18,6 +21,8 @@ static Feature *feature_free(Feature *f) {
|
||||
free(f->documentation);
|
||||
free(f->appstream);
|
||||
|
||||
condition_free_list(f->suggest_on);
|
||||
|
||||
return mfree(f);
|
||||
}
|
||||
|
||||
@@ -30,6 +35,7 @@ Feature *feature_new(void) {
|
||||
|
||||
*f = (Feature) {
|
||||
.n_ref = 1,
|
||||
.suggest = -1,
|
||||
};
|
||||
|
||||
return f;
|
||||
@@ -45,10 +51,22 @@ int feature_read_definition(Feature *f, const char *root, const char *path, cons
|
||||
assert(f);
|
||||
|
||||
ConfigTableItem table[] = {
|
||||
{ "Feature", "Description", config_parse_string, 0, &f->description },
|
||||
{ "Feature", "Documentation", config_parse_url_specifiers, 0, &f->documentation },
|
||||
{ "Feature", "AppStream", config_parse_url_specifiers, 0, &f->appstream },
|
||||
{ "Feature", "Enabled", config_parse_bool, 0, &f->enabled },
|
||||
{ "Feature", "Description", config_parse_string, 0, &f->description },
|
||||
{ "Feature", "Documentation", config_parse_url_specifiers, 0, &f->documentation },
|
||||
{ "Feature", "AppStream", config_parse_url_specifiers, 0, &f->appstream },
|
||||
{ "Feature", "Enabled", config_parse_bool, 0, &f->enabled },
|
||||
{ "Feature", "Suggest", config_parse_tristate, 0, &f->suggest },
|
||||
{ "Feature", "SuggestOnArchitecture", config_parse_condition, CONDITION_ARCHITECTURE, &f->suggest_on },
|
||||
{ "Feature", "SuggestOnFirmware", config_parse_condition, CONDITION_FIRMWARE, &f->suggest_on },
|
||||
{ "Feature", "SuggestOnVirtualization", config_parse_condition, CONDITION_VIRTUALIZATION, &f->suggest_on },
|
||||
{ "Feature", "SuggestOnHost", config_parse_condition, CONDITION_HOST, &f->suggest_on },
|
||||
{ "Feature", "SuggestOnFraction", config_parse_condition, CONDITION_FRACTION, &f->suggest_on },
|
||||
{ "Feature", "SuggestOnKernelCommandLine", config_parse_condition, CONDITION_KERNEL_COMMAND_LINE, &f->suggest_on },
|
||||
{ "Feature", "SuggestOnVersion", config_parse_condition, CONDITION_VERSION, &f->suggest_on },
|
||||
{ "Feature", "SuggestOnCredential", config_parse_condition, CONDITION_CREDENTIAL, &f->suggest_on },
|
||||
{ "Feature", "SuggestOnSecurity", config_parse_condition, CONDITION_SECURITY, &f->suggest_on },
|
||||
{ "Feature", "SuggestOnOSRelease", config_parse_condition, CONDITION_OS_RELEASE, &f->suggest_on },
|
||||
{ "Feature", "SuggestOnMachineTag", config_parse_condition, CONDITION_MACHINE_TAG, &f->suggest_on },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -82,3 +100,15 @@ int feature_read_definition(Feature *f, const char *root, const char *path, cons
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int feature_is_suggested(Feature *f) {
|
||||
assert(f);
|
||||
|
||||
if (f->suggest >= 0)
|
||||
return f->suggest;
|
||||
|
||||
if (!f->suggest_on) /* no condition → false */
|
||||
return false;
|
||||
|
||||
return condition_test_list(f->suggest_on, environ, suggest_on_type_to_string, /* logger= */ NULL, /* userdata= */ NULL);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ typedef struct Feature {
|
||||
char *appstream;
|
||||
|
||||
bool enabled;
|
||||
|
||||
int suggest;
|
||||
Condition *suggest_on;
|
||||
} Feature;
|
||||
|
||||
Feature *feature_new(void);
|
||||
@@ -23,3 +26,5 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Feature*, feature_unref);
|
||||
extern const struct hash_ops feature_hash_ops;
|
||||
|
||||
int feature_read_definition(Feature *f, const char *root, const char *path, const char *const *conf_file_dirs);
|
||||
|
||||
int feature_is_suggested(Feature *f);
|
||||
|
||||
+91
-11
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "build.h"
|
||||
#include "bus-polkit.h"
|
||||
#include "condition.h"
|
||||
#include "conf-files.h"
|
||||
#include "conf-parser.h"
|
||||
#include "constants.h"
|
||||
@@ -38,6 +39,7 @@
|
||||
#include "pretty-print.h"
|
||||
#include "runtime-scope.h"
|
||||
#include "sort-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "sysupdate.h"
|
||||
@@ -87,6 +89,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_transfer_source, freep);
|
||||
.cleanup = -1, \
|
||||
.installdb_fd = -EBADF, \
|
||||
.target_identifier.class = _TARGET_CLASS_INVALID, \
|
||||
.component_suggest = -1, \
|
||||
}
|
||||
|
||||
void context_done(Context *c) {
|
||||
@@ -126,6 +129,7 @@ void context_done(Context *c) {
|
||||
c->transfer_source = mfree(c->transfer_source);
|
||||
|
||||
target_identifier_done(&c->target_identifier);
|
||||
condition_free_list(c->component_suggest_on);
|
||||
}
|
||||
|
||||
static int context_from_cmdline(Context *ret) {
|
||||
@@ -346,9 +350,21 @@ static int read_component(Context *c) {
|
||||
return log_oom();
|
||||
|
||||
ConfigTableItem table[] = {
|
||||
{ "Component", "Description", config_parse_string, 0, &c->component_description },
|
||||
{ "Component", "Documentation", config_parse_url_specifiers_many, 0, &c->component_documentation },
|
||||
{ "Component", "Enabled", config_parse_bool, 0, &c->component_enabled },
|
||||
{ "Component", "Description", config_parse_string, 0, &c->component_description },
|
||||
{ "Component", "Documentation", config_parse_url_specifiers_many, 0, &c->component_documentation },
|
||||
{ "Component", "Enabled", config_parse_bool, 0, &c->component_enabled },
|
||||
{ "Component", "Suggest", config_parse_tristate, 0, &c->component_suggest },
|
||||
{ "Component", "SuggestOnArchitecture", config_parse_condition, CONDITION_ARCHITECTURE, &c->component_suggest_on },
|
||||
{ "Component", "SuggestOnFirmware", config_parse_condition, CONDITION_FIRMWARE, &c->component_suggest_on },
|
||||
{ "Component", "SuggestOnVirtualization", config_parse_condition, CONDITION_VIRTUALIZATION, &c->component_suggest_on },
|
||||
{ "Component", "SuggestOnHost", config_parse_condition, CONDITION_HOST, &c->component_suggest_on },
|
||||
{ "Component", "SuggestOnFraction", config_parse_condition, CONDITION_FRACTION, &c->component_suggest_on },
|
||||
{ "Component", "SuggestOnKernelCommandLine", config_parse_condition, CONDITION_KERNEL_COMMAND_LINE, &c->component_suggest_on },
|
||||
{ "Component", "SuggestOnVersion", config_parse_condition, CONDITION_VERSION, &c->component_suggest_on },
|
||||
{ "Component", "SuggestOnCredential", config_parse_condition, CONDITION_CREDENTIAL, &c->component_suggest_on },
|
||||
{ "Component", "SuggestOnSecurity", config_parse_condition, CONDITION_SECURITY, &c->component_suggest_on },
|
||||
{ "Component", "SuggestOnOSRelease", config_parse_condition, CONDITION_OS_RELEASE, &c->component_suggest_on },
|
||||
{ "Component", "SuggestOnMachineTag", config_parse_condition, CONDITION_MACHINE_TAG, &c->component_suggest_on },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -1876,6 +1892,20 @@ static int verb_features(int argc, char *argv[], uintptr_t _data, void *userdata
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
r = feature_is_suggested(f);
|
||||
if (r < 0) {
|
||||
errno = -r; /* Let's make %m below show this error */
|
||||
_cleanup_free_ char *k = asprintf_safe("error (%m)");
|
||||
r = table_add_many(table,
|
||||
TABLE_FIELD, "Suggested",
|
||||
TABLE_STRING, k);
|
||||
} else
|
||||
r = table_add_many(table,
|
||||
TABLE_FIELD, "Suggested",
|
||||
TABLE_BOOLEAN, r);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
if (f->description) {
|
||||
r = table_add_many(table, TABLE_FIELD, "Description", TABLE_STRING, f->description);
|
||||
if (r < 0)
|
||||
@@ -1908,14 +1938,28 @@ static int verb_features(int argc, char *argv[], uintptr_t _data, void *userdata
|
||||
|
||||
return table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, arg_legend);
|
||||
} else if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)) {
|
||||
table = table_new("", "feature", "description", "documentation");
|
||||
table = table_new("enabled", "suggested", "feature", "description", "documentation");
|
||||
if (!table)
|
||||
return log_oom();
|
||||
|
||||
table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
|
||||
|
||||
HASHMAP_FOREACH(f, context.features) {
|
||||
r = table_add_many(table,
|
||||
TABLE_BOOLEAN_CHECKMARK, f->enabled,
|
||||
TABLE_SET_COLOR, ansi_highlight_green_red(f->enabled),
|
||||
TABLE_SET_COLOR, ansi_highlight_green_red(f->enabled));
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
r = feature_is_suggested(f);
|
||||
if (r < 0)
|
||||
r = table_add_many(table, TABLE_EMPTY);
|
||||
else
|
||||
r = table_add_many(table, TABLE_BOOLEAN_CHECKMARK, r);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_STRING, f->id,
|
||||
TABLE_STRING, f->description,
|
||||
TABLE_STRING, f->documentation,
|
||||
@@ -2435,16 +2479,30 @@ static int context_list_components(Context *context, char ***ret_component_names
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int context_component_is_suggested(Context *c) {
|
||||
assert(c);
|
||||
|
||||
/* Only applies to components, not to the main system */
|
||||
if (!c->component)
|
||||
return -ENOTTY;
|
||||
|
||||
if (c->component_suggest >= 0)
|
||||
return c->component_suggest;
|
||||
|
||||
if (!c->component_suggest_on) /* no condition → false */
|
||||
return false;
|
||||
|
||||
return condition_test_list(c->component_suggest_on, environ, suggest_on_type_to_string, /* logger= */ NULL, /* userdata= */ NULL);
|
||||
}
|
||||
|
||||
VERB_NOARG(verb_components, "components",
|
||||
"Show list of components");
|
||||
static int verb_components(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
_cleanup_(context_done) Context context = CONTEXT_NULL;
|
||||
_cleanup_strv_free_ char **component_names = NULL;
|
||||
bool has_default_component = false;
|
||||
int r;
|
||||
|
||||
assert(argc <= 1);
|
||||
|
||||
_cleanup_(context_done) Context context = CONTEXT_NULL;
|
||||
r = context_from_cmdline(&context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -2459,6 +2517,8 @@ static int verb_components(int argc, char *argv[], uintptr_t _data, void *userda
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_strv_free_ char **component_names = NULL;
|
||||
bool has_default_component = false;
|
||||
r = context_list_components(&context, &component_names, &has_default_component);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to enumerate components: %m");
|
||||
@@ -2469,7 +2529,7 @@ static int verb_components(int argc, char *argv[], uintptr_t _data, void *userda
|
||||
return 0;
|
||||
}
|
||||
|
||||
_cleanup_(table_unrefp) Table *t = table_new("", "component", "description", "documentation");
|
||||
_cleanup_(table_unrefp) Table *t = table_new("enabled", "suggested", "component", "description", "documentation");
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
@@ -2479,6 +2539,7 @@ static int verb_components(int argc, char *argv[], uintptr_t _data, void *userda
|
||||
r = table_add_many(
|
||||
t,
|
||||
TABLE_EMPTY,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, "<default>",
|
||||
TABLE_SET_COLOR, ansi_highlight(),
|
||||
TABLE_STRING, "Default Component",
|
||||
@@ -2506,12 +2567,25 @@ static int verb_components(int argc, char *argv[], uintptr_t _data, void *userda
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
r = table_add_many(
|
||||
t,
|
||||
TABLE_BOOLEAN_CHECKMARK, cc.component_enabled,
|
||||
TABLE_SET_COLOR, ansi_highlight_green_red(cc.component_enabled));
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
r = context_component_is_suggested(&cc);
|
||||
if (r < 0)
|
||||
r = table_add_many(t, TABLE_EMPTY);
|
||||
else
|
||||
r = table_add_many(t, TABLE_BOOLEAN_CHECKMARK, r);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
const char *doc = cc.component_documentation ? cc.component_documentation[0] : NULL;
|
||||
|
||||
r = table_add_many(
|
||||
t,
|
||||
TABLE_BOOLEAN_CHECKMARK, cc.component_enabled,
|
||||
TABLE_SET_COLOR, ansi_highlight_green_red(cc.component_enabled),
|
||||
TABLE_STRING, *i,
|
||||
TABLE_STRING, cc.component_description,
|
||||
TABLE_STRING, doc,
|
||||
@@ -2850,10 +2924,16 @@ static int vl_server(void) {
|
||||
static int run(int argc, char *argv[]) {
|
||||
int r;
|
||||
|
||||
LIBAPPARMOR_NOTE(recommended);
|
||||
LIBAUDIT_NOTE(recommended);
|
||||
LIBBLKID_NOTE(recommended);
|
||||
LIBCRYPTO_NOTE(suggested);
|
||||
LIBCRYPTSETUP_NOTE(suggested);
|
||||
LIBMOUNT_NOTE(recommended);
|
||||
LIBSELINUX_NOTE(recommended);
|
||||
LIBTSS2_ESYS_NOTE(suggested);
|
||||
LIBTSS2_MU_NOTE(suggested);
|
||||
LIBTSS2_RC_NOTE(suggested);
|
||||
|
||||
log_setup();
|
||||
|
||||
|
||||
@@ -28,6 +28,9 @@ typedef struct Context {
|
||||
char **component_documentation;
|
||||
bool component_enabled;
|
||||
|
||||
int component_suggest;
|
||||
Condition *component_suggest_on;
|
||||
|
||||
Transfer **transfers;
|
||||
size_t n_transfers;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user