Compare commits
42 Commits
bbb4248a5e
...
5e20ad261d
Author | SHA1 | Date |
---|---|---|
![]() |
5e20ad261d | |
![]() |
7c78827c19 | |
![]() |
1b88fa8ae4 | |
![]() |
2f7d51ee01 | |
![]() |
74c2faff3d | |
![]() |
354be2190f | |
![]() |
d17ae799f2 | |
![]() |
13d9fecdd0 | |
![]() |
d9ac4b925d | |
![]() |
edc49209f1 | |
![]() |
2791b2bc3d | |
![]() |
7baf24c949 | |
![]() |
ce921df8d1 | |
![]() |
c96a5d9912 | |
![]() |
6858c1fd8b | |
![]() |
b1236ce38b | |
![]() |
710653d3bc | |
![]() |
d9826d303b | |
![]() |
10ed8cda58 | |
![]() |
52278e0634 | |
![]() |
4cf443e644 | |
![]() |
a85f73fa55 | |
![]() |
09ddaf2af3 | |
![]() |
919aeb666a | |
![]() |
1b25b88f82 | |
![]() |
5c6e6f5ad1 | |
![]() |
10d786458c | |
![]() |
d3af116afd | |
![]() |
32b5deb1b2 | |
![]() |
6d1a69d0f0 | |
![]() |
25a9bd72ef | |
![]() |
4100e0f207 | |
![]() |
765ffa12ee | |
![]() |
5f43554f90 | |
![]() |
70669fa2fe | |
![]() |
f92fac7e9b | |
![]() |
855800aaec | |
![]() |
f8b0277101 | |
![]() |
9ee08c8dce | |
![]() |
19aa8c0f0e | |
![]() |
3e8a4defa8 | |
![]() |
76a8f5ae4b |
|
@ -25,7 +25,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
- uses: systemd/mkosi@7e4ec15aee6b98300b2ee14265bc647a716a9f8a
|
||||
- uses: systemd/mkosi@dbb4020beee2cdf250f93a425794f1cf8b0fe693
|
||||
|
||||
# Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space
|
||||
# immediately, we remove the files in the background. However, we first move them to a different location
|
||||
|
@ -90,7 +90,6 @@ jobs:
|
|||
sudo mkosi sandbox -- \
|
||||
meson setup \
|
||||
--buildtype=debugoptimized \
|
||||
-Dintegration-tests=true \
|
||||
build
|
||||
|
||||
- name: Build image
|
||||
|
@ -120,7 +119,8 @@ jobs:
|
|||
meson test \
|
||||
-C build \
|
||||
--no-rebuild \
|
||||
--suite integration-tests \
|
||||
--setup=integration \
|
||||
--suite=integration-tests \
|
||||
--print-errorlogs \
|
||||
--no-stdsplit \
|
||||
--num-processes "$(($(nproc) - 1))" \
|
||||
|
|
|
@ -120,7 +120,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
- uses: systemd/mkosi@7e4ec15aee6b98300b2ee14265bc647a716a9f8a
|
||||
- uses: systemd/mkosi@dbb4020beee2cdf250f93a425794f1cf8b0fe693
|
||||
|
||||
# Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space
|
||||
# immediately, we remove the files in the background. However, we first move them to a different location
|
||||
|
@ -197,7 +197,6 @@ jobs:
|
|||
sudo mkosi sandbox -- \
|
||||
meson setup \
|
||||
--buildtype=debugoptimized \
|
||||
-Dintegration-tests=true \
|
||||
-Dbpf-framework=disabled \
|
||||
build
|
||||
|
||||
|
@ -233,7 +232,8 @@ jobs:
|
|||
meson test \
|
||||
-C build \
|
||||
--no-rebuild \
|
||||
--suite integration-tests \
|
||||
--setup=integration \
|
||||
--suite=integration-tests \
|
||||
--print-errorlogs \
|
||||
--no-stdsplit \
|
||||
--num-processes "$(($(nproc) - 1))" \
|
||||
|
|
4
TODO
4
TODO
|
@ -735,10 +735,6 @@ Features:
|
|||
* machined: optionally track nspawn unix-export/ runtime for each machined, and
|
||||
then update systemd-ssh-proxy so that it can connect to that.
|
||||
|
||||
* add a new ExecStart= flag that inserts the configured user's shell as first
|
||||
word in the command line. (maybe use character '.'). Usecase: tool such as
|
||||
run0 can use that to spawn the target user's default shell.
|
||||
|
||||
* introduce mntid_t, and make it 64bit, as apparently the kernel switched to
|
||||
64bit mount ids
|
||||
|
||||
|
|
21
man/run0.xml
21
man/run0.xml
|
@ -167,6 +167,18 @@
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--login-environment</option></term>
|
||||
<term><option>-i</option></term>
|
||||
|
||||
<listitem><para>Invokes the target user's login shell and runs the specified command (if any) via it.
|
||||
If <option>-D/--chdir=</option> is not specified, additionally switch to the target user's home directory
|
||||
even for the root user.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--setenv=<replaceable>NAME</replaceable>[=<replaceable>VALUE</replaceable>]</option></term>
|
||||
|
||||
|
@ -290,9 +302,12 @@
|
|||
|
||||
<para>All command line arguments after the first non-option argument become part of the command line of
|
||||
the launched process. If no command line is specified an interactive shell is invoked. The shell to
|
||||
invoke may be controlled via <option>--setenv=SHELL=…</option> and currently defaults to the
|
||||
<emphasis>originating user's</emphasis> shell (i.e. not the target user's!) if operating locally, or
|
||||
<filename>/bin/sh</filename> when operating with <option>--machine=</option>.</para>
|
||||
invoke may be controlled via <option>-i/--login-environment</option> - when specified the target user's shell
|
||||
is used - or <option>--setenv=SHELL=…</option>. By default, the <emphasis>originating user's</emphasis> shell
|
||||
is executed if operating locally, or <filename>/bin/sh</filename> when operating with <option>--machine=</option>.</para>
|
||||
|
||||
<para>Note that unlike <command>sudo</command>, <command>run0</command> always spawns shells with login shell
|
||||
semantics, regardless of <option>-i</option>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
|
|
@ -1397,7 +1397,7 @@
|
|||
<tbody>
|
||||
<row>
|
||||
<entry><literal>@</literal></entry>
|
||||
<entry>If the executable path is prefixed with <literal>@</literal>, the second specified token will be passed as <constant>argv[0]</constant> to the executed process (instead of the actual filename), followed by the further arguments specified.</entry>
|
||||
<entry>If the executable path is prefixed with <literal>@</literal>, the second specified token will be passed as <constant>argv[0]</constant> to the executed process (instead of the actual filename), followed by the further arguments specified, unless <literal>|</literal> is also specified, in which case it enables login shell semantics for the shell spawned by prefixing <literal>-</literal> to <constant>argv[0]</constant>.</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
|
@ -1420,14 +1420,19 @@
|
|||
|
||||
<entry>Similar to the <literal>+</literal> character discussed above this permits invoking command lines with elevated privileges. However, unlike <literal>+</literal> the <literal>!</literal> character exclusively alters the effect of <varname>User=</varname>, <varname>Group=</varname> and <varname>SupplementaryGroups=</varname>, i.e. only the stanzas that affect user and group credentials. Note that this setting may be combined with <varname>DynamicUser=</varname>, in which case a dynamic user/group pair is allocated before the command is invoked, but credential changing is left to the executed process itself.</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>|</literal></entry>
|
||||
|
||||
<entry>If <literal>|</literal> is specified standalone as executable path, invoke the user's default shell. If specified as a prefix, use the shell (<literal>-c</literal>) to spawn the executable. When <literal>@</literal> is used in conjunction, <constant>argv[0]</constant> of shell will be prefixed with <literal>-</literal> to enable login shell semantics.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para><literal>@</literal>, <literal>-</literal>, <literal>:</literal>, and one of
|
||||
<literal>+</literal>/<literal>!</literal>/<literal>!!</literal> may be used together and they can appear in any
|
||||
order. However, only one of <literal>+</literal>, <literal>!</literal>, <literal>!!</literal> may be used at a
|
||||
time.</para>
|
||||
<para><literal>@</literal>, <literal>|</literal>, <literal>-</literal>, <literal>:</literal>, and one of
|
||||
<literal>+</literal>/<literal>!</literal> may be used together and they can appear in any order.
|
||||
However, <literal>+</literal> and <literal>!</literal> may not be specified at the same time.</para>
|
||||
|
||||
<para>For each command, the first argument must be either an absolute path to an executable or a simple
|
||||
file name without any slashes. If the command is not a full (absolute) path, it will be resolved to a
|
||||
|
@ -1490,11 +1495,6 @@ ExecStart=/bin/echo $ONE $TWO $THREE</programlisting>
|
|||
includes e.g. <varname>$USER</varname>, but not
|
||||
<varname>$TERM</varname>).</para>
|
||||
|
||||
<para>Note that shell command lines are not directly supported. If
|
||||
shell command lines are to be used, they need to be passed
|
||||
explicitly to a shell implementation of some kind. Example:</para>
|
||||
<programlisting>ExecStart=sh -c 'dmesg | tac'</programlisting>
|
||||
|
||||
<para>Example:</para>
|
||||
|
||||
<programlisting>ExecStart=echo one
|
||||
|
|
11
meson.build
11
meson.build
|
@ -13,6 +13,12 @@ project('systemd', 'c',
|
|||
meson_version : '>= 0.62.0',
|
||||
)
|
||||
|
||||
add_test_setup(
|
||||
'default',
|
||||
exclude_suites : ['integration-tests'],
|
||||
is_default : true,
|
||||
)
|
||||
|
||||
project_major_version = meson.project_version().split('.')[0].split('~')[0]
|
||||
if meson.project_version().contains('.')
|
||||
project_minor_version = meson.project_version().split('.')[-1].split('~')[0]
|
||||
|
@ -339,7 +345,6 @@ meson_build_sh = find_program('tools/meson-build.sh')
|
|||
want_tests = get_option('tests')
|
||||
want_slow_tests = want_tests != 'false' and get_option('slow-tests')
|
||||
want_fuzz_tests = want_tests != 'false' and get_option('fuzz-tests')
|
||||
want_integration_tests = want_tests != 'false' and get_option('integration-tests')
|
||||
install_tests = want_tests != 'false' and get_option('install-tests')
|
||||
|
||||
if add_languages('cpp', native : false, required : fuzzer_build)
|
||||
|
@ -2661,10 +2666,6 @@ endif
|
|||
#####################################################################
|
||||
|
||||
mkosi = find_program('mkosi', required : false)
|
||||
if want_integration_tests and not mkosi.found()
|
||||
error('Could not find mkosi which is required to run the integration tests')
|
||||
endif
|
||||
|
||||
mkosi_depends = public_programs
|
||||
|
||||
foreach executable : ['systemd-journal-remote', 'systemd-sbsign', 'systemd-keyutil']
|
||||
|
|
|
@ -509,7 +509,7 @@ option('install-tests', type : 'boolean', value : false,
|
|||
description : 'install test executables')
|
||||
option('log-message-verification', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
|
||||
description : 'do fake printf() calls to verify format strings')
|
||||
option('integration-tests', type : 'boolean', value : false,
|
||||
option('integration-tests', type : 'boolean', value : false, deprecated : true,
|
||||
description : 'run the integration tests')
|
||||
|
||||
option('ok-color', type : 'combo',
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
[Config]
|
||||
MinimumVersion=commit:7e4ec15aee6b98300b2ee14265bc647a716a9f8a
|
||||
MinimumVersion=commit:dbb4020beee2cdf250f93a425794f1cf8b0fe693
|
||||
Dependencies=
|
||||
exitrd
|
||||
initrd
|
||||
|
@ -78,8 +78,7 @@ KernelCommandLine=
|
|||
oops=panic
|
||||
panic=-1
|
||||
softlockup_panic=1
|
||||
# Disabled due to BTRFS issue, waiting for the fix to become available
|
||||
panic_on_warn=0
|
||||
panic_on_warn=1
|
||||
psi=1
|
||||
mitigations=off
|
||||
|
||||
|
|
|
@ -77,6 +77,20 @@ ENV{DDC_DEVICE}=="?*", TAG+="uaccess"
|
|||
# media player raw devices (for user-mode drivers, Android SDK, etc.)
|
||||
SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess"
|
||||
|
||||
# Android devices (ADB DbC, ADB, Fastboot)
|
||||
# Used to interact with devices over Android Debug Bridge and Fastboot protocols, see:
|
||||
# * https://developer.android.com/tools/adb
|
||||
# * https://source.android.com/docs/setup/test/running
|
||||
# * https://source.android.com/docs/setup/test/flash
|
||||
#
|
||||
# The bInterfaceClass and bInterfaceSubClass used are documented in source code here:
|
||||
# * https://android.googlesource.com/platform/packages/modules/adb/+/d0db47dcdf941673f405e1095e6ffb5e565902e5/adb.h#199
|
||||
# * https://android.googlesource.com/platform/system/core/+/7199051aaf0ddfa2849650933119307327d8669c/fastboot/fastboot.cpp#244
|
||||
#
|
||||
# Since it's using a generic vendor specific interface class, this can potentially result
|
||||
# in a rare case where non-ADB/Fastboot device ends up with an ID_DEBUG_APPLIANCE="android".
|
||||
SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="*:dc0201:*|*:ff4201:*|*:ff4203:*", ENV{ID_DEBUG_APPLIANCE}="android"
|
||||
|
||||
# software-defined radio communication devices
|
||||
ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="uaccess"
|
||||
|
||||
|
@ -111,4 +125,7 @@ SUBSYSTEM=="hidraw", ENV{ID_HARDWARE_WALLET}=="1", TAG+="uaccess"
|
|||
# As defined in https://en.wikipedia.org/wiki/3Dconnexion
|
||||
SUBSYSTEM=="hidraw", ENV{ID_INPUT_3D_MOUSE}=="1", TAG+="uaccess"
|
||||
|
||||
# Debug interfaces (e.g. Android Debug Bridge)
|
||||
ENV{ID_DEBUG_APPLIANCE}=="?*", TAG+="uaccess"
|
||||
|
||||
LABEL="uaccess_end"
|
||||
|
|
|
@ -31,7 +31,7 @@ static void log_syntax_callback(const char *unit, int level, void *userdata) {
|
|||
|
||||
r = set_put_strdup(s, unit);
|
||||
if (r < 0) {
|
||||
set_free_free(*s);
|
||||
set_free(*s);
|
||||
*s = POINTER_MAX;
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ static int verify_unit(Unit *u, bool check_man, const char *root) {
|
|||
static void set_destroy_ignore_pointer_max(Set **s) {
|
||||
if (*s == POINTER_MAX)
|
||||
return;
|
||||
set_free_free(*s);
|
||||
set_free(*s);
|
||||
}
|
||||
|
||||
int verify_units(
|
||||
|
|
|
@ -884,9 +884,12 @@ int replace_env_argv(
|
|||
char ***ret_bad_variables) {
|
||||
|
||||
_cleanup_strv_free_ char **n = NULL, **unset_variables = NULL, **bad_variables = NULL;
|
||||
size_t k = 0, l = 0;
|
||||
size_t k = 0, l;
|
||||
int r;
|
||||
|
||||
assert(!strv_isempty(argv));
|
||||
assert(ret);
|
||||
|
||||
l = strv_length(argv);
|
||||
|
||||
n = new(char*, l+1);
|
||||
|
|
|
@ -1001,13 +1001,13 @@ int fd_verify_safe_flags_full(int fd, int extra_flags) {
|
|||
if (flags < 0)
|
||||
return -errno;
|
||||
|
||||
unexpected_flags = flags & ~(O_ACCMODE|O_NOFOLLOW|RAW_O_LARGEFILE|extra_flags);
|
||||
unexpected_flags = flags & ~(O_ACCMODE_STRICT|O_NOFOLLOW|RAW_O_LARGEFILE|extra_flags);
|
||||
if (unexpected_flags != 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EREMOTEIO),
|
||||
"Unexpected flags set for extrinsic fd: 0%o",
|
||||
(unsigned) unexpected_flags);
|
||||
|
||||
return flags & (O_ACCMODE | extra_flags); /* return the flags variable, but remove the noise */
|
||||
return flags & (O_ACCMODE_STRICT | extra_flags); /* return the flags variable, but remove the noise */
|
||||
}
|
||||
|
||||
int read_nr_open(void) {
|
||||
|
@ -1132,7 +1132,7 @@ int fds_are_same_mount(int fd1, int fd2) {
|
|||
}
|
||||
|
||||
const char* accmode_to_string(int flags) {
|
||||
switch (flags & O_ACCMODE) {
|
||||
switch (flags & O_ACCMODE_STRICT) {
|
||||
case O_RDONLY:
|
||||
return "ro";
|
||||
case O_WRONLY:
|
||||
|
|
|
@ -1036,7 +1036,7 @@ int open_mkdir_at_full(int dirfd, const char *path, int flags, XOpenFlags xopen_
|
|||
|
||||
if (flags & ~(O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_EXCL|O_NOATIME|O_NOFOLLOW|O_PATH))
|
||||
return -EINVAL;
|
||||
if ((flags & O_ACCMODE) != O_RDONLY)
|
||||
if ((flags & O_ACCMODE_STRICT) != O_RDONLY)
|
||||
return -EINVAL;
|
||||
|
||||
/* Note that O_DIRECTORY|O_NOFOLLOW is implied, but we allow specifying it anyway. The following
|
||||
|
|
|
@ -88,8 +88,10 @@ OrderedHashmap* _ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DE
|
|||
#define hashmap_new(ops) _hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
#define ordered_hashmap_new(ops) _ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
|
||||
#define hashmap_free_and_replace(a, b) \
|
||||
#define hashmap_free_and_replace(a, b) \
|
||||
free_and_replace_full(a, b, hashmap_free)
|
||||
#define ordered_hashmap_free_and_replace(a, b) \
|
||||
free_and_replace_full(a, b, ordered_hashmap_free)
|
||||
|
||||
HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
|
||||
static inline Hashmap* hashmap_free(Hashmap *h) {
|
||||
|
|
|
@ -43,3 +43,9 @@
|
|||
#ifndef AT_HANDLE_FID
|
||||
#define AT_HANDLE_FID AT_REMOVEDIR
|
||||
#endif
|
||||
|
||||
/* On musl, O_ACCMODE is defined as (03|O_SEARCH), unlike glibc which defines it as
|
||||
* (O_RDONLY|O_WRONLY|O_RDWR). Additionally, O_SEARCH is simply defined as O_PATH. This changes the behaviour
|
||||
* of O_ACCMODE in certain situations, which we don't want. This definition is copied from glibc and works
|
||||
* around the problems with musl's definition. */
|
||||
#define O_ACCMODE_STRICT (O_RDONLY|O_WRONLY|O_RDWR)
|
||||
|
|
|
@ -1470,11 +1470,12 @@ int bus_property_get_exec_ex_command_list(
|
|||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
static char *exec_command_flags_to_exec_chars(ExecCommandFlags flags) {
|
||||
static char* exec_command_flags_to_exec_chars(ExecCommandFlags flags) {
|
||||
return strjoin(FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE) ? "-" : "",
|
||||
FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND) ? ":" : "",
|
||||
FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED) ? "+" : "",
|
||||
FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID) ? "!" : "");
|
||||
FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID) ? "!" : "",
|
||||
FLAGS_SET(flags, EXEC_COMMAND_PREFIX_SHELL) ? "|" : "");
|
||||
}
|
||||
|
||||
int bus_set_transient_exec_command(
|
||||
|
@ -1502,30 +1503,58 @@ int bus_set_transient_exec_command(
|
|||
return r;
|
||||
|
||||
while ((r = sd_bus_message_enter_container(message, 'r', ex_prop ? "sasas" : "sasb")) > 0) {
|
||||
_cleanup_strv_free_ char **argv = NULL, **ex_opts = NULL;
|
||||
_cleanup_strv_free_ char **argv = NULL;
|
||||
const char *path;
|
||||
int b;
|
||||
ExecCommandFlags command_flags;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!path_is_absolute(path) && !filename_is_valid(path))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"\"%s\" is neither a valid executable name nor an absolute path",
|
||||
path);
|
||||
|
||||
r = sd_bus_message_read_strv(message, &argv);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (strv_isempty(argv))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"\"%s\" argv cannot be empty", name);
|
||||
if (ex_prop) {
|
||||
_cleanup_strv_free_ char **ex_opts = NULL;
|
||||
|
||||
r = ex_prop ? sd_bus_message_read_strv(message, &ex_opts) : sd_bus_message_read(message, "b", &b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = sd_bus_message_read_strv(message, &ex_opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = exec_command_flags_from_strv(ex_opts, &command_flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
int b;
|
||||
|
||||
r = sd_bus_message_read(message, "b", &b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
command_flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
|
||||
}
|
||||
|
||||
if (!FLAGS_SET(command_flags, EXEC_COMMAND_PREFIX_SHELL)) {
|
||||
if (!path_is_absolute(path) && !filename_is_valid(path))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"\"%s\" is neither a valid executable name nor an absolute path",
|
||||
path);
|
||||
|
||||
if (strv_isempty(argv))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"\"%s\" argv cannot be empty", name);
|
||||
} else {
|
||||
/* Always normalize path and argv0 to be "sh" */
|
||||
path = "/bin/sh";
|
||||
|
||||
if (strv_isempty(argv))
|
||||
r = strv_extend(&argv, path);
|
||||
else
|
||||
r = free_and_strdup(&argv[0], argv[0][0] == '-' ? "-sh" : "sh");
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
|
@ -1540,19 +1569,13 @@ int bus_set_transient_exec_command(
|
|||
|
||||
*c = (ExecCommand) {
|
||||
.argv = TAKE_PTR(argv),
|
||||
.flags = command_flags,
|
||||
};
|
||||
|
||||
r = path_simplify_alloc(path, &c->path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ex_prop) {
|
||||
r = exec_command_flags_from_strv(ex_opts, &c->flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (b)
|
||||
c->flags |= EXEC_COMMAND_IGNORE_FAILURE;
|
||||
|
||||
exec_command_append_list(exec_command, TAKE_PTR(c));
|
||||
}
|
||||
|
||||
|
@ -1583,17 +1606,19 @@ int bus_set_transient_exec_command(
|
|||
_cleanup_free_ char *a = NULL, *exec_chars = NULL;
|
||||
UnitWriteFlags esc_flags = UNIT_ESCAPE_SPECIFIERS |
|
||||
(FLAGS_SET(c->flags, EXEC_COMMAND_NO_ENV_EXPAND) ? UNIT_ESCAPE_EXEC_SYNTAX : UNIT_ESCAPE_EXEC_SYNTAX_ENV);
|
||||
bool prefix_shell = FLAGS_SET(c->flags, EXEC_COMMAND_PREFIX_SHELL);
|
||||
|
||||
exec_chars = exec_command_flags_to_exec_chars(c->flags);
|
||||
if (!exec_chars)
|
||||
return -ENOMEM;
|
||||
|
||||
a = unit_concat_strv(c->argv, esc_flags);
|
||||
a = unit_concat_strv(prefix_shell ? strv_skip(c->argv, 1) : c->argv, esc_flags);
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
|
||||
if (streq_ptr(c->path, c->argv ? c->argv[0] : NULL))
|
||||
fprintf(f, "%s=%s%s\n", written_name, exec_chars, a);
|
||||
if (prefix_shell || streq(c->path, c->argv[0]))
|
||||
fprintf(f, "%s=%s%s%s\n",
|
||||
written_name, exec_chars, prefix_shell && c->argv[0][0] == '-' ? "@" : "", a);
|
||||
else {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
const char *p;
|
||||
|
|
|
@ -267,7 +267,7 @@ static int acquire_path(const char *path, int flags, mode_t mode) {
|
|||
|
||||
assert(path);
|
||||
|
||||
if (IN_SET(flags & O_ACCMODE, O_WRONLY, O_RDWR))
|
||||
if (IN_SET(flags & O_ACCMODE_STRICT, O_WRONLY, O_RDWR))
|
||||
flags |= O_CREAT;
|
||||
|
||||
fd = open(path, flags|O_NOCTTY, mode);
|
||||
|
@ -291,9 +291,9 @@ static int acquire_path(const char *path, int flags, mode_t mode) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if ((flags & O_ACCMODE) == O_RDONLY)
|
||||
if ((flags & O_ACCMODE_STRICT) == O_RDONLY)
|
||||
r = shutdown(fd, SHUT_WR);
|
||||
else if ((flags & O_ACCMODE) == O_WRONLY)
|
||||
else if ((flags & O_ACCMODE_STRICT) == O_WRONLY)
|
||||
r = shutdown(fd, SHUT_RD);
|
||||
else
|
||||
r = 0;
|
||||
|
@ -4649,12 +4649,11 @@ int exec_invoke(
|
|||
const CGroupContext *cgroup_context,
|
||||
int *exit_status) {
|
||||
|
||||
_cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **joined_exec_search_path = NULL, **accum_env = NULL, **replaced_argv = NULL;
|
||||
_cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **joined_exec_search_path = NULL, **accum_env = NULL;
|
||||
int r;
|
||||
const char *username = NULL, *groupname = NULL;
|
||||
_cleanup_free_ char *home_buffer = NULL, *memory_pressure_path = NULL, *own_user = NULL;
|
||||
const char *pwent_home = NULL, *shell = NULL;
|
||||
char **final_argv = NULL;
|
||||
dev_t journal_stream_dev = 0;
|
||||
ino_t journal_stream_ino = 0;
|
||||
bool needs_sandboxing, /* Do we need to set up full sandboxing? (i.e. all namespacing, all MAC stuff, caps, yadda yadda */
|
||||
|
@ -4896,7 +4895,7 @@ int exec_invoke(
|
|||
|
||||
if (context->user)
|
||||
u = context->user;
|
||||
else if (context->pam_name) {
|
||||
else if (context->pam_name || FLAGS_SET(command->flags, EXEC_COMMAND_PREFIX_SHELL)) {
|
||||
/* If PAM is enabled but no user name is explicitly selected, then use our own one. */
|
||||
own_user = getusername_malloc();
|
||||
if (!own_user) {
|
||||
|
@ -5501,17 +5500,28 @@ int exec_invoke(
|
|||
/* Now that the mount namespace has been set up and privileges adjusted, let's look for the thing we
|
||||
* shall execute. */
|
||||
|
||||
const char *path = command->path;
|
||||
|
||||
if (FLAGS_SET(command->flags, EXEC_COMMAND_PREFIX_SHELL)) {
|
||||
if (!shell) {
|
||||
log_exec_debug(context, params,
|
||||
"Shell prefixing requested for user without default shell, using /bin/sh: %s",
|
||||
strna(username));
|
||||
assert(streq(path, "/bin/sh"));
|
||||
} else
|
||||
path = shell;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *executable = NULL;
|
||||
_cleanup_close_ int executable_fd = -EBADF;
|
||||
r = find_executable_full(command->path, /* root= */ NULL, context->exec_search_path, false, &executable, &executable_fd);
|
||||
r = find_executable_full(path, /* root= */ NULL, context->exec_search_path, false, &executable, &executable_fd);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_EXEC;
|
||||
log_exec_struct_errno(context, params, LOG_NOTICE, r,
|
||||
LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED_STR),
|
||||
LOG_EXEC_MESSAGE(params,
|
||||
"Unable to locate executable '%s': %m",
|
||||
command->path),
|
||||
LOG_ITEM("EXECUTABLE=%s", command->path));
|
||||
"Unable to locate executable '%s': %m", path),
|
||||
LOG_ITEM("EXECUTABLE=%s", path));
|
||||
/* If the error will be ignored by manager, tune down the log level here. Missing executable
|
||||
* is very much expected in this case. */
|
||||
return r != -ENOMEM && FLAGS_SET(command->flags, EXEC_COMMAND_IGNORE_FAILURE) ? 1 : r;
|
||||
|
@ -5935,10 +5945,13 @@ int exec_invoke(
|
|||
strv_free_and_replace(accum_env, ee);
|
||||
}
|
||||
|
||||
if (!FLAGS_SET(command->flags, EXEC_COMMAND_NO_ENV_EXPAND)) {
|
||||
_cleanup_strv_free_ char **replaced_argv = NULL, **prefixed_argv = NULL;
|
||||
char **final_argv = FLAGS_SET(command->flags, EXEC_COMMAND_PREFIX_SHELL) ? strv_skip(command->argv, 1) : command->argv;
|
||||
|
||||
if (final_argv && !FLAGS_SET(command->flags, EXEC_COMMAND_NO_ENV_EXPAND)) {
|
||||
_cleanup_strv_free_ char **unset_variables = NULL, **bad_variables = NULL;
|
||||
|
||||
r = replace_env_argv(command->argv, accum_env, &replaced_argv, &unset_variables, &bad_variables);
|
||||
r = replace_env_argv(final_argv, accum_env, &replaced_argv, &unset_variables, &bad_variables);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_MEMORY;
|
||||
return log_exec_error_errno(context,
|
||||
|
@ -5963,8 +5976,33 @@ int exec_invoke(
|
|||
"Invalid environment variable name evaluates to an empty string: %s",
|
||||
strna(jb));
|
||||
}
|
||||
} else
|
||||
final_argv = command->argv;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(command->flags, EXEC_COMMAND_PREFIX_SHELL)) {
|
||||
r = strv_extendf(&prefixed_argv, "%s%s", command->argv[0][0] == '-' ? "-" : "", path);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_MEMORY;
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (!strv_isempty(final_argv)) {
|
||||
_cleanup_free_ char *cmdline_joined = NULL;
|
||||
|
||||
cmdline_joined = strv_join(final_argv, " ");
|
||||
if (!cmdline_joined) {
|
||||
*exit_status = EXIT_MEMORY;
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = strv_extend_many(&prefixed_argv, "-c", cmdline_joined);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_MEMORY;
|
||||
return log_oom();
|
||||
}
|
||||
}
|
||||
|
||||
final_argv = prefixed_argv;
|
||||
}
|
||||
|
||||
log_command_line(context, params, "Executing", executable, final_argv);
|
||||
|
||||
|
|
|
@ -888,7 +888,7 @@ int config_parse_exec(
|
|||
bool semicolon;
|
||||
|
||||
do {
|
||||
_cleanup_free_ char *path = NULL, *firstword = NULL;
|
||||
_cleanup_free_ char *firstword = NULL;
|
||||
|
||||
semicolon = false;
|
||||
|
||||
|
@ -915,6 +915,8 @@ int config_parse_exec(
|
|||
*
|
||||
* "-": Ignore if the path doesn't exist
|
||||
* "@": Allow overriding argv[0] (supplied as a separate argument)
|
||||
* "|": Prefix the cmdline with target user's shell (when combined with "@" invoke
|
||||
* login shell semantics)
|
||||
* ":": Disable environment variable substitution
|
||||
* "+": Run with full privileges and no sandboxing
|
||||
* "!": Apply sandboxing except for user/group credentials
|
||||
|
@ -926,6 +928,8 @@ int config_parse_exec(
|
|||
separate_argv0 = true;
|
||||
else if (*f == ':' && !FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND))
|
||||
flags |= EXEC_COMMAND_NO_ENV_EXPAND;
|
||||
else if (*f == '|' && !FLAGS_SET(flags, EXEC_COMMAND_PREFIX_SHELL))
|
||||
flags |= EXEC_COMMAND_PREFIX_SHELL;
|
||||
else if (*f == '+' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID)) && !ambient_hack)
|
||||
flags |= EXEC_COMMAND_FULLY_PRIVILEGED;
|
||||
else if (*f == '!' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID)) && !ambient_hack)
|
||||
|
@ -947,46 +951,60 @@ int config_parse_exec(
|
|||
|
||||
ignore = FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE);
|
||||
|
||||
r = unit_path_printf(u, f, &path);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r,
|
||||
"Failed to resolve unit specifiers in '%s'%s: %m",
|
||||
f, ignore ? ", ignoring" : "");
|
||||
return ignore ? 0 : -ENOEXEC;
|
||||
}
|
||||
|
||||
if (isempty(path)) {
|
||||
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
|
||||
"Empty path in command line%s: %s",
|
||||
ignore ? ", ignoring" : "", rvalue);
|
||||
return ignore ? 0 : -ENOEXEC;
|
||||
}
|
||||
if (!string_is_safe(path)) {
|
||||
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
|
||||
"Executable path contains special characters%s: %s",
|
||||
ignore ? ", ignoring" : "", path);
|
||||
return ignore ? 0 : -ENOEXEC;
|
||||
}
|
||||
if (path_implies_directory(path)) {
|
||||
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
|
||||
"Executable path specifies a directory%s: %s",
|
||||
ignore ? ", ignoring" : "", path);
|
||||
return ignore ? 0 : -ENOEXEC;
|
||||
}
|
||||
|
||||
if (!(path_is_absolute(path) ? path_is_valid(path) : filename_is_valid(path))) {
|
||||
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
|
||||
"Neither a valid executable name nor an absolute path%s: %s",
|
||||
ignore ? ", ignoring" : "", path);
|
||||
return ignore ? 0 : -ENOEXEC;
|
||||
}
|
||||
|
||||
_cleanup_strv_free_ char **args = NULL;
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
||||
if (!separate_argv0)
|
||||
if (strv_extend(&args, path) < 0)
|
||||
if (FLAGS_SET(flags, EXEC_COMMAND_PREFIX_SHELL)) {
|
||||
/* Use /bin/sh as placeholder since we can't do NSS lookups in pid1. This would
|
||||
* be exported to various dbus properties and is used to determine SELinux label -
|
||||
* which isn't accurate, but is a best-effort thing to assume all shells have more
|
||||
* or less the same label. */
|
||||
path = strdup("/bin/sh");
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
if (strv_extend_many(&args, separate_argv0 ? "-sh" : "sh", empty_to_null(f)) < 0)
|
||||
return log_oom();
|
||||
} else {
|
||||
r = unit_path_printf(u, f, &path);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r,
|
||||
"Failed to resolve unit specifiers in '%s'%s: %m",
|
||||
f, ignore ? ", ignoring" : "");
|
||||
return ignore ? 0 : -ENOEXEC;
|
||||
}
|
||||
|
||||
if (isempty(path)) {
|
||||
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
|
||||
"Empty path in command line%s: %s",
|
||||
ignore ? ", ignoring" : "", rvalue);
|
||||
return ignore ? 0 : -ENOEXEC;
|
||||
}
|
||||
if (!string_is_safe(path)) {
|
||||
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
|
||||
"Executable path contains special characters%s: %s",
|
||||
ignore ? ", ignoring" : "", path);
|
||||
return ignore ? 0 : -ENOEXEC;
|
||||
}
|
||||
if (path_implies_directory(path)) {
|
||||
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
|
||||
"Executable path specifies a directory%s: %s",
|
||||
ignore ? ", ignoring" : "", path);
|
||||
return ignore ? 0 : -ENOEXEC;
|
||||
}
|
||||
|
||||
if (!(path_is_absolute(path) ? path_is_valid(path) : filename_is_valid(path))) {
|
||||
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
|
||||
"Neither a valid executable name nor an absolute path%s: %s",
|
||||
ignore ? ", ignoring" : "", path);
|
||||
return ignore ? 0 : -ENOEXEC;
|
||||
}
|
||||
|
||||
if (!separate_argv0)
|
||||
if (strv_extend(&args, path) < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
while (!isempty(p)) {
|
||||
_cleanup_free_ char *word = NULL, *resolved = NULL;
|
||||
|
||||
|
|
|
@ -3204,7 +3204,7 @@ int service_deserialize_exec_command(
|
|||
bool control, found = false, last = false;
|
||||
int r;
|
||||
|
||||
enum ExecCommandState {
|
||||
enum {
|
||||
STATE_EXEC_COMMAND_TYPE,
|
||||
STATE_EXEC_COMMAND_INDEX,
|
||||
STATE_EXEC_COMMAND_PATH,
|
||||
|
@ -3230,6 +3230,7 @@ int service_deserialize_exec_command(
|
|||
break;
|
||||
|
||||
switch (state) {
|
||||
|
||||
case STATE_EXEC_COMMAND_TYPE:
|
||||
id = service_exec_command_from_string(arg);
|
||||
if (id < 0)
|
||||
|
@ -3237,11 +3238,12 @@ int service_deserialize_exec_command(
|
|||
|
||||
state = STATE_EXEC_COMMAND_INDEX;
|
||||
break;
|
||||
|
||||
case STATE_EXEC_COMMAND_INDEX:
|
||||
/* PID 1234 is serialized as either '1234' or '+1234'. The second form is used to
|
||||
* mark the last command in a sequence. We warn if the deserialized command doesn't
|
||||
* match what we have loaded from the unit, but we don't need to warn if that is the
|
||||
* last command. */
|
||||
/* ExecCommand index 1234 is serialized as either '1234' or '+1234'. The second form
|
||||
* is used to mark the last command in a sequence. We warn if the deserialized command
|
||||
* doesn't match what we have loaded from the unit, but we don't need to warn if
|
||||
* that is the last command. */
|
||||
|
||||
r = safe_atou(arg, &idx);
|
||||
if (r < 0)
|
||||
|
@ -3250,15 +3252,18 @@ int service_deserialize_exec_command(
|
|||
|
||||
state = STATE_EXEC_COMMAND_PATH;
|
||||
break;
|
||||
|
||||
case STATE_EXEC_COMMAND_PATH:
|
||||
path = TAKE_PTR(arg);
|
||||
state = STATE_EXEC_COMMAND_ARGS;
|
||||
break;
|
||||
|
||||
case STATE_EXEC_COMMAND_ARGS:
|
||||
r = strv_extend(&argv, arg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
|
|
@ -38,11 +38,10 @@ static VacuumCandidate* vacuum_candidate_free(VacuumCandidate *c) {
|
|||
}
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(VacuumCandidate*, vacuum_candidate_free);
|
||||
|
||||
static Hashmap* vacuum_candidate_hashmap_free(Hashmap *h) {
|
||||
return hashmap_free_with_destructor(h, vacuum_candidate_free);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, vacuum_candidate_hashmap_free);
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
vacuum_candidate_hash_ops,
|
||||
void, trivial_hash_func, trivial_compare_func,
|
||||
VacuumCandidate, vacuum_candidate_free);
|
||||
|
||||
static int uid_from_file_name(const char *filename, uid_t *uid) {
|
||||
const char *p, *e, *u;
|
||||
|
@ -141,7 +140,7 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
|
|||
}
|
||||
|
||||
for (;;) {
|
||||
_cleanup_(vacuum_candidate_hashmap_freep) Hashmap *h = NULL;
|
||||
_cleanup_hashmap_free_ Hashmap *h = NULL;
|
||||
VacuumCandidate *worst = NULL;
|
||||
uint64_t sum = 0;
|
||||
|
||||
|
@ -171,10 +170,6 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
|
|||
if (exclude_fd >= 0 && stat_inode_same(&exclude_st, &st))
|
||||
continue;
|
||||
|
||||
r = hashmap_ensure_allocated(&h, NULL);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
t = timespec_load(&st.st_mtim);
|
||||
|
||||
c = hashmap_get(h, UID_TO_PTR(uid));
|
||||
|
@ -197,7 +192,7 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
|
|||
return r;
|
||||
n->oldest_mtime = t;
|
||||
|
||||
r = hashmap_put(h, UID_TO_PTR(uid), n);
|
||||
r = hashmap_ensure_put(&h, &vacuum_candidate_hash_ops, UID_TO_PTR(uid), n);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ static void device_unref_many(sd_device **devices, size_t n) {
|
|||
static void device_enumerator_unref_devices(sd_device_enumerator *enumerator) {
|
||||
assert(enumerator);
|
||||
|
||||
hashmap_clear_with_destructor(enumerator->devices_by_syspath, sd_device_unref);
|
||||
hashmap_clear(enumerator->devices_by_syspath);
|
||||
device_unref_many(enumerator->devices, enumerator->n_devices);
|
||||
enumerator->devices = mfree(enumerator->devices);
|
||||
enumerator->n_devices = 0;
|
||||
|
@ -471,6 +471,11 @@ failed:
|
|||
return r;
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
device_hash_ops_by_syspath,
|
||||
char, path_hash_func, path_compare,
|
||||
sd_device, sd_device_unref);
|
||||
|
||||
int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device) {
|
||||
const char *syspath;
|
||||
int r;
|
||||
|
@ -482,7 +487,7 @@ int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *de
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_ensure_put(&enumerator->devices_by_syspath, &string_hash_ops, syspath, device);
|
||||
r = hashmap_ensure_put(&enumerator->devices_by_syspath, &device_hash_ops_by_syspath, syspath, device);
|
||||
if (IN_SET(r, -EEXIST, 0))
|
||||
return 0;
|
||||
if (r < 0)
|
||||
|
|
|
@ -692,8 +692,8 @@ int device_clone_with_db(sd_device *device, sd_device **ret) {
|
|||
void device_cleanup_tags(sd_device *device) {
|
||||
assert(device);
|
||||
|
||||
device->all_tags = set_free_free(device->all_tags);
|
||||
device->current_tags = set_free_free(device->current_tags);
|
||||
device->all_tags = set_free(device->all_tags);
|
||||
device->current_tags = set_free(device->current_tags);
|
||||
device->property_tags_outdated = true;
|
||||
device->tags_generation++;
|
||||
}
|
||||
|
@ -701,7 +701,7 @@ void device_cleanup_tags(sd_device *device) {
|
|||
void device_cleanup_devlinks(sd_device *device) {
|
||||
assert(device);
|
||||
|
||||
set_free_free(device->devlinks);
|
||||
set_free(device->devlinks);
|
||||
device->devlinks = NULL;
|
||||
device->property_devlinks_outdated = true;
|
||||
device->devlinks_generation++;
|
||||
|
|
|
@ -98,7 +98,7 @@ DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
|||
JournalFile, journal_file_close);
|
||||
|
||||
static int mmap_prot_from_open_flags(int flags) {
|
||||
switch (flags & O_ACCMODE) {
|
||||
switch (flags & O_ACCMODE_STRICT) {
|
||||
case O_RDONLY:
|
||||
return PROT_READ;
|
||||
case O_WRONLY:
|
||||
|
@ -4075,10 +4075,10 @@ int journal_file_open(
|
|||
assert(mmap_cache);
|
||||
assert(ret);
|
||||
|
||||
if (!IN_SET((open_flags & O_ACCMODE), O_RDONLY, O_RDWR))
|
||||
if (!IN_SET((open_flags & O_ACCMODE_STRICT), O_RDONLY, O_RDWR))
|
||||
return -EINVAL;
|
||||
|
||||
if ((open_flags & O_ACCMODE) == O_RDONLY && FLAGS_SET(open_flags, O_CREAT))
|
||||
if ((open_flags & O_ACCMODE_STRICT) == O_RDONLY && FLAGS_SET(open_flags, O_CREAT))
|
||||
return -EINVAL;
|
||||
|
||||
if (fname && (open_flags & O_CREAT) && !endswith(fname, ".journal"))
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
|
@ -15,6 +14,7 @@
|
|||
#include "compress.h"
|
||||
#include "hashmap.h"
|
||||
#include "journal-def.h"
|
||||
#include "missing_fcntl.h"
|
||||
#include "mmap-cache.h"
|
||||
#include "sparse-endian.h"
|
||||
#include "time-util.h"
|
||||
|
@ -391,5 +391,5 @@ static inline uint32_t COMPRESSION_TO_HEADER_INCOMPATIBLE_FLAG(Compression c) {
|
|||
|
||||
static inline bool journal_file_writable(JournalFile *f) {
|
||||
assert(f);
|
||||
return (f->open_flags & O_ACCMODE) != O_RDONLY;
|
||||
return (f->open_flags & O_ACCMODE_STRICT) != O_RDONLY;
|
||||
}
|
||||
|
|
|
@ -46,11 +46,21 @@ static GenericNetlinkFamily *genl_family_free(GenericNetlinkFamily *f) {
|
|||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(GenericNetlinkFamily*, genl_family_free);
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
genl_family_hash_ops_by_name,
|
||||
char, string_hash_func, string_compare_func,
|
||||
GenericNetlinkFamily, genl_family_free);
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
genl_family_hash_ops_by_id,
|
||||
void, trivial_hash_func, trivial_compare_func,
|
||||
GenericNetlinkFamily, genl_family_free);
|
||||
|
||||
void genl_clear_family(sd_netlink *nl) {
|
||||
assert(nl);
|
||||
|
||||
nl->genl_family_by_name = hashmap_free_with_destructor(nl->genl_family_by_name, genl_family_free);
|
||||
nl->genl_family_by_id = hashmap_free_with_destructor(nl->genl_family_by_id, genl_family_free);
|
||||
nl->genl_family_by_name = hashmap_free(nl->genl_family_by_name);
|
||||
nl->genl_family_by_id = hashmap_free(nl->genl_family_by_id);
|
||||
}
|
||||
|
||||
static int genl_family_new_unsupported(
|
||||
|
@ -80,7 +90,7 @@ static int genl_family_new_unsupported(
|
|||
if (!f->name)
|
||||
return -ENOMEM;
|
||||
|
||||
r = hashmap_ensure_put(&nl->genl_family_by_name, &string_hash_ops, f->name, f);
|
||||
r = hashmap_ensure_put(&nl->genl_family_by_name, &genl_family_hash_ops_by_name, f->name, f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -190,11 +200,11 @@ static int genl_family_new(
|
|||
return r;
|
||||
}
|
||||
|
||||
r = hashmap_ensure_put(&nl->genl_family_by_id, NULL, UINT_TO_PTR(f->id), f);
|
||||
r = hashmap_ensure_put(&nl->genl_family_by_id, &genl_family_hash_ops_by_id, UINT_TO_PTR(f->id), f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_ensure_put(&nl->genl_family_by_name, &string_hash_ops, f->name, f);
|
||||
r = hashmap_ensure_put(&nl->genl_family_by_name, &genl_family_hash_ops_by_name, f->name, f);
|
||||
if (r < 0) {
|
||||
hashmap_remove(nl->genl_family_by_id, UINT_TO_PTR(f->id));
|
||||
return r;
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
|
||||
struct udev_device;
|
||||
|
||||
struct udev_device *udev_device_new(struct udev *udev, sd_device *device);
|
||||
sd_device *udev_device_get_sd_device(struct udev_device *udev_device);
|
||||
struct udev_device* udev_device_new(struct udev *udev, sd_device *device);
|
||||
sd_device* udev_device_get_sd_device(struct udev_device *udev_device);
|
||||
|
|
|
@ -120,7 +120,7 @@ _public_ dev_t udev_device_get_devnum(struct udev_device *udev_device) {
|
|||
*
|
||||
* Returns: the driver name string, or #NULL if there is no driver attached.
|
||||
**/
|
||||
_public_ const char *udev_device_get_driver(struct udev_device *udev_device) {
|
||||
_public_ const char* udev_device_get_driver(struct udev_device *udev_device) {
|
||||
const char *driver;
|
||||
int r;
|
||||
|
||||
|
@ -141,7 +141,7 @@ _public_ const char *udev_device_get_driver(struct udev_device *udev_device) {
|
|||
*
|
||||
* Returns: the devtype name of the udev device, or #NULL if it cannot be determined
|
||||
**/
|
||||
_public_ const char *udev_device_get_devtype(struct udev_device *udev_device) {
|
||||
_public_ const char* udev_device_get_devtype(struct udev_device *udev_device) {
|
||||
const char *devtype;
|
||||
int r;
|
||||
|
||||
|
@ -165,7 +165,7 @@ _public_ const char *udev_device_get_devtype(struct udev_device *udev_device) {
|
|||
*
|
||||
* Returns: the subsystem name of the udev device, or #NULL if it cannot be determined
|
||||
**/
|
||||
_public_ const char *udev_device_get_subsystem(struct udev_device *udev_device) {
|
||||
_public_ const char* udev_device_get_subsystem(struct udev_device *udev_device) {
|
||||
const char *subsystem;
|
||||
int r;
|
||||
|
||||
|
@ -187,7 +187,7 @@ _public_ const char *udev_device_get_subsystem(struct udev_device *udev_device)
|
|||
*
|
||||
* Returns: the property string, or #NULL if there is no such property.
|
||||
**/
|
||||
_public_ const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key) {
|
||||
_public_ const char* udev_device_get_property_value(struct udev_device *udev_device, const char *key) {
|
||||
const char *value;
|
||||
int r;
|
||||
|
||||
|
@ -200,7 +200,7 @@ _public_ const char *udev_device_get_property_value(struct udev_device *udev_dev
|
|||
return value;
|
||||
}
|
||||
|
||||
struct udev_device *udev_device_new(struct udev *udev, sd_device *device) {
|
||||
struct udev_device* udev_device_new(struct udev *udev, sd_device *device) {
|
||||
_cleanup_(udev_list_freep) struct udev_list *properties = NULL, *all_tags = NULL, *current_tags = NULL, *sysattrs = NULL, *devlinks = NULL;
|
||||
struct udev_device *udev_device;
|
||||
|
||||
|
@ -254,7 +254,7 @@ struct udev_device *udev_device_new(struct udev *udev, sd_device *device) {
|
|||
*
|
||||
* Returns: a new udev device, or #NULL, if it does not exist
|
||||
**/
|
||||
_public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) {
|
||||
_public_ struct udev_device* udev_device_new_from_syspath(struct udev *udev, const char *syspath) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
|
||||
int r;
|
||||
|
||||
|
@ -281,7 +281,7 @@ _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, con
|
|||
*
|
||||
* Returns: a new udev device, or #NULL, if it does not exist
|
||||
**/
|
||||
_public_ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) {
|
||||
_public_ struct udev_device* udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
|
||||
int r;
|
||||
|
||||
|
@ -310,7 +310,7 @@ _public_ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char
|
|||
*
|
||||
* Returns: a new udev device, or #NULL, if it does not exist
|
||||
**/
|
||||
_public_ struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) {
|
||||
_public_ struct udev_device* udev_device_new_from_device_id(struct udev *udev, const char *id) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
|
||||
int r;
|
||||
|
||||
|
@ -336,7 +336,7 @@ _public_ struct udev_device *udev_device_new_from_device_id(struct udev *udev, c
|
|||
*
|
||||
* Returns: a new udev device, or #NULL, if it does not exist
|
||||
**/
|
||||
_public_ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) {
|
||||
_public_ struct udev_device* udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
|
||||
int r;
|
||||
|
||||
|
@ -361,7 +361,7 @@ _public_ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev
|
|||
*
|
||||
* Returns: a new udev device, or #NULL, if it does not exist
|
||||
**/
|
||||
_public_ struct udev_device *udev_device_new_from_environment(struct udev *udev) {
|
||||
_public_ struct udev_device* udev_device_new_from_environment(struct udev *udev) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
|
||||
int r;
|
||||
|
||||
|
@ -372,7 +372,7 @@ _public_ struct udev_device *udev_device_new_from_environment(struct udev *udev)
|
|||
return udev_device_new(udev, device);
|
||||
}
|
||||
|
||||
static struct udev_device *device_new_from_parent(struct udev_device *child) {
|
||||
static struct udev_device* device_new_from_parent(struct udev_device *child) {
|
||||
sd_device *parent;
|
||||
int r;
|
||||
|
||||
|
@ -403,7 +403,7 @@ static struct udev_device *device_new_from_parent(struct udev_device *child) {
|
|||
*
|
||||
* Returns: a new udev device, or #NULL, if it no parent exist.
|
||||
**/
|
||||
_public_ struct udev_device *udev_device_get_parent(struct udev_device *udev_device) {
|
||||
_public_ struct udev_device* udev_device_get_parent(struct udev_device *udev_device) {
|
||||
assert_return_errno(udev_device, NULL, EINVAL);
|
||||
|
||||
if (!udev_device->parent_set) {
|
||||
|
@ -436,7 +436,11 @@ _public_ struct udev_device *udev_device_get_parent(struct udev_device *udev_dev
|
|||
*
|
||||
* Returns: a new udev device, or #NULL if no matching parent exists.
|
||||
**/
|
||||
_public_ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) {
|
||||
_public_ struct udev_device* udev_device_get_parent_with_subsystem_devtype(
|
||||
struct udev_device *udev_device,
|
||||
const char *subsystem,
|
||||
const char *devtype) {
|
||||
|
||||
sd_device *parent;
|
||||
int r;
|
||||
|
||||
|
@ -467,13 +471,13 @@ _public_ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struc
|
|||
*
|
||||
* Returns: the udev library context
|
||||
**/
|
||||
_public_ struct udev *udev_device_get_udev(struct udev_device *udev_device) {
|
||||
_public_ struct udev* udev_device_get_udev(struct udev_device *udev_device) {
|
||||
assert_return_errno(udev_device, NULL, EINVAL);
|
||||
|
||||
return udev_device->udev;
|
||||
}
|
||||
|
||||
static struct udev_device *udev_device_free(struct udev_device *udev_device) {
|
||||
static struct udev_device* udev_device_free(struct udev_device *udev_device) {
|
||||
assert(udev_device);
|
||||
|
||||
sd_device_unref(udev_device->device);
|
||||
|
@ -517,7 +521,7 @@ DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_device, udev_device, udev_devic
|
|||
*
|
||||
* Returns: the devpath of the udev device
|
||||
**/
|
||||
_public_ const char *udev_device_get_devpath(struct udev_device *udev_device) {
|
||||
_public_ const char* udev_device_get_devpath(struct udev_device *udev_device) {
|
||||
const char *devpath;
|
||||
int r;
|
||||
|
||||
|
@ -539,7 +543,7 @@ _public_ const char *udev_device_get_devpath(struct udev_device *udev_device) {
|
|||
*
|
||||
* Returns: the sys path of the udev device
|
||||
**/
|
||||
_public_ const char *udev_device_get_syspath(struct udev_device *udev_device) {
|
||||
_public_ const char* udev_device_get_syspath(struct udev_device *udev_device) {
|
||||
const char *syspath;
|
||||
int r;
|
||||
|
||||
|
@ -560,7 +564,7 @@ _public_ const char *udev_device_get_syspath(struct udev_device *udev_device) {
|
|||
*
|
||||
* Returns: the name string of the device
|
||||
**/
|
||||
_public_ const char *udev_device_get_sysname(struct udev_device *udev_device) {
|
||||
_public_ const char* udev_device_get_sysname(struct udev_device *udev_device) {
|
||||
const char *sysname;
|
||||
int r;
|
||||
|
||||
|
@ -581,7 +585,7 @@ _public_ const char *udev_device_get_sysname(struct udev_device *udev_device) {
|
|||
*
|
||||
* Returns: the trailing number string of the device name
|
||||
**/
|
||||
_public_ const char *udev_device_get_sysnum(struct udev_device *udev_device) {
|
||||
_public_ const char* udev_device_get_sysnum(struct udev_device *udev_device) {
|
||||
const char *sysnum;
|
||||
int r;
|
||||
|
||||
|
@ -605,7 +609,7 @@ _public_ const char *udev_device_get_sysnum(struct udev_device *udev_device) {
|
|||
*
|
||||
* Returns: the device node file name of the udev device, or #NULL if no device node exists
|
||||
**/
|
||||
_public_ const char *udev_device_get_devnode(struct udev_device *udev_device) {
|
||||
_public_ const char* udev_device_get_devnode(struct udev_device *udev_device) {
|
||||
const char *devnode;
|
||||
int r;
|
||||
|
||||
|
@ -631,7 +635,7 @@ _public_ const char *udev_device_get_devnode(struct udev_device *udev_device) {
|
|||
*
|
||||
* Returns: the first entry of the device node link list
|
||||
**/
|
||||
_public_ struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) {
|
||||
_public_ struct udev_list_entry* udev_device_get_devlinks_list_entry(struct udev_device *udev_device) {
|
||||
assert_return_errno(udev_device, NULL, EINVAL);
|
||||
|
||||
if (device_get_devlinks_generation(udev_device->device) != udev_device->devlinks_generation ||
|
||||
|
@ -661,7 +665,7 @@ _public_ struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev
|
|||
*
|
||||
* Returns: the first entry of the property list
|
||||
**/
|
||||
_public_ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device) {
|
||||
_public_ struct udev_list_entry* udev_device_get_properties_list_entry(struct udev_device *udev_device) {
|
||||
assert_return_errno(udev_device, NULL, EINVAL);
|
||||
|
||||
if (device_get_properties_generation(udev_device->device) != udev_device->properties_generation ||
|
||||
|
@ -689,7 +693,7 @@ _public_ struct udev_list_entry *udev_device_get_properties_list_entry(struct ud
|
|||
*
|
||||
* Returns: the kernel action value, or #NULL if there is no action value available.
|
||||
**/
|
||||
_public_ const char *udev_device_get_action(struct udev_device *udev_device) {
|
||||
_public_ const char* udev_device_get_action(struct udev_device *udev_device) {
|
||||
sd_device_action_t action;
|
||||
|
||||
assert_return_errno(udev_device, NULL, EINVAL);
|
||||
|
@ -735,7 +739,7 @@ _public_ unsigned long long int udev_device_get_usec_since_initialized(struct ud
|
|||
*
|
||||
* Returns: the content of a sys attribute file, or #NULL if there is no sys attribute value.
|
||||
**/
|
||||
_public_ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) {
|
||||
_public_ const char* udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) {
|
||||
const char *value;
|
||||
int r;
|
||||
|
||||
|
@ -780,7 +784,7 @@ _public_ int udev_device_set_sysattr_value(struct udev_device *udev_device, cons
|
|||
*
|
||||
* Returns: the first entry of the property list
|
||||
**/
|
||||
_public_ struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device) {
|
||||
_public_ struct udev_list_entry* udev_device_get_sysattr_list_entry(struct udev_device *udev_device) {
|
||||
assert_return_errno(udev_device, NULL, EINVAL);
|
||||
|
||||
if (!udev_device->sysattrs_read) {
|
||||
|
@ -832,7 +836,7 @@ _public_ int udev_device_get_is_initialized(struct udev_device *udev_device) {
|
|||
*
|
||||
* Returns: the first entry of the tag list
|
||||
**/
|
||||
_public_ struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) {
|
||||
_public_ struct udev_list_entry* udev_device_get_tags_list_entry(struct udev_device *udev_device) {
|
||||
assert_return_errno(udev_device, NULL, EINVAL);
|
||||
|
||||
if (device_get_tags_generation(udev_device->device) != udev_device->all_tags_generation ||
|
||||
|
@ -850,7 +854,7 @@ _public_ struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_dev
|
|||
return udev_list_get_entry(udev_device->all_tags);
|
||||
}
|
||||
|
||||
_public_ struct udev_list_entry *udev_device_get_current_tags_list_entry(struct udev_device *udev_device) {
|
||||
_public_ struct udev_list_entry* udev_device_get_current_tags_list_entry(struct udev_device *udev_device) {
|
||||
assert_return_errno(udev_device, NULL, EINVAL);
|
||||
|
||||
if (device_get_tags_generation(udev_device->device) != udev_device->current_tags_generation ||
|
||||
|
@ -889,7 +893,7 @@ _public_ int udev_device_has_current_tag(struct udev_device *udev_device, const
|
|||
return sd_device_has_current_tag(udev_device->device, tag) > 0;
|
||||
}
|
||||
|
||||
sd_device *udev_device_get_sd_device(struct udev_device *udev_device) {
|
||||
sd_device* udev_device_get_sd_device(struct udev_device *udev_device) {
|
||||
assert(udev_device);
|
||||
|
||||
return udev_device->device;
|
||||
|
|
|
@ -49,7 +49,7 @@ struct udev_enumerate {
|
|||
*
|
||||
* Returns: an enumeration context.
|
||||
**/
|
||||
_public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) {
|
||||
_public_ struct udev_enumerate* udev_enumerate_new(struct udev *udev) {
|
||||
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
|
||||
_cleanup_(udev_list_freep) struct udev_list *list = NULL;
|
||||
struct udev_enumerate *udev_enumerate;
|
||||
|
@ -81,7 +81,7 @@ _public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) {
|
|||
return udev_enumerate;
|
||||
}
|
||||
|
||||
static struct udev_enumerate *udev_enumerate_free(struct udev_enumerate *udev_enumerate) {
|
||||
static struct udev_enumerate* udev_enumerate_free(struct udev_enumerate *udev_enumerate) {
|
||||
assert(udev_enumerate);
|
||||
|
||||
udev_list_free(udev_enumerate->devices_list);
|
||||
|
@ -117,7 +117,7 @@ DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_enumerate, udev_enumerate, udev
|
|||
*
|
||||
* Returns: a pointer to the context.
|
||||
*/
|
||||
_public_ struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) {
|
||||
_public_ struct udev* udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) {
|
||||
assert_return_errno(udev_enumerate, NULL, EINVAL);
|
||||
|
||||
return udev_enumerate->udev;
|
||||
|
@ -131,7 +131,7 @@ _public_ struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumer
|
|||
*
|
||||
* Returns: a udev_list_entry.
|
||||
*/
|
||||
_public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) {
|
||||
_public_ struct udev_list_entry* udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) {
|
||||
struct udev_list_entry *e;
|
||||
|
||||
assert_return_errno(udev_enumerate, NULL, EINVAL);
|
||||
|
|
|
@ -34,7 +34,7 @@ struct udev_hwdb {
|
|||
*
|
||||
* Returns: a hwdb context.
|
||||
**/
|
||||
_public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
|
||||
_public_ struct udev_hwdb* udev_hwdb_new(struct udev *udev) {
|
||||
_cleanup_(udev_list_freep) struct udev_list *list = NULL;
|
||||
_cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb_internal = NULL;
|
||||
struct udev_hwdb *hwdb;
|
||||
|
@ -61,7 +61,7 @@ _public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
|
|||
return hwdb;
|
||||
}
|
||||
|
||||
static struct udev_hwdb *udev_hwdb_free(struct udev_hwdb *hwdb) {
|
||||
static struct udev_hwdb* udev_hwdb_free(struct udev_hwdb *hwdb) {
|
||||
assert(hwdb);
|
||||
|
||||
sd_hwdb_unref(hwdb->hwdb);
|
||||
|
@ -102,7 +102,7 @@ DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_hwdb, udev_hwdb, udev_hwdb_free
|
|||
*
|
||||
* Returns: a udev_list_entry.
|
||||
*/
|
||||
_public_ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned flags) {
|
||||
_public_ struct udev_list_entry* udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned flags) {
|
||||
const char *key, *value;
|
||||
struct udev_list_entry *e;
|
||||
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
struct udev_list;
|
||||
|
||||
struct udev_list *udev_list_new(bool unique);
|
||||
struct udev_list* udev_list_new(bool unique);
|
||||
void udev_list_cleanup(struct udev_list *list);
|
||||
struct udev_list *udev_list_free(struct udev_list *list);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_list *, udev_list_free);
|
||||
struct udev_list* udev_list_free(struct udev_list *list);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_list*, udev_list_free);
|
||||
|
||||
struct udev_list_entry *udev_list_get_entry(struct udev_list *list);
|
||||
struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *name, const char *value);
|
||||
struct udev_list_entry* udev_list_get_entry(struct udev_list *list);
|
||||
struct udev_list_entry* udev_list_entry_add(struct udev_list *list, const char *name, const char *value);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include "hashmap.h"
|
||||
#include "libudev-list-internal.h"
|
||||
#include "list.h"
|
||||
#include "sort-util.h"
|
||||
|
||||
/**
|
||||
* SECTION:libudev-list
|
||||
|
@ -34,7 +33,7 @@ struct udev_list {
|
|||
bool uptodate:1;
|
||||
};
|
||||
|
||||
static struct udev_list_entry *udev_list_entry_free(struct udev_list_entry *entry) {
|
||||
static struct udev_list_entry* udev_list_entry_free(struct udev_list_entry *entry) {
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
|
@ -52,9 +51,14 @@ static struct udev_list_entry *udev_list_entry_free(struct udev_list_entry *entr
|
|||
return mfree(entry);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_list_entry *, udev_list_entry_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_list_entry*, udev_list_entry_free);
|
||||
|
||||
struct udev_list *udev_list_new(bool unique) {
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
udev_list_entry_hash_ops,
|
||||
char, string_hash_func, string_compare_func,
|
||||
struct udev_list_entry, udev_list_entry_free);
|
||||
|
||||
struct udev_list* udev_list_new(bool unique) {
|
||||
struct udev_list *list;
|
||||
|
||||
list = new(struct udev_list, 1);
|
||||
|
@ -68,36 +72,26 @@ struct udev_list *udev_list_new(bool unique) {
|
|||
return list;
|
||||
}
|
||||
|
||||
struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *_name, const char *_value) {
|
||||
struct udev_list_entry* udev_list_entry_add(struct udev_list *list, const char *name, const char *value) {
|
||||
_cleanup_(udev_list_entry_freep) struct udev_list_entry *entry = NULL;
|
||||
_cleanup_free_ char *name = NULL, *value = NULL;
|
||||
|
||||
assert(list);
|
||||
assert(_name);
|
||||
assert(name);
|
||||
|
||||
name = strdup(_name);
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
if (_value) {
|
||||
value = strdup(_value);
|
||||
if (!value)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entry = new(struct udev_list_entry, 1);
|
||||
entry = new0(struct udev_list_entry, 1);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
*entry = (struct udev_list_entry) {
|
||||
.name = TAKE_PTR(name),
|
||||
.value = TAKE_PTR(value),
|
||||
};
|
||||
if (strdup_to(&entry->name, name) < 0)
|
||||
return NULL;
|
||||
|
||||
if (strdup_to(&entry->value, value) < 0)
|
||||
return NULL;
|
||||
|
||||
if (list->unique) {
|
||||
udev_list_entry_free(hashmap_get(list->unique_entries, entry->name));
|
||||
|
||||
if (hashmap_ensure_put(&list->unique_entries, &string_hash_ops, entry->name, entry) < 0)
|
||||
if (hashmap_ensure_put(&list->unique_entries, &udev_list_entry_hash_ops, entry->name, entry) < 0)
|
||||
return NULL;
|
||||
|
||||
list->uptodate = false;
|
||||
|
@ -115,13 +109,13 @@ void udev_list_cleanup(struct udev_list *list) {
|
|||
|
||||
if (list->unique) {
|
||||
list->uptodate = false;
|
||||
hashmap_clear_with_destructor(list->unique_entries, udev_list_entry_free);
|
||||
hashmap_clear(list->unique_entries);
|
||||
} else
|
||||
LIST_FOREACH(entries, i, list->entries)
|
||||
udev_list_entry_free(i);
|
||||
}
|
||||
|
||||
struct udev_list *udev_list_free(struct udev_list *list) {
|
||||
struct udev_list* udev_list_free(struct udev_list *list) {
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
|
@ -131,11 +125,7 @@ struct udev_list *udev_list_free(struct udev_list *list) {
|
|||
return mfree(list);
|
||||
}
|
||||
|
||||
static int udev_list_entry_compare_func(struct udev_list_entry * const *a, struct udev_list_entry * const *b) {
|
||||
return strcmp((*a)->name, (*b)->name);
|
||||
}
|
||||
|
||||
struct udev_list_entry *udev_list_get_entry(struct udev_list *list) {
|
||||
struct udev_list_entry* udev_list_get_entry(struct udev_list *list) {
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
|
@ -151,18 +141,10 @@ struct udev_list_entry *udev_list_get_entry(struct udev_list *list) {
|
|||
LIST_PREPEND(entries, list->entries, hashmap_first(list->unique_entries));
|
||||
else {
|
||||
_cleanup_free_ struct udev_list_entry **buf = NULL;
|
||||
struct udev_list_entry *entry, **p;
|
||||
|
||||
buf = new(struct udev_list_entry *, n);
|
||||
if (!buf)
|
||||
if (hashmap_dump_sorted(list->unique_entries, (void***) &buf, /* ret_n = */ NULL) < 0)
|
||||
return NULL;
|
||||
|
||||
p = buf;
|
||||
HASHMAP_FOREACH(entry, list->unique_entries)
|
||||
*p++ = entry;
|
||||
|
||||
typesafe_qsort(buf, n, udev_list_entry_compare_func);
|
||||
|
||||
for (size_t j = n; j > 0; j--)
|
||||
LIST_PREPEND(entries, list->entries, buf[j-1]);
|
||||
}
|
||||
|
@ -181,7 +163,7 @@ struct udev_list_entry *udev_list_get_entry(struct udev_list *list) {
|
|||
*
|
||||
* Returns: udev_list_entry, #NULL if no more entries are available.
|
||||
*/
|
||||
_public_ struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) {
|
||||
_public_ struct udev_list_entry* udev_list_entry_get_next(struct udev_list_entry *list_entry) {
|
||||
if (!list_entry)
|
||||
return NULL;
|
||||
if (list_entry->list->unique && !list_entry->list->uptodate)
|
||||
|
@ -198,7 +180,7 @@ _public_ struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry
|
|||
*
|
||||
* Returns: udev_list_entry, #NULL if no matching entry is found.
|
||||
*/
|
||||
_public_ struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name) {
|
||||
_public_ struct udev_list_entry* udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name) {
|
||||
if (!list_entry)
|
||||
return NULL;
|
||||
if (!list_entry->list->unique || !list_entry->list->uptodate)
|
||||
|
@ -214,7 +196,7 @@ _public_ struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_en
|
|||
*
|
||||
* Returns: the name string of this entry.
|
||||
*/
|
||||
_public_ const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) {
|
||||
_public_ const char* udev_list_entry_get_name(struct udev_list_entry *list_entry) {
|
||||
if (!list_entry)
|
||||
return NULL;
|
||||
return list_entry->name;
|
||||
|
@ -228,7 +210,7 @@ _public_ const char *udev_list_entry_get_name(struct udev_list_entry *list_entry
|
|||
*
|
||||
* Returns: the value string of this entry.
|
||||
*/
|
||||
_public_ const char *udev_list_entry_get_value(struct udev_list_entry *list_entry) {
|
||||
_public_ const char* udev_list_entry_get_value(struct udev_list_entry *list_entry) {
|
||||
if (!list_entry)
|
||||
return NULL;
|
||||
return list_entry->value;
|
||||
|
|
|
@ -63,7 +63,7 @@ static MonitorNetlinkGroup monitor_netlink_group_from_string(const char *name) {
|
|||
*
|
||||
* Returns: a new udev monitor, or #NULL, in case of an error
|
||||
**/
|
||||
_public_ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) {
|
||||
_public_ struct udev_monitor* udev_monitor_new_from_netlink(struct udev *udev, const char *name) {
|
||||
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL;
|
||||
struct udev_monitor *udev_monitor;
|
||||
MonitorNetlinkGroup g;
|
||||
|
@ -133,7 +133,7 @@ _public_ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_moni
|
|||
return sd_device_monitor_set_receive_buffer_size(udev_monitor->monitor, (size_t) size);
|
||||
}
|
||||
|
||||
static struct udev_monitor *udev_monitor_free(struct udev_monitor *udev_monitor) {
|
||||
static struct udev_monitor* udev_monitor_free(struct udev_monitor *udev_monitor) {
|
||||
assert(udev_monitor);
|
||||
|
||||
sd_device_monitor_unref(udev_monitor->monitor);
|
||||
|
@ -169,7 +169,7 @@ DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_monitor, udev_monitor, udev_mon
|
|||
*
|
||||
* Returns: the udev library context
|
||||
**/
|
||||
_public_ struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) {
|
||||
_public_ struct udev* udev_monitor_get_udev(struct udev_monitor *udev_monitor) {
|
||||
assert_return(udev_monitor, NULL);
|
||||
|
||||
return udev_monitor->udev;
|
||||
|
@ -236,7 +236,7 @@ static int udev_monitor_receive_sd_device(struct udev_monitor *udev_monitor, sd_
|
|||
*
|
||||
* Returns: a new udev device, or #NULL, in case of an error
|
||||
**/
|
||||
_public_ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) {
|
||||
_public_ struct udev_device* udev_monitor_receive_device(struct udev_monitor *udev_monitor) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
|
||||
int r;
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ struct udev_queue {
|
|||
*
|
||||
* Returns: the udev queue context, or #NULL on error.
|
||||
**/
|
||||
_public_ struct udev_queue *udev_queue_new(struct udev *udev) {
|
||||
_public_ struct udev_queue* udev_queue_new(struct udev *udev) {
|
||||
struct udev_queue *udev_queue;
|
||||
|
||||
udev_queue = new(struct udev_queue, 1);
|
||||
|
@ -56,7 +56,7 @@ _public_ struct udev_queue *udev_queue_new(struct udev *udev) {
|
|||
return udev_queue;
|
||||
}
|
||||
|
||||
static struct udev_queue *udev_queue_free(struct udev_queue *udev_queue) {
|
||||
static struct udev_queue* udev_queue_free(struct udev_queue *udev_queue) {
|
||||
assert(udev_queue);
|
||||
|
||||
safe_close(udev_queue->fd);
|
||||
|
@ -91,7 +91,7 @@ DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_queue, udev_queue, udev_queue_f
|
|||
*
|
||||
* Returns: the udev library context.
|
||||
**/
|
||||
_public_ struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) {
|
||||
_public_ struct udev* udev_queue_get_udev(struct udev_queue *udev_queue) {
|
||||
assert_return_errno(udev_queue, NULL, EINVAL);
|
||||
|
||||
return udev_queue->udev;
|
||||
|
@ -155,8 +155,11 @@ _public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) {
|
|||
*
|
||||
* Returns: a flag indicating if udev is currently handling events.
|
||||
**/
|
||||
_public_ int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue,
|
||||
unsigned long long int start, unsigned long long int end) {
|
||||
_public_ int udev_queue_get_seqnum_sequence_is_finished(
|
||||
struct udev_queue *udev_queue,
|
||||
unsigned long long int start,
|
||||
unsigned long long int end) {
|
||||
|
||||
return udev_queue_is_empty() > 0;
|
||||
}
|
||||
|
||||
|
@ -181,7 +184,7 @@ _public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, un
|
|||
*
|
||||
* Returns: NULL.
|
||||
**/
|
||||
_public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) {
|
||||
_public_ struct udev_list_entry* udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) {
|
||||
return_with_errno(NULL, ENODATA);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ struct udev {
|
|||
*
|
||||
* Returns: stored userdata
|
||||
**/
|
||||
_public_ void *udev_get_userdata(struct udev *udev) {
|
||||
_public_ void* udev_get_userdata(struct udev *udev) {
|
||||
assert_return(udev, NULL);
|
||||
|
||||
return udev->userdata;
|
||||
|
@ -66,7 +66,7 @@ _public_ void udev_set_userdata(struct udev *udev, void *userdata) {
|
|||
*
|
||||
* Returns: a new udev library context
|
||||
**/
|
||||
_public_ struct udev *udev_new(void) {
|
||||
_public_ struct udev* udev_new(void) {
|
||||
struct udev *udev;
|
||||
|
||||
udev = new(struct udev, 1);
|
||||
|
@ -99,7 +99,7 @@ DEFINE_PUBLIC_TRIVIAL_REF_FUNC(struct udev, udev);
|
|||
*
|
||||
* Returns: the passed udev library context if it has still an active reference, or #NULL otherwise.
|
||||
**/
|
||||
_public_ struct udev *udev_unref(struct udev *udev) {
|
||||
_public_ struct udev* udev_unref(struct udev *udev) {
|
||||
if (!udev)
|
||||
return NULL;
|
||||
|
||||
|
@ -123,10 +123,14 @@ _public_ struct udev *udev_unref(struct udev *udev) {
|
|||
*
|
||||
**/
|
||||
_public_ void udev_set_log_fn(
|
||||
struct udev *udev,
|
||||
void (*log_fn)(struct udev *udev,
|
||||
int priority, const char *file, int line, const char *fn,
|
||||
const char *format, va_list args)) {
|
||||
struct udev *udev,
|
||||
void (*log_fn)(struct udev *udev,
|
||||
int priority,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *fn,
|
||||
const char *format,
|
||||
va_list args)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,16 +18,21 @@ extern "C" {
|
|||
* allows custom logging
|
||||
*/
|
||||
struct udev;
|
||||
struct udev *udev_ref(struct udev *udev);
|
||||
struct udev *udev_unref(struct udev *udev);
|
||||
struct udev *udev_new(void);
|
||||
void udev_set_log_fn(struct udev *udev,
|
||||
void (*log_fn)(struct udev *udev,
|
||||
int priority, const char *file, int line, const char *fn,
|
||||
const char *format, va_list args)) __attribute__((__deprecated__));
|
||||
struct udev* udev_ref(struct udev *udev);
|
||||
struct udev* udev_unref(struct udev *udev);
|
||||
struct udev* udev_new(void);
|
||||
void udev_set_log_fn(
|
||||
struct udev *udev,
|
||||
void (*log_fn)(struct udev *udev,
|
||||
int priority,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *fn,
|
||||
const char *format,
|
||||
va_list args)) __attribute__((__deprecated__));
|
||||
int udev_get_log_priority(struct udev *udev) __attribute__((__deprecated__));
|
||||
void udev_set_log_priority(struct udev *udev, int priority) __attribute__((__deprecated__));
|
||||
void *udev_get_userdata(struct udev *udev);
|
||||
void* udev_get_userdata(struct udev *udev);
|
||||
void udev_set_userdata(struct udev *udev, void *userdata);
|
||||
|
||||
/*
|
||||
|
@ -36,8 +41,8 @@ void udev_set_userdata(struct udev *udev, void *userdata);
|
|||
* access to libudev generated lists
|
||||
*/
|
||||
struct udev_list_entry;
|
||||
struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry);
|
||||
struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name);
|
||||
struct udev_list_entry* udev_list_entry_get_next(struct udev_list_entry *list_entry);
|
||||
struct udev_list_entry* udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name);
|
||||
const char* udev_list_entry_get_name(struct udev_list_entry *list_entry);
|
||||
const char* udev_list_entry_get_value(struct udev_list_entry *list_entry);
|
||||
/**
|
||||
|
@ -58,18 +63,20 @@ const char* udev_list_entry_get_value(struct udev_list_entry *list_entry);
|
|||
* access to sysfs/kernel devices
|
||||
*/
|
||||
struct udev_device;
|
||||
struct udev_device *udev_device_ref(struct udev_device *udev_device);
|
||||
struct udev_device *udev_device_unref(struct udev_device *udev_device);
|
||||
struct udev *udev_device_get_udev(struct udev_device *udev_device);
|
||||
struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath);
|
||||
struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum);
|
||||
struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname);
|
||||
struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id);
|
||||
struct udev_device *udev_device_new_from_environment(struct udev *udev);
|
||||
struct udev_device* udev_device_ref(struct udev_device *udev_device);
|
||||
struct udev_device* udev_device_unref(struct udev_device *udev_device);
|
||||
struct udev* udev_device_get_udev(struct udev_device *udev_device);
|
||||
struct udev_device* udev_device_new_from_syspath(struct udev *udev, const char *syspath);
|
||||
struct udev_device* udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum);
|
||||
struct udev_device* udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname);
|
||||
struct udev_device* udev_device_new_from_device_id(struct udev *udev, const char *id);
|
||||
struct udev_device* udev_device_new_from_environment(struct udev *udev);
|
||||
/* udev_device_get_parent_*() does not take a reference on the returned device, it is automatically unref'd with the parent */
|
||||
struct udev_device *udev_device_get_parent(struct udev_device *udev_device);
|
||||
struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device,
|
||||
const char *subsystem, const char *devtype);
|
||||
struct udev_device* udev_device_get_parent(struct udev_device *udev_device);
|
||||
struct udev_device* udev_device_get_parent_with_subsystem_devtype(
|
||||
struct udev_device *udev_device,
|
||||
const char *subsystem,
|
||||
const char *devtype);
|
||||
/* retrieve device properties */
|
||||
const char* udev_device_get_devpath(struct udev_device *udev_device);
|
||||
const char* udev_device_get_subsystem(struct udev_device *udev_device);
|
||||
|
@ -79,11 +86,11 @@ const char* udev_device_get_sysname(struct udev_device *udev_device);
|
|||
const char* udev_device_get_sysnum(struct udev_device *udev_device);
|
||||
const char* udev_device_get_devnode(struct udev_device *udev_device);
|
||||
int udev_device_get_is_initialized(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_current_tags_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry* udev_device_get_devlinks_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry* udev_device_get_properties_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry* udev_device_get_tags_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry* udev_device_get_current_tags_list_entry(struct udev_device *udev_device);
|
||||
struct udev_list_entry* udev_device_get_sysattr_list_entry(struct udev_device *udev_device);
|
||||
const char* udev_device_get_property_value(struct udev_device *udev_device, const char *key);
|
||||
const char* udev_device_get_driver(struct udev_device *udev_device);
|
||||
dev_t udev_device_get_devnum(struct udev_device *udev_device);
|
||||
|
@ -101,19 +108,21 @@ int udev_device_has_current_tag(struct udev_device *udev_device, const char *tag
|
|||
* access to kernel uevents and udev events
|
||||
*/
|
||||
struct udev_monitor;
|
||||
struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor);
|
||||
struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor);
|
||||
struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor);
|
||||
struct udev_monitor* udev_monitor_ref(struct udev_monitor *udev_monitor);
|
||||
struct udev_monitor* udev_monitor_unref(struct udev_monitor *udev_monitor);
|
||||
struct udev* udev_monitor_get_udev(struct udev_monitor *udev_monitor);
|
||||
/* kernel and udev generated events over netlink */
|
||||
struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name);
|
||||
struct udev_monitor* udev_monitor_new_from_netlink(struct udev *udev, const char *name);
|
||||
/* bind socket */
|
||||
int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor);
|
||||
int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size);
|
||||
int udev_monitor_get_fd(struct udev_monitor *udev_monitor);
|
||||
struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor);
|
||||
struct udev_device* udev_monitor_receive_device(struct udev_monitor *udev_monitor);
|
||||
/* in-kernel socket filters to select messages that get delivered to a listener */
|
||||
int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor,
|
||||
const char *subsystem, const char *devtype);
|
||||
int udev_monitor_filter_add_match_subsystem_devtype(
|
||||
struct udev_monitor *udev_monitor,
|
||||
const char *subsystem,
|
||||
const char *devtype);
|
||||
int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag);
|
||||
int udev_monitor_filter_update(struct udev_monitor *udev_monitor);
|
||||
int udev_monitor_filter_remove(struct udev_monitor *udev_monitor);
|
||||
|
@ -124,10 +133,10 @@ int udev_monitor_filter_remove(struct udev_monitor *udev_monitor);
|
|||
* search sysfs for specific devices and provide a sorted list
|
||||
*/
|
||||
struct udev_enumerate;
|
||||
struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate);
|
||||
struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate);
|
||||
struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate);
|
||||
struct udev_enumerate *udev_enumerate_new(struct udev *udev);
|
||||
struct udev_enumerate* udev_enumerate_ref(struct udev_enumerate *udev_enumerate);
|
||||
struct udev_enumerate* udev_enumerate_unref(struct udev_enumerate *udev_enumerate);
|
||||
struct udev* udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate);
|
||||
struct udev_enumerate* udev_enumerate_new(struct udev *udev);
|
||||
/* device properties filter */
|
||||
int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
|
||||
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
|
||||
|
@ -143,7 +152,7 @@ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char
|
|||
int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate);
|
||||
int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate);
|
||||
/* return device list */
|
||||
struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
|
||||
struct udev_list_entry* udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
|
||||
|
||||
/*
|
||||
* udev_queue
|
||||
|
@ -151,20 +160,22 @@ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *ude
|
|||
* access to the currently running udev events
|
||||
*/
|
||||
struct udev_queue;
|
||||
struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue);
|
||||
struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue);
|
||||
struct udev *udev_queue_get_udev(struct udev_queue *udev_queue);
|
||||
struct udev_queue *udev_queue_new(struct udev *udev);
|
||||
struct udev_queue* udev_queue_ref(struct udev_queue *udev_queue);
|
||||
struct udev_queue* udev_queue_unref(struct udev_queue *udev_queue);
|
||||
struct udev* udev_queue_get_udev(struct udev_queue *udev_queue);
|
||||
struct udev_queue* udev_queue_new(struct udev *udev);
|
||||
unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) __attribute__((__deprecated__));
|
||||
unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) __attribute__((__deprecated__));
|
||||
int udev_queue_get_udev_is_active(struct udev_queue *udev_queue);
|
||||
int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue);
|
||||
int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) __attribute__((__deprecated__));
|
||||
int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue,
|
||||
unsigned long long int start, unsigned long long int end) __attribute__((__deprecated__));
|
||||
int udev_queue_get_seqnum_sequence_is_finished(
|
||||
struct udev_queue *udev_queue,
|
||||
unsigned long long int start,
|
||||
unsigned long long int end) __attribute__((__deprecated__));
|
||||
int udev_queue_get_fd(struct udev_queue *udev_queue);
|
||||
int udev_queue_flush(struct udev_queue *udev_queue);
|
||||
struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) __attribute__((__deprecated__));
|
||||
struct udev_list_entry* udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) __attribute__((__deprecated__));
|
||||
|
||||
/*
|
||||
* udev_hwdb
|
||||
|
@ -172,10 +183,10 @@ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev
|
|||
* access to the static hardware properties database
|
||||
*/
|
||||
struct udev_hwdb;
|
||||
struct udev_hwdb *udev_hwdb_new(struct udev *udev);
|
||||
struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb);
|
||||
struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb);
|
||||
struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned flags);
|
||||
struct udev_hwdb* udev_hwdb_new(struct udev *udev);
|
||||
struct udev_hwdb* udev_hwdb_ref(struct udev_hwdb *hwdb);
|
||||
struct udev_hwdb* udev_hwdb_unref(struct udev_hwdb *hwdb);
|
||||
struct udev_list_entry* udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned flags);
|
||||
|
||||
/*
|
||||
* udev_util
|
||||
|
|
|
@ -536,7 +536,7 @@ static int method_set_tty(sd_bus_message *message, void *userdata, sd_bus_error
|
|||
flags = fcntl(fd, F_GETFL, 0);
|
||||
if (flags < 0)
|
||||
return -errno;
|
||||
if ((flags & O_ACCMODE) != O_RDWR)
|
||||
if ((flags & O_ACCMODE_STRICT) != O_RDWR)
|
||||
return -EACCES;
|
||||
if (FLAGS_SET(flags, O_PATH))
|
||||
return -ENOTTY;
|
||||
|
|
|
@ -99,7 +99,7 @@ static int validate_image_fd(int fd, MountImageParameters *p) {
|
|||
if (fl < 0)
|
||||
return log_debug_errno(fl, "Image file descriptor has unsafe flags set: %m");
|
||||
|
||||
switch (fl & O_ACCMODE) {
|
||||
switch (fl & O_ACCMODE_STRICT) {
|
||||
|
||||
case O_RDONLY:
|
||||
p->read_only = true;
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
|
||||
#define STATIC_BRIDGE_FDB_ENTRIES_PER_NETWORK_MAX 1024U
|
||||
|
||||
/* remove and FDB entry. */
|
||||
BridgeFDB *bridge_fdb_free(BridgeFDB *fdb) {
|
||||
static BridgeFDB* bridge_fdb_free(BridgeFDB *fdb) {
|
||||
if (!fdb)
|
||||
return NULL;
|
||||
|
||||
|
@ -40,7 +39,11 @@ BridgeFDB *bridge_fdb_free(BridgeFDB *fdb) {
|
|||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(BridgeFDB, bridge_fdb_free);
|
||||
|
||||
/* create a new FDB entry or get an existing one. */
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
bridge_fdb_hash_ops_by_section,
|
||||
ConfigSection, config_section_hash_func, config_section_compare_func,
|
||||
BridgeFDB, bridge_fdb_free);
|
||||
|
||||
static int bridge_fdb_new_static(
|
||||
Network *network,
|
||||
const char *filename,
|
||||
|
@ -83,13 +86,12 @@ static int bridge_fdb_new_static(
|
|||
.ntf_flags = NEIGHBOR_CACHE_ENTRY_FLAGS_SELF,
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&network->bridge_fdb_entries_by_section, &config_section_hash_ops, fdb->section, fdb);
|
||||
r = hashmap_ensure_put(&network->bridge_fdb_entries_by_section, &bridge_fdb_hash_ops_by_section, fdb->section, fdb);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* return allocated FDB structure. */
|
||||
*ret = TAKE_PTR(fdb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,8 +40,6 @@ typedef struct BridgeFDB {
|
|||
int outgoing_ifindex;
|
||||
} BridgeFDB;
|
||||
|
||||
BridgeFDB *bridge_fdb_free(BridgeFDB *fdb);
|
||||
|
||||
void network_drop_invalid_bridge_fdb_entries(Network *network);
|
||||
|
||||
int link_request_static_bridge_fdb(Link *link);
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
#include "networkd-manager.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-queue.h"
|
||||
#include "networkd-util.h"
|
||||
#include "string-util.h"
|
||||
#include "vlan-util.h"
|
||||
|
||||
#define STATIC_BRIDGE_MDB_ENTRIES_PER_NETWORK_MAX 1024U
|
||||
|
||||
/* remove MDB entry. */
|
||||
BridgeMDB *bridge_mdb_free(BridgeMDB *mdb) {
|
||||
static BridgeMDB* bridge_mdb_free(BridgeMDB *mdb) {
|
||||
if (!mdb)
|
||||
return NULL;
|
||||
|
||||
|
@ -32,7 +32,11 @@ BridgeMDB *bridge_mdb_free(BridgeMDB *mdb) {
|
|||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(BridgeMDB, bridge_mdb_free);
|
||||
|
||||
/* create a new MDB entry or get an existing one. */
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
bridge_mdb_hash_ops_by_section,
|
||||
ConfigSection, config_section_hash_func, config_section_compare_func,
|
||||
BridgeMDB, bridge_mdb_free);
|
||||
|
||||
static int bridge_mdb_new_static(
|
||||
Network *network,
|
||||
const char *filename,
|
||||
|
@ -74,7 +78,7 @@ static int bridge_mdb_new_static(
|
|||
.type = _BRIDGE_MDB_ENTRY_TYPE_INVALID,
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&network->bridge_mdb_entries_by_section, &config_section_hash_ops, mdb->section, mdb);
|
||||
r = hashmap_ensure_put(&network->bridge_mdb_entries_by_section, &bridge_mdb_hash_ops_by_section, mdb->section, mdb);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include "conf-parser.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "networkd-util.h"
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Network Network;
|
||||
|
@ -30,8 +29,6 @@ typedef struct BridgeMDB {
|
|||
uint16_t vlan_id;
|
||||
} BridgeMDB;
|
||||
|
||||
BridgeMDB *bridge_mdb_free(BridgeMDB *mdb);
|
||||
|
||||
void network_drop_invalid_bridge_mdb_entries(Network *network);
|
||||
|
||||
int link_request_static_bridge_mdb(Link *link);
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
#include "networkd-network.h"
|
||||
#include "networkd-util.h"
|
||||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(DHCPStaticLease, dhcp_static_lease_free);
|
||||
|
||||
DHCPStaticLease *dhcp_static_lease_free(DHCPStaticLease *static_lease) {
|
||||
static DHCPStaticLease* dhcp_static_lease_free(DHCPStaticLease *static_lease) {
|
||||
if (!static_lease)
|
||||
return NULL;
|
||||
|
||||
|
@ -21,6 +19,13 @@ DHCPStaticLease *dhcp_static_lease_free(DHCPStaticLease *static_lease) {
|
|||
return mfree(static_lease);
|
||||
}
|
||||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(DHCPStaticLease, dhcp_static_lease_free);
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
static_lease_hash_ops_by_section,
|
||||
ConfigSection, config_section_hash_func, config_section_compare_func,
|
||||
DHCPStaticLease, dhcp_static_lease_free);
|
||||
|
||||
static int dhcp_static_lease_new(DHCPStaticLease **ret) {
|
||||
DHCPStaticLease *p;
|
||||
|
||||
|
@ -60,7 +65,8 @@ static int lease_new_static(Network *network, const char *filename, unsigned sec
|
|||
|
||||
static_lease->network = network;
|
||||
static_lease->section = TAKE_PTR(n);
|
||||
r = hashmap_ensure_put(&network->dhcp_static_leases_by_section, &config_section_hash_ops, static_lease->section, static_lease);
|
||||
|
||||
r = hashmap_ensure_put(&network->dhcp_static_leases_by_section, &static_lease_hash_ops_by_section, static_lease->section, static_lease);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ typedef struct DHCPStaticLease {
|
|||
size_t client_id_size;
|
||||
} DHCPStaticLease;
|
||||
|
||||
DHCPStaticLease *dhcp_static_lease_free(DHCPStaticLease *lease);
|
||||
void network_drop_invalid_static_leases(Network *network);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_static_lease_address);
|
||||
|
|
|
@ -281,7 +281,7 @@ int config_parse_dnssec_negative_trust_anchors(
|
|||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*nta = set_free_free(*nta);
|
||||
*nta = set_free(*nta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -306,7 +306,7 @@ int config_parse_dnssec_negative_trust_anchors(
|
|||
continue;
|
||||
}
|
||||
|
||||
r = set_ensure_consume(nta, &dns_name_hash_ops, TAKE_PTR(w));
|
||||
r = set_ensure_consume(nta, &dns_name_hash_ops_free, TAKE_PTR(w));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,13 @@ void network_adjust_ipv6_proxy_ndp(Network *network) {
|
|||
log_once(LOG_WARNING,
|
||||
"%s: IPv6 proxy NDP addresses are set, but IPv6 is not supported by kernel, "
|
||||
"Ignoring IPv6 proxy NDP addresses.", network->filename);
|
||||
network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses);
|
||||
network->ipv6_proxy_ndp_addresses = set_free(network->ipv6_proxy_ndp_addresses);
|
||||
return;
|
||||
}
|
||||
|
||||
if (network->ipv6_proxy_ndp == 0) {
|
||||
log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network->filename);
|
||||
network->ipv6_proxy_ndp_addresses = set_free(network->ipv6_proxy_ndp_addresses);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,7 +155,7 @@ int config_parse_ipv6_proxy_ndp_address(
|
|||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses);
|
||||
network->ipv6_proxy_ndp_addresses = set_free(network->ipv6_proxy_ndp_addresses);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -170,11 +176,9 @@ int config_parse_ipv6_proxy_ndp_address(
|
|||
if (!address)
|
||||
return log_oom();
|
||||
|
||||
r = set_ensure_put(&network->ipv6_proxy_ndp_addresses, &in6_addr_hash_ops, address);
|
||||
r = set_ensure_consume(&network->ipv6_proxy_ndp_addresses, &in6_addr_hash_ops_free, TAKE_PTR(address));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
if (r > 0)
|
||||
TAKE_PTR(address);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -479,7 +479,7 @@ int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_e
|
|||
}
|
||||
|
||||
int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_set_free_free_ Set *ns = NULL;
|
||||
_cleanup_set_free_ Set *ns = NULL;
|
||||
_cleanup_strv_free_ char **ntas = NULL;
|
||||
Link *l = ASSERT_PTR(userdata);
|
||||
int r;
|
||||
|
@ -502,7 +502,7 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v
|
|||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid negative trust anchor domain: %s", *i);
|
||||
}
|
||||
|
||||
ns = set_new(&dns_name_hash_ops);
|
||||
ns = set_new(&dns_name_hash_ops_free);
|
||||
if (!ns)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -523,8 +523,7 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v
|
|||
if (r == 0)
|
||||
return 1; /* Polkit will call us back */
|
||||
|
||||
set_free_free(l->dnssec_negative_trust_anchors);
|
||||
l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
|
||||
set_free_and_replace(l->dnssec_negative_trust_anchors, ns);
|
||||
|
||||
r = link_save_and_clean_full(l, /* also_save_manager = */ true);
|
||||
if (r < 0)
|
||||
|
|
|
@ -231,7 +231,7 @@ void link_dns_settings_clear(Link *link) {
|
|||
link->dnssec_mode = _DNSSEC_MODE_INVALID;
|
||||
link->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
|
||||
|
||||
link->dnssec_negative_trust_anchors = set_free_free(link->dnssec_negative_trust_anchors);
|
||||
link->dnssec_negative_trust_anchors = set_free(link->dnssec_negative_trust_anchors);
|
||||
}
|
||||
|
||||
static void link_free_engines(Link *link) {
|
||||
|
@ -261,7 +261,7 @@ static void link_free_engines(Link *link) {
|
|||
link->radv = sd_radv_unref(link->radv);
|
||||
}
|
||||
|
||||
static Link *link_free(Link *link) {
|
||||
static Link* link_free(Link *link) {
|
||||
assert(link);
|
||||
|
||||
(void) link_clear_sysctl_shadows(link);
|
||||
|
@ -295,7 +295,7 @@ static Link *link_free(Link *link) {
|
|||
hashmap_free(link->bound_to_links);
|
||||
hashmap_free(link->bound_by_links);
|
||||
|
||||
set_free_with_destructor(link->slaves, link_unref);
|
||||
set_free(link->slaves);
|
||||
|
||||
network_unref(link->network);
|
||||
|
||||
|
@ -307,6 +307,11 @@ static Link *link_free(Link *link) {
|
|||
|
||||
DEFINE_TRIVIAL_REF_UNREF_FUNC(Link, link, link_free);
|
||||
|
||||
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
link_hash_ops,
|
||||
void, trivial_hash_func, trivial_compare_func,
|
||||
Link, link_unref);
|
||||
|
||||
int link_get_by_index(Manager *m, int ifindex, Link **ret) {
|
||||
Link *link;
|
||||
|
||||
|
@ -985,7 +990,7 @@ static int link_append_to_master(Link *link) {
|
|||
if (link_get_master(link, &master) < 0)
|
||||
return 0;
|
||||
|
||||
r = set_ensure_put(&master->slaves, NULL, link);
|
||||
r = set_ensure_put(&master->slaves, &link_hash_ops, link);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
|
@ -2746,7 +2751,7 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
|
|||
.dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&manager->links_by_index, NULL, INT_TO_PTR(link->ifindex), link);
|
||||
r = hashmap_ensure_put(&manager->links_by_index, &link_hash_ops, INT_TO_PTR(link->ifindex), link);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to store link into manager: %m");
|
||||
|
||||
|
|
|
@ -222,6 +222,8 @@ typedef struct Link {
|
|||
char **ntp;
|
||||
} Link;
|
||||
|
||||
extern const struct hash_ops link_hash_ops;
|
||||
|
||||
typedef int (*link_netlink_message_handler_t)(sd_netlink*, sd_netlink_message*, Link*);
|
||||
|
||||
bool link_is_ready_to_configure(Link *link, bool allow_unmanaged);
|
||||
|
|
|
@ -672,15 +672,16 @@ Manager* manager_free(Manager *m) {
|
|||
m->request_queue = ordered_set_free(m->request_queue);
|
||||
m->remove_request_queue = ordered_set_free(m->remove_request_queue);
|
||||
|
||||
m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref);
|
||||
m->new_wlan_ifindices = set_free(m->new_wlan_ifindices);
|
||||
|
||||
m->dirty_links = set_free(m->dirty_links);
|
||||
m->links_by_name = hashmap_free(m->links_by_name);
|
||||
m->links_by_hw_addr = hashmap_free(m->links_by_hw_addr);
|
||||
m->links_by_dhcp_pd_subnet_prefix = hashmap_free(m->links_by_dhcp_pd_subnet_prefix);
|
||||
m->links_by_index = hashmap_free_with_destructor(m->links_by_index, link_unref);
|
||||
m->links_by_index = hashmap_free(m->links_by_index);
|
||||
|
||||
m->dhcp_pd_subnet_ids = set_free(m->dhcp_pd_subnet_ids);
|
||||
m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref);
|
||||
m->networks = ordered_hashmap_free(m->networks);
|
||||
|
||||
/* The same object may be registered with multiple names, and netdev_detach() may drop multiple
|
||||
* entries. Hence, hashmap_free_with_destructor() cannot be used. */
|
||||
|
@ -691,7 +692,7 @@ Manager* manager_free(Manager *m) {
|
|||
m->tuntap_fds_by_name = hashmap_free(m->tuntap_fds_by_name);
|
||||
|
||||
m->wiphy_by_name = hashmap_free(m->wiphy_by_name);
|
||||
m->wiphy_by_index = hashmap_free_with_destructor(m->wiphy_by_index, wiphy_free);
|
||||
m->wiphy_by_index = hashmap_free(m->wiphy_by_index);
|
||||
|
||||
ordered_set_free(m->address_pools);
|
||||
|
||||
|
|
|
@ -89,11 +89,11 @@ void network_adjust_ndisc(Network *network) {
|
|||
/* When RouterAllowList=, PrefixAllowList= or RouteAllowList= are specified, then
|
||||
* RouterDenyList=, PrefixDenyList= or RouteDenyList= are ignored, respectively. */
|
||||
if (!set_isempty(network->ndisc_allow_listed_router))
|
||||
network->ndisc_deny_listed_router = set_free_free(network->ndisc_deny_listed_router);
|
||||
network->ndisc_deny_listed_router = set_free(network->ndisc_deny_listed_router);
|
||||
if (!set_isempty(network->ndisc_allow_listed_prefix))
|
||||
network->ndisc_deny_listed_prefix = set_free_free(network->ndisc_deny_listed_prefix);
|
||||
network->ndisc_deny_listed_prefix = set_free(network->ndisc_deny_listed_prefix);
|
||||
if (!set_isempty(network->ndisc_allow_listed_route_prefix))
|
||||
network->ndisc_deny_listed_route_prefix = set_free_free(network->ndisc_deny_listed_route_prefix);
|
||||
network->ndisc_deny_listed_route_prefix = set_free(network->ndisc_deny_listed_route_prefix);
|
||||
}
|
||||
|
||||
static int ndisc_check_ready(Link *link);
|
||||
|
|
|
@ -44,6 +44,16 @@
|
|||
#include "strv.h"
|
||||
#include "tclass.h"
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
network_hash_ops,
|
||||
char, string_hash_func, string_compare_func,
|
||||
Network, network_unref);
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
stacked_netdevs_hash_ops,
|
||||
char, string_hash_func, string_compare_func,
|
||||
NetDev, netdev_unref);
|
||||
|
||||
static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret) {
|
||||
const char *kind_string;
|
||||
NetDev *netdev;
|
||||
|
@ -105,14 +115,14 @@ static int network_resolve_stacked_netdevs(Network *network) {
|
|||
if (network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev) <= 0)
|
||||
continue;
|
||||
|
||||
r = hashmap_ensure_put(&network->stacked_netdevs, &string_hash_ops, netdev->ifname, netdev);
|
||||
r = hashmap_ensure_put(&network->stacked_netdevs, &stacked_netdevs_hash_ops, netdev->ifname, netdev);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "%s: Failed to add NetDev '%s' to network, ignoring: %m",
|
||||
network->filename, (const char *) name);
|
||||
|
||||
netdev = NULL;
|
||||
TAKE_PTR(netdev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -291,11 +301,6 @@ int network_verify(Network *network) {
|
|||
if (network->keep_configuration < 0)
|
||||
network->keep_configuration = KEEP_CONFIGURATION_NO;
|
||||
|
||||
if (network->ipv6_proxy_ndp == 0 && !set_isempty(network->ipv6_proxy_ndp_addresses)) {
|
||||
log_warning("%s: IPv6ProxyNDP= is disabled. Ignoring IPv6ProxyNDPAddress=.", network->filename);
|
||||
network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses);
|
||||
}
|
||||
|
||||
r = network_drop_invalid_addresses(network);
|
||||
if (r < 0)
|
||||
return r; /* network_drop_invalid_addresses() logs internally. */
|
||||
|
@ -594,7 +599,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
|||
if (r < 0)
|
||||
return r; /* network_verify() logs internally. */
|
||||
|
||||
r = ordered_hashmap_ensure_put(networks, &string_hash_ops, network->name, network);
|
||||
r = ordered_hashmap_ensure_put(networks, &network_hash_ops, network->name, network);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "%s: Failed to store configuration into hashmap: %m", filename);
|
||||
|
||||
|
@ -645,7 +650,7 @@ static bool network_netdev_equal(Network *a, Network *b) {
|
|||
}
|
||||
|
||||
int network_reload(Manager *manager) {
|
||||
OrderedHashmap *new_networks = NULL;
|
||||
_cleanup_ordered_hashmap_free_ OrderedHashmap *new_networks = NULL;
|
||||
Network *n, *old;
|
||||
int r;
|
||||
|
||||
|
@ -653,7 +658,7 @@ int network_reload(Manager *manager) {
|
|||
|
||||
r = network_load(manager, &new_networks);
|
||||
if (r < 0)
|
||||
goto failure;
|
||||
return r;
|
||||
|
||||
ORDERED_HASHMAP_FOREACH(n, new_networks) {
|
||||
r = network_get_by_name(manager, n->name, &old);
|
||||
|
@ -675,14 +680,13 @@ int network_reload(Manager *manager) {
|
|||
/* Nothing updated, use the existing Network object, and drop the new one. */
|
||||
r = ordered_hashmap_replace(new_networks, old->name, old);
|
||||
if (r < 0)
|
||||
goto failure;
|
||||
return r;
|
||||
|
||||
network_ref(old);
|
||||
network_unref(n);
|
||||
}
|
||||
|
||||
ordered_hashmap_free_with_destructor(manager->networks, network_unref);
|
||||
manager->networks = new_networks;
|
||||
ordered_hashmap_free_and_replace(manager->networks, new_networks);
|
||||
|
||||
r = manager_build_dhcp_pd_subnet_ids(manager);
|
||||
if (r < 0)
|
||||
|
@ -693,11 +697,6 @@ int network_reload(Manager *manager) {
|
|||
return r;
|
||||
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
ordered_hashmap_free_with_destructor(new_networks, network_unref);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int manager_build_dhcp_pd_subnet_ids(Manager *manager) {
|
||||
|
@ -752,7 +751,7 @@ static Network *network_free(Network *network) {
|
|||
free(network->dns);
|
||||
ordered_set_free(network->search_domains);
|
||||
ordered_set_free(network->route_domains);
|
||||
set_free_free(network->dnssec_negative_trust_anchors);
|
||||
set_free(network->dnssec_negative_trust_anchors);
|
||||
|
||||
/* DHCP server */
|
||||
free(network->dhcp_server_relay_agent_circuit_id);
|
||||
|
@ -825,23 +824,23 @@ static Network *network_free(Network *network) {
|
|||
netdev_unref(network->bridge);
|
||||
netdev_unref(network->bond);
|
||||
netdev_unref(network->vrf);
|
||||
hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
|
||||
hashmap_free(network->stacked_netdevs);
|
||||
|
||||
/* static configs */
|
||||
set_free_free(network->ipv6_proxy_ndp_addresses);
|
||||
set_free(network->ipv6_proxy_ndp_addresses);
|
||||
ordered_hashmap_free(network->addresses_by_section);
|
||||
hashmap_free(network->routes_by_section);
|
||||
ordered_hashmap_free(network->nexthops_by_section);
|
||||
hashmap_free_with_destructor(network->bridge_fdb_entries_by_section, bridge_fdb_free);
|
||||
hashmap_free_with_destructor(network->bridge_mdb_entries_by_section, bridge_mdb_free);
|
||||
hashmap_free(network->bridge_fdb_entries_by_section);
|
||||
hashmap_free(network->bridge_mdb_entries_by_section);
|
||||
ordered_hashmap_free(network->neighbors_by_section);
|
||||
hashmap_free(network->address_labels_by_section);
|
||||
hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
|
||||
hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
|
||||
hashmap_free_with_destructor(network->pref64_prefixes_by_section, prefix64_free);
|
||||
hashmap_free(network->prefixes_by_section);
|
||||
hashmap_free(network->route_prefixes_by_section);
|
||||
hashmap_free(network->pref64_prefixes_by_section);
|
||||
hashmap_free(network->rules_by_section);
|
||||
hashmap_free_with_destructor(network->dhcp_static_leases_by_section, dhcp_static_lease_free);
|
||||
ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
|
||||
hashmap_free(network->dhcp_static_leases_by_section);
|
||||
ordered_hashmap_free(network->sr_iov_by_section);
|
||||
hashmap_free(network->qdiscs_by_section);
|
||||
hashmap_free(network->tclasses_by_section);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ bool link_radv_enabled(Link *link) {
|
|||
return link->network->router_prefix_delegation;
|
||||
}
|
||||
|
||||
Prefix* prefix_free(Prefix *prefix) {
|
||||
static Prefix* prefix_free(Prefix *prefix) {
|
||||
if (!prefix)
|
||||
return NULL;
|
||||
|
||||
|
@ -52,6 +52,11 @@ Prefix* prefix_free(Prefix *prefix) {
|
|||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(Prefix, prefix_free);
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
prefix_hash_ops_by_section,
|
||||
ConfigSection, config_section_hash_func, config_section_compare_func,
|
||||
Prefix, prefix_free);
|
||||
|
||||
static int prefix_new_static(Network *network, const char *filename, unsigned section_line, Prefix **ret) {
|
||||
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||
_cleanup_(prefix_freep) Prefix *prefix = NULL;
|
||||
|
@ -87,7 +92,7 @@ static int prefix_new_static(Network *network, const char *filename, unsigned se
|
|||
.prefix.preferred_until = USEC_INFINITY,
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&network->prefixes_by_section, &config_section_hash_ops, prefix->section, prefix);
|
||||
r = hashmap_ensure_put(&network->prefixes_by_section, &prefix_hash_ops_by_section, prefix->section, prefix);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -95,7 +100,7 @@ static int prefix_new_static(Network *network, const char *filename, unsigned se
|
|||
return 0;
|
||||
}
|
||||
|
||||
RoutePrefix* route_prefix_free(RoutePrefix *prefix) {
|
||||
static RoutePrefix* route_prefix_free(RoutePrefix *prefix) {
|
||||
if (!prefix)
|
||||
return NULL;
|
||||
|
||||
|
@ -111,6 +116,11 @@ RoutePrefix* route_prefix_free(RoutePrefix *prefix) {
|
|||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(RoutePrefix, route_prefix_free);
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
route_prefix_hash_ops_by_section,
|
||||
ConfigSection, config_section_hash_func, config_section_compare_func,
|
||||
RoutePrefix, route_prefix_free);
|
||||
|
||||
static int route_prefix_new_static(Network *network, const char *filename, unsigned section_line, RoutePrefix **ret) {
|
||||
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||
_cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL;
|
||||
|
@ -143,7 +153,7 @@ static int route_prefix_new_static(Network *network, const char *filename, unsig
|
|||
.route.valid_until = USEC_INFINITY,
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&network->route_prefixes_by_section, &config_section_hash_ops, prefix->section, prefix);
|
||||
r = hashmap_ensure_put(&network->route_prefixes_by_section, &route_prefix_hash_ops_by_section, prefix->section, prefix);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -151,7 +161,7 @@ static int route_prefix_new_static(Network *network, const char *filename, unsig
|
|||
return 0;
|
||||
}
|
||||
|
||||
Prefix64* prefix64_free(Prefix64 *prefix) {
|
||||
static Prefix64* prefix64_free(Prefix64 *prefix) {
|
||||
if (!prefix)
|
||||
return NULL;
|
||||
|
||||
|
@ -167,6 +177,11 @@ Prefix64* prefix64_free(Prefix64 *prefix) {
|
|||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(Prefix64, prefix64_free);
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
prefix64_hash_ops_by_section,
|
||||
ConfigSection, config_section_hash_func, config_section_compare_func,
|
||||
Prefix64, prefix64_free);
|
||||
|
||||
static int prefix64_new_static(Network *network, const char *filename, unsigned section_line, Prefix64 **ret) {
|
||||
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||
_cleanup_(prefix64_freep) Prefix64 *prefix = NULL;
|
||||
|
@ -199,7 +214,7 @@ static int prefix64_new_static(Network *network, const char *filename, unsigned
|
|||
.prefix64.valid_until = USEC_INFINITY,
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&network->pref64_prefixes_by_section, &config_section_hash_ops, prefix->section, prefix);
|
||||
r = hashmap_ensure_put(&network->pref64_prefixes_by_section, &prefix64_hash_ops_by_section, prefix->section, prefix);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -809,9 +824,9 @@ void network_adjust_radv(Network *network) {
|
|||
}
|
||||
|
||||
if (!FLAGS_SET(network->router_prefix_delegation, RADV_PREFIX_DELEGATION_STATIC)) {
|
||||
network->prefixes_by_section = hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
|
||||
network->route_prefixes_by_section = hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
|
||||
network->pref64_prefixes_by_section = hashmap_free_with_destructor(network->pref64_prefixes_by_section, prefix64_free);
|
||||
network->prefixes_by_section = hashmap_free(network->prefixes_by_section);
|
||||
network->route_prefixes_by_section = hashmap_free(network->route_prefixes_by_section);
|
||||
network->pref64_prefixes_by_section = hashmap_free(network->pref64_prefixes_by_section);
|
||||
}
|
||||
|
||||
if (!network->router_prefix_delegation)
|
||||
|
|
|
@ -52,10 +52,6 @@ typedef struct Prefix64 {
|
|||
sd_ndisc_prefix64 prefix64;
|
||||
} Prefix64;
|
||||
|
||||
Prefix* prefix_free(Prefix *prefix);
|
||||
RoutePrefix* route_prefix_free(RoutePrefix *prefix);
|
||||
Prefix64* prefix64_free(Prefix64 *prefix);
|
||||
|
||||
void network_adjust_radv(Network *network);
|
||||
|
||||
int link_request_radv_addresses(Link *link);
|
||||
|
|
|
@ -947,8 +947,6 @@ static int link_save(Link *link) {
|
|||
}
|
||||
|
||||
void link_dirty(Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
|
@ -962,10 +960,9 @@ void link_dirty(Link *link) {
|
|||
/* Also mark manager dirty as link is dirty */
|
||||
link->manager->dirty = true;
|
||||
|
||||
r = set_ensure_put(&link->manager->dirty_links, NULL, link);
|
||||
if (r <= 0)
|
||||
/* Ignore allocation errors and don't take another ref if the link was already dirty */
|
||||
return;
|
||||
if (set_ensure_put(&link->manager->dirty_links, &link_hash_ops, link) <= 0)
|
||||
return; /* Ignore allocation errors and don't take another ref if the link was already dirty */
|
||||
|
||||
link_ref(link);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "udev-util.h"
|
||||
#include "wifi-util.h"
|
||||
|
||||
Wiphy *wiphy_free(Wiphy *w) {
|
||||
static Wiphy* wiphy_free(Wiphy *w) {
|
||||
if (!w)
|
||||
return NULL;
|
||||
|
||||
|
@ -29,6 +29,13 @@ Wiphy *wiphy_free(Wiphy *w) {
|
|||
return mfree(w);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Wiphy*, wiphy_free);
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
wiphy_hash_ops,
|
||||
void, trivial_hash_func, trivial_compare_func,
|
||||
Wiphy, wiphy_free);
|
||||
|
||||
static int wiphy_new(Manager *manager, sd_netlink_message *message, Wiphy **ret) {
|
||||
_cleanup_(wiphy_freep) Wiphy *w = NULL;
|
||||
_cleanup_free_ char *name = NULL;
|
||||
|
@ -56,7 +63,7 @@ static int wiphy_new(Manager *manager, sd_netlink_message *message, Wiphy **ret)
|
|||
.name = TAKE_PTR(name),
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&manager->wiphy_by_index, NULL, UINT32_TO_PTR(w->index), w);
|
||||
r = hashmap_ensure_put(&manager->wiphy_by_index, &wiphy_hash_ops, UINT32_TO_PTR(w->index), w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
|
@ -31,9 +31,6 @@ typedef struct Wiphy {
|
|||
RFKillState rfkill_state;
|
||||
} Wiphy;
|
||||
|
||||
Wiphy *wiphy_free(Wiphy *w);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Wiphy*, wiphy_free);
|
||||
|
||||
int wiphy_get_by_index(Manager *manager, uint32_t index, Wiphy **ret);
|
||||
int wiphy_get_by_name(Manager *manager, const char *name, Wiphy **ret);
|
||||
|
||||
|
|
|
@ -101,6 +101,7 @@ static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
|
|||
static char *arg_shell_prompt_prefix = NULL;
|
||||
static int arg_lightweight = -1;
|
||||
static char *arg_area = NULL;
|
||||
static bool arg_login_environment = false;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_description, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_environment, strv_freep);
|
||||
|
@ -212,6 +213,7 @@ static int help_sudo_mode(void) {
|
|||
" -g --group=GROUP Run as system group\n"
|
||||
" --nice=NICE Nice level\n"
|
||||
" -D --chdir=PATH Set working directory\n"
|
||||
" -i --login-environment Invoke command via target user's login shell and home\n"
|
||||
" --setenv=NAME[=VALUE] Set environment variable\n"
|
||||
" --background=COLOR Set ANSI color for background\n"
|
||||
" --pty Request allocation of a pseudo TTY for stdio\n"
|
||||
|
@ -254,7 +256,7 @@ static int add_timer_property(const char *name, const char *val) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static char **make_login_shell_cmdline(const char *shell) {
|
||||
static char** make_login_shell_cmdline(const char *shell) {
|
||||
_cleanup_free_ char *argv0 = NULL;
|
||||
|
||||
assert(shell);
|
||||
|
@ -842,6 +844,7 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
|||
{ "group", required_argument, NULL, 'g' },
|
||||
{ "nice", required_argument, NULL, ARG_NICE },
|
||||
{ "chdir", required_argument, NULL, 'D' },
|
||||
{ "login-environment", no_argument, NULL, 'i' },
|
||||
{ "setenv", required_argument, NULL, ARG_SETENV },
|
||||
{ "background", required_argument, NULL, ARG_BACKGROUND },
|
||||
{ "pty", no_argument, NULL, ARG_PTY },
|
||||
|
@ -861,7 +864,7 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
|||
/* Resetting to 0 forces the invocation of an internal initialization routine of getopt_long()
|
||||
* that checks for GNU extensions in optstring ('-' or '+' at the beginning). */
|
||||
optind = 0;
|
||||
while ((c = getopt_long(argc, argv, "+hVu:g:D:a:", options, NULL)) >= 0)
|
||||
while ((c = getopt_long(argc, argv, "+hVu:g:D:a:i", options, NULL)) >= 0)
|
||||
|
||||
switch (c) {
|
||||
|
||||
|
@ -975,6 +978,10 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
|||
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
arg_login_environment = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -991,7 +998,7 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
if (!arg_working_directory) {
|
||||
if (arg_exec_user) {
|
||||
if (arg_exec_user || arg_login_environment) {
|
||||
/* When switching to a specific user, also switch to its home directory. */
|
||||
arg_working_directory = strdup("~");
|
||||
if (!arg_working_directory)
|
||||
|
@ -1023,9 +1030,11 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
|||
arg_send_sighup = true;
|
||||
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
if (argc > optind)
|
||||
if (argc > optind) {
|
||||
l = strv_copy(argv + optind);
|
||||
else {
|
||||
if (!l)
|
||||
return log_oom();
|
||||
} else if (!arg_login_environment) {
|
||||
const char *e;
|
||||
|
||||
e = strv_env_get(arg_environment, "SHELL");
|
||||
|
@ -1050,9 +1059,19 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
l = make_login_shell_cmdline(arg_exec_path);
|
||||
if (!l)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (arg_login_environment) {
|
||||
arg_exec_path = strdup("/bin/sh");
|
||||
if (!arg_exec_path)
|
||||
return log_oom();
|
||||
|
||||
r = strv_prepend(&l, "-sh");
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
if (!l)
|
||||
return log_oom();
|
||||
|
||||
strv_free_and_replace(arg_cmdline, l);
|
||||
|
||||
|
@ -1092,6 +1111,12 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
|
|||
if (strv_extend(&arg_property, "PAMName=systemd-run0") < 0)
|
||||
return log_oom();
|
||||
|
||||
/* The service manager ignores SIGPIPE for all spawned processes by default. Let's explicitly override
|
||||
* that here, since we're primarily invoked in interactive environments, and the termination of
|
||||
* local terminal session should be acknowledged by remote even for --pipe stdio. */
|
||||
if (strv_extend(&arg_property, "IgnoreSIGPIPE=no") < 0)
|
||||
return log_oom();
|
||||
|
||||
if (!arg_background && arg_stdio == ARG_STDIO_PTY && shall_tint_background()) {
|
||||
double hue;
|
||||
|
||||
|
@ -1260,10 +1285,8 @@ static int transient_kill_set_properties(sd_bus_message *m) {
|
|||
static int transient_service_set_properties(sd_bus_message *m, const char *pty_path, int pty_fd) {
|
||||
int r, send_term; /* tri-state */
|
||||
|
||||
/* We disable environment expansion on the server side via ExecStartEx=:.
|
||||
* ExecStartEx was added relatively recently (v243), and some bugs were fixed only later.
|
||||
* So use that feature only if required. It will fail with older systemds. */
|
||||
bool use_ex_prop = !arg_expand_environment;
|
||||
/* Use ExecStartEx if new exec flags are required. */
|
||||
bool use_ex_prop = !arg_expand_environment || arg_login_environment;
|
||||
|
||||
assert(m);
|
||||
assert((!!pty_path) == (pty_fd >= 0));
|
||||
|
@ -1450,7 +1473,9 @@ static int transient_service_set_properties(sd_bus_message *m, const char *pty_p
|
|||
_cleanup_strv_free_ char **opts = NULL;
|
||||
|
||||
r = exec_command_flags_to_strv(
|
||||
(arg_expand_environment ? 0 : EXEC_COMMAND_NO_ENV_EXPAND)|(arg_ignore_failure ? EXEC_COMMAND_IGNORE_FAILURE : 0),
|
||||
(arg_expand_environment ? 0 : EXEC_COMMAND_NO_ENV_EXPAND)|
|
||||
(arg_ignore_failure ? EXEC_COMMAND_IGNORE_FAILURE : 0)|
|
||||
(arg_login_environment ? EXEC_COMMAND_PREFIX_SHELL : 0),
|
||||
&opts);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to format execute flags: %m");
|
||||
|
@ -2810,7 +2835,12 @@ static int run(int argc, char* argv[]) {
|
|||
|
||||
if (strv_isempty(arg_cmdline))
|
||||
t = strdup(arg_unit);
|
||||
else if (startswith(arg_cmdline[0], "-")) {
|
||||
else if (arg_login_environment) {
|
||||
if (arg_cmdline[1])
|
||||
t = quote_command_line(arg_cmdline + 1, SHELL_ESCAPE_EMPTY);
|
||||
else
|
||||
t = strjoin("LOGIN", arg_exec_user ? ": " : NULL, arg_exec_user);
|
||||
} else if (startswith(arg_cmdline[0], "-")) {
|
||||
/* Drop the login shell marker from the command line when generating the description,
|
||||
* in order to minimize user confusion. */
|
||||
_cleanup_strv_free_ char **l = strv_copy(arg_cmdline);
|
||||
|
|
|
@ -331,17 +331,28 @@ static int bus_append_exec_command(sd_bus_message *m, const char *field, const c
|
|||
}
|
||||
break;
|
||||
|
||||
case '|':
|
||||
if (FLAGS_SET(flags, EXEC_COMMAND_PREFIX_SHELL))
|
||||
done = true;
|
||||
else {
|
||||
flags |= EXEC_COMMAND_PREFIX_SHELL;
|
||||
eq++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
done = true;
|
||||
}
|
||||
} while (!done);
|
||||
|
||||
if (!is_ex_prop && (flags & (EXEC_COMMAND_NO_ENV_EXPAND|EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID))) {
|
||||
if (!is_ex_prop && (flags & (EXEC_COMMAND_NO_ENV_EXPAND|EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_PREFIX_SHELL))) {
|
||||
/* Upgrade the ExecXYZ= property to ExecXYZEx= for convenience */
|
||||
is_ex_prop = true;
|
||||
|
||||
upgraded_name = strjoin(field, "Ex");
|
||||
if (!upgraded_name)
|
||||
return log_oom();
|
||||
field = upgraded_name;
|
||||
}
|
||||
|
||||
if (is_ex_prop) {
|
||||
|
@ -350,21 +361,36 @@ static int bus_append_exec_command(sd_bus_message *m, const char *field, const c
|
|||
return log_error_errno(r, "Failed to convert ExecCommandFlags to strv: %m");
|
||||
}
|
||||
|
||||
if (explicit_path) {
|
||||
if (FLAGS_SET(flags, EXEC_COMMAND_PREFIX_SHELL)) {
|
||||
path = strdup("/bin/sh");
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
} else if (explicit_path) {
|
||||
r = extract_first_word(&eq, &path, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse path: %m");
|
||||
if (r == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No executable path specified, refusing.");
|
||||
if (isempty(eq))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Got empty command line, refusing.");
|
||||
}
|
||||
|
||||
r = strv_split_full(&l, eq, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse command line: %m");
|
||||
|
||||
if (FLAGS_SET(flags, EXEC_COMMAND_PREFIX_SHELL)) {
|
||||
r = strv_prepend(&l, explicit_path ? "-sh" : "sh");
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, upgraded_name ?: field);
|
||||
r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
|
|
|
@ -146,13 +146,13 @@ int memfd_clone_fd(int fd, const char *name, int mode) {
|
|||
|
||||
assert(fd >= 0);
|
||||
assert(name);
|
||||
assert(IN_SET(mode & O_ACCMODE, O_RDONLY, O_RDWR));
|
||||
assert(IN_SET(mode & O_ACCMODE_STRICT, O_RDONLY, O_RDWR));
|
||||
assert((mode & ~(O_RDONLY|O_RDWR|O_CLOEXEC)) == 0);
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
ro = (mode & O_ACCMODE) == O_RDONLY;
|
||||
ro = (mode & O_ACCMODE_STRICT) == O_RDONLY;
|
||||
exec = st.st_mode & 0111;
|
||||
|
||||
mfd = memfd_create_wrapper(name,
|
||||
|
|
|
@ -488,6 +488,7 @@ static const char* const exec_command_strings[] = {
|
|||
"privileged", /* EXEC_COMMAND_FULLY_PRIVILEGED */
|
||||
"no-setuid", /* EXEC_COMMAND_NO_SETUID */
|
||||
"no-env-expand", /* EXEC_COMMAND_NO_ENV_EXPAND */
|
||||
"prefix-shell", /* EXEC_COMMAND_PREFIX_SHELL */
|
||||
};
|
||||
|
||||
assert_cc((1 << ELEMENTSOF(exec_command_strings)) - 1 == _EXEC_COMMAND_FLAGS_ALL);
|
||||
|
|
|
@ -49,8 +49,9 @@ typedef enum ExecCommandFlags {
|
|||
EXEC_COMMAND_FULLY_PRIVILEGED = 1 << 1,
|
||||
EXEC_COMMAND_NO_SETUID = 1 << 2,
|
||||
EXEC_COMMAND_NO_ENV_EXPAND = 1 << 3,
|
||||
EXEC_COMMAND_PREFIX_SHELL = 1 << 4,
|
||||
_EXEC_COMMAND_FLAGS_INVALID = -EINVAL,
|
||||
_EXEC_COMMAND_FLAGS_ALL = (1 << 4) -1,
|
||||
_EXEC_COMMAND_FLAGS_ALL = (1 << 5) -1,
|
||||
} ExecCommandFlags;
|
||||
|
||||
int exec_command_flags_from_strv(char * const *ex_opts, ExecCommandFlags *ret);
|
||||
|
|
|
@ -504,7 +504,7 @@ int journal_file_open_reliably(
|
|||
-EIDRM)) /* File has been deleted */
|
||||
return r;
|
||||
|
||||
if ((open_flags & O_ACCMODE) == O_RDONLY)
|
||||
if ((open_flags & O_ACCMODE_STRICT) == O_RDONLY)
|
||||
return r;
|
||||
|
||||
if (!(open_flags & O_CREAT))
|
||||
|
@ -519,7 +519,7 @@ int journal_file_open_reliably(
|
|||
/* The file is corrupted. Try opening it read-only as the template before rotating to inherit its
|
||||
* sequence number and ID. */
|
||||
r = journal_file_open(-EBADF, fname,
|
||||
(open_flags & ~(O_ACCMODE|O_CREAT|O_EXCL)) | O_RDONLY,
|
||||
(open_flags & ~(O_ACCMODE_STRICT|O_CREAT|O_EXCL)) | O_RDONLY,
|
||||
file_flags, 0, compress_threshold_bytes, NULL,
|
||||
mmap_cache, /* template = */ NULL, &old_file);
|
||||
if (r < 0)
|
||||
|
|
|
@ -500,7 +500,7 @@ static int loop_device_make_internal(
|
|||
.block_size = sector_size,
|
||||
.info = {
|
||||
/* Use the specified flags, but configure the read-only flag from the open flags, and force autoclear */
|
||||
.lo_flags = (loop_flags & ~LO_FLAGS_READ_ONLY) | ((open_flags & O_ACCMODE) == O_RDONLY ? LO_FLAGS_READ_ONLY : 0) | LO_FLAGS_AUTOCLEAR,
|
||||
.lo_flags = (loop_flags & ~LO_FLAGS_READ_ONLY) | ((open_flags & O_ACCMODE_STRICT) == O_RDONLY ? LO_FLAGS_READ_ONLY : 0) | LO_FLAGS_AUTOCLEAR,
|
||||
.lo_offset = offset,
|
||||
.lo_sizelimit = size == UINT64_MAX ? 0 : size,
|
||||
},
|
||||
|
|
|
@ -9,6 +9,25 @@
|
|||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
static SRIOV* sr_iov_free(SRIOV *sr_iov) {
|
||||
if (!sr_iov)
|
||||
return NULL;
|
||||
|
||||
if (sr_iov->sr_iov_by_section && sr_iov->section)
|
||||
ordered_hashmap_remove(sr_iov->sr_iov_by_section, sr_iov->section);
|
||||
|
||||
config_section_free(sr_iov->section);
|
||||
|
||||
return mfree(sr_iov);
|
||||
}
|
||||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(SRIOV, sr_iov_free);
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
sr_iov_hash_ops_by_section,
|
||||
ConfigSection, config_section_hash_func, config_section_compare_func,
|
||||
SRIOV, sr_iov_free);
|
||||
|
||||
static int sr_iov_new(SRIOV **ret) {
|
||||
SRIOV *sr_iov;
|
||||
|
||||
|
@ -57,7 +76,7 @@ static int sr_iov_new_static(OrderedHashmap **sr_iov_by_section, const char *fil
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_hashmap_ensure_put(sr_iov_by_section, &config_section_hash_ops, n, sr_iov);
|
||||
r = ordered_hashmap_ensure_put(sr_iov_by_section, &sr_iov_hash_ops_by_section, n, sr_iov);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -68,18 +87,6 @@ static int sr_iov_new_static(OrderedHashmap **sr_iov_by_section, const char *fil
|
|||
return 0;
|
||||
}
|
||||
|
||||
SRIOV *sr_iov_free(SRIOV *sr_iov) {
|
||||
if (!sr_iov)
|
||||
return NULL;
|
||||
|
||||
if (sr_iov->sr_iov_by_section && sr_iov->section)
|
||||
ordered_hashmap_remove(sr_iov->sr_iov_by_section, sr_iov->section);
|
||||
|
||||
config_section_free(sr_iov->section);
|
||||
|
||||
return mfree(sr_iov);
|
||||
}
|
||||
|
||||
void sr_iov_hash_func(const SRIOV *sr_iov, struct siphash *state) {
|
||||
assert(sr_iov);
|
||||
assert(state);
|
||||
|
|
|
@ -32,7 +32,6 @@ typedef struct SRIOV {
|
|||
struct ether_addr mac;
|
||||
} SRIOV;
|
||||
|
||||
SRIOV *sr_iov_free(SRIOV *sr_iov);
|
||||
void sr_iov_hash_func(const SRIOV *sr_iov, struct siphash *state);
|
||||
int sr_iov_compare_func(const SRIOV *s1, const SRIOV *s2);
|
||||
int sr_iov_set_netlink_message(SRIOV *sr_iov, sd_netlink_message *req);
|
||||
|
@ -40,8 +39,6 @@ int sr_iov_get_num_vfs(sd_device *device, uint32_t *ret);
|
|||
int sr_iov_set_num_vfs(sd_device *device, uint32_t num_vfs, OrderedHashmap *sr_iov_by_section);
|
||||
int sr_iov_drop_invalid_sections(uint32_t num_vfs, OrderedHashmap *sr_iov_by_section);
|
||||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(SRIOV, sr_iov_free);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_uint32);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_boolean);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_link_state);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "blockdev-util.h"
|
||||
#include "detach-loopback.h"
|
||||
#include "device-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "shutdown.h"
|
||||
|
||||
|
@ -106,8 +107,12 @@ static int delete_loopback(const char *device) {
|
|||
|
||||
fd = open(device, O_RDONLY|O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
log_debug_errno(errno, "Failed to open loopback device %s: %m", device);
|
||||
return errno == ENOENT ? 0 : -errno;
|
||||
if (ERRNO_IS_DEVICE_ABSENT(errno)) {
|
||||
log_debug_errno(errno, "Tried to open loopback device '%s', but device disappeared by now, ignoring: %m", device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return log_debug_errno(errno, "Failed to open loopback device '%s': %m", device);
|
||||
}
|
||||
|
||||
/* Loopback block devices don't sync in-flight blocks when we clear the fd, hence sync explicitly
|
||||
|
|
|
@ -131,12 +131,21 @@ static int delete_md(RaidDevice *m) {
|
|||
assert(m->path);
|
||||
|
||||
fd = open(m->path, O_RDONLY|O_CLOEXEC|O_EXCL);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
if (fd < 0) {
|
||||
if (ERRNO_IS_DEVICE_ABSENT(errno)) {
|
||||
log_debug_errno(errno, "Tried to open MD device '%s', but device disappeared by now, ignoring: %m", m->path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return log_debug_errno(errno, "Failed to open MD device '%s': %m", m->path);
|
||||
}
|
||||
|
||||
(void) sync_with_progress(fd);
|
||||
|
||||
return RET_NERRNO(ioctl(fd, STOP_ARRAY, NULL));
|
||||
if (ioctl(fd, STOP_ARRAY, NULL) < 0)
|
||||
return log_debug_errno(errno, "Failed to issue STOP_ARRAY on MD device '%s': %m", m->path);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int md_points_list_detach(RaidDevice **head, bool *changed, bool last_try) {
|
||||
|
@ -164,8 +173,9 @@ static int md_points_list_detach(RaidDevice **head, bool *changed, bool last_try
|
|||
n_failed++;
|
||||
continue;
|
||||
}
|
||||
if (r > 0)
|
||||
*changed = true;
|
||||
|
||||
*changed = true;
|
||||
raid_device_free(head, m);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "alloc-util.h"
|
||||
#include "detach-swap.h"
|
||||
#include "errno-util.h"
|
||||
#include "libmount-util.h"
|
||||
|
||||
static void swap_device_free(SwapDevice **head, SwapDevice *m) {
|
||||
|
@ -74,20 +75,23 @@ int swap_list_get(const char *swaps, SwapDevice **head) {
|
|||
}
|
||||
|
||||
static int swap_points_list_off(SwapDevice **head, bool *changed) {
|
||||
int n_failed = 0;
|
||||
int n_failed = 0, r;
|
||||
|
||||
assert(head);
|
||||
assert(changed);
|
||||
|
||||
LIST_FOREACH(swap_device, m, *head) {
|
||||
log_info("Deactivating swap %s.", m->path);
|
||||
if (swapoff(m->path) < 0) {
|
||||
log_warning_errno(errno, "Could not deactivate swap %s: %m", m->path);
|
||||
r = RET_NERRNO(swapoff(m->path));
|
||||
if (ERRNO_IS_NEG_DEVICE_ABSENT(r))
|
||||
log_debug_errno(r, "Tried to deactivate swap '%s', but swap disappeared by now, ignoring: %m", m->path);
|
||||
else if (r < 0) {
|
||||
log_warning_errno(r, "Could not deactivate swap %s: %m", m->path);
|
||||
n_failed++;
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
*changed = true;
|
||||
|
||||
*changed = true;
|
||||
swap_device_free(head, m);
|
||||
}
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ static void context_done(Context *c) {
|
|||
hashmap_free(c->database_by_gid);
|
||||
hashmap_free(c->database_by_groupname);
|
||||
|
||||
set_free_free(c->names);
|
||||
set_free(c->names);
|
||||
uid_range_free(c->uid_range);
|
||||
}
|
||||
|
||||
|
@ -231,9 +231,8 @@ static int load_user_database(Context *c) {
|
|||
if (!n)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Note that we use NULL hash_ops (i.e. trivial_hash_ops) here, so identical strings can
|
||||
* exist in the set. */
|
||||
r = set_ensure_consume(&c->names, /* hash_ops= */ NULL, n);
|
||||
/* Note that we use trivial_hash_ops_free here, so identical strings can exist in the set. */
|
||||
r = set_ensure_consume(&c->names, &trivial_hash_ops_free, n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(r > 0); /* The set uses pointer comparisons, so n must not be in the set. */
|
||||
|
@ -274,9 +273,8 @@ static int load_group_database(Context *c) {
|
|||
if (!n)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Note that we use NULL hash_ops (i.e. trivial_hash_ops) here, so identical strings can
|
||||
* exist in the set. */
|
||||
r = set_ensure_consume(&c->names, /* hash_ops= */ NULL, n);
|
||||
/* Note that we use trivial_hash_ops_free here, so identical strings can exist in the set. */
|
||||
r = set_ensure_consume(&c->names, &trivial_hash_ops_free, n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(r > 0); /* The set uses pointer comparisons, so n must not be in the set. */
|
||||
|
|
|
@ -64,7 +64,7 @@ typedef struct SysvStub {
|
|||
bool loaded;
|
||||
} SysvStub;
|
||||
|
||||
static SysvStub* free_sysvstub(SysvStub *s) {
|
||||
static SysvStub* sysvstub_free(SysvStub *s) {
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
|
@ -78,11 +78,12 @@ static SysvStub* free_sysvstub(SysvStub *s) {
|
|||
strv_free(s->wanted_by);
|
||||
return mfree(s);
|
||||
}
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(SysvStub*, free_sysvstub);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(SysvStub*, sysvstub_free);
|
||||
|
||||
static void free_sysvstub_hashmapp(Hashmap **h) {
|
||||
hashmap_free_with_destructor(*h, free_sysvstub);
|
||||
}
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
sysvstub_hash_ops,
|
||||
char, string_hash_func, string_compare_func,
|
||||
SysvStub, sysvstub_free);
|
||||
|
||||
static int add_alias(const char *service, const char *alias) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
|
@ -728,7 +729,7 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
|
|||
|
||||
FOREACH_DIRENT(de, d, log_error_errno(errno, "Failed to enumerate directory %s, ignoring: %m", *path)) {
|
||||
_cleanup_free_ char *fpath = NULL, *name = NULL;
|
||||
_cleanup_(free_sysvstubp) SysvStub *service = NULL;
|
||||
_cleanup_(sysvstub_freep) SysvStub *service = NULL;
|
||||
struct stat st;
|
||||
|
||||
if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) {
|
||||
|
@ -894,7 +895,7 @@ finish:
|
|||
}
|
||||
|
||||
static int run(const char *dest, const char *dest_early, const char *dest_late) {
|
||||
_cleanup_(free_sysvstub_hashmapp) Hashmap *all_services = NULL;
|
||||
_cleanup_hashmap_free_ Hashmap *all_services = NULL;
|
||||
_cleanup_(lookup_paths_done) LookupPaths lp = {};
|
||||
SysvStub *service;
|
||||
int r;
|
||||
|
@ -910,7 +911,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
all_services = hashmap_new(&string_hash_ops);
|
||||
all_services = hashmap_new(&sysvstub_hash_ops);
|
||||
if (!all_services)
|
||||
return log_oom();
|
||||
|
||||
|
|
|
@ -1104,7 +1104,7 @@ TEST(fdopen_independent) {
|
|||
zero(buf);
|
||||
assert_se(fread(buf, 1, sizeof(buf), f) == strlen(TEST_TEXT));
|
||||
ASSERT_STREQ(buf, TEST_TEXT);
|
||||
assert_se((fcntl(fileno(f), F_GETFL) & O_ACCMODE) == O_RDONLY);
|
||||
assert_se((fcntl(fileno(f), F_GETFL) & O_ACCMODE_STRICT) == O_RDONLY);
|
||||
assert_se(FLAGS_SET(fcntl(fileno(f), F_GETFD), FD_CLOEXEC));
|
||||
f = safe_fclose(f);
|
||||
|
||||
|
@ -1112,7 +1112,7 @@ TEST(fdopen_independent) {
|
|||
zero(buf);
|
||||
assert_se(fread(buf, 1, sizeof(buf), f) == strlen(TEST_TEXT));
|
||||
ASSERT_STREQ(buf, TEST_TEXT);
|
||||
assert_se((fcntl(fileno(f), F_GETFL) & O_ACCMODE) == O_RDONLY);
|
||||
assert_se((fcntl(fileno(f), F_GETFL) & O_ACCMODE_STRICT) == O_RDONLY);
|
||||
assert_se(!FLAGS_SET(fcntl(fileno(f), F_GETFD), FD_CLOEXEC));
|
||||
f = safe_fclose(f);
|
||||
|
||||
|
@ -1120,7 +1120,7 @@ TEST(fdopen_independent) {
|
|||
zero(buf);
|
||||
assert_se(fread(buf, 1, sizeof(buf), f) == strlen(TEST_TEXT));
|
||||
ASSERT_STREQ(buf, TEST_TEXT);
|
||||
assert_se((fcntl(fileno(f), F_GETFL) & O_ACCMODE) == O_RDWR);
|
||||
assert_se((fcntl(fileno(f), F_GETFL) & O_ACCMODE_STRICT) == O_RDWR);
|
||||
assert_se(FLAGS_SET(fcntl(fileno(f), F_GETFD), FD_CLOEXEC));
|
||||
f = safe_fclose(f);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ static LinkConfig* link_config_free(LinkConfig *config) {
|
|||
erase_and_free(config->wol_password);
|
||||
cpu_set_free(config->rps_cpu_mask);
|
||||
|
||||
ordered_hashmap_free_with_destructor(config->sr_iov_by_section, sr_iov_free);
|
||||
ordered_hashmap_free(config->sr_iov_by_section);
|
||||
|
||||
return mfree(config);
|
||||
}
|
||||
|
|
|
@ -38,14 +38,14 @@ directory (`OutputDirectory=`) to point to the other directory using `mkosi/mkos
|
|||
After the image has been built, the integration tests can be run with:
|
||||
|
||||
```shell
|
||||
$ env SYSTEMD_INTEGRATION_TESTS=1 mkosi -f sandbox -- meson test -C build --suite integration-tests --num-processes "$(($(nproc) / 4))"
|
||||
$ mkosi -f sandbox -- meson test -C build --setup=integration --suite integration-tests --num-processes "$(($(nproc) / 4))"
|
||||
```
|
||||
|
||||
As usual, specific tests can be run in meson by appending the name of the test
|
||||
which is usually the name of the directory e.g.
|
||||
|
||||
```shell
|
||||
$ env SYSTEMD_INTEGRATION_TESTS=1 mkosi -f sandbox -- meson test -C build -v TEST-01-BASIC
|
||||
$ mkosi -f sandbox -- meson test -C build --setup=integration -v TEST-01-BASIC
|
||||
```
|
||||
|
||||
See `mkosi -f sandbox -- meson introspect build --tests` for a list of tests.
|
||||
|
@ -55,7 +55,7 @@ To interactively debug a failing integration test, the `--interactive` option
|
|||
newer:
|
||||
|
||||
```shell
|
||||
$ env SYSTEMD_INTEGRATION_TESTS=1 mkosi -f sandbox -- meson test -C build -i TEST-01-BASIC
|
||||
$ mkosi -f sandbox -- meson test -C build --setup=integration -i TEST-01-BASIC
|
||||
```
|
||||
|
||||
Due to limitations in meson, the integration tests do not yet depend on the
|
||||
|
@ -64,7 +64,7 @@ running the integration tests. To rebuild the image and rerun a test, the
|
|||
following command can be used:
|
||||
|
||||
```shell
|
||||
$ mkosi -f sandbox -- meson compile -C build mkosi && env SYSTEMD_INTEGRATION_TESTS=1 mkosi -f sandbox -- meson test -C build -v TEST-01-BASIC
|
||||
$ mkosi -f sandbox -- meson compile -C build mkosi && mkosi -f sandbox -- meson test -C build --setup=integration -v TEST-01-BASIC
|
||||
```
|
||||
|
||||
The integration tests use the same mkosi configuration that's used when you run
|
||||
|
@ -78,7 +78,7 @@ To iterate on an integration test, let's first get a shell in the integration te
|
|||
the following:
|
||||
|
||||
```shell
|
||||
$ mkosi -f sandbox -- meson compile -C build mkosi && env SYSTEMD_INTEGRATION_TESTS=1 TEST_SHELL=1 mkosi -f sandbox -- meson test -C build -i TEST-01-BASIC
|
||||
$ mkosi -f sandbox -- meson compile -C build mkosi && mkosi -f sandbox -- meson test -C build --setup=shell -i TEST-01-BASIC
|
||||
```
|
||||
|
||||
This will get us a shell in the integration test environment after booting the machine without running the
|
||||
|
@ -107,7 +107,7 @@ re-running the test will first install the new packages we just built, make a ne
|
|||
the test again. You can keep running the loop of `mkosi -R`, `systemctl soft-reboot` and
|
||||
`systemctl start ...` until the changes to the integration test are working.
|
||||
|
||||
If you're debugging a failing integration test (running `meson test --interactive` without `TEST_SHELL`),
|
||||
If you're debugging a failing integration test (running `meson test --interactive`),
|
||||
there's no need to run `systemctl start ...`, running `systemctl soft-reboot` on its own is sufficient to
|
||||
rerun the test.
|
||||
|
||||
|
@ -120,10 +120,6 @@ rerun the test.
|
|||
`TEST_NO_KVM=1`: Disable qemu KVM auto-detection (may be necessary when you're
|
||||
trying to run the *vanilla* qemu and have both qemu and qemu-kvm installed)
|
||||
|
||||
`TEST_SHELL=1`: Configure the machine to be more *user-friendly* for
|
||||
interactive debugging (e.g. by setting a usable default terminal, suppressing
|
||||
the shutdown after the test, etc.).
|
||||
|
||||
`TEST_MATCH_SUBTEST=subtest`: If the test makes use of `run_subtests` use this
|
||||
variable to provide a POSIX extended regex to run only subtests matching the
|
||||
expression.
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Service]
|
||||
Type=oneshot
|
||||
Environment=SHLVL=100
|
||||
ExecStartPre=-|false
|
||||
ExecStart=|@echo with login shell $$SHELL: lvl $$SHLVL
|
||||
ExecStart=:|"str='with normal shell'" printenv str
|
||||
ExecStart=|echo YAY! >/tmp/TEST-07-PID1.prefix-shell.flag
|
|
@ -361,7 +361,7 @@ def statfs(path: Path) -> str:
|
|||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--mkosi', required=True)
|
||||
parser.add_argument('--mkosi', default=None)
|
||||
parser.add_argument('--meson-source-dir', required=True, type=Path)
|
||||
parser.add_argument('--meson-build-dir', required=True, type=Path)
|
||||
parser.add_argument('--name', required=True)
|
||||
|
@ -379,6 +379,12 @@ def main() -> None:
|
|||
parser.add_argument('mkosi_args', nargs='*')
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.mkosi:
|
||||
args.mkosi = shutil.which('mkosi')
|
||||
if not args.mkosi:
|
||||
print('Could not find mkosi which is required to run the integration tests', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# The meson source directory can either be the top-level repository directory or the
|
||||
# test/integration-tests/standalone subdirectory in the repository directory. The mkosi configuration
|
||||
# will always be a parent directory of one of these directories and at most 4 levels upwards, so don't
|
||||
|
@ -395,13 +401,6 @@ def main() -> None:
|
|||
)
|
||||
exit(1)
|
||||
|
||||
if not bool(int(os.getenv('SYSTEMD_INTEGRATION_TESTS', '0'))):
|
||||
print(
|
||||
f'SYSTEMD_INTEGRATION_TESTS=1 not found in environment, skipping {args.name}',
|
||||
file=sys.stderr,
|
||||
)
|
||||
exit(77)
|
||||
|
||||
if args.slow and not bool(int(os.getenv('SYSTEMD_SLOW_TESTS', '0'))):
|
||||
print(
|
||||
f'SYSTEMD_SLOW_TESTS=1 not found in environment, skipping {args.name}',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
# We'd give these more descriptive names but only alphanumeric characters are allowed.
|
||||
add_test_setup('integration')
|
||||
add_test_setup('shell', env : {'TEST_SHELL' : '1'})
|
||||
|
||||
integration_test_wrapper = find_program('integration-test-wrapper.py')
|
||||
integration_tests = []
|
||||
integration_test_template = {
|
||||
|
@ -129,11 +133,11 @@ foreach integration_test : integration_tests
|
|||
integration_test_args += ['--skip']
|
||||
endif
|
||||
|
||||
if not mkosi.found()
|
||||
continue
|
||||
if mkosi.found()
|
||||
integration_test_args += ['--mkosi', mkosi.full_path()]
|
||||
endif
|
||||
|
||||
integration_test_args += ['--mkosi', mkosi.full_path(), '--']
|
||||
integration_test_args += ['--']
|
||||
|
||||
if integration_test['cmdline'].length() > 0
|
||||
integration_test_args += [
|
||||
|
@ -151,19 +155,12 @@ foreach integration_test : integration_tests
|
|||
|
||||
integration_test_args += integration_test['mkosi-args']
|
||||
|
||||
integration_test_env = {}
|
||||
|
||||
if want_integration_tests
|
||||
integration_test_env += {'SYSTEMD_INTEGRATION_TESTS': '1'}
|
||||
endif
|
||||
|
||||
# We don't explicitly depend on the "mkosi" target because that means the image is rebuilt on every
|
||||
# "ninja -C build". Instead, the mkosi target has to be rebuilt manually before running the
|
||||
# integration tests with mkosi.
|
||||
test(
|
||||
integration_test['name'],
|
||||
integration_test_wrapper,
|
||||
env : integration_test_env,
|
||||
args : integration_test_args,
|
||||
timeout : integration_test['timeout'],
|
||||
priority : integration_test['priority'],
|
||||
|
|
|
@ -16,7 +16,6 @@ project('systemd-testsuite',
|
|||
|
||||
fs = import('fs')
|
||||
mkosi = find_program('mkosi', required : true)
|
||||
want_integration_tests = true
|
||||
|
||||
# meson refuses .. in subdir() so we use a symlink to trick it into accepting it anyway.
|
||||
subdir('integration-tests')
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
# shellcheck disable=SC2016
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
# shellcheck source=test/units/util.sh
|
||||
. "$(dirname "$0")"/util.sh
|
||||
|
||||
systemd-run --wait -p ExecStartPre="|true" \
|
||||
-p ExecStartPre="|@echo a >/tmp/TEST-07-PID1.prefix-shell.flag" \
|
||||
true
|
||||
assert_eq "$(cat /tmp/TEST-07-PID1.prefix-shell.flag)" "a"
|
||||
rm /tmp/TEST-07-PID1.prefix-shell.flag
|
||||
|
||||
systemctl start prefix-shell.service
|
||||
assert_eq "$(cat /tmp/TEST-07-PID1.prefix-shell.flag)" "YAY!"
|
||||
|
||||
journalctl --sync
|
||||
journalctl -b -u prefix-shell.service --grep "with login shell .*: lvl 101"
|
||||
journalctl -b -u prefix-shell.service --grep "with normal shell"
|
|
@ -256,10 +256,20 @@ if [[ -e /usr/lib/pam.d/systemd-run0 ]] || [[ -e /etc/pam.d/systemd-run0 ]]; the
|
|||
# Validate that we actually went properly through PAM (XDG_SESSION_TYPE is set by pam_systemd)
|
||||
assert_eq "$(run0 ${tu:+"--user=$tu"} bash -c 'echo $XDG_SESSION_TYPE')" "unspecified"
|
||||
|
||||
# Test shell prefixing
|
||||
assert_eq "$(run0 ${tu:+"--user=$tu"} --setenv=SHLVL=10 printenv SHLVL)" "10"
|
||||
if [[ ! -v ASAN_OPTIONS ]]; then
|
||||
assert_eq "$(run0 ${tu:+"--user=$tu"} --setenv=SHLVL=10 -i echo \$SHLVL)" "11"
|
||||
fi
|
||||
|
||||
if [[ -n "$tu" ]]; then
|
||||
# Validate that $SHELL is set to login shell of target user when cmdline is supplied (not invoking shell)
|
||||
TARGET_LOGIN_SHELL="$(getent passwd "$tu" | cut -d: -f7)"
|
||||
assert_eq "$(run0 --user="$tu" printenv SHELL)" "$TARGET_LOGIN_SHELL"
|
||||
# ... or when the command is chained by login shell
|
||||
if [[ ! -v ASAN_OPTIONS ]]; then
|
||||
assert_eq "$(run0 --user="$tu" -i printenv SHELL)" "$TARGET_LOGIN_SHELL"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
# Let's chain a couple of run0 calls together, for fun
|
||||
|
|
Loading…
Reference in New Issue