schema tree BUGFIX accessible tree fixes
diff --git a/src/xpath.c b/src/xpath.c
index 55a0f6b..533e2da 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -773,6 +773,7 @@
new->ctx = set->ctx;
new->ctx_node = set->ctx_node;
new->root_type = set->root_type;
+ new->context_op = set->context_op;
new->local_mod = set->local_mod;
new->tree = set->tree;
new->format = set->format;
@@ -5360,14 +5361,15 @@
*
* @param[in] node Node to check.
* @param[in] root_type XPath root node type.
+ * @param[in] context_op XPath operation parent.
* @param[in] node_name Node name in the dictionary to move to, NULL for any node.
* @param[in] moveto_mod Expected module of the node, NULL for any.
* @return LY_ERR (LY_ENOT if node does not match, LY_EINCOMPLETE on unresolved when,
* LY_EINVAL if netither node nor any children match)
*/
static LY_ERR
-moveto_node_check(const struct lyd_node *node, enum lyxp_node_type root_type, const char *node_name,
- const struct lys_module *moveto_mod)
+moveto_node_check(const struct lyd_node *node, enum lyxp_node_type root_type, const struct lysc_node *context_op,
+ const char *node_name, const struct lys_module *moveto_mod)
{
/* module check */
if (moveto_mod && (node->schema->module != moveto_mod)) {
@@ -5377,6 +5379,8 @@
/* context check */
if ((root_type == LYXP_NODE_ROOT_CONFIG) && (node->schema->flags & LYS_CONFIG_R)) {
return LY_EINVAL;
+ } else if (context_op && (node->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && (node->schema != context_op)) {
+ return LY_EINVAL;
}
/* name check */
@@ -5398,13 +5402,14 @@
*
* @param[in] node Schema node to check.
* @param[in] root_type XPath root node type.
+ * @param[in] context_op XPath operation parent.
* @param[in] node_name Node name in the dictionary to move to, NULL for any nodes.
* @param[in] moveto_mod Expected module of the node, NULL for any.
* @return LY_ERR (LY_ENOT if node does not match, LY_EINVAL if neither node nor any children match)
*/
static LY_ERR
-moveto_scnode_check(const struct lysc_node *node, enum lyxp_node_type root_type, const char *node_name,
- const struct lys_module *moveto_mod)
+moveto_scnode_check(const struct lysc_node *node, enum lyxp_node_type root_type, const struct lysc_node *context_op,
+ const char *node_name, const struct lys_module *moveto_mod)
{
/* module check */
if (moveto_mod && (node->module != moveto_mod)) {
@@ -5414,6 +5419,8 @@
/* context check */
if ((root_type == LYXP_NODE_ROOT_CONFIG) && (node->flags & LYS_CONFIG_R)) {
return LY_EINVAL;
+ } else if (context_op && (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && (node != context_op)) {
+ return LY_EINVAL;
}
/* name check */
@@ -5464,7 +5471,7 @@
}
for (sub = siblings; sub; sub = sub->next) {
- rc = moveto_node_check(sub, set->root_type, ncname, mod);
+ rc = moveto_node_check(sub, set->root_type, set->context_op, ncname, mod);
if (rc == LY_SUCCESS) {
if (!replaced) {
set_replace_node(set, sub, 0, LYXP_NODE_ELEM, i);
@@ -5520,6 +5527,10 @@
if ((set->root_type == LYXP_NODE_ROOT_CONFIG) && (scnode->flags & LYS_CONFIG_R)) {
lyxp_set_free_content(set);
goto cleanup;
+ } else if (set->context_op && (scnode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
+ && (scnode != set->context_op)) {
+ lyxp_set_free_content(set);
+ goto cleanup;
}
/* create specific data instance if needed */
@@ -5624,7 +5635,7 @@
iter = NULL;
/* module may not be implemented */
while (mod->implemented && (iter = lys_getnext(iter, NULL, mod->compiled, getnext_opts))) {
- if (!moveto_scnode_check(iter, set->root_type, ncname, mod)) {
+ if (!moveto_scnode_check(iter, set->root_type, set->context_op, ncname, mod)) {
idx = lyxp_set_scnode_insert_node(set, iter, LYXP_NODE_ELEM);
/* we need to prevent these nodes from being considered in this moveto */
if ((idx < orig_used) && (idx > i)) {
@@ -5645,7 +5656,7 @@
} else if (set->val.scnodes[i].type == LYXP_NODE_ELEM) {
iter = NULL;
while ((iter = lys_getnext(iter, start_parent, NULL, getnext_opts))) {
- if (!moveto_scnode_check(iter, set->root_type, ncname, (mod ? mod : set->local_mod))) {
+ if (!moveto_scnode_check(iter, set->root_type, set->context_op, ncname, (mod ? mod : set->local_mod))) {
idx = lyxp_set_scnode_insert_node(set, iter, LYXP_NODE_ELEM);
if ((idx < orig_used) && (idx > i)) {
set->val.scnodes[idx].in_ctx = 2;
@@ -5705,7 +5716,7 @@
/* TREE DFS */
start = set->val.nodes[i].node;
for (elem = next = start; elem; elem = next) {
- rc = moveto_node_check(elem, set->root_type, ncname, mod);
+ rc = moveto_node_check(elem, set->root_type, set->context_op, ncname, mod);
if (!rc) {
/* add matching node into result set */
set_insert_node(&ret_set, elem, 0, LYXP_NODE_ELEM, ret_set.used);
@@ -5800,7 +5811,7 @@
goto next_iter;
}
- rc = moveto_scnode_check(elem, set->root_type, ncname, mod);
+ rc = moveto_scnode_check(elem, set->root_type, set->context_op, ncname, mod);
if (!rc) {
if ((idx = lyxp_set_scnode_dup_node_check(set, elem, LYXP_NODE_ELEM, i)) > -1) {
set->val.scnodes[idx].in_ctx = 1;
@@ -6902,17 +6913,17 @@
prev_lo = ly_log_options(0);
/* parse the predicate(s) */
- LY_CHECK_GOTO(ret = ly_path_parse_predicate(scnode->module->ctx, exp->expr + exp->tok_pos[*tok_idx], pred_len,
+ LY_CHECK_GOTO(ret = ly_path_parse_predicate(scnode->module->ctx, scnode, exp->expr + exp->tok_pos[*tok_idx], pred_len,
LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_SIMPLE, &exp2), cleanup);
/* compile */
switch (format) {
case LYD_SCHEMA:
- ret = ly_path_compile_predicate(scnode->module->ctx, scnode->module, scnode, exp2, &pred_idx, lys_resolve_prefix,
- scnode->module, LYD_SCHEMA, predicates, pred_type);
+ ret = ly_path_compile_predicate(scnode->module->ctx, scnode, scnode->module, scnode, exp2, &pred_idx,
+ lys_resolve_prefix, scnode->module, LYD_SCHEMA, predicates, pred_type);
break;
case LYD_JSON:
- ret = ly_path_compile_predicate(scnode->module->ctx, scnode->module, scnode, exp2, &pred_idx,
+ ret = ly_path_compile_predicate(scnode->module->ctx, scnode, scnode->module, scnode, exp2, &pred_idx,
lydjson_resolve_prefix, NULL, LYD_JSON, predicates, pred_type);
break;
case LYD_XML:
@@ -7050,8 +7061,7 @@
if (i == -1) {
path = lysc_path(set->ctx_scnode, LYSC_PATH_LOG, NULL, 0);
LOGWRN(set->ctx, "Schema node \"%.*s\" not found (%.*s) with context node \"%s\".",
- exp->tok_len[*tok_idx], &exp->expr[exp->tok_pos[*tok_idx]],
- exp->tok_pos[*tok_idx] + exp->tok_len[*tok_idx], exp->expr, path);
+ ncname_len, ncname, ncname - exp->expr, exp->expr, path);
free(path);
}
} else {
@@ -8305,19 +8315,25 @@
static enum lyxp_node_type
lyxp_get_root_type(const struct lyd_node *ctx_node, const struct lysc_node *ctx_scnode, int options)
{
+ const struct lysc_node *op;
+
if (options & LYXP_SCNODE_ALL) {
- if (options & LYXP_SCNODE) {
+ for (op = ctx_scnode; op && !(op->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)); op = op->parent);
+
+ if (op || (options & LYXP_SCNODE)) {
/* general root that can access everything */
return LYXP_NODE_ROOT;
} else if (!ctx_scnode || (ctx_scnode->flags & LYS_CONFIG_W)) {
/* root context node can access only config data (because we said so, it is unspecified) */
return LYXP_NODE_ROOT_CONFIG;
- } else {
- return LYXP_NODE_ROOT;
}
+ return LYXP_NODE_ROOT;
}
- if (!ctx_node || (ctx_node->schema->flags & LYS_CONFIG_W)) {
+ op = ctx_node ? ctx_node->schema : NULL;
+ for (; op && !(op->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)); op = op->parent);
+
+ if (!ctx_node || (!op && (ctx_node->schema->flags & LYS_CONFIG_W))) {
/* root context node can access only config data (because we said so, it is unspecified) */
return LYXP_NODE_ROOT_CONFIG;
}
@@ -8350,6 +8366,9 @@
set->ctx = local_mod->ctx;
set->ctx_node = ctx_node;
set->root_type = lyxp_get_root_type(real_ctx_node, NULL, options);
+ for (set->context_op = ctx_node->schema;
+ set->context_op && !(set->context_op->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF));
+ set->context_op = set->context_op->parent);
set->local_mod = local_mod;
set->tree = tree;
set->format = format;
@@ -8618,6 +8637,9 @@
set->ctx = ctx;
set->ctx_scnode = ctx_scnode;
set->root_type = lyxp_get_root_type(NULL, real_ctx_scnode, options);
+ for (set->context_op = ctx_scnode;
+ set->context_op && !(set->context_op->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF));
+ set->context_op = set->context_op->parent);
set->local_mod = local_mod;
set->format = format;