1
0
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:
Zbigniew Jędrzejewski-Szmek 2016-02-13 10:36:02 -05:00
commit 06e948901a
37 changed files with 37 additions and 1993 deletions

9
.gitignore vendored
View File

@ -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

View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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}

View File

@ -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>

View File

@ -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>

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -1 +0,0 @@
../Makefile

View File

@ -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, \
}

View File

@ -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,

View File

@ -1 +0,0 @@
/libsystemd-*.pc

View File

@ -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}

View File

@ -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:
*;
};

View File

@ -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}

View File

@ -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:
*;
};

View File

@ -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}

View File

@ -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;

View File

@ -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}

View File

@ -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;

View File

@ -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 ".")

View File

@ -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),

View File

@ -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,

View File

@ -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;

View File

@ -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)

View File

@ -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" },

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}