From: Ivan Kruglov Date: Fri, 15 May 2026 10:16:00 +0000 (-0700) Subject: json-util: add json_dispatch_job_id() dispatcher for job IDs X-Git-Tag: v261-rc1~80^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2d4f2441f5c6331efbfa07d06467398f582d6616;p=thirdparty%2Fsystemd.git json-util: add json_dispatch_job_id() dispatcher for job IDs Job IDs are uint32_t values that are always >= 1 (the manager's ID counter starts at 1 and wraps from UINT32_MAX back to 1, never assigning 0). Add a dedicated dispatch function that validates this constraint, rejecting 0 and treating null as "unset" (0). Co-developed-by: Claude Opus 4.6 --- diff --git a/src/libsystemd/sd-json/json-util.c b/src/libsystemd/sd-json/json-util.c index 40102a69989..c6727ac760a 100644 --- a/src/libsystemd/sd-json/json-util.c +++ b/src/libsystemd/sd-json/json-util.c @@ -796,6 +796,27 @@ int json_dispatch_access_mode(const char *name, sd_json_variant *variant, sd_jso return 0; } +int json_dispatch_job_id(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { + uint32_t *id = ASSERT_PTR(userdata); + uint32_t k; + int r; + + if (sd_json_variant_is_null(variant)) { + *id = 0; + return 0; + } + + r = sd_json_dispatch_uint32(name, variant, flags, &k); + if (r < 0) + return r; + + if (k == 0) + return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid job ID.", strna(name)); + + *id = k; + return 0; +} + int json_variant_compare(sd_json_variant *a, sd_json_variant *b) { int r; diff --git a/src/libsystemd/sd-json/json-util.h b/src/libsystemd/sd-json/json-util.h index 0b5ea32f87d..48a0afa289d 100644 --- a/src/libsystemd/sd-json/json-util.h +++ b/src/libsystemd/sd-json/json-util.h @@ -132,6 +132,7 @@ int json_dispatch_ifindex(const char *name, sd_json_variant *variant, sd_json_di int json_dispatch_log_level(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); int json_dispatch_strv_environment(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); int json_dispatch_access_mode(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); +int json_dispatch_job_id(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); static inline int json_variant_unbase64_iovec(sd_json_variant *v, struct iovec *ret) { return sd_json_variant_unbase64(v, ret ? &ret->iov_base : NULL, ret ? &ret->iov_len : NULL); diff --git a/src/libsystemd/sd-json/test-json.c b/src/libsystemd/sd-json/test-json.c index 3be4b09660b..5d5765b3544 100644 --- a/src/libsystemd/sd-json/test-json.c +++ b/src/libsystemd/sd-json/test-json.c @@ -1569,6 +1569,69 @@ TEST(access_mode) { &mm), ERANGE); } +TEST(job_id) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + + ASSERT_OK(sd_json_parse("{\"a\": 1, \"b\": 4294967295, \"c\": null}", + /* flags= */ 0, + &v, + /* reterr_line= */ NULL, + /* reterr_column= */ NULL)); + + struct { + uint32_t a, b, c; + } data = { 99, 99, 99 }; + + ASSERT_OK(sd_json_dispatch( + v, + (const sd_json_dispatch_field[]) { + { "a", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_job_id, voffsetof(data, a), 0 }, + { "b", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_job_id, voffsetof(data, b), 0 }, + { "c", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_job_id, voffsetof(data, c), 0 }, + {}, + }, + /* flags= */ 0, + &data)); + + ASSERT_EQ(data.a, UINT32_C(1)); + ASSERT_EQ(data.b, UINT32_MAX); + ASSERT_EQ(data.c, UINT32_C(0)); + + /* Zero is not a valid job ID */ + sd_json_variant_unrefp(&v); + ASSERT_OK(sd_json_parse("{\"a\": 0}", + /* flags= */ 0, + &v, + /* reterr_line= */ NULL, + /* reterr_column= */ NULL)); + + ASSERT_ERROR(sd_json_dispatch( + v, + (const sd_json_dispatch_field[]) { + { "a", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_job_id, voffsetof(data, a), 0 }, + {}, + }, + /* flags= */ 0, + &data), EINVAL); + + /* Negative values are not valid */ + sd_json_variant_unrefp(&v); + ASSERT_OK(sd_json_parse("{\"a\": -1}", + /* flags= */ 0, + &v, + /* reterr_line= */ NULL, + /* reterr_column= */ NULL)); + + ASSERT_ERROR(sd_json_dispatch( + v, + (const sd_json_dispatch_field[]) { + { "a", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_job_id, voffsetof(data, a), 0 }, + {}, + }, + /* flags= */ 0, + &data), EINVAL); +} + static void test_json_variant_compare_one(const char *a, const char *b, int expected) { int r;