1
0
mirror of https://github.com/systemd/systemd synced 2026-04-01 04:34:51 +02:00

Compare commits

..

No commits in common. "fe6e6cb6a00109b1162f5c9727878d692e6915b5" and "3b3113b87c9e721ec386329b9dc6484561377f85" have entirely different histories.

36 changed files with 1039 additions and 1266 deletions

View File

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

View File

@ -72,10 +72,7 @@ conf.set10('SD_BOOT', false)
# Create a title-less summary section early, so it ends up first in the output. # 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. # More items are added later after they have been detected.
summary({ summary({'build mode' : get_option('mode')})
'libc' : get_option('libc'),
'build mode' : get_option('mode'),
})
##################################################################### #####################################################################
@ -560,10 +557,6 @@ conf.set10('HAVE_WARNING_ZERO_AS_NULL_POINTER_CONSTANT', have)
conf.set('_GNU_SOURCE', 1) conf.set('_GNU_SOURCE', 1)
conf.set('__SANE_USERSPACE_TYPES__', true) 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_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_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>')) conf.set('SIZEOF_RLIM_T', cc.sizeof('rlim_t', prefix : '#include <sys/resource.h>'))
@ -579,7 +572,6 @@ assert(long_max > 100000)
conf.set_quoted('LONG_MAX_STR', f'@long_max@') conf.set_quoted('LONG_MAX_STR', f'@long_max@')
foreach ident : [ 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 ['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 ['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 ['strerrorname_np', '''#include <string.h>'''], # since glibc-2.32
@ -708,8 +700,6 @@ foreach header : [
endforeach endforeach
foreach header : [ foreach header : [
'gshadow.h',
'nss.h',
'sys/sdt.h', 'sys/sdt.h',
'threads.h', 'threads.h',
'valgrind/memcheck.h', 'valgrind/memcheck.h',
@ -720,20 +710,6 @@ foreach header : [
cc.has_header(header)) cc.has_header(header))
endforeach 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') fallback_hostname = get_option('fallback-hostname')
@ -910,7 +886,6 @@ foreach option : ['adm-gid',
'clock-gid', 'clock-gid',
'dialout-gid', 'dialout-gid',
'disk-gid', 'disk-gid',
'empower-gid',
'input-gid', 'input-gid',
'kmem-gid', 'kmem-gid',
'kvm-gid', 'kvm-gid',
@ -1026,22 +1001,6 @@ librt = cc.find_library('rt')
libm = cc.find_library('m') libm = cc.find_library('m')
libdl = cc.find_library('dl') 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, # 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. # 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. # If it is installed, but not needed, it will be dropped because of --as-needed.
@ -1643,60 +1602,52 @@ conf.set10('ENABLE_NSPAWN', feature.allowed())
conf.set10('DEFAULT_MOUNTFSD_TRUSTED_DIRECTORIES', get_option('default-mountfsd-trusted-directories')) conf.set10('DEFAULT_MOUNTFSD_TRUSTED_DIRECTORIES', get_option('default-mountfsd-trusted-directories'))
foreach tuple : [ foreach term : ['analyze',
['analyze'], 'backlight',
['backlight'], 'binfmt',
['binfmt'], 'compat-mutable-uid-boundaries',
['compat-mutable-uid-boundaries'], 'coredump',
['coredump'], 'efi',
['efi'], 'environment-d',
['environment-d'], 'firstboot',
['firstboot'], 'gshadow',
['gshadow', conf.get('HAVE_GSHADOW_H') == 1, 'gshadow.h not found'], 'hibernate',
['hibernate'], 'hostnamed',
['hostnamed'], 'hwdb',
['hwdb'], 'idn',
['idn', conf.get('HAVE_NI_IDN') == 1, 'NI_IDN is not defined'], 'ima',
['ima'], 'ipe',
['ipe'], 'initrd',
['initrd'], 'kernel-install',
['kernel-install'], 'ldconfig',
['ldconfig'], 'localed',
['localed'], 'logind',
['logind'], 'machined',
['machined'], 'mountfsd',
['mountfsd'], 'networkd',
['networkd'], 'nsresourced',
['nsresourced'], 'nss-myhostname',
['nss-myhostname', conf.get('HAVE_NSS_H') == 1, 'nss.h not found'], 'nss-systemd',
['nss-systemd', conf.get('HAVE_NSS_H') == 1, 'nss.h not found'], 'oomd',
['oomd'], 'portabled',
['portabled'], 'pstore',
['pstore'], 'quotacheck',
['quotacheck'], 'randomseed',
['randomseed'], 'resolve',
['resolve'], 'rfkill',
['rfkill'], 'smack',
['smack'], 'sysext',
['sysext'], 'sysusers',
['sysusers'], 'timedated',
['timedated'], 'timesyncd',
['timesyncd'], 'tmpfiles',
['tmpfiles'], 'tpm',
['tpm'], 'userdb',
['utmp'], 'utmp',
['userdb'], 'vconsole',
['vconsole'], 'xdg-autostart']
['xdg-autostart'], have = get_option(term)
] name = 'ENABLE_' + term.underscorify().to_upper()
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) conf.set10(name, have)
endforeach endforeach
@ -1705,16 +1656,11 @@ enable_sysusers = conf.get('ENABLE_SYSUSERS') == 1
foreach tuple : [['nss-mymachines', 'machined'], foreach tuple : [['nss-mymachines', 'machined'],
['nss-resolve', 'resolve']] ['nss-resolve', 'resolve']]
want = get_option(tuple[0]) want = get_option(tuple[0])
if want.enabled() if want.allowed()
if conf.get('HAVE_NSS_H') != 1 have = get_option(tuple[1])
error('@0@ is requested but nss.h not found'.format(tuple[0])) if want.enabled() and not have
endif
if not get_option(tuple[1])
error('@0@ is requested but @1@ is disabled'.format(tuple[0], tuple[1])) error('@0@ is requested but @1@ is disabled'.format(tuple[0], tuple[1]))
endif endif
have = true
elif want.allowed()
have = get_option(tuple[1]) and conf.get('HAVE_NSS_H') == 1
else else
have = false have = false
endif endif
@ -2122,15 +2068,6 @@ 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 = [ basic_includes = [
include_directories( include_directories(
'src/basic', 'src/basic',

View File

@ -295,8 +295,6 @@ option('dialout-gid', type : 'integer', value : 0,
description : 'soft-static allocation for the "dialout" group') description : 'soft-static allocation for the "dialout" group')
option('disk-gid', type : 'integer', value : 0, option('disk-gid', type : 'integer', value : 0,
description : 'soft-static allocation for the "disk" group') 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, option('input-gid', type : 'integer', value : 0,
description : 'soft-static allocation for the "input" group') description : 'soft-static allocation for the "input" group')
option('kmem-gid', type : 'integer', value : 0, option('kmem-gid', type : 'integer', value : 0,
@ -402,8 +400,6 @@ option('ima', type : 'boolean',
option('ipe', type : 'boolean', option('ipe', type : 'boolean',
description : 'IPE support') 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' }, option('acl', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
description : 'libacl support') description : 'libacl support')
option('audit', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' }, option('audit', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },

View File

@ -960,41 +960,6 @@ int fd_is_opath(int fd) {
return FLAGS_SET(r, O_PATH); 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 fd_verify_safe_flags_full(int fd, int extra_flags) {
int flags, unexpected_flags; int flags, unexpected_flags;

View File

@ -151,7 +151,6 @@ 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_reopen_condition(int fd, int flags, int mask, int *ret_new_fd);
int fd_is_opath(int 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); int fd_verify_safe_flags_full(int fd, int extra_flags);
static inline int fd_verify_safe_flags(int fd) { static inline int fd_verify_safe_flags(int fd) {

View File

@ -13,7 +13,6 @@
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
#include "hexdecoct.h"
#include "io-util.h" #include "io-util.h"
#include "log.h" #include "log.h"
#include "parse-util.h" #include "parse-util.h"
@ -625,97 +624,19 @@ char* format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
return buf; 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 parse_gmtoff(const char *t, long *ret) {
int r;
assert(t); assert(t);
struct tm tm; struct tm tm;
const char *k = strptime(t, "%z", &tm); const char *k = strptime(t, "%z", &tm);
if (k && *k == '\0') { if (!k || *k != '\0')
/* Success! */ return -EINVAL;
if (ret) if (ret)
*ret = tm.tm_gmtoff; *ret = tm.tm_gmtoff;
return 0; 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;
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;
}
static int parse_timestamp_impl( static int parse_timestamp_impl(
const char *t, const char *t,
size_t max_len, size_t max_len,
@ -889,11 +810,7 @@ static int parse_timestamp_impl(
if (!k || *k != ' ') if (!k || *k != ' ')
continue; 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; weekday = day->nr;
#endif
t = k + 1; t = k + 1;
break; break;
} }
@ -1090,7 +1007,10 @@ int parse_timestamp(const char *t, usec_t *ret) {
* not follow the timezone change in the current area. */ * not follow the timezone change in the current area. */
tzset(); tzset();
for (int j = 0; j <= 1; j++) { for (int j = 0; j <= 1; j++) {
if (!streq_ptr(tz, get_tzname(j))) if (isempty(tzname[j]))
continue;
if (!streq(tz, tzname[j]))
continue; continue;
/* The specified timezone matches tzname[] of the local timezone. */ /* The specified timezone matches tzname[] of the local timezone. */

View File

@ -149,7 +149,6 @@ static inline char* format_timestamp(char *buf, size_t l, usec_t t) {
#define FORMAT_TIMESTAMP_STYLE(t, style) \ #define FORMAT_TIMESTAMP_STYLE(t, style) \
format_timestamp_style((char[FORMAT_TIMESTAMP_MAX]){}, FORMAT_TIMESTAMP_MAX, 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_gmtoff(const char *t, long *ret);
int parse_timestamp(const char *t, usec_t *ret); int parse_timestamp(const char *t, usec_t *ret);

View File

@ -182,11 +182,6 @@ if get_option('mode') == 'developer' and get_option('debug')
efi_c_args += '-DEFI_DEBUG' efi_c_args += '-DEFI_DEBUG'
endif 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 = [ efi_c_ld_args = [
'-nostdlib', '-nostdlib',
'-static-pie', '-static-pie',

View File

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

View File

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

View File

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

View File

@ -1,13 +0,0 @@
/* 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,8 +16,6 @@ libc_wrapper_sources = files(
'xattr.c', 'xattr.c',
) )
subdir('musl')
sources += libc_wrapper_sources sources += libc_wrapper_sources
libc_wrapper_static = static_library( libc_wrapper_static = static_library(

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4131,12 +4131,28 @@ int journal_file_open(
.last_direction = _DIRECTION_INVALID, .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) { if (f->fd < 0) {
/* We pass O_NONBLOCK here, so that in case somebody pointed us to some character device node or FIFO /* 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 * 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. */ * it doesn't hurt in that case. */
f->fd = openat_report_new(AT_FDCWD, fname, f->open_flags|O_CLOEXEC|O_NONBLOCK, f->mode, &newly_created); f->fd = openat_report_new(AT_FDCWD, f->path, f->open_flags|O_CLOEXEC|O_NONBLOCK, f->mode, &newly_created);
if (f->fd < 0) { if (f->fd < 0) {
r = f->fd; r = f->fd;
goto fail; goto fail;
@ -4149,23 +4165,12 @@ int journal_file_open(
if (r < 0) if (r < 0)
goto fail; goto fail;
r = fd_get_path(f->fd, &f->path);
if (r < 0)
goto fail;
if (!newly_created) { if (!newly_created) {
r = journal_file_fstat(f); r = journal_file_fstat(f);
if (r < 0) if (r < 0)
goto fail; goto fail;
} }
} else { } 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); r = journal_file_fstat(f);
if (r < 0) if (r < 0)
goto fail; goto fail;

View File

@ -1580,7 +1580,6 @@ static int add_any_file(
const char *path) { const char *path) {
_cleanup_close_ int our_fd = -EBADF; _cleanup_close_ int our_fd = -EBADF;
_cleanup_free_ char *resolved_path = NULL;
JournalFile *f; JournalFile *f;
struct stat st; struct stat st;
int r; int r;
@ -1607,14 +1606,6 @@ static int add_any_file(
r = log_debug_errno(errno, "Failed to turn off O_NONBLOCK for %s: %m", path); r = log_debug_errno(errno, "Failed to turn off O_NONBLOCK for %s: %m", path);
goto error; 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) { if (fstat(fd, &st) < 0) {
@ -1749,7 +1740,7 @@ static int add_file_by_name(
if (!path) if (!path)
return -ENOMEM; return -ENOMEM;
return add_any_file(j, /* fd = */ -EBADF, path); return add_any_file(j, -1, path);
} }
static int remove_file_by_name( static int remove_file_by_name(
@ -2436,7 +2427,7 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
return -ENOMEM; return -ENOMEM;
STRV_FOREACH(path, paths) { STRV_FOREACH(path, paths) {
r = add_any_file(j, /* fd = */ -EBADF, *path); r = add_any_file(j, -1, *path);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -2523,7 +2514,7 @@ _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fd
if (r < 0) if (r < 0)
goto fail; goto fail;
r = add_any_file(j, fds[i], /* path = */ NULL); r = add_any_file(j, fds[i], NULL);
if (r < 0) if (r < 0)
goto fail; 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) { static int method_set_tty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Session *s = ASSERT_PTR(userdata); Session *s = ASSERT_PTR(userdata);
int fd, r, flags;
_cleanup_free_ char *q = NULL; _cleanup_free_ char *q = NULL;
int fd, r;
assert(message); assert(message);
@ -543,11 +543,15 @@ 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))) 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"); return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You must be in control of this session to set tty");
r = fd_vet_accmode(fd, O_RDWR); assert(fd >= 0);
if (r == -EPROTOTYPE)
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0)
return -errno;
if ((flags & O_ACCMODE_STRICT) != O_RDWR)
return -EACCES; return -EACCES;
if (r < 0) if (FLAGS_SET(flags, O_PATH))
return r; return -ENOTTY;
r = getttyname_malloc(fd, &q); r = getttyname_malloc(fd, &q);
if (r < 0) if (r < 0)

View File

@ -1,8 +0,0 @@
// 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,8 +18,3 @@ custom_target(
command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'],
install : pamconfdir != 'no', install : pamconfdir != 'no',
install_dir : pamconfdir) install_dir : pamconfdir)
if install_polkit
install_data('empower.rules',
install_dir : polkitrulesdir)
endif

View File

@ -1420,15 +1420,6 @@ 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); r = sd_bus_message_append(m, "(sv)", "AmbientCapabilities", "t", CAP_MASK_ALL);
if (r < 0) if (r < 0)
return bus_log_create_error(r); 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) { if (arg_nice_set) {

View File

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

View File

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

View File

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

View File

@ -878,29 +878,4 @@ TEST(fd_get_path) {
assert_se(chdir(saved_cwd) >= 0); 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); DEFINE_TEST_MAIN(LOG_DEBUG);

View File

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

View File

@ -15,7 +15,7 @@
static void set_timezone(const char *tz) { static void set_timezone(const char *tz) {
ASSERT_OK(set_unset_env("TZ", tz, /* overwrite = */ true)); ASSERT_OK(set_unset_env("TZ", tz, /* overwrite = */ true));
tzset(); tzset();
log_info("TZ=%s, tzname[0]=%s, tzname[1]=%s", strna(getenv("TZ")), strempty(get_tzname(/* dst= */ false)), strempty(get_tzname(/* dst= */ true))); log_info("TZ=%s, tzname[0]=%s, tzname[1]=%s", strna(getenv("TZ")), strempty(tzname[0]), strempty(tzname[1]));
} }
TEST(parse_sec) { TEST(parse_sec) {
@ -400,28 +400,6 @@ static void test_format_timestamp_impl(usec_t x) {
const char *xx = FORMAT_TIMESTAMP(x); const char *xx = FORMAT_TIMESTAMP(x);
ASSERT_NOT_NULL(xx); 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; usec_t y;
ASSERT_OK(parse_timestamp(xx, &y)); ASSERT_OK(parse_timestamp(xx, &y));
const char *yy = FORMAT_TIMESTAMP(y); const char *yy = FORMAT_TIMESTAMP(y);
@ -1131,15 +1109,15 @@ TEST(in_utc_timezone) {
assert_se(setenv("TZ", "UTC", 1) >= 0); assert_se(setenv("TZ", "UTC", 1) >= 0);
assert_se(in_utc_timezone()); assert_se(in_utc_timezone());
ASSERT_STREQ(get_tzname(/* dst= */ false), "UTC"); ASSERT_STREQ(tzname[0], "UTC");
ASSERT_STREQ(get_tzname(/* dst= */ true), "UTC"); ASSERT_STREQ(tzname[1], "UTC");
assert_se(timezone == 0); assert_se(timezone == 0);
assert_se(daylight == 0); assert_se(daylight == 0);
assert_se(setenv("TZ", "Europe/Berlin", 1) >= 0); assert_se(setenv("TZ", "Europe/Berlin", 1) >= 0);
assert_se(!in_utc_timezone()); assert_se(!in_utc_timezone());
ASSERT_STREQ(get_tzname(/* dst= */ false), "CET"); ASSERT_STREQ(tzname[0], "CET");
ASSERT_STREQ(get_tzname(/* dst= */ true), "CEST"); ASSERT_STREQ(tzname[1], "CEST");
} }
TEST(map_clock_usec) { TEST(map_clock_usec) {

View File

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

View File

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