blob: 55276477c4604ea548d8f94069a37fc4fa93e23e [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
Michal Vasko2d162e12015-09-24 14:33:29 +02002 * @file tree_schema.c
Radek Krejcida04f4a2015-05-21 12:54:09 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vasko2d162e12015-09-24 14:33:29 +02004 * @brief Manipulation with libyang schema data structures
Radek Krejcida04f4a2015-05-21 12:54:09 +02005 *
Michal Vasko53b7da02018-02-13 15:28:42 +01006 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
Radek Krejcida04f4a2015-05-21 12:54:09 +02007 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
Radek Krejci54f6fb32016-02-24 12:56:39 +010014
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020015#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020016
Michal Vaskob0bbf5f2018-02-16 09:35:59 +010017#ifdef __APPLE__
18# include <sys/param.h>
19#endif
Radek Krejci812b10a2015-05-28 16:48:25 +020020#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020021#include <ctype.h>
Radek Krejcib051f722016-02-25 15:12:21 +010022#include <limits.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020023#include <stdlib.h>
24#include <sys/mman.h>
Michal Vasko662610a2015-12-07 11:25:45 +010025#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020026#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010027#include <fcntl.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020028#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010029#include <unistd.h>
30#include <errno.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020031
32#include "common.h"
33#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020034#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020035#include "resolve.h"
Michal Vasko88c29542015-11-27 14:57:53 +010036#include "xml.h"
Michal Vasko5b3492c2016-07-20 09:37:40 +020037#include "xpath.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020038#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020039#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020040#include "validation.h"
Pavol Vicanf7cc2852016-03-22 23:27:35 +010041#include "parser_yang.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020042
Radek Krejci8d6b7422017-02-03 14:42:13 +010043static int lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci5138e9f2017-04-12 13:10:46 +020044 int in_grp, int shallow, struct unres_schema *unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020045
Radek Krejci65aca412018-01-24 11:23:06 +010046API const struct lys_node_list *
47lys_is_key(const struct lys_node_leaf *node, uint8_t *index)
48{
49 struct lys_node *parent = (struct lys_node *)node;
50 struct lys_node_list *list;
51 uint8_t i;
52
53 if (!node || node->nodetype != LYS_LEAF) {
54 return NULL;
55 }
56
57 do {
58 parent = lys_parent(parent);
59 } while (parent && parent->nodetype == LYS_USES);
60
61 if (!parent || parent->nodetype != LYS_LIST) {
62 return NULL;
63 }
64
65 list = (struct lys_node_list*)parent;
66 for (i = 0; i < list->keys_size; i++) {
67 if (list->keys[i] == node) {
68 if (index) {
69 (*index) = i;
70 }
71 return list;
72 }
73 }
74 return NULL;
75}
76
Radek Krejci9ff0a922016-07-14 13:08:05 +020077API const struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +010078lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020079{
Radek Krejci9ff0a922016-07-14 13:08:05 +020080 int i;
Radek Krejci48061fb2015-08-05 15:41:07 +020081
Radek Krejci27fe55e2016-09-13 17:13:35 +020082 if (!node) {
83 return NULL;
84 }
85
Radek Krejci48061fb2015-08-05 15:41:07 +020086check:
87 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
88 /* input/output does not have if-feature, so skip them */
89
90 /* check local if-features */
Michal Vaskoc5c26b02016-06-29 11:10:29 +020091 for (i = 0; i < node->iffeature_size; i++) {
Radek Krejci69b8d922016-07-27 13:13:41 +020092 if (!resolve_iffeature(&node->iffeature[i])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +020093 return node;
Radek Krejci48061fb2015-08-05 15:41:07 +020094 }
95 }
96 }
97
98 if (!recursive) {
99 return NULL;
100 }
101
102 /* go through parents */
103 if (node->nodetype == LYS_AUGMENT) {
104 /* go to parent actually means go to the target node */
105 node = ((struct lys_node_augment *)node)->target;
Michal Vasko17549192017-03-13 10:19:33 +0100106 if (!node) {
107 /* unresolved augment, let's say it's enabled */
108 return NULL;
109 }
Radek Krejci48061fb2015-08-05 15:41:07 +0200110 } else if (node->parent) {
111 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +0200112 } else {
113 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +0200114 }
115
Radek Krejci074bf852015-08-19 14:22:16 +0200116 if (recursive == 2) {
117 /* continue only if the node cannot have a data instance */
118 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
119 return NULL;
120 }
121 }
122 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +0200123}
124
Michal Vasko1dca6882015-10-22 14:29:42 +0200125int
Michal Vasko36cbaa42015-12-14 13:15:48 +0100126lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
127 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +0200128{
Radek Krejcic071c542016-01-27 14:57:51 +0100129 const struct lys_node *node, *parent = NULL;
130 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +0100131 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +0200132
Michal Vasko36cbaa42015-12-14 13:15:48 +0100133 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +0200134 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +0200135
Michal Vasko36cbaa42015-12-14 13:15:48 +0100136 /* fill the lengths in case the caller is so indifferent */
137 if (!mod_name_len) {
138 mod_name_len = strlen(mod_name);
139 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200140 if (!nam_len) {
141 nam_len = strlen(name);
142 }
143
Michal Vasko9e635ac2016-10-17 11:44:09 +0200144 while (siblings && (siblings->nodetype == LYS_USES)) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200145 siblings = siblings->child;
146 }
Michal Vasko9e635ac2016-10-17 11:44:09 +0200147 if (!siblings) {
148 /* unresolved uses */
149 return EXIT_FAILURE;
150 }
151
Michal Vasko680f8b42016-10-17 10:27:37 +0200152 if (siblings->nodetype == LYS_GROUPING) {
153 for (node = siblings; (node->nodetype == LYS_GROUPING) && (node->prev != siblings); node = node->prev);
154 if (node->nodetype == LYS_GROUPING) {
155 /* we went through all the siblings, only groupings there - no valid sibling */
156 return EXIT_FAILURE;
157 }
158 /* update siblings to be valid */
159 siblings = node;
160 }
161
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200162 /* set parent correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100163 parent = lys_parent(siblings);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200164
Michal Vasko680f8b42016-10-17 10:27:37 +0200165 /* go up all uses */
166 while (parent && (parent->nodetype == LYS_USES)) {
167 parent = lys_parent(parent);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200168 }
169
Radek Krejcic071c542016-01-27 14:57:51 +0100170 if (!parent) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200171 /* handle situation when there is a top-level uses referencing a foreign grouping */
172 for (node = siblings; lys_parent(node) && (node->nodetype == LYS_USES); node = lys_parent(node));
173 mod = lys_node_module(node);
Michal Vasko1dca6882015-10-22 14:29:42 +0200174 }
175
Radek Krejcic071c542016-01-27 14:57:51 +0100176 /* try to find the node */
177 node = NULL;
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100178 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | LYS_GETNEXT_WITHINOUT))) {
Radek Krejcic071c542016-01-27 14:57:51 +0100179 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100180 /* module name comparison */
181 node_mod_name = lys_node_module(node)->name;
Michal Vaskob42b6972016-06-06 14:21:30 +0200182 if (!ly_strequal(node_mod_name, mod_name, 1) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100183 continue;
184 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200185
Radek Krejcic071c542016-01-27 14:57:51 +0100186 /* direct name check */
Michal Vaskob42b6972016-06-06 14:21:30 +0200187 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100188 if (ret) {
189 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200190 }
Radek Krejcic071c542016-01-27 14:57:51 +0100191 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200192 }
193 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200194 }
195
196 return EXIT_FAILURE;
197}
198
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200199int
Michal Vaskobb520442017-05-23 10:55:18 +0200200lys_getnext_data(const struct lys_module *mod, const struct lys_node *parent, const char *name, int nam_len,
201 LYS_NODE type, const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200202{
Michal Vaskobb520442017-05-23 10:55:18 +0200203 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200204
Michal Vaskobb520442017-05-23 10:55:18 +0200205 assert((mod || parent) && name);
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200206 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
207
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200208 if (!mod) {
Michal Vaskobb520442017-05-23 10:55:18 +0200209 mod = lys_node_module(parent);
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200210 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200211
Michal Vasko4f0dad02016-02-15 14:08:23 +0100212 /* try to find the node */
213 node = NULL;
Michal Vasko24476fa2017-03-08 12:33:48 +0100214 while ((node = lys_getnext(node, parent, mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100215 if (!type || (node->nodetype & type)) {
216 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200217 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100218 continue;
219 }
220
Michal Vasko4f0dad02016-02-15 14:08:23 +0100221 /* direct name check */
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100222 if (!strncmp(node->name, name, nam_len) && !node->name[nam_len]) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100223 if (ret) {
224 *ret = node;
225 }
226 return EXIT_SUCCESS;
227 }
Radek Krejcic071c542016-01-27 14:57:51 +0100228 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200229 }
230
231 return EXIT_FAILURE;
232}
233
Michal Vasko1e62a092015-12-01 12:27:20 +0100234API const struct lys_node *
235lys_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200236{
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100237 const struct lys_node *next, *aug_parent;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100238 struct lys_node **snode;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200239
Michal Vasko75702cd2018-02-12 11:27:09 +0100240 if ((!parent && !module) || (module && module->type) || (parent && (parent->nodetype == LYS_USES) && !(options & LYS_GETNEXT_PARENTUSES))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100241 LOGARG;
Michal Vasko24476fa2017-03-08 12:33:48 +0100242 return NULL;
243 }
244
Radek Krejci8bc87f62015-09-02 16:19:05 +0200245 if (!last) {
246 /* first call */
247
248 /* get know where to start */
249 if (parent) {
250 /* schema subtree */
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100251 snode = lys_child(parent, LYS_UNKNOWN);
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100252 /* do not return anything if the augment does not have any children */
Radek Krejcibb08db32017-07-03 11:29:17 +0200253 if (!snode || !(*snode) || ((parent->nodetype == LYS_AUGMENT) && ((*snode)->parent != parent))) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100254 return NULL;
255 }
256 next = last = *snode;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200257 } else {
258 /* top level data */
Michal Vaskocb45f472018-02-12 10:47:42 +0100259 if (!(options & LYS_GETNEXT_NOSTATECHECK) && (module->disabled || !module->implemented)) {
260 /* nothing to return from a disabled/imported module */
261 return NULL;
262 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200263 next = last = module->data;
264 }
Radek Krejci972724f2016-08-12 15:24:40 +0200265 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
266 /* continue with uses content */
267 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200268 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200269 /* continue after the last returned value */
270 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200271 }
272
273repeat:
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100274 if (parent && (parent->nodetype == LYS_AUGMENT) && next) {
275 /* do not return anything outside the parent augment */
276 aug_parent = next->parent;
277 do {
278 while (aug_parent && (aug_parent->nodetype != LYS_AUGMENT)) {
279 aug_parent = aug_parent->parent;
280 }
281 if (aug_parent) {
282 if (aug_parent == parent) {
283 break;
284 }
285 aug_parent = ((struct lys_node_augment *)aug_parent)->target;
286 }
287
288 } while (aug_parent);
289 if (!aug_parent) {
290 return NULL;
291 }
292 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200293 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200294 if (options & LYS_GETNEXT_WITHGROUPING) {
295 return next;
296 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200297 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200298 }
299
Radek Krejci972724f2016-08-12 15:24:40 +0200300 if (!next) { /* cover case when parent is augment */
301 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200302 /* no next element */
303 return NULL;
304 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200305 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200306 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200307 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200308 } else {
309 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200310 }
311
Michal Vaskocb45f472018-02-12 10:47:42 +0100312 if (!(options & LYS_GETNEXT_NOSTATECHECK) && lys_is_disabled(next, 0)) {
313 next = next->next;
314 goto repeat;
315 }
316
Radek Krejci7f40ce32015-08-12 20:38:46 +0200317 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200318 case LYS_INPUT:
319 case LYS_OUTPUT:
320 if (options & LYS_GETNEXT_WITHINOUT) {
321 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200322 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200323 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200324 } else {
325 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200326 }
Radek Krejci972724f2016-08-12 15:24:40 +0200327 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200328
Michal Vaskoa5835e92015-10-20 15:07:39 +0200329 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200330 if (options & LYS_GETNEXT_WITHCASE) {
331 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200332 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200333 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200334 } else {
335 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200336 }
Radek Krejci972724f2016-08-12 15:24:40 +0200337 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200338
Michal Vasko1dca6882015-10-22 14:29:42 +0200339 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200340 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200341 if (options & LYS_GETNEXT_WITHUSES) {
342 return next;
343 } else if (next->child) {
344 next = next->child;
345 } else {
346 next = next->next;
347 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200348 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200349
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200350 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200351 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200352 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200353 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200354 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200355 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200356 case LYS_LIST:
357 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200358 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200359
Radek Krejci972724f2016-08-12 15:24:40 +0200360 case LYS_CONTAINER:
361 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
362 if (next->child) {
363 /* go into */
364 next = next->child;
365 } else {
366 next = next->next;
367 }
368 goto repeat;
369 } else {
370 return next;
371 }
372
Radek Krejci8bc87f62015-09-02 16:19:05 +0200373 case LYS_CHOICE:
374 if (options & LYS_GETNEXT_WITHCHOICE) {
375 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200376 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200377 /* go into */
378 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200379 } else {
380 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200381 }
Radek Krejci972724f2016-08-12 15:24:40 +0200382 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200383
Radek Krejci7f40ce32015-08-12 20:38:46 +0200384 default:
385 /* we should not be here */
386 return NULL;
387 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200388}
389
Radek Krejcibf285832017-01-26 16:05:41 +0100390void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200391lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200392{
Michal Vaskof75b2772018-03-14 09:55:33 +0100393 struct lys_node *parent, *first, **pp = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +0100394 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200395
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200396 if (!node) {
397 return;
398 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200400 /* unlink from data model if necessary */
401 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100402 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100403 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100404 if (main_module->data == node) {
405 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200406 }
407 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200408
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200409 /* store pointers to important nodes */
410 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200411 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200412 /* handle augments - first, unlink it from the augment parent ... */
413 if (parent->child == node) {
Radek Krejcic9d78692017-08-24 17:17:18 +0200414 parent->child = (node->next && node->next->parent == parent) ? node->next : NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200415 }
Radek Krejcifec2e142017-01-05 15:19:03 +0100416
417 if (parent->flags & LYS_NOTAPPLIED) {
418 /* data are not connected in the target, so we cannot continue with the target as a parent */
419 parent = NULL;
420 } else {
421 /* data are connected in target, so we will continue with the target as a parent */
422 parent = ((struct lys_node_augment *)parent)->target;
423 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200424 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200426 /* unlink from parent */
427 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100428 if (parent->nodetype == LYS_EXT) {
429 pp = (struct lys_node **)lys_ext_complex_get_substmt(lys_snode2stmt(node->nodetype),
430 (struct lys_ext_instance_complex*)parent, NULL);
431 if (*pp == node) {
432 *pp = node->next;
433 }
434 } else if (parent->child == node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200435 parent->child = node->next;
436 }
437 node->parent = NULL;
438 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200440 /* unlink from siblings */
441 if (node->prev == node) {
442 /* there are no more siblings */
443 return;
444 }
445 if (node->next) {
446 node->next->prev = node->prev;
447 } else {
448 /* unlinking the last element */
449 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100450 if (parent->nodetype == LYS_EXT) {
451 first = *(struct lys_node **)pp;
452 } else {
453 first = parent->child;
454 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200455 } else {
456 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200457 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200458 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200459 }
460 }
461 first->prev = node->prev;
462 }
463 if (node->prev->next) {
464 node->prev->next = node->next;
465 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200467 /* clean up the unlinked element */
468 node->next = NULL;
469 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200470}
471
Michal Vasko563ef092015-09-04 13:17:23 +0200472struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100473lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200474{
475 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200476
477 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200478 /* top-level augment, look into module (uses augment is handled correctly below) */
479 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
Radek Krejci115fa882017-03-01 16:15:07 +0100480 par_iter = lys_main_module(par_iter->parent->module)->data;
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200481 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200482 break;
483 }
484 }
485
Michal Vasko38a00412018-03-14 10:01:50 +0100486 if (par_iter->nodetype == LYS_EXT) {
487 /* we are in a top-level extension, search grouping in top-level groupings */
488 par_iter = lys_main_module(par_iter->module)->data;
489 if (!par_iter) {
490 /* not connected yet, wait */
491 return NULL;
492 }
493 } else if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200494 continue;
495 }
496
497 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
498 if (!stop) {
499 stop = par_iter;
500 } else if (iter == stop) {
501 break;
502 }
503 if (iter->nodetype != LYS_GROUPING) {
504 continue;
505 }
506
Radek Krejcif8426a72015-10-31 23:14:03 +0100507 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200508 return (struct lys_node_grp *)iter;
509 }
510 }
511 }
512
Michal Vasko563ef092015-09-04 13:17:23 +0200513 return NULL;
514}
515
Radek Krejci10c760e2015-08-14 14:45:43 +0200516/*
517 * get next grouping in the root's subtree, in the
518 * first call, tha last is NULL
519 */
520static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200521lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200522{
Radek Krejci10c760e2015-08-14 14:45:43 +0200523 struct lys_node *last = (struct lys_node *)lastgrp;
524 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200525
Radek Krejci10c760e2015-08-14 14:45:43 +0200526 assert(root);
527
528 if (!last) {
529 last = root;
530 }
531
532 while (1) {
533 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
534 next = last->child;
535 } else {
536 next = NULL;
537 }
538 if (!next) {
539 if (last == root) {
540 /* we are done */
541 return NULL;
542 }
543
544 /* no children, go to siblings */
545 next = last->next;
546 }
547 while (!next) {
548 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100549 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200550 /* we are done */
551 return NULL;
552 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200553 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100554 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200555 }
556
557 if (next->nodetype == LYS_GROUPING) {
558 return (struct lys_node_grp *)next;
559 }
560
561 last = next;
562 }
563}
564
Michal Vasko0d343d12015-08-24 14:57:36 +0200565/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200566int
Radek Krejci07911992015-08-14 15:13:31 +0200567lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
568{
Michal Vasko563ef092015-09-04 13:17:23 +0200569 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200570 struct lys_node_grp *grp;
Radek Krejcif95b6292017-02-13 15:57:37 +0100571 int down, up;
Radek Krejci07911992015-08-14 15:13:31 +0200572
573 assert(node);
574
575 if (!parent) {
576 assert(module);
577 } else {
578 module = parent->module;
579 }
Radek Krejci115fa882017-03-01 16:15:07 +0100580 module = lys_main_module(module);
Radek Krejci07911992015-08-14 15:13:31 +0200581
582 switch (node->nodetype) {
583 case LYS_GROUPING:
584 /* 6.2.1, rule 6 */
585 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100586 start = *lys_child(parent, LYS_GROUPING);
587 if (!start) {
Radek Krejci07911992015-08-14 15:13:31 +0200588 down = 0;
589 start = parent;
Radek Krejcif95b6292017-02-13 15:57:37 +0100590 } else {
591 down = 1;
592 }
593 if (parent->nodetype == LYS_EXT) {
594 up = 0;
595 } else {
596 up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200597 }
598 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100599 down = up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200600 start = module->data;
601 }
602 /* go up */
Radek Krejcif95b6292017-02-13 15:57:37 +0100603 if (up && lys_find_grouping_up(node->name, start)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100604 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200605 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200606 }
607 /* go down, because grouping can be defined after e.g. container in which is collision */
608 if (down) {
609 for (iter = start, stop = NULL; iter; iter = iter->prev) {
610 if (!stop) {
611 stop = start;
612 } else if (iter == stop) {
613 break;
614 }
615 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
616 continue;
617 }
618
619 grp = NULL;
620 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100621 if (ly_strequal(node->name, grp->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100622 LOGVAL(module->ctx, LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200623 return EXIT_FAILURE;
624 }
625 }
626 }
627 }
628 break;
629 case LYS_LEAF:
630 case LYS_LEAFLIST:
631 case LYS_LIST:
632 case LYS_CONTAINER:
633 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200634 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200635 /* 6.2.1, rule 7 */
636 if (parent) {
637 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200638 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
639 if (iter->nodetype == LYS_AUGMENT) {
640 if (((struct lys_node_augment *)iter)->target) {
641 /* augment is resolved, go up */
642 iter = ((struct lys_node_augment *)iter)->target;
643 continue;
644 }
645 /* augment is not resolved, this is the final parent */
646 break;
647 }
Radek Krejci07911992015-08-14 15:13:31 +0200648 iter = iter->parent;
649 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200650
Radek Krejci07911992015-08-14 15:13:31 +0200651 if (!iter) {
652 stop = NULL;
653 iter = module->data;
Radek Krejcif95b6292017-02-13 15:57:37 +0100654 } else if (iter->nodetype == LYS_EXT) {
655 stop = iter;
PavolVican9d61d402018-02-05 15:52:48 +0100656 iter = (struct lys_node *)lys_child(iter, node->nodetype);
657 if (iter) {
658 iter = *(struct lys_node **)iter;
659 }
Radek Krejci07911992015-08-14 15:13:31 +0200660 } else {
661 stop = iter;
662 iter = iter->child;
663 }
664 } else {
665 stop = NULL;
666 iter = module->data;
667 }
668 while (iter) {
669 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
670 iter = iter->child;
671 continue;
672 }
673
Radek Krejcibf2abff2016-08-23 15:51:52 +0200674 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100675 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100676 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200677 return EXIT_FAILURE;
678 }
679 }
680
681 /* special case for choice - we must check the choice's name as
682 * well as the names of nodes under the choice
683 */
684 if (iter->nodetype == LYS_CHOICE) {
685 iter = iter->child;
686 continue;
687 }
688
689 /* go to siblings */
690 if (!iter->next) {
691 /* no sibling, go to parent's sibling */
692 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200693 /* for parent LYS_AUGMENT */
694 if (iter->parent == stop) {
695 iter = stop;
696 break;
697 }
698 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200699 if (iter && iter->next) {
700 break;
701 }
702 } while (iter != stop);
703
704 if (iter == stop) {
705 break;
706 }
707 }
708 iter = iter->next;
709 }
710 break;
711 case LYS_CASE:
712 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100713 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100714 start = *lys_child(parent, LYS_CASE);
Radek Krejcic071c542016-01-27 14:57:51 +0100715 } else {
716 start = module->data;
717 }
718
719 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200720 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200721 continue;
722 }
723
Radek Krejci749190d2016-02-18 16:26:25 +0100724 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100725 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200726 return EXIT_FAILURE;
727 }
728 }
729 break;
730 default:
731 /* no check needed */
732 break;
733 }
734
735 return EXIT_SUCCESS;
736}
737
Michal Vasko0d343d12015-08-24 14:57:36 +0200738/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200739int
Radek Krejci10c760e2015-08-14 14:45:43 +0200740lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
741{
Michal Vasko53b7da02018-02-13 15:28:42 +0100742 struct ly_ctx *ctx = child->module->ctx;
Radek Krejcic9d78692017-08-24 17:17:18 +0200743 struct lys_node *iter, **pchild;
Radek Krejci41a349b2016-10-24 19:21:59 +0200744 struct lys_node_inout *in, *out, *inout;
Radek Krejci744c2d42017-03-26 13:30:00 -0500745 struct lys_node_case *c;
746 int type, shortcase = 0;
Radek Krejcif95b6292017-02-13 15:57:37 +0100747 void *p;
748 struct lyext_substmt *info = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200750 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200751
Radek Krejci10c760e2015-08-14 14:45:43 +0200752 if (parent) {
753 type = parent->nodetype;
754 module = parent->module;
755 } else {
756 assert(module);
Radek Krejcife3a1382016-11-04 10:30:11 +0100757 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
Radek Krejci10c760e2015-08-14 14:45:43 +0200758 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200759 }
760
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200761 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200762 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200763 case LYS_CONTAINER:
764 case LYS_LIST:
765 case LYS_GROUPING:
Radek Krejci96935402016-11-04 16:27:28 +0100766 case LYS_USES:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200767 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200768 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200769 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100770 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200771 return EXIT_FAILURE;
772 }
773 break;
Radek Krejci76512572015-08-04 09:47:08 +0200774 case LYS_INPUT:
775 case LYS_OUTPUT:
776 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200777 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200778 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200779 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100780 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200781 return EXIT_FAILURE;
782 }
783 break;
Radek Krejci76512572015-08-04 09:47:08 +0200784 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200785 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200786 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100787 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200788 return EXIT_FAILURE;
789 }
Radek Krejci744c2d42017-03-26 13:30:00 -0500790 if (child->nodetype != LYS_CASE) {
791 shortcase = 1;
792 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200793 break;
Radek Krejci76512572015-08-04 09:47:08 +0200794 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200795 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200796 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100797 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200798 return EXIT_FAILURE;
799 }
800 break;
Radek Krejci76512572015-08-04 09:47:08 +0200801 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200802 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200803 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100804 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200805 return EXIT_FAILURE;
806 }
807 break;
Radek Krejci76512572015-08-04 09:47:08 +0200808 case LYS_LEAF:
809 case LYS_LEAFLIST:
810 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200811 case LYS_ANYDATA:
Michal Vasko53b7da02018-02-13 15:28:42 +0100812 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
813 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100814 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200815 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200816 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200817 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200818 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskodb017262017-01-24 13:10:04 +0100819 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100820 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200821 return EXIT_FAILURE;
822 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200823 break;
824 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200825 /* top level */
826 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200827 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200828 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100829 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200830 return EXIT_FAILURE;
831 }
Radek Krejcif95b6292017-02-13 15:57:37 +0100832 break;
833 case LYS_EXT:
834 /* plugin-defined */
835 p = lys_ext_complex_get_substmt(lys_snode2stmt(child->nodetype), (struct lys_ext_instance_complex*)parent, &info);
836 if (!p) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100837 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype),
Radek Krejcif95b6292017-02-13 15:57:37 +0100838 ((struct lys_ext_instance_complex*)parent)->def->name);
839 return EXIT_FAILURE;
840 }
841 /* TODO check cardinality */
Radek Krejcic071c542016-01-27 14:57:51 +0100842 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200843 }
844
845 /* check identifier uniqueness */
Michal Vasko15a43372017-09-25 14:12:42 +0200846 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && lys_check_id(child, parent, module)) {
Radek Krejci07911992015-08-14 15:13:31 +0200847 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200848 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200850 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200851 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200852 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200853
Radek Krejcif95b6292017-02-13 15:57:37 +0100854 if ((child->nodetype & (LYS_INPUT | LYS_OUTPUT)) && parent->nodetype != LYS_EXT) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200855 /* replace the implicit input/output node */
856 if (child->nodetype == LYS_OUTPUT) {
857 inout = (struct lys_node_inout *)parent->child->next;
858 } else { /* LYS_INPUT */
859 inout = (struct lys_node_inout *)parent->child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200860 parent->child = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200861 }
862 if (inout->next) {
863 child->next = inout->next;
864 inout->next->prev = child;
865 inout->next = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200866 } else {
Radek Krejci41a349b2016-10-24 19:21:59 +0200867 parent->child->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200868 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200869 child->prev = inout->prev;
870 if (inout->prev->next) {
871 inout->prev->next = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200872 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200873 inout->prev = (struct lys_node *)inout;
874 child->parent = parent;
875 inout->parent = NULL;
876 lys_node_free((struct lys_node *)inout, NULL, 0);
877 } else {
Radek Krejci744c2d42017-03-26 13:30:00 -0500878 if (shortcase) {
879 /* create the implicit case to allow it to serve as a target of the augments,
880 * it won't be printed, but it will be present in the tree */
881 c = calloc(1, sizeof *c);
Michal Vasko53b7da02018-02-13 15:28:42 +0100882 LY_CHECK_ERR_RETURN(!c, LOGMEM(ctx), EXIT_FAILURE);
Radek Krejci744c2d42017-03-26 13:30:00 -0500883 c->name = lydict_insert(module->ctx, child->name, 0);
884 c->flags = LYS_IMPLICIT;
885 c->module = module;
886 c->nodetype = LYS_CASE;
887 c->prev = (struct lys_node*)c;
888 lys_node_addchild(parent, module, (struct lys_node*)c);
889 parent = (struct lys_node*)c;
890 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200891 /* connect the child correctly */
892 if (!parent) {
893 if (module->data) {
894 module->data->prev->next = child;
895 child->prev = module->data->prev;
896 module->data->prev = child;
897 } else {
898 module->data = child;
899 }
900 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100901 pchild = lys_child(parent, child->nodetype);
902 assert(pchild);
903
Radek Krejcic9d78692017-08-24 17:17:18 +0200904 child->parent = parent;
Radek Krejcif95b6292017-02-13 15:57:37 +0100905 if (!(*pchild)) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200906 /* the only/first child of the parent */
Radek Krejcif95b6292017-02-13 15:57:37 +0100907 *pchild = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200908 iter = child;
909 } else {
910 /* add a new child at the end of parent's child list */
Radek Krejcif95b6292017-02-13 15:57:37 +0100911 iter = (*pchild)->prev;
Radek Krejci41a349b2016-10-24 19:21:59 +0200912 iter->next = child;
913 child->prev = iter;
914 }
915 while (iter->next) {
916 iter = iter->next;
917 iter->parent = parent;
918 }
Radek Krejcic9d78692017-08-24 17:17:18 +0200919 (*pchild)->prev = iter;
Radek Krejci41a349b2016-10-24 19:21:59 +0200920 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200921 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200922
Michal Vaskoe022a562016-09-27 14:24:15 +0200923 /* check config value (but ignore them in groupings and augments) */
Radek Krejcif95b6292017-02-13 15:57:37 +0100924 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); iter = iter->parent);
Michal Vaskoe022a562016-09-27 14:24:15 +0200925 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200926 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
927 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100928 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, child, "true", "config");
929 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200930 return EXIT_FAILURE;
931 }
932 }
933
Radek Krejci41771502016-04-14 17:52:32 +0200934 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200935 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200936 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200937 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200938 /* store it only into container or list - the only data inner nodes */
939 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
940 if (iter->flags & LYS_INCL_STATUS) {
941 /* done, someone else set it already from here */
942 break;
943 }
944 /* set flag about including status data */
945 iter->flags |= LYS_INCL_STATUS;
946 }
947 }
948 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200949
950 /* create implicit input/output nodes to have available them as possible target for augment */
Radek Krejci60251232017-08-24 17:13:08 +0200951 if ((child->nodetype & (LYS_RPC | LYS_ACTION)) && !child->child) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200952 in = calloc(1, sizeof *in);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200953 out = calloc(1, sizeof *out);
954 if (!in || !out) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100955 LOGMEM(ctx);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200956 free(in);
957 free(out);
958 return EXIT_FAILURE;
959 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200960 in->nodetype = LYS_INPUT;
961 in->name = lydict_insert(child->module->ctx, "input", 5);
Radek Krejci41a349b2016-10-24 19:21:59 +0200962 out->nodetype = LYS_OUTPUT;
Radek Krejcia8d111f2017-05-31 13:57:37 +0200963 out->name = lydict_insert(child->module->ctx, "output", 6);
Radek Krejci41a349b2016-10-24 19:21:59 +0200964 in->module = out->module = child->module;
965 in->parent = out->parent = child;
966 in->flags = out->flags = LYS_IMPLICIT;
967 in->next = (struct lys_node *)out;
968 in->prev = (struct lys_node *)out;
969 out->prev = (struct lys_node *)in;
970 child->child = (struct lys_node *)in;
971 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200972 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200973}
974
Michal Vasko29245662017-04-18 15:56:31 +0200975const struct lys_module *
Michal Vaskofb98dc42018-01-11 13:38:28 +0100976lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, const char *revision, int internal, int implement)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200977{
Radek Krejcia1df1682016-04-11 14:56:59 +0200978 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200979 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200980 unsigned int len;
Radek Krejcif347abc2016-06-22 10:18:47 +0200981
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200982 if (!ctx || !data) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100983 LOGARG;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200984 return NULL;
985 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200986
Radek Krejcia1df1682016-04-11 14:56:59 +0200987 if (!internal && format == LYS_IN_YANG) {
988 /* enlarge data by 2 bytes for flex */
989 len = strlen(data);
990 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
Michal Vasko53b7da02018-02-13 15:28:42 +0100991 LY_CHECK_ERR_RETURN(!enlarged_data, LOGMEM(ctx), NULL);
Radek Krejcia1df1682016-04-11 14:56:59 +0200992 memcpy(enlarged_data, data, len);
993 enlarged_data[len] = enlarged_data[len + 1] = '\0';
994 data = enlarged_data;
995 }
996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200997 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200998 case LYS_IN_YIN:
Michal Vaskofb98dc42018-01-11 13:38:28 +0100999 mod = yin_read_module(ctx, data, revision, implement);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001000 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001001 case LYS_IN_YANG:
Michal Vaskofb98dc42018-01-11 13:38:28 +01001002 mod = yang_read_module(ctx, data, 0, revision, implement);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001003 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001004 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001005 LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001006 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001007 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001008
Radek Krejcia1df1682016-04-11 14:56:59 +02001009 free(enlarged_data);
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001010
1011 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
1012 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
1013 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
1014 * the anotation definitions available in the internal schema structure. There is another hack in schema
1015 * printers to do not print this internally added annotation. */
1016 if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
Radek Krejci5b190662017-04-13 08:56:14 +02001017 if (lyp_add_ietf_netconf_annotations(mod)) {
Michal Vasko10681e82018-01-16 14:54:16 +01001018 lys_free(mod, NULL, 1, 1);
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001019 return NULL;
1020 }
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001021 }
1022
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001023 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001024}
1025
Radek Krejcia1df1682016-04-11 14:56:59 +02001026API const struct lys_module *
1027lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
1028{
Michal Vaskofb98dc42018-01-11 13:38:28 +01001029 return lys_parse_mem_(ctx, data, format, NULL, 0, 1);
Radek Krejcia1df1682016-04-11 14:56:59 +02001030}
1031
Michal Vasko5a721fd2016-02-16 12:16:48 +01001032struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001033lys_sub_parse_mem(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001034{
Michal Vasko5b998712017-01-26 10:34:06 +01001035 char *enlarged_data = NULL;
Michal Vasko5a721fd2016-02-16 12:16:48 +01001036 struct lys_submodule *submod = NULL;
Michal Vasko5b998712017-01-26 10:34:06 +01001037 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001039 assert(module);
1040 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001041
Michal Vasko5b998712017-01-26 10:34:06 +01001042 if (format == LYS_IN_YANG) {
1043 /* enlarge data by 2 bytes for flex */
1044 len = strlen(data);
1045 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
Michal Vasko53b7da02018-02-13 15:28:42 +01001046 LY_CHECK_ERR_RETURN(!enlarged_data, LOGMEM(module->ctx), NULL);
Michal Vasko5b998712017-01-26 10:34:06 +01001047 memcpy(enlarged_data, data, len);
1048 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1049 data = enlarged_data;
1050 }
1051
Radek Krejcic071c542016-01-27 14:57:51 +01001052 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +02001053 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001055 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001056 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001057 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001058 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001059 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001060 submod = yang_read_submodule(module, data, 0, unres);
1061 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001062 default:
Radek Krejci90a550a2016-04-13 16:00:58 +02001063 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001064 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001065 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001066
Michal Vasko5b998712017-01-26 10:34:06 +01001067 free(enlarged_data);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001068 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001069}
1070
Michal Vasko1e62a092015-12-01 12:27:20 +01001071API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001072lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1073{
1074 int fd;
1075 const struct lys_module *ret;
Radek Krejcid80c8602016-10-25 11:56:03 +02001076 const char *rev, *dot, *filename;
1077 size_t len;
Michal Vasko662610a2015-12-07 11:25:45 +01001078
1079 if (!ctx || !path) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001080 LOGARG;
Michal Vasko662610a2015-12-07 11:25:45 +01001081 return NULL;
1082 }
1083
1084 fd = open(path, O_RDONLY);
1085 if (fd == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001086 LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
Michal Vasko662610a2015-12-07 11:25:45 +01001087 return NULL;
1088 }
1089
1090 ret = lys_parse_fd(ctx, fd, format);
1091 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +01001092
Radek Krejcid80c8602016-10-25 11:56:03 +02001093 if (!ret) {
1094 /* error */
1095 return NULL;
1096 }
1097
1098 /* check that name and revision match filename */
1099 filename = strrchr(path, '/');
1100 if (!filename) {
1101 filename = path;
1102 } else {
1103 filename++;
1104 }
1105 rev = strchr(filename, '@');
1106 dot = strrchr(filename, '.');
1107
1108 /* name */
1109 len = strlen(ret->name);
1110 if (strncmp(filename, ret->name, len) ||
1111 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001112 LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, ret->name);
Radek Krejcid80c8602016-10-25 11:56:03 +02001113 }
1114 if (rev) {
1115 len = dot - ++rev;
1116 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001117 LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", filename,
Radek Krejcid80c8602016-10-25 11:56:03 +02001118 ret->rev_size ? ret->rev[0].date : "none");
1119 }
1120 }
1121
1122 if (!ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001123 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +01001124 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +01001125 }
1126
Michal Vasko662610a2015-12-07 11:25:45 +01001127 return ret;
1128}
1129
1130API const struct lys_module *
1131lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001132{
Michal Vaskofb98dc42018-01-11 13:38:28 +01001133 return lys_parse_fd_(ctx, fd, format, NULL, 1);
1134}
1135
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001136static void
1137lys_parse_set_filename(struct ly_ctx *ctx, const char **filename, int fd)
1138{
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001139#ifdef __APPLE__
1140 char path[MAXPATHLEN];
1141#else
Michal Vasko25601f32018-02-16 09:41:46 +01001142 int len;
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001143 char path[PATH_MAX], proc_path[32];
1144#endif
1145
1146#ifdef __APPLE__
1147 if (fcntl(fd, F_GETPATH, path) != -1) {
1148 *filename = lydict_insert(ctx, path, 0);
1149 }
1150#else
1151 /* get URI if there is /proc */
1152 sprintf(proc_path, "/proc/self/fd/%d", fd);
1153 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
1154 *filename = lydict_insert(ctx, path, len);
1155 }
1156#endif
1157}
1158
Michal Vaskofb98dc42018-01-11 13:38:28 +01001159const struct lys_module *
1160lys_parse_fd_(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, const char *revision, int implement)
1161{
Michal Vasko1e62a092015-12-01 12:27:20 +01001162 const struct lys_module *module;
Radek Krejci0fb11502017-01-31 16:45:42 +01001163 size_t length;
Radek Krejci63a91a92015-07-29 13:31:04 +02001164 char *addr;
1165
1166 if (!ctx || fd < 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001167 LOGARG;
Radek Krejci63a91a92015-07-29 13:31:04 +02001168 return NULL;
1169 }
1170
Michal Vasko53b7da02018-02-13 15:28:42 +01001171 if (lyp_mmap(ctx, fd, format == LYS_IN_YANG ? 1 : 0, &length, (void **)&addr)) {
1172 LOGERR(ctx, LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001173 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001174 } else if (!addr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001175 LOGERR(ctx, LY_EINVAL, "Empty schema file.");
Pavol Vicane36ea262015-11-12 11:57:47 +01001176 return NULL;
1177 }
Radek Krejci0fb11502017-01-31 16:45:42 +01001178
Michal Vaskofb98dc42018-01-11 13:38:28 +01001179 module = lys_parse_mem_(ctx, addr, format, revision, 1, implement);
Radek Krejci0fb11502017-01-31 16:45:42 +01001180 lyp_munmap(addr, length);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001181
Radek Krejcia77904e2016-02-25 16:23:45 +01001182 if (module && !module->filepath) {
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001183 lys_parse_set_filename(ctx, (const char **)&module->filepath, fd);
Radek Krejcib051f722016-02-25 15:12:21 +01001184 }
1185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001186 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001187}
1188
Michal Vasko5a721fd2016-02-16 12:16:48 +01001189struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001190lys_sub_parse_fd(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001191{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001192 struct lys_submodule *submodule;
Radek Krejci0fb11502017-01-31 16:45:42 +01001193 size_t length;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001194 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001195
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001196 assert(module);
1197 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001198
Michal Vasko53b7da02018-02-13 15:28:42 +01001199 if (lyp_mmap(module->ctx, fd, format == LYS_IN_YANG ? 1 : 0, &length, (void **)&addr)) {
1200 LOGERR(module->ctx, LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001201 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001202 } else if (!addr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001203 LOGERR(module->ctx, LY_EINVAL, "Empty submodule schema file.");
Michal Vasko2e7241e2016-02-15 16:06:34 +01001204 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001205 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001206
Michal Vasko5b998712017-01-26 10:34:06 +01001207 /* get the main module */
1208 module = lys_main_module(module);
1209
1210 switch (format) {
1211 case LYS_IN_YIN:
1212 submodule = yin_read_submodule(module, addr, unres);
1213 break;
1214 case LYS_IN_YANG:
1215 submodule = yang_read_submodule(module, addr, 0, unres);
1216 break;
1217 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001218 LOGINT(module->ctx);
Michal Vasko85d41522017-02-24 09:49:16 +01001219 return NULL;
Michal Vasko5b998712017-01-26 10:34:06 +01001220 }
1221
Radek Krejcic645a3a2017-01-31 16:59:00 +01001222 lyp_munmap(addr, length);
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001223
1224 if (submodule && !submodule->filepath) {
1225 lys_parse_set_filename(module->ctx, (const char **)&submodule->filepath, fd);
1226 }
1227
Michal Vasko5a721fd2016-02-16 12:16:48 +01001228 return submodule;
1229
Radek Krejciefaeba32015-05-27 14:30:57 +02001230}
1231
Radek Krejcibf285832017-01-26 16:05:41 +01001232int
1233lys_ext_iter(struct lys_ext_instance **ext, uint8_t ext_size, uint8_t start, LYEXT_SUBSTMT substmt)
1234{
1235 unsigned int u;
1236
1237 for (u = start; u < ext_size; u++) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001238 if (ext[u]->insubstmt == substmt) {
Radek Krejcibf285832017-01-26 16:05:41 +01001239 return u;
1240 }
1241 }
1242
1243 return -1;
1244}
1245
Radek Krejcifdc0d702017-01-23 15:58:38 +01001246/*
1247 * duplicate extension instance
1248 */
1249int
Michal Vasko17e8ba32018-02-15 10:58:56 +01001250lys_ext_dup(struct ly_ctx *ctx, struct lys_module *mod, struct lys_ext_instance **orig, uint8_t size, void *parent,
1251 LYEXT_PAR parent_type, struct lys_ext_instance ***new, int shallow, struct unres_schema *unres)
Radek Krejcifdc0d702017-01-23 15:58:38 +01001252{
1253 int i;
1254 uint8_t u = 0;
1255 struct lys_ext_instance **result;
1256 struct unres_ext *info, *info_orig;
fanchanghu8d86f6b2017-06-10 12:49:54 +08001257 size_t len;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001258
1259 assert(new);
1260
1261 if (!size) {
1262 if (orig) {
Michal Vasko17e8ba32018-02-15 10:58:56 +01001263 LOGINT(ctx);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001264 return EXIT_FAILURE;
1265 }
1266 (*new) = NULL;
1267 return EXIT_SUCCESS;
1268 }
1269
1270 (*new) = result = calloc(size, sizeof *result);
Michal Vasko17e8ba32018-02-15 10:58:56 +01001271 LY_CHECK_ERR_RETURN(!result, LOGMEM(ctx), EXIT_FAILURE);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001272 for (u = 0; u < size; u++) {
1273 if (orig[u]) {
1274 /* resolved extension instance, just duplicate it */
Radek Krejci8de8f612017-02-16 15:03:32 +01001275 switch(orig[u]->ext_type) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001276 case LYEXT_FLAG:
1277 result[u] = malloc(sizeof(struct lys_ext_instance));
Michal Vasko17e8ba32018-02-15 10:58:56 +01001278 LY_CHECK_ERR_GOTO(!result[u], LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001279 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001280 case LYEXT_COMPLEX:
fanchanghu8d86f6b2017-06-10 12:49:54 +08001281 len = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->instance_size;
1282 result[u] = calloc(1, len);
Michal Vasko17e8ba32018-02-15 10:58:56 +01001283 LY_CHECK_ERR_GOTO(!result[u], LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001284
Radek Krejcifebdad72017-02-06 11:35:51 +01001285 ((struct lys_ext_instance_complex*)result[u])->substmt = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001286 /* TODO duplicate data in extension instance content */
fanchanghu8d86f6b2017-06-10 12:49:54 +08001287 memcpy((void*)result[u] + sizeof(**orig), (void*)orig[u] + sizeof(**orig), len - sizeof(**orig));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001288 break;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001289 }
1290 /* generic part */
1291 result[u]->def = orig[u]->def;
fanchanghu8d86f6b2017-06-10 12:49:54 +08001292 result[u]->flags = LYEXT_OPT_CONTENT;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001293 result[u]->arg_value = lydict_insert(ctx, orig[u]->arg_value, 0);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001294 result[u]->parent = parent;
1295 result[u]->parent_type = parent_type;
Radek Krejcifebdad72017-02-06 11:35:51 +01001296 result[u]->insubstmt = orig[u]->insubstmt;
1297 result[u]->insubstmt_index = orig[u]->insubstmt_index;
Radek Krejci8de8f612017-02-16 15:03:32 +01001298 result[u]->ext_type = orig[u]->ext_type;
Radek Krejci7f1d47e2017-04-12 15:29:02 +02001299 result[u]->priv = NULL;
1300 result[u]->nodetype = LYS_EXT;
1301 result[u]->module = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001302
1303 /* extensions */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001304 result[u]->ext_size = orig[u]->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001305 if (lys_ext_dup(ctx, mod, orig[u]->ext, orig[u]->ext_size, result[u],
Radek Krejci5138e9f2017-04-12 13:10:46 +02001306 LYEXT_PAR_EXTINST, &result[u]->ext, shallow, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001307 goto error;
1308 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02001309
1310 /* in case of shallow copy (duplication for deviation), duplicate only the link to private data
1311 * in a new copy, otherwise (grouping instantiation) do not duplicate the private data */
1312 if (shallow) {
1313 result[u]->priv = orig[u]->priv;
1314 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01001315 } else {
1316 /* original extension is not yet resolved, so duplicate it in unres */
1317 i = unres_schema_find(unres, -1, &orig, UNRES_EXT);
1318 if (i == -1) {
1319 /* extension not found in unres */
Michal Vasko17e8ba32018-02-15 10:58:56 +01001320 LOGINT(ctx);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001321 goto error;
1322 }
1323 info_orig = unres->str_snode[i];
1324 info = malloc(sizeof *info);
Michal Vasko17e8ba32018-02-15 10:58:56 +01001325 LY_CHECK_ERR_GOTO(!info, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001326 info->datatype = info_orig->datatype;
1327 if (info->datatype == LYS_IN_YIN) {
Michal Vasko17e8ba32018-02-15 10:58:56 +01001328 info->data.yin = lyxml_dup_elem(ctx, info_orig->data.yin, NULL, 1);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001329 } /* else TODO YANG */
1330 info->parent = parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001331 info->mod = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001332 info->parent_type = parent_type;
1333 info->ext_index = u;
1334 if (unres_schema_add_node(info->mod, unres, new, UNRES_EXT, (struct lys_node *)info) == -1) {
1335 goto error;
1336 }
1337 }
1338 }
1339
1340 return EXIT_SUCCESS;
1341
1342error:
1343 (*new) = NULL;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001344 lys_extension_instances_free(ctx, result, u, NULL);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001345 return EXIT_FAILURE;
1346}
1347
Radek Krejci1d82ef62015-08-07 14:44:40 +02001348static struct lys_restr *
Radek Krejci5138e9f2017-04-12 13:10:46 +02001349lys_restr_dup(struct lys_module *mod, struct lys_restr *old, int size, int shallow, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001350{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001351 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001352 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001353
Radek Krejci3733a802015-06-19 13:43:21 +02001354 if (!size) {
1355 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001356 }
Radek Krejci3733a802015-06-19 13:43:21 +02001357
1358 result = calloc(size, sizeof *result);
Michal Vasko53b7da02018-02-13 15:28:42 +01001359 LY_CHECK_ERR_RETURN(!result, LOGMEM(mod->ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001360
Radek Krejci3733a802015-06-19 13:43:21 +02001361 for (i = 0; i < size; i++) {
Radek Krejci77f22b22017-01-17 15:23:03 +01001362 result[i].ext_size = old[i].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001363 lys_ext_dup(mod->ctx, mod, old[i].ext, old[i].ext_size, &result[i], LYEXT_PAR_RESTR, &result[i].ext, shallow, unres);
Radek Krejci8d6b7422017-02-03 14:42:13 +01001364 result[i].expr = lydict_insert(mod->ctx, old[i].expr, 0);
1365 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1366 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1367 result[i].eapptag = lydict_insert(mod->ctx, old[i].eapptag, 0);
1368 result[i].emsg = lydict_insert(mod->ctx, old[i].emsg, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001369 }
1370
1371 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001372}
1373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001374void
Radek Krejci5138e9f2017-04-12 13:10:46 +02001375lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr,
1376 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci0bd5db42015-06-19 13:30:07 +02001377{
1378 assert(ctx);
1379 if (!restr) {
1380 return;
1381 }
1382
Radek Krejci5138e9f2017-04-12 13:10:46 +02001383 lys_extension_instances_free(ctx, restr->ext, restr->ext_size, private_destructor);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001384 lydict_remove(ctx, restr->expr);
1385 lydict_remove(ctx, restr->dsc);
1386 lydict_remove(ctx, restr->ref);
1387 lydict_remove(ctx, restr->eapptag);
1388 lydict_remove(ctx, restr->emsg);
1389}
1390
Pavol Vican05810b62016-11-23 14:07:22 +01001391void
Radek Krejci5138e9f2017-04-12 13:10:46 +02001392lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size,
Frank Rimplerc4db1c72017-09-12 12:56:39 +00001393 int shallow, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001394{
1395 uint8_t i;
1396
1397 for (i = 0; i < iffeature_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02001398 lys_extension_instances_free(ctx, iffeature[i].ext, iffeature[i].ext_size, private_destructor);
Michal Vasko15a43372017-09-25 14:12:42 +02001399 if (!shallow) {
Frank Rimpler2a503f52017-09-12 15:21:18 +00001400 free(iffeature[i].expr);
1401 free(iffeature[i].features);
1402 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001403 }
1404 free(iffeature);
1405}
1406
Michal Vaskob84f88a2015-09-24 13:16:10 +02001407static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001408type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001409 LY_DATA_TYPE base, int in_grp, int shallow, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001410{
1411 int i;
Radek Krejcidce5f972017-09-12 15:47:49 +02001412 unsigned int u;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001413
1414 switch (base) {
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001415 case LY_TYPE_BINARY:
1416 if (old->info.binary.length) {
1417 new->info.binary.length = lys_restr_dup(mod, old->info.binary.length, 1, shallow, unres);
1418 }
1419 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001420
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001421 case LY_TYPE_BITS:
1422 new->info.bits.count = old->info.bits.count;
1423 if (new->info.bits.count) {
1424 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
Michal Vasko53b7da02018-02-13 15:28:42 +01001425 LY_CHECK_ERR_RETURN(!new->info.bits.bit, LOGMEM(mod->ctx), -1);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001426
Radek Krejcidce5f972017-09-12 15:47:49 +02001427 for (u = 0; u < new->info.bits.count; u++) {
1428 new->info.bits.bit[u].name = lydict_insert(mod->ctx, old->info.bits.bit[u].name, 0);
1429 new->info.bits.bit[u].dsc = lydict_insert(mod->ctx, old->info.bits.bit[u].dsc, 0);
1430 new->info.bits.bit[u].ref = lydict_insert(mod->ctx, old->info.bits.bit[u].ref, 0);
1431 new->info.bits.bit[u].flags = old->info.bits.bit[u].flags;
1432 new->info.bits.bit[u].pos = old->info.bits.bit[u].pos;
1433 new->info.bits.bit[u].ext_size = old->info.bits.bit[u].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001434 if (lys_ext_dup(mod->ctx, mod, old->info.bits.bit[u].ext, old->info.bits.bit[u].ext_size,
Radek Krejcidce5f972017-09-12 15:47:49 +02001435 &new->info.bits.bit[u], LYEXT_PAR_TYPE_BIT,
1436 &new->info.bits.bit[u].ext, shallow, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001437 return -1;
1438 }
1439 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001440 }
1441 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001442
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001443 case LY_TYPE_DEC64:
1444 new->info.dec64.dig = old->info.dec64.dig;
1445 new->info.dec64.div = old->info.dec64.div;
1446 if (old->info.dec64.range) {
1447 new->info.dec64.range = lys_restr_dup(mod, old->info.dec64.range, 1, shallow, unres);
1448 }
1449 break;
1450
1451 case LY_TYPE_ENUM:
1452 new->info.enums.count = old->info.enums.count;
1453 if (new->info.enums.count) {
1454 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Michal Vasko53b7da02018-02-13 15:28:42 +01001455 LY_CHECK_ERR_RETURN(!new->info.enums.enm, LOGMEM(mod->ctx), -1);
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001456
Radek Krejcidce5f972017-09-12 15:47:49 +02001457 for (u = 0; u < new->info.enums.count; u++) {
1458 new->info.enums.enm[u].name = lydict_insert(mod->ctx, old->info.enums.enm[u].name, 0);
1459 new->info.enums.enm[u].dsc = lydict_insert(mod->ctx, old->info.enums.enm[u].dsc, 0);
1460 new->info.enums.enm[u].ref = lydict_insert(mod->ctx, old->info.enums.enm[u].ref, 0);
1461 new->info.enums.enm[u].flags = old->info.enums.enm[u].flags;
1462 new->info.enums.enm[u].value = old->info.enums.enm[u].value;
1463 new->info.enums.enm[u].ext_size = old->info.enums.enm[u].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001464 if (lys_ext_dup(mod->ctx, mod, old->info.enums.enm[u].ext, old->info.enums.enm[u].ext_size,
Radek Krejcidce5f972017-09-12 15:47:49 +02001465 &new->info.enums.enm[u], LYEXT_PAR_TYPE_ENUM,
1466 &new->info.enums.enm[u].ext, shallow, unres)) {
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001467 return -1;
1468 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001469 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001470 }
1471 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001472
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001473 case LY_TYPE_IDENT:
1474 new->info.ident.count = old->info.ident.count;
1475 if (old->info.ident.count) {
1476 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
Michal Vasko53b7da02018-02-13 15:28:42 +01001477 LY_CHECK_ERR_RETURN(!new->info.ident.ref, LOGMEM(mod->ctx), -1);
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001478 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1479 } else {
1480 /* there can be several unresolved base identities, duplicate them all */
1481 i = -1;
1482 do {
1483 i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF);
1484 if (i != -1) {
1485 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001486 return -1;
1487 }
1488 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001489 --i;
1490 } while (i > -1);
1491 }
1492 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001493
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001494 case LY_TYPE_INST:
1495 new->info.inst.req = old->info.inst.req;
1496 break;
1497
1498 case LY_TYPE_INT8:
1499 case LY_TYPE_INT16:
1500 case LY_TYPE_INT32:
1501 case LY_TYPE_INT64:
1502 case LY_TYPE_UINT8:
1503 case LY_TYPE_UINT16:
1504 case LY_TYPE_UINT32:
1505 case LY_TYPE_UINT64:
1506 if (old->info.num.range) {
1507 new->info.num.range = lys_restr_dup(mod, old->info.num.range, 1, shallow, unres);
1508 }
1509 break;
1510
1511 case LY_TYPE_LEAFREF:
1512 if (old->info.lref.path) {
1513 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
1514 if (!in_grp && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
1515 return -1;
1516 }
1517 }
1518 break;
1519
1520 case LY_TYPE_STRING:
1521 if (old->info.str.length) {
1522 new->info.str.length = lys_restr_dup(mod, old->info.str.length, 1, shallow, unres);
1523 }
Radek Krejcib53154b2017-07-19 09:14:13 +02001524 if (old->info.str.pat_count) {
1525 new->info.str.patterns = lys_restr_dup(mod, old->info.str.patterns, old->info.str.pat_count, shallow, unres);
1526 new->info.str.pat_count = old->info.str.pat_count;
Michal Vaskofcd974b2017-08-22 10:17:49 +02001527#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001528 if (!in_grp) {
1529 new->info.str.patterns_pcre = malloc(new->info.str.pat_count * 2 * sizeof *new->info.str.patterns_pcre);
Michal Vasko53b7da02018-02-13 15:28:42 +01001530 LY_CHECK_ERR_RETURN(!new->info.str.patterns_pcre, LOGMEM(mod->ctx), -1);
Radek Krejcia4c107d2017-10-27 14:19:26 +02001531 for (u = 0; u < new->info.str.pat_count; u++) {
Michal Vaskoa26db302018-02-14 15:22:10 +01001532 if (lyp_precompile_pattern(mod->ctx, &new->info.str.patterns[u].expr[1],
Radek Krejcia4c107d2017-10-27 14:19:26 +02001533 (pcre**)&new->info.str.patterns_pcre[2 * u],
1534 (pcre_extra**)&new->info.str.patterns_pcre[2 * u + 1])) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001535 free(new->info.str.patterns_pcre);
1536 new->info.str.patterns_pcre = NULL;
1537 return -1;
1538 }
1539 }
1540 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001541#endif
Radek Krejcib53154b2017-07-19 09:14:13 +02001542 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001543 break;
1544
1545 case LY_TYPE_UNION:
1546 new->info.uni.has_ptr_type = old->info.uni.has_ptr_type;
1547 new->info.uni.count = old->info.uni.count;
1548 if (new->info.uni.count) {
1549 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001550 LY_CHECK_ERR_RETURN(!new->info.uni.types, LOGMEM(mod->ctx), -1);
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001551
Radek Krejcidce5f972017-09-12 15:47:49 +02001552 for (u = 0; u < new->info.uni.count; u++) {
1553 if (lys_type_dup(mod, parent, &(new->info.uni.types[u]), &(old->info.uni.types[u]), in_grp,
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001554 shallow, unres)) {
1555 return -1;
1556 }
1557 }
1558 }
1559 break;
1560
1561 default:
1562 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1563 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001564 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001565
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001566 return EXIT_SUCCESS;
1567}
1568
1569struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001570lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
Radek Krejci5138e9f2017-04-12 13:10:46 +02001571 int in_grp, int shallow, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001572{
1573 struct yang_type *new;
1574
1575 new = calloc(1, sizeof *new);
Michal Vasko53b7da02018-02-13 15:28:42 +01001576 LY_CHECK_ERR_RETURN(!new, LOGMEM(module->ctx), NULL);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001577 new->flags = old->flags;
1578 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001579 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001580 new->type = type;
1581 if (!new->name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001582 LOGMEM(module->ctx);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001583 goto error;
1584 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02001585 if (type_dup(module, parent, type, old->type, new->base, in_grp, shallow, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001586 new->type->base = new->base;
Radek Krejci5138e9f2017-04-12 13:10:46 +02001587 lys_type_free(module->ctx, new->type, NULL);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001588 memset(&new->type->info, 0, sizeof new->type->info);
1589 goto error;
1590 }
1591 return new;
1592
Michal Vasko53b7da02018-02-13 15:28:42 +01001593error:
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001594 free(new);
1595 return NULL;
1596}
1597
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001598int
1599lys_copy_union_leafrefs(struct lys_module *mod, struct lys_node *parent, struct lys_type *type, struct lys_type *prev_new,
1600 struct unres_schema *unres)
1601{
1602 struct lys_type new;
Radek Krejcidce5f972017-09-12 15:47:49 +02001603 unsigned int i, top_type;
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001604 struct lys_ext_instance **ext;
1605 uint8_t ext_size;
1606 void *reloc;
1607
1608 if (!prev_new) {
1609 /* this is the "top-level" type, meaning it is a real type and no typedef directly above */
1610 top_type = 1;
1611
1612 memset(&new, 0, sizeof new);
1613
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001614 new.base = type->base;
1615 new.parent = (struct lys_tpdf *)parent;
1616
1617 prev_new = &new;
1618 } else {
1619 /* this is not top-level type, just a type of a typedef */
1620 top_type = 0;
1621 }
1622
Radek Krejci9c5cb6d2017-08-09 11:15:23 +02001623 assert(type->der);
1624 if (type->der->module) {
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001625 /* typedef, skip it, but keep the extensions */
1626 ext_size = type->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001627 if (lys_ext_dup(mod->ctx, mod, type->ext, type->ext_size, prev_new, LYEXT_PAR_TYPE, &ext, 0, unres)) {
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001628 return -1;
1629 }
1630 if (prev_new->ext) {
1631 reloc = realloc(prev_new->ext, (prev_new->ext_size + ext_size) * sizeof *prev_new->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001632 LY_CHECK_ERR_RETURN(!reloc, LOGMEM(mod->ctx), -1);
Radek Krejci70379e22017-08-09 11:21:07 +02001633 prev_new->ext = reloc;
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001634
1635 memcpy(prev_new->ext + prev_new->ext_size, ext, ext_size * sizeof *ext);
1636 free(ext);
1637
1638 prev_new->ext_size += ext_size;
1639 } else {
1640 prev_new->ext = ext;
1641 prev_new->ext_size = ext_size;
1642 }
1643
1644 if (lys_copy_union_leafrefs(mod, parent, &type->der->type, prev_new, unres)) {
1645 return -1;
1646 }
1647 } else {
1648 /* type, just make a deep copy */
1649 switch (type->base) {
1650 case LY_TYPE_UNION:
1651 prev_new->info.uni.has_ptr_type = type->info.uni.has_ptr_type;
1652 prev_new->info.uni.count = type->info.uni.count;
1653 /* this cannot be a typedef anymore */
1654 assert(prev_new->info.uni.count);
1655
1656 prev_new->info.uni.types = calloc(prev_new->info.uni.count, sizeof *prev_new->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001657 LY_CHECK_ERR_RETURN(!prev_new->info.uni.types, LOGMEM(mod->ctx), -1);
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001658
1659 for (i = 0; i < prev_new->info.uni.count; i++) {
1660 if (lys_copy_union_leafrefs(mod, parent, &(type->info.uni.types[i]), &(prev_new->info.uni.types[i]), unres)) {
1661 return -1;
1662 }
1663 }
1664
1665 prev_new->der = type->der;
1666 break;
1667 default:
1668 if (lys_type_dup(mod, parent, prev_new, type, 0, 0, unres)) {
1669 return -1;
1670 }
1671 break;
1672 }
1673 }
1674
1675 if (top_type) {
1676 memcpy(type, prev_new, sizeof *type);
1677 }
1678 return EXIT_SUCCESS;
1679}
1680
Radek Krejci43ce4b72017-01-04 11:02:38 +01001681API const void *
1682lys_ext_instance_substmt(const struct lys_ext_instance *ext)
1683{
1684 if (!ext) {
1685 return NULL;
1686 }
1687
Radek Krejcifebdad72017-02-06 11:35:51 +01001688 switch (ext->insubstmt) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001689 case LYEXT_SUBSTMT_SELF:
1690 case LYEXT_SUBSTMT_MODIFIER:
1691 case LYEXT_SUBSTMT_VERSION:
1692 return NULL;
1693 case LYEXT_SUBSTMT_ARGUMENT:
1694 if (ext->parent_type == LYEXT_PAR_EXT) {
1695 return ((struct lys_ext_instance*)ext->parent)->arg_value;
1696 }
1697 break;
1698 case LYEXT_SUBSTMT_BASE:
1699 if (ext->parent_type == LYEXT_PAR_TYPE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001700 return ((struct lys_type*)ext->parent)->info.ident.ref[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001701 } else if (ext->parent_type == LYEXT_PAR_IDENT) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001702 return ((struct lys_ident*)ext->parent)->base[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001703 }
1704 break;
1705 case LYEXT_SUBSTMT_BELONGSTO:
1706 if (ext->parent_type == LYEXT_PAR_MODULE && ((struct lys_module*)ext->parent)->type) {
1707 return ((struct lys_submodule*)ext->parent)->belongsto;
1708 }
1709 break;
1710 case LYEXT_SUBSTMT_CONFIG:
1711 case LYEXT_SUBSTMT_MANDATORY:
1712 if (ext->parent_type == LYEXT_PAR_NODE) {
1713 return &((struct lys_node*)ext->parent)->flags;
1714 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1715 return &((struct lys_deviate*)ext->parent)->flags;
1716 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1717 return &((struct lys_refine*)ext->parent)->flags;
1718 }
1719 break;
1720 case LYEXT_SUBSTMT_CONTACT:
1721 if (ext->parent_type == LYEXT_PAR_MODULE) {
1722 return ((struct lys_module*)ext->parent)->contact;
1723 }
1724 break;
1725 case LYEXT_SUBSTMT_DEFAULT:
1726 if (ext->parent_type == LYEXT_PAR_NODE) {
1727 switch (((struct lys_node*)ext->parent)->nodetype) {
1728 case LYS_LEAF:
1729 case LYS_LEAFLIST:
1730 /* in case of leaf, the index is supposed to be 0, so it will return the
1731 * correct pointer despite the leaf structure does not have dflt as array */
Radek Krejcifebdad72017-02-06 11:35:51 +01001732 return ((struct lys_node_leaflist*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001733 case LYS_CHOICE:
1734 return ((struct lys_node_choice*)ext->parent)->dflt;
1735 default:
1736 /* internal error */
1737 break;
1738 }
1739 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1740 return ((struct lys_tpdf*)ext->parent)->dflt;
1741 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001742 return ((struct lys_deviate*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001743 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001744 return &((struct lys_refine*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001745 }
1746 break;
1747 case LYEXT_SUBSTMT_DESCRIPTION:
1748 switch (ext->parent_type) {
1749 case LYEXT_PAR_NODE:
1750 return ((struct lys_node*)ext->parent)->dsc;
1751 case LYEXT_PAR_MODULE:
1752 return ((struct lys_module*)ext->parent)->dsc;
1753 case LYEXT_PAR_IMPORT:
1754 return ((struct lys_import*)ext->parent)->dsc;
1755 case LYEXT_PAR_INCLUDE:
1756 return ((struct lys_include*)ext->parent)->dsc;
1757 case LYEXT_PAR_EXT:
1758 return ((struct lys_ext*)ext->parent)->dsc;
1759 case LYEXT_PAR_FEATURE:
1760 return ((struct lys_feature*)ext->parent)->dsc;
1761 case LYEXT_PAR_TPDF:
1762 return ((struct lys_tpdf*)ext->parent)->dsc;
1763 case LYEXT_PAR_TYPE_BIT:
1764 return ((struct lys_type_bit*)ext->parent)->dsc;
1765 case LYEXT_PAR_TYPE_ENUM:
1766 return ((struct lys_type_enum*)ext->parent)->dsc;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001767 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001768 return ((struct lys_restr*)ext->parent)->dsc;
1769 case LYEXT_PAR_WHEN:
1770 return ((struct lys_when*)ext->parent)->dsc;
1771 case LYEXT_PAR_IDENT:
1772 return ((struct lys_ident*)ext->parent)->dsc;
1773 case LYEXT_PAR_DEVIATION:
1774 return ((struct lys_deviation*)ext->parent)->dsc;
1775 case LYEXT_PAR_REVISION:
1776 return ((struct lys_revision*)ext->parent)->dsc;
1777 case LYEXT_PAR_REFINE:
1778 return ((struct lys_refine*)ext->parent)->dsc;
1779 default:
1780 break;
1781 }
1782 break;
1783 case LYEXT_SUBSTMT_ERRTAG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001784 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001785 return ((struct lys_restr*)ext->parent)->eapptag;
1786 }
1787 break;
1788 case LYEXT_SUBSTMT_ERRMSG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01001789 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001790 return ((struct lys_restr*)ext->parent)->emsg;
1791 }
1792 break;
1793 case LYEXT_SUBSTMT_DIGITS:
1794 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_DEC64) {
1795 return &((struct lys_type*)ext->parent)->info.dec64.dig;
1796 }
1797 break;
1798 case LYEXT_SUBSTMT_KEY:
1799 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1800 return ((struct lys_node_list*)ext->parent)->keys;
1801 }
1802 break;
1803 case LYEXT_SUBSTMT_MAX:
1804 if (ext->parent_type == LYEXT_PAR_NODE) {
1805 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1806 return &((struct lys_node_list*)ext->parent)->max;
1807 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1808 return &((struct lys_node_leaflist*)ext->parent)->max;
1809 }
1810 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1811 return &((struct lys_refine*)ext->parent)->mod.list.max;
1812 }
1813 break;
1814 case LYEXT_SUBSTMT_MIN:
1815 if (ext->parent_type == LYEXT_PAR_NODE) {
1816 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
1817 return &((struct lys_node_list*)ext->parent)->min;
1818 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
1819 return &((struct lys_node_leaflist*)ext->parent)->min;
1820 }
1821 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1822 return &((struct lys_refine*)ext->parent)->mod.list.min;
1823 }
1824 break;
1825 case LYEXT_SUBSTMT_NAMESPACE:
1826 if (ext->parent_type == LYEXT_PAR_MODULE && !((struct lys_module*)ext->parent)->type) {
1827 return ((struct lys_module*)ext->parent)->ns;
1828 }
1829 break;
1830 case LYEXT_SUBSTMT_ORDEREDBY:
1831 if (ext->parent_type == LYEXT_PAR_NODE &&
1832 (((struct lys_node*)ext->parent)->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
1833 return &((struct lys_node_list*)ext->parent)->flags;
1834 }
1835 break;
1836 case LYEXT_SUBSTMT_ORGANIZATION:
1837 if (ext->parent_type == LYEXT_PAR_MODULE) {
1838 return ((struct lys_module*)ext->parent)->org;
1839 }
1840 break;
1841 case LYEXT_SUBSTMT_PATH:
1842 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1843 return ((struct lys_type*)ext->parent)->info.lref.path;
1844 }
1845 break;
1846 case LYEXT_SUBSTMT_POSITION:
1847 if (ext->parent_type == LYEXT_PAR_TYPE_BIT) {
1848 return &((struct lys_type_bit*)ext->parent)->pos;
1849 }
1850 break;
1851 case LYEXT_SUBSTMT_PREFIX:
1852 if (ext->parent_type == LYEXT_PAR_MODULE) {
1853 /* covers also lys_submodule */
1854 return ((struct lys_module*)ext->parent)->prefix;
1855 } else if (ext->parent_type == LYEXT_PAR_IMPORT) {
1856 return ((struct lys_import*)ext->parent)->prefix;
1857 }
1858 break;
1859 case LYEXT_SUBSTMT_PRESENCE:
1860 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_CONTAINER) {
1861 return ((struct lys_node_container*)ext->parent)->presence;
1862 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1863 return ((struct lys_refine*)ext->parent)->mod.presence;
1864 }
1865 break;
1866 case LYEXT_SUBSTMT_REFERENCE:
1867 switch (ext->parent_type) {
1868 case LYEXT_PAR_NODE:
1869 return ((struct lys_node*)ext->parent)->ref;
1870 case LYEXT_PAR_MODULE:
1871 return ((struct lys_module*)ext->parent)->ref;
1872 case LYEXT_PAR_IMPORT:
1873 return ((struct lys_import*)ext->parent)->ref;
1874 case LYEXT_PAR_INCLUDE:
1875 return ((struct lys_include*)ext->parent)->ref;
1876 case LYEXT_PAR_EXT:
1877 return ((struct lys_ext*)ext->parent)->ref;
1878 case LYEXT_PAR_FEATURE:
1879 return ((struct lys_feature*)ext->parent)->ref;
1880 case LYEXT_PAR_TPDF:
1881 return ((struct lys_tpdf*)ext->parent)->ref;
1882 case LYEXT_PAR_TYPE_BIT:
1883 return ((struct lys_type_bit*)ext->parent)->ref;
1884 case LYEXT_PAR_TYPE_ENUM:
1885 return ((struct lys_type_enum*)ext->parent)->ref;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001886 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001887 return ((struct lys_restr*)ext->parent)->ref;
1888 case LYEXT_PAR_WHEN:
1889 return ((struct lys_when*)ext->parent)->ref;
1890 case LYEXT_PAR_IDENT:
1891 return ((struct lys_ident*)ext->parent)->ref;
1892 case LYEXT_PAR_DEVIATION:
1893 return ((struct lys_deviation*)ext->parent)->ref;
1894 case LYEXT_PAR_REVISION:
1895 return ((struct lys_revision*)ext->parent)->ref;
1896 case LYEXT_PAR_REFINE:
1897 return ((struct lys_refine*)ext->parent)->ref;
1898 default:
1899 break;
1900 }
1901 break;
Radek Krejcibe336392017-02-07 10:54:24 +01001902 case LYEXT_SUBSTMT_REQINSTANCE:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001903 if (ext->parent_type == LYEXT_PAR_TYPE) {
1904 if (((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
1905 return &((struct lys_type*)ext->parent)->info.lref.req;
1906 } else if (((struct lys_type*)ext->parent)->base == LY_TYPE_INST) {
1907 return &((struct lys_type*)ext->parent)->info.inst.req;
1908 }
1909 }
1910 break;
1911 case LYEXT_SUBSTMT_REVISIONDATE:
1912 if (ext->parent_type == LYEXT_PAR_IMPORT) {
1913 return ((struct lys_import*)ext->parent)->rev;
1914 } else if (ext->parent_type == LYEXT_PAR_INCLUDE) {
1915 return ((struct lys_include*)ext->parent)->rev;
1916 }
1917 break;
1918 case LYEXT_SUBSTMT_STATUS:
1919 switch (ext->parent_type) {
1920 case LYEXT_PAR_NODE:
1921 case LYEXT_PAR_IDENT:
1922 case LYEXT_PAR_TPDF:
1923 case LYEXT_PAR_EXT:
1924 case LYEXT_PAR_FEATURE:
1925 case LYEXT_PAR_TYPE_ENUM:
1926 case LYEXT_PAR_TYPE_BIT:
1927 /* in all structures the flags member is at the same offset */
1928 return &((struct lys_node*)ext->parent)->flags;
1929 default:
1930 break;
1931 }
1932 break;
1933 case LYEXT_SUBSTMT_UNIQUE:
1934 if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001935 return &((struct lys_deviate*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001936 } else if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001937 return &((struct lys_node_list*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001938 }
1939 break;
1940 case LYEXT_SUBSTMT_UNITS:
1941 if (ext->parent_type == LYEXT_PAR_NODE &&
1942 (((struct lys_node*)ext->parent)->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1943 /* units is at the same offset in both lys_node_leaf and lys_node_leaflist */
1944 return ((struct lys_node_leaf*)ext->parent)->units;
1945 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1946 return ((struct lys_tpdf*)ext->parent)->units;
1947 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1948 return ((struct lys_deviate*)ext->parent)->units;
1949 }
1950 break;
1951 case LYEXT_SUBSTMT_VALUE:
1952 if (ext->parent_type == LYEXT_PAR_TYPE_ENUM) {
1953 return &((struct lys_type_enum*)ext->parent)->value;
1954 }
1955 break;
1956 case LYEXT_SUBSTMT_YINELEM:
1957 if (ext->parent_type == LYEXT_PAR_EXT) {
1958 return &((struct lys_ext*)ext->parent)->flags;
1959 }
1960 break;
1961 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001962 LOGINT(ext->module->ctx);
Radek Krejci43ce4b72017-01-04 11:02:38 +01001963 return NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01001964}
1965
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001966static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001967lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci5138e9f2017-04-12 13:10:46 +02001968 int in_grp, int shallow, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001969{
1970 int i;
1971
Radek Krejci3733a802015-06-19 13:43:21 +02001972 new->base = old->base;
1973 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001974 new->parent = (struct lys_tpdf *)parent;
Radek Krejcif0bb3602017-01-25 17:05:08 +01001975 new->ext_size = old->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001976 if (lys_ext_dup(mod->ctx, mod, old->ext, old->ext_size, new, LYEXT_PAR_TYPE, &new->ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01001977 return -1;
Radek Krejcie534c132016-11-23 13:32:31 +01001978 }
Radek Krejci3733a802015-06-19 13:43:21 +02001979
Michal Vasko1c007172017-03-10 10:20:44 +01001980 i = unres_schema_find(unres, -1, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001981 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001982 /* HACK (serious one) for unres */
1983 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001984 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02001985 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, in_grp,
1986 shallow, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001987 } else {
1988 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1989 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001990 /* all these unres additions can fail even though they did not before */
Michal Vasko1c007172017-03-10 10:20:44 +01001991 if (!new->der || (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent) == -1)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001992 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001993 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001994 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001995 }
1996
Radek Krejci5138e9f2017-04-12 13:10:46 +02001997 return type_dup(mod, parent, new, old, new->base, in_grp, shallow, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001998}
1999
2000void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002001lys_type_free(struct ly_ctx *ctx, struct lys_type *type,
2002 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002003{
Radek Krejcidce5f972017-09-12 15:47:49 +02002004 unsigned int i;
Radek Krejci5a065542015-05-22 15:02:07 +02002005
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002006 assert(ctx);
2007 if (!type) {
2008 return;
2009 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002010
Radek Krejci5138e9f2017-04-12 13:10:46 +02002011 lys_extension_instances_free(ctx, type->ext, type->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002013 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02002014 case LY_TYPE_BINARY:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002015 lys_restr_free(ctx, type->info.binary.length, private_destructor);
Radek Krejci0bd5db42015-06-19 13:30:07 +02002016 free(type->info.binary.length);
2017 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02002018 case LY_TYPE_BITS:
2019 for (i = 0; i < type->info.bits.count; i++) {
2020 lydict_remove(ctx, type->info.bits.bit[i].name);
2021 lydict_remove(ctx, type->info.bits.bit[i].dsc);
2022 lydict_remove(ctx, type->info.bits.bit[i].ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002023 lys_iffeature_free(ctx, type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size, 0,
Radek Krejci5138e9f2017-04-12 13:10:46 +02002024 private_destructor);
2025 lys_extension_instances_free(ctx, type->info.bits.bit[i].ext, type->info.bits.bit[i].ext_size,
2026 private_destructor);
Radek Krejci994b6f62015-06-18 16:47:27 +02002027 }
2028 free(type->info.bits.bit);
2029 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02002030
2031 case LY_TYPE_DEC64:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002032 lys_restr_free(ctx, type->info.dec64.range, private_destructor);
Radek Krejcif9401c32015-06-26 16:47:36 +02002033 free(type->info.dec64.range);
2034 break;
2035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002036 case LY_TYPE_ENUM:
2037 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002038 lydict_remove(ctx, type->info.enums.enm[i].name);
2039 lydict_remove(ctx, type->info.enums.enm[i].dsc);
2040 lydict_remove(ctx, type->info.enums.enm[i].ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002041 lys_iffeature_free(ctx, type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size, 0,
Radek Krejci5138e9f2017-04-12 13:10:46 +02002042 private_destructor);
2043 lys_extension_instances_free(ctx, type->info.enums.enm[i].ext, type->info.enums.enm[i].ext_size,
2044 private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002045 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02002046 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002047 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02002048
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02002049 case LY_TYPE_INT8:
2050 case LY_TYPE_INT16:
2051 case LY_TYPE_INT32:
2052 case LY_TYPE_INT64:
2053 case LY_TYPE_UINT8:
2054 case LY_TYPE_UINT16:
2055 case LY_TYPE_UINT32:
2056 case LY_TYPE_UINT64:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002057 lys_restr_free(ctx, type->info.num.range, private_destructor);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02002058 free(type->info.num.range);
2059 break;
2060
Radek Krejcidc4c1412015-06-19 15:39:54 +02002061 case LY_TYPE_LEAFREF:
2062 lydict_remove(ctx, type->info.lref.path);
2063 break;
2064
Radek Krejci3733a802015-06-19 13:43:21 +02002065 case LY_TYPE_STRING:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002066 lys_restr_free(ctx, type->info.str.length, private_destructor);
Radek Krejci3733a802015-06-19 13:43:21 +02002067 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02002068 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002069 lys_restr_free(ctx, &type->info.str.patterns[i], private_destructor);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002070#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02002071 if (type->info.str.patterns_pcre) {
2072 pcre_free((pcre*)type->info.str.patterns_pcre[2 * i]);
2073 pcre_free_study((pcre_extra*)type->info.str.patterns_pcre[2 * i + 1]);
2074 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02002075#endif
Radek Krejci5fbc9162015-06-19 14:11:11 +02002076 }
2077 free(type->info.str.patterns);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002078#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02002079 free(type->info.str.patterns_pcre);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002080#endif
Radek Krejci3733a802015-06-19 13:43:21 +02002081 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02002082
Radek Krejcie4c366b2015-07-02 10:11:31 +02002083 case LY_TYPE_UNION:
2084 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002085 lys_type_free(ctx, &type->info.uni.types[i], private_destructor);
Radek Krejcie4c366b2015-07-02 10:11:31 +02002086 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02002087 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02002088 break;
2089
Michal Vaskod3282192016-09-05 11:27:57 +02002090 case LY_TYPE_IDENT:
2091 free(type->info.ident.ref);
2092 break;
2093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002094 default:
Michal Vaskod3282192016-09-05 11:27:57 +02002095 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002096 break;
2097 }
Radek Krejci5a065542015-05-22 15:02:07 +02002098}
2099
Radek Krejci1d82ef62015-08-07 14:44:40 +02002100static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002101lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf,
2102 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002103{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 assert(ctx);
2105 if (!tpdf) {
2106 return;
2107 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002109 lydict_remove(ctx, tpdf->name);
2110 lydict_remove(ctx, tpdf->dsc);
2111 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002112
Radek Krejci5138e9f2017-04-12 13:10:46 +02002113 lys_type_free(ctx, &tpdf->type, private_destructor);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002115 lydict_remove(ctx, tpdf->units);
2116 lydict_remove(ctx, tpdf->dflt);
Radek Krejcie534c132016-11-23 13:32:31 +01002117
Radek Krejci5138e9f2017-04-12 13:10:46 +02002118 lys_extension_instances_free(ctx, tpdf->ext, tpdf->ext_size, private_destructor);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002119}
2120
Radek Krejci1d82ef62015-08-07 14:44:40 +02002121static struct lys_when *
Radek Krejci5138e9f2017-04-12 13:10:46 +02002122lys_when_dup(struct lys_module *mod, struct lys_when *old, int shallow, struct unres_schema *unres)
Radek Krejci00768f42015-06-18 17:04:04 +02002123{
Radek Krejci76512572015-08-04 09:47:08 +02002124 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02002125
2126 if (!old) {
2127 return NULL;
2128 }
2129
2130 new = calloc(1, sizeof *new);
Michal Vasko53b7da02018-02-13 15:28:42 +01002131 LY_CHECK_ERR_RETURN(!new, LOGMEM(mod->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01002132 new->cond = lydict_insert(mod->ctx, old->cond, 0);
2133 new->dsc = lydict_insert(mod->ctx, old->dsc, 0);
2134 new->ref = lydict_insert(mod->ctx, old->ref, 0);
Radek Krejcif0bb3602017-01-25 17:05:08 +01002135 new->ext_size = old->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01002136 lys_ext_dup(mod->ctx, mod, old->ext, old->ext_size, new, LYEXT_PAR_WHEN, &new->ext, shallow, unres);
Radek Krejci00768f42015-06-18 17:04:04 +02002137
2138 return new;
2139}
2140
Michal Vasko0308dd62015-10-07 09:14:40 +02002141void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002142lys_when_free(struct ly_ctx *ctx, struct lys_when *w,
2143 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002144{
2145 if (!w) {
2146 return;
2147 }
2148
Radek Krejci5138e9f2017-04-12 13:10:46 +02002149 lys_extension_instances_free(ctx, w->ext, w->ext_size, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002150 lydict_remove(ctx, w->cond);
2151 lydict_remove(ctx, w->dsc);
2152 lydict_remove(ctx, w->ref);
2153
2154 free(w);
2155}
2156
Radek Krejcib7f5e412015-08-13 10:15:51 +02002157static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002158lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment *aug,
2159 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib7f5e412015-08-13 10:15:51 +02002160{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02002161 struct lys_node *next, *sub;
2162
Radek Krejcic071c542016-01-27 14:57:51 +01002163 /* children from a resolved augment are freed under the target node */
Radek Krejci0ec51da2016-12-14 16:42:03 +01002164 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002165 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002166 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002167 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02002168 }
2169
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002170 lydict_remove(ctx, aug->target_name);
2171 lydict_remove(ctx, aug->dsc);
2172 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002173
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002174 lys_iffeature_free(ctx, aug->iffeature, aug->iffeature_size, 0, private_destructor);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002175 lys_extension_instances_free(ctx, aug->ext, aug->ext_size, private_destructor);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002176
Radek Krejci5138e9f2017-04-12 13:10:46 +02002177 lys_when_free(ctx, aug->when, private_destructor);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002178}
2179
Radek Krejci1d82ef62015-08-07 14:44:40 +02002180static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002181lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident,
2182 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci6793db02015-05-22 17:49:54 +02002183{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002184 assert(ctx);
2185 if (!ident) {
2186 return;
2187 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002188
Radek Krejci018f1f52016-08-03 16:01:20 +02002189 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02002190 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002191 lydict_remove(ctx, ident->name);
2192 lydict_remove(ctx, ident->dsc);
2193 lydict_remove(ctx, ident->ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002194 lys_iffeature_free(ctx, ident->iffeature, ident->iffeature_size, 0, private_destructor);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002195 lys_extension_instances_free(ctx, ident->ext, ident->ext_size, private_destructor);
Radek Krejci6793db02015-05-22 17:49:54 +02002196
2197}
2198
Radek Krejci1d82ef62015-08-07 14:44:40 +02002199static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002200lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp,
2201 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002202{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002203 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002204
Radek Krejcid12f57b2015-08-06 10:43:39 +02002205 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002206 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002207 lys_tpdf_free(ctx, &grp->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002208 }
2209 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002210}
2211
Radek Krejci1d82ef62015-08-07 14:44:40 +02002212static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002213lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io,
2214 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcid12f57b2015-08-06 10:43:39 +02002215{
2216 int i;
2217
2218 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
2219 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002220 lys_tpdf_free(ctx, &io->tpdf[i], private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002221 }
2222 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002223
2224 for (i = 0; i < io->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002225 lys_restr_free(ctx, &io->must[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002226 }
2227 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002228}
2229
Radek Krejci1d82ef62015-08-07 14:44:40 +02002230static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002231lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif,
2232 void (*private_destructor)(const struct lys_node *node, void *priv))
Pavol Vican7cff97e2016-08-09 14:56:08 +02002233{
2234 int i;
2235
2236 for (i = 0; i < notif->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002237 lys_restr_free(ctx, &notif->must[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002238 }
2239 free(notif->must);
2240
2241 for (i = 0; i < notif->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002242 lys_tpdf_free(ctx, &notif->tpdf[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002243 }
2244 free(notif->tpdf);
2245}
2246static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002247lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml,
2248 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci537cf382015-06-04 11:07:01 +02002249{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002252 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002253 lys_restr_free(ctx, &anyxml->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 }
2255 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002256
Radek Krejci5138e9f2017-04-12 13:10:46 +02002257 lys_when_free(ctx, anyxml->when, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002258}
2259
Radek Krejci1d82ef62015-08-07 14:44:40 +02002260static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002261lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf,
2262 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002263{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002264 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002265
Radek Krejci85a54be2016-10-20 12:39:56 +02002266 /* leafref backlinks */
2267 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002268
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002270 lys_restr_free(ctx, &leaf->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002271 }
2272 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002273
Radek Krejci5138e9f2017-04-12 13:10:46 +02002274 lys_when_free(ctx, leaf->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002275
Radek Krejci5138e9f2017-04-12 13:10:46 +02002276 lys_type_free(ctx, &leaf->type, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002277 lydict_remove(ctx, leaf->units);
2278 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02002279}
2280
Radek Krejci1d82ef62015-08-07 14:44:40 +02002281static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002282lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist,
2283 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002284{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002286
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002287 if (llist->backlinks) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002288 /* leafref backlinks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002289 ly_set_free(llist->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002290 }
2291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 for (i = 0; i < llist->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002293 lys_restr_free(ctx, &llist->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002294 }
2295 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002296
Pavol Vican38321d02016-08-16 14:56:02 +02002297 for (i = 0; i < llist->dflt_size; i++) {
2298 lydict_remove(ctx, llist->dflt[i]);
2299 }
2300 free(llist->dflt);
2301
Radek Krejci5138e9f2017-04-12 13:10:46 +02002302 lys_when_free(ctx, llist->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002303
Radek Krejci5138e9f2017-04-12 13:10:46 +02002304 lys_type_free(ctx, &llist->type, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002305 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02002306}
2307
Radek Krejci1d82ef62015-08-07 14:44:40 +02002308static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002309lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list,
2310 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002311{
Radek Krejci581ce772015-11-10 17:22:40 +01002312 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002313
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314 /* handle only specific parts for LY_NODE_LIST */
Michal Vaskoaaeab1d2018-02-16 09:36:46 +01002315 lys_when_free(ctx, list->when, private_destructor);
Radek Krejci537cf382015-06-04 11:07:01 +02002316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002317 for (i = 0; i < list->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002318 lys_restr_free(ctx, &list->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002319 }
2320 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002321
Michal Vaskoaaeab1d2018-02-16 09:36:46 +01002322 for (i = 0; i < list->tpdf_size; i++) {
2323 lys_tpdf_free(ctx, &list->tpdf[i], private_destructor);
2324 }
2325 free(list->tpdf);
2326
2327 free(list->keys);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002329 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02002330 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002331 lydict_remove(ctx, list->unique[i].expr[j]);
2332 }
2333 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 }
2335 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02002336
Michal Vaskoaaeab1d2018-02-16 09:36:46 +01002337 lydict_remove(ctx, list->keys_str);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002338}
2339
Radek Krejci1d82ef62015-08-07 14:44:40 +02002340static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002341lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont,
2342 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002343{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002344 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002346 /* handle only specific parts for LY_NODE_CONTAINER */
2347 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02002348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002349 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002350 lys_tpdf_free(ctx, &cont->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351 }
2352 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02002353
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002354 for (i = 0; i < cont->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002355 lys_restr_free(ctx, &cont->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 }
2357 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002358
Radek Krejci5138e9f2017-04-12 13:10:46 +02002359 lys_when_free(ctx, cont->when, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002360}
2361
Radek Krejci1d82ef62015-08-07 14:44:40 +02002362static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002363lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f,
2364 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci3cf9e222015-06-18 11:37:50 +02002365{
2366 lydict_remove(ctx, f->name);
2367 lydict_remove(ctx, f->dsc);
2368 lydict_remove(ctx, f->ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002369 lys_iffeature_free(ctx, f->iffeature, f->iffeature_size, 0, private_destructor);
Radek Krejci9de2c042016-10-19 16:53:06 +02002370 ly_set_free(f->depfeatures);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002371 lys_extension_instances_free(ctx, f->ext, f->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002372}
2373
2374static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002375lys_extension_free(struct ly_ctx *ctx, struct lys_ext *e,
2376 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie534c132016-11-23 13:32:31 +01002377{
2378 lydict_remove(ctx, e->name);
2379 lydict_remove(ctx, e->dsc);
2380 lydict_remove(ctx, e->ref);
2381 lydict_remove(ctx, e->argument);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002382 lys_extension_instances_free(ctx, e->ext, e->ext_size, private_destructor);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002383}
2384
Radek Krejci1d82ef62015-08-07 14:44:40 +02002385static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002386lys_deviation_free(struct lys_module *module, struct lys_deviation *dev,
2387 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcieb00f512015-07-01 16:44:58 +02002388{
Radek Krejci581ce772015-11-10 17:22:40 +01002389 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01002390 struct ly_ctx *ctx;
2391 struct lys_node *next, *elem;
2392
2393 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002394
2395 lydict_remove(ctx, dev->target_name);
2396 lydict_remove(ctx, dev->dsc);
2397 lydict_remove(ctx, dev->ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002398 lys_extension_instances_free(ctx, dev->ext, dev->ext_size, private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002399
Pavol Vican64d0b762016-08-25 10:44:59 +02002400 if (!dev->deviate) {
Michal Vasko7427b262018-05-14 15:23:55 +02002401 return;
Pavol Vican64d0b762016-08-25 10:44:59 +02002402 }
2403
Michal Vasko7427b262018-05-14 15:23:55 +02002404 /* it could not be applied because it failed to be applied */
2405 if (dev->orig_node) {
2406 /* the module was freed, but we only need the context from orig_node, use ours */
2407 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2408 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
2409 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
2410 elem->module = module;
Michal Vaskoff006c12016-02-17 11:15:19 +01002411
Michal Vasko7427b262018-05-14 15:23:55 +02002412 LY_TREE_DFS_END(dev->orig_node, next, elem);
2413 }
2414 lys_node_free(dev->orig_node, NULL, 0);
2415 } else {
2416 /* it's just a shallow copy, freeing one node */
2417 dev->orig_node->module = module;
2418 lys_node_free(dev->orig_node, NULL, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002419 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002420 }
2421
Radek Krejcieb00f512015-07-01 16:44:58 +02002422 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002423 lys_extension_instances_free(ctx, dev->deviate[i].ext, dev->deviate[i].ext_size, private_destructor);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002424
Radek Krejcid5a5c282016-08-15 15:38:08 +02002425 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02002426 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002427 }
2428 free(dev->deviate[i].dflt);
2429
Radek Krejcieb00f512015-07-01 16:44:58 +02002430 lydict_remove(ctx, dev->deviate[i].units);
2431
2432 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2433 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002434 lys_restr_free(ctx, &dev->deviate[i].must[j], private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002435 }
2436 free(dev->deviate[i].must);
2437
2438 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002439 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
2440 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
2441 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01002442 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002443 }
2444 free(dev->deviate[i].unique);
2445 }
2446 }
2447 free(dev->deviate);
2448}
2449
Radek Krejci1d82ef62015-08-07 14:44:40 +02002450static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002451lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses,
2452 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie1fa8582015-06-08 09:46:45 +02002453{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002454 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02002455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002456 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02002457 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002458 lydict_remove(ctx, uses->refine[i].dsc);
2459 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002460
Radek Krejcifde04bd2017-09-13 16:38:38 +02002461 lys_iffeature_free(ctx, uses->refine[i].iffeature, uses->refine[i].iffeature_size, 0, private_destructor);
2462
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002463 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002464 lys_restr_free(ctx, &uses->refine[i].must[j], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002465 }
2466 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002467
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002468 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02002469 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002470 }
2471 free(uses->refine[i].dflt);
2472
Radek Krejci5138e9f2017-04-12 13:10:46 +02002473 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002474
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002475 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002476 lydict_remove(ctx, uses->refine[i].mod.presence);
2477 }
2478 }
2479 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002481 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002482 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002483 }
2484 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002485
Radek Krejci5138e9f2017-04-12 13:10:46 +02002486 lys_when_free(ctx, uses->when, private_destructor);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002487}
2488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002489void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002490lys_node_free(struct lys_node *node, void (*private_destructor)(const struct lys_node *node, void *priv), int shallow)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002491{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002492 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002493 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002495 if (!node) {
2496 return;
2497 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002499 assert(node->module);
2500 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002501
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002502 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002503
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002504 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002505 if (node->priv && private_destructor) {
2506 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002507 }
2508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002509 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002510 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002511 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002512 lys_iffeature_free(ctx, node->iffeature, node->iffeature_size, shallow, private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002513 lydict_remove(ctx, node->dsc);
2514 lydict_remove(ctx, node->ref);
2515 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002516
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002517 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002518 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002519 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002520 }
2521 }
2522
Radek Krejci5138e9f2017-04-12 13:10:46 +02002523 lys_extension_instances_free(ctx, node->ext, node->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002525 /* specific part */
2526 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002527 case LYS_CONTAINER:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002528 lys_container_free(ctx, (struct lys_node_container *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002529 break;
Radek Krejci76512572015-08-04 09:47:08 +02002530 case LYS_CHOICE:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002531 lys_when_free(ctx, ((struct lys_node_choice *)node)->when, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002532 break;
Radek Krejci76512572015-08-04 09:47:08 +02002533 case LYS_LEAF:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002534 lys_leaf_free(ctx, (struct lys_node_leaf *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002535 break;
Radek Krejci76512572015-08-04 09:47:08 +02002536 case LYS_LEAFLIST:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002537 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002538 break;
Radek Krejci76512572015-08-04 09:47:08 +02002539 case LYS_LIST:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002540 lys_list_free(ctx, (struct lys_node_list *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002541 break;
Radek Krejci76512572015-08-04 09:47:08 +02002542 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002543 case LYS_ANYDATA:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002544 lys_anydata_free(ctx, (struct lys_node_anydata *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002545 break;
Radek Krejci76512572015-08-04 09:47:08 +02002546 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002547 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002548 break;
Radek Krejci76512572015-08-04 09:47:08 +02002549 case LYS_CASE:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002550 lys_when_free(ctx, ((struct lys_node_case *)node)->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002551 break;
Radek Krejci76512572015-08-04 09:47:08 +02002552 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002553 /* do nothing */
2554 break;
Radek Krejci76512572015-08-04 09:47:08 +02002555 case LYS_GROUPING:
2556 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002557 case LYS_ACTION:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002558 lys_grp_free(ctx, (struct lys_node_grp *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002559 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02002560 case LYS_NOTIF:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002561 lys_notif_free(ctx, (struct lys_node_notif *)node, private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002562 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002563 case LYS_INPUT:
2564 case LYS_OUTPUT:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002565 lys_inout_free(ctx, (struct lys_node_inout *)node, private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002566 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01002567 case LYS_EXT:
Michal Vasko591e0b22015-08-13 13:53:43 +02002568 case LYS_UNKNOWN:
Michal Vasko53b7da02018-02-13 15:28:42 +01002569 LOGINT(ctx);
Michal Vasko591e0b22015-08-13 13:53:43 +02002570 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002571 }
Radek Krejci5a065542015-05-22 15:02:07 +02002572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002573 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002574 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002575 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002576}
2577
Radek Krejci2eee5c02016-12-06 19:18:05 +01002578API struct lys_module *
2579lys_implemented_module(const struct lys_module *mod)
Radek Krejci0fa54e92016-09-14 14:01:05 +02002580{
2581 struct ly_ctx *ctx;
2582 int i;
2583
2584 if (!mod || mod->implemented) {
2585 /* invalid argument or the module itself is implemented */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002586 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002587 }
2588
2589 ctx = mod->ctx;
2590 for (i = 0; i < ctx->models.used; i++) {
2591 if (!ctx->models.list[i]->implemented) {
2592 continue;
2593 }
2594
2595 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
2596 /* we have some revision of the module implemented */
2597 return ctx->models.list[i];
2598 }
2599 }
2600
2601 /* we have no revision of the module implemented, return the module itself,
2602 * it is up to the caller to set the module implemented when needed */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002603 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002604}
2605
Michal Vasko13b15832015-08-19 11:04:48 +02002606/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002607static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002608module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002609{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002610 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002611 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002612 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002614 assert(module->ctx);
2615 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002616
Michal Vaskob746fff2016-02-11 11:37:50 +01002617 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002618 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002619 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002620 lydict_remove(ctx, module->imp[i].dsc);
2621 lydict_remove(ctx, module->imp[i].ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002622 lys_extension_instances_free(ctx, module->imp[i].ext, module->imp[i].ext_size, private_destructor);
Radek Krejci225376f2016-02-16 17:36:22 +01002623 }
Radek Krejcidce51452015-06-16 15:20:08 +02002624 free(module->imp);
2625
Radek Krejcic071c542016-01-27 14:57:51 +01002626 /* submodules don't have data tree, the data nodes
2627 * are placed in the main module altogether */
2628 if (!module->type) {
2629 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002630 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002631 }
Radek Krejci21181962015-06-30 14:11:00 +02002632 }
Radek Krejci5a065542015-05-22 15:02:07 +02002633
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002634 lydict_remove(ctx, module->dsc);
2635 lydict_remove(ctx, module->ref);
2636 lydict_remove(ctx, module->org);
2637 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002638 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002639
Radek Krejcieb00f512015-07-01 16:44:58 +02002640 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002641 for (i = 0; i < module->rev_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002642 lys_extension_instances_free(ctx, module->rev[i].ext, module->rev[i].ext_size, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002643 lydict_remove(ctx, module->rev[i].dsc);
2644 lydict_remove(ctx, module->rev[i].ref);
2645 }
2646 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002647
Radek Krejcieb00f512015-07-01 16:44:58 +02002648 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002649 for (i = 0; i < module->ident_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002650 lys_ident_free(ctx, &module->ident[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002651 }
2652 module->ident_size = 0;
2653 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002654
Radek Krejcieb00f512015-07-01 16:44:58 +02002655 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002656 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002657 lys_tpdf_free(ctx, &module->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002658 }
2659 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002660
Radek Krejcie534c132016-11-23 13:32:31 +01002661 /* extension instances */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002662 lys_extension_instances_free(ctx, module->ext, module->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002663
Radek Krejcieb00f512015-07-01 16:44:58 +02002664 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002665 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002666 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002667 }
2668 free(module->augment);
2669
Radek Krejcieb00f512015-07-01 16:44:58 +02002670 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002671 for (i = 0; i < module->features_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002672 lys_feature_free(ctx, &module->features[i], private_destructor);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002673 }
2674 free(module->features);
2675
Radek Krejcieb00f512015-07-01 16:44:58 +02002676 /* deviations */
2677 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002678 lys_deviation_free(module, &module->deviation[i], private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002679 }
2680 free(module->deviation);
2681
Radek Krejcie534c132016-11-23 13:32:31 +01002682 /* extensions */
2683 for (i = 0; i < module->extensions_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002684 lys_extension_free(ctx, &module->extensions[i], private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002685 }
2686 free(module->extensions);
2687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002688 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002689 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002690}
2691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002692void
Michal Vaskob746fff2016-02-11 11:37:50 +01002693lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002694{
Michal Vasko10681e82018-01-16 14:54:16 +01002695 int i;
2696
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002697 if (!submodule) {
2698 return;
2699 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002700
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002701 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002702 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002703
Michal Vasko10681e82018-01-16 14:54:16 +01002704 /* include */
2705 for (i = 0; i < submodule->inc_size; i++) {
2706 lydict_remove(submodule->ctx, submodule->inc[i].dsc);
2707 lydict_remove(submodule->ctx, submodule->inc[i].ref);
2708 lys_extension_instances_free(submodule->ctx, submodule->inc[i].ext, submodule->inc[i].ext_size, private_destructor);
2709 /* complete submodule free is done only from main module since
2710 * submodules propagate their includes to the main module */
2711 }
2712 free(submodule->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002713
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002714 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002715}
2716
Radek Krejcib53154b2017-07-19 09:14:13 +02002717int
2718lys_ingrouping(const struct lys_node *node)
Radek Krejci3a5501d2016-07-18 22:03:34 +02002719{
2720 const struct lys_node *iter = node;
2721 assert(node);
2722
2723 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2724 if (!iter) {
2725 return 0;
2726 } else {
2727 return 1;
2728 }
2729}
2730
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002731/*
2732 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
2733 */
2734static struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01002735lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002736 struct unres_schema *unres, int shallow, int finalize)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002737{
Radek Krejci7b9f5662016-11-07 16:28:37 +01002738 struct lys_node *retval = NULL, *iter, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002739 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002740 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002741 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002742 struct unres_list_uniq *unique_info;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002743 uint16_t flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002744
Michal Vaskoc07187d2015-08-13 15:20:57 +02002745 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002746 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002747 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002748 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002749 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002750 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002751 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002752 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002753 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002754 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002755 struct lys_node_anydata *any = NULL;
2756 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002757 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002758 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002759 struct lys_node_rpc_action *rpc = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02002760 struct lys_node_inout *io = NULL;
Radek Krejcic43151c2017-03-12 07:10:52 +01002761 struct lys_node_notif *ntf = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002762 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002763 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002765 /* we cannot just duplicate memory since the strings are stored in
2766 * dictionary and we need to update dictionary counters.
2767 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002768
Radek Krejci1d82ef62015-08-07 14:44:40 +02002769 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002770 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002771 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002772 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002773 break;
2774
Radek Krejci76512572015-08-04 09:47:08 +02002775 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002776 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002777 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002778 break;
2779
Radek Krejci76512572015-08-04 09:47:08 +02002780 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002781 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002782 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002783 break;
2784
Radek Krejci76512572015-08-04 09:47:08 +02002785 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002786 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002787 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002788 break;
2789
Radek Krejci76512572015-08-04 09:47:08 +02002790 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002791 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002792 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002793 break;
2794
Radek Krejci76512572015-08-04 09:47:08 +02002795 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002796 case LYS_ANYDATA:
2797 any = calloc(1, sizeof *any);
2798 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002799 break;
2800
Radek Krejci76512572015-08-04 09:47:08 +02002801 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002802 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002803 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002804 break;
2805
Radek Krejci76512572015-08-04 09:47:08 +02002806 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002807 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002808 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002809 break;
2810
Radek Krejci76512572015-08-04 09:47:08 +02002811 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002812 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002813 rpc = calloc(1, sizeof *rpc);
2814 retval = (struct lys_node *)rpc;
2815 break;
2816
Radek Krejci76512572015-08-04 09:47:08 +02002817 case LYS_INPUT:
2818 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002819 io = calloc(1, sizeof *io);
2820 retval = (struct lys_node *)io;
2821 break;
2822
Radek Krejci76512572015-08-04 09:47:08 +02002823 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002824 ntf = calloc(1, sizeof *ntf);
2825 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002826 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002827
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002828 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01002829 LOGINT(ctx);
Michal Vasko49168a22015-08-17 16:35:41 +02002830 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002831 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002832 LY_CHECK_ERR_RETURN(!retval, LOGMEM(ctx), NULL);
Michal Vasko253035f2015-12-17 16:58:13 +01002833
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002834 /*
2835 * duplicate generic part of the structure
2836 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002837 retval->name = lydict_insert(ctx, node->name, 0);
2838 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2839 retval->ref = lydict_insert(ctx, node->ref, 0);
2840 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002841
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002842 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002843 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002845 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002846
Radek Krejcif0bb3602017-01-25 17:05:08 +01002847 retval->ext_size = node->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01002848 if (lys_ext_dup(ctx, module, node->ext, node->ext_size, retval, LYEXT_PAR_NODE, &retval->ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002849 goto error;
2850 }
2851
Radek Krejci06214042016-11-04 16:25:58 +01002852 if (node->iffeature_size) {
2853 retval->iffeature_size = node->iffeature_size;
2854 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01002855 LY_CHECK_ERR_GOTO(!retval->iffeature, LOGMEM(ctx), error);
Michal Vasko253035f2015-12-17 16:58:13 +01002856 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002857
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002858 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002859 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002860 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2861 if (size1) {
2862 /* there is something to duplicate */
2863
2864 /* duplicate compiled expression */
2865 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2866 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01002867 LY_CHECK_ERR_GOTO(!retval->iffeature[i].expr, LOGMEM(ctx), error);
Radek Krejci9ff0a922016-07-14 13:08:05 +02002868 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2869
2870 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02002871 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Michal Vasko53b7da02018-02-13 15:28:42 +01002872 LY_CHECK_ERR_GOTO(!retval->iffeature[i].features, LOGMEM(ctx); free(retval->iffeature[i].expr), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002873
Radek Krejci9ff0a922016-07-14 13:08:05 +02002874 for (j = 0; (unsigned int)j < size2; j++) {
2875 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2876 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02002877 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002878 /* feature is resolved in origin, so copy it
2879 * - duplication is used for instantiating groupings
2880 * and if-feature inside grouping is supposed to be
2881 * resolved inside the original grouping, so we want
2882 * to keep pointers to features from the grouping
2883 * context */
2884 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2885 } else if (rc == -1) {
2886 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02002887 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02002888 }
2889 }
Radek Krejcif0bb3602017-01-25 17:05:08 +01002890
2891 /* duplicate if-feature's extensions */
2892 retval->iffeature[i].ext_size = node->iffeature[i].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01002893 if (lys_ext_dup(ctx, module, node->iffeature[i].ext, node->iffeature[i].ext_size,
Radek Krejci5138e9f2017-04-12 13:10:46 +02002894 &retval->iffeature[i], LYEXT_PAR_IFFEATURE, &retval->iffeature[i].ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002895 goto error;
2896 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002897 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002898
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002899 /* inherit config flags */
Radek Krejci7b9f5662016-11-07 16:28:37 +01002900 p = parent;
2901 do {
2902 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
2903 } while (iter && iter->nodetype == LYS_AUGMENT && (p = lys_parent(iter)));
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002904 if (iter) {
2905 flags = iter->flags & LYS_CONFIG_MASK;
2906 } else {
2907 /* default */
2908 flags = LYS_CONFIG_W;
2909 }
2910
2911 switch (finalize) {
2912 case 1:
2913 /* inherit config flags */
2914 if (retval->flags & LYS_CONFIG_SET) {
2915 /* skip nodes with an explicit config value */
2916 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002917 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
2918 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002919 goto error;
2920 }
2921 break;
2922 }
2923
2924 if (retval->nodetype != LYS_USES) {
2925 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
2926 }
Radek Krejci2cc25322017-09-06 16:32:02 +02002927
2928 /* inherit status */
Radek Krejcie2807ea2017-09-07 10:52:21 +02002929 if ((parent->flags & LYS_STATUS_MASK) > (retval->flags & LYS_STATUS_MASK)) {
2930 /* but do it only in case the parent has a stonger status */
2931 retval->flags &= ~LYS_STATUS_MASK;
2932 retval->flags |= (parent->flags & LYS_STATUS_MASK);
2933 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002934 break;
2935 case 2:
2936 /* erase config flags */
2937 retval->flags &= ~LYS_CONFIG_MASK;
2938 retval->flags &= ~LYS_CONFIG_SET;
2939 break;
2940 }
2941
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002942 /* connect it to the parent */
2943 if (lys_node_addchild(parent, retval->module, retval)) {
2944 goto error;
2945 }
Radek Krejcidce51452015-06-16 15:20:08 +02002946
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002947 /* go recursively */
2948 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002949 LY_TREE_FOR(node->child, iter) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002950 if (iter->nodetype & LYS_GROUPING) {
2951 /* do not instantiate groupings */
2952 continue;
2953 }
Radek Krejci6ff885d2017-01-03 14:06:22 +01002954 if (!lys_node_dup_recursion(module, retval, iter, unres, 0, finalize)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002955 goto error;
2956 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002957 }
2958 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002959
2960 if (finalize == 1) {
2961 /* check that configuration lists have keys
2962 * - we really want to check keys_size in original node, because the keys are
2963 * not yet resolved here, it is done below in nodetype specific part */
2964 if ((retval->nodetype == LYS_LIST) && (retval->flags & LYS_CONFIG_W)
2965 && !((struct lys_node_list *)node)->keys_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01002966 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002967 goto error;
2968 }
2969 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002970 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002971 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002972 }
2973
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002974 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002975 * duplicate specific part of the structure
2976 */
2977 switch (node->nodetype) {
2978 case LYS_CONTAINER:
2979 if (cont_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002980 cont->when = lys_when_dup(module, cont_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002981 LY_CHECK_GOTO(!cont->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002982 }
2983 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002984
Radek Krejcia8d111f2017-05-31 13:57:37 +02002985 if (cont_orig->must) {
2986 cont->must = lys_restr_dup(module, cont_orig->must, cont_orig->must_size, shallow, unres);
2987 LY_CHECK_GOTO(!cont->must, error);
2988 cont->must_size = cont_orig->must_size;
2989 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002990
Radek Krejcif0bb3602017-01-25 17:05:08 +01002991 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
2992
2993 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002994 case LYS_CHOICE:
2995 if (choice_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002996 choice->when = lys_when_dup(module, choice_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002997 LY_CHECK_GOTO(!choice->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002998 }
2999
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003000 if (!shallow) {
3001 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003002 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
3003 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
3004 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003005 if (rc) {
3006 if (rc == EXIT_FAILURE) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003007 LOGINT(ctx);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003008 }
3009 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02003010 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003011 } else {
3012 /* useless to check return value, we don't know whether
3013 * there really wasn't any default defined or it just hasn't
3014 * been resolved, we just hope for the best :)
3015 */
3016 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02003017 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003018 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003019 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003020 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003021 break;
3022
3023 case LYS_LEAF:
Radek Krejcib53154b2017-07-19 09:14:13 +02003024 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), lys_ingrouping(retval), shallow, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02003025 goto error;
3026 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
3028
3029 if (leaf_orig->dflt) {
3030 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003031 }
3032
Radek Krejcia8d111f2017-05-31 13:57:37 +02003033 if (leaf_orig->must) {
3034 leaf->must = lys_restr_dup(module, leaf_orig->must, leaf_orig->must_size, shallow, unres);
3035 LY_CHECK_GOTO(!leaf->must, error);
3036 leaf->must_size = leaf_orig->must_size;
3037 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003038
3039 if (leaf_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003040 leaf->when = lys_when_dup(module, leaf_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003041 LY_CHECK_GOTO(!leaf->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003042 }
3043 break;
3044
3045 case LYS_LEAFLIST:
Radek Krejcib53154b2017-07-19 09:14:13 +02003046 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), lys_ingrouping(retval), shallow, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02003047 goto error;
3048 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003049 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
3050
3051 llist->min = llist_orig->min;
3052 llist->max = llist_orig->max;
3053
Radek Krejcia8d111f2017-05-31 13:57:37 +02003054 if (llist_orig->must) {
3055 llist->must = lys_restr_dup(module, llist_orig->must, llist_orig->must_size, shallow, unres);
3056 LY_CHECK_GOTO(!llist->must, error);
3057 llist->must_size = llist_orig->must_size;
3058 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059
Radek Krejcia8d111f2017-05-31 13:57:37 +02003060 if (llist_orig->dflt) {
3061 llist->dflt = malloc(llist_orig->dflt_size * sizeof *llist->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01003062 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003063 llist->dflt_size = llist_orig->dflt_size;
Radek Krejcia8d111f2017-05-31 13:57:37 +02003064
Radek Krejcic699e422017-06-02 15:18:58 +02003065 for (i = 0; i < llist->dflt_size; i++) {
3066 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
Radek Krejci51673202016-11-01 17:00:32 +01003067 }
3068 }
3069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003070 if (llist_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003071 llist->when = lys_when_dup(module, llist_orig->when, shallow, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003072 }
3073 break;
3074
3075 case LYS_LIST:
3076 list->min = list_orig->min;
3077 list->max = list_orig->max;
3078
Radek Krejcia8d111f2017-05-31 13:57:37 +02003079 if (list_orig->must) {
3080 list->must = lys_restr_dup(module, list_orig->must, list_orig->must_size, shallow, unres);
3081 LY_CHECK_GOTO(!list->must, error);
3082 list->must_size = list_orig->must_size;
3083 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003084
Radek Krejcif0bb3602017-01-25 17:05:08 +01003085 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Michal Vasko38d01f72015-06-15 09:41:06 +02003086
Radek Krejcia8d111f2017-05-31 13:57:37 +02003087 if (list_orig->keys_size) {
3088 list->keys = calloc(list_orig->keys_size, sizeof *list->keys);
Michal Vasko53b7da02018-02-13 15:28:42 +01003089 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
Radek Krejci5c08a992016-11-02 13:30:04 +01003090 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003091 list->keys_size = list_orig->keys_size;
Michal Vasko0ea41032015-06-16 08:53:55 +02003092
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003093 if (!shallow) {
Radek Krejci5c08a992016-11-02 13:30:04 +01003094 /* the keys are going to be resolved only if the list is instantiated in data tree, not just
3095 * in another grouping */
3096 for (iter = parent; iter && iter->nodetype != LYS_GROUPING; iter = iter->parent);
3097 if (!iter && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
3098 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003099 }
Michal Vasko0ea41032015-06-16 08:53:55 +02003100 } else {
Radek Krejcia8d111f2017-05-31 13:57:37 +02003101 memcpy(list->keys, list_orig->keys, list_orig->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02003102 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003103 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003104
Radek Krejcia8d111f2017-05-31 13:57:37 +02003105 if (list_orig->unique) {
3106 list->unique = malloc(list_orig->unique_size * sizeof *list->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01003107 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003108 list->unique_size = list_orig->unique_size;
Radek Krejci581ce772015-11-10 17:22:40 +01003109
Radek Krejcic699e422017-06-02 15:18:58 +02003110 for (i = 0; i < list->unique_size; ++i) {
3111 list->unique[i].expr = malloc(list_orig->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01003112 LY_CHECK_ERR_GOTO(!list->unique[i].expr, LOGMEM(ctx), error);
Radek Krejcic699e422017-06-02 15:18:58 +02003113 list->unique[i].expr_size = list_orig->unique[i].expr_size;
3114 for (j = 0; j < list->unique[i].expr_size; j++) {
3115 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
3116
3117 /* if it stays in unres list, duplicate it also there */
3118 unique_info = malloc(sizeof *unique_info);
Michal Vasko53b7da02018-02-13 15:28:42 +01003119 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM(ctx), error);
Radek Krejcic699e422017-06-02 15:18:58 +02003120 unique_info->list = (struct lys_node *)list;
3121 unique_info->expr = list->unique[i].expr[j];
3122 unique_info->trg_type = &list->unique[i].trg_type;
3123 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
3124 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 }
3126 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003127
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003128 if (list_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003129 list->when = lys_when_dup(module, list_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003130 LY_CHECK_GOTO(!list->when, error);
Radek Krejciefaeba32015-05-27 14:30:57 +02003131 }
Radek Krejcidce51452015-06-16 15:20:08 +02003132 break;
3133
3134 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02003135 case LYS_ANYDATA:
Radek Krejcia8d111f2017-05-31 13:57:37 +02003136 if (any_orig->must) {
3137 any->must = lys_restr_dup(module, any_orig->must, any_orig->must_size, shallow, unres);
3138 LY_CHECK_GOTO(!any->must, error);
3139 any->must_size = any_orig->must_size;
3140 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003141
Radek Krejcibf2abff2016-08-23 15:51:52 +02003142 if (any_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003143 any->when = lys_when_dup(module, any_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003144 LY_CHECK_GOTO(!any->when, error);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003145 }
3146 break;
3147
3148 case LYS_USES:
3149 uses->grp = uses_orig->grp;
3150
3151 if (uses_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003152 uses->when = lys_when_dup(module, uses_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003153 LY_CHECK_GOTO(!uses->when, error);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003154 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003155 /* it is not needed to duplicate refine, nor augment. They are already applied to the uses children */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003156 break;
3157
3158 case LYS_CASE:
3159 if (cs_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003160 cs->when = lys_when_dup(module, cs_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003161 LY_CHECK_GOTO(!cs->when, error);
Radek Krejcidce51452015-06-16 15:20:08 +02003162 }
3163 break;
3164
Radek Krejci96935402016-11-04 16:27:28 +01003165 case LYS_ACTION:
Radek Krejcidce51452015-06-16 15:20:08 +02003166 case LYS_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003167 case LYS_INPUT:
3168 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02003169 case LYS_NOTIF:
Radek Krejcif0bb3602017-01-25 17:05:08 +01003170 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003171 break;
3172
3173 default:
3174 /* LY_NODE_AUGMENT */
Michal Vasko53b7da02018-02-13 15:28:42 +01003175 LOGINT(ctx);
Michal Vasko49168a22015-08-17 16:35:41 +02003176 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003177 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003178
3179 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02003180
3181error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003182 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02003183 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003184}
3185
Radek Krejcib3142312016-11-09 11:04:12 +01003186int
3187lys_has_xpath(const struct lys_node *node)
3188{
3189 assert(node);
3190
3191 switch (node->nodetype) {
3192 case LYS_AUGMENT:
3193 if (((struct lys_node_augment *)node)->when) {
3194 return 1;
3195 }
3196 break;
3197 case LYS_CASE:
3198 if (((struct lys_node_case *)node)->when) {
3199 return 1;
3200 }
3201 break;
3202 case LYS_CHOICE:
3203 if (((struct lys_node_choice *)node)->when) {
3204 return 1;
3205 }
3206 break;
3207 case LYS_ANYDATA:
3208 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
3209 return 1;
3210 }
3211 break;
3212 case LYS_LEAF:
3213 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
3214 return 1;
3215 }
3216 break;
3217 case LYS_LEAFLIST:
3218 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
3219 return 1;
3220 }
3221 break;
3222 case LYS_LIST:
3223 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
3224 return 1;
3225 }
3226 break;
3227 case LYS_CONTAINER:
3228 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
3229 return 1;
3230 }
3231 break;
3232 case LYS_INPUT:
3233 case LYS_OUTPUT:
3234 if (((struct lys_node_inout *)node)->must_size) {
3235 return 1;
3236 }
3237 break;
3238 case LYS_NOTIF:
3239 if (((struct lys_node_notif *)node)->must_size) {
3240 return 1;
3241 }
3242 break;
3243 case LYS_USES:
3244 if (((struct lys_node_uses *)node)->when) {
3245 return 1;
3246 }
3247 break;
3248 default:
3249 /* does not have XPath */
3250 break;
3251 }
3252
3253 return 0;
3254}
3255
Michal Vasko568b1952018-01-30 15:53:30 +01003256int
3257lys_type_is_local(const struct lys_type *type)
3258{
3259 if (!type->der->module) {
3260 /* build-in type */
3261 return 1;
3262 }
3263 /* type->parent can be either a typedef or leaf/leaf-list, but module pointers are compatible */
3264 return (lys_main_module(type->der->module) == lys_main_module(((struct lys_tpdf *)type->parent)->module));
3265}
3266
Radek Krejci2cc25322017-09-06 16:32:02 +02003267/*
3268 * shallow -
3269 * - do not inherit status from the parent
3270 */
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003271struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01003272lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003273 struct unres_schema *unres, int shallow)
3274{
3275 struct lys_node *p = NULL;
Radek Krejcib3142312016-11-09 11:04:12 +01003276 int finalize = 0;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003277 struct lys_node *result, *iter, *next;
3278
3279 if (!shallow) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003280 /* get know where in schema tree we are to know what should be done during instantiation of the grouping */
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003281 for (p = parent;
3282 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
3283 p = lys_parent(p));
3284 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
3285 }
3286
Radek Krejci6ff885d2017-01-03 14:06:22 +01003287 result = lys_node_dup_recursion(module, parent, node, unres, shallow, finalize);
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003288 if (finalize) {
3289 /* check xpath expressions in the instantiated tree */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003290 for (iter = next = result; iter; iter = next) {
Radek Krejcib3142312016-11-09 11:04:12 +01003291 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
Radek Krejci3c48d042016-11-07 14:42:36 +01003292 /* invalid xpath */
3293 return NULL;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003294 }
3295
3296 /* select next item */
3297 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
3298 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
3299 next = NULL;
3300 } else {
3301 next = iter->child;
3302 }
3303 if (!next) {
3304 /* no children, try siblings */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003305 if (iter == result) {
3306 /* we are done, no next element to process */
3307 break;
3308 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003309 next = iter->next;
3310 }
3311 while (!next) {
3312 /* parent is already processed, go to its sibling */
3313 iter = lys_parent(iter);
Radek Krejci7212e0a2017-03-08 15:58:22 +01003314 if (lys_parent(iter) == lys_parent(result)) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003315 /* we are done, no next element to process */
3316 break;
3317 }
3318 next = iter->next;
3319 }
3320 }
3321 }
3322
3323 return result;
3324}
3325
Michal Vasko13b15832015-08-19 11:04:48 +02003326void
Michal Vaskoff006c12016-02-17 11:15:19 +01003327lys_node_switch(struct lys_node *dst, struct lys_node *src)
3328{
3329 struct lys_node *child;
3330
Michal Vaskob42b6972016-06-06 14:21:30 +02003331 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01003332
3333 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02003334 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01003335 dst->prev->next = src;
3336 }
3337
3338 /* sibling prev */
3339 if (dst->next) {
3340 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02003341 } else {
3342 for (child = dst->prev; child->prev->next; child = child->prev);
3343 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01003344 }
3345
3346 /* next */
3347 src->next = dst->next;
3348 dst->next = NULL;
3349
3350 /* prev */
3351 if (dst->prev != dst) {
3352 src->prev = dst->prev;
3353 }
3354 dst->prev = dst;
3355
3356 /* parent child */
Radek Krejci30bfcd22017-01-27 16:54:48 +01003357 if (dst->parent) {
3358 if (dst->parent->child == dst) {
3359 dst->parent->child = src;
3360 }
Radek Krejci115fa882017-03-01 16:15:07 +01003361 } else if (lys_main_module(dst->module)->data == dst) {
3362 lys_main_module(dst->module)->data = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01003363 }
3364
3365 /* parent */
Radek Krejci30bfcd22017-01-27 16:54:48 +01003366 src->parent = dst->parent; dst->parent = NULL;
3367
Michal Vaskoff006c12016-02-17 11:15:19 +01003368
3369 /* child parent */
3370 LY_TREE_FOR(dst->child, child) {
3371 if (child->parent == dst) {
3372 child->parent = src;
3373 }
3374 }
3375
3376 /* child */
3377 src->child = dst->child;
3378 dst->child = NULL;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003379
3380 /* node-specific data */
3381 switch (dst->nodetype) {
3382 case LYS_CONTAINER:
3383 ((struct lys_node_container *)src)->tpdf_size = ((struct lys_node_container *)dst)->tpdf_size;
3384 ((struct lys_node_container *)src)->tpdf = ((struct lys_node_container *)dst)->tpdf;
3385 ((struct lys_node_container *)dst)->tpdf_size = 0;
3386 ((struct lys_node_container *)dst)->tpdf = NULL;
3387 break;
3388 case LYS_LIST:
3389 ((struct lys_node_list *)src)->tpdf_size = ((struct lys_node_list *)dst)->tpdf_size;
3390 ((struct lys_node_list *)src)->tpdf = ((struct lys_node_list *)dst)->tpdf;
3391 ((struct lys_node_list *)dst)->tpdf_size = 0;
3392 ((struct lys_node_list *)dst)->tpdf = NULL;
3393 break;
3394 case LYS_RPC:
3395 case LYS_ACTION:
3396 ((struct lys_node_rpc_action *)src)->tpdf_size = ((struct lys_node_rpc_action *)dst)->tpdf_size;
3397 ((struct lys_node_rpc_action *)src)->tpdf = ((struct lys_node_rpc_action *)dst)->tpdf;
3398 ((struct lys_node_rpc_action *)dst)->tpdf_size = 0;
3399 ((struct lys_node_rpc_action *)dst)->tpdf = NULL;
3400 break;
3401 case LYS_NOTIF:
3402 ((struct lys_node_notif *)src)->tpdf_size = ((struct lys_node_notif *)dst)->tpdf_size;
3403 ((struct lys_node_notif *)src)->tpdf = ((struct lys_node_notif *)dst)->tpdf;
3404 ((struct lys_node_notif *)dst)->tpdf_size = 0;
3405 ((struct lys_node_notif *)dst)->tpdf = NULL;
3406 break;
3407 case LYS_INPUT:
3408 case LYS_OUTPUT:
3409 ((struct lys_node_inout *)src)->tpdf_size = ((struct lys_node_inout *)dst)->tpdf_size;
3410 ((struct lys_node_inout *)src)->tpdf = ((struct lys_node_inout *)dst)->tpdf;
3411 ((struct lys_node_inout *)dst)->tpdf_size = 0;
3412 ((struct lys_node_inout *)dst)->tpdf = NULL;
3413 break;
3414 default:
3415 /* nothing special */
3416 break;
3417 }
3418
Michal Vaskoff006c12016-02-17 11:15:19 +01003419}
3420
3421void
Michal Vasko10681e82018-01-16 14:54:16 +01003422lys_free(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv), int free_subs, int remove_from_ctx)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003423{
3424 struct ly_ctx *ctx;
3425 int i;
3426
3427 if (!module) {
3428 return;
3429 }
3430
3431 /* remove schema from the context */
3432 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01003433 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02003434 for (i = 0; i < ctx->models.used; i++) {
3435 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01003436 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003437 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01003438 memmove(&ctx->models.list[i], ctx->models.list[i + 1], (ctx->models.used - i) * sizeof *ctx->models.list);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003439 ctx->models.list[ctx->models.used] = NULL;
3440 /* we are done */
3441 break;
3442 }
3443 }
3444 }
3445
3446 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01003447 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003448
Michal Vasko10681e82018-01-16 14:54:16 +01003449 /* include */
3450 for (i = 0; i < module->inc_size; i++) {
3451 lydict_remove(ctx, module->inc[i].dsc);
3452 lydict_remove(ctx, module->inc[i].ref);
3453 lys_extension_instances_free(ctx, module->inc[i].ext, module->inc[i].ext_size, private_destructor);
3454 /* complete submodule free is done only from main module since
3455 * submodules propagate their includes to the main module */
3456 if (free_subs) {
3457 lys_submodule_free(module->inc[i].submodule, private_destructor);
3458 }
3459 }
3460 free(module->inc);
3461
Radek Krejcida04f4a2015-05-21 12:54:09 +02003462 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01003463 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003464
3465 free(module);
3466}
Radek Krejci7e97c352015-06-19 16:26:34 +02003467
Radek Krejci9de2c042016-10-19 16:53:06 +02003468static void
3469lys_features_disable_recursive(struct lys_feature *f)
3470{
3471 unsigned int i;
3472 struct lys_feature *depf;
3473
3474 /* disable the feature */
3475 f->flags &= ~LYS_FENABLED;
3476
3477 /* by disabling feature we have to disable also all features that depends on this feature */
3478 if (f->depfeatures) {
3479 for (i = 0; i < f->depfeatures->number; i++) {
3480 depf = (struct lys_feature *)f->depfeatures->set.g[i];
3481 if (depf->flags & LYS_FENABLED) {
3482 lys_features_disable_recursive(depf);
3483 }
3484 }
3485 }
3486}
3487
3488
Radek Krejci7e97c352015-06-19 16:26:34 +02003489/*
3490 * op: 1 - enable, 0 - disable
3491 */
3492static int
Michal Vasko1e62a092015-12-01 12:27:20 +01003493lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02003494{
3495 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003496 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02003497 int progress, faili, failj, failk;
3498
3499 uint8_t fsize;
3500 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02003501
3502 if (!module || !name || !strlen(name)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003503 LOGARG;
Radek Krejci7e97c352015-06-19 16:26:34 +02003504 return EXIT_FAILURE;
3505 }
3506
3507 if (!strcmp(name, "*")) {
3508 /* enable all */
3509 all = 1;
3510 }
3511
Radek Krejcia889c1f2016-10-19 15:50:11 +02003512 progress = failk = 1;
3513 while (progress && failk) {
3514 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
3515 if (i == -1) {
3516 fsize = module->features_size;
3517 f = module->features;
3518 } else {
3519 fsize = module->inc[i].submodule->features_size;
3520 f = module->inc[i].submodule->features;
3521 }
3522
3523 for (j = 0; j < fsize; j++) {
3524 if (all || !strcmp(f[j].name, name)) {
Michal Vasko34c3b552016-11-21 09:07:43 +01003525 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
3526 if (all) {
3527 /* skip already set features */
3528 continue;
3529 } else {
3530 /* feature already set correctly */
3531 return EXIT_SUCCESS;
3532 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003533 }
3534
3535 if (op) {
3536 /* check referenced features if they are enabled */
3537 for (k = 0; k < f[j].iffeature_size; k++) {
3538 if (!resolve_iffeature(&f[j].iffeature[k])) {
3539 if (all) {
3540 faili = i;
3541 failj = j;
3542 failk = k + 1;
3543 break;
3544 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003545 LOGERR(module->ctx, LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
Radek Krejcia889c1f2016-10-19 15:50:11 +02003546 f[j].name, k + 1);
3547 return EXIT_FAILURE;
3548 }
3549 }
3550 }
3551
3552 if (k == f[j].iffeature_size) {
3553 /* the last check passed, do the change */
3554 f[j].flags |= LYS_FENABLED;
3555 progress++;
3556 }
3557 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02003558 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02003559 progress++;
3560 }
3561 if (!all) {
3562 /* stop in case changing a single feature */
3563 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003564 }
3565 }
Radek Krejci7e97c352015-06-19 16:26:34 +02003566 }
3567 }
3568 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003569 if (failk) {
3570 /* print info about the last failing feature */
Michal Vasko53b7da02018-02-13 15:28:42 +01003571 LOGERR(module->ctx, LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
Radek Krejcia889c1f2016-10-19 15:50:11 +02003572 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
3573 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02003574 }
3575
3576 if (all) {
3577 return EXIT_SUCCESS;
3578 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02003579 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02003580 return EXIT_FAILURE;
3581 }
3582}
3583
3584API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003585lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003586{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003587 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02003588}
3589
3590API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003591lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003592{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003593 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003594}
3595
3596API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003597lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003598{
3599 int i, j;
3600
3601 if (!module || !feature) {
3602 return -1;
3603 }
3604
3605 /* search for the specified feature */
3606 /* module itself */
3607 for (i = 0; i < module->features_size; i++) {
3608 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003609 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003610 return 1;
3611 } else {
3612 return 0;
3613 }
3614 }
3615 }
3616
3617 /* submodules */
3618 for (j = 0; j < module->inc_size; j++) {
3619 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
3620 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003621 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003622 return 1;
3623 } else {
3624 return 0;
3625 }
3626 }
3627 }
3628 }
3629
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003630 /* feature definition not found */
3631 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02003632}
Michal Vasko2367e7c2015-07-07 11:33:44 +02003633
Radek Krejci96a10da2015-07-30 11:00:14 +02003634API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01003635lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02003636{
Radek Krejci96a10da2015-07-30 11:00:14 +02003637 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003638 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003639 unsigned int count;
3640
3641 if (!module) {
3642 return NULL;
3643 }
3644
3645 count = module->features_size;
3646 for (i = 0; i < module->inc_size; i++) {
3647 count += module->inc[i].submodule->features_size;
3648 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003649 result = malloc((count + 1) * sizeof *result);
Michal Vasko53b7da02018-02-13 15:28:42 +01003650 LY_CHECK_ERR_RETURN(!result, LOGMEM(module->ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003651
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003652 if (states) {
3653 *states = malloc((count + 1) * sizeof **states);
Michal Vasko53b7da02018-02-13 15:28:42 +01003654 LY_CHECK_ERR_RETURN(!(*states), LOGMEM(module->ctx); free(result), NULL);
Michal Vasko2367e7c2015-07-07 11:33:44 +02003655 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003656 count = 0;
3657
3658 /* module itself */
3659 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003660 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003661 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003662 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003663 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003664 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003665 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003666 }
3667 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003668 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003669 }
3670
3671 /* submodules */
3672 for (j = 0; j < module->inc_size; j++) {
3673 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003674 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003675 if (states) {
3676 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3677 (*states)[count] = 1;
3678 } else {
3679 (*states)[count] = 0;
3680 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003681 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003682 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003683 }
3684 }
3685
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003686 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003687 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003688
3689 return result;
3690}
Michal Vaskobaefb032015-09-24 14:52:10 +02003691
Radek Krejci6910a032016-04-13 10:06:21 +02003692API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01003693lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01003694{
Michal Vaskof53187d2017-01-13 13:23:14 +01003695 if (!node) {
3696 return NULL;
3697 }
3698
Radek Krejcic071c542016-01-27 14:57:51 +01003699 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
3700}
3701
Radek Krejci6910a032016-04-13 10:06:21 +02003702API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02003703lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01003704{
Michal Vaskof53187d2017-01-13 13:23:14 +01003705 if (!module) {
3706 return NULL;
3707 }
3708
Michal Vasko320e8532016-02-15 13:11:57 +01003709 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
3710}
3711
Michal Vaskobaefb032015-09-24 14:52:10 +02003712API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01003713lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02003714{
Radek Krejcif95b6292017-02-13 15:57:37 +01003715 struct lys_node *parent;
3716
3717 if (!node) {
Michal Vaskobaefb032015-09-24 14:52:10 +02003718 return NULL;
3719 }
3720
Radek Krejcif95b6292017-02-13 15:57:37 +01003721 if (node->nodetype == LYS_EXT) {
3722 if (((struct lys_ext_instance_complex*)node)->parent_type != LYEXT_PAR_NODE) {
3723 return NULL;
3724 }
3725 parent = (struct lys_node*)((struct lys_ext_instance_complex*)node)->parent;
3726 } else if (!node->parent) {
3727 return NULL;
3728 } else {
3729 parent = node->parent;
Michal Vaskobaefb032015-09-24 14:52:10 +02003730 }
3731
Radek Krejcif95b6292017-02-13 15:57:37 +01003732 if (parent->nodetype == LYS_AUGMENT) {
3733 return ((struct lys_node_augment *)parent)->target;
3734 } else {
3735 return parent;
3736 }
3737}
3738
3739struct lys_node **
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01003740lys_child(const struct lys_node *node, LYS_NODE nodetype)
Radek Krejcif95b6292017-02-13 15:57:37 +01003741{
3742 void *pp;
3743 assert(node);
3744
3745 if (node->nodetype == LYS_EXT) {
3746 pp = lys_ext_complex_get_substmt(lys_snode2stmt(nodetype), (struct lys_ext_instance_complex*)node, NULL);
3747 if (!pp) {
3748 return NULL;
3749 }
3750 return (struct lys_node **)pp;
Michal Vasko54d4c202017-08-09 14:09:18 +02003751 } else if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Radek Krejcif7fe2cb2017-08-09 10:27:12 +02003752 return NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +01003753 } else {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01003754 return (struct lys_node **)&node->child;
Radek Krejcif95b6292017-02-13 15:57:37 +01003755 }
Michal Vaskobaefb032015-09-24 14:52:10 +02003756}
Michal Vasko1b229152016-01-13 11:28:38 +01003757
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003758API void *
Michal Vasko1b229152016-01-13 11:28:38 +01003759lys_set_private(const struct lys_node *node, void *priv)
3760{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003761 void *prev;
3762
Michal Vasko1b229152016-01-13 11:28:38 +01003763 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003764 LOGARG;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003765 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01003766 }
3767
Mislav Novakovicb5529e52016-02-29 11:42:43 +01003768 prev = node->priv;
3769 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003770
3771 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01003772}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003773
Michal Vasko01c6fd22016-05-20 11:43:05 +02003774int
3775lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
3776{
Michal Vasko53b7da02018-02-13 15:28:42 +01003777 struct lys_node_leaf *iter;
3778 struct ly_ctx *ctx = leafref_target->module->ctx;
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003779
Michal Vasko48a573d2016-07-01 11:46:02 +02003780 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003781 LOGINT(ctx);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003782 return -1;
3783 }
3784
Pavol Vican93175152016-08-30 15:34:44 +02003785 /* check for config flag */
Radek Krejcic688ca02017-03-20 12:54:39 +01003786 if (((struct lys_node_leaf*)leafref)->type.info.lref.req != -1 &&
3787 (leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003788 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, leafref,
Radek Krejcid831dd42017-03-16 12:59:30 +01003789 "The leafref %s is config but refers to a non-config %s.",
Pavol Vican93175152016-08-30 15:34:44 +02003790 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
3791 return -1;
3792 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003793 /* check for cycles */
Michal Vasko53b7da02018-02-13 15:28:42 +01003794 for (iter = leafref_target; iter && iter->type.base == LY_TYPE_LEAFREF; iter = iter->type.info.lref.target) {
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003795 if ((void *)iter == (void *)leafref) {
3796 /* cycle detected */
Michal Vasko53b7da02018-02-13 15:28:42 +01003797 LOGVAL(ctx, LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003798 return -1;
3799 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003800 }
3801
3802 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02003803 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02003804 if (!leafref_target->backlinks) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003805 leafref_target->backlinks = (void *)ly_set_new();
Radek Krejci85a54be2016-10-20 12:39:56 +02003806 if (!leafref_target->backlinks) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003807 LOGMEM(ctx);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003808 return -1;
3809 }
3810 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003811 ly_set_add(leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003812
3813 return 0;
3814}
3815
Michal Vasko8548e082016-07-22 12:00:18 +02003816/* not needed currently */
3817#if 0
3818
Michal Vasko5b3492c2016-07-20 09:37:40 +02003819static const char *
3820lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
3821{
3822 struct lys_module *prev_mod;
3823 uint32_t str_len, mod_len, buf_idx;
3824
Radek Krejcibf2abff2016-08-23 15:51:52 +02003825 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003826 LOGINT;
3827 return NULL;
3828 }
3829
3830 buf_idx = buf_len - 1;
3831 buf[buf_idx] = '\0';
3832
3833 while (node) {
3834 if (lys_parent(node)) {
3835 prev_mod = lys_node_module(lys_parent(node));
3836 } else {
3837 prev_mod = NULL;
3838 }
3839
Radek Krejcibf2abff2016-08-23 15:51:52 +02003840 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003841 str_len = strlen(node->name);
3842
3843 if (prev_mod != node->module) {
3844 mod_len = strlen(node->module->name);
3845 } else {
3846 mod_len = 0;
3847 }
3848
3849 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
3850 LOGINT;
3851 return NULL;
3852 }
3853
3854 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
3855
3856 buf[buf_idx] = '/';
3857 if (mod_len) {
3858 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
3859 buf[buf_idx + 1 + mod_len] = ':';
3860 }
3861 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
3862 }
3863
3864 node = lys_parent(node);
3865 }
3866
3867 return buf + buf_idx;
3868}
3869
Michal Vasko8548e082016-07-22 12:00:18 +02003870#endif
3871
3872API struct ly_set *
Michal Vasko9ff79aa2017-07-03 14:10:32 +02003873lys_xpath_atomize(const struct lys_node *ctx_node, enum lyxp_node_type ctx_node_type, const char *expr, int options)
Michal Vasko5b3492c2016-07-20 09:37:40 +02003874{
Michal Vasko508a50d2016-09-07 14:50:33 +02003875 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02003876 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003877 uint32_t i;
3878
Michal Vasko9ff79aa2017-07-03 14:10:32 +02003879 if (!ctx_node || !expr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003880 LOGARG;
Michal Vasko8548e082016-07-22 12:00:18 +02003881 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003882 }
3883
Michal Vaskob94a5e42016-09-08 14:01:56 +02003884 /* adjust the root */
Michal Vasko9ff79aa2017-07-03 14:10:32 +02003885 if ((ctx_node_type == LYXP_NODE_ROOT) || (ctx_node_type == LYXP_NODE_ROOT_CONFIG)) {
Michal Vaskob94a5e42016-09-08 14:01:56 +02003886 do {
Michal Vaskocb45f472018-02-12 10:47:42 +01003887 ctx_node = lys_getnext(NULL, NULL, lys_node_module(ctx_node), LYS_GETNEXT_NOSTATECHECK);
Michal Vasko9ff79aa2017-07-03 14:10:32 +02003888 } while ((ctx_node_type == LYXP_NODE_ROOT_CONFIG) && (ctx_node->flags & LYS_CONFIG_R));
Michal Vaskob94a5e42016-09-08 14:01:56 +02003889 }
3890
Michal Vasko508a50d2016-09-07 14:50:33 +02003891 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02003892
3893 if (options & LYXP_MUST) {
3894 options &= ~LYXP_MUST;
3895 options |= LYXP_SNODE_MUST;
3896 } else if (options & LYXP_WHEN) {
3897 options &= ~LYXP_WHEN;
3898 options |= LYXP_SNODE_WHEN;
3899 } else {
3900 options |= LYXP_SNODE;
3901 }
3902
Michal Vasko9ff79aa2017-07-03 14:10:32 +02003903 if (lyxp_atomize(expr, ctx_node, ctx_node_type, &set, options, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003904 free(set.val.snodes);
Michal Vasko53b7da02018-02-13 15:28:42 +01003905 LOGVAL(ctx_node->module->ctx, LYE_SPEC, LY_VLOG_LYS, ctx_node, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko8548e082016-07-22 12:00:18 +02003906 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003907 }
3908
Michal Vasko8548e082016-07-22 12:00:18 +02003909 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003910
Michal Vasko508a50d2016-09-07 14:50:33 +02003911 for (i = 0; i < set.used; ++i) {
3912 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003913 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02003914 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02003915 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02003916 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02003917 return NULL;
3918 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003919 break;
3920 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02003921 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003922 break;
3923 }
3924 }
3925
Michal Vasko508a50d2016-09-07 14:50:33 +02003926 free(set.val.snodes);
3927 return ret_set;
3928}
3929
3930API struct ly_set *
3931lys_node_xpath_atomize(const struct lys_node *node, int options)
3932{
3933 const struct lys_node *next, *elem, *parent, *tmp;
3934 struct lyxp_set set;
3935 struct ly_set *ret_set;
3936 uint16_t i;
3937
3938 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003939 LOGARG;
Michal Vasko508a50d2016-09-07 14:50:33 +02003940 return NULL;
3941 }
3942
3943 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
3944 if (!parent) {
3945 /* not in input, output, or notification */
3946 return NULL;
3947 }
3948
3949 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02003950 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003951 return NULL;
3952 }
3953
3954 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoc04173b2018-03-09 10:43:22 +01003955 if ((options & LYXP_NO_LOCAL) && !(elem->flags & (LYS_XPCONF_DEP | LYS_XPSTATE_DEP))) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003956 /* elem has no dependencies from other subtrees and local nodes get discarded */
3957 goto next_iter;
3958 }
3959
Michal Vaskof96dfb62017-08-17 12:23:49 +02003960 if (lyxp_node_atomize(elem, &set, 0)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003961 ly_set_free(ret_set);
3962 free(set.val.snodes);
3963 return NULL;
3964 }
3965
3966 for (i = 0; i < set.used; ++i) {
3967 switch (set.val.snodes[i].type) {
3968 case LYXP_NODE_ELEM:
3969 if (options & LYXP_NO_LOCAL) {
3970 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
3971 if (tmp) {
3972 /* in local subtree, discard */
3973 break;
3974 }
3975 }
3976 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
3977 ly_set_free(ret_set);
3978 free(set.val.snodes);
3979 return NULL;
3980 }
3981 break;
3982 default:
3983 /* ignore roots, text and attr should not ever appear */
3984 break;
3985 }
3986 }
3987
3988 free(set.val.snodes);
3989 if (!(options & LYXP_RECURSIVE)) {
3990 break;
3991 }
3992next_iter:
3993 LY_TREE_DFS_END(node, next, elem);
3994 }
3995
Michal Vasko8548e082016-07-22 12:00:18 +02003996 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003997}
3998
Michal Vasko44ab1462017-05-18 13:18:36 +02003999/* logs */
4000int
4001apply_aug(struct lys_node_augment *augment, struct unres_schema *unres)
Radek Krejci0ec51da2016-12-14 16:42:03 +01004002{
Michal Vasko44ab1462017-05-18 13:18:36 +02004003 struct lys_node *child, *parent;
4004 int clear_config;
4005 unsigned int u;
Michal Vaskod02e30e2018-01-22 13:35:48 +01004006 uint8_t *v;
Michal Vasko44ab1462017-05-18 13:18:36 +02004007 struct lys_ext_instance *ext;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004008
4009 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
4010
Radek Krejcic9d78692017-08-24 17:17:18 +02004011 if (!augment->child) {
4012 /* nothing to apply */
4013 goto success;
4014 }
4015
Michal Vaskobb520442017-05-23 10:55:18 +02004016 /* check that all the modules are implemented */
4017 for (parent = augment->target; parent; parent = lys_parent(parent)) {
4018 if (!lys_node_module(parent)->implemented) {
4019 if (lys_set_implemented(lys_node_module(parent))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004020 LOGERR(augment->module->ctx, ly_errno, "Making the augment target module \"%s\" implemented failed.",
4021 lys_node_module(parent)->name);
Michal Vaskobb520442017-05-23 10:55:18 +02004022 return -1;
4023 }
Michal Vaskobb520442017-05-23 10:55:18 +02004024 }
4025 }
4026
Radek Krejci0ec51da2016-12-14 16:42:03 +01004027 /* reconnect augmenting data into the target - add them to the target child list */
4028 if (augment->target->child) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004029 child = augment->target->child->prev;
4030 child->next = augment->child;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004031 augment->target->child->prev = augment->child->prev;
Michal Vasko44ab1462017-05-18 13:18:36 +02004032 augment->child->prev = child;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004033 } else {
4034 augment->target->child = augment->child;
4035 }
4036
Michal Vasko44ab1462017-05-18 13:18:36 +02004037 /* inherit config information from actual parent */
4038 for (parent = augment->target; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); parent = lys_parent(parent));
4039 clear_config = (parent) ? 1 : 0;
4040 LY_TREE_FOR(augment->child, child) {
4041 if (inherit_config_flag(child, augment->target->flags & LYS_CONFIG_MASK, clear_config)) {
4042 return -1;
4043 }
4044 }
4045
4046 /* inherit extensions if any */
4047 for (u = 0; u < augment->target->ext_size; u++) {
4048 ext = augment->target->ext[u]; /* shortcut */
4049 if (ext && ext->def->plugin && (ext->def->plugin->flags & LYEXT_OPT_INHERIT)) {
Michal Vaskod02e30e2018-01-22 13:35:48 +01004050 v = malloc(sizeof *v);
Michal Vasko53b7da02018-02-13 15:28:42 +01004051 LY_CHECK_ERR_RETURN(!v, LOGMEM(augment->module->ctx), -1);
Michal Vaskod02e30e2018-01-22 13:35:48 +01004052 *v = u;
4053 if (unres_schema_add_node(lys_main_module(augment->module), unres, &augment->target->ext,
4054 UNRES_EXT_FINALIZE, (struct lys_node *)v) == -1) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004055 /* something really bad happend since the extension finalization is not actually
4056 * being resolved while adding into unres, so something more serious with the unres
4057 * list itself must happened */
4058 return -1;
4059 }
4060 }
4061 }
4062
Radek Krejcic9d78692017-08-24 17:17:18 +02004063success:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004064 /* remove the flag about not applicability */
4065 augment->flags &= ~LYS_NOTAPPLIED;
Michal Vasko44ab1462017-05-18 13:18:36 +02004066 return EXIT_SUCCESS;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004067}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004068
Radek Krejcib2541a32016-12-12 16:45:57 +01004069static void
4070remove_aug(struct lys_node_augment *augment)
4071{
4072 struct lys_node *last, *elem;
4073
Michal Vaskof1aa47d2017-09-21 12:09:29 +02004074 if ((augment->flags & LYS_NOTAPPLIED) || !augment->target) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004075 /* skip already not applied augment */
Radek Krejcib2541a32016-12-12 16:45:57 +01004076 return;
4077 }
4078
4079 elem = augment->child;
4080 if (elem) {
4081 LY_TREE_FOR(elem, last) {
4082 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
4083 break;
4084 }
4085 }
4086 /* elem is first augment child, last is the last child */
4087
4088 /* parent child ptr */
4089 if (augment->target->child == elem) {
4090 augment->target->child = last->next;
4091 }
4092
4093 /* parent child next ptr */
4094 if (elem->prev->next) {
4095 elem->prev->next = last->next;
4096 }
4097
4098 /* parent child prev ptr */
4099 if (last->next) {
4100 last->next->prev = elem->prev;
4101 } else if (augment->target->child) {
4102 augment->target->child->prev = elem->prev;
4103 }
4104
4105 /* update augment children themselves */
4106 elem->prev = last;
4107 last->next = NULL;
4108 }
4109
Radek Krejci0ec51da2016-12-14 16:42:03 +01004110 /* augment->target still keeps the resolved target, but for lys_augment_free()
4111 * we have to keep information that this augment is not applied to free its data */
4112 augment->flags |= LYS_NOTAPPLIED;
Radek Krejcib2541a32016-12-12 16:45:57 +01004113}
4114
Radek Krejci30bfcd22017-01-27 16:54:48 +01004115/*
4116 * @param[in] module - the module where the deviation is defined
4117 */
4118static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004119lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004120{
Radek Krejcic9d78692017-08-24 17:17:18 +02004121 int ret, reapply = 0;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004122 char *parent_path;
4123 struct lys_node *target = NULL, *parent;
Michal Vasko50576712017-07-28 12:28:33 +02004124 struct ly_set *set;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004125
4126 if (!dev->deviate) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004127 return;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004128 }
4129
4130 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
4131 if (dev->orig_node) {
4132 /* removing not-supported deviation ... */
4133 if (strrchr(dev->target_name, '/') != dev->target_name) {
4134 /* ... from a parent */
4135
4136 /* reconnect to its previous position */
4137 parent = dev->orig_node->parent;
Michal Vaskoa1074a52018-01-03 12:18:53 +01004138 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejcic9d78692017-08-24 17:17:18 +02004139 dev->orig_node->parent = NULL;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004140 /* the original node was actually from augment, we have to get know if the augment is
4141 * applied (its module is enabled and implemented). If yes, the node will be connected
4142 * to the augment and the linkage with the target will be fixed if needed, otherwise
4143 * it will be connected only to the augment */
Radek Krejcic9d78692017-08-24 17:17:18 +02004144 if (!(parent->flags & LYS_NOTAPPLIED)) {
4145 /* start with removing augment if applied before adding nodes, we have to make sure
4146 * that everything will be connect correctly */
4147 remove_aug((struct lys_node_augment *)parent);
4148 reapply = 1;
4149 }
4150 /* connect the deviated node back into the augment */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004151 lys_node_addchild(parent, NULL, dev->orig_node);
Radek Krejcic9d78692017-08-24 17:17:18 +02004152 if (reapply) {
Radek Krejci30bfcd22017-01-27 16:54:48 +01004153 /* augment is supposed to be applied, so fix pointers in target and the status of the original node */
Michal Vasko823fbe02017-12-14 11:01:40 +01004154 parent->flags |= LYS_NOTAPPLIED; /* allow apply_aug() */
4155 apply_aug((struct lys_node_augment *)parent, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004156 }
Michal Vaskoa1074a52018-01-03 12:18:53 +01004157 } else if (parent && (parent->nodetype == LYS_USES)) {
4158 /* uses child */
4159 lys_node_addchild(parent, NULL, dev->orig_node);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004160 } else {
4161 /* non-augment, non-toplevel */
4162 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
Michal Vasko50576712017-07-28 12:28:33 +02004163 ret = resolve_schema_nodeid(parent_path, NULL, module, &set, 0, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004164 free(parent_path);
Michal Vasko50576712017-07-28 12:28:33 +02004165 if (ret == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004166 LOGINT(module->ctx);
Michal Vasko50576712017-07-28 12:28:33 +02004167 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004168 return;
4169 }
Michal Vasko50576712017-07-28 12:28:33 +02004170 target = set->set.s[0];
4171 ly_set_free(set);
4172
Radek Krejci30bfcd22017-01-27 16:54:48 +01004173 lys_node_addchild(target, NULL, dev->orig_node);
4174 }
4175 } else {
4176 /* ... from top-level data */
4177 lys_node_addchild(NULL, (struct lys_module *)dev->orig_node->module, dev->orig_node);
4178 }
4179
4180 dev->orig_node = NULL;
4181 } else {
4182 /* adding not-supported deviation */
Michal Vasko50576712017-07-28 12:28:33 +02004183 ret = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4184 if (ret == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004185 LOGINT(module->ctx);
Michal Vasko50576712017-07-28 12:28:33 +02004186 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004187 return;
4188 }
Michal Vasko50576712017-07-28 12:28:33 +02004189 target = set->set.s[0];
4190 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004191
4192 /* unlink and store the original node */
4193 parent = target->parent;
4194 lys_node_unlink(target);
Michal Vaskoa1074a52018-01-03 12:18:53 +01004195 if (parent && (parent->nodetype & (LYS_AUGMENT | LYS_USES))) {
Radek Krejci30bfcd22017-01-27 16:54:48 +01004196 /* hack for augment, because when the original will be sometime reconnected back, we actually need
4197 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
4198 * path), so we need to remember the augment as an addition */
Michal Vaskoa1074a52018-01-03 12:18:53 +01004199 /* we also need to remember the parent uses so that we connect it back to it when switching deviation state */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004200 target->parent = parent;
4201 }
4202 dev->orig_node = target;
4203 }
4204 } else {
Michal Vasko50576712017-07-28 12:28:33 +02004205 ret = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4206 if (ret == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004207 LOGINT(module->ctx);
Michal Vasko50576712017-07-28 12:28:33 +02004208 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004209 return;
4210 }
Michal Vasko50576712017-07-28 12:28:33 +02004211 target = set->set.s[0];
4212 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004213
4214 lys_node_switch(target, dev->orig_node);
4215 dev->orig_node = target;
4216 }
4217}
4218
4219/* temporarily removes or applies deviations, updates module deviation flag accordingly */
4220void
Michal Vasko5a65f212018-03-19 15:08:08 +01004221lys_enable_deviations(struct lys_module *module)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004222{
4223 uint32_t i = 0, j;
4224 const struct lys_module *mod;
4225 const char *ptr;
Michal Vasko44ab1462017-05-18 13:18:36 +02004226 struct unres_schema *unres;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004227
4228 if (module->deviated) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004229 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01004230 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
Michal Vasko44ab1462017-05-18 13:18:36 +02004231
Radek Krejci30bfcd22017-01-27 16:54:48 +01004232 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
4233 if (mod == module) {
4234 continue;
4235 }
4236
4237 for (j = 0; j < mod->deviation_size; ++j) {
4238 ptr = strstr(mod->deviation[j].target_name, module->name);
4239 if (ptr && ptr[strlen(module->name)] == ':') {
Michal Vasko44ab1462017-05-18 13:18:36 +02004240 lys_switch_deviation(&mod->deviation[j], mod, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004241 }
4242 }
4243 }
4244
Michal Vasko5a65f212018-03-19 15:08:08 +01004245 assert(module->deviated == 2);
4246 module->deviated = 1;
4247
4248 for (j = 0; j < module->inc_size; j++) {
4249 if (module->inc[j].submodule->deviated) {
4250 module->inc[j].submodule->deviated = module->deviated;
4251 }
Radek Krejci30bfcd22017-01-27 16:54:48 +01004252 }
Michal Vasko5a65f212018-03-19 15:08:08 +01004253
4254 if (unres->count) {
4255 resolve_unres_schema(module, unres);
4256 }
4257 unres_schema_free(module, &unres, 1);
4258 }
4259}
4260
4261void
4262lys_disable_deviations(struct lys_module *module)
4263{
4264 uint32_t i, j;
4265 const struct lys_module *mod;
4266 const char *ptr;
4267 struct unres_schema *unres;
4268
4269 if (module->deviated) {
4270 unres = calloc(1, sizeof *unres);
4271 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
4272
4273 i = module->ctx->models.used;
4274 while (i--) {
4275 mod = module->ctx->models.list[i];
4276
4277 if (mod == module) {
4278 continue;
4279 }
4280
4281 j = mod->deviation_size;
4282 while (j--) {
4283 ptr = strstr(mod->deviation[j].target_name, module->name);
4284 if (ptr && ptr[strlen(module->name)] == ':') {
4285 lys_switch_deviation(&mod->deviation[j], mod, unres);
4286 }
4287 }
4288 }
4289
4290 assert(module->deviated == 1);
4291 module->deviated = 2;
4292
Radek Krejci29eac3d2017-06-01 16:50:02 +02004293 for (j = 0; j < module->inc_size; j++) {
4294 if (module->inc[j].submodule->deviated) {
4295 module->inc[j].submodule->deviated = module->deviated;
4296 }
4297 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004298
4299 if (unres->count) {
4300 resolve_unres_schema(module, unres);
4301 }
4302 unres_schema_free(module, &unres, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004303 }
4304}
4305
4306static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004307apply_dev(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004308{
Michal Vasko44ab1462017-05-18 13:18:36 +02004309 lys_switch_deviation(dev, module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004310
4311 assert(dev->orig_node);
Radek Krejci29eac3d2017-06-01 16:50:02 +02004312 lys_node_module(dev->orig_node)->deviated = 1; /* main module */
4313 dev->orig_node->module->deviated = 1; /* possible submodule */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004314}
4315
4316static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004317remove_dev(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004318{
4319 uint32_t idx = 0, j;
4320 const struct lys_module *mod;
Radek Krejci29eac3d2017-06-01 16:50:02 +02004321 struct lys_module *target_mod, *target_submod;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004322 const char *ptr;
4323
4324 if (dev->orig_node) {
4325 target_mod = lys_node_module(dev->orig_node);
Radek Krejci29eac3d2017-06-01 16:50:02 +02004326 target_submod = dev->orig_node->module;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004327 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004328 LOGINT(module->ctx);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004329 return;
4330 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004331 lys_switch_deviation(dev, module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004332
4333 /* clear the deviation flag if possible */
4334 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
4335 if ((mod == module) || (mod == target_mod)) {
4336 continue;
4337 }
4338
4339 for (j = 0; j < mod->deviation_size; ++j) {
4340 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
4341 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
4342 /* some other module deviation targets the inspected module, flag remains */
4343 break;
4344 }
4345 }
4346
4347 if (j < mod->deviation_size) {
4348 break;
4349 }
4350 }
4351
4352 if (!mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02004353 target_mod->deviated = 0; /* main module */
4354 target_submod->deviated = 0; /* possible submodule */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004355 }
4356}
4357
4358void
4359lys_sub_module_apply_devs_augs(struct lys_module *module)
4360{
4361 uint8_t u, v;
Michal Vasko44ab1462017-05-18 13:18:36 +02004362 struct unres_schema *unres;
4363
4364 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01004365 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
Radek Krejci30bfcd22017-01-27 16:54:48 +01004366
4367 /* remove applied deviations */
4368 for (u = 0; u < module->deviation_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004369 apply_dev(&module->deviation[u], module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004370 }
4371 /* remove applied augments */
4372 for (u = 0; u < module->augment_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004373 apply_aug(&module->augment[u], unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004374 }
4375
4376 /* remove deviation and augments defined in submodules */
4377 for (v = 0; v < module->inc_size; ++v) {
4378 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004379 apply_dev(&module->inc[v].submodule->deviation[u], module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004380 }
4381
4382 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004383 apply_aug(&module->inc[v].submodule->augment[u], unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004384 }
4385 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004386
4387 if (unres->count) {
4388 resolve_unres_schema(module, unres);
4389 }
4390 /* nothing else left to do even if something is not resolved */
4391 unres_schema_free(module, &unres, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004392}
4393
Radek Krejcib2541a32016-12-12 16:45:57 +01004394void
4395lys_sub_module_remove_devs_augs(struct lys_module *module)
4396{
4397 uint8_t u, v;
Michal Vasko44ab1462017-05-18 13:18:36 +02004398 struct unres_schema *unres;
4399
4400 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01004401 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
Radek Krejcib2541a32016-12-12 16:45:57 +01004402
4403 /* remove applied deviations */
4404 for (u = 0; u < module->deviation_size; ++u) {
Michal Vasko7427b262018-05-14 15:23:55 +02004405 /* the deviation could be not applied because it failed to be applied */
4406 if (module->deviation[u].orig_node) {
4407 remove_dev(&module->deviation[u], module, unres);
4408 }
Radek Krejcib2541a32016-12-12 16:45:57 +01004409 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004410 /* remove applied augments */
Radek Krejcib2541a32016-12-12 16:45:57 +01004411 for (u = 0; u < module->augment_size; ++u) {
4412 remove_aug(&module->augment[u]);
4413 }
4414
4415 /* remove deviation and augments defined in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004416 for (v = 0; v < module->inc_size && module->inc[v].submodule; ++v) {
Radek Krejcib2541a32016-12-12 16:45:57 +01004417 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
Michal Vasko7427b262018-05-14 15:23:55 +02004418 if (module->inc[v].submodule->deviation[u].orig_node) {
4419 remove_dev(&module->inc[v].submodule->deviation[u], module, unres);
4420 }
Radek Krejcidbc15262016-06-16 14:58:29 +02004421 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004422
Radek Krejcib2541a32016-12-12 16:45:57 +01004423 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4424 remove_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004425 }
4426 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004427
4428 if (unres->count) {
4429 resolve_unres_schema(module, unres);
4430 }
4431 /* nothing else left to do even if something is not resolved */
4432 unres_schema_free(module, &unres, 1);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004433}
4434
Radek Krejci27fe55e2016-09-13 17:13:35 +02004435static int
4436lys_set_implemented_recursion(struct lys_module *module, struct unres_schema *unres)
4437{
4438 struct lys_node *root, *next, *node;
Radek Krejci9e6af732017-04-27 14:40:25 +02004439 uint16_t i, j;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004440
4441 for (i = 0; i < module->augment_size; i++) {
4442 /* apply augment */
Michal Vasko44ab1462017-05-18 13:18:36 +02004443 assert(module->augment[i].target);
4444 if (apply_aug(&module->augment[i], unres)) {
4445 return EXIT_FAILURE;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004446 }
4447 }
Radek Krejci9e6af732017-04-27 14:40:25 +02004448
4449 /* identities */
4450 for (i = 0; i < module->ident_size; i++) {
4451 for (j = 0; j < module->ident[i].base_size; j++) {
4452 resolve_identity_backlink_update(&module->ident[i], module->ident[i].base[j]);
4453 }
4454 }
4455
Radek Krejci27fe55e2016-09-13 17:13:35 +02004456 LY_TREE_FOR(module->data, root) {
4457 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
4458 LY_TREE_DFS_BEGIN(root, next, node) {
4459 if (node->nodetype == LYS_GROUPING) {
4460 goto nextsibling;
4461 }
4462 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
4463 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
4464 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
4465 UNRES_TYPE_LEAFREF, node) == -1) {
4466 return EXIT_FAILURE;
4467 }
4468 }
4469 }
4470
4471 /* modified LY_TREE_DFS_END */
4472 next = node->child;
4473 /* child exception for leafs, leaflists and anyxml without children */
4474 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4475 next = NULL;
4476 }
4477 if (!next) {
4478nextsibling:
4479 /* no children */
4480 if (node == root) {
4481 /* we are done, root has no children */
4482 break;
4483 }
4484 /* try siblings */
4485 next = node->next;
4486 }
4487 while (!next) {
4488 /* parent is already processed, go to its sibling */
4489 node = lys_parent(node);
4490 /* no siblings, go back through parents */
4491 if (lys_parent(node) == lys_parent(root)) {
4492 /* we are done, no next element to process */
4493 break;
4494 }
4495 next = node->next;
4496 }
4497 }
4498 }
4499
4500 return EXIT_SUCCESS;
4501}
4502
4503API int
4504lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02004505{
4506 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004507 struct unres_schema *unres;
Radek Krejci9e6af732017-04-27 14:40:25 +02004508 int i, j, k, disabled = 0;
Michal Vasko26055752016-05-03 11:36:31 +02004509
Radek Krejci27fe55e2016-09-13 17:13:35 +02004510 if (!module) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004511 LOGARG;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004512 return EXIT_FAILURE;
4513 }
4514
4515 module = lys_main_module(module);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004516
4517 if (module->disabled) {
4518 disabled = 1;
4519 lys_set_enabled(module);
4520 }
4521
Michal Vasko26055752016-05-03 11:36:31 +02004522 if (module->implemented) {
4523 return EXIT_SUCCESS;
4524 }
4525
4526 ctx = module->ctx;
4527
4528 for (i = 0; i < ctx->models.used; ++i) {
4529 if (module == ctx->models.list[i]) {
4530 continue;
4531 }
4532
4533 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004534 LOGERR(ctx, LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004535 if (disabled) {
4536 /* set it back disabled */
4537 lys_set_disabled(module);
4538 }
Michal Vasko26055752016-05-03 11:36:31 +02004539 return EXIT_FAILURE;
4540 }
4541 }
4542
Radek Krejci27fe55e2016-09-13 17:13:35 +02004543 unres = calloc(1, sizeof *unres);
4544 if (!unres) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004545 LOGMEM(ctx);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004546 if (disabled) {
4547 /* set it back disabled */
4548 lys_set_disabled(module);
4549 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004550 return EXIT_FAILURE;
4551 }
4552 /* recursively make the module implemented */
4553 ((struct lys_module *)module)->implemented = 1;
4554 if (lys_set_implemented_recursion((struct lys_module *)module, unres)) {
4555 goto error;
4556 }
4557 /* process augments in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004558 for (i = 0; i < module->inc_size && module->inc[i].submodule; ++i) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004559 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
4560 /* apply augment */
Michal Vasko44ab1462017-05-18 13:18:36 +02004561 assert(module->inc[i].submodule->augment[j].target);
4562 if (apply_aug(&module->inc[i].submodule->augment[j], unres)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004563 goto error;
4564 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004565 }
Radek Krejci9e6af732017-04-27 14:40:25 +02004566
4567 /* identities */
4568 for (j = 0; j < module->inc[i].submodule->ident_size; j++) {
4569 for (k = 0; k < module->inc[i].submodule->ident[j].base_size; k++) {
4570 resolve_identity_backlink_update(&module->inc[i].submodule->ident[j],
4571 module->inc[i].submodule->ident[j].base[k]);
4572 }
4573 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004574 }
Radek Krejcidf46e222016-11-08 11:57:37 +01004575 /* try again resolve augments in other modules possibly augmenting this one,
4576 * since we have just enabled it
4577 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02004578 /* resolve rest of unres items */
4579 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
4580 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004581 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004582 unres_schema_free(NULL, &unres, 0);
Michal Vasko26055752016-05-03 11:36:31 +02004583
Radek Krejci29eac3d2017-06-01 16:50:02 +02004584 /* reflect implemented flag in submodules */
4585 for (i = 0; i < module->inc_size; i++) {
4586 module->inc[i].submodule->implemented = 1;
4587 }
4588
Michal Vaskobe136f62017-09-21 12:08:39 +02004589 LOGVRB("Module \"%s%s%s\" now implemented.", module->name, (module->rev_size ? "@" : ""),
4590 (module->rev_size ? module->rev[0].date : ""));
Michal Vasko26055752016-05-03 11:36:31 +02004591 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004592
4593error:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004594 if (disabled) {
4595 /* set it back disabled */
4596 lys_set_disabled(module);
4597 }
4598
Radek Krejci27fe55e2016-09-13 17:13:35 +02004599 ((struct lys_module *)module)->implemented = 0;
Michal Vasko44ab1462017-05-18 13:18:36 +02004600 unres_schema_free((struct lys_module *)module, &unres, 1);
Radek Krejci27fe55e2016-09-13 17:13:35 +02004601 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004602}
4603
4604void
4605lys_submodule_module_data_free(struct lys_submodule *submodule)
4606{
4607 struct lys_node *next, *elem;
4608
4609 /* remove parsed data */
4610 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
4611 if (elem->module == (struct lys_module *)submodule) {
4612 lys_node_free(elem, NULL, 0);
4613 }
4614 }
4615}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02004616
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004617API char *
Michal Vasko395b0a02018-01-22 09:36:20 +01004618lys_path(const struct lys_node *node, int options)
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004619{
Michal Vasko53b7da02018-02-13 15:28:42 +01004620 char *buf = NULL;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004621
4622 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004623 LOGARG;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004624 return NULL;
4625 }
4626
Michal Vasko53b7da02018-02-13 15:28:42 +01004627 if (ly_vlog_build_path(LY_VLOG_LYS, node, &buf, !options)) {
Michal Vasko59631dd2017-10-02 11:56:11 +02004628 return NULL;
4629 }
4630
Michal Vasko53b7da02018-02-13 15:28:42 +01004631 return buf;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004632}
Radek Krejci9ad23f42016-10-31 15:46:52 +01004633
Michal Vasko50576712017-07-28 12:28:33 +02004634API char *
4635lys_data_path(const struct lys_node *node)
4636{
Michal Vasko53b7da02018-02-13 15:28:42 +01004637 char *result = NULL, buf[1024];
PavolVicanb28bbff2018-02-21 00:44:02 +01004638 const char *separator, *name;
Michal Vasko50576712017-07-28 12:28:33 +02004639 int i, used;
4640 struct ly_set *set;
4641 const struct lys_module *prev_mod;
4642
4643 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004644 LOGARG;
Michal Vasko50576712017-07-28 12:28:33 +02004645 return NULL;
4646 }
4647
Michal Vasko50576712017-07-28 12:28:33 +02004648 set = ly_set_new();
Michal Vasko53b7da02018-02-13 15:28:42 +01004649 LY_CHECK_ERR_GOTO(!set, LOGMEM(node->module->ctx), cleanup);
Michal Vasko50576712017-07-28 12:28:33 +02004650
4651 while (node) {
4652 ly_set_add(set, (void *)node, 0);
4653 do {
4654 node = lys_parent(node);
4655 } while (node && (node->nodetype & (LYS_USES | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
4656 }
4657
4658 prev_mod = NULL;
4659 used = 0;
4660 for (i = set->number - 1; i > -1; --i) {
4661 node = set->set.s[i];
PavolVicanb28bbff2018-02-21 00:44:02 +01004662 if (node->nodetype == LYS_EXT) {
4663 if (strcmp(((struct lys_ext_instance *)node)->def->name, "yang-data")) {
4664 continue;
4665 }
4666 name = ((struct lys_ext_instance *)node)->arg_value;
4667 separator = ":#";
4668 } else {
4669 name = node->name;
4670 separator = ":";
4671 }
Michal Vasko50576712017-07-28 12:28:33 +02004672 used += sprintf(buf + used, "/%s%s%s", (lys_node_module(node) == prev_mod ? "" : lys_node_module(node)->name),
PavolVicanb28bbff2018-02-21 00:44:02 +01004673 (lys_node_module(node) == prev_mod ? "" : separator), name);
Michal Vasko50576712017-07-28 12:28:33 +02004674 prev_mod = lys_node_module(node);
4675 }
4676
4677 result = strdup(buf);
Michal Vasko53b7da02018-02-13 15:28:42 +01004678 LY_CHECK_ERR_GOTO(!result, LOGMEM(node->module->ctx), cleanup);
Michal Vasko50576712017-07-28 12:28:33 +02004679
Michal Vasko53b7da02018-02-13 15:28:42 +01004680cleanup:
Michal Vasko50576712017-07-28 12:28:33 +02004681 ly_set_free(set);
Michal Vasko50576712017-07-28 12:28:33 +02004682 return result;
4683}
4684
Michal Vaskobb520442017-05-23 10:55:18 +02004685struct lys_node_augment *
4686lys_getnext_target_aug(struct lys_node_augment *last, const struct lys_module *mod, const struct lys_node *aug_target)
4687{
4688 int i, j, last_found;
4689
Michal Vaskob6906872018-03-12 11:35:09 +01004690 assert(mod && aug_target);
4691
Michal Vaskobb520442017-05-23 10:55:18 +02004692 if (!last) {
4693 last_found = 1;
4694 } else {
4695 last_found = 0;
4696 }
4697
4698 /* search module augments */
4699 for (i = 0; i < mod->augment_size; ++i) {
4700 if (!mod->augment[i].target) {
4701 /* still unresolved, skip */
4702 continue;
4703 }
4704
4705 if (mod->augment[i].target == aug_target) {
4706 if (last_found) {
4707 /* next match after last */
4708 return &mod->augment[i];
4709 }
4710
4711 if (&mod->augment[i] == last) {
4712 last_found = 1;
4713 }
4714 }
4715 }
4716
4717 /* search submodule augments */
4718 for (i = 0; i < mod->inc_size; ++i) {
4719 for (j = 0; j < mod->inc[i].submodule->augment_size; ++j) {
4720 if (!mod->inc[i].submodule->augment[j].target) {
4721 continue;
4722 }
4723
4724 if (mod->inc[i].submodule->augment[j].target == aug_target) {
4725 if (last_found) {
4726 /* next match after last */
4727 return &mod->inc[i].submodule->augment[j];
4728 }
4729
4730 if (&mod->inc[i].submodule->augment[j] == last) {
4731 last_found = 1;
4732 }
4733 }
4734 }
4735 }
4736
4737 return NULL;
4738}
4739
Michal Vasko50576712017-07-28 12:28:33 +02004740API struct ly_set *
4741lys_find_path(const struct lys_module *cur_module, const struct lys_node *cur_node, const char *path)
4742{
4743 struct ly_set *ret;
4744 int rc;
4745
4746 if ((!cur_module && !cur_node) || !path) {
4747 return NULL;
4748 }
4749
4750 rc = resolve_schema_nodeid(path, cur_node, cur_module, &ret, 1, 1);
4751 if (rc == -1) {
4752 return NULL;
4753 }
4754
4755 return ret;
4756}
4757
Radek Krejci8d6b7422017-02-03 14:42:13 +01004758static void
4759lys_extcomplex_free_str(struct ly_ctx *ctx, struct lys_ext_instance_complex *ext, LY_STMT stmt)
4760{
4761 struct lyext_substmt *info;
Radek Krejcib71243e2017-02-08 16:20:08 +01004762 const char **str, ***a;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004763 int c;
4764
4765 str = lys_ext_complex_get_substmt(stmt, ext, &info);
4766 if (!str || !(*str)) {
4767 return;
4768 }
4769 if (info->cardinality >= LY_STMT_CARD_SOME) {
4770 /* we have array */
Radek Krejcib71243e2017-02-08 16:20:08 +01004771 a = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01004772 for (str = (*(const char ***)str), c = 0; str[c]; c++) {
4773 lydict_remove(ctx, str[c]);
Radek Krejci8d6b7422017-02-03 14:42:13 +01004774 }
Radek Krejci56c80412017-02-09 10:44:16 +01004775 free(a[0]);
4776 if (stmt == LY_STMT_BELONGSTO) {
4777 for (str = a[1], c = 0; str[c]; c++) {
4778 lydict_remove(ctx, str[c]);
4779 }
4780 free(a[1]);
PavolVican99c70722017-02-18 17:25:52 +01004781 } else if (stmt == LY_STMT_ARGUMENT) {
4782 free(a[1]);
Radek Krejci56c80412017-02-09 10:44:16 +01004783 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01004784 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01004785 lydict_remove(ctx, str[0]);
4786 if (stmt == LY_STMT_BELONGSTO) {
4787 lydict_remove(ctx, str[1]);
4788 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01004789 }
4790}
4791void
Radek Krejci5138e9f2017-04-12 13:10:46 +02004792lys_extension_instances_free(struct ly_ctx *ctx, struct lys_ext_instance **e, unsigned int size,
4793 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci8d6b7422017-02-03 14:42:13 +01004794{
Radek Krejcif8d05c22017-02-10 15:33:35 +01004795 unsigned int i, j, k;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004796 struct lyext_substmt *substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004797 void **pp, **start;
Radek Krejcif95b6292017-02-13 15:57:37 +01004798 struct lys_node *siter, *snext;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004799
4800#define EXTCOMPLEX_FREE_STRUCT(STMT, TYPE, FUNC, FREE, ARGS...) \
Radek Krejcib84686f2017-02-09 16:04:55 +01004801 pp = lys_ext_complex_get_substmt(STMT, (struct lys_ext_instance_complex *)e[i], NULL); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01004802 if (!pp || !(*pp)) { break; } \
Radek Krejcib84686f2017-02-09 16:04:55 +01004803 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */ \
Radek Krejci8d6b7422017-02-03 14:42:13 +01004804 for (start = pp = *pp; *pp; pp++) { \
Radek Krejci5138e9f2017-04-12 13:10:46 +02004805 FUNC(ctx, (TYPE *)(*pp), ##ARGS, private_destructor); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01004806 if (FREE) { free(*pp); } \
4807 } \
4808 free(start); \
4809 } else { /* single item */ \
Radek Krejci5138e9f2017-04-12 13:10:46 +02004810 FUNC(ctx, (TYPE *)(*pp), ##ARGS, private_destructor); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01004811 if (FREE) { free(*pp); } \
4812 }
4813
PavolVican9d61d402018-02-05 15:52:48 +01004814 if (!size || !e) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01004815 return;
4816 }
4817
4818 for (i = 0; i < size; i++) {
4819 if (!e[i]) {
4820 continue;
4821 }
4822
4823 if (e[i]->flags & (LYEXT_OPT_INHERIT)) {
4824 /* no free, this is just a shadow copy of the original extension instance */
4825 } else {
4826 if (e[i]->flags & (LYEXT_OPT_YANG)) {
4827 free(e[i]->def); /* remove name of instance extension */
PavolVican19dc6152017-02-06 12:04:15 +01004828 e[i]->def = NULL;
PavolVicandb0e8172017-02-20 00:46:09 +01004829 yang_free_ext_data((struct yang_ext_substmt *)e[i]->parent); /* remove backup part of yang file */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004830 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02004831 /* remove private object */
4832 if (e[i]->priv && private_destructor) {
4833 private_destructor((struct lys_node*)e[i], e[i]->priv);
4834 }
4835 lys_extension_instances_free(ctx, e[i]->ext, e[i]->ext_size, private_destructor);
Radek Krejci8d6b7422017-02-03 14:42:13 +01004836 lydict_remove(ctx, e[i]->arg_value);
4837 }
4838
fanchanghu8d86f6b2017-06-10 12:49:54 +08004839 if (e[i]->def && e[i]->def->plugin && e[i]->def->plugin->type == LYEXT_COMPLEX
4840 && ((e[i]->flags & LYEXT_OPT_CONTENT) == 0)) {
Radek Krejcifebdad72017-02-06 11:35:51 +01004841 substmt = ((struct lys_ext_instance_complex *)e[i])->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004842 for (j = 0; substmt[j].stmt; j++) {
4843 switch(substmt[j].stmt) {
4844 case LY_STMT_DESCRIPTION:
4845 case LY_STMT_REFERENCE:
4846 case LY_STMT_UNITS:
Radek Krejcib71243e2017-02-08 16:20:08 +01004847 case LY_STMT_ARGUMENT:
4848 case LY_STMT_DEFAULT:
4849 case LY_STMT_ERRTAG:
4850 case LY_STMT_ERRMSG:
4851 case LY_STMT_PREFIX:
4852 case LY_STMT_NAMESPACE:
4853 case LY_STMT_PRESENCE:
4854 case LY_STMT_REVISIONDATE:
4855 case LY_STMT_KEY:
4856 case LY_STMT_BASE:
4857 case LY_STMT_BELONGSTO:
4858 case LY_STMT_CONTACT:
4859 case LY_STMT_ORGANIZATION:
4860 case LY_STMT_PATH:
Radek Krejci8d6b7422017-02-03 14:42:13 +01004861 lys_extcomplex_free_str(ctx, (struct lys_ext_instance_complex *)e[i], substmt[j].stmt);
4862 break;
4863 case LY_STMT_TYPE:
4864 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPE, struct lys_type, lys_type_free, 1);
4865 break;
Radek Krejci63fc0962017-02-15 13:20:18 +01004866 case LY_STMT_TYPEDEF:
4867 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPEDEF, struct lys_tpdf, lys_tpdf_free, 1);
4868 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004869 case LY_STMT_IFFEATURE:
Frank Rimplerc4db1c72017-09-12 12:56:39 +00004870 EXTCOMPLEX_FREE_STRUCT(LY_STMT_IFFEATURE, struct lys_iffeature, lys_iffeature_free, 0, 1, 0);
Radek Krejci8d6b7422017-02-03 14:42:13 +01004871 break;
Radek Krejci5496fae2017-02-10 13:26:48 +01004872 case LY_STMT_MAX:
4873 case LY_STMT_MIN:
4874 case LY_STMT_POSITION:
PavolVican2ed9f4e2017-02-16 00:08:45 +01004875 case LY_STMT_VALUE:
Radek Krejcif8d05c22017-02-10 15:33:35 +01004876 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
Radek Krejci716cd7a2017-02-15 12:23:41 +01004877 if (substmt[j].cardinality >= LY_STMT_CARD_SOME && *pp) {
Radek Krejcif8d05c22017-02-10 15:33:35 +01004878 for(k = 0; ((uint32_t**)(*pp))[k]; k++) {
4879 free(((uint32_t**)(*pp))[k]);
4880 }
4881 }
4882 free(*pp);
4883 break;
4884 case LY_STMT_DIGITS:
Radek Krejcib84686f2017-02-09 16:04:55 +01004885 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
4886 /* free the array */
4887 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
4888 free(*pp);
4889 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01004890 break;
Radek Krejci37f9ba32017-02-10 16:50:35 +01004891 case LY_STMT_MODULE:
4892 /* modules are part of the context, so they will be freed there */
4893 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
4894 /* free the array */
4895 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
4896 free(*pp);
4897 }
4898 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01004899 case LY_STMT_ACTION:
Radek Krejcib31762b2017-02-15 10:48:42 +01004900 case LY_STMT_ANYDATA:
4901 case LY_STMT_ANYXML:
4902 case LY_STMT_CASE:
4903 case LY_STMT_CHOICE:
4904 case LY_STMT_CONTAINER:
4905 case LY_STMT_GROUPING:
4906 case LY_STMT_INPUT:
4907 case LY_STMT_LEAF:
4908 case LY_STMT_LEAFLIST:
4909 case LY_STMT_LIST:
4910 case LY_STMT_NOTIFICATION:
4911 case LY_STMT_OUTPUT:
4912 case LY_STMT_RPC:
4913 case LY_STMT_USES:
Radek Krejcif95b6292017-02-13 15:57:37 +01004914 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
4915 LY_TREE_FOR_SAFE((struct lys_node *)(*pp), snext, siter) {
4916 lys_node_free(siter, NULL, 0);
4917 }
Radek Krejcib31762b2017-02-15 10:48:42 +01004918 *pp = NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +01004919 break;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01004920 case LY_STMT_UNIQUE:
4921 pp = lys_ext_complex_get_substmt(LY_STMT_UNIQUE, (struct lys_ext_instance_complex *)e[i], NULL);
4922 if (!pp || !(*pp)) {
4923 break;
4924 }
4925 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
4926 for (start = pp = *pp; *pp; pp++) {
4927 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
4928 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
4929 }
4930 free((*(struct lys_unique**)pp)->expr);
4931 free(*pp);
4932 }
4933 free(start);
4934 } else { /* single item */
4935 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
4936 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
4937 }
4938 free((*(struct lys_unique**)pp)->expr);
4939 free(*pp);
4940 }
4941 break;
Radek Krejciaa9c5202017-02-15 16:10:14 +01004942 case LY_STMT_LENGTH:
4943 case LY_STMT_MUST:
4944 case LY_STMT_PATTERN:
4945 case LY_STMT_RANGE:
4946 EXTCOMPLEX_FREE_STRUCT(substmt[j].stmt, struct lys_restr, lys_restr_free, 1);
4947 break;
Radek Krejcic5cc5302017-02-16 10:07:46 +01004948 case LY_STMT_WHEN:
4949 EXTCOMPLEX_FREE_STRUCT(LY_STMT_WHEN, struct lys_when, lys_when_free, 0);
4950 break;
Radek Krejci7417a082017-02-16 11:07:59 +01004951 case LY_STMT_REVISION:
4952 pp = lys_ext_complex_get_substmt(LY_STMT_REVISION, (struct lys_ext_instance_complex *)e[i], NULL);
4953 if (!pp || !(*pp)) {
4954 break;
4955 }
4956 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
4957 for (start = pp = *pp; *pp; pp++) {
4958 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
4959 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
4960 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
Radek Krejci5138e9f2017-04-12 13:10:46 +02004961 (*(struct lys_revision**)pp)->ext_size, private_destructor);
Radek Krejci7417a082017-02-16 11:07:59 +01004962 free(*pp);
4963 }
4964 free(start);
4965 } else { /* single item */
4966 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
4967 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
4968 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
Radek Krejci5138e9f2017-04-12 13:10:46 +02004969 (*(struct lys_revision**)pp)->ext_size, private_destructor);
Radek Krejci7417a082017-02-16 11:07:59 +01004970 free(*pp);
4971 }
4972 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01004973 default:
Radek Krejcib84686f2017-02-09 16:04:55 +01004974 /* nothing to free */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004975 break;
4976 }
4977 }
4978 }
4979
4980 free(e[i]);
4981 }
4982 free(e);
4983
4984#undef EXTCOMPLEX_FREE_STRUCT
4985}