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,16 +80,34 @@ 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
84101 *
102+ * Name offset is used to return the offset of the name in the query string.
85103 * The caller is responsible for freeing all of the allocated indexes,
86104 * regardless of the return value.
87105 */
88106static const struct ctl_node * ctl_find_node (const struct ctl_node * nodes ,
89107 const char * name ,
90- struct ctl_index_utlist * indexes ) {
108+ struct ctl_index_utlist * indexes ,
109+ int * name_offset ) {
110+ assert (name_offset != NULL );
91111 const struct ctl_node * n = NULL ;
92112 char * sptr = NULL ;
93113 char * parse_str = Strdup (name );
@@ -102,6 +122,10 @@ static const struct ctl_node *ctl_find_node(const struct ctl_node *nodes,
102122 * in the main ctl tree.
103123 */
104124 while (node_name != NULL ) {
125+ * name_offset = (int )(node_name - parse_str );
126+ if (n != NULL && n -> type == CTL_NODE_SUBTREE ) {
127+ break ;
128+ }
105129 char * endptr ;
106130 /*
107131 * Ignore errno from strtol: FreeBSD returns EINVAL if no
@@ -128,6 +152,7 @@ static const struct ctl_node *ctl_find_node(const struct ctl_node *nodes,
128152 break ;
129153 }
130154 }
155+
131156 if (n -> name == NULL ) {
132157 goto error ;
133158 }
@@ -244,21 +269,29 @@ static void ctl_query_cleanup_real_args(const struct ctl_node *n,
244269 */
245270static int ctl_exec_query_read (void * ctx , const struct ctl_node * n ,
246271 enum ctl_query_source source , void * arg ,
247- struct ctl_index_utlist * indexes ) {
272+ struct ctl_index_utlist * indexes ,
273+ char * extra_name ,
274+ umf_ctl_query_type query_type ) {
275+ (void )extra_name , (void )query_type ;
248276 if (arg == NULL ) {
249277 errno = EINVAL ;
250278 return -1 ;
251279 }
252280
253- return n -> cb [CTL_QUERY_READ ](ctx , source , arg , indexes );
281+ assert (MAX_CTL_QUERY_TYPE != query_type );
282+ return n -> cb [CTL_QUERY_READ ](ctx , source , arg , indexes , NULL ,
283+ MAX_CTL_QUERY_TYPE );
254284}
255285
256286/*
257287 * ctl_exec_query_write -- (internal) calls the write callback of a node
258288 */
259289static int ctl_exec_query_write (void * ctx , const struct ctl_node * n ,
260290 enum ctl_query_source source , void * arg ,
261- struct ctl_index_utlist * indexes ) {
291+ struct ctl_index_utlist * indexes ,
292+ char * extra_name ,
293+ umf_ctl_query_type query_type ) {
294+ (void )extra_name , (void )query_type ;
262295 if (arg == NULL ) {
263296 errno = EINVAL ;
264297 return -1 ;
@@ -269,7 +302,9 @@ static int ctl_exec_query_write(void *ctx, const struct ctl_node *n,
269302 return -1 ;
270303 }
271304
272- int ret = n -> cb [CTL_QUERY_WRITE ](ctx , source , real_arg , indexes );
305+ assert (MAX_CTL_QUERY_TYPE != query_type );
306+ int ret = n -> cb [CTL_QUERY_WRITE ](ctx , source , real_arg , indexes , NULL ,
307+ MAX_CTL_QUERY_TYPE );
273308 ctl_query_cleanup_real_args (n , real_arg , source );
274309
275310 return ret ;
@@ -280,24 +315,40 @@ static int ctl_exec_query_write(void *ctx, const struct ctl_node *n,
280315 */
281316static int ctl_exec_query_runnable (void * ctx , const struct ctl_node * n ,
282317 enum ctl_query_source source , void * arg ,
283- struct ctl_index_utlist * indexes ) {
284- return n -> cb [CTL_QUERY_RUNNABLE ](ctx , source , arg , indexes );
318+ struct ctl_index_utlist * indexes ,
319+ char * extra_name ,
320+ umf_ctl_query_type query_type ) {
321+ (void )extra_name , (void )query_type ;
322+ assert (MAX_CTL_QUERY_TYPE != query_type );
323+ return n -> cb [CTL_QUERY_RUNNABLE ](ctx , source , arg , indexes , NULL ,
324+ MAX_CTL_QUERY_TYPE );
325+ }
326+
327+ static int ctl_exec_query_subtree (void * ctx , const struct ctl_node * n ,
328+ enum ctl_query_source source , void * arg ,
329+ struct ctl_index_utlist * indexes ,
330+ char * extra_name ,
331+ umf_ctl_query_type query_type ) {
332+ return n -> cb [CTL_QUERY_SUBTREE ](ctx , source , arg , indexes , extra_name ,
333+ query_type );
285334}
286335
287336static int (* ctl_exec_query [MAX_CTL_QUERY_TYPE ])(
288337 void * ctx , const struct ctl_node * n , enum ctl_query_source source ,
289- void * arg , struct ctl_index_utlist * indexes ) = {
338+ void * arg , struct ctl_index_utlist * indexes , char * extra_name ,
339+ umf_ctl_query_type query_type ) = {
290340 ctl_exec_query_read ,
291341 ctl_exec_query_write ,
292342 ctl_exec_query_runnable ,
343+ ctl_exec_query_subtree ,
293344};
294345
295346/*
296347 * ctl_query -- (internal) parses the name and calls the appropriate methods
297348 * from the ctl tree
298349 */
299350int ctl_query (struct ctl * ctl , void * ctx , enum ctl_query_source source ,
300- const char * name , enum ctl_query_type type , void * arg ) {
351+ const char * name , umf_ctl_query_type type , void * arg ) {
301352 if (name == NULL ) {
302353 errno = EINVAL ;
303354 return -1 ;
@@ -315,22 +366,28 @@ int ctl_query(struct ctl *ctl, void *ctx, enum ctl_query_source source,
315366 }
316367
317368 int ret = -1 ;
369+ int name_offset = 0 ;
318370
319- const struct ctl_node * n = ctl_find_node (CTL_NODE (global ), name , indexes );
371+ const struct ctl_node * n =
372+ ctl_find_node (CTL_NODE (global ), name , indexes , & name_offset );
320373
321374 if (n == NULL && ctl ) {
322375 ctl_delete_indexes (indexes );
323376 indexes = NULL ;
324- n = ctl_find_node (ctl -> root , name , indexes );
377+ n = ctl_find_node (ctl -> root , name , indexes , & name_offset );
325378 }
326379
327- if (n == NULL || n -> type != CTL_NODE_LEAF || n -> cb [type ] == NULL ) {
380+ if (n == NULL ||
381+ (n -> type != CTL_NODE_LEAF && n -> type != CTL_NODE_SUBTREE ) ||
382+ n -> cb [n -> type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type ] == NULL ) {
328383 errno = EINVAL ;
329384 goto out ;
330385 }
331386
332- ret = ctl_exec_query [type ](ctx , n , source , arg , indexes );
333-
387+ char * extra_name = (char * )& name [0 ] + name_offset ;
388+ ret =
389+ ctl_exec_query [n -> type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type ](
390+ ctx , n , source , arg , indexes , extra_name , type );
334391out :
335392 ctl_delete_indexes (indexes );
336393
0 commit comments