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,33 @@ 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 ) {
91110 const struct ctl_node * n = NULL ;
92111 char * sptr = NULL ;
93112 char * parse_str = Strdup (name );
@@ -102,6 +121,10 @@ static const struct ctl_node *ctl_find_node(const struct ctl_node *nodes,
102121 * in the main ctl tree.
103122 */
104123 while (node_name != NULL ) {
124+ * name_offset = (int )(node_name - parse_str );
125+ if (n != NULL && n -> type == CTL_NODE_SUBTREE ) {
126+ break ;
127+ }
105128 char * endptr ;
106129 /*
107130 * Ignore errno from strtol: FreeBSD returns EINVAL if no
@@ -128,6 +151,7 @@ static const struct ctl_node *ctl_find_node(const struct ctl_node *nodes,
128151 break ;
129152 }
130153 }
154+
131155 if (n -> name == NULL ) {
132156 goto error ;
133157 }
@@ -244,21 +268,29 @@ static void ctl_query_cleanup_real_args(const struct ctl_node *n,
244268 */
245269static int ctl_exec_query_read (void * ctx , const struct ctl_node * n ,
246270 enum ctl_query_source source , void * arg ,
247- struct ctl_index_utlist * indexes ) {
271+ struct ctl_index_utlist * indexes ,
272+ char * extra_name ,
273+ umf_ctl_query_type query_type ) {
274+ (void )extra_name , (void )query_type ;
248275 if (arg == NULL ) {
249276 errno = EINVAL ;
250277 return -1 ;
251278 }
252279
253- return n -> cb [CTL_QUERY_READ ](ctx , source , arg , indexes );
280+ assert (MAX_CTL_QUERY_TYPE != query_type );
281+ return n -> cb [CTL_QUERY_READ ](ctx , source , arg , indexes , NULL ,
282+ MAX_CTL_QUERY_TYPE );
254283}
255284
256285/*
257286 * ctl_exec_query_write -- (internal) calls the write callback of a node
258287 */
259288static int ctl_exec_query_write (void * ctx , const struct ctl_node * n ,
260289 enum ctl_query_source source , void * arg ,
261- struct ctl_index_utlist * indexes ) {
290+ struct ctl_index_utlist * indexes ,
291+ char * extra_name ,
292+ umf_ctl_query_type query_type ) {
293+ (void )extra_name , (void )query_type ;
262294 if (arg == NULL ) {
263295 errno = EINVAL ;
264296 return -1 ;
@@ -269,7 +301,9 @@ static int ctl_exec_query_write(void *ctx, const struct ctl_node *n,
269301 return -1 ;
270302 }
271303
272- int ret = n -> cb [CTL_QUERY_WRITE ](ctx , source , real_arg , indexes );
304+ assert (MAX_CTL_QUERY_TYPE != query_type );
305+ int ret = n -> cb [CTL_QUERY_WRITE ](ctx , source , real_arg , indexes , NULL ,
306+ MAX_CTL_QUERY_TYPE );
273307 ctl_query_cleanup_real_args (n , real_arg , source );
274308
275309 return ret ;
@@ -280,24 +314,40 @@ static int ctl_exec_query_write(void *ctx, const struct ctl_node *n,
280314 */
281315static int ctl_exec_query_runnable (void * ctx , const struct ctl_node * n ,
282316 enum ctl_query_source source , void * arg ,
283- struct ctl_index_utlist * indexes ) {
284- return n -> cb [CTL_QUERY_RUNNABLE ](ctx , source , arg , indexes );
317+ struct ctl_index_utlist * indexes ,
318+ char * extra_name ,
319+ umf_ctl_query_type query_type ) {
320+ (void )extra_name , (void )query_type ;
321+ assert (MAX_CTL_QUERY_TYPE != query_type );
322+ return n -> cb [CTL_QUERY_RUNNABLE ](ctx , source , arg , indexes , NULL ,
323+ MAX_CTL_QUERY_TYPE );
324+ }
325+
326+ static int ctl_exec_query_subtree (void * ctx , const struct ctl_node * n ,
327+ enum ctl_query_source source , void * arg ,
328+ struct ctl_index_utlist * indexes ,
329+ char * extra_name ,
330+ umf_ctl_query_type query_type ) {
331+ return n -> cb [CTL_QUERY_SUBTREE ](ctx , source , arg , indexes , extra_name ,
332+ query_type );
285333}
286334
287335static int (* ctl_exec_query [MAX_CTL_QUERY_TYPE ])(
288336 void * ctx , const struct ctl_node * n , enum ctl_query_source source ,
289- void * arg , struct ctl_index_utlist * indexes ) = {
337+ void * arg , struct ctl_index_utlist * indexes , char * extra_name ,
338+ umf_ctl_query_type query_type ) = {
290339 ctl_exec_query_read ,
291340 ctl_exec_query_write ,
292341 ctl_exec_query_runnable ,
342+ ctl_exec_query_subtree ,
293343};
294344
295345/*
296346 * ctl_query -- (internal) parses the name and calls the appropriate methods
297347 * from the ctl tree
298348 */
299349int ctl_query (struct ctl * ctl , void * ctx , enum ctl_query_source source ,
300- const char * name , enum ctl_query_type type , void * arg ) {
350+ const char * name , umf_ctl_query_type type , void * arg ) {
301351 if (name == NULL ) {
302352 errno = EINVAL ;
303353 return -1 ;
@@ -315,22 +365,28 @@ int ctl_query(struct ctl *ctl, void *ctx, enum ctl_query_source source,
315365 }
316366
317367 int ret = -1 ;
368+ int name_offset = 0 ;
318369
319- const struct ctl_node * n = ctl_find_node (CTL_NODE (global ), name , indexes );
370+ const struct ctl_node * n =
371+ ctl_find_node (CTL_NODE (global ), name , indexes , & name_offset );
320372
321373 if (n == NULL && ctl ) {
322374 ctl_delete_indexes (indexes );
323375 indexes = NULL ;
324- n = ctl_find_node (ctl -> root , name , indexes );
376+ n = ctl_find_node (ctl -> root , name , indexes , & name_offset );
325377 }
326378
327- if (n == NULL || n -> type != CTL_NODE_LEAF || n -> cb [type ] == NULL ) {
379+ if (n == NULL ||
380+ (n -> type != CTL_NODE_LEAF && n -> type != CTL_NODE_SUBTREE ) ||
381+ n -> cb [n -> type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type ] == NULL ) {
328382 errno = EINVAL ;
329383 goto out ;
330384 }
331385
332- ret = ctl_exec_query [type ](ctx , n , source , arg , indexes );
333-
386+ char * extra_name = (char * )& name [0 ] + name_offset ;
387+ ret =
388+ ctl_exec_query [n -> type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type ](
389+ ctx , n , source , arg , indexes , extra_name , type );
334390out :
335391 ctl_delete_indexes (indexes );
336392
0 commit comments