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,29 @@ 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 ,
253+ char * extra_name ,
254+ enum ctl_query_type query_type ) {
255+ (void )extra_name , (void )query_type ;
248256 if (arg == NULL ) {
249257 errno = EINVAL ;
250258 return -1 ;
251259 }
252260
253- return n -> cb [CTL_QUERY_READ ](ctx , source , arg , indexes );
261+ assert (MAX_CTL_QUERY_TYPE != query_type );
262+ return n -> cb [CTL_QUERY_READ ](ctx , source , arg , indexes , NULL ,
263+ MAX_CTL_QUERY_TYPE );
254264}
255265
256266/*
257267 * ctl_exec_query_write -- (internal) calls the write callback of a node
258268 */
259269static int ctl_exec_query_write (void * ctx , const struct ctl_node * n ,
260270 enum ctl_query_source source , void * arg ,
261- struct ctl_index_utlist * indexes ) {
271+ struct ctl_index_utlist * indexes ,
272+ char * extra_name ,
273+ enum ctl_query_type query_type ) {
274+ (void )extra_name , (void )query_type ;
262275 if (arg == NULL ) {
263276 errno = EINVAL ;
264277 return -1 ;
@@ -269,7 +282,9 @@ static int ctl_exec_query_write(void *ctx, const struct ctl_node *n,
269282 return -1 ;
270283 }
271284
272- int ret = n -> cb [CTL_QUERY_WRITE ](ctx , source , real_arg , indexes );
285+ assert (MAX_CTL_QUERY_TYPE != query_type );
286+ int ret = n -> cb [CTL_QUERY_WRITE ](ctx , source , real_arg , indexes , NULL ,
287+ MAX_CTL_QUERY_TYPE );
273288 ctl_query_cleanup_real_args (n , real_arg , source );
274289
275290 return ret ;
@@ -280,16 +295,32 @@ static int ctl_exec_query_write(void *ctx, const struct ctl_node *n,
280295 */
281296static int ctl_exec_query_runnable (void * ctx , const struct ctl_node * n ,
282297 enum ctl_query_source source , void * arg ,
283- struct ctl_index_utlist * indexes ) {
284- return n -> cb [CTL_QUERY_RUNNABLE ](ctx , source , arg , indexes );
298+ struct ctl_index_utlist * indexes ,
299+ char * extra_name ,
300+ enum ctl_query_type query_type ) {
301+ (void )extra_name , (void )query_type ;
302+ assert (MAX_CTL_QUERY_TYPE != query_type );
303+ return n -> cb [CTL_QUERY_RUNNABLE ](ctx , source , arg , indexes , NULL ,
304+ MAX_CTL_QUERY_TYPE );
305+ }
306+
307+ static int ctl_exec_query_subtree (void * ctx , const struct ctl_node * n ,
308+ enum ctl_query_source source , void * arg ,
309+ struct ctl_index_utlist * indexes ,
310+ char * extra_name ,
311+ enum ctl_query_type query_type ) {
312+ return n -> cb [CTL_QUERY_SUBTREE ](ctx , source , arg , indexes , extra_name ,
313+ query_type );
285314}
286315
287316static int (* ctl_exec_query [MAX_CTL_QUERY_TYPE ])(
288317 void * ctx , const struct ctl_node * n , enum ctl_query_source source ,
289- void * arg , struct ctl_index_utlist * indexes ) = {
318+ void * arg , struct ctl_index_utlist * indexes , char * extra_name ,
319+ enum ctl_query_type query_type ) = {
290320 ctl_exec_query_read ,
291321 ctl_exec_query_write ,
292322 ctl_exec_query_runnable ,
323+ ctl_exec_query_subtree ,
293324};
294325
295326/*
@@ -324,13 +355,17 @@ int ctl_query(struct ctl *ctl, void *ctx, enum ctl_query_source source,
324355 n = ctl_find_node (ctl -> root , name , indexes );
325356 }
326357
327- if (n == NULL || n -> type != CTL_NODE_LEAF || n -> cb [type ] == NULL ) {
358+ if (n == NULL ||
359+ (n -> type != CTL_NODE_LEAF && n -> type != CTL_NODE_SUBTREE ) ||
360+ n -> cb [n -> type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type ] == NULL ) {
328361 errno = EINVAL ;
329362 goto out ;
330363 }
331364
332- ret = ctl_exec_query [type ](ctx , n , source , arg , indexes );
333-
365+ char * extra_name = strstr (name , n -> name );
366+ ret =
367+ ctl_exec_query [n -> type == CTL_NODE_SUBTREE ? CTL_QUERY_SUBTREE : type ](
368+ ctx , n , source , arg , indexes , extra_name , type );
334369out :
335370 ctl_delete_indexes (indexes );
336371
@@ -594,3 +629,9 @@ int ctl_arg_string(const void *arg, void *dest, size_t dest_size) {
594629
595630 return 0 ;
596631}
632+
633+ void umfCtlGet (const char * name , ...) { (void )name ; }
634+
635+ void umfCtlSet (const char * name , ...) { (void )name ; }
636+
637+ void umfCtlExec (const char * name , ...) { (void )name ; }
0 commit comments