1
0
mirror of https://github.com/systemd/systemd synced 2025-10-05 03:34:46 +02:00

Compare commits

..

No commits in common. "2d8ce4c70114d9163be9ff45bdece1551a7036cc" and "43b4e3058c106e663bbd5413e7bd106e55d6fd79" have entirely different histories.

25 changed files with 264 additions and 379 deletions

58
NEWS
View File

@ -438,40 +438,36 @@ CHANGES WITH 248:
portable service image, useful for updating images on-the-fly.
Contributions from: Adam Nielsen, Adrian Vovk, AJ Jordan, Alan Perry,
Alastair Pharo, Alexander Batischev, Ali Abdallah, Andrew Balmos, Anita
Zhang, Annika Wickert, Ansgar Burchardt, Antonius Frie, Ardy, Arian van
Putten, Ariel Fermani, Arnaud T, A S Alam, Bastien Nocera, Benjamin
Berg, Benjamin Robin, Björn Daase, caoxia, Carlo Wood, Charles Lee,
ChopperRob, chri2, Christian Ehrhardt, Christian Hesse, Christopher
Obbard, clayton craft, corvusnix, cprn, d032747, Daan De Meyer, Daniele
Medri, Daniel Rusek, Dan Streetman, Darren Ng, David Edmundson, Deepak
Rawat, Devon Pringle, Dmitry Borodaenko, dropsignal, Einsler Lee, Endre
Szabo, Evgeny Vereshchagin, Fabian Affolter, Felipe Borges,
feliperodriguesfr, Felix Stupp, Florian Hülsmann, Florian Klink,
Florian Westphal, Franck Bui, Frantisek Sumsal, Gablegritule, Gaël
PORTAY, Gaurav, Giedrius Statkevičius, Greg Depoire--Ferrer, Gustavo
Costa, Hans de Goede, Hela Basa, heretoenhance, Iago López Galeiras,
igo95862, Ilya Dmitrichenko, Jameer Pathan, Jan Tojnar, Jiehong,
Jinyuan Si, Joerg Behrmann, John Slade, Jonathan G. Underwood, Jonathan
Alexander Batischev, Ali Abdallah, Andrew Balmos, Anita Zhang, Ansgar
Burchardt, Antonius Frie, Ardy, Arian van Putten, Ariel Fermani, Arnaud
T, A S Alam, Bastien Nocera, Benjamin Berg, Benjamin Robin, Björn
Daase, chri2, Christian Ehrhardt, Christian Hesse, Christopher Obbard,
clayton craft, corvusnix, cprn, d032747, Daan De Meyer, Daniele Medri,
Dan Streetman, Darren Ng, David Edmundson, Deepak Rawat, Devon Pringle,
Dmitry Borodaenko, dropsignal, Einsler Lee, Endre Szabo, Evgeny
Vereshchagin, Fabian Affolter, Felipe Borges, feliperodriguesfr, Felix
Stupp, Florian Hülsmann, Florian Klink, Florian Westphal, Franck Bui,
Frantisek Sumsal, Gablegritule, Gaël PORTAY, Gaurav, Giedrius
Statkevičius, Greg Depoire--Ferrer, Hans de Goede, heretoenhance, Iago
López Galeiras, igo95862, Ilya Dmitrichenko, Jameer Pathan, Jan Tojnar,
Jiehong, Jinyuan Si, John Slade, Jonathan G. Underwood, Jonathan
McDowell, Josh Triplett, Joshua Watt, Julia Cartwright, Julien Humbert,
Kairui Song, Karel Zak, Kevin P. Fleming, Khem Raj, Konomi, krissgjeng,
l4gfcm, Lajos Veres, Lennart Poettering, Luca Boccassi, Luca BRUNO,
Lucas Werkmeister, Luka Kudra, Luna Jernberg, Marc-André Lureau, Martin
Wilck, Matthias Klumpp, Matt Turner, Michael Marley, Michal Fabik,
Michał Kopeć, Michal Koutný, Michal Sekletár, Mike Gilbert, milovlad,
moson-mo, Nick, nihilix-melix, Oğuz Ersen, Ondrej Mosnacek, pali, Pavel
Hrdina, Pavel Sapezhko, Perry Yuan, Peter Hutterer, Pierre Dubouilh,
Piotr Drąg, Richard Laager, rnhmjoj, RussianNeuroMancer, Sebastiaan van
Stijn, Sergey Bugaev, shenyangyang4, simmon, Simonas Kazlauskas,
Slimane Selyan Amiri, Stefan Agner, Steve Ramage, Susant Sahani, Sven
Mueller, Tad Fisher, Takashi Iwai, Thomas Haller, Tom Shield, Topi
Miettinen, Torsten Hilbrich, Tyler Hicks, Ulrich Ölmann, Vincent
Pelletier, Vinnie Magro, Vito Caputo, Vlad, walbit-de, Weblate, Weblate
(bot), Whired Planck, wouter bolsterlee, X Ruoyao, Yuri Chornoivan, Yu
Watanabe, Zach Smith, Zbigniew Jędrzejewski-Szmek, Zmicer Turok, Дамјан
Георгиевски
l4gfcm, Lennart Poettering, Luca Boccassi, Luca BRUNO, Lucas
Werkmeister, Luka Kudra, Luna Jernberg, Marc-André Lureau, Matthias
Klumpp, Matt Turner, Michael Marley, Michal Fabik, Michał Kopeć, Michal
Sekletár, Mike Gilbert, milovlad, moson-mo, Nick, nihilix-melix, Oğuz
Ersen, Ondrej Mosnacek, pali, Pavel Hrdina, Pavel Sapezhko, Peter
Hutterer, Pierre Dubouilh, Piotr Drąg, Richard Laager, rnhmjoj,
RussianNeuroMancer, Sebastiaan van Stijn, Sergey Bugaev, shenyangyang4,
Simonas Kazlauskas, Stefan Agner, Steve Ramage, Susant Sahani, Sven
Mueller, Tad Fisher, Takashi Iwai, Thomas Haller, Topi Miettinen,
Torsten Hilbrich, Tyler Hicks, Ulrich Ölmann, Vinnie Magro, Vito
Caputo, Vlad, walbit-de, Weblate, Weblate (bot), Whired Planck, wouter
bolsterlee, Yuri Chornoivan, Yu Watanabe, Zach Smith, Zbigniew
Jędrzejewski-Szmek, Zmicer Turok, Дамјан Георгиевски
— Warsaw, 2021-03-11
— Warsaw, 2021-02-23
CHANGES WITH 247:

View File

@ -587,11 +587,11 @@ layout: default
time you need that please immediately undefine `basename()`, and add a
comment about it, so that no code ever ends up using the POSIX version!
- Never use `FILENAME_MAX`. Use `PATH_MAX` instead (for checking maximum size
of paths) and `NAME_MAX` (for checking maximum size of filenames).
`FILENAME_MAX` is not POSIX, and is a confusingly named alias for `PATH_MAX`
on Linux. Note the `NAME_MAX` does not include space for a trailing `NUL`,
but `PATH_MAX` does. UNIX FTW!
- Never use FILENAME_MAX. Use PATH_MAX instead (for checking maximum size of
paths) and NAME_MAX (for checking maximum size of filenames). FILENAME_MAX is
not POSIX, and is a confusingly named alias for PATH_MAX on Linux. Note the
NAME_MAX does not include space for a trailing NUL, but PATH_MAX does. UNIX
FTW!
## Committing to git

View File

@ -216,7 +216,7 @@
<listitem><para>Specifies the network interface to execute the query on. This may either be specified as numeric
interface index or as network interface string (e.g. <literal>en0</literal>). Note that this option has no
effect if system-wide DNS configuration (as configured in <filename>/etc/resolv.conf</filename> or
<filename>/etc/systemd/resolved.conf</filename>) in place of per-link configuration is used.</para></listitem>
<filename>/etc/systemd/resolve.conf</filename>) in place of per-link configuration is used.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -533,12 +533,14 @@ static int controller_is_v1_accessible(const char *root, const char *controller)
assert(controller);
dn = controller_to_dirname(controller);
/* If root if specified, we check that:
cpath = strjoina("/sys/fs/cgroup/", dn);
if (root)
/* Also check that:
* - possible subcgroup is created at root,
* - we can modify the hierarchy. */
* - we can modify the hierarchy.
* "Leak" cpath on stack */
cpath = strjoina(cpath, root, "/cgroup.procs");
cpath = strjoina("/sys/fs/cgroup/", dn, root, root ? "/cgroup.procs" : NULL);
if (laccess(cpath, root ? W_OK : F_OK) < 0)
return -errno;

View File

@ -69,14 +69,14 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
return -ENOMEM;
if (c == 0) {
if ((flags & EXTRACT_UNESCAPE_RELAX) &&
if ((flags & EXTRACT_CUNESCAPE_RELAX) &&
(quote == 0 || flags & EXTRACT_RELAX)) {
/* If we find an unquoted trailing backslash and we're in
* EXTRACT_UNESCAPE_RELAX mode, keep it verbatim in the
* EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the
* output.
*
* Unbalanced quotes will only be allowed in EXTRACT_RELAX
* mode, EXTRACT_UNESCAPE_RELAX mode does not allow them.
* mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them.
*/
s[sz++] = '\\';
goto finish_force_terminate;
@ -102,10 +102,10 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
else
sz += utf8_encode_unichar(s + sz, u);
} else if ((flags & EXTRACT_UNESCAPE_SEPARATORS) &&
(strchr(separators, **p) || **p == '\\'))
/* An escaped separator char or the escape char itself */
strchr(separators, **p))
/* An escaped separator char */
s[sz++] = c;
else if (flags & EXTRACT_UNESCAPE_RELAX) {
else if (flags & EXTRACT_CUNESCAPE_RELAX) {
s[sz++] = '\\';
s[sz++] = c;
} else
@ -196,7 +196,7 @@ int extract_first_word_and_warn(
const char *rvalue) {
/* Try to unquote it, if it fails, warn about it and try again
* but this time using EXTRACT_UNESCAPE_RELAX to keep the
* but this time using EXTRACT_CUNESCAPE_RELAX to keep the
* backslashes verbatim in invalid escape sequences. */
const char *save;
@ -207,11 +207,11 @@ int extract_first_word_and_warn(
if (r >= 0)
return r;
if (r == -EINVAL && !(flags & EXTRACT_UNESCAPE_RELAX)) {
if (r == -EINVAL && !(flags & EXTRACT_CUNESCAPE_RELAX)) {
/* Retry it with EXTRACT_UNESCAPE_RELAX. */
/* Retry it with EXTRACT_CUNESCAPE_RELAX. */
*p = save;
r = extract_first_word(p, ret, separators, flags|EXTRACT_UNESCAPE_RELAX);
r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX);
if (r >= 0) {
/* It worked this time, hence it must have been an invalid escape sequence. */
log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Ignoring unknown escape sequences: \"%s\"", *ret);

View File

@ -4,15 +4,13 @@
#include "macro.h"
typedef enum ExtractFlags {
EXTRACT_RELAX = 1 << 0, /* Allow unbalanced quote and eat up trailing backslash. */
EXTRACT_CUNESCAPE = 1 << 1, /* Unescape known escape sequences. */
EXTRACT_UNESCAPE_RELAX = 1 << 2, /* Allow and keep unknown escape sequences, allow and keep trailing backslash. */
EXTRACT_UNESCAPE_SEPARATORS = 1 << 3, /* Unescape separators (those specified, or whitespace by default). */
EXTRACT_UNQUOTE = 1 << 4, /* Remove quoting with "" and ''. */
EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 5, /* Don't treat multiple adjacent separators as one */
EXTRACT_RETAIN_ESCAPE = 1 << 6, /* Treat escape character '\' as any other character without special meaning */
/* Note that if no flags are specified, escaped escape characters will be silently stripped. */
EXTRACT_RELAX = 1 << 0,
EXTRACT_CUNESCAPE = 1 << 1,
EXTRACT_CUNESCAPE_RELAX = 1 << 2,
EXTRACT_UNESCAPE_SEPARATORS = 1 << 3,
EXTRACT_UNQUOTE = 1 << 4,
EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 5,
EXTRACT_RETAIN_ESCAPE = 1 << 6,
} ExtractFlags;
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);

View File

@ -142,7 +142,7 @@ static int vl_method_subscribe_managed_oom_cgroups(
/* We only take one subscriber for this method so return an error if there's already an existing one.
* This shouldn't happen since systemd-oomd is the only client of this method. */
if (FLAGS_SET(flags, VARLINK_METHOD_MORE) && m->managed_oom_varlink_request)
return varlink_error(link, VARLINK_ERROR_SUBSCRIPTION_TAKEN, NULL);
return varlink_error(m->managed_oom_varlink_request, VARLINK_ERROR_SUBSCRIPTION_TAKEN, NULL);
r = json_build(&arr, JSON_BUILD_EMPTY_ARRAY);
if (r < 0)
@ -188,7 +188,6 @@ static int vl_method_subscribe_managed_oom_cgroups(
if (!FLAGS_SET(flags, VARLINK_METHOD_MORE))
return varlink_reply(link, v);
assert(!m->managed_oom_varlink_request);
m->managed_oom_varlink_request = varlink_ref(link);
return varlink_notify(m->managed_oom_varlink_request, v);
}
@ -476,6 +475,7 @@ void manager_varlink_done(Manager *m) {
assert(m);
/* Send the final message if we still have a subscribe request open. */
if (m->managed_oom_varlink_request)
m->managed_oom_varlink_request = varlink_close_unref(m->managed_oom_varlink_request);
m->varlink_server = varlink_server_unref(m->varlink_server);

View File

@ -1019,7 +1019,7 @@ static void mount_enter_mounting(Mount *m) {
if (p) {
_cleanup_free_ char *opts = NULL;
r = fstab_filter_options(p->options, "nofail\0" "noauto\0" "auto\0", NULL, NULL, NULL, &opts);
r = fstab_filter_options(p->options, "nofail\0" "noauto\0" "auto\0", NULL, NULL, &opts);
if (r < 0)
goto fail;

View File

@ -301,9 +301,7 @@ static int create_disk(
netdev = fstab_test_option(options, "_netdev\0");
attach_in_initrd = fstab_test_option(options, "x-initrd.attach\0");
keyfile_can_timeout = fstab_filter_options(options,
"keyfile-timeout\0",
NULL, &keyfile_timeout_value, NULL, NULL);
keyfile_can_timeout = fstab_filter_options(options, "keyfile-timeout\0", NULL, &keyfile_timeout_value, NULL);
if (keyfile_can_timeout < 0)
return log_error_errno(keyfile_can_timeout, "Failed to parse keyfile-timeout= option value: %m");
@ -312,12 +310,11 @@ static int create_disk(
"header\0",
NULL,
&header_path,
NULL,
headerdev ? &filtered_header : NULL);
if (detached_header < 0)
return log_error_errno(detached_header, "Failed to parse header= option value: %m");
tmp = fstab_filter_options(options, "tmp\0", NULL, &tmp_fstype, NULL, NULL);
tmp = fstab_filter_options(options, "tmp\0", NULL, &tmp_fstype, NULL);
if (tmp < 0)
return log_error_errno(tmp, "Failed to parse tmp= option value: %m");
@ -605,7 +602,7 @@ static int filter_header_device(const char *options,
assert(ret_headerdev);
assert(ret_filtered_headerdev_options);
r = fstab_filter_options(options, "header\0", NULL, &headerspec, NULL, &filtered_headerspec);
r = fstab_filter_options(options, "header\0", NULL, &headerspec, &filtered_headerspec);
if (r < 0)
return log_error_errno(r, "Failed to parse header= option value: %m");

View File

@ -631,7 +631,7 @@ static int action_copy(DissectedImage *m, LoopDevice *d) {
if (r < 0)
return log_error_errno(r, "Failed to copy bytes from %s in mage '%s' to stdout: %m", arg_source, arg_image);
/* When we copy to stdout we don't copy any attributes (i.e. no access mode, no ownership, no xattr, no times) */
/* When we copy to stdou we don't copy any attributes (i.e. no access mode, no ownership, no xattr, no times) */
return 0;
}

View File

@ -200,7 +200,7 @@ static int write_timeout(
usec_t u;
int r;
r = fstab_filter_options(opts, filter, NULL, &timeout, NULL, NULL);
r = fstab_filter_options(opts, filter, NULL, &timeout, NULL);
if (r < 0)
return log_warning_errno(r, "Failed to parse options: %m");
if (r == 0)
@ -241,7 +241,7 @@ static int write_dependency(
assert(f);
assert(opts);
r = fstab_filter_options(opts, filter, NULL, NULL, &names, NULL);
r = fstab_extract_values(opts, filter, &names);
if (r < 0)
return log_warning_errno(r, "Failed to parse options: %m");
if (r == 0)
@ -274,17 +274,17 @@ static int write_dependency(
static int write_after(FILE *f, const char *opts) {
return write_dependency(f, opts,
"x-systemd.after\0", "After=%1$s\n");
"x-systemd.after", "After=%1$s\n");
}
static int write_requires_after(FILE *f, const char *opts) {
return write_dependency(f, opts,
"x-systemd.requires\0", "After=%1$s\nRequires=%1$s\n");
"x-systemd.requires", "After=%1$s\nRequires=%1$s\n");
}
static int write_before(FILE *f, const char *opts) {
return write_dependency(f, opts,
"x-systemd.before\0", "Before=%1$s\n");
"x-systemd.before", "Before=%1$s\n");
}
static int write_requires_mounts_for(FILE *f, const char *opts) {
@ -295,7 +295,7 @@ static int write_requires_mounts_for(FILE *f, const char *opts) {
assert(f);
assert(opts);
r = fstab_filter_options(opts, "x-systemd.requires-mounts-for\0", NULL, NULL, &paths, NULL);
r = fstab_extract_values(opts, "x-systemd.requires-mounts-for", &paths);
if (r < 0)
return log_warning_errno(r, "Failed to parse options: %m");
if (r == 0)
@ -376,11 +376,11 @@ static int add_mount(
mount_point_ignore(where))
return 0;
r = fstab_filter_options(opts, "x-systemd.wanted-by\0", NULL, NULL, &wanted_by, NULL);
r = fstab_extract_values(opts, "x-systemd.wanted-by", &wanted_by);
if (r < 0)
return r;
r = fstab_filter_options(opts, "x-systemd.required-by\0", NULL, NULL, &required_by, NULL);
r = fstab_extract_values(opts, "x-systemd.required-by", &required_by);
if (r < 0)
return r;
@ -611,11 +611,11 @@ static int parse_fstab(bool initrd) {
* /etc/fstab. So we canonicalize here. Note that we use CHASE_NONEXISTENT to handle the case
* where a symlink refers to another mount target; this works assuming the sub-mountpoint
* target is the final directory. */
k = chase_symlinks(where, initrd ? "/sysroot" : NULL,
r = chase_symlinks(where, initrd ? "/sysroot" : NULL,
CHASE_PREFIX_ROOT | CHASE_NONEXISTENT,
&canonical_where, NULL);
if (k < 0) /* If we can't canonicalize we continue on as if it wasn't a symlink */
log_debug_errno(k, "Failed to read symlink target for %s, ignoring: %m", where);
if (r < 0) /* If we can't canonicalize we continue on as if it wasn't a symlink */
log_debug_errno(r, "Failed to read symlink target for %s, ignoring: %m", where);
else if (streq(canonical_where, where)) /* If it was fully canonicalized, suppress the change */
canonical_where = mfree(canonical_where);
else

View File

@ -201,8 +201,6 @@ static void test_basic(bool with_pidfd) {
uint64_t event_now;
int64_t priority;
log_info("/* %s(pidfd=%s) */", __func__, yes_no(with_pidfd));
assert_se(setenv("SYSTEMD_PIDFD", yes_no(with_pidfd), 1) >= 0);
assert_se(pipe(a) >= 0);
@ -304,8 +302,6 @@ static void test_sd_event_now(void) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
uint64_t event_now;
log_info("/* %s */", __func__);
assert_se(sd_event_new(&e) >= 0);
assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0);
assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) > 0);
@ -343,8 +339,6 @@ static void test_rtqueue(void) {
sd_event_source *u = NULL, *v = NULL, *s = NULL;
sd_event *e = NULL;
log_info("/* %s */", __func__);
assert_se(sd_event_default(&e) >= 0);
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2, -1) >= 0);
@ -485,8 +479,6 @@ static void test_inotify(unsigned n_create_events) {
const char *q;
unsigned i;
log_info("/* %s(%u) */", __func__, n_create_events);
assert_se(sd_event_default(&e) >= 0);
assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0);
@ -553,8 +545,6 @@ static void test_pidfd(void) {
int pidfd;
pid_t pid, pid2;
log_info("/* %s */", __func__);
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
pid = fork();
@ -629,8 +619,6 @@ static void test_ratelimit(void) {
uint64_t interval;
unsigned count, burst;
log_info("/* %s */", __func__);
assert_se(sd_event_default(&e) >= 0);
assert_se(pipe2(p, O_CLOEXEC|O_NONBLOCK) >= 0);

View File

@ -170,7 +170,7 @@ static int run(int argc, char *argv[]) {
notify_msg = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
log_debug("systemd-oomd started%s.", arg_dry_run ? " in dry run mode" : "");
log_info("systemd-oomd starting%s!", arg_dry_run ? " in dry run mode" : "");
r = sd_event_loop(m->event);
if (r < 0)

View File

@ -2,7 +2,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
set -ex
[[ -e /dev/loop-control ]] || exit 77
[[ -f /dev/loop-control ]] || exit 77
repart=$1
test -x $repart

View File

@ -348,7 +348,7 @@ int config_parse_dnssd_txt(
int r;
r = extract_first_word(&rvalue, &word, NULL,
EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_RELAX);
EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX);
if (r == 0)
break;
if (r == -ENOMEM)

View File

@ -1344,28 +1344,20 @@ static int mount_partition(
}
if (directory) {
/* Automatically create missing mount points inside the image, if necessary. */
if (!FLAGS_SET(flags, DISSECT_IMAGE_READ_ONLY)) {
/* Automatically create missing mount points, if necessary. */
r = mkdir_p_root(where, directory, uid_shift, (gid_t) uid_shift, 0755);
if (r < 0 && r != -EROFS)
if (r < 0)
return r;
}
r = chase_symlinks(directory, where, CHASE_PREFIX_ROOT, &chased, NULL);
if (r < 0)
return r;
p = chased;
} else {
/* Create top-level mount if missing but only if this is asked for. This won't modify the
* image (as the branch above does) but the host hierarchy, and the created directory might
* survive our mount in the host hierarchy hence. */
if (FLAGS_SET(flags, DISSECT_IMAGE_MKDIR)) {
r = mkdir_p(where, 0755);
if (r < 0)
return r;
}
} else
p = where;
}
/* If requested, turn on discard support. */
if (fstype_can_discard(fstype) &&
@ -1390,6 +1382,12 @@ static int mount_partition(
if (!strextend_with_separator(&options, ",", m->mount_options))
return -ENOMEM;
if (FLAGS_SET(flags, DISSECT_IMAGE_MKDIR)) {
r = mkdir_p(p, 0755);
if (r < 0)
return r;
}
r = mount_nofollow_verbose(LOG_DEBUG, node, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), options);
if (r < 0)
return r;
@ -1422,6 +1420,10 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
return r;
}
/* Mask DISSECT_IMAGE_MKDIR for all subdirs: the idea is that only the top-level mount point is
* created if needed, but the image itself not modified. */
flags &= ~DISSECT_IMAGE_MKDIR;
if ((flags & DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY) == 0) {
/* For us mounting root always means mounting /usr as well */
r = mount_partition(m->partitions + PARTITION_USR, where, "/usr", uid_shift, flags);

View File

@ -86,7 +86,7 @@ typedef enum DissectImageFlags {
DISSECT_IMAGE_FSCK = 1 << 11, /* File system check the partition before mounting (no effect when combined with DISSECT_IMAGE_READ_ONLY) */
DISSECT_IMAGE_NO_PARTITION_TABLE = 1 << 12, /* Only recognize single file system images */
DISSECT_IMAGE_VERITY_SHARE = 1 << 13, /* When activating a verity device, reuse existing one if already open */
DISSECT_IMAGE_MKDIR = 1 << 14, /* Make top-level directory to mount right before mounting, if missing */
DISSECT_IMAGE_MKDIR = 1 << 14, /* Make directory to mount right before mounting, if missing */
} DissectImageFlags;
struct DissectedImage {

View File

@ -79,95 +79,34 @@ int fstab_is_mount_point(const char *mount) {
return false;
}
int fstab_filter_options(
const char *opts,
const char *names,
const char **ret_namefound,
char **ret_value,
char ***ret_values,
char **ret_filtered) {
int fstab_filter_options(const char *opts, const char *names,
const char **ret_namefound, char **ret_value, char **ret_filtered) {
const char *name, *namefound = NULL, *x;
_cleanup_strv_free_ char **stor = NULL, **values = NULL;
_cleanup_free_ char *value = NULL, **filtered = NULL;
_cleanup_strv_free_ char **stor = NULL;
_cleanup_free_ char *v = NULL, **strv = NULL;
int r;
assert(names && *names);
assert(!(ret_value && ret_values));
if (!opts)
goto answer;
/* Finds any options matching 'names', and returns:
* - the last matching option name in ret_namefound,
* - the last matching value in ret_value,
* - any matching values in ret_values,
* - the rest of the option string in ret_filtered.
*
* If !ret_value and !ret_values and !ret_filtered, this function is not allowed to fail.
*
* Returns negative on error, true if any matching options were found, false otherwise. */
/* If !ret_value and !ret_filtered, this function is not allowed to fail. */
if (ret_filtered || ret_value || ret_values) {
/* For backwards compatibility, we need to pass-through escape characters.
* The only ones we "consume" are the ones used as "\," or "\\". */
r = strv_split_full(&stor, opts, ",", EXTRACT_UNESCAPE_SEPARATORS | EXTRACT_UNESCAPE_RELAX);
if (r < 0)
return r;
filtered = memdup(stor, sizeof(char*) * (strv_length(stor) + 1));
if (!filtered)
return -ENOMEM;
char **t = filtered;
for (char **s = t; *s; s++) {
NULSTR_FOREACH(name, names) {
x = startswith(*s, name);
if (!x)
continue;
/* Match name, but when ret_values, only when followed by assignment. */
if (*x == '=' || (!ret_values && *x == '\0'))
goto found;
}
*t = *s;
t++;
continue;
found:
/* Keep the last occurrence found */
namefound = name;
if (ret_value || ret_values) {
assert(IN_SET(*x, '=', '\0'));
if (ret_value) {
r = free_and_strdup(&value, *x == '=' ? x + 1 : NULL);
if (r < 0)
return r;
} else if (*x) {
r = strv_extend(&values, x + 1);
if (r < 0)
return r;
}
}
}
*t = NULL;
} else
if (!ret_filtered) {
for (const char *word = opts;;) {
const char *end = word;
/* Look for a *non-escaped* comma separator. Only commas and backslashes can be
* escaped, so "\," and "\\" are the only valid escape sequences, and we can do a
* very simple test here. */
/* Look for an *non-escaped* comma separator. Only commas can be escaped, so "\," is
* the only valid escape sequence, so we can do a very simple test here. */
for (;;) {
end += strcspn(end, ",\\");
size_t n = strcspn(end, ",");
if (IN_SET(*end, ',', '\0'))
end += n;
if (n > 0 && end[-1] == '\\')
end++;
else
break;
assert(*end == '\\');
end ++; /* Skip the backslash */
if (*end != '\0')
end ++; /* Skip the escaped char, but watch out for a trailing commma */
}
NULSTR_FOREACH(name, names) {
@ -180,6 +119,17 @@ int fstab_filter_options(
x = word + strlen(name);
if (IN_SET(*x, '\0', '=', ',')) {
namefound = name;
if (ret_value) {
bool eq = *x == '=';
assert(eq || IN_SET(*x, ',', '\0'));
r = free_and_strndup(&v,
eq ? x + 1 : NULL,
eq ? end - x - 1 : 0);
if (r < 0)
return r;
}
break;
}
}
@ -189,6 +139,38 @@ int fstab_filter_options(
else
break;
}
} else {
r = strv_split_full(&stor, opts, ",", EXTRACT_DONT_COALESCE_SEPARATORS | EXTRACT_UNESCAPE_SEPARATORS);
if (r < 0)
return r;
strv = memdup(stor, sizeof(char*) * (strv_length(stor) + 1));
if (!strv)
return -ENOMEM;
char **t = strv;
for (char **s = strv; *s; s++) {
NULSTR_FOREACH(name, names) {
x = startswith(*s, name);
if (x && IN_SET(*x, '\0', '='))
goto found;
}
*t = *s;
t++;
continue;
found:
/* Keep the last occurrence found */
namefound = name;
if (ret_value) {
assert(IN_SET(*x, '=', '\0'));
r = free_and_strdup(&v, *x == '=' ? x + 1 : NULL);
if (r < 0)
return r;
}
}
*t = NULL;
}
answer:
if (ret_namefound)
@ -196,27 +178,54 @@ answer:
if (ret_filtered) {
char *f;
f = strv_join_full(filtered, ",", NULL, true);
f = strv_join_full(strv, ",", NULL, true);
if (!f)
return -ENOMEM;
*ret_filtered = f;
}
if (ret_value)
*ret_value = TAKE_PTR(value);
if (ret_values)
*ret_values = TAKE_PTR(values);
*ret_value = TAKE_PTR(v);
return !!namefound;
}
int fstab_extract_values(const char *opts, const char *name, char ***values) {
_cleanup_strv_free_ char **optsv = NULL, **res = NULL;
char **s;
assert(opts);
assert(name);
assert(values);
optsv = strv_split(opts, ",");
if (!optsv)
return -ENOMEM;
STRV_FOREACH(s, optsv) {
char *arg;
int r;
arg = startswith(*s, name);
if (!arg || *arg != '=')
continue;
r = strv_extend(&res, arg + 1);
if (r < 0)
return r;
}
*values = TAKE_PTR(res);
return !!*values;
}
int fstab_find_pri(const char *options, int *ret) {
_cleanup_free_ char *opt = NULL;
int r, pri;
assert(ret);
r = fstab_filter_options(options, "pri\0", NULL, &opt, NULL, NULL);
r = fstab_filter_options(options, "pri\0", NULL, &opt, NULL);
if (r < 0)
return r;
if (r == 0 || !opt)

View File

@ -10,16 +10,12 @@ bool fstab_is_extrinsic(const char *mount, const char *opts);
int fstab_is_mount_point(const char *mount);
int fstab_has_fstype(const char *fstype);
int fstab_filter_options(
const char *opts,
const char *names,
const char **ret_namefound,
char **ret_value,
char ***ret_values,
char **ret_filtered);
int fstab_filter_options(const char *opts, const char *names, const char **namefound, char **value, char **filtered);
int fstab_extract_values(const char *opts, const char *name, char ***values);
static inline bool fstab_test_option(const char *opts, const char *names) {
return !!fstab_filter_options(opts, names, NULL, NULL, NULL, NULL);
return !!fstab_filter_options(opts, names, NULL, NULL, NULL);
}
int fstab_find_pri(const char *options, int *ret);
@ -30,7 +26,7 @@ static inline bool fstab_test_yes_no_option(const char *opts, const char *yes_no
/* If first name given is last, return 1.
* If second name given is last or neither is found, return 0. */
assert_se(fstab_filter_options(opts, yes_no, &opt, NULL, NULL, NULL) >= 0);
assert_se(fstab_filter_options(opts, yes_no, &opt, NULL, NULL) >= 0);
return opt == yes_no;
}

View File

@ -215,13 +215,9 @@ int generator_write_timeouts(
r = fstab_filter_options(opts, "comment=systemd.device-timeout\0"
"x-systemd.device-timeout\0",
NULL, &timeout, NULL, filtered);
if (r < 0) {
log_warning_errno(r, "Failed to parse fstab options, ignoring: %m");
return 0;
}
if (r == 0)
return 0;
NULL, &timeout, filtered);
if (r <= 0)
return r;
r = parse_sec_fix_0(timeout, &u);
if (r < 0) {

View File

@ -1206,9 +1206,8 @@ int varlink_close(Varlink *v) {
varlink_set_state(v, VARLINK_DISCONNECTED);
/* Let's take a reference first, since varlink_detach_server() might drop the final ref from the
* disconnect callback, which would invalidate the pointer we are holding before we can call
* varlink_clear(). */
/* Let's take a reference first, since varlink_detach_server() might drop the final (dangling) ref
* which would destroy us before we can call varlink_clear() */
varlink_ref(v);
varlink_detach_server(v);
varlink_clear(v);
@ -1221,33 +1220,17 @@ Varlink* varlink_close_unref(Varlink *v) {
if (!v)
return NULL;
/* A reference is given to us to be destroyed. But when calling varlink_close(), a callback might
* also drop a reference. We allow this, and will hold a temporary reference to the object to make
* sure that the object still exists when control returns to us. If there's just one reference
* remaining after varlink_close(), even though there were at least two right before, we'll handle
* that gracefully instead of crashing.
*
* In other words, this call drops the donated reference, but if the internal call to varlink_close()
* dropped a reference to, we don't drop the reference afain. This allows the caller to say:
* global_object->varlink = varlink_close_unref(global_object->varlink);
* even though there is some callback which has access to global_object and may drop the reference
* stored in global_object->varlink. Without this step, the same code would have to be written as:
* Varlink *t = TAKE_PTR(global_object->varlink);
* varlink_close_unref(t);
*/
/* n_ref >= 1 */
varlink_ref(v); /* n_ref >= 2 */
varlink_close(v); /* n_ref >= 1 */
if (v->n_ref > 1)
v->n_ref--; /* n_ref >= 1 */
(void) varlink_close(v);
return varlink_unref(v);
}
Varlink* varlink_flush_close_unref(Varlink *v) {
if (v)
varlink_flush(v);
if (!v)
return NULL;
return varlink_close_unref(v);
(void) varlink_flush(v);
(void) varlink_close(v);
return varlink_unref(v);
}
static int varlink_enqueue_json(Varlink *v, JsonVariant *m) {

View File

@ -172,19 +172,19 @@ static void test_extract_first_word(void) {
assert_se(isempty(p));
p = original = "fooo\\";
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNESCAPE_RELAX) > 0);
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0);
assert_se(streq(t, "fooo\\"));
free(t);
assert_se(isempty(p));
p = original = "fooo\\";
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNESCAPE_RELAX|EXTRACT_RELAX) > 0);
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
assert_se(streq(t, "fooo\\"));
free(t);
assert_se(isempty(p));
p = original = "fooo\\";
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_RELAX) > 0);
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
assert_se(streq(t, "fooo\\"));
free(t);
assert_se(isempty(p));
@ -230,17 +230,17 @@ static void test_extract_first_word(void) {
assert_se(isempty(p));
p = original = "\"foo\\";
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_UNESCAPE_RELAX) == -EINVAL);
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE_RELAX) == -EINVAL);
assert_se(p == original + 5);
p = original = "\"foo\\";
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_UNESCAPE_RELAX|EXTRACT_RELAX) > 0);
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
assert_se(streq(t, "foo\\"));
free(t);
assert_se(isempty(p));
p = original = "\"foo\\";
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_RELAX|EXTRACT_RELAX) > 0);
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
assert_se(streq(t, "foo\\"));
free(t);
assert_se(isempty(p));
@ -252,13 +252,13 @@ static void test_extract_first_word(void) {
assert_se(p == original + 10);
p = original = "fooo\\ bar quux";
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNESCAPE_RELAX) > 0);
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0);
assert_se(streq(t, "fooo bar"));
free(t);
assert_se(p == original + 10);
p = original = "fooo\\ bar quux";
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNESCAPE_RELAX|EXTRACT_RELAX) > 0);
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
assert_se(streq(t, "fooo bar"));
free(t);
assert_se(p == original + 10);
@ -268,7 +268,7 @@ static void test_extract_first_word(void) {
assert_se(p == original + 5);
p = original = "fooo\\ bar quux";
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_RELAX) > 0);
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
assert_se(streq(t, "fooo\\ bar"));
free(t);
assert_se(p == original + 10);
@ -278,13 +278,13 @@ static void test_extract_first_word(void) {
assert_se(p == original + 1);
p = original = "\\w+@\\K[\\d.]+";
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_RELAX) > 0);
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
assert_se(streq(t, "\\w+@\\K[\\d.]+"));
free(t);
assert_se(isempty(p));
p = original = "\\w+\\b";
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_RELAX) > 0);
assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
assert_se(streq(t, "\\w+\b"));
free(t);
assert_se(isempty(p));
@ -344,39 +344,6 @@ static void test_extract_first_word(void) {
free(t);
assert_se(p == NULL);
p = "\\:";
assert_se(extract_first_word(&p, &t, ":", EXTRACT_UNESCAPE_SEPARATORS) == 1);
assert_se(streq(t, ":"));
free(t);
assert_se(p == NULL);
p = "a\\:b";
assert_se(extract_first_word(&p, &t, ":", EXTRACT_UNESCAPE_SEPARATORS) == 1);
assert_se(streq(t, "a:b"));
free(t);
assert_se(p == NULL);
p = "a\\ b:c";
assert_se(extract_first_word(&p, &t, WHITESPACE ":", EXTRACT_UNESCAPE_SEPARATORS) == 1);
assert_se(streq(t, "a b"));
free(t);
assert_se(extract_first_word(&p, &t, WHITESPACE ":", EXTRACT_UNESCAPE_SEPARATORS) == 1);
assert_se(streq(t, "c"));
free(t);
assert_se(p == NULL);
p = "a\\ b:c\\x";
assert_se(extract_first_word(&p, &t, ":", EXTRACT_UNESCAPE_SEPARATORS) == -EINVAL);
p = "a\\\\ b:c\\\\x";
assert_se(extract_first_word(&p, &t, ":", EXTRACT_UNESCAPE_SEPARATORS) == 1);
assert_se(streq(t, "a\\ b"));
free(t);
assert_se(extract_first_word(&p, &t, ":", EXTRACT_UNESCAPE_SEPARATORS) == 1);
assert_se(streq(t, "c\\x"));
free(t);
assert_se(p == NULL);
p = "\\:";
assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS) == 1);
assert_se(streq(t, ":"));
@ -398,18 +365,6 @@ static void test_extract_first_word(void) {
free(t);
assert_se(p == NULL);
p = "a\\ b:c\\x";
assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS) == -EINVAL);
p = "a\\\\ b:c\\\\x";
assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS) == 1);
assert_se(streq(t, "a\\ b"));
free(t);
assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS) == 1);
assert_se(streq(t, "c\\x"));
free(t);
assert_se(p == NULL);
p = "\\:";
assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE) == -EINVAL);

View File

@ -6,125 +6,94 @@
#include "fstab-util.h"
#include "log.h"
#include "string-util.h"
#include "strv.h"
/*
int fstab_filter_options(
const char *opts,
const char *names,
const char **ret_namefound,
const char **ret_value,
const char **ret_values,
char **ret_filtered);
int fstab_filter_options(const char *opts, const char *names,
const char **namefound, char **value, char **filtered);
*/
static void do_fstab_filter_options(const char *opts,
const char *remove,
int r_expected,
int r_values_expected,
const char *name_expected,
const char *value_expected,
const char *values_expected,
const char *filtered_expected) {
int r;
const char *name;
_cleanup_free_ char *value = NULL, *filtered = NULL, *joined = NULL;
_cleanup_strv_free_ char **values = NULL;
_cleanup_free_ char *value = NULL, *filtered = NULL;
/* test mode which returns the last value */
r = fstab_filter_options(opts, remove, &name, &value, NULL, &filtered);
log_info("1: \"%s\" → %d, \"%s\", \"%s\", \"%s\", expected %d, \"%s\", \"%s\", \"%s\"",
opts, r, strnull(name), value, filtered,
r = fstab_filter_options(opts, remove, &name, &value, &filtered);
log_info("\"%s\" → %d, \"%s\", \"%s\", \"%s\", expected %d, \"%s\", \"%s\", \"%s\"",
opts, r, name, value, filtered,
r_expected, name_expected, value_expected, filtered_expected ?: opts);
assert_se(r == r_expected);
assert_se(streq_ptr(name, name_expected));
assert_se(streq_ptr(value, value_expected));
assert_se(streq_ptr(filtered, filtered_expected ?: opts));
/* test mode which returns all the values */
r = fstab_filter_options(opts, remove, &name, NULL, &values, NULL);
assert_se(joined = strv_join(values, ":"));
log_info("2: \"%s\" → %d, \"%s\", \"%s\", expected %d, \"%s\", \"%s\"",
opts, r, strnull(name), joined,
r_values_expected, name_expected, values_expected);
assert_se(r == r_values_expected);
assert_se(streq_ptr(name, r_values_expected > 0 ? name_expected : NULL));
assert_se(streq_ptr(joined, values_expected));
/* also test the malloc-less mode */
r = fstab_filter_options(opts, remove, &name, NULL, NULL, NULL);
log_info("3: \"%s\" → %d, \"%s\", expected %d, \"%s\"\n-",
opts, r, strnull(name),
r = fstab_filter_options(opts, remove, &name, NULL, NULL);
log_info("\"%s\" → %d, \"%s\", expected %d, \"%s\"\n-",
opts, r, name,
r_expected, name_expected);
assert_se(r == r_expected);
assert_se(streq_ptr(name, name_expected));
}
static void test_fstab_filter_options(void) {
do_fstab_filter_options("opt=0", "opt\0x-opt\0", 1, 1, "opt", "0", "0", "");
do_fstab_filter_options("opt=0", "x-opt\0opt\0", 1, 1, "opt", "0", "0", "");
do_fstab_filter_options("opt", "opt\0x-opt\0", 1, 0, "opt", NULL, "", "");
do_fstab_filter_options("opt", "x-opt\0opt\0", 1, 0, "opt", NULL, "", "");
do_fstab_filter_options("x-opt", "x-opt\0opt\0", 1, 0, "x-opt", NULL, "", "");
do_fstab_filter_options("opt=0", "opt\0x-opt\0", 1, "opt", "0", "");
do_fstab_filter_options("opt=0", "x-opt\0opt\0", 1, "opt", "0", "");
do_fstab_filter_options("opt", "opt\0x-opt\0", 1, "opt", NULL, "");
do_fstab_filter_options("opt", "x-opt\0opt\0", 1, "opt", NULL, "");
do_fstab_filter_options("x-opt", "x-opt\0opt\0", 1, "x-opt", NULL, "");
do_fstab_filter_options("opt=0,other", "opt\0x-opt\0", 1, 1, "opt", "0", "0", "other");
do_fstab_filter_options("opt=0,other", "x-opt\0opt\0", 1, 1, "opt", "0", "0", "other");
do_fstab_filter_options("opt,other", "opt\0x-opt\0", 1, 0, "opt", NULL, "", "other");
do_fstab_filter_options("opt,other", "x-opt\0opt\0", 1, 0, "opt", NULL, "", "other");
do_fstab_filter_options("x-opt,other", "opt\0x-opt\0", 1, 0, "x-opt", NULL, "", "other");
do_fstab_filter_options("opt=0,other", "opt\0x-opt\0", 1, "opt", "0", "other");
do_fstab_filter_options("opt=0,other", "x-opt\0opt\0", 1, "opt", "0", "other");
do_fstab_filter_options("opt,other", "opt\0x-opt\0", 1, "opt", NULL, "other");
do_fstab_filter_options("opt,other", "x-opt\0opt\0", 1, "opt", NULL, "other");
do_fstab_filter_options("x-opt,other", "opt\0x-opt\0", 1, "x-opt", NULL, "other");
do_fstab_filter_options("opt=0\\,1,other", "opt\0x-opt\0", 1, 1, "opt", "0,1", "0,1", "other");
do_fstab_filter_options("opt=0,other,x-opt\\,foobar", "x-opt\0opt\0", 1, 1, "opt", "0", "0", "other,x-opt\\,foobar");
do_fstab_filter_options("opt,other,x-opt\\,part", "opt\0x-opt\0", 1, 0, "opt", NULL, "", "other,x-opt\\,part");
do_fstab_filter_options("opt,other,part\\,x-opt", "x-opt\0opt\0", 1, 0, "opt", NULL, "", "other,part\\,x-opt");
do_fstab_filter_options("opt,other\\,\\,\\,opt,x-part", "opt\0x-opt\0", 1, 0, "opt", NULL, "", "other\\,\\,\\,opt,x-part");
do_fstab_filter_options("opt=0\\,1,other", "opt\0x-opt\0", 1, "opt", "0,1", "other");
do_fstab_filter_options("opt=0,other,x-opt\\,foobar", "x-opt\0opt\0", 1, "opt", "0", "other,x-opt\\,foobar");
do_fstab_filter_options("opt,other,x-opt\\,part", "opt\0x-opt\0", 1, "opt", NULL, "other,x-opt\\,part");
do_fstab_filter_options("opt,other,part\\,x-opt", "x-opt\0opt\0", 1, "opt", NULL, "other,part\\,x-opt");
do_fstab_filter_options("opt,other\\,\\,\\,opt,x-part", "opt\0x-opt\0", 1, "opt", NULL, "other\\,\\,\\,opt,x-part");
do_fstab_filter_options("opto=0,other", "opt\0x-opt\0", 0, 0, NULL, NULL, "", NULL);
do_fstab_filter_options("opto,other", "opt\0x-opt\0", 0, 0, NULL, NULL, "", NULL);
do_fstab_filter_options("x-opto,other", "opt\0x-opt\0", 0, 0, NULL, NULL, "", NULL);
do_fstab_filter_options("opto=0,other", "opt\0x-opt\0", 0, NULL, NULL, NULL);
do_fstab_filter_options("opto,other", "opt\0x-opt\0", 0, NULL, NULL, NULL);
do_fstab_filter_options("x-opto,other", "opt\0x-opt\0", 0, NULL, NULL, NULL);
do_fstab_filter_options("first,opt=0", "opt\0x-opt\0", 1, 1, "opt", "0", "0", "first");
do_fstab_filter_options("first=1,opt=0", "opt\0x-opt\0", 1, 1, "opt", "0", "0", "first=1");
do_fstab_filter_options("first,opt=", "opt\0x-opt\0", 1, 1, "opt", "", "", "first");
do_fstab_filter_options("first=1,opt", "opt\0x-opt\0", 1, 0, "opt", NULL, "", "first=1");
do_fstab_filter_options("first=1,x-opt", "opt\0x-opt\0", 1, 0, "x-opt", NULL, "", "first=1");
do_fstab_filter_options("first,opt=0", "opt\0x-opt\0", 1, "opt", "0", "first");
do_fstab_filter_options("first=1,opt=0", "opt\0x-opt\0", 1, "opt", "0", "first=1");
do_fstab_filter_options("first,opt=", "opt\0x-opt\0", 1, "opt", "", "first");
do_fstab_filter_options("first=1,opt", "opt\0x-opt\0", 1, "opt", NULL, "first=1");
do_fstab_filter_options("first=1,x-opt", "opt\0x-opt\0", 1, "x-opt", NULL, "first=1");
do_fstab_filter_options("first,opt=0,last=1", "opt\0x-opt\0", 1, 1, "opt", "0", "0", "first,last=1");
do_fstab_filter_options("first=1,opt=0,last=2", "x-opt\0opt\0", 1, 1, "opt", "0", "0", "first=1,last=2");
do_fstab_filter_options("first,opt,last", "opt\0", 1, 0, "opt", NULL, "", "first,last");
do_fstab_filter_options("first=1,opt,last", "x-opt\0opt\0", 1, 0, "opt", NULL, "", "first=1,last");
do_fstab_filter_options("first=,opt,last", "opt\0noopt\0", 1, 0, "opt", NULL, "", "first=,last");
do_fstab_filter_options("first,opt=0,last=1", "opt\0x-opt\0", 1, "opt", "0", "first,last=1");
do_fstab_filter_options("first=1,opt=0,last=2", "x-opt\0opt\0", 1, "opt", "0", "first=1,last=2");
do_fstab_filter_options("first,opt,last", "opt\0", 1, "opt", NULL, "first,last");
do_fstab_filter_options("first=1,opt,last", "x-opt\0opt\0", 1, "opt", NULL, "first=1,last");
do_fstab_filter_options("first=,opt,last", "opt\0noopt\0", 1, "opt", NULL, "first=,last");
/* check repeated options */
do_fstab_filter_options("first,opt=0,noopt=1,last=1", "opt\0noopt\0", 1, 1, "noopt", "1", "0:1", "first,last=1");
do_fstab_filter_options("first=1,opt=0,last=2,opt=1", "opt\0", 1, 1, "opt", "1", "0:1", "first=1,last=2");
do_fstab_filter_options("x-opt=0,x-opt=1", "opt\0x-opt\0", 1, 1, "x-opt", "1", "0:1", "");
do_fstab_filter_options("opt=0,x-opt=1", "opt\0x-opt\0", 1, 1, "x-opt", "1", "0:1", "");
do_fstab_filter_options("opt=0,opt=1,opt=,opt=,opt=2", "opt\0noopt\0", 1, 1, "opt", "2", "0:1:::2", "");
do_fstab_filter_options("first,opt=0,noopt=1,last=1", "opt\0noopt\0", 1, "noopt", "1", "first,last=1");
do_fstab_filter_options("first=1,opt=0,last=2,opt=1", "opt\0", 1, "opt", "1", "first=1,last=2");
do_fstab_filter_options("x-opt=0,x-opt=1", "opt\0x-opt\0", 1, "x-opt", "1", "");
do_fstab_filter_options("opt=0,x-opt=1", "opt\0x-opt\0", 1, "x-opt", "1", "");
/* check that semicolons are not misinterpreted */
do_fstab_filter_options("opt=0;", "opt\0", 1, 1, "opt", "0;", "0;", "");
do_fstab_filter_options("opt;=0", "x-opt\0opt\0noopt\0x-noopt\0", 0, 0, NULL, NULL, "", NULL);
do_fstab_filter_options("opt;", "opt\0x-opt\0", 0, 0, NULL, NULL, "", NULL);
do_fstab_filter_options("opt=0;", "opt\0", 1, "opt", "0;", "");
do_fstab_filter_options("opt;=0", "x-opt\0opt\0noopt\0x-noopt\0", 0, NULL, NULL, NULL);
do_fstab_filter_options("opt;", "opt\0x-opt\0", 0, NULL, NULL, NULL);
/* check that spaces are not misinterpreted */
do_fstab_filter_options("opt=0 ", "opt\0", 1, 1, "opt", "0 ", "0 ", "");
do_fstab_filter_options("opt =0", "x-opt\0opt\0noopt\0x-noopt\0", 0, 0, NULL, NULL, "", NULL);
do_fstab_filter_options(" opt ", "opt\0x-opt\0", 0, 0, NULL, NULL, "", NULL);
do_fstab_filter_options("opt=0 ", "opt\0", 1, "opt", "0 ", "");
do_fstab_filter_options("opt =0", "x-opt\0opt\0noopt\0x-noopt\0", 0, NULL, NULL, NULL);
do_fstab_filter_options(" opt ", "opt\0x-opt\0", 0, NULL, NULL, NULL);
/* check function with NULL args */
do_fstab_filter_options(NULL, "opt\0", 0, 0, NULL, NULL, "", "");
do_fstab_filter_options("", "opt\0", 0, 0, NULL, NULL, "", "");
/* unnecessary comma separators */
do_fstab_filter_options("opt=x,,,,", "opt\0", 1, 1, "opt", "x", "x", "");
do_fstab_filter_options(",,,opt=x,,,,", "opt\0", 1, 1, "opt", "x", "x", "");
/* escaped characters */
do_fstab_filter_options("opt1=\\\\,opt2=\\xff", "opt1\0", 1, 1, "opt1", "\\", "\\", "opt2=\\xff");
do_fstab_filter_options("opt1=\\\\,opt2=\\xff", "opt2\0", 1, 1, "opt2", "\\xff", "\\xff", "opt1=\\");
/* check function will NULL args */
do_fstab_filter_options(NULL, "opt\0", 0, NULL, NULL, "");
do_fstab_filter_options("", "opt\0", 0, NULL, NULL, "");
}
static void test_fstab_find_pri(void) {

View File

@ -345,12 +345,6 @@ static void test_strjoina(void) {
actual = strjoina("foo", NULL, "bar");
assert_se(streq(actual, "foo"));
actual = strjoina("/sys/fs/cgroup/", "dn", "/a/b/c", "/cgroup.procs");
assert_se(streq(actual, "/sys/fs/cgroup/dn/a/b/c/cgroup.procs"));
actual = strjoina("/sys/fs/cgroup/", "dn", NULL, NULL);
assert_se(streq(actual, "/sys/fs/cgroup/dn"));
}
static void test_strjoin(void) {

View File

@ -333,12 +333,12 @@ static void test_strv_split(void) {
l = strv_free_erase(l);
assert_se(strv_split_full(&l, " 'one' \" two\t three \"' four five", NULL,
EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_UNESCAPE_RELAX) == 2);
EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_CUNESCAPE_RELAX) == 2);
assert_se(strv_equal(l, (char**) input_table_quoted_joined));
l = strv_free_erase(l);
assert_se(strv_split_full(&l, "\\", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_UNESCAPE_RELAX) == 1);
assert_se(strv_split_full(&l, "\\", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_CUNESCAPE_RELAX) == 1);
assert_se(strv_equal(l, STRV_MAKE("\\")));
}