Compare commits
51 Commits
a1447e77a7
...
197db625a3
Author | SHA1 | Date |
---|---|---|
Lennart Poettering | 197db625a3 | |
Robert Marko | adbb2b6afe | |
Franck Bui | 6e220b4b88 | |
Lennart Poettering | 12ce0f4173 | |
Lennart Poettering | a6b3be1abf | |
Lennart Poettering | 244d9793ee | |
Lennart Poettering | 39c4e2c1a1 | |
Tobias Kaufmann | 198dc17845 | |
Tobias Kaufmann | 16fcb1918a | |
Zbigniew Jędrzejewski-Szmek | 90e30d767a | |
Zbigniew Jędrzejewski-Szmek | 03b62851a9 | |
Zbigniew Jędrzejewski-Szmek | 0645b83a40 | |
Zbigniew Jędrzejewski-Szmek | d59d954d7f | |
Zbigniew Jędrzejewski-Szmek | 45638a63c0 | |
Zbigniew Jędrzejewski-Szmek | 0e8d185938 | |
Zbigniew Jędrzejewski-Szmek | ecaf258eb4 | |
Zbigniew Jędrzejewski-Szmek | 087908c140 | |
Zbigniew Jędrzejewski-Szmek | 2417658d6a | |
Zbigniew Jędrzejewski-Szmek | da277e90a4 | |
Zbigniew Jędrzejewski-Szmek | cc24f0b872 | |
Zbigniew Jędrzejewski-Szmek | dd2fff3a18 | |
Zbigniew Jędrzejewski-Szmek | 7896ad8f66 | |
Zbigniew Jędrzejewski-Szmek | dd630d3cac | |
Zbigniew Jędrzejewski-Szmek | 0ef14adc1c | |
Zbigniew Jędrzejewski-Szmek | aa3b40c3f9 | |
Zbigniew Jędrzejewski-Szmek | 87a4d416e5 | |
Zbigniew Jędrzejewski-Szmek | ae7ef63f21 | |
Zbigniew Jędrzejewski-Szmek | 46ed9f4ce1 | |
Yu Watanabe | e77f52e5f9 | |
Yu Watanabe | a725efb08b | |
Yu Watanabe | d31f33e3c9 | |
Yu Watanabe | e13af7bdb6 | |
Yu Watanabe | ded71ab3bc | |
Yu Watanabe | 2807a79424 | |
Yu Watanabe | d9d9b2a0ae | |
Yu Watanabe | b92f350789 | |
Yu Watanabe | 1263c85ef3 | |
Yu Watanabe | 8c63924c8d | |
Yu Watanabe | d157714b68 | |
Yu Watanabe | 8ed6f81ba3 | |
Yu Watanabe | 93c5b90459 | |
Yu Watanabe | 38104ee2a5 | |
Yu Watanabe | ab54f12b78 | |
Yu Watanabe | 09c69ecaeb | |
Yu Watanabe | a718b951ac | |
Yu Watanabe | 3b4e123173 | |
Zbigniew Jędrzejewski-Szmek | 434fef6de3 | |
Zbigniew Jędrzejewski-Szmek | 46bf625aca | |
Zbigniew Jędrzejewski-Szmek | 81823e6c12 | |
Zbigniew Jędrzejewski-Szmek | 53cd7f3374 | |
Zbigniew Jędrzejewski-Szmek | 0176728a73 |
|
@ -74,9 +74,6 @@ 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
|
||||||
|
|
|
@ -199,10 +199,11 @@
|
||||||
<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 and sleep keys and the lid switch to trigger
|
system power, reboot and sleep keys and the lid switch to trigger
|
||||||
actions such as system power-off or suspend. Can be one of
|
actions such as system power-off, reboot or suspend. Can be one of
|
||||||
<literal>ignore</literal>,
|
<literal>ignore</literal>,
|
||||||
<literal>poweroff</literal>,
|
<literal>poweroff</literal>,
|
||||||
<literal>reboot</literal>,
|
<literal>reboot</literal>,
|
||||||
|
@ -219,7 +220,8 @@
|
||||||
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>.
|
defaults to <literal>poweroff</literal>, <varname>HandleRebootKey=</varname>
|
||||||
|
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>.
|
||||||
|
@ -240,7 +242,8 @@
|
||||||
<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
|
||||||
|
@ -253,20 +256,23 @@
|
||||||
<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 and sleep keys and the lid switch are triggered are subject
|
takes when the power, reboot and sleep keys and the lid switch are triggered are subject
|
||||||
to high-level inhibitor locks ("shutdown", "sleep", "idle"). Low level inhibitor
|
to high-level inhibitor locks ("shutdown", "reboot", "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", "sleep", and "idle" inhibitor locks are ignored.
|
"shutdown", "reboot" "sleep", and "idle" inhibitor locks are ignored.
|
||||||
<varname>PowerKeyIgnoreInhibited=</varname>,
|
<varname>PowerKeyIgnoreInhibited=</varname>,
|
||||||
<varname>SuspendKeyIgnoreInhibited=</varname>, and
|
<varname>SuspendKeyIgnoreInhibited=</varname>,
|
||||||
<varname>HibernateKeyIgnoreInhibited=</varname> default to <literal>no</literal>.
|
<varname>HibernateKeyIgnoreInhibited=</varname> and
|
||||||
|
<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
|
||||||
|
|
|
@ -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>ifindices</parameter></paramdef>
|
<paramdef>int **<parameter>ret_ifindices</parameter></paramdef>
|
||||||
</funcprototype>
|
</funcprototype>
|
||||||
</funcsynopsis>
|
</funcsynopsis>
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
|
@ -53,21 +53,22 @@
|
||||||
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
|
<para><function>sd_machine_get_ifindices()</function> may be used to determine the numeric indices of the
|
||||||
to determine the numeric indices of the network interfaces on the
|
network interfaces on the host that are pointing towards the specified locally running virtual machine or
|
||||||
host that are pointing towards the specified locally running
|
container. The vm or container must be registered with
|
||||||
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 returned array needs to be freed with the libc <citerefentry
|
The output parameter <parameter>ret_ifindices</parameter> may be passed as <constant>NULL</constant> when
|
||||||
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
the output value is not needed. The returned array needs to be freed with the libc <citerefentry
|
||||||
call after use.</para>
|
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry> call after
|
||||||
|
use.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Return Value</title>
|
<title>Return Value</title>
|
||||||
|
|
||||||
<para>On success, these calls return 0 or a positive integer. On failure, these calls return a negative
|
<para>On success, these functions return a non-negative integer.
|
||||||
errno-style error code.</para>
|
<function>sd_machine_get_ifindices()</function> returns the number of the relevant network interfaces.
|
||||||
|
On failure, these calls return a negative errno-style error code.</para>
|
||||||
|
|
||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Errors</title>
|
<title>Errors</title>
|
||||||
|
|
|
@ -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>sessions</parameter></paramdef>
|
<paramdef>char ***<parameter>ret_sessions</parameter></paramdef>
|
||||||
<paramdef>uid_t **<parameter>uid</parameter></paramdef>
|
<paramdef>uid_t **<parameter>ret_uids</parameter></paramdef>
|
||||||
<paramdef>unsigned int *<parameter>n_uids</parameter></paramdef>
|
<paramdef>unsigned int *<parameter>ret_n_uids</parameter></paramdef>
|
||||||
</funcprototype>
|
</funcprototype>
|
||||||
|
|
||||||
<funcprototype>
|
<funcprototype>
|
||||||
|
@ -68,21 +68,16 @@
|
||||||
<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
|
<para><function>sd_seat_get_sessions()</function> may be used to determine all sessions on the specified
|
||||||
determine all sessions on the specified seat. Returns two arrays,
|
seat. Returns two arrays, one (<constant>NULL</constant> terminated) with the session identifiers of the
|
||||||
one (<constant>NULL</constant> terminated) with the session
|
sessions and one with the user identifiers of the Unix users the sessions belong to. An additional
|
||||||
identifiers of the sessions and one with the user identifiers of
|
parameter may be used to return the number of entries in the latter array. This value is the same as the
|
||||||
the Unix users the sessions belong to. An additional parameter may
|
return value if the return value is nonnegative. The output parameters may be passed as
|
||||||
be used to return the number of entries in the latter array. This
|
<constant>NULL</constant> in case these output values are not needed. The arrays and the strings
|
||||||
value is the same the return value, if the latter is nonnegative.
|
referenced by them need to be freed with the libc <citerefentry
|
||||||
The two arrays and the last parameter may be passed as
|
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry> call after
|
||||||
<constant>NULL</constant> in case these values need not to be
|
use. Note that instead of an empty array <constant>NULL</constant> may be returned and should be
|
||||||
determined. The arrays and the strings referenced by them need to
|
considered equivalent to an empty array.</para>
|
||||||
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.
|
||||||
|
|
|
@ -652,14 +652,13 @@ 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 **path) {
|
int cg_pid_get_path(const char *controller, pid_t pid, char **ret_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))
|
||||||
|
@ -675,8 +674,6 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **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");
|
||||||
|
@ -688,13 +685,13 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_cleanup_free_ char *line = NULL;
|
_cleanup_free_ char *line = NULL;
|
||||||
char *e, *p;
|
char *e;
|
||||||
|
|
||||||
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)
|
||||||
break;
|
return -ENODATA;
|
||||||
|
|
||||||
if (unified) {
|
if (unified) {
|
||||||
e = startswith(line, "0:");
|
e = startswith(line, "0:");
|
||||||
|
@ -706,9 +703,6 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **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)
|
||||||
|
@ -718,31 +712,27 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
|
||||||
e = strchr(l, ':');
|
e = strchr(l, ':');
|
||||||
if (!e)
|
if (!e)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
*e = 0;
|
*e = 0;
|
||||||
FOREACH_WORD_SEPARATOR(word, k, l, ",", state)
|
|
||||||
if (k == cs && memcmp(word, controller_str, cs) == 0) {
|
r = string_contains_word(l, ",", controller_str);
|
||||||
found = true;
|
if (r < 0)
|
||||||
break;
|
return r;
|
||||||
}
|
if (r == 0)
|
||||||
if (!found)
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = strdup(e + 1);
|
char *path = strdup(e + 1);
|
||||||
if (!p)
|
if (!path)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Truncate suffix indicating the process is a zombie */
|
/* Truncate suffix indicating the process is a zombie */
|
||||||
e = endswith(p, " (deleted)");
|
e = endswith(path, " (deleted)");
|
||||||
if (e)
|
if (e)
|
||||||
*e = 0;
|
*e = 0;
|
||||||
|
|
||||||
*path = p;
|
*ret_path = path;
|
||||||
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) {
|
||||||
|
|
|
@ -687,7 +687,7 @@ char **replace_env_argv(char **argv, char **env) {
|
||||||
if (e) {
|
if (e) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE);
|
r = strv_split_full(&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);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#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) {
|
||||||
|
|
|
@ -538,6 +538,9 @@ 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 }; \
|
||||||
|
|
|
@ -617,40 +617,62 @@ bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd_inc_sndbuf(int fd, size_t n) {
|
int fd_set_sndbuf(int fd, size_t n, bool increase) {
|
||||||
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) && (size_t) value >= n*2)
|
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* If we have the privileges we will ignore the kernel limit. */
|
/* First, try to set the buffer size with SO_SNDBUF. */
|
||||||
|
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) {
|
/* SO_SNDBUF above may set to the kernel limit, instead of the requested size.
|
||||||
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
|
* So, we need to check the actual buffer size here. */
|
||||||
if (r < 0)
|
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
|
||||||
return r;
|
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. */
|
||||||
|
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd_inc_rcvbuf(int fd, size_t n) {
|
int fd_set_rcvbuf(int fd, size_t n, bool increase) {
|
||||||
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) && (size_t) value >= n*2)
|
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* If we have the privileges we will ignore the kernel limit. */
|
/* First, try to set the buffer size with SO_RCVBUF. */
|
||||||
|
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) {
|
/* SO_RCVBUF above may set to the kernel limit, instead of the requested size.
|
||||||
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
|
* So, we need to check the actual buffer size here. */
|
||||||
if (r < 0)
|
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
|
||||||
return r;
|
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. */
|
||||||
|
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,8 +118,14 @@ 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_inc_sndbuf(int fd, size_t n);
|
int fd_set_sndbuf(int fd, size_t n, bool increase);
|
||||||
int fd_inc_rcvbuf(int fd, size_t n);
|
static inline int fd_inc_sndbuf(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);
|
||||||
|
|
|
@ -8,12 +8,14 @@
|
||||||
|
|
||||||
#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"
|
||||||
|
@ -110,83 +112,6 @@ 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;
|
||||||
|
@ -1207,3 +1132,30 @@ 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;
|
||||||
|
}
|
||||||
|
|
|
@ -108,24 +108,6 @@ 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_;
|
||||||
|
@ -280,3 +262,8 @@ 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);
|
||||||
|
}
|
||||||
|
|
|
@ -256,44 +256,6 @@ 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;
|
||||||
|
@ -317,7 +279,7 @@ char **strv_split_newlines(const char *s) {
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
|
int strv_split_full(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;
|
||||||
|
|
|
@ -72,13 +72,19 @@ 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_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
|
int strv_split_full(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
|
||||||
|
@ -123,10 +129,6 @@ 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; \
|
||||||
|
|
|
@ -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(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason,
|
log_unit_full_errno(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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m",
|
log_unit_full_errno(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, 0,
|
log_unit_full(u, u->warned_clamping_cpu_quota_period ? LOG_DEBUG : LOG_WARNING,
|
||||||
"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(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
|
log_unit_full_errno(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(u, LOG_LEVEL_CGROUP_WRITE(r), r,
|
log_unit_full_errno(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(u, r == -EBUSY ? LOG_DEBUG : LOG_WARNING, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path);
|
log_unit_full_errno(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;
|
||||||
|
|
|
@ -4255,8 +4255,16 @@ static int exec_child(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is done before enforce_user, but ambient set
|
/* Ambient capabilities are cleared during setresuid() (in enforce_user()) even with
|
||||||
* does not survive over setresuid() if keep_caps is not set. */
|
* keep-caps 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) {
|
||||||
|
@ -4282,21 +4290,12 @@ static int exec_child(
|
||||||
if (!needs_ambient_hack &&
|
if (!needs_ambient_hack &&
|
||||||
context->capability_ambient_set != 0) {
|
context->capability_ambient_set != 0) {
|
||||||
|
|
||||||
/* Fix the ambient capabilities after user change. */
|
/* Raise 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4438,15 +4438,13 @@ int config_parse_set_status(
|
||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
size_t l;
|
|
||||||
const char *word, *state;
|
|
||||||
int r;
|
|
||||||
ExitStatusSet *status_set = data;
|
ExitStatusSet *status_set = data;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(filename);
|
assert(filename);
|
||||||
assert(lvalue);
|
assert(lvalue);
|
||||||
assert(rvalue);
|
assert(rvalue);
|
||||||
assert(data);
|
assert(status_set);
|
||||||
|
|
||||||
/* Empty assignment resets the list */
|
/* Empty assignment resets the list */
|
||||||
if (isempty(rvalue)) {
|
if (isempty(rvalue)) {
|
||||||
|
@ -4454,25 +4452,26 @@ int config_parse_set_status(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FOREACH_WORD(word, l, rvalue, state) {
|
for (const char *p = rvalue;;) {
|
||||||
_cleanup_free_ char *temp;
|
_cleanup_free_ char *word = NULL;
|
||||||
Bitmap *bitmap;
|
Bitmap *bitmap;
|
||||||
|
|
||||||
temp = strndup(word, l);
|
r = extract_first_word(&p, &word, NULL, 0);
|
||||||
if (!temp)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_error_errno(r, "Failed to parse %s: %m", lvalue);
|
||||||
|
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(temp);
|
r = exit_status_from_string(word);
|
||||||
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(temp);
|
r = signal_from_string(word);
|
||||||
|
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;
|
||||||
|
@ -4484,10 +4483,6 @@ 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(
|
||||||
|
|
|
@ -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, 0, "New main PID "PID_FMT" is the manager, refusing.", pid);
|
log_unit_full(UNIT(s), prio, "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, 0, "New main PID "PID_FMT" is the control process, refusing.", pid);
|
log_unit_full(UNIT(s), prio, "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, 0, "New main PID "PID_FMT" does not exist or is a zombie.", pid);
|
log_unit_full(UNIT(s), prio, "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_full(UNIT(s), LOG_DEBUG, r,
|
log_unit_debug_errno(UNIT(s), 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(UNIT(s), prio, fd,
|
return log_unit_full_errno(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(UNIT(s), prio, r, "Failed to parse PID from file %s: %m", s->pid_file);
|
return log_unit_full_errno(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;
|
||||||
|
|
|
@ -381,8 +381,10 @@ 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)) {
|
||||||
return log_unit_warning(s, "Requested freezer operation is not supported by all children of the slice");
|
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)
|
||||||
|
|
|
@ -1058,20 +1058,15 @@ static void socket_apply_socket_options(Socket *s, int fd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->receive_buffer > 0) {
|
if (s->receive_buffer > 0) {
|
||||||
/* We first try with SO_RCVBUFFORCE, in case we have the perms for that */
|
r = fd_set_rcvbuf(fd, s->receive_buffer, false);
|
||||||
if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, s->receive_buffer) < 0) {
|
if (r < 0)
|
||||||
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, s->receive_buffer);
|
log_unit_warning_errno(UNIT(s), r, "SO_RCVBUF/SO_RCVBUFFORCE failed: %m");
|
||||||
if (r < 0)
|
|
||||||
log_unit_warning_errno(UNIT(s), r, "SO_RCVBUF failed: %m");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->send_buffer > 0) {
|
if (s->send_buffer > 0) {
|
||||||
if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, s->send_buffer) < 0) {
|
r = fd_set_sndbuf(fd, s->receive_buffer, false);
|
||||||
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, s->send_buffer);
|
if (r < 0)
|
||||||
if (r < 0)
|
log_unit_warning_errno(UNIT(s), r, "SO_SNDBUF/SO_SNDBUFFORCE failed: %m");
|
||||||
log_unit_warning_errno(UNIT(s), r, "SO_SNDBUF failed: %m");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->mark >= 0) {
|
if (s->mark >= 0) {
|
||||||
|
|
|
@ -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(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
|
log_unit_full_errno(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -998,10 +998,9 @@ 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(dep,
|
log_unit_full_errno(dep, r == -ERFKILL ? LOG_INFO : LOG_WARNING, r,
|
||||||
r == -ERFKILL ? LOG_INFO : LOG_WARNING,
|
"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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1035,10 +1034,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(dep,
|
log_unit_full_errno(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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(unit, level, error, ...) \
|
#define log_unit_full_errno(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,17 +904,19 @@ 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_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__)
|
#define log_unit_full(unit, level, ...) (void) log_unit_full_errno(unit, level, 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_errno(unit, error, ...) log_unit_full(unit, LOG_DEBUG, error, ##__VA_ARGS__)
|
#define log_unit_debug(unit, ...) log_unit_full_errno(unit, LOG_DEBUG, 0, __VA_ARGS__)
|
||||||
#define log_unit_info_errno(unit, error, ...) log_unit_full(unit, LOG_INFO, error, ##__VA_ARGS__)
|
#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, __VA_ARGS__)
|
||||||
#define log_unit_notice_errno(unit, error, ...) log_unit_full(unit, LOG_NOTICE, error, ##__VA_ARGS__)
|
#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, __VA_ARGS__)
|
||||||
#define log_unit_warning_errno(unit, error, ...) log_unit_full(unit, LOG_WARNING, error, ##__VA_ARGS__)
|
#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, __VA_ARGS__)
|
||||||
#define log_unit_error_errno(unit, error, ...) log_unit_full(unit, LOG_ERR, error, ##__VA_ARGS__)
|
#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, __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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
FOREACH_WORD_SEPARATOR(word, l, options, ",", state) {
|
for (;;) {
|
||||||
_cleanup_free_ char *o;
|
_cleanup_free_ char *word = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
o = strndup(word, l);
|
r = extract_first_word(&options, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||||
if (!o)
|
if (r < 0)
|
||||||
return -ENOMEM;
|
return log_debug_errno(r, "Failed to parse options: %m");
|
||||||
r = parse_one_option(o);
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
r = parse_one_option(word);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -541,28 +541,33 @@ static int help(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_flags(const char *flag_str, int flags) {
|
static int parse_flags(const char *flag_str, int flags) {
|
||||||
const char *word, *state;
|
for (;;) {
|
||||||
size_t l;
|
_cleanup_free_ char *word = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
FOREACH_WORD_SEPARATOR(word, l, flag_str, ",", state) {
|
r = extract_first_word(&flag_str, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||||
if (strneq("masked", word, l))
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0)
|
||||||
|
return flags;
|
||||||
|
|
||||||
|
if (streq(word, "masked"))
|
||||||
flags |= SHOW_MASKED;
|
flags |= SHOW_MASKED;
|
||||||
else if (strneq ("equivalent", word, l))
|
else if (streq(word, "equivalent"))
|
||||||
flags |= SHOW_EQUIVALENT;
|
flags |= SHOW_EQUIVALENT;
|
||||||
else if (strneq("redirected", word, l))
|
else if (streq(word, "redirected"))
|
||||||
flags |= SHOW_REDIRECTED;
|
flags |= SHOW_REDIRECTED;
|
||||||
else if (strneq("overridden", word, l))
|
else if (streq(word, "overridden"))
|
||||||
flags |= SHOW_OVERRIDDEN;
|
flags |= SHOW_OVERRIDDEN;
|
||||||
else if (strneq("unchanged", word, l))
|
else if (streq(word, "unchanged"))
|
||||||
flags |= SHOW_UNCHANGED;
|
flags |= SHOW_UNCHANGED;
|
||||||
else if (strneq("extended", word, l))
|
else if (streq(word, "extended"))
|
||||||
flags |= SHOW_EXTENDED;
|
flags |= SHOW_EXTENDED;
|
||||||
else if (strneq("default", word, l))
|
else if (streq(word, "default"))
|
||||||
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[]) {
|
||||||
|
|
|
@ -99,89 +99,85 @@ 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)
|
||||||
_cleanup_free_ char *container_ttys = NULL;
|
/* Add console shell and look at $container_ttys, but don't do add any
|
||||||
|
* further magic if we are in a container. */
|
||||||
|
return run_container();
|
||||||
|
|
||||||
log_debug("Automatically adding console shell.");
|
/* Automatically add in a serial getty on all active kernel consoles */
|
||||||
|
_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 = add_symlink("console-getty.service", "console-getty.service");
|
r = extract_first_word(&p, &tty, NULL, 0);
|
||||||
|
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",
|
||||||
|
|
|
@ -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_extract(&words, getter, WHITESPACE, EXTRACT_UNQUOTE);
|
r = strv_split_full(&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");
|
||||||
|
|
||||||
|
|
|
@ -950,74 +950,69 @@ _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
|
bool seqnum_id_set = false,
|
||||||
seqnum_id_set = false,
|
seqnum_set = false,
|
||||||
seqnum_set = false,
|
boot_id_set = false,
|
||||||
boot_id_set = false,
|
monotonic_set = false,
|
||||||
monotonic_set = false,
|
realtime_set = false,
|
||||||
realtime_set = false,
|
xor_hash_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);
|
||||||
|
|
||||||
FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) {
|
for (const char *p = cursor;;) {
|
||||||
char *item;
|
_cleanup_free_ char *word = NULL;
|
||||||
int k = 0;
|
|
||||||
|
|
||||||
if (l < 2 || word[1] != '=')
|
r = extract_first_word(&p, &word, ";", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||||
|
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;
|
||||||
k = sd_id128_from_string(item+2, &seqnum_id);
|
r = sd_id128_from_string(word + 2, &seqnum_id);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
seqnum_set = true;
|
seqnum_set = true;
|
||||||
if (sscanf(item+2, "%llx", &seqnum) != 1)
|
if (sscanf(word + 2, "%llx", &seqnum) != 1)
|
||||||
k = -EINVAL;
|
return -EINVAL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
boot_id_set = true;
|
boot_id_set = true;
|
||||||
k = sd_id128_from_string(item+2, &boot_id);
|
r = sd_id128_from_string(word + 2, &boot_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
monotonic_set = true;
|
monotonic_set = true;
|
||||||
if (sscanf(item+2, "%llx", &monotonic) != 1)
|
if (sscanf(word + 2, "%llx", &monotonic) != 1)
|
||||||
k = -EINVAL;
|
return -EINVAL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
realtime_set = true;
|
realtime_set = true;
|
||||||
if (sscanf(item+2, "%llx", &realtime) != 1)
|
if (sscanf(word + 2, "%llx", &realtime) != 1)
|
||||||
k = -EINVAL;
|
return -EINVAL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
xor_hash_set = true;
|
xor_hash_set = true;
|
||||||
if (sscanf(item+2, "%llx", &xor_hash) != 1)
|
if (sscanf(word + 2, "%llx", &xor_hash) != 1)
|
||||||
k = -EINVAL;
|
return -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(item);
|
|
||||||
|
|
||||||
if (k < 0)
|
|
||||||
return k;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!seqnum_set || !seqnum_id_set) &&
|
if ((!seqnum_set || !seqnum_id_set) &&
|
||||||
|
|
|
@ -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_extract(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
n_names = strv_split_full(&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;
|
||||||
|
|
|
@ -91,18 +91,9 @@ 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) {
|
||||||
int r, n = (int) size;
|
|
||||||
|
|
||||||
assert_return(m, -EINVAL);
|
assert_return(m, -EINVAL);
|
||||||
assert_return((size_t) n == size, -EINVAL);
|
|
||||||
|
|
||||||
if (setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, n) < 0) {
|
return fd_set_rcvbuf(m->sock, size, false);
|
||||||
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) {
|
||||||
|
|
|
@ -316,34 +316,33 @@ 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")) {
|
||||||
const char *word, *state;
|
for (const char *p = value;;) {
|
||||||
size_t l;
|
_cleanup_free_ char *word = NULL;
|
||||||
|
|
||||||
FOREACH_WORD(word, l, value, state) {
|
r = extract_first_word(&p, &word, NULL, 0);
|
||||||
char devlink[l + 1];
|
|
||||||
|
|
||||||
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", devlink);
|
return r;
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
r = device_add_devlink(device, word);
|
||||||
|
if (r < 0)
|
||||||
|
return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", word);
|
||||||
}
|
}
|
||||||
} else if (STR_IN_SET(key, "TAGS", "CURRENT_TAGS")) {
|
} else if (STR_IN_SET(key, "TAGS", "CURRENT_TAGS")) {
|
||||||
const char *word, *state;
|
for (const char *p = value;;) {
|
||||||
size_t l;
|
_cleanup_free_ char *word = NULL;
|
||||||
|
|
||||||
FOREACH_WORD_SEPARATOR(word, l, value, ":", state) {
|
r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||||
char tag[l + 1];
|
|
||||||
|
|
||||||
(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", tag);
|
return r;
|
||||||
}
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
r = device_add_tag(device, word, streq(key, "CURRENT_TAGS"));
|
||||||
|
if (r < 0)
|
||||||
|
return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", word);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
r = device_add_property_internal(device, key, value);
|
r = device_add_property_internal(device, key, value);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|
|
@ -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(device, level, error, ...) \
|
#define log_device_full_errno(device, level, error, ...) \
|
||||||
({ \
|
({ \
|
||||||
const char *_sysname = NULL; \
|
const char *_sysname = NULL; \
|
||||||
sd_device *_d = (device); \
|
sd_device *_d = (device); \
|
||||||
|
@ -46,17 +46,19 @@
|
||||||
(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_debug(device, ...) log_device_full(device, LOG_DEBUG, 0, ##__VA_ARGS__)
|
#define log_device_full(device, level, ...) (void) log_device_full_errno(device, level, 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_errno(device, error, ...) log_device_full(device, LOG_DEBUG, error, ##__VA_ARGS__)
|
#define log_device_debug(device, ...) log_device_full_errno(device, LOG_DEBUG, 0, __VA_ARGS__)
|
||||||
#define log_device_info_errno(device, error, ...) log_device_full(device, LOG_INFO, error, ##__VA_ARGS__)
|
#define log_device_info(device, ...) log_device_full(device, LOG_INFO, __VA_ARGS__)
|
||||||
#define log_device_notice_errno(device, error, ...) log_device_full(device, LOG_NOTICE, error, ##__VA_ARGS__)
|
#define log_device_notice(device, ...) log_device_full(device, LOG_NOTICE, __VA_ARGS__)
|
||||||
#define log_device_warning_errno(device, error, ...) log_device_full(device, LOG_WARNING, error, ##__VA_ARGS__)
|
#define log_device_warning(device, ...) log_device_full(device, LOG_WARNING, __VA_ARGS__)
|
||||||
#define log_device_error_errno(device, error, ...) log_device_full(device, LOG_ERR, error, ##__VA_ARGS__)
|
#define log_device_error(device, ...) log_device_full(device, LOG_ERR, __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__)
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#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"
|
||||||
|
@ -22,6 +23,7 @@
|
||||||
#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"
|
||||||
|
@ -331,35 +333,29 @@ 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 *t = NULL, *s = NULL, *p = NULL;
|
_cleanup_free_ char *filename = NULL, *content = 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, &p);
|
r = file_of_seat(seat, &filename);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
variable = require_active ? "ACTIVE_UID" : "UIDS";
|
r = parse_env_file(NULL, filename,
|
||||||
|
require_active ? "ACTIVE_UID" : "UIDS",
|
||||||
r = parse_env_file(NULL, p, variable, &s);
|
&content);
|
||||||
if (r == -ENOENT)
|
if (r == -ENOENT)
|
||||||
return 0;
|
return 0;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (isempty(s))
|
if (isempty(content))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (asprintf(&t, UID_FMT, uid) < 0)
|
char t[DECIMAL_STR_MAX(uid_t)];
|
||||||
return -ENOMEM;
|
xsprintf(t, UID_FMT, uid);
|
||||||
|
|
||||||
FOREACH_WORD(word, l, s, state)
|
return string_contains_word(content, ",", t);
|
||||||
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) {
|
||||||
|
@ -382,7 +378,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, " ");
|
a = strv_split(s, NULL);
|
||||||
if (!a)
|
if (!a)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -654,73 +650,70 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
|
_public_ int sd_seat_get_sessions(
|
||||||
_cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
|
const char *seat,
|
||||||
_cleanup_strv_free_ char **a = NULL;
|
char ***ret_sessions,
|
||||||
_cleanup_free_ uid_t *b = NULL;
|
uid_t **ret_uids,
|
||||||
unsigned n = 0;
|
unsigned *ret_n_uids) {
|
||||||
|
|
||||||
|
_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, &p);
|
r = file_of_seat(seat, &fname);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = parse_env_file(NULL, p,
|
r = parse_env_file(NULL, fname,
|
||||||
"SESSIONS", &s,
|
"SESSIONS", &session_line,
|
||||||
"UIDS", &t);
|
"UIDS", &uid_line);
|
||||||
if (r == -ENOENT)
|
if (r == -ENOENT)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (s) {
|
if (session_line) {
|
||||||
a = strv_split(s, " ");
|
sessions = strv_split(session_line, NULL);
|
||||||
if (!a)
|
if (!sessions)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
if (uids && t) {
|
n_sessions = strv_length(sessions);
|
||||||
const char *word, *state;
|
};
|
||||||
size_t l;
|
|
||||||
|
|
||||||
FOREACH_WORD(word, l, t, state)
|
if (ret_uids && uid_line) {
|
||||||
n++;
|
uids = new(uid_t, n_sessions);
|
||||||
|
if (!uids)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
if (n > 0) {
|
size_t n = 0;
|
||||||
unsigned i = 0;
|
for (const char *p = uid_line;;) {
|
||||||
|
_cleanup_free_ char *word = NULL;
|
||||||
|
|
||||||
b = new(uid_t, n);
|
r = extract_first_word(&p, &word, NULL, 0);
|
||||||
if (!b)
|
if (r < 0)
|
||||||
return -ENOMEM;
|
return r;
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
FOREACH_WORD(word, l, t, state) {
|
r = parse_uid(word, &uids[n++]);
|
||||||
_cleanup_free_ char *k = NULL;
|
if (r < 0)
|
||||||
|
return r;
|
||||||
k = strndup(word, l);
|
|
||||||
if (!k)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
r = parse_uid(k, b + i);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (n != n_sessions)
|
||||||
|
return -EUCLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = (int) strv_length(a);
|
if (ret_sessions)
|
||||||
|
*ret_sessions = TAKE_PTR(sessions);
|
||||||
|
if (ret_uids)
|
||||||
|
*ret_uids = TAKE_PTR(uids);
|
||||||
|
if (ret_n_uids)
|
||||||
|
*ret_n_uids = n_sessions;
|
||||||
|
|
||||||
if (sessions)
|
return n_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) {
|
||||||
|
@ -901,47 +894,52 @@ _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 **ifindices) {
|
_public_ int sd_machine_get_ifindices(const char *machine, int **ret_ifindices) {
|
||||||
_cleanup_free_ char *netif = NULL;
|
_cleanup_free_ char *netif_line = NULL;
|
||||||
size_t l, allocated = 0, nr = 0;
|
const char *p;
|
||||||
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);
|
r = parse_env_file(NULL, p, "NETIF", &netif_line);
|
||||||
if (r == -ENOENT)
|
if (r == -ENOENT)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (!netif) {
|
if (!netif_line) {
|
||||||
*ifindices = NULL;
|
*ret_ifindices = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FOREACH_WORD(word, l, netif, state) {
|
_cleanup_strv_free_ char **tt = strv_split(netif_line, NULL);
|
||||||
char buf[l+1];
|
if (!tt)
|
||||||
int ifi;
|
return -ENOMEM;
|
||||||
|
|
||||||
*(char*) (mempcpy(buf, word, l)) = 0;
|
size_t n = 0;
|
||||||
|
int *ifindices;
|
||||||
ifi = parse_ifindex(buf);
|
if (ret_ifindices) {
|
||||||
if (ifi < 0)
|
ifindices = new(int, strv_length(tt));
|
||||||
continue;
|
if (!ifindices)
|
||||||
|
|
||||||
if (!GREEDY_REALLOC(ni, allocated, nr+1)) {
|
|
||||||
free(ni);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
ni[nr++] = ifi;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*ifindices = ni;
|
for (size_t i = 0; tt[i]; i++) {
|
||||||
return nr;
|
int ind;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
|
@ -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_extract(&a, l, WHITESPACE, EXTRACT_UNQUOTE);
|
r = strv_split_full(&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_extract(&a, l, WHITESPACE, EXTRACT_UNQUOTE);
|
r = strv_split_full(&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_extract(&b, l, WHITESPACE, EXTRACT_UNQUOTE);
|
r = strv_split_full(&b, l, WHITESPACE, EXTRACT_UNQUOTE);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define CONST_MAX4(a, b, c, d) CONST_MAX(CONST_MAX(a, b), CONST_MAX(c, d))
|
#define CONST_MAX5(a, b, c, d, e) CONST_MAX(CONST_MAX(a, b), CONST_MAX(CONST_MAX(c, d), e))
|
||||||
|
|
||||||
#define ULONG_BITS (sizeof(unsigned long)*8)
|
#define ULONG_BITS (sizeof(unsigned long)*8)
|
||||||
|
|
||||||
|
@ -158,7 +158,20 @@ 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 is a bit confused here:
|
/* The kernel naming is a bit confusing 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"
|
||||||
|
@ -231,7 +244,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_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1];
|
unsigned long keys[CONST_MAX5(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND, KEY_RESTART)/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;
|
||||||
|
@ -239,7 +252,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +274,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_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1] = {},
|
keys[CONST_MAX5(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND, KEY_RESTART)/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;
|
||||||
|
|
||||||
|
@ -285,6 +299,7 @@ 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,
|
||||||
|
|
|
@ -43,10 +43,12 @@ 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;
|
||||||
|
|
||||||
|
@ -675,6 +677,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3240,6 +3240,7 @@ 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,
|
||||||
|
|
|
@ -30,10 +30,12 @@ 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)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#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"
|
||||||
|
@ -451,7 +452,15 @@ 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[97];
|
static thread_local char buffer[STRLEN(
|
||||||
|
"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)
|
||||||
|
@ -472,6 +481,8 @@ 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;
|
||||||
|
@ -481,31 +492,41 @@ const char *inhibit_what_to_string(InhibitWhat w) {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
InhibitWhat inhibit_what_from_string(const char *s) {
|
int inhibit_what_from_string(const char *s) {
|
||||||
InhibitWhat what = 0;
|
InhibitWhat what = 0;
|
||||||
const char *word, *state;
|
|
||||||
size_t l;
|
|
||||||
|
|
||||||
FOREACH_WORD_SEPARATOR(word, l, s, ":", state) {
|
for (const char *p = s;;) {
|
||||||
if (l == 8 && strneq(word, "shutdown", l))
|
_cleanup_free_ char *word = NULL;
|
||||||
|
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 (l == 5 && strneq(word, "sleep", l))
|
else if (streq(word, "sleep"))
|
||||||
what |= INHIBIT_SLEEP;
|
what |= INHIBIT_SLEEP;
|
||||||
else if (l == 4 && strneq(word, "idle", l))
|
else if (streq(word, "idle"))
|
||||||
what |= INHIBIT_IDLE;
|
what |= INHIBIT_IDLE;
|
||||||
else if (l == 16 && strneq(word, "handle-power-key", l))
|
else if (streq(word, "handle-power-key"))
|
||||||
what |= INHIBIT_HANDLE_POWER_KEY;
|
what |= INHIBIT_HANDLE_POWER_KEY;
|
||||||
else if (l == 18 && strneq(word, "handle-suspend-key", l))
|
else if (streq(word, "handle-suspend-key"))
|
||||||
what |= INHIBIT_HANDLE_SUSPEND_KEY;
|
what |= INHIBIT_HANDLE_SUSPEND_KEY;
|
||||||
else if (l == 20 && strneq(word, "handle-hibernate-key", l))
|
else if (streq(word, "handle-hibernate-key"))
|
||||||
what |= INHIBIT_HANDLE_HIBERNATE_KEY;
|
what |= INHIBIT_HANDLE_HIBERNATE_KEY;
|
||||||
else if (l == 17 && strneq(word, "handle-lid-switch", l))
|
else if (streq(word, "handle-lid-switch"))
|
||||||
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] = {
|
||||||
|
|
|
@ -11,7 +11,8 @@ 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_WHAT_MAX = 1 << 7,
|
INHIBIT_HANDLE_REBOOT_KEY = 1 << 7,
|
||||||
|
_INHIBIT_WHAT_MAX = 1 << 8,
|
||||||
_INHIBIT_WHAT_INVALID = -1
|
_INHIBIT_WHAT_INVALID = -1
|
||||||
} InhibitWhat;
|
} InhibitWhat;
|
||||||
|
|
||||||
|
@ -66,7 +67,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);
|
||||||
InhibitWhat inhibit_what_from_string(const char *s);
|
int 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);
|
||||||
|
|
|
@ -18,16 +18,19 @@
|
||||||
#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
|
||||||
|
|
|
@ -107,11 +107,13 @@ 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;
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,17 @@
|
||||||
</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>
|
||||||
|
|
|
@ -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, 0,
|
log_link_full(link, set_contains(link->dhcp6_addresses, addr) ? LOG_DEBUG : LOG_INFO,
|
||||||
"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);
|
||||||
|
|
||||||
|
|
|
@ -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(link, level, err,
|
return log_link_full_errno(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 ? " " : "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,16 +261,19 @@ 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,
|
/* udev does not initialize devices inside containers, so we rely on them being already
|
||||||
* so we rely on them being already initialized before
|
* initialized before entering the container. */
|
||||||
* entering the container */
|
if (path_is_read_only_fs("/sys") > 0)
|
||||||
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");
|
||||||
|
@ -1347,7 +1350,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)
|
||||||
return r;
|
log_warning_errno(r, "Failed to increase receive buffer size for general netlink socket, ignoring: %m");
|
||||||
|
|
||||||
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)
|
||||||
|
@ -1369,9 +1372,14 @@ static int manager_connect_rtnl(Manager *m) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
|
/* Bump receiver buffer, but only if we are not called via socket activation, as in that
|
||||||
if (r < 0)
|
* case systemd sets the receive buffer size for us, and the value in the .socket unit
|
||||||
return r;
|
* should take full effect. */
|
||||||
|
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)
|
||||||
|
|
|
@ -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_extract(&lower, s, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
k = strv_split_full(&lower, s, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
return k;
|
return k;
|
||||||
if (k < 2)
|
if (k < 2)
|
||||||
|
|
|
@ -88,13 +88,12 @@ 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, l;
|
size_t sz = 0;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
@ -208,16 +207,19 @@ 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);
|
||||||
|
|
||||||
FOREACH_WORD(word, l, x, state) {
|
for (const char *p = x;;) {
|
||||||
char c[l+1];
|
_cleanup_free_ char *word = NULL;
|
||||||
|
|
||||||
memcpy(c, word, l);
|
r = extract_first_word(&p, &word, NULL, 0);
|
||||||
c[l] = 0;
|
if (r < 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(c, &gids[n_gids++]);
|
r = parse_gid(word, &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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_extract(&l, eq, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE);
|
r = strv_split_full(&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");
|
||||||
|
|
||||||
|
|
|
@ -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, x, *ys; \
|
type **enums = data; \
|
||||||
_cleanup_free_ type *xs = NULL; \
|
_cleanup_free_ type *xs = NULL; \
|
||||||
const char *word, *state; \
|
size_t i = 0; \
|
||||||
size_t l, i = 0; \
|
int r; \
|
||||||
\
|
\
|
||||||
assert(filename); \
|
assert(filename); \
|
||||||
assert(lvalue); \
|
assert(lvalue); \
|
||||||
|
@ -255,29 +255,32 @@ typedef enum Disabled {
|
||||||
\
|
\
|
||||||
*xs = invalid; \
|
*xs = invalid; \
|
||||||
\
|
\
|
||||||
FOREACH_WORD(word, l, rvalue, state) { \
|
for (const char *p = rvalue;;) { \
|
||||||
_cleanup_free_ char *en = NULL; \
|
_cleanup_free_ char *en = NULL; \
|
||||||
type *new_xs; \
|
type x, *new_xs; \
|
||||||
\
|
\
|
||||||
en = strndup(word, l); \
|
r = extract_first_word(&p, &en, NULL, 0); \
|
||||||
if (!en) \
|
if (r == -ENOMEM) \
|
||||||
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 (ys = xs; x != invalid && *ys != invalid; ys++) { \
|
for (type *ys = xs; x != invalid && *ys != invalid; ys++) \
|
||||||
if (*ys == x) { \
|
if (*ys == x) { \
|
||||||
log_syntax(unit, LOG_NOTICE, filename, \
|
log_syntax(unit, LOG_NOTICE, filename, line, 0, \
|
||||||
line, 0, \
|
"Duplicate entry, ignoring: %s", \
|
||||||
"Duplicate entry, ignoring: %s", \
|
|
||||||
en); \
|
en); \
|
||||||
x = invalid; \
|
x = invalid; \
|
||||||
} \
|
} \
|
||||||
} \
|
|
||||||
\
|
\
|
||||||
if (x == invalid) \
|
if (x == invalid) \
|
||||||
continue; \
|
continue; \
|
||||||
|
@ -292,6 +295,5 @@ typedef enum Disabled {
|
||||||
*(xs + i) = invalid; \
|
*(xs + i) = invalid; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
free_and_replace(*enums, xs); \
|
return free_and_replace(*enums, xs); \
|
||||||
return 0; \
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,50 +81,53 @@ 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, *n = NULL, *x;
|
const char *name, *namefound = 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 !value and !filtered, this function is not allowed to fail. */
|
/* If !ret_value and !ret_filtered, this function is not allowed to fail. */
|
||||||
|
|
||||||
if (!ret_filtered) {
|
if (!ret_filtered) {
|
||||||
const char *word, *state;
|
for (const char *word = opts;;) {
|
||||||
size_t l;
|
const char *end = word + strcspn(word, ",");
|
||||||
|
|
||||||
FOREACH_WORD_SEPARATOR(word, l, opts, ",", state)
|
|
||||||
NULSTR_FOREACH(name, names) {
|
NULSTR_FOREACH(name, names) {
|
||||||
if (l < strlen(name))
|
if (end < word + 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
|
/* We know that the string is NUL terminated, so *x is valid */
|
||||||
* terminated, so *x is valid */
|
|
||||||
x = word + strlen(name);
|
x = word + strlen(name);
|
||||||
if (IN_SET(*x, '\0', '=', ',')) {
|
if (IN_SET(*x, '\0', '=', ',')) {
|
||||||
n = name;
|
namefound = name;
|
||||||
if (ret_value) {
|
if (ret_value) {
|
||||||
free(v);
|
bool eq = *x == '=';
|
||||||
if (IN_SET(*x, '\0', ','))
|
assert(eq || IN_SET(*x, ',', '\0'));
|
||||||
v = NULL;
|
|
||||||
else {
|
r = free_and_strndup(&v,
|
||||||
assert(*x == '=');
|
eq ? x + 1 : NULL,
|
||||||
x++;
|
eq ? end - x - 1 : 0);
|
||||||
v = strndup(x, l - strlen(name) - 1);
|
if (r < 0)
|
||||||
if (!v)
|
return r;
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
char **t, **s;
|
|
||||||
|
|
||||||
|
if (*end)
|
||||||
|
word = end + 1;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
stor = strv_split(opts, ",");
|
stor = strv_split(opts, ",");
|
||||||
if (!stor)
|
if (!stor)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -132,7 +135,8 @@ int fstab_filter_options(const char *opts, const char *names,
|
||||||
if (!strv)
|
if (!strv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (s = t = strv; *s; s++) {
|
char **t = strv;
|
||||||
|
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', '='))
|
||||||
|
@ -144,18 +148,12 @@ int fstab_filter_options(const char *opts, const char *names,
|
||||||
continue;
|
continue;
|
||||||
found:
|
found:
|
||||||
/* Keep the last occurrence found */
|
/* Keep the last occurrence found */
|
||||||
n = name;
|
namefound = name;
|
||||||
if (ret_value) {
|
if (ret_value) {
|
||||||
free(v);
|
assert(IN_SET(*x, '=', '\0'));
|
||||||
if (*x == '\0')
|
r = free_and_strdup(&v, *x == '=' ? x + 1 : NULL);
|
||||||
v = NULL;
|
if (r < 0)
|
||||||
else {
|
return r;
|
||||||
assert(*x == '=');
|
|
||||||
x++;
|
|
||||||
v = strdup(x);
|
|
||||||
if (!v)
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*t = NULL;
|
*t = NULL;
|
||||||
|
@ -163,7 +161,7 @@ int fstab_filter_options(const char *opts, const char *names,
|
||||||
|
|
||||||
answer:
|
answer:
|
||||||
if (ret_namefound)
|
if (ret_namefound)
|
||||||
*ret_namefound = n;
|
*ret_namefound = namefound;
|
||||||
if (ret_filtered) {
|
if (ret_filtered) {
|
||||||
char *f;
|
char *f;
|
||||||
|
|
||||||
|
@ -176,7 +174,7 @@ answer:
|
||||||
if (ret_value)
|
if (ret_value)
|
||||||
*ret_value = TAKE_PTR(v);
|
*ret_value = TAKE_PTR(v);
|
||||||
|
|
||||||
return !!n;
|
return !!namefound;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fstab_extract_values(const char *opts, const char *name, char ***values) {
|
int fstab_extract_values(const char *opts, const char *name, char ***values) {
|
||||||
|
|
|
@ -14,24 +14,26 @@
|
||||||
* See, network/networkd-link.h for example.
|
* See, network/networkd-link.h for example.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define log_link_full(link, level, error, ...) \
|
#define log_link_full_errno(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_debug(link, ...) log_link_full(link, LOG_DEBUG, 0, ##__VA_ARGS__)
|
#define log_link_full(link, level, ...) (void) log_link_full_errno(link, level, 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_errno(link, error, ...) log_link_full(link, LOG_DEBUG, error, ##__VA_ARGS__)
|
#define log_link_debug(link, ...) log_link_full_errno(link, LOG_DEBUG, 0, __VA_ARGS__)
|
||||||
#define log_link_info_errno(link, error, ...) log_link_full(link, LOG_INFO, error, ##__VA_ARGS__)
|
#define log_link_info(link, ...) log_link_full(link, LOG_INFO, __VA_ARGS__)
|
||||||
#define log_link_notice_errno(link, error, ...) log_link_full(link, LOG_NOTICE, error, ##__VA_ARGS__)
|
#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, __VA_ARGS__)
|
||||||
#define log_link_warning_errno(link, error, ...) log_link_full(link, LOG_WARNING, error, ##__VA_ARGS__)
|
#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, __VA_ARGS__)
|
||||||
#define log_link_error_errno(link, error, ...) log_link_full(link, LOG_ERR, error, ##__VA_ARGS__)
|
#define log_link_error(link, ...) log_link_full(link, LOG_ERR, __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
|
||||||
|
|
|
@ -100,9 +100,8 @@ int parse_sleep_config(SleepConfig **ret_sleep_config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int can_sleep_state(char **types) {
|
int can_sleep_state(char **types) {
|
||||||
char **type;
|
_cleanup_free_ char *text = NULL;
|
||||||
int r;
|
int r;
|
||||||
_cleanup_free_ char *p = NULL;
|
|
||||||
|
|
||||||
if (strv_isempty(types))
|
if (strv_isempty(types))
|
||||||
return true;
|
return true;
|
||||||
|
@ -113,34 +112,27 @@ int can_sleep_state(char **types) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = read_one_line_file("/sys/power/state", &p);
|
r = read_one_line_file("/sys/power/state", &text);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
STRV_FOREACH(type, types) {
|
const char *found;
|
||||||
const char *word, *state;
|
r = string_contains_word_strv(text, NULL, types, &found);
|
||||||
size_t l, k;
|
if (r < 0)
|
||||||
|
return log_debug_errno(r, "Failed to parse /sys/power/state: %m");
|
||||||
k = strlen(*type);
|
if (r > 0)
|
||||||
FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state)
|
log_debug("Sleep mode \"%s\" is supported by the kernel.", found);
|
||||||
if (l == k && memcmp(word, *type, l) == 0) {
|
else if (DEBUG_LOGGING) {
|
||||||
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 false;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int can_sleep_disk(char **types) {
|
int can_sleep_disk(char **types) {
|
||||||
_cleanup_free_ char *p = NULL;
|
_cleanup_free_ char *text = NULL;
|
||||||
char **type;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (strv_isempty(types))
|
if (strv_isempty(types))
|
||||||
|
@ -152,29 +144,38 @@ int can_sleep_disk(char **types) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = read_one_line_file("/sys/power/disk", &p);
|
r = read_one_line_file("/sys/power/disk", &text);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
STRV_FOREACH(type, types) {
|
for (const char *p = text;;) {
|
||||||
const char *word, *state;
|
_cleanup_free_ char *word = NULL;
|
||||||
size_t l, k;
|
|
||||||
|
|
||||||
k = strlen(*type);
|
r = extract_first_word(&p, &word, NULL, 0);
|
||||||
FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state) {
|
if (r < 0)
|
||||||
if (l == k && memcmp(word, *type, l) == 0)
|
return log_debug_errno(r, "Failed to parse /sys/power/disk: %m");
|
||||||
return true;
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
if (l == k + 2 &&
|
char *s = word;
|
||||||
word[0] == '[' &&
|
size_t l = strlen(s);
|
||||||
memcmp(word + 1, *type, l - 2) == 0 &&
|
if (s[0] == '[' && s[l-1] == ']') {
|
||||||
word[l-1] == ']')
|
s[l-1] = '\0';
|
||||||
return true;
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,11 @@ 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(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids);
|
int sd_seat_get_sessions(
|
||||||
|
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_;
|
||||||
|
@ -195,7 +199,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 **ifindices);
|
int sd_machine_get_ifindices(const char *machine, int **ret_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. */
|
||||||
|
|
|
@ -140,6 +140,8 @@ _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)
|
||||||
|
|
|
@ -11,6 +11,8 @@ 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"));
|
||||||
|
@ -387,6 +389,8 @@ 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"));
|
||||||
|
@ -531,6 +535,8 @@ 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));
|
||||||
|
|
|
@ -10,8 +10,9 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static void test_string_erase(void) {
|
static void test_string_erase(void) {
|
||||||
char *x;
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
|
char *x;
|
||||||
x = strdupa("");
|
x = strdupa("");
|
||||||
assert_se(streq(string_erase(x), ""));
|
assert_se(streq(string_erase(x), ""));
|
||||||
|
|
||||||
|
@ -33,17 +34,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));
|
||||||
|
|
||||||
r = free_and_strndup(t, src, l);
|
int 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;
|
||||||
|
@ -91,6 +92,7 @@ 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);
|
||||||
|
@ -118,6 +120,8 @@ 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);
|
||||||
|
@ -137,6 +141,8 @@ 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"), ""));
|
||||||
|
@ -216,19 +222,24 @@ 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) {
|
||||||
char *r;
|
log_info("/* %s */", __func__);
|
||||||
char input[] = " hello, waldo. ";
|
|
||||||
|
|
||||||
r = strstrip(input);
|
char *ret, input[] = " hello, waldo. ";
|
||||||
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));
|
||||||
|
@ -240,6 +251,8 @@ 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));
|
||||||
|
@ -263,6 +276,8 @@ 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);
|
||||||
|
@ -288,11 +303,15 @@ 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);
|
||||||
|
@ -302,6 +321,8 @@ 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");
|
||||||
|
@ -359,6 +380,8 @@ 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);
|
||||||
|
@ -371,26 +394,36 @@ static void test_strcmp_ptr(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_foreach_word(void) {
|
static void test_foreach_word(void) {
|
||||||
const char *word, *state;
|
log_info("/* %s */", __func__);
|
||||||
size_t l;
|
|
||||||
int i = 0;
|
const char *test = "test abc d\te f ";
|
||||||
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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FOREACH_WORD(word, l, test, state)
|
size_t i = 0;
|
||||||
assert_se(strneq(expected[i++], word, l));
|
int r;
|
||||||
|
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) {
|
||||||
int i = 0, r;
|
size_t i = 0;
|
||||||
|
int r;
|
||||||
|
|
||||||
printf("<<<%s>>>\n", test);
|
printf("<<<%s>>>\n", test);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -412,6 +445,8 @@ 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",
|
||||||
|
@ -437,6 +472,8 @@ 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"));
|
||||||
|
@ -447,6 +484,8 @@ 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"));
|
||||||
|
@ -457,6 +496,8 @@ 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);
|
||||||
|
@ -465,6 +506,7 @@ 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 ",
|
||||||
|
@ -489,6 +531,8 @@ 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",
|
||||||
|
@ -502,6 +546,8 @@ 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";
|
||||||
|
@ -514,11 +560,15 @@ 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);
|
||||||
|
@ -541,6 +591,8 @@ 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"));
|
||||||
|
@ -555,12 +607,16 @@ 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"));
|
||||||
|
@ -573,6 +629,8 @@ 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"));
|
||||||
|
@ -605,6 +663,8 @@ 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);
|
||||||
|
@ -676,6 +736,8 @@ 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);
|
||||||
|
@ -742,6 +804,88 @@ 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);
|
||||||
|
|
||||||
|
@ -777,6 +921,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,12 @@ 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,
|
||||||
|
@ -232,7 +238,7 @@ static void test_strv_unquote(const char *quoted, char **list) {
|
||||||
|
|
||||||
log_info("/* %s */", __func__);
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE);
|
r = strv_split_full(&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, " | ");
|
||||||
|
@ -251,7 +257,7 @@ static void test_invalid_unquote(const char *quoted) {
|
||||||
|
|
||||||
log_info("/* %s */", __func__);
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE);
|
r = strv_split_full(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE);
|
||||||
assert_se(s == NULL);
|
assert_se(s == NULL);
|
||||||
assert_se(r == -EINVAL);
|
assert_se(r == -EINVAL);
|
||||||
}
|
}
|
||||||
|
@ -281,47 +287,39 @@ static void test_strv_split(void) {
|
||||||
|
|
||||||
strv_free_erase(l);
|
strv_free_erase(l);
|
||||||
|
|
||||||
l = strv_split_full(" one two\t three", NULL, 0);
|
assert_se(strv_split_full(&l, " one two\t three", NULL, 0) == 3);
|
||||||
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);
|
||||||
|
|
||||||
l = strv_split_full(" 'one' \" two\t three \" ' four five'", NULL, SPLIT_QUOTES);
|
assert_se(strv_split_full(&l, " 'one' \" two\t three \" ' four five'", NULL, EXTRACT_UNQUOTE) == 3);
|
||||||
assert_se(l);
|
|
||||||
assert_se(strv_equal(l, (char**) input_table_quoted));
|
assert_se(strv_equal(l, (char**) input_table_quoted));
|
||||||
|
|
||||||
strv_free_erase(l);
|
l = strv_free_erase(l);
|
||||||
|
|
||||||
/* missing last quote ignores the last element. */
|
/* missing last quote causes extraction to fail. */
|
||||||
l = strv_split_full(" 'one' \" two\t three \" ' four five' ' ignored element ", NULL, SPLIT_QUOTES);
|
assert_se(strv_split_full(&l, " 'one' \" two\t three \" ' four five", NULL, EXTRACT_UNQUOTE) == -EINVAL);
|
||||||
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));
|
||||||
|
|
||||||
strv_free_erase(l);
|
l = strv_free_erase(l);
|
||||||
|
|
||||||
/* missing last quote, but the last element is _not_ ignored with SPLIT_RELAX. */
|
/* missing separator between items */
|
||||||
l = strv_split_full(" 'one' \" two\t three \" ' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX);
|
assert_se(strv_split_full(&l, " 'one' \" two\t three \"' four five'", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX) == 2);
|
||||||
assert_se(l);
|
assert_se(strv_equal(l, (char**) input_table_quoted_joined));
|
||||||
assert_se(strv_equal(l, (char**) input_table_quoted));
|
|
||||||
|
|
||||||
strv_free_erase(l);
|
l = strv_free_erase(l);
|
||||||
|
|
||||||
/* missing separator between */
|
assert_se(strv_split_full(&l, " 'one' \" two\t three \"' four five", NULL,
|
||||||
l = strv_split_full(" 'one' \" two\t three \"' four five'", NULL, SPLIT_QUOTES | SPLIT_RELAX);
|
EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_CUNESCAPE_RELAX) == 2);
|
||||||
assert_se(l);
|
assert_se(strv_equal(l, (char**) input_table_quoted_joined));
|
||||||
assert_se(strv_equal(l, (char**) input_table_quoted));
|
|
||||||
|
|
||||||
strv_free_erase(l);
|
l = strv_free_erase(l);
|
||||||
|
|
||||||
l = strv_split_full(" 'one' \" two\t three \"' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX);
|
assert_se(strv_split_full(&l, "\\", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_CUNESCAPE_RELAX) == 1);
|
||||||
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("\\")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,71 +331,70 @@ 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);
|
||||||
|
|
||||||
strv_free(l);
|
assert_se(l = strv_split("", NULL));
|
||||||
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(l);
|
||||||
assert_se(strv_isempty(l));
|
assert_se(strv_isempty(l));
|
||||||
|
l = strv_free(l);
|
||||||
|
|
||||||
strv_free(l);
|
assert_se(strv_split_full(&l, "", NULL, EXTRACT_UNQUOTE) == 0);
|
||||||
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);
|
||||||
|
|
||||||
strv_free(l);
|
assert_se(strv_split_full(&l, "", WHITESPACE, EXTRACT_UNQUOTE) == 0);
|
||||||
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);
|
||||||
|
|
||||||
strv_free(l);
|
assert_se(strv_split_full(&l, "", WHITESPACE, EXTRACT_UNQUOTE | EXTRACT_RELAX) == 0);
|
||||||
l = strv_split_full("", WHITESPACE, SPLIT_QUOTES);
|
|
||||||
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_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);
|
||||||
|
|
||||||
strv_free(l);
|
assert_se(strv_split_full(&l, " ", NULL, 0) == 0);
|
||||||
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);
|
||||||
|
|
||||||
strv_free(l);
|
assert_se(strv_split_full(&l, " ", WHITESPACE, EXTRACT_UNQUOTE) == 0);
|
||||||
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);
|
||||||
|
|
||||||
strv_free(l);
|
assert_se(strv_split_full(&l, " ", NULL, EXTRACT_UNQUOTE) == 0);
|
||||||
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);
|
||||||
|
|
||||||
strv_free(l);
|
assert_se(strv_split_full(&l, " ", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX) == 0);
|
||||||
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_extract(void) {
|
static void test_strv_split_full(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_extract(&l, str, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
r = strv_split_full(&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"));
|
||||||
|
@ -1026,7 +1023,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
test_strv_split();
|
test_strv_split();
|
||||||
test_strv_split_empty();
|
test_strv_split_empty();
|
||||||
test_strv_split_extract();
|
test_strv_split_full();
|
||||||
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();
|
||||||
|
|
|
@ -320,7 +320,8 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr
|
||||||
case NET_ADDR_PERM:
|
case NET_ADDR_PERM:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return log_device_warning(device, "Unknown addr_assign_type %u, ignoring", addr_type);
|
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))
|
||||||
|
|
|
@ -87,7 +87,7 @@ static int map_keycode(sd_device *dev, int fd, int scancode, const char *keycode
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* parse_token(const char *current, int32_t *val_out) {
|
static const 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 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;
|
||||||
char *next;
|
const 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(dev, "Failed to parse EV_ABS override '%s'", value);
|
return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "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);
|
||||||
|
|
|
@ -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(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL: %m");
|
log_device_full_errno(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(dev, k == -ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL: %m");
|
log_device_full_errno(dev, k == -ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL: %m");
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
r = k;
|
r = k;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,6 +109,7 @@ 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);
|
||||||
|
@ -117,9 +118,10 @@ int udev_builtin_run(sd_device *dev, UdevBuiltinCommand cmd, const char *command
|
||||||
if (!builtins[cmd])
|
if (!builtins[cmd])
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
argv = strv_split_full(command, NULL, SPLIT_QUOTES | SPLIT_RELAX);
|
r = strv_split_full(&argv, command, NULL,
|
||||||
if (!argv)
|
EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_RETAIN_ESCAPE);
|
||||||
return -ENOMEM;
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
/* we need '0' here to reset the internal state */
|
/* we need '0' here to reset the internal state */
|
||||||
optind = 0;
|
optind = 0;
|
||||||
|
|
|
@ -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, 0,
|
log_device_full(spawn->device, spawn->accept_failure ? LOG_DEBUG : LOG_WARNING,
|
||||||
"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);
|
||||||
|
|
||||||
argv = strv_split_full(cmd, NULL, SPLIT_QUOTES|SPLIT_RELAX);
|
r = strv_split_full(&argv, cmd, NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_RETAIN_ESCAPE);
|
||||||
if (!argv)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_device_error_errno(event->dev, r, "Failed to split command: %m");
|
||||||
|
|
||||||
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),
|
||||||
|
|
|
@ -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(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r,
|
log_device_full_errno(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(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q,
|
log_device_full_errno(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(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q,
|
log_device_full_errno(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);
|
||||||
|
|
||||||
|
|
|
@ -182,43 +182,46 @@ struct UdevRules {
|
||||||
|
|
||||||
/*** Logging helpers ***/
|
/*** Logging helpers ***/
|
||||||
|
|
||||||
#define log_rule_full(device, rules, level, error, fmt, ...) \
|
#define log_rule_full_errno(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(device, level, error, "%s:%u " fmt, \
|
log_device_full_errno(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_debug(device, rules, ...) log_rule_full(device, rules, LOG_DEBUG, 0, ##__VA_ARGS__)
|
#define log_rule_full(device, rules, level, ...) (void) log_rule_full_errno(device, rules, level, 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_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_DEBUG, error, ##__VA_ARGS__)
|
#define log_rule_debug(device, rules, ...) log_rule_full_errno(device, rules, LOG_DEBUG, 0, __VA_ARGS__)
|
||||||
#define log_rule_info_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_INFO, error, ##__VA_ARGS__)
|
#define log_rule_info(device, rules, ...) log_rule_full(device, rules, LOG_INFO, __VA_ARGS__)
|
||||||
#define log_rule_notice_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_NOTICE, error, ##__VA_ARGS__)
|
#define log_rule_notice(device, rules, ...) log_rule_full(device, rules, LOG_NOTICE, __VA_ARGS__)
|
||||||
#define log_rule_warning_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_WARNING, error, ##__VA_ARGS__)
|
#define log_rule_warning(device, rules, ...) log_rule_full(device, rules, LOG_WARNING, __VA_ARGS__)
|
||||||
#define log_rule_error_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_ERR, error, ##__VA_ARGS__)
|
#define log_rule_error(device, rules, ...) log_rule_full(device, rules, LOG_ERR, __VA_ARGS__)
|
||||||
|
|
||||||
#define log_token_full(rules, ...) log_rule_full(NULL, rules, ##__VA_ARGS__)
|
#define log_rule_debug_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_DEBUG, error, __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_debug(rules, ...) log_token_full(rules, LOG_DEBUG, 0, ##__VA_ARGS__)
|
#define log_token_full_errno(rules, level, error, ...) log_rule_full_errno(NULL, rules, level, error, __VA_ARGS__)
|
||||||
#define log_token_info(rules, ...) log_token_full(rules, LOG_INFO, 0, ##__VA_ARGS__)
|
#define log_token_full(rules, level, ...) (void) log_token_full_errno(rules, level, 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_errno(rules, error, ...) log_token_full(rules, LOG_DEBUG, error, ##__VA_ARGS__)
|
#define log_token_debug(rules, ...) log_token_full_errno(rules, LOG_DEBUG, 0, __VA_ARGS__)
|
||||||
#define log_token_info_errno(rules, error, ...) log_token_full(rules, LOG_INFO, error, ##__VA_ARGS__)
|
#define log_token_info(rules, ...) log_token_full(rules, LOG_INFO, __VA_ARGS__)
|
||||||
#define log_token_notice_errno(rules, error, ...) log_token_full(rules, LOG_NOTICE, error, ##__VA_ARGS__)
|
#define log_token_notice(rules, ...) log_token_full(rules, LOG_NOTICE, __VA_ARGS__)
|
||||||
#define log_token_warning_errno(rules, error, ...) log_token_full(rules, LOG_WARNING, error, ##__VA_ARGS__)
|
#define log_token_warning(rules, ...) log_token_full(rules, LOG_WARNING, __VA_ARGS__)
|
||||||
#define log_token_error_errno(rules, error, ...) log_token_full(rules, LOG_ERR, error, ##__VA_ARGS__)
|
#define log_token_error(rules, ...) log_token_full(rules, LOG_ERR, __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), \
|
||||||
|
|
|
@ -97,10 +97,8 @@ 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(dev,
|
return log_device_full_errno(dev, errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
|
||||||
errno == ENOENT ? LOG_DEBUG : LOG_ERR,
|
"Failed to add device '%s' to watch: %m", devnode);
|
||||||
errno,
|
|
||||||
"Failed to add device '%s' to watch: %m", devnode);
|
|
||||||
|
|
||||||
device_set_watch_handle(dev, wd);
|
device_set_watch_handle(dev, wd);
|
||||||
|
|
||||||
|
|
|
@ -1686,8 +1686,11 @@ 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) {
|
||||||
(void) sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024);
|
r = 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)
|
||||||
|
|
|
@ -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 '.
|
||||||
*/
|
*/
|
||||||
exec_split = strv_split_full(exec, WHITESPACE, SPLIT_QUOTES | SPLIT_RELAX);
|
r = strv_split_full(&exec_split, exec, NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX);
|
||||||
if (!exec_split)
|
if (r < 0)
|
||||||
return -ENOMEM;
|
return r;
|
||||||
|
|
||||||
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");
|
||||||
|
|
Loading…
Reference in New Issue