blob: 7a6bf6d1f0a9332137b5854ff9e964d2f75213ad [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;
Michal Vaskodcf98e62016-05-05 17:53:53 +0200151 while ((node = lys_getnext(node, lys_parent(siblings), mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100152 if (!type || (node->nodetype & type)) {
153 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200154 if (lys_node_module(node) != lys_main_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 Krejci7531aa22016-04-12 13:52:19 +0200289 const struct lys_node *siter = NULL, *missing_parent = NULL;
Radek Krejci96e20852016-04-11 17:51:26 +0200290 struct lys_node *parent = NULL;
Radek Krejci7531aa22016-04-12 13:52:19 +0200291 const struct lyd_node *diter = NULL;
Radek Krejcidc154432016-01-21 11:10:59 +0100292 struct ly_set *set = NULL;
Michal Vaskof610fd42016-04-19 10:38:20 +0200293 unsigned int i, toplevel = (stop && stop->nodetype != LYS_OUTPUT) ? 0 : 1;
Michal Vasko84f821a2016-04-11 11:03:42 +0200294 uint32_t minmax, min, max;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200295
Radek Krejci7531aa22016-04-12 13:52:19 +0200296 if (data) {
297 /* go to the correct data level */
298 for (parent = lys_parent(node); parent && parent != stop; parent = lys_parent(parent)) {
299 /* 7.6.5, rule 1 (presence container), checking presence
300 * is not needed since it is done in check_mand_getnext()
301 */
302
303 if (parent->nodetype != LYS_CONTAINER) {
304 /* not interested in LYS_USES, LYS_CASE or LYS_CHOICE,
305 * because they are not instantiated in data tree */
306 continue;
307 }
308 /* add the parent to the list for searching in data tree */
309 if (!set) {
310 set = ly_set_new();
311 }
312 /* ignore return - memory error is logged and we will
313 * check at least the rest of nodes we have */
314 (void)ly_set_add(set, parent);
315 }
316 if (set) {
317 for (i = set->number; i > 0; ) {
318 i--;
319 LY_TREE_FOR(toplevel ? data : data->child, diter) {
320 if (diter->schema == set->set.s[i]) {
321 break;
322 }
323 }
324 if (!diter) {
325 /* instance not found */
326 missing_parent = set->set.s[i];
Radek Krejci29ac4f92016-04-12 15:05:53 +0200327 if (toplevel) {
328 data = NULL;
329 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200330 break;
331 }
332 data = diter;
333 toplevel = 0;
334 if (data->validity == LYD_VAL_OK) {
335 /* already checked */
336 ly_set_free(set);
337 return EXIT_SUCCESS;
338 }
339 }
340 ly_set_free(set);
341 }
342 } else {
343 missing_parent = node;
344 }
345
Radek Krejci7f40ce32015-08-12 20:38:46 +0200346 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci7531aa22016-04-12 13:52:19 +0200347 if (missing_parent) {
Radek Krejci29ac4f92016-04-12 15:05:53 +0200348 LOGVAL(LYE_MISSELEM, LY_VLOG_LYD, data, node->name,
349 (lys_parent(node) ? lys_parent(node)->name : lys_node_module(node)->name));
Michal Vasko84f821a2016-04-11 11:03:42 +0200350 return EXIT_FAILURE;
Radek Krejci2342cf62016-01-29 16:48:23 +0100351 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200352
Radek Krejci2342cf62016-01-29 16:48:23 +0100353 switch (node->nodetype) {
354 case LYS_LEAF:
355 case LYS_ANYXML:
356 case LYS_CHOICE:
Michal Vasko84f821a2016-04-11 11:03:42 +0200357 if (lys_parent(node) && lys_parent(node)->nodetype == LYS_CASE) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100358 /* 7.6.5, rule 2 */
359 /* 7.9.4, rule 1 */
Radek Krejci7531aa22016-04-12 13:52:19 +0200360
361 /* try to find the node's siblings in data */
362 LY_TREE_FOR(toplevel ? data : data->child, diter) {
363 LY_TREE_FOR(lys_parent(node)->child, siter) {
364 if (siter == diter->schema) {
365 /* some sibling exists, rule applies */
Radek Krejci2342cf62016-01-29 16:48:23 +0100366 break;
367 }
368 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200369 if (siter) {
370 break;
371 }
Radek Krejci2342cf62016-01-29 16:48:23 +0100372 }
373 if (!siter) {
374 /* no sibling exists */
Michal Vasko84f821a2016-04-11 11:03:42 +0200375 return EXIT_SUCCESS;
Radek Krejci2342cf62016-01-29 16:48:23 +0100376 }
Radek Krejci2342cf62016-01-29 16:48:23 +0100377 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200378
Radek Krejci96e20852016-04-11 17:51:26 +0200379 if (node->nodetype == LYS_CHOICE) {
380 siter = NULL;
Radek Krejci7531aa22016-04-12 13:52:19 +0200381 LY_TREE_FOR(toplevel ? data : data->child, diter) {
Radek Krejci96e20852016-04-11 17:51:26 +0200382 while ((siter = lys_getnext(siter, node, NULL, 0))) {
383 if (diter->schema == siter) {
384 return EXIT_SUCCESS;
385 }
386 }
387 }
388 } else {
Radek Krejci7531aa22016-04-12 13:52:19 +0200389 LY_TREE_FOR(toplevel ? data : data->child, diter) {
Radek Krejci96e20852016-04-11 17:51:26 +0200390 if (diter->schema == node) {
391 return EXIT_SUCCESS;
392 }
Radek Krejci2342cf62016-01-29 16:48:23 +0100393 }
394 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200395
Radek Krejci2342cf62016-01-29 16:48:23 +0100396 /* instance not found */
397 /* 7.6.5, rule 3 (or 2) */
398 /* 7.9.4, rule 2 */
Michal Vasko84f821a2016-04-11 11:03:42 +0200399 if (node->nodetype == LYS_CHOICE) {
Radek Krejci29ac4f92016-04-12 15:05:53 +0200400 LOGVAL(LYE_NOMANDCHOICE, LY_VLOG_LYD, toplevel ? NULL : data, node->name);
Michal Vasko84f821a2016-04-11 11:03:42 +0200401 } else {
Radek Krejci29ac4f92016-04-12 15:05:53 +0200402 LOGVAL(LYE_MISSELEM, LY_VLOG_LYD, toplevel ? NULL : data, node->name,
Michal Vasko84f821a2016-04-11 11:03:42 +0200403 (lys_parent(node) ? lys_parent(node)->name : lys_node_module(node)->name));
404 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200405 break;
Radek Krejci2342cf62016-01-29 16:48:23 +0100406 default:
407 /* error */
Radek Krejci7531aa22016-04-12 13:52:19 +0200408 LOGINT;
Radek Krejci2342cf62016-01-29 16:48:23 +0100409 break;
410 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200411 return EXIT_FAILURE;
412
Radek Krejci14a11a62015-08-17 17:27:38 +0200413 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
414 /* search for number of instances */
415 minmax = 0;
Radek Krejci7531aa22016-04-12 13:52:19 +0200416 if (!missing_parent) {
417 LY_TREE_FOR(toplevel ? data : data->child, diter) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100418 if (diter->schema == node) {
419 minmax++;
Michal Vasko05ed8422016-04-12 11:38:24 +0200420 /* remember the last instance, we will use it in the log message */
421 data = diter;
Radek Krejci2342cf62016-01-29 16:48:23 +0100422 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200423 }
424 }
425
426 /* check the specified constraints */
427 if (node->nodetype == LYS_LIST) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200428 min = ((struct lys_node_list *)node)->min;
429 max = ((struct lys_node_list *)node)->max;
430 } else {
431 min = ((struct lys_node_leaflist *)node)->min;
432 max = ((struct lys_node_leaflist *)node)->max;
433 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200434
Michal Vasko84f821a2016-04-11 11:03:42 +0200435 if (min && (minmax < min)) {
Radek Krejci29ac4f92016-04-12 15:05:53 +0200436 LOGVAL(LYE_NOMIN, LY_VLOG_LYD, toplevel ? NULL : data, node->name);
Michal Vasko84f821a2016-04-11 11:03:42 +0200437 return EXIT_FAILURE;
438 }
439 if (max && (minmax > max)) {
Radek Krejci29ac4f92016-04-12 15:05:53 +0200440 LOGVAL(LYE_NOMAX, LY_VLOG_LYD, toplevel ? NULL : data, node->name);
Michal Vasko84f821a2016-04-11 11:03:42 +0200441 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200442 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200443 }
444
Michal Vasko84f821a2016-04-11 11:03:42 +0200445 return EXIT_SUCCESS;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200446}
447
Michal Vasko84f821a2016-04-11 11:03:42 +0200448int
Radek Krejci763122e2016-04-05 16:35:33 +0200449ly_check_mandatory(const struct lyd_node *data, const struct lys_node *schema, int status)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200450{
Michal Vasko84f821a2016-04-11 11:03:42 +0200451 const struct lys_node *siter, *saux, *saux2, *parent = NULL, *parent2;
Michal Vasko1e62a092015-12-01 12:27:20 +0100452 const struct lyd_node *diter;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200453 int found;
454
Radek Krejci2342cf62016-01-29 16:48:23 +0100455 assert(data || schema);
456
Radek Krejci7531aa22016-04-12 13:52:19 +0200457 if (schema) {
458 /* schema is preferred regardless the data */
Radek Krejci2342cf62016-01-29 16:48:23 +0100459 siter = schema;
Radek Krejci7531aa22016-04-12 13:52:19 +0200460 } else {
461 /* !schema && data */
Radek Krejcie2f12212016-02-12 13:50:22 +0100462 schema = data->schema;
463 siter = data->schema->child;
Radek Krejci2342cf62016-01-29 16:48:23 +0100464 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200465
466repeat:
467 while (siter) {
Radek Krejci763122e2016-04-05 16:35:33 +0200468 if (lys_is_disabled(siter, 2) || (!status && (siter->flags & LYS_CONFIG_R))) {
Radek Krejci074bf852015-08-19 14:22:16 +0200469 siter = siter->next;
470 continue;
471 }
472
Radek Krejci7f40ce32015-08-12 20:38:46 +0200473 switch (siter->nodetype) {
474 case LYS_CONTAINER:
475 case LYS_LEAF:
476 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200477 case LYS_LIST:
478 case LYS_LEAFLIST:
479 /* check if there is some mandatory node; first test the siter itself ... */
Michal Vasko84f821a2016-04-11 11:03:42 +0200480 if (check_mand_check(siter, lys_parent(siter), data)) {
481 return EXIT_FAILURE;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200482 }
483 /* ... and then the subtree */
Radek Krejcicf82e932016-04-11 17:52:31 +0200484 if (siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200485 saux = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100486 while ((saux = check_mand_getnext(saux, siter, NULL))) {
Radek Krejcie8da2e02016-04-11 17:53:34 +0200487 if ((status || (saux->flags & LYS_CONFIG_W)) && check_mand_check(saux, lys_parent(siter), data)) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200488 return EXIT_FAILURE;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200489 }
490 }
491 }
492 siter = siter->next;
493 break;
494 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200495 /* search for instance */
496 saux = siter;
497 siter = siter->child;
498 found = 0;
499 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200500repeat_choice:
Radek Krejci2342cf62016-01-29 16:48:23 +0100501 while (siter && data) {
Radek Krejci763122e2016-04-05 16:35:33 +0200502 if (lys_is_disabled(siter, 2) || (!status && (siter->flags & LYS_CONFIG_R))) {
Radek Krejci074bf852015-08-19 14:22:16 +0200503 siter = siter->next;
504 continue;
505 }
506
Radek Krejci14a11a62015-08-17 17:27:38 +0200507 switch (siter->nodetype) {
508 case LYS_CONTAINER:
509 case LYS_LEAF:
510 case LYS_LEAFLIST:
511 case LYS_LIST:
512 case LYS_ANYXML:
513 LY_TREE_FOR(data->child, diter) {
514 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200515 break;
516 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200517 }
518 if (diter) {
519 /* got instance */
520 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200521 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200522 saux2 = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100523 while ((saux2 = check_mand_getnext(saux2, parent2, NULL))) {
Radek Krejci7531aa22016-04-12 13:52:19 +0200524 if (check_mand_check(saux2, lys_parent(saux), data)) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200525 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200526 }
527 }
528 }
529 siter = parent2 = NULL;
530 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200531 break;
532 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200533 siter = siter->next;
534 break;
535 case LYS_CASE:
536 case LYS_CHOICE:
537 case LYS_USES:
538 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200539 if (!parent2) {
540 parent2 = siter;
541 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200542 siter = siter->child;
543 break;
544 case LYS_AUGMENT:
545 case LYS_GROUPING:
546 /* skip */
547 siter = siter->next;
548 break;
549 default:
550 /* error */
551 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200552 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200553 }
554
Radek Krejci14a11a62015-08-17 17:27:38 +0200555 if (parent2) {
556 siter = parent2->next;
Michal Vasko84f821a2016-04-11 11:03:42 +0200557 if (lys_parent(parent2) == saux) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200558 parent2 = NULL;
559 } else {
Michal Vasko84f821a2016-04-11 11:03:42 +0200560 parent2 = lys_parent(parent2);
Radek Krejci14a11a62015-08-17 17:27:38 +0200561 }
562 goto repeat_choice;
563 }
564
Radek Krejci074bf852015-08-19 14:22:16 +0200565 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci7531aa22016-04-12 13:52:19 +0200566 LOGVAL(LYE_MISSELEM, LY_VLOG_LYD, data, saux->name,
567 (lys_parent(saux) ? lys_parent(saux)->name : lys_node_module(saux)->name));
Michal Vasko84f821a2016-04-11 11:03:42 +0200568 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200569 }
570
571 /* go to next */
572 siter = saux->next;
573
Radek Krejci7f40ce32015-08-12 20:38:46 +0200574 break;
575 case LYS_USES:
576 case LYS_CASE:
Michal Vaskof610fd42016-04-19 10:38:20 +0200577 case LYS_INPUT:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200578 /* go into */
579 parent = siter;
580 siter = siter->child;
581 break;
582 default:
583 /* can ignore, go to next */
584 siter = siter->next;
585 break;
586 }
587 }
588
589 if (parent) {
590 siter = parent->next;
Michal Vasko9eb6dd02016-05-02 14:52:40 +0200591 if (lys_parent(parent) == schema) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200592 parent = NULL;
593 } else {
Michal Vasko84f821a2016-04-11 11:03:42 +0200594 parent = lys_parent(parent);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200595 }
596 goto repeat;
597 }
598
Michal Vasko84f821a2016-04-11 11:03:42 +0200599 return EXIT_SUCCESS;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200600}
601
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200602void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200603lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200604{
Radek Krejci76512572015-08-04 09:47:08 +0200605 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100606 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200608 if (!node) {
609 return;
610 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200612 /* unlink from data model if necessary */
613 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100614 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100615 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100616 if (main_module->data == node) {
617 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200618 }
619 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200621 /* store pointers to important nodes */
622 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200623 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200624 /* handle augments - first, unlink it from the augment parent ... */
625 if (parent->child == node) {
626 parent->child = node->next;
627 }
628 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200629 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200630 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200632 /* unlink from parent */
633 if (parent) {
634 if (parent->child == node) {
635 parent->child = node->next;
636 }
637 node->parent = NULL;
638 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200640 /* unlink from siblings */
641 if (node->prev == node) {
642 /* there are no more siblings */
643 return;
644 }
645 if (node->next) {
646 node->next->prev = node->prev;
647 } else {
648 /* unlinking the last element */
649 if (parent) {
650 first = parent->child;
651 } else {
652 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200653 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200654 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200655 }
656 }
657 first->prev = node->prev;
658 }
659 if (node->prev->next) {
660 node->prev->next = node->next;
661 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200663 /* clean up the unlinked element */
664 node->next = NULL;
665 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200666}
667
Michal Vasko563ef092015-09-04 13:17:23 +0200668struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100669lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200670{
671 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200672
673 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200674 /* top-level augment, look into module (uses augment is handled correctly below) */
675 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
676 par_iter = par_iter->parent->module->data;
677 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200678 break;
679 }
680 }
681
Michal Vasko6f929da2015-10-02 16:23:25 +0200682 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200683 continue;
684 }
685
686 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
687 if (!stop) {
688 stop = par_iter;
689 } else if (iter == stop) {
690 break;
691 }
692 if (iter->nodetype != LYS_GROUPING) {
693 continue;
694 }
695
Radek Krejcif8426a72015-10-31 23:14:03 +0100696 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200697 return (struct lys_node_grp *)iter;
698 }
699 }
700 }
701
Michal Vasko563ef092015-09-04 13:17:23 +0200702 return NULL;
703}
704
Radek Krejci10c760e2015-08-14 14:45:43 +0200705/*
706 * get next grouping in the root's subtree, in the
707 * first call, tha last is NULL
708 */
709static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200710lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200711{
Radek Krejci10c760e2015-08-14 14:45:43 +0200712 struct lys_node *last = (struct lys_node *)lastgrp;
713 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200714
Radek Krejci10c760e2015-08-14 14:45:43 +0200715 assert(root);
716
717 if (!last) {
718 last = root;
719 }
720
721 while (1) {
722 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
723 next = last->child;
724 } else {
725 next = NULL;
726 }
727 if (!next) {
728 if (last == root) {
729 /* we are done */
730 return NULL;
731 }
732
733 /* no children, go to siblings */
734 next = last->next;
735 }
736 while (!next) {
737 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100738 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200739 /* we are done */
740 return NULL;
741 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200742 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100743 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200744 }
745
746 if (next->nodetype == LYS_GROUPING) {
747 return (struct lys_node_grp *)next;
748 }
749
750 last = next;
751 }
752}
753
Michal Vasko0d343d12015-08-24 14:57:36 +0200754/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200755int
Radek Krejci07911992015-08-14 15:13:31 +0200756lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
757{
Michal Vasko563ef092015-09-04 13:17:23 +0200758 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200759 struct lys_node_grp *grp;
760 int down;
761
762 assert(node);
763
764 if (!parent) {
765 assert(module);
766 } else {
767 module = parent->module;
768 }
769
770 switch (node->nodetype) {
771 case LYS_GROUPING:
772 /* 6.2.1, rule 6 */
773 if (parent) {
774 if (parent->child) {
775 down = 1;
776 start = parent->child;
777 } else {
778 down = 0;
779 start = parent;
780 }
781 } else {
782 down = 1;
783 start = module->data;
784 }
785 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100786 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100787 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200788 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200789 }
790 /* go down, because grouping can be defined after e.g. container in which is collision */
791 if (down) {
792 for (iter = start, stop = NULL; iter; iter = iter->prev) {
793 if (!stop) {
794 stop = start;
795 } else if (iter == stop) {
796 break;
797 }
798 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
799 continue;
800 }
801
802 grp = NULL;
803 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100804 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100805 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200806 return EXIT_FAILURE;
807 }
808 }
809 }
810 }
811 break;
812 case LYS_LEAF:
813 case LYS_LEAFLIST:
814 case LYS_LIST:
815 case LYS_CONTAINER:
816 case LYS_CHOICE:
817 case LYS_ANYXML:
818 /* 6.2.1, rule 7 */
819 if (parent) {
820 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200821 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
822 if (iter->nodetype == LYS_AUGMENT) {
823 if (((struct lys_node_augment *)iter)->target) {
824 /* augment is resolved, go up */
825 iter = ((struct lys_node_augment *)iter)->target;
826 continue;
827 }
828 /* augment is not resolved, this is the final parent */
829 break;
830 }
Radek Krejci07911992015-08-14 15:13:31 +0200831 iter = iter->parent;
832 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200833
Radek Krejci07911992015-08-14 15:13:31 +0200834 if (!iter) {
835 stop = NULL;
836 iter = module->data;
837 } else {
838 stop = iter;
839 iter = iter->child;
840 }
841 } else {
842 stop = NULL;
843 iter = module->data;
844 }
845 while (iter) {
846 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
847 iter = iter->child;
848 continue;
849 }
850
851 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100852 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100853 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200854 return EXIT_FAILURE;
855 }
856 }
857
858 /* special case for choice - we must check the choice's name as
859 * well as the names of nodes under the choice
860 */
861 if (iter->nodetype == LYS_CHOICE) {
862 iter = iter->child;
863 continue;
864 }
865
866 /* go to siblings */
867 if (!iter->next) {
868 /* no sibling, go to parent's sibling */
869 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200870 /* for parent LYS_AUGMENT */
871 if (iter->parent == stop) {
872 iter = stop;
873 break;
874 }
875 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200876 if (iter && iter->next) {
877 break;
878 }
879 } while (iter != stop);
880
881 if (iter == stop) {
882 break;
883 }
884 }
885 iter = iter->next;
886 }
887 break;
888 case LYS_CASE:
889 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100890 if (parent) {
891 start = parent->child;
892 } else {
893 start = module->data;
894 }
895
896 LY_TREE_FOR(start, iter) {
Radek Krejci07911992015-08-14 15:13:31 +0200897 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
898 continue;
899 }
900
Radek Krejci749190d2016-02-18 16:26:25 +0100901 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100902 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200903 return EXIT_FAILURE;
904 }
905 }
906 break;
907 default:
908 /* no check needed */
909 break;
910 }
911
912 return EXIT_SUCCESS;
913}
914
Michal Vasko0d343d12015-08-24 14:57:36 +0200915/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200916int
Radek Krejci10c760e2015-08-14 14:45:43 +0200917lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
918{
Radek Krejci92720552015-10-05 15:28:27 +0200919 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200920 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200922 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200923
Radek Krejci10c760e2015-08-14 14:45:43 +0200924 if (parent) {
925 type = parent->nodetype;
926 module = parent->module;
927 } else {
928 assert(module);
929 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200930 }
931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200932 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200933 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200934 case LYS_CONTAINER:
935 case LYS_LIST:
936 case LYS_GROUPING:
937 case LYS_USES:
938 case LYS_INPUT:
939 case LYS_OUTPUT:
940 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200941 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200942 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
943 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100944 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200945 return EXIT_FAILURE;
946 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200948 break;
Radek Krejci76512572015-08-04 09:47:08 +0200949 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200951 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100952 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200953 return EXIT_FAILURE;
954 }
955 break;
Radek Krejci76512572015-08-04 09:47:08 +0200956 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200957 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200958 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100959 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200960 return EXIT_FAILURE;
961 }
962 break;
Radek Krejci76512572015-08-04 09:47:08 +0200963 case LYS_RPC:
964 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100965 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200966 return EXIT_FAILURE;
967 }
968 break;
Radek Krejci76512572015-08-04 09:47:08 +0200969 case LYS_LEAF:
970 case LYS_LEAFLIST:
971 case LYS_ANYXML:
Radek Krejci48464ed2016-03-17 15:44:09 +0100972 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
973 LOGVAL(LYE_SPEC, LY_VLOG_LYS, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100974 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200975 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200976 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200977 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200978 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
979 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100980 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200981 return EXIT_FAILURE;
982 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200983 break;
984 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200985 /* top level */
986 if (!(child->nodetype &
987 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
988 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100989 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200990 return EXIT_FAILURE;
991 }
992
Radek Krejcic071c542016-01-27 14:57:51 +0100993 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200994 }
995
996 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200997 if (lys_check_id(child, parent, module)) {
998 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200999 }
Radek Krejcib7155b52015-06-10 17:03:01 +02001000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001001 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001002 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001003 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001004
Radek Krejci10c760e2015-08-14 14:45:43 +02001005 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +02001006 if (module->data) {
1007 module->data->prev->next = child;
1008 child->prev = module->data->prev;
1009 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001010 } else {
Radek Krejci92720552015-10-05 15:28:27 +02001011 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001012 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001013 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +02001014 if (!parent->child) {
1015 /* the only/first child of the parent */
1016 parent->child = child;
1017 child->parent = parent;
1018 iter = child;
1019 } else {
1020 /* add a new child at the end of parent's child list */
1021 iter = parent->child->prev;
1022 iter->next = child;
1023 child->prev = iter;
1024 }
1025 while (iter->next) {
1026 iter = iter->next;
1027 iter->parent = parent;
1028 }
1029 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001030 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001031
Radek Krejci41771502016-04-14 17:52:32 +02001032 /* propagate information about status data presence */
1033 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML)) &&
1034 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +02001035 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +02001036 /* store it only into container or list - the only data inner nodes */
1037 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
1038 if (iter->flags & LYS_INCL_STATUS) {
1039 /* done, someone else set it already from here */
1040 break;
1041 }
1042 /* set flag about including status data */
1043 iter->flags |= LYS_INCL_STATUS;
1044 }
1045 }
1046 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001047 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001048}
1049
Radek Krejcia1df1682016-04-11 14:56:59 +02001050static const struct lys_module *
1051lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001052{
Radek Krejcia1df1682016-04-11 14:56:59 +02001053 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001054 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +02001055 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001057 if (!ctx || !data) {
1058 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1059 return NULL;
1060 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001061
Radek Krejcia1df1682016-04-11 14:56:59 +02001062 if (!internal && format == LYS_IN_YANG) {
1063 /* enlarge data by 2 bytes for flex */
1064 len = strlen(data);
1065 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
1066 if (!enlarged_data) {
1067 LOGMEM;
1068 return NULL;
1069 }
1070 memcpy(enlarged_data, data, len);
1071 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1072 data = enlarged_data;
1073 }
1074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001075 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001076 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +01001077 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001078 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001079 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001080 mod = yang_read_module(ctx, data, 0, NULL, 1);
1081 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001082 default:
Radek Krejcia1df1682016-04-11 14:56:59 +02001083 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001084 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001085 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001086
Radek Krejcia1df1682016-04-11 14:56:59 +02001087 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001088 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001089}
1090
Radek Krejcia1df1682016-04-11 14:56:59 +02001091API const struct lys_module *
1092lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
1093{
1094 return lys_parse_mem_(ctx, data, format, 0);
1095}
1096
Michal Vasko5a721fd2016-02-16 12:16:48 +01001097struct lys_submodule *
1098lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001099{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001100 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001102 assert(module);
1103 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001104
Radek Krejcic071c542016-01-27 14:57:51 +01001105 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +02001106 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001107
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001108 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001109 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001110 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001111 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001112 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001113 submod = yang_read_submodule(module, data, 0, unres);
1114 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001115 default:
Radek Krejci90a550a2016-04-13 16:00:58 +02001116 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001117 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001118 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001119
Michal Vasko5a721fd2016-02-16 12:16:48 +01001120 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001121}
1122
Michal Vasko1e62a092015-12-01 12:27:20 +01001123API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001124lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1125{
1126 int fd;
1127 const struct lys_module *ret;
1128
1129 if (!ctx || !path) {
1130 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1131 return NULL;
1132 }
1133
1134 fd = open(path, O_RDONLY);
1135 if (fd == -1) {
1136 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1137 return NULL;
1138 }
1139
1140 ret = lys_parse_fd(ctx, fd, format);
1141 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +01001142
Radek Krejcia77904e2016-02-25 16:23:45 +01001143 if (ret && !ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001144 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +01001145 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +01001146 }
1147
Michal Vasko662610a2015-12-07 11:25:45 +01001148 return ret;
1149}
1150
1151API const struct lys_module *
1152lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001153{
Michal Vasko1e62a092015-12-01 12:27:20 +01001154 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001155 struct stat sb;
1156 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001157 char buf[PATH_MAX];
1158 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001159
1160 if (!ctx || fd < 0) {
1161 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1162 return NULL;
1163 }
1164
Radek Krejci10a833c2015-12-16 15:28:37 +01001165 if (fstat(fd, &sb) == -1) {
1166 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1167 return NULL;
1168 }
Radek Krejcib051f722016-02-25 15:12:21 +01001169 if (!S_ISREG(sb.st_mode)) {
1170 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
1171 return NULL;
1172 }
1173
Michal Vasko164d9012016-04-01 10:16:59 +02001174 if (!sb.st_size) {
1175 LOGERR(LY_EINVAL, "File empty.");
1176 return NULL;
1177 }
1178
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001179 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001180 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001181 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001182 return NULL;
1183 }
Radek Krejcia1df1682016-04-11 14:56:59 +02001184 module = lys_parse_mem_(ctx, addr, format, 1);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001185 munmap(addr, sb.st_size + 2);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001186
Radek Krejcia77904e2016-02-25 16:23:45 +01001187 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001188 /* get URI if there is /proc */
1189 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001190 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1191 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1192 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1193 }
1194 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001195 }
Radek Krejcib051f722016-02-25 15:12:21 +01001196 }
1197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001198 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001199}
1200
Michal Vasko5a721fd2016-02-16 12:16:48 +01001201struct lys_submodule *
1202lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001203{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001204 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001205 struct stat sb;
1206 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001207
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001208 assert(module);
1209 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001210
Radek Krejci10a833c2015-12-16 15:28:37 +01001211 if (fstat(fd, &sb) == -1) {
1212 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001213 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001214 }
Michal Vasko164d9012016-04-01 10:16:59 +02001215
1216 if (!sb.st_size) {
1217 LOGERR(LY_EINVAL, "File empty.");
1218 return NULL;
1219 }
1220
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001221 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001222 if (addr == MAP_FAILED) {
1223 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001224 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001225 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001226 submodule = lys_submodule_parse(module, addr, format, unres);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001227 munmap(addr, sb.st_size + 2);
Radek Krejciefaeba32015-05-27 14:30:57 +02001228
Michal Vasko5a721fd2016-02-16 12:16:48 +01001229 return submodule;
1230
Radek Krejciefaeba32015-05-27 14:30:57 +02001231}
1232
Radek Krejci1d82ef62015-08-07 14:44:40 +02001233static struct lys_restr *
1234lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001235{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001236 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001237 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001238
Radek Krejci3733a802015-06-19 13:43:21 +02001239 if (!size) {
1240 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001241 }
Radek Krejci3733a802015-06-19 13:43:21 +02001242
1243 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001244 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001245 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001246 return NULL;
1247 }
Radek Krejci3733a802015-06-19 13:43:21 +02001248 for (i = 0; i < size; i++) {
1249 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1250 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1251 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1252 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1253 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1254 }
1255
1256 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001257}
1258
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001259void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001260lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001261{
1262 assert(ctx);
1263 if (!restr) {
1264 return;
1265 }
1266
1267 lydict_remove(ctx, restr->expr);
1268 lydict_remove(ctx, restr->dsc);
1269 lydict_remove(ctx, restr->ref);
1270 lydict_remove(ctx, restr->eapptag);
1271 lydict_remove(ctx, restr->emsg);
1272}
1273
Michal Vaskob84f88a2015-09-24 13:16:10 +02001274static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001275type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
1276 LY_DATA_TYPE base, struct unres_schema *unres)
1277{
1278 int i;
1279
1280 switch (base) {
1281 case LY_TYPE_BINARY:
1282 if (old->info.binary.length) {
1283 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
1284 }
1285 break;
1286
1287 case LY_TYPE_BITS:
1288 new->info.bits.count = old->info.bits.count;
1289 if (new->info.bits.count) {
1290 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1291 if (!new->info.bits.bit) {
1292 LOGMEM;
1293 return -1;
1294 }
1295 for (i = 0; i < new->info.bits.count; i++) {
1296 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1297 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1298 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1299 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1300 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1301 }
1302 }
1303 break;
1304
1305 case LY_TYPE_DEC64:
1306 new->info.dec64.dig = old->info.dec64.dig;
1307 if (old->info.dec64.range) {
1308 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
1309 }
1310 break;
1311
1312 case LY_TYPE_ENUM:
1313 new->info.enums.count = old->info.enums.count;
1314 if (new->info.enums.count) {
1315 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1316 if (!new->info.enums.enm) {
1317 LOGMEM;
1318 return -1;
1319 }
1320 for (i = 0; i < new->info.enums.count; i++) {
1321 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1322 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1323 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1324 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1325 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
1326 }
1327 }
1328 break;
1329
1330 case LY_TYPE_IDENT:
1331 if (old->info.ident.ref) {
1332 new->info.ident.ref = old->info.ident.ref;
1333 } else {
1334 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
1335 if (i > -1 && unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i])) {
1336 return -1;
1337 }
1338 }
1339 break;
1340
1341 case LY_TYPE_INST:
1342 new->info.inst.req = old->info.inst.req;
1343 break;
1344
1345 case LY_TYPE_INT8:
1346 case LY_TYPE_INT16:
1347 case LY_TYPE_INT32:
1348 case LY_TYPE_INT64:
1349 case LY_TYPE_UINT8:
1350 case LY_TYPE_UINT16:
1351 case LY_TYPE_UINT32:
1352 case LY_TYPE_UINT64:
1353 if (old->info.num.range) {
1354 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
1355 }
1356 break;
1357
1358 case LY_TYPE_LEAFREF:
1359 if (old->info.lref.path) {
1360 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
1361 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent)) {
1362 return -1;
1363 }
1364 }
1365 break;
1366
1367 case LY_TYPE_STRING:
1368 if (old->info.str.length) {
1369 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
1370 }
1371 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
1372 new->info.str.pat_count = old->info.str.pat_count;
1373 break;
1374
1375 case LY_TYPE_UNION:
1376 new->info.uni.count = old->info.uni.count;
1377 if (new->info.uni.count) {
1378 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1379 if (!new->info.uni.types) {
1380 LOGMEM;
1381 return -1;
1382 }
1383 for (i = 0; i < new->info.uni.count; i++) {
1384 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1385 return -1;
1386 }
1387 }
1388 }
1389 break;
1390
1391 default:
1392 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1393 break;
1394 }
1395 return EXIT_SUCCESS;
1396}
1397
1398struct yang_type *
1399lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type, struct unres_schema *unres)
1400{
1401 struct yang_type *new;
1402
1403 new = calloc(1, sizeof *new);
1404 if (!new) {
1405 LOGMEM;
1406 return NULL;
1407 }
1408 new->flags = old->flags;
1409 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001410 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001411 new->type = type;
1412 if (!new->name) {
1413 LOGMEM;
1414 goto error;
1415 }
1416 if (type_dup(module, parent, type, old->type, new->base, unres)) {
1417 new->type->base = new->base;
1418 lys_type_free(module->ctx, new->type);
1419 memset(&new->type->info, 0, sizeof new->type->info);
1420 goto error;
1421 }
1422 return new;
1423
1424 error:
1425 free(new);
1426 return NULL;
1427}
1428
1429static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001430lys_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 +02001431 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001432{
1433 int i;
1434
Michal Vasko1dca6882015-10-22 14:29:42 +02001435 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001436 new->base = old->base;
1437 new->der = old->der;
1438
Michal Vasko0bd29d12015-08-19 11:45:49 +02001439 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001440 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001441 /* HACK (serious one) for unres */
1442 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001443 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
1444 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, unres);
1445 } else {
1446 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1447 }
Radek Krejcic071c542016-01-27 14:57:51 +01001448 new->parent = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001449 /* all these unres additions can fail even though they did not before */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001450 if (!new->der || unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001451 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001452 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001453 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001454 }
1455
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001456 return type_dup(mod, parent, new, old, new->base, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001457}
1458
1459void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001460lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001461{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001462 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001463
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001464 assert(ctx);
1465 if (!type) {
1466 return;
1467 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001468
Michal Vasko1dca6882015-10-22 14:29:42 +02001469 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001471 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001472 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001473 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001474 free(type->info.binary.length);
1475 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001476 case LY_TYPE_BITS:
1477 for (i = 0; i < type->info.bits.count; i++) {
1478 lydict_remove(ctx, type->info.bits.bit[i].name);
1479 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1480 lydict_remove(ctx, type->info.bits.bit[i].ref);
1481 }
1482 free(type->info.bits.bit);
1483 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001484
1485 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001486 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001487 free(type->info.dec64.range);
1488 break;
1489
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001490 case LY_TYPE_ENUM:
1491 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001492 lydict_remove(ctx, type->info.enums.enm[i].name);
1493 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1494 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001495 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001496 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001497 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001498
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001499 case LY_TYPE_INT8:
1500 case LY_TYPE_INT16:
1501 case LY_TYPE_INT32:
1502 case LY_TYPE_INT64:
1503 case LY_TYPE_UINT8:
1504 case LY_TYPE_UINT16:
1505 case LY_TYPE_UINT32:
1506 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001507 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001508 free(type->info.num.range);
1509 break;
1510
Radek Krejcidc4c1412015-06-19 15:39:54 +02001511 case LY_TYPE_LEAFREF:
1512 lydict_remove(ctx, type->info.lref.path);
1513 break;
1514
Radek Krejci3733a802015-06-19 13:43:21 +02001515 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001516 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001517 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001518 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001519 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001520 }
1521 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001522 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001523
Radek Krejcie4c366b2015-07-02 10:11:31 +02001524 case LY_TYPE_UNION:
1525 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001526 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001527 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001528 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001529 break;
1530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001531 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001532 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001533 break;
1534 }
Radek Krejci5a065542015-05-22 15:02:07 +02001535}
1536
Radek Krejci1d82ef62015-08-07 14:44:40 +02001537static void
1538lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001539{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001540 assert(ctx);
1541 if (!tpdf) {
1542 return;
1543 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001544
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001545 lydict_remove(ctx, tpdf->name);
1546 lydict_remove(ctx, tpdf->dsc);
1547 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001548
Radek Krejci1d82ef62015-08-07 14:44:40 +02001549 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001550
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001551 lydict_remove(ctx, tpdf->units);
1552 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001553}
1554
Michal Vaskob84f88a2015-09-24 13:16:10 +02001555static struct lys_tpdf *
1556lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1557{
1558 struct lys_tpdf *result;
1559 int i, j;
1560
1561 if (!size) {
1562 return NULL;
1563 }
1564
1565 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001566 if (!result) {
1567 LOGMEM;
1568 return NULL;
1569 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001570 for (i = 0; i < size; i++) {
1571 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1572 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1573 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1574 result[i].flags = old[i].flags;
1575 result[i].module = old[i].module;
1576
1577 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1578 for (j = 0; j <= i; ++j) {
1579 lys_tpdf_free(mod->ctx, &result[j]);
1580 }
1581 free(result);
1582 return NULL;
1583 }
1584
1585 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1586 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1587 }
1588
1589 return result;
1590}
1591
Radek Krejci1d82ef62015-08-07 14:44:40 +02001592static struct lys_when *
1593lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001594{
Radek Krejci76512572015-08-04 09:47:08 +02001595 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001596
1597 if (!old) {
1598 return NULL;
1599 }
1600
1601 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001602 if (!new) {
1603 LOGMEM;
1604 return NULL;
1605 }
Radek Krejci00768f42015-06-18 17:04:04 +02001606 new->cond = lydict_insert(ctx, old->cond, 0);
1607 new->dsc = lydict_insert(ctx, old->dsc, 0);
1608 new->ref = lydict_insert(ctx, old->ref, 0);
1609
1610 return new;
1611}
1612
Michal Vasko0308dd62015-10-07 09:14:40 +02001613void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001614lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001615{
1616 if (!w) {
1617 return;
1618 }
1619
1620 lydict_remove(ctx, w->cond);
1621 lydict_remove(ctx, w->dsc);
1622 lydict_remove(ctx, w->ref);
1623
1624 free(w);
1625}
1626
Radek Krejcib7f5e412015-08-13 10:15:51 +02001627static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001628lys_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 +02001629{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001630 struct lys_node *next, *sub;
1631
Radek Krejcic071c542016-01-27 14:57:51 +01001632 /* children from a resolved augment are freed under the target node */
Michal Vaskod2fbade2016-05-02 17:14:00 +02001633 if (!aug->target) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001634 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001635 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001636 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001637 }
1638
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001639 lydict_remove(ctx, aug->target_name);
1640 lydict_remove(ctx, aug->dsc);
1641 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001642
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001643 free(aug->features);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001644
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001645 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001646}
1647
Radek Krejci76512572015-08-04 09:47:08 +02001648static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001649lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001650{
Radek Krejci76512572015-08-04 09:47:08 +02001651 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001652 struct lys_node *old_child, *new_child;
1653 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001655 if (!size) {
1656 return NULL;
1657 }
Radek Krejci106efc02015-06-10 14:36:27 +02001658
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001659 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001660 if (!new) {
1661 LOGMEM;
1662 return NULL;
1663 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001664 for (i = 0; i < size; i++) {
1665 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1666 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1667 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1668 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001669 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001670 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001671
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001672 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001673 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1674 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001675 LOGINT;
1676 free(new);
1677 return NULL;
1678 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001679 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001680
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001681 /* Correct the augment nodes.
1682 * This function can only be called from lys_node_dup() with uses
1683 * being the node duplicated, so we must have a case of grouping
1684 * with a uses with augments. The augmented nodes have already been
1685 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001686 * (it was set to their actual data parent, not an augment), and
1687 * the new augment does not have child pointer to its augment nodes,
1688 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001689 */
1690 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001691 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001692 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001693 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001694 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001695 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001696 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001697 LY_TREE_FOR(old[i].child, old_child) {
1698 /* all augment nodes were connected as siblings, there can be no more after this */
1699 if (old_child->parent != (struct lys_node *)&old[i]) {
1700 break;
1701 }
1702
Radek Krejci749190d2016-02-18 16:26:25 +01001703 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001704
1705 new_child->parent = (struct lys_node *)&new[i];
1706 new_child = new_child->next;
1707 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001708 }
Radek Krejci106efc02015-06-10 14:36:27 +02001709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001710 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001711}
1712
Radek Krejci76512572015-08-04 09:47:08 +02001713static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001714lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001715{
Radek Krejci76512572015-08-04 09:47:08 +02001716 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001717 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001718
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001719 if (!size) {
1720 return NULL;
1721 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001722
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001723 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001724 if (!result) {
1725 LOGMEM;
1726 return NULL;
1727 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001728 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001729 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001730 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1731 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001732 result[i].flags = old[i].flags;
1733 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001734
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001735 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001736 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001737
Radek Krejci76512572015-08-04 09:47:08 +02001738 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001739 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001740 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001741 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001742 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001743 result[i].mod.list = old[i].mod.list;
1744 }
1745 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001746
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001747 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001748}
1749
Radek Krejci1d82ef62015-08-07 14:44:40 +02001750static void
1751lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001752{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001753 assert(ctx);
1754 if (!ident) {
1755 return;
1756 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001757
Radek Krejci1b61d0e2016-04-15 13:55:44 +02001758 free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001759 lydict_remove(ctx, ident->name);
1760 lydict_remove(ctx, ident->dsc);
1761 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001762
1763}
1764
Radek Krejci1d82ef62015-08-07 14:44:40 +02001765static void
1766lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001767{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001768 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001769
Radek Krejcid12f57b2015-08-06 10:43:39 +02001770 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001771 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001772 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001773 }
1774 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001775}
1776
Radek Krejci1d82ef62015-08-07 14:44:40 +02001777static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001778lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1779{
1780 int i;
1781
1782 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1783 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001784 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001785 }
1786 free(io->tpdf);
1787}
1788
Radek Krejci1d82ef62015-08-07 14:44:40 +02001789static void
1790lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001791{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001792 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001793
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001794 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001795 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 }
1797 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001798
Radek Krejci1d82ef62015-08-07 14:44:40 +02001799 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001800}
1801
Radek Krejci1d82ef62015-08-07 14:44:40 +02001802static void
1803lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001804{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001805 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001806
Radek Krejci46c4cd72016-01-21 15:13:52 +01001807 if (leaf->child) {
1808 /* leafref backlinks */
1809 ly_set_free((struct ly_set *)leaf->child);
1810 }
1811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001812 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001813 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001814 }
1815 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001816
Radek Krejci1d82ef62015-08-07 14:44:40 +02001817 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001818
Radek Krejci1d82ef62015-08-07 14:44:40 +02001819 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001820 lydict_remove(ctx, leaf->units);
1821 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001822}
1823
Radek Krejci1d82ef62015-08-07 14:44:40 +02001824static void
1825lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001826{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001827 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001828
Radek Krejci46c4cd72016-01-21 15:13:52 +01001829 if (llist->child) {
1830 /* leafref backlinks */
1831 ly_set_free((struct ly_set *)llist->child);
1832 }
1833
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001834 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001835 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001836 }
1837 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001838
Radek Krejci1d82ef62015-08-07 14:44:40 +02001839 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001840
Radek Krejci1d82ef62015-08-07 14:44:40 +02001841 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001842 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001843}
1844
Radek Krejci1d82ef62015-08-07 14:44:40 +02001845static void
1846lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001847{
Radek Krejci581ce772015-11-10 17:22:40 +01001848 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001850 /* handle only specific parts for LY_NODE_LIST */
1851 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001852 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001853 }
1854 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001855
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001856 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001857 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001858 }
1859 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001860
Radek Krejci1d82ef62015-08-07 14:44:40 +02001861 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001863 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001864 for (j = 0; j > list->unique[i].expr_size; j++) {
1865 lydict_remove(ctx, list->unique[i].expr[j]);
1866 }
1867 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001868 }
1869 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001871 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001872}
1873
Radek Krejci1d82ef62015-08-07 14:44:40 +02001874static void
1875lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001876{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001877 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001879 /* handle only specific parts for LY_NODE_CONTAINER */
1880 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001882 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001883 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001884 }
1885 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001887 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001888 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001889 }
1890 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001891
Radek Krejci1d82ef62015-08-07 14:44:40 +02001892 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001893}
1894
Radek Krejci1d82ef62015-08-07 14:44:40 +02001895static void
1896lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001897{
1898 lydict_remove(ctx, f->name);
1899 lydict_remove(ctx, f->dsc);
1900 lydict_remove(ctx, f->ref);
1901 free(f->features);
1902}
1903
Radek Krejci1d82ef62015-08-07 14:44:40 +02001904static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001905lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001906{
Radek Krejci581ce772015-11-10 17:22:40 +01001907 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001908 struct ly_ctx *ctx;
1909 struct lys_node *next, *elem;
1910
1911 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001912
1913 lydict_remove(ctx, dev->target_name);
1914 lydict_remove(ctx, dev->dsc);
1915 lydict_remove(ctx, dev->ref);
1916
Michal Vaskoff006c12016-02-17 11:15:19 +01001917 /* the module was freed, but we only need the context from orig_node, use ours */
1918 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1919 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1920 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1921 elem->module = module;
1922
1923 LY_TREE_DFS_END(dev->orig_node, next, elem);
1924 }
1925 lys_node_free(dev->orig_node, NULL, 0);
1926 } else {
1927 /* it's just a shallow copy, freeing one node */
1928 dev->orig_node->module = module;
1929 lys_node_free(dev->orig_node, NULL, 1);
1930 }
1931
Radek Krejcieb00f512015-07-01 16:44:58 +02001932 for (i = 0; i < dev->deviate_size; i++) {
1933 lydict_remove(ctx, dev->deviate[i].dflt);
1934 lydict_remove(ctx, dev->deviate[i].units);
1935
1936 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1937 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001938 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001939 }
1940 free(dev->deviate[i].must);
1941
1942 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001943 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1944 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1945 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01001946 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001947 }
1948 free(dev->deviate[i].unique);
1949 }
1950 }
1951 free(dev->deviate);
1952}
1953
Radek Krejci1d82ef62015-08-07 14:44:40 +02001954static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001955lys_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 +02001956{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001957 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001958
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001959 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001960 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001961 lydict_remove(ctx, uses->refine[i].dsc);
1962 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001963
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001964 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001965 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001966 }
1967 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001968
Radek Krejci76512572015-08-04 09:47:08 +02001969 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001970 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001971 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001972 lydict_remove(ctx, uses->refine[i].mod.presence);
1973 }
1974 }
1975 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001977 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001978 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001979 }
1980 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001981
Radek Krejci1d82ef62015-08-07 14:44:40 +02001982 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001983}
1984
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001985void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001986lys_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 +02001987{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001988 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001989 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001990
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001991 if (!node) {
1992 return;
1993 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001994
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001995 assert(node->module);
1996 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001997
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001998 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001999
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002000 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002001 if (node->priv && private_destructor) {
2002 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002003 }
2004
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002005 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002006 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002007 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
2008 free(node->features);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002009 lydict_remove(ctx, node->dsc);
2010 lydict_remove(ctx, node->ref);
2011 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002012
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002013 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002014 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002015 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002016 }
2017 }
2018
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002019 /* specific part */
2020 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002021 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002022 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002023 break;
Radek Krejci76512572015-08-04 09:47:08 +02002024 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002025 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002026 break;
Radek Krejci76512572015-08-04 09:47:08 +02002027 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002028 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002029 break;
Radek Krejci76512572015-08-04 09:47:08 +02002030 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002031 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002032 break;
Radek Krejci76512572015-08-04 09:47:08 +02002033 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002034 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002035 break;
Radek Krejci76512572015-08-04 09:47:08 +02002036 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002037 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002038 break;
Radek Krejci76512572015-08-04 09:47:08 +02002039 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002040 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002041 break;
Radek Krejci76512572015-08-04 09:47:08 +02002042 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002043 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002044 break;
Radek Krejci76512572015-08-04 09:47:08 +02002045 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002046 /* do nothing */
2047 break;
Radek Krejci76512572015-08-04 09:47:08 +02002048 case LYS_GROUPING:
2049 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02002050 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002051 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002052 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002053
2054 case LYS_INPUT:
2055 case LYS_OUTPUT:
2056 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
2057 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02002058 case LYS_UNKNOWN:
2059 LOGINT;
2060 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002061 }
Radek Krejci5a065542015-05-22 15:02:07 +02002062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002063 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002064 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002065 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002066}
2067
Michal Vasko1e62a092015-12-01 12:27:20 +01002068const struct lys_module *
2069lys_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 +02002070{
Radek Krejcic071c542016-01-27 14:57:51 +01002071 const struct lys_module *main_module;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002072 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002073
Michal Vaskoa7789a82016-02-11 15:42:55 +01002074 assert(!prefix || !name);
2075
Michal Vaskob6729c62015-10-21 12:09:47 +02002076 if (prefix && !pref_len) {
2077 pref_len = strlen(prefix);
2078 }
2079 if (name && !name_len) {
2080 name_len = strlen(name);
2081 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002082
Radek Krejcic4283442016-04-22 09:19:27 +02002083 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002084
2085 /* module own prefix, submodule own prefix, (sub)module own name */
2086 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2087 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002088 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002089 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002090 }
2091
Michal Vasko8ce24d72015-10-21 11:27:26 +02002092 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002093 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2094 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002095 return module->imp[i].module;
2096 }
2097 }
2098
2099 return NULL;
2100}
2101
Michal Vasko13b15832015-08-19 11:04:48 +02002102/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002104module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002105{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002106 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002107 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002108 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002109
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002110 assert(module->ctx);
2111 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002112
Michal Vaskob746fff2016-02-11 11:37:50 +01002113 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002114 for (i = 0; i < module->imp_size; i++) {
Radek Krejci4f78b532016-02-17 13:43:00 +01002115 if (!module->imp[i].external) {
2116 lydict_remove(ctx, module->imp[i].prefix);
2117 }
Radek Krejci225376f2016-02-16 17:36:22 +01002118 }
Radek Krejcidce51452015-06-16 15:20:08 +02002119 free(module->imp);
2120
Radek Krejcic071c542016-01-27 14:57:51 +01002121 /* submodules don't have data tree, the data nodes
2122 * are placed in the main module altogether */
2123 if (!module->type) {
2124 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002125 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002126 }
Radek Krejci21181962015-06-30 14:11:00 +02002127 }
Radek Krejci5a065542015-05-22 15:02:07 +02002128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 lydict_remove(ctx, module->dsc);
2130 lydict_remove(ctx, module->ref);
2131 lydict_remove(ctx, module->org);
2132 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002133 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002134
Radek Krejcieb00f512015-07-01 16:44:58 +02002135 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 for (i = 0; i < module->rev_size; i++) {
2137 lydict_remove(ctx, module->rev[i].dsc);
2138 lydict_remove(ctx, module->rev[i].ref);
2139 }
2140 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002141
Radek Krejcieb00f512015-07-01 16:44:58 +02002142 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002144 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002145 }
2146 module->ident_size = 0;
2147 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002148
Radek Krejcieb00f512015-07-01 16:44:58 +02002149 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002151 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002152 }
2153 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002154
Radek Krejcieb00f512015-07-01 16:44:58 +02002155 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 for (i = 0; i < module->inc_size; i++) {
Radek Krejcic071c542016-01-27 14:57:51 +01002157 /* complete submodule free is done only from main module since
2158 * submodules propagate their includes to the main module */
2159 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002160 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002161 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002162 }
2163 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002164
Radek Krejcieb00f512015-07-01 16:44:58 +02002165 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002166 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002167 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002168 }
2169 free(module->augment);
2170
Radek Krejcieb00f512015-07-01 16:44:58 +02002171 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002172 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002173 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002174 }
2175 free(module->features);
2176
Radek Krejcieb00f512015-07-01 16:44:58 +02002177 /* deviations */
2178 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002179 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002180 }
2181 free(module->deviation);
2182
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002183 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002184 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002185}
2186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187void
Michal Vaskob746fff2016-02-11 11:37:50 +01002188lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002189{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002190 if (!submodule) {
2191 return;
2192 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002195 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002200}
2201
Radek Krejci76512572015-08-04 09:47:08 +02002202struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002203lys_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 +01002204 uint8_t nacm, struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002205{
Radek Krejcic071c542016-01-27 14:57:51 +01002206 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002208 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002209
Michal Vaskoc07187d2015-08-13 15:20:57 +02002210 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002211 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002212 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002213 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002214 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002215 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002216 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002217 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002218 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002219 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002220 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002221 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002222 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002223 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002224 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002225 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002226 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002227 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002228 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002229 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002230 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002231 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002232 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002233 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002234
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 /* we cannot just duplicate memory since the strings are stored in
2236 * dictionary and we need to update dictionary counters.
2237 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002238
Radek Krejci1d82ef62015-08-07 14:44:40 +02002239 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002240 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002241 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002242 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002243 break;
2244
Radek Krejci76512572015-08-04 09:47:08 +02002245 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002247 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002248 break;
2249
Radek Krejci76512572015-08-04 09:47:08 +02002250 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002252 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 break;
2254
Radek Krejci76512572015-08-04 09:47:08 +02002255 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002257 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002258 break;
2259
Radek Krejci76512572015-08-04 09:47:08 +02002260 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002261 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002262 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002263 break;
2264
Radek Krejci76512572015-08-04 09:47:08 +02002265 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002266 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002267 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002268 break;
2269
Radek Krejci76512572015-08-04 09:47:08 +02002270 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002271 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002272 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002273 break;
2274
Radek Krejci76512572015-08-04 09:47:08 +02002275 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002276 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002277 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002278 break;
2279
Radek Krejci76512572015-08-04 09:47:08 +02002280 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002281 grp = calloc(1, sizeof *grp);
2282 retval = (struct lys_node *)grp;
2283 break;
2284
Radek Krejci76512572015-08-04 09:47:08 +02002285 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002286 rpc = calloc(1, sizeof *rpc);
2287 retval = (struct lys_node *)rpc;
2288 break;
2289
Radek Krejci76512572015-08-04 09:47:08 +02002290 case LYS_INPUT:
2291 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002292 io = calloc(1, sizeof *io);
2293 retval = (struct lys_node *)io;
2294 break;
2295
Radek Krejci76512572015-08-04 09:47:08 +02002296 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002297 ntf = calloc(1, sizeof *ntf);
2298 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002299 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002301 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002302 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002303 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 }
Radek Krejcib388c152015-06-04 17:03:03 +02002305
Michal Vasko253035f2015-12-17 16:58:13 +01002306 if (!retval) {
2307 LOGMEM;
2308 return NULL;
2309 }
2310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002311 /*
2312 * duplicate generic part of the structure
2313 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002314 retval->name = lydict_insert(ctx, node->name, 0);
2315 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2316 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002317 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002318 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002319 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002320 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002321 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002325 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002327 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002328
Radek Krejci1d82ef62015-08-07 14:44:40 +02002329 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002330 retval->features = calloc(retval->features_size, sizeof *retval->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002331 if (!retval->features) {
2332 LOGMEM;
2333 goto error;
2334 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002335
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002336 if (!shallow) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002337 for (i = 0; i < node->features_size; ++i) {
2338 retval->features[i] = (struct lys_feature *)retval;
2339 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
2340 retval->features[i] = node->features[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002341 }
2342 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002343
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002344 /* connect it to the parent */
2345 if (lys_node_addchild(parent, retval->module, retval)) {
2346 goto error;
2347 }
Radek Krejcidce51452015-06-16 15:20:08 +02002348
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002349 /* go recursively */
2350 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2351 LY_TREE_FOR(node->child, child) {
2352 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres, 0)) {
2353 goto error;
2354 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002355 }
2356 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002357 } else {
2358 memcpy(retval->features, node->features, retval->features_size * sizeof *retval->features);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002359 }
2360
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002361 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002362 * duplicate specific part of the structure
2363 */
2364 switch (node->nodetype) {
2365 case LYS_CONTAINER:
2366 if (cont_orig->when) {
2367 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002368 }
2369 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002371 cont->must_size = cont_orig->must_size;
2372 cont->tpdf_size = cont_orig->tpdf_size;
2373
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002374 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskodcf98e62016-05-05 17:53:53 +02002375 cont->tpdf = lys_tpdf_dup(module, lys_parent(node), cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002376 break;
2377
2378 case LYS_CHOICE:
2379 if (choice_orig->when) {
2380 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002381 }
2382
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002383 if (!shallow) {
2384 if (choice_orig->dflt) {
2385 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0, LYS_ANYXML
2386 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
2387 | LYS_LIST, (const struct lys_node **)&choice->dflt);
2388 if (rc) {
2389 if (rc == EXIT_FAILURE) {
2390 LOGINT;
2391 }
2392 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002393 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002394 } else {
2395 /* useless to check return value, we don't know whether
2396 * there really wasn't any default defined or it just hasn't
2397 * been resolved, we just hope for the best :)
2398 */
2399 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002400 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002401 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002402 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002403 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002404 break;
2405
2406 case LYS_LEAF:
Michal Vaskodcf98e62016-05-05 17:53:53 +02002407 if (lys_type_dup(module, lys_parent(node), &(leaf->type), &(leaf_orig->type), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002408 goto error;
2409 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002410 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2411
2412 if (leaf_orig->dflt) {
2413 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci48464ed2016-03-17 15:44:09 +01002414 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002415 goto error;
2416 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002417 }
2418
2419 leaf->must_size = leaf_orig->must_size;
2420 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002421
2422 if (leaf_orig->when) {
2423 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002424 }
2425 break;
2426
2427 case LYS_LEAFLIST:
Michal Vaskodcf98e62016-05-05 17:53:53 +02002428 if (lys_type_dup(module, lys_parent(node), &(llist->type), &(llist_orig->type), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002429 goto error;
2430 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002431 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2432
2433 llist->min = llist_orig->min;
2434 llist->max = llist_orig->max;
2435
2436 llist->must_size = llist_orig->must_size;
2437 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002438
2439 if (llist_orig->when) {
2440 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002441 }
2442 break;
2443
2444 case LYS_LIST:
2445 list->min = list_orig->min;
2446 list->max = list_orig->max;
2447
2448 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002449 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002450
Radek Krejci581ce772015-11-10 17:22:40 +01002451 list->tpdf_size = list_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002452 list->tpdf = lys_tpdf_dup(module, lys_parent(node), list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002453
Radek Krejci581ce772015-11-10 17:22:40 +01002454 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002455 if (list->keys_size) {
2456 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002457 if (!list->keys) {
2458 LOGMEM;
2459 goto error;
2460 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002461
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002462 if (!shallow) {
2463 /* we managed to resolve it before, resolve it again manually */
2464 if (list_orig->keys[0]) {
2465 for (i = 0; i < list->keys_size; ++i) {
2466 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2467 (const struct lys_node **)&list->keys[i]);
2468 if (rc) {
2469 if (rc == EXIT_FAILURE) {
2470 LOGINT;
2471 }
2472 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002473 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002474 }
2475 /* it was not resolved yet, add unres copy */
2476 } else {
2477 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2478 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002479 goto error;
2480 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002481 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002482 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002483 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002484 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002485 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002486
Radek Krejci581ce772015-11-10 17:22:40 +01002487 list->unique_size = list_orig->unique_size;
2488 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002489 if (!list->unique) {
2490 LOGMEM;
2491 goto error;
2492 }
Radek Krejci581ce772015-11-10 17:22:40 +01002493 for (i = 0; i < list->unique_size; ++i) {
2494 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2495 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002496 if (!list->unique[i].expr) {
2497 LOGMEM;
2498 goto error;
2499 }
Radek Krejci581ce772015-11-10 17:22:40 +01002500 for (j = 0; j < list->unique[i].expr_size; j++) {
2501 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2502
2503 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002504 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002505 }
2506 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002507
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002508 if (list_orig->when) {
2509 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002510 }
Radek Krejcidce51452015-06-16 15:20:08 +02002511 break;
2512
2513 case LYS_ANYXML:
2514 anyxml->must_size = anyxml_orig->must_size;
2515 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002516
2517 if (anyxml_orig->when) {
2518 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002519 }
2520 break;
2521
2522 case LYS_USES:
2523 uses->grp = uses_orig->grp;
2524
2525 if (uses_orig->when) {
2526 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002527 }
2528
2529 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002530 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002531 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002532 if (!shallow) {
2533 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
2534 if (!uses->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002535 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002536 goto error;
2537 }
Michal Vasko49168a22015-08-17 16:35:41 +02002538 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002539 } else {
2540 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002541 }
2542 break;
2543
Radek Krejcidce51452015-06-16 15:20:08 +02002544 case LYS_CASE:
2545 if (cs_orig->when) {
2546 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002547 }
2548 break;
2549
2550 case LYS_GROUPING:
2551 grp->tpdf_size = grp_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002552 grp->tpdf = lys_tpdf_dup(module, lys_parent(node), grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002553 break;
2554
2555 case LYS_RPC:
2556 rpc->tpdf_size = rpc_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002557 rpc->tpdf = lys_tpdf_dup(module, lys_parent(node), rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002558 break;
2559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002560 case LYS_INPUT:
2561 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002562 io->tpdf_size = io_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002563 io->tpdf = lys_tpdf_dup(module, lys_parent(node), io_orig->tpdf, io->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 break;
2565
Radek Krejcida04f4a2015-05-21 12:54:09 +02002566 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002567 ntf->tpdf_size = ntf_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002568 ntf->tpdf = lys_tpdf_dup(module, lys_parent(node), ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002569 break;
2570
2571 default:
2572 /* LY_NODE_AUGMENT */
2573 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002574 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002575 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002576
2577 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002578
2579error:
2580
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002581 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002582 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002583}
2584
Michal Vasko13b15832015-08-19 11:04:48 +02002585void
Michal Vaskoff006c12016-02-17 11:15:19 +01002586lys_node_switch(struct lys_node *dst, struct lys_node *src)
2587{
2588 struct lys_node *child;
2589
2590 assert((dst->module == src->module) && (dst->name == src->name) && (dst->nodetype == src->nodetype));
2591
2592 /* sibling next */
2593 if (dst->prev != dst) {
2594 dst->prev->next = src;
2595 }
2596
2597 /* sibling prev */
2598 if (dst->next) {
2599 dst->next->prev = src;
2600 }
2601
2602 /* parent child prev */
2603 if (!dst->next && dst->parent) {
2604 dst->parent->child->prev = src;
2605 }
2606
2607 /* next */
2608 src->next = dst->next;
2609 dst->next = NULL;
2610
2611 /* prev */
2612 if (dst->prev != dst) {
2613 src->prev = dst->prev;
2614 }
2615 dst->prev = dst;
2616
2617 /* parent child */
2618 if (dst->parent && (dst->parent->child == dst)) {
2619 dst->parent->child = src;
2620 }
2621
2622 /* parent */
2623 src->parent = dst->parent;
2624 dst->parent = NULL;
2625
2626 /* child parent */
2627 LY_TREE_FOR(dst->child, child) {
2628 if (child->parent == dst) {
2629 child->parent = src;
2630 }
2631 }
2632
2633 /* child */
2634 src->child = dst->child;
2635 dst->child = NULL;
2636}
2637
2638void
Michal Vasko627975a2016-02-11 11:39:03 +01002639lys_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 +02002640{
2641 struct ly_ctx *ctx;
2642 int i;
2643
2644 if (!module) {
2645 return;
2646 }
2647
2648 /* remove schema from the context */
2649 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002650 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002651 for (i = 0; i < ctx->models.used; i++) {
2652 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002653 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002654 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002655 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 +02002656 ctx->models.list[ctx->models.used] = NULL;
2657 /* we are done */
2658 break;
2659 }
2660 }
2661 }
2662
2663 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002664 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002665
2666 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002667 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002668
2669 free(module);
2670}
Radek Krejci7e97c352015-06-19 16:26:34 +02002671
2672/*
2673 * op: 1 - enable, 0 - disable
2674 */
2675static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002676lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002677{
2678 int all = 0;
2679 int i, j, k;
2680
2681 if (!module || !name || !strlen(name)) {
2682 return EXIT_FAILURE;
2683 }
2684
2685 if (!strcmp(name, "*")) {
2686 /* enable all */
2687 all = 1;
2688 }
2689
2690 /* module itself */
2691 for (i = 0; i < module->features_size; i++) {
2692 if (all || !strcmp(module->features[i].name, name)) {
2693 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002694 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002695 /* enable referenced features (recursion) */
2696 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002697 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002698 module->features[i].features[k]->name, op);
2699 }
2700 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002701 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002702 }
2703 if (!all) {
2704 return EXIT_SUCCESS;
2705 }
2706 }
2707 }
2708
2709 /* submodules */
2710 for (j = 0; j < module->inc_size; j++) {
2711 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2712 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2713 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002714 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002715 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002716 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002717 }
2718 if (!all) {
2719 return EXIT_SUCCESS;
2720 }
2721 }
2722 }
2723 }
2724
2725 if (all) {
2726 return EXIT_SUCCESS;
2727 } else {
2728 return EXIT_FAILURE;
2729 }
2730}
2731
2732API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002733lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002734{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002735 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002736}
2737
2738API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002739lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002740{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002741 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002742}
2743
2744API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002745lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002746{
2747 int i, j;
2748
2749 if (!module || !feature) {
2750 return -1;
2751 }
2752
2753 /* search for the specified feature */
2754 /* module itself */
2755 for (i = 0; i < module->features_size; i++) {
2756 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002757 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002758 return 1;
2759 } else {
2760 return 0;
2761 }
2762 }
2763 }
2764
2765 /* submodules */
2766 for (j = 0; j < module->inc_size; j++) {
2767 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2768 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002769 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002770 return 1;
2771 } else {
2772 return 0;
2773 }
2774 }
2775 }
2776 }
2777
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002778 /* feature definition not found */
2779 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002780}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002781
Radek Krejci96a10da2015-07-30 11:00:14 +02002782API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002783lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002784{
Radek Krejci96a10da2015-07-30 11:00:14 +02002785 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002786 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002787 unsigned int count;
2788
2789 if (!module) {
2790 return NULL;
2791 }
2792
2793 count = module->features_size;
2794 for (i = 0; i < module->inc_size; i++) {
2795 count += module->inc[i].submodule->features_size;
2796 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002797 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002798 if (!result) {
2799 LOGMEM;
2800 return NULL;
2801 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002802 if (states) {
2803 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002804 if (!(*states)) {
2805 LOGMEM;
2806 free(result);
2807 return NULL;
2808 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002809 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002810 count = 0;
2811
2812 /* module itself */
2813 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002814 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002815 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002816 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002817 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002818 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002819 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002820 }
2821 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002822 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002823 }
2824
2825 /* submodules */
2826 for (j = 0; j < module->inc_size; j++) {
2827 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002828 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002829 if (states) {
2830 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2831 (*states)[count] = 1;
2832 } else {
2833 (*states)[count] = 0;
2834 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002835 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002836 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002837 }
2838 }
2839
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002840 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002841 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002842
2843 return result;
2844}
Michal Vaskobaefb032015-09-24 14:52:10 +02002845
Radek Krejci6910a032016-04-13 10:06:21 +02002846API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002847lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002848{
2849 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2850}
2851
Radek Krejci6910a032016-04-13 10:06:21 +02002852API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02002853lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01002854{
2855 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2856}
2857
Michal Vaskobaefb032015-09-24 14:52:10 +02002858API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002859lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002860{
2861 if (!node || !node->parent) {
2862 return NULL;
2863 }
2864
2865 if (node->parent->nodetype == LYS_AUGMENT) {
2866 return ((struct lys_node_augment *)node->parent)->target;
2867 }
2868
2869 return node->parent;
2870}
Michal Vasko1b229152016-01-13 11:28:38 +01002871
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002872API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002873lys_set_private(const struct lys_node *node, void *priv)
2874{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002875 void *prev;
2876
Michal Vasko1b229152016-01-13 11:28:38 +01002877 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002878 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2879 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002880 }
2881
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002882 prev = node->priv;
2883 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002884
2885 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002886}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002887
2888static void
2889lys_switch_deviation(struct lys_deviation *dev, struct lys_module *dev_module)
2890{
2891 int ret;
2892 char *parent_path;
2893 struct lys_node *target;
2894 const struct lys_module *target_module;
2895
2896 target_module = lys_get_import_module(dev_module, NULL, 0, dev->target_name + 1,
2897 strcspn(dev->target_name, ":") - 1);
2898
2899 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2900 if (dev->orig_node) {
2901 /* removing not-supported deviation ... */
2902 if (strrchr(dev->target_name, '/') != dev->target_name) {
2903 /* ... from a parent */
2904 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
2905
2906 target = NULL;
2907 ret = resolve_augment_schema_nodeid(parent_path, NULL, target_module, (const struct lys_node **)&target);
2908 free(parent_path);
2909 if (ret || !target) {
2910 LOGINT;
2911 return;
2912 }
2913
2914 lys_node_addchild(target, NULL, dev->orig_node);
2915 } else {
2916 /* ... from top-level data */
2917 lys_node_addchild(NULL, (struct lys_module *)target_module, dev->orig_node);
2918 }
2919
2920 dev->orig_node = NULL;
2921 } else {
2922 /* adding not-supported deviation */
2923 target = NULL;
2924 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
2925 if (ret || !target) {
2926 LOGINT;
2927 return;
2928 }
2929
2930 lys_node_unlink(target);
2931 dev->orig_node = target;
2932 }
2933 } else {
2934 target = NULL;
2935 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
2936 if (ret || !target) {
2937 LOGINT;
2938 return;
2939 }
2940
2941 lys_node_switch(target, dev->orig_node);
2942 dev->orig_node = target;
2943 }
2944}
2945
2946void
2947lys_deviation_add_ext_imports(struct lys_module *dev_target_module, struct lys_module *dev_module)
2948{
2949 int i, j;
2950
2951 /* mark the target module as deviated */
2952 dev_target_module->deviated = 1;
2953
2954 /* copy our imports to the deviated module (deviations may need them to work) */
2955 for (i = 0; i < dev_module->imp_size; ++i) {
2956 for (j = 0; j < dev_target_module->imp_size; ++j) {
2957 if (dev_module->imp[i].module == dev_target_module->imp[j].module) {
2958 break;
2959 }
2960 }
2961
2962 if (j < dev_target_module->imp_size) {
2963 /* import is already there */
2964 continue;
2965 }
2966
2967 /* copy the import, mark it as external */
2968 ++dev_target_module->imp_size;
2969 dev_target_module->imp = ly_realloc(dev_target_module->imp, dev_target_module->imp_size * sizeof *dev_target_module->imp);
2970 if (!dev_target_module->imp) {
2971 LOGMEM;
2972 return;
2973 }
2974 dev_target_module->imp[dev_target_module->imp_size - 1].module = dev_module->imp[i].module;
2975 dev_target_module->imp[dev_target_module->imp_size - 1].prefix = lydict_insert(dev_module->ctx, dev_module->imp[i].prefix, 0);
2976 memcpy(dev_target_module->imp[dev_target_module->imp_size - 1].rev, dev_module->imp[i].rev, LY_REV_SIZE);
2977 dev_target_module->imp[dev_target_module->imp_size - 1].external = 1;
2978 }
2979
2980 /* copy ourselves to the deviated module as a special import (if we haven't yet, there could be more deviations of the same module) */
2981 for (i = 0; i < dev_target_module->imp_size; ++i) {
2982 if (dev_target_module->imp[i].module == dev_module) {
2983 break;
2984 }
2985 }
2986
2987 if (i == dev_target_module->imp_size) {
2988 ++dev_target_module->imp_size;
2989 dev_target_module->imp = ly_realloc(dev_target_module->imp, dev_target_module->imp_size * sizeof *dev_target_module->imp);
2990 if (!dev_target_module->imp) {
2991 LOGMEM;
2992 return;
2993 }
2994 dev_target_module->imp[dev_target_module->imp_size - 1].module = dev_module;
2995 dev_target_module->imp[dev_target_module->imp_size - 1].prefix = lydict_insert(dev_module->ctx, dev_module->prefix, 0);
2996 if (dev_module->rev_size) {
2997 memcpy(dev_target_module->imp[dev_target_module->imp_size - 1].rev, dev_module->rev[0].date, LY_REV_SIZE);
2998 } else {
2999 memset(dev_target_module->imp[dev_target_module->imp_size - 1].rev, 0, LY_REV_SIZE);
3000 }
3001 dev_target_module->imp[dev_target_module->imp_size - 1].external = 2;
3002 } else {
3003 /* it could have been added by another deviating module that imported this deviating module */
3004 dev_target_module->imp[i].external = 2;
3005 }
3006}
3007
3008/* temporarily removes or applies deviations, updates module deviation flag accordingly */
3009void
3010lys_switch_deviations(struct lys_module *module)
3011{
3012 uint8_t i, j, changes = 0;
3013
3014 for (i = 0; i < module->imp_size; ++i) {
3015 if (module->imp[i].external == 2) {
3016 for (j = 0; j < module->imp[i].module->deviation_size; ++j) {
3017 lys_switch_deviation(&module->imp[i].module->deviation[j], module->imp[i].module);
3018 }
3019
3020 changes = 1;
3021 }
3022 }
3023
3024 if (changes) {
3025 if (module->deviated) {
3026 module->deviated = 0;
3027 } else {
3028 module->deviated = 1;
3029 }
3030 }
3031}
3032
3033/* not needed currently, but tested and working */
3034#if 0
3035
3036void
3037lys_sub_module_apply_devs_augs(struct lys_module *module)
3038{
3039 int i;
3040 struct lys_node_augment *aug;
3041 struct lys_node *last;
3042
3043 /* re-apply deviations */
3044 for (i = 0; i < module->deviation_size; ++i) {
3045 lys_switch_deviation(&module->deviation[i], module);
3046 assert(module->deviation[i].orig_node);
3047 lys_deviation_add_ext_imports(lys_node_module(module->deviation[i].orig_node), module);
3048 }
3049
3050 /* re-apply augments */
3051 for (i = 0; i < module->augment_size; ++i) {
3052 aug = &module->augment[i];
3053 assert(aug->target);
3054
3055 /* reconnect augmenting data into the target - add them to the target child list */
3056 if (aug->target->child) {
3057 last = aug->target->child->prev;
3058 last->next = aug->child;
3059 aug->target->child->prev = aug->child->prev;
3060 aug->child->prev = last;
3061 } else {
3062 aug->target->child = aug->child;
3063 }
3064 }
3065}
3066
3067#endif
3068
3069void
3070lys_sub_module_remove_devs_augs(struct lys_module *module)
3071{
3072 int i, j, flag;
3073 struct lys_node *last, *elem;
3074 struct lys_module *orig_mod;
3075
3076 /* remove applied deviations */
3077 for (i = 0; i < module->deviation_size; ++i) {
3078 lys_switch_deviation(&module->deviation[i], module);
3079
3080 /* remove our deviation import, clear deviated flag is possible */
3081 orig_mod = lys_node_module(module->deviation[i].orig_node);
3082 flag = 0;
3083 for (j = 0; j < orig_mod->imp_size; ++j) {
3084 if (orig_mod->imp[j].external == 2) {
3085 if (orig_mod->imp[j].module == lys_main_module(module)) {
3086 /* our deviation import, remove it */
3087 --orig_mod->imp_size;
3088 if (j < orig_mod->imp_size) {
3089 memcpy(&orig_mod->imp[j], &orig_mod->imp[j + 1], (orig_mod->imp_size - j) * sizeof *orig_mod->imp);
3090 }
3091 --j;
3092 } else {
3093 /* some other deviation, we cannot clear the deviated flag */
3094 flag = 1;
3095 }
3096 }
3097 }
3098 if (!flag) {
3099 /* it's safe to clear the deviated flag */
3100 orig_mod->deviated = 0;
3101 }
3102 }
3103
3104 /* remove applied augments */
3105 for (i = 0; i < module->augment_size; ++i) {
3106 assert(module->augment[i].target);
3107
3108 elem = module->augment[i].child;
3109 if (elem) {
3110 LY_TREE_FOR(elem, last) {
3111 if (!last->next || (last->next->parent != (struct lys_node *)&module->augment[i])) {
3112 break;
3113 }
3114 }
3115 /* elem is first augment child, last is the last child */
3116
3117 /* parent child ptr */
3118 if (module->augment[i].target->child == elem) {
3119 module->augment[i].target->child = last->next;
3120 }
3121
3122 /* parent child next ptr */
3123 if (elem->prev->next) {
3124 elem->prev->next = last->next;
3125 }
3126
3127 /* parent child prev ptr */
3128 if (last->next) {
3129 last->next->prev = elem->prev;
3130 } else if (module->augment[i].target->child) {
3131 module->augment[i].target->child->prev = elem->prev;
3132 }
3133
3134 /* update augment children themselves */
3135 elem->prev = last;
3136 last->next = NULL;
3137 }
Michal Vaskob8f71322016-05-03 11:39:56 +02003138
3139 /* needs to be NULL for lys_augment_free() to free the children */
3140 module->augment[i].target = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003141 }
3142}
3143
Michal Vasko26055752016-05-03 11:36:31 +02003144int
3145lys_module_set_implement(struct lys_module *module)
3146{
3147 struct ly_ctx *ctx;
3148 int i;
3149
3150 if (module->implemented) {
3151 return EXIT_SUCCESS;
3152 }
3153
3154 ctx = module->ctx;
3155
3156 for (i = 0; i < ctx->models.used; ++i) {
3157 if (module == ctx->models.list[i]) {
3158 continue;
3159 }
3160
3161 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
3162 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
3163 return EXIT_FAILURE;
3164 }
3165 }
3166
3167 module->implemented = 1;
3168 return EXIT_SUCCESS;
3169}
3170
3171int
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003172lys_sub_module_set_dev_aug_target_implement(struct lys_module *module)
3173{
3174 int i;
3175 struct lys_module *trg_mod;
3176
3177 for (i = 0; i < module->deviation_size; ++i) {
3178 assert(module->deviation[i].orig_node);
3179 trg_mod = lys_node_module(module->deviation[i].orig_node);
Michal Vasko26055752016-05-03 11:36:31 +02003180 if (lys_module_set_implement(trg_mod)) {
3181 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003182 }
3183 }
3184
3185 for (i = 0; i < module->augment_size; ++i) {
3186 assert(module->augment[i].target);
3187 trg_mod = lys_node_module(module->augment[i].target);
Michal Vasko26055752016-05-03 11:36:31 +02003188 if (lys_module_set_implement(trg_mod)) {
3189 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003190 }
3191 }
Michal Vasko26055752016-05-03 11:36:31 +02003192
3193 return EXIT_SUCCESS;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003194}
3195
3196void
3197lys_submodule_module_data_free(struct lys_submodule *submodule)
3198{
3199 struct lys_node *next, *elem;
3200
3201 /* remove parsed data */
3202 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
3203 if (elem->module == (struct lys_module *)submodule) {
3204 lys_node_free(elem, NULL, 0);
3205 }
3206 }
3207}