Compare commits

..

No commits in common. "197db625a30850f4234eed5994bc0e6cd3e7242c" and "a1447e77a77b80db84cadc7b03f80f653f74118d" have entirely different histories.

69 changed files with 857 additions and 994 deletions

View File

@ -74,6 +74,9 @@ ForEachMacros:
- FOREACH_INOTIFY_EVENT - FOREACH_INOTIFY_EVENT
- FOREACH_STRING - FOREACH_STRING
- FOREACH_SUBSYSTEM - FOREACH_SUBSYSTEM
- _FOREACH_WORD
- FOREACH_WORD
- FOREACH_WORD_SEPARATOR
- HASHMAP_FOREACH - HASHMAP_FOREACH
- HASHMAP_FOREACH_IDX - HASHMAP_FOREACH_IDX
- HASHMAP_FOREACH_KEY - HASHMAP_FOREACH_KEY

View File

@ -199,11 +199,10 @@
<term><varname>HandleLidSwitch=</varname></term> <term><varname>HandleLidSwitch=</varname></term>
<term><varname>HandleLidSwitchExternalPower=</varname></term> <term><varname>HandleLidSwitchExternalPower=</varname></term>
<term><varname>HandleLidSwitchDocked=</varname></term> <term><varname>HandleLidSwitchDocked=</varname></term>
<term><varname>HandleRebootKey=</varname></term>
<listitem><para>Controls how logind shall handle the <listitem><para>Controls how logind shall handle the
system power, reboot and sleep keys and the lid switch to trigger system power and sleep keys and the lid switch to trigger
actions such as system power-off, reboot or suspend. Can be one of actions such as system power-off or suspend. Can be one of
<literal>ignore</literal>, <literal>ignore</literal>,
<literal>poweroff</literal>, <literal>poweroff</literal>,
<literal>reboot</literal>, <literal>reboot</literal>,
@ -220,8 +219,7 @@
in the respective event. Only input devices with the in the respective event. Only input devices with the
<literal>power-switch</literal> udev tag will be watched for <literal>power-switch</literal> udev tag will be watched for
key/lid switch events. <varname>HandlePowerKey=</varname> key/lid switch events. <varname>HandlePowerKey=</varname>
defaults to <literal>poweroff</literal>, <varname>HandleRebootKey=</varname> defaults to <literal>poweroff</literal>.
defaults to <literal>reboot</literal>.
<varname>HandleSuspendKey=</varname> and <varname>HandleSuspendKey=</varname> and
<varname>HandleLidSwitch=</varname> default to <varname>HandleLidSwitch=</varname> default to
<literal>suspend</literal>. <literal>suspend</literal>.
@ -242,8 +240,7 @@
<para>A different application may disable logind's handling of system power and <para>A different application may disable logind's handling of system power and
sleep keys and the lid switch by taking a low-level inhibitor lock sleep keys and the lid switch by taking a low-level inhibitor lock
(<literal>handle-power-key</literal>, <literal>handle-suspend-key</literal>, (<literal>handle-power-key</literal>, <literal>handle-suspend-key</literal>,
<literal>handle-hibernate-key</literal>, <literal>handle-lid-switch</literal>, <literal>handle-hibernate-key</literal>, <literal>handle-lid-switch</literal>).
<literal>handle-reboot-switch</literal>).
This is most commonly used by graphical desktop environments This is most commonly used by graphical desktop environments
to take over suspend and hibernation handling, and to use their own configuration to take over suspend and hibernation handling, and to use their own configuration
mechanisms. If a low-level inhibitor lock is taken, logind will not take any mechanisms. If a low-level inhibitor lock is taken, logind will not take any
@ -256,23 +253,20 @@
<term><varname>SuspendKeyIgnoreInhibited=</varname></term> <term><varname>SuspendKeyIgnoreInhibited=</varname></term>
<term><varname>HibernateKeyIgnoreInhibited=</varname></term> <term><varname>HibernateKeyIgnoreInhibited=</varname></term>
<term><varname>LidSwitchIgnoreInhibited=</varname></term> <term><varname>LidSwitchIgnoreInhibited=</varname></term>
<term><varname>RebootKeyIgnoreInhibited=</varname></term>
<listitem><para>Controls whether actions that <command>systemd-logind</command> <listitem><para>Controls whether actions that <command>systemd-logind</command>
takes when the power, reboot and sleep keys and the lid switch are triggered are subject takes when the power and sleep keys and the lid switch are triggered are subject
to high-level inhibitor locks ("shutdown", "reboot", "sleep", "idle"). Low level inhibitor to high-level inhibitor locks ("shutdown", "sleep", "idle"). Low level inhibitor
locks (<literal>handle-power-key</literal>, <literal>handle-suspend-key</literal>, locks (<literal>handle-power-key</literal>, <literal>handle-suspend-key</literal>,
<literal>handle-hibernate-key</literal>, <literal>handle-lid-switch</literal>, <literal>handle-hibernate-key</literal>, <literal>handle-lid-switch</literal>),
<literal>handle-reboot-key</literal>),
are always honored, irrespective of this setting.</para> are always honored, irrespective of this setting.</para>
<para>These settings take boolean arguments. If <literal>no</literal>, the <para>These settings take boolean arguments. If <literal>no</literal>, the
inhibitor locks taken by applications are respected. If <literal>yes</literal>, inhibitor locks taken by applications are respected. If <literal>yes</literal>,
"shutdown", "reboot" "sleep", and "idle" inhibitor locks are ignored. "shutdown", "sleep", and "idle" inhibitor locks are ignored.
<varname>PowerKeyIgnoreInhibited=</varname>, <varname>PowerKeyIgnoreInhibited=</varname>,
<varname>SuspendKeyIgnoreInhibited=</varname>, <varname>SuspendKeyIgnoreInhibited=</varname>, and
<varname>HibernateKeyIgnoreInhibited=</varname> and <varname>HibernateKeyIgnoreInhibited=</varname> default to <literal>no</literal>.
<varname>RebootKeyIgnoreInhibited=</varname> default to <literal>no</literal>.
<varname>LidSwitchIgnoreInhibited=</varname> defaults to <literal>yes</literal>. <varname>LidSwitchIgnoreInhibited=</varname> defaults to <literal>yes</literal>.
This means that when <command>systemd-logind</command> is handling events by This means that when <command>systemd-logind</command> is handling events by
itself (no low level inhibitor locks are taken by another application), the lid itself (no low level inhibitor locks are taken by another application), the lid

View File

@ -35,7 +35,7 @@
<funcprototype> <funcprototype>
<funcdef>int <function>sd_machine_get_ifindices</function></funcdef> <funcdef>int <function>sd_machine_get_ifindices</function></funcdef>
<paramdef>const char* <parameter>machine</parameter></paramdef> <paramdef>const char* <parameter>machine</parameter></paramdef>
<paramdef>int **<parameter>ret_ifindices</parameter></paramdef> <paramdef>int **<parameter>ifindices</parameter></paramdef>
</funcprototype> </funcprototype>
</funcsynopsis> </funcsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -53,22 +53,21 @@
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry> project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para> call after use.</para>
<para><function>sd_machine_get_ifindices()</function> may be used to determine the numeric indices of the <para><function>sd_machine_get_ifindices()</function> may be used
network interfaces on the host that are pointing towards the specified locally running virtual machine or to determine the numeric indices of the network interfaces on the
container. The vm or container must be registered with host that are pointing towards the specified locally running
virtual machine or container that is registered with
<citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>. <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
The output parameter <parameter>ret_ifindices</parameter> may be passed as <constant>NULL</constant> when The returned array needs to be freed with the libc <citerefentry
the output value is not needed. The returned array needs to be freed with the libc <citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry> call after call after use.</para>
use.</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
<title>Return Value</title> <title>Return Value</title>
<para>On success, these functions return a non-negative integer. <para>On success, these calls return 0 or a positive integer. On failure, these calls return a negative
<function>sd_machine_get_ifindices()</function> returns the number of the relevant network interfaces. errno-style error code.</para>
On failure, these calls return a negative errno-style error code.</para>
<refsect2> <refsect2>
<title>Errors</title> <title>Errors</title>

View File

@ -38,9 +38,9 @@
<funcprototype> <funcprototype>
<funcdef>int <function>sd_seat_get_sessions</function></funcdef> <funcdef>int <function>sd_seat_get_sessions</function></funcdef>
<paramdef>const char *<parameter>seat</parameter></paramdef> <paramdef>const char *<parameter>seat</parameter></paramdef>
<paramdef>char ***<parameter>ret_sessions</parameter></paramdef> <paramdef>char ***<parameter>sessions</parameter></paramdef>
<paramdef>uid_t **<parameter>ret_uids</parameter></paramdef> <paramdef>uid_t **<parameter>uid</parameter></paramdef>
<paramdef>unsigned int *<parameter>ret_n_uids</parameter></paramdef> <paramdef>unsigned int *<parameter>n_uids</parameter></paramdef>
</funcprototype> </funcprototype>
<funcprototype> <funcprototype>
@ -68,16 +68,21 @@
<citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry> <citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para> call after use.</para>
<para><function>sd_seat_get_sessions()</function> may be used to determine all sessions on the specified <para><function>sd_seat_get_sessions()</function> may be used to
seat. Returns two arrays, one (<constant>NULL</constant> terminated) with the session identifiers of the determine all sessions on the specified seat. Returns two arrays,
sessions and one with the user identifiers of the Unix users the sessions belong to. An additional one (<constant>NULL</constant> terminated) with the session
parameter may be used to return the number of entries in the latter array. This value is the same as the identifiers of the sessions and one with the user identifiers of
return value if the return value is nonnegative. The output parameters may be passed as the Unix users the sessions belong to. An additional parameter may
<constant>NULL</constant> in case these output values are not needed. The arrays and the strings be used to return the number of entries in the latter array. This
referenced by them need to be freed with the libc <citerefentry value is the same the return value, if the latter is nonnegative.
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry> call after The two arrays and the last parameter may be passed as
use. Note that instead of an empty array <constant>NULL</constant> may be returned and should be <constant>NULL</constant> in case these values need not to be
considered equivalent to an empty array.</para> determined. The arrays and the strings referenced by them need to
be freed with the libc
<citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use. Note that instead of an empty array
<constant>NULL</constant> may be returned and should be considered
equivalent to an empty array.</para>
<para><function>sd_seat_can_tty()</function> may be used to <para><function>sd_seat_can_tty()</function> may be used to
determine whether a specific seat provides TTY functionality, i.e. determine whether a specific seat provides TTY functionality, i.e.

View File

@ -652,13 +652,14 @@ int cg_remove_xattr(const char *controller, const char *path, const char *name)
return 0; return 0;
} }
int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) { int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
const char *fs, *controller_str; const char *fs, *controller_str;
int unified, r; int unified, r;
size_t cs = 0;
assert(path);
assert(pid >= 0); assert(pid >= 0);
assert(ret_path);
if (controller) { if (controller) {
if (!cg_controller_is_valid(controller)) if (!cg_controller_is_valid(controller))
@ -674,6 +675,8 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) {
controller_str = SYSTEMD_CGROUP_CONTROLLER_LEGACY; controller_str = SYSTEMD_CGROUP_CONTROLLER_LEGACY;
else else
controller_str = controller; controller_str = controller;
cs = strlen(controller_str);
} }
fs = procfs_file_alloca(pid, "cgroup"); fs = procfs_file_alloca(pid, "cgroup");
@ -685,13 +688,13 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) {
for (;;) { for (;;) {
_cleanup_free_ char *line = NULL; _cleanup_free_ char *line = NULL;
char *e; char *e, *p;
r = read_line(f, LONG_LINE_MAX, &line); r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0) if (r < 0)
return r; return r;
if (r == 0) if (r == 0)
return -ENODATA; break;
if (unified) { if (unified) {
e = startswith(line, "0:"); e = startswith(line, "0:");
@ -703,6 +706,9 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) {
continue; continue;
} else { } else {
char *l; char *l;
size_t k;
const char *word, *state;
bool found = false;
l = strchr(line, ':'); l = strchr(line, ':');
if (!l) if (!l)
@ -712,27 +718,31 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) {
e = strchr(l, ':'); e = strchr(l, ':');
if (!e) if (!e)
continue; continue;
*e = 0;
r = string_contains_word(l, ",", controller_str); *e = 0;
if (r < 0) FOREACH_WORD_SEPARATOR(word, k, l, ",", state)
return r; if (k == cs && memcmp(word, controller_str, cs) == 0) {
if (r == 0) found = true;
break;
}
if (!found)
continue; continue;
} }
char *path = strdup(e + 1); p = strdup(e + 1);
if (!path) if (!p)
return -ENOMEM; return -ENOMEM;
/* Truncate suffix indicating the process is a zombie */ /* Truncate suffix indicating the process is a zombie */
e = endswith(path, " (deleted)"); e = endswith(p, " (deleted)");
if (e) if (e)
*e = 0; *e = 0;
*ret_path = path; *path = p;
return 0; return 0;
} }
return -ENODATA;
} }
int cg_install_release_agent(const char *controller, const char *agent) { int cg_install_release_agent(const char *controller, const char *agent) {

View File

@ -687,7 +687,7 @@ char **replace_env_argv(char **argv, char **env) {
if (e) { if (e) {
int r; int r;
r = strv_split_full(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE); r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE);
if (r < 0) { if (r < 0) {
ret[k] = NULL; ret[k] = NULL;
strv_free(ret); strv_free(ret);

View File

@ -14,7 +14,6 @@
#include "log.h" #include "log.h"
#include "macro.h" #include "macro.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h"
#include "utf8.h" #include "utf8.h"
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) { int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {

View File

@ -538,9 +538,6 @@ static inline int __coverity_check_and_return__(int condition) {
(y) = (_t); \ (y) = (_t); \
} while (false) } while (false)
#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
/* Iterates through a specified list of pointers. Accepts NULL pointers, but uses (void*) -1 as internal marker for EOL. */ /* Iterates through a specified list of pointers. Accepts NULL pointers, but uses (void*) -1 as internal marker for EOL. */
#define FOREACH_POINTER(p, x, ...) \ #define FOREACH_POINTER(p, x, ...) \
for (typeof(p) *_l = (typeof(p)[]) { ({ p = x; }), ##__VA_ARGS__, (void*) -1 }; \ for (typeof(p) *_l = (typeof(p)[]) { ({ p = x; }), ##__VA_ARGS__, (void*) -1 }; \

View File

@ -617,62 +617,40 @@ bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b
return false; return false;
} }
int fd_set_sndbuf(int fd, size_t n, bool increase) { int fd_inc_sndbuf(int fd, size_t n) {
int r, value; int r, value;
socklen_t l = sizeof(value); socklen_t l = sizeof(value);
if (n > INT_MAX)
return -ERANGE;
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
return 0; return 0;
/* First, try to set the buffer size with SO_SNDBUF. */
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n);
if (r < 0)
return r;
/* SO_SNDBUF above may set to the kernel limit, instead of the requested size.
* So, we need to check the actual buffer size here. */
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;
/* If we have the privileges we will ignore the kernel limit. */ /* If we have the privileges we will ignore the kernel limit. */
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
if (r < 0) if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) {
return r; r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
if (r < 0)
return r;
}
return 1; return 1;
} }
int fd_set_rcvbuf(int fd, size_t n, bool increase) { int fd_inc_rcvbuf(int fd, size_t n) {
int r, value; int r, value;
socklen_t l = sizeof(value); socklen_t l = sizeof(value);
if (n > INT_MAX)
return -ERANGE;
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
return 0; return 0;
/* First, try to set the buffer size with SO_RCVBUF. */
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n);
if (r < 0)
return r;
/* SO_RCVBUF above may set to the kernel limit, instead of the requested size.
* So, we need to check the actual buffer size here. */
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;
/* If we have the privileges we will ignore the kernel limit. */ /* If we have the privileges we will ignore the kernel limit. */
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
if (r < 0) if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) {
return r; r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
if (r < 0)
return r;
}
return 1; return 1;
} }

View File

@ -118,14 +118,8 @@ int netlink_family_from_string(const char *s) _pure_;
bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b); bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b);
int fd_set_sndbuf(int fd, size_t n, bool increase); int fd_inc_sndbuf(int fd, size_t n);
static inline int fd_inc_sndbuf(int fd, size_t n) { int fd_inc_rcvbuf(int fd, size_t n);
return fd_set_sndbuf(fd, n, true);
}
int fd_set_rcvbuf(int fd, size_t n, bool increase);
static inline int fd_inc_rcvbuf(int fd, size_t n) {
return fd_set_rcvbuf(fd, n, true);
}
int ip_tos_to_string_alloc(int i, char **s); int ip_tos_to_string_alloc(int i, char **s);
int ip_tos_from_string(const char *s); int ip_tos_from_string(const char *s);

View File

@ -8,14 +8,12 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "escape.h" #include "escape.h"
#include "extract-word.h"
#include "fileio.h" #include "fileio.h"
#include "gunicode.h" #include "gunicode.h"
#include "locale-util.h" #include "locale-util.h"
#include "macro.h" #include "macro.h"
#include "memory-util.h" #include "memory-util.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h"
#include "terminal-util.h" #include "terminal-util.h"
#include "utf8.h" #include "utf8.h"
#include "util.h" #include "util.h"
@ -112,6 +110,83 @@ char* first_word(const char *s, const char *word) {
return (char*) p; return (char*) p;
} }
static size_t strcspn_escaped(const char *s, const char *reject) {
bool escaped = false;
int n;
for (n = 0; s[n] != '\0'; n++) {
if (escaped)
escaped = false;
else if (s[n] == '\\')
escaped = true;
else if (strchr(reject, s[n]))
break;
}
return n;
}
/* Split a string into words. */
const char* split(
const char **state,
size_t *l,
const char *separator,
SplitFlags flags) {
const char *current;
assert(state);
assert(l);
if (!separator)
separator = WHITESPACE;
current = *state;
if (*current == '\0') /* already at the end? */
return NULL;
current += strspn(current, separator); /* skip leading separators */
if (*current == '\0') { /* at the end now? */
*state = current;
return NULL;
}
if (FLAGS_SET(flags, SPLIT_QUOTES)) {
if (strchr(QUOTES, *current)) {
/* We are looking at a quote */
*l = strcspn_escaped(current + 1, CHAR_TO_STR(*current));
if (current[*l + 1] != *current ||
(current[*l + 2] != 0 && !strchr(separator, current[*l + 2]))) {
/* right quote missing or garbage at the end */
if (FLAGS_SET(flags, SPLIT_RELAX)) {
*state = current + *l + 1 + (current[*l + 1] != '\0');
return current + 1;
}
*state = current;
return NULL;
}
*state = current++ + *l + 2;
} else {
/* We are looking at a something that is not a quote */
*l = strcspn_escaped(current, separator);
if (current[*l] && !strchr(separator, current[*l]) && !FLAGS_SET(flags, SPLIT_RELAX)) {
/* unfinished escape */
*state = current;
return NULL;
}
*state = current + *l;
}
} else {
*l = strcspn(current, separator);
*state = current + *l;
}
return current;
}
char *strnappend(const char *s, const char *suffix, size_t b) { char *strnappend(const char *s, const char *suffix, size_t b) {
size_t a; size_t a;
char *r; char *r;
@ -1132,30 +1207,3 @@ int string_extract_line(const char *s, size_t i, char **ret) {
c++; c++;
} }
} }
int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word) {
/* In the default mode with no separators specified, we split on whitespace and
* don't coalesce separators. */
const ExtractFlags flags = separators ? EXTRACT_DONT_COALESCE_SEPARATORS : 0;
const char *found = NULL;
for (const char *p = string;;) {
_cleanup_free_ char *w = NULL;
int r;
r = extract_first_word(&p, &w, separators, flags);
if (r < 0)
return r;
if (r == 0)
break;
found = strv_find(words, w);
if (found)
break;
}
if (ret_word)
*ret_word = found;
return !!found;
}

View File

@ -108,6 +108,24 @@ char *endswith_no_case(const char *s, const char *postfix) _pure_;
char *first_word(const char *s, const char *word) _pure_; char *first_word(const char *s, const char *word) _pure_;
typedef enum SplitFlags {
SPLIT_QUOTES = 0x01 << 0,
SPLIT_RELAX = 0x01 << 1,
} SplitFlags;
/* Smelly. Do not use this anymore. Use extract_first_word() instead! */
const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags);
/* Similar, don't use this anymore */
#define FOREACH_WORD(word, length, s, state) \
_FOREACH_WORD(word, length, s, WHITESPACE, 0, state)
#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \
_FOREACH_WORD(word, length, s, separator, 0, state)
#define _FOREACH_WORD(word, length, s, separator, flags, state) \
for ((state) = (s), (word) = split(&(state), &(length), (separator), (flags)); (word); (word) = split(&(state), &(length), (separator), (flags)))
char *strnappend(const char *s, const char *suffix, size_t length); char *strnappend(const char *s, const char *suffix, size_t length);
char *strjoin_real(const char *x, ...) _sentinel_; char *strjoin_real(const char *x, ...) _sentinel_;
@ -262,8 +280,3 @@ char* string_erase(char *x);
int string_truncate_lines(const char *s, size_t n_lines, char **ret); int string_truncate_lines(const char *s, size_t n_lines, char **ret);
int string_extract_line(const char *s, size_t i, char **ret); int string_extract_line(const char *s, size_t i, char **ret);
int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word);
static inline int string_contains_word(const char *string, const char *separators, const char *word) {
return string_contains_word_strv(string, separators, STRV_MAKE(word), NULL);
}

View File

@ -256,6 +256,44 @@ int strv_extend_strv_concat(char ***a, char * const *b, const char *suffix) {
return 0; return 0;
} }
char **strv_split_full(const char *s, const char *separator, SplitFlags flags) {
const char *word, *state;
size_t l;
size_t n, i;
char **r;
assert(s);
if (!separator)
separator = WHITESPACE;
s += strspn(s, separator);
if (isempty(s))
return new0(char*, 1);
n = 0;
_FOREACH_WORD(word, l, s, separator, flags, state)
n++;
r = new(char*, n+1);
if (!r)
return NULL;
i = 0;
_FOREACH_WORD(word, l, s, separator, flags, state) {
r[i] = strndup(word, l);
if (!r[i]) {
strv_free(r);
return NULL;
}
i++;
}
r[i] = NULL;
return r;
}
char **strv_split_newlines(const char *s) { char **strv_split_newlines(const char *s) {
char **l; char **l;
size_t n; size_t n;
@ -279,7 +317,7 @@ char **strv_split_newlines(const char *s) {
return l; return l;
} }
int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags) { int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
_cleanup_strv_free_ char **l = NULL; _cleanup_strv_free_ char **l = NULL;
size_t n = 0, allocated = 0; size_t n = 0, allocated = 0;
int r; int r;

View File

@ -72,19 +72,13 @@ static inline bool strv_isempty(char * const *l) {
return !l || !*l; return !l || !*l;
} }
char **strv_split_full(const char *s, const char *separator, SplitFlags flags);
static inline char **strv_split(const char *s, const char *separator) {
return strv_split_full(s, separator, 0);
}
char **strv_split_newlines(const char *s); char **strv_split_newlines(const char *s);
int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags); int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
static inline char **strv_split(const char *s, const char *separators) {
char **ret;
int r;
r = strv_split_full(&ret, s, separators, 0);
if (r < 0)
return NULL;
return ret;
}
/* Given a string containing white-space separated tuples of words themselves separated by ':', /* Given a string containing white-space separated tuples of words themselves separated by ':',
* returns a vector of strings. If the second element in a tuple is missing, the corresponding * returns a vector of strings. If the second element in a tuple is missing, the corresponding
@ -129,6 +123,10 @@ bool strv_overlap(char * const *a, char * const *b) _pure_;
char **strv_sort(char **l); char **strv_sort(char **l);
void strv_print(char * const *l); void strv_print(char * const *l);
#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
#define strv_from_stdarg_alloca(first) \ #define strv_from_stdarg_alloca(first) \
({ \ ({ \
char **_l; \ char **_l; \

View File

@ -899,11 +899,11 @@ void emit_bpf_firewall_warning(Unit *u) {
if (!warned) { if (!warned) {
bool quiet = bpf_firewall_unsupported_reason == -EPERM && detect_container(); bool quiet = bpf_firewall_unsupported_reason == -EPERM && detect_container();
log_unit_full_errno(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason, log_unit_full(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason,
"unit configures an IP firewall, but %s.\n" "unit configures an IP firewall, but %s.\n"
"(This warning is only shown for the first unit using IP firewalling.)", "(This warning is only shown for the first unit using IP firewalling.)",
getuid() != 0 ? "not running as root" : getuid() != 0 ? "not running as root" :
"the local system does not support BPF/cgroup firewalling"); "the local system does not support BPF/cgroup firewalling");
warned = true; warned = true;
} }
} }

View File

@ -78,8 +78,8 @@ static int set_attribute_and_warn(Unit *u, const char *controller, const char *a
r = cg_set_attribute(controller, u->cgroup_path, attribute, value); r = cg_set_attribute(controller, u->cgroup_path, attribute, value);
if (r < 0) if (r < 0)
log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m", log_unit_full(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m",
strna(attribute), isempty(u->cgroup_path) ? "/" : u->cgroup_path, (int) strcspn(value, NEWLINE), value); strna(attribute), isempty(u->cgroup_path) ? "/" : u->cgroup_path, (int) strcspn(value, NEWLINE), value);
return r; return r;
} }
@ -724,7 +724,7 @@ static usec_t cgroup_cpu_adjust_period_and_log(Unit *u, usec_t period, usec_t qu
if (new_period != period) { if (new_period != period) {
char v[FORMAT_TIMESPAN_MAX]; char v[FORMAT_TIMESPAN_MAX];
log_unit_full(u, u->warned_clamping_cpu_quota_period ? LOG_DEBUG : LOG_WARNING, log_unit_full(u, u->warned_clamping_cpu_quota_period ? LOG_DEBUG : LOG_WARNING, 0,
"Clamping CPU interval for cpu.max: period is now %s", "Clamping CPU interval for cpu.max: period is now %s",
format_timespan(v, sizeof(v), new_period, 1)); format_timespan(v, sizeof(v), new_period, 1));
u->warned_clamping_cpu_quota_period = true; u->warned_clamping_cpu_quota_period = true;
@ -986,8 +986,8 @@ static int cgroup_apply_devices(Unit *u) {
else else
r = cg_set_attribute("devices", path, "devices.allow", "a"); r = cg_set_attribute("devices", path, "devices.allow", "a");
if (r < 0) if (r < 0)
log_unit_full_errno(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r, log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to reset devices.allow/devices.deny: %m"); "Failed to reset devices.allow/devices.deny: %m");
} }
bool allow_list_static = policy == CGROUP_DEVICE_POLICY_CLOSED || bool allow_list_static = policy == CGROUP_DEVICE_POLICY_CLOSED ||
@ -1351,8 +1351,8 @@ static void cgroup_context_apply(
else else
r = 0; r = 0;
if (r < 0) if (r < 0)
log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r, log_unit_full(u, LOG_LEVEL_CGROUP_WRITE(r), r,
"Failed to write to tasks limit sysctls: %m"); "Failed to write to tasks limit sysctls: %m");
} }
/* The attribute itself is not available on the host root cgroup, and in the container case we want to /* The attribute itself is not available on the host root cgroup, and in the container case we want to
@ -2435,7 +2435,7 @@ void unit_prune_cgroup(Unit *u) {
* the containing slice is stopped. So even if we failed now, this unit shouldn't assume * the containing slice is stopped. So even if we failed now, this unit shouldn't assume
* that the cgroup is still realized the next time it is started. Do not return early * that the cgroup is still realized the next time it is started. Do not return early
* on error, continue cleanup. */ * on error, continue cleanup. */
log_unit_full_errno(u, r == -EBUSY ? LOG_DEBUG : LOG_WARNING, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path); log_unit_full(u, r == -EBUSY ? LOG_DEBUG : LOG_WARNING, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path);
if (is_root_slice) if (is_root_slice)
return; return;

View File

@ -4255,16 +4255,8 @@ static int exec_child(
} }
} }
/* Ambient capabilities are cleared during setresuid() (in enforce_user()) even with /* This is done before enforce_user, but ambient set
* keep-caps set. * does not survive over setresuid() if keep_caps is not set. */
* To be able to raise the ambient capabilities after setresuid() they have to be
* added to the inherited set and keep caps has to be set (done in enforce_user()).
* After setresuid() the ambient capabilities can be raised as they are present in
* the permitted and inhertiable set. However it is possible that someone wants to
* set ambient capabilities without changing the user, so we also set the ambient
* capabilities here.
* The requested ambient capabilities are raised in the inheritable set if the
* second argument is true. */
if (!needs_ambient_hack) { if (!needs_ambient_hack) {
r = capability_ambient_set_apply(context->capability_ambient_set, true); r = capability_ambient_set_apply(context->capability_ambient_set, true);
if (r < 0) { if (r < 0) {
@ -4290,12 +4282,21 @@ static int exec_child(
if (!needs_ambient_hack && if (!needs_ambient_hack &&
context->capability_ambient_set != 0) { context->capability_ambient_set != 0) {
/* Raise the ambient capabilities after user change. */ /* Fix the ambient capabilities after user change. */
r = capability_ambient_set_apply(context->capability_ambient_set, false); r = capability_ambient_set_apply(context->capability_ambient_set, false);
if (r < 0) { if (r < 0) {
*exit_status = EXIT_CAPABILITIES; *exit_status = EXIT_CAPABILITIES;
return log_unit_error_errno(unit, r, "Failed to apply ambient capabilities (after UID change): %m"); return log_unit_error_errno(unit, r, "Failed to apply ambient capabilities (after UID change): %m");
} }
/* If we were asked to change user and ambient capabilities
* were requested, we had to add keep-caps to the securebits
* so that we would maintain the inherited capability set
* through the setresuid(). Make sure that the bit is added
* also to the context secure_bits so that we don't try to
* drop the bit away next. */
secure_bits |= 1<<SECURE_KEEP_CAPS;
} }
} }
} }

View File

@ -4438,13 +4438,15 @@ int config_parse_set_status(
void *data, void *data,
void *userdata) { void *userdata) {
ExitStatusSet *status_set = data; size_t l;
const char *word, *state;
int r; int r;
ExitStatusSet *status_set = data;
assert(filename); assert(filename);
assert(lvalue); assert(lvalue);
assert(rvalue); assert(rvalue);
assert(status_set); assert(data);
/* Empty assignment resets the list */ /* Empty assignment resets the list */
if (isempty(rvalue)) { if (isempty(rvalue)) {
@ -4452,26 +4454,25 @@ int config_parse_set_status(
return 0; return 0;
} }
for (const char *p = rvalue;;) { FOREACH_WORD(word, l, rvalue, state) {
_cleanup_free_ char *word = NULL; _cleanup_free_ char *temp;
Bitmap *bitmap; Bitmap *bitmap;
r = extract_first_word(&p, &word, NULL, 0); temp = strndup(word, l);
if (r < 0) if (!temp)
return log_error_errno(r, "Failed to parse %s: %m", lvalue); return log_oom();
if (r == 0)
return 0;
/* We need to call exit_status_from_string() first, because we want /* We need to call exit_status_from_string() first, because we want
* to parse numbers as exit statuses, not signals. */ * to parse numbers as exit statuses, not signals. */
r = exit_status_from_string(word); r = exit_status_from_string(temp);
if (r >= 0) { if (r >= 0) {
assert(r >= 0 && r < 256); assert(r >= 0 && r < 256);
bitmap = &status_set->status; bitmap = &status_set->status;
} else { } else {
r = signal_from_string(word); r = signal_from_string(temp);
if (r < 0) {
if (r <= 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, log_syntax(unit, LOG_ERR, filename, line, 0,
"Failed to parse value, ignoring: %s", word); "Failed to parse value, ignoring: %s", word);
continue; continue;
@ -4483,6 +4484,10 @@ int config_parse_set_status(
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to set signal or status %s: %m", word); return log_error_errno(r, "Failed to set signal or status %s: %m", word);
} }
if (!isempty(state))
log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
return 0;
} }
int config_parse_namespace_path_strv( int config_parse_namespace_path_strv(

View File

@ -918,17 +918,17 @@ static int service_is_suitable_main_pid(Service *s, pid_t pid, int prio) {
* good */ * good */
if (pid == getpid_cached() || pid == 1) { if (pid == getpid_cached() || pid == 1) {
log_unit_full(UNIT(s), prio, "New main PID "PID_FMT" is the manager, refusing.", pid); log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" is the manager, refusing.", pid);
return -EPERM; return -EPERM;
} }
if (pid == s->control_pid) { if (pid == s->control_pid) {
log_unit_full(UNIT(s), prio, "New main PID "PID_FMT" is the control process, refusing.", pid); log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" is the control process, refusing.", pid);
return -EPERM; return -EPERM;
} }
if (!pid_is_alive(pid)) { if (!pid_is_alive(pid)) {
log_unit_full(UNIT(s), prio, "New main PID "PID_FMT" does not exist or is a zombie.", pid); log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" does not exist or is a zombie.", pid);
return -ESRCH; return -ESRCH;
} }
@ -958,16 +958,16 @@ static int service_load_pid_file(Service *s, bool may_warn) {
r = chase_symlinks(s->pid_file, NULL, CHASE_SAFE, NULL, &fd); r = chase_symlinks(s->pid_file, NULL, CHASE_SAFE, NULL, &fd);
if (r == -ENOLINK) { if (r == -ENOLINK) {
log_unit_debug_errno(UNIT(s), r, log_unit_full(UNIT(s), LOG_DEBUG, r,
"Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file); "Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file);
questionable_pid_file = true; questionable_pid_file = true;
r = chase_symlinks(s->pid_file, NULL, 0, NULL, &fd); r = chase_symlinks(s->pid_file, NULL, 0, NULL, &fd);
} }
if (r < 0) if (r < 0)
return log_unit_full_errno(UNIT(s), prio, fd, return log_unit_full(UNIT(s), prio, fd,
"Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state));
/* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd /* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd
* chase_symlinks() returned us into a proper fd first. */ * chase_symlinks() returned us into a proper fd first. */
@ -980,7 +980,7 @@ static int service_load_pid_file(Service *s, bool may_warn) {
r = parse_pid(k, &pid); r = parse_pid(k, &pid);
if (r < 0) if (r < 0)
return log_unit_full_errno(UNIT(s), prio, r, "Failed to parse PID from file %s: %m", s->pid_file); return log_unit_full(UNIT(s), prio, r, "Failed to parse PID from file %s: %m", s->pid_file);
if (s->main_pid_known && pid == s->main_pid) if (s->main_pid_known && pid == s->main_pid)
return 0; return 0;

View File

@ -381,10 +381,8 @@ static int slice_freezer_action(Unit *s, FreezerAction action) {
assert(s); assert(s);
assert(IN_SET(action, FREEZER_FREEZE, FREEZER_THAW)); assert(IN_SET(action, FREEZER_FREEZE, FREEZER_THAW));
if (!slice_freezer_action_supported_by_children(s)) { if (!slice_freezer_action_supported_by_children(s))
log_unit_warning(s, "Requested freezer operation is not supported by all children of the slice"); return log_unit_warning(s, "Requested freezer operation is not supported by all children of the slice");
return 0;
}
HASHMAP_FOREACH_KEY(v, member, s->dependencies[UNIT_BEFORE]) { HASHMAP_FOREACH_KEY(v, member, s->dependencies[UNIT_BEFORE]) {
if (UNIT_DEREF(member->slice) != s) if (UNIT_DEREF(member->slice) != s)

View File

@ -1058,15 +1058,20 @@ static void socket_apply_socket_options(Socket *s, int fd) {
} }
if (s->receive_buffer > 0) { if (s->receive_buffer > 0) {
r = fd_set_rcvbuf(fd, s->receive_buffer, false); /* We first try with SO_RCVBUFFORCE, in case we have the perms for that */
if (r < 0) if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, s->receive_buffer) < 0) {
log_unit_warning_errno(UNIT(s), r, "SO_RCVBUF/SO_RCVBUFFORCE failed: %m"); r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, s->receive_buffer);
if (r < 0)
log_unit_warning_errno(UNIT(s), r, "SO_RCVBUF failed: %m");
}
} }
if (s->send_buffer > 0) { if (s->send_buffer > 0) {
r = fd_set_sndbuf(fd, s->receive_buffer, false); if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, s->send_buffer) < 0) {
if (r < 0) r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, s->send_buffer);
log_unit_warning_errno(UNIT(s), r, "SO_SNDBUF/SO_SNDBUFFORCE failed: %m"); if (r < 0)
log_unit_warning_errno(UNIT(s), r, "SO_SNDBUF failed: %m");
}
} }
if (s->mark >= 0) { if (s->mark >= 0) {

View File

@ -284,8 +284,8 @@ static int swap_load_devnode(Swap *s) {
r = device_new_from_stat_rdev(&d, &st); r = device_new_from_stat_rdev(&d, &st);
if (r < 0) { if (r < 0) {
log_unit_full_errno(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, log_unit_full(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to allocate device for swap %s: %m", s->what); "Failed to allocate device for swap %s: %m", s->what);
return 0; return 0;
} }

View File

@ -998,9 +998,10 @@ int transaction_add_job_and_dependencies(
SET_FOREACH(dep, following) { SET_FOREACH(dep, following) {
r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, false, false, ignore_order, e); r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, false, false, ignore_order, e);
if (r < 0) { if (r < 0) {
log_unit_full_errno(dep, r == -ERFKILL ? LOG_INFO : LOG_WARNING, r, log_unit_full(dep,
"Cannot add dependency job, ignoring: %s", r == -ERFKILL ? LOG_INFO : LOG_WARNING,
bus_error_message(e, r)); r, "Cannot add dependency job, ignoring: %s",
bus_error_message(e, r));
sd_bus_error_free(e); sd_bus_error_free(e);
} }
} }
@ -1034,10 +1035,10 @@ int transaction_add_job_and_dependencies(
r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, ignore_order, e); r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, ignore_order, e);
if (r < 0) { if (r < 0) {
/* unit masked, job type not applicable and unit not found are not considered as errors. */ /* unit masked, job type not applicable and unit not found are not considered as errors. */
log_unit_full_errno(dep, log_unit_full(dep,
IN_SET(r, -ERFKILL, -EBADR, -ENOENT) ? LOG_DEBUG : LOG_WARNING, IN_SET(r, -ERFKILL, -EBADR, -ENOENT) ? LOG_DEBUG : LOG_WARNING,
r, "Cannot add dependency job, ignoring: %s", r, "Cannot add dependency job, ignoring: %s",
bus_error_message(e, r)); bus_error_message(e, r));
sd_bus_error_free(e); sd_bus_error_free(e);
} }
} }

View File

@ -896,7 +896,7 @@ int unit_thaw_vtable_common(Unit *u);
/* Macros which append UNIT= or USER_UNIT= to the message */ /* Macros which append UNIT= or USER_UNIT= to the message */
#define log_unit_full_errno(unit, level, error, ...) \ #define log_unit_full(unit, level, error, ...) \
({ \ ({ \
const Unit *_u = (unit); \ const Unit *_u = (unit); \
(log_get_max_level() < LOG_PRI(level)) ? -ERRNO_VALUE(error) : \ (log_get_max_level() < LOG_PRI(level)) ? -ERRNO_VALUE(error) : \
@ -904,19 +904,17 @@ int unit_thaw_vtable_common(Unit *u);
log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
}) })
#define log_unit_full(unit, level, ...) (void) log_unit_full_errno(unit, level, 0, __VA_ARGS__) #define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__)
#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, 0, ##__VA_ARGS__)
#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, 0, ##__VA_ARGS__)
#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, 0, ##__VA_ARGS__)
#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, 0, ##__VA_ARGS__)
#define log_unit_debug(unit, ...) log_unit_full_errno(unit, LOG_DEBUG, 0, __VA_ARGS__) #define log_unit_debug_errno(unit, error, ...) log_unit_full(unit, LOG_DEBUG, error, ##__VA_ARGS__)
#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, __VA_ARGS__) #define log_unit_info_errno(unit, error, ...) log_unit_full(unit, LOG_INFO, error, ##__VA_ARGS__)
#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, __VA_ARGS__) #define log_unit_notice_errno(unit, error, ...) log_unit_full(unit, LOG_NOTICE, error, ##__VA_ARGS__)
#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, __VA_ARGS__) #define log_unit_warning_errno(unit, error, ...) log_unit_full(unit, LOG_WARNING, error, ##__VA_ARGS__)
#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, __VA_ARGS__) #define log_unit_error_errno(unit, error, ...) log_unit_full(unit, LOG_ERR, error, ##__VA_ARGS__)
#define log_unit_debug_errno(unit, error, ...) log_unit_full_errno(unit, LOG_DEBUG, error, __VA_ARGS__)
#define log_unit_info_errno(unit, error, ...) log_unit_full_errno(unit, LOG_INFO, error, __VA_ARGS__)
#define log_unit_notice_errno(unit, error, ...) log_unit_full_errno(unit, LOG_NOTICE, error, __VA_ARGS__)
#define log_unit_warning_errno(unit, error, ...) log_unit_full_errno(unit, LOG_WARNING, error, __VA_ARGS__)
#define log_unit_error_errno(unit, error, ...) log_unit_full_errno(unit, LOG_ERR, error, __VA_ARGS__)
#define LOG_UNIT_MESSAGE(unit, fmt, ...) "MESSAGE=%s: " fmt, (unit)->id, ##__VA_ARGS__ #define LOG_UNIT_MESSAGE(unit, fmt, ...) "MESSAGE=%s: " fmt, (unit)->id, ##__VA_ARGS__
#define LOG_UNIT_ID(unit) (unit)->manager->unit_log_format_string, (unit)->id #define LOG_UNIT_ID(unit) (unit)->manager->unit_log_format_string, (unit)->id

View File

@ -288,19 +288,19 @@ static int parse_one_option(const char *option) {
} }
static int parse_options(const char *options) { static int parse_options(const char *options) {
const char *word, *state;
size_t l;
int r;
assert(options); assert(options);
for (;;) { FOREACH_WORD_SEPARATOR(word, l, options, ",", state) {
_cleanup_free_ char *word = NULL; _cleanup_free_ char *o;
int r;
r = extract_first_word(&options, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS); o = strndup(word, l);
if (r < 0) if (!o)
return log_debug_errno(r, "Failed to parse options: %m"); return -ENOMEM;
if (r == 0) r = parse_one_option(o);
break;
r = parse_one_option(word);
if (r < 0) if (r < 0)
return r; return r;
} }

View File

@ -541,33 +541,28 @@ static int help(void) {
} }
static int parse_flags(const char *flag_str, int flags) { static int parse_flags(const char *flag_str, int flags) {
for (;;) { const char *word, *state;
_cleanup_free_ char *word = NULL; size_t l;
int r;
r = extract_first_word(&flag_str, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS); FOREACH_WORD_SEPARATOR(word, l, flag_str, ",", state) {
if (r < 0) if (strneq("masked", word, l))
return r;
if (r == 0)
return flags;
if (streq(word, "masked"))
flags |= SHOW_MASKED; flags |= SHOW_MASKED;
else if (streq(word, "equivalent")) else if (strneq ("equivalent", word, l))
flags |= SHOW_EQUIVALENT; flags |= SHOW_EQUIVALENT;
else if (streq(word, "redirected")) else if (strneq("redirected", word, l))
flags |= SHOW_REDIRECTED; flags |= SHOW_REDIRECTED;
else if (streq(word, "overridden")) else if (strneq("overridden", word, l))
flags |= SHOW_OVERRIDDEN; flags |= SHOW_OVERRIDDEN;
else if (streq(word, "unchanged")) else if (strneq("unchanged", word, l))
flags |= SHOW_UNCHANGED; flags |= SHOW_UNCHANGED;
else if (streq(word, "extended")) else if (strneq("extended", word, l))
flags |= SHOW_EXTENDED; flags |= SHOW_EXTENDED;
else if (streq(word, "default")) else if (strneq("default", word, l))
flags |= SHOW_DEFAULTS; flags |= SHOW_DEFAULTS;
else else
return -EINVAL; return -EINVAL;
} }
return flags;
} }
static int parse_argv(int argc, char *argv[]) { static int parse_argv(int argc, char *argv[]) {

View File

@ -99,85 +99,89 @@ static int verify_tty(const char *name) {
return 0; return 0;
} }
static int run_container(void) {
_cleanup_free_ char *container_ttys = NULL;
int r;
log_debug("Automatically adding console shell.");
r = add_symlink("console-getty.service", "console-getty.service");
if (r < 0)
return r;
/* When $container_ttys is set for PID 1, spawn gettys on all ptys named therein.
* Note that despite the variable name we only support ptys here. */
(void) getenv_for_pid(1, "container_ttys", &container_ttys);
for (const char *p = container_ttys;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to parse $container_ttys: %m");
if (r == 0)
return 0;
const char *tty = word;
/* First strip off /dev/ if it is specified */
tty = path_startswith(tty, "/dev/") ?: tty;
/* Then, make sure it's actually a pty */
tty = path_startswith(tty, "pts/");
if (!tty)
continue;
r = add_container_getty(tty);
if (r < 0)
return r;
}
}
static int run(const char *dest, const char *dest_early, const char *dest_late) { static int run(const char *dest, const char *dest_early, const char *dest_late) {
_cleanup_free_ char *active = NULL;
const char *j;
int r; int r;
assert_se(arg_dest = dest); assert_se(arg_dest = dest);
if (detect_container() > 0) if (detect_container() > 0) {
/* Add console shell and look at $container_ttys, but don't do add any _cleanup_free_ char *container_ttys = NULL;
* further magic if we are in a container. */
return run_container();
/* Automatically add in a serial getty on all active kernel consoles */ log_debug("Automatically adding console shell.");
_cleanup_free_ char *active = NULL;
(void) read_one_line_file("/sys/class/tty/console/active", &active);
for (const char *p = active;;) {
_cleanup_free_ char *tty = NULL;
r = extract_first_word(&p, &tty, NULL, 0); r = add_symlink("console-getty.service", "console-getty.service");
if (r < 0)
return log_error_errno(r, "Failed to parse /sys/class/tty/console/active: %m");
if (r == 0)
break;
/* We assume that gettys on virtual terminals are started via manual configuration and do
* this magic only for non-VC terminals. */
if (isempty(tty) || tty_is_vc(tty))
continue;
if (verify_tty(tty) < 0)
continue;
r = add_serial_getty(tty);
if (r < 0) if (r < 0)
return r; return r;
/* When $container_ttys is set for PID 1, spawn
* gettys on all ptys named therein. Note that despite
* the variable name we only support ptys here. */
r = getenv_for_pid(1, "container_ttys", &container_ttys);
if (r > 0) {
const char *word, *state;
size_t l;
FOREACH_WORD(word, l, container_ttys, state) {
const char *t;
char tty[l + 1];
memcpy(tty, word, l);
tty[l] = 0;
/* First strip off /dev/ if it is specified */
t = path_startswith(tty, "/dev/");
if (!t)
t = tty;
/* Then, make sure it's actually a pty */
t = path_startswith(t, "pts/");
if (!t)
continue;
r = add_container_getty(t);
if (r < 0)
return r;
}
}
/* Don't add any further magic if we are in a container */
return 0;
}
if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
const char *word, *state;
size_t l;
/* Automatically add in a serial getty on all active
* kernel consoles */
FOREACH_WORD(word, l, active, state) {
_cleanup_free_ char *tty = NULL;
tty = strndup(word, l);
if (!tty)
return log_oom();
/* We assume that gettys on virtual terminals are
* started via manual configuration and do this magic
* only for non-VC terminals. */
if (isempty(tty) || tty_is_vc(tty))
continue;
if (verify_tty(tty) < 0)
continue;
r = add_serial_getty(tty);
if (r < 0)
return r;
}
} }
/* Automatically add in a serial getty on the first /* Automatically add in a serial getty on the first
* virtualizer console */ * virtualizer console */
const char *j;
FOREACH_STRING(j, FOREACH_STRING(j,
"hvc0", "hvc0",
"xvc0", "xvc0",

View File

@ -124,7 +124,7 @@ static int spawn_getter(const char *getter) {
_cleanup_strv_free_ char **words = NULL; _cleanup_strv_free_ char **words = NULL;
assert(getter); assert(getter);
r = strv_split_full(&words, getter, WHITESPACE, EXTRACT_UNQUOTE); r = strv_split_extract(&words, getter, WHITESPACE, EXTRACT_UNQUOTE);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to split getter option: %m"); return log_error_errno(r, "Failed to split getter option: %m");

View File

@ -950,69 +950,74 @@ _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) {
} }
_public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) { _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
const char *word, *state;
size_t l;
unsigned long long seqnum, monotonic, realtime, xor_hash; unsigned long long seqnum, monotonic, realtime, xor_hash;
bool seqnum_id_set = false, bool
seqnum_set = false, seqnum_id_set = false,
boot_id_set = false, seqnum_set = false,
monotonic_set = false, boot_id_set = false,
realtime_set = false, monotonic_set = false,
xor_hash_set = false; realtime_set = false,
xor_hash_set = false;
sd_id128_t seqnum_id, boot_id; sd_id128_t seqnum_id, boot_id;
int r;
assert_return(j, -EINVAL); assert_return(j, -EINVAL);
assert_return(!journal_pid_changed(j), -ECHILD); assert_return(!journal_pid_changed(j), -ECHILD);
assert_return(!isempty(cursor), -EINVAL); assert_return(!isempty(cursor), -EINVAL);
for (const char *p = cursor;;) { FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) {
_cleanup_free_ char *word = NULL; char *item;
int k = 0;
r = extract_first_word(&p, &word, ";", EXTRACT_DONT_COALESCE_SEPARATORS); if (l < 2 || word[1] != '=')
if (r < 0)
return r;
if (r == 0)
break;
if (word[0] == '\0' || word[1] != '=')
return -EINVAL; return -EINVAL;
item = strndup(word, l);
if (!item)
return -ENOMEM;
switch (word[0]) { switch (word[0]) {
case 's': case 's':
seqnum_id_set = true; seqnum_id_set = true;
r = sd_id128_from_string(word + 2, &seqnum_id); k = sd_id128_from_string(item+2, &seqnum_id);
if (r < 0)
return r;
break; break;
case 'i': case 'i':
seqnum_set = true; seqnum_set = true;
if (sscanf(word + 2, "%llx", &seqnum) != 1) if (sscanf(item+2, "%llx", &seqnum) != 1)
return -EINVAL; k = -EINVAL;
break; break;
case 'b': case 'b':
boot_id_set = true; boot_id_set = true;
r = sd_id128_from_string(word + 2, &boot_id); k = sd_id128_from_string(item+2, &boot_id);
break; break;
case 'm': case 'm':
monotonic_set = true; monotonic_set = true;
if (sscanf(word + 2, "%llx", &monotonic) != 1) if (sscanf(item+2, "%llx", &monotonic) != 1)
return -EINVAL; k = -EINVAL;
break; break;
case 't': case 't':
realtime_set = true; realtime_set = true;
if (sscanf(word + 2, "%llx", &realtime) != 1) if (sscanf(item+2, "%llx", &realtime) != 1)
return -EINVAL; k = -EINVAL;
break; break;
case 'x': case 'x':
xor_hash_set = true; xor_hash_set = true;
if (sscanf(word + 2, "%llx", &xor_hash) != 1) if (sscanf(item+2, "%llx", &xor_hash) != 1)
return -EINVAL; k = -EINVAL;
break; break;
} }
free(item);
if (k < 0)
return k;
} }
if ((!seqnum_set || !seqnum_id_set) && if ((!seqnum_set || !seqnum_id_set) &&

View File

@ -101,7 +101,7 @@ _public_ int sd_listen_fds_with_names(int unset_environment, char ***names) {
e = getenv("LISTEN_FDNAMES"); e = getenv("LISTEN_FDNAMES");
if (e) { if (e) {
n_names = strv_split_full(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS); n_names = strv_split_extract(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (n_names < 0) { if (n_names < 0) {
unsetenv_all(unset_environment); unsetenv_all(unset_environment);
return n_names; return n_names;

View File

@ -91,9 +91,18 @@ int device_monitor_allow_unicast_sender(sd_device_monitor *m, sd_device_monitor
} }
_public_ int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, size_t size) { _public_ int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, size_t size) {
assert_return(m, -EINVAL); int r, n = (int) size;
return fd_set_rcvbuf(m->sock, size, false); assert_return(m, -EINVAL);
assert_return((size_t) n == size, -EINVAL);
if (setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, n) < 0) {
r = setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUF, n);
if (r < 0)
return r;
}
return 0;
} }
int device_monitor_disconnect(sd_device_monitor *m) { int device_monitor_disconnect(sd_device_monitor *m) {

View File

@ -316,33 +316,34 @@ static int device_amend(sd_device *device, const char *key, const char *value) {
if (r < 0) if (r < 0)
return log_device_debug_errno(device, r, "sd-device: Failed to set SEQNUM to '%s': %m", value); return log_device_debug_errno(device, r, "sd-device: Failed to set SEQNUM to '%s': %m", value);
} else if (streq(key, "DEVLINKS")) { } else if (streq(key, "DEVLINKS")) {
for (const char *p = value;;) { const char *word, *state;
_cleanup_free_ char *word = NULL; size_t l;
r = extract_first_word(&p, &word, NULL, 0); FOREACH_WORD(word, l, value, state) {
if (r < 0) char devlink[l + 1];
return r;
if (r == 0)
break;
r = device_add_devlink(device, word); strncpy(devlink, word, l);
devlink[l] = '\0';
r = device_add_devlink(device, devlink);
if (r < 0) if (r < 0)
return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", word); return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", devlink);
} }
} else if (STR_IN_SET(key, "TAGS", "CURRENT_TAGS")) { } else if (STR_IN_SET(key, "TAGS", "CURRENT_TAGS")) {
for (const char *p = value;;) { const char *word, *state;
_cleanup_free_ char *word = NULL; size_t l;
r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); FOREACH_WORD_SEPARATOR(word, l, value, ":", state) {
if (r < 0) char tag[l + 1];
return r;
if (r == 0)
break;
r = device_add_tag(device, word, streq(key, "CURRENT_TAGS")); (void) strncpy(tag, word, l);
tag[l] = '\0';
r = device_add_tag(device, tag, streq(key, "CURRENT_TAGS"));
if (r < 0) if (r < 0)
return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", word); return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", tag);
} }
} else { } else {
r = device_add_property_internal(device, key, value); r = device_add_property_internal(device, key, value);
if (r < 0) if (r < 0)

View File

@ -36,7 +36,7 @@
device; \ device; \
device = sd_device_enumerator_get_subsystem_next(enumerator)) device = sd_device_enumerator_get_subsystem_next(enumerator))
#define log_device_full_errno(device, level, error, ...) \ #define log_device_full(device, level, error, ...) \
({ \ ({ \
const char *_sysname = NULL; \ const char *_sysname = NULL; \
sd_device *_d = (device); \ sd_device *_d = (device); \
@ -46,19 +46,17 @@
(void) sd_device_get_sysname(_d, &_sysname); \ (void) sd_device_get_sysname(_d, &_sysname); \
log_object_internal(_level, _error, PROJECT_FILE, __LINE__, __func__, \ log_object_internal(_level, _error, PROJECT_FILE, __LINE__, __func__, \
_sysname ? "DEVICE=" : NULL, _sysname, \ _sysname ? "DEVICE=" : NULL, _sysname, \
NULL, NULL, __VA_ARGS__); \ NULL, NULL, ##__VA_ARGS__); \
}) })
#define log_device_full(device, level, ...) (void) log_device_full_errno(device, level, 0, __VA_ARGS__) #define log_device_debug(device, ...) log_device_full(device, LOG_DEBUG, 0, ##__VA_ARGS__)
#define log_device_info(device, ...) log_device_full(device, LOG_INFO, 0, ##__VA_ARGS__)
#define log_device_notice(device, ...) log_device_full(device, LOG_NOTICE, 0, ##__VA_ARGS__)
#define log_device_warning(device, ...) log_device_full(device, LOG_WARNING, 0, ##__VA_ARGS__)
#define log_device_error(device, ...) log_device_full(device, LOG_ERR, 0, ##__VA_ARGS__)
#define log_device_debug(device, ...) log_device_full_errno(device, LOG_DEBUG, 0, __VA_ARGS__) #define log_device_debug_errno(device, error, ...) log_device_full(device, LOG_DEBUG, error, ##__VA_ARGS__)
#define log_device_info(device, ...) log_device_full(device, LOG_INFO, __VA_ARGS__) #define log_device_info_errno(device, error, ...) log_device_full(device, LOG_INFO, error, ##__VA_ARGS__)
#define log_device_notice(device, ...) log_device_full(device, LOG_NOTICE, __VA_ARGS__) #define log_device_notice_errno(device, error, ...) log_device_full(device, LOG_NOTICE, error, ##__VA_ARGS__)
#define log_device_warning(device, ...) log_device_full(device, LOG_WARNING, __VA_ARGS__) #define log_device_warning_errno(device, error, ...) log_device_full(device, LOG_WARNING, error, ##__VA_ARGS__)
#define log_device_error(device, ...) log_device_full(device, LOG_ERR, __VA_ARGS__) #define log_device_error_errno(device, error, ...) log_device_full(device, LOG_ERR, error, ##__VA_ARGS__)
#define log_device_debug_errno(device, error, ...) log_device_full_errno(device, LOG_DEBUG, error, __VA_ARGS__)
#define log_device_info_errno(device, error, ...) log_device_full_errno(device, LOG_INFO, error, __VA_ARGS__)
#define log_device_notice_errno(device, error, ...) log_device_full_errno(device, LOG_NOTICE, error, __VA_ARGS__)
#define log_device_warning_errno(device, error, ...) log_device_full_errno(device, LOG_WARNING, error, __VA_ARGS__)
#define log_device_error_errno(device, error, ...) log_device_full_errno(device, LOG_ERR, error, __VA_ARGS__)

View File

@ -12,7 +12,6 @@
#include "dirent-util.h" #include "dirent-util.h"
#include "env-file.h" #include "env-file.h"
#include "escape.h" #include "escape.h"
#include "extract-word.h"
#include "fd-util.h" #include "fd-util.h"
#include "format-util.h" #include "format-util.h"
#include "fs-util.h" #include "fs-util.h"
@ -23,7 +22,6 @@
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "socket-util.h" #include "socket-util.h"
#include "stdio-util.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
#include "user-util.h" #include "user-util.h"
@ -333,29 +331,35 @@ static int file_of_seat(const char *seat, char **_p) {
} }
_public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) { _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
_cleanup_free_ char *filename = NULL, *content = NULL; _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
size_t l;
int r; int r;
const char *word, *variable, *state;
assert_return(uid_is_valid(uid), -EINVAL); assert_return(uid_is_valid(uid), -EINVAL);
r = file_of_seat(seat, &filename); r = file_of_seat(seat, &p);
if (r < 0) if (r < 0)
return r; return r;
r = parse_env_file(NULL, filename, variable = require_active ? "ACTIVE_UID" : "UIDS";
require_active ? "ACTIVE_UID" : "UIDS",
&content); r = parse_env_file(NULL, p, variable, &s);
if (r == -ENOENT) if (r == -ENOENT)
return 0; return 0;
if (r < 0) if (r < 0)
return r; return r;
if (isempty(content)) if (isempty(s))
return 0; return 0;
char t[DECIMAL_STR_MAX(uid_t)]; if (asprintf(&t, UID_FMT, uid) < 0)
xsprintf(t, UID_FMT, uid); return -ENOMEM;
return string_contains_word(content, ",", t); FOREACH_WORD(word, l, s, state)
if (strneq(t, word, l))
return 1;
return 0;
} }
static int uid_get_array(uid_t uid, const char *variable, char ***array) { static int uid_get_array(uid_t uid, const char *variable, char ***array) {
@ -378,7 +382,7 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) {
if (r < 0) if (r < 0)
return r; return r;
a = strv_split(s, NULL); a = strv_split(s, " ");
if (!a) if (!a)
return -ENOMEM; return -ENOMEM;
@ -650,70 +654,73 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
return 0; return 0;
} }
_public_ int sd_seat_get_sessions( _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
const char *seat, _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
char ***ret_sessions, _cleanup_strv_free_ char **a = NULL;
uid_t **ret_uids, _cleanup_free_ uid_t *b = NULL;
unsigned *ret_n_uids) { unsigned n = 0;
_cleanup_free_ char *fname = NULL, *session_line = NULL, *uid_line = NULL;
_cleanup_strv_free_ char **sessions = NULL;
_cleanup_free_ uid_t *uids = NULL;
unsigned n_sessions = 0;
int r; int r;
r = file_of_seat(seat, &fname); r = file_of_seat(seat, &p);
if (r < 0) if (r < 0)
return r; return r;
r = parse_env_file(NULL, fname, r = parse_env_file(NULL, p,
"SESSIONS", &session_line, "SESSIONS", &s,
"UIDS", &uid_line); "UIDS", &t);
if (r == -ENOENT) if (r == -ENOENT)
return -ENXIO; return -ENXIO;
if (r < 0) if (r < 0)
return r; return r;
if (session_line) { if (s) {
sessions = strv_split(session_line, NULL); a = strv_split(s, " ");
if (!sessions) if (!a)
return -ENOMEM; return -ENOMEM;
n_sessions = strv_length(sessions);
};
if (ret_uids && uid_line) {
uids = new(uid_t, n_sessions);
if (!uids)
return -ENOMEM;
size_t n = 0;
for (const char *p = uid_line;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r < 0)
return r;
if (r == 0)
break;
r = parse_uid(word, &uids[n++]);
if (r < 0)
return r;
}
if (n != n_sessions)
return -EUCLEAN;
} }
if (ret_sessions) if (uids && t) {
*ret_sessions = TAKE_PTR(sessions); const char *word, *state;
if (ret_uids) size_t l;
*ret_uids = TAKE_PTR(uids);
if (ret_n_uids)
*ret_n_uids = n_sessions;
return n_sessions; FOREACH_WORD(word, l, t, state)
n++;
if (n > 0) {
unsigned i = 0;
b = new(uid_t, n);
if (!b)
return -ENOMEM;
FOREACH_WORD(word, l, t, state) {
_cleanup_free_ char *k = NULL;
k = strndup(word, l);
if (!k)
return -ENOMEM;
r = parse_uid(k, b + i);
if (r < 0)
return r;
i++;
}
}
}
r = (int) strv_length(a);
if (sessions)
*sessions = TAKE_PTR(a);
if (uids)
*uids = TAKE_PTR(b);
if (n_uids)
*n_uids = n;
return r;
} }
static int seat_get_can(const char *seat, const char *variable) { static int seat_get_can(const char *seat, const char *variable) {
@ -894,52 +901,47 @@ _public_ int sd_machine_get_class(const char *machine, char **class) {
return 0; return 0;
} }
_public_ int sd_machine_get_ifindices(const char *machine, int **ret_ifindices) { _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
_cleanup_free_ char *netif_line = NULL; _cleanup_free_ char *netif = NULL;
const char *p; size_t l, allocated = 0, nr = 0;
int *ni = NULL;
const char *p, *word, *state;
int r; int r;
assert_return(machine_name_is_valid(machine), -EINVAL); assert_return(machine_name_is_valid(machine), -EINVAL);
assert_return(ifindices, -EINVAL);
p = strjoina("/run/systemd/machines/", machine); p = strjoina("/run/systemd/machines/", machine);
r = parse_env_file(NULL, p, "NETIF", &netif_line); r = parse_env_file(NULL, p, "NETIF", &netif);
if (r == -ENOENT) if (r == -ENOENT)
return -ENXIO; return -ENXIO;
if (r < 0) if (r < 0)
return r; return r;
if (!netif_line) { if (!netif) {
*ret_ifindices = NULL; *ifindices = NULL;
return 0; return 0;
} }
_cleanup_strv_free_ char **tt = strv_split(netif_line, NULL); FOREACH_WORD(word, l, netif, state) {
if (!tt) char buf[l+1];
return -ENOMEM; int ifi;
size_t n = 0; *(char*) (mempcpy(buf, word, l)) = 0;
int *ifindices;
if (ret_ifindices) { ifi = parse_ifindex(buf);
ifindices = new(int, strv_length(tt)); if (ifi < 0)
if (!ifindices) continue;
if (!GREEDY_REALLOC(ni, allocated, nr+1)) {
free(ni);
return -ENOMEM; return -ENOMEM;
}
ni[nr++] = ifi;
} }
for (size_t i = 0; tt[i]; i++) { *ifindices = ni;
int ind; return nr;
ind = parse_ifindex(tt[i]);
if (ind < 0)
/* Return -EUCLEAN to distinguish from -EINVAL for invalid args */
return ind == -EINVAL ? -EUCLEAN : ind;
if (ret_ifindices)
ifindices[n] = ind;
n++;
}
if (ret_ifindices)
*ret_ifindices = ifindices;
return n;
} }
static int MONITOR_TO_FD(sd_login_monitor *m) { static int MONITOR_TO_FD(sd_login_monitor *m) {

View File

@ -251,7 +251,7 @@ int x11_read_data(Context *c, sd_bus_message *m) {
if (in_section && first_word(l, "Option")) { if (in_section && first_word(l, "Option")) {
_cleanup_strv_free_ char **a = NULL; _cleanup_strv_free_ char **a = NULL;
r = strv_split_full(&a, l, WHITESPACE, EXTRACT_UNQUOTE); r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_UNQUOTE);
if (r < 0) if (r < 0)
return r; return r;
@ -274,7 +274,7 @@ int x11_read_data(Context *c, sd_bus_message *m) {
} else if (!in_section && first_word(l, "Section")) { } else if (!in_section && first_word(l, "Section")) {
_cleanup_strv_free_ char **a = NULL; _cleanup_strv_free_ char **a = NULL;
r = strv_split_full(&a, l, WHITESPACE, EXTRACT_UNQUOTE); r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_UNQUOTE);
if (r < 0) if (r < 0)
return -ENOMEM; return -ENOMEM;
@ -489,7 +489,7 @@ static int read_next_mapping(const char* filename,
if (IN_SET(l[0], 0, '#')) if (IN_SET(l[0], 0, '#'))
continue; continue;
r = strv_split_full(&b, l, WHITESPACE, EXTRACT_UNQUOTE); r = strv_split_extract(&b, l, WHITESPACE, EXTRACT_UNQUOTE);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -14,7 +14,7 @@
#include "string-util.h" #include "string-util.h"
#include "util.h" #include "util.h"
#define CONST_MAX5(a, b, c, d, e) CONST_MAX(CONST_MAX(a, b), CONST_MAX(CONST_MAX(c, d), e)) #define CONST_MAX4(a, b, c, d) CONST_MAX(CONST_MAX(a, b), CONST_MAX(c, d))
#define ULONG_BITS (sizeof(unsigned long)*8) #define ULONG_BITS (sizeof(unsigned long)*8)
@ -158,20 +158,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true); manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true);
break; break;
/* The kernel naming is a bit confusing here: /* The kernel is a bit confused here:
KEY_RESTART was probably introduced for media playback purposes, but
is now being predominantly used to indicate device reboot.
*/
case KEY_RESTART:
log_struct(LOG_INFO,
LOG_MESSAGE("Reboot key pressed."),
"MESSAGE_ID=" SD_MESSAGE_REBOOT_KEY_STR);
manager_handle_action(b->manager, INHIBIT_HANDLE_REBOOT_KEY, b->manager->handle_reboot_key, b->manager->reboot_key_ignore_inhibited, true);
break;
/* The kernel naming is a bit confusing here:
KEY_SLEEP = suspend-to-ram, which everybody else calls "suspend" KEY_SLEEP = suspend-to-ram, which everybody else calls "suspend"
KEY_SUSPEND = suspend-to-disk, which everybody else calls "hibernate" KEY_SUSPEND = suspend-to-disk, which everybody else calls "hibernate"
@ -244,7 +231,7 @@ static int button_suitable(int fd) {
return -errno; return -errno;
if (bitset_get(types, EV_KEY)) { if (bitset_get(types, EV_KEY)) {
unsigned long keys[CONST_MAX5(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND, KEY_RESTART)/ULONG_BITS+1]; unsigned long keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1];
if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof keys), keys) < 0) if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof keys), keys) < 0)
return -errno; return -errno;
@ -252,8 +239,7 @@ static int button_suitable(int fd) {
if (bitset_get(keys, KEY_POWER) || if (bitset_get(keys, KEY_POWER) ||
bitset_get(keys, KEY_POWER2) || bitset_get(keys, KEY_POWER2) ||
bitset_get(keys, KEY_SLEEP) || bitset_get(keys, KEY_SLEEP) ||
bitset_get(keys, KEY_SUSPEND) || bitset_get(keys, KEY_SUSPEND))
bitset_get(keys, KEY_RESTART))
return true; return true;
} }
@ -274,7 +260,7 @@ static int button_suitable(int fd) {
static int button_set_mask(const char *name, int fd) { static int button_set_mask(const char *name, int fd) {
unsigned long unsigned long
types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1] = {}, types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1] = {},
keys[CONST_MAX5(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND, KEY_RESTART)/ULONG_BITS+1] = {}, keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1] = {},
switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {}; switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {};
struct input_mask mask; struct input_mask mask;
@ -299,7 +285,6 @@ static int button_set_mask(const char *name, int fd) {
bitset_put(keys, KEY_POWER2); bitset_put(keys, KEY_POWER2);
bitset_put(keys, KEY_SLEEP); bitset_put(keys, KEY_SLEEP);
bitset_put(keys, KEY_SUSPEND); bitset_put(keys, KEY_SUSPEND);
bitset_put(keys, KEY_RESTART);
mask = (struct input_mask) { mask = (struct input_mask) {
.type = EV_KEY, .type = EV_KEY,

View File

@ -43,12 +43,10 @@ void manager_reset_config(Manager *m) {
m->handle_lid_switch = HANDLE_SUSPEND; m->handle_lid_switch = HANDLE_SUSPEND;
m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID; m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID;
m->handle_lid_switch_docked = HANDLE_IGNORE; m->handle_lid_switch_docked = HANDLE_IGNORE;
m->handle_reboot_key = HANDLE_REBOOT;
m->power_key_ignore_inhibited = false; m->power_key_ignore_inhibited = false;
m->suspend_key_ignore_inhibited = false; m->suspend_key_ignore_inhibited = false;
m->hibernate_key_ignore_inhibited = false; m->hibernate_key_ignore_inhibited = false;
m->lid_switch_ignore_inhibited = true; m->lid_switch_ignore_inhibited = true;
m->reboot_key_ignore_inhibited = false;
m->holdoff_timeout_usec = 30 * USEC_PER_SEC; m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
@ -677,8 +675,6 @@ bool manager_all_buttons_ignored(Manager *m) {
return false; return false;
if (m->handle_lid_switch_docked != HANDLE_IGNORE) if (m->handle_lid_switch_docked != HANDLE_IGNORE)
return false; return false;
if (m->handle_reboot_key != HANDLE_IGNORE)
return false;
return true; return true;
} }

View File

@ -3240,7 +3240,6 @@ static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error
w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" : w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" : w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" : w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
w == INHIBIT_HANDLE_REBOOT_KEY ? "org.freedesktop.login1.inhibit-handle-reboot-key" :
w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" : w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
"org.freedesktop.login1.inhibit-handle-lid-switch", "org.freedesktop.login1.inhibit-handle-lid-switch",
NULL, NULL,

View File

@ -30,12 +30,10 @@ Login.HandleHibernateKey, config_parse_handle_action, 0, offse
Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch) Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch)
Login.HandleLidSwitchExternalPower, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_ep) Login.HandleLidSwitchExternalPower, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_ep)
Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked) Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked)
Login.HandleRebootKey, config_parse_handle_action, 0, offsetof(Manager, handle_reboot_key)
Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited) Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited)
Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited) Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited)
Login.HibernateKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, hibernate_key_ignore_inhibited) Login.HibernateKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, hibernate_key_ignore_inhibited)
Login.LidSwitchIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, lid_switch_ignore_inhibited) Login.LidSwitchIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, lid_switch_ignore_inhibited)
Login.RebootKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, reboot_key_ignore_inhibited)
Login.HoldoffTimeoutSec, config_parse_sec, 0, offsetof(Manager, holdoff_timeout_usec) Login.HoldoffTimeoutSec, config_parse_sec, 0, offsetof(Manager, holdoff_timeout_usec)
Login.IdleAction, config_parse_handle_action, 0, offsetof(Manager, idle_action) Login.IdleAction, config_parse_handle_action, 0, offsetof(Manager, idle_action)
Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec) Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec)

View File

@ -8,7 +8,6 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "env-file.h" #include "env-file.h"
#include "errno-list.h"
#include "escape.h" #include "escape.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
@ -452,15 +451,7 @@ bool manager_is_inhibited(
} }
const char *inhibit_what_to_string(InhibitWhat w) { const char *inhibit_what_to_string(InhibitWhat w) {
static thread_local char buffer[STRLEN( static thread_local char buffer[97];
"shutdown:"
"sleep:"
"idle:"
"handle-power-key:"
"handle-suspend-key:"
"handle-hibernate-key:"
"handle-lid-switch:"
"handle-reboot-key")+1];
char *p; char *p;
if (w < 0 || w >= _INHIBIT_WHAT_MAX) if (w < 0 || w >= _INHIBIT_WHAT_MAX)
@ -481,8 +472,6 @@ const char *inhibit_what_to_string(InhibitWhat w) {
p = stpcpy(p, "handle-hibernate-key:"); p = stpcpy(p, "handle-hibernate-key:");
if (w & INHIBIT_HANDLE_LID_SWITCH) if (w & INHIBIT_HANDLE_LID_SWITCH)
p = stpcpy(p, "handle-lid-switch:"); p = stpcpy(p, "handle-lid-switch:");
if (w & INHIBIT_HANDLE_REBOOT_KEY)
p = stpcpy(p, "handle-reboot-key:");
if (p > buffer) if (p > buffer)
*(p-1) = 0; *(p-1) = 0;
@ -492,41 +481,31 @@ const char *inhibit_what_to_string(InhibitWhat w) {
return buffer; return buffer;
} }
int inhibit_what_from_string(const char *s) { InhibitWhat inhibit_what_from_string(const char *s) {
InhibitWhat what = 0; InhibitWhat what = 0;
const char *word, *state;
size_t l;
for (const char *p = s;;) { FOREACH_WORD_SEPARATOR(word, l, s, ":", state) {
_cleanup_free_ char *word = NULL; if (l == 8 && strneq(word, "shutdown", l))
int r;
/* A sanity check that our return values fit in an int */
assert_cc((int) _INHIBIT_WHAT_MAX == _INHIBIT_WHAT_MAX);
r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0)
return r;
if (r == 0)
return what;
if (streq(word, "shutdown"))
what |= INHIBIT_SHUTDOWN; what |= INHIBIT_SHUTDOWN;
else if (streq(word, "sleep")) else if (l == 5 && strneq(word, "sleep", l))
what |= INHIBIT_SLEEP; what |= INHIBIT_SLEEP;
else if (streq(word, "idle")) else if (l == 4 && strneq(word, "idle", l))
what |= INHIBIT_IDLE; what |= INHIBIT_IDLE;
else if (streq(word, "handle-power-key")) else if (l == 16 && strneq(word, "handle-power-key", l))
what |= INHIBIT_HANDLE_POWER_KEY; what |= INHIBIT_HANDLE_POWER_KEY;
else if (streq(word, "handle-suspend-key")) else if (l == 18 && strneq(word, "handle-suspend-key", l))
what |= INHIBIT_HANDLE_SUSPEND_KEY; what |= INHIBIT_HANDLE_SUSPEND_KEY;
else if (streq(word, "handle-hibernate-key")) else if (l == 20 && strneq(word, "handle-hibernate-key", l))
what |= INHIBIT_HANDLE_HIBERNATE_KEY; what |= INHIBIT_HANDLE_HIBERNATE_KEY;
else if (streq(word, "handle-lid-switch")) else if (l == 17 && strneq(word, "handle-lid-switch", l))
what |= INHIBIT_HANDLE_LID_SWITCH; what |= INHIBIT_HANDLE_LID_SWITCH;
else if (streq(word, "handle-reboot-key"))
what |= INHIBIT_HANDLE_REBOOT_KEY;
else else
return _INHIBIT_WHAT_INVALID; return _INHIBIT_WHAT_INVALID;
} }
return what;
} }
static const char* const inhibit_mode_table[_INHIBIT_MODE_MAX] = { static const char* const inhibit_mode_table[_INHIBIT_MODE_MAX] = {

View File

@ -11,8 +11,7 @@ typedef enum InhibitWhat {
INHIBIT_HANDLE_SUSPEND_KEY = 1 << 4, INHIBIT_HANDLE_SUSPEND_KEY = 1 << 4,
INHIBIT_HANDLE_HIBERNATE_KEY = 1 << 5, INHIBIT_HANDLE_HIBERNATE_KEY = 1 << 5,
INHIBIT_HANDLE_LID_SWITCH = 1 << 6, INHIBIT_HANDLE_LID_SWITCH = 1 << 6,
INHIBIT_HANDLE_REBOOT_KEY = 1 << 7, _INHIBIT_WHAT_MAX = 1 << 7,
_INHIBIT_WHAT_MAX = 1 << 8,
_INHIBIT_WHAT_INVALID = -1 _INHIBIT_WHAT_INVALID = -1
} InhibitWhat; } InhibitWhat;
@ -67,7 +66,7 @@ InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm);
bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since, bool ignore_inactive, bool ignore_uid, uid_t uid, Inhibitor **offending); bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since, bool ignore_inactive, bool ignore_uid, uid_t uid, Inhibitor **offending);
const char *inhibit_what_to_string(InhibitWhat k); const char *inhibit_what_to_string(InhibitWhat k);
int inhibit_what_from_string(const char *s); InhibitWhat inhibit_what_from_string(const char *s);
const char *inhibit_mode_to_string(InhibitMode k); const char *inhibit_mode_to_string(InhibitMode k);
InhibitMode inhibit_mode_from_string(const char *s); InhibitMode inhibit_mode_from_string(const char *s);

View File

@ -18,19 +18,16 @@
#KillOnlyUsers= #KillOnlyUsers=
#KillExcludeUsers=root #KillExcludeUsers=root
#InhibitDelayMaxSec=5 #InhibitDelayMaxSec=5
#UserStopDelaySec=10
#HandlePowerKey=poweroff #HandlePowerKey=poweroff
#HandleSuspendKey=suspend #HandleSuspendKey=suspend
#HandleHibernateKey=hibernate #HandleHibernateKey=hibernate
#HandleLidSwitch=suspend #HandleLidSwitch=suspend
#HandleLidSwitchExternalPower=suspend #HandleLidSwitchExternalPower=suspend
#HandleLidSwitchDocked=ignore #HandleLidSwitchDocked=ignore
#HandleRebootKey=reboot
#PowerKeyIgnoreInhibited=no #PowerKeyIgnoreInhibited=no
#SuspendKeyIgnoreInhibited=no #SuspendKeyIgnoreInhibited=no
#HibernateKeyIgnoreInhibited=no #HibernateKeyIgnoreInhibited=no
#LidSwitchIgnoreInhibited=yes #LidSwitchIgnoreInhibited=yes
#RebootKeyIgnoreInhibited=no
#HoldoffTimeoutSec=30s #HoldoffTimeoutSec=30s
#IdleAction=ignore #IdleAction=ignore
#IdleActionSec=30min #IdleActionSec=30min

View File

@ -107,13 +107,11 @@ struct Manager {
HandleAction handle_lid_switch; HandleAction handle_lid_switch;
HandleAction handle_lid_switch_ep; HandleAction handle_lid_switch_ep;
HandleAction handle_lid_switch_docked; HandleAction handle_lid_switch_docked;
HandleAction handle_reboot_key;
bool power_key_ignore_inhibited; bool power_key_ignore_inhibited;
bool suspend_key_ignore_inhibited; bool suspend_key_ignore_inhibited;
bool hibernate_key_ignore_inhibited; bool hibernate_key_ignore_inhibited;
bool lid_switch_ignore_inhibited; bool lid_switch_ignore_inhibited;
bool reboot_key_ignore_inhibited;
bool remove_ipc; bool remove_ipc;

View File

@ -113,17 +113,6 @@
</defaults> </defaults>
</action> </action>
<action id="org.freedesktop.login1.inhibit-handle-reboot-key">
<description gettext-domain="systemd">Allow applications to inhibit system handling of the reboot key</description>
<message gettext-domain="systemd">Authentication is required for an application to inhibit system handling of the reboot key.</message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.inhibit-handle-suspend-key org.freedesktop.login1.inhibit-handle-hibernate-key org.freedesktop.login1.inhibit-handle-lid-switch</annotate>
</action>
<action id="org.freedesktop.login1.set-self-linger"> <action id="org.freedesktop.login1.set-self-linger">
<description gettext-domain="systemd">Allow non-logged-in user to run programs</description> <description gettext-domain="systemd">Allow non-logged-in user to run programs</description>
<message gettext-domain="systemd">Explicit request is required to run programs as a non-logged-in user.</message> <message gettext-domain="systemd">Explicit request is required to run programs as a non-logged-in user.</message>

View File

@ -983,7 +983,7 @@ static int dhcp6_update_address(
addr->cinfo.ifa_valid = lifetime_valid; addr->cinfo.ifa_valid = lifetime_valid;
(void) in_addr_to_string(addr->family, &addr->in_addr, &buffer); (void) in_addr_to_string(addr->family, &addr->in_addr, &buffer);
log_link_full(link, set_contains(link->dhcp6_addresses, addr) ? LOG_DEBUG : LOG_INFO, log_link_full(link, set_contains(link->dhcp6_addresses, addr) ? LOG_DEBUG : LOG_INFO, 0,
"DHCPv6 address %s/%u timeout preferred %d valid %d", "DHCPv6 address %s/%u timeout preferred %d valid %d",
strna(buffer), addr->prefixlen, lifetime_preferred, lifetime_valid); strna(buffer), addr->prefixlen, lifetime_preferred, lifetime_valid);

View File

@ -4660,10 +4660,10 @@ int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, in
const char *err_msg = NULL; const char *err_msg = NULL;
(void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg); (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
return log_link_full_errno(link, level, err, return log_link_full(link, level, err,
"%s: %s%s%s%m", "%s: %s%s%s%m",
msg, msg,
strempty(err_msg), strempty(err_msg),
err_msg && !endswith(err_msg, ".") ? "." : "", err_msg && !endswith(err_msg, ".") ? "." : "",
err_msg ? " " : ""); err_msg ? " " : "");
} }

View File

@ -36,11 +36,11 @@
#include "path-util.h" #include "path-util.h"
#include "set.h" #include "set.h"
#include "signal-util.h" #include "signal-util.h"
#include "stat-util.h"
#include "strv.h" #include "strv.h"
#include "sysctl-util.h" #include "sysctl-util.h"
#include "tmpfile-util.h" #include "tmpfile-util.h"
#include "udev-util.h" #include "udev-util.h"
#include "virt.h"
/* use 128 MB for receive socket kernel queue. */ /* use 128 MB for receive socket kernel queue. */
#define RCVBUF_SIZE (128*1024*1024) #define RCVBUF_SIZE (128*1024*1024)
@ -261,19 +261,16 @@ static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *devi
static int manager_connect_udev(Manager *m) { static int manager_connect_udev(Manager *m) {
int r; int r;
/* udev does not initialize devices inside containers, so we rely on them being already /* udev does not initialize devices inside containers,
* initialized before entering the container. */ * so we rely on them being already initialized before
if (path_is_read_only_fs("/sys") > 0) * entering the container */
if (detect_container() > 0)
return 0; return 0;
r = sd_device_monitor_new(&m->device_monitor); r = sd_device_monitor_new(&m->device_monitor);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to initialize device monitor: %m"); return log_error_errno(r, "Failed to initialize device monitor: %m");
r = sd_device_monitor_set_receive_buffer_size(m->device_monitor, RCVBUF_SIZE);
if (r < 0)
log_warning_errno(r, "Failed to increase buffer size for device monitor, ignoring: %m");
r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "net", NULL); r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "net", NULL);
if (r < 0) if (r < 0)
return log_error_errno(r, "Could not add device monitor filter: %m"); return log_error_errno(r, "Could not add device monitor filter: %m");
@ -1350,7 +1347,7 @@ static int manager_connect_genl(Manager *m) {
r = sd_netlink_inc_rcvbuf(m->genl, RCVBUF_SIZE); r = sd_netlink_inc_rcvbuf(m->genl, RCVBUF_SIZE);
if (r < 0) if (r < 0)
log_warning_errno(r, "Failed to increase receive buffer size for general netlink socket, ignoring: %m"); return r;
r = sd_netlink_attach_event(m->genl, m->event, 0); r = sd_netlink_attach_event(m->genl, m->event, 0);
if (r < 0) if (r < 0)
@ -1372,14 +1369,9 @@ static int manager_connect_rtnl(Manager *m) {
if (r < 0) if (r < 0)
return r; return r;
/* Bump receiver buffer, but only if we are not called via socket activation, as in that r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
* case systemd sets the receive buffer size for us, and the value in the .socket unit if (r < 0)
* should take full effect. */ return r;
if (fd < 0) {
r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
if (r < 0)
log_warning_errno(r, "Failed to increase receive buffer size for rtnl socket, ignoring: %m");
}
r = sd_netlink_attach_event(m->rtnl, m->event, 0); r = sd_netlink_attach_event(m->rtnl, m->event, 0);
if (r < 0) if (r < 0)

View File

@ -301,7 +301,7 @@ int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_onl
CustomMount *m; CustomMount *m;
int k; int k;
k = strv_split_full(&lower, s, ":", EXTRACT_DONT_COALESCE_SEPARATORS); k = strv_split_extract(&lower, s, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (k < 0) if (k < 0)
return k; return k;
if (k < 2) if (k < 2)

View File

@ -88,12 +88,13 @@ int change_uid_gid_raw(
int change_uid_gid(const char *user, char **_home) { int change_uid_gid(const char *user, char **_home) {
char *x, *u, *g, *h; char *x, *u, *g, *h;
const char *word, *state;
_cleanup_free_ gid_t *gids = NULL; _cleanup_free_ gid_t *gids = NULL;
_cleanup_free_ char *home = NULL, *line = NULL; _cleanup_free_ char *home = NULL, *line = NULL;
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
unsigned n_gids = 0; unsigned n_gids = 0;
size_t sz = 0; size_t sz = 0, l;
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
pid_t pid; pid_t pid;
@ -207,19 +208,16 @@ int change_uid_gid(const char *user, char **_home) {
x += strcspn(x, WHITESPACE); x += strcspn(x, WHITESPACE);
x += strspn(x, WHITESPACE); x += strspn(x, WHITESPACE);
for (const char *p = x;;) { FOREACH_WORD(word, l, x, state) {
_cleanup_free_ char *word = NULL; char c[l+1];
r = extract_first_word(&p, &word, NULL, 0); memcpy(c, word, l);
if (r < 0) c[l] = 0;
return log_error_errno(r, "Failed to parse group data from getent: %m");
if (r == 0)
break;
if (!GREEDY_REALLOC(gids, sz, n_gids+1)) if (!GREEDY_REALLOC(gids, sz, n_gids+1))
return log_oom(); return log_oom();
r = parse_gid(word, &gids[n_gids++]); r = parse_gid(c, &gids[n_gids++]);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to parse group data from getent: %m"); return log_error_errno(r, "Failed to parse group data from getent: %m");
} }

View File

@ -340,7 +340,7 @@ static int bus_append_exec_command(sd_bus_message *m, const char *field, const c
return log_error_errno(r, "Failed to parse path: %m"); return log_error_errno(r, "Failed to parse path: %m");
} }
r = strv_split_full(&l, eq, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE); r = strv_split_extract(&l, eq, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to parse command line: %m"); return log_error_errno(r, "Failed to parse command line: %m");

View File

@ -239,10 +239,10 @@ typedef enum Disabled {
#define DEFINE_CONFIG_PARSE_ENUMV(function, name, type, invalid, msg) \ #define DEFINE_CONFIG_PARSE_ENUMV(function, name, type, invalid, msg) \
CONFIG_PARSER_PROTOTYPE(function) { \ CONFIG_PARSER_PROTOTYPE(function) { \
type **enums = data; \ type **enums = data, x, *ys; \
_cleanup_free_ type *xs = NULL; \ _cleanup_free_ type *xs = NULL; \
size_t i = 0; \ const char *word, *state; \
int r; \ size_t l, i = 0; \
\ \
assert(filename); \ assert(filename); \
assert(lvalue); \ assert(lvalue); \
@ -255,32 +255,29 @@ typedef enum Disabled {
\ \
*xs = invalid; \ *xs = invalid; \
\ \
for (const char *p = rvalue;;) { \ FOREACH_WORD(word, l, rvalue, state) { \
_cleanup_free_ char *en = NULL; \ _cleanup_free_ char *en = NULL; \
type x, *new_xs; \ type *new_xs; \
\ \
r = extract_first_word(&p, &en, NULL, 0); \ en = strndup(word, l); \
if (r == -ENOMEM) \ if (!en) \
return log_oom(); \ return log_oom(); \
if (r < 0) \
return log_syntax(unit, LOG_ERR, filename, line, 0, \
msg ": %s", en); \
if (r == 0) \
break; \
\ \
if ((x = name##_from_string(en)) < 0) { \ if ((x = name##_from_string(en)) < 0) { \
log_syntax(unit, LOG_WARNING, filename, line, 0, \ log_syntax(unit, LOG_WARNING, filename, line, 0, \
msg ", ignoring: %s", en); \ msg ", ignoring: %s", en); \
continue; \ continue; \
} \ } \
\ \
for (type *ys = xs; x != invalid && *ys != invalid; ys++) \ for (ys = xs; x != invalid && *ys != invalid; ys++) { \
if (*ys == x) { \ if (*ys == x) { \
log_syntax(unit, LOG_NOTICE, filename, line, 0, \ log_syntax(unit, LOG_NOTICE, filename, \
"Duplicate entry, ignoring: %s", \ line, 0, \
"Duplicate entry, ignoring: %s", \
en); \ en); \
x = invalid; \ x = invalid; \
} \ } \
} \
\ \
if (x == invalid) \ if (x == invalid) \
continue; \ continue; \
@ -295,5 +292,6 @@ typedef enum Disabled {
*(xs + i) = invalid; \ *(xs + i) = invalid; \
} \ } \
\ \
return free_and_replace(*enums, xs); \ free_and_replace(*enums, xs); \
return 0; \
} }

View File

@ -81,53 +81,50 @@ int fstab_is_mount_point(const char *mount) {
int fstab_filter_options(const char *opts, const char *names, int fstab_filter_options(const char *opts, const char *names,
const char **ret_namefound, char **ret_value, char **ret_filtered) { const char **ret_namefound, char **ret_value, char **ret_filtered) {
const char *name, *namefound = NULL, *x; const char *name, *n = NULL, *x;
_cleanup_strv_free_ char **stor = NULL; _cleanup_strv_free_ char **stor = NULL;
_cleanup_free_ char *v = NULL, **strv = NULL; _cleanup_free_ char *v = NULL, **strv = NULL;
int r;
assert(names && *names); assert(names && *names);
if (!opts) if (!opts)
goto answer; goto answer;
/* If !ret_value and !ret_filtered, this function is not allowed to fail. */ /* If !value and !filtered, this function is not allowed to fail. */
if (!ret_filtered) { if (!ret_filtered) {
for (const char *word = opts;;) { const char *word, *state;
const char *end = word + strcspn(word, ","); size_t l;
FOREACH_WORD_SEPARATOR(word, l, opts, ",", state)
NULSTR_FOREACH(name, names) { NULSTR_FOREACH(name, names) {
if (end < word + strlen(name)) if (l < strlen(name))
continue; continue;
if (!strneq(word, name, strlen(name))) if (!strneq(word, name, strlen(name)))
continue; continue;
/* We know that the string is NUL terminated, so *x is valid */ /* we know that the string is NUL
* terminated, so *x is valid */
x = word + strlen(name); x = word + strlen(name);
if (IN_SET(*x, '\0', '=', ',')) { if (IN_SET(*x, '\0', '=', ',')) {
namefound = name; n = name;
if (ret_value) { if (ret_value) {
bool eq = *x == '='; free(v);
assert(eq || IN_SET(*x, ',', '\0')); if (IN_SET(*x, '\0', ','))
v = NULL;
r = free_and_strndup(&v, else {
eq ? x + 1 : NULL, assert(*x == '=');
eq ? end - x - 1 : 0); x++;
if (r < 0) v = strndup(x, l - strlen(name) - 1);
return r; if (!v)
return -ENOMEM;
}
} }
break;
} }
} }
if (*end)
word = end + 1;
else
break;
}
} else { } else {
char **t, **s;
stor = strv_split(opts, ","); stor = strv_split(opts, ",");
if (!stor) if (!stor)
return -ENOMEM; return -ENOMEM;
@ -135,8 +132,7 @@ int fstab_filter_options(const char *opts, const char *names,
if (!strv) if (!strv)
return -ENOMEM; return -ENOMEM;
char **t = strv; for (s = t = strv; *s; s++) {
for (char **s = strv; *s; s++) {
NULSTR_FOREACH(name, names) { NULSTR_FOREACH(name, names) {
x = startswith(*s, name); x = startswith(*s, name);
if (x && IN_SET(*x, '\0', '=')) if (x && IN_SET(*x, '\0', '='))
@ -148,12 +144,18 @@ int fstab_filter_options(const char *opts, const char *names,
continue; continue;
found: found:
/* Keep the last occurrence found */ /* Keep the last occurrence found */
namefound = name; n = name;
if (ret_value) { if (ret_value) {
assert(IN_SET(*x, '=', '\0')); free(v);
r = free_and_strdup(&v, *x == '=' ? x + 1 : NULL); if (*x == '\0')
if (r < 0) v = NULL;
return r; else {
assert(*x == '=');
x++;
v = strdup(x);
if (!v)
return -ENOMEM;
}
} }
} }
*t = NULL; *t = NULL;
@ -161,7 +163,7 @@ int fstab_filter_options(const char *opts, const char *names,
answer: answer:
if (ret_namefound) if (ret_namefound)
*ret_namefound = namefound; *ret_namefound = n;
if (ret_filtered) { if (ret_filtered) {
char *f; char *f;
@ -174,7 +176,7 @@ answer:
if (ret_value) if (ret_value)
*ret_value = TAKE_PTR(v); *ret_value = TAKE_PTR(v);
return !!namefound; return !!n;
} }
int fstab_extract_values(const char *opts, const char *name, char ***values) { int fstab_extract_values(const char *opts, const char *name, char ***values) {

View File

@ -14,26 +14,24 @@
* See, network/networkd-link.h for example. * See, network/networkd-link.h for example.
*/ */
#define log_link_full_errno(link, level, error, ...) \ #define log_link_full(link, level, error, ...) \
({ \ ({ \
const Link *_l = (link); \ const Link *_l = (link); \
(_l && _l->ifname) ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \ (_l && _l->ifname) ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \
log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
}) \ }) \
#define log_link_full(link, level, ...) (void) log_link_full_errno(link, level, 0, __VA_ARGS__) #define log_link_debug(link, ...) log_link_full(link, LOG_DEBUG, 0, ##__VA_ARGS__)
#define log_link_info(link, ...) log_link_full(link, LOG_INFO, 0, ##__VA_ARGS__)
#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, 0, ##__VA_ARGS__)
#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, 0, ##__VA_ARGS__)
#define log_link_error(link, ...) log_link_full(link, LOG_ERR, 0, ##__VA_ARGS__)
#define log_link_debug(link, ...) log_link_full_errno(link, LOG_DEBUG, 0, __VA_ARGS__) #define log_link_debug_errno(link, error, ...) log_link_full(link, LOG_DEBUG, error, ##__VA_ARGS__)
#define log_link_info(link, ...) log_link_full(link, LOG_INFO, __VA_ARGS__) #define log_link_info_errno(link, error, ...) log_link_full(link, LOG_INFO, error, ##__VA_ARGS__)
#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, __VA_ARGS__) #define log_link_notice_errno(link, error, ...) log_link_full(link, LOG_NOTICE, error, ##__VA_ARGS__)
#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, __VA_ARGS__) #define log_link_warning_errno(link, error, ...) log_link_full(link, LOG_WARNING, error, ##__VA_ARGS__)
#define log_link_error(link, ...) log_link_full(link, LOG_ERR, __VA_ARGS__) #define log_link_error_errno(link, error, ...) log_link_full(link, LOG_ERR, error, ##__VA_ARGS__)
#define log_link_debug_errno(link, error, ...) log_link_full_errno(link, LOG_DEBUG, error, __VA_ARGS__)
#define log_link_info_errno(link, error, ...) log_link_full_errno(link, LOG_INFO, error, __VA_ARGS__)
#define log_link_notice_errno(link, error, ...) log_link_full_errno(link, LOG_NOTICE, error, __VA_ARGS__)
#define log_link_warning_errno(link, error, ...) log_link_full_errno(link, LOG_WARNING, error, __VA_ARGS__)
#define log_link_error_errno(link, error, ...) log_link_full_errno(link, LOG_ERR, error, __VA_ARGS__)
#define LOG_LINK_MESSAGE(link, fmt, ...) "MESSAGE=%s: " fmt, (link)->ifname, ##__VA_ARGS__ #define LOG_LINK_MESSAGE(link, fmt, ...) "MESSAGE=%s: " fmt, (link)->ifname, ##__VA_ARGS__
#define LOG_LINK_INTERFACE(link) "INTERFACE=%s", (link)->ifname #define LOG_LINK_INTERFACE(link) "INTERFACE=%s", (link)->ifname

View File

@ -100,8 +100,9 @@ int parse_sleep_config(SleepConfig **ret_sleep_config) {
} }
int can_sleep_state(char **types) { int can_sleep_state(char **types) {
_cleanup_free_ char *text = NULL; char **type;
int r; int r;
_cleanup_free_ char *p = NULL;
if (strv_isempty(types)) if (strv_isempty(types))
return true; return true;
@ -112,27 +113,34 @@ int can_sleep_state(char **types) {
return false; return false;
} }
r = read_one_line_file("/sys/power/state", &text); r = read_one_line_file("/sys/power/state", &p);
if (r < 0) { if (r < 0) {
log_debug_errno(r, "Failed to read /sys/power/state, cannot sleep: %m"); log_debug_errno(r, "Failed to read /sys/power/state, cannot sleep: %m");
return false; return false;
} }
const char *found; STRV_FOREACH(type, types) {
r = string_contains_word_strv(text, NULL, types, &found); const char *word, *state;
if (r < 0) size_t l, k;
return log_debug_errno(r, "Failed to parse /sys/power/state: %m");
if (r > 0) k = strlen(*type);
log_debug("Sleep mode \"%s\" is supported by the kernel.", found); FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state)
else if (DEBUG_LOGGING) { if (l == k && memcmp(word, *type, l) == 0) {
log_debug("Sleep mode \"%s\" is supported by the kernel.", *type);
return true;
}
}
if (DEBUG_LOGGING) {
_cleanup_free_ char *t = strv_join(types, "/"); _cleanup_free_ char *t = strv_join(types, "/");
log_debug("Sleep mode %s not supported by the kernel, sorry.", strnull(t)); log_debug("Sleep mode %s not supported by the kernel, sorry.", strnull(t));
} }
return r; return false;
} }
int can_sleep_disk(char **types) { int can_sleep_disk(char **types) {
_cleanup_free_ char *text = NULL; _cleanup_free_ char *p = NULL;
char **type;
int r; int r;
if (strv_isempty(types)) if (strv_isempty(types))
@ -144,38 +152,29 @@ int can_sleep_disk(char **types) {
return false; return false;
} }
r = read_one_line_file("/sys/power/disk", &text); r = read_one_line_file("/sys/power/disk", &p);
if (r < 0) { if (r < 0) {
log_debug_errno(r, "Couldn't read /sys/power/disk: %m"); log_debug_errno(r, "Couldn't read /sys/power/disk: %m");
return false; return false;
} }
for (const char *p = text;;) { STRV_FOREACH(type, types) {
_cleanup_free_ char *word = NULL; const char *word, *state;
size_t l, k;
r = extract_first_word(&p, &word, NULL, 0); k = strlen(*type);
if (r < 0) FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state) {
return log_debug_errno(r, "Failed to parse /sys/power/disk: %m"); if (l == k && memcmp(word, *type, l) == 0)
if (r == 0) return true;
break;
char *s = word; if (l == k + 2 &&
size_t l = strlen(s); word[0] == '[' &&
if (s[0] == '[' && s[l-1] == ']') { memcmp(word + 1, *type, l - 2) == 0 &&
s[l-1] = '\0'; word[l-1] == ']')
s++; return true;
}
if (strv_contains(types, s)) {
log_debug("Disk sleep mode \"%s\" is supported by the kernel.", s);
return true;
} }
} }
if (DEBUG_LOGGING) {
_cleanup_free_ char *t = strv_join(types, "/");
log_debug("Disk sleep mode %s not supported by the kernel, sorry.", strnull(t));
}
return false; return false;
} }

View File

@ -180,11 +180,7 @@ int sd_seat_get_active(const char *seat, char **session, uid_t *uid);
/* Return sessions and users on seat. Returns number of sessions. /* Return sessions and users on seat. Returns number of sessions.
* If sessions is NULL, this returns only the number of sessions. */ * If sessions is NULL, this returns only the number of sessions. */
int sd_seat_get_sessions( int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids);
const char *seat,
char ***ret_sessions,
uid_t **ret_uids,
unsigned *ret_n_uids);
/* Return whether the seat is multi-session capable */ /* Return whether the seat is multi-session capable */
int sd_seat_can_multi_session(const char *seat) _sd_deprecated_; int sd_seat_can_multi_session(const char *seat) _sd_deprecated_;
@ -199,7 +195,7 @@ int sd_seat_can_graphical(const char *seat);
int sd_machine_get_class(const char *machine, char **clazz); int sd_machine_get_class(const char *machine, char **clazz);
/* Return the list if host-side network interface indices of a machine */ /* Return the list if host-side network interface indices of a machine */
int sd_machine_get_ifindices(const char *machine, int **ret_ifindices); int sd_machine_get_ifindices(const char *machine, int **ifindices);
/* Get all seats, store in *seats. Returns the number of seats. If /* Get all seats, store in *seats. Returns the number of seats. If
* seats is NULL, this only returns the number of seats. */ * seats is NULL, this only returns the number of seats. */

View File

@ -140,8 +140,6 @@ _SD_BEGIN_DECLARATIONS;
#define SD_MESSAGE_SYSTEM_UNDOCKED_STR SD_ID128_MAKE_STR(51,e1,71,bd,58,52,48,56,81,10,14,4c,51,7c,ca,53) #define SD_MESSAGE_SYSTEM_UNDOCKED_STR SD_ID128_MAKE_STR(51,e1,71,bd,58,52,48,56,81,10,14,4c,51,7c,ca,53)
#define SD_MESSAGE_POWER_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71) #define SD_MESSAGE_POWER_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71)
#define SD_MESSAGE_POWER_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71) #define SD_MESSAGE_POWER_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71)
#define SD_MESSAGE_REBOOT_KEY SD_ID128_MAKE(9f,a9,d2,c0,12,13,4e,c3,85,45,1f,fe,31,6f,97,d0)
#define SD_MESSAGE_REBOOT_KEY_STR SD_ID128_MAKE_STR(9f,a9,d2,c0,12,13,4e,c3,85,45,1f,fe,31,6f,97,d0)
#define SD_MESSAGE_SUSPEND_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,72) #define SD_MESSAGE_SUSPEND_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,72)
#define SD_MESSAGE_SUSPEND_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,72) #define SD_MESSAGE_SUSPEND_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,72)
#define SD_MESSAGE_HIBERNATE_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,73) #define SD_MESSAGE_HIBERNATE_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,73)

View File

@ -11,8 +11,6 @@ static void test_extract_first_word(void) {
const char *p, *original; const char *p, *original;
char *t; char *t;
log_info("/* %s */", __func__);
p = original = "foobar waldo"; p = original = "foobar waldo";
assert_se(extract_first_word(&p, &t, NULL, 0) > 0); assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
assert_se(streq(t, "foobar")); assert_se(streq(t, "foobar"));
@ -389,8 +387,6 @@ static void test_extract_first_word_and_warn(void) {
const char *p, *original; const char *p, *original;
char *t; char *t;
log_info("/* %s */", __func__);
p = original = "foobar waldo"; p = original = "foobar waldo";
assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
assert_se(streq(t, "foobar")); assert_se(streq(t, "foobar"));
@ -535,8 +531,6 @@ static void test_extract_many_words(void) {
const char *p, *original; const char *p, *original;
char *a, *b, *c, *d, *e, *f; char *a, *b, *c, *d, *e, *f;
log_info("/* %s */", __func__);
p = original = "foobar waldi piep"; p = original = "foobar waldi piep";
assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 3); assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 3);
assert_se(isempty(p)); assert_se(isempty(p));

View File

@ -10,9 +10,8 @@
#include "util.h" #include "util.h"
static void test_string_erase(void) { static void test_string_erase(void) {
log_info("/* %s */", __func__);
char *x; char *x;
x = strdupa(""); x = strdupa("");
assert_se(streq(string_erase(x), "")); assert_se(streq(string_erase(x), ""));
@ -34,17 +33,17 @@ static void test_string_erase(void) {
} }
static void test_free_and_strndup_one(char **t, const char *src, size_t l, const char *expected, bool change) { static void test_free_and_strndup_one(char **t, const char *src, size_t l, const char *expected, bool change) {
int r;
log_debug("%s: \"%s\", \"%s\", %zd (expect \"%s\", %s)", log_debug("%s: \"%s\", \"%s\", %zd (expect \"%s\", %s)",
__func__, strnull(*t), strnull(src), l, strnull(expected), yes_no(change)); __func__, strnull(*t), strnull(src), l, strnull(expected), yes_no(change));
int r = free_and_strndup(t, src, l); r = free_and_strndup(t, src, l);
assert_se(streq_ptr(*t, expected)); assert_se(streq_ptr(*t, expected));
assert_se(r == change); /* check that change occurs only when necessary */ assert_se(r == change); /* check that change occurs only when necessary */
} }
static void test_free_and_strndup(void) { static void test_free_and_strndup(void) {
log_info("/* %s */", __func__);
static const struct test_case { static const struct test_case {
const char *src; const char *src;
size_t len; size_t len;
@ -92,7 +91,6 @@ static void test_free_and_strndup(void) {
} }
static void test_ascii_strcasecmp_n(void) { static void test_ascii_strcasecmp_n(void) {
log_info("/* %s */", __func__);
assert_se(ascii_strcasecmp_n("", "", 0) == 0); assert_se(ascii_strcasecmp_n("", "", 0) == 0);
assert_se(ascii_strcasecmp_n("", "", 1) == 0); assert_se(ascii_strcasecmp_n("", "", 1) == 0);
@ -120,8 +118,6 @@ static void test_ascii_strcasecmp_n(void) {
} }
static void test_ascii_strcasecmp_nn(void) { static void test_ascii_strcasecmp_nn(void) {
log_info("/* %s */", __func__);
assert_se(ascii_strcasecmp_nn("", 0, "", 0) == 0); assert_se(ascii_strcasecmp_nn("", 0, "", 0) == 0);
assert_se(ascii_strcasecmp_nn("", 0, "", 1) < 0); assert_se(ascii_strcasecmp_nn("", 0, "", 1) < 0);
assert_se(ascii_strcasecmp_nn("", 1, "", 0) > 0); assert_se(ascii_strcasecmp_nn("", 1, "", 0) > 0);
@ -141,8 +137,6 @@ static void test_ascii_strcasecmp_nn(void) {
static void test_cellescape(void) { static void test_cellescape(void) {
char buf[40]; char buf[40];
log_info("/* %s */", __func__);
assert_se(streq(cellescape(buf, 1, ""), "")); assert_se(streq(cellescape(buf, 1, ""), ""));
assert_se(streq(cellescape(buf, 1, "1"), "")); assert_se(streq(cellescape(buf, 1, "1"), ""));
assert_se(streq(cellescape(buf, 1, "12"), "")); assert_se(streq(cellescape(buf, 1, "12"), ""));
@ -222,24 +216,19 @@ static void test_cellescape(void) {
} }
static void test_streq_ptr(void) { static void test_streq_ptr(void) {
log_info("/* %s */", __func__);
assert_se(streq_ptr(NULL, NULL)); assert_se(streq_ptr(NULL, NULL));
assert_se(!streq_ptr("abc", "cdef")); assert_se(!streq_ptr("abc", "cdef"));
} }
static void test_strstrip(void) { static void test_strstrip(void) {
log_info("/* %s */", __func__); char *r;
char input[] = " hello, waldo. ";
char *ret, input[] = " hello, waldo. "; r = strstrip(input);
assert_se(streq(r, "hello, waldo."));
ret = strstrip(input);
assert_se(streq(ret, "hello, waldo."));
} }
static void test_strextend(void) { static void test_strextend(void) {
log_info("/* %s */", __func__);
_cleanup_free_ char *str = NULL; _cleanup_free_ char *str = NULL;
assert_se(strextend(&str, NULL)); assert_se(strextend(&str, NULL));
@ -251,8 +240,6 @@ static void test_strextend(void) {
} }
static void test_strextend_with_separator(void) { static void test_strextend_with_separator(void) {
log_info("/* %s */", __func__);
_cleanup_free_ char *str = NULL; _cleanup_free_ char *str = NULL;
assert_se(strextend_with_separator(&str, NULL, NULL)); assert_se(strextend_with_separator(&str, NULL, NULL));
@ -276,8 +263,6 @@ static void test_strextend_with_separator(void) {
} }
static void test_strrep(void) { static void test_strrep(void) {
log_info("/* %s */", __func__);
_cleanup_free_ char *one, *three, *zero; _cleanup_free_ char *one, *three, *zero;
one = strrep("waldo", 1); one = strrep("waldo", 1);
three = strrep("waldo", 3); three = strrep("waldo", 3);
@ -303,15 +288,11 @@ static void test_string_has_cc(void) {
} }
static void test_ascii_strlower(void) { static void test_ascii_strlower(void) {
log_info("/* %s */", __func__);
char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK"; char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk")); assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
} }
static void test_strshorten(void) { static void test_strshorten(void) {
log_info("/* %s */", __func__);
char s[] = "foobar"; char s[] = "foobar";
assert_se(strlen(strshorten(s, 6)) == 6); assert_se(strlen(strshorten(s, 6)) == 6);
@ -321,8 +302,6 @@ static void test_strshorten(void) {
} }
static void test_strjoina(void) { static void test_strjoina(void) {
log_info("/* %s */", __func__);
char *actual; char *actual;
actual = strjoina("", "foo", "bar"); actual = strjoina("", "foo", "bar");
@ -380,8 +359,6 @@ static void test_strjoin(void) {
} }
static void test_strcmp_ptr(void) { static void test_strcmp_ptr(void) {
log_info("/* %s */", __func__);
assert_se(strcmp_ptr(NULL, NULL) == 0); assert_se(strcmp_ptr(NULL, NULL) == 0);
assert_se(strcmp_ptr("", NULL) > 0); assert_se(strcmp_ptr("", NULL) > 0);
assert_se(strcmp_ptr("foo", NULL) > 0); assert_se(strcmp_ptr("foo", NULL) > 0);
@ -394,36 +371,26 @@ static void test_strcmp_ptr(void) {
} }
static void test_foreach_word(void) { static void test_foreach_word(void) {
log_info("/* %s */", __func__); const char *word, *state;
size_t l;
const char *test = "test abc d\te f "; int i = 0;
const char test[] = "test abc d\te f ";
const char * const expected[] = { const char * const expected[] = {
"test", "test",
"abc", "abc",
"d", "d",
"e", "e",
"f", "f",
"",
NULL
}; };
size_t i = 0; FOREACH_WORD(word, l, test, state)
int r; assert_se(strneq(expected[i++], word, l));
for (const char *p = test;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0) {
assert_se(i == ELEMENTSOF(expected));
break;
}
assert_se(r > 0);
assert_se(streq(expected[i++], word));
}
} }
static void check(const char *test, char** expected, bool trailing) { static void check(const char *test, char** expected, bool trailing) {
size_t i = 0; int i = 0, r;
int r;
printf("<<<%s>>>\n", test); printf("<<<%s>>>\n", test);
for (;;) { for (;;) {
@ -445,8 +412,6 @@ static void check(const char *test, char** expected, bool trailing) {
} }
static void test_foreach_word_quoted(void) { static void test_foreach_word_quoted(void) {
log_info("/* %s */", __func__);
check("test a b c 'd' e '' '' hhh '' '' \"a b c\"", check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
STRV_MAKE("test", STRV_MAKE("test",
"a", "a",
@ -472,8 +437,6 @@ static void test_foreach_word_quoted(void) {
} }
static void test_endswith(void) { static void test_endswith(void) {
log_info("/* %s */", __func__);
assert_se(endswith("foobar", "bar")); assert_se(endswith("foobar", "bar"));
assert_se(endswith("foobar", "")); assert_se(endswith("foobar", ""));
assert_se(endswith("foobar", "foobar")); assert_se(endswith("foobar", "foobar"));
@ -484,8 +447,6 @@ static void test_endswith(void) {
} }
static void test_endswith_no_case(void) { static void test_endswith_no_case(void) {
log_info("/* %s */", __func__);
assert_se(endswith_no_case("fooBAR", "bar")); assert_se(endswith_no_case("fooBAR", "bar"));
assert_se(endswith_no_case("foobar", "")); assert_se(endswith_no_case("foobar", ""));
assert_se(endswith_no_case("foobar", "FOOBAR")); assert_se(endswith_no_case("foobar", "FOOBAR"));
@ -496,8 +457,6 @@ static void test_endswith_no_case(void) {
} }
static void test_delete_chars(void) { static void test_delete_chars(void) {
log_info("/* %s */", __func__);
char *s, input[] = " hello, waldo. abc"; char *s, input[] = " hello, waldo. abc";
s = delete_chars(input, WHITESPACE); s = delete_chars(input, WHITESPACE);
@ -506,7 +465,6 @@ static void test_delete_chars(void) {
} }
static void test_delete_trailing_chars(void) { static void test_delete_trailing_chars(void) {
log_info("/* %s */", __func__);
char *s, char *s,
input1[] = " \n \r k \n \r ", input1[] = " \n \r k \n \r ",
@ -531,8 +489,6 @@ static void test_delete_trailing_chars(void) {
} }
static void test_delete_trailing_slashes(void) { static void test_delete_trailing_slashes(void) {
log_info("/* %s */", __func__);
char s1[] = "foobar//", char s1[] = "foobar//",
s2[] = "foobar/", s2[] = "foobar/",
s3[] = "foobar", s3[] = "foobar",
@ -546,8 +502,6 @@ static void test_delete_trailing_slashes(void) {
} }
static void test_skip_leading_chars(void) { static void test_skip_leading_chars(void) {
log_info("/* %s */", __func__);
char input1[] = " \n \r k \n \r ", char input1[] = " \n \r k \n \r ",
input2[] = "kkkkthiskkkiskkkaktestkkk", input2[] = "kkkkthiskkkiskkkaktestkkk",
input3[] = "abcdef"; input3[] = "abcdef";
@ -560,15 +514,11 @@ static void test_skip_leading_chars(void) {
} }
static void test_in_charset(void) { static void test_in_charset(void) {
log_info("/* %s */", __func__);
assert_se(in_charset("dddaaabbbcccc", "abcd")); assert_se(in_charset("dddaaabbbcccc", "abcd"));
assert_se(!in_charset("dddaaabbbcccc", "abc f")); assert_se(!in_charset("dddaaabbbcccc", "abc f"));
} }
static void test_split_pair(void) { static void test_split_pair(void) {
log_info("/* %s */", __func__);
_cleanup_free_ char *a = NULL, *b = NULL; _cleanup_free_ char *a = NULL, *b = NULL;
assert_se(split_pair("", "", &a, &b) == -EINVAL); assert_se(split_pair("", "", &a, &b) == -EINVAL);
@ -591,8 +541,6 @@ static void test_split_pair(void) {
} }
static void test_first_word(void) { static void test_first_word(void) {
log_info("/* %s */", __func__);
assert_se(first_word("Hello", "")); assert_se(first_word("Hello", ""));
assert_se(first_word("Hello", "Hello")); assert_se(first_word("Hello", "Hello"));
assert_se(first_word("Hello world", "Hello")); assert_se(first_word("Hello world", "Hello"));
@ -607,16 +555,12 @@ static void test_first_word(void) {
} }
static void test_strlen_ptr(void) { static void test_strlen_ptr(void) {
log_info("/* %s */", __func__);
assert_se(strlen_ptr("foo") == 3); assert_se(strlen_ptr("foo") == 3);
assert_se(strlen_ptr("") == 0); assert_se(strlen_ptr("") == 0);
assert_se(strlen_ptr(NULL) == 0); assert_se(strlen_ptr(NULL) == 0);
} }
static void test_memory_startswith(void) { static void test_memory_startswith(void) {
log_info("/* %s */", __func__);
assert_se(streq(memory_startswith("", 0, ""), "")); assert_se(streq(memory_startswith("", 0, ""), ""));
assert_se(streq(memory_startswith("", 1, ""), "")); assert_se(streq(memory_startswith("", 1, ""), ""));
assert_se(streq(memory_startswith("x", 2, ""), "x")); assert_se(streq(memory_startswith("x", 2, ""), "x"));
@ -629,8 +573,6 @@ static void test_memory_startswith(void) {
} }
static void test_memory_startswith_no_case(void) { static void test_memory_startswith_no_case(void) {
log_info("/* %s */", __func__);
assert_se(streq(memory_startswith_no_case("", 0, ""), "")); assert_se(streq(memory_startswith_no_case("", 0, ""), ""));
assert_se(streq(memory_startswith_no_case("", 1, ""), "")); assert_se(streq(memory_startswith_no_case("", 1, ""), ""));
assert_se(streq(memory_startswith_no_case("x", 2, ""), "x")); assert_se(streq(memory_startswith_no_case("x", 2, ""), "x"));
@ -663,8 +605,6 @@ static void test_string_truncate_lines_one(const char *input, size_t n_lines, co
} }
static void test_string_truncate_lines(void) { static void test_string_truncate_lines(void) {
log_info("/* %s */", __func__);
test_string_truncate_lines_one("", 0, "", false); test_string_truncate_lines_one("", 0, "", false);
test_string_truncate_lines_one("", 1, "", false); test_string_truncate_lines_one("", 1, "", false);
test_string_truncate_lines_one("", 2, "", false); test_string_truncate_lines_one("", 2, "", false);
@ -736,8 +676,6 @@ static void test_string_extract_lines_one(const char *input, size_t i, const cha
} }
static void test_string_extract_line(void) { static void test_string_extract_line(void) {
log_info("/* %s */", __func__);
test_string_extract_lines_one("", 0, "", false); test_string_extract_lines_one("", 0, "", false);
test_string_extract_lines_one("", 1, "", false); test_string_extract_lines_one("", 1, "", false);
test_string_extract_lines_one("", 2, "", false); test_string_extract_lines_one("", 2, "", false);
@ -804,88 +742,6 @@ static void test_string_extract_line(void) {
test_string_extract_lines_one("\n\n\nx\n", 3, "x", false); test_string_extract_lines_one("\n\n\nx\n", 3, "x", false);
} }
static void test_string_contains_word_strv(void) {
log_info("/* %s */", __func__);
const char *w;
assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("a", "b"), NULL));
assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("a", "b"), &w));
assert_se(streq(w, "a"));
assert_se(!string_contains_word_strv("a b cc", NULL, STRV_MAKE("d"), &w));
assert_se(w == NULL);
assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("b", "a"), &w));
assert_se(streq(w, "a"));
assert_se(string_contains_word_strv("b a b cc", NULL, STRV_MAKE("b", "a", "b"), &w));
assert_se(streq(w, "b"));
assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("b", ""), &w));
assert_se(streq(w, "b"));
assert_se(!string_contains_word_strv("a b cc", NULL, STRV_MAKE(""), &w));
assert_se(w == NULL);
assert_se(string_contains_word_strv("a b cc", " ", STRV_MAKE(""), &w));
assert_se(streq(w, ""));
}
static void test_string_contains_word(void) {
log_info("/* %s */", __func__);
assert_se( string_contains_word("a b cc", NULL, "a"));
assert_se( string_contains_word("a b cc", NULL, "b"));
assert_se(!string_contains_word("a b cc", NULL, "c"));
assert_se( string_contains_word("a b cc", NULL, "cc"));
assert_se(!string_contains_word("a b cc", NULL, "d"));
assert_se(!string_contains_word("a b cc", NULL, "a b"));
assert_se(!string_contains_word("a b cc", NULL, "a b c"));
assert_se(!string_contains_word("a b cc", NULL, "b c"));
assert_se(!string_contains_word("a b cc", NULL, "b cc"));
assert_se(!string_contains_word("a b cc", NULL, "a "));
assert_se(!string_contains_word("a b cc", NULL, " b "));
assert_se(!string_contains_word("a b cc", NULL, " cc"));
assert_se( string_contains_word(" a b\t\tcc", NULL, "a"));
assert_se( string_contains_word(" a b\t\tcc", NULL, "b"));
assert_se(!string_contains_word(" a b\t\tcc", NULL, "c"));
assert_se( string_contains_word(" a b\t\tcc", NULL, "cc"));
assert_se(!string_contains_word(" a b\t\tcc", NULL, "d"));
assert_se(!string_contains_word(" a b\t\tcc", NULL, "a b"));
assert_se(!string_contains_word(" a b\t\tcc", NULL, "a b\t\tc"));
assert_se(!string_contains_word(" a b\t\tcc", NULL, "b\t\tc"));
assert_se(!string_contains_word(" a b\t\tcc", NULL, "b\t\tcc"));
assert_se(!string_contains_word(" a b\t\tcc", NULL, "a "));
assert_se(!string_contains_word(" a b\t\tcc", NULL, " b "));
assert_se(!string_contains_word(" a b\t\tcc", NULL, " cc"));
assert_se(!string_contains_word(" a b\t\tcc", NULL, ""));
assert_se(!string_contains_word(" a b\t\tcc", NULL, " "));
assert_se(!string_contains_word(" a b\t\tcc", NULL, " "));
assert_se( string_contains_word(" a b\t\tcc", " ", ""));
assert_se( string_contains_word(" a b\t\tcc", "\t", ""));
assert_se( string_contains_word(" a b\t\tcc", WHITESPACE, ""));
assert_se( string_contains_word("a:b:cc", ":#", "a"));
assert_se( string_contains_word("a:b:cc", ":#", "b"));
assert_se(!string_contains_word("a:b:cc", ":#", "c"));
assert_se( string_contains_word("a:b:cc", ":#", "cc"));
assert_se(!string_contains_word("a:b:cc", ":#", "d"));
assert_se(!string_contains_word("a:b:cc", ":#", "a:b"));
assert_se(!string_contains_word("a:b:cc", ":#", "a:b:c"));
assert_se(!string_contains_word("a:b:cc", ":#", "b:c"));
assert_se(!string_contains_word("a#b#cc", ":#", "b:cc"));
assert_se( string_contains_word("a#b#cc", ":#", "b"));
assert_se( string_contains_word("a#b#cc", ":#", "cc"));
assert_se(!string_contains_word("a:b:cc", ":#", "a:"));
assert_se(!string_contains_word("a:b cc", ":#", "b"));
assert_se( string_contains_word("a:b cc", ":#", "b cc"));
assert_se(!string_contains_word("a:b:cc", ":#", ":cc"));
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG); test_setup_logging(LOG_DEBUG);
@ -921,8 +777,6 @@ int main(int argc, char *argv[]) {
test_memory_startswith_no_case(); test_memory_startswith_no_case();
test_string_truncate_lines(); test_string_truncate_lines();
test_string_extract_line(); test_string_extract_line();
test_string_contains_word_strv();
test_string_contains_word();
return 0; return 0;
} }

View File

@ -100,12 +100,6 @@ static const char* const input_table_quoted[] = {
NULL, NULL,
}; };
static const char* const input_table_quoted_joined[] = {
"one",
" two\t three " " four five",
NULL,
};
static const char* const input_table_one[] = { static const char* const input_table_one[] = {
"one", "one",
NULL, NULL,
@ -238,7 +232,7 @@ static void test_strv_unquote(const char *quoted, char **list) {
log_info("/* %s */", __func__); log_info("/* %s */", __func__);
r = strv_split_full(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE); r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE);
assert_se(r == (int) strv_length(list)); assert_se(r == (int) strv_length(list));
assert_se(s); assert_se(s);
j = strv_join(s, " | "); j = strv_join(s, " | ");
@ -257,7 +251,7 @@ static void test_invalid_unquote(const char *quoted) {
log_info("/* %s */", __func__); log_info("/* %s */", __func__);
r = strv_split_full(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE); r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE);
assert_se(s == NULL); assert_se(s == NULL);
assert_se(r == -EINVAL); assert_se(r == -EINVAL);
} }
@ -287,39 +281,47 @@ static void test_strv_split(void) {
strv_free_erase(l); strv_free_erase(l);
assert_se(strv_split_full(&l, " one two\t three", NULL, 0) == 3); l = strv_split_full(" one two\t three", NULL, 0);
assert_se(l);
assert_se(strv_equal(l, (char**) input_table_multiple)); assert_se(strv_equal(l, (char**) input_table_multiple));
strv_free_erase(l); strv_free_erase(l);
assert_se(strv_split_full(&l, " 'one' \" two\t three \" ' four five'", NULL, EXTRACT_UNQUOTE) == 3); l = strv_split_full(" 'one' \" two\t three \" ' four five'", NULL, SPLIT_QUOTES);
assert_se(l);
assert_se(strv_equal(l, (char**) input_table_quoted)); assert_se(strv_equal(l, (char**) input_table_quoted));
l = strv_free_erase(l); strv_free_erase(l);
/* missing last quote causes extraction to fail. */ /* missing last quote ignores the last element. */
assert_se(strv_split_full(&l, " 'one' \" two\t three \" ' four five", NULL, EXTRACT_UNQUOTE) == -EINVAL); l = strv_split_full(" 'one' \" two\t three \" ' four five' ' ignored element ", NULL, SPLIT_QUOTES);
assert_se(!l); assert_se(l);
/* missing last quote, but the last element is _not_ ignored with EXTRACT_RELAX. */
assert_se(strv_split_full(&l, " 'one' \" two\t three \" ' four five", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX) == 3);
assert_se(strv_equal(l, (char**) input_table_quoted)); assert_se(strv_equal(l, (char**) input_table_quoted));
l = strv_free_erase(l); strv_free_erase(l);
/* missing separator between items */ /* missing last quote, but the last element is _not_ ignored with SPLIT_RELAX. */
assert_se(strv_split_full(&l, " 'one' \" two\t three \"' four five'", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX) == 2); l = strv_split_full(" 'one' \" two\t three \" ' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX);
assert_se(strv_equal(l, (char**) input_table_quoted_joined)); assert_se(l);
assert_se(strv_equal(l, (char**) input_table_quoted));
l = strv_free_erase(l); strv_free_erase(l);
assert_se(strv_split_full(&l, " 'one' \" two\t three \"' four five", NULL, /* missing separator between */
EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_CUNESCAPE_RELAX) == 2); l = strv_split_full(" 'one' \" two\t three \"' four five'", NULL, SPLIT_QUOTES | SPLIT_RELAX);
assert_se(strv_equal(l, (char**) input_table_quoted_joined)); assert_se(l);
assert_se(strv_equal(l, (char**) input_table_quoted));
l = strv_free_erase(l); strv_free_erase(l);
assert_se(strv_split_full(&l, "\\", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_CUNESCAPE_RELAX) == 1); l = strv_split_full(" 'one' \" two\t three \"' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX);
assert_se(l);
assert_se(strv_equal(l, (char**) input_table_quoted));
strv_free_erase(l);
l = strv_split_full("\\", NULL, SPLIT_QUOTES | SPLIT_RELAX);
assert_se(l);
assert_se(strv_equal(l, STRV_MAKE("\\"))); assert_se(strv_equal(l, STRV_MAKE("\\")));
} }
@ -331,70 +333,71 @@ static void test_strv_split_empty(void) {
l = strv_split("", WHITESPACE); l = strv_split("", WHITESPACE);
assert_se(l); assert_se(l);
assert_se(strv_isempty(l)); assert_se(strv_isempty(l));
l = strv_free(l);
assert_se(l = strv_split("", NULL));
assert_se(strv_isempty(l));
l = strv_free(l);
assert_se(strv_split_full(&l, "", NULL, 0) == 0);
assert_se(l);
assert_se(strv_isempty(l));
l = strv_free(l);
assert_se(strv_split_full(&l, "", NULL, EXTRACT_UNQUOTE) == 0);
assert_se(l);
assert_se(strv_isempty(l));
l = strv_free(l);
assert_se(strv_split_full(&l, "", WHITESPACE, EXTRACT_UNQUOTE) == 0);
assert_se(l);
assert_se(strv_isempty(l));
l = strv_free(l);
assert_se(strv_split_full(&l, "", WHITESPACE, EXTRACT_UNQUOTE | EXTRACT_RELAX) == 0);
assert_se(l);
assert_se(strv_isempty(l));
strv_free(l); strv_free(l);
l = strv_split("", NULL);
assert_se(l);
assert_se(strv_isempty(l));
strv_free(l);
l = strv_split_full("", NULL, 0);
assert_se(l);
assert_se(strv_isempty(l));
strv_free(l);
l = strv_split_full("", NULL, SPLIT_QUOTES);
assert_se(l);
assert_se(strv_isempty(l));
strv_free(l);
l = strv_split_full("", WHITESPACE, SPLIT_QUOTES);
assert_se(l);
assert_se(strv_isempty(l));
strv_free(l);
l = strv_split_full("", WHITESPACE, SPLIT_QUOTES | SPLIT_RELAX);
assert_se(l);
assert_se(strv_isempty(l));
strv_free(l);
l = strv_split(" ", WHITESPACE); l = strv_split(" ", WHITESPACE);
assert_se(l); assert_se(l);
assert_se(strv_isempty(l)); assert_se(strv_isempty(l));
strv_free(l);
strv_free(l);
l = strv_split(" ", NULL); l = strv_split(" ", NULL);
assert_se(l); assert_se(l);
assert_se(strv_isempty(l)); assert_se(strv_isempty(l));
l = strv_free(l);
assert_se(strv_split_full(&l, " ", NULL, 0) == 0); strv_free(l);
l = strv_split_full(" ", NULL, 0);
assert_se(l); assert_se(l);
assert_se(strv_isempty(l)); assert_se(strv_isempty(l));
l = strv_free(l);
assert_se(strv_split_full(&l, " ", WHITESPACE, EXTRACT_UNQUOTE) == 0); strv_free(l);
l = strv_split_full(" ", WHITESPACE, SPLIT_QUOTES);
assert_se(l); assert_se(l);
assert_se(strv_isempty(l)); assert_se(strv_isempty(l));
l = strv_free(l);
assert_se(strv_split_full(&l, " ", NULL, EXTRACT_UNQUOTE) == 0); strv_free(l);
l = strv_split_full(" ", NULL, SPLIT_QUOTES);
assert_se(l); assert_se(l);
assert_se(strv_isempty(l)); assert_se(strv_isempty(l));
l = strv_free(l);
assert_se(strv_split_full(&l, " ", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX) == 0); strv_free(l);
l = strv_split_full(" ", NULL, SPLIT_QUOTES | SPLIT_RELAX);
assert_se(l); assert_se(l);
assert_se(strv_isempty(l)); assert_se(strv_isempty(l));
} }
static void test_strv_split_full(void) { static void test_strv_split_extract(void) {
_cleanup_strv_free_ char **l = NULL; _cleanup_strv_free_ char **l = NULL;
const char *str = ":foo\\:bar::waldo:"; const char *str = ":foo\\:bar::waldo:";
int r; int r;
log_info("/* %s */", __func__); log_info("/* %s */", __func__);
r = strv_split_full(&l, str, ":", EXTRACT_DONT_COALESCE_SEPARATORS); r = strv_split_extract(&l, str, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
assert_se(r == (int) strv_length(l)); assert_se(r == (int) strv_length(l));
assert_se(streq_ptr(l[0], "")); assert_se(streq_ptr(l[0], ""));
assert_se(streq_ptr(l[1], "foo:bar")); assert_se(streq_ptr(l[1], "foo:bar"));
@ -1023,7 +1026,7 @@ int main(int argc, char *argv[]) {
test_strv_split(); test_strv_split();
test_strv_split_empty(); test_strv_split_empty();
test_strv_split_full(); test_strv_split_extract();
test_strv_split_colon_pairs(); test_strv_split_colon_pairs();
test_strv_split_newlines(); test_strv_split_newlines();
test_strv_split_nulstr(); test_strv_split_nulstr();

View File

@ -320,8 +320,7 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr
case NET_ADDR_PERM: case NET_ADDR_PERM:
break; break;
default: default:
log_device_warning(device, "Unknown addr_assign_type %u, ignoring", addr_type); return log_device_warning(device, "Unknown addr_assign_type %u, ignoring", addr_type);
return 0;
} }
if (want_random == (addr_type == NET_ADDR_RANDOM)) if (want_random == (addr_type == NET_ADDR_RANDOM))

View File

@ -87,7 +87,7 @@ static int map_keycode(sd_device *dev, int fd, int scancode, const char *keycode
return 0; return 0;
} }
static const char* parse_token(const char *current, int32_t *val_out) { static char* parse_token(const char *current, int32_t *val_out) {
char *next; char *next;
int32_t val; int32_t val;
@ -109,7 +109,7 @@ static const char* parse_token(const char *current, int32_t *val_out) {
static int override_abs(sd_device *dev, int fd, unsigned evcode, const char *value) { static int override_abs(sd_device *dev, int fd, unsigned evcode, const char *value) {
struct input_absinfo absinfo; struct input_absinfo absinfo;
const char *next; char *next;
int r; int r;
r = ioctl(fd, EVIOCGABS(evcode), &absinfo); r = ioctl(fd, EVIOCGABS(evcode), &absinfo);
@ -122,7 +122,7 @@ static int override_abs(sd_device *dev, int fd, unsigned evcode, const char *val
next = parse_token(next, &absinfo.fuzz); next = parse_token(next, &absinfo.fuzz);
next = parse_token(next, &absinfo.flat); next = parse_token(next, &absinfo.flat);
if (!next) if (!next)
return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Failed to parse EV_ABS override '%s'", value); return log_device_error(dev, "Failed to parse EV_ABS override '%s'", value);
log_device_debug(dev, "keyboard: %x overridden with %"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32, log_device_debug(dev, "keyboard: %x overridden with %"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32,
evcode, absinfo.minimum, absinfo.maximum, absinfo.resolution, absinfo.fuzz, absinfo.flat); evcode, absinfo.minimum, absinfo.maximum, absinfo.resolution, absinfo.fuzz, absinfo.flat);

View File

@ -50,7 +50,7 @@ static int builtin_uaccess(sd_device *dev, int argc, char *argv[], bool test) {
r = devnode_acl(path, true, false, 0, true, uid); r = devnode_acl(path, true, false, 0, true, uid);
if (r < 0) { if (r < 0) {
log_device_full_errno(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL: %m"); log_device_full(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL: %m");
goto finish; goto finish;
} }
@ -64,7 +64,7 @@ finish:
/* Better be safe than sorry and reset ACL */ /* Better be safe than sorry and reset ACL */
k = devnode_acl(path, true, false, 0, false, 0); k = devnode_acl(path, true, false, 0, false, 0);
if (k < 0) { if (k < 0) {
log_device_full_errno(dev, k == -ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL: %m"); log_device_full(dev, k == -ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL: %m");
if (r >= 0) if (r >= 0)
r = k; r = k;
} }

View File

@ -109,7 +109,6 @@ UdevBuiltinCommand udev_builtin_lookup(const char *command) {
int udev_builtin_run(sd_device *dev, UdevBuiltinCommand cmd, const char *command, bool test) { int udev_builtin_run(sd_device *dev, UdevBuiltinCommand cmd, const char *command, bool test) {
_cleanup_strv_free_ char **argv = NULL; _cleanup_strv_free_ char **argv = NULL;
int r;
assert(dev); assert(dev);
assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX); assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX);
@ -118,10 +117,9 @@ int udev_builtin_run(sd_device *dev, UdevBuiltinCommand cmd, const char *command
if (!builtins[cmd]) if (!builtins[cmd])
return -EOPNOTSUPP; return -EOPNOTSUPP;
r = strv_split_full(&argv, command, NULL, argv = strv_split_full(command, NULL, SPLIT_QUOTES | SPLIT_RELAX);
EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_RETAIN_ESCAPE); if (!argv)
if (r < 0) return -ENOMEM;
return r;
/* we need '0' here to reset the internal state */ /* we need '0' here to reset the internal state */
optind = 0; optind = 0;

View File

@ -633,7 +633,7 @@ static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userd
if (si->si_status == 0) if (si->si_status == 0)
log_device_debug(spawn->device, "Process '%s' succeeded.", spawn->cmd); log_device_debug(spawn->device, "Process '%s' succeeded.", spawn->cmd);
else else
log_device_full(spawn->device, spawn->accept_failure ? LOG_DEBUG : LOG_WARNING, log_device_full(spawn->device, spawn->accept_failure ? LOG_DEBUG : LOG_WARNING, 0,
"Process '%s' failed with exit code %i.", spawn->cmd, si->si_status); "Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
ret = si->si_status; ret = si->si_status;
break; break;
@ -747,9 +747,9 @@ int udev_event_spawn(UdevEvent *event,
return log_device_error_errno(event->dev, errno, return log_device_error_errno(event->dev, errno,
"Failed to create pipe for command '%s': %m", cmd); "Failed to create pipe for command '%s': %m", cmd);
r = strv_split_full(&argv, cmd, NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_RETAIN_ESCAPE); argv = strv_split_full(cmd, NULL, SPLIT_QUOTES|SPLIT_RELAX);
if (r < 0) if (!argv)
return log_device_error_errno(event->dev, r, "Failed to split command: %m"); return log_oom();
if (isempty(argv[0])) if (isempty(argv[0]))
return log_device_error_errno(event->dev, SYNTHETIC_ERRNO(EINVAL), return log_device_error_errno(event->dev, SYNTHETIC_ERRNO(EINVAL),

View File

@ -324,13 +324,13 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
r = chmod_and_chown(devnode, mode, uid, gid); r = chmod_and_chown(devnode, mode, uid, gid);
if (r < 0) if (r < 0)
log_device_full_errno(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, log_device_full(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r,
"Failed to set owner/mode of %s to uid=" UID_FMT "Failed to set owner/mode of %s to uid=" UID_FMT
", gid=" GID_FMT ", mode=%#o: %m", ", gid=" GID_FMT ", mode=%#o: %m",
devnode, devnode,
uid_is_valid(uid) ? uid : stats.st_uid, uid_is_valid(uid) ? uid : stats.st_uid,
gid_is_valid(gid) ? gid : stats.st_gid, gid_is_valid(gid) ? gid : stats.st_gid,
mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777); mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777);
} else } else
log_device_debug(dev, "Preserve permissions of %s, uid=" UID_FMT ", gid=" GID_FMT ", mode=%#o", log_device_debug(dev, "Preserve permissions of %s, uid=" UID_FMT ", gid=" GID_FMT ", mode=%#o",
devnode, devnode,
@ -347,8 +347,8 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
q = mac_selinux_apply(devnode, label); q = mac_selinux_apply(devnode, label);
if (q < 0) if (q < 0)
log_device_full_errno(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, log_device_full(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q,
"SECLABEL: failed to set SELinux label '%s': %m", label); "SECLABEL: failed to set SELinux label '%s': %m", label);
else else
log_device_debug(dev, "SECLABEL: set SELinux label '%s'", label); log_device_debug(dev, "SECLABEL: set SELinux label '%s'", label);
@ -357,8 +357,8 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
q = mac_smack_apply(devnode, SMACK_ATTR_ACCESS, label); q = mac_smack_apply(devnode, SMACK_ATTR_ACCESS, label);
if (q < 0) if (q < 0)
log_device_full_errno(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, log_device_full(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q,
"SECLABEL: failed to set SMACK label '%s': %m", label); "SECLABEL: failed to set SMACK label '%s': %m", label);
else else
log_device_debug(dev, "SECLABEL: set SMACK label '%s'", label); log_device_debug(dev, "SECLABEL: set SMACK label '%s'", label);

View File

@ -182,46 +182,43 @@ struct UdevRules {
/*** Logging helpers ***/ /*** Logging helpers ***/
#define log_rule_full_errno(device, rules, level, error, fmt, ...) \ #define log_rule_full(device, rules, level, error, fmt, ...) \
({ \ ({ \
UdevRules *_r = (rules); \ UdevRules *_r = (rules); \
UdevRuleFile *_f = _r ? _r->current_file : NULL; \ UdevRuleFile *_f = _r ? _r->current_file : NULL; \
UdevRuleLine *_l = _f ? _f->current_line : NULL; \ UdevRuleLine *_l = _f ? _f->current_line : NULL; \
const char *_n = _f ? _f->filename : NULL; \ const char *_n = _f ? _f->filename : NULL; \
\ \
log_device_full_errno(device, level, error, "%s:%u " fmt, \ log_device_full(device, level, error, "%s:%u " fmt, \
strna(_n), _l ? _l->line_number : 0, \ strna(_n), _l ? _l->line_number : 0, \
##__VA_ARGS__); \ ##__VA_ARGS__); \
}) })
#define log_rule_full(device, rules, level, ...) (void) log_rule_full_errno(device, rules, level, 0, __VA_ARGS__) #define log_rule_debug(device, rules, ...) log_rule_full(device, rules, LOG_DEBUG, 0, ##__VA_ARGS__)
#define log_rule_info(device, rules, ...) log_rule_full(device, rules, LOG_INFO, 0, ##__VA_ARGS__)
#define log_rule_notice(device, rules, ...) log_rule_full(device, rules, LOG_NOTICE, 0, ##__VA_ARGS__)
#define log_rule_warning(device, rules, ...) log_rule_full(device, rules, LOG_WARNING, 0, ##__VA_ARGS__)
#define log_rule_error(device, rules, ...) log_rule_full(device, rules, LOG_ERR, 0, ##__VA_ARGS__)
#define log_rule_debug(device, rules, ...) log_rule_full_errno(device, rules, LOG_DEBUG, 0, __VA_ARGS__) #define log_rule_debug_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_DEBUG, error, ##__VA_ARGS__)
#define log_rule_info(device, rules, ...) log_rule_full(device, rules, LOG_INFO, __VA_ARGS__) #define log_rule_info_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_INFO, error, ##__VA_ARGS__)
#define log_rule_notice(device, rules, ...) log_rule_full(device, rules, LOG_NOTICE, __VA_ARGS__) #define log_rule_notice_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_NOTICE, error, ##__VA_ARGS__)
#define log_rule_warning(device, rules, ...) log_rule_full(device, rules, LOG_WARNING, __VA_ARGS__) #define log_rule_warning_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_WARNING, error, ##__VA_ARGS__)
#define log_rule_error(device, rules, ...) log_rule_full(device, rules, LOG_ERR, __VA_ARGS__) #define log_rule_error_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_ERR, error, ##__VA_ARGS__)
#define log_rule_debug_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_DEBUG, error, __VA_ARGS__) #define log_token_full(rules, ...) log_rule_full(NULL, rules, ##__VA_ARGS__)
#define log_rule_info_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_INFO, error, __VA_ARGS__)
#define log_rule_notice_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_NOTICE, error, __VA_ARGS__)
#define log_rule_warning_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_WARNING, error, __VA_ARGS__)
#define log_rule_error_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_ERR, error, __VA_ARGS__)
#define log_token_full_errno(rules, level, error, ...) log_rule_full_errno(NULL, rules, level, error, __VA_ARGS__) #define log_token_debug(rules, ...) log_token_full(rules, LOG_DEBUG, 0, ##__VA_ARGS__)
#define log_token_full(rules, level, ...) (void) log_token_full_errno(rules, level, 0, __VA_ARGS__) #define log_token_info(rules, ...) log_token_full(rules, LOG_INFO, 0, ##__VA_ARGS__)
#define log_token_notice(rules, ...) log_token_full(rules, LOG_NOTICE, 0, ##__VA_ARGS__)
#define log_token_warning(rules, ...) log_token_full(rules, LOG_WARNING, 0, ##__VA_ARGS__)
#define log_token_error(rules, ...) log_token_full(rules, LOG_ERR, 0, ##__VA_ARGS__)
#define log_token_debug(rules, ...) log_token_full_errno(rules, LOG_DEBUG, 0, __VA_ARGS__) #define log_token_debug_errno(rules, error, ...) log_token_full(rules, LOG_DEBUG, error, ##__VA_ARGS__)
#define log_token_info(rules, ...) log_token_full(rules, LOG_INFO, __VA_ARGS__) #define log_token_info_errno(rules, error, ...) log_token_full(rules, LOG_INFO, error, ##__VA_ARGS__)
#define log_token_notice(rules, ...) log_token_full(rules, LOG_NOTICE, __VA_ARGS__) #define log_token_notice_errno(rules, error, ...) log_token_full(rules, LOG_NOTICE, error, ##__VA_ARGS__)
#define log_token_warning(rules, ...) log_token_full(rules, LOG_WARNING, __VA_ARGS__) #define log_token_warning_errno(rules, error, ...) log_token_full(rules, LOG_WARNING, error, ##__VA_ARGS__)
#define log_token_error(rules, ...) log_token_full(rules, LOG_ERR, __VA_ARGS__) #define log_token_error_errno(rules, error, ...) log_token_full(rules, LOG_ERR, error, ##__VA_ARGS__)
#define log_token_debug_errno(rules, error, ...) log_token_full_errno(rules, LOG_DEBUG, error, __VA_ARGS__)
#define log_token_info_errno(rules, error, ...) log_token_full_errno(rules, LOG_INFO, error, __VA_ARGS__)
#define log_token_notice_errno(rules, error, ...) log_token_full_errno(rules, LOG_NOTICE, error, __VA_ARGS__)
#define log_token_warning_errno(rules, error, ...) log_token_full_errno(rules, LOG_WARNING, error, __VA_ARGS__)
#define log_token_error_errno(rules, error, ...) log_token_full_errno(rules, LOG_ERR, error, __VA_ARGS__)
#define _log_token_invalid(rules, key, type) \ #define _log_token_invalid(rules, key, type) \
log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), \ log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), \

View File

@ -97,8 +97,10 @@ int udev_watch_begin(sd_device *dev) {
log_device_debug(dev, "Adding watch on '%s'", devnode); log_device_debug(dev, "Adding watch on '%s'", devnode);
wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE); wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE);
if (wd < 0) if (wd < 0)
return log_device_full_errno(dev, errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, return log_device_full(dev,
"Failed to add device '%s' to watch: %m", devnode); errno == ENOENT ? LOG_DEBUG : LOG_ERR,
errno,
"Failed to add device '%s' to watch: %m", devnode);
device_set_watch_handle(dev, wd); device_set_watch_handle(dev, wd);

View File

@ -1686,11 +1686,8 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
/* Bump receiver buffer, but only if we are not called via socket activation, as in that /* Bump receiver buffer, but only if we are not called via socket activation, as in that
* case systemd sets the receive buffer size for us, and the value in the .socket unit * case systemd sets the receive buffer size for us, and the value in the .socket unit
* should take full effect. */ * should take full effect. */
if (fd_uevent < 0) { if (fd_uevent < 0)
r = sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024); (void) sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024);
if (r < 0)
log_warning_errno(r, "Failed to set receive buffer size for device monitor, ignoring: %m");
}
r = device_monitor_enable_receiving(manager->monitor); r = device_monitor_enable_receiving(manager->monitor);
if (r < 0) if (r < 0)

View File

@ -385,9 +385,9 @@ int xdg_autostart_format_exec_start(
* NOTE: Technically, XDG only specifies " as quotes, while this also * NOTE: Technically, XDG only specifies " as quotes, while this also
* accepts '. * accepts '.
*/ */
r = strv_split_full(&exec_split, exec, NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX); exec_split = strv_split_full(exec, WHITESPACE, SPLIT_QUOTES | SPLIT_RELAX);
if (r < 0) if (!exec_split)
return r; return -ENOMEM;
if (strv_isempty(exec_split)) if (strv_isempty(exec_split))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Exec line is empty"); return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Exec line is empty");