From 1db9575bd2f15fa0c9f4927bfa7fb1b065a64802 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Wed, 29 Jul 2026 16:25:42 +0200 Subject: [PATCH 1/2] conf: add an util to iterate on sequence A YAML sequence of single key maps, such as `outputs`, stores its entries at outputs.. so a direct lookup of outputs. never matches. Add SCConfNodeLookupInSequence() to walk such a sequence and return the entries matching a given name. Ticket: 8606 --- rust/sys/src/sys.rs | 5 +++++ src/conf.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/conf.h | 2 ++ 3 files changed, 49 insertions(+) diff --git a/rust/sys/src/sys.rs b/rust/sys/src/sys.rs index 566c570d05..97f2cab8eb 100644 --- a/rust/sys/src/sys.rs +++ b/rust/sys/src/sys.rs @@ -343,6 +343,11 @@ extern "C" { node: *const SCConfNode, key: *const ::std::os::raw::c_char, ) -> *const ::std::os::raw::c_char; } +extern "C" { + pub fn SCConfNodeLookupInSequence( + seq: *const SCConfNode, key: *const ::std::os::raw::c_char, prev: *const SCConfNode, + ) -> *mut SCConfNode; +} extern "C" { pub fn SCConfNodeRemove(arg1: *mut SCConfNode); } diff --git a/src/conf.c b/src/conf.c index 4dc5118081..605837c564 100644 --- a/src/conf.c +++ b/src/conf.c @@ -886,6 +886,48 @@ const char *SCConfNodeLookupChildValue(const SCConfNode *node, const char *name) return NULL; } +/** + * \brief Find a named entry inside a sequence node. + * + * A YAML sequence of single key maps -- the shape used by "outputs" -- + * stores each entry as an unnamed node holding one child, so an entry is + * found at seq.. and not at seq.. This walks the sequence and + * returns the child named \a key. + * + * A sequence may hold several entries with the same name (several eve-log + * outputs for instance), so \a prev allows iterating over all of them: + * pass NULL to get the first match, then the previous result to get the + * next one. + * + * \param seq The sequence node, may be NULL. + * \param key The name of the entry to look for. + * \param prev NULL to start, or the previously returned node to continue. + * + * \retval The matching SCConfNode or NULL when there is no (further) match. + */ +SCConfNode *SCConfNodeLookupInSequence( + const SCConfNode *seq, const char *key, const SCConfNode *prev) +{ + if (seq == NULL || key == NULL) + return NULL; + + bool seen = (prev == NULL); + SCConfNode *entry; + TAILQ_FOREACH (entry, &seq->head, next) { + SCConfNode *child = SCConfNodeLookupChild(entry, key); + if (child == NULL) + continue; + if (!seen) { + if (child == prev) + seen = true; + continue; + } + return child; + } + + return NULL; +} + /** * \brief Lookup for a key value under a specific node * diff --git a/src/conf.h b/src/conf.h index 34f1c0709f..9cf84b53a2 100644 --- a/src/conf.h +++ b/src/conf.h @@ -81,6 +81,8 @@ void SCConfCreateContextBackup(void); void SCConfRestoreContextBackup(void); SCConfNode *SCConfNodeLookupChild(const SCConfNode *node, const char *key); const char *SCConfNodeLookupChildValue(const SCConfNode *node, const char *key); +SCConfNode *SCConfNodeLookupInSequence( + const SCConfNode *seq, const char *key, const SCConfNode *prev); void SCConfNodeRemove(SCConfNode *); void SCConfRegisterTests(void); int SCConfNodeChildValueIsTrue(const SCConfNode *node, const char *key); From 460a7f9615ebf4ca891a6626d158b71732e52e31 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Fri, 24 Jul 2026 00:09:54 +0200 Subject: [PATCH 2/2] conf: better handling of set In the case of --set=foo.0=bar, the 0 was not creating a sequence if ever the sequence is not existing. Ticket: 8606 --- src/conf.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/conf.c b/src/conf.c index 605837c564..747e1f48f4 100644 --- a/src/conf.c +++ b/src/conf.c @@ -97,6 +97,18 @@ SCConfNode *SCConfNodeGetNodeOrCreate(SCConfNode *parent, const char *name, int node->parent = parent; node->final = final; TAILQ_INSERT_TAIL(&parent->head, node, next); + + /* Numeric-only key implies the parent is a sequence (yaml + * "- foo" produces the same shape). This lets --set style + * overrides populate list-typed config nodes. */ + if (parent != NULL) { + const char *p = key; + while (*p != '\0' && isdigit((unsigned char)*p)) + p++; + if (*p == '\0' && p != key) { + parent->is_seq = 1; + } + } } key = next; parent = node;