mirror of
https://git.proxmox.com/git/systemd
synced 2025-06-05 14:51:26 +00:00
New upstream version 246.6
This commit is contained in:
parent
7de6915edf
commit
883b242a8a
3
TODO
3
TODO
@ -581,6 +581,9 @@ Features:
|
|||||||
* sd-bus: add vtable flag, that may be used to request client creds implicitly
|
* sd-bus: add vtable flag, that may be used to request client creds implicitly
|
||||||
and asynchronously before dispatching the operation
|
and asynchronously before dispatching the operation
|
||||||
|
|
||||||
|
* sd-bus: parse addresses given in sd_bus_set_addresses immediately and not
|
||||||
|
only when used. Add unit tests.
|
||||||
|
|
||||||
* make use of ethtool veth peer info in machined, for automatically finding out
|
* make use of ethtool veth peer info in machined, for automatically finding out
|
||||||
host-side interface pointing to the container.
|
host-side interface pointing to the container.
|
||||||
|
|
||||||
|
@ -10,3 +10,4 @@
|
|||||||
<!ENTITY MEMORY_ACCOUNTING_DEFAULT @MEMORY_ACCOUNTING_DEFAULT_YES_NO@>
|
<!ENTITY MEMORY_ACCOUNTING_DEFAULT @MEMORY_ACCOUNTING_DEFAULT_YES_NO@>
|
||||||
<!ENTITY KILL_USER_PROCESSES @KILL_USER_PROCESSES_YES_NO@>
|
<!ENTITY KILL_USER_PROCESSES @KILL_USER_PROCESSES_YES_NO@>
|
||||||
<!ENTITY DEBUGTTY @DEBUGTTY@>
|
<!ENTITY DEBUGTTY @DEBUGTTY@>
|
||||||
|
<!ENTITY RC_LOCAL_PATH @RC_LOCAL_PATH@>
|
||||||
|
@ -556,10 +556,13 @@
|
|||||||
|
|
||||||
<listitem><para>Takes a file system path. Configures where to place the user's home directory. When
|
<listitem><para>Takes a file system path. Configures where to place the user's home directory. When
|
||||||
LUKS2 storage is used refers to the path to the loopback file, otherwise to the path to the home
|
LUKS2 storage is used refers to the path to the loopback file, otherwise to the path to the home
|
||||||
directory. When unspecified defaults to <filename>/home/$USER.home</filename> when LUKS storage is
|
directory (which may be in <filename>/home/</filename> or any other accessible filesystem). When
|
||||||
used and <filename>/home/$USER.homedir</filename> for the other storage mechanisms. Not defined for
|
unspecified defaults to <filename>/home/$USER.home</filename> when LUKS storage is used and
|
||||||
the <literal>cifs</literal> storage mechanism. To use LUKS2 storage on a regular block device (for
|
<filename>/home/$USER.homedir</filename> for the other storage mechanisms. Not defined for the
|
||||||
example a USB stick) pass the path to the block device here.</para></listitem>
|
<literal>cifs</literal> storage mechanism. To use LUKS2 storage on a regular block device (for
|
||||||
|
example a USB stick) pass the path to the block device here. Specifying the path to a directory here
|
||||||
|
when using LUKS2 storage is not allowed. Similar, specifying the path to a regular file or device
|
||||||
|
node is not allowed if any of the other storage backends are used.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version='1.0'?>
|
||||||
<!--*-nxml-*-->
|
|
||||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
|
||||||
|
<!ENTITY % entities SYSTEM "custom-entities.ent" >
|
||||||
|
%entities;
|
||||||
|
]>
|
||||||
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
|
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
|
||||||
|
|
||||||
<refentry id="systemd-rc-local-generator" conditional='HAVE_SYSV_COMPAT'>
|
<refentry id="systemd-rc-local-generator" conditional='HAVE_SYSV_COMPAT'>
|
||||||
<refentryinfo>
|
<refentryinfo>
|
||||||
<title>systemd-rc-local-generator</title>
|
<title>systemd-rc-local-generator</title>
|
||||||
@ -16,7 +19,7 @@
|
|||||||
|
|
||||||
<refnamediv>
|
<refnamediv>
|
||||||
<refname>systemd-rc-local-generator</refname>
|
<refname>systemd-rc-local-generator</refname>
|
||||||
<refpurpose>Compatibility generator for starting <filename>/etc/rc.local</filename> during boot</refpurpose>
|
<refpurpose>Compatibility generator for starting <filename>&RC_LOCAL_PATH;</filename> during boot</refpurpose>
|
||||||
</refnamediv>
|
</refnamediv>
|
||||||
|
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
@ -27,17 +30,17 @@
|
|||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
|
|
||||||
<para><filename>systemd-rc-local-generator</filename> is a generator that checks whether
|
<para><filename>systemd-rc-local-generator</filename> is a generator that checks whether
|
||||||
<filename>/etc/rc.local</filename> exists and is executable, and if it is pulls the
|
<filename>&RC_LOCAL_PATH;</filename> exists and is executable, and if it is pulls the
|
||||||
<filename>rc-local.service</filename> unit into the boot process. This unit is responsible for running this script
|
<filename>rc-local.service</filename> unit into the boot process. This unit is responsible for running
|
||||||
during late boot. Note that the script will be run with slightly different semantics than the original System V
|
this script during late boot. Note that the script will be run with slightly different semantics than the
|
||||||
version, which was run "last" in the boot process, which is a concept that does not translate to systemd. The
|
original System V version, which was run "last" in the boot process, which is a concept that does not
|
||||||
script is run after <filename>network.target</filename>, but in parallel with most other regular system
|
translate to systemd. The script is run after <filename>network.target</filename>, but in parallel with
|
||||||
services.</para>
|
most other regular system services.</para>
|
||||||
|
|
||||||
<para>Support for <filename>/etc/rc.local</filename> is provided
|
<para>Support for <filename>&RC_LOCAL_PATH;</filename> is provided for compatibility with specific System
|
||||||
for compatibility with specific System V systems only. However, it is strongly recommended to avoid making use of
|
V systems only. However, it is strongly recommended to avoid making use of this script today, and instead
|
||||||
this script today, and instead provide proper unit files with appropriate dependencies for any scripts to run
|
provide proper unit files with appropriate dependencies for any scripts to run during the boot process.
|
||||||
during the boot process.</para>
|
Note that the path to the script is set a compile time and varies between distributions.</para>
|
||||||
|
|
||||||
<para><filename>systemd-rc-local-generator</filename> implements
|
<para><filename>systemd-rc-local-generator</filename> implements
|
||||||
<citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
|
<citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
|
||||||
|
@ -335,18 +335,14 @@
|
|||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>RemainAfterElapse=</varname></term>
|
<term><varname>RemainAfterElapse=</varname></term>
|
||||||
|
|
||||||
<listitem><para>Takes a boolean argument. If true, an elapsed
|
<listitem><para>Takes a boolean argument. If true, a timer will stay loaded, and its state remains
|
||||||
timer will stay loaded, and its state remains queryable. If
|
queryable even after it elapsed and the associated unit (as configured with <varname>Unit=</varname>,
|
||||||
false, an elapsed timer unit that cannot elapse anymore is
|
see above) deactivated again. If false, an elapsed timer unit that cannot elapse anymore is unloaded
|
||||||
unloaded. Turning this off is particularly useful for
|
once its associated unit deactivated again. Turning this off is particularly useful for transient
|
||||||
transient timer units that shall disappear after they first
|
timer units. Note that this setting has an effect when repeatedly starting a timer unit: if
|
||||||
elapse. Note that this setting has an effect on repeatedly
|
<varname>RemainAfterElapse=</varname> is on, starting the timer a second time has no effect. However,
|
||||||
starting a timer unit that only elapses once: if
|
if <varname>RemainAfterElapse=</varname> is off and the timer unit was already unloaded, it can be
|
||||||
<varname>RemainAfterElapse=</varname> is on, it will not be
|
started again, and thus the service can be triggered multiple times. Defaults to
|
||||||
started again, and is guaranteed to elapse only once. However,
|
|
||||||
if <varname>RemainAfterElapse=</varname> is off, it might be
|
|
||||||
started again if it is already elapsed, and thus be triggered
|
|
||||||
multiple times. Defaults to
|
|
||||||
<varname>yes</varname>.</para></listitem>
|
<varname>yes</varname>.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
@ -209,7 +209,7 @@ conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', join_paths(pkgsysc
|
|||||||
conf.set_quoted('SYSTEM_DATA_UNIT_PATH', systemunitdir)
|
conf.set_quoted('SYSTEM_DATA_UNIT_PATH', systemunitdir)
|
||||||
conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path)
|
conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path)
|
||||||
conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
|
conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
|
||||||
conf.set_quoted('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local'))
|
conf.set_quoted('RC_LOCAL_PATH', get_option('rc-local'))
|
||||||
|
|
||||||
conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper())
|
conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper())
|
||||||
|
|
||||||
@ -296,7 +296,7 @@ substs.set('CERTIFICATEROOT', get_option('certif
|
|||||||
substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed'))
|
substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed'))
|
||||||
substs.set('SYSTEM_SYSVINIT_PATH', sysvinit_path)
|
substs.set('SYSTEM_SYSVINIT_PATH', sysvinit_path)
|
||||||
substs.set('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
|
substs.set('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
|
||||||
substs.set('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local'))
|
substs.set('RC_LOCAL_PATH', get_option('rc-local'))
|
||||||
substs.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'yes' : 'no')
|
substs.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'yes' : 'no')
|
||||||
substs.set('STATUS_UNIT_FORMAT_DEFAULT', status_unit_format_default)
|
substs.set('STATUS_UNIT_FORMAT_DEFAULT', status_unit_format_default)
|
||||||
substs.set('HIGH_RLIMIT_NOFILE', conf.get('HIGH_RLIMIT_NOFILE'))
|
substs.set('HIGH_RLIMIT_NOFILE', conf.get('HIGH_RLIMIT_NOFILE'))
|
||||||
|
@ -209,17 +209,21 @@ static int parse_env_file_internal(
|
|||||||
case DOUBLE_QUOTE_VALUE_ESCAPE:
|
case DOUBLE_QUOTE_VALUE_ESCAPE:
|
||||||
state = DOUBLE_QUOTE_VALUE;
|
state = DOUBLE_QUOTE_VALUE;
|
||||||
|
|
||||||
if (c == '"') {
|
if (strchr(SHELL_NEED_ESCAPE, c)) {
|
||||||
|
/* If this is a char that needs escaping, just unescape it. */
|
||||||
if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
|
if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
value[n_value++] = '"';
|
value[n_value++] = c;
|
||||||
} else if (!strchr(NEWLINE, c)) {
|
} else if (c != '\n') {
|
||||||
|
/* If other char than what needs escaping, keep the "\" in place, like the
|
||||||
|
* real shell does. */
|
||||||
if (!GREEDY_REALLOC(value, value_alloc, n_value+3))
|
if (!GREEDY_REALLOC(value, value_alloc, n_value+3))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
value[n_value++] = '\\';
|
value[n_value++] = '\\';
|
||||||
value[n_value++] = c;
|
value[n_value++] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Escaped newlines (aka "continuation lines") are eaten up entirely */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMENT:
|
case COMMENT:
|
||||||
|
@ -3,11 +3,7 @@
|
|||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
for i in *.h */*.h; do
|
for i in *.h */*.h; do
|
||||||
if [[ $i == 'wireguard.h' ]]; then
|
curl https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/$i -o $i
|
||||||
curl https://raw.githubusercontent.com/WireGuard/WireGuard/master/src/uapi/$i -o $i
|
|
||||||
else
|
|
||||||
curl https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/$i -o $i
|
|
||||||
fi
|
|
||||||
|
|
||||||
sed -i -e 's/__user //g' -e '/^#include <linux\/compiler.h>/ d' $i
|
sed -i -e 's/__user //g' -e '/^#include <linux\/compiler.h>/ d' $i
|
||||||
done
|
done
|
||||||
|
@ -635,6 +635,7 @@ int fd_set_sndbuf(int fd, size_t n, bool increase) {
|
|||||||
|
|
||||||
/* SO_SNDBUF above may set to the kernel limit, instead of the requested size.
|
/* SO_SNDBUF above may set to the kernel limit, instead of the requested size.
|
||||||
* So, we need to check the actual buffer size here. */
|
* So, we need to check the actual buffer size here. */
|
||||||
|
l = sizeof(value);
|
||||||
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
|
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
|
||||||
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
|
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
|
||||||
return 1;
|
return 1;
|
||||||
@ -665,6 +666,7 @@ int fd_set_rcvbuf(int fd, size_t n, bool increase) {
|
|||||||
|
|
||||||
/* SO_RCVBUF above may set to the kernel limit, instead of the requested size.
|
/* SO_RCVBUF above may set to the kernel limit, instead of the requested size.
|
||||||
* So, we need to check the actual buffer size here. */
|
* So, we need to check the actual buffer size here. */
|
||||||
|
l = sizeof(value);
|
||||||
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
|
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
|
||||||
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
|
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1472,7 +1472,9 @@ static int install_random_seed(const char *esp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderSystemToken", NULL, NULL, &token_size);
|
r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderSystemToken", NULL, NULL, &token_size);
|
||||||
if (r < 0) {
|
if (r == -ENODATA)
|
||||||
|
log_debug_errno(r, "LoaderSystemToken EFI variable is invalid (too short?), replacing.");
|
||||||
|
else if (r < 0) {
|
||||||
if (r != -ENOENT)
|
if (r != -ENOENT)
|
||||||
return log_error_errno(r, "Failed to test system token validity: %m");
|
return log_error_errno(r, "Failed to test system token validity: %m");
|
||||||
} else {
|
} else {
|
||||||
|
@ -2396,7 +2396,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
assert(argc >= 0);
|
assert(argc >= 0);
|
||||||
assert(argv);
|
assert(argv);
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "hH:M:qj", options, NULL)) >= 0)
|
while ((c = getopt_long(argc, argv, "hH:M:qjl", options, NULL)) >= 0)
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
|
||||||
|
@ -507,8 +507,8 @@ static void automount_trigger_notify(Unit *u, Unit *other) {
|
|||||||
assert(other);
|
assert(other);
|
||||||
|
|
||||||
/* Filter out invocations with bogus state */
|
/* Filter out invocations with bogus state */
|
||||||
if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT)
|
assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
|
||||||
return;
|
assert(other->type == UNIT_MOUNT);
|
||||||
|
|
||||||
/* Don't propagate state changes from the mount if we are already down */
|
/* Don't propagate state changes from the mount if we are already down */
|
||||||
if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING))
|
if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING))
|
||||||
|
@ -748,10 +748,23 @@ static void path_trigger_notify(Unit *u, Unit *other) {
|
|||||||
assert(u);
|
assert(u);
|
||||||
assert(other);
|
assert(other);
|
||||||
|
|
||||||
/* Invoked whenever the unit we trigger changes state or gains
|
/* Invoked whenever the unit we trigger changes state or gains or loses a job */
|
||||||
* or loses a job */
|
|
||||||
|
|
||||||
if (other->load_state != UNIT_LOADED)
|
/* Filter out invocations with bogus state */
|
||||||
|
assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
|
||||||
|
|
||||||
|
/* Don't propagate state changes from the triggered unit if we are already down */
|
||||||
|
if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Propagate start limit hit state */
|
||||||
|
if (other->start_limit_hit) {
|
||||||
|
path_enter_dead(p, PATH_FAILURE_UNIT_START_LIMIT_HIT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't propagate anything if there's still a job queued */
|
||||||
|
if (other->job)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (p->state == PATH_RUNNING &&
|
if (p->state == PATH_RUNNING &&
|
||||||
@ -790,6 +803,7 @@ static const char* const path_result_table[_PATH_RESULT_MAX] = {
|
|||||||
[PATH_SUCCESS] = "success",
|
[PATH_SUCCESS] = "success",
|
||||||
[PATH_FAILURE_RESOURCES] = "resources",
|
[PATH_FAILURE_RESOURCES] = "resources",
|
||||||
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||||
|
[PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
|
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
|
||||||
|
@ -45,6 +45,7 @@ typedef enum PathResult {
|
|||||||
PATH_SUCCESS,
|
PATH_SUCCESS,
|
||||||
PATH_FAILURE_RESOURCES,
|
PATH_FAILURE_RESOURCES,
|
||||||
PATH_FAILURE_START_LIMIT_HIT,
|
PATH_FAILURE_START_LIMIT_HIT,
|
||||||
|
PATH_FAILURE_UNIT_START_LIMIT_HIT,
|
||||||
_PATH_RESULT_MAX,
|
_PATH_RESULT_MAX,
|
||||||
_PATH_RESULT_INVALID = -1
|
_PATH_RESULT_INVALID = -1
|
||||||
} PathResult;
|
} PathResult;
|
||||||
|
@ -3284,13 +3284,8 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
|
|||||||
assert(other);
|
assert(other);
|
||||||
|
|
||||||
/* Filter out invocations with bogus state */
|
/* Filter out invocations with bogus state */
|
||||||
if (!IN_SET(other->load_state,
|
assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
|
||||||
UNIT_LOADED,
|
assert(other->type == UNIT_SERVICE);
|
||||||
UNIT_NOT_FOUND,
|
|
||||||
UNIT_BAD_SETTING,
|
|
||||||
UNIT_ERROR,
|
|
||||||
UNIT_MASKED) || other->type != UNIT_SERVICE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Don't propagate state changes from the service if we are already down */
|
/* Don't propagate state changes from the service if we are already down */
|
||||||
if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING))
|
if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING))
|
||||||
|
@ -746,8 +746,8 @@ static void timer_trigger_notify(Unit *u, Unit *other) {
|
|||||||
assert(u);
|
assert(u);
|
||||||
assert(other);
|
assert(other);
|
||||||
|
|
||||||
if (other->load_state != UNIT_LOADED)
|
/* Filter out invocations with bogus state */
|
||||||
return;
|
assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
|
||||||
|
|
||||||
/* Reenable all timers that depend on unit state */
|
/* Reenable all timers that depend on unit state */
|
||||||
LIST_FOREACH(value, v, t->values)
|
LIST_FOREACH(value, v, t->values)
|
||||||
|
@ -949,7 +949,7 @@ int transaction_add_job_and_dependencies(
|
|||||||
|
|
||||||
/* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set
|
/* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set
|
||||||
* temporarily. */
|
* temporarily. */
|
||||||
if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_MASKED))
|
if (!UNIT_IS_LOAD_COMPLETE(unit->load_state))
|
||||||
return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
|
return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
|
||||||
|
|
||||||
if (type != JOB_STOP) {
|
if (type != JOB_STOP) {
|
||||||
|
@ -49,6 +49,10 @@ static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) {
|
|||||||
return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED);
|
return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool UNIT_IS_LOAD_COMPLETE(UnitLoadState t) {
|
||||||
|
return t >= 0 && t < _UNIT_LOAD_STATE_MAX && t != UNIT_STUB && t != UNIT_MERGED;
|
||||||
|
}
|
||||||
|
|
||||||
/* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We
|
/* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We
|
||||||
* use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be
|
* use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be
|
||||||
* created as a result of multiple "reasons", hence the bitmask. */
|
* created as a result of multiple "reasons", hence the bitmask. */
|
||||||
|
@ -425,7 +425,7 @@ static int add_mount(
|
|||||||
* the systemd mount-timeout doesn't interfere.
|
* the systemd mount-timeout doesn't interfere.
|
||||||
* By placing these options first, they can be over-ridden by
|
* By placing these options first, they can be over-ridden by
|
||||||
* settings in /etc/fstab. */
|
* settings in /etc/fstab. */
|
||||||
opts = strjoina("x-systemd.mount-timeout=infinity,retry=10000,", opts, ",fg");
|
opts = strjoina("x-systemd.mount-timeout=infinity,retry=10000,nofail,", opts, ",fg");
|
||||||
SET_FLAG(flags, NOFAIL, true);
|
SET_FLAG(flags, NOFAIL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1267,15 +1267,22 @@ int home_create(Home *h, UserRecord *secret, sd_bus_error *error) {
|
|||||||
assert(h);
|
assert(h);
|
||||||
|
|
||||||
switch (home_get_state(h)) {
|
switch (home_get_state(h)) {
|
||||||
case HOME_INACTIVE:
|
case HOME_INACTIVE: {
|
||||||
|
int t;
|
||||||
|
|
||||||
if (h->record->storage < 0)
|
if (h->record->storage < 0)
|
||||||
break; /* if no storage is defined we don't know what precisely to look for, hence
|
break; /* if no storage is defined we don't know what precisely to look for, hence
|
||||||
* HOME_INACTIVE is OK in that case too. */
|
* HOME_INACTIVE is OK in that case too. */
|
||||||
|
|
||||||
if (IN_SET(user_record_test_image_path(h->record), USER_TEST_MAYBE, USER_TEST_UNDEFINED))
|
t = user_record_test_image_path(h->record);
|
||||||
|
if (IN_SET(t, USER_TEST_MAYBE, USER_TEST_UNDEFINED))
|
||||||
break; /* And if the image path test isn't conclusive, let's also go on */
|
break; /* And if the image path test isn't conclusive, let's also go on */
|
||||||
|
|
||||||
_fallthrough_;
|
if (IN_SET(t, -EBADFD, -ENOTDIR))
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_HOME_EXISTS, "Selected home image of user %s already exists or has wrong inode type.", h->user_name);
|
||||||
|
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_HOME_EXISTS, "Selected home image of user %s already exists.", h->user_name);
|
||||||
|
}
|
||||||
case HOME_UNFIXATED:
|
case HOME_UNFIXATED:
|
||||||
return sd_bus_error_setf(error, BUS_ERROR_HOME_EXISTS, "Home of user %s already exists.", h->user_name);
|
return sd_bus_error_setf(error, BUS_ERROR_HOME_EXISTS, "Home of user %s already exists.", h->user_name);
|
||||||
case HOME_ABSENT:
|
case HOME_ABSENT:
|
||||||
@ -2709,6 +2716,19 @@ int home_set_current_message(Home *h, sd_bus_message *m) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int home_wait_for_worker(Home *h) {
|
||||||
|
assert(h);
|
||||||
|
|
||||||
|
if (h->worker_pid <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log_info("Worker process for home %s is still running while exiting. Waiting for it to finish.", h->user_name);
|
||||||
|
(void) wait_for_terminate(h->worker_pid, NULL);
|
||||||
|
(void) hashmap_remove_value(h->manager->homes_by_worker_pid, PID_TO_PTR(h->worker_pid), h);
|
||||||
|
h->worker_pid = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static const char* const home_state_table[_HOME_STATE_MAX] = {
|
static const char* const home_state_table[_HOME_STATE_MAX] = {
|
||||||
[HOME_UNFIXATED] = "unfixated",
|
[HOME_UNFIXATED] = "unfixated",
|
||||||
[HOME_ABSENT] = "absent",
|
[HOME_ABSENT] = "absent",
|
||||||
|
@ -164,5 +164,7 @@ int home_auto_login(Home *h, char ***ret_seats);
|
|||||||
|
|
||||||
int home_set_current_message(Home *h, sd_bus_message *m);
|
int home_set_current_message(Home *h, sd_bus_message *m);
|
||||||
|
|
||||||
|
int home_wait_for_worker(Home *h);
|
||||||
|
|
||||||
const char *home_state_to_string(HomeState state);
|
const char *home_state_to_string(HomeState state);
|
||||||
HomeState home_state_from_string(const char *s);
|
HomeState home_state_from_string(const char *s);
|
||||||
|
@ -232,8 +232,14 @@ int manager_new(Manager **ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Manager* manager_free(Manager *m) {
|
Manager* manager_free(Manager *m) {
|
||||||
|
Home *h;
|
||||||
|
Iterator i;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
|
HASHMAP_FOREACH(h, m->homes_by_worker_pid, i)
|
||||||
|
(void) home_wait_for_worker(h);
|
||||||
|
|
||||||
hashmap_free(m->homes_by_uid);
|
hashmap_free(m->homes_by_uid);
|
||||||
hashmap_free(m->homes_by_name);
|
hashmap_free(m->homes_by_name);
|
||||||
hashmap_free(m->homes_by_worker_pid);
|
hashmap_free(m->homes_by_worker_pid);
|
||||||
|
@ -18,8 +18,9 @@ fi
|
|||||||
|
|
||||||
MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID
|
MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID
|
||||||
|
|
||||||
ENTRY_DIR="/$MACHINE_ID/$KERNEL_VERSION"
|
BOOT_ROOT=${ENTRY_DIR_ABS%/$MACHINE_ID/$KERNEL_VERSION}
|
||||||
BOOT_ROOT=${ENTRY_DIR_ABS%$ENTRY_DIR}
|
BOOT_MNT=$(stat -c %m $BOOT_ROOT)
|
||||||
|
ENTRY_DIR=/${ENTRY_DIR_ABS#$BOOT_MNT}
|
||||||
|
|
||||||
if [[ $COMMAND == remove ]]; then
|
if [[ $COMMAND == remove ]]; then
|
||||||
rm -f "$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION.conf"
|
rm -f "$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION.conf"
|
||||||
|
@ -783,7 +783,6 @@ static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
|
|||||||
int r;
|
int r;
|
||||||
struct addrinfo *result, hints = {
|
struct addrinfo *result, hints = {
|
||||||
.ai_socktype = SOCK_STREAM,
|
.ai_socktype = SOCK_STREAM,
|
||||||
.ai_flags = AI_ADDRCONFIG,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(b);
|
assert(b);
|
||||||
|
@ -66,7 +66,10 @@ int stub_pid1(sd_id128_t uuid) {
|
|||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
/* Return in the child */
|
/* Return in the child */
|
||||||
assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0);
|
assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0);
|
||||||
setsid();
|
|
||||||
|
if (setsid() < 0)
|
||||||
|
return log_error_errno(errno, "Failed to become session leader in payload process: %m");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2172,7 +2172,7 @@ static int setup_pts(const char *dest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int setup_stdio_as_dev_console(void) {
|
static int setup_stdio_as_dev_console(void) {
|
||||||
int terminal;
|
_cleanup_close_ int terminal = -1;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
terminal = open_terminal("/dev/console", O_RDWR);
|
terminal = open_terminal("/dev/console", O_RDWR);
|
||||||
@ -2187,6 +2187,7 @@ static int setup_stdio_as_dev_console(void) {
|
|||||||
|
|
||||||
/* invalidates 'terminal' on success and failure */
|
/* invalidates 'terminal' on success and failure */
|
||||||
r = rearrange_stdio(terminal, terminal, terminal);
|
r = rearrange_stdio(terminal, terminal, terminal);
|
||||||
|
TAKE_FD(terminal);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m");
|
return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m");
|
||||||
|
|
||||||
|
@ -3142,7 +3142,7 @@ static int find_root(char **ret, int *ret_fd) {
|
|||||||
if (!s)
|
if (!s)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
fd = open(arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, 0777);
|
fd = open(arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, 0666);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return log_error_errno(errno, "Failed to create '%s': %m", arg_node);
|
return log_error_errno(errno, "Failed to create '%s': %m", arg_node);
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
|
|||||||
|
|
||||||
assert_se(arg_dest = dest);
|
assert_se(arg_dest = dest);
|
||||||
|
|
||||||
if (check_executable(RC_LOCAL_SCRIPT_PATH_START) >= 0) {
|
if (check_executable(RC_LOCAL_PATH) >= 0) {
|
||||||
log_debug("Automatically adding rc-local.service.");
|
log_debug("Automatically adding rc-local.service.");
|
||||||
|
|
||||||
r = add_symlink("rc-local.service", "multi-user.target");
|
r = add_symlink("rc-local.service", "multi-user.target");
|
||||||
|
@ -770,7 +770,12 @@ int dissect_image(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m->partitions[PARTITION_ROOT].found) {
|
if (m->partitions[PARTITION_ROOT].found) {
|
||||||
|
/* If we found the primary arch, then invalidate the secondary arch to avoid any ambiguities,
|
||||||
|
* since we never want to mount the secondary arch in this case. */
|
||||||
|
m->partitions[PARTITION_ROOT_SECONDARY].found = false;
|
||||||
|
m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found = false;
|
||||||
|
} else {
|
||||||
/* No root partition found? Then let's see if ther's one for the secondary architecture. And if not
|
/* No root partition found? Then let's see if ther's one for the secondary architecture. And if not
|
||||||
* either, then check if there's a single generic one, and use that. */
|
* either, then check if there's a single generic one, and use that. */
|
||||||
|
|
||||||
@ -815,12 +820,6 @@ int dissect_image(
|
|||||||
if (!m->partitions[PARTITION_ROOT_VERITY].found || !m->partitions[PARTITION_ROOT].found)
|
if (!m->partitions[PARTITION_ROOT_VERITY].found || !m->partitions[PARTITION_ROOT].found)
|
||||||
return -EADDRNOTAVAIL;
|
return -EADDRNOTAVAIL;
|
||||||
|
|
||||||
/* If we found the primary root with the hash, then we definitely want to suppress any secondary root
|
|
||||||
* (which would be weird, after all the root hash should only be assigned to one pair of
|
|
||||||
* partitions... */
|
|
||||||
m->partitions[PARTITION_ROOT_SECONDARY].found = false;
|
|
||||||
m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found = false;
|
|
||||||
|
|
||||||
/* If we found a verity setup, then the root partition is necessarily read-only. */
|
/* If we found a verity setup, then the root partition is necessarily read-only. */
|
||||||
m->partitions[PARTITION_ROOT].rw = false;
|
m->partitions[PARTITION_ROOT].rw = false;
|
||||||
|
|
||||||
@ -992,7 +991,7 @@ static int mount_partition(
|
|||||||
/* If requested, turn on discard support. */
|
/* If requested, turn on discard support. */
|
||||||
if (fstype_can_discard(fstype) &&
|
if (fstype_can_discard(fstype) &&
|
||||||
((flags & DISSECT_IMAGE_DISCARD) ||
|
((flags & DISSECT_IMAGE_DISCARD) ||
|
||||||
((flags & DISSECT_IMAGE_DISCARD_ON_LOOP) && is_loop_device(m->node)))) {
|
((flags & DISSECT_IMAGE_DISCARD_ON_LOOP) && is_loop_device(m->node) > 0))) {
|
||||||
options = strdup("discard");
|
options = strdup("discard");
|
||||||
if (!options)
|
if (!options)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -418,7 +418,6 @@ static int resolve_remote(Connection *c) {
|
|||||||
static const struct addrinfo hints = {
|
static const struct addrinfo hints = {
|
||||||
.ai_family = AF_UNSPEC,
|
.ai_family = AF_UNSPEC,
|
||||||
.ai_socktype = SOCK_STREAM,
|
.ai_socktype = SOCK_STREAM,
|
||||||
.ai_flags = AI_ADDRCONFIG
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *node, *service;
|
const char *node, *service;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "env-file.h"
|
#include "env-file.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
|
#include "fileio.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
@ -132,6 +133,46 @@ static void test_load_env_file_5(void) {
|
|||||||
assert_se(data[2] == NULL);
|
assert_se(data[2] == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_write_and_load_env_file(void) {
|
||||||
|
const char *v;
|
||||||
|
|
||||||
|
/* Make sure that our writer, parser and the shell agree on what our env var files mean */
|
||||||
|
|
||||||
|
FOREACH_STRING(v,
|
||||||
|
"obbardc-laptop",
|
||||||
|
"obbardc\\-laptop",
|
||||||
|
"obbardc-lap\\top",
|
||||||
|
"obbardc-lap\\top",
|
||||||
|
"obbardc-lap\\\\top",
|
||||||
|
"double\"quote",
|
||||||
|
"single\'quote",
|
||||||
|
"dollar$dollar",
|
||||||
|
"newline\nnewline") {
|
||||||
|
_cleanup_(unlink_and_freep) char *p = NULL;
|
||||||
|
_cleanup_strv_free_ char **l = NULL;
|
||||||
|
_cleanup_free_ char *j = NULL, *w = NULL, *cmd = NULL, *from_shell = NULL;
|
||||||
|
_cleanup_pclose_ FILE *f = NULL;
|
||||||
|
size_t sz;
|
||||||
|
|
||||||
|
assert_se(tempfn_random_child(NULL, NULL, &p) >= 0);
|
||||||
|
|
||||||
|
assert_se(j = strjoin("TEST=", v));
|
||||||
|
assert_se(write_env_file(p, STRV_MAKE(j)) >= 0);
|
||||||
|
|
||||||
|
assert_se(cmd = strjoin(". ", p, " && /bin/echo -n \"$TEST\""));
|
||||||
|
assert_se(f = popen(cmd, "re"));
|
||||||
|
assert_se(read_full_stream(f, &from_shell, &sz) >= 0);
|
||||||
|
assert_se(sz == strlen(v));
|
||||||
|
assert_se(streq(from_shell, v));
|
||||||
|
|
||||||
|
assert_se(load_env_file(NULL, p, &l) >= 0);
|
||||||
|
assert_se(strv_equal(l, STRV_MAKE(j)));
|
||||||
|
|
||||||
|
assert_se(parse_env_file(NULL, p, "TEST", &w) >= 0);
|
||||||
|
assert_se(streq_ptr(w, v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
test_setup_logging(LOG_INFO);
|
test_setup_logging(LOG_INFO);
|
||||||
|
|
||||||
@ -140,4 +181,8 @@ int main(int argc, char *argv[]) {
|
|||||||
test_load_env_file_3();
|
test_load_env_file_3();
|
||||||
test_load_env_file_4();
|
test_load_env_file_4();
|
||||||
test_load_env_file_5();
|
test_load_env_file_5();
|
||||||
|
|
||||||
|
test_write_and_load_env_file();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -151,6 +151,18 @@ static void test_parse_env_file(void) {
|
|||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_one_shell_var(const char *file, const char *variable, const char *value) {
|
||||||
|
_cleanup_free_ char *cmd = NULL, *from_shell = NULL;
|
||||||
|
_cleanup_pclose_ FILE *f = NULL;
|
||||||
|
size_t sz;
|
||||||
|
|
||||||
|
assert_se(cmd = strjoin(". ", file, " && /bin/echo -n \"$", variable, "\""));
|
||||||
|
assert_se(f = popen(cmd, "re"));
|
||||||
|
assert_se(read_full_stream(f, &from_shell, &sz) >= 0);
|
||||||
|
assert_se(sz == strlen(value));
|
||||||
|
assert_se(streq(from_shell, value));
|
||||||
|
}
|
||||||
|
|
||||||
static void test_parse_multiline_env_file(void) {
|
static void test_parse_multiline_env_file(void) {
|
||||||
_cleanup_(unlink_tempfilep) char
|
_cleanup_(unlink_tempfilep) char
|
||||||
t[] = "/tmp/test-fileio-in-XXXXXX",
|
t[] = "/tmp/test-fileio-in-XXXXXX",
|
||||||
@ -162,8 +174,8 @@ static void test_parse_multiline_env_file(void) {
|
|||||||
|
|
||||||
assert_se(fmkostemp_safe(t, "w", &f) == 0);
|
assert_se(fmkostemp_safe(t, "w", &f) == 0);
|
||||||
fputs("one=BAR\\\n"
|
fputs("one=BAR\\\n"
|
||||||
" VAR\\\n"
|
"\\ \\ \\ \\ VAR\\\n"
|
||||||
"\tGAR\n"
|
"\\\tGAR\n"
|
||||||
"#comment\n"
|
"#comment\n"
|
||||||
"two=\"bar\\\n"
|
"two=\"bar\\\n"
|
||||||
" var\\\n"
|
" var\\\n"
|
||||||
@ -173,9 +185,13 @@ static void test_parse_multiline_env_file(void) {
|
|||||||
" var \\\n"
|
" var \\\n"
|
||||||
"\tgar \"\n", f);
|
"\tgar \"\n", f);
|
||||||
|
|
||||||
fflush(f);
|
assert_se(fflush_and_check(f) >= 0);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
test_one_shell_var(t, "one", "BAR VAR\tGAR");
|
||||||
|
test_one_shell_var(t, "two", "bar var\tgar");
|
||||||
|
test_one_shell_var(t, "tri", "bar var \tgar ");
|
||||||
|
|
||||||
r = load_env_file(NULL, t, &a);
|
r = load_env_file(NULL, t, &a);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
|
@ -8,16 +8,16 @@
|
|||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
|
|
||||||
# This unit gets pulled automatically into multi-user.target by
|
# This unit gets pulled automatically into multi-user.target by
|
||||||
# systemd-rc-local-generator if @RC_LOCAL_SCRIPT_PATH_START@ is executable.
|
# systemd-rc-local-generator if @RC_LOCAL_PATH@ is executable.
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=@RC_LOCAL_SCRIPT_PATH_START@ Compatibility
|
Description=@RC_LOCAL_PATH@ Compatibility
|
||||||
Documentation=man:systemd-rc-local-generator(8)
|
Documentation=man:systemd-rc-local-generator(8)
|
||||||
ConditionFileIsExecutable=@RC_LOCAL_SCRIPT_PATH_START@
|
ConditionFileIsExecutable=@RC_LOCAL_PATH@
|
||||||
After=network.target
|
After=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=forking
|
Type=forking
|
||||||
ExecStart=@RC_LOCAL_SCRIPT_PATH_START@ start
|
ExecStart=@RC_LOCAL_PATH@ start
|
||||||
TimeoutSec=0
|
TimeoutSec=0
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
GuessMainPID=no
|
GuessMainPID=no
|
||||||
|
Loading…
Reference in New Issue
Block a user