mirror of
https://git.proxmox.com/git/systemd
synced 2025-06-03 21:40:57 +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
|
||||
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
|
||||
host-side interface pointing to the container.
|
||||
|
||||
|
@ -10,3 +10,4 @@
|
||||
<!ENTITY MEMORY_ACCOUNTING_DEFAULT @MEMORY_ACCOUNTING_DEFAULT_YES_NO@>
|
||||
<!ENTITY KILL_USER_PROCESSES @KILL_USER_PROCESSES_YES_NO@>
|
||||
<!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
|
||||
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
|
||||
used and <filename>/home/$USER.homedir</filename> for the other storage mechanisms. Not defined for
|
||||
the <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.</para></listitem>
|
||||
directory (which may be in <filename>/home/</filename> or any other accessible filesystem). When
|
||||
unspecified defaults to <filename>/home/$USER.home</filename> when LUKS storage is used and
|
||||
<filename>/home/$USER.homedir</filename> for the other storage mechanisms. Not defined for the
|
||||
<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>
|
||||
|
@ -1,8 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--*-nxml-*-->
|
||||
<?xml version='1.0'?>
|
||||
<!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+ -->
|
||||
|
||||
<refentry id="systemd-rc-local-generator" conditional='HAVE_SYSV_COMPAT'>
|
||||
<refentryinfo>
|
||||
<title>systemd-rc-local-generator</title>
|
||||
@ -16,7 +19,7 @@
|
||||
|
||||
<refnamediv>
|
||||
<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>
|
||||
|
||||
<refsynopsisdiv>
|
||||
@ -27,17 +30,17 @@
|
||||
<title>Description</title>
|
||||
|
||||
<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.service</filename> unit into the boot process. This unit is responsible for running this script
|
||||
during late boot. Note that the script will be run with slightly different semantics than the original System V
|
||||
version, which was run "last" in the boot process, which is a concept that does not translate to systemd. The
|
||||
script is run after <filename>network.target</filename>, but in parallel with most other regular system
|
||||
services.</para>
|
||||
<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 during late boot. Note that the script will be run with slightly different semantics than the
|
||||
original System V version, which was run "last" in the boot process, which is a concept that does not
|
||||
translate to systemd. The script is run after <filename>network.target</filename>, but in parallel with
|
||||
most other regular system services.</para>
|
||||
|
||||
<para>Support for <filename>/etc/rc.local</filename> is provided
|
||||
for compatibility with specific System V systems only. However, it is strongly recommended to avoid making use of
|
||||
this script today, and instead provide proper unit files with appropriate dependencies for any scripts to run
|
||||
during the boot process.</para>
|
||||
<para>Support for <filename>&RC_LOCAL_PATH;</filename> is provided for compatibility with specific System
|
||||
V systems only. However, it is strongly recommended to avoid making use of this script today, and instead
|
||||
provide proper unit files with appropriate dependencies for any scripts to run during the boot process.
|
||||
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
|
||||
<citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
|
||||
|
@ -335,18 +335,14 @@
|
||||
<varlistentry>
|
||||
<term><varname>RemainAfterElapse=</varname></term>
|
||||
|
||||
<listitem><para>Takes a boolean argument. If true, an elapsed
|
||||
timer will stay loaded, and its state remains queryable. If
|
||||
false, an elapsed timer unit that cannot elapse anymore is
|
||||
unloaded. Turning this off is particularly useful for
|
||||
transient timer units that shall disappear after they first
|
||||
elapse. Note that this setting has an effect on repeatedly
|
||||
starting a timer unit that only elapses once: if
|
||||
<varname>RemainAfterElapse=</varname> is on, it will not be
|
||||
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
|
||||
<listitem><para>Takes a boolean argument. If true, a timer will stay loaded, and its state remains
|
||||
queryable even after it elapsed and the associated unit (as configured with <varname>Unit=</varname>,
|
||||
see above) deactivated again. If false, an elapsed timer unit that cannot elapse anymore is unloaded
|
||||
once its associated unit deactivated again. Turning this off is particularly useful for transient
|
||||
timer units. Note that this setting has an effect when repeatedly starting a timer unit: if
|
||||
<varname>RemainAfterElapse=</varname> is on, starting the timer a second time has no effect. However,
|
||||
if <varname>RemainAfterElapse=</varname> is off and the timer unit was already unloaded, it can be
|
||||
started again, and thus the service can be triggered multiple times. Defaults to
|
||||
<varname>yes</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
</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_SYSVINIT_PATH', sysvinit_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())
|
||||
|
||||
@ -296,7 +296,7 @@ substs.set('CERTIFICATEROOT', get_option('certif
|
||||
substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed'))
|
||||
substs.set('SYSTEM_SYSVINIT_PATH', sysvinit_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('STATUS_UNIT_FORMAT_DEFAULT', status_unit_format_default)
|
||||
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:
|
||||
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))
|
||||
return -ENOMEM;
|
||||
value[n_value++] = '"';
|
||||
} else if (!strchr(NEWLINE, c)) {
|
||||
value[n_value++] = 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))
|
||||
return -ENOMEM;
|
||||
value[n_value++] = '\\';
|
||||
value[n_value++] = c;
|
||||
}
|
||||
|
||||
/* Escaped newlines (aka "continuation lines") are eaten up entirely */
|
||||
break;
|
||||
|
||||
case COMMENT:
|
||||
|
@ -3,11 +3,7 @@
|
||||
set -eu
|
||||
|
||||
for i in *.h */*.h; do
|
||||
if [[ $i == 'wireguard.h' ]]; then
|
||||
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
|
||||
curl https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/$i -o $i
|
||||
|
||||
sed -i -e 's/__user //g' -e '/^#include <linux\/compiler.h>/ d' $i
|
||||
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, we need to check the actual buffer size here. */
|
||||
l = sizeof(value);
|
||||
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)
|
||||
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, we need to check the actual buffer size here. */
|
||||
l = sizeof(value);
|
||||
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)
|
||||
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);
|
||||
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)
|
||||
return log_error_errno(r, "Failed to test system token validity: %m");
|
||||
} else {
|
||||
|
@ -2396,7 +2396,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
assert(argc >= 0);
|
||||
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) {
|
||||
|
||||
|
@ -507,8 +507,8 @@ static void automount_trigger_notify(Unit *u, Unit *other) {
|
||||
assert(other);
|
||||
|
||||
/* Filter out invocations with bogus state */
|
||||
if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT)
|
||||
return;
|
||||
assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
|
||||
assert(other->type == UNIT_MOUNT);
|
||||
|
||||
/* Don't propagate state changes from the mount if we are already down */
|
||||
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(other);
|
||||
|
||||
/* Invoked whenever the unit we trigger changes state or gains
|
||||
* or loses a job */
|
||||
/* Invoked whenever the unit we trigger changes state or gains 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;
|
||||
|
||||
if (p->state == PATH_RUNNING &&
|
||||
@ -790,6 +803,7 @@ static const char* const path_result_table[_PATH_RESULT_MAX] = {
|
||||
[PATH_SUCCESS] = "success",
|
||||
[PATH_FAILURE_RESOURCES] = "resources",
|
||||
[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);
|
||||
|
@ -45,6 +45,7 @@ typedef enum PathResult {
|
||||
PATH_SUCCESS,
|
||||
PATH_FAILURE_RESOURCES,
|
||||
PATH_FAILURE_START_LIMIT_HIT,
|
||||
PATH_FAILURE_UNIT_START_LIMIT_HIT,
|
||||
_PATH_RESULT_MAX,
|
||||
_PATH_RESULT_INVALID = -1
|
||||
} PathResult;
|
||||
|
@ -3284,13 +3284,8 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
|
||||
assert(other);
|
||||
|
||||
/* Filter out invocations with bogus state */
|
||||
if (!IN_SET(other->load_state,
|
||||
UNIT_LOADED,
|
||||
UNIT_NOT_FOUND,
|
||||
UNIT_BAD_SETTING,
|
||||
UNIT_ERROR,
|
||||
UNIT_MASKED) || other->type != UNIT_SERVICE)
|
||||
return;
|
||||
assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
|
||||
assert(other->type == UNIT_SERVICE);
|
||||
|
||||
/* Don't propagate state changes from the service if we are already down */
|
||||
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(other);
|
||||
|
||||
if (other->load_state != UNIT_LOADED)
|
||||
return;
|
||||
/* Filter out invocations with bogus state */
|
||||
assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
|
||||
|
||||
/* Reenable all timers that depend on unit state */
|
||||
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
|
||||
* 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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
* 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. */
|
||||
|
@ -425,7 +425,7 @@ static int add_mount(
|
||||
* the systemd mount-timeout doesn't interfere.
|
||||
* By placing these options first, they can be over-ridden by
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
@ -1267,15 +1267,22 @@ int home_create(Home *h, UserRecord *secret, sd_bus_error *error) {
|
||||
assert(h);
|
||||
|
||||
switch (home_get_state(h)) {
|
||||
case HOME_INACTIVE:
|
||||
case HOME_INACTIVE: {
|
||||
int t;
|
||||
|
||||
if (h->record->storage < 0)
|
||||
break; /* if no storage is defined we don't know what precisely to look for, hence
|
||||
* 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 */
|
||||
|
||||
_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:
|
||||
return sd_bus_error_setf(error, BUS_ERROR_HOME_EXISTS, "Home of user %s already exists.", h->user_name);
|
||||
case HOME_ABSENT:
|
||||
@ -2709,6 +2716,19 @@ int home_set_current_message(Home *h, sd_bus_message *m) {
|
||||
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] = {
|
||||
[HOME_UNFIXATED] = "unfixated",
|
||||
[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_wait_for_worker(Home *h);
|
||||
|
||||
const char *home_state_to_string(HomeState state);
|
||||
HomeState home_state_from_string(const char *s);
|
||||
|
@ -232,8 +232,14 @@ int manager_new(Manager **ret) {
|
||||
}
|
||||
|
||||
Manager* manager_free(Manager *m) {
|
||||
Home *h;
|
||||
Iterator i;
|
||||
|
||||
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_name);
|
||||
hashmap_free(m->homes_by_worker_pid);
|
||||
|
@ -18,8 +18,9 @@ fi
|
||||
|
||||
MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID
|
||||
|
||||
ENTRY_DIR="/$MACHINE_ID/$KERNEL_VERSION"
|
||||
BOOT_ROOT=${ENTRY_DIR_ABS%$ENTRY_DIR}
|
||||
BOOT_ROOT=${ENTRY_DIR_ABS%/$MACHINE_ID/$KERNEL_VERSION}
|
||||
BOOT_MNT=$(stat -c %m $BOOT_ROOT)
|
||||
ENTRY_DIR=/${ENTRY_DIR_ABS#$BOOT_MNT}
|
||||
|
||||
if [[ $COMMAND == remove ]]; then
|
||||
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;
|
||||
struct addrinfo *result, hints = {
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_ADDRCONFIG,
|
||||
};
|
||||
|
||||
assert(b);
|
||||
|
@ -66,7 +66,10 @@ int stub_pid1(sd_id128_t uuid) {
|
||||
if (pid == 0) {
|
||||
/* Return in the child */
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2172,7 +2172,7 @@ static int setup_pts(const char *dest) {
|
||||
}
|
||||
|
||||
static int setup_stdio_as_dev_console(void) {
|
||||
int terminal;
|
||||
_cleanup_close_ int terminal = -1;
|
||||
int r;
|
||||
|
||||
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 */
|
||||
r = rearrange_stdio(terminal, terminal, terminal);
|
||||
TAKE_FD(terminal);
|
||||
if (r < 0)
|
||||
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)
|
||||
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)
|
||||
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);
|
||||
|
||||
if (check_executable(RC_LOCAL_SCRIPT_PATH_START) >= 0) {
|
||||
if (check_executable(RC_LOCAL_PATH) >= 0) {
|
||||
log_debug("Automatically adding rc-local.service.");
|
||||
|
||||
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
|
||||
* 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)
|
||||
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. */
|
||||
m->partitions[PARTITION_ROOT].rw = false;
|
||||
|
||||
@ -992,7 +991,7 @@ static int mount_partition(
|
||||
/* If requested, turn on discard support. */
|
||||
if (fstype_can_discard(fstype) &&
|
||||
((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");
|
||||
if (!options)
|
||||
return -ENOMEM;
|
||||
|
@ -418,7 +418,6 @@ static int resolve_remote(Connection *c) {
|
||||
static const struct addrinfo hints = {
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_ADDRCONFIG
|
||||
};
|
||||
|
||||
const char *node, *service;
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "env-file.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "macro.h"
|
||||
#include "strv.h"
|
||||
@ -132,6 +133,46 @@ static void test_load_env_file_5(void) {
|
||||
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[]) {
|
||||
test_setup_logging(LOG_INFO);
|
||||
|
||||
@ -140,4 +181,8 @@ int main(int argc, char *argv[]) {
|
||||
test_load_env_file_3();
|
||||
test_load_env_file_4();
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
_cleanup_(unlink_tempfilep) char
|
||||
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);
|
||||
fputs("one=BAR\\\n"
|
||||
" VAR\\\n"
|
||||
"\tGAR\n"
|
||||
"\\ \\ \\ \\ VAR\\\n"
|
||||
"\\\tGAR\n"
|
||||
"#comment\n"
|
||||
"two=\"bar\\\n"
|
||||
" var\\\n"
|
||||
@ -173,9 +185,13 @@ static void test_parse_multiline_env_file(void) {
|
||||
" var \\\n"
|
||||
"\tgar \"\n", f);
|
||||
|
||||
fflush(f);
|
||||
assert_se(fflush_and_check(f) >= 0);
|
||||
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);
|
||||
assert_se(r >= 0);
|
||||
|
||||
|
@ -8,16 +8,16 @@
|
||||
# (at your option) any later version.
|
||||
|
||||
# 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]
|
||||
Description=@RC_LOCAL_SCRIPT_PATH_START@ Compatibility
|
||||
Description=@RC_LOCAL_PATH@ Compatibility
|
||||
Documentation=man:systemd-rc-local-generator(8)
|
||||
ConditionFileIsExecutable=@RC_LOCAL_SCRIPT_PATH_START@
|
||||
ConditionFileIsExecutable=@RC_LOCAL_PATH@
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
ExecStart=@RC_LOCAL_SCRIPT_PATH_START@ start
|
||||
ExecStart=@RC_LOCAL_PATH@ start
|
||||
TimeoutSec=0
|
||||
RemainAfterExit=yes
|
||||
GuessMainPID=no
|
||||
|
Loading…
Reference in New Issue
Block a user