]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-varlink: mark functions that can take 'more' flag in IDL structures with an explic...
authorLennart Poettering <lennart@poettering.net>
Tue, 1 Oct 2024 07:34:25 +0000 (09:34 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 2 Oct 2024 07:22:52 +0000 (09:22 +0200)
Let's mark functions that accept the 'more' flag explicitly for that,
and validate for this explicitly.

This is preparation for
https://github.com/varlink/varlink.github.io/issues/26, if we get that
one day. Let's make sure that from day #1 we have this info available
even if we don't generate this in the IDL for now.

Also enables the two flags for all interfaces we export that use the
logic.

13 files changed:
src/libsystemd/sd-varlink/sd-varlink-idl.c
src/libsystemd/sd-varlink/sd-varlink.c
src/libsystemd/sd-varlink/varlink-idl-util.h
src/shared/varlink-io.systemd.BootControl.c
src/shared/varlink-io.systemd.Import.c
src/shared/varlink-io.systemd.Machine.c
src/shared/varlink-io.systemd.ManagedOOM.c
src/shared/varlink-io.systemd.PCRLock.c
src/shared/varlink-io.systemd.Resolve.Monitor.c
src/shared/varlink-io.systemd.UserDatabase.c
src/shared/varlink-io.systemd.sysext.c
src/systemd/sd-varlink-idl.h
src/test/test-varlink-idl.c

index 76a2499561db12b3e01e0b202d66ffd1873ef77f..58edcf02f769eea6f6515f672328043a92d8a3b5 100644 (file)
@@ -374,6 +374,20 @@ static int varlink_idl_format_symbol(
                 break;
 
         case SD_VARLINK_METHOD:
+
+                /* Sooner or later we want to export this in a proper IDL language construct, see
+                 * https://github.com/varlink/varlink.github.io/issues/26 – but for now export this as a
+                 * comment. */
+                if ((symbol->symbol_flags & (SD_VARLINK_REQUIRES_MORE|SD_VARLINK_SUPPORTS_MORE)) != 0) {
+                        fputs(colors[COLOR_COMMENT], f);
+                        if (FLAGS_SET(symbol->symbol_flags, SD_VARLINK_REQUIRES_MORE))
+                                fputs("# [Requires 'more' flag]", f);
+                        else
+                                fputs("# [Supports 'more' flag]", f);
+                        fputs(colors[COLOR_RESET], f);
+                        fputs("\n", f);
+                }
+
                 fputs(colors[COLOR_SYMBOL_TYPE], f);
                 fputs("method ", f);
                 fputs(colors[COLOR_IDENTIFIER], f);
@@ -1761,15 +1775,15 @@ static int varlink_idl_validate_field(const sd_varlink_field *field, sd_json_var
         return 0;
 }
 
-static int varlink_idl_validate_symbol(const sd_varlink_symbol *symbol, sd_json_variant *v, sd_varlink_field_direction_t direction, const char **bad_field) {
+static int varlink_idl_validate_symbol(const sd_varlink_symbol *symbol, sd_json_variant *v, sd_varlink_field_direction_t direction, const char **reterr_bad_field) {
         int r;
 
         assert(symbol);
         assert(!IN_SET(symbol->symbol_type, _SD_VARLINK_SYMBOL_COMMENT, _SD_VARLINK_INTERFACE_COMMENT));
 
         if (!v) {
-                if (bad_field)
-                        *bad_field = NULL;
+                if (reterr_bad_field)
+                        *reterr_bad_field = NULL;
                 return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Null object passed, refusing.");
         }
 
@@ -1780,8 +1794,8 @@ static int varlink_idl_validate_symbol(const sd_varlink_symbol *symbol, sd_json_
                 const char *s;
 
                 if (!sd_json_variant_is_string(v)) {
-                        if (bad_field)
-                                *bad_field = symbol->name;
+                        if (reterr_bad_field)
+                                *reterr_bad_field = symbol->name;
                         return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Passed non-string to enum field '%s', refusing.", strna(symbol->name));
                 }
 
@@ -1801,8 +1815,8 @@ static int varlink_idl_validate_symbol(const sd_varlink_symbol *symbol, sd_json_
                 }
 
                 if (!found) {
-                        if (bad_field)
-                                *bad_field = s;
+                        if (reterr_bad_field)
+                                *reterr_bad_field = s;
                         return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Passed unrecognized string '%s' to enum field '%s', refusing.", s, strna(symbol->name));
                 }
 
@@ -1813,8 +1827,8 @@ static int varlink_idl_validate_symbol(const sd_varlink_symbol *symbol, sd_json_
         case SD_VARLINK_METHOD:
         case SD_VARLINK_ERROR: {
                 if (!sd_json_variant_is_object(v)) {
-                        if (bad_field)
-                                *bad_field = symbol->name;
+                        if (reterr_bad_field)
+                                *reterr_bad_field = symbol->name;
                         return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Passed non-object to field '%s', refusing.", strna(symbol->name));
                 }
 
@@ -1828,8 +1842,8 @@ static int varlink_idl_validate_symbol(const sd_varlink_symbol *symbol, sd_json_
 
                         r = varlink_idl_validate_field(field, sd_json_variant_by_key(v, field->name));
                         if (r < 0) {
-                                if (bad_field)
-                                        *bad_field = field->name;
+                                if (reterr_bad_field)
+                                        *reterr_bad_field = field->name;
                                 return r;
                         }
                 }
@@ -1838,8 +1852,8 @@ static int varlink_idl_validate_symbol(const sd_varlink_symbol *symbol, sd_json_
                 const char *name;
                 JSON_VARIANT_OBJECT_FOREACH(name, e, v) {
                         if (!varlink_idl_find_field(symbol, name)) {
-                                if (bad_field)
-                                        *bad_field = name;
+                                if (reterr_bad_field)
+                                        *reterr_bad_field = name;
                                 return varlink_idl_log(SYNTHETIC_ERRNO(EBUSY), "Field '%s' not defined for object, refusing.", name);
                         }
                 }
@@ -1858,32 +1872,40 @@ static int varlink_idl_validate_symbol(const sd_varlink_symbol *symbol, sd_json_
         return 1; /* validated */
 }
 
-static int varlink_idl_validate_method(const sd_varlink_symbol *method, sd_json_variant *v, sd_varlink_field_direction_t direction, const char **bad_field) {
-        assert(IN_SET(direction, SD_VARLINK_INPUT, SD_VARLINK_OUTPUT));
+int varlink_idl_validate_method_call(const sd_varlink_symbol *method, sd_json_variant *v, sd_varlink_method_flags_t flags, const char **reterr_bad_field) {
 
         if (!method)
                 return 0; /* Can't validate */
         if (method->symbol_type != SD_VARLINK_METHOD)
                 return -EBADMSG;
 
-        return varlink_idl_validate_symbol(method, v, direction, bad_field);
-}
+        /* If method calls require the "more" flag, but none is given, return a recognizable error */
+        if (FLAGS_SET(method->symbol_flags, SD_VARLINK_REQUIRES_MORE) && !FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
+                return -EBADE;
 
-int varlink_idl_validate_method_call(const sd_varlink_symbol *method, sd_json_variant *v, const char **bad_field) {
-        return varlink_idl_validate_method(method, v, SD_VARLINK_INPUT, bad_field);
+        return varlink_idl_validate_symbol(method, v, SD_VARLINK_INPUT, reterr_bad_field);
 }
 
-int varlink_idl_validate_method_reply(const sd_varlink_symbol *method, sd_json_variant *v, const char **bad_field) {
-        return varlink_idl_validate_method(method, v, SD_VARLINK_OUTPUT, bad_field);
+int varlink_idl_validate_method_reply(const sd_varlink_symbol *method, sd_json_variant *v, sd_varlink_reply_flags_t flags, const char **reterr_bad_field) {
+        if (!method)
+                return 0; /* Can't validate */
+        if (method->symbol_type != SD_VARLINK_METHOD)
+                return -EBADMSG;
+
+        /* If method replies have the "continues" flag set, but the method is not allowed to generate that, return a recognizable error */
+        if (FLAGS_SET(flags, SD_VARLINK_REPLY_CONTINUES) && (method->symbol_type & (SD_VARLINK_SUPPORTS_MORE|SD_VARLINK_REQUIRES_MORE)) == 0)
+                return -EBADE;
+
+        return varlink_idl_validate_symbol(method, v, SD_VARLINK_OUTPUT, reterr_bad_field);
 }
 
-int varlink_idl_validate_error(const sd_varlink_symbol *error, sd_json_variant *v, const char **bad_field) {
+int varlink_idl_validate_error(const sd_varlink_symbol *error, sd_json_variant *v, const char **reterr_bad_field) {
         if (!error)
                 return 0; /* Can't validate */
         if (error->symbol_type != SD_VARLINK_ERROR)
                 return -EBADMSG;
 
-        return varlink_idl_validate_symbol(error, v, SD_VARLINK_REGULAR, bad_field);
+        return varlink_idl_validate_symbol(error, v, SD_VARLINK_REGULAR, reterr_bad_field);
 }
 
 const sd_varlink_symbol* varlink_idl_find_symbol(
index 007746f64f61b1e3268a71af49340f3cc9c99028..70615bb3e3b6db7e3b07224d8ee96cea1c189c09 100644 (file)
@@ -1354,8 +1354,17 @@ static int varlink_dispatch_method(sd_varlink *v) {
                 else {
                         const char *bad_field;
 
-                        r = varlink_idl_validate_method_call(v->current_method, parameters, &bad_field);
-                        if (r < 0) {
+                        r = varlink_idl_validate_method_call(v->current_method, parameters, flags, &bad_field);
+                        if (r == -EBADE) {
+                                varlink_log_errno(v, r, "Method %s() called without 'more' flag, but flag needs to be set: %m",
+                                                  method);
+
+                                if (v->state == VARLINK_PROCESSING_METHOD) {
+                                        r = sd_varlink_error(v, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
+                                        if (r < 0)
+                                                return r;
+                                }
+                        } else if (r < 0) {
                                 /* Please adjust test/units/end.sh when updating the log message. */
                                 varlink_log_errno(v, r, "Parameters for method %s() didn't pass validation on field '%s': %m",
                                                   method, strna(bad_field));
@@ -1365,8 +1374,9 @@ static int varlink_dispatch_method(sd_varlink *v) {
                                         if (r < 0)
                                                 return r;
                                 }
-                                invalid = true;
                         }
+
+                        invalid = r < 0;
                 }
 
                 if (!invalid) {
@@ -2439,7 +2449,7 @@ _public_ int sd_varlink_reply(sd_varlink *v, sd_json_variant *parameters) {
         if (v->current_method) {
                 const char *bad_field = NULL;
 
-                r = varlink_idl_validate_method_reply(v->current_method, parameters, &bad_field);
+                r = varlink_idl_validate_method_reply(v->current_method, parameters, /* flags= */ 0, &bad_field);
                 if (r < 0)
                         /* Please adjust test/units/end.sh when updating the log message. */
                         varlink_log_errno(v, r, "Return parameters for method reply %s() didn't pass validation on field '%s', ignoring: %m",
@@ -2652,8 +2662,11 @@ _public_ int sd_varlink_notify(sd_varlink *v, sd_json_variant *parameters) {
         if (v->current_method) {
                 const char *bad_field = NULL;
 
-                r = varlink_idl_validate_method_reply(v->current_method, parameters, &bad_field);
-                if (r < 0)
+                r = varlink_idl_validate_method_reply(v->current_method, parameters, SD_VARLINK_REPLY_CONTINUES, &bad_field);
+                if (r == -EBADE)
+                        varlink_log_errno(v, r, "Method reply for %s() has 'continues' flag set, but IDL structure doesn't allow that, ignoring: %m",
+                                          v->current_method->name);
+                else if (r < 0)
                         /* Please adjust test/units/end.sh when updating the log message. */
                         varlink_log_errno(v, r, "Return parameters for method reply %s() didn't pass validation on field '%s', ignoring: %m",
                                           v->current_method->name, strna(bad_field));
index fab836a72321a197a26440b0ead6c57c4e5dd3a3..8c9274eefa63addd10187385a574c9ca13f4acc9 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include "sd-varlink.h"
 #include "sd-varlink-idl.h"
 
 #include "macro.h"
@@ -20,6 +21,6 @@ int varlink_idl_consistent(const sd_varlink_interface *interface, int level);
 const sd_varlink_symbol* varlink_idl_find_symbol(const sd_varlink_interface *interface, sd_varlink_symbol_type_t type, const char *name);
 const sd_varlink_field* varlink_idl_find_field(const sd_varlink_symbol *symbol, const char *name);
 
-int varlink_idl_validate_method_call(const sd_varlink_symbol *method, sd_json_variant *v, const char **bad_field);
-int varlink_idl_validate_method_reply(const sd_varlink_symbol *method, sd_json_variant *v, const char **bad_field);
+int varlink_idl_validate_method_call(const sd_varlink_symbol *method, sd_json_variant *v, sd_varlink_method_flags_t flags, const char **reterr_bad_field);
+int varlink_idl_validate_method_reply(const sd_varlink_symbol *method, sd_json_variant *v, sd_varlink_reply_flags_t flags, const char **reterr_bad_field);
 int varlink_idl_validate_error(const sd_varlink_symbol *error, sd_json_variant *v, const char **bad_field);
index 449cc98bb414d0083856133abaec4baa42210dc1..364fa8470e5725e9f968ca26b0823a2d44cc4df5 100644 (file)
@@ -43,8 +43,9 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
                 SD_VARLINK_FIELD_COMMENT("Indicates whether this entry has been booted."),
                 SD_VARLINK_DEFINE_FIELD(isSelected, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE));
 
-static SD_VARLINK_DEFINE_METHOD(
+static SD_VARLINK_DEFINE_METHOD_FULL(
                 ListBootEntries,
+                SD_VARLINK_REQUIRES_MORE,
                 SD_VARLINK_FIELD_COMMENT("A boot menu entry structure"),
                 SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(entry, BootEntry, SD_VARLINK_NULLABLE));
 
index 03af5a98c3c037eac01448a81c34f335795709c1..02eb70d91d7ef127a21e0d5f610df1816df509cd 100644 (file)
@@ -53,8 +53,9 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
                 SD_VARLINK_FIELD_COMMENT("The priority of the log message, using the BSD syslog priority levels"),
                 SD_VARLINK_DEFINE_FIELD(priority, SD_VARLINK_INT, 0));
 
-static SD_VARLINK_DEFINE_METHOD(
+static SD_VARLINK_DEFINE_METHOD_FULL(
                 ListTransfers,
+                SD_VARLINK_REQUIRES_MORE,
                 SD_VARLINK_FIELD_COMMENT("Image class to filter by"),
                 SD_VARLINK_DEFINE_INPUT_BY_TYPE(class, ImageClass, SD_VARLINK_NULLABLE),
                 SD_VARLINK_FIELD_COMMENT("A unique numeric identifier for the ongoing transfer"),
@@ -70,8 +71,9 @@ static SD_VARLINK_DEFINE_METHOD(
                 SD_VARLINK_FIELD_COMMENT("Progress in percent"),
                 SD_VARLINK_DEFINE_OUTPUT(percent, SD_VARLINK_FLOAT, 0));
 
-static SD_VARLINK_DEFINE_METHOD(
+static SD_VARLINK_DEFINE_METHOD_FULL(
                 Pull,
+                SD_VARLINK_SUPPORTS_MORE,
                 SD_VARLINK_FIELD_COMMENT("The remote URL to download from"),
                 SD_VARLINK_DEFINE_INPUT(remote, SD_VARLINK_STRING, 0),
                 SD_VARLINK_FIELD_COMMENT("The local image name to download to"),
index 1c8f39e3c794aec72570d8b3acec73b32a0d027c..5841bf02ced7b8fb8eb5d799fa5feb4bddb6b78b 100644 (file)
@@ -28,8 +28,9 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
                 SD_VARLINK_FIELD_COMMENT("Timestamp in µs in the CLOCK_MONOTONIC clock"),
                 SD_VARLINK_DEFINE_FIELD(monotonic, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
 
-static SD_VARLINK_DEFINE_METHOD(
+static SD_VARLINK_DEFINE_METHOD_FULL(
                 List,
+                SD_VARLINK_SUPPORTS_MORE,
                 SD_VARLINK_FIELD_COMMENT("If non-null the name of a running machine to report details on. If null/unspecified enumerates all running machines."),
                 SD_VARLINK_DEFINE_INPUT(name, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
                 SD_VARLINK_FIELD_COMMENT("Name of the machine"),
index 8fc329b707a9d05965065083c398af0cb00d56a2..763b0abfbd886024e9e7ab8334e6140d6c300ba5 100644 (file)
@@ -9,8 +9,9 @@
  *
  * Compare with io.systemd.oom where the client/server roles of oomd and the service manager are swapped! */
 
-static SD_VARLINK_DEFINE_METHOD(
+static SD_VARLINK_DEFINE_METHOD_FULL(
                 SubscribeManagedOOMCGroups,
+                SD_VARLINK_SUPPORTS_MORE,
                 SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(cgroups, ControlGroup, SD_VARLINK_ARRAY));
 
 static SD_VARLINK_DEFINE_ERROR(SubscriptionTaken);
index f385eb31c3f0f766e37130777761575d6b3a166f..15e37cd2845136bc62073ab08dcf9da15a369842 100644 (file)
@@ -2,8 +2,9 @@
 
 #include "varlink-io.systemd.PCRLock.h"
 
-static SD_VARLINK_DEFINE_METHOD(
+static SD_VARLINK_DEFINE_METHOD_FULL(
                 ReadEventLog,
+                SD_VARLINK_REQUIRES_MORE,
                 SD_VARLINK_DEFINE_OUTPUT(record, SD_VARLINK_OBJECT, 0));
 
 static SD_VARLINK_DEFINE_METHOD(
index 8c9fb51469780fdfaaa32e65873cc44a0810aac7..f5650b10116a4138a6c9fc08e982d33ef139573e 100644 (file)
@@ -17,8 +17,9 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
                 SD_VARLINK_DEFINE_FIELD(raw, SD_VARLINK_STRING, 0),
                 SD_VARLINK_DEFINE_FIELD(ifindex, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
 
-static SD_VARLINK_DEFINE_METHOD(
+static SD_VARLINK_DEFINE_METHOD_FULL(
                 SubscribeQueryResults,
+                SD_VARLINK_REQUIRES_MORE,
                 SD_VARLINK_DEFINE_INPUT(allowInteractiveAuthentication, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
                 /* First reply */
                 SD_VARLINK_DEFINE_OUTPUT(ready, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
index b714550f7d95c5e6e40c03bd943788f27aa1f469..3dc72c025790ca42dff3855c4e206924bb77be87 100644 (file)
@@ -2,24 +2,27 @@
 
 #include "varlink-io.systemd.UserDatabase.h"
 
-static SD_VARLINK_DEFINE_METHOD(
+static SD_VARLINK_DEFINE_METHOD_FULL(
                 GetUserRecord,
+                SD_VARLINK_SUPPORTS_MORE,
                 SD_VARLINK_DEFINE_INPUT(uid, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
                 SD_VARLINK_DEFINE_INPUT(userName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
                 SD_VARLINK_DEFINE_INPUT(service, SD_VARLINK_STRING, 0),
                 SD_VARLINK_DEFINE_OUTPUT(record, SD_VARLINK_OBJECT, 0),
                 SD_VARLINK_DEFINE_OUTPUT(incomplete, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE));
 
-static SD_VARLINK_DEFINE_METHOD(
+static SD_VARLINK_DEFINE_METHOD_FULL(
                 GetGroupRecord,
+                SD_VARLINK_SUPPORTS_MORE,
                 SD_VARLINK_DEFINE_INPUT(gid, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
                 SD_VARLINK_DEFINE_INPUT(groupName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
                 SD_VARLINK_DEFINE_INPUT(service, SD_VARLINK_STRING, 0),
                 SD_VARLINK_DEFINE_OUTPUT(record, SD_VARLINK_OBJECT, 0),
                 SD_VARLINK_DEFINE_OUTPUT(incomplete, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE));
 
-static SD_VARLINK_DEFINE_METHOD(
+static SD_VARLINK_DEFINE_METHOD_FULL(
                 GetMemberships,
+                SD_VARLINK_SUPPORTS_MORE,
                 SD_VARLINK_DEFINE_INPUT(userName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
                 SD_VARLINK_DEFINE_INPUT(groupName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
                 SD_VARLINK_DEFINE_INPUT(service, SD_VARLINK_STRING, 0),
index b20afb2950fd3e2f2a03677fd4765c08606a374d..90eb8177d1e9cf37bcba7f7f773cb8d166d3d7df 100644 (file)
@@ -33,8 +33,9 @@ static SD_VARLINK_DEFINE_METHOD(
                 SD_VARLINK_DEFINE_INPUT(noReload, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
                 SD_VARLINK_DEFINE_INPUT(noexec, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE));
 
-static SD_VARLINK_DEFINE_METHOD(
+static SD_VARLINK_DEFINE_METHOD_FULL(
                 List,
+                SD_VARLINK_REQUIRES_MORE,
                 SD_VARLINK_DEFINE_INPUT_BY_TYPE(class, ImageClass, SD_VARLINK_NULLABLE),
                 SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(Class, ImageClass, 0),
                 SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(Type, ImageType, 0),
index d2fd458cac7df6606c764aa09e64ae40390bb335..e5e8a57498899c00b68f8c28a9c44cbc26ef31c3 100644 (file)
@@ -53,7 +53,9 @@ __extension__ typedef enum _SD_ENUM_TYPE_S64(sd_varlink_symbol_type_t) {
 } sd_varlink_symbol_type_t;
 
 __extension__ typedef enum _SD_ENUM_TYPE_S64(sd_varlink_symbol_flags_t) {
-        _SD_VARLINK_SYMBOL_FLAGS_MAX     = (1 << 0) - 1,
+        SD_VARLINK_SUPPORTS_MORE         = 1 << 0, /* Call supports "more" flag */
+        SD_VARLINK_REQUIRES_MORE         = 1 << 1, /* Call requires "more" flag */
+        _SD_VARLINK_SYMBOL_FLAGS_MAX     = (1 << 2) - 1,
         _SD_VARLINK_SYMBOL_FLAGS_INVALID = -EINVAL,
         _SD_ENUM_FORCE_S64(SD_VARLINK_SYMBOL_FLAGS)
 } sd_varlink_symbol_flags_t;
@@ -163,6 +165,14 @@ struct sd_varlink_interface {
                 .fields = { __VA_ARGS__ __VA_OPT__(,) {}},              \
         }
 
+#define SD_VARLINK_DEFINE_METHOD_FULL(_name, _flags, ...)               \
+        const sd_varlink_symbol vl_method_ ## _name = {                 \
+                .name = #_name,                                         \
+                .symbol_type = SD_VARLINK_METHOD,                       \
+                .symbol_flags = _flags,                                 \
+                .fields = { __VA_ARGS__ __VA_OPT__(,) {}},              \
+        }
+
 #define SD_VARLINK_DEFINE_ERROR(_name, ...)                             \
         const sd_varlink_symbol vl_error_ ## _name = {                  \
                 .name = #_name,                                         \
index 4283ae7c0182a5067f0fcd3ca8a4853a9dde5481..af48216865b263f002a0363802ff44e779e89790 100644 (file)
@@ -305,7 +305,7 @@ TEST(validate_json) {
 
         const sd_varlink_symbol* symbol = ASSERT_PTR(varlink_idl_find_symbol(parsed, SD_VARLINK_METHOD, "Mymethod"));
 
-        assert_se(varlink_idl_validate_method_call(symbol, v, NULL) >= 0);
+        assert_se(varlink_idl_validate_method_call(symbol, v, /* flags= */ 0, /* reterr_bad_field= */ NULL) >= 0);
 }
 
 static int test_recursive_one(unsigned depth) {