1
0
mirror of https://github.com/systemd/systemd synced 2026-04-07 15:44:49 +02:00

Compare commits

..

No commits in common. "21d00e52db110f4413299849330e824ab7f6e558" and "e92777d275a7f8f05bbc39a25660ee493aa52095" have entirely different histories.

26 changed files with 198 additions and 385 deletions

View File

@ -371,16 +371,6 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>systemd.getty_auto=</varname></term>
<listitem>
<para>Configures whether the <filename>serial-getty@.service</filename> will run.
For details, see
<citerefentry><refentrytitle>systemd-getty-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>systemd.gpt_auto=</varname></term> <term><varname>systemd.gpt_auto=</varname></term>
<term><varname>rd.systemd.gpt_auto=</varname></term> <term><varname>rd.systemd.gpt_auto=</varname></term>
@ -551,7 +541,6 @@
<citerefentry><refentrytitle>systemd-cryptsetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-cryptsetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-veritysetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-veritysetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-getty-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-volatile-root.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-volatile-root.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-modules-load.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-modules-load.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,

View File

@ -53,43 +53,10 @@
Elsewhere)</ulink>.</para> Elsewhere)</ulink>.</para>
</refsect1> </refsect1>
<refsect1>
<title>Kernel Command Line</title>
<para><filename>systemd-getty-generator</filename> understands the following
<citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry>
parameters:</para>
<variablelist class='kernel-commandline-options'>
<varlistentry>
<term><varname>systemd.getty_auto=</varname></term>
<listitem><para>this options take an optional boolean argument, and default to yes.
The generator is enabled by default, and a false value may be used to disable it.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Environment</title>
<variablelist class='environment-variables'>
<varlistentry>
<term><varname>$SYSTEMD_GETTY_AUTO</varname></term>
<listitem><para>This variable takes an optional boolean argument, and default to yes.
The generator is enabled by default, and a false value may be used to disable it.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1> <refsect1>
<title>See Also</title> <title>See Also</title>
<para> <para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>agetty</refentrytitle><manvolnum>8</manvolnum></citerefentry> <citerefentry project='man-pages'><refentrytitle>agetty</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para> </para>
</refsect1> </refsect1>

View File

@ -1011,77 +1011,3 @@ int parse_cifs_service(
return 0; return 0;
} }
int open_mkdir_at(int dirfd, const char *path, int flags, mode_t mode) {
_cleanup_close_ int fd = -1, parent_fd = -1;
_cleanup_free_ char *fname = NULL;
bool made;
int r;
/* Creates a directory with mkdirat() and then opens it, in the "most atomic" fashion we can
* do. Guarantees that the returned fd refers to a directory. If O_EXCL is specified will fail if the
* dir already exists. Otherwise will open an existing dir, but only if it is one. */
if (flags & ~(O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_EXCL|O_NOATIME|O_NOFOLLOW|O_PATH))
return -EINVAL;
if ((flags & O_ACCMODE) != O_RDONLY)
return -EINVAL;
/* Note that O_DIRECTORY|O_NOFOLLOW is implied, but we allow specifying it anyway. The following
* flags actually make sense to specify: O_CLOEXEC, O_EXCL, O_NOATIME, O_PATH */
if (isempty(path))
return -EINVAL;
if (!filename_is_valid(path)) {
_cleanup_free_ char *parent = NULL;
/* If this is not a valid filename, it's a path. Let's open the parent directory then, so
* that we can pin it, and operate below it. */
r = path_extract_directory(path, &parent);
if (r < 0)
return r;
r = path_extract_filename(path, &fname);
if (r < 0)
return r;
parent_fd = openat(dirfd, parent, O_PATH|O_DIRECTORY|O_CLOEXEC);
if (parent_fd < 0)
return -errno;
dirfd = parent_fd;
path = fname;
}
r = RET_NERRNO(mkdirat(dirfd, path, mode));
if (r == -EEXIST) {
if (FLAGS_SET(flags, O_EXCL))
return -EEXIST;
made = false;
} else if (r < 0)
return r;
else
made = true;
fd = RET_NERRNO(openat(dirfd, path, (flags & ~O_EXCL)|O_DIRECTORY|O_NOFOLLOW));
if (fd < 0) {
if (fd == -ENOENT) /* We got ENOENT? then someone else immediately removed it after we
* created it. In that case let's return immediately without unlinking
* anything, because there simply isn't anything to unlink anymore. */
return -ENOENT;
if (fd == -ELOOP) /* is a symlink? exists already → created by someone else, don't unlink */
return -EEXIST;
if (fd == -ENOTDIR) /* not a directory? exists already → created by someone else, don't unlink */
return -EEXIST;
if (made)
(void) unlinkat(dirfd, path, AT_REMOVEDIR);
return fd;
}
return TAKE_FD(fd);
}

View File

@ -108,5 +108,3 @@ static inline int conservative_rename(const char *oldpath, const char *newpath)
int posix_fallocate_loop(int fd, uint64_t offset, uint64_t size); int posix_fallocate_loop(int fd, uint64_t offset, uint64_t size);
int parse_cifs_service(const char *s, char **ret_host, char **ret_service, char **ret_path); int parse_cifs_service(const char *s, char **ret_host, char **ret_service, char **ret_path);
int open_mkdir_at(int dirfd, const char *path, int flags, mode_t mode);

View File

@ -2499,7 +2499,6 @@ int temporary_filesystem_add(
static int make_tmp_prefix(const char *prefix) { static int make_tmp_prefix(const char *prefix) {
_cleanup_free_ char *t = NULL; _cleanup_free_ char *t = NULL;
_cleanup_close_ int fd = -1;
int r; int r;
/* Don't do anything unless we know the dir is actually missing */ /* Don't do anything unless we know the dir is actually missing */
@ -2518,20 +2517,18 @@ static int make_tmp_prefix(const char *prefix) {
if (r < 0) if (r < 0)
return r; return r;
/* umask will corrupt this access mode, but that doesn't matter, we need to call chmod() anyway for if (mkdir(t, 0777) < 0) /* umask will corrupt this access mode, but that doesn't matter, we need to
* the suid bit, below. */ * call chmod() anyway for the suid bit, below. */
fd = open_mkdir_at(AT_FDCWD, t, O_EXCL|O_CLOEXEC, 0777); return -errno;
if (fd < 0)
return fd;
r = RET_NERRNO(fchmod(fd, 01777)); if (chmod(t, 01777) < 0) {
if (r < 0) { r = -errno;
(void) rmdir(t); (void) rmdir(t);
return r; return r;
} }
r = RET_NERRNO(rename(t, prefix)); if (rename(t, prefix) < 0) {
if (r < 0) { r = -errno;
(void) rmdir(t); (void) rmdir(t);
return r == -EEXIST ? 0 : r; /* it's fine if someone else created the dir by now */ return r == -EEXIST ? 0 : r; /* it's fine if someone else created the dir by now */
} }

View File

@ -200,7 +200,7 @@ _public_ int cryptsetup_token_validate(
} }
JSON_VARIANT_ARRAY_FOREACH(e, w) { JSON_VARIANT_ARRAY_FOREACH(e, w) {
uint64_t u; uintmax_t u;
if (!json_variant_is_number(e)) { if (!json_variant_is_number(e)) {
crypt_log_debug(cd, "TPM2 PCR is not a number."); crypt_log_debug(cd, "TPM2 PCR is not a number.");

View File

@ -78,7 +78,7 @@ int parse_luks2_tpm2_data(
return -EINVAL; return -EINVAL;
JSON_VARIANT_ARRAY_FOREACH(e, w) { JSON_VARIANT_ARRAY_FOREACH(e, w) {
uint64_t u; uintmax_t u;
if (!json_variant_is_number(e)) if (!json_variant_is_number(e))
return -EINVAL; return -EINVAL;

View File

@ -116,7 +116,7 @@ int find_tpm2_auto_data(
assert(pcr_mask == 0); assert(pcr_mask == 0);
JSON_VARIANT_ARRAY_FOREACH(e, w) { JSON_VARIANT_ARRAY_FOREACH(e, w) {
uint64_t u; uintmax_t u;
if (!json_variant_is_number(e)) if (!json_variant_is_number(e))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),

View File

@ -11,10 +11,8 @@
#include "generator.h" #include "generator.h"
#include "log.h" #include "log.h"
#include "mkdir-label.h" #include "mkdir-label.h"
#include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "process-util.h" #include "process-util.h"
#include "proc-cmdline.h"
#include "strv.h" #include "strv.h"
#include "terminal-util.h" #include "terminal-util.h"
#include "unit-name.h" #include "unit-name.h"
@ -22,7 +20,6 @@
#include "virt.h" #include "virt.h"
static const char *arg_dest = NULL; static const char *arg_dest = NULL;
static bool arg_enabled = true;
static int add_symlink(const char *fservice, const char *tservice) { static int add_symlink(const char *fservice, const char *tservice) {
char *from, *to; char *from, *to;
@ -142,48 +139,11 @@ static int run_container(void) {
} }
} }
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
int r;
assert(key);
if (proc_cmdline_key_streq(key, "systemd.getty_auto")) {
r = value ? parse_boolean(value) : 1;
if (r < 0)
log_warning_errno(r, "Failed to parse getty_auto switch \"%s\", ignoring: %m", value);
else
arg_enabled = r;
}
return 0;
}
static int run(const char *dest, const char *dest_early, const char *dest_late) { static int run(const char *dest, const char *dest_early, const char *dest_late) {
_cleanup_free_ char *getty_auto = NULL;
int r; int r;
assert_se(arg_dest = dest); assert_se(arg_dest = dest);
r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
r = getenv_for_pid(1, "SYSTEMD_GETTY_AUTO", &getty_auto);
if (r < 0)
log_warning_errno(r, "Failed to parse $SYSTEMD_GETTY_AUTO environment variable, ignoring: %m");
else if (r > 0) {
r = parse_boolean(getty_auto);
if (r < 0)
log_warning_errno(r, "Failed to parse $SYSTEMD_GETTY_AUTO value \"%s\", ignoring: %m", getty_auto);
else
arg_enabled = r;
}
if (!arg_enabled) {
log_debug("Disabled, exiting.");
return 0;
}
if (detect_container() > 0) if (detect_container() > 0)
/* Add console shell and look at $container_ttys, but don't do add any /* Add console shell and look at $container_ttys, but don't do add any
* further magic if we are in a container. */ * further magic if we are in a container. */

View File

@ -837,7 +837,7 @@ static int update_last_change(JsonVariant **v, bool with_password, bool override
c = json_variant_by_key(*v, "lastChangeUSec"); c = json_variant_by_key(*v, "lastChangeUSec");
if (c) { if (c) {
uint64_t u; uintmax_t u;
if (!override) if (!override)
goto update_password; goto update_password;
@ -860,7 +860,7 @@ update_password:
c = json_variant_by_key(*v, "lastPasswordChangeUSec"); c = json_variant_by_key(*v, "lastPasswordChangeUSec");
if (c) { if (c) {
uint64_t u; uintmax_t u;
if (!override) if (!override)
return 0; return 0;

View File

@ -127,17 +127,15 @@ int home_setup_cifs(
return log_oom(); return log_oom();
if (FLAGS_SET(flags, HOME_SETUP_CIFS_MKDIR)) { if (FLAGS_SET(flags, HOME_SETUP_CIFS_MKDIR)) {
setup->root_fd = open_mkdir_at(AT_FDCWD, j, O_CLOEXEC, 0700); r = mkdir_p(j, 0700);
if (setup->root_fd < 0) if (r < 0)
return log_error_errno(setup->root_fd, "Failed to create CIFS subdirectory: %m"); return log_error_errno(r, "Failed to create CIFS subdirectory: %m");
} }
} }
if (setup->root_fd < 0) {
setup->root_fd = open(j ?: HOME_RUNTIME_WORK_DIR, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); setup->root_fd = open(j ?: HOME_RUNTIME_WORK_DIR, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
if (setup->root_fd < 0) if (setup->root_fd < 0)
return log_error_errno(errno, "Failed to open home directory: %m"); return log_error_errno(errno, "Failed to open home directory: %m");
}
setup->mount_suffix = TAKE_PTR(cdir); setup->mount_suffix = TAKE_PTR(cdir);
return 0; return 0;

View File

@ -133,9 +133,9 @@ static int dump_link_description(char **patterns) {
return log_oom(); return log_oom();
JSON_VARIANT_ARRAY_FOREACH(i, json_variant_by_key(v, "Interfaces")) { JSON_VARIANT_ARRAY_FOREACH(i, json_variant_by_key(v, "Interfaces")) {
char ifindex_str[DECIMAL_STR_MAX(int64_t)]; char ifindex_str[DECIMAL_STR_MAX(intmax_t)];
const char *name; const char *name;
int64_t index; intmax_t index;
size_t pos; size_t pos;
name = json_variant_string(json_variant_by_key(i, "Name")); name = json_variant_string(json_variant_by_key(i, "Name"));

View File

@ -94,7 +94,7 @@ int link_build_json(Link *link, JsonVariant **ret) {
} }
static int link_json_compare(JsonVariant * const *a, JsonVariant * const *b) { static int link_json_compare(JsonVariant * const *a, JsonVariant * const *b) {
int64_t index_a, index_b; intmax_t index_a, index_b;
assert(a && *a); assert(a && *a);
assert(b && *b); assert(b && *b);

View File

@ -99,7 +99,7 @@ static int oci_terminal(const char *name, JsonVariant *v, JsonDispatchFlags flag
static int oci_console_dimension(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { static int oci_console_dimension(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
unsigned *u = userdata; unsigned *u = userdata;
uint64_t k; uintmax_t k;
assert(u); assert(u);
@ -226,7 +226,7 @@ static int oci_rlimit_value(const char *name, JsonVariant *v, JsonDispatchFlags
z = (rlim_t) json_variant_unsigned(v); z = (rlim_t) json_variant_unsigned(v);
if ((uint64_t) z != json_variant_unsigned(v)) if ((uintmax_t) z != json_variant_unsigned(v))
return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL),
"rlimits limit out of range, refusing."); "rlimits limit out of range, refusing.");
} }
@ -346,7 +346,7 @@ static int oci_capabilities(const char *name, JsonVariant *v, JsonDispatchFlags
static int oci_oom_score_adj(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { static int oci_oom_score_adj(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
Settings *s = userdata; Settings *s = userdata;
int64_t k; intmax_t k;
assert(s); assert(s);
@ -363,14 +363,14 @@ static int oci_oom_score_adj(const char *name, JsonVariant *v, JsonDispatchFlags
static int oci_uid_gid(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { static int oci_uid_gid(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
uid_t *uid = userdata, u; uid_t *uid = userdata, u;
uint64_t k; uintmax_t k;
assert(uid); assert(uid);
assert_cc(sizeof(uid_t) == sizeof(gid_t)); assert_cc(sizeof(uid_t) == sizeof(gid_t));
k = json_variant_unsigned(v); k = json_variant_unsigned(v);
u = (uid_t) k; u = (uid_t) k;
if ((uint64_t) u != k) if ((uintmax_t) u != k)
return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL),
"UID/GID out of range: %ji", k); "UID/GID out of range: %ji", k);
@ -698,7 +698,7 @@ static int oci_namespaces(const char *name, JsonVariant *v, JsonDispatchFlags fl
static int oci_uid_gid_range(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { static int oci_uid_gid_range(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
uid_t *uid = userdata, u; uid_t *uid = userdata, u;
uint64_t k; uintmax_t k;
assert(uid); assert(uid);
assert_cc(sizeof(uid_t) == sizeof(gid_t)); assert_cc(sizeof(uid_t) == sizeof(gid_t));
@ -709,7 +709,7 @@ static int oci_uid_gid_range(const char *name, JsonVariant *v, JsonDispatchFlags
k = json_variant_unsigned(v); k = json_variant_unsigned(v);
u = (uid_t) k; u = (uid_t) k;
if ((uint64_t) u != k) if ((uintmax_t) u != k)
return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE),
"UID/GID out of range: %ji", k); "UID/GID out of range: %ji", k);
if (u == 0) if (u == 0)
@ -803,7 +803,7 @@ static int oci_device_type(const char *name, JsonVariant *v, JsonDispatchFlags f
static int oci_device_major(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { static int oci_device_major(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
unsigned *u = userdata; unsigned *u = userdata;
uint64_t k; uintmax_t k;
assert_se(u); assert_se(u);
@ -818,7 +818,7 @@ static int oci_device_major(const char *name, JsonVariant *v, JsonDispatchFlags
static int oci_device_minor(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { static int oci_device_minor(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
unsigned *u = userdata; unsigned *u = userdata;
uint64_t k; uintmax_t k;
assert_se(u); assert_se(u);
@ -833,14 +833,14 @@ static int oci_device_minor(const char *name, JsonVariant *v, JsonDispatchFlags
static int oci_device_file_mode(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { static int oci_device_file_mode(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
mode_t *mode = userdata, m; mode_t *mode = userdata, m;
uint64_t k; uintmax_t k;
assert(mode); assert(mode);
k = json_variant_unsigned(v); k = json_variant_unsigned(v);
m = (mode_t) k; m = (mode_t) k;
if ((m & ~07777) != 0 || (uint64_t) m != k) if ((m & ~07777) != 0 || (uintmax_t) m != k)
return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE),
"fileMode out of range, refusing."); "fileMode out of range, refusing.");
@ -1175,7 +1175,7 @@ static int oci_cgroup_devices(const char *name, JsonVariant *v, JsonDispatchFlag
static int oci_cgroup_memory_limit(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { static int oci_cgroup_memory_limit(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
uint64_t *m = userdata; uint64_t *m = userdata;
uint64_t k; uintmax_t k;
assert(m); assert(m);
@ -1275,7 +1275,7 @@ struct cpu_data {
static int oci_cgroup_cpu_shares(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { static int oci_cgroup_cpu_shares(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
uint64_t *u = userdata; uint64_t *u = userdata;
uint64_t k; uintmax_t k;
assert(u); assert(u);
@ -1290,7 +1290,7 @@ static int oci_cgroup_cpu_shares(const char *name, JsonVariant *v, JsonDispatchF
static int oci_cgroup_cpu_quota(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { static int oci_cgroup_cpu_quota(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
uint64_t *u = userdata; uint64_t *u = userdata;
uint64_t k; uintmax_t k;
assert(u); assert(u);
@ -1382,7 +1382,7 @@ static int oci_cgroup_cpu(const char *name, JsonVariant *v, JsonDispatchFlags fl
static int oci_cgroup_block_io_weight(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { static int oci_cgroup_block_io_weight(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
Settings *s = userdata; Settings *s = userdata;
uint64_t k; uintmax_t k;
int r; int r;
assert(s); assert(s);
@ -1414,17 +1414,17 @@ static int oci_cgroup_block_io_weight_device(const char *name, JsonVariant *v, J
struct device_data { struct device_data {
unsigned major; unsigned major;
unsigned minor; unsigned minor;
uint64_t weight; uintmax_t weight;
} data = { } data = {
.major = UINT_MAX, .major = UINT_MAX,
.minor = UINT_MAX, .minor = UINT_MAX,
.weight = UINT64_MAX, .weight = UINTMAX_MAX,
}; };
static const JsonDispatch table[] = { static const JsonDispatch table[] = {
{ "major", JSON_VARIANT_UNSIGNED, oci_device_major, offsetof(struct device_data, major), JSON_MANDATORY }, { "major", JSON_VARIANT_UNSIGNED, oci_device_major, offsetof(struct device_data, major), JSON_MANDATORY },
{ "minor", JSON_VARIANT_UNSIGNED, oci_device_minor, offsetof(struct device_data, minor), JSON_MANDATORY }, { "minor", JSON_VARIANT_UNSIGNED, oci_device_minor, offsetof(struct device_data, minor), JSON_MANDATORY },
{ "weight", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(struct device_data, weight), 0 }, { "weight", JSON_VARIANT_UNSIGNED, json_dispatch_uintmax, offsetof(struct device_data, weight), 0 },
{ "leafWeight", JSON_VARIANT_INTEGER, oci_unsupported, 0, JSON_PERMISSIVE }, { "leafWeight", JSON_VARIANT_INTEGER, oci_unsupported, 0, JSON_PERMISSIVE },
{} {}
}; };
@ -1435,7 +1435,7 @@ static int oci_cgroup_block_io_weight_device(const char *name, JsonVariant *v, J
if (r < 0) if (r < 0)
return r; return r;
if (data.weight == UINT64_MAX) if (data.weight == UINTMAX_MAX)
continue; continue;
if (data.weight < CGROUP_BLKIO_WEIGHT_MIN || data.weight > CGROUP_BLKIO_WEIGHT_MAX) if (data.weight < CGROUP_BLKIO_WEIGHT_MIN || data.weight > CGROUP_BLKIO_WEIGHT_MAX)
@ -1475,7 +1475,7 @@ static int oci_cgroup_block_io_throttle(const char *name, JsonVariant *v, JsonDi
struct device_data { struct device_data {
unsigned major; unsigned major;
unsigned minor; unsigned minor;
uint64_t rate; uintmax_t rate;
} data = { } data = {
.major = UINT_MAX, .major = UINT_MAX,
.minor = UINT_MAX, .minor = UINT_MAX,
@ -1484,7 +1484,7 @@ static int oci_cgroup_block_io_throttle(const char *name, JsonVariant *v, JsonDi
static const JsonDispatch table[] = { static const JsonDispatch table[] = {
{ "major", JSON_VARIANT_UNSIGNED, oci_device_major, offsetof(struct device_data, major), JSON_MANDATORY }, { "major", JSON_VARIANT_UNSIGNED, oci_device_major, offsetof(struct device_data, major), JSON_MANDATORY },
{ "minor", JSON_VARIANT_UNSIGNED, oci_device_minor, offsetof(struct device_data, minor), JSON_MANDATORY }, { "minor", JSON_VARIANT_UNSIGNED, oci_device_minor, offsetof(struct device_data, minor), JSON_MANDATORY },
{ "rate", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(struct device_data, rate), JSON_MANDATORY }, { "rate", JSON_VARIANT_UNSIGNED, json_dispatch_uintmax, offsetof(struct device_data, rate), JSON_MANDATORY },
{} {}
}; };
@ -1557,7 +1557,7 @@ static int oci_cgroup_pids(const char *name, JsonVariant *v, JsonDispatchFlags f
m = (uint64_t) json_variant_unsigned(k); m = (uint64_t) json_variant_unsigned(k);
if ((uint64_t) m != json_variant_unsigned(k)) if ((uintmax_t) m != json_variant_unsigned(k))
return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL),
"pids limit out of range, refusing."); "pids limit out of range, refusing.");
} }
@ -2097,7 +2097,7 @@ static int oci_linux(const char *name, JsonVariant *v, JsonDispatchFlags flags,
static int oci_hook_timeout(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { static int oci_hook_timeout(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
usec_t *u = userdata; usec_t *u = userdata;
uint64_t k; uintmax_t k;
k = json_variant_unsigned(v); k = json_variant_unsigned(v);
if (k == 0 || k > (UINT64_MAX-1)/USEC_PER_SEC) if (k == 0 || k > (UINT64_MAX-1)/USEC_PER_SEC)

View File

@ -82,7 +82,7 @@ static uint32_t ifindex_to_scopeid(int family, const void *a, int ifindex) {
static int json_dispatch_ifindex(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { static int json_dispatch_ifindex(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
int *ifi = userdata; int *ifi = userdata;
int64_t t; intmax_t t;
assert(variant); assert(variant);
assert(ifi); assert(ifi);
@ -100,7 +100,7 @@ static int json_dispatch_ifindex(const char *name, JsonVariant *variant, JsonDis
static int json_dispatch_family(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { static int json_dispatch_family(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
int *family = userdata; int *family = userdata;
int64_t t; intmax_t t;
assert(variant); assert(variant);
assert(family); assert(family);
@ -160,7 +160,7 @@ static int json_dispatch_address(const char *name, JsonVariant *variant, JsonDis
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is array of unexpected size.", strna(name)); return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is array of unexpected size.", strna(name));
JSON_VARIANT_ARRAY_FOREACH(i, variant) { JSON_VARIANT_ARRAY_FOREACH(i, variant) {
int64_t b; intmax_t b;
if (!json_variant_is_integer(i)) if (!json_variant_is_integer(i))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Element %zu of JSON field '%s' is not an integer.", k, strna(name)); return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Element %zu of JSON field '%s' is not an integer.", k, strna(name));

View File

@ -364,7 +364,7 @@ static int json_dispatch_address(const char *name, JsonVariant *variant, JsonDis
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is array of unexpected size.", strna(name)); return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is array of unexpected size.", strna(name));
JSON_VARIANT_ARRAY_FOREACH(i, variant) { JSON_VARIANT_ARRAY_FOREACH(i, variant) {
int64_t b; intmax_t b;
if (!json_variant_is_integer(i)) if (!json_variant_is_integer(i))
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Element %zu of JSON field '%s' is not an integer.", k, strna(name)); return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Element %zu of JSON field '%s' is not an integer.", k, strna(name));

View File

@ -485,6 +485,8 @@ static int hardlink_context_setup(
} }
static int hardlink_context_realize(HardlinkContext *c) { static int hardlink_context_realize(HardlinkContext *c) {
int r;
if (!c) if (!c)
return 0; return 0;
@ -496,9 +498,15 @@ static int hardlink_context_realize(HardlinkContext *c) {
assert(c->subdir); assert(c->subdir);
c->dir_fd = open_mkdir_at(c->parent_fd, c->subdir, O_EXCL|O_CLOEXEC, 0700); if (mkdirat(c->parent_fd, c->subdir, 0700) < 0)
if (c->dir_fd < 0) return -errno;
return c->dir_fd;
c->dir_fd = openat(c->parent_fd, c->subdir, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
if (c->dir_fd < 0) {
r = -errno;
(void) unlinkat(c->parent_fd, c->subdir, AT_REMOVEDIR);
return r;
}
return 1; return 1;
} }

View File

@ -215,10 +215,10 @@ int get_credential_host_secret(CredentialSecretFlags flags, void **ret, size_t *
fn = "credential.secret"; fn = "credential.secret";
} }
mkdir_parents(p, 0755); (void) mkdir_p(p, 0755);
dfd = open_mkdir_at(AT_FDCWD, p, O_CLOEXEC, 0755); dfd = open(p, O_CLOEXEC|O_DIRECTORY|O_RDONLY);
if (dfd < 0) if (dfd < 0)
return dfd; return -errno;
if (FLAGS_SET(flags, CREDENTIAL_SECRET_FAIL_ON_TEMPORARY_FS)) { if (FLAGS_SET(flags, CREDENTIAL_SECRET_FAIL_ON_TEMPORARY_FS)) {
r = fd_is_temporary_fs(dfd); r = fd_is_temporary_fs(dfd);

View File

@ -9,16 +9,16 @@
* interface with this. */ * interface with this. */
typedef union JsonValue { typedef union JsonValue {
/* Encodes a simple value. This structure is generally 8 bytes wide (as double is 64bit). */ /* Encodes a simple value. On x86-64 this structure is 16 bytes wide (as long double is 128bit). */
bool boolean; bool boolean;
double real; long double real;
int64_t integer; intmax_t integer;
uint64_t unsig; uintmax_t unsig;
} JsonValue; } JsonValue;
/* Let's protect us against accidental structure size changes on our most relevant arch */ /* Let's protect us against accidental structure size changes on our most relevant arch */
#ifdef __x86_64__ #ifdef __x86_64__
assert_cc(sizeof(JsonValue) == 8U); assert_cc(sizeof(JsonValue) == 16U);
#endif #endif
#define JSON_VALUE_NULL ((JsonValue) {}) #define JSON_VALUE_NULL ((JsonValue) {})

View File

@ -114,16 +114,16 @@ struct JsonVariant {
}; };
}; };
/* Inside string arrays we have a series of JsonVariant structures one after the other. In this case, strings longer /* Inside string arrays we have a series of JasonVariant structures one after the other. In this case, strings longer
* than INLINE_STRING_MAX are stored as references, and all shorter ones inline. (This means on x86-64 strings up * than INLINE_STRING_MAX are stored as references, and all shorter ones inline. (This means on x86-64 strings up
* to 7 chars are stored within the array elements, and all others in separate allocations) */ * to 15 chars are stored within the array elements, and all others in separate allocations) */
#define INLINE_STRING_MAX (sizeof(JsonVariant) - offsetof(JsonVariant, string) - 1U) #define INLINE_STRING_MAX (sizeof(JsonVariant) - offsetof(JsonVariant, string) - 1U)
/* Let's make sure this structure isn't increased in size accidentally. This check is only for our most relevant arch /* Let's make sure this structure isn't increased in size accidentally. This check is only for our most relevant arch
* (x86-64). */ * (x86-64). */
#ifdef __x86_64__ #ifdef __x86_64__
assert_cc(sizeof(JsonVariant) == 40U); assert_cc(sizeof(JsonVariant) == 48U);
assert_cc(INLINE_STRING_MAX == 7U); assert_cc(INLINE_STRING_MAX == 15U);
#endif #endif
static JsonSource* json_source_new(const char *name) { static JsonSource* json_source_new(const char *name) {
@ -305,7 +305,7 @@ static int json_variant_new(JsonVariant **ret, JsonVariantType type, size_t spac
return 0; return 0;
} }
int json_variant_new_integer(JsonVariant **ret, int64_t i) { int json_variant_new_integer(JsonVariant **ret, intmax_t i) {
JsonVariant *v; JsonVariant *v;
int r; int r;
@ -326,7 +326,7 @@ int json_variant_new_integer(JsonVariant **ret, int64_t i) {
return 0; return 0;
} }
int json_variant_new_unsigned(JsonVariant **ret, uint64_t u) { int json_variant_new_unsigned(JsonVariant **ret, uintmax_t u) {
JsonVariant *v; JsonVariant *v;
int r; int r;
@ -346,7 +346,7 @@ int json_variant_new_unsigned(JsonVariant **ret, uint64_t u) {
return 0; return 0;
} }
int json_variant_new_real(JsonVariant **ret, double d) { int json_variant_new_real(JsonVariant **ret, long double d) {
JsonVariant *v; JsonVariant *v;
int r; int r;
@ -748,13 +748,13 @@ static size_t json_variant_size(JsonVariant* v) {
return offsetof(JsonVariant, string) + strlen(v->string) + 1; return offsetof(JsonVariant, string) + strlen(v->string) + 1;
case JSON_VARIANT_REAL: case JSON_VARIANT_REAL:
return offsetof(JsonVariant, value) + sizeof(double); return offsetof(JsonVariant, value) + sizeof(long double);
case JSON_VARIANT_UNSIGNED: case JSON_VARIANT_UNSIGNED:
return offsetof(JsonVariant, value) + sizeof(uint64_t); return offsetof(JsonVariant, value) + sizeof(uintmax_t);
case JSON_VARIANT_INTEGER: case JSON_VARIANT_INTEGER:
return offsetof(JsonVariant, value) + sizeof(int64_t); return offsetof(JsonVariant, value) + sizeof(intmax_t);
case JSON_VARIANT_BOOLEAN: case JSON_VARIANT_BOOLEAN:
return offsetof(JsonVariant, value) + sizeof(bool); return offsetof(JsonVariant, value) + sizeof(bool);
@ -895,7 +895,7 @@ mismatch:
return false; return false;
} }
int64_t json_variant_integer(JsonVariant *v) { intmax_t json_variant_integer(JsonVariant *v) {
if (!v) if (!v)
goto mismatch; goto mismatch;
if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER || if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
@ -913,23 +913,23 @@ int64_t json_variant_integer(JsonVariant *v) {
return v->value.integer; return v->value.integer;
case JSON_VARIANT_UNSIGNED: case JSON_VARIANT_UNSIGNED:
if (v->value.unsig <= INT64_MAX) if (v->value.unsig <= INTMAX_MAX)
return (int64_t) v->value.unsig; return (intmax_t) v->value.unsig;
log_debug("Unsigned integer %ju requested as signed integer and out of range, returning 0.", v->value.unsig); log_debug("Unsigned integer %ju requested as signed integer and out of range, returning 0.", v->value.unsig);
return 0; return 0;
case JSON_VARIANT_REAL: { case JSON_VARIANT_REAL: {
int64_t converted; intmax_t converted;
converted = (int64_t) v->value.real; converted = (intmax_t) v->value.real;
DISABLE_WARNING_FLOAT_EQUAL; DISABLE_WARNING_FLOAT_EQUAL;
if ((double) converted == v->value.real) if ((long double) converted == v->value.real)
return converted; return converted;
REENABLE_WARNING; REENABLE_WARNING;
log_debug("Real %g requested as integer, and cannot be converted losslessly, returning 0.", v->value.real); log_debug("Real %Lg requested as integer, and cannot be converted losslessly, returning 0.", v->value.real);
return 0; return 0;
} }
@ -942,7 +942,7 @@ mismatch:
return 0; return 0;
} }
uint64_t json_variant_unsigned(JsonVariant *v) { uintmax_t json_variant_unsigned(JsonVariant *v) {
if (!v) if (!v)
goto mismatch; goto mismatch;
if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER || if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
@ -958,7 +958,7 @@ uint64_t json_variant_unsigned(JsonVariant *v) {
case JSON_VARIANT_INTEGER: case JSON_VARIANT_INTEGER:
if (v->value.integer >= 0) if (v->value.integer >= 0)
return (uint64_t) v->value.integer; return (uintmax_t) v->value.integer;
log_debug("Signed integer %ju requested as unsigned integer and out of range, returning 0.", v->value.integer); log_debug("Signed integer %ju requested as unsigned integer and out of range, returning 0.", v->value.integer);
return 0; return 0;
@ -967,16 +967,16 @@ uint64_t json_variant_unsigned(JsonVariant *v) {
return v->value.unsig; return v->value.unsig;
case JSON_VARIANT_REAL: { case JSON_VARIANT_REAL: {
uint64_t converted; uintmax_t converted;
converted = (uint64_t) v->value.real; converted = (uintmax_t) v->value.real;
DISABLE_WARNING_FLOAT_EQUAL; DISABLE_WARNING_FLOAT_EQUAL;
if ((double) converted == v->value.real) if ((long double) converted == v->value.real)
return converted; return converted;
REENABLE_WARNING; REENABLE_WARNING;
log_debug("Real %g requested as unsigned integer, and cannot be converted losslessly, returning 0.", v->value.real); log_debug("Real %Lg requested as unsigned integer, and cannot be converted losslessly, returning 0.", v->value.real);
return 0; return 0;
} }
@ -989,7 +989,7 @@ mismatch:
return 0; return 0;
} }
double json_variant_real(JsonVariant *v) { long double json_variant_real(JsonVariant *v) {
if (!v) if (!v)
return 0.0; return 0.0;
if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER || if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
@ -1007,9 +1007,11 @@ double json_variant_real(JsonVariant *v) {
return v->value.real; return v->value.real;
case JSON_VARIANT_INTEGER: { case JSON_VARIANT_INTEGER: {
double converted = (double) v->value.integer; long double converted;
if ((int64_t) converted == v->value.integer) converted = (long double) v->value.integer;
if ((intmax_t) converted == v->value.integer)
return converted; return converted;
log_debug("Signed integer %ji requested as real, and cannot be converted losslessly, returning 0.", v->value.integer); log_debug("Signed integer %ji requested as real, and cannot be converted losslessly, returning 0.", v->value.integer);
@ -1017,9 +1019,11 @@ double json_variant_real(JsonVariant *v) {
} }
case JSON_VARIANT_UNSIGNED: { case JSON_VARIANT_UNSIGNED: {
double converted = (double) v->value.unsig; long double converted;
if ((uint64_t) converted == v->value.unsig) converted = (long double) v->value.unsig;
if ((uintmax_t) converted == v->value.unsig)
return converted; return converted;
log_debug("Unsigned integer %ju requested as real, and cannot be converted losslessly, returning 0.", v->value.unsig); log_debug("Unsigned integer %ju requested as real, and cannot be converted losslessly, returning 0.", v->value.unsig);
@ -1119,11 +1123,10 @@ JsonVariantType json_variant_type(JsonVariant *v) {
return v->type; return v->type;
} }
_function_no_sanitize_float_cast_overflow_ _function_no_sanitize_float_cast_overflow_ bool json_variant_has_type(JsonVariant *v, JsonVariantType type) {
bool json_variant_has_type(JsonVariant *v, JsonVariantType type) {
JsonVariantType rt; JsonVariantType rt;
/* Note: we turn off ubsan float cast overflow detection for this function, since it would complain /* Note: we turn off ubsan float cast overflo detection for this function, since it would complain
* about our float casts but we do them explicitly to detect conversion errors. */ * about our float casts but we do them explicitly to detect conversion errors. */
v = json_variant_dereference(v); v = json_variant_dereference(v);
@ -1155,21 +1158,21 @@ bool json_variant_has_type(JsonVariant *v, JsonVariantType type) {
if (rt == JSON_VARIANT_INTEGER && type == JSON_VARIANT_UNSIGNED) if (rt == JSON_VARIANT_INTEGER && type == JSON_VARIANT_UNSIGNED)
return v->value.integer >= 0; return v->value.integer >= 0;
if (rt == JSON_VARIANT_UNSIGNED && type == JSON_VARIANT_INTEGER) if (rt == JSON_VARIANT_UNSIGNED && type == JSON_VARIANT_INTEGER)
return v->value.unsig <= INT64_MAX; return v->value.unsig <= INTMAX_MAX;
/* Any integer that can be converted lossley to a real and back may also be considered a real */ /* Any integer that can be converted lossley to a real and back may also be considered a real */
if (rt == JSON_VARIANT_INTEGER && type == JSON_VARIANT_REAL) if (rt == JSON_VARIANT_INTEGER && type == JSON_VARIANT_REAL)
return (int64_t) (double) v->value.integer == v->value.integer; return (intmax_t) (long double) v->value.integer == v->value.integer;
if (rt == JSON_VARIANT_UNSIGNED && type == JSON_VARIANT_REAL) if (rt == JSON_VARIANT_UNSIGNED && type == JSON_VARIANT_REAL)
return (uint64_t) (double) v->value.unsig == v->value.unsig; return (uintmax_t) (long double) v->value.unsig == v->value.unsig;
DISABLE_WARNING_FLOAT_EQUAL; DISABLE_WARNING_FLOAT_EQUAL;
/* Any real that can be converted losslessly to an integer and back may also be considered an integer */ /* Any real that can be converted losslessly to an integer and back may also be considered an integer */
if (rt == JSON_VARIANT_REAL && type == JSON_VARIANT_INTEGER) if (rt == JSON_VARIANT_REAL && type == JSON_VARIANT_INTEGER)
return (double) (int64_t) v->value.real == v->value.real; return (long double) (intmax_t) v->value.real == v->value.real;
if (rt == JSON_VARIANT_REAL && type == JSON_VARIANT_UNSIGNED) if (rt == JSON_VARIANT_REAL && type == JSON_VARIANT_UNSIGNED)
return (double) (uint64_t) v->value.real == v->value.real; return (long double) (uintmax_t) v->value.real == v->value.real;
REENABLE_WARNING; REENABLE_WARNING;
@ -1573,7 +1576,7 @@ static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const cha
if (flags & JSON_FORMAT_COLOR) if (flags & JSON_FORMAT_COLOR)
fputs(ansi_highlight_blue(), f); fputs(ansi_highlight_blue(), f);
fprintf(f, "%.*e", DECIMAL_DIG, json_variant_real(v)); fprintf(f, "%.*Le", DECIMAL_DIG, json_variant_real(v));
if (flags & JSON_FORMAT_COLOR) if (flags & JSON_FORMAT_COLOR)
fputs(ANSI_NORMAL, f); fputs(ANSI_NORMAL, f);
@ -1961,7 +1964,7 @@ int json_variant_set_field_string(JsonVariant **v, const char *field, const char
return json_variant_set_field(v, field, m); return json_variant_set_field(v, field, m);
} }
int json_variant_set_field_integer(JsonVariant **v, const char *field, int64_t i) { int json_variant_set_field_integer(JsonVariant **v, const char *field, intmax_t i) {
_cleanup_(json_variant_unrefp) JsonVariant *m = NULL; _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
int r; int r;
@ -1972,7 +1975,7 @@ int json_variant_set_field_integer(JsonVariant **v, const char *field, int64_t i
return json_variant_set_field(v, field, m); return json_variant_set_field(v, field, m);
} }
int json_variant_set_field_unsigned(JsonVariant **v, const char *field, uint64_t u) { int json_variant_set_field_unsigned(JsonVariant **v, const char *field, uintmax_t u) {
_cleanup_(json_variant_unrefp) JsonVariant *m = NULL; _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
int r; int r;
@ -2189,19 +2192,19 @@ static int json_variant_copy(JsonVariant **nv, JsonVariant *v) {
t = json_variant_type(v); t = json_variant_type(v);
switch (t) { switch (t) {
case JSON_VARIANT_INTEGER: case JSON_VARIANT_INTEGER:
k = sizeof(int64_t); k = sizeof(intmax_t);
value.integer = json_variant_integer(v); value.integer = json_variant_integer(v);
source = &value; source = &value;
break; break;
case JSON_VARIANT_UNSIGNED: case JSON_VARIANT_UNSIGNED:
k = sizeof(uint64_t); k = sizeof(uintmax_t);
value.unsig = json_variant_unsigned(v); value.unsig = json_variant_unsigned(v);
source = &value; source = &value;
break; break;
case JSON_VARIANT_REAL: case JSON_VARIANT_REAL:
k = sizeof(double); k = sizeof(long double);
value.real = json_variant_real(v); value.real = json_variant_real(v);
source = &value; source = &value;
break; break;
@ -2524,9 +2527,9 @@ static int json_parse_string(const char **p, char **ret) {
static int json_parse_number(const char **p, JsonValue *ret) { static int json_parse_number(const char **p, JsonValue *ret) {
bool negative = false, exponent_negative = false, is_real = false; bool negative = false, exponent_negative = false, is_real = false;
double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0; long double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0;
int64_t i = 0; intmax_t i = 0;
uint64_t u = 0; uintmax_t u = 0;
const char *c; const char *c;
assert(p); assert(p);
@ -2550,23 +2553,23 @@ static int json_parse_number(const char **p, JsonValue *ret) {
if (!is_real) { if (!is_real) {
if (negative) { if (negative) {
if (i < INT64_MIN / 10) /* overflow */ if (i < INTMAX_MIN / 10) /* overflow */
is_real = true; is_real = true;
else { else {
int64_t t = 10 * i; intmax_t t = 10 * i;
if (t < INT64_MIN + (*c - '0')) /* overflow */ if (t < INTMAX_MIN + (*c - '0')) /* overflow */
is_real = true; is_real = true;
else else
i = t - (*c - '0'); i = t - (*c - '0');
} }
} else { } else {
if (u > UINT64_MAX / 10) /* overflow */ if (u > UINTMAX_MAX / 10) /* overflow */
is_real = true; is_real = true;
else { else {
uint64_t t = 10 * u; uintmax_t t = 10 * u;
if (t > UINT64_MAX - (*c - '0')) /* overflow */ if (t > UINTMAX_MAX - (*c - '0')) /* overflow */
is_real = true; is_real = true;
else else
u = t + (*c - '0'); u = t + (*c - '0');
@ -2616,7 +2619,7 @@ static int json_parse_number(const char **p, JsonValue *ret) {
*p = c; *p = c;
if (is_real) { if (is_real) {
ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10((exponent_negative ? -1.0 : 1.0) * exponent); ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10l((exponent_negative ? -1.0 : 1.0) * exponent);
return JSON_TOKEN_REAL; return JSON_TOKEN_REAL;
} else if (negative) { } else if (negative) {
ret->integer = i; ret->integer = i;
@ -3288,14 +3291,14 @@ int json_buildv(JsonVariant **ret, va_list ap) {
} }
case _JSON_BUILD_INTEGER: { case _JSON_BUILD_INTEGER: {
int64_t j; intmax_t j;
if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
r = -EINVAL; r = -EINVAL;
goto finish; goto finish;
} }
j = va_arg(ap, int64_t); j = va_arg(ap, intmax_t);
if (current->n_suppress == 0) { if (current->n_suppress == 0) {
r = json_variant_new_integer(&add, j); r = json_variant_new_integer(&add, j);
@ -3316,14 +3319,14 @@ int json_buildv(JsonVariant **ret, va_list ap) {
} }
case _JSON_BUILD_UNSIGNED: { case _JSON_BUILD_UNSIGNED: {
uint64_t j; uintmax_t j;
if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
r = -EINVAL; r = -EINVAL;
goto finish; goto finish;
} }
j = va_arg(ap, uint64_t); j = va_arg(ap, uintmax_t);
if (current->n_suppress == 0) { if (current->n_suppress == 0) {
r = json_variant_new_unsigned(&add, j); r = json_variant_new_unsigned(&add, j);
@ -3344,14 +3347,14 @@ int json_buildv(JsonVariant **ret, va_list ap) {
} }
case _JSON_BUILD_REAL: { case _JSON_BUILD_REAL: {
double d; long double d;
if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
r = -EINVAL; r = -EINVAL;
goto finish; goto finish;
} }
d = va_arg(ap, double); d = va_arg(ap, long double);
if (current->n_suppress == 0) { if (current->n_suppress == 0) {
r = json_variant_new_real(&add, d); r = json_variant_new_real(&add, d);
@ -4064,8 +4067,8 @@ int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchF
return 0; return 0;
} }
int json_dispatch_int64(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { int json_dispatch_intmax(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
int64_t *i = userdata; intmax_t *i = userdata;
assert(variant); assert(variant);
assert(i); assert(i);
@ -4077,8 +4080,8 @@ int json_dispatch_int64(const char *name, JsonVariant *variant, JsonDispatchFlag
return 0; return 0;
} }
int json_dispatch_uint64(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { int json_dispatch_uintmax(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
uint64_t *u = userdata; uintmax_t *u = userdata;
assert(variant); assert(variant);
assert(u); assert(u);
@ -4228,7 +4231,7 @@ int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFl
int json_dispatch_uid_gid(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { int json_dispatch_uid_gid(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
uid_t *uid = userdata; uid_t *uid = userdata;
uint64_t k; uintmax_t k;
assert_cc(sizeof(uid_t) == sizeof(uint32_t)); assert_cc(sizeof(uid_t) == sizeof(uint32_t));
assert_cc(sizeof(gid_t) == sizeof(uint32_t)); assert_cc(sizeof(gid_t) == sizeof(uint32_t));

View File

@ -29,10 +29,10 @@
Limitations: Limitations:
- Doesn't allow embedded NUL in strings - Doesn't allow embedded NUL in strings
- Can't store integers outside of the -922337203685477580818446744073709551615 range (it will use 'double' for - Can't store integers outside of the -922337203685477580818446744073709551615 range (it will use 'long double' for
values outside this range, which is lossy) values outside this range, which is lossy)
- Can't store negative zero (will be treated identical to positive zero, and not retained across serialization) - Can't store negative zero (will be treated identical to positive zero, and not retained across serialization)
- Can't store non-integer numbers that can't be stored in "double" losslessly - Can't store non-integer numbers that can't be stored in "long double" losslessly
- Allows creation and parsing of objects with duplicate keys. The "dispatcher" will refuse them however. This means - Allows creation and parsing of objects with duplicate keys. The "dispatcher" will refuse them however. This means
we can parse and pass around such objects, but will carefully refuse them when we convert them into our own data. we can parse and pass around such objects, but will carefully refuse them when we convert them into our own data.
@ -59,9 +59,9 @@ typedef enum JsonVariantType {
int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n); int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n);
int json_variant_new_base64(JsonVariant **ret, const void *p, size_t n); int json_variant_new_base64(JsonVariant **ret, const void *p, size_t n);
int json_variant_new_hex(JsonVariant **ret, const void *p, size_t n); int json_variant_new_hex(JsonVariant **ret, const void *p, size_t n);
int json_variant_new_integer(JsonVariant **ret, int64_t i); int json_variant_new_integer(JsonVariant **ret, intmax_t i);
int json_variant_new_unsigned(JsonVariant **ret, uint64_t u); int json_variant_new_unsigned(JsonVariant **ret, uintmax_t u);
int json_variant_new_real(JsonVariant **ret, double d); int json_variant_new_real(JsonVariant **ret, long double d);
int json_variant_new_boolean(JsonVariant **ret, bool b); int json_variant_new_boolean(JsonVariant **ret, bool b);
int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n); int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n);
int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n); int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n);
@ -81,9 +81,9 @@ void json_variant_unref_many(JsonVariant **array, size_t n);
DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref);
const char *json_variant_string(JsonVariant *v); const char *json_variant_string(JsonVariant *v);
int64_t json_variant_integer(JsonVariant *v); intmax_t json_variant_integer(JsonVariant *v);
uint64_t json_variant_unsigned(JsonVariant *v); uintmax_t json_variant_unsigned(JsonVariant *v);
double json_variant_real(JsonVariant *v); long double json_variant_real(JsonVariant *v);
bool json_variant_boolean(JsonVariant *v); bool json_variant_boolean(JsonVariant *v);
JsonVariantType json_variant_type(JsonVariant *v); JsonVariantType json_variant_type(JsonVariant *v);
@ -189,8 +189,8 @@ int json_variant_filter(JsonVariant **v, char **to_remove);
int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *value); int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *value);
int json_variant_set_field_string(JsonVariant **v, const char *field, const char *value); int json_variant_set_field_string(JsonVariant **v, const char *field, const char *value);
int json_variant_set_field_integer(JsonVariant **v, const char *field, int64_t value); int json_variant_set_field_integer(JsonVariant **v, const char *field, intmax_t value);
int json_variant_set_field_unsigned(JsonVariant **v, const char *field, uint64_t value); int json_variant_set_field_unsigned(JsonVariant **v, const char *field, uintmax_t value);
int json_variant_set_field_boolean(JsonVariant **v, const char *field, bool b); int json_variant_set_field_boolean(JsonVariant **v, const char *field, bool b);
int json_variant_set_field_strv(JsonVariant **v, const char *field, char **l); int json_variant_set_field_strv(JsonVariant **v, const char *field, char **l);
@ -240,9 +240,9 @@ enum {
}; };
#define JSON_BUILD_STRING(s) _JSON_BUILD_STRING, (const char*) { s } #define JSON_BUILD_STRING(s) _JSON_BUILD_STRING, (const char*) { s }
#define JSON_BUILD_INTEGER(i) _JSON_BUILD_INTEGER, (int64_t) { i } #define JSON_BUILD_INTEGER(i) _JSON_BUILD_INTEGER, (intmax_t) { i }
#define JSON_BUILD_UNSIGNED(u) _JSON_BUILD_UNSIGNED, (uint64_t) { u } #define JSON_BUILD_UNSIGNED(u) _JSON_BUILD_UNSIGNED, (uintmax_t) { u }
#define JSON_BUILD_REAL(d) _JSON_BUILD_REAL, (double) { d } #define JSON_BUILD_REAL(d) _JSON_BUILD_REAL, (long double) { d }
#define JSON_BUILD_BOOLEAN(b) _JSON_BUILD_BOOLEAN, (bool) { b } #define JSON_BUILD_BOOLEAN(b) _JSON_BUILD_BOOLEAN, (bool) { b }
#define JSON_BUILD_ARRAY(...) _JSON_BUILD_ARRAY_BEGIN, __VA_ARGS__, _JSON_BUILD_ARRAY_END #define JSON_BUILD_ARRAY(...) _JSON_BUILD_ARRAY_BEGIN, __VA_ARGS__, _JSON_BUILD_ARRAY_END
#define JSON_BUILD_EMPTY_ARRAY _JSON_BUILD_ARRAY_BEGIN, _JSON_BUILD_ARRAY_END #define JSON_BUILD_EMPTY_ARRAY _JSON_BUILD_ARRAY_BEGIN, _JSON_BUILD_ARRAY_END
@ -297,8 +297,8 @@ int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags
int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_int64(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); int json_dispatch_intmax(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_uint64(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); int json_dispatch_uintmax(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_uid_gid(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); int json_dispatch_uid_gid(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
@ -306,6 +306,12 @@ int json_dispatch_user_group_name(const char *name, JsonVariant *variant, JsonDi
int json_dispatch_id128(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); int json_dispatch_id128(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_unsupported(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); int json_dispatch_unsupported(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
assert_cc(sizeof(uintmax_t) == sizeof(uint64_t));
#define json_dispatch_uint64 json_dispatch_uintmax
assert_cc(sizeof(intmax_t) == sizeof(int64_t));
#define json_dispatch_int64 json_dispatch_intmax
assert_cc(sizeof(uint32_t) == sizeof(unsigned)); assert_cc(sizeof(uint32_t) == sizeof(unsigned));
#define json_dispatch_uint json_dispatch_uint32 #define json_dispatch_uint json_dispatch_uint32

View File

@ -252,7 +252,7 @@ int json_dispatch_gecos(const char *name, JsonVariant *variant, JsonDispatchFlag
static int json_dispatch_nice(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { static int json_dispatch_nice(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
int *nl = userdata; int *nl = userdata;
int64_t m; intmax_t m;
if (json_variant_is_null(variant)) { if (json_variant_is_null(variant)) {
*nl = INT_MAX; *nl = INT_MAX;
@ -276,10 +276,10 @@ static int json_dispatch_rlimit_value(const char *name, JsonVariant *variant, Js
if (json_variant_is_null(variant)) if (json_variant_is_null(variant))
*ret = RLIM_INFINITY; *ret = RLIM_INFINITY;
else if (json_variant_is_unsigned(variant)) { else if (json_variant_is_unsigned(variant)) {
uint64_t w; uintmax_t w;
w = json_variant_unsigned(variant); w = json_variant_unsigned(variant);
if (w == RLIM_INFINITY || (uint64_t) w != json_variant_unsigned(variant)) if (w == RLIM_INFINITY || (uintmax_t) w != json_variant_unsigned(variant))
return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "Resource limit value '%s' is out of range.", name); return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "Resource limit value '%s' is out of range.", name);
*ret = (rlim_t) w; *ret = (rlim_t) w;
@ -453,7 +453,7 @@ static int json_dispatch_image_path(const char *name, JsonVariant *variant, Json
static int json_dispatch_umask(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { static int json_dispatch_umask(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
mode_t *m = userdata; mode_t *m = userdata;
uint64_t k; uintmax_t k;
if (json_variant_is_null(variant)) { if (json_variant_is_null(variant)) {
*m = MODE_INVALID; *m = MODE_INVALID;
@ -473,7 +473,7 @@ static int json_dispatch_umask(const char *name, JsonVariant *variant, JsonDispa
static int json_dispatch_access_mode(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { static int json_dispatch_access_mode(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
mode_t *m = userdata; mode_t *m = userdata;
uint64_t k; uintmax_t k;
if (json_variant_is_null(variant)) { if (json_variant_is_null(variant)) {
*m = MODE_INVALID; *m = MODE_INVALID;
@ -564,7 +564,8 @@ static int json_dispatch_storage(const char *name, JsonVariant *variant, JsonDis
} }
static int json_dispatch_tasks_or_memory_max(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { static int json_dispatch_tasks_or_memory_max(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
uint64_t *limit = userdata, k; uint64_t *limit = userdata;
uintmax_t k;
if (json_variant_is_null(variant)) { if (json_variant_is_null(variant)) {
*limit = UINT64_MAX; *limit = UINT64_MAX;
@ -583,7 +584,8 @@ static int json_dispatch_tasks_or_memory_max(const char *name, JsonVariant *vari
} }
static int json_dispatch_weight(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { static int json_dispatch_weight(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
uint64_t *weight = userdata, k; uint64_t *weight = userdata;
uintmax_t k;
if (json_variant_is_null(variant)) { if (json_variant_is_null(variant)) {
*weight = UINT64_MAX; *weight = UINT64_MAX;

View File

@ -952,49 +952,6 @@ static void test_parse_cifs_service(void) {
test_parse_cifs_service_one("//./a", NULL, NULL, NULL, -EINVAL); test_parse_cifs_service_one("//./a", NULL, NULL, NULL, -EINVAL);
} }
static void test_open_mkdir_at(void) {
_cleanup_close_ int fd = -1, subdir_fd = -1, subsubdir_fd = -1;
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
log_info("/* %s */", __func__);
assert_se(open_mkdir_at(AT_FDCWD, "/proc", O_EXCL|O_CLOEXEC, 0) == -EEXIST);
fd = open_mkdir_at(AT_FDCWD, "/proc", O_CLOEXEC, 0);
assert_se(fd >= 0);
fd = safe_close(fd);
assert_se(open_mkdir_at(AT_FDCWD, "/bin/sh", O_EXCL|O_CLOEXEC, 0) == -EEXIST);
assert_se(open_mkdir_at(AT_FDCWD, "/bin/sh", O_CLOEXEC, 0) == -EEXIST);
assert_se(mkdtemp_malloc(NULL, &t) >= 0);
assert_se(open_mkdir_at(AT_FDCWD, t, O_EXCL|O_CLOEXEC, 0) == -EEXIST);
assert_se(open_mkdir_at(AT_FDCWD, t, O_PATH|O_EXCL|O_CLOEXEC, 0) == -EEXIST);
fd = open_mkdir_at(AT_FDCWD, t, O_CLOEXEC, 0000);
assert_se(fd >= 0);
fd = safe_close(fd);
fd = open_mkdir_at(AT_FDCWD, t, O_PATH|O_CLOEXEC, 0000);
assert_se(fd >= 0);
subdir_fd = open_mkdir_at(fd, "xxx", O_PATH|O_EXCL|O_CLOEXEC, 0700);
assert_se(subdir_fd >= 0);
assert_se(open_mkdir_at(fd, "xxx", O_PATH|O_EXCL|O_CLOEXEC, 0) == -EEXIST);
subsubdir_fd = open_mkdir_at(subdir_fd, "yyy", O_EXCL|O_CLOEXEC, 0700);
assert_se(subsubdir_fd >= 0);
subsubdir_fd = safe_close(subsubdir_fd);
assert_se(open_mkdir_at(subdir_fd, "yyy", O_EXCL|O_CLOEXEC, 0) == -EEXIST);
assert_se(open_mkdir_at(fd, "xxx/yyy", O_EXCL|O_CLOEXEC, 0) == -EEXIST);
subsubdir_fd = open_mkdir_at(fd, "xxx/yyy", O_CLOEXEC, 0700);
assert_se(subsubdir_fd >= 0);
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO); test_setup_logging(LOG_INFO);
@ -1015,7 +972,6 @@ int main(int argc, char *argv[]) {
test_conservative_rename(); test_conservative_rename();
test_rmdir_parents(); test_rmdir_parents();
test_parse_cifs_service(); test_parse_cifs_service();
test_open_mkdir_at();
return 0; return 0;
} }

View File

@ -46,23 +46,28 @@ static void test_tokenizer(const char *data, ...) {
assert_se(streq_ptr(nn, str)); assert_se(streq_ptr(nn, str));
} else if (t == JSON_TOKEN_REAL) { } else if (t == JSON_TOKEN_REAL) {
double d; long double d;
d = va_arg(ap, double); d = va_arg(ap, long double);
/* Valgrind doesn't support long double calculations and automatically downgrades to 80bit:
* http://www.valgrind.org/docs/manual/manual-core.html#manual-core.limits.
* Some architectures might not support long double either.
*/
assert_se(fabsl(d - v.real) < 1e-10 || assert_se(fabsl(d - v.real) < 1e-10 ||
fabsl((d - v.real) / v.real) < 1e-10); fabsl((d - v.real) / v.real) < 1e-10);
} else if (t == JSON_TOKEN_INTEGER) { } else if (t == JSON_TOKEN_INTEGER) {
int64_t i; intmax_t i;
i = va_arg(ap, int64_t); i = va_arg(ap, intmax_t);
assert_se(i == v.integer); assert_se(i == v.integer);
} else if (t == JSON_TOKEN_UNSIGNED) { } else if (t == JSON_TOKEN_UNSIGNED) {
uint64_t u; uintmax_t u;
u = va_arg(ap, uint64_t); u = va_arg(ap, uintmax_t);
assert_se(u == v.unsig); assert_se(u == v.unsig);
} else if (t == JSON_TOKEN_BOOLEAN) { } else if (t == JSON_TOKEN_BOOLEAN) {
@ -518,17 +523,17 @@ static void test_bisect(void) {
} }
static void test_float_match(JsonVariant *v) { static void test_float_match(JsonVariant *v) {
const double delta = 0.0001; const long double delta = 0.0001;
assert_se(json_variant_is_array(v)); assert_se(json_variant_is_array(v));
assert_se(json_variant_elements(v) == 9); assert_se(json_variant_elements(v) == 9);
assert_se(fabsl((double) 1.0 - ((double) DBL_MIN / json_variant_real(json_variant_by_index(v, 0)))) <= delta); assert_se(fabsl((long double) 1.0 - ((long double) DBL_MIN / json_variant_real(json_variant_by_index(v, 0)))) <= delta);
assert_se(fabsl((double) 1.0 - ((double) DBL_MAX / json_variant_real(json_variant_by_index(v, 1)))) <= delta); assert_se(fabsl((long double) 1.0 - ((long double) DBL_MAX / json_variant_real(json_variant_by_index(v, 1)))) <= delta);
assert_se(json_variant_is_null(json_variant_by_index(v, 2))); /* nan is not supported by json → null */ assert_se(json_variant_is_null(json_variant_by_index(v, 2))); /* nan is not supported by json → null */
assert_se(json_variant_is_null(json_variant_by_index(v, 3))); /* +inf is not supported by json → null */ assert_se(json_variant_is_null(json_variant_by_index(v, 3))); /* +inf is not supported by json → null */
assert_se(json_variant_is_null(json_variant_by_index(v, 4))); /* -inf is not supported by json → null */ assert_se(json_variant_is_null(json_variant_by_index(v, 4))); /* -inf is not supported by json → null */
assert_se(json_variant_is_null(json_variant_by_index(v, 5)) || assert_se(json_variant_is_null(json_variant_by_index(v, 5)) ||
fabsl((double) 1.0 - ((double) HUGE_VAL / json_variant_real(json_variant_by_index(v, 5)))) <= delta); /* HUGE_VAL might be +inf, but might also be something else */ fabsl((long double) 1.0 - ((long double) HUGE_VAL / json_variant_real(json_variant_by_index(v, 5)))) <= delta); /* HUGE_VAL might be +inf, but might also be something else */
assert_se(json_variant_is_real(json_variant_by_index(v, 6)) && assert_se(json_variant_is_real(json_variant_by_index(v, 6)) &&
json_variant_is_integer(json_variant_by_index(v, 6)) && json_variant_is_integer(json_variant_by_index(v, 6)) &&
json_variant_integer(json_variant_by_index(v, 6)) == 0); json_variant_integer(json_variant_by_index(v, 6)) == 0);
@ -575,19 +580,19 @@ int main(int argc, char *argv[]) {
test_tokenizer("x", -EINVAL); test_tokenizer("x", -EINVAL);
test_tokenizer("", JSON_TOKEN_END); test_tokenizer("", JSON_TOKEN_END);
test_tokenizer(" ", JSON_TOKEN_END); test_tokenizer(" ", JSON_TOKEN_END);
test_tokenizer("0", JSON_TOKEN_UNSIGNED, (uint64_t) 0, JSON_TOKEN_END); test_tokenizer("0", JSON_TOKEN_UNSIGNED, (uintmax_t) 0, JSON_TOKEN_END);
test_tokenizer("-0", JSON_TOKEN_INTEGER, (int64_t) 0, JSON_TOKEN_END); test_tokenizer("-0", JSON_TOKEN_INTEGER, (intmax_t) 0, JSON_TOKEN_END);
test_tokenizer("1234", JSON_TOKEN_UNSIGNED, (uint64_t) 1234, JSON_TOKEN_END); test_tokenizer("1234", JSON_TOKEN_UNSIGNED, (uintmax_t) 1234, JSON_TOKEN_END);
test_tokenizer("-1234", JSON_TOKEN_INTEGER, (int64_t) -1234, JSON_TOKEN_END); test_tokenizer("-1234", JSON_TOKEN_INTEGER, (intmax_t) -1234, JSON_TOKEN_END);
test_tokenizer("18446744073709551615", JSON_TOKEN_UNSIGNED, (uint64_t) UINT64_MAX, JSON_TOKEN_END); test_tokenizer("18446744073709551615", JSON_TOKEN_UNSIGNED, (uintmax_t) UINT64_MAX, JSON_TOKEN_END);
test_tokenizer("-9223372036854775808", JSON_TOKEN_INTEGER, (int64_t) INT64_MIN, JSON_TOKEN_END); test_tokenizer("-9223372036854775808", JSON_TOKEN_INTEGER, (intmax_t) INT64_MIN, JSON_TOKEN_END);
test_tokenizer("18446744073709551616", JSON_TOKEN_REAL, (double) 18446744073709551616.0L, JSON_TOKEN_END); test_tokenizer("18446744073709551616", JSON_TOKEN_REAL, (long double) 18446744073709551616.0L, JSON_TOKEN_END);
test_tokenizer("-9223372036854775809", JSON_TOKEN_REAL, (double) -9223372036854775809.0L, JSON_TOKEN_END); test_tokenizer("-9223372036854775809", JSON_TOKEN_REAL, (long double) -9223372036854775809.0L, JSON_TOKEN_END);
test_tokenizer("-1234", JSON_TOKEN_INTEGER, (int64_t) -1234, JSON_TOKEN_END); test_tokenizer("-1234", JSON_TOKEN_INTEGER, (intmax_t) -1234, JSON_TOKEN_END);
test_tokenizer("3.141", JSON_TOKEN_REAL, (double) 3.141, JSON_TOKEN_END); test_tokenizer("3.141", JSON_TOKEN_REAL, (long double) 3.141, JSON_TOKEN_END);
test_tokenizer("0.0", JSON_TOKEN_REAL, (double) 0.0, JSON_TOKEN_END); test_tokenizer("0.0", JSON_TOKEN_REAL, (long double) 0.0, JSON_TOKEN_END);
test_tokenizer("7e3", JSON_TOKEN_REAL, (double) 7e3, JSON_TOKEN_END); test_tokenizer("7e3", JSON_TOKEN_REAL, (long double) 7e3, JSON_TOKEN_END);
test_tokenizer("-7e-3", JSON_TOKEN_REAL, (double) -7e-3, JSON_TOKEN_END); test_tokenizer("-7e-3", JSON_TOKEN_REAL, (long double) -7e-3, JSON_TOKEN_END);
test_tokenizer("true", JSON_TOKEN_BOOLEAN, true, JSON_TOKEN_END); test_tokenizer("true", JSON_TOKEN_BOOLEAN, true, JSON_TOKEN_END);
test_tokenizer("false", JSON_TOKEN_BOOLEAN, false, JSON_TOKEN_END); test_tokenizer("false", JSON_TOKEN_BOOLEAN, false, JSON_TOKEN_END);
test_tokenizer("null", JSON_TOKEN_NULL, JSON_TOKEN_END); test_tokenizer("null", JSON_TOKEN_NULL, JSON_TOKEN_END);
@ -607,7 +612,7 @@ int main(int argc, char *argv[]) {
test_tokenizer("\"\\udc00\\udc00\"", -EINVAL); test_tokenizer("\"\\udc00\\udc00\"", -EINVAL);
test_tokenizer("\"\\ud801\\udc37\"", JSON_TOKEN_STRING, "\xf0\x90\x90\xb7", JSON_TOKEN_END); test_tokenizer("\"\\ud801\\udc37\"", JSON_TOKEN_STRING, "\xf0\x90\x90\xb7", JSON_TOKEN_END);
test_tokenizer("[1, 2, -3]", JSON_TOKEN_ARRAY_OPEN, JSON_TOKEN_UNSIGNED, (uint64_t) 1, JSON_TOKEN_COMMA, JSON_TOKEN_UNSIGNED, (uint64_t) 2, JSON_TOKEN_COMMA, JSON_TOKEN_INTEGER, (int64_t) -3, JSON_TOKEN_ARRAY_CLOSE, JSON_TOKEN_END); test_tokenizer("[1, 2, -3]", JSON_TOKEN_ARRAY_OPEN, JSON_TOKEN_UNSIGNED, (uintmax_t) 1, JSON_TOKEN_COMMA, JSON_TOKEN_UNSIGNED, (uintmax_t) 2, JSON_TOKEN_COMMA, JSON_TOKEN_INTEGER, (intmax_t) -3, JSON_TOKEN_ARRAY_CLOSE, JSON_TOKEN_END);
test_variant("{\"k\": \"v\", \"foo\": [1, 2, 3], \"bar\": {\"zap\": null}}", test_1); test_variant("{\"k\": \"v\", \"foo\": [1, 2, 3], \"bar\": {\"zap\": null}}", test_1);
test_variant("{\"mutant\": [1, null, \"1\", {\"1\": [1, \"1\"]}], \"thisisaverylongproperty\": 1.27}", test_2); test_variant("{\"mutant\": [1, null, \"1\", {\"1\": [1, \"1\"]}], \"thisisaverylongproperty\": 1.27}", test_2);

View File

@ -57,8 +57,6 @@ int main(void) {
info(long long unsigned); info(long long unsigned);
info(__syscall_ulong_t); info(__syscall_ulong_t);
info(__syscall_slong_t); info(__syscall_slong_t);
info(intmax_t);
info(uintmax_t);
info(float); info(float);
info(double); info(double);

View File

@ -26,7 +26,7 @@ static int block_write_fd = -1;
static int method_something(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { static int method_something(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
_cleanup_(json_variant_unrefp) JsonVariant *ret = NULL; _cleanup_(json_variant_unrefp) JsonVariant *ret = NULL;
JsonVariant *a, *b; JsonVariant *a, *b;
int64_t x, y; intmax_t x, y;
int r; int r;
a = json_variant_by_key(parameters, "a"); a = json_variant_by_key(parameters, "a");