1
0
mirror of https://github.com/systemd/systemd synced 2026-03-31 20:24:50 +02:00

Compare commits

...

31 Commits

Author SHA1 Message Date
Yu Watanabe
fe6e6cb6a0
time-util: several fixlets/workarounds for supporting musl (#39688) 2025-11-13 05:18:25 +09:00
Yu Watanabe
d278d5bc3d
sd-journal: fix relative path handling (#38681)
Fixes #38667.
2025-11-13 05:12:00 +09:00
Yu Watanabe
ca3933bf49
core/dbus-service: validate type of received ExecContext fds (#39680) 2025-11-13 05:11:07 +09:00
Yu Watanabe
7ebfcfc17b
meson: add musl support (#39686) 2025-11-13 05:10:22 +09:00
Yu Watanabe
7dad0db2ee musl: meson: gracefully disable gshadow, nss, and idn support
- musl does not support gshadow, and does not provide gshadow.h,
- musl does not support nss, and does not provide nss.h which is necessary
  for each nss modules,
- musl does not provide NI_IDN.
2025-11-13 04:44:32 +09:00
Yu Watanabe
17e343b58b musl: meson: check existence of renameat2()
musl-1.2.5 does not provide renameat2(). Note, it is added by
05ce67fea9,
hence hopefully it will be provided by musl-1.2.6 or newer.
2025-11-13 04:44:00 +09:00
Yu Watanabe
0736854da9 musl: meson: make musl not define wchar_t in their header
Otherwise, musl defines wchar_t as int, which conflicts with the
assumption by sd-boot, i.e. wchar_t is 2 bytes.

Fixes the following build error:
```
In file included from ../src/boot/efi-log.h:4,
                 from ../src/boot/linux_x86.c:13:
../src/boot/efi.h:19:24: error: conflicting types for 'wchar_t'; have 'short unsigned int'
   19 | typedef __WCHAR_TYPE__ wchar_t;
      |                        ^~~~~~~
In file included from /usr/include/stddef.h:19,
                 from ../src/boot/efi.h:9:
/usr/include/bits/alltypes.h:10:13: note: previous declaration of 'wchar_t' with type 'wchar_t' {aka 'int'}
   10 | typedef int wchar_t;
      |             ^~~~~~~
```
2025-11-13 04:44:00 +09:00
Yu Watanabe
fb33d20c07 musl: meson: explicitly set _LARGEFILE64_SOURCE
glibc sets it when _GNU_SOURCE is defined, however, musl does not.
Let's explicitly define it to make getdents64() and struct dirent64
available even when building with musl.
2025-11-13 04:44:00 +09:00
Yu Watanabe
bd19ffd9cb musl: meson: explicitly link with libintl when necessary
On some musl based distributions dgettext() may be provided by libintl.so.
Hence, we need to add dependency in that case.
2025-11-13 04:44:00 +09:00
Yu Watanabe
a4c45279a7 musl: meson: allow to choose libc implementation
This also introduces skeleton directories for storing musl specific code.
2025-11-13 04:44:00 +09:00
Daan De Meyer
e182d66faa test-varlink: Migrate to new assertion macros 2025-11-12 19:59:05 +01:00
Daan De Meyer
3150c34270 run0: Never ask --empower sessions for polkit auth
A --empower session is effectively root without being UID 0, so it
doesn't make sense to enforce polkit authentication in those. Let's
add the empower group, add --empower sessions to that group and ship
a polkit rule to skip authentication for all users in the empower
group.

(As a side-effect this will also allow users to add themselves to this
group outside of 'run0 --empower' to mimick NOPASSWD from sudo)
2025-11-12 19:55:35 +01:00
Yu Watanabe
f8a3ae1be6 musl: test-time-util: skip parsing back when currently unused timezone is set 2025-11-13 03:13:59 +09:00
Yu Watanabe
8d5b306bb9 musl: time-util: skip tm.tm_wday check
musl does not set tm_wday when it is explicitly requested.
The check is not necessary at all, it is just for safety.
Let's skip it when built with musl.
2025-11-13 03:13:59 +09:00
Yu Watanabe
6431f2e072 musl: time-util: introduce get_tzname() helper function
musl leaves the DST timezone name unset if there is no DST.
The helper function maps that back to no DST.
2025-11-13 03:13:55 +09:00
Yu Watanabe
3ac4d68498 musl: time-util: make parse_gmtoff() accept extended timezone offset format
musl v1.2.5 does not support %z specifier in strptime(). Since
fced99e93d
%z is supported, but it only supports strict RFC-822/ISO 8601 format,
that is, 4 digits with sign (e.g. +0900 or -1400), but does not support
extended format: 2 digits or colon separated 4 digits (e.g. +09 or -14:00).
Let's add fallback logic to make it support the extended timezone spec.
2025-11-13 02:40:32 +09:00
Daan De Meyer
d82d500b40
Migrate various tests to new assertion macros (#39691)
Split out of #39608
2025-11-12 16:17:38 +01:00
Mike Yuan
8be3780699
core/dbus-service: validate type of received ExecContext fds 2025-11-12 15:44:51 +01:00
Mike Yuan
51bb3a0932
logind-session-dbus: use fd_vet_accmode() where appropriate 2025-11-12 15:44:50 +01:00
Mike Yuan
2c5d73660e
test-fd-util: add unit test for fd_vet_accmode()
Co-authored-by: Chris Down <chris@chrisdown.name>
2025-11-12 15:44:50 +01:00
Mike Yuan
7cf4f07567
fd-util: introduce fd_vet_accmode()
Inspired by #39674
2025-11-12 15:44:50 +01:00
Yu Watanabe
733c5c98ad sd-journal: resolve paths passed to sd_journal_open_files() and friends
Fixes #38667.
2025-11-12 15:18:40 +01:00
Yu Watanabe
09811f99f4 sd-journal: use -EBADF for invalidated file descriptor 2025-11-12 15:18:40 +01:00
Daan De Meyer
e81dc81a5c test-rm-rf: Migrate to new assertion macros 2025-11-12 14:24:14 +01:00
Daan De Meyer
13027e040a test-bus-chat: Migrate to TEST() and new assertion macros
- Also contains various other small cleanups
2025-11-12 14:24:14 +01:00
Daan De Meyer
e59ed77e13 test-bus-watch-bind: Migrate to new assertion macros 2025-11-12 14:24:14 +01:00
Daan De Meyer
0fd7280fbc test-bus-server: Migrate to new assertion macros 2025-11-12 14:24:14 +01:00
Daan De Meyer
4fd7bec2c9 test-bus-peersockaddr: Migrate to new assertion macros 2025-11-12 14:24:12 +01:00
Daan De Meyer
491706368b test-bus-objects: Migrate to new assertion macros 2025-11-12 14:20:24 +01:00
Daan De Meyer
6b136bcd02 test-event: Migrate to new assertion macros 2025-11-12 14:20:24 +01:00
Daan De Meyer
0d21ab7377 tests: Return result from some ASSERT() macros 2025-11-12 14:20:24 +01:00
36 changed files with 1266 additions and 1039 deletions

View File

@ -295,8 +295,9 @@
<listitem><para>If specified, run0 will elevate the privileges of the selected user (using
<option>--user=</option>) or the current user if no user is explicitly selected. Currently this means
we give the user all available capabilities, but other privileges may be granted in the future as
well when using this option.</para>
we give the invoked process all available capabilities and add the the <literal>empower</literal>
group as a supplemental group (for which all polkit actions are allowed by default), but other
privileges may be granted in the future as well when using this option.</para>
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>

View File

@ -72,7 +72,10 @@ conf.set10('SD_BOOT', false)
# Create a title-less summary section early, so it ends up first in the output.
# More items are added later after they have been detected.
summary({'build mode' : get_option('mode')})
summary({
'libc' : get_option('libc'),
'build mode' : get_option('mode'),
})
#####################################################################
@ -557,6 +560,10 @@ conf.set10('HAVE_WARNING_ZERO_AS_NULL_POINTER_CONSTANT', have)
conf.set('_GNU_SOURCE', 1)
conf.set('__SANE_USERSPACE_TYPES__', true)
# glibc always defines _LARGEFILE64_SOURCE when _GNU_SOURCE is set, but musl does not do that,
# and it is necessary for making getdents64() and struct dirent64 exist.
conf.set('_LARGEFILE64_SOURCE', 1)
conf.set('SIZEOF_DEV_T', cc.sizeof('dev_t', prefix : '#include <sys/types.h>'))
conf.set('SIZEOF_INO_T', cc.sizeof('ino_t', prefix : '#include <sys/types.h>'))
conf.set('SIZEOF_RLIM_T', cc.sizeof('rlim_t', prefix : '#include <sys/resource.h>'))
@ -572,6 +579,7 @@ assert(long_max > 100000)
conf.set_quoted('LONG_MAX_STR', f'@long_max@')
foreach ident : [
['renameat2', '''#include <stdio.h>'''], # since musl-1.2.6
['set_mempolicy', '''#include <sys/syscall.h>'''], # declared at numaif.h provided by libnuma, which we do not use
['get_mempolicy', '''#include <sys/syscall.h>'''], # declared at numaif.h provided by libnuma, which we do not use
['strerrorname_np', '''#include <string.h>'''], # since glibc-2.32
@ -700,6 +708,8 @@ foreach header : [
endforeach
foreach header : [
'gshadow.h',
'nss.h',
'sys/sdt.h',
'threads.h',
'valgrind/memcheck.h',
@ -710,6 +720,20 @@ foreach header : [
cc.has_header(header))
endforeach
foreach ident : [
['NI_IDN', 'netdb.h']
]
if meson.version().version_compare('>=1.3.0')
have = cc.has_define(ident[0],
prefix : '''#include <@0@>'''.format(ident[1]),
args : '-D_GNU_SOURCE')
else
have = cc.has_header_symbol(ident[1], ident[0])
endif
conf.set10('HAVE_' + ident[0], have)
endforeach
#####################################################################
fallback_hostname = get_option('fallback-hostname')
@ -886,6 +910,7 @@ foreach option : ['adm-gid',
'clock-gid',
'dialout-gid',
'disk-gid',
'empower-gid',
'input-gid',
'kmem-gid',
'kvm-gid',
@ -1001,6 +1026,22 @@ librt = cc.find_library('rt')
libm = cc.find_library('m')
libdl = cc.find_library('dl')
# On some distributions that use musl (e.g. Alpine), libintl.h may be provided by gettext rather than musl.
# In that case, we need to explicitly link with libintl.so.
if cc.has_function('dgettext',
prefix : '''#include <libintl.h>''',
args : '-D_GNU_SOURCE')
libintl = []
else
libintl = cc.find_library('intl')
if not cc.has_function('dgettext',
prefix : '''#include <libintl.h>''',
args : '-D_GNU_SOURCE',
dependencies : libintl)
error('dgettext() not found')
endif
endif
# On some architectures, libatomic is required. But on some installations,
# it is found, but actual linking fails. So let's try to use it opportunistically.
# If it is installed, but not needed, it will be dropped because of --as-needed.
@ -1602,52 +1643,60 @@ conf.set10('ENABLE_NSPAWN', feature.allowed())
conf.set10('DEFAULT_MOUNTFSD_TRUSTED_DIRECTORIES', get_option('default-mountfsd-trusted-directories'))
foreach term : ['analyze',
'backlight',
'binfmt',
'compat-mutable-uid-boundaries',
'coredump',
'efi',
'environment-d',
'firstboot',
'gshadow',
'hibernate',
'hostnamed',
'hwdb',
'idn',
'ima',
'ipe',
'initrd',
'kernel-install',
'ldconfig',
'localed',
'logind',
'machined',
'mountfsd',
'networkd',
'nsresourced',
'nss-myhostname',
'nss-systemd',
'oomd',
'portabled',
'pstore',
'quotacheck',
'randomseed',
'resolve',
'rfkill',
'smack',
'sysext',
'sysusers',
'timedated',
'timesyncd',
'tmpfiles',
'tpm',
'userdb',
'utmp',
'vconsole',
'xdg-autostart']
have = get_option(term)
name = 'ENABLE_' + term.underscorify().to_upper()
foreach tuple : [
['analyze'],
['backlight'],
['binfmt'],
['compat-mutable-uid-boundaries'],
['coredump'],
['efi'],
['environment-d'],
['firstboot'],
['gshadow', conf.get('HAVE_GSHADOW_H') == 1, 'gshadow.h not found'],
['hibernate'],
['hostnamed'],
['hwdb'],
['idn', conf.get('HAVE_NI_IDN') == 1, 'NI_IDN is not defined'],
['ima'],
['ipe'],
['initrd'],
['kernel-install'],
['ldconfig'],
['localed'],
['logind'],
['machined'],
['mountfsd'],
['networkd'],
['nsresourced'],
['nss-myhostname', conf.get('HAVE_NSS_H') == 1, 'nss.h not found'],
['nss-systemd', conf.get('HAVE_NSS_H') == 1, 'nss.h not found'],
['oomd'],
['portabled'],
['pstore'],
['quotacheck'],
['randomseed'],
['resolve'],
['rfkill'],
['smack'],
['sysext'],
['sysusers'],
['timedated'],
['timesyncd'],
['tmpfiles'],
['tpm'],
['utmp'],
['userdb'],
['vconsole'],
['xdg-autostart'],
]
have = get_option(tuple[0])
if have and tuple.length() >= 3 and not tuple[1]
warning('@0@ support is requested but @1@, disabling it'.format(tuple[0], tuple[2]))
have = false
endif
name = 'ENABLE_' + tuple[0].underscorify().to_upper()
conf.set10(name, have)
endforeach
@ -1656,11 +1705,16 @@ enable_sysusers = conf.get('ENABLE_SYSUSERS') == 1
foreach tuple : [['nss-mymachines', 'machined'],
['nss-resolve', 'resolve']]
want = get_option(tuple[0])
if want.allowed()
have = get_option(tuple[1])
if want.enabled() and not have
if want.enabled()
if conf.get('HAVE_NSS_H') != 1
error('@0@ is requested but nss.h not found'.format(tuple[0]))
endif
if not get_option(tuple[1])
error('@0@ is requested but @1@ is disabled'.format(tuple[0], tuple[1]))
endif
have = true
elif want.allowed()
have = get_option(tuple[1]) and conf.get('HAVE_NSS_H') == 1
else
have = false
endif
@ -2068,6 +2122,15 @@ system_includes = [
),
]
if get_option('libc') == 'musl'
system_include_args = [
'-isystem', meson.project_build_root() / 'src/include/musl',
'-isystem', meson.project_source_root() / 'src/include/musl',
] + system_include_args
system_includes += include_directories('src/include/musl', is_system : true)
endif
basic_includes = [
include_directories(
'src/basic',

View File

@ -295,6 +295,8 @@ option('dialout-gid', type : 'integer', value : 0,
description : 'soft-static allocation for the "dialout" group')
option('disk-gid', type : 'integer', value : 0,
description : 'soft-static allocation for the "disk" group')
option('empower-gid', type : 'integer', value : 0,
description : 'soft-static allocation for the "empower" group')
option('input-gid', type : 'integer', value : 0,
description : 'soft-static allocation for the "input" group')
option('kmem-gid', type : 'integer', value : 0,
@ -400,6 +402,8 @@ option('ima', type : 'boolean',
option('ipe', type : 'boolean',
description : 'IPE support')
option('libc', type : 'combo', choices : ['glibc', 'musl'],
description : 'libc implementation to be used')
option('acl', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
description : 'libacl support')
option('audit', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },

View File

@ -960,6 +960,41 @@ int fd_is_opath(int fd) {
return FLAGS_SET(r, O_PATH);
}
int fd_vet_accmode(int fd, int mode) {
int flags;
/* Check if fd is opened with desired access mode.
*
* Returns > 0 on strict match, == 0 if opened for both reading and writing (partial match),
* -EPROTOTYPE otherwise. O_PATH fds are always refused with -EBADFD.
*
* Note that while on O_DIRECTORY -EISDIR will be returned, this should not be relied upon as
* the flag might not have been specified when open() was called originally. */
assert(fd >= 0);
assert(IN_SET(mode, O_RDONLY, O_WRONLY, O_RDWR));
flags = fcntl(fd, F_GETFL);
if (flags < 0)
return -errno;
if (FLAGS_SET(flags, O_DIRECTORY))
return -EISDIR;
if (FLAGS_SET(flags, O_PATH))
return -EBADFD;
flags &= O_ACCMODE_STRICT;
if (flags == mode)
return 1;
if (flags == O_RDWR)
return 0;
return -EPROTOTYPE;
}
int fd_verify_safe_flags_full(int fd, int extra_flags) {
int flags, unexpected_flags;

View File

@ -151,6 +151,7 @@ int fd_reopen_propagate_append_and_position(int fd, int flags);
int fd_reopen_condition(int fd, int flags, int mask, int *ret_new_fd);
int fd_is_opath(int fd);
int fd_vet_accmode(int fd, int mode);
int fd_verify_safe_flags_full(int fd, int extra_flags);
static inline int fd_verify_safe_flags(int fd) {

View File

@ -13,6 +13,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "hexdecoct.h"
#include "io-util.h"
#include "log.h"
#include "parse-util.h"
@ -624,16 +625,94 @@ char* format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
return buf;
}
const char* get_tzname(bool dst) {
/* musl leaves the DST timezone name unset if there is no DST, map this back to no DST */
if (dst && isempty(tzname[1]))
dst = false;
return empty_to_null(tzname[dst]);
}
int parse_gmtoff(const char *t, long *ret) {
int r;
assert(t);
struct tm tm;
const char *k = strptime(t, "%z", &tm);
if (!k || *k != '\0')
if (k && *k == '\0') {
/* Success! */
if (ret)
*ret = tm.tm_gmtoff;
return 0;
}
/* musl v1.2.5 does not support %z specifier in strptime(). Since
* https://github.com/kraj/musl/commit/fced99e93daeefb0192fd16304f978d4401d1d77
* %z is supported, but it only supports strict RFC-822/ISO 8601 format, that is, 4 digits with sign
* (e.g. +0900 or -1400), but does not support extended format: 2 digits or colon separated 4 digits
* (e.g. +09 or -14:00). Let's add fallback logic to make it support the extended timezone spec. */
bool positive;
switch (*t) {
case '+':
positive = true;
break;
case '-':
positive = false;
break;
default:
return -EINVAL;
}
t++;
r = undecchar(*t);
if (r < 0)
return r;
usec_t u = r * 10 * USEC_PER_HOUR;
t++;
r = undecchar(*t);
if (r < 0)
return r;
u += r * USEC_PER_HOUR;
t++;
if (*t == '\0') /* 2 digits case */
goto finalize;
if (*t == ':') /* skip colon */
t++;
r = undecchar(*t);
if (r < 0)
return r;
if (r >= 6) /* refuse minutes equal to or larger than 60 */
return -EINVAL;
if (ret)
*ret = tm.tm_gmtoff;
u += r * 10 * USEC_PER_MINUTE;
t++;
r = undecchar(*t);
if (r < 0)
return r;
u += r * USEC_PER_MINUTE;
t++;
if (*t != '\0')
return -EINVAL;
finalize:
if (u > USEC_PER_DAY) /* refuse larger than one day */
return -EINVAL;
if (ret) {
long gmtoff = u / USEC_PER_SEC;
*ret = positive ? gmtoff : -gmtoff;
}
return 0;
}
@ -810,7 +889,11 @@ static int parse_timestamp_impl(
if (!k || *k != ' ')
continue;
#ifdef __GLIBC__
/* musl does not set tm_wday field and set 0 unless it is explicitly requested by %w or so.
* In the below, let's only check tm_wday field only when built with glibc. */
weekday = day->nr;
#endif
t = k + 1;
break;
}
@ -1007,10 +1090,7 @@ int parse_timestamp(const char *t, usec_t *ret) {
* not follow the timezone change in the current area. */
tzset();
for (int j = 0; j <= 1; j++) {
if (isempty(tzname[j]))
continue;
if (!streq(tz, tzname[j]))
if (!streq_ptr(tz, get_tzname(j)))
continue;
/* The specified timezone matches tzname[] of the local timezone. */

View File

@ -149,6 +149,7 @@ static inline char* format_timestamp(char *buf, size_t l, usec_t t) {
#define FORMAT_TIMESTAMP_STYLE(t, style) \
format_timestamp_style((char[FORMAT_TIMESTAMP_MAX]){}, FORMAT_TIMESTAMP_MAX, t, style)
const char* get_tzname(bool dst);
int parse_gmtoff(const char *t, long *ret);
int parse_timestamp(const char *t, usec_t *ret);

View File

@ -182,6 +182,11 @@ if get_option('mode') == 'developer' and get_option('debug')
efi_c_args += '-DEFI_DEBUG'
endif
if get_option('libc') == 'musl'
# To make musl not define wchar_t as int, rather than short.
efi_c_args += '-D__DEFINED_wchar_t'
endif
efi_c_ld_args = [
'-nostdlib',
'-static-pie',

View File

@ -28,6 +28,7 @@
#include "selinux-access.h"
#include "service.h"
#include "signal-util.h"
#include "stat-util.h"
#include "string-util.h"
#include "unit.h"
@ -488,21 +489,32 @@ static int bus_set_transient_exit_status(
static int bus_set_transient_exec_context_fd(
Unit *u,
const char *name,
int *p,
bool *b,
int verify_mode,
sd_bus_message *message,
UnitWriteFlags flags,
sd_bus_error *error) {
int fd, r;
assert(name);
assert(p);
assert(b);
assert(verify_mode == O_DIRECTORY || (verify_mode & ~O_ACCMODE_STRICT) == 0);
r = sd_bus_message_read(message, "h", &fd);
if (r < 0)
return r;
if (verify_mode == O_DIRECTORY)
r = fd_verify_directory(fd);
else
r = fd_vet_accmode(fd, verify_mode);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "%s passed is of incompatible type: %m", name);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
int copy;
@ -689,13 +701,13 @@ static int bus_service_set_transient_property(
return bus_set_transient_exec_command(u, name, &s->exec_command[ci], message, flags, error);
if (streq(name, "StandardInputFileDescriptor"))
return bus_set_transient_exec_context_fd(u, &s->stdin_fd, &s->exec_context.stdio_as_fds, message, flags, error);
return bus_set_transient_exec_context_fd(u, name, &s->stdin_fd, &s->exec_context.stdio_as_fds, O_RDONLY, message, flags, error);
if (streq(name, "StandardOutputFileDescriptor"))
return bus_set_transient_exec_context_fd(u, &s->stdout_fd, &s->exec_context.stdio_as_fds, message, flags, error);
return bus_set_transient_exec_context_fd(u, name, &s->stdout_fd, &s->exec_context.stdio_as_fds, O_WRONLY, message, flags, error);
if (streq(name, "StandardErrorFileDescriptor"))
return bus_set_transient_exec_context_fd(u, &s->stderr_fd, &s->exec_context.stdio_as_fds, message, flags, error);
return bus_set_transient_exec_context_fd(u, name, &s->stderr_fd, &s->exec_context.stdio_as_fds, O_WRONLY, message, flags, error);
if (streq(name, "OpenFile")) {
const char *path, *fdname;
@ -802,7 +814,7 @@ static int bus_service_set_transient_property(
}
if (streq(name, "RootDirectoryFileDescriptor"))
return bus_set_transient_exec_context_fd(u, &s->root_directory_fd, &s->exec_context.root_directory_as_fd, message, flags, error);
return bus_set_transient_exec_context_fd(u, name, &s->root_directory_fd, &s->exec_context.root_directory_as_fd, O_DIRECTORY, message, flags, error);
return 0;
}

View File

@ -3208,7 +3208,7 @@ static int manager_dispatch_timezone_change(
/* Read the new timezone */
tzset();
log_debug("Timezone has been changed (now: %s).", tzname[daylight]);
log_debug("Timezone has been changed (now: %s).", get_tzname(daylight));
HASHMAP_FOREACH(u, m->units)
if (UNIT_VTABLE(u)->timezone_change)

View File

@ -115,6 +115,7 @@ modules += [
'sources' : pam_systemd_home_sources,
'dependencies' : [
libcrypt,
libintl,
libpam_misc,
libpam,
threads,

13
src/include/musl/stdio.h Normal file
View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include_next <stdio.h>
#if !HAVE_RENAMEAT2
# define RENAME_NOREPLACE (1 << 0)
# define RENAME_EXCHANGE (1 << 1)
# define RENAME_WHITEOUT (1 << 2)
int missing_renameat2(int __oldfd, const char *__old, int __newfd, const char *__new, unsigned __flags);
# define renameat2 missing_renameat2
#endif

View File

@ -16,6 +16,8 @@ libc_wrapper_sources = files(
'xattr.c',
)
subdir('musl')
sources += libc_wrapper_sources
libc_wrapper_static = static_library(

View File

@ -0,0 +1,9 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if get_option('libc') != 'musl'
subdir_done()
endif
libc_wrapper_sources += files(
'stdio.c',
)

11
src/libc/musl/stdio.c Normal file
View File

@ -0,0 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
#if !HAVE_RENAMEAT2
int missing_renameat2(int __oldfd, const char *__old, int __newfd, const char *__new, unsigned __flags) {
return syscall(__NR_renameat2, __oldfd, __old, __newfd, __new, __flags);
}
#endif

View File

@ -45,13 +45,13 @@ static int object_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_
return 0;
}
static int server_init(sd_bus **ret_bus) {
_cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
static int server_init(sd_bus **ret) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
const char *unique, *desc;
sd_id128_t id;
int r;
assert_se(ret_bus);
assert(ret);
r = sd_bus_open_user_with_description(&bus, "my bus!");
if (r < 0)
@ -65,8 +65,8 @@ static int server_init(sd_bus **ret_bus) {
if (r < 0)
return log_error_errno(r, "Failed to get unique name: %m");
assert_se(sd_bus_get_description(bus, &desc) >= 0);
assert_se(streq(desc, "my bus!"));
ASSERT_OK(sd_bus_get_description(bus, &desc));
ASSERT_STREQ(desc, "my bus!");
log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
log_info("Unique ID: %s", unique);
@ -94,12 +94,11 @@ static int server_init(sd_bus **ret_bus) {
bus_match_dump(stdout, &bus->match_callbacks, 0);
*ret_bus = TAKE_PTR(bus);
*ret = TAKE_PTR(bus);
return 0;
}
static int server(sd_bus *_bus) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = ASSERT_PTR(_bus);
static int server(sd_bus *bus) {
bool client1_gone = false, client2_gone = false;
int r;
@ -250,7 +249,7 @@ static void* client1(void *p) {
goto finish;
}
assert_se(streq(hello, "hello"));
ASSERT_STREQ(hello, "hello");
if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
r = log_error_errno(errno, "Failed to allocate pipe: %m");
@ -494,44 +493,30 @@ finish:
return INT_TO_PTR(r);
}
int main(int argc, char *argv[]) {
TEST(chat) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
pthread_t c1, c2;
sd_bus *bus;
void *p;
int q, r;
int r;
test_setup_logging(LOG_INFO);
r = server_init(&bus);
if (r < 0)
return log_tests_skipped("Failed to connect to bus");
return (void) log_tests_skipped_errno(r, "Failed to connect to bus: %m");
log_info("Initialized...");
r = pthread_create(&c1, NULL, client1, bus);
if (r != 0)
return EXIT_FAILURE;
r = pthread_create(&c2, NULL, client2, bus);
if (r != 0)
return EXIT_FAILURE;
ASSERT_OK(-pthread_create(&c1, NULL, client1, NULL));
ASSERT_OK(-pthread_create(&c2, NULL, client2, NULL));
r = server(bus);
q = pthread_join(c1, &p);
if (q != 0)
return EXIT_FAILURE;
if (PTR_TO_INT(p) < 0)
return EXIT_FAILURE;
q = pthread_join(c2, &p);
if (q != 0)
return EXIT_FAILURE;
if (PTR_TO_INT(p) < 0)
return EXIT_FAILURE;
if (r < 0)
return EXIT_FAILURE;
return EXIT_SUCCESS;
ASSERT_OK(-pthread_join(c1, &p));
ASSERT_OK(PTR_TO_INT(p));
ASSERT_OK(-pthread_join(c2, &p));
ASSERT_OK(PTR_TO_INT(p));
ASSERT_OK(r);
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -23,13 +23,10 @@ static int something_handler(sd_bus_message *m, void *userdata, sd_bus_error *re
struct context *c = userdata;
const char *s;
char *n = NULL;
int r;
r = sd_bus_message_read(m, "s", &s);
assert_se(r > 0);
ASSERT_OK_POSITIVE(sd_bus_message_read(m, "s", &s));
n = strjoin("<<<", s, ">>>");
assert_se(n);
ASSERT_NOT_NULL(n = strjoin("<<<", s, ">>>"));
free(c->something);
c->something = n;
@ -37,36 +34,31 @@ static int something_handler(sd_bus_message *m, void *userdata, sd_bus_error *re
log_info("AlterSomething() called, got %s, returning %s", s, n);
/* This should fail, since the return type doesn't match */
assert_se(sd_bus_reply_method_return(m, "u", 4711) == -ENOMSG);
ASSERT_ERROR(sd_bus_reply_method_return(m, "u", 4711), ENOMSG);
r = sd_bus_reply_method_return(m, "s", n);
assert_se(r >= 0);
ASSERT_OK(sd_bus_reply_method_return(m, "s", n));
return 1;
}
static int exit_handler(sd_bus_message *m, void *userdata, sd_bus_error *reterr_error) {
struct context *c = userdata;
int r;
c->quit = true;
log_info("Exit called");
r = sd_bus_reply_method_return(m, "");
assert_se(r >= 0);
ASSERT_OK(sd_bus_reply_method_return(m, ""));
return 1;
}
static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *reterr_error) {
struct context *c = userdata;
int r;
log_info("property get for %s called, returning \"%s\".", property, c->something);
r = sd_bus_message_append(reply, "s", c->something);
assert_se(r >= 0);
ASSERT_OK(sd_bus_message_append(reply, "s", c->something));
return 1;
}
@ -75,15 +67,12 @@ static int set_handler(sd_bus *bus, const char *path, const char *interface, con
struct context *c = userdata;
const char *s;
char *n;
int r;
log_info("property set for %s called", property);
r = sd_bus_message_read(value, "s", &s);
assert_se(r >= 0);
ASSERT_OK(sd_bus_message_read(value, "s", &s));
n = strdup(s);
assert_se(n);
ASSERT_NOT_NULL(n = strdup(s));
free(c->something);
c->something = n;
@ -94,87 +83,67 @@ static int set_handler(sd_bus *bus, const char *path, const char *interface, con
static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *reterr_error) {
_cleanup_free_ char *s = NULL;
const char *x;
int r;
assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0);
r = sd_bus_message_append(reply, "s", s);
assert_se(r >= 0);
ASSERT_OK(asprintf(&s, "object %p, path %s", userdata, path));
ASSERT_OK(sd_bus_message_append(reply, "s", s));
assert_se(x = startswith(path, "/value/"));
ASSERT_NOT_NULL(x = startswith(path, "/value/"));
assert_se(PTR_TO_UINT(userdata) == 30);
ASSERT_EQ(PTR_TO_UINT(userdata), 30U);
return 1;
}
static int notify_test(sd_bus_message *m, void *userdata, sd_bus_error *reterr_error) {
int r;
ASSERT_OK(sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL));
assert_se(sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_reply_method_return(m, NULL));
return 1;
}
static int notify_test2(sd_bus_message *m, void *userdata, sd_bus_error *reterr_error) {
int r;
ASSERT_OK(sd_bus_emit_properties_changed_strv(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", NULL));
assert_se(sd_bus_emit_properties_changed_strv(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", NULL) >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_reply_method_return(m, NULL));
return 1;
}
static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error *reterr_error) {
int r;
ASSERT_OK(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL));
assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_reply_method_return(m, NULL));
return 1;
}
static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_error *reterr_error) {
int r;
ASSERT_OK(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL));
assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_reply_method_return(m, NULL));
return 1;
}
static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *reterr_error) {
int r;
ASSERT_OK(sd_bus_emit_object_added(sd_bus_message_get_bus(m), "/value/a/x"));
assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), "/value/a/x") >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_reply_method_return(m, NULL));
return 1;
}
static int emit_object_with_manager_added(sd_bus_message *m, void *userdata, sd_bus_error *reterr_error) {
assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), "/value/a") >= 0);
ASSERT_OK(sd_bus_emit_object_added(sd_bus_message_get_bus(m), "/value/a"));
return ASSERT_SE_NONNEG(sd_bus_reply_method_return(m, NULL));
return ASSERT_OK(sd_bus_reply_method_return(m, NULL));
}
static int emit_object_removed(sd_bus_message *m, void *userdata, sd_bus_error *reterr_error) {
int r;
ASSERT_OK(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), "/value/a/x"));
assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), "/value/a/x") >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_reply_method_return(m, NULL));
return 1;
}
@ -210,7 +179,7 @@ static const sd_bus_vtable vtable2[] = {
static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *reterr_error) {
if (object_path_startswith("/value", path))
assert_se(*nodes = strv_new("/value/c", "/value/b", "/value/a"));
ASSERT_NOT_NULL(*nodes = strv_new("/value/c", "/value/b", "/value/a"));
return 1;
}
@ -218,7 +187,7 @@ static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, ch
static int enumerator2_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *reterr_error) {
if (object_path_startswith("/value/a", path))
assert_se(*nodes = strv_new("/value/a/z", "/value/a/x", "/value/a/y"));
ASSERT_NOT_NULL(*nodes = strv_new("/value/a/z", "/value/a/x", "/value/a/y"));
return 1;
}
@ -230,9 +199,9 @@ static int enumerator3_callback(sd_bus *bus, const char *path, void *userdata, c
return 1;
for (unsigned i = 10; i < 20; i++)
assert_se(strv_extendf(&v, "/value/b/%u", i) >= 0);
ASSERT_OK(strv_extendf(&v, "/value/b/%u", i));
for (unsigned i = 29; i >= 20; i--)
assert_se(strv_extendf(&v, "/value/b/%u", i) >= 0);
ASSERT_OK(strv_extendf(&v, "/value/b/%u", i));
*nodes = TAKE_PTR(v);
return 1;
@ -246,22 +215,22 @@ static void* server(void *p) {
c->quit = false;
assert_se(sd_id128_randomize(&id) >= 0);
ASSERT_OK(sd_id128_randomize(&id));
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
assert_se(sd_bus_set_server(bus, 1, id) >= 0);
ASSERT_OK(sd_bus_new(&bus));
ASSERT_OK(sd_bus_set_fd(bus, c->fds[0], c->fds[0]));
ASSERT_OK(sd_bus_set_server(bus, 1, id));
assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0);
assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL) >= 0);
assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/b", enumerator3_callback, NULL) >= 0);
assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0);
assert_se(sd_bus_add_object_manager(bus, NULL, "/value/a") >= 0);
ASSERT_OK(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c));
ASSERT_OK(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c));
ASSERT_OK(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)));
ASSERT_OK(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL));
ASSERT_OK(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL));
ASSERT_OK(sd_bus_add_node_enumerator(bus, NULL, "/value/b", enumerator3_callback, NULL));
ASSERT_OK(sd_bus_add_object_manager(bus, NULL, "/value"));
ASSERT_OK(sd_bus_add_object_manager(bus, NULL, "/value/a"));
assert_se(sd_bus_start(bus) >= 0);
ASSERT_OK(sd_bus_start(bus));
log_error("Entering event loop on server");
@ -304,178 +273,147 @@ static int client(struct context *c) {
const char *s;
int r;
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
assert_se(sd_bus_start(bus) >= 0);
ASSERT_OK(sd_bus_new(&bus));
ASSERT_OK(sd_bus_set_fd(bus, c->fds[1], c->fds[1]));
ASSERT_OK(sd_bus_start(bus));
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "NoOperation", &error, NULL, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "NoOperation", &error, NULL, NULL));
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo");
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo"));
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
assert_se(streq(s, "<<<hallo>>>"));
ASSERT_OK(sd_bus_message_read(reply, "s", &s));
ASSERT_STREQ(s, "<<<hallo>>>");
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, "");
assert_se(r < 0);
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
ASSERT_FAIL(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, ""));
ASSERT_TRUE(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
sd_bus_error_free(&error);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, NULL); /* NULL and "" are equivalent */
assert_se(r < 0);
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
ASSERT_FAIL(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, NULL)); /* NULL and "" are equivalent */
ASSERT_TRUE(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
sd_bus_error_free(&error);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo");
assert_se(r < 0);
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS));
ASSERT_FAIL(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo"));
ASSERT_TRUE(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS));
sd_bus_error_free(&error);
r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
assert_se(r >= 0);
ASSERT_OK(sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s"));
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
assert_se(streq(s, "<<<hallo>>>"));
ASSERT_OK(sd_bus_message_read(reply, "s", &s));
ASSERT_STREQ(s, "<<<hallo>>>");
reply = sd_bus_message_unref(reply);
r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test");
assert_se(r >= 0);
ASSERT_OK(sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test"));
r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
assert_se(r >= 0);
ASSERT_OK(sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s"));
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
assert_se(streq(s, "test"));
ASSERT_OK(sd_bus_message_read(reply, "s", &s));
ASSERT_STREQ(s, "test");
reply = sd_bus_message_unref(reply);
r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815);
assert_se(r >= 0);
ASSERT_OK(sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815));
assert_se(c->automatic_integer_property == 815);
ASSERT_EQ(c->automatic_integer_property, 815U);
r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!");
assert_se(r >= 0);
ASSERT_OK(sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!"));
assert_se(streq(c->automatic_string_property, "Du Dödel, Du!"));
ASSERT_STREQ(c->automatic_string_property, "Du Dödel, Du!");
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""));
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
ASSERT_OK(sd_bus_message_read(reply, "s", &s));
fputs(s, stdout);
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL); /* NULL and "" are equivalent */
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL)); /* NULL and "" are equivalent */
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
ASSERT_OK(sd_bus_message_read(reply, "s", &s));
fputs(s, stdout);
reply = sd_bus_message_unref(reply);
r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s");
assert_se(r >= 0);
ASSERT_OK(sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s"));
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
ASSERT_OK(sd_bus_message_read(reply, "s", &s));
log_info("read %s", s);
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL));
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
ASSERT_OK(sd_bus_message_read(reply, "s", &s));
fputs(s, stdout);
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL));
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
ASSERT_OK(sd_bus_message_read(reply, "s", &s));
fputs(s, stdout);
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL));
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
ASSERT_OK(sd_bus_message_read(reply, "s", &s));
fputs(s, stdout);
assert_se(lines = strv_split_newlines(s));
assert_se(strv_contains(lines, " <node name=\"x\"/>"));
assert_se(strv_contains(lines, " <node name=\"y\"/>"));
assert_se(strv_contains(lines, " <node name=\"z\"/>"));
ASSERT_NOT_NULL(lines = strv_split_newlines(s));
ASSERT_TRUE(strv_contains(lines, " <node name=\"x\"/>"));
ASSERT_TRUE(strv_contains(lines, " <node name=\"y\"/>"));
ASSERT_TRUE(strv_contains(lines, " <node name=\"z\"/>"));
lines = strv_free(lines);
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/b", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/b", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL));
r = sd_bus_message_read(reply, "s", &s);
assert_se(r >= 0);
ASSERT_OK(sd_bus_message_read(reply, "s", &s));
fputs(s, stdout);
assert_se(lines = strv_split_newlines(s));
ASSERT_NOT_NULL(lines = strv_split_newlines(s));
for (unsigned i = 10; i < 30; i++) {
_cleanup_free_ char *n = NULL;
assert_se(asprintf(&n, " <node name=\"%u\"/>", i) >= 0);
assert_se(strv_contains(lines, n));
ASSERT_OK(asprintf(&n, " <node name=\"%u\"/>", i));
ASSERT_TRUE(strv_contains(lines, n));
}
lines = strv_free(lines);
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", NULL));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2");
assert_se(r < 0);
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE));
ASSERT_FAIL(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2"));
ASSERT_TRUE(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE));
sd_bus_error_free(&error);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, NULL);
assert_se(r < 0);
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
ASSERT_FAIL(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, NULL));
ASSERT_TRUE(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
sd_bus_error_free(&error);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, NULL));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
/* Check that /value/b does not have ObjectManager interface but /value/a does */
assert_se(sd_bus_message_rewind(reply, 1) > 0);
assert_se(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{oa{sa{sv}}}") > 0);
ASSERT_OK_POSITIVE(sd_bus_message_rewind(reply, 1));
ASSERT_OK_POSITIVE(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{oa{sa{sv}}}"));
unsigned path_count = 0;
while (ASSERT_SE_NONNEG(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "oa{sa{sv}}")) > 0) {
while (ASSERT_OK(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "oa{sa{sv}}")) > 0) {
const char *path = NULL;
assert_se(sd_bus_message_read_basic(reply, 'o', &path) > 0);
ASSERT_OK_POSITIVE(sd_bus_message_read_basic(reply, 'o', &path));
/* Check if the enumerated path is sorted. */
switch (path_count) {
@ -498,154 +436,140 @@ static int client(struct context *c) {
/* Check that there is no object manager interface here */
bool found_object_manager_interface = false;
assert_se(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sa{sv}}") > 0);
while (ASSERT_SE_NONNEG(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sa{sv}")) > 0) {
ASSERT_OK_POSITIVE(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sa{sv}}"));
while (ASSERT_OK(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sa{sv}")) > 0) {
const char *interface_name = NULL;
assert_se(sd_bus_message_read_basic(reply, 's', &interface_name) > 0);
ASSERT_OK_POSITIVE(sd_bus_message_read_basic(reply, 's', &interface_name));
if (streq(interface_name, "org.freedesktop.DBus.ObjectManager"))
found_object_manager_interface = true;
assert_se(sd_bus_message_skip(reply, "a{sv}") >= 0);
assert_se(sd_bus_message_exit_container(reply) >= 0);
ASSERT_OK(sd_bus_message_skip(reply, "a{sv}"));
ASSERT_OK(sd_bus_message_exit_container(reply));
}
assert_se(sd_bus_message_exit_container(reply) >= 0);
ASSERT_OK(sd_bus_message_exit_container(reply));
assert_se(found_object_manager_interface == streq(path, "/value/a"));
ASSERT_EQ(found_object_manager_interface, streq(path, "/value/a"));
assert_se(sd_bus_message_exit_container(reply) >= 0);
ASSERT_OK(sd_bus_message_exit_container(reply));
}
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, NULL));
r = sd_bus_process(bus, &reply);
assert_se(r > 0);
ASSERT_OK_POSITIVE(r = sd_bus_process(bus, &reply));
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
ASSERT_OK_POSITIVE(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest2", &error, NULL, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest2", &error, NULL, NULL));
r = sd_bus_process(bus, &reply);
assert_se(r > 0);
ASSERT_OK_POSITIVE(r = sd_bus_process(bus, &reply));
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
ASSERT_OK_POSITIVE(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, NULL));
r = sd_bus_process(bus, &reply);
assert_se(r > 0);
ASSERT_OK_POSITIVE(r = sd_bus_process(bus, &reply));
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
ASSERT_OK_POSITIVE(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, NULL));
r = sd_bus_process(bus, &reply);
assert_se(r > 0);
ASSERT_OK_POSITIVE(r = sd_bus_process(bus, &reply));
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
ASSERT_OK_POSITIVE(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectAdded", &error, NULL, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectAdded", &error, NULL, NULL));
r = sd_bus_process(bus, &reply);
assert_se(r > 0);
ASSERT_OK_POSITIVE(r = sd_bus_process(bus, &reply));
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
ASSERT_OK_POSITIVE(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
/* Check if /value/a/x does not have org.freedesktop.DBus.ObjectManager */
assert_se(sd_bus_message_rewind(reply, 1) >= 0);
ASSERT_OK(sd_bus_message_rewind(reply, 1));
const char* should_be_value_a_x = NULL;
assert_se(sd_bus_message_read_basic(reply, 'o', &should_be_value_a_x) > 0);
assert_se(streq(should_be_value_a_x, "/value/a/x"));
assert_se(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sa{sv}}") > 0);
while (ASSERT_SE_NONNEG(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sa{sv}")) > 0) {
ASSERT_OK_POSITIVE(sd_bus_message_read_basic(reply, 'o', &should_be_value_a_x));
ASSERT_STREQ(should_be_value_a_x, "/value/a/x");
ASSERT_OK_POSITIVE(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sa{sv}}"));
while (ASSERT_OK(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sa{sv}")) > 0) {
const char* interface_name = NULL;
assert_se(sd_bus_message_read_basic(reply, 's', &interface_name) > 0);
ASSERT_OK_POSITIVE(sd_bus_message_read_basic(reply, 's', &interface_name));
assert(!streq(interface_name, "org.freedesktop.DBus.ObjectManager"));
ASSERT_FALSE(streq(interface_name, "org.freedesktop.DBus.ObjectManager"));
assert_se(sd_bus_message_skip(reply, "a{sv}") >= 0);
ASSERT_OK(sd_bus_message_skip(reply, "a{sv}"));
assert_se(sd_bus_message_exit_container(reply) >= 0);
ASSERT_OK(sd_bus_message_exit_container(reply));
}
reply = sd_bus_message_unref(reply);
assert_se(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectWithManagerAdded", &error, NULL, NULL) >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectWithManagerAdded", &error, NULL, NULL));
assert_se(sd_bus_process(bus, &reply) > 0);
ASSERT_OK_POSITIVE(sd_bus_process(bus, &reply));
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
ASSERT_OK_POSITIVE(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
/* Check if /value/a has org.freedesktop.DBus.ObjectManager */
assert_se(sd_bus_message_rewind(reply, 1) >= 0);
ASSERT_OK(sd_bus_message_rewind(reply, 1));
const char* should_be_value_a = NULL;
bool found_object_manager = false;
assert_se(sd_bus_message_read_basic(reply, 'o', &should_be_value_a) > 0);
assert_se(streq(should_be_value_a, "/value/a"));
assert_se(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sa{sv}}") > 0);
while (ASSERT_SE_NONNEG(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sa{sv}")) > 0) {
ASSERT_OK_POSITIVE(sd_bus_message_read_basic(reply, 'o', &should_be_value_a));
ASSERT_STREQ(should_be_value_a, "/value/a");
ASSERT_OK_POSITIVE(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sa{sv}}"));
while (ASSERT_OK(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sa{sv}")) > 0) {
const char* interface_name = NULL;
assert_se(sd_bus_message_read_basic(reply, 's', &interface_name));
ASSERT_OK_POSITIVE(sd_bus_message_read_basic(reply, 's', &interface_name));
if (streq(interface_name, "org.freedesktop.DBus.ObjectManager")) {
found_object_manager = true;
break;
}
assert_se(sd_bus_message_skip(reply, "a{sv}") >= 0);
ASSERT_OK(sd_bus_message_skip(reply, "a{sv}"));
assert_se(sd_bus_message_exit_container(reply) >= 0);
ASSERT_OK(sd_bus_message_exit_container(reply));
}
assert_se(found_object_manager);
ASSERT_TRUE(found_object_manager);
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectRemoved", &error, NULL, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectRemoved", &error, NULL, NULL));
r = sd_bus_process(bus, &reply);
assert_se(r > 0);
ASSERT_OK_POSITIVE(r = sd_bus_process(bus, &reply));
assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
ASSERT_OK_POSITIVE(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
/* Check if /value/a/x does not have org.freedesktop.DBus.ObjectManager */
assert_se(sd_bus_message_rewind(reply, 1) >= 0);
ASSERT_OK(sd_bus_message_rewind(reply, 1));
should_be_value_a_x = NULL;
assert_se(sd_bus_message_read_basic(reply, 'o', &should_be_value_a_x) > 0);
assert_se(streq(should_be_value_a_x, "/value/a/x"));
assert_se(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s") > 0);
ASSERT_OK_POSITIVE(sd_bus_message_read_basic(reply, 'o', &should_be_value_a_x));
ASSERT_STREQ(should_be_value_a_x, "/value/a/x");
ASSERT_OK_POSITIVE(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s"));
const char* deleted_interface_name = NULL;
while (ASSERT_SE_NONNEG(sd_bus_message_read_basic(reply, 's', &deleted_interface_name)) > 0) {
assert(!streq(deleted_interface_name, "org.freedesktop.DBus.ObjectManager"));
}
assert_se(sd_bus_message_exit_container(reply) >= 0);
while (ASSERT_OK(sd_bus_message_read_basic(reply, 's', &deleted_interface_name)))
ASSERT_FALSE(streq(deleted_interface_name, "org.freedesktop.DBus.ObjectManager"));
ASSERT_OK(sd_bus_message_exit_container(reply));
reply = sd_bus_message_unref(reply);
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, NULL));
sd_bus_flush(bus);
@ -661,9 +585,9 @@ int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
c.automatic_integer_property = 4711;
assert_se(c.automatic_string_property = strdup("dudeldu"));
ASSERT_NOT_NULL(c.automatic_string_property = strdup("dudeldu"));
assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds));
r = pthread_create(&s, NULL, server, &c);
if (r != 0)

View File

@ -14,8 +14,8 @@
#include "user-util.h"
static bool gid_list_contained(const gid_t *a, size_t n, const gid_t *b, size_t m) {
assert_se(a || n == 0);
assert_se(b || m == 0);
ASSERT_TRUE(a || n == 0);
ASSERT_TRUE(b || m == 0);
/* Checks if every entry in a[] is also in b[] */
@ -46,77 +46,70 @@ static void* server(void *p) {
sd_id128_t id;
int r;
assert_se(sd_id128_randomize(&id) >= 0);
ASSERT_OK(sd_id128_randomize(&id));
fd = accept4(listen_fd, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK);
assert_se(fd >= 0);
ASSERT_OK_ERRNO(fd = accept4(listen_fd, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK));
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_fd(bus, fd, fd) >= 0);
ASSERT_OK(sd_bus_new(&bus));
ASSERT_OK(sd_bus_set_fd(bus, fd, fd));
TAKE_FD(fd);
assert_se(sd_bus_set_server(bus, true, id) >= 0);
assert_se(sd_bus_negotiate_creds(bus, 1, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_SUPPLEMENTARY_GIDS) >= 0);
assert_se(sd_bus_start(bus) >= 0);
assert_se(sd_bus_get_owner_creds(bus, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_SUPPLEMENTARY_GIDS, &c) >= 0);
ASSERT_OK(sd_bus_set_server(bus, true, id));
ASSERT_OK(sd_bus_negotiate_creds(bus, 1, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_SUPPLEMENTARY_GIDS));
ASSERT_OK(sd_bus_start(bus));
ASSERT_OK(sd_bus_get_owner_creds(bus, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_SUPPLEMENTARY_GIDS, &c));
bus_creds_dump(c, /* f= */ NULL, /* terse= */ false);
uid_t u;
assert_se(sd_bus_creds_get_euid(c, &u) >= 0);
assert_se(u == getuid());
ASSERT_OK(sd_bus_creds_get_euid(c, &u));
ASSERT_EQ(u, getuid());
gid_t g;
assert_se(sd_bus_creds_get_egid(c, &g) >= 0);
assert_se(g == getgid());
ASSERT_OK(sd_bus_creds_get_egid(c, &g));
ASSERT_EQ(g, getgid());
pid_t pid;
assert_se(sd_bus_creds_get_pid(c, &pid) >= 0);
assert_se(pid == getpid_cached());
ASSERT_OK(sd_bus_creds_get_pid(c, &pid));
ASSERT_EQ(pid, getpid_cached());
int pidfd = -EBADF;
if (sd_bus_creds_get_pidfd_dup(c, &pidfd) >= 0) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
assert_se(pidref_set_pidfd_take(&pidref, pidfd) >= 0);
assert_se(pidref_is_self(&pidref));
ASSERT_OK(pidref_set_pidfd_take(&pidref, pidfd));
ASSERT_TRUE(pidref_is_self(&pidref));
}
const gid_t *gl = NULL;
int n;
n = sd_bus_creds_get_supplementary_gids(c, &gl);
int n = sd_bus_creds_get_supplementary_gids(c, &gl);
if (n >= 0) {
_cleanup_free_ gid_t *gg = NULL;
r = getgroups_alloc(&gg);
assert_se(r >= 0);
assert_se(gid_list_same(gl, n, gg, r));
ASSERT_OK(r = getgroups_alloc(&gg));
ASSERT_TRUE(gid_list_same(gl, n, gg, r));
}
const char *comm;
assert_se(sd_bus_creds_get_comm(c, &comm) >= 0);
assert_se(pid_get_comm(0, &our_comm) >= 0);
assert_se(streq_ptr(comm, our_comm));
ASSERT_OK(sd_bus_creds_get_comm(c, &comm));
ASSERT_OK(pid_get_comm(0, &our_comm));
ASSERT_STREQ(comm, our_comm);
const char *description;
assert_se(sd_bus_creds_get_description(c, &description) >= 0);
assert_se(streq_ptr(description, "wuffwuff"));
ASSERT_OK(sd_bus_creds_get_description(c, &description));
ASSERT_STREQ(description, "wuffwuff");
for (;;) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
r = sd_bus_process(bus, &m);
assert_se(r >= 0);
ASSERT_OK(r = sd_bus_process(bus, &m));
if (r == 0) {
assert_se(sd_bus_wait(bus, UINT64_MAX) >= 0);
ASSERT_OK(sd_bus_wait(bus, UINT64_MAX));
continue;
}
if (m && sd_bus_message_is_method_call(m, "foo.foo", "Foo") > 0) {
assert_se(sd_bus_reply_method_return(m, "s", "bar") >= 0);
ASSERT_OK(sd_bus_reply_method_return(m, "s", "bar"));
break;
}
}
@ -129,15 +122,15 @@ static void* client(void *p) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *z;
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_description(bus, "wuffwuff") >= 0);
assert_se(sd_bus_set_address(bus, p) >= 0);
assert_se(sd_bus_start(bus) >= 0);
ASSERT_OK(sd_bus_new(&bus));
ASSERT_OK(sd_bus_set_description(bus, "wuffwuff"));
ASSERT_OK(sd_bus_set_address(bus, p));
ASSERT_OK(sd_bus_start(bus));
assert_se(sd_bus_call_method(bus, "foo.foo", "/foo", "foo.foo", "Foo", NULL, &reply, "s", "foo") >= 0);
ASSERT_OK(sd_bus_call_method(bus, "foo.foo", "/foo", "foo.foo", "Foo", NULL, &reply, "s", "foo"));
assert_se(sd_bus_message_read(reply, "s", &z) >= 0);
assert_se(streq_ptr(z, "bar"));
ASSERT_OK(sd_bus_message_read(reply, "s", &z));
ASSERT_STREQ(z, "bar");
return NULL;
}
@ -151,27 +144,24 @@ TEST(description) {
socklen_t salen;
pthread_t s, c;
fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
assert_se(fd >= 0);
assert_se(bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path)) >= 0); /* force auto-bind */
assert_se(listen(fd, 1) >= 0);
ASSERT_OK_ERRNO(fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0));
ASSERT_OK_ERRNO(bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path))); /* force auto-bind */
ASSERT_OK_ERRNO(listen(fd, 1));
salen = sizeof(sa);
assert_se(getsockname(fd, &sa.sa, &salen) >= 0);
assert_se(salen >= offsetof(struct sockaddr_un, sun_path));
assert_se(sa.un.sun_path[0] == 0);
ASSERT_OK_ERRNO(getsockname(fd, &sa.sa, &salen));
ASSERT_GE(salen, offsetof(struct sockaddr_un, sun_path));
ASSERT_EQ(sa.un.sun_path[0], 0);
assert_se(asprintf(&a, "unix:abstract=%s", sa.un.sun_path + 1) >= 0);
ASSERT_OK(asprintf(&a, "unix:abstract=%s", sa.un.sun_path + 1));
assert_se(pthread_create(&s, NULL, server, INT_TO_PTR(fd)) == 0);
ASSERT_OK(-pthread_create(&s, NULL, server, INT_TO_PTR(fd)));
TAKE_FD(fd);
assert_se(pthread_create(&c, NULL, client, a) == 0);
ASSERT_OK(-pthread_create(&c, NULL, client, a));
assert_se(pthread_join(s, NULL) == 0);
assert_se(pthread_join(c, NULL) == 0);
ASSERT_OK(-pthread_join(s, NULL));
ASSERT_OK(-pthread_join(c, NULL));
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -5,7 +5,6 @@
#include "sd-bus.h"
#include "bus-error.h"
#include "log.h"
#include "memory-util.h"
#include "string-util.h"
@ -27,14 +26,14 @@ static int _server(struct context *c) {
bool quit = false;
int r;
assert_se(sd_id128_randomize(&id) >= 0);
ASSERT_OK(sd_id128_randomize(&id));
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
assert_se(sd_bus_set_server(bus, 1, id) >= 0);
assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0);
assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
assert_se(sd_bus_start(bus) >= 0);
ASSERT_OK(sd_bus_new(&bus));
ASSERT_OK(sd_bus_set_fd(bus, c->fds[0], c->fds[0]));
ASSERT_OK(sd_bus_set_server(bus, 1, id));
ASSERT_OK(sd_bus_set_anonymous(bus, c->server_anonymous_auth));
ASSERT_OK(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds));
ASSERT_OK(sd_bus_start(bus));
while (!quit) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
@ -44,9 +43,7 @@ static int _server(struct context *c) {
return log_error_errno(r, "Failed to process requests: %m");
if (r == 0) {
r = sd_bus_wait(bus, UINT64_MAX);
if (r < 0)
return log_error_errno(r, "Failed to wait: %m");
ASSERT_OK(sd_bus_wait(bus, UINT64_MAX));
continue;
}
@ -57,29 +54,21 @@ static int _server(struct context *c) {
if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) {
assert_se((sd_bus_can_send(bus, 'h') >= 1) ==
(c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));
ASSERT_EQ(sd_bus_can_send(bus, 'h') >= 1,
c->server_negotiate_unix_fds && c->client_negotiate_unix_fds);
r = sd_bus_message_new_method_return(m, &reply);
if (r < 0)
return log_error_errno(r, "Failed to allocate return: %m");
ASSERT_OK(sd_bus_message_new_method_return(m, &reply));
quit = true;
} else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
r = sd_bus_message_new_method_error(
} else if (sd_bus_message_is_method_call(m, NULL, NULL))
ASSERT_OK(sd_bus_message_new_method_error(
m,
&reply,
&SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
if (r < 0)
return log_error_errno(r, "Failed to allocate return: %m");
}
&SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method.")));
if (reply) {
r = sd_bus_send(bus, reply, NULL);
if (r < 0)
return log_error_errno(r, "Failed to send reply: %m");
}
if (reply)
ASSERT_OK(sd_bus_send(bus, reply, NULL));
}
return 0;
@ -93,29 +82,22 @@ static int client(struct context *c) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
_cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
assert_se(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0);
assert_se(sd_bus_set_anonymous(bus, c->client_anonymous_auth) >= 0);
assert_se(sd_bus_start(bus) >= 0);
ASSERT_OK(sd_bus_new(&bus));
ASSERT_OK(sd_bus_set_fd(bus, c->fds[1], c->fds[1]));
ASSERT_OK(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds));
ASSERT_OK(sd_bus_set_anonymous(bus, c->client_anonymous_auth));
ASSERT_OK(sd_bus_start(bus));
r = sd_bus_message_new_method_call(
ASSERT_OK(sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.systemd.test",
"/",
"org.freedesktop.systemd.test",
"Exit");
if (r < 0)
return log_error_errno(r, "Failed to allocate method call: %m");
"Exit"));
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0)
return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r));
return 0;
return sd_bus_call(bus, m, 0, &error, &reply);
}
static int test_one(bool client_negotiate_unix_fds, bool server_negotiate_unix_fds,
@ -128,7 +110,7 @@ static int test_one(bool client_negotiate_unix_fds, bool server_negotiate_unix_f
zero(c);
assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds));
c.client_negotiate_unix_fds = client_negotiate_unix_fds;
c.server_negotiate_unix_fds = server_negotiate_unix_fds;
@ -155,30 +137,15 @@ static int test_one(bool client_negotiate_unix_fds, bool server_negotiate_unix_f
}
int main(int argc, char *argv[]) {
int r;
test_setup_logging(LOG_DEBUG);
r = test_one(true, true, false, false);
assert_se(r >= 0);
r = test_one(true, false, false, false);
assert_se(r >= 0);
r = test_one(false, true, false, false);
assert_se(r >= 0);
r = test_one(false, false, false, false);
assert_se(r >= 0);
r = test_one(true, true, true, true);
assert_se(r >= 0);
r = test_one(true, true, false, true);
assert_se(r >= 0);
r = test_one(true, true, true, false);
assert_se(r == -EPERM);
ASSERT_OK(test_one(true, true, false, false));
ASSERT_OK(test_one(true, false, false, false));
ASSERT_OK(test_one(false, true, false, false));
ASSERT_OK(test_one(false, false, false, false));
ASSERT_OK(test_one(true, true, true, true));
ASSERT_OK(test_one(true, true, false, true));
ASSERT_ERROR(test_one(true, true, true, false), EPERM);
return EXIT_SUCCESS;
}

View File

@ -24,14 +24,14 @@
static int method_foobar(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
log_info("Got Foobar() call.");
assert_se(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 0) >= 0);
ASSERT_OK(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 0));
return sd_bus_reply_method_return(m, NULL);
}
static int method_exit(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
log_info("Got Exit() call");
assert_se(sd_bus_reply_method_return(m, NULL) >= 0);
ASSERT_OK(sd_bus_reply_method_return(m, NULL));
/* Simulate D-Bus going away to test the bus_exit_now() path with exit_on_disconnect set */
bus_enter_closing(sd_bus_message_get_bus(m));
return 0;
@ -56,37 +56,37 @@ static void* thread_server(void *p) {
/* Let's play some games, by slowly creating the socket directory, and renaming it in the middle */
usleep_safe(100 * USEC_PER_MSEC);
assert_se(mkdir_parents(path, 0755) >= 0);
ASSERT_OK(mkdir_parents(path, 0755));
usleep_safe(100 * USEC_PER_MSEC);
assert_se(path_extract_directory(path, &d) >= 0);
assert_se(asprintf(&suffixed, "%s.%" PRIx64, d, random_u64()) >= 0);
assert_se(rename(d, suffixed) >= 0);
ASSERT_OK(path_extract_directory(path, &d));
ASSERT_OK(asprintf(&suffixed, "%s.%" PRIx64, d, random_u64()));
ASSERT_OK_ERRNO(rename(d, suffixed));
usleep_safe(100 * USEC_PER_MSEC);
assert_se(asprintf(&suffixed2, "%s.%" PRIx64, d, random_u64()) >= 0);
assert_se(symlink(suffixed2, d) >= 0);
ASSERT_OK(asprintf(&suffixed2, "%s.%" PRIx64, d, random_u64()));
ASSERT_OK_ERRNO(symlink(suffixed2, d));
usleep_safe(100 * USEC_PER_MSEC);
assert_se(path_extract_filename(suffixed, &suffixed_basename) >= 0);
assert_se(symlink(suffixed_basename, suffixed2) >= 0);
ASSERT_OK(path_extract_filename(suffixed, &suffixed_basename));
ASSERT_OK_ERRNO(symlink(suffixed_basename, suffixed2));
usleep_safe(100 * USEC_PER_MSEC);
socklen_t sa_len;
r = sockaddr_un_set_path(&u.un, path);
assert_se(r >= 0);
ASSERT_OK(r);
sa_len = r;
fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
assert_se(fd >= 0);
ASSERT_OK_ERRNO(fd);
assert_se(bind(fd, &u.sa, sa_len) >= 0);
ASSERT_OK_ERRNO(bind(fd, &u.sa, sa_len));
usleep_safe(100 * USEC_PER_MSEC);
assert_se(listen(fd, SOMAXCONN_DELUXE) >= 0);
ASSERT_OK_ERRNO(listen(fd, SOMAXCONN_DELUXE));
usleep_safe(100 * USEC_PER_MSEC);
assert_se(touch(path) >= 0);
ASSERT_OK(touch(path));
usleep_safe(100 * USEC_PER_MSEC);
log_debug("Initialized server");
@ -97,31 +97,31 @@ static void* thread_server(void *p) {
sd_id128_t id;
int bus_fd, code;
assert_se(sd_id128_randomize(&id) >= 0);
ASSERT_OK(sd_id128_randomize(&id));
assert_se(sd_event_new(&event) >= 0);
ASSERT_OK(sd_event_new(&event));
bus_fd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
assert_se(bus_fd >= 0);
ASSERT_OK_ERRNO(bus_fd);
log_debug("Accepted server connection");
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_exit_on_disconnect(bus, true) >= 0);
assert_se(sd_bus_set_description(bus, "server") >= 0);
assert_se(sd_bus_set_fd(bus, bus_fd, bus_fd) >= 0);
assert_se(sd_bus_set_server(bus, true, id) >= 0);
/* assert_se(sd_bus_set_anonymous(bus, true) >= 0); */
ASSERT_OK(sd_bus_new(&bus));
ASSERT_OK(sd_bus_set_exit_on_disconnect(bus, true));
ASSERT_OK(sd_bus_set_description(bus, "server"));
ASSERT_OK(sd_bus_set_fd(bus, bus_fd, bus_fd));
ASSERT_OK(sd_bus_set_server(bus, true, id));
/* ASSERT_OK(sd_bus_set_anonymous(bus, true)); */
assert_se(sd_bus_attach_event(bus, event, 0) >= 0);
ASSERT_OK(sd_bus_attach_event(bus, event, 0));
assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "foo.TestInterface", vtable, NULL) >= 0);
ASSERT_OK(sd_bus_add_object_vtable(bus, NULL, "/foo", "foo.TestInterface", vtable, NULL));
assert_se(sd_bus_start(bus) >= 0);
ASSERT_OK(sd_bus_start(bus));
assert_se(sd_event_loop(event) >= 0);
ASSERT_OK(sd_event_loop(event));
assert_se(sd_event_get_exit_code(event, &code) >= 0);
ASSERT_OK(sd_event_get_exit_code(event, &code));
if (code > 0)
break;
@ -136,20 +136,18 @@ static void* thread_client1(void *p) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
const char *path = p, *t;
int r;
log_debug("Initializing client1");
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_description(bus, "client1") >= 0);
ASSERT_OK(sd_bus_new(&bus));
ASSERT_OK(sd_bus_set_description(bus, "client1"));
t = strjoina("unix:path=", path);
assert_se(sd_bus_set_address(bus, t) >= 0);
assert_se(sd_bus_set_watch_bind(bus, true) >= 0);
assert_se(sd_bus_start(bus) >= 0);
ASSERT_OK(sd_bus_set_address(bus, t));
ASSERT_OK(sd_bus_set_watch_bind(bus, true));
ASSERT_OK(sd_bus_start(bus));
r = sd_bus_call_method(bus, "foo.bar", "/foo", "foo.TestInterface", "Foobar", &error, NULL, NULL);
assert_se(r >= 0);
ASSERT_OK(sd_bus_call_method(bus, "foo.bar", "/foo", "foo.TestInterface", "Foobar", &error, NULL, NULL));
log_debug("Client1 done");
@ -157,8 +155,8 @@ static void* thread_client1(void *p) {
}
static int client2_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
assert_se(sd_bus_message_is_method_error(m, NULL) == 0);
assert_se(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 0) >= 0);
ASSERT_OK_ZERO(sd_bus_message_is_method_error(m, NULL));
ASSERT_OK(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 0));
return 0;
}
@ -169,19 +167,19 @@ static void* thread_client2(void *p) {
log_debug("Initializing client2");
assert_se(sd_event_new(&event) >= 0);
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_description(bus, "client2") >= 0);
ASSERT_OK(sd_event_new(&event));
ASSERT_OK(sd_bus_new(&bus));
ASSERT_OK(sd_bus_set_description(bus, "client2"));
t = strjoina("unix:path=", path);
assert_se(sd_bus_set_address(bus, t) >= 0);
assert_se(sd_bus_set_watch_bind(bus, true) >= 0);
assert_se(sd_bus_attach_event(bus, event, 0) >= 0);
assert_se(sd_bus_start(bus) >= 0);
ASSERT_OK(sd_bus_set_address(bus, t));
ASSERT_OK(sd_bus_set_watch_bind(bus, true));
ASSERT_OK(sd_bus_attach_event(bus, event, 0));
ASSERT_OK(sd_bus_start(bus));
assert_se(sd_bus_call_method_async(bus, NULL, "foo.bar", "/foo", "foo.TestInterface", "Foobar", client2_callback, NULL, NULL) >= 0);
ASSERT_OK(sd_bus_call_method_async(bus, NULL, "foo.bar", "/foo", "foo.TestInterface", "Foobar", client2_callback, NULL, NULL));
assert_se(sd_event_loop(event) >= 0);
ASSERT_OK(sd_event_loop(event));
log_debug("Client2 done");
@ -192,15 +190,15 @@ static void request_exit(const char *path) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
const char *t;
assert_se(sd_bus_new(&bus) >= 0);
ASSERT_OK(sd_bus_new(&bus));
t = strjoina("unix:path=", path);
assert_se(sd_bus_set_address(bus, t) >= 0);
assert_se(sd_bus_set_watch_bind(bus, true) >= 0);
assert_se(sd_bus_set_description(bus, "request-exit") >= 0);
assert_se(sd_bus_start(bus) >= 0);
ASSERT_OK(sd_bus_set_address(bus, t));
ASSERT_OK(sd_bus_set_watch_bind(bus, true));
ASSERT_OK(sd_bus_set_description(bus, "request-exit"));
ASSERT_OK(sd_bus_start(bus));
assert_se(sd_bus_call_method(bus, "foo.bar", "/foo", "foo.TestInterface", "Exit", NULL, NULL, NULL) >= 0);
ASSERT_OK(sd_bus_call_method(bus, "foo.bar", "/foo", "foo.TestInterface", "Exit", NULL, NULL, NULL));
}
int main(int argc, char *argv[]) {
@ -212,20 +210,20 @@ int main(int argc, char *argv[]) {
/* We use /dev/shm here rather than /tmp, since some weird distros might set up /tmp as some weird fs that
* doesn't support inotify properly. */
assert_se(mkdtemp_malloc("/dev/shm/systemd-watch-bind-XXXXXX", &d) >= 0);
ASSERT_OK(mkdtemp_malloc("/dev/shm/systemd-watch-bind-XXXXXX", &d));
path = strjoina(d, "/this/is/a/socket");
assert_se(pthread_create(&server, NULL, thread_server, path) == 0);
assert_se(pthread_create(&client1, NULL, thread_client1, path) == 0);
assert_se(pthread_create(&client2, NULL, thread_client2, path) == 0);
ASSERT_OK(-pthread_create(&server, NULL, thread_server, path));
ASSERT_OK(-pthread_create(&client1, NULL, thread_client1, path));
ASSERT_OK(-pthread_create(&client2, NULL, thread_client2, path));
assert_se(pthread_join(client1, NULL) == 0);
assert_se(pthread_join(client2, NULL) == 0);
ASSERT_OK(-pthread_join(client1, NULL));
ASSERT_OK(-pthread_join(client2, NULL));
request_exit(path);
assert_se(pthread_join(server, NULL) == 0);
ASSERT_OK(-pthread_join(server, NULL));
return 0;
}

View File

@ -41,18 +41,18 @@ static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userda
log_info("got IO on %c", PTR_TO_INT(userdata));
if (userdata == INT_TO_PTR('a')) {
assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
assert_se(!got_a);
ASSERT_OK(sd_event_source_set_enabled(s, SD_EVENT_OFF));
ASSERT_FALSE(got_a);
got_a = true;
} else if (userdata == INT_TO_PTR('b')) {
assert_se(!got_b);
ASSERT_FALSE(got_b);
got_b = true;
} else if (userdata == INT_TO_PTR('d')) {
got_d++;
if (got_d < 2)
assert_se(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT) >= 0);
ASSERT_OK(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT));
else
assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
ASSERT_OK(sd_event_source_set_enabled(s, SD_EVENT_OFF));
} else
assert_not_reached();
@ -61,19 +61,19 @@ static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userda
static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
assert_se(s);
assert_se(si);
ASSERT_NOT_NULL(s);
ASSERT_NOT_NULL(si);
assert_se(si->si_uid == getuid());
assert_se(si->si_signo == SIGCHLD);
assert_se(si->si_code == CLD_EXITED);
assert_se(si->si_status == 78);
ASSERT_EQ(si->si_uid, getuid());
ASSERT_EQ(si->si_signo, SIGCHLD);
ASSERT_EQ(si->si_code, CLD_EXITED);
ASSERT_EQ(si->si_status, 78);
log_info("got child on %c", PTR_TO_INT(userdata));
assert_se(userdata == INT_TO_PTR('f'));
ASSERT_PTR_EQ(userdata, INT_TO_PTR('f'));
assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0);
ASSERT_OK(sd_event_exit(sd_event_source_get_event(s), 0));
sd_event_source_unref(s);
return 1;
@ -84,36 +84,35 @@ static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si,
pid_t pid;
siginfo_t plain_si;
assert_se(s);
assert_se(si);
ASSERT_NOT_NULL(s);
ASSERT_NOT_NULL(si);
log_info("got signal on %c", PTR_TO_INT(userdata));
assert_se(userdata == INT_TO_PTR('e'));
ASSERT_PTR_EQ(userdata, INT_TO_PTR('e'));
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGUSR2) >= 0);
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGUSR2));
pid = fork();
assert_se(pid >= 0);
ASSERT_OK_ERRNO(pid = fork());
if (pid == 0) {
sigset_t ss;
assert_se(sigemptyset(&ss) >= 0);
assert_se(sigaddset(&ss, SIGUSR2) >= 0);
ASSERT_OK_ERRNO(sigemptyset(&ss));
ASSERT_OK_ERRNO(sigaddset(&ss, SIGUSR2));
zero(plain_si);
assert_se(sigwaitinfo(&ss, &plain_si) >= 0);
ASSERT_OK_ERRNO(sigwaitinfo(&ss, &plain_si));
assert_se(plain_si.si_signo == SIGUSR2);
assert_se(plain_si.si_value.sival_int == 4711);
ASSERT_EQ(plain_si.si_signo, SIGUSR2);
ASSERT_EQ(plain_si.si_value.sival_int, 4711);
_exit(78);
}
assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0);
assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
assert_se(sd_event_source_set_child_process_own(p, true) >= 0);
ASSERT_OK(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')));
ASSERT_OK(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT));
ASSERT_OK(sd_event_source_set_child_process_own(p, true));
/* We can't use structured initialization here, since the structure contains various unions and these
* fields lie in overlapping (carefully aligned) unions that LLVM is allergic to allow assignments
@ -125,7 +124,7 @@ static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si,
plain_si.si_uid = getuid();
plain_si.si_value.sival_int = 4711;
assert_se(sd_event_source_send_child_signal(p, SIGUSR2, &plain_si, 0) >= 0);
ASSERT_OK(sd_event_source_send_child_signal(p, SIGUSR2, &plain_si, 0));
sd_event_source_unref(s);
@ -135,16 +134,16 @@ static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si,
static int defer_handler(sd_event_source *s, void *userdata) {
sd_event_source *p = NULL;
assert_se(s);
ASSERT_NOT_NULL(s);
log_info("got defer on %c", PTR_TO_INT(userdata));
assert_se(userdata == INT_TO_PTR('d'));
ASSERT_PTR_EQ(userdata, INT_TO_PTR('d'));
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1) >= 0);
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1));
assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0);
assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
ASSERT_OK(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')));
ASSERT_OK(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT));
raise(SIGUSR1);
sd_event_source_unref(s);
@ -162,10 +161,10 @@ static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
if (do_quit) {
sd_event_source *p;
assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0);
assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
ASSERT_OK(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')));
ASSERT_OK(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT));
} else {
assert_se(!got_c);
ASSERT_FALSE(got_c);
got_c = true;
}
} else
@ -203,84 +202,92 @@ TEST(basic) {
uint64_t event_now;
int64_t priority;
assert_se(pipe(a) >= 0);
assert_se(pipe(b) >= 0);
assert_se(pipe(d) >= 0);
assert_se(pipe(k) >= 0);
ASSERT_OK_ERRNO(pipe(a));
ASSERT_OK_ERRNO(pipe(b));
ASSERT_OK_ERRNO(pipe(d));
ASSERT_OK_ERRNO(pipe(k));
assert_se(sd_event_default(&e) >= 0);
assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0);
ASSERT_OK(sd_event_default(&e));
ASSERT_OK_POSITIVE(sd_event_now(e, CLOCK_MONOTONIC, &event_now));
assert_se(sd_event_set_watchdog(e, true) >= 0);
ASSERT_OK(sd_event_set_watchdog(e, true));
/* Test whether we cleanly can destroy an io event source from its own handler */
got_unref = false;
assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0);
assert_se(write(k[1], &ch, 1) == 1);
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
assert_se(got_unref);
ASSERT_OK(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL));
ASSERT_OK_EQ_ERRNO(write(k[1], &ch, 1), 1);
ASSERT_OK_POSITIVE(sd_event_run(e, UINT64_MAX));
ASSERT_TRUE(got_unref);
got_a = false, got_b = false, got_c = false, got_d = 0;
/* Add a oneshot handler, trigger it, reenable it, and trigger it again. */
assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0);
assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0);
assert_se(write(d[1], &ch, 1) >= 0);
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
assert_se(got_d == 1);
assert_se(write(d[1], &ch, 1) >= 0);
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
assert_se(got_d == 2);
ASSERT_OK(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')));
ASSERT_OK(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT));
ASSERT_OK_ERRNO(write(d[1], &ch, 1));
ASSERT_OK_POSITIVE(sd_event_run(e, UINT64_MAX));
ASSERT_EQ(got_d, 1U);
ASSERT_OK_ERRNO(write(d[1], &ch, 1));
ASSERT_OK_POSITIVE(sd_event_run(e, UINT64_MAX));
ASSERT_EQ(got_d, 2U);
assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0);
assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0);
ASSERT_OK(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')));
ASSERT_OK(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')));
do_quit = false;
assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0);
assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0);
ASSERT_OK(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')));
ASSERT_OK(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')));
assert_se(sd_event_source_set_priority(x, 99) >= 0);
assert_se(sd_event_source_get_priority(x, &priority) >= 0);
assert_se(priority == 99);
assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0);
assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0);
assert_se(sd_event_source_set_priority(z, 50) >= 0);
assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0);
ASSERT_OK(sd_event_source_set_priority(x, 99));
ASSERT_OK(sd_event_source_get_priority(x, &priority));
ASSERT_EQ(priority, 99);
ASSERT_OK(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT));
ASSERT_OK(sd_event_source_set_prepare(x, prepare_handler));
ASSERT_OK(sd_event_source_set_priority(z, 50));
ASSERT_OK(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT));
ASSERT_OK(sd_event_source_set_prepare(z, prepare_handler));
/* Test for floating event sources */
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1) >= 0);
assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0);
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1));
ASSERT_OK(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL));
assert_se(write(a[1], &ch, 1) >= 0);
assert_se(write(b[1], &ch, 1) >= 0);
ASSERT_OK_ERRNO(write(a[1], &ch, 1));
ASSERT_OK_ERRNO(write(b[1], &ch, 1));
assert_se(!got_a && !got_b && !got_c);
ASSERT_FALSE(got_a);
ASSERT_FALSE(got_b);
ASSERT_FALSE(got_c);
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
ASSERT_OK_POSITIVE(sd_event_run(e, UINT64_MAX));
assert_se(!got_a && got_b && !got_c);
ASSERT_FALSE(got_a);
ASSERT_TRUE(got_b);
ASSERT_FALSE(got_c);
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
ASSERT_OK_POSITIVE(sd_event_run(e, UINT64_MAX));
assert_se(!got_a && got_b && got_c);
ASSERT_FALSE(got_a);
ASSERT_TRUE(got_b);
ASSERT_TRUE(got_c);
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
ASSERT_OK_POSITIVE(sd_event_run(e, UINT64_MAX));
assert_se(got_a && got_b && got_c);
ASSERT_TRUE(got_a);
ASSERT_TRUE(got_b);
ASSERT_TRUE(got_c);
sd_event_source_unref(x);
sd_event_source_unref(y);
do_quit = true;
assert_se(sd_event_add_post(e, NULL, post_handler, NULL) >= 0);
assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0);
assert_se(sd_event_source_set_time(z, event_now + 200 * USEC_PER_MSEC) >= 0);
assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
ASSERT_OK(sd_event_add_post(e, NULL, post_handler, NULL));
ASSERT_OK_ZERO(sd_event_now(e, CLOCK_MONOTONIC, &event_now));
ASSERT_OK(sd_event_source_set_time(z, event_now + 200 * USEC_PER_MSEC));
ASSERT_OK(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT));
assert_se(sd_event_loop(e) >= 0);
assert_se(got_post);
assert_se(got_exit);
ASSERT_OK(sd_event_loop(e));
ASSERT_TRUE(got_post);
ASSERT_TRUE(got_exit);
sd_event_source_unref(z);
sd_event_source_unref(q);
@ -299,24 +306,24 @@ TEST(sd_event_now) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
uint64_t event_now;
assert_se(sd_event_new(&e) >= 0);
assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0);
assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) > 0);
assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) > 0);
assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) > 0);
assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) > 0);
assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
ASSERT_OK(sd_event_new(&e));
ASSERT_OK_POSITIVE(sd_event_now(e, CLOCK_MONOTONIC, &event_now));
ASSERT_OK_POSITIVE(sd_event_now(e, CLOCK_REALTIME, &event_now));
ASSERT_OK_POSITIVE(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now));
ASSERT_OK_POSITIVE(sd_event_now(e, CLOCK_BOOTTIME, &event_now));
ASSERT_OK_POSITIVE(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now));
ASSERT_ERROR(sd_event_now(e, -1, &event_now), EOPNOTSUPP);
ASSERT_ERROR(sd_event_now(e, 900 /* arbitrary big number */, &event_now), EOPNOTSUPP);
assert_se(sd_event_run(e, 0) == 0);
ASSERT_OK_ZERO(sd_event_run(e, 0));
assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0);
assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) == 0);
assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) == 0);
assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) == 0);
assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) == 0);
assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
ASSERT_OK_ZERO(sd_event_now(e, CLOCK_MONOTONIC, &event_now));
ASSERT_OK_ZERO(sd_event_now(e, CLOCK_REALTIME, &event_now));
ASSERT_OK_ZERO(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now));
ASSERT_OK_ZERO(sd_event_now(e, CLOCK_BOOTTIME, &event_now));
ASSERT_OK_ZERO(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now));
ASSERT_ERROR(sd_event_now(e, -1, &event_now), EOPNOTSUPP);
ASSERT_ERROR(sd_event_now(e, 900 /* arbitrary big number */, &event_now), EOPNOTSUPP);
}
static int last_rtqueue_sigval = 0;
@ -332,43 +339,43 @@ TEST(rtqueue) {
sd_event_source *u = NULL, *v = NULL, *s = NULL;
sd_event *e = NULL;
assert_se(sd_event_default(&e) >= 0);
ASSERT_OK(sd_event_default(&e));
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2) >= 0);
assert_se(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL) >= 0);
assert_se(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL) >= 0);
assert_se(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL) >= 0);
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2));
ASSERT_OK(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL));
ASSERT_OK(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL));
ASSERT_OK(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL));
assert_se(sd_event_source_set_priority(v, -10) >= 0);
ASSERT_OK(sd_event_source_set_priority(v, -10));
assert_se(sigqueue(getpid_cached(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }) >= 0);
assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }) >= 0);
assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 3 }) >= 0);
assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }) >= 0);
assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 5 }) >= 0);
ASSERT_OK_ERRNO(sigqueue(getpid_cached(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }));
ASSERT_OK_ERRNO(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }));
ASSERT_OK_ERRNO(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 3 }));
ASSERT_OK_ERRNO(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }));
ASSERT_OK_ERRNO(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 5 }));
assert_se(n_rtqueue == 0);
assert_se(last_rtqueue_sigval == 0);
ASSERT_EQ(n_rtqueue, 0);
ASSERT_EQ(last_rtqueue_sigval, 0);
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
assert_se(n_rtqueue == 1);
assert_se(last_rtqueue_sigval == 2); /* first SIGRTMIN+3 */
ASSERT_OK_EQ(sd_event_run(e, UINT64_MAX), 1);
ASSERT_EQ(n_rtqueue, 1);
ASSERT_EQ(last_rtqueue_sigval, 2); /* first SIGRTMIN+3 */
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
assert_se(n_rtqueue == 2);
assert_se(last_rtqueue_sigval == 4); /* second SIGRTMIN+3 */
ASSERT_OK_EQ(sd_event_run(e, UINT64_MAX), 1);
ASSERT_EQ(n_rtqueue, 2);
ASSERT_EQ(last_rtqueue_sigval, 4); /* second SIGRTMIN+3 */
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
assert_se(n_rtqueue == 3);
assert_se(last_rtqueue_sigval == 3); /* first SIGUSR2 */
ASSERT_OK_EQ(sd_event_run(e, UINT64_MAX), 1);
ASSERT_EQ(n_rtqueue, 3);
ASSERT_EQ(last_rtqueue_sigval, 3); /* first SIGUSR2 */
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
assert_se(n_rtqueue == 4);
assert_se(last_rtqueue_sigval == 1); /* SIGRTMIN+2 */
ASSERT_OK_EQ(sd_event_run(e, UINT64_MAX), 1);
ASSERT_EQ(n_rtqueue, 4);
ASSERT_EQ(last_rtqueue_sigval, 1); /* SIGRTMIN+2 */
assert_se(sd_event_run(e, 0) == 0); /* the other SIGUSR2 is dropped, because the first one was still queued */
assert_se(n_rtqueue == 4);
assert_se(last_rtqueue_sigval == 1);
ASSERT_OK_ZERO(sd_event_run(e, 0)); /* the other SIGUSR2 is dropped, because the first one was still queued */
ASSERT_EQ(n_rtqueue, 4);
ASSERT_EQ(last_rtqueue_sigval, 1);
sd_event_source_unref(u);
sd_event_source_unref(v);
@ -390,8 +397,8 @@ struct inotify_context {
static void maybe_exit(sd_event_source *s, struct inotify_context *c) {
unsigned n;
assert_se(s);
assert_se(c);
ASSERT_NOT_NULL(s);
ASSERT_NOT_NULL(c);
if (!c->delete_self_handler_called)
return;
@ -415,31 +422,31 @@ static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, v
const char *path, *description;
unsigned bit, n;
assert_se(sd_event_source_get_inotify_path(s, &path) >= 0);
ASSERT_OK(sd_event_source_get_inotify_path(s, &path));
assert_se(sd_event_source_get_description(s, &description) >= 0);
assert_se(safe_atou(description, &n) >= 0);
ASSERT_OK(sd_event_source_get_description(s, &description));
ASSERT_OK(safe_atou(description, &n));
assert_se(n <= 3);
ASSERT_LE(n, 3U);
bit = 1U << n;
if (ev->mask & IN_Q_OVERFLOW) {
log_info("inotify-handler for %s <%s>: overflow", path, description);
c->create_overflow |= bit;
} else if (ev->mask & IN_CREATE) {
assert_se(path_equal_or_inode_same(path, c->path, 0));
ASSERT_TRUE(path_equal_or_inode_same(path, c->path, 0));
if (streq(ev->name, "sub"))
log_debug("inotify-handler for %s <%s>: create on %s", path, description, ev->name);
else {
unsigned i;
assert_se(safe_atou(ev->name, &i) >= 0);
assert_se(i < c->n_create_events);
ASSERT_OK(safe_atou(ev->name, &i));
ASSERT_LT(i, c->n_create_events);
c->create_called[i] |= bit;
}
} else if (ev->mask & IN_DELETE) {
log_info("inotify-handler for %s <%s>: delete of %s", path, description, ev->name);
assert_se(streq(ev->name, "sub"));
ASSERT_STREQ(ev->name, "sub");
} else
assert_not_reached();
@ -451,7 +458,7 @@ static int delete_self_handler(sd_event_source *s, const struct inotify_event *e
struct inotify_context *c = ASSERT_PTR(userdata);
const char *path;
assert_se(sd_event_source_get_inotify_path(s, &path) >= 0);
ASSERT_OK(sd_event_source_get_inotify_path(s, &path));
if (ev->mask & IN_Q_OVERFLOW) {
log_info("delete-self-handler for %s: overflow", path);
@ -480,46 +487,46 @@ static void test_inotify_one(unsigned n_create_events) {
log_info("/* %s(%u) */", __func__, n_create_events);
assert_se(sd_event_default(&e) >= 0);
ASSERT_OK(sd_event_default(&e));
assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0);
ASSERT_OK(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p));
context.path = p;
assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE|IN_ONLYDIR, inotify_handler, &context) >= 0);
assert_se(sd_event_add_inotify(e, &b, p, IN_CREATE|IN_DELETE|IN_DONT_FOLLOW, inotify_handler, &context) >= 0);
assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_IDLE) >= 0);
assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_NORMAL) >= 0);
assert_se(sd_event_add_inotify(e, &c, p, IN_CREATE|IN_DELETE|IN_EXCL_UNLINK, inotify_handler, &context) >= 0);
assert_se(sd_event_source_set_priority(c, SD_EVENT_PRIORITY_IDLE) >= 0);
ASSERT_OK(sd_event_add_inotify(e, &a, p, IN_CREATE|IN_ONLYDIR, inotify_handler, &context));
ASSERT_OK(sd_event_add_inotify(e, &b, p, IN_CREATE|IN_DELETE|IN_DONT_FOLLOW, inotify_handler, &context));
ASSERT_OK(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_IDLE));
ASSERT_OK(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_NORMAL));
ASSERT_OK(sd_event_add_inotify(e, &c, p, IN_CREATE|IN_DELETE|IN_EXCL_UNLINK, inotify_handler, &context));
ASSERT_OK(sd_event_source_set_priority(c, SD_EVENT_PRIORITY_IDLE));
assert_se(sd_event_source_set_description(a, "0") >= 0);
assert_se(sd_event_source_set_description(b, "1") >= 0);
assert_se(sd_event_source_set_description(c, "2") >= 0);
ASSERT_OK(sd_event_source_set_description(a, "0"));
ASSERT_OK(sd_event_source_set_description(b, "1"));
ASSERT_OK(sd_event_source_set_description(c, "2"));
assert_se(sd_event_source_get_inotify_path(a, &pp) >= 0);
assert_se(path_equal_or_inode_same(pp, p, 0));
assert_se(sd_event_source_get_inotify_path(b, &pp) >= 0);
assert_se(path_equal_or_inode_same(pp, p, 0));
assert_se(sd_event_source_get_inotify_path(b, &pp) >= 0);
assert_se(path_equal_or_inode_same(pp, p, 0));
ASSERT_OK(sd_event_source_get_inotify_path(a, &pp));
ASSERT_TRUE(path_equal_or_inode_same(pp, p, 0));
ASSERT_OK(sd_event_source_get_inotify_path(b, &pp));
ASSERT_TRUE(path_equal_or_inode_same(pp, p, 0));
ASSERT_OK(sd_event_source_get_inotify_path(b, &pp));
ASSERT_TRUE(path_equal_or_inode_same(pp, p, 0));
q = strjoina(p, "/sub");
assert_se(touch(q) >= 0);
assert_se(sd_event_add_inotify(e, &d, q, IN_DELETE_SELF, delete_self_handler, &context) >= 0);
ASSERT_OK(touch(q));
ASSERT_OK(sd_event_add_inotify(e, &d, q, IN_DELETE_SELF, delete_self_handler, &context));
for (i = 0; i < n_create_events; i++) {
char buf[DECIMAL_STR_MAX(unsigned)+1];
_cleanup_free_ char *z = NULL;
xsprintf(buf, "%u", i);
assert_se(z = path_join(p, buf));
ASSERT_NOT_NULL(z = path_join(p, buf));
assert_se(touch(z) >= 0);
ASSERT_OK(touch(z));
}
assert_se(unlink(q) >= 0);
ASSERT_OK_ERRNO(unlink(q));
assert_se(sd_event_loop(e) >= 0);
ASSERT_OK(sd_event_loop(e));
sd_event_source_unref(a);
sd_event_source_unref(b);
@ -535,19 +542,19 @@ TEST(inotify) {
}
static int pidfd_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
assert_se(s);
assert_se(si);
ASSERT_NOT_NULL(s);
ASSERT_NOT_NULL(si);
assert_se(si->si_uid == getuid());
assert_se(si->si_signo == SIGCHLD);
assert_se(si->si_code == CLD_EXITED);
assert_se(si->si_status == 66);
ASSERT_EQ(si->si_uid, getuid());
ASSERT_EQ(si->si_signo, SIGCHLD);
ASSERT_EQ(si->si_code, CLD_EXITED);
ASSERT_EQ(si->si_status, 66);
log_info("got pidfd on %c", PTR_TO_INT(userdata));
assert_se(userdata == INT_TO_PTR('p'));
ASSERT_PTR_EQ(userdata, INT_TO_PTR('p'));
assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0);
ASSERT_OK(sd_event_exit(sd_event_source_get_event(s), 0));
sd_event_source_unref(s);
return 0;
@ -559,40 +566,36 @@ TEST(pidfd) {
int pidfd;
pid_t pid, pid2;
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD));
pid = fork();
ASSERT_OK_ERRNO(pid = fork());
if (pid == 0)
/* child */
_exit(66);
assert_se(pid > 1);
ASSERT_OK(pidfd = pidfd_open(pid, 0));
pid2 = fork();
ASSERT_OK_ERRNO(pid2 = fork());
if (pid2 == 0)
freeze();
assert_se(pid > 2);
assert_se(sd_event_default(&e) >= 0);
assert_se(sd_event_add_child_pidfd(e, &s, pidfd, WEXITED, pidfd_handler, INT_TO_PTR('p')) >= 0);
assert_se(sd_event_source_set_child_pidfd_own(s, true) >= 0);
ASSERT_OK(sd_event_default(&e));
ASSERT_OK(sd_event_add_child_pidfd(e, &s, pidfd, WEXITED, pidfd_handler, INT_TO_PTR('p')));
ASSERT_OK(sd_event_source_set_child_pidfd_own(s, true));
/* This one should never trigger, since our second child lives forever */
assert_se(sd_event_add_child(e, &t, pid2, WEXITED, pidfd_handler, INT_TO_PTR('q')) >= 0);
assert_se(sd_event_source_set_child_process_own(t, true) >= 0);
ASSERT_OK(sd_event_add_child(e, &t, pid2, WEXITED, pidfd_handler, INT_TO_PTR('q')));
ASSERT_OK(sd_event_source_set_child_process_own(t, true));
assert_se(sd_event_loop(e) >= 0);
ASSERT_OK(sd_event_loop(e));
/* Child should still be alive */
assert_se(kill(pid2, 0) >= 0);
ASSERT_OK_ERRNO(kill(pid2, 0));
t = sd_event_source_unref(t);
/* Child should now be dead, since we dropped the ref */
assert_se(kill(pid2, 0) < 0 && errno == ESRCH);
ASSERT_ERROR_ERRNO(kill(pid2, 0), ESRCH);
sd_event_unref(e);
}
@ -632,73 +635,74 @@ TEST(ratelimit) {
uint64_t interval;
unsigned count, burst;
assert_se(sd_event_default(&e) >= 0);
assert_se(pipe2(p, O_CLOEXEC|O_NONBLOCK) >= 0);
ASSERT_OK(sd_event_default(&e));
ASSERT_OK_ERRNO(pipe2(p, O_CLOEXEC|O_NONBLOCK));
assert_se(sd_event_add_io(e, &s, p[0], EPOLLIN, ratelimit_io_handler, &count) >= 0);
assert_se(sd_event_source_set_description(s, "test-ratelimit-io") >= 0);
assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5) >= 0);
assert_se(sd_event_source_get_ratelimit(s, &interval, &burst) >= 0);
assert_se(interval == 1 * USEC_PER_SEC && burst == 5);
ASSERT_OK(sd_event_add_io(e, &s, p[0], EPOLLIN, ratelimit_io_handler, &count));
ASSERT_OK(sd_event_source_set_description(s, "test-ratelimit-io"));
ASSERT_OK(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5));
ASSERT_OK(sd_event_source_get_ratelimit(s, &interval, &burst));
ASSERT_EQ(interval, 1 * USEC_PER_SEC);
ASSERT_EQ(burst, 5U);
assert_se(write(p[1], "1", 1) == 1);
ASSERT_OK_EQ_ERRNO(write(p[1], "1", 1), 1);
count = 0;
for (unsigned i = 0; i < 10; i++) {
log_debug("slow loop iteration %u", i);
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
assert_se(usleep_safe(250 * USEC_PER_MSEC) >= 0);
ASSERT_OK(sd_event_run(e, UINT64_MAX));
ASSERT_OK(usleep_safe(250 * USEC_PER_MSEC));
}
assert_se(sd_event_source_is_ratelimited(s) == 0);
assert_se(count == 10);
ASSERT_OK_ZERO(sd_event_source_is_ratelimited(s));
ASSERT_EQ(count, 10U);
log_info("ratelimit_io_handler: called %u times, event source not ratelimited", count);
assert_se(sd_event_source_set_ratelimit(s, 0, 0) >= 0);
assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5) >= 0);
ASSERT_OK(sd_event_source_set_ratelimit(s, 0, 0));
ASSERT_OK(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5));
count = 0;
for (unsigned i = 0; i < 10; i++) {
log_debug("fast event loop iteration %u", i);
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
assert_se(usleep_safe(10) >= 0);
ASSERT_OK(sd_event_run(e, UINT64_MAX));
ASSERT_OK(usleep_safe(10));
}
log_info("ratelimit_io_handler: called %u times, event source got ratelimited", count);
assert_se(count < 10);
ASSERT_LT(count, 10U);
s = sd_event_source_unref(s);
safe_close_pair(p);
count = 0;
assert_se(sd_event_add_time_relative(e, &s, CLOCK_MONOTONIC, 1000, 1, ratelimit_time_handler, &count) >= 0);
assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10) == 0);
ASSERT_OK(sd_event_add_time_relative(e, &s, CLOCK_MONOTONIC, 1000, 1, ratelimit_time_handler, &count));
ASSERT_OK_ZERO(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10));
do {
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
ASSERT_OK(sd_event_run(e, UINT64_MAX));
} while (!sd_event_source_is_ratelimited(s));
log_info("ratelimit_time_handler: called %u times, event source got ratelimited", count);
assert_se(count == 10);
ASSERT_EQ(count, 10U);
/* In order to get rid of active rate limit client needs to disable it explicitly */
assert_se(sd_event_source_set_ratelimit(s, 0, 0) >= 0);
assert_se(!sd_event_source_is_ratelimited(s));
ASSERT_OK(sd_event_source_set_ratelimit(s, 0, 0));
ASSERT_OK_ZERO(sd_event_source_is_ratelimited(s));
assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10) >= 0);
ASSERT_OK(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10));
/* Set callback that will be invoked when we leave rate limited state. */
assert_se(sd_event_source_set_ratelimit_expire_callback(s, ratelimit_expired) >= 0);
ASSERT_OK(sd_event_source_set_ratelimit_expire_callback(s, ratelimit_expired));
do {
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
ASSERT_OK(sd_event_run(e, UINT64_MAX));
} while (!sd_event_source_is_ratelimited(s));
log_info("ratelimit_time_handler: called 10 more times, event source got ratelimited");
assert_se(count == 20);
ASSERT_EQ(count, 20U);
/* Dispatch the event loop once more and check that ratelimit expiration callback got called */
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
assert_se(expired == 0);
ASSERT_OK(sd_event_run(e, UINT64_MAX));
ASSERT_EQ(expired, 0);
}
TEST(simple_timeout) {
@ -707,29 +711,29 @@ TEST(simple_timeout) {
some_time = random_u64_range(2 * USEC_PER_SEC);
assert_se(sd_event_default(&e) >= 0);
ASSERT_OK(sd_event_default(&e));
assert_se(sd_event_prepare(e) == 0);
ASSERT_OK_ZERO(sd_event_prepare(e));
f = now(CLOCK_MONOTONIC);
assert_se(sd_event_wait(e, some_time) >= 0);
ASSERT_OK(sd_event_wait(e, some_time));
t = now(CLOCK_MONOTONIC);
/* The event loop may sleep longer than the specified time (timer accuracy, scheduling latencies, …),
* but never shorter. Let's check that. */
assert_se(t >= usec_add(f, some_time));
ASSERT_GE(t, usec_add(f, some_time));
}
static int inotify_self_destroy_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) {
sd_event_source **p = userdata;
assert_se(ev);
assert_se(p);
assert_se(*p == s);
ASSERT_NOT_NULL(ev);
ASSERT_NOT_NULL(p);
ASSERT_PTR_EQ(*p, s);
assert_se(FLAGS_SET(ev->mask, IN_ATTRIB));
ASSERT_TRUE(FLAGS_SET(ev->mask, IN_ATTRIB));
assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0);
ASSERT_OK(sd_event_exit(sd_event_source_get_event(s), 0));
*p = sd_event_source_unref(*p); /* here's what we actually intend to test: we destroy the event
* source from inside the event source handler */
@ -744,14 +748,13 @@ TEST(inotify_self_destroy) {
/* Tests that destroying an inotify event source from its own handler is safe */
assert_se(sd_event_default(&e) >= 0);
ASSERT_OK(sd_event_default(&e));
fd = mkostemp_safe(path);
assert_se(fd >= 0);
assert_se(sd_event_add_inotify_fd(e, &s, fd, IN_ATTRIB, inotify_self_destroy_handler, &s) >= 0);
ASSERT_OK(fd = mkostemp_safe(path));
ASSERT_OK(sd_event_add_inotify_fd(e, &s, fd, IN_ATTRIB, inotify_self_destroy_handler, &s));
fd = safe_close(fd);
assert_se(unlink(path) >= 0); /* This will trigger IN_ATTRIB because link count goes to zero */
assert_se(sd_event_loop(e) >= 0);
ASSERT_OK_ERRNO(unlink(path)); /* This will trigger IN_ATTRIB because link count goes to zero */
ASSERT_OK(sd_event_loop(e));
}
struct inotify_process_buffered_data_context {
@ -763,10 +766,10 @@ static int inotify_process_buffered_data_handler(sd_event_source *s, const struc
struct inotify_process_buffered_data_context *c = ASSERT_PTR(userdata);
const char *description;
assert_se(sd_event_source_get_description(s, &description) >= 0);
ASSERT_OK(sd_event_source_get_description(s, &description));
assert_se(c->i < 2);
assert_se(streq(c->path[c->i], description));
ASSERT_LT(c->i, 2U);
ASSERT_STREQ(c->path[c->i], description);
c->i++;
return 1;
@ -780,30 +783,30 @@ TEST(inotify_process_buffered_data) {
/* For issue #23826 */
assert_se(sd_event_default(&e) >= 0);
ASSERT_OK(sd_event_default(&e));
assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0);
assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &q) >= 0);
ASSERT_OK(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p));
ASSERT_OK(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &q));
struct inotify_process_buffered_data_context context = {
.path = { p, q },
};
assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE, inotify_process_buffered_data_handler, &context) >= 0);
assert_se(sd_event_add_inotify(e, &b, q, IN_CREATE, inotify_process_buffered_data_handler, &context) >= 0);
ASSERT_OK(sd_event_add_inotify(e, &a, p, IN_CREATE, inotify_process_buffered_data_handler, &context));
ASSERT_OK(sd_event_add_inotify(e, &b, q, IN_CREATE, inotify_process_buffered_data_handler, &context));
assert_se(z = path_join(p, "aaa"));
assert_se(touch(z) >= 0);
ASSERT_NOT_NULL(z = path_join(p, "aaa"));
ASSERT_OK(touch(z));
z = mfree(z);
assert_se(z = path_join(q, "bbb"));
assert_se(touch(z) >= 0);
ASSERT_NOT_NULL(z = path_join(q, "bbb"));
ASSERT_OK(touch(z));
z = mfree(z);
assert_se(sd_event_run(e, 10 * USEC_PER_SEC) > 0);
assert_se(sd_event_prepare(e) > 0); /* issue #23826: this was 0. */
assert_se(sd_event_dispatch(e) > 0);
assert_se(sd_event_prepare(e) == 0);
assert_se(sd_event_wait(e, 0) == 0);
ASSERT_OK_POSITIVE(sd_event_run(e, 10 * USEC_PER_SEC));
ASSERT_OK_POSITIVE(sd_event_prepare(e)); /* issue #23826: this was 0. */
ASSERT_OK_POSITIVE(sd_event_dispatch(e));
ASSERT_OK_ZERO(sd_event_prepare(e));
ASSERT_OK_ZERO(sd_event_wait(e, 0));
}
static int inotify_handler_issue_38265(sd_event_source *s, const struct inotify_event *event, void *userdata) {
@ -844,19 +847,19 @@ TEST(fork) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
int r;
assert_se(sd_event_default(&e) >= 0);
assert_se(sd_event_prepare(e) == 0);
ASSERT_OK(sd_event_default(&e));
ASSERT_OK_ZERO(sd_event_prepare(e));
/* Check that after a fork the cleanup functions return NULL */
r = safe_fork("(bus-fork-test)", FORK_WAIT|FORK_LOG, NULL);
if (r == 0) {
assert_se(e);
assert_se(sd_event_ref(e) == NULL);
assert_se(sd_event_unref(e) == NULL);
ASSERT_NOT_NULL(e);
ASSERT_NULL(sd_event_ref(e));
ASSERT_NULL(sd_event_unref(e));
_exit(EXIT_SUCCESS);
}
assert_se(r >= 0);
ASSERT_OK(r);
}
TEST(sd_event_source_set_io_fd) {
@ -864,23 +867,23 @@ TEST(sd_event_source_set_io_fd) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
_cleanup_close_pair_ int pfd_a[2] = EBADF_PAIR, pfd_b[2] = EBADF_PAIR;
assert_se(sd_event_default(&e) >= 0);
ASSERT_OK(sd_event_default(&e));
assert_se(pipe2(pfd_a, O_CLOEXEC) >= 0);
assert_se(pipe2(pfd_b, O_CLOEXEC) >= 0);
ASSERT_OK_ERRNO(pipe2(pfd_a, O_CLOEXEC));
ASSERT_OK_ERRNO(pipe2(pfd_b, O_CLOEXEC));
assert_se(sd_event_add_io(e, &s, pfd_a[0], EPOLLIN, NULL, INT_TO_PTR(-ENOANO)) >= 0);
assert_se(sd_event_source_set_io_fd_own(s, true) >= 0);
ASSERT_OK(sd_event_add_io(e, &s, pfd_a[0], EPOLLIN, NULL, INT_TO_PTR(-ENOANO)));
ASSERT_OK(sd_event_source_set_io_fd_own(s, true));
TAKE_FD(pfd_a[0]);
assert_se(sd_event_source_set_io_fd(s, pfd_b[0]) >= 0);
ASSERT_OK(sd_event_source_set_io_fd(s, pfd_b[0]));
TAKE_FD(pfd_b[0]);
}
static int hup_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
unsigned *c = userdata;
assert_se(revents == EPOLLHUP);
ASSERT_EQ(revents, (uint32_t) EPOLLHUP);
(*c)++;
return 0;
@ -894,47 +897,42 @@ TEST(leave_ratelimit) {
unsigned c = 0;
int r;
assert_se(sd_event_default(&e) >= 0);
ASSERT_OK(sd_event_default(&e));
/* Create an event source that will continuously fire by creating a pipe whose write side is closed,
* and which hence will only see EOF and constant EPOLLHUP */
assert_se(pipe2(pfd, O_CLOEXEC) >= 0);
assert_se(sd_event_add_io(e, &s, pfd[0], EPOLLIN, hup_callback, &c) >= 0);
assert_se(sd_event_source_set_io_fd_own(s, true) >= 0);
assert_se(sd_event_source_set_ratelimit(s, 5*USEC_PER_MINUTE, 5) >= 0);
ASSERT_OK_ERRNO(pipe2(pfd, O_CLOEXEC));
ASSERT_OK(sd_event_add_io(e, &s, pfd[0], EPOLLIN, hup_callback, &c));
ASSERT_OK(sd_event_source_set_io_fd_own(s, true));
ASSERT_OK(sd_event_source_set_ratelimit(s, 5*USEC_PER_MINUTE, 5));
pfd[0] = -EBADF;
pfd[1] = safe_close(pfd[1]); /* Trigger continuous EOF */
for (;;) {
r = sd_event_prepare(e);
assert_se(r >= 0);
ASSERT_OK(r = sd_event_prepare(e));
if (r == 0) {
r = sd_event_wait(e, UINT64_MAX);
assert_se(r > 0);
}
if (r == 0)
ASSERT_OK_POSITIVE(sd_event_wait(e, UINT64_MAX));
r = sd_event_dispatch(e);
assert_se(r > 0);
ASSERT_OK_POSITIVE(sd_event_dispatch(e));
r = sd_event_source_is_ratelimited(s);
assert_se(r >= 0);
ASSERT_OK(r = sd_event_source_is_ratelimited(s));
if (c < 5)
/* First four dispatches should just work */
assert_se(!r);
ASSERT_FALSE(r);
else if (c == 5) {
/* The fifth dispatch should still work, but we now expect the ratelimit to be hit subsequently */
if (!expect_ratelimit) {
assert_se(!r);
assert_se(sd_event_source_leave_ratelimit(s) == 0); /* this should be a NOP, and return 0 hence */
ASSERT_FALSE(r);
ASSERT_OK_ZERO(sd_event_source_leave_ratelimit(s)); /* this should be a NOP, and return 0 hence */
expect_ratelimit = true;
} else {
/* We expected the ratelimit, let's leave it manually, and verify it */
assert_se(r);
assert_se(sd_event_source_leave_ratelimit(s) > 0); /* we are ratelimited, hence should return > 0 */
assert_se(sd_event_source_is_ratelimited(s) == 0);
ASSERT_TRUE(r);
ASSERT_OK_POSITIVE(sd_event_source_leave_ratelimit(s)); /* we are ratelimited, hence should return > 0 */
ASSERT_OK_ZERO(sd_event_source_is_ratelimited(s));
manually_left_ratelimit = true;
}
@ -945,7 +943,7 @@ TEST(leave_ratelimit) {
}
/* Verify we definitely hit the ratelimit and left it manually again */
assert_se(manually_left_ratelimit);
ASSERT_TRUE(manually_left_ratelimit);
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -4131,28 +4131,12 @@ int journal_file_open(
.last_direction = _DIRECTION_INVALID,
};
if (fname) {
f->path = strdup(fname);
if (!f->path) {
r = -ENOMEM;
goto fail;
}
} else {
assert(fd >= 0);
/* If we don't know the path, fill in something explanatory and vaguely useful */
if (asprintf(&f->path, "/proc/self/%i", fd) < 0) {
r = -ENOMEM;
goto fail;
}
}
if (f->fd < 0) {
/* We pass O_NONBLOCK here, so that in case somebody pointed us to some character device node or FIFO
* or so, we likely fail quickly than block for long. For regular files O_NONBLOCK has no effect, hence
* it doesn't hurt in that case. */
f->fd = openat_report_new(AT_FDCWD, f->path, f->open_flags|O_CLOEXEC|O_NONBLOCK, f->mode, &newly_created);
f->fd = openat_report_new(AT_FDCWD, fname, f->open_flags|O_CLOEXEC|O_NONBLOCK, f->mode, &newly_created);
if (f->fd < 0) {
r = f->fd;
goto fail;
@ -4165,12 +4149,23 @@ int journal_file_open(
if (r < 0)
goto fail;
r = fd_get_path(f->fd, &f->path);
if (r < 0)
goto fail;
if (!newly_created) {
r = journal_file_fstat(f);
if (r < 0)
goto fail;
}
} else {
/* If we don't know the path, fill in something explanatory and vaguely useful */
f->path = strdup(fname ?: FORMAT_PROC_FD_PATH(fd));
if (!f->path) {
r = -ENOMEM;
goto fail;
}
r = journal_file_fstat(f);
if (r < 0)
goto fail;

View File

@ -1580,6 +1580,7 @@ static int add_any_file(
const char *path) {
_cleanup_close_ int our_fd = -EBADF;
_cleanup_free_ char *resolved_path = NULL;
JournalFile *f;
struct stat st;
int r;
@ -1606,6 +1607,14 @@ static int add_any_file(
r = log_debug_errno(errno, "Failed to turn off O_NONBLOCK for %s: %m", path);
goto error;
}
r = fd_get_path(fd, &resolved_path);
if (r < 0) {
r = log_debug_errno(r, "Failed to resolve path '%s': %m", path);
goto error;
}
path = resolved_path;
}
if (fstat(fd, &st) < 0) {
@ -1740,7 +1749,7 @@ static int add_file_by_name(
if (!path)
return -ENOMEM;
return add_any_file(j, -1, path);
return add_any_file(j, /* fd = */ -EBADF, path);
}
static int remove_file_by_name(
@ -2427,7 +2436,7 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
return -ENOMEM;
STRV_FOREACH(path, paths) {
r = add_any_file(j, -1, *path);
r = add_any_file(j, /* fd = */ -EBADF, *path);
if (r < 0)
return r;
}
@ -2514,7 +2523,7 @@ _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fd
if (r < 0)
goto fail;
r = add_any_file(j, fds[i], NULL);
r = add_any_file(j, fds[i], /* path = */ NULL);
if (r < 0)
goto fail;
}

View File

@ -531,8 +531,8 @@ static int method_set_display(sd_bus_message *message, void *userdata, sd_bus_er
static int method_set_tty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Session *s = ASSERT_PTR(userdata);
int fd, r, flags;
_cleanup_free_ char *q = NULL;
int fd, r;
assert(message);
@ -543,15 +543,11 @@ static int method_set_tty(sd_bus_message *message, void *userdata, sd_bus_error
if (!session_is_controller(s, sd_bus_message_get_sender(message)))
return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You must be in control of this session to set tty");
assert(fd >= 0);
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0)
return -errno;
if ((flags & O_ACCMODE_STRICT) != O_RDWR)
r = fd_vet_accmode(fd, O_RDWR);
if (r == -EPROTOTYPE)
return -EACCES;
if (FLAGS_SET(flags, O_PATH))
return -ENOTTY;
if (r < 0)
return r;
r = getttyname_malloc(fd, &q);
if (r < 0)

8
src/run/empower.rules Normal file
View File

@ -0,0 +1,8 @@
// Allow all actions for users who are in the "empower" group. Users are added to the
// "empower" group by running run0 --empower.
polkit.addRule(function(action, subject) {
if (subject.isInGroup("empower")) {
return polkit.Result.YES;
}
});

View File

@ -18,3 +18,8 @@ custom_target(
command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'],
install : pamconfdir != 'no',
install_dir : pamconfdir)
if install_polkit
install_data('empower.rules',
install_dir : polkitrulesdir)
endif

View File

@ -1420,6 +1420,15 @@ static int transient_service_set_properties(sd_bus_message *m, const char *pty_p
r = sd_bus_message_append(m, "(sv)", "AmbientCapabilities", "t", CAP_MASK_ALL);
if (r < 0)
return bus_log_create_error(r);
r = getgrnam_malloc("empower", /* ret= */ NULL);
if (r < 0 && r != -ESRCH)
return log_error_errno(r, "Failed to look up group 'empower' via NSS: %m");
if (r >= 0) {
r = sd_bus_message_append(m, "(sv)", "SupplementaryGroups", "as", 1, "empower");
if (r < 0)
return bus_log_create_error(r);
}
}
if (arg_nice_set) {

View File

@ -370,9 +370,10 @@ int calendar_spec_to_string(const CalendarSpec *c, char **ret) {
tzset();
if (!isempty(tzname[c->dst])) {
const char *z = get_tzname(c->dst);
if (z) {
fputc(' ', f);
fputs(tzname[c->dst], f);
fputs(z, f);
}
}
@ -897,10 +898,11 @@ int calendar_spec_from_string(const char *p, CalendarSpec **ret) {
/* Check if the local timezone was specified? */
for (j = 0; j <= 1; j++) {
if (isempty(tzname[j]))
const char *z = get_tzname(j);
if (!z)
continue;
e = endswith_no_case(p, tzname[j]);
e = endswith_no_case(p, z);
if (!e)
continue;
if (e == p)

View File

@ -175,7 +175,12 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
unsigned long long: "%llu")
#ifdef __COVERITY__
# define ASSERT_OK(expr) __coverity_check__((expr) >= 0)
# define ASSERT_OK(expr) \
({ \
typeof(expr) _result = (expr); \
__coverity_check__(_result >= 0); \
_result; \
})
#else
# define ASSERT_OK(expr) \
({ \
@ -183,6 +188,7 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
if (_result < 0) \
log_test_failed("Expected \"%s\" to succeed, but got error: %"PRIiMAX"/%s", \
#expr, (intmax_t) _result, ERRNO_NAME(_result)); \
_result; \
})
#endif
@ -190,7 +196,8 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
# define ASSERT_OK_OR(expr, ...) \
({ \
typeof(expr) _result = (expr); \
__coverity_check__(_result >= 0 || IN_SET(_result, 0, __VA_ARGS__) \
__coverity_check__(_result >= 0 || IN_SET(_result, 0, __VA_ARGS__); \
_result; \
})
#else
# define ASSERT_OK_OR(expr, ...) \
@ -199,12 +206,18 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
if (_result < 0 && !IN_SET(_result, 0, __VA_ARGS__)) \
log_test_failed("\"%s\" failed with unexpected error: %"PRIiMAX"/%s", \
#expr, (intmax_t) _result, ERRNO_NAME(_result)); \
_result; \
})
#endif
/* For functions that return a boolean on success and a negative errno on failure. */
#ifdef __COVERITY__
# define ASSERT_OK_POSITIVE(expr) __coverity_check__((expr) > 0)
# define ASSERT_OK_POSITIVE(expr) \
({ \
typeof(expr) _result = (expr); \
__coverity_check__(_result > 0); \
_result; \
})
#else
# define ASSERT_OK_POSITIVE(expr) \
({ \
@ -214,11 +227,17 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
#expr, (intmax_t) _result, ERRNO_NAME(_result)); \
if (_result == 0) \
log_test_failed("Expected \"%s\" to be positive, but it is zero.", #expr); \
_result; \
})
#endif
#ifdef __COVERITY__
# define ASSERT_OK_ZERO(expr) __coverity_check__((expr) == 0)
# define ASSERT_OK_ZERO(expr) \
({ \
typeof(expr) _result = (expr); \
__coverity_check__(_result == 0); \
_result; \
})
#else
# define ASSERT_OK_ZERO(expr) \
({ \
@ -229,11 +248,18 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
if (_result != 0) \
log_test_failed("Expected \"%s\" to be zero, but it is %"PRIiMAX".", \
#expr, (intmax_t) _result); \
_result; \
})
#endif
#ifdef __COVERITY__
# define ASSERT_OK_EQ(expr1, expr2) __coverity_check__((expr1) == (expr2))
# define ASSERT_OK_EQ(expr1, expr2) \
({ \
typeof(expr1) _expr1 = (expr1); \
typeof(expr2) _expr2 = (expr2); \
__coverity_check__(_expr1 == _expr2); \
_expr1; \
})
#else
# define ASSERT_OK_EQ(expr1, expr2) \
({ \
@ -245,12 +271,18 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
if (_expr1 != _expr2) \
log_test_failed("Expected \"%s == %s\", got %"PRIiMAX" != %"PRIiMAX, \
#expr1, #expr2, (intmax_t) _expr1, (intmax_t) _expr2); \
_expr1; \
})
#endif
/* For functions that return a boolean on success and set errno on failure. */
#ifdef __COVERITY__
# define ASSERT_OK_ERRNO(expr) __coverity_check__((expr) >= 0)
# define ASSERT_OK_ERRNO(expr) \
({ \
typeof(expr) _result = (expr); \
__coverity_check__(_result >= 0); \
_result; \
})
#else
# define ASSERT_OK_ERRNO(expr) \
({ \
@ -258,11 +290,17 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
if (_result < 0) \
log_test_failed("Expected \"%s\" to succeed, but got errno: %d/%s", \
#expr, errno, ERRNO_NAME(errno)); \
_result; \
})
#endif
#ifdef __COVERITY__
# define ASSERT_OK_ZERO_ERRNO(expr) __coverity_check__((expr) == 0)
# define ASSERT_OK_ZERO_ERRNO(expr) \
({ \
typeof(expr) _result = (expr); \
__coverity_check__(_result == 0); \
_result; \
})
#else
# define ASSERT_OK_ZERO_ERRNO(expr) \
({ \
@ -273,11 +311,18 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
if (_result != 0) \
log_test_failed("Expected \"%s\" to be zero, but it is %"PRIiMAX".", \
#expr, (intmax_t) _result); \
_result; \
})
#endif
#ifdef __COVERITY__
# define ASSERT_OK_EQ_ERRNO(expr1, expr2) __coverity_check__((expr1) == (expr2))
# define ASSERT_OK_EQ_ERRNO(expr1, expr2) \
({ \
typeof(expr1) _expr1 = (expr1); \
typeof(expr2) _expr2 = (expr2); \
__coverity_check__(_expr1 == _expr2); \
_expr1; \
})
#else
# define ASSERT_OK_EQ_ERRNO(expr1, expr2) \
({ \
@ -289,22 +334,35 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
if (_expr1 != _expr2) \
log_test_failed("Expected \"%s == %s\", but %"PRIiMAX" != %"PRIiMAX, \
#expr1, #expr2, (intmax_t) _expr1, (intmax_t) _expr2); \
_expr1; \
})
#endif
#ifdef __COVERITY__
# define ASSERT_FAIL(expr) __coverity_check__((expr) < 0)
# define ASSERT_FAIL(expr) \
({ \
typeof(expr) _result = (expr); \
__coverity_check__(_result < 0); \
_result; \
})
#else
# define ASSERT_FAIL(expr) \
({ \
typeof(expr) _result = (expr); \
if (_result >= 0) \
log_test_failed("Expected \"%s\" to fail, but it succeeded.", #expr); \
_result; \
})
#endif
#ifdef __COVERITY__
# define ASSERT_ERROR(expr1, expr2) __coverity_check__((expr1) == -(expr2))
# define ASSERT_ERROR(expr1, expr2) \
({ \
int _expr1 = (expr1); \
int _expr2 = (expr2); \
__coverity_check__((_expr1) == -(_expr2)); \
_expr1; \
})
#else
# define ASSERT_ERROR(expr1, expr2) \
({ \
@ -316,11 +374,18 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
else if (-_expr1 != _expr2) \
log_test_failed("Expected \"%s\" to fail with error %d/%s, but got %d/%s", \
#expr1, -_expr2, ERRNO_NAME(_expr2), _expr1, ERRNO_NAME(_expr1)); \
_expr1; \
})
#endif
#ifdef __COVERITY__
# define ASSERT_ERROR_ERRNO(expr1, expr2) __coverity_check__((expr1) < 0 && errno == (expr2))
# define ASSERT_ERROR_ERRNO(expr1, expr2) \
({ \
int _expr1 = (expr1); \
int _expr2 = (expr2); \
__coverity_check__(_expr1 < 0 && errno == _expr2); \
_expr1; \
})
#else
# define ASSERT_ERROR_ERRNO(expr1, expr2) \
({ \
@ -332,6 +397,7 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
else if (errno != _expr2) \
log_test_failed("Expected \"%s\" to fail with errno %d/%s, but got %d/%s", \
#expr1, _expr2, ERRNO_NAME(_expr2), errno, ERRNO_NAME(errno)); \
_expr1; \
})
#endif

View File

@ -26,8 +26,13 @@
#include "tests.h"
#include "tpm2-util.h"
#define ASSERT_DLOPEN(func, cond) \
cond ? ASSERT_OK(func()) : ASSERT_ERROR(func(), EOPNOTSUPP)
#define ASSERT_DLOPEN(func, cond) \
do { \
if (cond) \
ASSERT_OK(func()); \
else \
ASSERT_ERROR(func(), EOPNOTSUPP); \
} while (false)
static int run(int argc, char **argv) {
test_setup_logging(LOG_DEBUG);

View File

@ -878,4 +878,29 @@ TEST(fd_get_path) {
assert_se(chdir(saved_cwd) >= 0);
}
TEST(fd_vet_accmode) {
_cleanup_(unlink_tempfilep) char name[] = "/tmp/test-fd-accmode.XXXXXX";
_cleanup_close_ int fd_rw = -EBADF, fd_ro = -EBADF, fd_wo = -EBADF, fd_opath = -EBADF;
ASSERT_OK(fd_rw = mkostemp_safe(name));
ASSERT_OK_ZERO(fd_vet_accmode(fd_rw, O_RDONLY));
ASSERT_OK_ZERO(fd_vet_accmode(fd_rw, O_WRONLY));
ASSERT_OK_POSITIVE(fd_vet_accmode(fd_rw, O_RDWR));
ASSERT_OK_ERRNO(fd_ro = open(name, O_RDONLY | O_CLOEXEC));
ASSERT_OK_POSITIVE(fd_vet_accmode(fd_ro, O_RDONLY));
ASSERT_ERROR(fd_vet_accmode(fd_ro, O_WRONLY), EPROTOTYPE);
ASSERT_ERROR(fd_vet_accmode(fd_ro, O_RDWR), EPROTOTYPE);
ASSERT_OK_ERRNO(fd_wo = open(name, O_WRONLY | O_CLOEXEC));
ASSERT_ERROR(fd_vet_accmode(fd_wo, O_RDONLY), EPROTOTYPE);
ASSERT_OK_POSITIVE(fd_vet_accmode(fd_wo, O_WRONLY));
ASSERT_ERROR(fd_vet_accmode(fd_wo, O_RDWR), EPROTOTYPE);
ASSERT_OK_ERRNO(fd_opath = open(name, O_PATH | O_CLOEXEC));
ASSERT_ERROR(fd_vet_accmode(fd_opath, O_RDONLY), EBADFD);
ASSERT_ERROR(fd_vet_accmode(fd_opath, O_WRONLY), EBADFD);
ASSERT_ERROR(fd_vet_accmode(fd_opath, O_RDWR), EBADFD);
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -14,76 +14,80 @@ static void test_rm_rf_chmod_inner(void) {
const char *a, *b, *x, *y;
struct stat st;
assert_se(getuid() != 0);
ASSERT_NE(getuid(), 0U);
assert_se(mkdtemp_malloc("/tmp/test-rm-rf.XXXXXXX", &d) >= 0);
ASSERT_OK(mkdtemp_malloc("/tmp/test-rm-rf.XXXXXXX", &d));
a = strjoina(d, "/a");
b = strjoina(a, "/b");
x = strjoina(d, "/x");
y = strjoina(x, "/y");
assert_se(mkdir(x, 0700) >= 0);
assert_se(mknod(y, S_IFREG | 0600, 0) >= 0);
ASSERT_OK_ERRNO(mkdir(x, 0700));
ASSERT_OK_ERRNO(mknod(y, S_IFREG | 0600, 0));
assert_se(chmod(y, 0400) >= 0);
assert_se(chmod(x, 0500) >= 0);
assert_se(chmod(d, 0500) >= 0);
ASSERT_OK_ERRNO(chmod(y, 0400));
ASSERT_OK_ERRNO(chmod(x, 0500));
ASSERT_OK_ERRNO(chmod(d, 0500));
assert_se(rm_rf(d, REMOVE_PHYSICAL) == -EACCES);
ASSERT_ERROR(rm_rf(d, REMOVE_PHYSICAL), EACCES);
assert_se(access(d, F_OK) >= 0);
assert_se(access(x, F_OK) >= 0);
assert_se(access(y, F_OK) >= 0);
ASSERT_OK_ERRNO(access(d, F_OK));
ASSERT_OK_ERRNO(access(x, F_OK));
ASSERT_OK_ERRNO(access(y, F_OK));
assert_se(rm_rf(d, REMOVE_PHYSICAL|REMOVE_CHMOD) >= 0);
ASSERT_OK(rm_rf(d, REMOVE_PHYSICAL|REMOVE_CHMOD));
assert_se(access(d, F_OK) >= 0);
assert_se(access(x, F_OK) < 0 && errno == ENOENT);
assert_se(access(y, F_OK) < 0 && errno == ENOENT);
ASSERT_OK_ERRNO(access(d, F_OK));
ASSERT_ERROR_ERRNO(access(x, F_OK), ENOENT);
ASSERT_ERROR_ERRNO(access(y, F_OK), ENOENT);
assert_se(mkdir(a, 0700) >= 0);
assert_se(mkdir(b, 0700) >= 0);
assert_se(mkdir(x, 0700) >= 0);
assert_se(mknod(y, S_IFREG | 0600, 0) >= 0);
ASSERT_OK_ERRNO(mkdir(a, 0700));
ASSERT_OK_ERRNO(mkdir(b, 0700));
ASSERT_OK_ERRNO(mkdir(x, 0700));
ASSERT_OK_ERRNO(mknod(y, S_IFREG | 0600, 0));
assert_se(chmod(b, 0000) >= 0);
assert_se(chmod(a, 0000) >= 0);
assert_se(chmod(y, 0000) >= 0);
assert_se(chmod(x, 0000) >= 0);
assert_se(chmod(d, 0500) >= 0);
ASSERT_OK_ERRNO(chmod(b, 0000));
ASSERT_OK_ERRNO(chmod(a, 0000));
ASSERT_OK_ERRNO(chmod(y, 0000));
ASSERT_OK_ERRNO(chmod(x, 0000));
ASSERT_OK_ERRNO(chmod(d, 0500));
assert_se(rm_rf(d, REMOVE_PHYSICAL|REMOVE_CHMOD|REMOVE_CHMOD_RESTORE|REMOVE_ONLY_DIRECTORIES) == -ENOTEMPTY);
ASSERT_ERROR(rm_rf(d, REMOVE_PHYSICAL|REMOVE_CHMOD|REMOVE_CHMOD_RESTORE|REMOVE_ONLY_DIRECTORIES), ENOTEMPTY);
assert_se(access(a, F_OK) < 0 && errno == ENOENT);
assert_se(access(d, F_OK) >= 0);
assert_se(stat(d, &st) >= 0 && (st.st_mode & 07777) == 0500);
assert_se(access(x, F_OK) >= 0);
assert_se(stat(x, &st) >= 0 && (st.st_mode & 07777) == 0000);
assert_se(chmod(x, 0700) >= 0);
assert_se(access(y, F_OK) >= 0);
assert_se(stat(y, &st) >= 0 && (st.st_mode & 07777) == 0000);
ASSERT_ERROR_ERRNO(access(a, F_OK), ENOENT);
ASSERT_OK_ERRNO(access(d, F_OK));
ASSERT_OK_ERRNO(stat(d, &st));
ASSERT_EQ(st.st_mode & 07777, 0500U);
ASSERT_OK_ERRNO(access(x, F_OK));
ASSERT_OK_ERRNO(stat(x, &st));
ASSERT_EQ(st.st_mode & 07777, 0000U);
ASSERT_OK_ERRNO(chmod(x, 0700));
ASSERT_OK_ERRNO(access(y, F_OK));
ASSERT_OK_ERRNO(stat(y, &st));
ASSERT_EQ(st.st_mode & 07777, 0000U);
assert_se(chmod(y, 0000) >= 0);
assert_se(chmod(x, 0000) >= 0);
assert_se(chmod(d, 0000) >= 0);
ASSERT_OK_ERRNO(chmod(y, 0000));
ASSERT_OK_ERRNO(chmod(x, 0000));
ASSERT_OK_ERRNO(chmod(d, 0000));
assert_se(rm_rf(d, REMOVE_PHYSICAL|REMOVE_CHMOD|REMOVE_CHMOD_RESTORE) >= 0);
ASSERT_OK(rm_rf(d, REMOVE_PHYSICAL|REMOVE_CHMOD|REMOVE_CHMOD_RESTORE));
assert_se(stat(d, &st) >= 0 && (st.st_mode & 07777) == 0000);
assert_se(access(d, F_OK) >= 0);
assert_se(chmod(d, 0700) >= 0);
assert_se(access(x, F_OK) < 0 && errno == ENOENT);
ASSERT_OK_ERRNO(stat(d, &st));
ASSERT_EQ(st.st_mode & 07777, 0000U);
ASSERT_OK_ERRNO(access(d, F_OK));
ASSERT_OK_ERRNO(chmod(d, 0700));
ASSERT_ERROR_ERRNO(access(x, F_OK), ENOENT);
assert_se(mkdir(x, 0700) >= 0);
assert_se(mknod(y, S_IFREG | 0600, 0) >= 0);
ASSERT_OK_ERRNO(mkdir(x, 0700));
ASSERT_OK_ERRNO(mknod(y, S_IFREG | 0600, 0));
assert_se(chmod(y, 0000) >= 0);
assert_se(chmod(x, 0000) >= 0);
assert_se(chmod(d, 0000) >= 0);
ASSERT_OK_ERRNO(chmod(y, 0000));
ASSERT_OK_ERRNO(chmod(x, 0000));
ASSERT_OK_ERRNO(chmod(d, 0000));
assert_se(rm_rf(d, REMOVE_PHYSICAL|REMOVE_CHMOD|REMOVE_ROOT) >= 0);
ASSERT_OK(rm_rf(d, REMOVE_PHYSICAL|REMOVE_CHMOD|REMOVE_ROOT));
assert_se(access(d, F_OK) < 0 && errno == ENOENT);
ASSERT_ERROR_ERRNO(access(d, F_OK), ENOENT);
}
TEST(rm_rf_chmod) {
@ -96,13 +100,12 @@ TEST(rm_rf_chmod) {
/* This test only works unpriv (as only then the access mask for the owning user matters),
* hence drop privs here */
r = safe_fork("(setresuid)", FORK_DEATHSIG_SIGTERM|FORK_WAIT, NULL);
assert_se(r >= 0);
ASSERT_OK(r = safe_fork("(setresuid)", FORK_DEATHSIG_SIGTERM|FORK_WAIT, NULL));
if (r == 0) {
/* child */
assert_se(setresuid(1, 1, 1) >= 0);
ASSERT_OK_ERRNO(setresuid(1, 1, 1));
test_rm_rf_chmod_inner();
_exit(EXIT_SUCCESS);

View File

@ -15,7 +15,7 @@
static void set_timezone(const char *tz) {
ASSERT_OK(set_unset_env("TZ", tz, /* overwrite = */ true));
tzset();
log_info("TZ=%s, tzname[0]=%s, tzname[1]=%s", strna(getenv("TZ")), strempty(tzname[0]), strempty(tzname[1]));
log_info("TZ=%s, tzname[0]=%s, tzname[1]=%s", strna(getenv("TZ")), strempty(get_tzname(/* dst= */ false)), strempty(get_tzname(/* dst= */ true)));
}
TEST(parse_sec) {
@ -400,6 +400,28 @@ static void test_format_timestamp_impl(usec_t x) {
const char *xx = FORMAT_TIMESTAMP(x);
ASSERT_NOT_NULL(xx);
/* Because of the timezone change, format_timestamp() may set timezone that is currently unused.
* E.g. Africa/Juba uses EAT since Sat Jan 15 10:00:00 2000 and until Sun Jan 31 20:59:59 2021, but
* now CAT/CAST is used there (see zdump for more details). In such cases, format_timestamp() may set
* the timezone used at the specified time (which happens when built with musl), but it may not match
* the timezone currently used, thus we may not parse back the timestamp. */
const char *space;
ASSERT_NOT_NULL(space = strrchr(xx, ' '));
const char *tz = space + 1;
if (!streq_ptr(tz, get_tzname(/* dst= */ false)) &&
!streq_ptr(tz, get_tzname(/* dst= */ true)) &&
parse_gmtoff(tz, NULL) < 0) {
log_warning("@" USEC_FMT " → %s, timezone '%s' is currently unused, ignoring.", x, xx, tz);
/* Verify the generated string except for the timezone part. Of course, in most cases, parsed
* time does not match with the input, hence only check if it is parsable. */
ASSERT_OK(parse_timestamp(strndupa_safe(xx, space - xx), NULL));
return;
}
usec_t y;
ASSERT_OK(parse_timestamp(xx, &y));
const char *yy = FORMAT_TIMESTAMP(y);
@ -1109,15 +1131,15 @@ TEST(in_utc_timezone) {
assert_se(setenv("TZ", "UTC", 1) >= 0);
assert_se(in_utc_timezone());
ASSERT_STREQ(tzname[0], "UTC");
ASSERT_STREQ(tzname[1], "UTC");
ASSERT_STREQ(get_tzname(/* dst= */ false), "UTC");
ASSERT_STREQ(get_tzname(/* dst= */ true), "UTC");
assert_se(timezone == 0);
assert_se(daylight == 0);
assert_se(setenv("TZ", "Europe/Berlin", 1) >= 0);
assert_se(!in_utc_timezone());
ASSERT_STREQ(tzname[0], "CET");
ASSERT_STREQ(tzname[1], "CEST");
ASSERT_STREQ(get_tzname(/* dst= */ false), "CET");
ASSERT_STREQ(get_tzname(/* dst= */ true), "CEST");
}
TEST(map_clock_usec) {

View File

@ -34,20 +34,14 @@ static int method_something(sd_varlink *link, sd_json_variant *parameters, sd_va
int r;
a = sd_json_variant_by_key(parameters, "a");
if (!a) {
r = sd_varlink_error(link, "io.test.BadParameters", NULL);
assert_se(r == -EBADR);
return r;
}
if (!a)
return ASSERT_ERROR(sd_varlink_error(link, "io.test.BadParameters", NULL), EBADR);
x = sd_json_variant_integer(a);
b = sd_json_variant_by_key(parameters, "b");
if (!b) {
r = sd_varlink_error(link, "io.test.BadParameters", NULL);
assert_se(r == -EBADR);
return r;
}
if (!b)
return ASSERT_ERROR(sd_varlink_error(link, "io.test.BadParameters", NULL), EBADR);
y = sd_json_variant_integer(b);
@ -101,9 +95,8 @@ static void test_fd(int fd, const void *buf, size_t n) {
char rbuf[n + 1];
ssize_t m;
m = read(fd, rbuf, n + 1);
assert_se(m >= 0);
assert_se(memcmp_nn(buf, n, rbuf, m) == 0);
ASSERT_OK_ERRNO(m = read(fd, rbuf, n + 1));
ASSERT_OK_ZERO(memcmp_nn(buf, n, rbuf, m));
}
static int method_passfd(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
@ -112,40 +105,32 @@ static int method_passfd(sd_varlink *link, sd_json_variant *parameters, sd_varli
int r;
a = sd_json_variant_by_key(parameters, "fd");
if (!a) {
r = sd_varlink_error_invalid_parameter_name(link, "fd");
assert_se(r == -EINVAL);
return r;
}
if (!a)
return ASSERT_ERROR(sd_varlink_error_invalid_parameter_name(link, "fd"), EINVAL);
ASSERT_STREQ(sd_json_variant_string(a), "whoop");
int xx = sd_varlink_peek_fd(link, 0),
yy = sd_varlink_peek_fd(link, 1),
zz = sd_varlink_peek_fd(link, 2);
int xx, yy, zz;
ASSERT_OK(xx = sd_varlink_peek_fd(link, 0));
ASSERT_OK(yy = sd_varlink_peek_fd(link, 1));
ASSERT_OK(zz = sd_varlink_peek_fd(link, 2));
log_info("%i %i %i", xx, yy, zz);
assert_se(xx >= 0);
assert_se(yy >= 0);
assert_se(zz >= 0);
test_fd(xx, "foo", 3);
test_fd(yy, "bar", 3);
test_fd(zz, "quux", 4);
_cleanup_close_ int vv = memfd_new_and_seal_string("data", "miau");
_cleanup_close_ int ww = memfd_new_and_seal_string("data", "wuff");
assert_se(vv >= 0);
assert_se(ww >= 0);
_cleanup_close_ int vv = -EBADF, ww = -EBADF;
ASSERT_OK(vv = memfd_new_and_seal_string("data", "miau"));
ASSERT_OK(ww = memfd_new_and_seal_string("data", "wuff"));
r = sd_json_build(&ret, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("yo", SD_JSON_BUILD_INTEGER(88))));
if (r < 0)
return r;
assert_se(sd_varlink_push_fd(link, vv) == 0);
assert_se(sd_varlink_push_fd(link, ww) == 1);
ASSERT_OK_EQ(sd_varlink_push_fd(link, vv), 0);
ASSERT_OK_EQ(sd_varlink_push_fd(link, ww), 1);
TAKE_FD(vv);
TAKE_FD(ww);
@ -176,7 +161,7 @@ static int reply(sd_varlink *link, sd_json_variant *parameters, const char *erro
sum = sd_json_variant_by_key(parameters, "sum");
assert_se(sd_json_variant_integer(sum) == 7+22);
ASSERT_EQ(sd_json_variant_integer(sum), 7+22);
if (++n_done == 2)
sd_event_exit(sd_varlink_get_event(link), EXIT_FAILURE);
@ -187,13 +172,13 @@ static int reply(sd_varlink *link, sd_json_variant *parameters, const char *erro
static int on_connect(sd_varlink_server *s, sd_varlink *link, void *userdata) {
uid_t uid = UID_INVALID;
assert_se(s);
assert_se(link);
ASSERT_NOT_NULL(s);
ASSERT_NOT_NULL(link);
assert_se(sd_varlink_get_peer_uid(link, &uid) >= 0);
assert_se(getuid() == uid);
assert_se(sd_varlink_set_allow_fd_passing_input(link, true) >= 0);
assert_se(sd_varlink_set_allow_fd_passing_output(link, true) >= 0);
ASSERT_OK(sd_varlink_get_peer_uid(link, &uid));
ASSERT_EQ(getuid(), uid);
ASSERT_OK(sd_varlink_set_allow_fd_passing_input(link, true));
ASSERT_OK(sd_varlink_set_allow_fd_passing_output(link, true));
return 0;
}
@ -223,37 +208,37 @@ static void flood_test(const char *address) {
log_debug("Flooding server...");
/* Block the main event loop while we flood */
assert_se(write(block_write_fd, &x, sizeof(x)) == sizeof(x));
ASSERT_OK_EQ_ERRNO(write(block_write_fd, &x, sizeof(x)), (ssize_t) sizeof(x));
assert_se(sd_event_default(&e) >= 0);
ASSERT_OK(sd_event_default(&e));
/* Flood the server with connections */
assert_se(connections = new0(sd_varlink*, OVERLOAD_CONNECTIONS));
ASSERT_NOT_NULL(connections = new0(sd_varlink*, OVERLOAD_CONNECTIONS));
for (k = 0; k < OVERLOAD_CONNECTIONS; k++) {
_cleanup_free_ char *t = NULL;
log_debug("connection %zu", k);
assert_se(sd_varlink_connect_address(connections + k, address) >= 0);
ASSERT_OK(sd_varlink_connect_address(connections + k, address));
assert_se(asprintf(&t, "flood-%zu", k) >= 0);
assert_se(sd_varlink_set_description(connections[k], t) >= 0);
assert_se(sd_varlink_attach_event(connections[k], e, k) >= 0);
assert_se(sd_varlink_sendb(connections[k], "io.test.Rubbish", SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("id", SD_JSON_BUILD_INTEGER(k)))) >= 0);
ASSERT_OK(asprintf(&t, "flood-%zu", k));
ASSERT_OK(sd_varlink_set_description(connections[k], t));
ASSERT_OK(sd_varlink_attach_event(connections[k], e, k));
ASSERT_OK(sd_varlink_sendb(connections[k], "io.test.Rubbish", SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("id", SD_JSON_BUILD_INTEGER(k)))));
}
/* Then, create one more, which should fail */
log_debug("Creating overload connection...");
assert_se(sd_varlink_connect_address(&c, address) >= 0);
assert_se(sd_varlink_set_description(c, "overload-client") >= 0);
assert_se(sd_varlink_attach_event(c, e, k) >= 0);
assert_se(sd_varlink_bind_reply(c, overload_reply) >= 0);
assert_se(sd_varlink_invokeb(c, "io.test.Overload", SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("foo", JSON_BUILD_CONST_STRING("bar")))) >= 0);
ASSERT_OK(sd_varlink_connect_address(&c, address));
ASSERT_OK(sd_varlink_set_description(c, "overload-client"));
ASSERT_OK(sd_varlink_attach_event(c, e, k));
ASSERT_OK(sd_varlink_bind_reply(c, overload_reply));
ASSERT_OK(sd_varlink_invokeb(c, "io.test.Overload", SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("foo", JSON_BUILD_CONST_STRING("bar")))));
/* Unblock it */
log_debug("Unblocking server...");
block_write_fd = safe_close(block_write_fd);
/* This loop will terminate as soon as the overload reply callback is called */
assert_se(sd_event_loop(e) >= 0);
ASSERT_OK(sd_event_loop(e));
/* And close all connections again */
for (k = 0; k < OVERLOAD_CONNECTIONS; k++)
@ -268,63 +253,59 @@ static void *thread(void *arg) {
const char *error_id, *e;
int x = 0;
assert_se(sd_json_build(&i, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_INTEGER(88)),
SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_INTEGER(99)))) >= 0);
ASSERT_OK(sd_json_build(&i, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_INTEGER(88)),
SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_INTEGER(99)))));
assert_se(sd_varlink_connect_address(&c, arg) >= 0);
assert_se(sd_varlink_set_description(c, "thread-client") >= 0);
assert_se(sd_varlink_set_allow_fd_passing_input(c, true) >= 0);
assert_se(sd_varlink_set_allow_fd_passing_output(c, true) >= 0);
ASSERT_OK(sd_varlink_connect_address(&c, arg));
ASSERT_OK(sd_varlink_set_description(c, "thread-client"));
ASSERT_OK(sd_varlink_set_allow_fd_passing_input(c, true));
ASSERT_OK(sd_varlink_set_allow_fd_passing_output(c, true));
/* Test that client is able to perform two sequential sd_varlink_collect calls if first resulted in an error */
assert_se(sd_json_build(&wrong, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_INTEGER(88)),
SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_INTEGER(99)))) >= 0);
assert_se(sd_varlink_collect(c, "io.test.DoSomethingMore", wrong, &j, &error_id) >= 0);
assert_se(strcmp_ptr(error_id, "org.varlink.service.InvalidParameter") == 0);
ASSERT_OK(sd_json_build(&wrong, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_INTEGER(88)),
SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_INTEGER(99)))));
ASSERT_OK(sd_varlink_collect(c, "io.test.DoSomethingMore", wrong, &j, &error_id));
ASSERT_STREQ(error_id, "org.varlink.service.InvalidParameter");
assert_se(sd_varlink_collect(c, "io.test.DoSomethingMore", i, &j, &error_id) >= 0);
ASSERT_OK(sd_varlink_collect(c, "io.test.DoSomethingMore", i, &j, &error_id));
assert_se(!error_id);
assert_se(sd_json_variant_is_array(j) && !sd_json_variant_is_blank_array(j));
ASSERT_NULL(error_id);
ASSERT_TRUE(sd_json_variant_is_array(j));
ASSERT_FALSE(sd_json_variant_is_blank_array(j));
JSON_VARIANT_ARRAY_FOREACH(k, j) {
assert_se(sd_json_variant_integer(sd_json_variant_by_key(k, "sum")) == 88 + (99 * x));
ASSERT_EQ(sd_json_variant_integer(sd_json_variant_by_key(k, "sum")), 88 + (99 * x));
x++;
}
assert_se(x == 6);
ASSERT_EQ(x, 6);
assert_se(sd_varlink_call(c, "io.test.DoSomething", i, &o, &e) >= 0);
assert_se(sd_json_variant_integer(sd_json_variant_by_key(o, "sum")) == 88 + 99);
assert_se(!e);
ASSERT_OK(sd_varlink_call(c, "io.test.DoSomething", i, &o, &e));
ASSERT_EQ(sd_json_variant_integer(sd_json_variant_by_key(o, "sum")), 88 + 99);
ASSERT_NULL(e);
int fd1 = memfd_new_and_seal_string("data", "foo");
int fd2 = memfd_new_and_seal_string("data", "bar");
int fd3 = memfd_new_and_seal_string("data", "quux");
int fd1, fd2, fd3;
ASSERT_OK(fd1 = memfd_new_and_seal_string("data", "foo"));
ASSERT_OK(fd2 = memfd_new_and_seal_string("data", "bar"));
ASSERT_OK(fd3 = memfd_new_and_seal_string("data", "quux"));
assert_se(fd1 >= 0);
assert_se(fd2 >= 0);
assert_se(fd3 >= 0);
ASSERT_OK_EQ(sd_varlink_push_fd(c, fd1), 0);
ASSERT_OK_EQ(sd_varlink_push_fd(c, fd2), 1);
ASSERT_OK_EQ(sd_varlink_push_fd(c, fd3), 2);
assert_se(sd_varlink_push_fd(c, fd1) == 0);
assert_se(sd_varlink_push_fd(c, fd2) == 1);
assert_se(sd_varlink_push_fd(c, fd3) == 2);
ASSERT_OK(sd_varlink_callb(c, "io.test.PassFD", &o, &e, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("fd", SD_JSON_BUILD_STRING("whoop")))));
ASSERT_NULL(e);
assert_se(sd_varlink_callb(c, "io.test.PassFD", &o, &e, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("fd", SD_JSON_BUILD_STRING("whoop")))) >= 0);
assert_se(!e);
int fd4 = sd_varlink_peek_fd(c, 0);
int fd5 = sd_varlink_peek_fd(c, 1);
assert_se(fd4 >= 0);
assert_se(fd5 >= 0);
int fd4, fd5;
ASSERT_OK(fd4 = sd_varlink_peek_fd(c, 0));
ASSERT_OK(fd5 = sd_varlink_peek_fd(c, 1));
test_fd(fd4, "miau", 4);
test_fd(fd5, "wuff", 4);
assert_se(sd_varlink_callb(c, "io.test.PassFD", &o, &e, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("fdx", SD_JSON_BUILD_STRING("whoopx")))) >= 0);
ASSERT_OK(sd_varlink_callb(c, "io.test.PassFD", &o, &e, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("fdx", SD_JSON_BUILD_STRING("whoopx")))));
ASSERT_TRUE(sd_varlink_error_is_invalid_parameter(e, o, "fd"));
assert_se(sd_varlink_callb(c, "io.test.IDontExist", &o, &e, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("x", SD_JSON_BUILD_REAL(5.5)))) >= 0);
ASSERT_OK(sd_varlink_callb(c, "io.test.IDontExist", &o, &e, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("x", SD_JSON_BUILD_REAL(5.5)))));
ASSERT_STREQ(sd_json_variant_string(sd_json_variant_by_key(o, "method")), "io.test.IDontExist");
ASSERT_STREQ(e, SD_VARLINK_ERROR_METHOD_NOT_FOUND);
@ -332,7 +313,7 @@ static void *thread(void *arg) {
ASSERT_ERROR(sd_varlink_error_to_errno(e, o), EHWPOISON);
flood_test(arg);
assert_se(sd_varlink_send(c, "io.test.Done", NULL) >= 0);
ASSERT_OK(sd_varlink_send(c, "io.test.Done", NULL));
return NULL;
}
@ -340,16 +321,16 @@ static void *thread(void *arg) {
static int block_fd_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
char c;
assert_se(fd_nonblock(fd, false) >= 0);
ASSERT_OK(fd_nonblock(fd, false));
assert_se(read(fd, &c, sizeof(c)) == sizeof(c));
ASSERT_OK_EQ_ERRNO(read(fd, &c, sizeof(c)), (ssize_t) sizeof(c));
/* When a character is written to this pipe we'll block until the pipe is closed. */
assert_se(read(fd, &c, sizeof(c)) == 0);
ASSERT_OK_ZERO_ERRNO(read(fd, &c, sizeof(c)));
assert_se(fd_nonblock(fd, true) >= 0);
ASSERT_OK(fd_nonblock(fd, true));
assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
ASSERT_OK(sd_event_source_set_enabled(s, SD_EVENT_OFF));
return 0;
}
@ -365,47 +346,47 @@ TEST(chat) {
pthread_t t;
const char *sp;
assert_se(mkdtemp_malloc("/tmp/varlink-test-XXXXXX", &tmpdir) >= 0);
ASSERT_OK(mkdtemp_malloc("/tmp/varlink-test-XXXXXX", &tmpdir));
sp = strjoina(tmpdir, "/socket");
assert_se(sd_event_default(&e) >= 0);
ASSERT_OK(sd_event_default(&e));
assert_se(pipe2(block_fds, O_NONBLOCK|O_CLOEXEC) >= 0);
assert_se(sd_event_add_io(e, &block_event, block_fds[0], EPOLLIN, block_fd_handler, NULL) >= 0);
assert_se(sd_event_source_set_priority(block_event, SD_EVENT_PRIORITY_IMPORTANT) >= 0);
ASSERT_OK_ERRNO(pipe2(block_fds, O_NONBLOCK|O_CLOEXEC));
ASSERT_OK(sd_event_add_io(e, &block_event, block_fds[0], EPOLLIN, block_fd_handler, NULL));
ASSERT_OK(sd_event_source_set_priority(block_event, SD_EVENT_PRIORITY_IMPORTANT));
block_write_fd = TAKE_FD(block_fds[1]);
assert_se(varlink_server_new(&s, SD_VARLINK_SERVER_ACCOUNT_UID, NULL) >= 0);
assert_se(sd_varlink_server_set_info(s, "Vendor", "Product", "Version", "URL") >= 0);
assert_se(varlink_set_info_systemd(s) >= 0);
assert_se(sd_varlink_server_set_description(s, "our-server") >= 0);
ASSERT_OK(varlink_server_new(&s, SD_VARLINK_SERVER_ACCOUNT_UID, NULL));
ASSERT_OK(sd_varlink_server_set_info(s, "Vendor", "Product", "Version", "URL"));
ASSERT_OK(varlink_set_info_systemd(s));
ASSERT_OK(sd_varlink_server_set_description(s, "our-server"));
assert_se(sd_varlink_server_bind_method(s, "io.test.PassFD", method_passfd) >= 0);
assert_se(sd_varlink_server_bind_method(s, "io.test.DoSomething", method_something) >= 0);
assert_se(sd_varlink_server_bind_method(s, "io.test.DoSomethingMore", method_something_more) >= 0);
assert_se(sd_varlink_server_bind_method(s, "io.test.FailWithErrno", method_fail_with_errno) >= 0);
assert_se(sd_varlink_server_bind_method(s, "io.test.Done", method_done) >= 0);
assert_se(sd_varlink_server_bind_connect(s, on_connect) >= 0);
assert_se(sd_varlink_server_listen_address(s, sp, 0600) >= 0);
assert_se(sd_varlink_server_attach_event(s, e, 0) >= 0);
assert_se(sd_varlink_server_set_connections_max(s, OVERLOAD_CONNECTIONS) >= 0);
ASSERT_OK(sd_varlink_server_bind_method(s, "io.test.PassFD", method_passfd));
ASSERT_OK(sd_varlink_server_bind_method(s, "io.test.DoSomething", method_something));
ASSERT_OK(sd_varlink_server_bind_method(s, "io.test.DoSomethingMore", method_something_more));
ASSERT_OK(sd_varlink_server_bind_method(s, "io.test.FailWithErrno", method_fail_with_errno));
ASSERT_OK(sd_varlink_server_bind_method(s, "io.test.Done", method_done));
ASSERT_OK(sd_varlink_server_bind_connect(s, on_connect));
ASSERT_OK(sd_varlink_server_listen_address(s, sp, 0600));
ASSERT_OK(sd_varlink_server_attach_event(s, e, 0));
ASSERT_OK(sd_varlink_server_set_connections_max(s, OVERLOAD_CONNECTIONS));
assert_se(sd_json_build(&v, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_INTEGER(7)),
SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_INTEGER(22)))) >= 0);
ASSERT_OK(sd_json_build(&v, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_INTEGER(7)),
SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_INTEGER(22)))));
assert_se(sd_varlink_connect_address(&c, sp) >= 0);
assert_se(sd_varlink_set_description(c, "main-client") >= 0);
assert_se(sd_varlink_bind_reply(c, reply) >= 0);
ASSERT_OK(sd_varlink_connect_address(&c, sp));
ASSERT_OK(sd_varlink_set_description(c, "main-client"));
ASSERT_OK(sd_varlink_bind_reply(c, reply));
assert_se(sd_varlink_invoke(c, "io.test.DoSomething", v) >= 0);
ASSERT_OK(sd_varlink_invoke(c, "io.test.DoSomething", v));
assert_se(sd_varlink_attach_event(c, e, 0) >= 0);
ASSERT_OK(sd_varlink_attach_event(c, e, 0));
assert_se(pthread_create(&t, NULL, thread, (void*) sp) == 0);
ASSERT_OK(-pthread_create(&t, NULL, thread, (void*) sp));
assert_se(sd_event_loop(e) >= 0);
ASSERT_OK(sd_event_loop(e));
assert_se(pthread_join(t, NULL) == 0);
ASSERT_OK(-pthread_join(t, NULL));
}
static int method_invalid(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
@ -426,38 +407,38 @@ static int method_invalid(sd_varlink *link, sd_json_variant *parameters, sd_varl
}
static int reply_invalid(sd_varlink *link, sd_json_variant *parameters, const char *error_id, sd_varlink_reply_flags_t flags, void *userdata) {
assert(sd_varlink_error_is_invalid_parameter(error_id, parameters, "idontexist"));
assert(sd_event_exit(sd_varlink_get_event(link), EXIT_SUCCESS) >= 0);
ASSERT_TRUE(sd_varlink_error_is_invalid_parameter(error_id, parameters, "idontexist"));
ASSERT_OK(sd_event_exit(sd_varlink_get_event(link), EXIT_SUCCESS));
return 0;
}
TEST(invalid_parameter) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
assert_se(sd_event_default(&e) >= 0);
ASSERT_OK(sd_event_default(&e));
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *s = NULL;
assert_se(sd_varlink_server_new(&s, 0) >= 0);
ASSERT_OK(sd_varlink_server_new(&s, 0));
assert_se(sd_varlink_server_attach_event(s, e, 0) >= 0);
ASSERT_OK(sd_varlink_server_attach_event(s, e, 0));
assert_se(sd_varlink_server_bind_method(s, "foo.mytest.Invalid", method_invalid) >= 0);
ASSERT_OK(sd_varlink_server_bind_method(s, "foo.mytest.Invalid", method_invalid));
int connfd[2];
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, connfd) >= 0);
assert_se(sd_varlink_server_add_connection(s, connfd[0], /* ret= */ NULL) >= 0);
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, connfd));
ASSERT_OK(sd_varlink_server_add_connection(s, connfd[0], /* ret= */ NULL));
_cleanup_(sd_varlink_unrefp) sd_varlink *c = NULL;
assert_se(sd_varlink_connect_fd(&c, connfd[1]) >= 0);
ASSERT_OK(sd_varlink_connect_fd(&c, connfd[1]));
assert_se(sd_varlink_attach_event(c, e, 0) >= 0);
ASSERT_OK(sd_varlink_attach_event(c, e, 0));
assert_se(sd_varlink_bind_reply(c, reply_invalid) >= 0);
ASSERT_OK(sd_varlink_bind_reply(c, reply_invalid));
assert_se(sd_varlink_invokebo(c, "foo.mytest.Invalid",
ASSERT_OK(sd_varlink_invokebo(c, "foo.mytest.Invalid",
SD_JSON_BUILD_PAIR_STRING("iexist", "foo"),
SD_JSON_BUILD_PAIR_STRING("idontexist", "bar")) >= 0);
SD_JSON_BUILD_PAIR_STRING("idontexist", "bar")));
assert_se(sd_event_loop(e) >= 0);
ASSERT_OK(sd_event_loop(e));
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -733,9 +733,9 @@ static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *
log_struct(LOG_INFO,
LOG_MESSAGE_ID(SD_MESSAGE_TIMEZONE_CHANGE_STR),
LOG_ITEM("TIMEZONE=%s", c->zone),
LOG_ITEM("TIMEZONE_SHORTNAME=%s", tzname[daylight]),
LOG_ITEM("TIMEZONE_SHORTNAME=%s", get_tzname(daylight)),
LOG_ITEM("DAYLIGHT=%i", daylight),
LOG_MESSAGE("Changed time zone to '%s' (%s).", c->zone, tzname[daylight]));
LOG_MESSAGE("Changed time zone to '%s' (%s).", c->zone, get_tzname(daylight)));
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
"/org/freedesktop/timedate1", "org.freedesktop.timedate1", "Timezone",

View File

@ -16,8 +16,9 @@ u! {{NOBODY_USER_NAME}} 65534:65534 "Kernel Overflow User" -
# Administrator group: can *see* more than normal users
g adm {{ADM_GID }} - -
# Administrator group: can *do* more than normal users
# Administrator groups: can *do* more than normal users
g wheel {{WHEEL_GID }} - -
g empower {{EMPOWER_GID}} - -
# Access to shared database of users on the system
g utmp {{UTMP_GID }} - -