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