mirror of
https://github.com/systemd/systemd.git
synced 2025-03-28 02:50:16 +03:00
Merge pull request #2603 from poettering/drop-compat-libs
Some spring cleaning
This commit is contained in:
commit
06e948901a
9
.gitignore
vendored
9
.gitignore
vendored
@ -5,7 +5,6 @@
|
||||
*.log
|
||||
*.o
|
||||
*.plist
|
||||
*.pyc
|
||||
*.stamp
|
||||
*.swp
|
||||
*.trs
|
||||
@ -39,7 +38,6 @@
|
||||
/hostnamectl
|
||||
/install-tree
|
||||
/journalctl
|
||||
/libsystemd-*.c
|
||||
/libtool
|
||||
/linuxx64.efi.stub
|
||||
/localectl
|
||||
@ -48,7 +46,6 @@
|
||||
/mtd_probe
|
||||
/networkctl
|
||||
/scsi_id
|
||||
/systemadm
|
||||
/systemctl
|
||||
/systemd
|
||||
/systemd-ac-power
|
||||
@ -77,7 +74,6 @@
|
||||
/systemd-fsck
|
||||
/systemd-fstab-generator
|
||||
/systemd-getty-generator
|
||||
/systemd-gnome-ask-password-agent
|
||||
/systemd-gpt-auto-generator
|
||||
/systemd-hibernate-resume
|
||||
/systemd-hibernate-resume-generator
|
||||
@ -91,7 +87,6 @@
|
||||
/systemd-journal-remote
|
||||
/systemd-journal-upload
|
||||
/systemd-journald
|
||||
/systemd-kmsg-syslogd
|
||||
/systemd-localed
|
||||
/systemd-logind
|
||||
/systemd-machine-id-setup
|
||||
@ -106,7 +101,6 @@
|
||||
/systemd-quotacheck
|
||||
/systemd-random-seed
|
||||
/systemd-rc-local-generator
|
||||
/systemd-remount-api-vfs
|
||||
/systemd-remount-fs
|
||||
/systemd-reply-password
|
||||
/systemd-resolve
|
||||
@ -125,7 +119,6 @@
|
||||
/systemd-timesyncd
|
||||
/systemd-tmpfiles
|
||||
/systemd-tty-ask-password-agent
|
||||
/systemd-uaccess
|
||||
/systemd-udevd
|
||||
/systemd-update-done
|
||||
/systemd-update-utmp
|
||||
@ -218,7 +211,6 @@
|
||||
/test-journal-stream
|
||||
/test-journal-syslog
|
||||
/test-journal-verify
|
||||
/test-json
|
||||
/test-libsystemd-sym*
|
||||
/test-libudev
|
||||
/test-libudev-sym*
|
||||
@ -262,7 +254,6 @@
|
||||
/test-siphash24
|
||||
/test-sleep
|
||||
/test-socket-util
|
||||
/test-ssd
|
||||
/test-strbuf
|
||||
/test-string-util
|
||||
/test-strip-tab-ansi
|
||||
|
150
Makefile.am
150
Makefile.am
@ -46,24 +46,6 @@ LIBSYSTEMD_CURRENT=14
|
||||
LIBSYSTEMD_REVISION=0
|
||||
LIBSYSTEMD_AGE=14
|
||||
|
||||
# The following four libraries only exist for compatibility reasons,
|
||||
# their version info should not be bumped anymore
|
||||
LIBSYSTEMD_LOGIN_CURRENT=9
|
||||
LIBSYSTEMD_LOGIN_REVISION=3
|
||||
LIBSYSTEMD_LOGIN_AGE=9
|
||||
|
||||
LIBSYSTEMD_DAEMON_CURRENT=0
|
||||
LIBSYSTEMD_DAEMON_REVISION=12
|
||||
LIBSYSTEMD_DAEMON_AGE=0
|
||||
|
||||
LIBSYSTEMD_ID128_CURRENT=0
|
||||
LIBSYSTEMD_ID128_REVISION=28
|
||||
LIBSYSTEMD_ID128_AGE=0
|
||||
|
||||
LIBSYSTEMD_JOURNAL_CURRENT=11
|
||||
LIBSYSTEMD_JOURNAL_REVISION=5
|
||||
LIBSYSTEMD_JOURNAL_AGE=11
|
||||
|
||||
# Dirs of external packages
|
||||
dbuspolicydir=@dbuspolicydir@
|
||||
dbussessionservicedir=@dbussessionservicedir@
|
||||
@ -913,8 +895,6 @@ libbasic_la_SOURCES = \
|
||||
src/basic/audit-util.h \
|
||||
src/basic/xml.c \
|
||||
src/basic/xml.h \
|
||||
src/basic/json.c \
|
||||
src/basic/json.h \
|
||||
src/basic/barrier.c \
|
||||
src/basic/barrier.h \
|
||||
src/basic/async.c \
|
||||
@ -1477,7 +1457,6 @@ tests += \
|
||||
test-tables \
|
||||
test-device-nodes \
|
||||
test-xml \
|
||||
test-json \
|
||||
test-architecture \
|
||||
test-socket-util \
|
||||
test-fdset \
|
||||
@ -1931,12 +1910,6 @@ test_xml_SOURCES = \
|
||||
test_xml_LDADD = \
|
||||
libshared.la
|
||||
|
||||
test_json_SOURCES = \
|
||||
src/test/test-json.c
|
||||
|
||||
test_json_LDADD = \
|
||||
libshared.la
|
||||
|
||||
test_list_SOURCES = \
|
||||
src/test/test-list.c
|
||||
|
||||
@ -5045,8 +5018,6 @@ systemd_pull_SOURCES = \
|
||||
src/import/import-compress.h \
|
||||
src/import/curl-util.c \
|
||||
src/import/curl-util.h \
|
||||
src/import/aufs-util.c \
|
||||
src/import/aufs-util.h \
|
||||
src/import/qcow2-util.c \
|
||||
src/import/qcow2-util.h
|
||||
|
||||
@ -5801,127 +5772,6 @@ EXTRA_DIST += \
|
||||
test/loopy.service.d \
|
||||
test/loopy.service.d/compat.conf
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
if ENABLE_COMPAT_LIBS
|
||||
libsystemd-%.c: src/compat-libs/libsystemd-%.sym
|
||||
$(AM_V_at)$(MKDIR_P) $(dir $@)
|
||||
$(AM_V_GEN)sed -r -n 's/^ +(sd_.*);/obsolete_lib(\1,$(notdir $(basename $<)));/p' <$< >$@
|
||||
|
||||
BUILT_SOURCES += \
|
||||
libsystemd-journal.c \
|
||||
libsystemd-login.c \
|
||||
libsystemd-id128.c \
|
||||
libsystemd-daemon.c
|
||||
|
||||
nodist_libsystemd_journal_la_SOURCES = \
|
||||
libsystemd-journal.c
|
||||
|
||||
libsystemd_journal_la_SOURCES = \
|
||||
src/compat-libs/libsystemd-journal.sym
|
||||
|
||||
libsystemd_journal_la_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
-imacros$(top_srcdir)/src/compat-libs/linkwarning.h
|
||||
|
||||
libsystemd_journal_la_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-version-info $(LIBSYSTEMD_JOURNAL_CURRENT):$(LIBSYSTEMD_JOURNAL_REVISION):$(LIBSYSTEMD_JOURNAL_AGE) \
|
||||
-Wl,--version-script=$(top_srcdir)/src/compat-libs/libsystemd-journal.sym
|
||||
|
||||
libsystemd_journal_la_LIBADD = \
|
||||
libsystemd-journal-internal.la \
|
||||
libsystemd-internal.la
|
||||
|
||||
nodist_libsystemd_login_la_SOURCES = \
|
||||
libsystemd-login.c
|
||||
|
||||
libsystemd_login_la_SOURCES = \
|
||||
src/compat-libs/libsystemd-login.sym
|
||||
|
||||
libsystemd_login_la_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
-imacros$(top_srcdir)/src/compat-libs/linkwarning.h
|
||||
|
||||
libsystemd_login_la_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-version-info $(LIBSYSTEMD_LOGIN_CURRENT):$(LIBSYSTEMD_LOGIN_REVISION):$(LIBSYSTEMD_LOGIN_AGE) \
|
||||
-Wl,--version-script=$(top_srcdir)/src/compat-libs/libsystemd-login.sym
|
||||
|
||||
libsystemd_login_la_LIBADD = \
|
||||
libsystemd-internal.la
|
||||
|
||||
nodist_libsystemd_id128_la_SOURCES = \
|
||||
libsystemd-id128.c
|
||||
|
||||
libsystemd_id128_la_SOURCES = \
|
||||
src/compat-libs/libsystemd-id128.sym
|
||||
|
||||
libsystemd_id128_la_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
-imacros$(top_srcdir)/src/compat-libs/linkwarning.h
|
||||
|
||||
libsystemd_id128_la_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-version-info $(LIBSYSTEMD_ID128_CURRENT):$(LIBSYSTEMD_ID128_REVISION):$(LIBSYSTEMD_ID128_AGE) \
|
||||
-Wl,--version-script=$(top_srcdir)/src/compat-libs/libsystemd-id128.sym
|
||||
|
||||
libsystemd_id128_la_LIBADD = \
|
||||
libsystemd-internal.la
|
||||
|
||||
nodist_libsystemd_daemon_la_SOURCES = \
|
||||
libsystemd-daemon.c
|
||||
|
||||
libsystemd_daemon_la_SOURCES = \
|
||||
src/compat-libs/libsystemd-daemon.sym
|
||||
|
||||
libsystemd_daemon_la_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
-imacros$(top_srcdir)/src/compat-libs/linkwarning.h
|
||||
|
||||
libsystemd_daemon_la_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-version-info $(LIBSYSTEMD_DAEMON_CURRENT):$(LIBSYSTEMD_DAEMON_REVISION):$(LIBSYSTEMD_DAEMON_AGE) \
|
||||
-Wl,--version-script=$(top_srcdir)/src/compat-libs/libsystemd-daemon.sym
|
||||
|
||||
libsystemd_daemon_la_LIBADD = \
|
||||
libsystemd-internal.la
|
||||
|
||||
lib_LTLIBRARIES += \
|
||||
libsystemd-journal.la \
|
||||
libsystemd-login.la \
|
||||
libsystemd-id128.la \
|
||||
libsystemd-daemon.la
|
||||
|
||||
pkgconfiglib_DATA += \
|
||||
src/compat-libs/libsystemd-journal.pc \
|
||||
src/compat-libs/libsystemd-login.pc \
|
||||
src/compat-libs/libsystemd-id128.pc \
|
||||
src/compat-libs/libsystemd-daemon.pc
|
||||
|
||||
# move lib from $(libdir) to $(rootlibdir) and update devel link, if needed
|
||||
compat-lib-install-hook:
|
||||
libname=libsystemd-login.so && $(move-to-rootlibdir)
|
||||
libname=libsystemd-journal.so && $(move-to-rootlibdir)
|
||||
libname=libsystemd-id128.so && $(move-to-rootlibdir)
|
||||
libname=libsystemd-daemon.so && $(move-to-rootlibdir)
|
||||
|
||||
compat-lib-uninstall-hook:
|
||||
rm -f $(DESTDIR)$(rootlibdir)/libsystemd-login.so*
|
||||
rm -f $(DESTDIR)$(rootlibdir)/libsystemd-journal.so*
|
||||
rm -f $(DESTDIR)$(rootlibdir)/libsystemd-id128.so*
|
||||
rm -f $(DESTDIR)$(rootlibdir)/libsystemd-daemon.so*
|
||||
|
||||
INSTALL_EXEC_HOOKS += compat-lib-install-hook
|
||||
UNINSTALL_EXEC_HOOKS += compat-lib-uninstall-hook
|
||||
endif
|
||||
|
||||
EXTRA_DIST += \
|
||||
src/compat-libs/linkwarning.h \
|
||||
src/compat-libs/libsystemd-journal.pc.in \
|
||||
src/compat-libs/libsystemd-login.pc.in \
|
||||
src/compat-libs/libsystemd-id128.pc.in \
|
||||
src/compat-libs/libsystemd-daemon.pc.in
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
substitutions = \
|
||||
'|rootlibexecdir=$(rootlibexecdir)|' \
|
||||
|
2
TODO
2
TODO
@ -38,8 +38,6 @@ Features:
|
||||
|
||||
* cache sd_event_now() result from before the first iteration...
|
||||
|
||||
* remove Capabilities=, after all AmbientCapabilities= and CapabilityBoundingSet= should be enough.
|
||||
|
||||
* support for the new copy_file_range() syscall
|
||||
|
||||
* add systemctl stop --job-mode=triggering that follows TRIGGERED_BY deps and adds them to the same transaction
|
||||
|
10
autogen.sh
10
autogen.sh
@ -55,16 +55,16 @@ fi
|
||||
cd $oldpwd
|
||||
|
||||
if [ "x$1" = "xc" ]; then
|
||||
$topdir/configure CFLAGS='-g -O0 -ftrapv' --enable-compat-libs --enable-kdbus $args
|
||||
$topdir/configure CFLAGS='-g -O0 -ftrapv' --enable-kdbus $args
|
||||
make clean
|
||||
elif [ "x$1" = "xg" ]; then
|
||||
$topdir/configure CFLAGS='-g -Og -ftrapv' --enable-compat-libs --enable-kdbus $args
|
||||
$topdir/configure CFLAGS='-g -Og -ftrapv' --enable-kdbus $args
|
||||
make clean
|
||||
elif [ "x$1" = "xa" ]; then
|
||||
$topdir/configure CFLAGS='-g -O0 -Wsuggest-attribute=pure -Wsuggest-attribute=const -ftrapv' --enable-compat-libs --enable-kdbus $args
|
||||
$topdir/configure CFLAGS='-g -O0 -Wsuggest-attribute=pure -Wsuggest-attribute=const -ftrapv' --enable-kdbus $args
|
||||
make clean
|
||||
elif [ "x$1" = "xl" ]; then
|
||||
$topdir/configure CC=clang CFLAGS='-g -O0 -ftrapv' --enable-compat-libs --enable-kdbus $args
|
||||
$topdir/configure CC=clang CFLAGS='-g -O0 -ftrapv' --enable-kdbus $args
|
||||
make clean
|
||||
elif [ "x$1" = "xs" ]; then
|
||||
scan-build $topdir/configure CFLAGS='-std=gnu99 -g -O0 -ftrapv' --enable-kdbus $args
|
||||
@ -75,6 +75,6 @@ else
|
||||
echo "Initialized build system. For a common configuration please run:"
|
||||
echo "----------------------------------------------------------------"
|
||||
echo
|
||||
echo "$topdir/configure CFLAGS='-g -O0 -ftrapv' --enable-compat-libs --enable-kdbus $args"
|
||||
echo "$topdir/configure CFLAGS='-g -O0 -ftrapv' --enable-kdbus $args"
|
||||
echo
|
||||
fi
|
||||
|
12
configure.ac
12
configure.ac
@ -362,17 +362,6 @@ AC_ARG_ENABLE([utmp], AS_HELP_STRING([--disable-utmp], [disable utmp/wtmp log ha
|
||||
AS_IF([test "x$have_utmp" = "xyes"], [AC_DEFINE(HAVE_UTMP, 1, [Define if utmp/wtmp support is enabled])])
|
||||
AM_CONDITIONAL([HAVE_UTMP], [test "x$have_utmp" = "xyes"])
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
have_compat_libs=no
|
||||
AC_ARG_ENABLE([compat_libs], AS_HELP_STRING([--enable-compat-libs],[Enable creation of compatibility libraries]),
|
||||
[case "${enableval}" in
|
||||
yes) have_compat_libs=yes ;;
|
||||
no) have_compat_libs=no ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-compat-libs) ;;
|
||||
esac],
|
||||
[have_compat_libs=no])
|
||||
AM_CONDITIONAL([ENABLE_COMPAT_LIBS], [test "$have_compat_libs" = "yes"])
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
have_coverage=no
|
||||
AC_ARG_ENABLE(coverage, AS_HELP_STRING([--enable-coverage], [enable test coverage]))
|
||||
@ -1600,7 +1589,6 @@ AC_MSG_RESULT([
|
||||
test coverage: ${have_coverage}
|
||||
Split /usr: ${enable_split_usr}
|
||||
SysV compatibility: ${SYSTEM_SYSV_COMPAT}
|
||||
compatibility libraries: ${have_compat_libs}
|
||||
utmp/wtmp support: ${have_utmp}
|
||||
ldconfig support: ${enable_ldconfig}
|
||||
hibernate support: ${enable_hibernate}
|
||||
|
@ -406,15 +406,11 @@
|
||||
For processes that are not part of a session, returns -ENXIO.
|
||||
</para>
|
||||
|
||||
<para><function>sd_bus_creds_has_effective_cap()</function> will
|
||||
check whether the capability specified by
|
||||
<parameter>capability</parameter> was set in the effective
|
||||
capabilities mask. A positive return value means that is was
|
||||
set, zero means that it was not set, and a negative return
|
||||
value indicates an error. See
|
||||
<citerefentry project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
and <varname>Capabilities=</varname> and
|
||||
<varname>CapabilityBoundingSet=</varname> settings in
|
||||
<para><function>sd_bus_creds_has_effective_cap()</function> will check whether the capability specified by
|
||||
<parameter>capability</parameter> was set in the effective capabilities mask. A positive return value means that it
|
||||
was set, zero means that it was not set, and a negative return value indicates an error. See <citerefentry
|
||||
project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry> and the
|
||||
<varname>AmbientCapabilities=</varname> and <varname>CapabilityBoundingSet=</varname> settings in
|
||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
</para>
|
||||
|
||||
|
@ -778,32 +778,21 @@
|
||||
<varlistentry>
|
||||
<term><varname>CapabilityBoundingSet=</varname></term>
|
||||
|
||||
<listitem><para>Controls which capabilities to include in the
|
||||
capability bounding set for the executed process. See
|
||||
<citerefentry project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
for details. Takes a whitespace-separated list of capability
|
||||
names as read by
|
||||
<citerefentry project='mankier'><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
e.g. <constant>CAP_SYS_ADMIN</constant>,
|
||||
<constant>CAP_DAC_OVERRIDE</constant>,
|
||||
<constant>CAP_SYS_PTRACE</constant>. Capabilities listed will
|
||||
be included in the bounding set, all others are removed. If
|
||||
the list of capabilities is prefixed with
|
||||
<literal>~</literal>, all but the listed capabilities will be
|
||||
included, the effect of the assignment inverted. Note that
|
||||
this option also affects the respective capabilities in the
|
||||
effective, permitted and inheritable capability sets, on top
|
||||
of what <varname>Capabilities=</varname> does. If this option
|
||||
is not used, the capability bounding set is not modified on
|
||||
process execution, hence no limits on the capabilities of the
|
||||
process are enforced. This option may appear more than once, in
|
||||
which case the bounding sets are merged. If the empty string
|
||||
is assigned to this option, the bounding set is reset to the
|
||||
empty capability set, and all prior settings have no effect.
|
||||
If set to <literal>~</literal> (without any further argument),
|
||||
the bounding set is reset to the full set of available
|
||||
capabilities, also undoing any previous
|
||||
settings.</para></listitem>
|
||||
<listitem><para>Controls which capabilities to include in the capability bounding set for the executed
|
||||
process. See <citerefentry
|
||||
project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
||||
details. Takes a whitespace-separated list of capability names as read by <citerefentry
|
||||
project='mankier'><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
e.g. <constant>CAP_SYS_ADMIN</constant>, <constant>CAP_DAC_OVERRIDE</constant>,
|
||||
<constant>CAP_SYS_PTRACE</constant>. Capabilities listed will be included in the bounding set, all others are
|
||||
removed. If the list of capabilities is prefixed with <literal>~</literal>, all but the listed capabilities
|
||||
will be included, the effect of the assignment inverted. Note that this option also affects the respective
|
||||
capabilities in the effective, permitted and inheritable capability sets. If this option is not used, the
|
||||
capability bounding set is not modified on process execution, hence no limits on the capabilities of the
|
||||
process are enforced. This option may appear more than once, in which case the bounding sets are merged. If the
|
||||
empty string is assigned to this option, the bounding set is reset to the empty capability set, and all prior
|
||||
settings have no effect. If set to <literal>~</literal> (without any further argument), the bounding set is
|
||||
reset to the full set of available capabilities, also undoing any previous settings.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@ -853,20 +842,6 @@
|
||||
for details.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Capabilities=</varname></term>
|
||||
<listitem><para>Controls the
|
||||
<citerefentry project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
set for the executed process. Take a capability string
|
||||
describing the effective, permitted and inherited capability
|
||||
sets as documented in
|
||||
<citerefentry project='mankier'><refentrytitle>cap_from_text</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||
Note that these capability sets are usually influenced (and
|
||||
filtered) by the capabilities attached to the executed file.
|
||||
Due to that <varname>CapabilityBoundingSet=</varname> is
|
||||
probably a much more useful setting.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ReadWriteDirectories=</varname></term>
|
||||
<term><varname>ReadOnlyDirectories=</varname></term>
|
||||
|
@ -94,19 +94,6 @@ int fdset_put(FDSet *s, int fd) {
|
||||
return set_put(MAKE_SET(s), FD_TO_PTR(fd));
|
||||
}
|
||||
|
||||
int fdset_consume(FDSet *s, int fd) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(fd >= 0);
|
||||
|
||||
r = fdset_put(s, fd);
|
||||
if (r <= 0)
|
||||
safe_close(fd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int fdset_put_dup(FDSet *s, int fd) {
|
||||
int copy, r;
|
||||
|
||||
|
@ -32,7 +32,6 @@ FDSet* fdset_free(FDSet *s);
|
||||
|
||||
int fdset_put(FDSet *s, int fd);
|
||||
int fdset_put_dup(FDSet *s, int fd);
|
||||
int fdset_consume(FDSet *s, int fd);
|
||||
|
||||
bool fdset_contains(FDSet *s, int fd);
|
||||
int fdset_remove(FDSet *s, int fd);
|
||||
|
@ -283,24 +283,6 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
|
||||
assert(fd >= 0);
|
||||
|
||||
/* Under the assumption that we are running privileged we
|
||||
* first change the access mode and only then hand out
|
||||
* ownership to avoid a window where access is too open. */
|
||||
|
||||
if (mode != MODE_INVALID)
|
||||
if (fchmod(fd, mode) < 0)
|
||||
return -errno;
|
||||
|
||||
if (uid != UID_INVALID || gid != GID_INVALID)
|
||||
if (fchown(fd, uid, gid) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fchmod_umask(int fd, mode_t m) {
|
||||
mode_t u;
|
||||
int r;
|
||||
|
@ -43,7 +43,6 @@ int readlink_and_canonicalize(const char *p, char **r);
|
||||
int readlink_and_make_absolute_root(const char *root, const char *path, char **ret);
|
||||
|
||||
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
|
||||
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
int fchmod_umask(int fd, mode_t mode);
|
||||
|
||||
|
871
src/basic/json.c
871
src/basic/json.c
@ -1,871 +0,0 @@
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2014 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "json.h"
|
||||
#include "macro.h"
|
||||
#include "string-util.h"
|
||||
#include "utf8.h"
|
||||
|
||||
int json_variant_new(JsonVariant **ret, JsonVariantType type) {
|
||||
JsonVariant *v;
|
||||
|
||||
v = new0(JsonVariant, 1);
|
||||
if (!v)
|
||||
return -ENOMEM;
|
||||
v->type = type;
|
||||
*ret = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_variant_deep_copy(JsonVariant *ret, JsonVariant *variant) {
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
assert(variant);
|
||||
|
||||
ret->type = variant->type;
|
||||
ret->size = variant->size;
|
||||
|
||||
if (variant->type == JSON_VARIANT_STRING) {
|
||||
ret->string = memdup(variant->string, variant->size+1);
|
||||
if (!ret->string)
|
||||
return -ENOMEM;
|
||||
} else if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT) {
|
||||
size_t i;
|
||||
|
||||
ret->objects = new0(JsonVariant, variant->size);
|
||||
if (!ret->objects)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < variant->size; ++i) {
|
||||
r = json_variant_deep_copy(&ret->objects[i], &variant->objects[i]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
} else
|
||||
ret->value = variant->value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static JsonVariant *json_object_unref(JsonVariant *variant);
|
||||
|
||||
static JsonVariant *json_variant_unref_inner(JsonVariant *variant) {
|
||||
if (!variant)
|
||||
return NULL;
|
||||
|
||||
if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT)
|
||||
return json_object_unref(variant);
|
||||
else if (variant->type == JSON_VARIANT_STRING)
|
||||
free(variant->string);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static JsonVariant *json_raw_unref(JsonVariant *variant, size_t size) {
|
||||
if (!variant)
|
||||
return NULL;
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
json_variant_unref_inner(&variant[i]);
|
||||
|
||||
free(variant);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static JsonVariant *json_object_unref(JsonVariant *variant) {
|
||||
size_t i;
|
||||
|
||||
assert(variant);
|
||||
|
||||
if (!variant->objects)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < variant->size; ++i)
|
||||
json_variant_unref_inner(&variant->objects[i]);
|
||||
|
||||
free(variant->objects);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static JsonVariant **json_variant_array_unref(JsonVariant **variant) {
|
||||
size_t i = 0;
|
||||
JsonVariant *p = NULL;
|
||||
|
||||
if (!variant)
|
||||
return NULL;
|
||||
|
||||
while((p = (variant[i++])) != NULL) {
|
||||
if (p->type == JSON_VARIANT_STRING)
|
||||
free(p->string);
|
||||
free(p);
|
||||
}
|
||||
|
||||
free(variant);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant **, json_variant_array_unref);
|
||||
|
||||
JsonVariant *json_variant_unref(JsonVariant *variant) {
|
||||
if (!variant)
|
||||
return NULL;
|
||||
|
||||
if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT)
|
||||
json_object_unref(variant);
|
||||
else if (variant->type == JSON_VARIANT_STRING)
|
||||
free(variant->string);
|
||||
|
||||
free(variant);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *json_variant_string(JsonVariant *variant){
|
||||
assert(variant);
|
||||
assert(variant->type == JSON_VARIANT_STRING);
|
||||
|
||||
return variant->string;
|
||||
}
|
||||
|
||||
bool json_variant_bool(JsonVariant *variant) {
|
||||
assert(variant);
|
||||
assert(variant->type == JSON_VARIANT_BOOLEAN);
|
||||
|
||||
return variant->value.boolean;
|
||||
}
|
||||
|
||||
intmax_t json_variant_integer(JsonVariant *variant) {
|
||||
assert(variant);
|
||||
assert(variant->type == JSON_VARIANT_INTEGER);
|
||||
|
||||
return variant->value.integer;
|
||||
}
|
||||
|
||||
double json_variant_real(JsonVariant *variant) {
|
||||
assert(variant);
|
||||
assert(variant->type == JSON_VARIANT_REAL);
|
||||
|
||||
return variant->value.real;
|
||||
}
|
||||
|
||||
JsonVariant *json_variant_element(JsonVariant *variant, unsigned index) {
|
||||
assert(variant);
|
||||
assert(variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT);
|
||||
assert(index < variant->size);
|
||||
assert(variant->objects);
|
||||
|
||||
return &variant->objects[index];
|
||||
}
|
||||
|
||||
JsonVariant *json_variant_value(JsonVariant *variant, const char *key) {
|
||||
size_t i;
|
||||
|
||||
assert(variant);
|
||||
assert(variant->type == JSON_VARIANT_OBJECT);
|
||||
assert(variant->objects);
|
||||
|
||||
for (i = 0; i < variant->size; i += 2) {
|
||||
JsonVariant *p = &variant->objects[i];
|
||||
if (p->type == JSON_VARIANT_STRING && streq(key, p->string))
|
||||
return &variant->objects[i + 1];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void inc_lines(unsigned *line, const char *s, size_t n) {
|
||||
const char *p = s;
|
||||
|
||||
if (!line)
|
||||
return;
|
||||
|
||||
for (;;) {
|
||||
const char *f;
|
||||
|
||||
f = memchr(p, '\n', n);
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
n -= (f - p) + 1;
|
||||
p = f + 1;
|
||||
(*line)++;
|
||||
}
|
||||
}
|
||||
|
||||
static int unhex_ucs2(const char *c, uint16_t *ret) {
|
||||
int aa, bb, cc, dd;
|
||||
uint16_t x;
|
||||
|
||||
assert(c);
|
||||
assert(ret);
|
||||
|
||||
aa = unhexchar(c[0]);
|
||||
if (aa < 0)
|
||||
return -EINVAL;
|
||||
|
||||
bb = unhexchar(c[1]);
|
||||
if (bb < 0)
|
||||
return -EINVAL;
|
||||
|
||||
cc = unhexchar(c[2]);
|
||||
if (cc < 0)
|
||||
return -EINVAL;
|
||||
|
||||
dd = unhexchar(c[3]);
|
||||
if (dd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
x = ((uint16_t) aa << 12) |
|
||||
((uint16_t) bb << 8) |
|
||||
((uint16_t) cc << 4) |
|
||||
((uint16_t) dd);
|
||||
|
||||
if (x <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
*ret = x;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_parse_string(const char **p, char **ret) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
size_t n = 0, allocated = 0;
|
||||
const char *c;
|
||||
|
||||
assert(p);
|
||||
assert(*p);
|
||||
assert(ret);
|
||||
|
||||
c = *p;
|
||||
|
||||
if (*c != '"')
|
||||
return -EINVAL;
|
||||
|
||||
c++;
|
||||
|
||||
for (;;) {
|
||||
int len;
|
||||
|
||||
/* Check for EOF */
|
||||
if (*c == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check for control characters 0x00..0x1f */
|
||||
if (*c > 0 && *c < ' ')
|
||||
return -EINVAL;
|
||||
|
||||
/* Check for control character 0x7f */
|
||||
if (*c == 0x7f)
|
||||
return -EINVAL;
|
||||
|
||||
if (*c == '"') {
|
||||
if (!s) {
|
||||
s = strdup("");
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
} else
|
||||
s[n] = 0;
|
||||
|
||||
*p = c + 1;
|
||||
|
||||
*ret = s;
|
||||
s = NULL;
|
||||
return JSON_STRING;
|
||||
}
|
||||
|
||||
if (*c == '\\') {
|
||||
char ch = 0;
|
||||
c++;
|
||||
|
||||
if (*c == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (IN_SET(*c, '"', '\\', '/'))
|
||||
ch = *c;
|
||||
else if (*c == 'b')
|
||||
ch = '\b';
|
||||
else if (*c == 'f')
|
||||
ch = '\f';
|
||||
else if (*c == 'n')
|
||||
ch = '\n';
|
||||
else if (*c == 'r')
|
||||
ch = '\r';
|
||||
else if (*c == 't')
|
||||
ch = '\t';
|
||||
else if (*c == 'u') {
|
||||
char16_t x;
|
||||
int r;
|
||||
|
||||
r = unhex_ucs2(c + 1, &x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
c += 5;
|
||||
|
||||
if (!GREEDY_REALLOC(s, allocated, n + 4))
|
||||
return -ENOMEM;
|
||||
|
||||
if (!utf16_is_surrogate(x))
|
||||
n += utf8_encode_unichar(s + n, (char32_t) x);
|
||||
else if (utf16_is_trailing_surrogate(x))
|
||||
return -EINVAL;
|
||||
else {
|
||||
char16_t y;
|
||||
|
||||
if (c[0] != '\\' || c[1] != 'u')
|
||||
return -EINVAL;
|
||||
|
||||
r = unhex_ucs2(c + 2, &y);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
c += 6;
|
||||
|
||||
if (!utf16_is_trailing_surrogate(y))
|
||||
return -EINVAL;
|
||||
|
||||
n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y));
|
||||
}
|
||||
|
||||
continue;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
if (!GREEDY_REALLOC(s, allocated, n + 2))
|
||||
return -ENOMEM;
|
||||
|
||||
s[n++] = ch;
|
||||
c ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
len = utf8_encoded_valid_unichar(c);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
if (!GREEDY_REALLOC(s, allocated, n + len + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(s + n, c, len);
|
||||
n += len;
|
||||
c += len;
|
||||
}
|
||||
}
|
||||
|
||||
static int json_parse_number(const char **p, union json_value *ret) {
|
||||
bool negative = false, exponent_negative = false, is_double = false;
|
||||
double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0;
|
||||
intmax_t i = 0;
|
||||
const char *c;
|
||||
|
||||
assert(p);
|
||||
assert(*p);
|
||||
assert(ret);
|
||||
|
||||
c = *p;
|
||||
|
||||
if (*c == '-') {
|
||||
negative = true;
|
||||
c++;
|
||||
}
|
||||
|
||||
if (*c == '0')
|
||||
c++;
|
||||
else {
|
||||
if (!strchr("123456789", *c) || *c == 0)
|
||||
return -EINVAL;
|
||||
|
||||
do {
|
||||
if (!is_double) {
|
||||
int64_t t;
|
||||
|
||||
t = 10 * i + (*c - '0');
|
||||
if (t < i) /* overflow */
|
||||
is_double = false;
|
||||
else
|
||||
i = t;
|
||||
}
|
||||
|
||||
x = 10.0 * x + (*c - '0');
|
||||
c++;
|
||||
} while (strchr("0123456789", *c) && *c != 0);
|
||||
}
|
||||
|
||||
if (*c == '.') {
|
||||
is_double = true;
|
||||
c++;
|
||||
|
||||
if (!strchr("0123456789", *c) || *c == 0)
|
||||
return -EINVAL;
|
||||
|
||||
do {
|
||||
y = 10.0 * y + (*c - '0');
|
||||
shift = 10.0 * shift;
|
||||
c++;
|
||||
} while (strchr("0123456789", *c) && *c != 0);
|
||||
}
|
||||
|
||||
if (*c == 'e' || *c == 'E') {
|
||||
is_double = true;
|
||||
c++;
|
||||
|
||||
if (*c == '-') {
|
||||
exponent_negative = true;
|
||||
c++;
|
||||
} else if (*c == '+')
|
||||
c++;
|
||||
|
||||
if (!strchr("0123456789", *c) || *c == 0)
|
||||
return -EINVAL;
|
||||
|
||||
do {
|
||||
exponent = 10.0 * exponent + (*c - '0');
|
||||
c++;
|
||||
} while (strchr("0123456789", *c) && *c != 0);
|
||||
}
|
||||
|
||||
*p = c;
|
||||
|
||||
if (is_double) {
|
||||
ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10((exponent_negative ? -1.0 : 1.0) * exponent);
|
||||
return JSON_REAL;
|
||||
} else {
|
||||
ret->integer = negative ? -i : i;
|
||||
return JSON_INTEGER;
|
||||
}
|
||||
}
|
||||
|
||||
int json_tokenize(
|
||||
const char **p,
|
||||
char **ret_string,
|
||||
union json_value *ret_value,
|
||||
void **state,
|
||||
unsigned *line) {
|
||||
|
||||
const char *c;
|
||||
int t;
|
||||
int r;
|
||||
|
||||
enum {
|
||||
STATE_NULL,
|
||||
STATE_VALUE,
|
||||
STATE_VALUE_POST,
|
||||
};
|
||||
|
||||
assert(p);
|
||||
assert(*p);
|
||||
assert(ret_string);
|
||||
assert(ret_value);
|
||||
assert(state);
|
||||
|
||||
t = PTR_TO_INT(*state);
|
||||
c = *p;
|
||||
|
||||
if (t == STATE_NULL) {
|
||||
if (line)
|
||||
*line = 1;
|
||||
t = STATE_VALUE;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
const char *b;
|
||||
|
||||
b = c + strspn(c, WHITESPACE);
|
||||
if (*b == 0)
|
||||
return JSON_END;
|
||||
|
||||
inc_lines(line, c, b - c);
|
||||
c = b;
|
||||
|
||||
switch (t) {
|
||||
|
||||
case STATE_VALUE:
|
||||
|
||||
if (*c == '{') {
|
||||
*ret_string = NULL;
|
||||
*ret_value = JSON_VALUE_NULL;
|
||||
*p = c + 1;
|
||||
*state = INT_TO_PTR(STATE_VALUE);
|
||||
return JSON_OBJECT_OPEN;
|
||||
|
||||
} else if (*c == '}') {
|
||||
*ret_string = NULL;
|
||||
*ret_value = JSON_VALUE_NULL;
|
||||
*p = c + 1;
|
||||
*state = INT_TO_PTR(STATE_VALUE_POST);
|
||||
return JSON_OBJECT_CLOSE;
|
||||
|
||||
} else if (*c == '[') {
|
||||
*ret_string = NULL;
|
||||
*ret_value = JSON_VALUE_NULL;
|
||||
*p = c + 1;
|
||||
*state = INT_TO_PTR(STATE_VALUE);
|
||||
return JSON_ARRAY_OPEN;
|
||||
|
||||
} else if (*c == ']') {
|
||||
*ret_string = NULL;
|
||||
*ret_value = JSON_VALUE_NULL;
|
||||
*p = c + 1;
|
||||
*state = INT_TO_PTR(STATE_VALUE_POST);
|
||||
return JSON_ARRAY_CLOSE;
|
||||
|
||||
} else if (*c == '"') {
|
||||
r = json_parse_string(&c, ret_string);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_value = JSON_VALUE_NULL;
|
||||
*p = c;
|
||||
*state = INT_TO_PTR(STATE_VALUE_POST);
|
||||
return r;
|
||||
|
||||
} else if (strchr("-0123456789", *c)) {
|
||||
r = json_parse_number(&c, ret_value);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_string = NULL;
|
||||
*p = c;
|
||||
*state = INT_TO_PTR(STATE_VALUE_POST);
|
||||
return r;
|
||||
|
||||
} else if (startswith(c, "true")) {
|
||||
*ret_string = NULL;
|
||||
ret_value->boolean = true;
|
||||
*p = c + 4;
|
||||
*state = INT_TO_PTR(STATE_VALUE_POST);
|
||||
return JSON_BOOLEAN;
|
||||
|
||||
} else if (startswith(c, "false")) {
|
||||
*ret_string = NULL;
|
||||
ret_value->boolean = false;
|
||||
*p = c + 5;
|
||||
*state = INT_TO_PTR(STATE_VALUE_POST);
|
||||
return JSON_BOOLEAN;
|
||||
|
||||
} else if (startswith(c, "null")) {
|
||||
*ret_string = NULL;
|
||||
*ret_value = JSON_VALUE_NULL;
|
||||
*p = c + 4;
|
||||
*state = INT_TO_PTR(STATE_VALUE_POST);
|
||||
return JSON_NULL;
|
||||
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
case STATE_VALUE_POST:
|
||||
|
||||
if (*c == ':') {
|
||||
*ret_string = NULL;
|
||||
*ret_value = JSON_VALUE_NULL;
|
||||
*p = c + 1;
|
||||
*state = INT_TO_PTR(STATE_VALUE);
|
||||
return JSON_COLON;
|
||||
} else if (*c == ',') {
|
||||
*ret_string = NULL;
|
||||
*ret_value = JSON_VALUE_NULL;
|
||||
*p = c + 1;
|
||||
*state = INT_TO_PTR(STATE_VALUE);
|
||||
return JSON_COMMA;
|
||||
} else if (*c == '}') {
|
||||
*ret_string = NULL;
|
||||
*ret_value = JSON_VALUE_NULL;
|
||||
*p = c + 1;
|
||||
*state = INT_TO_PTR(STATE_VALUE_POST);
|
||||
return JSON_OBJECT_CLOSE;
|
||||
} else if (*c == ']') {
|
||||
*ret_string = NULL;
|
||||
*ret_value = JSON_VALUE_NULL;
|
||||
*p = c + 1;
|
||||
*state = INT_TO_PTR(STATE_VALUE_POST);
|
||||
return JSON_ARRAY_CLOSE;
|
||||
} else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static bool json_is_value(JsonVariant *var) {
|
||||
assert(var);
|
||||
|
||||
return var->type != JSON_VARIANT_CONTROL;
|
||||
}
|
||||
|
||||
static int json_scoped_parse(JsonVariant **tokens, size_t *i, size_t n, JsonVariant *scope) {
|
||||
bool arr = scope->type == JSON_VARIANT_ARRAY;
|
||||
int terminator = arr ? JSON_ARRAY_CLOSE : JSON_OBJECT_CLOSE;
|
||||
size_t allocated = 0, size = 0;
|
||||
JsonVariant *key = NULL, *value = NULL, *var = NULL, *items = NULL;
|
||||
enum {
|
||||
STATE_KEY,
|
||||
STATE_COLON,
|
||||
STATE_COMMA,
|
||||
STATE_VALUE
|
||||
} state = arr ? STATE_VALUE : STATE_KEY;
|
||||
|
||||
assert(tokens);
|
||||
assert(i);
|
||||
assert(scope);
|
||||
|
||||
while((var = *i < n ? tokens[(*i)++] : NULL) != NULL) {
|
||||
bool stopper;
|
||||
int r;
|
||||
|
||||
stopper = !json_is_value(var) && var->value.integer == terminator;
|
||||
|
||||
if (stopper) {
|
||||
if (state != STATE_COMMA && size > 0)
|
||||
goto error;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (state == STATE_KEY) {
|
||||
if (var->type != JSON_VARIANT_STRING)
|
||||
goto error;
|
||||
else {
|
||||
key = var;
|
||||
state = STATE_COLON;
|
||||
}
|
||||
}
|
||||
else if (state == STATE_COLON) {
|
||||
if (key == NULL)
|
||||
goto error;
|
||||
|
||||
if (json_is_value(var))
|
||||
goto error;
|
||||
|
||||
if (var->value.integer != JSON_COLON)
|
||||
goto error;
|
||||
|
||||
state = STATE_VALUE;
|
||||
}
|
||||
else if (state == STATE_VALUE) {
|
||||
_cleanup_json_variant_unref_ JsonVariant *v = NULL;
|
||||
size_t toadd = arr ? 1 : 2;
|
||||
|
||||
if (!json_is_value(var)) {
|
||||
int type = (var->value.integer == JSON_ARRAY_OPEN) ? JSON_VARIANT_ARRAY : JSON_VARIANT_OBJECT;
|
||||
|
||||
r = json_variant_new(&v, type);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = json_scoped_parse(tokens, i, n, v);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
value = v;
|
||||
}
|
||||
else
|
||||
value = var;
|
||||
|
||||
if(!GREEDY_REALLOC(items, allocated, size + toadd))
|
||||
goto error;
|
||||
|
||||
if (arr) {
|
||||
r = json_variant_deep_copy(&items[size], value);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
} else {
|
||||
r = json_variant_deep_copy(&items[size], key);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = json_variant_deep_copy(&items[size+1], value);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
size += toadd;
|
||||
state = STATE_COMMA;
|
||||
}
|
||||
else if (state == STATE_COMMA) {
|
||||
if (json_is_value(var))
|
||||
goto error;
|
||||
|
||||
if (var->value.integer != JSON_COMMA)
|
||||
goto error;
|
||||
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
|
||||
state = arr ? STATE_VALUE : STATE_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
json_raw_unref(items, size);
|
||||
return -EBADMSG;
|
||||
|
||||
out:
|
||||
scope->size = size;
|
||||
scope->objects = items;
|
||||
|
||||
return scope->type;
|
||||
}
|
||||
|
||||
static int json_parse_tokens(JsonVariant **tokens, size_t ntokens, JsonVariant **rv) {
|
||||
size_t it = 0;
|
||||
int r;
|
||||
JsonVariant *e;
|
||||
_cleanup_json_variant_unref_ JsonVariant *p = NULL;
|
||||
|
||||
assert(tokens);
|
||||
assert(ntokens);
|
||||
|
||||
e = tokens[it++];
|
||||
r = json_variant_new(&p, JSON_VARIANT_OBJECT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (e->type != JSON_VARIANT_CONTROL && e->value.integer != JSON_OBJECT_OPEN)
|
||||
return -EBADMSG;
|
||||
|
||||
r = json_scoped_parse(tokens, &it, ntokens, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*rv = p;
|
||||
p = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_tokens(const char *string, size_t size, JsonVariant ***tokens, size_t *n) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
_cleanup_(json_variant_array_unrefp) JsonVariant **items = NULL;
|
||||
union json_value v = {};
|
||||
void *json_state = NULL;
|
||||
const char *p;
|
||||
int t, r;
|
||||
size_t allocated = 0, s = 0;
|
||||
|
||||
assert(string);
|
||||
assert(n);
|
||||
|
||||
if (size <= 0)
|
||||
return -EBADMSG;
|
||||
|
||||
buf = strndup(string, size);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
p = buf;
|
||||
for (;;) {
|
||||
_cleanup_json_variant_unref_ JsonVariant *var = NULL;
|
||||
_cleanup_free_ char *rstr = NULL;
|
||||
|
||||
t = json_tokenize(&p, &rstr, &v, &json_state, NULL);
|
||||
|
||||
if (t < 0)
|
||||
return t;
|
||||
else if (t == JSON_END)
|
||||
break;
|
||||
|
||||
if (t <= JSON_ARRAY_CLOSE) {
|
||||
r = json_variant_new(&var, JSON_VARIANT_CONTROL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
var->value.integer = t;
|
||||
} else {
|
||||
switch (t) {
|
||||
case JSON_STRING:
|
||||
r = json_variant_new(&var, JSON_VARIANT_STRING);
|
||||
if (r < 0)
|
||||
return r;
|
||||
var->size = strlen(rstr);
|
||||
var->string = strdup(rstr);
|
||||
if (!var->string) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
break;
|
||||
case JSON_INTEGER:
|
||||
r = json_variant_new(&var, JSON_VARIANT_INTEGER);
|
||||
if (r < 0)
|
||||
return r;
|
||||
var->value = v;
|
||||
break;
|
||||
case JSON_REAL:
|
||||
r = json_variant_new(&var, JSON_VARIANT_REAL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
var->value = v;
|
||||
break;
|
||||
case JSON_BOOLEAN:
|
||||
r = json_variant_new(&var, JSON_VARIANT_BOOLEAN);
|
||||
if (r < 0)
|
||||
return r;
|
||||
var->value = v;
|
||||
break;
|
||||
case JSON_NULL:
|
||||
r = json_variant_new(&var, JSON_VARIANT_NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(items, allocated, s+2))
|
||||
return -ENOMEM;
|
||||
|
||||
items[s++] = var;
|
||||
items[s] = NULL;
|
||||
var = NULL;
|
||||
}
|
||||
|
||||
*n = s;
|
||||
*tokens = items;
|
||||
items = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int json_parse(const char *string, JsonVariant **rv) {
|
||||
_cleanup_(json_variant_array_unrefp) JsonVariant **s = NULL;
|
||||
JsonVariant *v = NULL;
|
||||
size_t n = 0;
|
||||
int r;
|
||||
|
||||
assert(string);
|
||||
assert(rv);
|
||||
|
||||
r = json_tokens(string, strlen(string), &s, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_parse_tokens(s, n, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*rv = v;
|
||||
return 0;
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2014 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "macro.h"
|
||||
#include "util.h"
|
||||
|
||||
enum {
|
||||
JSON_END,
|
||||
JSON_COLON,
|
||||
JSON_COMMA,
|
||||
JSON_OBJECT_OPEN,
|
||||
JSON_OBJECT_CLOSE,
|
||||
JSON_ARRAY_OPEN,
|
||||
JSON_ARRAY_CLOSE,
|
||||
JSON_STRING,
|
||||
JSON_REAL,
|
||||
JSON_INTEGER,
|
||||
JSON_BOOLEAN,
|
||||
JSON_NULL,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
JSON_VARIANT_CONTROL,
|
||||
JSON_VARIANT_STRING,
|
||||
JSON_VARIANT_INTEGER,
|
||||
JSON_VARIANT_BOOLEAN,
|
||||
JSON_VARIANT_REAL,
|
||||
JSON_VARIANT_ARRAY,
|
||||
JSON_VARIANT_OBJECT,
|
||||
JSON_VARIANT_NULL
|
||||
} JsonVariantType;
|
||||
|
||||
union json_value {
|
||||
bool boolean;
|
||||
double real;
|
||||
intmax_t integer;
|
||||
};
|
||||
|
||||
typedef struct JsonVariant {
|
||||
JsonVariantType type;
|
||||
size_t size;
|
||||
union {
|
||||
char *string;
|
||||
struct JsonVariant *objects;
|
||||
union json_value value;
|
||||
};
|
||||
} JsonVariant;
|
||||
|
||||
int json_variant_new(JsonVariant **ret, JsonVariantType type);
|
||||
JsonVariant *json_variant_unref(JsonVariant *v);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref);
|
||||
#define _cleanup_json_variant_unref_ _cleanup_(json_variant_unrefp)
|
||||
|
||||
char *json_variant_string(JsonVariant *v);
|
||||
bool json_variant_bool(JsonVariant *v);
|
||||
intmax_t json_variant_integer(JsonVariant *v);
|
||||
double json_variant_real(JsonVariant *v);
|
||||
|
||||
JsonVariant *json_variant_element(JsonVariant *v, unsigned index);
|
||||
JsonVariant *json_variant_value(JsonVariant *v, const char *key);
|
||||
|
||||
#define JSON_VALUE_NULL ((union json_value) {})
|
||||
|
||||
int json_tokenize(const char **p, char **ret_string, union json_value *ret_value, void **state, unsigned *line);
|
||||
|
||||
int json_parse(const char *string, JsonVariant **rv);
|
||||
int json_parse_measure(const char *string, size_t *size);
|
@ -1 +0,0 @@
|
||||
../Makefile
|
@ -36,7 +36,7 @@ void* mempool_alloc0_tile(struct mempool *mp);
|
||||
void mempool_free_tile(struct mempool *mp, void *p);
|
||||
|
||||
#define DEFINE_MEMPOOL(pool_name, tile_type, alloc_at_least) \
|
||||
struct mempool pool_name = { \
|
||||
static struct mempool pool_name = { \
|
||||
.tile_size = sizeof(tile_type), \
|
||||
.at_least = alloc_at_least, \
|
||||
}
|
||||
|
@ -72,13 +72,13 @@ static bool arg_batch = false;
|
||||
static bool arg_raw = false;
|
||||
static usec_t arg_delay = 1*USEC_PER_SEC;
|
||||
static char* arg_machine = NULL;
|
||||
static bool arg_recursive = true;
|
||||
|
||||
enum {
|
||||
static enum {
|
||||
COUNT_PIDS,
|
||||
COUNT_USERSPACE_PROCESSES,
|
||||
COUNT_ALL_PROCESSES,
|
||||
} arg_count = COUNT_PIDS;
|
||||
static bool arg_recursive = true;
|
||||
|
||||
static enum {
|
||||
ORDER_PATH,
|
||||
|
1
src/compat-libs/.gitignore
vendored
1
src/compat-libs/.gitignore
vendored
@ -1 +0,0 @@
|
||||
/libsystemd-*.pc
|
@ -1,19 +0,0 @@
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: systemd
|
||||
Description: systemd Daemon Utility Library - deprecated
|
||||
URL: @PACKAGE_URL@
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L${libdir} -lsystemd
|
||||
Cflags: -I${includedir}
|
@ -1,27 +0,0 @@
|
||||
/***
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
***/
|
||||
|
||||
/* Original symbols from systemd v31 */
|
||||
|
||||
LIBSYSTEMD_DAEMON_31 {
|
||||
global:
|
||||
sd_booted;
|
||||
sd_is_fifo;
|
||||
sd_is_mq;
|
||||
sd_is_socket;
|
||||
sd_is_socket_inet;
|
||||
sd_is_socket_unix;
|
||||
sd_is_special;
|
||||
sd_listen_fds;
|
||||
sd_notify;
|
||||
sd_notifyf;
|
||||
local:
|
||||
*;
|
||||
};
|
@ -1,18 +0,0 @@
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: systemd
|
||||
Description: systemd 128 Bit ID Utility Library - deprecated
|
||||
URL: @PACKAGE_URL@
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L${libdir} -lsystemd
|
||||
Cflags: -I${includedir}
|
@ -1,21 +0,0 @@
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
***/
|
||||
|
||||
/* Original symbols from systemd v38 */
|
||||
|
||||
LIBSYSTEMD_ID128_38 {
|
||||
global:
|
||||
sd_id128_to_string;
|
||||
sd_id128_from_string;
|
||||
sd_id128_randomize;
|
||||
sd_id128_get_machine;
|
||||
sd_id128_get_boot;
|
||||
local:
|
||||
*;
|
||||
};
|
@ -1,19 +0,0 @@
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: systemd
|
||||
Description: systemd Journal Utility Library - deprecated
|
||||
URL: @PACKAGE_URL@
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires: libsystemd = @PACKAGE_VERSION@
|
||||
Libs: -L${libdir} -lsystemd
|
||||
Cflags: -I${includedir}
|
@ -1,111 +0,0 @@
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
***/
|
||||
|
||||
/* Original symbols from systemd v38 */
|
||||
|
||||
LIBSYSTEMD_JOURNAL_38 {
|
||||
global:
|
||||
sd_journal_print;
|
||||
sd_journal_printv;
|
||||
sd_journal_send;
|
||||
sd_journal_sendv;
|
||||
sd_journal_stream_fd;
|
||||
sd_journal_open;
|
||||
sd_journal_close;
|
||||
sd_journal_previous;
|
||||
sd_journal_next;
|
||||
sd_journal_previous_skip;
|
||||
sd_journal_next_skip;
|
||||
sd_journal_get_realtime_usec;
|
||||
sd_journal_get_monotonic_usec;
|
||||
sd_journal_get_data;
|
||||
sd_journal_enumerate_data;
|
||||
sd_journal_restart_data;
|
||||
sd_journal_add_match;
|
||||
sd_journal_flush_matches;
|
||||
sd_journal_seek_head;
|
||||
sd_journal_seek_tail;
|
||||
sd_journal_seek_monotonic_usec;
|
||||
sd_journal_seek_realtime_usec;
|
||||
sd_journal_seek_cursor;
|
||||
sd_journal_get_cursor;
|
||||
sd_journal_get_fd;
|
||||
sd_journal_process;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
LIBSYSTEMD_JOURNAL_183 {
|
||||
global:
|
||||
sd_journal_print_with_location;
|
||||
sd_journal_printv_with_location;
|
||||
sd_journal_send_with_location;
|
||||
sd_journal_sendv_with_location;
|
||||
} LIBSYSTEMD_JOURNAL_38;
|
||||
|
||||
LIBSYSTEMD_JOURNAL_184 {
|
||||
global:
|
||||
sd_journal_get_cutoff_realtime_usec;
|
||||
sd_journal_get_cutoff_monotonic_usec;
|
||||
} LIBSYSTEMD_JOURNAL_183;
|
||||
|
||||
LIBSYSTEMD_JOURNAL_187 {
|
||||
global:
|
||||
sd_journal_wait;
|
||||
sd_journal_open_directory;
|
||||
sd_journal_add_disjunction;
|
||||
} LIBSYSTEMD_JOURNAL_184;
|
||||
|
||||
LIBSYSTEMD_JOURNAL_188 {
|
||||
global:
|
||||
sd_journal_perror;
|
||||
sd_journal_perror_with_location;
|
||||
} LIBSYSTEMD_JOURNAL_187;
|
||||
|
||||
LIBSYSTEMD_JOURNAL_190 {
|
||||
global:
|
||||
sd_journal_get_usage;
|
||||
} LIBSYSTEMD_JOURNAL_188;
|
||||
|
||||
LIBSYSTEMD_JOURNAL_195 {
|
||||
global:
|
||||
sd_journal_test_cursor;
|
||||
sd_journal_query_unique;
|
||||
sd_journal_enumerate_unique;
|
||||
sd_journal_restart_unique;
|
||||
} LIBSYSTEMD_JOURNAL_190;
|
||||
|
||||
LIBSYSTEMD_JOURNAL_196 {
|
||||
global:
|
||||
sd_journal_get_catalog;
|
||||
sd_journal_get_catalog_for_message_id;
|
||||
sd_journal_set_data_threshold;
|
||||
sd_journal_get_data_threshold;
|
||||
} LIBSYSTEMD_JOURNAL_195;
|
||||
|
||||
LIBSYSTEMD_JOURNAL_198 {
|
||||
global:
|
||||
sd_journal_reliable_fd;
|
||||
} LIBSYSTEMD_JOURNAL_196;
|
||||
|
||||
LIBSYSTEMD_JOURNAL_201 {
|
||||
global:
|
||||
sd_journal_get_events;
|
||||
sd_journal_get_timeout;
|
||||
} LIBSYSTEMD_JOURNAL_198;
|
||||
|
||||
LIBSYSTEMD_JOURNAL_202 {
|
||||
global:
|
||||
sd_journal_add_conjunction;
|
||||
} LIBSYSTEMD_JOURNAL_201;
|
||||
|
||||
LIBSYSTEMD_JOURNAL_205 {
|
||||
global:
|
||||
sd_journal_open_files;
|
||||
} LIBSYSTEMD_JOURNAL_202;
|
@ -1,18 +0,0 @@
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: systemd
|
||||
Description: systemd Login Utility Library - deprecated
|
||||
URL: @PACKAGE_URL@
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L${libdir} -lsystemd
|
||||
Cflags: -I${includedir}
|
@ -1,87 +0,0 @@
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
***/
|
||||
|
||||
/* Original symbols from systemd v31 */
|
||||
|
||||
LIBSYSTEMD_LOGIN_31 {
|
||||
global:
|
||||
sd_get_seats;
|
||||
sd_get_sessions;
|
||||
sd_get_uids;
|
||||
sd_login_monitor_flush;
|
||||
sd_login_monitor_get_fd;
|
||||
sd_login_monitor_new;
|
||||
sd_login_monitor_unref;
|
||||
sd_pid_get_owner_uid;
|
||||
sd_pid_get_session;
|
||||
sd_seat_can_multi_session;
|
||||
sd_seat_get_active;
|
||||
sd_seat_get_sessions;
|
||||
sd_session_get_seat;
|
||||
sd_session_get_uid;
|
||||
sd_session_is_active;
|
||||
sd_uid_get_seats;
|
||||
sd_uid_get_sessions;
|
||||
sd_uid_get_state;
|
||||
sd_uid_is_on_seat;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
LIBSYSTEMD_LOGIN_38 {
|
||||
global:
|
||||
sd_pid_get_unit;
|
||||
sd_session_get_service;
|
||||
} LIBSYSTEMD_LOGIN_31;
|
||||
|
||||
LIBSYSTEMD_LOGIN_43 {
|
||||
global:
|
||||
sd_session_get_type;
|
||||
sd_session_get_class;
|
||||
sd_session_get_display;
|
||||
} LIBSYSTEMD_LOGIN_38;
|
||||
|
||||
LIBSYSTEMD_LOGIN_186 {
|
||||
global:
|
||||
sd_session_get_state;
|
||||
sd_seat_can_tty;
|
||||
sd_seat_can_graphical;
|
||||
} LIBSYSTEMD_LOGIN_43;
|
||||
|
||||
LIBSYSTEMD_LOGIN_198 {
|
||||
global:
|
||||
sd_session_get_tty;
|
||||
} LIBSYSTEMD_LOGIN_186;
|
||||
|
||||
LIBSYSTEMD_LOGIN_201 {
|
||||
global:
|
||||
sd_login_monitor_get_events;
|
||||
sd_login_monitor_get_timeout;
|
||||
} LIBSYSTEMD_LOGIN_198;
|
||||
|
||||
LIBSYSTEMD_LOGIN_202 {
|
||||
global:
|
||||
sd_pid_get_user_unit;
|
||||
sd_pid_get_machine_name;
|
||||
} LIBSYSTEMD_LOGIN_201;
|
||||
|
||||
LIBSYSTEMD_LOGIN_203 {
|
||||
global:
|
||||
sd_get_machine_names;
|
||||
} LIBSYSTEMD_LOGIN_202;
|
||||
|
||||
LIBSYSTEMD_LOGIN_205 {
|
||||
global:
|
||||
sd_pid_get_slice;
|
||||
} LIBSYSTEMD_LOGIN_203;
|
||||
|
||||
LIBSYSTEMD_LOGIN_207 {
|
||||
global:
|
||||
sd_session_get_vt;
|
||||
} LIBSYSTEMD_LOGIN_205;
|
@ -1,35 +0,0 @@
|
||||
/***
|
||||
This file is part of systemd, but is heavily based on
|
||||
glibc's libc-symbols.h.
|
||||
|
||||
Copyright (C) 1995-1998,2000-2006,2008,2009 Free Software Foundation, Inc
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define __make_section_unallocated(section_string) \
|
||||
asm (".section " section_string "\n\t.previous");
|
||||
|
||||
#define __sec_comment "\n#APP\n\t#"
|
||||
|
||||
#define link_warning(symbol, msg) \
|
||||
__make_section_unallocated (".gnu.warning." #symbol) \
|
||||
static const char __evoke_link_warning_##symbol[] \
|
||||
__attribute__ ((used, section (".gnu.warning." #symbol __sec_comment))) \
|
||||
= msg
|
||||
|
||||
#define obsolete_lib(name, lib) \
|
||||
link_warning(name, #name " was moved to libsystemd. Do not use " #lib ".")
|
@ -312,7 +312,7 @@ static int property_get_ambient_capabilities(
|
||||
return sd_bus_message_append(reply, "t", c->capability_ambient_set);
|
||||
}
|
||||
|
||||
static int property_get_capabilities(
|
||||
static int property_get_empty_string(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
@ -321,23 +321,10 @@ static int property_get_capabilities(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
ExecContext *c = userdata;
|
||||
_cleanup_cap_free_charp_ char *t = NULL;
|
||||
const char *s;
|
||||
|
||||
assert(bus);
|
||||
assert(reply);
|
||||
assert(c);
|
||||
|
||||
if (c->capabilities)
|
||||
s = t = cap_to_text(c->capabilities, NULL);
|
||||
else
|
||||
s = "";
|
||||
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
return sd_bus_message_append(reply, "s", s);
|
||||
return sd_bus_message_append(reply, "s", "");
|
||||
}
|
||||
|
||||
static int property_get_syscall_filter(
|
||||
@ -700,7 +687,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
||||
SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
@ -746,10 +746,10 @@ static int enforce_groups(const ExecContext *context, const char *username, gid_
|
||||
static int enforce_user(const ExecContext *context, uid_t uid) {
|
||||
assert(context);
|
||||
|
||||
/* Sets (but doesn't lookup) the uid and make sure we keep the
|
||||
/* Sets (but doesn't look up) the uid and make sure we keep the
|
||||
* capabilities while doing so. */
|
||||
|
||||
if (context->capabilities || context->capability_ambient_set != 0) {
|
||||
if (context->capability_ambient_set != 0) {
|
||||
|
||||
/* First step: If we need to keep capabilities but
|
||||
* drop privileges we need to make sure we keep our
|
||||
@ -761,31 +761,9 @@ static int enforce_user(const ExecContext *context, uid_t uid) {
|
||||
if (prctl(PR_SET_SECUREBITS, sb) < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
/* Second step: set the capabilities. This will reduce
|
||||
* the capabilities to the minimum we need. */
|
||||
|
||||
if (context->capabilities) {
|
||||
_cleanup_cap_free_ cap_t d = NULL;
|
||||
static const cap_value_t bits[] = {
|
||||
CAP_SETUID, /* Necessary so that we can run setresuid() below */
|
||||
CAP_SETPCAP /* Necessary so that we can set PR_SET_SECUREBITS later on */
|
||||
};
|
||||
|
||||
d = cap_dup(context->capabilities);
|
||||
if (!d)
|
||||
return -errno;
|
||||
|
||||
if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
|
||||
cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0)
|
||||
return -errno;
|
||||
|
||||
if (cap_set_proc(d) < 0)
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
/* Third step: actually set the uids */
|
||||
/* Second step: actually set the uids */
|
||||
if (setresuid(uid, uid, uid) < 0)
|
||||
return -errno;
|
||||
|
||||
@ -1874,21 +1852,6 @@ static int exec_child(
|
||||
*exit_status = EXIT_CAPABILITIES;
|
||||
return r;
|
||||
}
|
||||
|
||||
if (context->capabilities) {
|
||||
|
||||
/* The capabilities in ambient set need to be also in the inherited
|
||||
* set. If they aren't, trying to get them will fail. Add the ambient
|
||||
* set inherited capabilities to the capability set in the context.
|
||||
* This is needed because if capabilities are set (using "Capabilities="
|
||||
* keyword), they will override whatever we set now. */
|
||||
|
||||
r = capability_update_inherited_set(context->capabilities, context->capability_ambient_set);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_CAPABILITIES;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (context->user) {
|
||||
@ -1927,12 +1890,6 @@ static int exec_child(
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (context->capabilities)
|
||||
if (cap_set_proc(context->capabilities) < 0) {
|
||||
*exit_status = EXIT_CAPABILITIES;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (context->no_new_privileges)
|
||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
|
||||
*exit_status = EXIT_NO_NEW_PRIVILEGES;
|
||||
@ -2175,11 +2132,6 @@ void exec_context_done(ExecContext *c) {
|
||||
|
||||
c->pam_name = mfree(c->pam_name);
|
||||
|
||||
if (c->capabilities) {
|
||||
cap_free(c->capabilities);
|
||||
c->capabilities = NULL;
|
||||
}
|
||||
|
||||
c->read_only_dirs = strv_free(c->read_only_dirs);
|
||||
c->read_write_dirs = strv_free(c->read_write_dirs);
|
||||
c->inaccessible_dirs = strv_free(c->inaccessible_dirs);
|
||||
@ -2538,14 +2490,6 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
|
||||
prefix, strna(lvl_str));
|
||||
}
|
||||
|
||||
if (c->capabilities) {
|
||||
_cleanup_cap_free_charp_ char *t;
|
||||
|
||||
t = cap_to_text(c->capabilities, NULL);
|
||||
if (t)
|
||||
fprintf(f, "%sCapabilities: %s\n", prefix, t);
|
||||
}
|
||||
|
||||
if (c->secure_bits)
|
||||
fprintf(f, "%sSecure Bits:%s%s%s%s%s%s\n",
|
||||
prefix,
|
||||
|
@ -155,10 +155,7 @@ struct ExecContext {
|
||||
unsigned long mount_flags;
|
||||
|
||||
uint64_t capability_bounding_set;
|
||||
|
||||
uint64_t capability_ambient_set;
|
||||
|
||||
cap_t capabilities;
|
||||
int secure_bits;
|
||||
|
||||
int syslog_priority;
|
||||
|
@ -45,7 +45,7 @@ $1.SyslogIdentifier, config_parse_unit_string_printf, 0,
|
||||
$1.SyslogFacility, config_parse_log_facility, 0, offsetof($1, exec_context.syslog_priority)
|
||||
$1.SyslogLevel, config_parse_log_level, 0, offsetof($1, exec_context.syslog_priority)
|
||||
$1.SyslogLevelPrefix, config_parse_bool, 0, offsetof($1, exec_context.syslog_level_prefix)
|
||||
$1.Capabilities, config_parse_exec_capabilities, 0, offsetof($1, exec_context)
|
||||
$1.Capabilities, config_parse_warn_compat, DISABLED_LEGACY, offsetof($1, exec_context)
|
||||
$1.SecureBits, config_parse_exec_secure_bits, 0, offsetof($1, exec_context)
|
||||
$1.CapabilityBoundingSet, config_parse_capability_set, 0, offsetof($1, exec_context.capability_bounding_set)
|
||||
$1.AmbientCapabilities, config_parse_capability_set, 0, offsetof($1, exec_context.capability_ambient_set)
|
||||
|
@ -951,38 +951,6 @@ int config_parse_exec_cpu_affinity(const char *unit,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_exec_capabilities(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
ExecContext *c = data;
|
||||
cap_t cap;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
cap = cap_from_text(rvalue);
|
||||
if (!cap) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse capabilities, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (c->capabilities)
|
||||
cap_free(c->capabilities);
|
||||
c->capabilities = cap;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_exec_secure_bits(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -3797,7 +3765,6 @@ void unit_dump_config_items(FILE *f) {
|
||||
{ config_parse_input, "INPUT" },
|
||||
{ config_parse_log_facility, "FACILITY" },
|
||||
{ config_parse_log_level, "LEVEL" },
|
||||
{ config_parse_exec_capabilities, "CAPABILITIES" },
|
||||
{ config_parse_exec_secure_bits, "SECUREBITS" },
|
||||
{ config_parse_capability_set, "BOUNDINGSET" },
|
||||
{ config_parse_limit, "LIMIT" },
|
||||
|
@ -52,7 +52,6 @@ int config_parse_exec_io_priority(const char *unit, const char *filename, unsign
|
||||
int config_parse_exec_cpu_sched_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_exec_cpu_sched_prio(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_exec_cpu_affinity(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_exec_capabilities(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_exec_secure_bits(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_capability_set(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
@ -1,73 +0,0 @@
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2014 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <ftw.h>
|
||||
|
||||
#include "aufs-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "string-util.h"
|
||||
#include "util.h"
|
||||
|
||||
static int nftw_cb(
|
||||
const char *fpath,
|
||||
const struct stat *sb,
|
||||
int flag,
|
||||
struct FTW *ftwbuf) {
|
||||
|
||||
const char *fn, *original;
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
fn = fpath + ftwbuf->base;
|
||||
|
||||
/* We remove all whiteout files, and all whiteouts */
|
||||
|
||||
original = startswith(fn, ".wh.");
|
||||
if (!original)
|
||||
return FTW_CONTINUE;
|
||||
|
||||
log_debug("Removing whiteout indicator %s.", fpath);
|
||||
r = rm_rf(fpath, REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
if (r < 0)
|
||||
return FTW_STOP;
|
||||
|
||||
if (!startswith(fn, ".wh..wh.")) {
|
||||
|
||||
p = alloca(ftwbuf->base + strlen(original));
|
||||
strcpy(mempcpy(p, fpath, ftwbuf->base), original);
|
||||
|
||||
log_debug("Removing deleted file %s.", p);
|
||||
r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
if (r < 0)
|
||||
return FTW_STOP;
|
||||
}
|
||||
|
||||
return FTW_CONTINUE;
|
||||
}
|
||||
|
||||
int aufs_resolve(const char *path) {
|
||||
int r;
|
||||
|
||||
errno = 0;
|
||||
r = nftw(path, nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
|
||||
if (r == FTW_STOP)
|
||||
return errno > 0 ? -errno : -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2014 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
int aufs_resolve(const char *path);
|
@ -36,7 +36,7 @@
|
||||
#define RC_LOCAL_SCRIPT_PATH_STOP "/sbin/halt.local"
|
||||
#endif
|
||||
|
||||
const char *arg_dest = "/tmp";
|
||||
static const char *arg_dest = "/tmp";
|
||||
|
||||
static int add_symlink(const char *service, const char *where) {
|
||||
_cleanup_free_ char *from = NULL, *to = NULL;
|
||||
|
@ -70,7 +70,7 @@ static const struct {
|
||||
UP must be read before DOWN */
|
||||
};
|
||||
|
||||
const char *arg_dest = "/tmp";
|
||||
static const char *arg_dest = "/tmp";
|
||||
|
||||
typedef struct SysvStub {
|
||||
char *name;
|
||||
|
@ -1,202 +0,0 @@
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2014 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "json.h"
|
||||
#include "string-util.h"
|
||||
#include "util.h"
|
||||
|
||||
static void test_one(const char *data, ...) {
|
||||
void *state = NULL;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, data);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
union json_value v = {};
|
||||
int t, tt;
|
||||
|
||||
t = json_tokenize(&data, &str, &v, &state, NULL);
|
||||
tt = va_arg(ap, int);
|
||||
|
||||
assert_se(t == tt);
|
||||
|
||||
if (t == JSON_END || t < 0)
|
||||
break;
|
||||
|
||||
else if (t == JSON_STRING) {
|
||||
const char *nn;
|
||||
|
||||
nn = va_arg(ap, const char *);
|
||||
assert_se(streq_ptr(nn, str));
|
||||
|
||||
} else if (t == JSON_REAL) {
|
||||
double d;
|
||||
|
||||
d = va_arg(ap, double);
|
||||
assert_se(fabs(d - v.real) < 0.001);
|
||||
|
||||
} else if (t == JSON_INTEGER) {
|
||||
intmax_t i;
|
||||
|
||||
i = va_arg(ap, intmax_t);
|
||||
assert_se(i == v.integer);
|
||||
|
||||
} else if (t == JSON_BOOLEAN) {
|
||||
bool b;
|
||||
|
||||
b = va_arg(ap, int);
|
||||
assert_se(b == v.boolean);
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
typedef void (*Test)(JsonVariant *);
|
||||
|
||||
static void test_file(const char *data, Test test) {
|
||||
_cleanup_json_variant_unref_ JsonVariant *v = NULL;
|
||||
int r;
|
||||
|
||||
r = json_parse(data, &v);
|
||||
assert_se(r == 0);
|
||||
assert_se(v != NULL);
|
||||
assert_se(v->type == JSON_VARIANT_OBJECT);
|
||||
|
||||
if (test)
|
||||
test(v);
|
||||
}
|
||||
|
||||
static void test_1(JsonVariant *v) {
|
||||
JsonVariant *p, *q;
|
||||
unsigned i;
|
||||
|
||||
/* 3 keys + 3 values */
|
||||
assert_se(v->size == 6);
|
||||
|
||||
/* has k */
|
||||
p = json_variant_value(v, "k");
|
||||
assert_se(p && p->type == JSON_VARIANT_STRING);
|
||||
|
||||
/* k equals v */
|
||||
assert_se(streq(json_variant_string(p), "v"));
|
||||
|
||||
/* has foo */
|
||||
p = json_variant_value(v, "foo");
|
||||
assert_se(p && p->type == JSON_VARIANT_ARRAY && p->size == 3);
|
||||
|
||||
/* check foo[0] = 1, foo[1] = 2, foo[2] = 3 */
|
||||
for (i = 0; i < 3; ++i) {
|
||||
q = json_variant_element(p, i);
|
||||
assert_se(q && q->type == JSON_VARIANT_INTEGER && json_variant_integer(q) == (i+1));
|
||||
}
|
||||
|
||||
/* has bar */
|
||||
p = json_variant_value(v, "bar");
|
||||
assert_se(p && p->type == JSON_VARIANT_OBJECT && p->size == 2);
|
||||
|
||||
/* zap is null */
|
||||
q = json_variant_value(p, "zap");
|
||||
assert_se(q && q->type == JSON_VARIANT_NULL);
|
||||
}
|
||||
|
||||
static void test_2(JsonVariant *v) {
|
||||
JsonVariant *p, *q;
|
||||
|
||||
/* 2 keys + 2 values */
|
||||
assert_se(v->size == 4);
|
||||
|
||||
/* has mutant */
|
||||
p = json_variant_value(v, "mutant");
|
||||
assert_se(p && p->type == JSON_VARIANT_ARRAY && p->size == 4);
|
||||
|
||||
/* mutant[0] == 1 */
|
||||
q = json_variant_element(p, 0);
|
||||
assert_se(q && q->type == JSON_VARIANT_INTEGER && json_variant_integer(q) == 1);
|
||||
|
||||
/* mutant[1] == null */
|
||||
q = json_variant_element(p, 1);
|
||||
assert_se(q && q->type == JSON_VARIANT_NULL);
|
||||
|
||||
/* mutant[2] == "1" */
|
||||
q = json_variant_element(p, 2);
|
||||
assert_se(q && q->type == JSON_VARIANT_STRING && streq(json_variant_string(q), "1"));
|
||||
|
||||
/* mutant[3] == JSON_VARIANT_OBJECT */
|
||||
q = json_variant_element(p, 3);
|
||||
assert_se(q && q->type == JSON_VARIANT_OBJECT && q->size == 2);
|
||||
|
||||
/* has 1 */
|
||||
p = json_variant_value(q, "1");
|
||||
assert_se(p && p->type == JSON_VARIANT_ARRAY && p->size == 2);
|
||||
|
||||
/* "1"[0] == 1 */
|
||||
q = json_variant_element(p, 0);
|
||||
assert_se(q && q->type == JSON_VARIANT_INTEGER && json_variant_integer(q) == 1);
|
||||
|
||||
/* "1"[1] == "1" */
|
||||
q = json_variant_element(p, 1);
|
||||
assert_se(q && q->type == JSON_VARIANT_STRING && streq(json_variant_string(q), "1"));
|
||||
|
||||
/* has blah */
|
||||
p = json_variant_value(v, "blah");
|
||||
assert_se(p && p->type == JSON_VARIANT_REAL && fabs(json_variant_real(p) - 1.27) < 0.001);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
test_one("x", -EINVAL);
|
||||
test_one("", JSON_END);
|
||||
test_one(" ", JSON_END);
|
||||
test_one("0", JSON_INTEGER, (intmax_t) 0, JSON_END);
|
||||
test_one("1234", JSON_INTEGER, (intmax_t) 1234, JSON_END);
|
||||
test_one("3.141", JSON_REAL, 3.141, JSON_END);
|
||||
test_one("0.0", JSON_REAL, 0.0, JSON_END);
|
||||
test_one("7e3", JSON_REAL, 7e3, JSON_END);
|
||||
test_one("-7e-3", JSON_REAL, -7e-3, JSON_END);
|
||||
test_one("true", JSON_BOOLEAN, true, JSON_END);
|
||||
test_one("false", JSON_BOOLEAN, false, JSON_END);
|
||||
test_one("null", JSON_NULL, JSON_END);
|
||||
test_one("{}", JSON_OBJECT_OPEN, JSON_OBJECT_CLOSE, JSON_END);
|
||||
test_one("\t {\n} \n", JSON_OBJECT_OPEN, JSON_OBJECT_CLOSE, JSON_END);
|
||||
test_one("[]", JSON_ARRAY_OPEN, JSON_ARRAY_CLOSE, JSON_END);
|
||||
test_one("\t [] \n\n", JSON_ARRAY_OPEN, JSON_ARRAY_CLOSE, JSON_END);
|
||||
test_one("\"\"", JSON_STRING, "", JSON_END);
|
||||
test_one("\"foo\"", JSON_STRING, "foo", JSON_END);
|
||||
test_one("\"foo\\nfoo\"", JSON_STRING, "foo\nfoo", JSON_END);
|
||||
test_one("{\"foo\" : \"bar\"}", JSON_OBJECT_OPEN, JSON_STRING, "foo", JSON_COLON, JSON_STRING, "bar", JSON_OBJECT_CLOSE, JSON_END);
|
||||
test_one("{\"foo\" : [true, false]}", JSON_OBJECT_OPEN, JSON_STRING, "foo", JSON_COLON, JSON_ARRAY_OPEN, JSON_BOOLEAN, true, JSON_COMMA, JSON_BOOLEAN, false, JSON_ARRAY_CLOSE, JSON_OBJECT_CLOSE, JSON_END);
|
||||
test_one("\"\xef\xbf\xbd\"", JSON_STRING, "\xef\xbf\xbd", JSON_END);
|
||||
test_one("\"\\ufffd\"", JSON_STRING, "\xef\xbf\xbd", JSON_END);
|
||||
test_one("\"\\uf\"", -EINVAL);
|
||||
test_one("\"\\ud800a\"", -EINVAL);
|
||||
test_one("\"\\udc00\\udc00\"", -EINVAL);
|
||||
test_one("\"\\ud801\\udc37\"", JSON_STRING, "\xf0\x90\x90\xb7", JSON_END);
|
||||
|
||||
test_one("[1, 2]", JSON_ARRAY_OPEN, JSON_INTEGER, (intmax_t) 1, JSON_COMMA, JSON_INTEGER, (intmax_t) 2, JSON_ARRAY_CLOSE, JSON_END);
|
||||
|
||||
test_file("{\"k\": \"v\", \"foo\": [1, 2, 3], \"bar\": {\"zap\": null}}", test_1);
|
||||
test_file("{\"mutant\": [1, null, \"1\", {\"1\": [1, \"1\"]}], \"blah\": 1.27}", test_2);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user