2525#include <string.h>
2626
2727#include "base_alloc/base_alloc_global.h"
28+ #include "umf/base.h"
2829#include "utils/utils_common.h"
2930#include "utlist.h"
3031
4344#define CTL_QUERY_NODE_SEPARATOR "."
4445#define CTL_VALUE_ARG_SEPARATOR ","
4546
47+ /* GLOBAL TREE */
4648static int ctl_global_first_free = 0 ;
4749static struct ctl_node CTL_NODE (global )[CTL_MAX_ENTRIES ];
4850
@@ -78,6 +80,21 @@ char *Strdup(const char *s) {
7880 return p ;
7981}
8082
83+ int umfCtlGet (const char * name , void * ctx , void * arg ) {
84+ return ctl_query (NULL , ctx , CTL_QUERY_PROGRAMMATIC , name , CTL_QUERY_READ ,
85+ arg );
86+ }
87+
88+ int umfCtlSet (const char * name , void * ctx , void * arg ) {
89+ return ctl_query (NULL , ctx , CTL_QUERY_PROGRAMMATIC , name , CTL_QUERY_WRITE ,
90+ arg );
91+ }
92+
93+ int umfCtlExec (const char * name , void * ctx , void * arg ) {
94+ return ctl_query (NULL , ctx , CTL_QUERY_PROGRAMMATIC , name ,
95+ CTL_QUERY_RUNNABLE , arg );
96+ }
97+
8198/*
8299 * ctl_find_node -- (internal) searches for a matching entry point in the
83100 * provided nodes
@@ -102,6 +119,9 @@ static const struct ctl_node *ctl_find_node(const struct ctl_node *nodes,
102119 * in the main ctl tree.
103120 */
104121 while (node_name != NULL ) {
122+ if (n != NULL && n -> type == CTL_NODE_SUBTREE ) {
123+ break ;
124+ }
105125 char * endptr ;
106126 /*
107127 * Ignore errno from strtol: FreeBSD returns EINVAL if no
@@ -128,6 +148,7 @@ static const struct ctl_node *ctl_find_node(const struct ctl_node *nodes,
128148 break ;
129149 }
130150 }
151+
131152 if (n -> name == NULL ) {
132153 goto error ;
133154 }
@@ -244,21 +265,29 @@ static void ctl_query_cleanup_real_args(const struct ctl_node *n,
244265 */
245266static int ctl_exec_query_read (void * ctx , const struct ctl_node * n ,
246267 enum ctl_query_source source , void * arg ,
247- struct ctl_index_utlist * indexes ) {
268+ struct ctl_index_utlist * indexes ,
269+ char * extra_name ,
270+ umf_ctl_query_type query_type ) {
271+ (void )extra_name , (void )query_type ;
248272 if (arg == NULL ) {
249273 errno = EINVAL ;
250274 return -1 ;
251275 }
252276
253- return n -> cb [CTL_QUERY_READ ](ctx , source , arg , indexes );
277+ assert (MAX_CTL_QUERY_TYPE != query_type );
278+ return n -> cb [CTL_QUERY_READ ](ctx , source , arg , indexes , NULL ,
279+ MAX_CTL_QUERY_TYPE );
254280}
255281
256282/*
257283 * ctl_exec_query_write -- (internal) calls the write callback of a node
258284 */
259285static int ctl_exec_query_write (void * ctx , const struct ctl_node * n ,
260286 enum ctl_query_source source , void * arg ,
261- struct ctl_index_utlist * indexes ) {
287+ struct ctl_index_utlist * indexes ,
288+ char * extra_name ,
289+ umf_ctl_query_type query_type ) {
290+ (void )extra_name , (void )query_type ;
262291 if (arg == NULL ) {
263292 errno = EINVAL ;
264293 return -1 ;
@@ -269,7 +298,9 @@ static int ctl_exec_query_write(void *ctx, const struct ctl_node *n,
269298 return -1 ;
270299 }
271300
272- int ret = n -> cb [CTL_QUERY_WRITE ](ctx , source , real_arg , indexes );
301+ assert (MAX_CTL_QUERY_TYPE != query_type );
302+ int ret = n -> cb [CTL_QUERY_WRITE ](ctx , source , real_arg , indexes , NULL ,
303+ MAX_CTL_QUERY_TYPE );
273304 ctl_query_cleanup_real_args (n , real_arg , source );
274305
275306 return ret ;
@@ -280,24 +311,40 @@ static int ctl_exec_query_write(void *ctx, const struct ctl_node *n,
280311 */
281312static int ctl_exec_query_runnable (void * ctx , const struct ctl_node * n ,
282313 enum ctl_query_source source , void * arg ,
283- struct ctl_index_utlist * indexes ) {
284- return n -> cb [CTL_QUERY_RUNNABLE ](ctx , source , arg , indexes );
314+ struct ctl_index_utlist * indexes ,
315+ char * extra_name ,
316+ umf_ctl_query_type query_type ) {
317+ (void )extra_name , (void )query_type ;
318+ assert (MAX_CTL_QUERY_TYPE != query_type );
319+ return n -> cb [CTL_QUERY_RUNNABLE ](ctx , source , arg , indexes , NULL ,
320+ MAX_CTL_QUERY_TYPE );
321+ }
322+
323+ static int ctl_exec_query_subtree (void * ctx , const struct ctl_node * n ,
324+ enum ctl_query_source source , void * arg ,
325+ struct ctl_index_utlist * indexes ,
326+ char * extra_name ,
327+ umf_ctl_query_type query_type ) {
328+ return n -> cb [CTL_QUERY_SUBTREE ](ctx , source , arg , indexes , extra_name ,
329+ query_type );
285330}
286331
287332static int (* ctl_exec_query [MAX_CTL_QUERY_TYPE ])(
288333 void * ctx , const struct ctl_node * n , enum ctl_query_source source ,
289- void * arg , struct ctl_index_utlist * indexes ) = {
334+ void * arg , struct ctl_index_utlist * indexes , char * extra_name ,
335+ umf_ctl_query_type query_type ) = {
290336 ctl_exec_query_read ,
291337 ctl_exec_query_write ,
292338 ctl_exec_query_runnable ,
339+ ctl_exec_query_subtree ,
293340};
294341
295342/*
296343 * ctl_query -- (internal) parses the name and calls the appropriate methods
297344 * from the ctl tree
298345 */
299346int ctl_query (struct ctl * ctl , void * ctx , enum ctl_query_source source ,
300- const char * name , enum ctl_query_type type , void * arg ) {
347+ const char * name , umf_ctl_query_type type , void * arg ) {
301348 if (name == NULL ) {
302349 errno = EINVAL ;
303350 return -1 ;
@@ -324,13 +371,17 @@ int ctl_query(struct ctl *ctl, void *ctx, enum ctl_query_source source,
324371 n = ctl_find_node (ctl -> root , name , indexes );
325372 }
326373
327- if (n == NULL || n -> type != CTL_NODE_LEAF || n -> cb [type ] == NULL ) {
374+ if (n == NULL ||
375+ (n -> type != CTL_NODE_LEAF && n -> type != CTL_NODE_SUBTREE ) ||
376+ n -> cb [n -> type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type ] == NULL ) {
328377 errno = EINVAL ;
329378 goto out ;
330379 }
331380
332- ret = ctl_exec_query [type ](ctx , n , source , arg , indexes );
333-
381+ char * extra_name = strstr (name , n -> name );
382+ ret =
383+ ctl_exec_query [n -> type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type ](
384+ ctx , n , source , arg , indexes , extra_name , type );
334385out :
335386 ctl_delete_indexes (indexes );
336387
0 commit comments