1
0
mirror of https://github.com/systemd/systemd synced 2025-09-23 22:04:45 +02:00

Compare commits

...

23 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek
2e2f6a01a0
Merge pull request #16143 from fbuihuu/fstab-generator-fix
fstab-generator: make sure explicit deps configured via mount options apply to .mount, not .automount unit
2020-07-07 20:06:18 +02:00
Alan Perry
5dc60faae5 add error message when bind mount src missing 2020-07-07 20:04:19 +02:00
Zbigniew Jędrzejewski-Szmek
2b0bf3ccf8
Merge pull request #16301 from poettering/firstboot-image
Add --image= switch to firstboot, similar to --root= but with support for operating on disk image
2020-07-07 19:44:12 +02:00
Zbigniew Jędrzejewski-Szmek
9870cfdf7f
Merge pull request #16388 from keszybz/xdg-desktop-fuzz-case
xdg-desktop fuzz case
2020-07-07 19:41:31 +02:00
Zbigniew Jędrzejewski-Szmek
60e3a5a252
Merge pull request #16390 from keszybz/coverity-and-typos
One coverity-inspired fix and spelling
2020-07-07 19:40:10 +02:00
Zbigniew Jędrzejewski-Szmek
dea7f5cc87 xdg-autostart: ignore all empty entries in multi-string entries
The desktop file specification allows entries like ";;;;;;", full of empty strings.
But looking at the actual list of supported keys [1], empty entries are meaningless
(unless we would allow e.g. the desktop name to be the empty string. But that doesn't
seem very useful either). So let's just simplify our life and skip any empty substrings
entirely.

This would also resolve the fuzzer case:
$ valgrind build/fuzz-xdg-desktop test/fuzz/fuzz-xdg-desktop/oss-fuzz-22812
test/fuzz/fuzz-xdg-desktop/oss-fuzz-22812... ok
==2899241== HEAP SUMMARY:
==2899241==     in use at exit: 0 bytes in 0 blocks
==2899241==   total heap usage: 484,385 allocs, 484,385 frees, 12,411,330 bytes allocated
↓
==2899650== HEAP SUMMARY:
==2899650==     in use at exit: 0 bytes in 0 blocks
==2899650==   total heap usage: 1,325 allocs, 1,325 frees, 1,463,602 bytes allocated
2020-07-07 14:02:16 +02:00
Topi Miettinen
f4e1a42592 man: match parentheses
Files found with:
for f in *; do \
    l=`tr -d '[^(]' < $f | wc -c`; \
    r=`tr -d '[^)]' < $f | wc -c`; \
    if [ $l -ne $r ]; then \
       echo $f $l $r; \
    fi; \
done
2020-07-07 13:31:39 +02:00
Zbigniew Jędrzejewski-Szmek
d1ca1f7c2a xdg-autostart: avoid quadratic behaviour in strv parsing
The fuzzer test case has a giant line with ";;;;;;;;;;;..." which is turned into
a strv of empty strings. Unfortunately, when pushing each string, strv_push() needs
to walk the whole array, which leads to quadratic behaviour. So let's use
greedy_allocation here and also keep location in the string to avoid iterating.

build/fuzz-xdg-desktop test/fuzz/fuzz-xdg-desktop/oss-fuzz-22812  51.10s user 0.01s system 99% cpu 51.295 total
↓
build/fuzz-xdg-desktop test/fuzz/fuzz-xdg-desktop/oss-fuzz-22812  0.07s user 0.01s system 96% cpu 0.083 total

Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22812.

Other minor changes:
- say "was already defined" instead of "defined multiple times" to make it
  clear that we're ignoring this second definition, and not all definitions
  of the key
- unescaping needs to be done also for the last entry
2020-07-07 12:20:43 +02:00
Zbigniew Jędrzejewski-Szmek
a53f024d71 journald: minor wording tweak in message
For a user "from the kernel" might be rather unclear.
2020-07-07 12:14:41 +02:00
Zbigniew Jędrzejewski-Szmek
cd990847b9 tree-wide: more repeated words 2020-07-07 12:08:22 +02:00
Zbigniew Jędrzejewski-Szmek
8ab0f03266 journal/compress: drop "future" code in zstd compression
We generally don't include stuff that is not used. This can be
easily ressurected if ever needed.

Fixes CID#1430210.
2020-07-07 12:06:26 +02:00
Zbigniew Jędrzejewski-Szmek
0da425df65 networkd: use capitalized "IP" and "TOS" in messages 2020-07-07 12:06:26 +02:00
Lennart Poettering
737ec51444 TODO 2020-07-07 11:20:42 +02:00
Lennart Poettering
a122502077 firstboot: add option to turn off welcome text display 2020-07-07 11:20:42 +02:00
Lennart Poettering
dcfdd62184 man: document the new --image= switch of systemd-firstboot 2020-07-07 11:20:42 +02:00
Lennart Poettering
3ff9fa591e firstboot: add --image= switch
This is like --root=, but takes an image file path or device node path
and dissects the image directly, mounting it internally.
2020-07-07 11:20:42 +02:00
Lennart Poettering
827ea52125 mount-util: use UMOUNT_NOFOLLOW in recursive umounter
When we only want to unmount mount points below some path then it is
against our interest to follow symlinks. Hence don't.
2020-07-07 11:20:42 +02:00
Lennart Poettering
e49ee28522 mount-util: add destructor helper that umounts + rmdirs a path 2020-07-07 11:20:42 +02:00
Lennart Poettering
e2ec9c4d3a namespace-util: introduce helper for combining unshare() + MS_SLAVE remount
We have multiple places we do these two non-trivial operations together,
let's introduce a unified helper for doing both at once.
2020-07-07 11:20:42 +02:00
Zbigniew Jędrzejewski-Szmek
9ecf5d9340 fuzz: add test case that should already be resolved 2020-07-07 10:26:28 +02:00
Zbigniew Jędrzejewski-Szmek
3f2e15abc5 sleep: one spelling unification
We use "writable" everywhere else.
2020-07-07 10:02:02 +02:00
Franck Bui
6371e69b49 fstab-generator: introduce an helper to write extra dependencies specified via the mount options
No functional change.
2020-07-01 16:35:13 +02:00
Franck Bui
045c5faf5a fstab-generator: extra dependencies specified in fstab should be applied to the mount unit
If an entry in fstab uses "x-systemd.automount" option and also asks for
additionnal dependencies via x-systemd.requires or such, then the dependencies
were applied to the automount unit.

But this unlikely to do the right thing and is inconsistent with what's done
for network mounts.

Indeed when an fstab entries has "_netdev,x-systemd.automount" options, the
dependencies against the network requested by "_netdev" are (correctly) applied
to the mount unit only and the automount unit remains ordered against
local-fs.target.

The same logic should be followed when extra deps are specified via the mount
options as automount units should always be ordered against local-fs.target.

Note: in general explicit deps specified via mount options should be used with
care and should be used to specify dependencies on other mount units only as it
can easily create ordering cycles otherwise like it's been seen in
https://github.com/systemd/systemd-stable/issues/69. Mount units (as well as
automount ones) are ordered before local-fs.target by default which is a
low-level target that most other units depend on.
2020-07-01 16:34:42 +02:00
40 changed files with 326 additions and 136 deletions

8
TODO
View File

@ -49,6 +49,9 @@ Features:
* nspawn: support time namespaces
* systemd-firstboot: make sure to always use chase_symlinks() before
reading/writing files
* add ConditionSecurity=tpm2
* Remove any support for booting without /usr pre-mounted in the initrd entirely.
@ -94,8 +97,9 @@ Features:
this, it's useful to have one that can dump contents of them, too.
* All tools that support --root= should also learn --image= so that they can
operate on disk images directly. Specifically: bootctl, firstboot, tmpfiles,
sysusers, systemctl, repart, journalctl, coredumpctl.
operate on disk images directly. Specifically: bootctl, tmpfiles, sysusers,
systemctl, repart, journalctl, coredumpctl. (Already done: systemd-nspawn,
systemd-firstboot)
* seccomp: by default mask x32 ABI system wide on x86-64. it's on its way out

View File

@ -180,7 +180,7 @@ strictly local context and without signatures doesn't have to deal with the
`perMachine` or `binding` sections and can include its data exclusively in the
regular section. A service that uses a separate, private channel for
authenticating users (or that doesn't have a concept of authentication at all)
does not need to to be concerned with the `secret` section of user records, as
does not need to be concerned with the `secret` section of user records, as
the fields included therein are only useful when executing authentication
operations natively against JSON user records.

View File

@ -24,7 +24,7 @@
<title>Introduction</title>
<para><citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
is a system service which may be used to to create, remove, change or inspect home areas. This page
is a system service which may be used to create, remove, change or inspect home areas. This page
describes the D-Bus interface.
</para>
</refsect1>
@ -227,7 +227,7 @@ node /org/freedesktop/home1 {
interface.</para>
<para><function>CreateHome()</function> registers and creates a new home directory. This takes a fully
specified JSON user record as argument (including the <literal>secret</literal> section. This registers
specified JSON user record as argument (including the <literal>secret</literal> section). This registers
the user record locally and creates a home directory matching it, depending on the settings specified
in the record in combination with local configuration.</para>

View File

@ -239,7 +239,7 @@ node /org/freedesktop/hostname1 {
<para><varname>KernelName</varname>, <varname>KernelRelease</varname>, and
<varname>KernelVersion</varname> expose the kernel name (e.g. <literal>Linux</literal>), release
(e.g. <literal>5.0.0-11</literal>, and version (i.e. the build number, e.g. <literal>#11</literal>) as
(e.g. <literal>5.0.0-11</literal>), and version (i.e. the build number, e.g. <literal>#11</literal>) as
reported by
<citerefentry project="man-pages"><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
<varname>OperatingSystemPrettyName</varname>, <varname>OperatingSystemCPEName</varname>, and

View File

@ -1472,12 +1472,12 @@ node /org/freedesktop/systemd1 {
<para>Read access is generally granted to all clients. Additionally, for unprivileged clients, some
operations are allowed through the polkit privilege system. Operations which modify unit state
(<function>StartUnit()</function>, <function>StopUnit()</function>, <function>KillUnit()</function>,
<function>RestartUnit()</function> and similar, <function>SetProperty</function>) require
<function>RestartUnit()</function> and similar, <function>SetProperty()</function>) require
<interfacename>org.freedesktop.systemd1.manage-units</interfacename>. Operations which modify unit file
enablement state (<function>EnableUnitFiles()</function>, <function>DisableUnitFiles()</function>,
<function>ReenableUnitFiles()</function>, <function>LinkUnitFiles()</function>,
<function>PresetUnitFiles</function>, <function>MaskUnitFiles</function>, and similar) require
<interfacename>org.freedesktop.systemd1.manage-unit-files</interfacename>). Operations which modify the
<interfacename>org.freedesktop.systemd1.manage-unit-files</interfacename>. Operations which modify the
exported environment (<function>SetEnvironment()</function>, <function>UnsetEnvironment()</function>,
<function>UnsetAndSetEnvironment()</function>) require
<interfacename>org.freedesktop.systemd1.set-environment</interfacename>. <function>Reload()</function>

View File

@ -140,7 +140,7 @@
<row>
<entry><constant>root-secondary</constant></entry>
<entry>Root file system partition of the secondary architecture of the local architecture; usually the matching 32bit architecture for the local 64bit architecture)</entry>
<entry>Root file system partition of the secondary architecture of the local architecture (usually the matching 32bit architecture for the local 64bit architecture)</entry>
</row>
<row>

View File

@ -332,7 +332,7 @@
information, in particular it should not be used for security-relevant decisions. That's because the
executable might have been replaced or removed by the time the value can be processed. Moreover, the
kernel exports this information in an ambiguous way (i.e. a deleted executable cannot be safely
distinguished from one whose name suffix is <literal> (deleted)</literal>.</para>
distinguished from one whose name suffix is <literal> (deleted)</literal>).</para>
<para><function>sd_bus_creds_get_cmdline()</function> will
retrieve an array of command line arguments (as stored in

View File

@ -79,7 +79,7 @@
<constant>POLLIN</constant>, <constant>POLLOUT</constant>, … events, or negative on error.
</para>
<para><function>sd_bus_get_timeout()</function> returns the timeout in µs to pass to to
<para><function>sd_bus_get_timeout()</function> returns the timeout in µs to pass to
<function>poll()</function> or a similar call when waiting for events on the specified bus
connection. The returned timeout may be zero, in which case a subsequent I/O polling call
should be invoked in non-blocking mode. The returned timeout may be

View File

@ -131,7 +131,7 @@
automatically as the code block is left:</para>
<programlisting>{
__attribute__((cleanup(sd_event_unrefp)) sd_event *event = NULL;
__attribute__((cleanup(sd_event_unrefp))) sd_event *event = NULL;
int r;
r = sd_event_default(&amp;event);

View File

@ -112,7 +112,7 @@
code block is left:</para>
<programlisting>{
__attribute__((cleanup(sd_login_monitor_unrefp)) sd_login_monitor *m = NULL;
__attribute__((cleanup(sd_login_monitor_unrefp))) sd_login_monitor *m = NULL;
int r;
r = sd_login_monitor_default(&amp;m);

View File

@ -343,7 +343,7 @@
boots. <citerefentry><refentrytitle>bootctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
<option>set-default</option> and <option>set-oneshot</option> commands make use of these variables. The boot
loader modifies <varname>LoaderEntryDefault</varname> on request, when the <keycap>d</keycap> key is used, see
above.)</para></listitem>
above.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -98,6 +98,18 @@
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--image=<replaceable>path</replaceable></option></term>
<listitem><para>Takes a path to a disk image file or block device node. If specified all operations
are applied to file system in the indicated disk image. This is similar to <option>--root=</option>
but operates on file systems stored in disk images or block devices. The disk image should either
contain just a file system or a set of file systems within a GPT partition table, following the
<ulink url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions
Specification</ulink>. For further information on supported disk images, see
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
switch of the same name.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--locale=<replaceable>LOCALE</replaceable></option></term>
<term><option>--locale-messages=<replaceable>LOCALE</replaceable></option></term>
@ -247,6 +259,14 @@
option should not be used lightly.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--welcome=</option></term>
<listitem><para>Takes a boolean argument. By default when prompting the user for configuration
options a brief welcome text is shown before the first question is asked. Pass false to this option
to turn off the welcome text.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>

View File

@ -558,7 +558,7 @@
With option <option>yes</option> systemd-nspawn waits for the
<literal>READY=1</literal> message from the init process in the container
before sending its own to systemd. For more details about notifications
see <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).</para></listitem>
see <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
</variablelist>

View File

@ -1699,7 +1699,7 @@ RestrictNamespaces=~cgroup net</programlisting>
<option>shared</option> mount propagation is used, but — as mentioned — as <option>slave</option> is applied
first, propagation from the unit's processes to the host is still turned off.</para>
<para>It is not recommended to to use <option>private</option> mount propagation for units, as this means
<para>It is not recommended to use <option>private</option> mount propagation for units, as this means
temporary mounts (such as removable media) of the host will stay mounted and thus indefinitely busy in forked
off processes, as unmount propagation events won't be received by the file system namespace of the unit.</para>

View File

@ -204,7 +204,11 @@
system that merges multiple mount points). See
<varname>After=</varname> and <varname>Requires=</varname> in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details.</para></listitem>
for details.</para>
<para>Note that this option always applies to the created mount unit
only regardless whether <option>x-systemd.automount</option> has been
specified.</para></listitem>
</varlistentry>
<varlistentry>
@ -223,7 +227,11 @@
unit.
See <varname>Before=</varname> and <varname>After=</varname> in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details.</para></listitem>
for details.</para>
<para>Note that these options always apply to the created mount unit
only regardless whether <option>x-systemd.automount</option> has been
specified.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -2,6 +2,7 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include "fd-util.h"
#include "missing_fs.h"
@ -169,3 +170,16 @@ int fd_is_network_ns(int fd) {
return r == CLONE_NEWNET;
}
int detach_mount_namespace(void) {
/* Detaches the mount namespace, disabling propagation from our namespace to the host */
if (unshare(CLONE_NEWNS) < 0)
return -errno;
if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0)
return -errno;
return 0;
}

View File

@ -7,3 +7,5 @@ int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
int fd_is_network_ns(int fd);
int detach_mount_namespace(void);

View File

@ -223,11 +223,9 @@ int machine_id_commit(const char *root) {
return log_error_errno(r, "Can't fetch current mount namespace: %m");
/* Switch to a new mount namespace, isolate ourself and unmount etc_machine_id in our new namespace */
if (unshare(CLONE_NEWNS) < 0)
return log_error_errno(errno, "Failed to enter new namespace: %m");
if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0)
return log_error_errno(errno, "Couldn't make-rslave / mountpoint in our private namespace: %m");
r = detach_mount_namespace();
if (r < 0)
return log_error_errno(r, "Failed to set up new mount namespace: %m");
if (umount(etc_machine_id) < 0)
return log_error_errno(errno, "Failed to unmount transient %s file in our private namespace: %m", etc_machine_id);

View File

@ -1017,8 +1017,11 @@ static void mount_enter_mounting(Mount *m) {
/* Create the source directory for bind-mounts if needed */
p = get_mount_parameters_fragment(m);
if (p && mount_is_bind(p))
(void) mkdir_p_label(p->what, m->directory_mode);
if (p && mount_is_bind(p)) {
r = mkdir_p_label(p->what, m->directory_mode);
if (r < 0)
log_unit_error_errno(UNIT(m), r, "Failed to make bind mount source '%s': %m", p->what);
}
if (p) {
_cleanup_free_ char *opts = NULL;

View File

@ -1034,7 +1034,7 @@ static int apply_mount(
/* Hmm, either the source or the destination are missing. Let's see if we can create the destination, then try again */
if (stat(what, &st) < 0)
log_debug_errno(errno, "Mount point source '%s' is not accessible: %m", what);
log_error_errno(errno, "Mount point source '%s' is not accessible: %m", what);
else {
int q;
@ -1046,7 +1046,7 @@ static int apply_mount(
q = touch(mount_entry_path(m));
if (q < 0)
log_debug_errno(q, "Failed to create destination mount point node '%s': %m", mount_entry_path(m));
log_error_errno(q, "Failed to create destination mount point node '%s': %m", mount_entry_path(m));
else
try_again = true;
}
@ -1060,7 +1060,7 @@ static int apply_mount(
}
if (r < 0)
return log_debug_errno(r, "Failed to mount %s to %s: %m", what, mount_entry_path(m));
return log_error_errno(r, "Failed to mount %s to %s: %m", what, mount_entry_path(m));
}
log_debug("Successfully mounted %s to %s", what, mount_entry_path(m));

View File

@ -258,7 +258,7 @@ int unit_add_name(Unit *u, const char *text) {
t = unit_name_to_type(name);
if (t < 0)
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EINVAL),
"failed to to derive unit type from name '%s': %m", name);
"failed to derive unit type from name '%s': %m", name);
if (u->type != _UNIT_TYPE_INVALID && t != u->type)
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EINVAL),

View File

@ -2,6 +2,7 @@
#include <fcntl.h>
#include <getopt.h>
#include <linux/loop.h>
#include <unistd.h>
#include "sd-id128.h"
@ -9,6 +10,7 @@
#include "alloc-util.h"
#include "ask-password-api.h"
#include "copy.h"
#include "dissect-image.h"
#include "env-file.h"
#include "fd-util.h"
#include "fileio.h"
@ -17,9 +19,12 @@
#include "kbd-util.h"
#include "libcrypt-util.h"
#include "locale-util.h"
#include "loop-util.h"
#include "main-func.h"
#include "memory-util.h"
#include "mkdir.h"
#include "mount-util.h"
#include "namespace-util.h"
#include "os-util.h"
#include "parse-util.h"
#include "path-util.h"
@ -31,10 +36,12 @@
#include "terminal-util.h"
#include "time-util.h"
#include "tmpfile-util-label.h"
#include "tmpfile-util.h"
#include "umask-util.h"
#include "user-util.h"
static char *arg_root = NULL;
static char *arg_image = NULL;
static char *arg_locale = NULL; /* $LANG */
static char *arg_keymap = NULL;
static char *arg_locale_messages = NULL; /* $LC_MESSAGES */
@ -55,8 +62,10 @@ static bool arg_copy_root_password = false;
static bool arg_force = false;
static bool arg_delete_root_password = false;
static bool arg_root_password_is_hashed = false;
static bool arg_welcome = true;
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
STATIC_DESTRUCTOR_REGISTER(arg_locale, freep);
STATIC_DESTRUCTOR_REGISTER(arg_locale_messages, freep);
STATIC_DESTRUCTOR_REGISTER(arg_keymap, freep);
@ -85,6 +94,9 @@ static void print_welcome(void) {
const char *pn;
int r;
if (!arg_welcome)
return;
if (done)
return;
@ -826,6 +838,75 @@ static int process_kernel_cmdline(void) {
return 0;
}
static int setup_image(char **ret_mount_dir, LoopDevice **ret_loop_device, DecryptedImage **ret_decrypted_image) {
DissectImageFlags f = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK;
_cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
_cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
_cleanup_(rmdir_and_freep) char *mount_dir = NULL;
_cleanup_free_ char *temp = NULL;
int r;
if (!arg_image) {
*ret_mount_dir = NULL;
*ret_decrypted_image = NULL;
*ret_loop_device = NULL;
return 0;
}
assert(!arg_root);
r = tempfn_random_child(NULL, "firstboot", &temp);
if (r < 0)
return log_error_errno(r, "Failed to generate temporary mount directory: %m");
r = loop_device_make_by_path(arg_image, O_RDWR, LO_FLAGS_PARTSCAN, &d);
if (r < 0)
return log_error_errno(r, "Failed to set up loopback device: %m");
r = dissect_image_and_warn(d->fd, arg_image, NULL, 0, NULL, f, &dissected_image);
if (r < 0)
return r;
r = dissected_image_decrypt_interactively(dissected_image, NULL, NULL, 0, NULL, NULL, NULL, 0, f, &decrypted_image);
if (r < 0)
return r;
r = detach_mount_namespace();
if (r < 0)
return log_error_errno(r, "Failed to detach mount namespace: %m");
mount_dir = strdup(temp);
if (!mount_dir)
return log_oom();
r = mkdir_p(mount_dir, 0700);
if (r < 0) {
mount_dir = mfree(mount_dir);
return log_error_errno(r, "Failed to create mount point: %m");
}
r = dissected_image_mount(dissected_image, mount_dir, UID_INVALID, f);
if (r < 0)
return log_error_errno(r, "Failed to mount image: %m");
if (decrypted_image) {
r = decrypted_image_relinquish(decrypted_image);
if (r < 0)
return log_error_errno(r, "Failed to relinquish DM devices: %m");
}
loop_device_relinquish(d);
arg_root = TAKE_PTR(temp);
*ret_mount_dir = TAKE_PTR(mount_dir);
*ret_decrypted_image = TAKE_PTR(decrypted_image);
*ret_loop_device = TAKE_PTR(d);
return 1;
}
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
@ -839,6 +920,7 @@ static int help(void) {
" -h --help Show this help\n"
" --version Show package version\n"
" --root=PATH Operate on an alternate filesystem root\n"
" --image=PATH Operate on an alternate filesystem image\n"
" --locale=LOCALE Set primary locale (LANG=)\n"
" --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n"
" --keymap=KEYMAP Set keymap\n"
@ -862,6 +944,7 @@ static int help(void) {
" --setup-machine-id Generate a new random machine ID\n"
" --force Overwrite existing files\n"
" --delete-root-password Delete root password\n"
" --welcome=no Disable the welcome text\n"
"\nSee the %s for details.\n"
, program_invocation_short_name
, link
@ -875,6 +958,7 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_ROOT,
ARG_IMAGE,
ARG_LOCALE,
ARG_LOCALE_MESSAGES,
ARG_KEYMAP,
@ -899,12 +983,14 @@ static int parse_argv(int argc, char *argv[]) {
ARG_SETUP_MACHINE_ID,
ARG_FORCE,
ARG_DELETE_ROOT_PASSWORD,
ARG_WELCOME,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "root", required_argument, NULL, ARG_ROOT },
{ "image", required_argument, NULL, ARG_IMAGE },
{ "locale", required_argument, NULL, ARG_LOCALE },
{ "locale-messages", required_argument, NULL, ARG_LOCALE_MESSAGES },
{ "keymap", required_argument, NULL, ARG_KEYMAP },
@ -929,6 +1015,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "setup-machine-id", no_argument, NULL, ARG_SETUP_MACHINE_ID },
{ "force", no_argument, NULL, ARG_FORCE },
{ "delete-root-password", no_argument, NULL, ARG_DELETE_ROOT_PASSWORD },
{ "welcome", required_argument, NULL, ARG_WELCOME },
{}
};
@ -953,6 +1040,12 @@ static int parse_argv(int argc, char *argv[]) {
return r;
break;
case ARG_IMAGE:
r = parse_path_argument_and_warn(optarg, false, &arg_image);
if (r < 0)
return r;
break;
case ARG_LOCALE:
r = free_and_strdup(&arg_locale, optarg);
if (r < 0)
@ -1086,7 +1179,6 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_SETUP_MACHINE_ID:
r = sd_id128_randomize(&arg_machine_id);
if (r < 0)
return log_error_errno(r, "Failed to generate randomized machine ID: %m");
@ -1101,6 +1193,14 @@ static int parse_argv(int argc, char *argv[]) {
arg_delete_root_password = true;
break;
case ARG_WELCOME:
r = parse_boolean(optarg);
if (r < 0)
return log_error_errno(r, "Failed to parse --welcome= argument: %s", optarg);
arg_welcome = r;
break;
case '?':
return -EINVAL;
@ -1120,11 +1220,16 @@ static int parse_argv(int argc, char *argv[]) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"--delete-root-password cannot be combined with other root password options");
if (arg_image && arg_root)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
return 1;
}
static int run(int argc, char *argv[]) {
bool enabled;
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
_cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL;
int r;
r = parse_argv(argc, argv);
@ -1135,11 +1240,23 @@ static int run(int argc, char *argv[]) {
umask(0022);
r = proc_cmdline_get_bool("systemd.firstboot", &enabled);
if (!arg_root && !arg_image) {
bool enabled;
/* If we are called without --root=/--image= let's honour the systemd.firstboot kernel
* command line option, because we are called to provision the host with basic settings (as
* opposed to some other file system tree/image) */
r = proc_cmdline_get_bool("systemd.firstboot", &enabled);
if (r < 0)
return log_error_errno(r, "Failed to parse systemd.firstboot= kernel command line argument, ignoring: %m");
if (r > 0 && !enabled)
return 0; /* disabled */
}
r = setup_image(&unlink_dir, &loop_device, &decrypted_image);
if (r < 0)
return log_error_errno(r, "Failed to parse systemd.firstboot= kernel command line argument, ignoring: %m");
if (r > 0 && !enabled)
return 0; /* disabled */
return r;
r = process_locale();
if (r < 0)

View File

@ -314,6 +314,29 @@ static int write_requires_mounts_for(FILE *f, const char *opts) {
return 0;
}
static int write_extra_dependencies(FILE *f, const char *opts) {
int r;
assert(f);
if (opts) {
r = write_after(f, opts);
if (r < 0)
return r;
r = write_requires_after(f, opts);
if (r < 0)
return r;
r = write_before(f, opts);
if (r < 0)
return r;
r = write_requires_mounts_for(f, opts);
if (r < 0)
return r;
}
return 0;
}
static int add_mount(
const char *dest,
const char *what,
@ -406,20 +429,9 @@ static int add_mount(
SET_FLAG(flags, NOFAIL, true);
}
if (!(flags & AUTOMOUNT) && opts) {
r = write_after(f, opts);
if (r < 0)
return r;
r = write_requires_after(f, opts);
if (r < 0)
return r;
r = write_before(f, opts);
if (r < 0)
return r;
r = write_requires_mounts_for(f, opts);
if (r < 0)
return r;
}
r = write_extra_dependencies(f, opts);
if (r < 0)
return r;
if (passno != 0) {
r = generator_write_fsck_deps(f, dest, what, where, fstype);
@ -530,21 +542,6 @@ static int add_mount(
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
source);
if (opts) {
r = write_after(f, opts);
if (r < 0)
return r;
r = write_requires_after(f, opts);
if (r < 0)
return r;
r = write_before(f, opts);
if (r < 0)
return r;
r = write_requires_mounts_for(f, opts);
if (r < 0)
return r;
}
fprintf(f,
"\n"
"[Automount]\n"

View File

@ -852,8 +852,6 @@ int compress_stream_zstd(int fdf, int fdt, uint64_t max_bytes) {
size_t in_allocsize, out_allocsize;
size_t z;
uint64_t left = max_bytes, in_bytes = 0;
/* This can be used in the future to add uncompressed size to the header */
uint64_t in_totalsize = 0;
assert(fdf >= 0);
assert(fdt >= 0);
@ -867,11 +865,6 @@ int compress_stream_zstd(int fdf, int fdt, uint64_t max_bytes) {
if (!cctx || !out_buff || !in_buff)
return -ENOMEM;
if (in_totalsize) {
z = ZSTD_CCtx_setPledgedSrcSize(cctx, in_totalsize);
if (z)
log_debug("Failed to enable ZSTD input size, ignoring: %s", ZSTD_getErrorName(z));
}
z = ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1);
if (ZSTD_isError(z))
log_debug("Failed to enable ZSTD checksum, ignoring: %s", ZSTD_getErrorName(z));

View File

@ -315,7 +315,7 @@ static int server_read_dev_kmsg(Server *s) {
if (IN_SET(errno, EAGAIN, EINTR, EPIPE))
return 0;
return log_error_errno(errno, "Failed to read from kernel: %m");
return log_error_errno(errno, "Failed to read from /dev/kmsg: %m");
}
dev_kmsg_record(s, buffer, l);

View File

@ -327,7 +327,7 @@ int config_parse_arp_ip_target_address(
r = extract_first_word(&rvalue, &n, NULL, 0);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse Bond ARP ip target address, ignoring assignment: %s",
"Failed to parse Bond ARP IP target address, ignoring assignment: %s",
rvalue);
return 0;
}
@ -337,7 +337,7 @@ int config_parse_arp_ip_target_address(
r = in_addr_from_string(AF_INET, n, &ip);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Bond ARP ip target address is invalid, ignoring assignment: %s", n);
"Bond ARP IP target address is invalid, ignoring assignment: %s", n);
continue;
}
@ -347,7 +347,7 @@ int config_parse_arp_ip_target_address(
if (ordered_set_size(b->arp_ip_targets) >= NETDEV_BOND_ARP_TARGETS_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Too many ARP ip targets are specified. The maximum number is %d. Ignoring assignment: %s",
"Too many ARP IP targets are specified. The maximum number is %d. Ignoring assignment: %s",
NETDEV_BOND_ARP_TARGETS_MAX, n);
continue;
}
@ -355,10 +355,10 @@ int config_parse_arp_ip_target_address(
r = ordered_set_put(b->arp_ip_targets, UINT32_TO_PTR(ip.in.s_addr));
if (r == -EEXIST)
log_syntax(unit, LOG_WARNING, filename, line, r,
"Bond ARP ip target address is duplicated, ignoring assignment: %s", n);
"Bond ARP IP target address is duplicated, ignoring assignment: %s", n);
if (r < 0)
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to store bond ARP ip target address '%s', ignoring assignment: %m", n);
"Failed to store bond ARP IP target address '%s', ignoring assignment: %m", n);
}
}

View File

@ -1025,7 +1025,7 @@ static int dhcp_lease_ip_change(sd_dhcp_client *client, Link *link) {
link->dhcp_lease_old = TAKE_PTR(link->dhcp_lease);
/* On ip address change, to keep the connectability, we would like to assign new address and
/* On IP address change, to keep the connectability, we would like to assign new address and
* routes, and then release old lease. There are two possible success paths:
*
* 1. new address and routes are configured.
@ -1066,12 +1066,12 @@ static int dhcp_server_is_deny_listed(Link *link, sd_dhcp_client *client) {
r = sd_dhcp_lease_get_server_identifier(lease, &addr);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m");
return log_link_debug_errno(link, r, "Failed to get DHCP server IP address: %m");
if (set_contains(link->network->dhcp_deny_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
log_struct(LOG_DEBUG,
LOG_LINK_INTERFACE(link),
LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in deny-listed ip addresses, ignoring offer",
LOG_LINK_MESSAGE(link, "DHCPv4 IP '%u.%u.%u.%u' found in deny-listed IP addresses, ignoring offer",
ADDRESS_FMT_VAL(addr)));
return true;
}
@ -1094,12 +1094,12 @@ static int dhcp_server_is_allow_listed(Link *link, sd_dhcp_client *client) {
r = sd_dhcp_lease_get_server_identifier(lease, &addr);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m");
return log_link_debug_errno(link, r, "Failed to get DHCP server IP address: %m");
if (set_contains(link->network->dhcp_allow_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
log_struct(LOG_DEBUG,
LOG_LINK_INTERFACE(link),
LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in allow-listed ip addresses, accepting offer",
LOG_LINK_MESSAGE(link, "DHCPv4 IP '%u.%u.%u.%u' found in allow-listed IP addresses, accepting offer",
ADDRESS_FMT_VAL(addr)));
return true;
}
@ -1520,7 +1520,7 @@ int dhcp4_configure(Link *link) {
if (link->network->ip_service_type > 0) {
r = sd_dhcp_client_set_service_type(link->dhcp_client, link->network->ip_service_type);
if (r < 0)
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set ip service type: %m");
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set IP service type: %m");
}
if (link->network->dhcp_fallback_lease_lifetime > 0) {

View File

@ -506,17 +506,17 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl
if (rule->tos > 0) {
r = sd_rtnl_message_routing_policy_rule_set_tos(m, rule->tos);
if (r < 0)
return log_link_error_errno(link, r, "Could not set ip rule tos: %m");
return log_link_error_errno(link, r, "Could not set IP rule TOS: %m");
}
if (rule->table < 256) {
r = sd_rtnl_message_routing_policy_rule_set_table(m, rule->table);
if (r < 0)
return log_link_error_errno(link, r, "Could not set ip rule table: %m");
return log_link_error_errno(link, r, "Could not set IP rule table: %m");
} else {
r = sd_rtnl_message_routing_policy_rule_set_table(m, RT_TABLE_UNSPEC);
if (r < 0)
return log_link_error_errno(link, r, "Could not set ip rule table: %m");
return log_link_error_errno(link, r, "Could not set IP rule table: %m");
r = sd_netlink_message_append_u32(m, FRA_TABLE, rule->table);
if (r < 0)
@ -698,7 +698,7 @@ int config_parse_routing_policy_rule_tos(
r = safe_atou8(rvalue, &n->tos);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse RPDB rule tos, ignoring: %s", rvalue);
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse RPDB rule TOS, ignoring: %s", rvalue);
return 0;
}
@ -1372,7 +1372,7 @@ int routing_policy_load_rules(const char *state_file, Set **rules) {
} else if (streq(a, "tos")) {
r = safe_atou8(b, &rule->tos);
if (r < 0) {
log_error_errno(r, "Failed to parse RPDB rule tos, ignoring: %s", b);
log_error_errno(r, "Failed to parse RPDB rule TOS, ignoring: %s", b);
continue;
}
} else if (streq(a, "table")) {

View File

@ -204,7 +204,7 @@ static int unit_file_find_dirs(
type = unit_name_to_type(name);
if (type < 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Failed to to derive unit type from unit name: %s",
"Failed to derive unit type from unit name: %s",
name);
if (is_instance) {
@ -254,7 +254,7 @@ int unit_file_find_dropin_paths(
type = unit_name_to_type(n);
if (type < 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Failed to to derive unit type from unit name: %s", n);
"Failed to derive unit type from unit name: %s", n);
/* Special top level drop in for "<unit type>.<suffix>". Add this last as it's the most generic
* and should be able to be overridden by more specific drop-ins. */

View File

@ -1435,7 +1435,7 @@ enum nl80211_commands {
* rates as defined by IEEE 802.11 7.3.2.2 but without the length
* restriction (at most %NL80211_MAX_SUPP_RATES).
* @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station
* to, or the AP interface the station was originally added to to.
* to, or the AP interface the station was originally added to.
* @NL80211_ATTR_STA_INFO: information about a station, part of station info
* given for %NL80211_CMD_GET_STATION, nested attribute containing
* info as possible, see &enum nl80211_sta_info.

View File

@ -58,8 +58,8 @@ int umount_recursive(const char *prefix, int flags) {
if (!path_startswith(path, prefix))
continue;
if (umount2(path, flags) < 0) {
r = log_debug_errno(errno, "Failed to umount %s: %m", path);
if (umount2(path, flags | UMOUNT_NOFOLLOW) < 0) {
log_debug_errno(errno, "Failed to umount %s, ignoring: %m", path);
continue;
}
@ -70,7 +70,6 @@ int umount_recursive(const char *prefix, int flags) {
break;
}
} while (again);
return n;

View File

@ -3,7 +3,9 @@
#include <mntent.h>
#include <stdio.h>
#include <unistd.h>
#include "errno-util.h"
#include "macro.h"
/* 4MB for contents of regular files, 64k inodes for directories, symbolic links and device specials,
@ -53,3 +55,12 @@ int mount_option_mangle(
char **ret_remaining_options);
int mode_to_inaccessible_node(const char *runtime_dir, mode_t mode, char **dest);
/* Useful for usage with _cleanup_(), unmounts, removes a directory and frees the pointer */
static inline void umount_and_rmdir_and_free(char *p) {
PROTECT_ERRNO;
(void) umount_recursive(p, 0);
(void) rmdir(p);
free(p);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, umount_and_rmdir_and_free);

View File

@ -21,6 +21,7 @@
#include "env-util.h"
#include "fs-util.h"
#include "log.h"
#include "namespace-util.h"
#include "path-util.h"
#include "random-util.h"
#include "strv.h"
@ -137,10 +138,7 @@ bool have_namespaces(void) {
if (pid == 0) {
/* child */
if (unshare(CLONE_NEWNS) < 0)
_exit(EXIT_FAILURE);
if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0)
if (detach_mount_namespace() < 0)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);

View File

@ -71,7 +71,7 @@ static int write_hibernate_location_info(const HibernateLocation *hibernate_loca
return 0;
}
return log_debug_errno(errno, "/sys/power/resume_offset not writeable: %m");
return log_debug_errno(errno, "/sys/power/resume_offset not writable: %m");
}
xsprintf(offset_str, "%" PRIu64, hibernate_location->offset);

View File

@ -636,7 +636,7 @@ static void test_setpriority_closest(void) {
q = getpriority(PRIO_PROCESS, 0);
assert_se(errno == 0 && p == q);
/* It should also be possible to to set the nice level to one higher */
/* It should also be possible to set the nice level to one higher */
if (p < PRIO_MAX-1) {
assert_se(setpriority_closest(++p) > 0);
@ -645,7 +645,7 @@ static void test_setpriority_closest(void) {
assert_se(errno == 0 && p == q);
}
/* It should also be possible to to set the nice level to two higher */
/* It should also be possible to set the nice level to two higher */
if (p < PRIO_MAX-1) {
assert_se(setpriority_closest(++p) > 0);

View File

@ -17,6 +17,7 @@
#include "log.h"
#include "main-func.h"
#include "mkdir.h"
#include "namespace-util.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "string-util.h"
@ -36,15 +37,13 @@ static int fake_filesystems(void) {
{ "test/run", "/etc/udev/rules.d", "Failed to mount empty /etc/udev/rules.d", true },
{ "test/run", UDEVLIBEXECDIR "/rules.d", "Failed to mount empty " UDEVLIBEXECDIR "/rules.d", true },
};
unsigned i;
int r;
if (unshare(CLONE_NEWNS) < 0)
return log_error_errno(errno, "Failed to call unshare(): %m");
r = detach_mount_namespace();
if (r < 0)
return log_error_errno(r, "Failed to detach mount namespace: %m");
if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0)
return log_error_errno(errno, "Failed to mount / as private: %m");
for (i = 0; i < ELEMENTSOF(fakefss); i++)
for (size_t i = 0; i < ELEMENTSOF(fakefss); i++)
if (mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL) < 0) {
log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "%s: %m", fakefss[i].error);
if (!fakefss[i].ignore_mount_error)

View File

@ -67,7 +67,7 @@ static void test_xdg_desktop_parse(unsigned i, const char *s) {
case 0:
assert_se(streq(service->exec_string, "/bin/sleep 100"));
assert_se(strv_equal(service->only_show_in, STRV_MAKE("A", "B")));
assert_se(strv_equal(service->not_show_in, STRV_MAKE("C", "", "D\\;", "E")));
assert_se(strv_equal(service->not_show_in, STRV_MAKE("C", "D\\;", "E")));
assert_se(!service->hidden);
break;
case 1:
@ -81,14 +81,12 @@ static void test_xdg_desktop_parse(unsigned i, const char *s) {
}
int main(int argc, char *argv[]) {
size_t i;
test_setup_logging(LOG_DEBUG);
test_translate_name();
test_xdg_format_exec_start();
for (i = 0; i < ELEMENTSOF(xdg_desktop_file); i++)
for (size_t i = 0; i < ELEMENTSOF(xdg_desktop_file); i++)
test_xdg_desktop_parse(i, xdg_desktop_file[i]);
return 0;

View File

@ -182,6 +182,40 @@ static int xdg_config_parse_string(
return 0;
}
static int strv_strndup_unescape_and_push(
const char *unit,
const char *filename,
unsigned line,
char ***sv,
size_t *n_allocated,
size_t *n,
const char *start,
const char *end) {
if (end == start)
return 0;
_cleanup_free_ char *copy = NULL;
int r;
copy = strndup(start, end - start);
if (!copy)
return log_oom();
r = xdg_unescape_string(unit, filename, line, copy);
if (r < 0)
return r;
if (!greedy_realloc((void**) sv, n_allocated, *n + 2, sizeof(char*))) /* One extra for NULL */
return log_oom();
(*sv)[*n] = TAKE_PTR(copy);
(*sv)[*n + 1] = NULL;
(*n)++;
return 0;
}
static int xdg_config_parse_strv(
const char *unit,
const char *filename,
@ -194,9 +228,7 @@ static int xdg_config_parse_strv(
void *data,
void *userdata) {
char ***sv = data;
const char *start;
const char *end;
char ***ret_sv = data;
int r;
assert(filename);
@ -205,23 +237,25 @@ static int xdg_config_parse_strv(
assert(data);
/* XDG does not allow duplicate definitions. */
if (*sv) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Key %s was defined multiple times, ignoring.", lvalue);
if (*ret_sv) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Key %s was already defined, ignoring.", lvalue);
return 0;
}
*sv = strv_new(NULL);
if (!*sv)
size_t n = 0, n_allocated = 0;
_cleanup_strv_free_ char **sv = NULL;
if (!GREEDY_REALLOC0(sv, n_allocated, 1))
return log_oom();
/* We cannot use strv_split because it does not handle escaping correctly. */
start = rvalue;
const char *start = rvalue, *end;
for (end = start; *end; end++) {
if (*end == '\\') {
/* Move forward, and ensure it is a valid escape. */
end++;
if (strchr("sntr\\;", *end) == NULL) {
if (!strchr("sntr\\;", *end)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Undefined escape sequence \\%c.", *end);
return 0;
}
@ -229,29 +263,24 @@ static int xdg_config_parse_strv(
}
if (*end == ';') {
_cleanup_free_ char *copy = NULL;
copy = strndup(start, end - start);
if (!copy)
return log_oom();
r = xdg_unescape_string(unit, filename, line, copy);
r = strv_strndup_unescape_and_push(unit, filename, line,
&sv, &n_allocated, &n,
start, end);
if (r < 0)
return r;
r = strv_consume(sv, TAKE_PTR(copy));
if (r < 0)
return log_oom();
start = end + 1;
}
}
/* Any trailing entry should be ignored if it is empty. */
if (end > start) {
r = strv_extend(sv, start);
if (r < 0)
return log_oom();
}
/* Handle the trailing entry after the last separator */
r = strv_strndup_unescape_and_push(unit, filename, line,
&sv, &n_allocated, &n,
start, end);
if (r < 0)
return r;
*ret_sv = TAKE_PTR(sv);
return 0;
}

Binary file not shown.

Binary file not shown.