4343#define CTL_QUERY_NODE_SEPARATOR "."
4444#define CTL_VALUE_ARG_SEPARATOR ","
4545
46+ /* GLOBAL TREE */
4647static int ctl_global_first_free = 0 ;
4748static struct ctl_node CTL_NODE (global )[CTL_MAX_ENTRIES ];
4849
@@ -102,6 +103,9 @@ static const struct ctl_node *ctl_find_node(const struct ctl_node *nodes,
102103 * in the main ctl tree.
103104 */
104105 while (node_name != NULL ) {
106+ if (n != NULL && n -> type == CTL_NODE_SUBTREE ) {
107+ break ;
108+ }
105109 char * endptr ;
106110 /*
107111 * Ignore errno from strtol: FreeBSD returns EINVAL if no
@@ -128,6 +132,7 @@ static const struct ctl_node *ctl_find_node(const struct ctl_node *nodes,
128132 break ;
129133 }
130134 }
135+
131136 if (n -> name == NULL ) {
132137 goto error ;
133138 }
@@ -244,21 +249,26 @@ static void ctl_query_cleanup_real_args(const struct ctl_node *n,
244249 */
245250static int ctl_exec_query_read (void * ctx , const struct ctl_node * n ,
246251 enum ctl_query_source source , void * arg ,
247- struct ctl_index_utlist * indexes ) {
252+ struct ctl_index_utlist * indexes , char * extra_name ,
253+ enum ctl_query_type query_type ) {
254+ (void )extra_name , (void )query_type ;
248255 if (arg == NULL ) {
249256 errno = EINVAL ;
250257 return -1 ;
251258 }
252259
253- return n -> cb [CTL_QUERY_READ ](ctx , source , arg , indexes );
260+ assert (MAX_CTL_QUERY_TYPE != query_type );
261+ return n -> cb [CTL_QUERY_READ ](ctx , source , arg , indexes , NULL , MAX_CTL_QUERY_TYPE );
254262}
255263
256264/*
257265 * ctl_exec_query_write -- (internal) calls the write callback of a node
258266 */
259267static int ctl_exec_query_write (void * ctx , const struct ctl_node * n ,
260268 enum ctl_query_source source , void * arg ,
261- struct ctl_index_utlist * indexes ) {
269+ struct ctl_index_utlist * indexes , char * extra_name ,
270+ enum ctl_query_type query_type ) {
271+ (void )extra_name , (void )query_type ;
262272 if (arg == NULL ) {
263273 errno = EINVAL ;
264274 return -1 ;
@@ -269,7 +279,8 @@ static int ctl_exec_query_write(void *ctx, const struct ctl_node *n,
269279 return -1 ;
270280 }
271281
272- int ret = n -> cb [CTL_QUERY_WRITE ](ctx , source , real_arg , indexes );
282+ assert (MAX_CTL_QUERY_TYPE != query_type );
283+ int ret = n -> cb [CTL_QUERY_WRITE ](ctx , source , real_arg , indexes , NULL , MAX_CTL_QUERY_TYPE );
273284 ctl_query_cleanup_real_args (n , real_arg , source );
274285
275286 return ret ;
@@ -280,16 +291,27 @@ static int ctl_exec_query_write(void *ctx, const struct ctl_node *n,
280291 */
281292static int ctl_exec_query_runnable (void * ctx , const struct ctl_node * n ,
282293 enum ctl_query_source source , void * arg ,
283- struct ctl_index_utlist * indexes ) {
284- return n -> cb [CTL_QUERY_RUNNABLE ](ctx , source , arg , indexes );
294+ struct ctl_index_utlist * indexes , char * extra_name ,
295+ enum ctl_query_type query_type ) {
296+ (void )extra_name , (void )query_type ;
297+ assert (MAX_CTL_QUERY_TYPE != query_type );
298+ return n -> cb [CTL_QUERY_RUNNABLE ](ctx , source , arg , indexes , NULL , MAX_CTL_QUERY_TYPE );
299+ }
300+
301+ static int ctl_exec_query_subtree (void * ctx , const struct ctl_node * n ,
302+ enum ctl_query_source source , void * arg ,
303+ struct ctl_index_utlist * indexes , char * extra_name ,
304+ enum ctl_query_type query_type ) {
305+ return n -> cb [CTL_QUERY_SUBTREE ](ctx , source , arg , indexes , extra_name , query_type );
285306}
286307
287308static int (* ctl_exec_query [MAX_CTL_QUERY_TYPE ])(
288309 void * ctx , const struct ctl_node * n , enum ctl_query_source source ,
289- void * arg , struct ctl_index_utlist * indexes ) = {
310+ void * arg , struct ctl_index_utlist * indexes , char * extra_name , enum ctl_query_type query_type ) = {
290311 ctl_exec_query_read ,
291312 ctl_exec_query_write ,
292313 ctl_exec_query_runnable ,
314+ ctl_exec_query_subtree ,
293315};
294316
295317/*
@@ -324,13 +346,13 @@ int ctl_query(struct ctl *ctl, void *ctx, enum ctl_query_source source,
324346 n = ctl_find_node (ctl -> root , name , indexes );
325347 }
326348
327- if (n == NULL || n -> type != CTL_NODE_LEAF || n -> cb [type ] == NULL ) {
349+ if (n == NULL || ( n -> type != CTL_NODE_LEAF && n -> type != CTL_NODE_SUBTREE ) || n -> cb [n -> type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type ] == NULL ) {
328350 errno = EINVAL ;
329351 goto out ;
330352 }
331353
332- ret = ctl_exec_query [ type ]( ctx , n , source , arg , indexes );
333-
354+ char * extra_name = strstr ( name , n -> name );
355+ ret = ctl_exec_query [ n -> type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type ]( ctx , n , source , arg , indexes , extra_name , type );
334356out :
335357 ctl_delete_indexes (indexes );
336358
@@ -594,3 +616,15 @@ int ctl_arg_string(const void *arg, void *dest, size_t dest_size) {
594616
595617 return 0 ;
596618}
619+
620+ void umfCtlGet (const char * name , ...) {
621+ (void )name ;
622+ }
623+
624+ void umfCtlSet (const char * name , ...) {
625+ (void )name ;
626+ }
627+
628+ void umfCtlExec (const char * name , ...) {
629+ (void )name ;
630+ }
0 commit comments