blob: 2a082166a7352440814f9ccd9e1a3764836e1f52 [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 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
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
Radek Krejci812b10a2015-05-28 16:48:25 +020017#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020018#include <ctype.h>
Radek Krejcib051f722016-02-25 15:12:21 +010019#include <limits.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <sys/mman.h>
Michal Vasko662610a2015-12-07 11:25:45 +010022#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020023#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010024#include <fcntl.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020025#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010026#include <unistd.h>
27#include <errno.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020028
29#include "common.h"
30#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020031#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020032#include "resolve.h"
Michal Vasko88c29542015-11-27 14:57:53 +010033#include "xml.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020034#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020035#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020036#include "validation.h"
Pavol Vicanf7cc2852016-03-22 23:27:35 +010037#include "parser_yang.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020038
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020039static int
40lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
41 struct unres_schema *unres);
42
Michal Vasko1e62a092015-12-01 12:27:20 +010043API const struct lys_feature *
44lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020045{
46 int i;
47
48check:
49 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
50 /* input/output does not have if-feature, so skip them */
51
52 /* check local if-features */
53 for (i = 0; i < node->features_size; i++) {
54 if (!(node->features[i]->flags & LYS_FENABLED)) {
55 return node->features[i];
56 }
57 }
58 }
59
60 if (!recursive) {
61 return NULL;
62 }
63
64 /* go through parents */
65 if (node->nodetype == LYS_AUGMENT) {
66 /* go to parent actually means go to the target node */
67 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020068 } else if (node->parent) {
69 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020070 } else {
71 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020072 }
73
Radek Krejci074bf852015-08-19 14:22:16 +020074 if (recursive == 2) {
75 /* continue only if the node cannot have a data instance */
76 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
77 return NULL;
78 }
79 }
80 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020081}
82
Michal Vasko1dca6882015-10-22 14:29:42 +020083int
Michal Vasko36cbaa42015-12-14 13:15:48 +010084lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
85 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020086{
Radek Krejcic071c542016-01-27 14:57:51 +010087 const struct lys_node *node, *parent = NULL;
88 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010089 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020090
Michal Vasko36cbaa42015-12-14 13:15:48 +010091 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020092 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020093
Michal Vasko36cbaa42015-12-14 13:15:48 +010094 /* fill the lengths in case the caller is so indifferent */
95 if (!mod_name_len) {
96 mod_name_len = strlen(mod_name);
97 }
Michal Vasko1dca6882015-10-22 14:29:42 +020098 if (!nam_len) {
99 nam_len = strlen(name);
100 }
101
Michal Vasko36cbaa42015-12-14 13:15:48 +0100102 /* set mod correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100103 parent = lys_parent(siblings);
104 if (!parent) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100105 mod = lys_node_module(siblings);
Michal Vasko1dca6882015-10-22 14:29:42 +0200106 }
107
Radek Krejcic071c542016-01-27 14:57:51 +0100108 /* try to find the node */
109 node = NULL;
110 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
111 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100112 /* module name comparison */
113 node_mod_name = lys_node_module(node)->name;
114 if ((node_mod_name != mod_name) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100115 continue;
116 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200117
Radek Krejcic071c542016-01-27 14:57:51 +0100118 /* direct name check */
119 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
120 if (ret) {
121 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200122 }
Radek Krejcic071c542016-01-27 14:57:51 +0100123 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200124 }
125 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200126 }
127
128 return EXIT_FAILURE;
129}
130
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200131int
Michal Vasko1e62a092015-12-01 12:27:20 +0100132lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
133 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200134{
Michal Vasko1e62a092015-12-01 12:27:20 +0100135 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200136
137 assert(siblings && name);
138 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
139
140 /* find the beginning */
141 while (siblings->prev->next) {
142 siblings = siblings->prev;
143 }
144
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200145 if (!mod) {
146 mod = siblings->module;
147 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200148
Michal Vasko4f0dad02016-02-15 14:08:23 +0100149 /* try to find the node */
150 node = NULL;
151 while ((node = lys_getnext(node, siblings->parent, mod, 0))) {
152 if (!type || (node->nodetype & type)) {
153 /* module check */
154 if (lys_node_module(node) != lys_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100155 continue;
156 }
157
Michal Vasko4f0dad02016-02-15 14:08:23 +0100158 /* direct name check */
Radek Krejci749190d2016-02-18 16:26:25 +0100159 if (ly_strequal(node->name, name, 0)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100160 if (ret) {
161 *ret = node;
162 }
163 return EXIT_SUCCESS;
164 }
Radek Krejcic071c542016-01-27 14:57:51 +0100165 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200166 }
167
168 return EXIT_FAILURE;
169}
170
Michal Vasko1e62a092015-12-01 12:27:20 +0100171API const struct lys_node *
172lys_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 +0200173{
Michal Vasko1e62a092015-12-01 12:27:20 +0100174 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200175
Radek Krejci8bc87f62015-09-02 16:19:05 +0200176 if (!last) {
177 /* first call */
178
179 /* get know where to start */
180 if (parent) {
181 /* schema subtree */
182 next = last = parent->child;
183 } else {
184 /* top level data */
185 assert(module);
186 next = last = module->data;
187 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200188 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200189 /* continue after the last returned value */
190 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200191 }
192
193repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200194 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200195 if (options & LYS_GETNEXT_WITHGROUPING) {
196 return next;
197 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200198 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200199 }
200
Radek Krejcic4ccbd92016-01-07 13:13:33 +0100201 if (!next) {
Radek Krejci63318e82016-02-12 09:43:12 +0100202 if (!last || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200203 /* no next element */
204 return NULL;
205 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200206 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200207 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200208 goto repeat;
209 }
210
211 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200212 case LYS_INPUT:
213 case LYS_OUTPUT:
214 if (options & LYS_GETNEXT_WITHINOUT) {
215 return next;
216 } else {
217 next = next->child;
218 goto repeat;
219 }
220 break;
221
Michal Vaskoa5835e92015-10-20 15:07:39 +0200222 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200223 if (options & LYS_GETNEXT_WITHCASE) {
224 return next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200225 } else {
226 next = next->child;
227 goto repeat;
Michal Vasko1dca6882015-10-22 14:29:42 +0200228 }
Michal Vaskob6eedf02015-10-22 16:07:03 +0200229 break;
230
Michal Vasko1dca6882015-10-22 14:29:42 +0200231 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200232 /* go into */
233 next = next->child;
234 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200235
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200236 case LYS_RPC:
237 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200238 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200239 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200240 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200241 case LYS_LIST:
242 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200243 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200244
245 case LYS_CHOICE:
246 if (options & LYS_GETNEXT_WITHCHOICE) {
247 return next;
248 } else {
249 /* go into */
250 next = next->child;
251 goto repeat;
252 }
253 break;
254
Radek Krejci7f40ce32015-08-12 20:38:46 +0200255 default:
256 /* we should not be here */
257 return NULL;
258 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200259
260
261}
262
Michal Vasko1e62a092015-12-01 12:27:20 +0100263static const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100264check_mand_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module)
Radek Krejci8bc87f62015-09-02 16:19:05 +0200265{
Michal Vasko1e62a092015-12-01 12:27:20 +0100266 const struct lys_node *next;
267
Radek Krejci2342cf62016-01-29 16:48:23 +0100268 next = lys_getnext(last, parent, module, LYS_GETNEXT_WITHCHOICE);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200269
Radek Krejci4b6c2112015-10-06 12:48:34 +0200270repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200271 if (next && next->nodetype == LYS_CONTAINER) {
272 if (((struct lys_node_container *)next)->presence) {
273 /* mandatory elements under the non-existing presence
274 * container are not mandatory - 7.6.5, rule 1 */
275 next = next->next;
276 } else {
277 /* go into */
278 next = next->child;
279 }
280 goto repeat;
281 }
282
283 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200284}
285
Michal Vasko84f821a2016-04-11 11:03:42 +0200286static int
Michal Vasko1e62a092015-12-01 12:27:20 +0100287check_mand_check(const struct lys_node *node, const struct lys_node *stop, const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200288{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200289 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200290 struct lyd_node *diter = NULL;
Radek Krejcidc154432016-01-21 11:10:59 +0100291 struct ly_set *set = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200292 unsigned int i;
Michal Vasko84f821a2016-04-11 11:03:42 +0200293 uint32_t minmax, min, max;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200294
295 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100296 if (!data) {
297 /* we have no data but a mandatory node */
Michal Vasko84f821a2016-04-11 11:03:42 +0200298 LOGVAL(LYE_MISSELEM, LY_VLOG_LYS, node, node->name,
299 (lys_parent(node) ? lys_parent(node)->name : lys_node_module(node)->name));
300 return EXIT_FAILURE;
Radek Krejci2342cf62016-01-29 16:48:23 +0100301 }
302 switch (node->nodetype) {
303 case LYS_LEAF:
304 case LYS_ANYXML:
305 case LYS_CHOICE:
Michal Vasko84f821a2016-04-11 11:03:42 +0200306 if (lys_parent(node) && lys_parent(node)->nodetype == LYS_CASE) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100307 /* 7.6.5, rule 2 */
308 /* 7.9.4, rule 1 */
Michal Vasko84f821a2016-04-11 11:03:42 +0200309 if (lys_parent(lys_parent(lys_parent(node))) == data->schema) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100310 /* the only case the node's siblings can exist is that the
311 * data node passed originally to ly_check_mandatory()
312 * had this choice as a child
313 */
314 /* try to find the node's siblings in data */
315 LY_TREE_FOR(data->child, diter) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200316 LY_TREE_FOR(lys_parent(node)->child, siter) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100317 if (siter == diter->schema) {
318 /* some sibling exists, rule applies */
319 break;
320 }
321 }
322 if (siter) {
323 break;
324 }
325 }
326 }
327 if (!siter) {
328 /* no sibling exists */
Michal Vasko84f821a2016-04-11 11:03:42 +0200329 return EXIT_SUCCESS;
Radek Krejci2342cf62016-01-29 16:48:23 +0100330 }
331 } else {
Michal Vasko84f821a2016-04-11 11:03:42 +0200332 for (parent = lys_parent(node); parent && parent != stop; parent = lys_parent(parent)) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100333 if (parent->nodetype != LYS_CONTAINER) {
334 /* 7.6.5, rule 1, checking presence is not needed
335 * since it is done in check_mand_getnext()
336 */
337 ly_set_free(set);
Michal Vasko84f821a2016-04-11 11:03:42 +0200338 return EXIT_SUCCESS;
Radek Krejci2342cf62016-01-29 16:48:23 +0100339 }
340 /* add the parent to the list for searching in data tree */
341 if (!set) {
342 set = ly_set_new();
343 }
344 /* ignore return - memory error is logged and we will
345 * check at least the rest of nodes we have */
346 (void)ly_set_add(set, parent);
347 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200348
Michal Vasko84f821a2016-04-11 11:03:42 +0200349 /* search for instance */
350 if (set) {
351 for (i = 0; i < set->number; i++) {
352 LY_TREE_FOR(data->child, diter) {
353 if (diter->schema == set->set.s[i]) {
354 break;
355 }
Radek Krejci2342cf62016-01-29 16:48:23 +0100356 }
Michal Vasko84f821a2016-04-11 11:03:42 +0200357 if (!diter) {
358 /* instance not found */
359 LOGVAL(LYE_MISSELEM, LY_VLOG_LYS, node, set->set.s[i]->name,
360 (lys_parent(set->set.s[i]) ? lys_parent(set->set.s[i])->name
361 : lys_node_module(set->set.s[i])->name));
362 ly_set_free(set);
363 return EXIT_FAILURE;
364 }
365 data = diter;
Radek Krejci2342cf62016-01-29 16:48:23 +0100366 }
Michal Vasko84f821a2016-04-11 11:03:42 +0200367 ly_set_free(set);
Radek Krejci2342cf62016-01-29 16:48:23 +0100368 }
Radek Krejci2342cf62016-01-29 16:48:23 +0100369 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200370
Radek Krejci2342cf62016-01-29 16:48:23 +0100371 LY_TREE_FOR(data->child, diter) {
372 if (diter->schema == node) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200373 return EXIT_SUCCESS;
Radek Krejci2342cf62016-01-29 16:48:23 +0100374 }
375 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200376
Radek Krejci2342cf62016-01-29 16:48:23 +0100377 /* instance not found */
378 /* 7.6.5, rule 3 (or 2) */
379 /* 7.9.4, rule 2 */
Michal Vasko84f821a2016-04-11 11:03:42 +0200380 if (node->nodetype == LYS_CHOICE) {
381 LOGVAL(LYE_NOMANDCHOICE, LY_VLOG_LYS, node, node->name);
382 } else {
383 LOGVAL(LYE_MISSELEM, LY_VLOG_LYS, node, node->name,
384 (lys_parent(node) ? lys_parent(node)->name : lys_node_module(node)->name));
385 }
386 return EXIT_FAILURE;;
Radek Krejci2342cf62016-01-29 16:48:23 +0100387 default:
388 /* error */
389 break;
390 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200391 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
392 /* search for number of instances */
393 minmax = 0;
Radek Krejci2342cf62016-01-29 16:48:23 +0100394 if (data) {
395 LY_TREE_FOR(data->child, diter) {
396 if (diter->schema == node) {
397 minmax++;
398 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200399 }
400 }
401
402 /* check the specified constraints */
403 if (node->nodetype == LYS_LIST) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200404 min = ((struct lys_node_list *)node)->min;
405 max = ((struct lys_node_list *)node)->max;
406 } else {
407 min = ((struct lys_node_leaflist *)node)->min;
408 max = ((struct lys_node_leaflist *)node)->max;
409 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200410
Michal Vasko84f821a2016-04-11 11:03:42 +0200411 if (min && (minmax < min)) {
412 LOGVAL(LYE_NOMIN, LY_VLOG_LYS, node, node->name);
413 return EXIT_FAILURE;
414 }
415 if (max && (minmax > max)) {
416 LOGVAL(LYE_NOMAX, LY_VLOG_LYS, node, node->name);
417 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200418 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200419 }
420
Michal Vasko84f821a2016-04-11 11:03:42 +0200421 return EXIT_SUCCESS;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200422}
423
Michal Vasko84f821a2016-04-11 11:03:42 +0200424int
Radek Krejci763122e2016-04-05 16:35:33 +0200425ly_check_mandatory(const struct lyd_node *data, const struct lys_node *schema, int status)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200426{
Michal Vasko84f821a2016-04-11 11:03:42 +0200427 const struct lys_node *siter, *saux, *saux2, *parent = NULL, *parent2;
Michal Vasko1e62a092015-12-01 12:27:20 +0100428 const struct lyd_node *diter;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200429 int found;
430
Radek Krejci2342cf62016-01-29 16:48:23 +0100431 assert(data || schema);
432
433 if (!data) { /* !data && schema */
434 siter = schema;
435 } else { /* data && !schema */
Radek Krejcie2f12212016-02-12 13:50:22 +0100436 schema = data->schema;
437 siter = data->schema->child;
Radek Krejci2342cf62016-01-29 16:48:23 +0100438 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200439
440repeat:
441 while (siter) {
Radek Krejci763122e2016-04-05 16:35:33 +0200442 if (lys_is_disabled(siter, 2) || (!status && (siter->flags & LYS_CONFIG_R))) {
Radek Krejci074bf852015-08-19 14:22:16 +0200443 siter = siter->next;
444 continue;
445 }
446
Radek Krejci7f40ce32015-08-12 20:38:46 +0200447 switch (siter->nodetype) {
448 case LYS_CONTAINER:
449 case LYS_LEAF:
450 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200451 case LYS_LIST:
452 case LYS_LEAFLIST:
453 /* check if there is some mandatory node; first test the siter itself ... */
Michal Vasko84f821a2016-04-11 11:03:42 +0200454 if (check_mand_check(siter, lys_parent(siter), data)) {
455 return EXIT_FAILURE;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200456 }
457 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200458 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
459 saux = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100460 while ((saux = check_mand_getnext(saux, siter, NULL))) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200461 if (check_mand_check(saux, siter, data)) {
462 return EXIT_FAILURE;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200463 }
464 }
465 }
466 siter = siter->next;
467 break;
468 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200469 /* search for instance */
470 saux = siter;
471 siter = siter->child;
472 found = 0;
473 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200474repeat_choice:
Radek Krejci2342cf62016-01-29 16:48:23 +0100475 while (siter && data) {
Radek Krejci763122e2016-04-05 16:35:33 +0200476 if (lys_is_disabled(siter, 2) || (!status && (siter->flags & LYS_CONFIG_R))) {
Radek Krejci074bf852015-08-19 14:22:16 +0200477 siter = siter->next;
478 continue;
479 }
480
Radek Krejci14a11a62015-08-17 17:27:38 +0200481 switch (siter->nodetype) {
482 case LYS_CONTAINER:
483 case LYS_LEAF:
484 case LYS_LEAFLIST:
485 case LYS_LIST:
486 case LYS_ANYXML:
487 LY_TREE_FOR(data->child, diter) {
488 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200489 break;
490 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200491 }
492 if (diter) {
493 /* got instance */
494 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200495 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200496 saux2 = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100497 while ((saux2 = check_mand_getnext(saux2, parent2, NULL))) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200498 if (check_mand_check(saux2, parent2, data)) {
499 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200500 }
501 }
502 }
503 siter = parent2 = NULL;
504 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200505 break;
506 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200507 siter = siter->next;
508 break;
509 case LYS_CASE:
510 case LYS_CHOICE:
511 case LYS_USES:
512 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200513 if (!parent2) {
514 parent2 = siter;
515 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200516 siter = siter->child;
517 break;
518 case LYS_AUGMENT:
519 case LYS_GROUPING:
520 /* skip */
521 siter = siter->next;
522 break;
523 default:
524 /* error */
525 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200526 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200527 }
528
Radek Krejci14a11a62015-08-17 17:27:38 +0200529 if (parent2) {
530 siter = parent2->next;
Michal Vasko84f821a2016-04-11 11:03:42 +0200531 if (lys_parent(parent2) == saux) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200532 parent2 = NULL;
533 } else {
Michal Vasko84f821a2016-04-11 11:03:42 +0200534 parent2 = lys_parent(parent2);
Radek Krejci14a11a62015-08-17 17:27:38 +0200535 }
536 goto repeat_choice;
537 }
538
Radek Krejci074bf852015-08-19 14:22:16 +0200539 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200540 LOGVAL(LYE_MISSELEM, LY_VLOG_LYS, saux, saux->name,
541 (lys_parent(saux) ? lys_parent(saux)->name : lys_node_module(saux)->name));
542 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200543 }
544
545 /* go to next */
546 siter = saux->next;
547
Radek Krejci7f40ce32015-08-12 20:38:46 +0200548 break;
549 case LYS_USES:
550 case LYS_CASE:
551 /* go into */
552 parent = siter;
553 siter = siter->child;
554 break;
555 default:
556 /* can ignore, go to next */
557 siter = siter->next;
558 break;
559 }
560 }
561
562 if (parent) {
563 siter = parent->next;
Radek Krejci2342cf62016-01-29 16:48:23 +0100564 if (parent->parent == schema) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200565 parent = NULL;
566 } else {
Michal Vasko84f821a2016-04-11 11:03:42 +0200567 parent = lys_parent(parent);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200568 }
569 goto repeat;
570 }
571
Michal Vasko84f821a2016-04-11 11:03:42 +0200572 return EXIT_SUCCESS;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200573}
574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200575void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200576lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200577{
Radek Krejci76512572015-08-04 09:47:08 +0200578 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100579 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200581 if (!node) {
582 return;
583 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200585 /* unlink from data model if necessary */
586 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100587 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100588 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100589 if (main_module->data == node) {
590 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200591 }
592 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200594 /* store pointers to important nodes */
595 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200596 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200597 /* handle augments - first, unlink it from the augment parent ... */
598 if (parent->child == node) {
599 parent->child = node->next;
600 }
601 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200602 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200603 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200604
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200605 /* unlink from parent */
606 if (parent) {
607 if (parent->child == node) {
608 parent->child = node->next;
609 }
610 node->parent = NULL;
611 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200612
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200613 /* unlink from siblings */
614 if (node->prev == node) {
615 /* there are no more siblings */
616 return;
617 }
618 if (node->next) {
619 node->next->prev = node->prev;
620 } else {
621 /* unlinking the last element */
622 if (parent) {
623 first = parent->child;
624 } else {
625 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200626 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200627 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200628 }
629 }
630 first->prev = node->prev;
631 }
632 if (node->prev->next) {
633 node->prev->next = node->next;
634 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200635
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200636 /* clean up the unlinked element */
637 node->next = NULL;
638 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200639}
640
Michal Vasko563ef092015-09-04 13:17:23 +0200641struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100642lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200643{
644 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200645
646 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200647 /* top-level augment, look into module (uses augment is handled correctly below) */
648 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
649 par_iter = par_iter->parent->module->data;
650 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200651 break;
652 }
653 }
654
Michal Vasko6f929da2015-10-02 16:23:25 +0200655 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200656 continue;
657 }
658
659 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
660 if (!stop) {
661 stop = par_iter;
662 } else if (iter == stop) {
663 break;
664 }
665 if (iter->nodetype != LYS_GROUPING) {
666 continue;
667 }
668
Radek Krejcif8426a72015-10-31 23:14:03 +0100669 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200670 return (struct lys_node_grp *)iter;
671 }
672 }
673 }
674
Michal Vasko563ef092015-09-04 13:17:23 +0200675 return NULL;
676}
677
Radek Krejci10c760e2015-08-14 14:45:43 +0200678/*
679 * get next grouping in the root's subtree, in the
680 * first call, tha last is NULL
681 */
682static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200683lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200684{
Radek Krejci10c760e2015-08-14 14:45:43 +0200685 struct lys_node *last = (struct lys_node *)lastgrp;
686 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200687
Radek Krejci10c760e2015-08-14 14:45:43 +0200688 assert(root);
689
690 if (!last) {
691 last = root;
692 }
693
694 while (1) {
695 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
696 next = last->child;
697 } else {
698 next = NULL;
699 }
700 if (!next) {
701 if (last == root) {
702 /* we are done */
703 return NULL;
704 }
705
706 /* no children, go to siblings */
707 next = last->next;
708 }
709 while (!next) {
710 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100711 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200712 /* we are done */
713 return NULL;
714 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200715 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100716 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200717 }
718
719 if (next->nodetype == LYS_GROUPING) {
720 return (struct lys_node_grp *)next;
721 }
722
723 last = next;
724 }
725}
726
Michal Vasko0d343d12015-08-24 14:57:36 +0200727/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200728int
Radek Krejci07911992015-08-14 15:13:31 +0200729lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
730{
Michal Vasko563ef092015-09-04 13:17:23 +0200731 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200732 struct lys_node_grp *grp;
733 int down;
734
735 assert(node);
736
737 if (!parent) {
738 assert(module);
739 } else {
740 module = parent->module;
741 }
742
743 switch (node->nodetype) {
744 case LYS_GROUPING:
745 /* 6.2.1, rule 6 */
746 if (parent) {
747 if (parent->child) {
748 down = 1;
749 start = parent->child;
750 } else {
751 down = 0;
752 start = parent;
753 }
754 } else {
755 down = 1;
756 start = module->data;
757 }
758 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100759 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100760 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200761 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200762 }
763 /* go down, because grouping can be defined after e.g. container in which is collision */
764 if (down) {
765 for (iter = start, stop = NULL; iter; iter = iter->prev) {
766 if (!stop) {
767 stop = start;
768 } else if (iter == stop) {
769 break;
770 }
771 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
772 continue;
773 }
774
775 grp = NULL;
776 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100777 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100778 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200779 return EXIT_FAILURE;
780 }
781 }
782 }
783 }
784 break;
785 case LYS_LEAF:
786 case LYS_LEAFLIST:
787 case LYS_LIST:
788 case LYS_CONTAINER:
789 case LYS_CHOICE:
790 case LYS_ANYXML:
791 /* 6.2.1, rule 7 */
792 if (parent) {
793 iter = parent;
794 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
795 iter = iter->parent;
796 }
797 if (!iter) {
798 stop = NULL;
799 iter = module->data;
800 } else {
801 stop = iter;
802 iter = iter->child;
803 }
804 } else {
805 stop = NULL;
806 iter = module->data;
807 }
808 while (iter) {
809 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
810 iter = iter->child;
811 continue;
812 }
813
814 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100815 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100816 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200817 return EXIT_FAILURE;
818 }
819 }
820
821 /* special case for choice - we must check the choice's name as
822 * well as the names of nodes under the choice
823 */
824 if (iter->nodetype == LYS_CHOICE) {
825 iter = iter->child;
826 continue;
827 }
828
829 /* go to siblings */
830 if (!iter->next) {
831 /* no sibling, go to parent's sibling */
832 do {
833 iter = iter->parent;
834 if (iter && iter->next) {
835 break;
836 }
837 } while (iter != stop);
838
839 if (iter == stop) {
840 break;
841 }
842 }
843 iter = iter->next;
844 }
845 break;
846 case LYS_CASE:
847 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100848 if (parent) {
849 start = parent->child;
850 } else {
851 start = module->data;
852 }
853
854 LY_TREE_FOR(start, iter) {
Radek Krejci07911992015-08-14 15:13:31 +0200855 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
856 continue;
857 }
858
Radek Krejci749190d2016-02-18 16:26:25 +0100859 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100860 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200861 return EXIT_FAILURE;
862 }
863 }
864 break;
865 default:
866 /* no check needed */
867 break;
868 }
869
870 return EXIT_SUCCESS;
871}
872
Michal Vasko0d343d12015-08-24 14:57:36 +0200873/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200874int
Radek Krejci10c760e2015-08-14 14:45:43 +0200875lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
876{
Radek Krejci92720552015-10-05 15:28:27 +0200877 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200878 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200880 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200881
Radek Krejci10c760e2015-08-14 14:45:43 +0200882 if (parent) {
883 type = parent->nodetype;
884 module = parent->module;
885 } else {
886 assert(module);
887 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200888 }
889
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200890 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200891 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200892 case LYS_CONTAINER:
893 case LYS_LIST:
894 case LYS_GROUPING:
895 case LYS_USES:
896 case LYS_INPUT:
897 case LYS_OUTPUT:
898 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200899 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200900 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
901 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100902 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200903 return EXIT_FAILURE;
904 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200905
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200906 break;
Radek Krejci76512572015-08-04 09:47:08 +0200907 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200908 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200909 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100910 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200911 return EXIT_FAILURE;
912 }
913 break;
Radek Krejci76512572015-08-04 09:47:08 +0200914 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200915 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200916 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100917 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200918 return EXIT_FAILURE;
919 }
920 break;
Radek Krejci76512572015-08-04 09:47:08 +0200921 case LYS_RPC:
922 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100923 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200924 return EXIT_FAILURE;
925 }
926 break;
Radek Krejci76512572015-08-04 09:47:08 +0200927 case LYS_LEAF:
928 case LYS_LEAFLIST:
929 case LYS_ANYXML:
Radek Krejci48464ed2016-03-17 15:44:09 +0100930 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
931 LOGVAL(LYE_SPEC, LY_VLOG_LYS, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100932 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200933 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200934 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200935 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200936 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
937 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100938 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200939 return EXIT_FAILURE;
940 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200941 break;
942 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200943 /* top level */
944 if (!(child->nodetype &
945 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
946 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100947 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200948 return EXIT_FAILURE;
949 }
950
Radek Krejcic071c542016-01-27 14:57:51 +0100951 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200952 }
953
954 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200955 if (lys_check_id(child, parent, module)) {
956 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200957 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200958
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200959 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200960 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200961 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200962
Radek Krejci10c760e2015-08-14 14:45:43 +0200963 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +0200964 if (module->data) {
965 module->data->prev->next = child;
966 child->prev = module->data->prev;
967 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200968 } else {
Radek Krejci92720552015-10-05 15:28:27 +0200969 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200970 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200971 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200972 if (!parent->child) {
973 /* the only/first child of the parent */
974 parent->child = child;
975 child->parent = parent;
976 iter = child;
977 } else {
978 /* add a new child at the end of parent's child list */
979 iter = parent->child->prev;
980 iter->next = child;
981 child->prev = iter;
982 }
983 while (iter->next) {
984 iter = iter->next;
985 iter->parent = parent;
986 }
987 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200988 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200989
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200990 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200991}
992
Radek Krejcia1df1682016-04-11 14:56:59 +0200993static const struct lys_module *
994lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200995{
Radek Krejcia1df1682016-04-11 14:56:59 +0200996 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200997 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200998 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001000 if (!ctx || !data) {
1001 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1002 return NULL;
1003 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001004
Radek Krejcia1df1682016-04-11 14:56:59 +02001005 if (!internal && format == LYS_IN_YANG) {
1006 /* enlarge data by 2 bytes for flex */
1007 len = strlen(data);
1008 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
1009 if (!enlarged_data) {
1010 LOGMEM;
1011 return NULL;
1012 }
1013 memcpy(enlarged_data, data, len);
1014 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1015 data = enlarged_data;
1016 }
1017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001018 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001019 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +01001020 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001021 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001022 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001023 mod = yang_read_module(ctx, data, 0, NULL, 1);
1024 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001025 default:
Radek Krejcia1df1682016-04-11 14:56:59 +02001026 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001027 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001028 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001029
Radek Krejcia1df1682016-04-11 14:56:59 +02001030 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001031 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001032}
1033
Radek Krejcia1df1682016-04-11 14:56:59 +02001034API const struct lys_module *
1035lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
1036{
1037 return lys_parse_mem_(ctx, data, format, 0);
1038}
1039
Michal Vasko5a721fd2016-02-16 12:16:48 +01001040struct lys_submodule *
1041lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001042{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001043 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001044
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001045 assert(module);
1046 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001047
Radek Krejcic071c542016-01-27 14:57:51 +01001048 /* get the main module */
Michal Vasko4f0dad02016-02-15 14:08:23 +01001049 module = lys_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001051 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001052 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001053 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001054 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001055 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001056 submod = yang_read_submodule(module, data, 0, unres);
1057 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001058 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001059 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001060 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001061 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001062
Michal Vasko5a721fd2016-02-16 12:16:48 +01001063 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001064}
1065
Michal Vasko1e62a092015-12-01 12:27:20 +01001066API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001067lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1068{
1069 int fd;
1070 const struct lys_module *ret;
1071
1072 if (!ctx || !path) {
1073 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1074 return NULL;
1075 }
1076
1077 fd = open(path, O_RDONLY);
1078 if (fd == -1) {
1079 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1080 return NULL;
1081 }
1082
1083 ret = lys_parse_fd(ctx, fd, format);
1084 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +01001085
Radek Krejcia77904e2016-02-25 16:23:45 +01001086 if (ret && !ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001087 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +01001088 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +01001089 }
1090
Michal Vasko662610a2015-12-07 11:25:45 +01001091 return ret;
1092}
1093
1094API const struct lys_module *
1095lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001096{
Michal Vasko1e62a092015-12-01 12:27:20 +01001097 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001098 struct stat sb;
1099 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001100 char buf[PATH_MAX];
1101 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001102
1103 if (!ctx || fd < 0) {
1104 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1105 return NULL;
1106 }
1107
Radek Krejci10a833c2015-12-16 15:28:37 +01001108 if (fstat(fd, &sb) == -1) {
1109 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1110 return NULL;
1111 }
Radek Krejcib051f722016-02-25 15:12:21 +01001112 if (!S_ISREG(sb.st_mode)) {
1113 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
1114 return NULL;
1115 }
1116
Michal Vasko164d9012016-04-01 10:16:59 +02001117 if (!sb.st_size) {
1118 LOGERR(LY_EINVAL, "File empty.");
1119 return NULL;
1120 }
1121
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001122 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001123 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001124 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001125 return NULL;
1126 }
Radek Krejcia1df1682016-04-11 14:56:59 +02001127 module = lys_parse_mem_(ctx, addr, format, 1);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001128 munmap(addr, sb.st_size + 2);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001129
Radek Krejcia77904e2016-02-25 16:23:45 +01001130 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001131 /* get URI if there is /proc */
1132 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001133 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1134 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1135 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1136 }
1137 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001138 }
Radek Krejcib051f722016-02-25 15:12:21 +01001139 }
1140
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001141 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001142}
1143
Michal Vasko5a721fd2016-02-16 12:16:48 +01001144struct lys_submodule *
1145lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001146{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001147 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001148 struct stat sb;
1149 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001151 assert(module);
1152 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001153
Radek Krejci10a833c2015-12-16 15:28:37 +01001154 if (fstat(fd, &sb) == -1) {
1155 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001156 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001157 }
Michal Vasko164d9012016-04-01 10:16:59 +02001158
1159 if (!sb.st_size) {
1160 LOGERR(LY_EINVAL, "File empty.");
1161 return NULL;
1162 }
1163
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001164 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001165 if (addr == MAP_FAILED) {
1166 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001167 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001168 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001169 submodule = lys_submodule_parse(module, addr, format, unres);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001170 munmap(addr, sb.st_size + 2);
Radek Krejciefaeba32015-05-27 14:30:57 +02001171
Michal Vasko5a721fd2016-02-16 12:16:48 +01001172 return submodule;
1173
Radek Krejciefaeba32015-05-27 14:30:57 +02001174}
1175
Radek Krejci1d82ef62015-08-07 14:44:40 +02001176static struct lys_restr *
1177lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001178{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001179 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001180 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001181
Radek Krejci3733a802015-06-19 13:43:21 +02001182 if (!size) {
1183 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001184 }
Radek Krejci3733a802015-06-19 13:43:21 +02001185
1186 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001187 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001188 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001189 return NULL;
1190 }
Radek Krejci3733a802015-06-19 13:43:21 +02001191 for (i = 0; i < size; i++) {
1192 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1193 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1194 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1195 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1196 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1197 }
1198
1199 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001200}
1201
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001202void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001203lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001204{
1205 assert(ctx);
1206 if (!restr) {
1207 return;
1208 }
1209
1210 lydict_remove(ctx, restr->expr);
1211 lydict_remove(ctx, restr->dsc);
1212 lydict_remove(ctx, restr->ref);
1213 lydict_remove(ctx, restr->eapptag);
1214 lydict_remove(ctx, restr->emsg);
1215}
1216
Michal Vaskob84f88a2015-09-24 13:16:10 +02001217static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001218type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
1219 LY_DATA_TYPE base, struct unres_schema *unres)
1220{
1221 int i;
1222
1223 switch (base) {
1224 case LY_TYPE_BINARY:
1225 if (old->info.binary.length) {
1226 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
1227 }
1228 break;
1229
1230 case LY_TYPE_BITS:
1231 new->info.bits.count = old->info.bits.count;
1232 if (new->info.bits.count) {
1233 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1234 if (!new->info.bits.bit) {
1235 LOGMEM;
1236 return -1;
1237 }
1238 for (i = 0; i < new->info.bits.count; i++) {
1239 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1240 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1241 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1242 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1243 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1244 }
1245 }
1246 break;
1247
1248 case LY_TYPE_DEC64:
1249 new->info.dec64.dig = old->info.dec64.dig;
1250 if (old->info.dec64.range) {
1251 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
1252 }
1253 break;
1254
1255 case LY_TYPE_ENUM:
1256 new->info.enums.count = old->info.enums.count;
1257 if (new->info.enums.count) {
1258 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1259 if (!new->info.enums.enm) {
1260 LOGMEM;
1261 return -1;
1262 }
1263 for (i = 0; i < new->info.enums.count; i++) {
1264 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1265 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1266 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1267 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1268 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
1269 }
1270 }
1271 break;
1272
1273 case LY_TYPE_IDENT:
1274 if (old->info.ident.ref) {
1275 new->info.ident.ref = old->info.ident.ref;
1276 } else {
1277 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
1278 if (i > -1 && unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i])) {
1279 return -1;
1280 }
1281 }
1282 break;
1283
1284 case LY_TYPE_INST:
1285 new->info.inst.req = old->info.inst.req;
1286 break;
1287
1288 case LY_TYPE_INT8:
1289 case LY_TYPE_INT16:
1290 case LY_TYPE_INT32:
1291 case LY_TYPE_INT64:
1292 case LY_TYPE_UINT8:
1293 case LY_TYPE_UINT16:
1294 case LY_TYPE_UINT32:
1295 case LY_TYPE_UINT64:
1296 if (old->info.num.range) {
1297 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
1298 }
1299 break;
1300
1301 case LY_TYPE_LEAFREF:
1302 if (old->info.lref.path) {
1303 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
1304 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent)) {
1305 return -1;
1306 }
1307 }
1308 break;
1309
1310 case LY_TYPE_STRING:
1311 if (old->info.str.length) {
1312 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
1313 }
1314 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
1315 new->info.str.pat_count = old->info.str.pat_count;
1316 break;
1317
1318 case LY_TYPE_UNION:
1319 new->info.uni.count = old->info.uni.count;
1320 if (new->info.uni.count) {
1321 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1322 if (!new->info.uni.types) {
1323 LOGMEM;
1324 return -1;
1325 }
1326 for (i = 0; i < new->info.uni.count; i++) {
1327 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1328 return -1;
1329 }
1330 }
1331 }
1332 break;
1333
1334 default:
1335 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1336 break;
1337 }
1338 return EXIT_SUCCESS;
1339}
1340
1341struct yang_type *
1342lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type, struct unres_schema *unres)
1343{
1344 struct yang_type *new;
1345
1346 new = calloc(1, sizeof *new);
1347 if (!new) {
1348 LOGMEM;
1349 return NULL;
1350 }
1351 new->flags = old->flags;
1352 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001353 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001354 new->type = type;
1355 if (!new->name) {
1356 LOGMEM;
1357 goto error;
1358 }
1359 if (type_dup(module, parent, type, old->type, new->base, unres)) {
1360 new->type->base = new->base;
1361 lys_type_free(module->ctx, new->type);
1362 memset(&new->type->info, 0, sizeof new->type->info);
1363 goto error;
1364 }
1365 return new;
1366
1367 error:
1368 free(new);
1369 return NULL;
1370}
1371
1372static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001373lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vaskof02e3742015-08-05 16:27:02 +02001374 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001375{
1376 int i;
1377
Michal Vasko1dca6882015-10-22 14:29:42 +02001378 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001379 new->base = old->base;
1380 new->der = old->der;
1381
Michal Vasko0bd29d12015-08-19 11:45:49 +02001382 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001383 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001384 /* HACK (serious one) for unres */
1385 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001386 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
1387 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, unres);
1388 } else {
1389 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1390 }
Radek Krejcic071c542016-01-27 14:57:51 +01001391 new->parent = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001392 /* all these unres additions can fail even though they did not before */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001393 if (!new->der || unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001394 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001395 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001396 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001397 }
1398
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001399 return type_dup(mod, parent, new, old, new->base, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001400}
1401
1402void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001403lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001404{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001405 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001407 assert(ctx);
1408 if (!type) {
1409 return;
1410 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001411
Michal Vasko1dca6882015-10-22 14:29:42 +02001412 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001414 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001415 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001416 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001417 free(type->info.binary.length);
1418 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001419 case LY_TYPE_BITS:
1420 for (i = 0; i < type->info.bits.count; i++) {
1421 lydict_remove(ctx, type->info.bits.bit[i].name);
1422 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1423 lydict_remove(ctx, type->info.bits.bit[i].ref);
1424 }
1425 free(type->info.bits.bit);
1426 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001427
1428 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001429 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001430 free(type->info.dec64.range);
1431 break;
1432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001433 case LY_TYPE_ENUM:
1434 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001435 lydict_remove(ctx, type->info.enums.enm[i].name);
1436 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1437 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001438 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001439 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001440 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001441
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001442 case LY_TYPE_INT8:
1443 case LY_TYPE_INT16:
1444 case LY_TYPE_INT32:
1445 case LY_TYPE_INT64:
1446 case LY_TYPE_UINT8:
1447 case LY_TYPE_UINT16:
1448 case LY_TYPE_UINT32:
1449 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001450 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001451 free(type->info.num.range);
1452 break;
1453
Radek Krejcidc4c1412015-06-19 15:39:54 +02001454 case LY_TYPE_LEAFREF:
1455 lydict_remove(ctx, type->info.lref.path);
1456 break;
1457
Radek Krejci3733a802015-06-19 13:43:21 +02001458 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001459 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001460 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001461 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001462 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001463 }
1464 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001465 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001466
Radek Krejcie4c366b2015-07-02 10:11:31 +02001467 case LY_TYPE_UNION:
1468 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001469 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001470 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001471 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001472 break;
1473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001474 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001475 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001476 break;
1477 }
Radek Krejci5a065542015-05-22 15:02:07 +02001478}
1479
Radek Krejci1d82ef62015-08-07 14:44:40 +02001480static void
1481lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001482{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001483 assert(ctx);
1484 if (!tpdf) {
1485 return;
1486 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001488 lydict_remove(ctx, tpdf->name);
1489 lydict_remove(ctx, tpdf->dsc);
1490 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001491
Radek Krejci1d82ef62015-08-07 14:44:40 +02001492 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001494 lydict_remove(ctx, tpdf->units);
1495 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001496}
1497
Michal Vaskob84f88a2015-09-24 13:16:10 +02001498static struct lys_tpdf *
1499lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1500{
1501 struct lys_tpdf *result;
1502 int i, j;
1503
1504 if (!size) {
1505 return NULL;
1506 }
1507
1508 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001509 if (!result) {
1510 LOGMEM;
1511 return NULL;
1512 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001513 for (i = 0; i < size; i++) {
1514 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1515 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1516 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1517 result[i].flags = old[i].flags;
1518 result[i].module = old[i].module;
1519
1520 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1521 for (j = 0; j <= i; ++j) {
1522 lys_tpdf_free(mod->ctx, &result[j]);
1523 }
1524 free(result);
1525 return NULL;
1526 }
1527
1528 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1529 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1530 }
1531
1532 return result;
1533}
1534
Radek Krejci1d82ef62015-08-07 14:44:40 +02001535static struct lys_when *
1536lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001537{
Radek Krejci76512572015-08-04 09:47:08 +02001538 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001539
1540 if (!old) {
1541 return NULL;
1542 }
1543
1544 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001545 if (!new) {
1546 LOGMEM;
1547 return NULL;
1548 }
Radek Krejci00768f42015-06-18 17:04:04 +02001549 new->cond = lydict_insert(ctx, old->cond, 0);
1550 new->dsc = lydict_insert(ctx, old->dsc, 0);
1551 new->ref = lydict_insert(ctx, old->ref, 0);
1552
1553 return new;
1554}
1555
Michal Vasko0308dd62015-10-07 09:14:40 +02001556void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001557lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001558{
1559 if (!w) {
1560 return;
1561 }
1562
1563 lydict_remove(ctx, w->cond);
1564 lydict_remove(ctx, w->dsc);
1565 lydict_remove(ctx, w->ref);
1566
1567 free(w);
1568}
1569
Radek Krejcib7f5e412015-08-13 10:15:51 +02001570static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001571lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib7f5e412015-08-13 10:15:51 +02001572{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001573 struct lys_node *next, *sub;
1574
Radek Krejcic071c542016-01-27 14:57:51 +01001575 /* children from a resolved augment are freed under the target node */
1576 if (!aug.target) {
1577 LY_TREE_FOR_SAFE(aug.child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001578 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001579 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001580 }
1581
Radek Krejcib7f5e412015-08-13 10:15:51 +02001582 lydict_remove(ctx, aug.target_name);
1583 lydict_remove(ctx, aug.dsc);
1584 lydict_remove(ctx, aug.ref);
1585
1586 free(aug.features);
1587
1588 lys_when_free(ctx, aug.when);
1589
Michal Vasko7d356a52015-08-19 15:06:31 +02001590 /* Do not free the children, they were appended somewhere and their
1591 * new parent will take care of them.
1592 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001593}
1594
Radek Krejci76512572015-08-04 09:47:08 +02001595static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001596lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001597{
Radek Krejci76512572015-08-04 09:47:08 +02001598 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001599 struct lys_node *old_child, *new_child;
1600 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001601
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001602 if (!size) {
1603 return NULL;
1604 }
Radek Krejci106efc02015-06-10 14:36:27 +02001605
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001606 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001607 if (!new) {
1608 LOGMEM;
1609 return NULL;
1610 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001611 for (i = 0; i < size; i++) {
1612 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1613 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1614 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1615 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001616 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001617 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001618
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001619 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001620 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1621 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001622 LOGINT;
1623 free(new);
1624 return NULL;
1625 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001626 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001627
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001628 /* Correct the augment nodes.
1629 * This function can only be called from lys_node_dup() with uses
1630 * being the node duplicated, so we must have a case of grouping
1631 * with a uses with augments. The augmented nodes have already been
1632 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001633 * (it was set to their actual data parent, not an augment), and
1634 * the new augment does not have child pointer to its augment nodes,
1635 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001636 */
1637 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001638 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001639 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001640 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001641 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001642 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001643 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001644 LY_TREE_FOR(old[i].child, old_child) {
1645 /* all augment nodes were connected as siblings, there can be no more after this */
1646 if (old_child->parent != (struct lys_node *)&old[i]) {
1647 break;
1648 }
1649
Radek Krejci749190d2016-02-18 16:26:25 +01001650 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001651
1652 new_child->parent = (struct lys_node *)&new[i];
1653 new_child = new_child->next;
1654 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001655 }
Radek Krejci106efc02015-06-10 14:36:27 +02001656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001657 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001658}
1659
Radek Krejci76512572015-08-04 09:47:08 +02001660static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001661lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001662{
Radek Krejci76512572015-08-04 09:47:08 +02001663 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001664 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001666 if (!size) {
1667 return NULL;
1668 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001669
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001671 if (!result) {
1672 LOGMEM;
1673 return NULL;
1674 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001675 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001676 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001677 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1678 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001679 result[i].flags = old[i].flags;
1680 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001682 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001683 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001684
Radek Krejci76512572015-08-04 09:47:08 +02001685 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001686 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001687 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001688 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001689 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001690 result[i].mod.list = old[i].mod.list;
1691 }
1692 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001693
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001694 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001695}
1696
Radek Krejci1d82ef62015-08-07 14:44:40 +02001697static void
1698lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001699{
Radek Krejcia52656e2015-08-05 13:41:50 +02001700 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001702 assert(ctx);
1703 if (!ident) {
1704 return;
1705 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001706
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001707 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001708 * if caller free only a single data model which is used (its identity is
1709 * reference from identity in another module), this silly freeing can lead
1710 * to segmentation fault. But without noting if the module is used by some
1711 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001712 *
1713 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001714 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001715 */
1716 while (ident->der) {
1717 der = ident->der;
1718 ident->der = der->next;
1719 free(der);
1720 }
Radek Krejci6793db02015-05-22 17:49:54 +02001721
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001722 lydict_remove(ctx, ident->name);
1723 lydict_remove(ctx, ident->dsc);
1724 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001725
1726}
1727
Radek Krejci1d82ef62015-08-07 14:44:40 +02001728static void
1729lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001730{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001731 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001732
Radek Krejcid12f57b2015-08-06 10:43:39 +02001733 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001734 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001735 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001736 }
1737 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001738}
1739
Radek Krejci1d82ef62015-08-07 14:44:40 +02001740static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001741lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1742{
1743 int i;
1744
1745 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1746 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001747 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001748 }
1749 free(io->tpdf);
1750}
1751
Radek Krejci1d82ef62015-08-07 14:44:40 +02001752static void
1753lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001754{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001755 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001756
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001757 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001758 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001759 }
1760 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001761
Radek Krejci1d82ef62015-08-07 14:44:40 +02001762 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001763}
1764
Radek Krejci1d82ef62015-08-07 14:44:40 +02001765static void
1766lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001767{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001768 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001769
Radek Krejci46c4cd72016-01-21 15:13:52 +01001770 if (leaf->child) {
1771 /* leafref backlinks */
1772 ly_set_free((struct ly_set *)leaf->child);
1773 }
1774
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001775 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001776 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001777 }
1778 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001779
Radek Krejci1d82ef62015-08-07 14:44:40 +02001780 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001781
Radek Krejci1d82ef62015-08-07 14:44:40 +02001782 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001783 lydict_remove(ctx, leaf->units);
1784 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001785}
1786
Radek Krejci1d82ef62015-08-07 14:44:40 +02001787static void
1788lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001789{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001790 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001791
Radek Krejci46c4cd72016-01-21 15:13:52 +01001792 if (llist->child) {
1793 /* leafref backlinks */
1794 ly_set_free((struct ly_set *)llist->child);
1795 }
1796
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001797 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001798 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001799 }
1800 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001801
Radek Krejci1d82ef62015-08-07 14:44:40 +02001802 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001803
Radek Krejci1d82ef62015-08-07 14:44:40 +02001804 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001805 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001806}
1807
Radek Krejci1d82ef62015-08-07 14:44:40 +02001808static void
1809lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001810{
Radek Krejci581ce772015-11-10 17:22:40 +01001811 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001812
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001813 /* handle only specific parts for LY_NODE_LIST */
1814 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001815 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001816 }
1817 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001819 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001820 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001821 }
1822 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001823
Radek Krejci1d82ef62015-08-07 14:44:40 +02001824 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001826 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001827 for (j = 0; j > list->unique[i].expr_size; j++) {
1828 lydict_remove(ctx, list->unique[i].expr[j]);
1829 }
1830 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001831 }
1832 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001833
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001834 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001835}
1836
Radek Krejci1d82ef62015-08-07 14:44:40 +02001837static void
1838lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001839{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001840 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001841
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001842 /* handle only specific parts for LY_NODE_CONTAINER */
1843 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001845 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001846 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001847 }
1848 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001850 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001851 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001852 }
1853 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001854
Radek Krejci1d82ef62015-08-07 14:44:40 +02001855 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001856}
1857
Radek Krejci1d82ef62015-08-07 14:44:40 +02001858static void
1859lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001860{
1861 lydict_remove(ctx, f->name);
1862 lydict_remove(ctx, f->dsc);
1863 lydict_remove(ctx, f->ref);
1864 free(f->features);
1865}
1866
Radek Krejci1d82ef62015-08-07 14:44:40 +02001867static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001868lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001869{
Radek Krejci581ce772015-11-10 17:22:40 +01001870 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001871 struct ly_ctx *ctx;
1872 struct lys_node *next, *elem;
1873
1874 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001875
1876 lydict_remove(ctx, dev->target_name);
1877 lydict_remove(ctx, dev->dsc);
1878 lydict_remove(ctx, dev->ref);
1879
Michal Vaskoff006c12016-02-17 11:15:19 +01001880 /* the module was freed, but we only need the context from orig_node, use ours */
1881 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1882 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1883 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1884 elem->module = module;
1885
1886 LY_TREE_DFS_END(dev->orig_node, next, elem);
1887 }
1888 lys_node_free(dev->orig_node, NULL, 0);
1889 } else {
1890 /* it's just a shallow copy, freeing one node */
1891 dev->orig_node->module = module;
1892 lys_node_free(dev->orig_node, NULL, 1);
1893 }
1894
Radek Krejcieb00f512015-07-01 16:44:58 +02001895 for (i = 0; i < dev->deviate_size; i++) {
1896 lydict_remove(ctx, dev->deviate[i].dflt);
1897 lydict_remove(ctx, dev->deviate[i].units);
1898
1899 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1900 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001901 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001902 }
1903 free(dev->deviate[i].must);
1904
1905 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001906 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1907 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1908 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01001909 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001910 }
1911 free(dev->deviate[i].unique);
1912 }
1913 }
1914 free(dev->deviate);
1915}
1916
Radek Krejci1d82ef62015-08-07 14:44:40 +02001917static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001918lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie1fa8582015-06-08 09:46:45 +02001919{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001920 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001922 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001923 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001924 lydict_remove(ctx, uses->refine[i].dsc);
1925 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001926
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001927 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001928 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001929 }
1930 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001931
Radek Krejci76512572015-08-04 09:47:08 +02001932 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001933 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001934 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001935 lydict_remove(ctx, uses->refine[i].mod.presence);
1936 }
1937 }
1938 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001939
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001940 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001941 lys_augment_free(ctx, uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001942 }
1943 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001944
Radek Krejci1d82ef62015-08-07 14:44:40 +02001945 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001946}
1947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001948void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001949lys_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 +02001950{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001951 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001952 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001953
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001954 if (!node) {
1955 return;
1956 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001957
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001958 assert(node->module);
1959 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001961 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001962
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001963 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01001964 if (node->priv && private_destructor) {
1965 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001966 }
1967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001968 /* common part */
Radek Krejcid12f57b2015-08-06 10:43:39 +02001969 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1970 free(node->features);
1971 lydict_remove(ctx, node->name);
1972 lydict_remove(ctx, node->dsc);
1973 lydict_remove(ctx, node->ref);
1974 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001975
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001976 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001977 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001978 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001979 }
1980 }
1981
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001982 /* specific part */
1983 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001984 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001985 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001986 break;
Radek Krejci76512572015-08-04 09:47:08 +02001987 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001988 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001989 break;
Radek Krejci76512572015-08-04 09:47:08 +02001990 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001991 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001992 break;
Radek Krejci76512572015-08-04 09:47:08 +02001993 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001994 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001995 break;
Radek Krejci76512572015-08-04 09:47:08 +02001996 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001997 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001998 break;
Radek Krejci76512572015-08-04 09:47:08 +02001999 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002000 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002001 break;
Radek Krejci76512572015-08-04 09:47:08 +02002002 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002003 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002004 break;
Radek Krejci76512572015-08-04 09:47:08 +02002005 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002006 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002007 break;
Radek Krejci76512572015-08-04 09:47:08 +02002008 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002009 /* do nothing */
2010 break;
Radek Krejci76512572015-08-04 09:47:08 +02002011 case LYS_GROUPING:
2012 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02002013 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002014 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002015 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002016
2017 case LYS_INPUT:
2018 case LYS_OUTPUT:
2019 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
2020 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02002021 case LYS_UNKNOWN:
2022 LOGINT;
2023 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002024 }
Radek Krejci5a065542015-05-22 15:02:07 +02002025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002026 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002027 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002028 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002029}
2030
Michal Vasko1e62a092015-12-01 12:27:20 +01002031const struct lys_module *
2032lys_get_import_module(const struct lys_module *module, const char *prefix, int pref_len, const char *name, int name_len)
Michal Vasko8ce24d72015-10-21 11:27:26 +02002033{
Radek Krejcic071c542016-01-27 14:57:51 +01002034 const struct lys_module *main_module;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002035 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002036
Michal Vaskoa7789a82016-02-11 15:42:55 +01002037 assert(!prefix || !name);
2038
Michal Vaskob6729c62015-10-21 12:09:47 +02002039 if (prefix && !pref_len) {
2040 pref_len = strlen(prefix);
2041 }
2042 if (name && !name_len) {
2043 name_len = strlen(name);
2044 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002045
Michal Vasko4f0dad02016-02-15 14:08:23 +01002046 main_module = lys_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002047
2048 /* module own prefix, submodule own prefix, (sub)module own name */
2049 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2050 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002051 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002052 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002053 }
2054
Michal Vasko8ce24d72015-10-21 11:27:26 +02002055 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002056 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2057 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002058 return module->imp[i].module;
2059 }
2060 }
2061
2062 return NULL;
2063}
2064
Michal Vasko13b15832015-08-19 11:04:48 +02002065/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002066static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002067module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002068{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002069 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002070 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002071 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002073 assert(module->ctx);
2074 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002075
Michal Vaskob746fff2016-02-11 11:37:50 +01002076 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002077 for (i = 0; i < module->imp_size; i++) {
Radek Krejci4f78b532016-02-17 13:43:00 +01002078 if (!module->imp[i].external) {
2079 lydict_remove(ctx, module->imp[i].prefix);
2080 }
Radek Krejci225376f2016-02-16 17:36:22 +01002081 }
Radek Krejcidce51452015-06-16 15:20:08 +02002082 free(module->imp);
2083
Radek Krejcic071c542016-01-27 14:57:51 +01002084 /* submodules don't have data tree, the data nodes
2085 * are placed in the main module altogether */
2086 if (!module->type) {
2087 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002088 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002089 }
Radek Krejci21181962015-06-30 14:11:00 +02002090 }
Radek Krejci5a065542015-05-22 15:02:07 +02002091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002092 lydict_remove(ctx, module->dsc);
2093 lydict_remove(ctx, module->ref);
2094 lydict_remove(ctx, module->org);
2095 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002096 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002097
Radek Krejcieb00f512015-07-01 16:44:58 +02002098 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 for (i = 0; i < module->rev_size; i++) {
2100 lydict_remove(ctx, module->rev[i].dsc);
2101 lydict_remove(ctx, module->rev[i].ref);
2102 }
2103 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002104
Radek Krejcieb00f512015-07-01 16:44:58 +02002105 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002106 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002107 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002108 }
2109 module->ident_size = 0;
2110 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002111
Radek Krejcieb00f512015-07-01 16:44:58 +02002112 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002113 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002114 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002115 }
2116 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002117
Radek Krejcieb00f512015-07-01 16:44:58 +02002118 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 for (i = 0; i < module->inc_size; i++) {
Radek Krejcic071c542016-01-27 14:57:51 +01002120 /* complete submodule free is done only from main module since
2121 * submodules propagate their includes to the main module */
2122 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002123 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002124 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 }
2126 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002127
Radek Krejcieb00f512015-07-01 16:44:58 +02002128 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002129 for (i = 0; i < module->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002130 lys_augment_free(ctx, module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002131 }
2132 free(module->augment);
2133
Radek Krejcieb00f512015-07-01 16:44:58 +02002134 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002135 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002136 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002137 }
2138 free(module->features);
2139
Radek Krejcieb00f512015-07-01 16:44:58 +02002140 /* deviations */
2141 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002142 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002143 }
2144 free(module->deviation);
2145
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002147 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002148}
2149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150void
Michal Vaskob746fff2016-02-11 11:37:50 +01002151lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002152{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002153 if (!submodule) {
2154 return;
2155 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002156
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002157 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002158 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002160 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002162 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002163}
2164
Radek Krejci76512572015-08-04 09:47:08 +02002165struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002166lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node, uint8_t flags,
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002167 uint8_t nacm, struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002168{
Radek Krejcic071c542016-01-27 14:57:51 +01002169 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002171 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002172
Michal Vaskoc07187d2015-08-13 15:20:57 +02002173 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002174 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002175 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002176 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002177 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002178 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002179 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002180 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002181 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002182 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002183 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002184 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002185 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002186 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002187 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002188 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002189 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002190 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002191 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002192 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002193 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002194 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002195 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002196 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 /* we cannot just duplicate memory since the strings are stored in
2199 * dictionary and we need to update dictionary counters.
2200 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002201
Radek Krejci1d82ef62015-08-07 14:44:40 +02002202 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002203 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002204 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002205 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002206 break;
2207
Radek Krejci76512572015-08-04 09:47:08 +02002208 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002210 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002211 break;
2212
Radek Krejci76512572015-08-04 09:47:08 +02002213 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002214 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002215 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002216 break;
2217
Radek Krejci76512572015-08-04 09:47:08 +02002218 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002219 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002220 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002221 break;
2222
Radek Krejci76512572015-08-04 09:47:08 +02002223 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002224 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002225 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 break;
2227
Radek Krejci76512572015-08-04 09:47:08 +02002228 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002230 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231 break;
2232
Radek Krejci76512572015-08-04 09:47:08 +02002233 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002235 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002236 break;
2237
Radek Krejci76512572015-08-04 09:47:08 +02002238 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002240 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002241 break;
2242
Radek Krejci76512572015-08-04 09:47:08 +02002243 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002244 grp = calloc(1, sizeof *grp);
2245 retval = (struct lys_node *)grp;
2246 break;
2247
Radek Krejci76512572015-08-04 09:47:08 +02002248 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002249 rpc = calloc(1, sizeof *rpc);
2250 retval = (struct lys_node *)rpc;
2251 break;
2252
Radek Krejci76512572015-08-04 09:47:08 +02002253 case LYS_INPUT:
2254 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002255 io = calloc(1, sizeof *io);
2256 retval = (struct lys_node *)io;
2257 break;
2258
Radek Krejci76512572015-08-04 09:47:08 +02002259 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002260 ntf = calloc(1, sizeof *ntf);
2261 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002262 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002264 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002265 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002266 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002267 }
Radek Krejcib388c152015-06-04 17:03:03 +02002268
Michal Vasko253035f2015-12-17 16:58:13 +01002269 if (!retval) {
2270 LOGMEM;
2271 return NULL;
2272 }
2273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002274 /*
2275 * duplicate generic part of the structure
2276 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002277 retval->name = lydict_insert(ctx, node->name, 0);
2278 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2279 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002280 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002281 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002282 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002283 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002284 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002287 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002288 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002290 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002291
Radek Krejci1d82ef62015-08-07 14:44:40 +02002292 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002293 retval->features = calloc(retval->features_size, sizeof *retval->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002294 if (!retval->features) {
2295 LOGMEM;
2296 goto error;
2297 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002298
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002299 if (!shallow) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002300 for (i = 0; i < node->features_size; ++i) {
2301 retval->features[i] = (struct lys_feature *)retval;
2302 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
2303 retval->features[i] = node->features[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 }
2305 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002306
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002307 /* connect it to the parent */
2308 if (lys_node_addchild(parent, retval->module, retval)) {
2309 goto error;
2310 }
Radek Krejcidce51452015-06-16 15:20:08 +02002311
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002312 /* go recursively */
2313 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2314 LY_TREE_FOR(node->child, child) {
2315 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres, 0)) {
2316 goto error;
2317 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002318 }
2319 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002320 } else {
2321 memcpy(retval->features, node->features, retval->features_size * sizeof *retval->features);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 }
2323
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002324 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002325 * duplicate specific part of the structure
2326 */
2327 switch (node->nodetype) {
2328 case LYS_CONTAINER:
2329 if (cont_orig->when) {
2330 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331 }
2332 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 cont->must_size = cont_orig->must_size;
2335 cont->tpdf_size = cont_orig->tpdf_size;
2336
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002337 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002338 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
2339 break;
2340
2341 case LYS_CHOICE:
2342 if (choice_orig->when) {
2343 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002344 }
2345
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002346 if (!shallow) {
2347 if (choice_orig->dflt) {
2348 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0, LYS_ANYXML
2349 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
2350 | LYS_LIST, (const struct lys_node **)&choice->dflt);
2351 if (rc) {
2352 if (rc == EXIT_FAILURE) {
2353 LOGINT;
2354 }
2355 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002356 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002357 } else {
2358 /* useless to check return value, we don't know whether
2359 * there really wasn't any default defined or it just hasn't
2360 * been resolved, we just hope for the best :)
2361 */
2362 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002363 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002364 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002365 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002366 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002367 break;
2368
2369 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002370 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2371 goto error;
2372 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002373 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2374
2375 if (leaf_orig->dflt) {
2376 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci48464ed2016-03-17 15:44:09 +01002377 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002378 goto error;
2379 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002380 }
2381
2382 leaf->must_size = leaf_orig->must_size;
2383 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002384
2385 if (leaf_orig->when) {
2386 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002387 }
2388 break;
2389
2390 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002391 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2392 goto error;
2393 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002394 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2395
2396 llist->min = llist_orig->min;
2397 llist->max = llist_orig->max;
2398
2399 llist->must_size = llist_orig->must_size;
2400 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002401
2402 if (llist_orig->when) {
2403 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002404 }
2405 break;
2406
2407 case LYS_LIST:
2408 list->min = list_orig->min;
2409 list->max = list_orig->max;
2410
2411 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002412 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002413
Radek Krejci581ce772015-11-10 17:22:40 +01002414 list->tpdf_size = list_orig->tpdf_size;
Michal Vasko0ea41032015-06-16 08:53:55 +02002415 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002416
Radek Krejci581ce772015-11-10 17:22:40 +01002417 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002418 if (list->keys_size) {
2419 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002420 if (!list->keys) {
2421 LOGMEM;
2422 goto error;
2423 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002424
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002425 if (!shallow) {
2426 /* we managed to resolve it before, resolve it again manually */
2427 if (list_orig->keys[0]) {
2428 for (i = 0; i < list->keys_size; ++i) {
2429 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2430 (const struct lys_node **)&list->keys[i]);
2431 if (rc) {
2432 if (rc == EXIT_FAILURE) {
2433 LOGINT;
2434 }
2435 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002436 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002437 }
2438 /* it was not resolved yet, add unres copy */
2439 } else {
2440 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2441 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002442 goto error;
2443 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002444 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002445 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002446 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002447 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002448 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002449
Radek Krejci581ce772015-11-10 17:22:40 +01002450 list->unique_size = list_orig->unique_size;
2451 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002452 if (!list->unique) {
2453 LOGMEM;
2454 goto error;
2455 }
Radek Krejci581ce772015-11-10 17:22:40 +01002456 for (i = 0; i < list->unique_size; ++i) {
2457 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2458 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002459 if (!list->unique[i].expr) {
2460 LOGMEM;
2461 goto error;
2462 }
Radek Krejci581ce772015-11-10 17:22:40 +01002463 for (j = 0; j < list->unique[i].expr_size; j++) {
2464 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2465
2466 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002467 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002468 }
2469 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002471 if (list_orig->when) {
2472 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002473 }
Radek Krejcidce51452015-06-16 15:20:08 +02002474 break;
2475
2476 case LYS_ANYXML:
2477 anyxml->must_size = anyxml_orig->must_size;
2478 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002479
2480 if (anyxml_orig->when) {
2481 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002482 }
2483 break;
2484
2485 case LYS_USES:
2486 uses->grp = uses_orig->grp;
2487
2488 if (uses_orig->when) {
2489 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002490 }
2491
2492 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002493 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002494 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002495 if (!shallow) {
2496 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
2497 if (!uses->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002498 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002499 goto error;
2500 }
Michal Vasko49168a22015-08-17 16:35:41 +02002501 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002502 } else {
2503 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002504 }
2505 break;
2506
Radek Krejcidce51452015-06-16 15:20:08 +02002507 case LYS_CASE:
2508 if (cs_orig->when) {
2509 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002510 }
2511 break;
2512
2513 case LYS_GROUPING:
2514 grp->tpdf_size = grp_orig->tpdf_size;
2515 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
2516 break;
2517
2518 case LYS_RPC:
2519 rpc->tpdf_size = rpc_orig->tpdf_size;
2520 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
2521 break;
2522
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002523 case LYS_INPUT:
2524 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002525 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002526 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
2527 break;
2528
Radek Krejcida04f4a2015-05-21 12:54:09 +02002529 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002530 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002531 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejci7e97c352015-06-19 16:26:34 +02002532 break;
2533
2534 default:
2535 /* LY_NODE_AUGMENT */
2536 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002537 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002538 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002539
2540 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002541
2542error:
2543
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002544 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002545 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002546}
2547
Michal Vasko13b15832015-08-19 11:04:48 +02002548void
Michal Vaskoff006c12016-02-17 11:15:19 +01002549lys_node_switch(struct lys_node *dst, struct lys_node *src)
2550{
2551 struct lys_node *child;
2552
2553 assert((dst->module == src->module) && (dst->name == src->name) && (dst->nodetype == src->nodetype));
2554
2555 /* sibling next */
2556 if (dst->prev != dst) {
2557 dst->prev->next = src;
2558 }
2559
2560 /* sibling prev */
2561 if (dst->next) {
2562 dst->next->prev = src;
2563 }
2564
2565 /* parent child prev */
2566 if (!dst->next && dst->parent) {
2567 dst->parent->child->prev = src;
2568 }
2569
2570 /* next */
2571 src->next = dst->next;
2572 dst->next = NULL;
2573
2574 /* prev */
2575 if (dst->prev != dst) {
2576 src->prev = dst->prev;
2577 }
2578 dst->prev = dst;
2579
2580 /* parent child */
2581 if (dst->parent && (dst->parent->child == dst)) {
2582 dst->parent->child = src;
2583 }
2584
2585 /* parent */
2586 src->parent = dst->parent;
2587 dst->parent = NULL;
2588
2589 /* child parent */
2590 LY_TREE_FOR(dst->child, child) {
2591 if (child->parent == dst) {
2592 child->parent = src;
2593 }
2594 }
2595
2596 /* child */
2597 src->child = dst->child;
2598 dst->child = NULL;
2599}
2600
2601void
Michal Vasko627975a2016-02-11 11:39:03 +01002602lys_free(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv), int remove_from_ctx)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002603{
2604 struct ly_ctx *ctx;
2605 int i;
2606
2607 if (!module) {
2608 return;
2609 }
2610
2611 /* remove schema from the context */
2612 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002613 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002614 for (i = 0; i < ctx->models.used; i++) {
2615 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002616 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002617 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002618 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 +02002619 ctx->models.list[ctx->models.used] = NULL;
2620 /* we are done */
2621 break;
2622 }
2623 }
2624 }
2625
2626 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002627 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002628
2629 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002630 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002631
2632 free(module);
2633}
Radek Krejci7e97c352015-06-19 16:26:34 +02002634
2635/*
2636 * op: 1 - enable, 0 - disable
2637 */
2638static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002639lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002640{
2641 int all = 0;
2642 int i, j, k;
2643
2644 if (!module || !name || !strlen(name)) {
2645 return EXIT_FAILURE;
2646 }
2647
2648 if (!strcmp(name, "*")) {
2649 /* enable all */
2650 all = 1;
2651 }
2652
2653 /* module itself */
2654 for (i = 0; i < module->features_size; i++) {
2655 if (all || !strcmp(module->features[i].name, name)) {
2656 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002657 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002658 /* enable referenced features (recursion) */
2659 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002660 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002661 module->features[i].features[k]->name, op);
2662 }
2663 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002664 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002665 }
2666 if (!all) {
2667 return EXIT_SUCCESS;
2668 }
2669 }
2670 }
2671
2672 /* submodules */
2673 for (j = 0; j < module->inc_size; j++) {
2674 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2675 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2676 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002677 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002678 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002679 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002680 }
2681 if (!all) {
2682 return EXIT_SUCCESS;
2683 }
2684 }
2685 }
2686 }
2687
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002688 /* TODO submodules of submodules ... */
2689
Radek Krejci7e97c352015-06-19 16:26:34 +02002690 if (all) {
2691 return EXIT_SUCCESS;
2692 } else {
2693 return EXIT_FAILURE;
2694 }
2695}
2696
2697API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002698lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002699{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002700 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002701}
2702
2703API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002704lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002705{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002706 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002707}
2708
2709API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002710lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002711{
2712 int i, j;
2713
2714 if (!module || !feature) {
2715 return -1;
2716 }
2717
2718 /* search for the specified feature */
2719 /* module itself */
2720 for (i = 0; i < module->features_size; i++) {
2721 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002722 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002723 return 1;
2724 } else {
2725 return 0;
2726 }
2727 }
2728 }
2729
2730 /* submodules */
2731 for (j = 0; j < module->inc_size; j++) {
2732 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2733 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002734 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002735 return 1;
2736 } else {
2737 return 0;
2738 }
2739 }
2740 }
2741 }
2742
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002743 /* feature definition not found */
2744 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002745}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002746
Radek Krejci96a10da2015-07-30 11:00:14 +02002747API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002748lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002749{
Radek Krejci96a10da2015-07-30 11:00:14 +02002750 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002751 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002752 unsigned int count;
2753
2754 if (!module) {
2755 return NULL;
2756 }
2757
2758 count = module->features_size;
2759 for (i = 0; i < module->inc_size; i++) {
2760 count += module->inc[i].submodule->features_size;
2761 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002762 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002763 if (!result) {
2764 LOGMEM;
2765 return NULL;
2766 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002767 if (states) {
2768 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002769 if (!(*states)) {
2770 LOGMEM;
2771 free(result);
2772 return NULL;
2773 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002774 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002775 count = 0;
2776
2777 /* module itself */
2778 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002779 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002780 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002781 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002782 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002783 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002784 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002785 }
2786 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002787 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002788 }
2789
2790 /* submodules */
2791 for (j = 0; j < module->inc_size; j++) {
2792 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002793 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002794 if (states) {
2795 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2796 (*states)[count] = 1;
2797 } else {
2798 (*states)[count] = 0;
2799 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002800 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002801 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002802 }
2803 }
2804
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002805 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002806 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002807
2808 return result;
2809}
Michal Vaskobaefb032015-09-24 14:52:10 +02002810
Radek Krejcic071c542016-01-27 14:57:51 +01002811struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002812lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002813{
2814 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2815}
2816
Michal Vasko320e8532016-02-15 13:11:57 +01002817struct lys_module *
2818lys_module(const struct lys_module *module)
2819{
2820 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2821}
2822
Michal Vaskobaefb032015-09-24 14:52:10 +02002823API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002824lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002825{
2826 if (!node || !node->parent) {
2827 return NULL;
2828 }
2829
2830 if (node->parent->nodetype == LYS_AUGMENT) {
2831 return ((struct lys_node_augment *)node->parent)->target;
2832 }
2833
2834 return node->parent;
2835}
Michal Vasko1b229152016-01-13 11:28:38 +01002836
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002837API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002838lys_set_private(const struct lys_node *node, void *priv)
2839{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002840 void *prev;
2841
Michal Vasko1b229152016-01-13 11:28:38 +01002842 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002843 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2844 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002845 }
2846
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002847 prev = node->priv;
2848 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002849
2850 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002851}