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.
fe6e6cb6a0
...
3b3113b87c
@ -295,9 +295,8 @@
|
||||
|
||||
<listitem><para>If specified, run0 will elevate the privileges of the selected user (using
|
||||
<option>--user=</option>) or the current user if no user is explicitly selected. Currently this means
|
||||
we give the invoked process all available capabilities and add the the <literal>empower</literal>
|
||||
group as a supplemental group (for which all polkit actions are allowed by default), but other
|
||||
privileges may be granted in the future as well when using this option.</para>
|
||||
we give the user all available capabilities, but other privileges may be granted in the future as
|
||||
well when using this option.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
163
meson.build
163
meson.build
@ -72,10 +72,7 @@ conf.set10('SD_BOOT', false)
|
||||
|
||||
# Create a title-less summary section early, so it ends up first in the output.
|
||||
# More items are added later after they have been detected.
|
||||
summary({
|
||||
'libc' : get_option('libc'),
|
||||
'build mode' : get_option('mode'),
|
||||
})
|
||||
summary({'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('__SANE_USERSPACE_TYPES__', true)
|
||||
|
||||
# glibc always defines _LARGEFILE64_SOURCE when _GNU_SOURCE is set, but musl does not do that,
|
||||
# and it is necessary for making getdents64() and struct dirent64 exist.
|
||||
conf.set('_LARGEFILE64_SOURCE', 1)
|
||||
|
||||
conf.set('SIZEOF_DEV_T', cc.sizeof('dev_t', prefix : '#include <sys/types.h>'))
|
||||
conf.set('SIZEOF_INO_T', cc.sizeof('ino_t', prefix : '#include <sys/types.h>'))
|
||||
conf.set('SIZEOF_RLIM_T', cc.sizeof('rlim_t', prefix : '#include <sys/resource.h>'))
|
||||
@ -579,7 +572,6 @@ assert(long_max > 100000)
|
||||
conf.set_quoted('LONG_MAX_STR', f'@long_max@')
|
||||
|
||||
foreach ident : [
|
||||
['renameat2', '''#include <stdio.h>'''], # since musl-1.2.6
|
||||
['set_mempolicy', '''#include <sys/syscall.h>'''], # declared at numaif.h provided by libnuma, which we do not use
|
||||
['get_mempolicy', '''#include <sys/syscall.h>'''], # declared at numaif.h provided by libnuma, which we do not use
|
||||
['strerrorname_np', '''#include <string.h>'''], # since glibc-2.32
|
||||
@ -708,8 +700,6 @@ foreach header : [
|
||||
endforeach
|
||||
|
||||
foreach header : [
|
||||
'gshadow.h',
|
||||
'nss.h',
|
||||
'sys/sdt.h',
|
||||
'threads.h',
|
||||
'valgrind/memcheck.h',
|
||||
@ -720,20 +710,6 @@ foreach header : [
|
||||
cc.has_header(header))
|
||||
endforeach
|
||||
|
||||
foreach ident : [
|
||||
['NI_IDN', 'netdb.h']
|
||||
]
|
||||
|
||||
if meson.version().version_compare('>=1.3.0')
|
||||
have = cc.has_define(ident[0],
|
||||
prefix : '''#include <@0@>'''.format(ident[1]),
|
||||
args : '-D_GNU_SOURCE')
|
||||
else
|
||||
have = cc.has_header_symbol(ident[1], ident[0])
|
||||
endif
|
||||
conf.set10('HAVE_' + ident[0], have)
|
||||
endforeach
|
||||
|
||||
#####################################################################
|
||||
|
||||
fallback_hostname = get_option('fallback-hostname')
|
||||
@ -910,7 +886,6 @@ foreach option : ['adm-gid',
|
||||
'clock-gid',
|
||||
'dialout-gid',
|
||||
'disk-gid',
|
||||
'empower-gid',
|
||||
'input-gid',
|
||||
'kmem-gid',
|
||||
'kvm-gid',
|
||||
@ -1026,22 +1001,6 @@ librt = cc.find_library('rt')
|
||||
libm = cc.find_library('m')
|
||||
libdl = cc.find_library('dl')
|
||||
|
||||
# On some distributions that use musl (e.g. Alpine), libintl.h may be provided by gettext rather than musl.
|
||||
# In that case, we need to explicitly link with libintl.so.
|
||||
if cc.has_function('dgettext',
|
||||
prefix : '''#include <libintl.h>''',
|
||||
args : '-D_GNU_SOURCE')
|
||||
libintl = []
|
||||
else
|
||||
libintl = cc.find_library('intl')
|
||||
if not cc.has_function('dgettext',
|
||||
prefix : '''#include <libintl.h>''',
|
||||
args : '-D_GNU_SOURCE',
|
||||
dependencies : libintl)
|
||||
error('dgettext() not found')
|
||||
endif
|
||||
endif
|
||||
|
||||
# On some architectures, libatomic is required. But on some installations,
|
||||
# it is found, but actual linking fails. So let's try to use it opportunistically.
|
||||
# If it is installed, but not needed, it will be dropped because of --as-needed.
|
||||
@ -1643,60 +1602,52 @@ conf.set10('ENABLE_NSPAWN', feature.allowed())
|
||||
|
||||
conf.set10('DEFAULT_MOUNTFSD_TRUSTED_DIRECTORIES', get_option('default-mountfsd-trusted-directories'))
|
||||
|
||||
foreach tuple : [
|
||||
['analyze'],
|
||||
['backlight'],
|
||||
['binfmt'],
|
||||
['compat-mutable-uid-boundaries'],
|
||||
['coredump'],
|
||||
['efi'],
|
||||
['environment-d'],
|
||||
['firstboot'],
|
||||
['gshadow', conf.get('HAVE_GSHADOW_H') == 1, 'gshadow.h not found'],
|
||||
['hibernate'],
|
||||
['hostnamed'],
|
||||
['hwdb'],
|
||||
['idn', conf.get('HAVE_NI_IDN') == 1, 'NI_IDN is not defined'],
|
||||
['ima'],
|
||||
['ipe'],
|
||||
['initrd'],
|
||||
['kernel-install'],
|
||||
['ldconfig'],
|
||||
['localed'],
|
||||
['logind'],
|
||||
['machined'],
|
||||
['mountfsd'],
|
||||
['networkd'],
|
||||
['nsresourced'],
|
||||
['nss-myhostname', conf.get('HAVE_NSS_H') == 1, 'nss.h not found'],
|
||||
['nss-systemd', conf.get('HAVE_NSS_H') == 1, 'nss.h not found'],
|
||||
['oomd'],
|
||||
['portabled'],
|
||||
['pstore'],
|
||||
['quotacheck'],
|
||||
['randomseed'],
|
||||
['resolve'],
|
||||
['rfkill'],
|
||||
['smack'],
|
||||
['sysext'],
|
||||
['sysusers'],
|
||||
['timedated'],
|
||||
['timesyncd'],
|
||||
['tmpfiles'],
|
||||
['tpm'],
|
||||
['utmp'],
|
||||
['userdb'],
|
||||
['vconsole'],
|
||||
['xdg-autostart'],
|
||||
]
|
||||
|
||||
have = get_option(tuple[0])
|
||||
if have and tuple.length() >= 3 and not tuple[1]
|
||||
warning('@0@ support is requested but @1@, disabling it'.format(tuple[0], tuple[2]))
|
||||
have = false
|
||||
endif
|
||||
|
||||
name = 'ENABLE_' + tuple[0].underscorify().to_upper()
|
||||
foreach term : ['analyze',
|
||||
'backlight',
|
||||
'binfmt',
|
||||
'compat-mutable-uid-boundaries',
|
||||
'coredump',
|
||||
'efi',
|
||||
'environment-d',
|
||||
'firstboot',
|
||||
'gshadow',
|
||||
'hibernate',
|
||||
'hostnamed',
|
||||
'hwdb',
|
||||
'idn',
|
||||
'ima',
|
||||
'ipe',
|
||||
'initrd',
|
||||
'kernel-install',
|
||||
'ldconfig',
|
||||
'localed',
|
||||
'logind',
|
||||
'machined',
|
||||
'mountfsd',
|
||||
'networkd',
|
||||
'nsresourced',
|
||||
'nss-myhostname',
|
||||
'nss-systemd',
|
||||
'oomd',
|
||||
'portabled',
|
||||
'pstore',
|
||||
'quotacheck',
|
||||
'randomseed',
|
||||
'resolve',
|
||||
'rfkill',
|
||||
'smack',
|
||||
'sysext',
|
||||
'sysusers',
|
||||
'timedated',
|
||||
'timesyncd',
|
||||
'tmpfiles',
|
||||
'tpm',
|
||||
'userdb',
|
||||
'utmp',
|
||||
'vconsole',
|
||||
'xdg-autostart']
|
||||
have = get_option(term)
|
||||
name = 'ENABLE_' + term.underscorify().to_upper()
|
||||
conf.set10(name, have)
|
||||
endforeach
|
||||
|
||||
@ -1705,16 +1656,11 @@ enable_sysusers = conf.get('ENABLE_SYSUSERS') == 1
|
||||
foreach tuple : [['nss-mymachines', 'machined'],
|
||||
['nss-resolve', 'resolve']]
|
||||
want = get_option(tuple[0])
|
||||
if want.enabled()
|
||||
if conf.get('HAVE_NSS_H') != 1
|
||||
error('@0@ is requested but nss.h not found'.format(tuple[0]))
|
||||
endif
|
||||
if not get_option(tuple[1])
|
||||
if want.allowed()
|
||||
have = get_option(tuple[1])
|
||||
if want.enabled() and not have
|
||||
error('@0@ is requested but @1@ is disabled'.format(tuple[0], tuple[1]))
|
||||
endif
|
||||
have = true
|
||||
elif want.allowed()
|
||||
have = get_option(tuple[1]) and conf.get('HAVE_NSS_H') == 1
|
||||
else
|
||||
have = false
|
||||
endif
|
||||
@ -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 = [
|
||||
include_directories(
|
||||
'src/basic',
|
||||
|
||||
@ -295,8 +295,6 @@ option('dialout-gid', type : 'integer', value : 0,
|
||||
description : 'soft-static allocation for the "dialout" group')
|
||||
option('disk-gid', type : 'integer', value : 0,
|
||||
description : 'soft-static allocation for the "disk" group')
|
||||
option('empower-gid', type : 'integer', value : 0,
|
||||
description : 'soft-static allocation for the "empower" group')
|
||||
option('input-gid', type : 'integer', value : 0,
|
||||
description : 'soft-static allocation for the "input" group')
|
||||
option('kmem-gid', type : 'integer', value : 0,
|
||||
@ -402,8 +400,6 @@ option('ima', type : 'boolean',
|
||||
option('ipe', type : 'boolean',
|
||||
description : 'IPE support')
|
||||
|
||||
option('libc', type : 'combo', choices : ['glibc', 'musl'],
|
||||
description : 'libc implementation to be used')
|
||||
option('acl', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
|
||||
description : 'libacl support')
|
||||
option('audit', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
|
||||
|
||||
@ -960,41 +960,6 @@ int fd_is_opath(int fd) {
|
||||
return FLAGS_SET(r, O_PATH);
|
||||
}
|
||||
|
||||
int fd_vet_accmode(int fd, int mode) {
|
||||
int flags;
|
||||
|
||||
/* Check if fd is opened with desired access mode.
|
||||
*
|
||||
* Returns > 0 on strict match, == 0 if opened for both reading and writing (partial match),
|
||||
* -EPROTOTYPE otherwise. O_PATH fds are always refused with -EBADFD.
|
||||
*
|
||||
* Note that while on O_DIRECTORY -EISDIR will be returned, this should not be relied upon as
|
||||
* the flag might not have been specified when open() was called originally. */
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(IN_SET(mode, O_RDONLY, O_WRONLY, O_RDWR));
|
||||
|
||||
flags = fcntl(fd, F_GETFL);
|
||||
if (flags < 0)
|
||||
return -errno;
|
||||
|
||||
if (FLAGS_SET(flags, O_DIRECTORY))
|
||||
return -EISDIR;
|
||||
|
||||
if (FLAGS_SET(flags, O_PATH))
|
||||
return -EBADFD;
|
||||
|
||||
flags &= O_ACCMODE_STRICT;
|
||||
|
||||
if (flags == mode)
|
||||
return 1;
|
||||
|
||||
if (flags == O_RDWR)
|
||||
return 0;
|
||||
|
||||
return -EPROTOTYPE;
|
||||
}
|
||||
|
||||
int fd_verify_safe_flags_full(int fd, int extra_flags) {
|
||||
int flags, unexpected_flags;
|
||||
|
||||
|
||||
@ -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_is_opath(int fd);
|
||||
int fd_vet_accmode(int fd, int mode);
|
||||
|
||||
int fd_verify_safe_flags_full(int fd, int extra_flags);
|
||||
static inline int fd_verify_safe_flags(int fd) {
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "io-util.h"
|
||||
#include "log.h"
|
||||
#include "parse-util.h"
|
||||
@ -625,94 +624,16 @@ char* format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char* get_tzname(bool dst) {
|
||||
/* musl leaves the DST timezone name unset if there is no DST, map this back to no DST */
|
||||
if (dst && isempty(tzname[1]))
|
||||
dst = false;
|
||||
|
||||
return empty_to_null(tzname[dst]);
|
||||
}
|
||||
|
||||
int parse_gmtoff(const char *t, long *ret) {
|
||||
int r;
|
||||
|
||||
assert(t);
|
||||
|
||||
struct tm tm;
|
||||
const char *k = strptime(t, "%z", &tm);
|
||||
if (k && *k == '\0') {
|
||||
/* Success! */
|
||||
if (ret)
|
||||
*ret = tm.tm_gmtoff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* musl v1.2.5 does not support %z specifier in strptime(). Since
|
||||
* https://github.com/kraj/musl/commit/fced99e93daeefb0192fd16304f978d4401d1d77
|
||||
* %z is supported, but it only supports strict RFC-822/ISO 8601 format, that is, 4 digits with sign
|
||||
* (e.g. +0900 or -1400), but does not support extended format: 2 digits or colon separated 4 digits
|
||||
* (e.g. +09 or -14:00). Let's add fallback logic to make it support the extended timezone spec. */
|
||||
|
||||
bool positive;
|
||||
switch (*t) {
|
||||
case '+':
|
||||
positive = true;
|
||||
break;
|
||||
case '-':
|
||||
positive = false;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
t++;
|
||||
r = undecchar(*t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
usec_t u = r * 10 * USEC_PER_HOUR;
|
||||
|
||||
t++;
|
||||
r = undecchar(*t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
u += r * USEC_PER_HOUR;
|
||||
|
||||
t++;
|
||||
if (*t == '\0') /* 2 digits case */
|
||||
goto finalize;
|
||||
|
||||
if (*t == ':') /* skip colon */
|
||||
t++;
|
||||
|
||||
r = undecchar(*t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r >= 6) /* refuse minutes equal to or larger than 60 */
|
||||
if (!k || *k != '\0')
|
||||
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;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
*ret = tm.tm_gmtoff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -889,11 +810,7 @@ static int parse_timestamp_impl(
|
||||
if (!k || *k != ' ')
|
||||
continue;
|
||||
|
||||
#ifdef __GLIBC__
|
||||
/* musl does not set tm_wday field and set 0 unless it is explicitly requested by %w or so.
|
||||
* In the below, let's only check tm_wday field only when built with glibc. */
|
||||
weekday = day->nr;
|
||||
#endif
|
||||
t = k + 1;
|
||||
break;
|
||||
}
|
||||
@ -1090,7 +1007,10 @@ int parse_timestamp(const char *t, usec_t *ret) {
|
||||
* not follow the timezone change in the current area. */
|
||||
tzset();
|
||||
for (int j = 0; j <= 1; j++) {
|
||||
if (!streq_ptr(tz, get_tzname(j)))
|
||||
if (isempty(tzname[j]))
|
||||
continue;
|
||||
|
||||
if (!streq(tz, tzname[j]))
|
||||
continue;
|
||||
|
||||
/* The specified timezone matches tzname[] of the local timezone. */
|
||||
|
||||
@ -149,7 +149,6 @@ static inline char* format_timestamp(char *buf, size_t l, usec_t t) {
|
||||
#define FORMAT_TIMESTAMP_STYLE(t, style) \
|
||||
format_timestamp_style((char[FORMAT_TIMESTAMP_MAX]){}, FORMAT_TIMESTAMP_MAX, t, style)
|
||||
|
||||
const char* get_tzname(bool dst);
|
||||
int parse_gmtoff(const char *t, long *ret);
|
||||
int parse_timestamp(const char *t, usec_t *ret);
|
||||
|
||||
|
||||
@ -182,11 +182,6 @@ if get_option('mode') == 'developer' and get_option('debug')
|
||||
efi_c_args += '-DEFI_DEBUG'
|
||||
endif
|
||||
|
||||
if get_option('libc') == 'musl'
|
||||
# To make musl not define wchar_t as int, rather than short.
|
||||
efi_c_args += '-D__DEFINED_wchar_t'
|
||||
endif
|
||||
|
||||
efi_c_ld_args = [
|
||||
'-nostdlib',
|
||||
'-static-pie',
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
#include "selinux-access.h"
|
||||
#include "service.h"
|
||||
#include "signal-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "unit.h"
|
||||
|
||||
@ -489,32 +488,21 @@ static int bus_set_transient_exit_status(
|
||||
|
||||
static int bus_set_transient_exec_context_fd(
|
||||
Unit *u,
|
||||
const char *name,
|
||||
int *p,
|
||||
bool *b,
|
||||
int verify_mode,
|
||||
sd_bus_message *message,
|
||||
UnitWriteFlags flags,
|
||||
sd_bus_error *error) {
|
||||
|
||||
int fd, r;
|
||||
|
||||
assert(name);
|
||||
assert(p);
|
||||
assert(b);
|
||||
assert(verify_mode == O_DIRECTORY || (verify_mode & ~O_ACCMODE_STRICT) == 0);
|
||||
|
||||
r = sd_bus_message_read(message, "h", &fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (verify_mode == O_DIRECTORY)
|
||||
r = fd_verify_directory(fd);
|
||||
else
|
||||
r = fd_vet_accmode(fd, verify_mode);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "%s passed is of incompatible type: %m", name);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
int copy;
|
||||
|
||||
@ -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);
|
||||
|
||||
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"))
|
||||
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"))
|
||||
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")) {
|
||||
const char *path, *fdname;
|
||||
@ -814,7 +802,7 @@ static int bus_service_set_transient_property(
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3208,7 +3208,7 @@ static int manager_dispatch_timezone_change(
|
||||
/* Read the new timezone */
|
||||
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)
|
||||
if (UNIT_VTABLE(u)->timezone_change)
|
||||
|
||||
@ -115,7 +115,6 @@ modules += [
|
||||
'sources' : pam_systemd_home_sources,
|
||||
'dependencies' : [
|
||||
libcrypt,
|
||||
libintl,
|
||||
libpam_misc,
|
||||
libpam,
|
||||
threads,
|
||||
|
||||
@ -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
|
||||
@ -16,8 +16,6 @@ libc_wrapper_sources = files(
|
||||
'xattr.c',
|
||||
)
|
||||
|
||||
subdir('musl')
|
||||
|
||||
sources += libc_wrapper_sources
|
||||
|
||||
libc_wrapper_static = static_library(
|
||||
|
||||
@ -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',
|
||||
)
|
||||
@ -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
|
||||
@ -45,13 +45,13 @@ static int object_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int server_init(sd_bus **ret) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
static int server_init(sd_bus **ret_bus) {
|
||||
_cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
|
||||
const char *unique, *desc;
|
||||
sd_id128_t id;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
assert_se(ret_bus);
|
||||
|
||||
r = sd_bus_open_user_with_description(&bus, "my bus!");
|
||||
if (r < 0)
|
||||
@ -65,8 +65,8 @@ static int server_init(sd_bus **ret) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get unique name: %m");
|
||||
|
||||
ASSERT_OK(sd_bus_get_description(bus, &desc));
|
||||
ASSERT_STREQ(desc, "my bus!");
|
||||
assert_se(sd_bus_get_description(bus, &desc) >= 0);
|
||||
assert_se(streq(desc, "my bus!"));
|
||||
|
||||
log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
|
||||
log_info("Unique ID: %s", unique);
|
||||
@ -94,11 +94,12 @@ static int server_init(sd_bus **ret) {
|
||||
|
||||
bus_match_dump(stdout, &bus->match_callbacks, 0);
|
||||
|
||||
*ret = TAKE_PTR(bus);
|
||||
*ret_bus = TAKE_PTR(bus);
|
||||
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;
|
||||
int r;
|
||||
|
||||
@ -249,7 +250,7 @@ static void* client1(void *p) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ASSERT_STREQ(hello, "hello");
|
||||
assert_se(streq(hello, "hello"));
|
||||
|
||||
if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
|
||||
r = log_error_errno(errno, "Failed to allocate pipe: %m");
|
||||
@ -493,30 +494,44 @@ finish:
|
||||
return INT_TO_PTR(r);
|
||||
}
|
||||
|
||||
TEST(chat) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
int main(int argc, char *argv[]) {
|
||||
pthread_t c1, c2;
|
||||
sd_bus *bus;
|
||||
void *p;
|
||||
int r;
|
||||
int q, r;
|
||||
|
||||
test_setup_logging(LOG_INFO);
|
||||
|
||||
r = server_init(&bus);
|
||||
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...");
|
||||
|
||||
ASSERT_OK(-pthread_create(&c1, NULL, client1, NULL));
|
||||
ASSERT_OK(-pthread_create(&c2, NULL, client2, NULL));
|
||||
r = pthread_create(&c1, NULL, client1, bus);
|
||||
if (r != 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
r = pthread_create(&c2, NULL, client2, bus);
|
||||
if (r != 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
r = server(bus);
|
||||
|
||||
ASSERT_OK(-pthread_join(c1, &p));
|
||||
ASSERT_OK(PTR_TO_INT(p));
|
||||
ASSERT_OK(-pthread_join(c2, &p));
|
||||
ASSERT_OK(PTR_TO_INT(p));
|
||||
ASSERT_OK(r);
|
||||
}
|
||||
q = pthread_join(c1, &p);
|
||||
if (q != 0)
|
||||
return EXIT_FAILURE;
|
||||
if (PTR_TO_INT(p) < 0)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -23,10 +23,13 @@ static int something_handler(sd_bus_message *m, void *userdata, sd_bus_error *re
|
||||
struct context *c = userdata;
|
||||
const char *s;
|
||||
char *n = NULL;
|
||||
int r;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static int exit_handler(sd_bus_message *m, void *userdata, sd_bus_error *reterr_error) {
|
||||
struct context *c = userdata;
|
||||
int r;
|
||||
|
||||
c->quit = true;
|
||||
|
||||
log_info("Exit called");
|
||||
|
||||
ASSERT_OK(sd_bus_reply_method_return(m, ""));
|
||||
r = sd_bus_reply_method_return(m, "");
|
||||
assert_se(r >= 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *reterr_error) {
|
||||
struct context *c = userdata;
|
||||
int r;
|
||||
|
||||
log_info("property get for %s called, returning \"%s\".", property, c->something);
|
||||
|
||||
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;
|
||||
}
|
||||
@ -67,12 +75,15 @@ static int set_handler(sd_bus *bus, const char *path, const char *interface, con
|
||||
struct context *c = userdata;
|
||||
const char *s;
|
||||
char *n;
|
||||
int r;
|
||||
|
||||
log_info("property set for %s called", property);
|
||||
|
||||
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);
|
||||
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) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
const char *x;
|
||||
int r;
|
||||
|
||||
ASSERT_OK(asprintf(&s, "object %p, path %s", userdata, path));
|
||||
ASSERT_OK(sd_bus_message_append(reply, "s", s));
|
||||
assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
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;
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
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;
|
||||
}
|
||||
@ -199,9 +230,9 @@ static int enumerator3_callback(sd_bus *bus, const char *path, void *userdata, c
|
||||
return 1;
|
||||
|
||||
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--)
|
||||
ASSERT_OK(strv_extendf(&v, "/value/b/%u", i));
|
||||
assert_se(strv_extendf(&v, "/value/b/%u", i) >= 0);
|
||||
|
||||
*nodes = TAKE_PTR(v);
|
||||
return 1;
|
||||
@ -215,22 +246,22 @@ static void* server(void *p) {
|
||||
|
||||
c->quit = false;
|
||||
|
||||
ASSERT_OK(sd_id128_randomize(&id));
|
||||
assert_se(sd_id128_randomize(&id) >= 0);
|
||||
|
||||
ASSERT_OK(sd_bus_new(&bus));
|
||||
ASSERT_OK(sd_bus_set_fd(bus, c->fds[0], c->fds[0]));
|
||||
ASSERT_OK(sd_bus_set_server(bus, 1, id));
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
|
||||
assert_se(sd_bus_set_server(bus, 1, id) >= 0);
|
||||
|
||||
ASSERT_OK(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c));
|
||||
ASSERT_OK(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c));
|
||||
ASSERT_OK(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)));
|
||||
ASSERT_OK(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL));
|
||||
ASSERT_OK(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL));
|
||||
ASSERT_OK(sd_bus_add_node_enumerator(bus, NULL, "/value/b", enumerator3_callback, NULL));
|
||||
ASSERT_OK(sd_bus_add_object_manager(bus, NULL, "/value"));
|
||||
ASSERT_OK(sd_bus_add_object_manager(bus, NULL, "/value/a"));
|
||||
assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
|
||||
assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
|
||||
assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
|
||||
assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0);
|
||||
assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL) >= 0);
|
||||
assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/b", enumerator3_callback, NULL) >= 0);
|
||||
assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0);
|
||||
assert_se(sd_bus_add_object_manager(bus, NULL, "/value/a") >= 0);
|
||||
|
||||
ASSERT_OK(sd_bus_start(bus));
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
log_error("Entering event loop on server");
|
||||
|
||||
@ -273,147 +304,178 @@ static int client(struct context *c) {
|
||||
const char *s;
|
||||
int r;
|
||||
|
||||
ASSERT_OK(sd_bus_new(&bus));
|
||||
ASSERT_OK(sd_bus_set_fd(bus, c->fds[1], c->fds[1]));
|
||||
ASSERT_OK(sd_bus_start(bus));
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
ASSERT_OK(sd_bus_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));
|
||||
ASSERT_STREQ(s, "<<<hallo>>>");
|
||||
r = sd_bus_message_read(reply, "s", &s);
|
||||
assert_se(r >= 0);
|
||||
assert_se(streq(s, "<<<hallo>>>"));
|
||||
|
||||
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, ""));
|
||||
ASSERT_TRUE(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
|
||||
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, "");
|
||||
assert_se(r < 0);
|
||||
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
|
||||
|
||||
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 */
|
||||
ASSERT_TRUE(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
|
||||
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, NULL); /* NULL and "" are equivalent */
|
||||
assert_se(r < 0);
|
||||
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
|
||||
|
||||
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"));
|
||||
ASSERT_TRUE(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS));
|
||||
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo");
|
||||
assert_se(r < 0);
|
||||
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS));
|
||||
|
||||
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));
|
||||
ASSERT_STREQ(s, "<<<hallo>>>");
|
||||
r = sd_bus_message_read(reply, "s", &s);
|
||||
assert_se(r >= 0);
|
||||
assert_se(streq(s, "<<<hallo>>>"));
|
||||
|
||||
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));
|
||||
ASSERT_STREQ(s, "test");
|
||||
r = sd_bus_message_read(reply, "s", &s);
|
||||
assert_se(r >= 0);
|
||||
assert_se(streq(s, "test"));
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
ASSERT_NOT_NULL(lines = strv_split_newlines(s));
|
||||
ASSERT_TRUE(strv_contains(lines, " <node name=\"x\"/>"));
|
||||
ASSERT_TRUE(strv_contains(lines, " <node name=\"y\"/>"));
|
||||
ASSERT_TRUE(strv_contains(lines, " <node name=\"z\"/>"));
|
||||
assert_se(lines = strv_split_newlines(s));
|
||||
assert_se(strv_contains(lines, " <node name=\"x\"/>"));
|
||||
assert_se(strv_contains(lines, " <node name=\"y\"/>"));
|
||||
assert_se(strv_contains(lines, " <node name=\"z\"/>"));
|
||||
lines = strv_free(lines);
|
||||
|
||||
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);
|
||||
|
||||
ASSERT_NOT_NULL(lines = strv_split_newlines(s));
|
||||
assert_se(lines = strv_split_newlines(s));
|
||||
for (unsigned i = 10; i < 30; i++) {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
|
||||
ASSERT_OK(asprintf(&n, " <node name=\"%u\"/>", i));
|
||||
ASSERT_TRUE(strv_contains(lines, n));
|
||||
assert_se(asprintf(&n, " <node name=\"%u\"/>", i) >= 0);
|
||||
assert_se(strv_contains(lines, n));
|
||||
}
|
||||
lines = strv_free(lines);
|
||||
|
||||
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);
|
||||
|
||||
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"));
|
||||
ASSERT_TRUE(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE));
|
||||
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2");
|
||||
assert_se(r < 0);
|
||||
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE));
|
||||
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));
|
||||
ASSERT_TRUE(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
|
||||
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, NULL);
|
||||
assert_se(r < 0);
|
||||
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
|
||||
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);
|
||||
|
||||
/* Check that /value/b does not have ObjectManager interface but /value/a does */
|
||||
ASSERT_OK_POSITIVE(sd_bus_message_rewind(reply, 1));
|
||||
ASSERT_OK_POSITIVE(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{oa{sa{sv}}}"));
|
||||
assert_se(sd_bus_message_rewind(reply, 1) > 0);
|
||||
assert_se(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{oa{sa{sv}}}") > 0);
|
||||
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;
|
||||
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. */
|
||||
switch (path_count) {
|
||||
@ -436,140 +498,154 @@ static int client(struct context *c) {
|
||||
|
||||
/* Check that there is no object manager interface here */
|
||||
bool found_object_manager_interface = false;
|
||||
ASSERT_OK_POSITIVE(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sa{sv}}"));
|
||||
while (ASSERT_OK(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sa{sv}")) > 0) {
|
||||
assert_se(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sa{sv}}") > 0);
|
||||
while (ASSERT_SE_NONNEG(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sa{sv}")) > 0) {
|
||||
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"))
|
||||
found_object_manager_interface = true;
|
||||
|
||||
ASSERT_OK(sd_bus_message_skip(reply, "a{sv}"));
|
||||
ASSERT_OK(sd_bus_message_exit_container(reply));
|
||||
assert_se(sd_bus_message_skip(reply, "a{sv}") >= 0);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
ASSERT_OK_POSITIVE(sd_bus_message_read_basic(reply, 'o', &should_be_value_a_x));
|
||||
ASSERT_STREQ(should_be_value_a_x, "/value/a/x");
|
||||
ASSERT_OK_POSITIVE(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sa{sv}}"));
|
||||
while (ASSERT_OK(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sa{sv}")) > 0) {
|
||||
assert_se(sd_bus_message_read_basic(reply, 'o', &should_be_value_a_x) > 0);
|
||||
assert_se(streq(should_be_value_a_x, "/value/a/x"));
|
||||
assert_se(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sa{sv}}") > 0);
|
||||
while (ASSERT_SE_NONNEG(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sa{sv}")) > 0) {
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
bool found_object_manager = false;
|
||||
ASSERT_OK_POSITIVE(sd_bus_message_read_basic(reply, 'o', &should_be_value_a));
|
||||
ASSERT_STREQ(should_be_value_a, "/value/a");
|
||||
ASSERT_OK_POSITIVE(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sa{sv}}"));
|
||||
while (ASSERT_OK(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sa{sv}")) > 0) {
|
||||
assert_se(sd_bus_message_read_basic(reply, 'o', &should_be_value_a) > 0);
|
||||
assert_se(streq(should_be_value_a, "/value/a"));
|
||||
assert_se(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sa{sv}}") > 0);
|
||||
while (ASSERT_SE_NONNEG(sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sa{sv}")) > 0) {
|
||||
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")) {
|
||||
found_object_manager = true;
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
ASSERT_OK_POSITIVE(sd_bus_message_read_basic(reply, 'o', &should_be_value_a_x));
|
||||
ASSERT_STREQ(should_be_value_a_x, "/value/a/x");
|
||||
ASSERT_OK_POSITIVE(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s"));
|
||||
assert_se(sd_bus_message_read_basic(reply, 'o', &should_be_value_a_x) > 0);
|
||||
assert_se(streq(should_be_value_a_x, "/value/a/x"));
|
||||
assert_se(sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s") > 0);
|
||||
const char* deleted_interface_name = NULL;
|
||||
while (ASSERT_OK(sd_bus_message_read_basic(reply, 's', &deleted_interface_name)))
|
||||
ASSERT_FALSE(streq(deleted_interface_name, "org.freedesktop.DBus.ObjectManager"));
|
||||
ASSERT_OK(sd_bus_message_exit_container(reply));
|
||||
while (ASSERT_SE_NONNEG(sd_bus_message_read_basic(reply, 's', &deleted_interface_name)) > 0) {
|
||||
assert(!streq(deleted_interface_name, "org.freedesktop.DBus.ObjectManager"));
|
||||
}
|
||||
assert_se(sd_bus_message_exit_container(reply) >= 0);
|
||||
|
||||
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);
|
||||
|
||||
@ -585,9 +661,9 @@ int main(int argc, char *argv[]) {
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
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);
|
||||
if (r != 0)
|
||||
|
||||
@ -14,8 +14,8 @@
|
||||
#include "user-util.h"
|
||||
|
||||
static bool gid_list_contained(const gid_t *a, size_t n, const gid_t *b, size_t m) {
|
||||
ASSERT_TRUE(a || n == 0);
|
||||
ASSERT_TRUE(b || m == 0);
|
||||
assert_se(a || n == 0);
|
||||
assert_se(b || m == 0);
|
||||
|
||||
/* Checks if every entry in a[] is also in b[] */
|
||||
|
||||
@ -46,70 +46,77 @@ static void* server(void *p) {
|
||||
sd_id128_t id;
|
||||
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_OK(sd_bus_set_fd(bus, fd, fd));
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_fd(bus, fd, fd) >= 0);
|
||||
TAKE_FD(fd);
|
||||
ASSERT_OK(sd_bus_set_server(bus, true, id));
|
||||
ASSERT_OK(sd_bus_negotiate_creds(bus, 1, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_SUPPLEMENTARY_GIDS));
|
||||
ASSERT_OK(sd_bus_start(bus));
|
||||
ASSERT_OK(sd_bus_get_owner_creds(bus, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_SUPPLEMENTARY_GIDS, &c));
|
||||
assert_se(sd_bus_set_server(bus, true, id) >= 0);
|
||||
assert_se(sd_bus_negotiate_creds(bus, 1, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_SUPPLEMENTARY_GIDS) >= 0);
|
||||
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
assert_se(sd_bus_get_owner_creds(bus, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_SUPPLEMENTARY_GIDS, &c) >= 0);
|
||||
|
||||
bus_creds_dump(c, /* f= */ NULL, /* terse= */ false);
|
||||
|
||||
uid_t u;
|
||||
ASSERT_OK(sd_bus_creds_get_euid(c, &u));
|
||||
ASSERT_EQ(u, getuid());
|
||||
assert_se(sd_bus_creds_get_euid(c, &u) >= 0);
|
||||
assert_se(u == getuid());
|
||||
|
||||
gid_t g;
|
||||
ASSERT_OK(sd_bus_creds_get_egid(c, &g));
|
||||
ASSERT_EQ(g, getgid());
|
||||
assert_se(sd_bus_creds_get_egid(c, &g) >= 0);
|
||||
assert_se(g == getgid());
|
||||
|
||||
pid_t pid;
|
||||
ASSERT_OK(sd_bus_creds_get_pid(c, &pid));
|
||||
ASSERT_EQ(pid, getpid_cached());
|
||||
assert_se(sd_bus_creds_get_pid(c, &pid) >= 0);
|
||||
assert_se(pid == getpid_cached());
|
||||
|
||||
int pidfd = -EBADF;
|
||||
if (sd_bus_creds_get_pidfd_dup(c, &pidfd) >= 0) {
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
|
||||
ASSERT_OK(pidref_set_pidfd_take(&pidref, pidfd));
|
||||
ASSERT_TRUE(pidref_is_self(&pidref));
|
||||
assert_se(pidref_set_pidfd_take(&pidref, pidfd) >= 0);
|
||||
assert_se(pidref_is_self(&pidref));
|
||||
}
|
||||
|
||||
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) {
|
||||
_cleanup_free_ gid_t *gg = NULL;
|
||||
ASSERT_OK(r = getgroups_alloc(&gg));
|
||||
ASSERT_TRUE(gid_list_same(gl, n, gg, r));
|
||||
r = getgroups_alloc(&gg);
|
||||
assert_se(r >= 0);
|
||||
|
||||
assert_se(gid_list_same(gl, n, gg, r));
|
||||
}
|
||||
|
||||
const char *comm;
|
||||
ASSERT_OK(sd_bus_creds_get_comm(c, &comm));
|
||||
ASSERT_OK(pid_get_comm(0, &our_comm));
|
||||
ASSERT_STREQ(comm, our_comm);
|
||||
assert_se(sd_bus_creds_get_comm(c, &comm) >= 0);
|
||||
assert_se(pid_get_comm(0, &our_comm) >= 0);
|
||||
assert_se(streq_ptr(comm, our_comm));
|
||||
|
||||
const char *description;
|
||||
ASSERT_OK(sd_bus_creds_get_description(c, &description));
|
||||
ASSERT_STREQ(description, "wuffwuff");
|
||||
assert_se(sd_bus_creds_get_description(c, &description) >= 0);
|
||||
assert_se(streq_ptr(description, "wuffwuff"));
|
||||
|
||||
for (;;) {
|
||||
_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) {
|
||||
ASSERT_OK(sd_bus_wait(bus, UINT64_MAX));
|
||||
assert_se(sd_bus_wait(bus, UINT64_MAX) >= 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -122,15 +129,15 @@ static void* client(void *p) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
const char *z;
|
||||
|
||||
ASSERT_OK(sd_bus_new(&bus));
|
||||
ASSERT_OK(sd_bus_set_description(bus, "wuffwuff"));
|
||||
ASSERT_OK(sd_bus_set_address(bus, p));
|
||||
ASSERT_OK(sd_bus_start(bus));
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_description(bus, "wuffwuff") >= 0);
|
||||
assert_se(sd_bus_set_address(bus, p) >= 0);
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
ASSERT_OK(sd_bus_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_STREQ(z, "bar");
|
||||
assert_se(sd_bus_message_read(reply, "s", &z) >= 0);
|
||||
assert_se(streq_ptr(z, "bar"));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -144,24 +151,27 @@ TEST(description) {
|
||||
socklen_t salen;
|
||||
pthread_t s, c;
|
||||
|
||||
ASSERT_OK_ERRNO(fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0));
|
||||
ASSERT_OK_ERRNO(bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path))); /* force auto-bind */
|
||||
ASSERT_OK_ERRNO(listen(fd, 1));
|
||||
fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
assert_se(bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path)) >= 0); /* force auto-bind */
|
||||
|
||||
assert_se(listen(fd, 1) >= 0);
|
||||
|
||||
salen = sizeof(sa);
|
||||
ASSERT_OK_ERRNO(getsockname(fd, &sa.sa, &salen));
|
||||
ASSERT_GE(salen, offsetof(struct sockaddr_un, sun_path));
|
||||
ASSERT_EQ(sa.un.sun_path[0], 0);
|
||||
assert_se(getsockname(fd, &sa.sa, &salen) >= 0);
|
||||
assert_se(salen >= offsetof(struct sockaddr_un, sun_path));
|
||||
assert_se(sa.un.sun_path[0] == 0);
|
||||
|
||||
ASSERT_OK(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);
|
||||
|
||||
ASSERT_OK(-pthread_create(&c, NULL, client, a));
|
||||
assert_se(pthread_create(&c, NULL, client, a) == 0);
|
||||
|
||||
ASSERT_OK(-pthread_join(s, NULL));
|
||||
ASSERT_OK(-pthread_join(c, NULL));
|
||||
assert_se(pthread_join(s, NULL) == 0);
|
||||
assert_se(pthread_join(c, NULL) == 0);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "bus-error.h"
|
||||
#include "log.h"
|
||||
#include "memory-util.h"
|
||||
#include "string-util.h"
|
||||
@ -26,14 +27,14 @@ static int _server(struct context *c) {
|
||||
bool quit = false;
|
||||
int r;
|
||||
|
||||
ASSERT_OK(sd_id128_randomize(&id));
|
||||
assert_se(sd_id128_randomize(&id) >= 0);
|
||||
|
||||
ASSERT_OK(sd_bus_new(&bus));
|
||||
ASSERT_OK(sd_bus_set_fd(bus, c->fds[0], c->fds[0]));
|
||||
ASSERT_OK(sd_bus_set_server(bus, 1, id));
|
||||
ASSERT_OK(sd_bus_set_anonymous(bus, c->server_anonymous_auth));
|
||||
ASSERT_OK(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds));
|
||||
ASSERT_OK(sd_bus_start(bus));
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
|
||||
assert_se(sd_bus_set_server(bus, 1, id) >= 0);
|
||||
assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0);
|
||||
assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
while (!quit) {
|
||||
_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");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -54,21 +57,29 @@ static int _server(struct context *c) {
|
||||
|
||||
if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) {
|
||||
|
||||
ASSERT_EQ(sd_bus_can_send(bus, 'h') >= 1,
|
||||
c->server_negotiate_unix_fds && c->client_negotiate_unix_fds);
|
||||
assert_se((sd_bus_can_send(bus, 'h') >= 1) ==
|
||||
(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;
|
||||
|
||||
} else if (sd_bus_message_is_method_call(m, NULL, NULL))
|
||||
ASSERT_OK(sd_bus_message_new_method_error(
|
||||
} else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
|
||||
r = sd_bus_message_new_method_error(
|
||||
m,
|
||||
&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)
|
||||
ASSERT_OK(sd_bus_send(bus, reply, NULL));
|
||||
if (reply) {
|
||||
r = sd_bus_send(bus, reply, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to send reply: %m");
|
||||
}
|
||||
}
|
||||
|
||||
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_unrefp) sd_bus *bus = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
int r;
|
||||
|
||||
ASSERT_OK(sd_bus_new(&bus));
|
||||
ASSERT_OK(sd_bus_set_fd(bus, c->fds[1], c->fds[1]));
|
||||
ASSERT_OK(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds));
|
||||
ASSERT_OK(sd_bus_set_anonymous(bus, c->client_anonymous_auth));
|
||||
ASSERT_OK(sd_bus_start(bus));
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
|
||||
assert_se(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0);
|
||||
assert_se(sd_bus_set_anonymous(bus, c->client_anonymous_auth) >= 0);
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
ASSERT_OK(sd_bus_message_new_method_call(
|
||||
r = sd_bus_message_new_method_call(
|
||||
bus,
|
||||
&m,
|
||||
"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,
|
||||
@ -110,7 +128,7 @@ static int test_one(bool client_negotiate_unix_fds, bool server_negotiate_unix_f
|
||||
|
||||
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.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 r;
|
||||
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
ASSERT_OK(test_one(true, true, false, false));
|
||||
ASSERT_OK(test_one(true, false, false, false));
|
||||
ASSERT_OK(test_one(false, true, false, false));
|
||||
ASSERT_OK(test_one(false, false, false, false));
|
||||
ASSERT_OK(test_one(true, true, true, true));
|
||||
ASSERT_OK(test_one(true, true, false, true));
|
||||
ASSERT_ERROR(test_one(true, true, true, false), EPERM);
|
||||
r = test_one(true, true, false, false);
|
||||
assert_se(r >= 0);
|
||||
|
||||
r = test_one(true, false, false, false);
|
||||
assert_se(r >= 0);
|
||||
|
||||
r = test_one(false, true, false, false);
|
||||
assert_se(r >= 0);
|
||||
|
||||
r = test_one(false, false, false, false);
|
||||
assert_se(r >= 0);
|
||||
|
||||
r = test_one(true, true, true, true);
|
||||
assert_se(r >= 0);
|
||||
|
||||
r = test_one(true, true, false, true);
|
||||
assert_se(r >= 0);
|
||||
|
||||
r = test_one(true, true, true, false);
|
||||
assert_se(r == -EPERM);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -24,14 +24,14 @@
|
||||
static int method_foobar(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
log_info("Got Foobar() call.");
|
||||
|
||||
ASSERT_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);
|
||||
}
|
||||
|
||||
static int method_exit(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
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 */
|
||||
bus_enter_closing(sd_bus_message_get_bus(m));
|
||||
return 0;
|
||||
@ -56,37 +56,37 @@ static void* thread_server(void *p) {
|
||||
/* Let's play some games, by slowly creating the socket directory, and renaming it in the middle */
|
||||
usleep_safe(100 * USEC_PER_MSEC);
|
||||
|
||||
ASSERT_OK(mkdir_parents(path, 0755));
|
||||
assert_se(mkdir_parents(path, 0755) >= 0);
|
||||
usleep_safe(100 * USEC_PER_MSEC);
|
||||
|
||||
ASSERT_OK(path_extract_directory(path, &d));
|
||||
ASSERT_OK(asprintf(&suffixed, "%s.%" PRIx64, d, random_u64()));
|
||||
ASSERT_OK_ERRNO(rename(d, suffixed));
|
||||
assert_se(path_extract_directory(path, &d) >= 0);
|
||||
assert_se(asprintf(&suffixed, "%s.%" PRIx64, d, random_u64()) >= 0);
|
||||
assert_se(rename(d, suffixed) >= 0);
|
||||
usleep_safe(100 * USEC_PER_MSEC);
|
||||
|
||||
ASSERT_OK(asprintf(&suffixed2, "%s.%" PRIx64, d, random_u64()));
|
||||
ASSERT_OK_ERRNO(symlink(suffixed2, d));
|
||||
assert_se(asprintf(&suffixed2, "%s.%" PRIx64, d, random_u64()) >= 0);
|
||||
assert_se(symlink(suffixed2, d) >= 0);
|
||||
usleep_safe(100 * USEC_PER_MSEC);
|
||||
|
||||
ASSERT_OK(path_extract_filename(suffixed, &suffixed_basename));
|
||||
ASSERT_OK_ERRNO(symlink(suffixed_basename, suffixed2));
|
||||
assert_se(path_extract_filename(suffixed, &suffixed_basename) >= 0);
|
||||
assert_se(symlink(suffixed_basename, suffixed2) >= 0);
|
||||
usleep_safe(100 * USEC_PER_MSEC);
|
||||
|
||||
socklen_t sa_len;
|
||||
r = sockaddr_un_set_path(&u.un, path);
|
||||
ASSERT_OK(r);
|
||||
assert_se(r >= 0);
|
||||
sa_len = r;
|
||||
|
||||
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);
|
||||
|
||||
ASSERT_OK_ERRNO(listen(fd, SOMAXCONN_DELUXE));
|
||||
assert_se(listen(fd, SOMAXCONN_DELUXE) >= 0);
|
||||
usleep_safe(100 * USEC_PER_MSEC);
|
||||
|
||||
ASSERT_OK(touch(path));
|
||||
assert_se(touch(path) >= 0);
|
||||
usleep_safe(100 * USEC_PER_MSEC);
|
||||
|
||||
log_debug("Initialized server");
|
||||
@ -97,31 +97,31 @@ static void* thread_server(void *p) {
|
||||
sd_id128_t id;
|
||||
int bus_fd, code;
|
||||
|
||||
ASSERT_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);
|
||||
ASSERT_OK_ERRNO(bus_fd);
|
||||
assert_se(bus_fd >= 0);
|
||||
|
||||
log_debug("Accepted server connection");
|
||||
|
||||
ASSERT_OK(sd_bus_new(&bus));
|
||||
ASSERT_OK(sd_bus_set_exit_on_disconnect(bus, true));
|
||||
ASSERT_OK(sd_bus_set_description(bus, "server"));
|
||||
ASSERT_OK(sd_bus_set_fd(bus, bus_fd, bus_fd));
|
||||
ASSERT_OK(sd_bus_set_server(bus, true, id));
|
||||
/* ASSERT_OK(sd_bus_set_anonymous(bus, true)); */
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_exit_on_disconnect(bus, true) >= 0);
|
||||
assert_se(sd_bus_set_description(bus, "server") >= 0);
|
||||
assert_se(sd_bus_set_fd(bus, bus_fd, bus_fd) >= 0);
|
||||
assert_se(sd_bus_set_server(bus, true, id) >= 0);
|
||||
/* assert_se(sd_bus_set_anonymous(bus, true) >= 0); */
|
||||
|
||||
ASSERT_OK(sd_bus_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)
|
||||
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_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
const char *path = p, *t;
|
||||
int r;
|
||||
|
||||
log_debug("Initializing client1");
|
||||
|
||||
ASSERT_OK(sd_bus_new(&bus));
|
||||
ASSERT_OK(sd_bus_set_description(bus, "client1"));
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_description(bus, "client1") >= 0);
|
||||
|
||||
t = strjoina("unix:path=", path);
|
||||
ASSERT_OK(sd_bus_set_address(bus, t));
|
||||
ASSERT_OK(sd_bus_set_watch_bind(bus, true));
|
||||
ASSERT_OK(sd_bus_start(bus));
|
||||
assert_se(sd_bus_set_address(bus, t) >= 0);
|
||||
assert_se(sd_bus_set_watch_bind(bus, true) >= 0);
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
ASSERT_OK(sd_bus_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");
|
||||
|
||||
@ -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) {
|
||||
ASSERT_OK_ZERO(sd_bus_message_is_method_error(m, NULL));
|
||||
ASSERT_OK(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 0));
|
||||
assert_se(sd_bus_message_is_method_error(m, NULL) == 0);
|
||||
assert_se(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 0) >= 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -167,19 +169,19 @@ static void* thread_client2(void *p) {
|
||||
|
||||
log_debug("Initializing client2");
|
||||
|
||||
ASSERT_OK(sd_event_new(&event));
|
||||
ASSERT_OK(sd_bus_new(&bus));
|
||||
ASSERT_OK(sd_bus_set_description(bus, "client2"));
|
||||
assert_se(sd_event_new(&event) >= 0);
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_description(bus, "client2") >= 0);
|
||||
|
||||
t = strjoina("unix:path=", path);
|
||||
ASSERT_OK(sd_bus_set_address(bus, t));
|
||||
ASSERT_OK(sd_bus_set_watch_bind(bus, true));
|
||||
ASSERT_OK(sd_bus_attach_event(bus, event, 0));
|
||||
ASSERT_OK(sd_bus_start(bus));
|
||||
assert_se(sd_bus_set_address(bus, t) >= 0);
|
||||
assert_se(sd_bus_set_watch_bind(bus, true) >= 0);
|
||||
assert_se(sd_bus_attach_event(bus, event, 0) >= 0);
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
ASSERT_OK(sd_bus_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");
|
||||
|
||||
@ -190,15 +192,15 @@ static void request_exit(const char *path) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
const char *t;
|
||||
|
||||
ASSERT_OK(sd_bus_new(&bus));
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
|
||||
t = strjoina("unix:path=", path);
|
||||
ASSERT_OK(sd_bus_set_address(bus, t));
|
||||
ASSERT_OK(sd_bus_set_watch_bind(bus, true));
|
||||
ASSERT_OK(sd_bus_set_description(bus, "request-exit"));
|
||||
ASSERT_OK(sd_bus_start(bus));
|
||||
assert_se(sd_bus_set_address(bus, t) >= 0);
|
||||
assert_se(sd_bus_set_watch_bind(bus, true) >= 0);
|
||||
assert_se(sd_bus_set_description(bus, "request-exit") >= 0);
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
ASSERT_OK(sd_bus_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[]) {
|
||||
@ -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
|
||||
* 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");
|
||||
|
||||
ASSERT_OK(-pthread_create(&server, NULL, thread_server, path));
|
||||
ASSERT_OK(-pthread_create(&client1, NULL, thread_client1, path));
|
||||
ASSERT_OK(-pthread_create(&client2, NULL, thread_client2, path));
|
||||
assert_se(pthread_create(&server, NULL, thread_server, path) == 0);
|
||||
assert_se(pthread_create(&client1, NULL, thread_client1, path) == 0);
|
||||
assert_se(pthread_create(&client2, NULL, thread_client2, path) == 0);
|
||||
|
||||
ASSERT_OK(-pthread_join(client1, NULL));
|
||||
ASSERT_OK(-pthread_join(client2, NULL));
|
||||
assert_se(pthread_join(client1, NULL) == 0);
|
||||
assert_se(pthread_join(client2, NULL) == 0);
|
||||
|
||||
request_exit(path);
|
||||
|
||||
ASSERT_OK(-pthread_join(server, NULL));
|
||||
assert_se(pthread_join(server, NULL) == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -41,18 +41,18 @@ static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userda
|
||||
log_info("got IO on %c", PTR_TO_INT(userdata));
|
||||
|
||||
if (userdata == INT_TO_PTR('a')) {
|
||||
ASSERT_OK(sd_event_source_set_enabled(s, SD_EVENT_OFF));
|
||||
ASSERT_FALSE(got_a);
|
||||
assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
|
||||
assert_se(!got_a);
|
||||
got_a = true;
|
||||
} else if (userdata == INT_TO_PTR('b')) {
|
||||
ASSERT_FALSE(got_b);
|
||||
assert_se(!got_b);
|
||||
got_b = true;
|
||||
} else if (userdata == INT_TO_PTR('d')) {
|
||||
got_d++;
|
||||
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
|
||||
ASSERT_OK(sd_event_source_set_enabled(s, SD_EVENT_OFF));
|
||||
assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
|
||||
} else
|
||||
assert_not_reached();
|
||||
|
||||
@ -61,19 +61,19 @@ static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userda
|
||||
|
||||
static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
|
||||
|
||||
ASSERT_NOT_NULL(s);
|
||||
ASSERT_NOT_NULL(si);
|
||||
assert_se(s);
|
||||
assert_se(si);
|
||||
|
||||
ASSERT_EQ(si->si_uid, getuid());
|
||||
ASSERT_EQ(si->si_signo, SIGCHLD);
|
||||
ASSERT_EQ(si->si_code, CLD_EXITED);
|
||||
ASSERT_EQ(si->si_status, 78);
|
||||
assert_se(si->si_uid == getuid());
|
||||
assert_se(si->si_signo == SIGCHLD);
|
||||
assert_se(si->si_code == CLD_EXITED);
|
||||
assert_se(si->si_status == 78);
|
||||
|
||||
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);
|
||||
|
||||
return 1;
|
||||
@ -84,35 +84,36 @@ static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si,
|
||||
pid_t pid;
|
||||
siginfo_t plain_si;
|
||||
|
||||
ASSERT_NOT_NULL(s);
|
||||
ASSERT_NOT_NULL(si);
|
||||
assert_se(s);
|
||||
assert_se(si);
|
||||
|
||||
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) {
|
||||
sigset_t ss;
|
||||
|
||||
ASSERT_OK_ERRNO(sigemptyset(&ss));
|
||||
ASSERT_OK_ERRNO(sigaddset(&ss, SIGUSR2));
|
||||
assert_se(sigemptyset(&ss) >= 0);
|
||||
assert_se(sigaddset(&ss, SIGUSR2) >= 0);
|
||||
|
||||
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_EQ(plain_si.si_value.sival_int, 4711);
|
||||
assert_se(plain_si.si_signo == SIGUSR2);
|
||||
assert_se(plain_si.si_value.sival_int == 4711);
|
||||
|
||||
_exit(78);
|
||||
}
|
||||
|
||||
ASSERT_OK(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')));
|
||||
ASSERT_OK(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT));
|
||||
ASSERT_OK(sd_event_source_set_child_process_own(p, true));
|
||||
assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0);
|
||||
assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
|
||||
assert_se(sd_event_source_set_child_process_own(p, true) >= 0);
|
||||
|
||||
/* 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
|
||||
@ -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_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);
|
||||
|
||||
@ -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) {
|
||||
sd_event_source *p = NULL;
|
||||
|
||||
ASSERT_NOT_NULL(s);
|
||||
assert_se(s);
|
||||
|
||||
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_OK(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT));
|
||||
assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0);
|
||||
assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
|
||||
raise(SIGUSR1);
|
||||
|
||||
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) {
|
||||
sd_event_source *p;
|
||||
|
||||
ASSERT_OK(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')));
|
||||
ASSERT_OK(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT));
|
||||
assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0);
|
||||
assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
|
||||
} else {
|
||||
ASSERT_FALSE(got_c);
|
||||
assert_se(!got_c);
|
||||
got_c = true;
|
||||
}
|
||||
} else
|
||||
@ -202,92 +203,84 @@ TEST(basic) {
|
||||
uint64_t event_now;
|
||||
int64_t priority;
|
||||
|
||||
ASSERT_OK_ERRNO(pipe(a));
|
||||
ASSERT_OK_ERRNO(pipe(b));
|
||||
ASSERT_OK_ERRNO(pipe(d));
|
||||
ASSERT_OK_ERRNO(pipe(k));
|
||||
assert_se(pipe(a) >= 0);
|
||||
assert_se(pipe(b) >= 0);
|
||||
assert_se(pipe(d) >= 0);
|
||||
assert_se(pipe(k) >= 0);
|
||||
|
||||
ASSERT_OK(sd_event_default(&e));
|
||||
ASSERT_OK_POSITIVE(sd_event_now(e, CLOCK_MONOTONIC, &event_now));
|
||||
assert_se(sd_event_default(&e) >= 0);
|
||||
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 */
|
||||
got_unref = false;
|
||||
ASSERT_OK(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL));
|
||||
ASSERT_OK_EQ_ERRNO(write(k[1], &ch, 1), 1);
|
||||
ASSERT_OK_POSITIVE(sd_event_run(e, UINT64_MAX));
|
||||
ASSERT_TRUE(got_unref);
|
||||
assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0);
|
||||
assert_se(write(k[1], &ch, 1) == 1);
|
||||
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
|
||||
assert_se(got_unref);
|
||||
|
||||
got_a = false, got_b = false, got_c = false, got_d = 0;
|
||||
|
||||
/* Add a oneshot handler, trigger it, reenable it, and trigger it again. */
|
||||
ASSERT_OK(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')));
|
||||
ASSERT_OK(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT));
|
||||
ASSERT_OK_ERRNO(write(d[1], &ch, 1));
|
||||
ASSERT_OK_POSITIVE(sd_event_run(e, UINT64_MAX));
|
||||
ASSERT_EQ(got_d, 1U);
|
||||
ASSERT_OK_ERRNO(write(d[1], &ch, 1));
|
||||
ASSERT_OK_POSITIVE(sd_event_run(e, UINT64_MAX));
|
||||
ASSERT_EQ(got_d, 2U);
|
||||
assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0);
|
||||
assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0);
|
||||
assert_se(write(d[1], &ch, 1) >= 0);
|
||||
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
|
||||
assert_se(got_d == 1);
|
||||
assert_se(write(d[1], &ch, 1) >= 0);
|
||||
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
|
||||
assert_se(got_d == 2);
|
||||
|
||||
ASSERT_OK(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')));
|
||||
ASSERT_OK(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')));
|
||||
assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0);
|
||||
assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0);
|
||||
|
||||
do_quit = false;
|
||||
ASSERT_OK(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')));
|
||||
ASSERT_OK(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')));
|
||||
assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0);
|
||||
assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0);
|
||||
|
||||
ASSERT_OK(sd_event_source_set_priority(x, 99));
|
||||
ASSERT_OK(sd_event_source_get_priority(x, &priority));
|
||||
ASSERT_EQ(priority, 99);
|
||||
ASSERT_OK(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT));
|
||||
ASSERT_OK(sd_event_source_set_prepare(x, prepare_handler));
|
||||
ASSERT_OK(sd_event_source_set_priority(z, 50));
|
||||
ASSERT_OK(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT));
|
||||
ASSERT_OK(sd_event_source_set_prepare(z, prepare_handler));
|
||||
assert_se(sd_event_source_set_priority(x, 99) >= 0);
|
||||
assert_se(sd_event_source_get_priority(x, &priority) >= 0);
|
||||
assert_se(priority == 99);
|
||||
assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0);
|
||||
assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0);
|
||||
assert_se(sd_event_source_set_priority(z, 50) >= 0);
|
||||
assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
|
||||
assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0);
|
||||
|
||||
/* Test for floating event sources */
|
||||
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1));
|
||||
ASSERT_OK(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL));
|
||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1) >= 0);
|
||||
assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0);
|
||||
|
||||
ASSERT_OK_ERRNO(write(a[1], &ch, 1));
|
||||
ASSERT_OK_ERRNO(write(b[1], &ch, 1));
|
||||
assert_se(write(a[1], &ch, 1) >= 0);
|
||||
assert_se(write(b[1], &ch, 1) >= 0);
|
||||
|
||||
ASSERT_FALSE(got_a);
|
||||
ASSERT_FALSE(got_b);
|
||||
ASSERT_FALSE(got_c);
|
||||
assert_se(!got_a && !got_b && !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_TRUE(got_b);
|
||||
ASSERT_FALSE(got_c);
|
||||
assert_se(!got_a && got_b && !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_TRUE(got_b);
|
||||
ASSERT_TRUE(got_c);
|
||||
assert_se(!got_a && got_b && 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_TRUE(got_b);
|
||||
ASSERT_TRUE(got_c);
|
||||
assert_se(got_a && got_b && got_c);
|
||||
|
||||
sd_event_source_unref(x);
|
||||
sd_event_source_unref(y);
|
||||
|
||||
do_quit = true;
|
||||
ASSERT_OK(sd_event_add_post(e, NULL, post_handler, NULL));
|
||||
ASSERT_OK_ZERO(sd_event_now(e, CLOCK_MONOTONIC, &event_now));
|
||||
ASSERT_OK(sd_event_source_set_time(z, event_now + 200 * USEC_PER_MSEC));
|
||||
ASSERT_OK(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT));
|
||||
assert_se(sd_event_add_post(e, NULL, post_handler, NULL) >= 0);
|
||||
assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0);
|
||||
assert_se(sd_event_source_set_time(z, event_now + 200 * USEC_PER_MSEC) >= 0);
|
||||
assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0);
|
||||
|
||||
ASSERT_OK(sd_event_loop(e));
|
||||
ASSERT_TRUE(got_post);
|
||||
ASSERT_TRUE(got_exit);
|
||||
assert_se(sd_event_loop(e) >= 0);
|
||||
assert_se(got_post);
|
||||
assert_se(got_exit);
|
||||
|
||||
sd_event_source_unref(z);
|
||||
sd_event_source_unref(q);
|
||||
@ -306,24 +299,24 @@ TEST(sd_event_now) {
|
||||
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
||||
uint64_t event_now;
|
||||
|
||||
ASSERT_OK(sd_event_new(&e));
|
||||
ASSERT_OK_POSITIVE(sd_event_now(e, CLOCK_MONOTONIC, &event_now));
|
||||
ASSERT_OK_POSITIVE(sd_event_now(e, CLOCK_REALTIME, &event_now));
|
||||
ASSERT_OK_POSITIVE(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now));
|
||||
ASSERT_OK_POSITIVE(sd_event_now(e, CLOCK_BOOTTIME, &event_now));
|
||||
ASSERT_OK_POSITIVE(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now));
|
||||
ASSERT_ERROR(sd_event_now(e, -1, &event_now), EOPNOTSUPP);
|
||||
ASSERT_ERROR(sd_event_now(e, 900 /* arbitrary big number */, &event_now), EOPNOTSUPP);
|
||||
assert_se(sd_event_new(&e) >= 0);
|
||||
assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0);
|
||||
assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) > 0);
|
||||
assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) > 0);
|
||||
assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) > 0);
|
||||
assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) > 0);
|
||||
assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
|
||||
assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
|
||||
|
||||
ASSERT_OK_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_OK_ZERO(sd_event_now(e, CLOCK_REALTIME, &event_now));
|
||||
ASSERT_OK_ZERO(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now));
|
||||
ASSERT_OK_ZERO(sd_event_now(e, CLOCK_BOOTTIME, &event_now));
|
||||
ASSERT_OK_ZERO(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now));
|
||||
ASSERT_ERROR(sd_event_now(e, -1, &event_now), EOPNOTSUPP);
|
||||
ASSERT_ERROR(sd_event_now(e, 900 /* arbitrary big number */, &event_now), EOPNOTSUPP);
|
||||
assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0);
|
||||
assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) == 0);
|
||||
assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) == 0);
|
||||
assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) == 0);
|
||||
assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) == 0);
|
||||
assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
|
||||
assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int last_rtqueue_sigval = 0;
|
||||
@ -339,43 +332,43 @@ TEST(rtqueue) {
|
||||
sd_event_source *u = NULL, *v = NULL, *s = 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_OK(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL));
|
||||
ASSERT_OK(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL));
|
||||
ASSERT_OK(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL));
|
||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2) >= 0);
|
||||
assert_se(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL) >= 0);
|
||||
assert_se(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL) >= 0);
|
||||
assert_se(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL) >= 0);
|
||||
|
||||
ASSERT_OK(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_OK_ERRNO(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }));
|
||||
ASSERT_OK_ERRNO(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 3 }));
|
||||
ASSERT_OK_ERRNO(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }));
|
||||
ASSERT_OK_ERRNO(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 5 }));
|
||||
assert_se(sigqueue(getpid_cached(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }) >= 0);
|
||||
assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }) >= 0);
|
||||
assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 3 }) >= 0);
|
||||
assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }) >= 0);
|
||||
assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 5 }) >= 0);
|
||||
|
||||
ASSERT_EQ(n_rtqueue, 0);
|
||||
ASSERT_EQ(last_rtqueue_sigval, 0);
|
||||
assert_se(n_rtqueue == 0);
|
||||
assert_se(last_rtqueue_sigval == 0);
|
||||
|
||||
ASSERT_OK_EQ(sd_event_run(e, UINT64_MAX), 1);
|
||||
ASSERT_EQ(n_rtqueue, 1);
|
||||
ASSERT_EQ(last_rtqueue_sigval, 2); /* first SIGRTMIN+3 */
|
||||
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
|
||||
assert_se(n_rtqueue == 1);
|
||||
assert_se(last_rtqueue_sigval == 2); /* first SIGRTMIN+3 */
|
||||
|
||||
ASSERT_OK_EQ(sd_event_run(e, UINT64_MAX), 1);
|
||||
ASSERT_EQ(n_rtqueue, 2);
|
||||
ASSERT_EQ(last_rtqueue_sigval, 4); /* second SIGRTMIN+3 */
|
||||
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
|
||||
assert_se(n_rtqueue == 2);
|
||||
assert_se(last_rtqueue_sigval == 4); /* second SIGRTMIN+3 */
|
||||
|
||||
ASSERT_OK_EQ(sd_event_run(e, UINT64_MAX), 1);
|
||||
ASSERT_EQ(n_rtqueue, 3);
|
||||
ASSERT_EQ(last_rtqueue_sigval, 3); /* first SIGUSR2 */
|
||||
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
|
||||
assert_se(n_rtqueue == 3);
|
||||
assert_se(last_rtqueue_sigval == 3); /* first SIGUSR2 */
|
||||
|
||||
ASSERT_OK_EQ(sd_event_run(e, UINT64_MAX), 1);
|
||||
ASSERT_EQ(n_rtqueue, 4);
|
||||
ASSERT_EQ(last_rtqueue_sigval, 1); /* SIGRTMIN+2 */
|
||||
assert_se(sd_event_run(e, UINT64_MAX) >= 1);
|
||||
assert_se(n_rtqueue == 4);
|
||||
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_EQ(n_rtqueue, 4);
|
||||
ASSERT_EQ(last_rtqueue_sigval, 1);
|
||||
assert_se(sd_event_run(e, 0) == 0); /* the other SIGUSR2 is dropped, because the first one was still queued */
|
||||
assert_se(n_rtqueue == 4);
|
||||
assert_se(last_rtqueue_sigval == 1);
|
||||
|
||||
sd_event_source_unref(u);
|
||||
sd_event_source_unref(v);
|
||||
@ -397,8 +390,8 @@ struct inotify_context {
|
||||
static void maybe_exit(sd_event_source *s, struct inotify_context *c) {
|
||||
unsigned n;
|
||||
|
||||
ASSERT_NOT_NULL(s);
|
||||
ASSERT_NOT_NULL(c);
|
||||
assert_se(s);
|
||||
assert_se(c);
|
||||
|
||||
if (!c->delete_self_handler_called)
|
||||
return;
|
||||
@ -422,31 +415,31 @@ static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, v
|
||||
const char *path, *description;
|
||||
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_OK(safe_atou(description, &n));
|
||||
assert_se(sd_event_source_get_description(s, &description) >= 0);
|
||||
assert_se(safe_atou(description, &n) >= 0);
|
||||
|
||||
ASSERT_LE(n, 3U);
|
||||
assert_se(n <= 3);
|
||||
bit = 1U << n;
|
||||
|
||||
if (ev->mask & IN_Q_OVERFLOW) {
|
||||
log_info("inotify-handler for %s <%s>: overflow", path, description);
|
||||
c->create_overflow |= bit;
|
||||
} else if (ev->mask & IN_CREATE) {
|
||||
ASSERT_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"))
|
||||
log_debug("inotify-handler for %s <%s>: create on %s", path, description, ev->name);
|
||||
else {
|
||||
unsigned i;
|
||||
|
||||
ASSERT_OK(safe_atou(ev->name, &i));
|
||||
ASSERT_LT(i, c->n_create_events);
|
||||
assert_se(safe_atou(ev->name, &i) >= 0);
|
||||
assert_se(i < c->n_create_events);
|
||||
c->create_called[i] |= bit;
|
||||
}
|
||||
} else if (ev->mask & IN_DELETE) {
|
||||
log_info("inotify-handler for %s <%s>: delete of %s", path, description, ev->name);
|
||||
ASSERT_STREQ(ev->name, "sub");
|
||||
assert_se(streq(ev->name, "sub"));
|
||||
} else
|
||||
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);
|
||||
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) {
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
ASSERT_OK(sd_event_add_inotify(e, &a, p, IN_CREATE|IN_ONLYDIR, inotify_handler, &context));
|
||||
ASSERT_OK(sd_event_add_inotify(e, &b, p, IN_CREATE|IN_DELETE|IN_DONT_FOLLOW, inotify_handler, &context));
|
||||
ASSERT_OK(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_IDLE));
|
||||
ASSERT_OK(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_NORMAL));
|
||||
ASSERT_OK(sd_event_add_inotify(e, &c, p, IN_CREATE|IN_DELETE|IN_EXCL_UNLINK, inotify_handler, &context));
|
||||
ASSERT_OK(sd_event_source_set_priority(c, SD_EVENT_PRIORITY_IDLE));
|
||||
assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE|IN_ONLYDIR, inotify_handler, &context) >= 0);
|
||||
assert_se(sd_event_add_inotify(e, &b, p, IN_CREATE|IN_DELETE|IN_DONT_FOLLOW, inotify_handler, &context) >= 0);
|
||||
assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_IDLE) >= 0);
|
||||
assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_NORMAL) >= 0);
|
||||
assert_se(sd_event_add_inotify(e, &c, p, IN_CREATE|IN_DELETE|IN_EXCL_UNLINK, inotify_handler, &context) >= 0);
|
||||
assert_se(sd_event_source_set_priority(c, SD_EVENT_PRIORITY_IDLE) >= 0);
|
||||
|
||||
ASSERT_OK(sd_event_source_set_description(a, "0"));
|
||||
ASSERT_OK(sd_event_source_set_description(b, "1"));
|
||||
ASSERT_OK(sd_event_source_set_description(c, "2"));
|
||||
assert_se(sd_event_source_set_description(a, "0") >= 0);
|
||||
assert_se(sd_event_source_set_description(b, "1") >= 0);
|
||||
assert_se(sd_event_source_set_description(c, "2") >= 0);
|
||||
|
||||
ASSERT_OK(sd_event_source_get_inotify_path(a, &pp));
|
||||
ASSERT_TRUE(path_equal_or_inode_same(pp, p, 0));
|
||||
ASSERT_OK(sd_event_source_get_inotify_path(b, &pp));
|
||||
ASSERT_TRUE(path_equal_or_inode_same(pp, p, 0));
|
||||
ASSERT_OK(sd_event_source_get_inotify_path(b, &pp));
|
||||
ASSERT_TRUE(path_equal_or_inode_same(pp, p, 0));
|
||||
assert_se(sd_event_source_get_inotify_path(a, &pp) >= 0);
|
||||
assert_se(path_equal_or_inode_same(pp, p, 0));
|
||||
assert_se(sd_event_source_get_inotify_path(b, &pp) >= 0);
|
||||
assert_se(path_equal_or_inode_same(pp, p, 0));
|
||||
assert_se(sd_event_source_get_inotify_path(b, &pp) >= 0);
|
||||
assert_se(path_equal_or_inode_same(pp, p, 0));
|
||||
|
||||
q = strjoina(p, "/sub");
|
||||
ASSERT_OK(touch(q));
|
||||
ASSERT_OK(sd_event_add_inotify(e, &d, q, IN_DELETE_SELF, delete_self_handler, &context));
|
||||
assert_se(touch(q) >= 0);
|
||||
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++) {
|
||||
char buf[DECIMAL_STR_MAX(unsigned)+1];
|
||||
_cleanup_free_ char *z = NULL;
|
||||
|
||||
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(b);
|
||||
@ -542,19 +535,19 @@ TEST(inotify) {
|
||||
}
|
||||
|
||||
static int pidfd_handler(sd_event_source *s, const siginfo_t *si, void *userdata) {
|
||||
ASSERT_NOT_NULL(s);
|
||||
ASSERT_NOT_NULL(si);
|
||||
assert_se(s);
|
||||
assert_se(si);
|
||||
|
||||
ASSERT_EQ(si->si_uid, getuid());
|
||||
ASSERT_EQ(si->si_signo, SIGCHLD);
|
||||
ASSERT_EQ(si->si_code, CLD_EXITED);
|
||||
ASSERT_EQ(si->si_status, 66);
|
||||
assert_se(si->si_uid == getuid());
|
||||
assert_se(si->si_signo == SIGCHLD);
|
||||
assert_se(si->si_code == CLD_EXITED);
|
||||
assert_se(si->si_status == 66);
|
||||
|
||||
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);
|
||||
|
||||
return 0;
|
||||
@ -566,36 +559,40 @@ TEST(pidfd) {
|
||||
int pidfd;
|
||||
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)
|
||||
/* child */
|
||||
_exit(66);
|
||||
|
||||
assert_se(pid > 1);
|
||||
|
||||
ASSERT_OK(pidfd = pidfd_open(pid, 0));
|
||||
|
||||
ASSERT_OK_ERRNO(pid2 = fork());
|
||||
pid2 = fork();
|
||||
if (pid2 == 0)
|
||||
freeze();
|
||||
|
||||
ASSERT_OK(sd_event_default(&e));
|
||||
ASSERT_OK(sd_event_add_child_pidfd(e, &s, pidfd, WEXITED, pidfd_handler, INT_TO_PTR('p')));
|
||||
ASSERT_OK(sd_event_source_set_child_pidfd_own(s, true));
|
||||
assert_se(pid > 2);
|
||||
|
||||
assert_se(sd_event_default(&e) >= 0);
|
||||
assert_se(sd_event_add_child_pidfd(e, &s, pidfd, WEXITED, pidfd_handler, INT_TO_PTR('p')) >= 0);
|
||||
assert_se(sd_event_source_set_child_pidfd_own(s, true) >= 0);
|
||||
|
||||
/* 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_OK(sd_event_source_set_child_process_own(t, true));
|
||||
assert_se(sd_event_add_child(e, &t, pid2, WEXITED, pidfd_handler, INT_TO_PTR('q')) >= 0);
|
||||
assert_se(sd_event_source_set_child_process_own(t, true) >= 0);
|
||||
|
||||
ASSERT_OK(sd_event_loop(e));
|
||||
assert_se(sd_event_loop(e) >= 0);
|
||||
|
||||
/* Child should still be alive */
|
||||
ASSERT_OK_ERRNO(kill(pid2, 0));
|
||||
assert_se(kill(pid2, 0) >= 0);
|
||||
|
||||
t = sd_event_source_unref(t);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
@ -635,74 +632,73 @@ TEST(ratelimit) {
|
||||
uint64_t interval;
|
||||
unsigned count, burst;
|
||||
|
||||
ASSERT_OK(sd_event_default(&e));
|
||||
ASSERT_OK_ERRNO(pipe2(p, O_CLOEXEC|O_NONBLOCK));
|
||||
assert_se(sd_event_default(&e) >= 0);
|
||||
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_OK(sd_event_source_set_description(s, "test-ratelimit-io"));
|
||||
ASSERT_OK(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5));
|
||||
ASSERT_OK(sd_event_source_get_ratelimit(s, &interval, &burst));
|
||||
ASSERT_EQ(interval, 1 * USEC_PER_SEC);
|
||||
ASSERT_EQ(burst, 5U);
|
||||
assert_se(sd_event_add_io(e, &s, p[0], EPOLLIN, ratelimit_io_handler, &count) >= 0);
|
||||
assert_se(sd_event_source_set_description(s, "test-ratelimit-io") >= 0);
|
||||
assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5) >= 0);
|
||||
assert_se(sd_event_source_get_ratelimit(s, &interval, &burst) >= 0);
|
||||
assert_se(interval == 1 * USEC_PER_SEC && burst == 5);
|
||||
|
||||
ASSERT_OK_EQ_ERRNO(write(p[1], "1", 1), 1);
|
||||
assert_se(write(p[1], "1", 1) == 1);
|
||||
|
||||
count = 0;
|
||||
for (unsigned i = 0; i < 10; i++) {
|
||||
log_debug("slow loop iteration %u", i);
|
||||
ASSERT_OK(sd_event_run(e, UINT64_MAX));
|
||||
ASSERT_OK(usleep_safe(250 * USEC_PER_MSEC));
|
||||
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
|
||||
assert_se(usleep_safe(250 * USEC_PER_MSEC) >= 0);
|
||||
}
|
||||
|
||||
ASSERT_OK_ZERO(sd_event_source_is_ratelimited(s));
|
||||
ASSERT_EQ(count, 10U);
|
||||
assert_se(sd_event_source_is_ratelimited(s) == 0);
|
||||
assert_se(count == 10);
|
||||
log_info("ratelimit_io_handler: called %u times, event source not ratelimited", count);
|
||||
|
||||
ASSERT_OK(sd_event_source_set_ratelimit(s, 0, 0));
|
||||
ASSERT_OK(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5));
|
||||
assert_se(sd_event_source_set_ratelimit(s, 0, 0) >= 0);
|
||||
assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5) >= 0);
|
||||
|
||||
count = 0;
|
||||
for (unsigned i = 0; i < 10; i++) {
|
||||
log_debug("fast event loop iteration %u", i);
|
||||
ASSERT_OK(sd_event_run(e, UINT64_MAX));
|
||||
ASSERT_OK(usleep_safe(10));
|
||||
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
|
||||
assert_se(usleep_safe(10) >= 0);
|
||||
}
|
||||
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);
|
||||
safe_close_pair(p);
|
||||
|
||||
count = 0;
|
||||
ASSERT_OK(sd_event_add_time_relative(e, &s, CLOCK_MONOTONIC, 1000, 1, ratelimit_time_handler, &count));
|
||||
ASSERT_OK_ZERO(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10));
|
||||
assert_se(sd_event_add_time_relative(e, &s, CLOCK_MONOTONIC, 1000, 1, ratelimit_time_handler, &count) >= 0);
|
||||
assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10) == 0);
|
||||
|
||||
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));
|
||||
|
||||
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 */
|
||||
ASSERT_OK(sd_event_source_set_ratelimit(s, 0, 0));
|
||||
ASSERT_OK_ZERO(sd_event_source_is_ratelimited(s));
|
||||
assert_se(sd_event_source_set_ratelimit(s, 0, 0) >= 0);
|
||||
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. */
|
||||
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 {
|
||||
ASSERT_OK(sd_event_run(e, UINT64_MAX));
|
||||
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
|
||||
} while (!sd_event_source_is_ratelimited(s));
|
||||
|
||||
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 */
|
||||
ASSERT_OK(sd_event_run(e, UINT64_MAX));
|
||||
ASSERT_EQ(expired, 0);
|
||||
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
|
||||
assert_se(expired == 0);
|
||||
}
|
||||
|
||||
TEST(simple_timeout) {
|
||||
@ -711,29 +707,29 @@ TEST(simple_timeout) {
|
||||
|
||||
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);
|
||||
ASSERT_OK(sd_event_wait(e, some_time));
|
||||
assert_se(sd_event_wait(e, some_time) >= 0);
|
||||
t = now(CLOCK_MONOTONIC);
|
||||
|
||||
/* The event loop may sleep longer than the specified time (timer accuracy, scheduling latencies, …),
|
||||
* but never shorter. Let's check that. */
|
||||
ASSERT_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) {
|
||||
sd_event_source **p = userdata;
|
||||
|
||||
ASSERT_NOT_NULL(ev);
|
||||
ASSERT_NOT_NULL(p);
|
||||
ASSERT_PTR_EQ(*p, s);
|
||||
assert_se(ev);
|
||||
assert_se(p);
|
||||
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
|
||||
* 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 */
|
||||
|
||||
ASSERT_OK(sd_event_default(&e));
|
||||
assert_se(sd_event_default(&e) >= 0);
|
||||
|
||||
ASSERT_OK(fd = mkostemp_safe(path));
|
||||
ASSERT_OK(sd_event_add_inotify_fd(e, &s, fd, IN_ATTRIB, inotify_self_destroy_handler, &s));
|
||||
fd = mkostemp_safe(path);
|
||||
assert_se(fd >= 0);
|
||||
assert_se(sd_event_add_inotify_fd(e, &s, fd, IN_ATTRIB, inotify_self_destroy_handler, &s) >= 0);
|
||||
fd = safe_close(fd);
|
||||
ASSERT_OK_ERRNO(unlink(path)); /* This will trigger IN_ATTRIB because link count goes to zero */
|
||||
ASSERT_OK(sd_event_loop(e));
|
||||
assert_se(unlink(path) >= 0); /* This will trigger IN_ATTRIB because link count goes to zero */
|
||||
assert_se(sd_event_loop(e) >= 0);
|
||||
}
|
||||
|
||||
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);
|
||||
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_STREQ(c->path[c->i], description);
|
||||
assert_se(c->i < 2);
|
||||
assert_se(streq(c->path[c->i], description));
|
||||
c->i++;
|
||||
|
||||
return 1;
|
||||
@ -783,30 +780,30 @@ TEST(inotify_process_buffered_data) {
|
||||
|
||||
/* 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_OK(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &q));
|
||||
assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0);
|
||||
assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &q) >= 0);
|
||||
|
||||
struct inotify_process_buffered_data_context context = {
|
||||
.path = { p, q },
|
||||
};
|
||||
|
||||
ASSERT_OK(sd_event_add_inotify(e, &a, p, IN_CREATE, inotify_process_buffered_data_handler, &context));
|
||||
ASSERT_OK(sd_event_add_inotify(e, &b, q, IN_CREATE, inotify_process_buffered_data_handler, &context));
|
||||
assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE, inotify_process_buffered_data_handler, &context) >= 0);
|
||||
assert_se(sd_event_add_inotify(e, &b, q, IN_CREATE, inotify_process_buffered_data_handler, &context) >= 0);
|
||||
|
||||
ASSERT_NOT_NULL(z = path_join(p, "aaa"));
|
||||
ASSERT_OK(touch(z));
|
||||
assert_se(z = path_join(p, "aaa"));
|
||||
assert_se(touch(z) >= 0);
|
||||
z = mfree(z);
|
||||
ASSERT_NOT_NULL(z = path_join(q, "bbb"));
|
||||
ASSERT_OK(touch(z));
|
||||
assert_se(z = path_join(q, "bbb"));
|
||||
assert_se(touch(z) >= 0);
|
||||
z = mfree(z);
|
||||
|
||||
ASSERT_OK_POSITIVE(sd_event_run(e, 10 * USEC_PER_SEC));
|
||||
ASSERT_OK_POSITIVE(sd_event_prepare(e)); /* issue #23826: this was 0. */
|
||||
ASSERT_OK_POSITIVE(sd_event_dispatch(e));
|
||||
ASSERT_OK_ZERO(sd_event_prepare(e));
|
||||
ASSERT_OK_ZERO(sd_event_wait(e, 0));
|
||||
assert_se(sd_event_run(e, 10 * USEC_PER_SEC) > 0);
|
||||
assert_se(sd_event_prepare(e) > 0); /* issue #23826: this was 0. */
|
||||
assert_se(sd_event_dispatch(e) > 0);
|
||||
assert_se(sd_event_prepare(e) == 0);
|
||||
assert_se(sd_event_wait(e, 0) == 0);
|
||||
}
|
||||
|
||||
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;
|
||||
int r;
|
||||
|
||||
ASSERT_OK(sd_event_default(&e));
|
||||
ASSERT_OK_ZERO(sd_event_prepare(e));
|
||||
assert_se(sd_event_default(&e) >= 0);
|
||||
assert_se(sd_event_prepare(e) == 0);
|
||||
|
||||
/* Check that after a fork the cleanup functions return NULL */
|
||||
r = safe_fork("(bus-fork-test)", FORK_WAIT|FORK_LOG, NULL);
|
||||
if (r == 0) {
|
||||
ASSERT_NOT_NULL(e);
|
||||
ASSERT_NULL(sd_event_ref(e));
|
||||
ASSERT_NULL(sd_event_unref(e));
|
||||
assert_se(e);
|
||||
assert_se(sd_event_ref(e) == NULL);
|
||||
assert_se(sd_event_unref(e) == NULL);
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
ASSERT_OK(r);
|
||||
assert_se(r >= 0);
|
||||
}
|
||||
|
||||
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_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_OK_ERRNO(pipe2(pfd_b, O_CLOEXEC));
|
||||
assert_se(pipe2(pfd_a, O_CLOEXEC) >= 0);
|
||||
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_OK(sd_event_source_set_io_fd_own(s, true));
|
||||
assert_se(sd_event_add_io(e, &s, pfd_a[0], EPOLLIN, NULL, INT_TO_PTR(-ENOANO)) >= 0);
|
||||
assert_se(sd_event_source_set_io_fd_own(s, true) >= 0);
|
||||
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]);
|
||||
}
|
||||
|
||||
static int hup_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
||||
unsigned *c = userdata;
|
||||
|
||||
ASSERT_EQ(revents, (uint32_t) EPOLLHUP);
|
||||
assert_se(revents == EPOLLHUP);
|
||||
|
||||
(*c)++;
|
||||
return 0;
|
||||
@ -897,42 +894,47 @@ TEST(leave_ratelimit) {
|
||||
unsigned c = 0;
|
||||
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,
|
||||
* and which hence will only see EOF and constant EPOLLHUP */
|
||||
ASSERT_OK_ERRNO(pipe2(pfd, O_CLOEXEC));
|
||||
ASSERT_OK(sd_event_add_io(e, &s, pfd[0], EPOLLIN, hup_callback, &c));
|
||||
ASSERT_OK(sd_event_source_set_io_fd_own(s, true));
|
||||
ASSERT_OK(sd_event_source_set_ratelimit(s, 5*USEC_PER_MINUTE, 5));
|
||||
assert_se(pipe2(pfd, O_CLOEXEC) >= 0);
|
||||
assert_se(sd_event_add_io(e, &s, pfd[0], EPOLLIN, hup_callback, &c) >= 0);
|
||||
assert_se(sd_event_source_set_io_fd_own(s, true) >= 0);
|
||||
assert_se(sd_event_source_set_ratelimit(s, 5*USEC_PER_MINUTE, 5) >= 0);
|
||||
|
||||
pfd[0] = -EBADF;
|
||||
pfd[1] = safe_close(pfd[1]); /* Trigger continuous EOF */
|
||||
|
||||
for (;;) {
|
||||
ASSERT_OK(r = sd_event_prepare(e));
|
||||
r = sd_event_prepare(e);
|
||||
assert_se(r >= 0);
|
||||
|
||||
if (r == 0)
|
||||
ASSERT_OK_POSITIVE(sd_event_wait(e, UINT64_MAX));
|
||||
if (r == 0) {
|
||||
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)
|
||||
/* First four dispatches should just work */
|
||||
ASSERT_FALSE(r);
|
||||
assert_se(!r);
|
||||
else if (c == 5) {
|
||||
/* The fifth dispatch should still work, but we now expect the ratelimit to be hit subsequently */
|
||||
if (!expect_ratelimit) {
|
||||
ASSERT_FALSE(r);
|
||||
ASSERT_OK_ZERO(sd_event_source_leave_ratelimit(s)); /* this should be a NOP, and return 0 hence */
|
||||
assert_se(!r);
|
||||
assert_se(sd_event_source_leave_ratelimit(s) == 0); /* this should be a NOP, and return 0 hence */
|
||||
expect_ratelimit = true;
|
||||
} else {
|
||||
/* We expected the ratelimit, let's leave it manually, and verify it */
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_OK_POSITIVE(sd_event_source_leave_ratelimit(s)); /* we are ratelimited, hence should return > 0 */
|
||||
ASSERT_OK_ZERO(sd_event_source_is_ratelimited(s));
|
||||
assert_se(r);
|
||||
assert_se(sd_event_source_leave_ratelimit(s) > 0); /* we are ratelimited, hence should return > 0 */
|
||||
assert_se(sd_event_source_is_ratelimited(s) == 0);
|
||||
|
||||
manually_left_ratelimit = true;
|
||||
}
|
||||
@ -943,7 +945,7 @@ TEST(leave_ratelimit) {
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
@ -4131,12 +4131,28 @@ int journal_file_open(
|
||||
.last_direction = _DIRECTION_INVALID,
|
||||
};
|
||||
|
||||
if (fname) {
|
||||
f->path = strdup(fname);
|
||||
if (!f->path) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
assert(fd >= 0);
|
||||
|
||||
/* If we don't know the path, fill in something explanatory and vaguely useful */
|
||||
if (asprintf(&f->path, "/proc/self/%i", fd) < 0) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (f->fd < 0) {
|
||||
/* We pass O_NONBLOCK here, so that in case somebody pointed us to some character device node or FIFO
|
||||
* or so, we likely fail quickly than block for long. For regular files O_NONBLOCK has no effect, hence
|
||||
* it doesn't hurt in that case. */
|
||||
|
||||
f->fd = openat_report_new(AT_FDCWD, 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) {
|
||||
r = f->fd;
|
||||
goto fail;
|
||||
@ -4149,23 +4165,12 @@ int journal_file_open(
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = fd_get_path(f->fd, &f->path);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (!newly_created) {
|
||||
r = journal_file_fstat(f);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
/* If we don't know the path, fill in something explanatory and vaguely useful */
|
||||
f->path = strdup(fname ?: FORMAT_PROC_FD_PATH(fd));
|
||||
if (!f->path) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = journal_file_fstat(f);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
@ -1580,7 +1580,6 @@ static int add_any_file(
|
||||
const char *path) {
|
||||
|
||||
_cleanup_close_ int our_fd = -EBADF;
|
||||
_cleanup_free_ char *resolved_path = NULL;
|
||||
JournalFile *f;
|
||||
struct stat st;
|
||||
int r;
|
||||
@ -1607,14 +1606,6 @@ static int add_any_file(
|
||||
r = log_debug_errno(errno, "Failed to turn off O_NONBLOCK for %s: %m", path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = fd_get_path(fd, &resolved_path);
|
||||
if (r < 0) {
|
||||
r = log_debug_errno(r, "Failed to resolve path '%s': %m", path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
path = resolved_path;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) < 0) {
|
||||
@ -1749,7 +1740,7 @@ static int add_file_by_name(
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
|
||||
return add_any_file(j, /* fd = */ -EBADF, path);
|
||||
return add_any_file(j, -1, path);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
STRV_FOREACH(path, paths) {
|
||||
r = add_any_file(j, /* fd = */ -EBADF, *path);
|
||||
r = add_any_file(j, -1, *path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -2523,7 +2514,7 @@ _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fd
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = add_any_file(j, fds[i], /* path = */ NULL);
|
||||
r = add_any_file(j, fds[i], NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -531,8 +531,8 @@ static int method_set_display(sd_bus_message *message, void *userdata, sd_bus_er
|
||||
|
||||
static int method_set_tty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Session *s = ASSERT_PTR(userdata);
|
||||
int fd, r, flags;
|
||||
_cleanup_free_ char *q = NULL;
|
||||
int fd, r;
|
||||
|
||||
assert(message);
|
||||
|
||||
@ -543,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)))
|
||||
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);
|
||||
if (r == -EPROTOTYPE)
|
||||
assert(fd >= 0);
|
||||
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
if (flags < 0)
|
||||
return -errno;
|
||||
if ((flags & O_ACCMODE_STRICT) != O_RDWR)
|
||||
return -EACCES;
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (FLAGS_SET(flags, O_PATH))
|
||||
return -ENOTTY;
|
||||
|
||||
r = getttyname_malloc(fd, &q);
|
||||
if (r < 0)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
});
|
||||
@ -18,8 +18,3 @@ custom_target(
|
||||
command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'],
|
||||
install : pamconfdir != 'no',
|
||||
install_dir : pamconfdir)
|
||||
|
||||
if install_polkit
|
||||
install_data('empower.rules',
|
||||
install_dir : polkitrulesdir)
|
||||
endif
|
||||
|
||||
@ -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);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = getgrnam_malloc("empower", /* ret= */ NULL);
|
||||
if (r < 0 && r != -ESRCH)
|
||||
return log_error_errno(r, "Failed to look up group 'empower' via NSS: %m");
|
||||
if (r >= 0) {
|
||||
r = sd_bus_message_append(m, "(sv)", "SupplementaryGroups", "as", 1, "empower");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_nice_set) {
|
||||
|
||||
@ -370,10 +370,9 @@ int calendar_spec_to_string(const CalendarSpec *c, char **ret) {
|
||||
|
||||
tzset();
|
||||
|
||||
const char *z = get_tzname(c->dst);
|
||||
if (z) {
|
||||
if (!isempty(tzname[c->dst])) {
|
||||
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? */
|
||||
for (j = 0; j <= 1; j++) {
|
||||
const char *z = get_tzname(j);
|
||||
if (!z)
|
||||
if (isempty(tzname[j]))
|
||||
continue;
|
||||
|
||||
e = endswith_no_case(p, z);
|
||||
e = endswith_no_case(p, tzname[j]);
|
||||
if (!e)
|
||||
continue;
|
||||
if (e == p)
|
||||
|
||||
@ -175,12 +175,7 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
|
||||
unsigned long long: "%llu")
|
||||
|
||||
#ifdef __COVERITY__
|
||||
# define ASSERT_OK(expr) \
|
||||
({ \
|
||||
typeof(expr) _result = (expr); \
|
||||
__coverity_check__(_result >= 0); \
|
||||
_result; \
|
||||
})
|
||||
# define ASSERT_OK(expr) __coverity_check__((expr) >= 0)
|
||||
#else
|
||||
# define ASSERT_OK(expr) \
|
||||
({ \
|
||||
@ -188,7 +183,6 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
|
||||
if (_result < 0) \
|
||||
log_test_failed("Expected \"%s\" to succeed, but got error: %"PRIiMAX"/%s", \
|
||||
#expr, (intmax_t) _result, ERRNO_NAME(_result)); \
|
||||
_result; \
|
||||
})
|
||||
#endif
|
||||
|
||||
@ -196,8 +190,7 @@ _noreturn_ void log_test_failed_internal(const char *file, int line, const char
|
||||
# define ASSERT_OK_OR(expr, ...) \
|
||||
({ \
|
||||
typeof(expr) _result = (expr); \
|
||||
__coverity_check__(_result >= 0 || IN_SET(_result, 0, __VA_ARGS__); \
|
||||
_result; \
|
||||
__coverity_check__(_result >= 0 || IN_SET(_result, 0, __VA_ARGS__) \
|
||||
})
|
||||
#else
|
||||
# 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__)) \
|
||||
log_test_failed("\"%s\" failed with unexpected error: %"PRIiMAX"/%s", \
|
||||
#expr, (intmax_t) _result, ERRNO_NAME(_result)); \
|
||||
_result; \
|
||||
})
|
||||
#endif
|
||||
|
||||
/* For functions that return a boolean on success and a negative errno on failure. */
|
||||
#ifdef __COVERITY__
|
||||
# define ASSERT_OK_POSITIVE(expr) \
|
||||
({ \
|
||||
typeof(expr) _result = (expr); \
|
||||
__coverity_check__(_result > 0); \
|
||||
_result; \
|
||||
})
|
||||
# define ASSERT_OK_POSITIVE(expr) __coverity_check__((expr) > 0)
|
||||
#else
|
||||
# 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)); \
|
||||
if (_result == 0) \
|
||||
log_test_failed("Expected \"%s\" to be positive, but it is zero.", #expr); \
|
||||
_result; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifdef __COVERITY__
|
||||
# define ASSERT_OK_ZERO(expr) \
|
||||
({ \
|
||||
typeof(expr) _result = (expr); \
|
||||
__coverity_check__(_result == 0); \
|
||||
_result; \
|
||||
})
|
||||
# define ASSERT_OK_ZERO(expr) __coverity_check__((expr) == 0)
|
||||
#else
|
||||
# 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) \
|
||||
log_test_failed("Expected \"%s\" to be zero, but it is %"PRIiMAX".", \
|
||||
#expr, (intmax_t) _result); \
|
||||
_result; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifdef __COVERITY__
|
||||
# define ASSERT_OK_EQ(expr1, expr2) \
|
||||
({ \
|
||||
typeof(expr1) _expr1 = (expr1); \
|
||||
typeof(expr2) _expr2 = (expr2); \
|
||||
__coverity_check__(_expr1 == _expr2); \
|
||||
_expr1; \
|
||||
})
|
||||
# define ASSERT_OK_EQ(expr1, expr2) __coverity_check__((expr1) == (expr2))
|
||||
#else
|
||||
# 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) \
|
||||
log_test_failed("Expected \"%s == %s\", got %"PRIiMAX" != %"PRIiMAX, \
|
||||
#expr1, #expr2, (intmax_t) _expr1, (intmax_t) _expr2); \
|
||||
_expr1; \
|
||||
})
|
||||
#endif
|
||||
|
||||
/* For functions that return a boolean on success and set errno on failure. */
|
||||
#ifdef __COVERITY__
|
||||
# define ASSERT_OK_ERRNO(expr) \
|
||||
({ \
|
||||
typeof(expr) _result = (expr); \
|
||||
__coverity_check__(_result >= 0); \
|
||||
_result; \
|
||||
})
|
||||
# define ASSERT_OK_ERRNO(expr) __coverity_check__((expr) >= 0)
|
||||
#else
|
||||
# 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) \
|
||||
log_test_failed("Expected \"%s\" to succeed, but got errno: %d/%s", \
|
||||
#expr, errno, ERRNO_NAME(errno)); \
|
||||
_result; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifdef __COVERITY__
|
||||
# define ASSERT_OK_ZERO_ERRNO(expr) \
|
||||
({ \
|
||||
typeof(expr) _result = (expr); \
|
||||
__coverity_check__(_result == 0); \
|
||||
_result; \
|
||||
})
|
||||
# define ASSERT_OK_ZERO_ERRNO(expr) __coverity_check__((expr) == 0)
|
||||
#else
|
||||
# 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) \
|
||||
log_test_failed("Expected \"%s\" to be zero, but it is %"PRIiMAX".", \
|
||||
#expr, (intmax_t) _result); \
|
||||
_result; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifdef __COVERITY__
|
||||
# define ASSERT_OK_EQ_ERRNO(expr1, expr2) \
|
||||
({ \
|
||||
typeof(expr1) _expr1 = (expr1); \
|
||||
typeof(expr2) _expr2 = (expr2); \
|
||||
__coverity_check__(_expr1 == _expr2); \
|
||||
_expr1; \
|
||||
})
|
||||
# define ASSERT_OK_EQ_ERRNO(expr1, expr2) __coverity_check__((expr1) == (expr2))
|
||||
#else
|
||||
# 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) \
|
||||
log_test_failed("Expected \"%s == %s\", but %"PRIiMAX" != %"PRIiMAX, \
|
||||
#expr1, #expr2, (intmax_t) _expr1, (intmax_t) _expr2); \
|
||||
_expr1; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifdef __COVERITY__
|
||||
# define ASSERT_FAIL(expr) \
|
||||
({ \
|
||||
typeof(expr) _result = (expr); \
|
||||
__coverity_check__(_result < 0); \
|
||||
_result; \
|
||||
})
|
||||
# define ASSERT_FAIL(expr) __coverity_check__((expr) < 0)
|
||||
#else
|
||||
# define ASSERT_FAIL(expr) \
|
||||
({ \
|
||||
typeof(expr) _result = (expr); \
|
||||
if (_result >= 0) \
|
||||
log_test_failed("Expected \"%s\" to fail, but it succeeded.", #expr); \
|
||||
_result; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifdef __COVERITY__
|
||||
# define ASSERT_ERROR(expr1, expr2) \
|
||||
({ \
|
||||
int _expr1 = (expr1); \
|
||||
int _expr2 = (expr2); \
|
||||
__coverity_check__((_expr1) == -(_expr2)); \
|
||||
_expr1; \
|
||||
})
|
||||
# define ASSERT_ERROR(expr1, expr2) __coverity_check__((expr1) == -(expr2))
|
||||
#else
|
||||
# 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) \
|
||||
log_test_failed("Expected \"%s\" to fail with error %d/%s, but got %d/%s", \
|
||||
#expr1, -_expr2, ERRNO_NAME(_expr2), _expr1, ERRNO_NAME(_expr1)); \
|
||||
_expr1; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifdef __COVERITY__
|
||||
# define ASSERT_ERROR_ERRNO(expr1, expr2) \
|
||||
({ \
|
||||
int _expr1 = (expr1); \
|
||||
int _expr2 = (expr2); \
|
||||
__coverity_check__(_expr1 < 0 && errno == _expr2); \
|
||||
_expr1; \
|
||||
})
|
||||
# define ASSERT_ERROR_ERRNO(expr1, expr2) __coverity_check__((expr1) < 0 && errno == (expr2))
|
||||
#else
|
||||
# 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) \
|
||||
log_test_failed("Expected \"%s\" to fail with errno %d/%s, but got %d/%s", \
|
||||
#expr1, _expr2, ERRNO_NAME(_expr2), errno, ERRNO_NAME(errno)); \
|
||||
_expr1; \
|
||||
})
|
||||
#endif
|
||||
|
||||
|
||||
@ -26,13 +26,8 @@
|
||||
#include "tests.h"
|
||||
#include "tpm2-util.h"
|
||||
|
||||
#define ASSERT_DLOPEN(func, cond) \
|
||||
do { \
|
||||
if (cond) \
|
||||
ASSERT_OK(func()); \
|
||||
else \
|
||||
ASSERT_ERROR(func(), EOPNOTSUPP); \
|
||||
} while (false)
|
||||
#define ASSERT_DLOPEN(func, cond) \
|
||||
cond ? ASSERT_OK(func()) : ASSERT_ERROR(func(), EOPNOTSUPP)
|
||||
|
||||
static int run(int argc, char **argv) {
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
@ -878,29 +878,4 @@ TEST(fd_get_path) {
|
||||
assert_se(chdir(saved_cwd) >= 0);
|
||||
}
|
||||
|
||||
TEST(fd_vet_accmode) {
|
||||
_cleanup_(unlink_tempfilep) char name[] = "/tmp/test-fd-accmode.XXXXXX";
|
||||
_cleanup_close_ int fd_rw = -EBADF, fd_ro = -EBADF, fd_wo = -EBADF, fd_opath = -EBADF;
|
||||
|
||||
ASSERT_OK(fd_rw = mkostemp_safe(name));
|
||||
ASSERT_OK_ZERO(fd_vet_accmode(fd_rw, O_RDONLY));
|
||||
ASSERT_OK_ZERO(fd_vet_accmode(fd_rw, O_WRONLY));
|
||||
ASSERT_OK_POSITIVE(fd_vet_accmode(fd_rw, O_RDWR));
|
||||
|
||||
ASSERT_OK_ERRNO(fd_ro = open(name, O_RDONLY | O_CLOEXEC));
|
||||
ASSERT_OK_POSITIVE(fd_vet_accmode(fd_ro, O_RDONLY));
|
||||
ASSERT_ERROR(fd_vet_accmode(fd_ro, O_WRONLY), EPROTOTYPE);
|
||||
ASSERT_ERROR(fd_vet_accmode(fd_ro, O_RDWR), EPROTOTYPE);
|
||||
|
||||
ASSERT_OK_ERRNO(fd_wo = open(name, O_WRONLY | O_CLOEXEC));
|
||||
ASSERT_ERROR(fd_vet_accmode(fd_wo, O_RDONLY), EPROTOTYPE);
|
||||
ASSERT_OK_POSITIVE(fd_vet_accmode(fd_wo, O_WRONLY));
|
||||
ASSERT_ERROR(fd_vet_accmode(fd_wo, O_RDWR), EPROTOTYPE);
|
||||
|
||||
ASSERT_OK_ERRNO(fd_opath = open(name, O_PATH | O_CLOEXEC));
|
||||
ASSERT_ERROR(fd_vet_accmode(fd_opath, O_RDONLY), EBADFD);
|
||||
ASSERT_ERROR(fd_vet_accmode(fd_opath, O_WRONLY), EBADFD);
|
||||
ASSERT_ERROR(fd_vet_accmode(fd_opath, O_RDWR), EBADFD);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
||||
@ -14,80 +14,76 @@ static void test_rm_rf_chmod_inner(void) {
|
||||
const char *a, *b, *x, *y;
|
||||
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");
|
||||
b = strjoina(a, "/b");
|
||||
x = strjoina(d, "/x");
|
||||
y = strjoina(x, "/y");
|
||||
|
||||
ASSERT_OK_ERRNO(mkdir(x, 0700));
|
||||
ASSERT_OK_ERRNO(mknod(y, S_IFREG | 0600, 0));
|
||||
assert_se(mkdir(x, 0700) >= 0);
|
||||
assert_se(mknod(y, S_IFREG | 0600, 0) >= 0);
|
||||
|
||||
ASSERT_OK_ERRNO(chmod(y, 0400));
|
||||
ASSERT_OK_ERRNO(chmod(x, 0500));
|
||||
ASSERT_OK_ERRNO(chmod(d, 0500));
|
||||
assert_se(chmod(y, 0400) >= 0);
|
||||
assert_se(chmod(x, 0500) >= 0);
|
||||
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_OK_ERRNO(access(x, F_OK));
|
||||
ASSERT_OK_ERRNO(access(y, F_OK));
|
||||
assert_se(access(d, F_OK) >= 0);
|
||||
assert_se(access(x, F_OK) >= 0);
|
||||
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_ERROR_ERRNO(access(x, F_OK), ENOENT);
|
||||
ASSERT_ERROR_ERRNO(access(y, F_OK), ENOENT);
|
||||
assert_se(access(d, F_OK) >= 0);
|
||||
assert_se(access(x, F_OK) < 0 && errno == ENOENT);
|
||||
assert_se(access(y, F_OK) < 0 && errno == ENOENT);
|
||||
|
||||
ASSERT_OK_ERRNO(mkdir(a, 0700));
|
||||
ASSERT_OK_ERRNO(mkdir(b, 0700));
|
||||
ASSERT_OK_ERRNO(mkdir(x, 0700));
|
||||
ASSERT_OK_ERRNO(mknod(y, S_IFREG | 0600, 0));
|
||||
assert_se(mkdir(a, 0700) >= 0);
|
||||
assert_se(mkdir(b, 0700) >= 0);
|
||||
assert_se(mkdir(x, 0700) >= 0);
|
||||
assert_se(mknod(y, S_IFREG | 0600, 0) >= 0);
|
||||
|
||||
ASSERT_OK_ERRNO(chmod(b, 0000));
|
||||
ASSERT_OK_ERRNO(chmod(a, 0000));
|
||||
ASSERT_OK_ERRNO(chmod(y, 0000));
|
||||
ASSERT_OK_ERRNO(chmod(x, 0000));
|
||||
ASSERT_OK_ERRNO(chmod(d, 0500));
|
||||
assert_se(chmod(b, 0000) >= 0);
|
||||
assert_se(chmod(a, 0000) >= 0);
|
||||
assert_se(chmod(y, 0000) >= 0);
|
||||
assert_se(chmod(x, 0000) >= 0);
|
||||
assert_se(chmod(d, 0500) >= 0);
|
||||
|
||||
ASSERT_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_OK_ERRNO(access(d, F_OK));
|
||||
ASSERT_OK_ERRNO(stat(d, &st));
|
||||
ASSERT_EQ(st.st_mode & 07777, 0500U);
|
||||
ASSERT_OK_ERRNO(access(x, F_OK));
|
||||
ASSERT_OK_ERRNO(stat(x, &st));
|
||||
ASSERT_EQ(st.st_mode & 07777, 0000U);
|
||||
ASSERT_OK_ERRNO(chmod(x, 0700));
|
||||
ASSERT_OK_ERRNO(access(y, F_OK));
|
||||
ASSERT_OK_ERRNO(stat(y, &st));
|
||||
ASSERT_EQ(st.st_mode & 07777, 0000U);
|
||||
assert_se(access(a, F_OK) < 0 && errno == ENOENT);
|
||||
assert_se(access(d, F_OK) >= 0);
|
||||
assert_se(stat(d, &st) >= 0 && (st.st_mode & 07777) == 0500);
|
||||
assert_se(access(x, F_OK) >= 0);
|
||||
assert_se(stat(x, &st) >= 0 && (st.st_mode & 07777) == 0000);
|
||||
assert_se(chmod(x, 0700) >= 0);
|
||||
assert_se(access(y, F_OK) >= 0);
|
||||
assert_se(stat(y, &st) >= 0 && (st.st_mode & 07777) == 0000);
|
||||
|
||||
ASSERT_OK_ERRNO(chmod(y, 0000));
|
||||
ASSERT_OK_ERRNO(chmod(x, 0000));
|
||||
ASSERT_OK_ERRNO(chmod(d, 0000));
|
||||
assert_se(chmod(y, 0000) >= 0);
|
||||
assert_se(chmod(x, 0000) >= 0);
|
||||
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_EQ(st.st_mode & 07777, 0000U);
|
||||
ASSERT_OK_ERRNO(access(d, F_OK));
|
||||
ASSERT_OK_ERRNO(chmod(d, 0700));
|
||||
ASSERT_ERROR_ERRNO(access(x, F_OK), ENOENT);
|
||||
assert_se(stat(d, &st) >= 0 && (st.st_mode & 07777) == 0000);
|
||||
assert_se(access(d, F_OK) >= 0);
|
||||
assert_se(chmod(d, 0700) >= 0);
|
||||
assert_se(access(x, F_OK) < 0 && errno == ENOENT);
|
||||
|
||||
ASSERT_OK_ERRNO(mkdir(x, 0700));
|
||||
ASSERT_OK_ERRNO(mknod(y, S_IFREG | 0600, 0));
|
||||
assert_se(mkdir(x, 0700) >= 0);
|
||||
assert_se(mknod(y, S_IFREG | 0600, 0) >= 0);
|
||||
|
||||
ASSERT_OK_ERRNO(chmod(y, 0000));
|
||||
ASSERT_OK_ERRNO(chmod(x, 0000));
|
||||
ASSERT_OK_ERRNO(chmod(d, 0000));
|
||||
assert_se(chmod(y, 0000) >= 0);
|
||||
assert_se(chmod(x, 0000) >= 0);
|
||||
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) {
|
||||
@ -100,12 +96,13 @@ TEST(rm_rf_chmod) {
|
||||
/* This test only works unpriv (as only then the access mask for the owning user matters),
|
||||
* 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) {
|
||||
/* child */
|
||||
|
||||
ASSERT_OK_ERRNO(setresuid(1, 1, 1));
|
||||
assert_se(setresuid(1, 1, 1) >= 0);
|
||||
|
||||
test_rm_rf_chmod_inner();
|
||||
_exit(EXIT_SUCCESS);
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
static void set_timezone(const char *tz) {
|
||||
ASSERT_OK(set_unset_env("TZ", tz, /* overwrite = */ true));
|
||||
tzset();
|
||||
log_info("TZ=%s, tzname[0]=%s, tzname[1]=%s", strna(getenv("TZ")), strempty(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) {
|
||||
@ -400,28 +400,6 @@ static void test_format_timestamp_impl(usec_t x) {
|
||||
const char *xx = FORMAT_TIMESTAMP(x);
|
||||
ASSERT_NOT_NULL(xx);
|
||||
|
||||
/* Because of the timezone change, format_timestamp() may set timezone that is currently unused.
|
||||
* E.g. Africa/Juba uses EAT since Sat Jan 15 10:00:00 2000 and until Sun Jan 31 20:59:59 2021, but
|
||||
* now CAT/CAST is used there (see zdump for more details). In such cases, format_timestamp() may set
|
||||
* the timezone used at the specified time (which happens when built with musl), but it may not match
|
||||
* the timezone currently used, thus we may not parse back the timestamp. */
|
||||
|
||||
const char *space;
|
||||
ASSERT_NOT_NULL(space = strrchr(xx, ' '));
|
||||
|
||||
const char *tz = space + 1;
|
||||
if (!streq_ptr(tz, get_tzname(/* dst= */ false)) &&
|
||||
!streq_ptr(tz, get_tzname(/* dst= */ true)) &&
|
||||
parse_gmtoff(tz, NULL) < 0) {
|
||||
|
||||
log_warning("@" USEC_FMT " → %s, timezone '%s' is currently unused, ignoring.", x, xx, tz);
|
||||
|
||||
/* Verify the generated string except for the timezone part. Of course, in most cases, parsed
|
||||
* time does not match with the input, hence only check if it is parsable. */
|
||||
ASSERT_OK(parse_timestamp(strndupa_safe(xx, space - xx), NULL));
|
||||
return;
|
||||
}
|
||||
|
||||
usec_t y;
|
||||
ASSERT_OK(parse_timestamp(xx, &y));
|
||||
const char *yy = FORMAT_TIMESTAMP(y);
|
||||
@ -1131,15 +1109,15 @@ TEST(in_utc_timezone) {
|
||||
|
||||
assert_se(setenv("TZ", "UTC", 1) >= 0);
|
||||
assert_se(in_utc_timezone());
|
||||
ASSERT_STREQ(get_tzname(/* dst= */ false), "UTC");
|
||||
ASSERT_STREQ(get_tzname(/* dst= */ true), "UTC");
|
||||
ASSERT_STREQ(tzname[0], "UTC");
|
||||
ASSERT_STREQ(tzname[1], "UTC");
|
||||
assert_se(timezone == 0);
|
||||
assert_se(daylight == 0);
|
||||
|
||||
assert_se(setenv("TZ", "Europe/Berlin", 1) >= 0);
|
||||
assert_se(!in_utc_timezone());
|
||||
ASSERT_STREQ(get_tzname(/* dst= */ false), "CET");
|
||||
ASSERT_STREQ(get_tzname(/* dst= */ true), "CEST");
|
||||
ASSERT_STREQ(tzname[0], "CET");
|
||||
ASSERT_STREQ(tzname[1], "CEST");
|
||||
}
|
||||
|
||||
TEST(map_clock_usec) {
|
||||
|
||||
@ -34,14 +34,20 @@ static int method_something(sd_varlink *link, sd_json_variant *parameters, sd_va
|
||||
int r;
|
||||
|
||||
a = sd_json_variant_by_key(parameters, "a");
|
||||
if (!a)
|
||||
return ASSERT_ERROR(sd_varlink_error(link, "io.test.BadParameters", NULL), EBADR);
|
||||
if (!a) {
|
||||
r = sd_varlink_error(link, "io.test.BadParameters", NULL);
|
||||
assert_se(r == -EBADR);
|
||||
return r;
|
||||
}
|
||||
|
||||
x = sd_json_variant_integer(a);
|
||||
|
||||
b = sd_json_variant_by_key(parameters, "b");
|
||||
if (!b)
|
||||
return ASSERT_ERROR(sd_varlink_error(link, "io.test.BadParameters", NULL), EBADR);
|
||||
if (!b) {
|
||||
r = sd_varlink_error(link, "io.test.BadParameters", NULL);
|
||||
assert_se(r == -EBADR);
|
||||
return r;
|
||||
}
|
||||
|
||||
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];
|
||||
ssize_t m;
|
||||
|
||||
ASSERT_OK_ERRNO(m = read(fd, rbuf, n + 1));
|
||||
ASSERT_OK_ZERO(memcmp_nn(buf, n, rbuf, m));
|
||||
m = read(fd, rbuf, n + 1);
|
||||
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) {
|
||||
@ -105,32 +112,40 @@ static int method_passfd(sd_varlink *link, sd_json_variant *parameters, sd_varli
|
||||
int r;
|
||||
|
||||
a = sd_json_variant_by_key(parameters, "fd");
|
||||
if (!a)
|
||||
return ASSERT_ERROR(sd_varlink_error_invalid_parameter_name(link, "fd"), EINVAL);
|
||||
if (!a) {
|
||||
r = sd_varlink_error_invalid_parameter_name(link, "fd");
|
||||
assert_se(r == -EINVAL);
|
||||
return r;
|
||||
}
|
||||
|
||||
ASSERT_STREQ(sd_json_variant_string(a), "whoop");
|
||||
|
||||
int xx, yy, zz;
|
||||
ASSERT_OK(xx = sd_varlink_peek_fd(link, 0));
|
||||
ASSERT_OK(yy = sd_varlink_peek_fd(link, 1));
|
||||
ASSERT_OK(zz = sd_varlink_peek_fd(link, 2));
|
||||
int xx = sd_varlink_peek_fd(link, 0),
|
||||
yy = sd_varlink_peek_fd(link, 1),
|
||||
zz = sd_varlink_peek_fd(link, 2);
|
||||
|
||||
log_info("%i %i %i", xx, yy, zz);
|
||||
|
||||
assert_se(xx >= 0);
|
||||
assert_se(yy >= 0);
|
||||
assert_se(zz >= 0);
|
||||
|
||||
test_fd(xx, "foo", 3);
|
||||
test_fd(yy, "bar", 3);
|
||||
test_fd(zz, "quux", 4);
|
||||
|
||||
_cleanup_close_ int vv = -EBADF, ww = -EBADF;
|
||||
ASSERT_OK(vv = memfd_new_and_seal_string("data", "miau"));
|
||||
ASSERT_OK(ww = memfd_new_and_seal_string("data", "wuff"));
|
||||
_cleanup_close_ int vv = memfd_new_and_seal_string("data", "miau");
|
||||
_cleanup_close_ int ww = memfd_new_and_seal_string("data", "wuff");
|
||||
|
||||
assert_se(vv >= 0);
|
||||
assert_se(ww >= 0);
|
||||
|
||||
r = sd_json_build(&ret, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("yo", SD_JSON_BUILD_INTEGER(88))));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
ASSERT_OK_EQ(sd_varlink_push_fd(link, vv), 0);
|
||||
ASSERT_OK_EQ(sd_varlink_push_fd(link, ww), 1);
|
||||
assert_se(sd_varlink_push_fd(link, vv) == 0);
|
||||
assert_se(sd_varlink_push_fd(link, ww) == 1);
|
||||
|
||||
TAKE_FD(vv);
|
||||
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");
|
||||
|
||||
ASSERT_EQ(sd_json_variant_integer(sum), 7+22);
|
||||
assert_se(sd_json_variant_integer(sum) == 7+22);
|
||||
|
||||
if (++n_done == 2)
|
||||
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) {
|
||||
uid_t uid = UID_INVALID;
|
||||
|
||||
ASSERT_NOT_NULL(s);
|
||||
ASSERT_NOT_NULL(link);
|
||||
assert_se(s);
|
||||
assert_se(link);
|
||||
|
||||
ASSERT_OK(sd_varlink_get_peer_uid(link, &uid));
|
||||
ASSERT_EQ(getuid(), uid);
|
||||
ASSERT_OK(sd_varlink_set_allow_fd_passing_input(link, true));
|
||||
ASSERT_OK(sd_varlink_set_allow_fd_passing_output(link, true));
|
||||
assert_se(sd_varlink_get_peer_uid(link, &uid) >= 0);
|
||||
assert_se(getuid() == uid);
|
||||
assert_se(sd_varlink_set_allow_fd_passing_input(link, true) >= 0);
|
||||
assert_se(sd_varlink_set_allow_fd_passing_output(link, true) >= 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -208,37 +223,37 @@ static void flood_test(const char *address) {
|
||||
log_debug("Flooding server...");
|
||||
|
||||
/* 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 */
|
||||
ASSERT_NOT_NULL(connections = new0(sd_varlink*, OVERLOAD_CONNECTIONS));
|
||||
assert_se(connections = new0(sd_varlink*, OVERLOAD_CONNECTIONS));
|
||||
for (k = 0; k < OVERLOAD_CONNECTIONS; k++) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
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_OK(sd_varlink_set_description(connections[k], t));
|
||||
ASSERT_OK(sd_varlink_attach_event(connections[k], e, k));
|
||||
ASSERT_OK(sd_varlink_sendb(connections[k], "io.test.Rubbish", SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("id", SD_JSON_BUILD_INTEGER(k)))));
|
||||
assert_se(asprintf(&t, "flood-%zu", k) >= 0);
|
||||
assert_se(sd_varlink_set_description(connections[k], t) >= 0);
|
||||
assert_se(sd_varlink_attach_event(connections[k], e, k) >= 0);
|
||||
assert_se(sd_varlink_sendb(connections[k], "io.test.Rubbish", SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("id", SD_JSON_BUILD_INTEGER(k)))) >= 0);
|
||||
}
|
||||
|
||||
/* Then, create one more, which should fail */
|
||||
log_debug("Creating overload connection...");
|
||||
ASSERT_OK(sd_varlink_connect_address(&c, address));
|
||||
ASSERT_OK(sd_varlink_set_description(c, "overload-client"));
|
||||
ASSERT_OK(sd_varlink_attach_event(c, e, k));
|
||||
ASSERT_OK(sd_varlink_bind_reply(c, overload_reply));
|
||||
ASSERT_OK(sd_varlink_invokeb(c, "io.test.Overload", SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("foo", JSON_BUILD_CONST_STRING("bar")))));
|
||||
assert_se(sd_varlink_connect_address(&c, address) >= 0);
|
||||
assert_se(sd_varlink_set_description(c, "overload-client") >= 0);
|
||||
assert_se(sd_varlink_attach_event(c, e, k) >= 0);
|
||||
assert_se(sd_varlink_bind_reply(c, overload_reply) >= 0);
|
||||
assert_se(sd_varlink_invokeb(c, "io.test.Overload", SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("foo", JSON_BUILD_CONST_STRING("bar")))) >= 0);
|
||||
|
||||
/* Unblock it */
|
||||
log_debug("Unblocking server...");
|
||||
block_write_fd = safe_close(block_write_fd);
|
||||
|
||||
/* This loop will terminate as soon as the overload reply callback is called */
|
||||
ASSERT_OK(sd_event_loop(e));
|
||||
assert_se(sd_event_loop(e) >= 0);
|
||||
|
||||
/* And close all connections again */
|
||||
for (k = 0; k < OVERLOAD_CONNECTIONS; k++)
|
||||
@ -253,59 +268,63 @@ static void *thread(void *arg) {
|
||||
const char *error_id, *e;
|
||||
int x = 0;
|
||||
|
||||
ASSERT_OK(sd_json_build(&i, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_INTEGER(88)),
|
||||
SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_INTEGER(99)))));
|
||||
assert_se(sd_json_build(&i, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_INTEGER(88)),
|
||||
SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_INTEGER(99)))) >= 0);
|
||||
|
||||
ASSERT_OK(sd_varlink_connect_address(&c, arg));
|
||||
ASSERT_OK(sd_varlink_set_description(c, "thread-client"));
|
||||
ASSERT_OK(sd_varlink_set_allow_fd_passing_input(c, true));
|
||||
ASSERT_OK(sd_varlink_set_allow_fd_passing_output(c, true));
|
||||
assert_se(sd_varlink_connect_address(&c, arg) >= 0);
|
||||
assert_se(sd_varlink_set_description(c, "thread-client") >= 0);
|
||||
assert_se(sd_varlink_set_allow_fd_passing_input(c, true) >= 0);
|
||||
assert_se(sd_varlink_set_allow_fd_passing_output(c, true) >= 0);
|
||||
|
||||
/* 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)),
|
||||
SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_INTEGER(99)))));
|
||||
ASSERT_OK(sd_varlink_collect(c, "io.test.DoSomethingMore", wrong, &j, &error_id));
|
||||
ASSERT_STREQ(error_id, "org.varlink.service.InvalidParameter");
|
||||
assert_se(sd_json_build(&wrong, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_INTEGER(88)),
|
||||
SD_JSON_BUILD_PAIR("c", SD_JSON_BUILD_INTEGER(99)))) >= 0);
|
||||
assert_se(sd_varlink_collect(c, "io.test.DoSomethingMore", wrong, &j, &error_id) >= 0);
|
||||
assert_se(strcmp_ptr(error_id, "org.varlink.service.InvalidParameter") == 0);
|
||||
|
||||
ASSERT_OK(sd_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_TRUE(sd_json_variant_is_array(j));
|
||||
ASSERT_FALSE(sd_json_variant_is_blank_array(j));
|
||||
assert_se(!error_id);
|
||||
assert_se(sd_json_variant_is_array(j) && !sd_json_variant_is_blank_array(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++;
|
||||
}
|
||||
ASSERT_EQ(x, 6);
|
||||
assert_se(x == 6);
|
||||
|
||||
ASSERT_OK(sd_varlink_call(c, "io.test.DoSomething", i, &o, &e));
|
||||
ASSERT_EQ(sd_json_variant_integer(sd_json_variant_by_key(o, "sum")), 88 + 99);
|
||||
ASSERT_NULL(e);
|
||||
assert_se(sd_varlink_call(c, "io.test.DoSomething", i, &o, &e) >= 0);
|
||||
assert_se(sd_json_variant_integer(sd_json_variant_by_key(o, "sum")) == 88 + 99);
|
||||
assert_se(!e);
|
||||
|
||||
int fd1, fd2, fd3;
|
||||
ASSERT_OK(fd1 = memfd_new_and_seal_string("data", "foo"));
|
||||
ASSERT_OK(fd2 = memfd_new_and_seal_string("data", "bar"));
|
||||
ASSERT_OK(fd3 = memfd_new_and_seal_string("data", "quux"));
|
||||
int fd1 = memfd_new_and_seal_string("data", "foo");
|
||||
int fd2 = memfd_new_and_seal_string("data", "bar");
|
||||
int fd3 = memfd_new_and_seal_string("data", "quux");
|
||||
|
||||
ASSERT_OK_EQ(sd_varlink_push_fd(c, fd1), 0);
|
||||
ASSERT_OK_EQ(sd_varlink_push_fd(c, fd2), 1);
|
||||
ASSERT_OK_EQ(sd_varlink_push_fd(c, fd3), 2);
|
||||
assert_se(fd1 >= 0);
|
||||
assert_se(fd2 >= 0);
|
||||
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_NULL(e);
|
||||
assert_se(sd_varlink_push_fd(c, fd1) == 0);
|
||||
assert_se(sd_varlink_push_fd(c, fd2) == 1);
|
||||
assert_se(sd_varlink_push_fd(c, fd3) == 2);
|
||||
|
||||
int fd4, fd5;
|
||||
ASSERT_OK(fd4 = sd_varlink_peek_fd(c, 0));
|
||||
ASSERT_OK(fd5 = sd_varlink_peek_fd(c, 1));
|
||||
assert_se(sd_varlink_callb(c, "io.test.PassFD", &o, &e, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("fd", SD_JSON_BUILD_STRING("whoop")))) >= 0);
|
||||
assert_se(!e);
|
||||
|
||||
int fd4 = sd_varlink_peek_fd(c, 0);
|
||||
int fd5 = sd_varlink_peek_fd(c, 1);
|
||||
|
||||
assert_se(fd4 >= 0);
|
||||
assert_se(fd5 >= 0);
|
||||
|
||||
test_fd(fd4, "miau", 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_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(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);
|
||||
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;
|
||||
}
|
||||
@ -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) {
|
||||
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. */
|
||||
|
||||
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;
|
||||
}
|
||||
@ -346,47 +365,47 @@ TEST(chat) {
|
||||
pthread_t t;
|
||||
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");
|
||||
|
||||
ASSERT_OK(sd_event_default(&e));
|
||||
assert_se(sd_event_default(&e) >= 0);
|
||||
|
||||
ASSERT_OK_ERRNO(pipe2(block_fds, O_NONBLOCK|O_CLOEXEC));
|
||||
ASSERT_OK(sd_event_add_io(e, &block_event, block_fds[0], EPOLLIN, block_fd_handler, NULL));
|
||||
ASSERT_OK(sd_event_source_set_priority(block_event, SD_EVENT_PRIORITY_IMPORTANT));
|
||||
assert_se(pipe2(block_fds, O_NONBLOCK|O_CLOEXEC) >= 0);
|
||||
assert_se(sd_event_add_io(e, &block_event, block_fds[0], EPOLLIN, block_fd_handler, NULL) >= 0);
|
||||
assert_se(sd_event_source_set_priority(block_event, SD_EVENT_PRIORITY_IMPORTANT) >= 0);
|
||||
block_write_fd = TAKE_FD(block_fds[1]);
|
||||
|
||||
ASSERT_OK(varlink_server_new(&s, SD_VARLINK_SERVER_ACCOUNT_UID, NULL));
|
||||
ASSERT_OK(sd_varlink_server_set_info(s, "Vendor", "Product", "Version", "URL"));
|
||||
ASSERT_OK(varlink_set_info_systemd(s));
|
||||
ASSERT_OK(sd_varlink_server_set_description(s, "our-server"));
|
||||
assert_se(varlink_server_new(&s, SD_VARLINK_SERVER_ACCOUNT_UID, NULL) >= 0);
|
||||
assert_se(sd_varlink_server_set_info(s, "Vendor", "Product", "Version", "URL") >= 0);
|
||||
assert_se(varlink_set_info_systemd(s) >= 0);
|
||||
assert_se(sd_varlink_server_set_description(s, "our-server") >= 0);
|
||||
|
||||
ASSERT_OK(sd_varlink_server_bind_method(s, "io.test.PassFD", method_passfd));
|
||||
ASSERT_OK(sd_varlink_server_bind_method(s, "io.test.DoSomething", method_something));
|
||||
ASSERT_OK(sd_varlink_server_bind_method(s, "io.test.DoSomethingMore", method_something_more));
|
||||
ASSERT_OK(sd_varlink_server_bind_method(s, "io.test.FailWithErrno", method_fail_with_errno));
|
||||
ASSERT_OK(sd_varlink_server_bind_method(s, "io.test.Done", method_done));
|
||||
ASSERT_OK(sd_varlink_server_bind_connect(s, on_connect));
|
||||
ASSERT_OK(sd_varlink_server_listen_address(s, sp, 0600));
|
||||
ASSERT_OK(sd_varlink_server_attach_event(s, e, 0));
|
||||
ASSERT_OK(sd_varlink_server_set_connections_max(s, OVERLOAD_CONNECTIONS));
|
||||
assert_se(sd_varlink_server_bind_method(s, "io.test.PassFD", method_passfd) >= 0);
|
||||
assert_se(sd_varlink_server_bind_method(s, "io.test.DoSomething", method_something) >= 0);
|
||||
assert_se(sd_varlink_server_bind_method(s, "io.test.DoSomethingMore", method_something_more) >= 0);
|
||||
assert_se(sd_varlink_server_bind_method(s, "io.test.FailWithErrno", method_fail_with_errno) >= 0);
|
||||
assert_se(sd_varlink_server_bind_method(s, "io.test.Done", method_done) >= 0);
|
||||
assert_se(sd_varlink_server_bind_connect(s, on_connect) >= 0);
|
||||
assert_se(sd_varlink_server_listen_address(s, sp, 0600) >= 0);
|
||||
assert_se(sd_varlink_server_attach_event(s, e, 0) >= 0);
|
||||
assert_se(sd_varlink_server_set_connections_max(s, OVERLOAD_CONNECTIONS) >= 0);
|
||||
|
||||
ASSERT_OK(sd_json_build(&v, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_INTEGER(7)),
|
||||
SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_INTEGER(22)))));
|
||||
assert_se(sd_json_build(&v, SD_JSON_BUILD_OBJECT(SD_JSON_BUILD_PAIR("a", SD_JSON_BUILD_INTEGER(7)),
|
||||
SD_JSON_BUILD_PAIR("b", SD_JSON_BUILD_INTEGER(22)))) >= 0);
|
||||
|
||||
ASSERT_OK(sd_varlink_connect_address(&c, sp));
|
||||
ASSERT_OK(sd_varlink_set_description(c, "main-client"));
|
||||
ASSERT_OK(sd_varlink_bind_reply(c, reply));
|
||||
assert_se(sd_varlink_connect_address(&c, sp) >= 0);
|
||||
assert_se(sd_varlink_set_description(c, "main-client") >= 0);
|
||||
assert_se(sd_varlink_bind_reply(c, reply) >= 0);
|
||||
|
||||
ASSERT_OK(sd_varlink_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) {
|
||||
@ -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) {
|
||||
ASSERT_TRUE(sd_varlink_error_is_invalid_parameter(error_id, parameters, "idontexist"));
|
||||
ASSERT_OK(sd_event_exit(sd_varlink_get_event(link), EXIT_SUCCESS));
|
||||
assert(sd_varlink_error_is_invalid_parameter(error_id, parameters, "idontexist"));
|
||||
assert(sd_event_exit(sd_varlink_get_event(link), EXIT_SUCCESS) >= 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(invalid_parameter) {
|
||||
_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;
|
||||
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];
|
||||
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, connfd));
|
||||
ASSERT_OK(sd_varlink_server_add_connection(s, connfd[0], /* ret= */ NULL));
|
||||
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, connfd) >= 0);
|
||||
assert_se(sd_varlink_server_add_connection(s, connfd[0], /* ret= */ NULL) >= 0);
|
||||
|
||||
_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("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);
|
||||
|
||||
@ -733,9 +733,9 @@ static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *
|
||||
log_struct(LOG_INFO,
|
||||
LOG_MESSAGE_ID(SD_MESSAGE_TIMEZONE_CHANGE_STR),
|
||||
LOG_ITEM("TIMEZONE=%s", c->zone),
|
||||
LOG_ITEM("TIMEZONE_SHORTNAME=%s", get_tzname(daylight)),
|
||||
LOG_ITEM("TIMEZONE_SHORTNAME=%s", tzname[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),
|
||||
"/org/freedesktop/timedate1", "org.freedesktop.timedate1", "Timezone",
|
||||
|
||||
@ -16,9 +16,8 @@ u! {{NOBODY_USER_NAME}} 65534:65534 "Kernel Overflow User" -
|
||||
# Administrator group: can *see* more than normal users
|
||||
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 empower {{EMPOWER_GID}} - -
|
||||
|
||||
# Access to shared database of users on the system
|
||||
g utmp {{UTMP_GID }} - -
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user