mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-03-08 20:58:20 +03:00
Merge pull request #18704 from keszybz/fallback-hostame-override
Allow overriding of fallback hostname through envvar and os-release field
This commit is contained in:
commit
a5e5e102ba
4
NEWS
4
NEWS
@ -256,8 +256,8 @@ CHANGES WITH 248:
|
||||
ignored. The goal is to honour configuration as specified by the
|
||||
user.
|
||||
|
||||
* systemd-hostnamed now exports the fallback hostname and the source of
|
||||
the configured hostname ("static", "transient", or "fallback") as
|
||||
* systemd-hostnamed now exports the default hostname and the source of
|
||||
the configured hostname ("static", "transient", or "default") as
|
||||
D-Bus properties.
|
||||
|
||||
* systemd-hostnamed now exports the "HardwareVendor" and
|
||||
|
@ -56,6 +56,10 @@ All tools:
|
||||
* `$SYSTEMD_EFI_OPTIONS` — if set, used instead of the string in the
|
||||
`SystemdOptions` EFI variable. Analogous to `$SYSTEMD_PROC_CMDLINE`.
|
||||
|
||||
* `$SYSTEMD_DEFAULT_HOSTNAME` — override the compiled-in fallback hostname
|
||||
(relevant in particular for the system manager and `systemd-hostnamed`).
|
||||
Must be a valid hostname (either a single label or a FQDN).
|
||||
|
||||
* `$SYSTEMD_IN_INITRD=[auto|lenient|0|1]` — if set, specifies initrd detection
|
||||
method. Defaults to `auto`. Behavior is defined as follows:
|
||||
`auto`: Checks if `/etc/initrd-release` exists, and a temporary fs is mounted
|
||||
|
@ -63,7 +63,7 @@ node /org/freedesktop/hostname1 {
|
||||
readonly s StaticHostname = '...';
|
||||
readonly s PrettyHostname = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s FallbackHostname = '...';
|
||||
readonly s DefaultHostname = '...';
|
||||
readonly s HostnameSource = '...';
|
||||
readonly s IconName = '...';
|
||||
readonly s Chassis = '...';
|
||||
@ -124,7 +124,7 @@ node /org/freedesktop/hostname1 {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="PrettyHostname"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="FallbackHostname"/>
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="DefaultHostname"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="HostnameSource"/>
|
||||
|
||||
@ -183,13 +183,15 @@ node /org/freedesktop/hostname1 {
|
||||
set this setting will be the empty string. Applications should then find a suitable fallback, such as the
|
||||
dynamic hostname.</para>
|
||||
|
||||
<para>The <varname>FallbackHostname</varname> property exposes the fallback hostname (configured at
|
||||
compilation time).</para>
|
||||
<para>The <varname>DefaultHostname</varname> property exposes the default hostname (configured through
|
||||
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>, or a
|
||||
fallback set at compilation time).</para>
|
||||
|
||||
<para>The <varname>HostnameSource</varname> property exposes the origin of the currently configured
|
||||
hostname. One of <literal>static</literal> (set from <filename>/etc/hostname</filename>),
|
||||
<literal>transient</literal> (a non-permanent hostname from an external source),
|
||||
<literal>fallback</literal> (the compiled-in fallback value).</para>
|
||||
<literal>default</literal> (the value from <filename>os-release</filename> or the the compiled-in
|
||||
fallback).</para>
|
||||
|
||||
<para>The <varname>IconName</varname> property exposes the <emphasis>icon name</emphasis> following the
|
||||
XDG icon naming spec. If not set, information such as the chassis type (see below) is used to find a
|
||||
@ -332,8 +334,8 @@ node /org/freedesktop/hostname1 {
|
||||
<listitem><para>Limit the hostname to 63 chars, which is the length of a DNS label.</para></listitem>
|
||||
|
||||
<listitem><para>If after stripping special chars the empty string is the result, you can pass this
|
||||
as-is to <filename>systemd-hostnamed</filename> in which case it will automatically use
|
||||
<literal>&FALLBACK_HOSTNAME;</literal>.</para></listitem>
|
||||
as-is to <filename>systemd-hostnamed</filename> in which case it will automatically use a suitable
|
||||
fallback.</para></listitem>
|
||||
|
||||
<listitem><para>Uppercase charaacters should be replaced with their lowercase equivalents.
|
||||
</para></listitem>
|
||||
|
@ -317,6 +317,23 @@
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>DEFAULT_HOSTNAME=</varname></term>
|
||||
|
||||
<listitem><para>A string specifying the hostname if
|
||||
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry> is not
|
||||
present and no other configuration source specifies the hostname. Must be either a single DNS label
|
||||
(a string composed of 7-bit ASCII lower-case characters and no spaces or dots, limited to the format
|
||||
allowed for DNS domain name labels), or a sequence of such labels separated by single dots that forms
|
||||
a valid DNS FQDN. The total length must be at most 64 characters.</para>
|
||||
|
||||
<para>See
|
||||
<citerefentry><refentrytitle>org.freedesktop.hostname1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for a description of how
|
||||
<citerefentry><refentrytitle>systemd-hostnamed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
determines the fallback hostname.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>SYSEXT_LEVEL=</varname></term>
|
||||
|
||||
|
@ -31,7 +31,9 @@
|
||||
<filename>/etc/systemd/system.conf.d/*.conf</filename>,
|
||||
<filename>/run/systemd/system.conf.d/*.conf</filename>,
|
||||
<filename>/usr/lib/systemd/system.conf.d/*.conf</filename></para>
|
||||
<para><filename>/etc/systemd/user.conf</filename>,
|
||||
|
||||
<para><filename>~/.config/systemd/user.conf</filename>,
|
||||
<filename>/etc/systemd/user.conf</filename>,
|
||||
<filename>/etc/systemd/user.conf.d/*.conf</filename>,
|
||||
<filename>/run/systemd/user.conf.d/*.conf</filename>,
|
||||
<filename>/usr/lib/systemd/user.conf.d/*.conf</filename></para>
|
||||
@ -40,16 +42,16 @@
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>When run as a system instance, systemd interprets the
|
||||
configuration file <filename>system.conf</filename> and the files
|
||||
in <filename>system.conf.d</filename> directories; when run as a
|
||||
user instance, systemd interprets the configuration file
|
||||
<filename>user.conf</filename> and the files in
|
||||
<filename>user.conf.d</filename> directories. These configuration
|
||||
files contain a few settings controlling basic manager
|
||||
operations. See
|
||||
<citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
for a general description of the syntax.</para>
|
||||
<para>When run as a system instance, <command>systemd</command> interprets the configuration file
|
||||
<filename>system.conf</filename> and the files in <filename>system.conf.d</filename> directories; when
|
||||
run as a user instance, it interprets the configuration file <filename>user.conf</filename> (either in
|
||||
the home directory of the user, or if not found, under <filename>/etc/systemd/</filename>) and the files
|
||||
in <filename>user.conf.d</filename> directories. These configuration files contain a few settings
|
||||
controlling basic manager operations.</para>
|
||||
|
||||
<para>See
|
||||
<citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>7</manvolnum></citerefentry> for a
|
||||
general description of the syntax.</para>
|
||||
</refsect1>
|
||||
|
||||
<xi:include href="standard-conf.xml" xpointer="main-conf" />
|
||||
@ -321,11 +323,10 @@
|
||||
<varlistentry>
|
||||
<term><varname>DefaultEnvironment=</varname></term>
|
||||
|
||||
<listitem><para>Sets manager environment variables passed to
|
||||
all executed processes. Takes a space-separated list of
|
||||
variable assignments. See
|
||||
<citerefentry project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
for details about environment variables.</para>
|
||||
<listitem><para>Configures environment variables passed to all executed processes. Takes a
|
||||
space-separated list of variable assignments. See <citerefentry
|
||||
project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
||||
details about environment variables.</para>
|
||||
|
||||
<para>Example:
|
||||
|
||||
@ -337,6 +338,20 @@
|
||||
<literal>VAR3</literal>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ManagerEnvironment=</varname></term>
|
||||
|
||||
<listitem><para>Takes the same arguments as <varname>DefaultEnvironment=</varname>, see above. Sets
|
||||
environment variables just for the manager process itself. These variables are not inherited by
|
||||
processes spawned by the service manager, use <varname>DefaultEnvironment=</varname> for that. Note
|
||||
that these variables are merged into the existing environment block. In particular, in case of the
|
||||
system manager, this includes variables set by the kernel based on the kernel command line.</para>
|
||||
|
||||
<para>Setting environment variables for the manager process may be useful to modify its behaviour.
|
||||
See <ulink url="https://systemd.io/ENVIRONMENT">ENVIRONMENT</ulink> for a descriptions of some
|
||||
variables understood by <command>systemd</command>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>DefaultCPUAccounting=</varname></term>
|
||||
<term><varname>DefaultBlockIOAccounting=</varname></term>
|
||||
|
@ -60,7 +60,7 @@
|
||||
<filename>$XDG_RUNTIME_DIR/systemd/user.control/*</filename>
|
||||
<filename>$XDG_RUNTIME_DIR/systemd/transient/*</filename>
|
||||
<filename>$XDG_RUNTIME_DIR/systemd/generator.early/*</filename>
|
||||
<filename>$XDG_CONFIG_HOME/systemd/user/*</filename>
|
||||
<filename>~/.config/systemd/user/*</filename>
|
||||
<filename>$XDG_CONFIG_DIRS/systemd/user/*</filename>
|
||||
<filename>/etc/systemd/user/*</filename>
|
||||
<filename>$XDG_RUNTIME_DIR/systemd/user/*</filename>
|
||||
|
@ -768,6 +768,21 @@ int set_unset_env(const char *name, const char *value, bool overwrite) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int putenv_dup(const char *assignment, bool override) {
|
||||
const char *e, *n;
|
||||
|
||||
e = strchr(assignment, '=');
|
||||
if (!e)
|
||||
return -EINVAL;
|
||||
|
||||
n = strndupa(assignment, e - assignment);
|
||||
|
||||
/* This is like putenv(), but uses setenv() so that our memory doesn't become part of environ[]. */
|
||||
if (setenv(n, e + 1, override) < 0)
|
||||
return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setenv_systemd_exec_pid(bool update_only) {
|
||||
char str[DECIMAL_STR_MAX(pid_t)];
|
||||
const char *e;
|
||||
|
@ -58,6 +58,9 @@ int getenv_bool_secure(const char *p);
|
||||
/* Like setenv, but calls unsetenv if value == NULL. */
|
||||
int set_unset_env(const char *name, const char *value, bool overwrite);
|
||||
|
||||
/* Like putenv, but duplicates the memory like setenv. */
|
||||
int putenv_dup(const char *assignment, bool override);
|
||||
|
||||
int setenv_systemd_exec_pid(bool update_only);
|
||||
|
||||
/* Parses and does sanity checks on an environment variable containing
|
||||
|
@ -3,14 +3,39 @@
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "hostname-util.h"
|
||||
#include "os-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
char* get_default_hostname(void) {
|
||||
int r;
|
||||
|
||||
const char *e = secure_getenv("SYSTEMD_DEFAULT_HOSTNAME");
|
||||
if (e) {
|
||||
if (hostname_is_valid(e, 0))
|
||||
return strdup(e);
|
||||
log_debug("Invalid hostname in $SYSTEMD_DEFAULT_HOSTNAME, ignoring: %s", e);
|
||||
}
|
||||
|
||||
_cleanup_free_ char *f = NULL;
|
||||
r = parse_os_release(NULL, "DEFAULT_HOSTNAME", &f);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse os-release, ignoring: %m");
|
||||
else if (f) {
|
||||
if (hostname_is_valid(f, 0))
|
||||
return TAKE_PTR(f);
|
||||
log_debug("Invalid hostname in os-release, ignoring: %s", f);
|
||||
}
|
||||
|
||||
return strdup(FALLBACK_HOSTNAME);
|
||||
}
|
||||
|
||||
char* gethostname_malloc(void) {
|
||||
struct utsname u;
|
||||
const char *s;
|
||||
@ -23,7 +48,7 @@ char* gethostname_malloc(void) {
|
||||
|
||||
s = u.nodename;
|
||||
if (isempty(s) || streq(s, "(none)"))
|
||||
s = FALLBACK_HOSTNAME;
|
||||
return get_default_hostname();
|
||||
|
||||
return strdup(s);
|
||||
}
|
||||
@ -31,6 +56,7 @@ char* gethostname_malloc(void) {
|
||||
char* gethostname_short_malloc(void) {
|
||||
struct utsname u;
|
||||
const char *s;
|
||||
_cleanup_free_ char *f = NULL;
|
||||
|
||||
/* Like above, but kills the FQDN part if present. */
|
||||
|
||||
@ -38,7 +64,10 @@ char* gethostname_short_malloc(void) {
|
||||
|
||||
s = u.nodename;
|
||||
if (isempty(s) || streq(s, "(none)") || s[0] == '.') {
|
||||
s = FALLBACK_HOSTNAME;
|
||||
s = f = get_default_hostname();
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
assert(s[0] != '.');
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "macro.h"
|
||||
#include "strv.h"
|
||||
|
||||
char* get_default_hostname(void);
|
||||
char* gethostname_malloc(void);
|
||||
char* gethostname_short_malloc(void);
|
||||
int gethostname_strict(char **ret);
|
||||
|
@ -376,6 +376,7 @@ static inline int __coverity_check_and_return__(int condition) {
|
||||
|
||||
#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
|
||||
#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
|
||||
#define STRV_MAKE_CONST(...) ((const char* const*) ((const char*[]) { __VA_ARGS__, NULL }))
|
||||
|
||||
/* Pointers range from NULL to POINTER_MAX */
|
||||
#define POINTER_MAX ((void*) UINTPTR_MAX)
|
||||
|
@ -170,6 +170,8 @@ basic_sources = files('''
|
||||
nulstr-util.h
|
||||
ordered-set.c
|
||||
ordered-set.h
|
||||
os-util.c
|
||||
os-util.h
|
||||
parse-util.c
|
||||
parse-util.h
|
||||
path-lookup.c
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "discover-image.h"
|
||||
#include "env-file.h"
|
||||
#include "env-util.h"
|
||||
#include "fd-util.h"
|
||||
@ -9,8 +8,27 @@
|
||||
#include "fs-util.h"
|
||||
#include "macro.h"
|
||||
#include "os-util.h"
|
||||
#include "path-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "utf8.h"
|
||||
|
||||
bool image_name_is_valid(const char *s) {
|
||||
if (!filename_is_valid(s))
|
||||
return false;
|
||||
|
||||
if (string_has_cc(s, NULL))
|
||||
return false;
|
||||
|
||||
if (!utf8_is_valid(s))
|
||||
return false;
|
||||
|
||||
/* Temporary files for atomically creating new files */
|
||||
if (startswith(s, ".#"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int path_is_extension_tree(const char *path, const char *extension) {
|
||||
int r;
|
||||
@ -118,7 +136,7 @@ static int parse_release_internal(const char *root, const char *extension, va_li
|
||||
return parse_env_filev(f, p, ap);
|
||||
}
|
||||
|
||||
int parse_extension_release(const char *root, const char *extension, ...) {
|
||||
int _parse_extension_release(const char *root, const char *extension, ...) {
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
@ -129,7 +147,7 @@ int parse_extension_release(const char *root, const char *extension, ...) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int parse_os_release(const char *root, ...) {
|
||||
int _parse_os_release(const char *root, ...) {
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
@ -193,74 +211,3 @@ int load_extension_release_pairs(const char *root, const char *extension, char *
|
||||
|
||||
return load_env_file_pairs(f, p, ret);
|
||||
}
|
||||
|
||||
int extension_release_validate(
|
||||
const char *name,
|
||||
const char *host_os_release_id,
|
||||
const char *host_os_release_version_id,
|
||||
const char *host_os_release_sysext_level,
|
||||
char **extension_release) {
|
||||
|
||||
const char *extension_release_id = NULL, *extension_release_sysext_level = NULL;
|
||||
|
||||
assert(name);
|
||||
assert(!isempty(host_os_release_id));
|
||||
|
||||
/* Now that we can look into the extension image, let's see if the OS version is compatible */
|
||||
if (strv_isempty(extension_release)) {
|
||||
log_debug("Extension '%s' carries no extension-release data, ignoring extension.", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extension_release_id = strv_env_pairs_get(extension_release, "ID");
|
||||
if (isempty(extension_release_id)) {
|
||||
log_debug("Extension '%s' does not contain ID in extension-release but requested to match '%s'",
|
||||
name, strna(host_os_release_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!streq_ptr(host_os_release_id, extension_release_id)) {
|
||||
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
|
||||
name, strna(extension_release_id), strna(host_os_release_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Rolling releases do not typically set VERSION_ID (eg: ArchLinux) */
|
||||
if (isempty(host_os_release_version_id) && isempty(host_os_release_sysext_level)) {
|
||||
log_debug("No version info on the host (rolling release?), but ID in %s matched.", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If the extension has a sysext API level declared, then it must match the host API
|
||||
* level. Otherwise, compare OS version as a whole */
|
||||
extension_release_sysext_level = strv_env_pairs_get(extension_release, "SYSEXT_LEVEL");
|
||||
if (!isempty(host_os_release_sysext_level) && !isempty(extension_release_sysext_level)) {
|
||||
if (!streq_ptr(host_os_release_sysext_level, extension_release_sysext_level)) {
|
||||
log_debug("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s'",
|
||||
name, strna(extension_release_sysext_level), strna(host_os_release_sysext_level));
|
||||
return 0;
|
||||
}
|
||||
} else if (!isempty(host_os_release_version_id)) {
|
||||
const char *extension_release_version_id;
|
||||
|
||||
extension_release_version_id = strv_env_pairs_get(extension_release, "VERSION_ID");
|
||||
if (isempty(extension_release_version_id)) {
|
||||
log_debug("Extension '%s' does not contain VERSION_ID in extension-release but requested to match '%s'",
|
||||
name, strna(host_os_release_version_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!streq_ptr(host_os_release_version_id, extension_release_version_id)) {
|
||||
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
|
||||
name, strna(extension_release_version_id), strna(host_os_release_version_id));
|
||||
return 0;
|
||||
}
|
||||
} else if (isempty(host_os_release_version_id) && isempty(host_os_release_sysext_level)) {
|
||||
/* Rolling releases do not typically set VERSION_ID (eg: ArchLinux) */
|
||||
log_debug("No version info on the host (rolling release?), but ID in %s matched.", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
log_debug("Version info of extension '%s' matches host.", name);
|
||||
return 1;
|
||||
}
|
@ -6,6 +6,8 @@
|
||||
/* The *_extension_release flavours will look for /usr/lib/extension-release/extension-release.NAME
|
||||
* in accordance with the OS extension specification, rather than for /usr/lib/ or /etc/os-release. */
|
||||
|
||||
bool image_name_is_valid(const char *s) _pure_;
|
||||
|
||||
int path_is_extension_tree(const char *path, const char *extension);
|
||||
static inline int path_is_os_tree(const char *path) {
|
||||
return path_is_extension_tree(path, NULL);
|
||||
@ -21,13 +23,11 @@ static inline int fopen_os_release(const char *root, char **ret_path, FILE **ret
|
||||
return fopen_extension_release(root, NULL, ret_path, ret_file);
|
||||
}
|
||||
|
||||
int parse_extension_release(const char *root, const char *extension, ...) _sentinel_;
|
||||
int parse_os_release(const char *root, ...) _sentinel_;
|
||||
int _parse_extension_release(const char *root, const char *extension, ...) _sentinel_;
|
||||
int _parse_os_release(const char *root, ...) _sentinel_;
|
||||
#define parse_extension_release(root, extension, ...) _parse_extension_release(root, extension, __VA_ARGS__, NULL)
|
||||
#define parse_os_release(root, ...) _parse_os_release(root, __VA_ARGS__, NULL)
|
||||
|
||||
int load_extension_release_pairs(const char *root, const char *extension, char ***ret);
|
||||
int load_os_release_pairs(const char *root, char ***ret);
|
||||
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret);
|
||||
|
||||
/* Given an image name (for logging purposes), a set of os-release values from the host
|
||||
* and a key-value pair vector of extension-release variables, check that the distro and
|
||||
* (system extension level or distro version) match and return 1, and 0 otherwise. */
|
||||
int extension_release_validate(const char *name, const char *host_os_release_id, const char *host_os_release_version_id, const char *host_os_release_sysext_level, char **extension_release);
|
@ -134,6 +134,7 @@ static usec_t arg_kexec_watchdog;
|
||||
static char *arg_early_core_pattern;
|
||||
static char *arg_watchdog_device;
|
||||
static char **arg_default_environment;
|
||||
static char **arg_manager_environment;
|
||||
static struct rlimit *arg_default_rlimit[_RLIMIT_MAX];
|
||||
static uint64_t arg_capability_bounding_set;
|
||||
static bool arg_no_new_privs;
|
||||
@ -163,6 +164,36 @@ static char **saved_env = NULL;
|
||||
static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
|
||||
const struct rlimit *saved_rlimit_memlock);
|
||||
|
||||
static int manager_find_user_config_paths(char ***ret_files, char ***ret_dirs) {
|
||||
_cleanup_free_ char *base = NULL;
|
||||
_cleanup_strv_free_ char **files = NULL, **dirs = NULL;
|
||||
int r;
|
||||
|
||||
r = xdg_user_config_dir(&base, "/systemd");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = strv_extendf(&files, "%s/user.conf", base);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = strv_extend(&files, PKGSYSCONFDIR "/user.conf");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = strv_consume(&dirs, TAKE_PTR(base));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = strv_extend_strv(&dirs, CONF_PATHS_STRV("systemd"), false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_files = TAKE_PTR(files);
|
||||
*ret_dirs = TAKE_PTR(dirs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_noreturn_ static void freeze_or_exit_or_reboot(void) {
|
||||
|
||||
/* If we are running in a container, let's prefer exiting, after all we can propagate an exit code to
|
||||
@ -640,6 +671,7 @@ static int parse_config_file(void) {
|
||||
{ "Manager", "DefaultStartLimitIntervalSec", config_parse_sec, 0, &arg_default_start_limit_interval },
|
||||
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
|
||||
{ "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
|
||||
{ "Manager", "ManagerEnvironment", config_parse_environ, 0, &arg_manager_environment },
|
||||
{ "Manager", "DefaultLimitCPU", config_parse_rlimit, RLIMIT_CPU, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitFSIZE", config_parse_rlimit, RLIMIT_FSIZE, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitDATA", config_parse_rlimit, RLIMIT_DATA, arg_default_rlimit },
|
||||
@ -668,26 +700,34 @@ static int parse_config_file(void) {
|
||||
{}
|
||||
};
|
||||
|
||||
const char *fn, *conf_dirs_nulstr;
|
||||
_cleanup_strv_free_ char **_free_files = NULL, **_free_dirs = NULL;
|
||||
|
||||
fn = arg_system ?
|
||||
PKGSYSCONFDIR "/system.conf" :
|
||||
PKGSYSCONFDIR "/user.conf";
|
||||
const char *const *files, *const *dirs, *suffix;
|
||||
int r;
|
||||
|
||||
conf_dirs_nulstr = arg_system ?
|
||||
CONF_PATHS_NULSTR("systemd/system.conf.d") :
|
||||
CONF_PATHS_NULSTR("systemd/user.conf.d");
|
||||
if (arg_system) {
|
||||
files = STRV_MAKE_CONST(PKGSYSCONFDIR "/system.conf");
|
||||
dirs = (const char* const*) CONF_PATHS_STRV("systemd");
|
||||
suffix = "system.conf.d";
|
||||
} else {
|
||||
r = manager_find_user_config_paths(&_free_files, &_free_dirs);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine config file paths: %m");
|
||||
files = (const char* const*) _free_files;
|
||||
dirs = (const char* const*) _free_dirs;
|
||||
suffix = "user.conf.d";
|
||||
}
|
||||
|
||||
(void) config_parse_many_nulstr(
|
||||
fn, conf_dirs_nulstr,
|
||||
(void) config_parse_many(
|
||||
files, dirs, suffix,
|
||||
"Manager\0",
|
||||
config_item_table_lookup, items,
|
||||
CONFIG_PARSE_WARN,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we used USEC_INFINITY
|
||||
* like everywhere else. */
|
||||
/* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we use
|
||||
* USEC_INFINITY like everywhere else. */
|
||||
if (arg_default_timeout_start_usec <= 0)
|
||||
arg_default_timeout_start_usec = USEC_INFINITY;
|
||||
if (arg_default_timeout_stop_usec <= 0)
|
||||
@ -1312,8 +1352,7 @@ static int status_welcome(void) {
|
||||
|
||||
r = parse_os_release(NULL,
|
||||
"PRETTY_NAME", &pretty_name,
|
||||
"ANSI_COLOR", &ansi_color,
|
||||
NULL);
|
||||
"ANSI_COLOR", &ansi_color);
|
||||
if (r < 0)
|
||||
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
|
||||
"Failed to read os-release file, ignoring: %m");
|
||||
@ -2263,6 +2302,19 @@ static void fallback_rlimit_memlock(const struct rlimit *saved_rlimit_memlock) {
|
||||
arg_default_rlimit[RLIMIT_MEMLOCK] = rl;
|
||||
}
|
||||
|
||||
static void setenv_manager_environment(void) {
|
||||
char **p;
|
||||
int r;
|
||||
|
||||
STRV_FOREACH(p, arg_manager_environment) {
|
||||
log_debug("Setting '%s' in our own environment.", *p);
|
||||
|
||||
r = putenv_dup(*p, true);
|
||||
if (r < 0)
|
||||
log_warning_errno(errno, "Failed to setenv \"%s\", ignoring: %m", *p);
|
||||
}
|
||||
}
|
||||
|
||||
static void reset_arguments(void) {
|
||||
/* Frees/resets arg_* variables, with a few exceptions commented below. */
|
||||
|
||||
@ -2296,6 +2348,7 @@ static void reset_arguments(void) {
|
||||
arg_watchdog_device = NULL;
|
||||
|
||||
arg_default_environment = strv_free(arg_default_environment);
|
||||
arg_manager_environment = strv_free(arg_manager_environment);
|
||||
rlimit_free_all(arg_default_rlimit);
|
||||
|
||||
arg_capability_bounding_set = CAP_ALL;
|
||||
@ -2357,6 +2410,9 @@ static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
|
||||
if (arg_show_status == _SHOW_STATUS_INVALID)
|
||||
arg_show_status = SHOW_STATUS_YES;
|
||||
|
||||
/* Push variables into the manager environment block */
|
||||
setenv_manager_environment();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -106,8 +106,7 @@ static void print_welcome(void) {
|
||||
r = parse_os_release(
|
||||
arg_root,
|
||||
"PRETTY_NAME", &pretty_name,
|
||||
"ANSI_COLOR", &ansi_color,
|
||||
NULL);
|
||||
"ANSI_COLOR", &ansi_color);
|
||||
if (r < 0)
|
||||
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
|
||||
"Failed to read os-release file, ignoring: %m");
|
||||
|
@ -159,8 +159,7 @@ static void context_read_os_release(Context *c) {
|
||||
r = parse_os_release(NULL,
|
||||
"PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
|
||||
"CPE_NAME", &c->data[PROP_OS_CPE_NAME],
|
||||
"HOME_URL", &c->data[PROP_OS_HOME_URL],
|
||||
NULL);
|
||||
"HOME_URL", &c->data[PROP_OS_HOME_URL]);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_warning_errno(r, "Failed to read os-release file, ignoring: %m");
|
||||
|
||||
@ -323,6 +322,7 @@ static int context_update_kernel_hostname(
|
||||
Context *c,
|
||||
const char *transient_hn) {
|
||||
|
||||
_cleanup_free_ char *_hn_free = NULL;
|
||||
const char *hn;
|
||||
HostnameSource hns;
|
||||
int r;
|
||||
@ -341,8 +341,11 @@ static int context_update_kernel_hostname(
|
||||
|
||||
/* ... and the ultimate fallback */
|
||||
} else {
|
||||
hn = FALLBACK_HOSTNAME;
|
||||
hns = HOSTNAME_FALLBACK;
|
||||
hn = _hn_free = get_default_hostname();
|
||||
if (!hn)
|
||||
return log_oom();
|
||||
|
||||
hns = HOSTNAME_DEFAULT;
|
||||
}
|
||||
|
||||
r = sethostname_idempotent(hn);
|
||||
@ -503,16 +506,20 @@ static int property_get_hostname(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
_cleanup_free_ char *current = NULL;
|
||||
_cleanup_free_ char *hn = NULL;
|
||||
int r;
|
||||
|
||||
r = gethostname_strict(¤t);
|
||||
if (r == -ENXIO)
|
||||
return sd_bus_message_append(reply, "s", FALLBACK_HOSTNAME);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = gethostname_strict(&hn);
|
||||
if (r < 0) {
|
||||
if (r != -ENXIO)
|
||||
return r;
|
||||
|
||||
return sd_bus_message_append(reply, "s", current);
|
||||
hn = get_default_hostname();
|
||||
if (!hn)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return sd_bus_message_append(reply, "s", hn);
|
||||
}
|
||||
|
||||
static int property_get_static_hostname(
|
||||
@ -532,7 +539,21 @@ static int property_get_static_hostname(
|
||||
return sd_bus_message_append(reply, "s", c->data[PROP_STATIC_HOSTNAME]);
|
||||
}
|
||||
|
||||
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_fallback_hostname, "s", FALLBACK_HOSTNAME);
|
||||
static int property_get_default_hostname(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
_cleanup_free_ char *hn = get_default_hostname();
|
||||
if (!hn)
|
||||
return log_oom();
|
||||
|
||||
return sd_bus_message_append(reply, "s", hn);
|
||||
}
|
||||
|
||||
static int property_get_hostname_source(
|
||||
sd_bus *bus,
|
||||
@ -560,16 +581,16 @@ static int property_get_hostname_source(
|
||||
|
||||
else {
|
||||
/* If the hostname was not set by us, try to figure out where it came from. If we set
|
||||
* it to the fallback hostname, the file will tell us. We compare the string because
|
||||
* it to the default hostname, the file will tell us. We compare the string because
|
||||
* it is possible that the hostname was set by an older version that had a different
|
||||
* fallback, in the initramfs or before we reexecuted. */
|
||||
|
||||
r = read_one_line_file("/run/systemd/fallback-hostname", &fallback);
|
||||
r = read_one_line_file("/run/systemd/default-hostname", &fallback);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_warning_errno(r, "Failed to read /run/systemd/fallback-hostname, ignoring: %m");
|
||||
log_warning_errno(r, "Failed to read /run/systemd/default-hostname, ignoring: %m");
|
||||
|
||||
if (streq_ptr(fallback, hostname))
|
||||
c->hostname_source = HOSTNAME_FALLBACK;
|
||||
c->hostname_source = HOSTNAME_DEFAULT;
|
||||
else
|
||||
c->hostname_source = HOSTNAME_TRANSIENT;
|
||||
}
|
||||
@ -967,7 +988,7 @@ static const sd_bus_vtable hostname_vtable[] = {
|
||||
SD_BUS_PROPERTY("Hostname", "s", property_get_hostname, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("StaticHostname", "s", property_get_static_hostname, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("PrettyHostname", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_PRETTY_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("FallbackHostname", "s", property_get_fallback_hostname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("DefaultHostname", "s", property_get_default_hostname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("HostnameSource", "s", property_get_hostname_source, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("IconName", "s", property_get_icon_name, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Chassis", "s", property_get_chassis, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
|
@ -755,7 +755,7 @@ static int request_handler_machine(
|
||||
if (r < 0)
|
||||
return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %m");
|
||||
|
||||
(void) parse_os_release(NULL, "PRETTY_NAME", &os_name, NULL);
|
||||
(void) parse_os_release(NULL, "PRETTY_NAME", &os_name);
|
||||
(void) get_virtualization(&v);
|
||||
|
||||
r = asprintf(&json,
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "loop-util.h"
|
||||
#include "missing_capability.h"
|
||||
#include "mount-util.h"
|
||||
#include "os-util.h"
|
||||
#include "process-util.h"
|
||||
#include "raw-clone.h"
|
||||
#include "strv.h"
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "machine-pool.h"
|
||||
#include "machined.h"
|
||||
#include "missing_capability.h"
|
||||
#include "os-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "stdio-util.h"
|
||||
|
@ -686,7 +686,7 @@ int netdev_load_one(Manager *manager, const char *filename) {
|
||||
|
||||
dropin_dirname = strjoina(basename(filename), ".d");
|
||||
r = config_parse_many(
|
||||
filename, NETWORK_DIRS, dropin_dirname,
|
||||
STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname,
|
||||
NETDEV_COMMON_SECTIONS NETDEV_OTHER_SECTIONS,
|
||||
config_item_perf_lookup, network_netdev_gperf_lookup,
|
||||
CONFIG_PARSE_WARN,
|
||||
@ -729,7 +729,7 @@ int netdev_load_one(Manager *manager, const char *filename) {
|
||||
NETDEV_VTABLE(netdev)->init(netdev);
|
||||
|
||||
r = config_parse_many(
|
||||
filename, NETWORK_DIRS, dropin_dirname,
|
||||
STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname,
|
||||
NETDEV_VTABLE(netdev)->sections,
|
||||
config_item_perf_lookup, network_netdev_gperf_lookup,
|
||||
CONFIG_PARSE_WARN,
|
||||
|
@ -446,7 +446,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
||||
};
|
||||
|
||||
r = config_parse_many(
|
||||
filename, NETWORK_DIRS, dropin_dirname,
|
||||
STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname,
|
||||
"Match\0"
|
||||
"Link\0"
|
||||
"SR-IOV\0"
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "bus-wait-for-jobs.h"
|
||||
#include "def.h"
|
||||
#include "dirent-util.h"
|
||||
#include "discover-image.h"
|
||||
#include "env-file.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
@ -20,6 +19,7 @@
|
||||
#include "fs-util.h"
|
||||
#include "locale-util.h"
|
||||
#include "main-func.h"
|
||||
#include "os-util.h"
|
||||
#include "pager.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "fileio.h"
|
||||
#include "io-util.h"
|
||||
#include "missing_capability.h"
|
||||
#include "os-util.h"
|
||||
#include "portable.h"
|
||||
#include "portabled-bus.h"
|
||||
#include "portabled-image-bus.h"
|
||||
|
@ -88,7 +88,7 @@ static int dnssd_service_load(Manager *manager, const char *filename) {
|
||||
dropin_dirname = strjoina(service->name, ".dnssd.d");
|
||||
|
||||
r = config_parse_many(
|
||||
filename, DNSSD_SERVICE_DIRS, dropin_dirname,
|
||||
STRV_MAKE_CONST(filename), DNSSD_SERVICE_DIRS, dropin_dirname,
|
||||
"Service\0",
|
||||
config_item_perf_lookup, resolved_dnssd_gperf_lookup,
|
||||
CONFIG_PARSE_WARN,
|
||||
|
@ -442,20 +442,25 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *fallback_hostname(void) {
|
||||
static char* fallback_hostname(void) {
|
||||
|
||||
/* Determine the fall back hostname. For exposing this system to the outside world, we cannot have it to be
|
||||
* "localhost" even if that's the compiled in hostname. In this case, let's revert to "linux" instead. */
|
||||
/* Determine the fall back hostname. For exposing this system to the outside world, we cannot have it
|
||||
* to be "localhost" even if that's the default hostname. In this case, let's revert to "linux"
|
||||
* instead. */
|
||||
|
||||
if (is_localhost(FALLBACK_HOSTNAME))
|
||||
return "linux";
|
||||
_cleanup_free_ char *n = get_default_hostname();
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
||||
return FALLBACK_HOSTNAME;
|
||||
if (is_localhost(n))
|
||||
return strdup("linux");
|
||||
|
||||
return TAKE_PTR(n);
|
||||
}
|
||||
|
||||
static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname, char **mdns_hostname) {
|
||||
_cleanup_free_ char *n = NULL, *m = NULL;
|
||||
char label[DNS_LABEL_MAX], *h;
|
||||
_cleanup_free_ char *h = NULL, *n = NULL, *m = NULL;
|
||||
char label[DNS_LABEL_MAX];
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
@ -463,7 +468,10 @@ static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname,
|
||||
assert(llmnr_hostname);
|
||||
assert(mdns_hostname);
|
||||
|
||||
p = fallback_hostname();
|
||||
p = h = fallback_hostname();
|
||||
if (!h)
|
||||
return log_oom();
|
||||
|
||||
r = dns_label_unescape(&p, label, sizeof label, 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to unescape fallback hostname: %m");
|
||||
@ -478,14 +486,9 @@ static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname,
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to concatenate mDNS hostname: %m");
|
||||
|
||||
h = strdup(fallback_hostname());
|
||||
if (!h)
|
||||
return log_oom();
|
||||
|
||||
*llmnr_hostname = TAKE_PTR(n);
|
||||
*mdns_hostname = TAKE_PTR(m);
|
||||
|
||||
*full_hostname = h;
|
||||
*full_hostname = TAKE_PTR(h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -420,11 +420,11 @@ int config_parse(
|
||||
if (ret_mtime)
|
||||
*ret_mtime = mtime;
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int config_parse_many_files(
|
||||
const char *conf_file,
|
||||
const char* const* conf_files,
|
||||
char **files,
|
||||
const char *sections,
|
||||
ConfigItemLookup lookup,
|
||||
@ -437,20 +437,23 @@ static int config_parse_many_files(
|
||||
char **fn;
|
||||
int r;
|
||||
|
||||
if (conf_file) {
|
||||
r = config_parse(NULL, conf_file, NULL, sections, lookup, table, flags, userdata, &mtime);
|
||||
/* First read the first found main config file. */
|
||||
STRV_FOREACH(fn, (char**) conf_files) {
|
||||
r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata, &mtime);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Then read all the drop-ins. */
|
||||
STRV_FOREACH(fn, files) {
|
||||
usec_t t;
|
||||
|
||||
r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata, &t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (t > mtime) /* Find the newest */
|
||||
mtime = t;
|
||||
mtime = MAX(mtime, t); /* Find the newest */
|
||||
}
|
||||
|
||||
if (ret_mtime)
|
||||
@ -477,12 +480,14 @@ int config_parse_many_nulstr(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata, ret_mtime);
|
||||
return config_parse_many_files(STRV_MAKE_CONST(conf_file),
|
||||
files, sections, lookup, table, flags, userdata,
|
||||
ret_mtime);
|
||||
}
|
||||
|
||||
/* Parse each config file in the directories specified as strv. */
|
||||
int config_parse_many(
|
||||
const char *conf_file,
|
||||
const char* const* conf_files,
|
||||
const char* const* conf_file_dirs,
|
||||
const char *dropin_dirname,
|
||||
const char *sections,
|
||||
@ -506,7 +511,7 @@ int config_parse_many(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata, ret_mtime);
|
||||
return config_parse_many_files(conf_files, files, sections, lookup, table, flags, userdata, ret_mtime);
|
||||
}
|
||||
|
||||
#define DEFINE_PARSER(type, vartype, conv_func) \
|
||||
|
@ -102,7 +102,7 @@ int config_parse_many_nulstr(
|
||||
usec_t *ret_mtime); /* possibly NULL */
|
||||
|
||||
int config_parse_many(
|
||||
const char *conf_file, /* possibly NULL */
|
||||
const char* const* conf_files, /* possibly empty */
|
||||
const char* const* conf_file_dirs,
|
||||
const char *dropin_dirname,
|
||||
const char *sections, /* nulstr */
|
||||
|
@ -1250,23 +1250,6 @@ int image_name_lock(const char *name, int operation, LockFile *ret) {
|
||||
return make_lock_file(p, operation, ret);
|
||||
}
|
||||
|
||||
bool image_name_is_valid(const char *s) {
|
||||
if (!filename_is_valid(s))
|
||||
return false;
|
||||
|
||||
if (string_has_cc(s, NULL))
|
||||
return false;
|
||||
|
||||
if (!utf8_is_valid(s))
|
||||
return false;
|
||||
|
||||
/* Temporary files for atomically creating new files */
|
||||
if (startswith(s, ".#"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool image_in_search_path(
|
||||
ImageClass class,
|
||||
const char *root,
|
||||
|
@ -76,8 +76,6 @@ int image_read_only(Image *i, bool b);
|
||||
const char* image_type_to_string(ImageType t) _const_;
|
||||
ImageType image_type_from_string(const char *s) _pure_;
|
||||
|
||||
bool image_name_is_valid(const char *s) _pure_;
|
||||
|
||||
int image_path_lock(const char *path, int operation, LockFile *global, LockFile *local);
|
||||
int image_name_lock(const char *name, int operation, LockFile *ret);
|
||||
|
||||
|
79
src/shared/extension-release.c
Normal file
79
src/shared/extension-release.c
Normal file
@ -0,0 +1,79 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "env-util.h"
|
||||
#include "extension-release.h"
|
||||
#include "log.h"
|
||||
#include "os-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
int extension_release_validate(
|
||||
const char *name,
|
||||
const char *host_os_release_id,
|
||||
const char *host_os_release_version_id,
|
||||
const char *host_os_release_sysext_level,
|
||||
char **extension_release) {
|
||||
|
||||
const char *extension_release_id = NULL, *extension_release_sysext_level = NULL;
|
||||
|
||||
assert(name);
|
||||
assert(!isempty(host_os_release_id));
|
||||
|
||||
/* Now that we can look into the extension image, let's see if the OS version is compatible */
|
||||
if (strv_isempty(extension_release)) {
|
||||
log_debug("Extension '%s' carries no extension-release data, ignoring extension.", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extension_release_id = strv_env_pairs_get(extension_release, "ID");
|
||||
if (isempty(extension_release_id)) {
|
||||
log_debug("Extension '%s' does not contain ID in extension-release but requested to match '%s'",
|
||||
name, strna(host_os_release_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!streq_ptr(host_os_release_id, extension_release_id)) {
|
||||
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
|
||||
name, strna(extension_release_id), strna(host_os_release_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Rolling releases do not typically set VERSION_ID (eg: ArchLinux) */
|
||||
if (isempty(host_os_release_version_id) && isempty(host_os_release_sysext_level)) {
|
||||
log_debug("No version info on the host (rolling release?), but ID in %s matched.", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If the extension has a sysext API level declared, then it must match the host API
|
||||
* level. Otherwise, compare OS version as a whole */
|
||||
extension_release_sysext_level = strv_env_pairs_get(extension_release, "SYSEXT_LEVEL");
|
||||
if (!isempty(host_os_release_sysext_level) && !isempty(extension_release_sysext_level)) {
|
||||
if (!streq_ptr(host_os_release_sysext_level, extension_release_sysext_level)) {
|
||||
log_debug("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s'",
|
||||
name, strna(extension_release_sysext_level), strna(host_os_release_sysext_level));
|
||||
return 0;
|
||||
}
|
||||
} else if (!isempty(host_os_release_version_id)) {
|
||||
const char *extension_release_version_id;
|
||||
|
||||
extension_release_version_id = strv_env_pairs_get(extension_release, "VERSION_ID");
|
||||
if (isempty(extension_release_version_id)) {
|
||||
log_debug("Extension '%s' does not contain VERSION_ID in extension-release but requested to match '%s'",
|
||||
name, strna(host_os_release_version_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!streq_ptr(host_os_release_version_id, extension_release_version_id)) {
|
||||
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
|
||||
name, strna(extension_release_version_id), strna(host_os_release_version_id));
|
||||
return 0;
|
||||
}
|
||||
} else if (isempty(host_os_release_version_id) && isempty(host_os_release_sysext_level)) {
|
||||
/* Rolling releases do not typically set VERSION_ID (eg: ArchLinux) */
|
||||
log_debug("No version info on the host (rolling release?), but ID in %s matched.", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
log_debug("Version info of extension '%s' matches host.", name);
|
||||
return 1;
|
||||
}
|
12
src/shared/extension-release.h
Normal file
12
src/shared/extension-release.h
Normal file
@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
/* Given an image name (for logging purposes), a set of os-release values from the host and a key-value pair
|
||||
* vector of extension-release variables, check that the distro and (system extension level or distro
|
||||
* version) match and return 1, and 0 otherwise. */
|
||||
int extension_release_validate(
|
||||
const char *name,
|
||||
const char *host_os_release_id,
|
||||
const char *host_os_release_version_id,
|
||||
const char *host_os_release_sysext_level,
|
||||
char **extension_release);
|
@ -152,13 +152,13 @@ void hostname_update_source_hint(const char *hostname, HostnameSource source) {
|
||||
* notice if somebody sets the hostname directly (not going through hostnamed).
|
||||
*/
|
||||
|
||||
if (source == HOSTNAME_FALLBACK) {
|
||||
r = write_string_file("/run/systemd/fallback-hostname", hostname,
|
||||
if (source == HOSTNAME_DEFAULT) {
|
||||
r = write_string_file("/run/systemd/default-hostname", hostname,
|
||||
WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_ATOMIC);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to create \"/run/systemd/fallback-hostname\": %m");
|
||||
log_warning_errno(r, "Failed to create \"/run/systemd/default-hostname\": %m");
|
||||
} else
|
||||
unlink_or_warn("/run/systemd/fallback-hostname");
|
||||
unlink_or_warn("/run/systemd/default-hostname");
|
||||
}
|
||||
|
||||
int hostname_setup(bool really) {
|
||||
@ -194,7 +194,7 @@ int hostname_setup(bool really) {
|
||||
}
|
||||
}
|
||||
|
||||
if (isempty(hn)) {
|
||||
if (!hn) {
|
||||
/* Don't override the hostname if it is already set and not explicitly configured */
|
||||
|
||||
char buf[HOST_NAME_MAX + 1] = {};
|
||||
@ -204,10 +204,13 @@ int hostname_setup(bool really) {
|
||||
}
|
||||
|
||||
if (enoent)
|
||||
log_info("No hostname configured, using fallback hostname.");
|
||||
log_info("No hostname configured, using default hostname.");
|
||||
|
||||
hn = FALLBACK_HOSTNAME;
|
||||
source = HOSTNAME_FALLBACK;
|
||||
hn = b = get_default_hostname();
|
||||
if (!hn)
|
||||
return log_oom();
|
||||
|
||||
source = HOSTNAME_DEFAULT;
|
||||
|
||||
}
|
||||
|
||||
@ -230,7 +233,7 @@ int hostname_setup(bool really) {
|
||||
static const char* const hostname_source_table[] = {
|
||||
[HOSTNAME_STATIC] = "static",
|
||||
[HOSTNAME_TRANSIENT] = "transient",
|
||||
[HOSTNAME_FALLBACK] = "fallback",
|
||||
[HOSTNAME_DEFAULT] = "default",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(hostname_source, HostnameSource);
|
||||
|
@ -7,7 +7,7 @@
|
||||
typedef enum HostnameSource {
|
||||
HOSTNAME_STATIC, /* from /etc/hostname */
|
||||
HOSTNAME_TRANSIENT, /* a transient hostname set through systemd, hostnamed, the container manager, or otherwise */
|
||||
HOSTNAME_FALLBACK, /* the compiled-in fallback was used */
|
||||
HOSTNAME_DEFAULT, /* the os-release default or the compiled-in fallback were used */
|
||||
_HOSTNAME_INVALID = -EINVAL,
|
||||
} HostnameSource;
|
||||
|
||||
|
@ -100,6 +100,8 @@ shared_sources = files('''
|
||||
exec-util.h
|
||||
exit-status.c
|
||||
exit-status.h
|
||||
extension-release.c
|
||||
extension-release.h
|
||||
fdset.c
|
||||
fdset.h
|
||||
fileio-label.c
|
||||
@ -196,8 +198,6 @@ shared_sources = files('''
|
||||
numa-util.h
|
||||
openssl-util.c
|
||||
openssl-util.h
|
||||
os-util.c
|
||||
os-util.h
|
||||
output-mode.c
|
||||
output-mode.h
|
||||
pager.c
|
||||
|
@ -203,7 +203,7 @@ static int specifier_os_release_common(const char *field, char **ret) {
|
||||
char *t = NULL;
|
||||
int r;
|
||||
|
||||
r = parse_os_release(NULL, field, &t, NULL);
|
||||
r = parse_os_release(NULL, field, &t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!t) {
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "dissect-image.h"
|
||||
#include "env-util.h"
|
||||
#include "escape.h"
|
||||
#include "extension-release.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "format-table.h"
|
||||
@ -472,8 +473,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
|
||||
arg_root,
|
||||
"ID", &host_os_release_id,
|
||||
"VERSION_ID", &host_os_release_version_id,
|
||||
"SYSEXT_LEVEL", &host_os_release_sysext_level,
|
||||
NULL);
|
||||
"SYSEXT_LEVEL", &host_os_release_sysext_level);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire 'os-release' data of OS tree '%s': %m", empty_to_root(arg_root));
|
||||
|
||||
|
@ -349,27 +349,27 @@ static void test_config_parse(unsigned i, const char *s) {
|
||||
|
||||
switch (i) {
|
||||
case 0 ... 4:
|
||||
assert_se(r == 0);
|
||||
assert_se(r == 1);
|
||||
assert_se(streq(setting1, "1"));
|
||||
break;
|
||||
|
||||
case 5 ... 10:
|
||||
assert_se(r == 0);
|
||||
assert_se(r == 1);
|
||||
assert_se(streq(setting1, "1 2 3"));
|
||||
break;
|
||||
|
||||
case 11:
|
||||
assert_se(r == 0);
|
||||
assert_se(r == 1);
|
||||
assert_se(streq(setting1, "1\\\\ \\\\2"));
|
||||
break;
|
||||
|
||||
case 12:
|
||||
assert_se(r == 0);
|
||||
assert_se(r == 1);
|
||||
assert_se(streq(setting1, x1000("ABCD")));
|
||||
break;
|
||||
|
||||
case 13 ... 14:
|
||||
assert_se(r == 0);
|
||||
assert_se(r == 1);
|
||||
assert_se(streq(setting1, x1000("ABCD") " foobar"));
|
||||
break;
|
||||
|
||||
@ -379,7 +379,7 @@ static void test_config_parse(unsigned i, const char *s) {
|
||||
break;
|
||||
|
||||
case 17:
|
||||
assert_se(r == 0);
|
||||
assert_se(r == 1);
|
||||
assert_se(streq(setting1, "2"));
|
||||
break;
|
||||
}
|
||||
|
@ -361,6 +361,19 @@ static void test_env_assignment_is_valid(void) {
|
||||
assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
|
||||
}
|
||||
|
||||
static void test_putenv_dup(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(putenv_dup("A=a1", true) == 0);
|
||||
assert_se(streq(getenv("A"), "a1"));
|
||||
assert_se(putenv_dup("A=a1", true) == 0);
|
||||
assert_se(streq(getenv("A"), "a1"));
|
||||
assert_se(putenv_dup("A=a2", false) == 0);
|
||||
assert_se(streq(getenv("A"), "a1"));
|
||||
assert_se(putenv_dup("A=a2", true) == 0);
|
||||
assert_se(streq(getenv("A"), "a2"));
|
||||
}
|
||||
|
||||
static void test_setenv_systemd_exec_pid(void) {
|
||||
_cleanup_free_ char *saved = NULL;
|
||||
const char *e;
|
||||
@ -416,6 +429,7 @@ int main(int argc, char *argv[]) {
|
||||
test_env_name_is_valid();
|
||||
test_env_value_is_valid();
|
||||
test_env_assignment_is_valid();
|
||||
test_putenv_dup();
|
||||
test_setenv_systemd_exec_pid();
|
||||
|
||||
return 0;
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
static void test_hostname_is_valid(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(hostname_is_valid("foobar", 0));
|
||||
assert_se(hostname_is_valid("foobar.com", 0));
|
||||
assert_se(!hostname_is_valid("foobar.com.", 0));
|
||||
@ -49,6 +51,8 @@ static void test_hostname_is_valid(void) {
|
||||
static void test_hostname_cleanup(void) {
|
||||
char *s;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
s = strdupa("foobar");
|
||||
assert_se(streq(hostname_cleanup(s), "foobar"));
|
||||
s = strdupa("foobar.com");
|
||||
@ -94,6 +98,8 @@ static void test_hostname_cleanup(void) {
|
||||
static void test_hostname_malloc(void) {
|
||||
_cleanup_free_ char *h = NULL, *l = NULL;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(h = gethostname_malloc());
|
||||
log_info("hostname_malloc: \"%s\"", h);
|
||||
|
||||
@ -101,21 +107,27 @@ static void test_hostname_malloc(void) {
|
||||
log_info("hostname_short_malloc: \"%s\"", l);
|
||||
}
|
||||
|
||||
static void test_fallback_hostname(void) {
|
||||
static void test_default_hostname(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
if (!hostname_is_valid(FALLBACK_HOSTNAME, 0)) {
|
||||
log_error("Configured fallback hostname \"%s\" is not valid.", FALLBACK_HOSTNAME);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
_cleanup_free_ char *n = get_default_hostname();
|
||||
assert_se(n);
|
||||
log_info("get_default_hostname: \"%s\"", n);
|
||||
assert_se(hostname_is_valid(n, 0));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
test_setup_logging(LOG_INFO);
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
test_hostname_is_valid();
|
||||
test_hostname_cleanup();
|
||||
test_hostname_malloc();
|
||||
|
||||
test_fallback_hostname();
|
||||
test_default_hostname();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user