blob: 04bda57bb2375a433bdade950d61c2154588a559 [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 Vasko5b3492c2016-07-20 09:37:40 +020034#include "xpath.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020035#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020036#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020037#include "validation.h"
Pavol Vicanf7cc2852016-03-22 23:27:35 +010038#include "parser_yang.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020039
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020040static int
41lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +020042 int tpdftype, struct unres_schema *unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020043
Radek Krejci9ff0a922016-07-14 13:08:05 +020044API const struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +010045lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020046{
Radek Krejci9ff0a922016-07-14 13:08:05 +020047 int i;
Radek Krejci48061fb2015-08-05 15:41:07 +020048
49check:
50 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
51 /* input/output does not have if-feature, so skip them */
52
53 /* check local if-features */
Michal Vaskoc5c26b02016-06-29 11:10:29 +020054 for (i = 0; i < node->iffeature_size; i++) {
Radek Krejci9ff0a922016-07-14 13:08:05 +020055 if (resolve_iffeature(&node->iffeature[i])) {
56 return node;
Radek Krejci48061fb2015-08-05 15:41:07 +020057 }
58 }
59 }
60
61 if (!recursive) {
62 return NULL;
63 }
64
65 /* go through parents */
66 if (node->nodetype == LYS_AUGMENT) {
67 /* go to parent actually means go to the target node */
68 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020069 } else if (node->parent) {
70 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020071 } else {
72 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020073 }
74
Radek Krejci074bf852015-08-19 14:22:16 +020075 if (recursive == 2) {
76 /* continue only if the node cannot have a data instance */
77 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
78 return NULL;
79 }
80 }
81 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020082}
83
Michal Vasko1dca6882015-10-22 14:29:42 +020084int
Michal Vasko36cbaa42015-12-14 13:15:48 +010085lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
86 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020087{
Radek Krejcic071c542016-01-27 14:57:51 +010088 const struct lys_node *node, *parent = NULL;
89 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010090 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020091
Michal Vasko36cbaa42015-12-14 13:15:48 +010092 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020093 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020094
Michal Vasko36cbaa42015-12-14 13:15:48 +010095 /* fill the lengths in case the caller is so indifferent */
96 if (!mod_name_len) {
97 mod_name_len = strlen(mod_name);
98 }
Michal Vasko1dca6882015-10-22 14:29:42 +020099 if (!nam_len) {
100 nam_len = strlen(name);
101 }
102
Michal Vasko36cbaa42015-12-14 13:15:48 +0100103 /* set mod correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100104 parent = lys_parent(siblings);
105 if (!parent) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100106 mod = lys_node_module(siblings);
Michal Vasko1dca6882015-10-22 14:29:42 +0200107 }
108
Radek Krejcic071c542016-01-27 14:57:51 +0100109 /* try to find the node */
110 node = NULL;
111 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
112 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100113 /* module name comparison */
114 node_mod_name = lys_node_module(node)->name;
Michal Vaskob42b6972016-06-06 14:21:30 +0200115 if (!ly_strequal(node_mod_name, mod_name, 1) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100116 continue;
117 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200118
Radek Krejcic071c542016-01-27 14:57:51 +0100119 /* direct name check */
Michal Vaskob42b6972016-06-06 14:21:30 +0200120 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100121 if (ret) {
122 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200123 }
Radek Krejcic071c542016-01-27 14:57:51 +0100124 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200125 }
126 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200127 }
128
129 return EXIT_FAILURE;
130}
131
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200132int
Michal Vasko1e62a092015-12-01 12:27:20 +0100133lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
134 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200135{
Michal Vasko1e62a092015-12-01 12:27:20 +0100136 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200137
138 assert(siblings && name);
139 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
140
141 /* find the beginning */
142 while (siblings->prev->next) {
143 siblings = siblings->prev;
144 }
145
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200146 if (!mod) {
147 mod = siblings->module;
148 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200149
Michal Vasko4f0dad02016-02-15 14:08:23 +0100150 /* try to find the node */
151 node = NULL;
Michal Vaskodcf98e62016-05-05 17:53:53 +0200152 while ((node = lys_getnext(node, lys_parent(siblings), mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100153 if (!type || (node->nodetype & type)) {
154 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200155 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100156 continue;
157 }
158
Michal Vasko4f0dad02016-02-15 14:08:23 +0100159 /* direct name check */
Radek Krejci749190d2016-02-18 16:26:25 +0100160 if (ly_strequal(node->name, name, 0)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100161 if (ret) {
162 *ret = node;
163 }
164 return EXIT_SUCCESS;
165 }
Radek Krejcic071c542016-01-27 14:57:51 +0100166 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200167 }
168
169 return EXIT_FAILURE;
170}
171
Michal Vasko1e62a092015-12-01 12:27:20 +0100172API const struct lys_node *
173lys_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 +0200174{
Michal Vasko1e62a092015-12-01 12:27:20 +0100175 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200176
Radek Krejci8bc87f62015-09-02 16:19:05 +0200177 if (!last) {
178 /* first call */
179
180 /* get know where to start */
181 if (parent) {
182 /* schema subtree */
183 next = last = parent->child;
184 } else {
185 /* top level data */
186 assert(module);
187 next = last = module->data;
188 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200189 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200190 /* continue after the last returned value */
191 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200192 }
193
194repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200195 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200196 if (options & LYS_GETNEXT_WITHGROUPING) {
197 return next;
198 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200199 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200200 }
201
Radek Krejcic4ccbd92016-01-07 13:13:33 +0100202 if (!next) {
Radek Krejci63318e82016-02-12 09:43:12 +0100203 if (!last || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200204 /* no next element */
205 return NULL;
206 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200207 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200208 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200209 goto repeat;
210 }
211
212 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200213 case LYS_INPUT:
214 case LYS_OUTPUT:
215 if (options & LYS_GETNEXT_WITHINOUT) {
216 return next;
217 } else {
218 next = next->child;
219 goto repeat;
220 }
221 break;
222
Michal Vaskoa5835e92015-10-20 15:07:39 +0200223 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200224 if (options & LYS_GETNEXT_WITHCASE) {
225 return next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200226 } else {
227 next = next->child;
228 goto repeat;
Michal Vasko1dca6882015-10-22 14:29:42 +0200229 }
Michal Vaskob6eedf02015-10-22 16:07:03 +0200230 break;
231
Michal Vasko1dca6882015-10-22 14:29:42 +0200232 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200233 /* go into */
234 next = next->child;
235 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200236
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200237 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200238 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200239 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200240 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200241 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200242 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200243 case LYS_LIST:
244 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200245 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200246
247 case LYS_CHOICE:
248 if (options & LYS_GETNEXT_WITHCHOICE) {
249 return next;
250 } else {
251 /* go into */
252 next = next->child;
253 goto repeat;
254 }
255 break;
256
Radek Krejci7f40ce32015-08-12 20:38:46 +0200257 default:
258 /* we should not be here */
259 return NULL;
260 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200261
262
263}
264
Michal Vasko1e62a092015-12-01 12:27:20 +0100265static const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100266check_mand_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module)
Radek Krejci8bc87f62015-09-02 16:19:05 +0200267{
Michal Vasko1e62a092015-12-01 12:27:20 +0100268 const struct lys_node *next;
269
Radek Krejci2342cf62016-01-29 16:48:23 +0100270 next = lys_getnext(last, parent, module, LYS_GETNEXT_WITHCHOICE);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200271
Radek Krejci4b6c2112015-10-06 12:48:34 +0200272repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200273 if (next && next->nodetype == LYS_CONTAINER) {
274 if (((struct lys_node_container *)next)->presence) {
275 /* mandatory elements under the non-existing presence
276 * container are not mandatory - 7.6.5, rule 1 */
277 next = next->next;
278 } else {
279 /* go into */
280 next = next->child;
281 }
282 goto repeat;
283 }
284
285 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200286}
287
Michal Vasko84f821a2016-04-11 11:03:42 +0200288static int
Michal Vasko1e62a092015-12-01 12:27:20 +0100289check_mand_check(const struct lys_node *node, const struct lys_node *stop, const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200290{
Radek Krejci7531aa22016-04-12 13:52:19 +0200291 const struct lys_node *siter = NULL, *missing_parent = NULL;
Radek Krejci96e20852016-04-11 17:51:26 +0200292 struct lys_node *parent = NULL;
Radek Krejci7531aa22016-04-12 13:52:19 +0200293 const struct lyd_node *diter = NULL;
Radek Krejcidc154432016-01-21 11:10:59 +0100294 struct ly_set *set = NULL;
Michal Vaskof610fd42016-04-19 10:38:20 +0200295 unsigned int i, toplevel = (stop && stop->nodetype != LYS_OUTPUT) ? 0 : 1;
Michal Vasko84f821a2016-04-11 11:03:42 +0200296 uint32_t minmax, min, max;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200297
Radek Krejci7531aa22016-04-12 13:52:19 +0200298 if (data) {
299 /* go to the correct data level */
300 for (parent = lys_parent(node); parent && parent != stop; parent = lys_parent(parent)) {
301 /* 7.6.5, rule 1 (presence container), checking presence
302 * is not needed since it is done in check_mand_getnext()
303 */
304
305 if (parent->nodetype != LYS_CONTAINER) {
306 /* not interested in LYS_USES, LYS_CASE or LYS_CHOICE,
307 * because they are not instantiated in data tree */
308 continue;
309 }
310 /* add the parent to the list for searching in data tree */
311 if (!set) {
312 set = ly_set_new();
313 }
314 /* ignore return - memory error is logged and we will
315 * check at least the rest of nodes we have */
Radek Krejci09891a22016-06-10 10:59:22 +0200316 (void)ly_set_add(set, parent, LY_SET_OPT_USEASLIST);
Radek Krejci7531aa22016-04-12 13:52:19 +0200317 }
318 if (set) {
319 for (i = set->number; i > 0; ) {
320 i--;
321 LY_TREE_FOR(toplevel ? data : data->child, diter) {
322 if (diter->schema == set->set.s[i]) {
323 break;
324 }
325 }
326 if (!diter) {
327 /* instance not found */
328 missing_parent = set->set.s[i];
329 break;
330 }
331 data = diter;
332 toplevel = 0;
333 if (data->validity == LYD_VAL_OK) {
334 /* already checked */
335 ly_set_free(set);
336 return EXIT_SUCCESS;
337 }
338 }
339 ly_set_free(set);
340 }
341 } else {
342 missing_parent = node;
343 }
344
Radek Krejci7f40ce32015-08-12 20:38:46 +0200345 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci7531aa22016-04-12 13:52:19 +0200346 if (missing_parent) {
Michal Vaskob68d4b42016-05-20 11:44:45 +0200347 LOGVAL(LYE_MISSELEM, LY_VLOG_LYD, toplevel ? NULL : data, node->name,
Radek Krejci29ac4f92016-04-12 15:05:53 +0200348 (lys_parent(node) ? lys_parent(node)->name : lys_node_module(node)->name));
Michal Vasko84f821a2016-04-11 11:03:42 +0200349 return EXIT_FAILURE;
Radek Krejci2342cf62016-01-29 16:48:23 +0100350 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200351
Radek Krejci2342cf62016-01-29 16:48:23 +0100352 switch (node->nodetype) {
353 case LYS_LEAF:
354 case LYS_ANYXML:
355 case LYS_CHOICE:
Michal Vasko84f821a2016-04-11 11:03:42 +0200356 if (lys_parent(node) && lys_parent(node)->nodetype == LYS_CASE) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100357 /* 7.6.5, rule 2 */
358 /* 7.9.4, rule 1 */
Radek Krejci7531aa22016-04-12 13:52:19 +0200359
360 /* try to find the node's siblings in data */
361 LY_TREE_FOR(toplevel ? data : data->child, diter) {
362 LY_TREE_FOR(lys_parent(node)->child, siter) {
363 if (siter == diter->schema) {
364 /* some sibling exists, rule applies */
Radek Krejci2342cf62016-01-29 16:48:23 +0100365 break;
366 }
367 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200368 if (siter) {
369 break;
370 }
Radek Krejci2342cf62016-01-29 16:48:23 +0100371 }
372 if (!siter) {
373 /* no sibling exists */
Michal Vasko84f821a2016-04-11 11:03:42 +0200374 return EXIT_SUCCESS;
Radek Krejci2342cf62016-01-29 16:48:23 +0100375 }
Radek Krejci2342cf62016-01-29 16:48:23 +0100376 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200377
Radek Krejci96e20852016-04-11 17:51:26 +0200378 if (node->nodetype == LYS_CHOICE) {
379 siter = NULL;
Radek Krejci7531aa22016-04-12 13:52:19 +0200380 LY_TREE_FOR(toplevel ? data : data->child, diter) {
Radek Krejci96e20852016-04-11 17:51:26 +0200381 while ((siter = lys_getnext(siter, node, NULL, 0))) {
382 if (diter->schema == siter) {
383 return EXIT_SUCCESS;
384 }
385 }
386 }
387 } else {
Radek Krejci7531aa22016-04-12 13:52:19 +0200388 LY_TREE_FOR(toplevel ? data : data->child, diter) {
Radek Krejci96e20852016-04-11 17:51:26 +0200389 if (diter->schema == node) {
390 return EXIT_SUCCESS;
391 }
Radek Krejci2342cf62016-01-29 16:48:23 +0100392 }
393 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200394
Radek Krejci2342cf62016-01-29 16:48:23 +0100395 /* instance not found */
396 /* 7.6.5, rule 3 (or 2) */
397 /* 7.9.4, rule 2 */
Michal Vasko84f821a2016-04-11 11:03:42 +0200398 if (node->nodetype == LYS_CHOICE) {
Radek Krejci29ac4f92016-04-12 15:05:53 +0200399 LOGVAL(LYE_NOMANDCHOICE, LY_VLOG_LYD, toplevel ? NULL : data, node->name);
Michal Vasko84f821a2016-04-11 11:03:42 +0200400 } else {
Radek Krejci29ac4f92016-04-12 15:05:53 +0200401 LOGVAL(LYE_MISSELEM, LY_VLOG_LYD, toplevel ? NULL : data, node->name,
Michal Vasko84f821a2016-04-11 11:03:42 +0200402 (lys_parent(node) ? lys_parent(node)->name : lys_node_module(node)->name));
403 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200404 break;
Radek Krejci2342cf62016-01-29 16:48:23 +0100405 default:
406 /* error */
Radek Krejci7531aa22016-04-12 13:52:19 +0200407 LOGINT;
Radek Krejci2342cf62016-01-29 16:48:23 +0100408 break;
409 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200410 return EXIT_FAILURE;
411
Radek Krejci14a11a62015-08-17 17:27:38 +0200412 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
413 /* search for number of instances */
414 minmax = 0;
Radek Krejci7531aa22016-04-12 13:52:19 +0200415 if (!missing_parent) {
416 LY_TREE_FOR(toplevel ? data : data->child, diter) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100417 if (diter->schema == node) {
418 minmax++;
Michal Vasko05ed8422016-04-12 11:38:24 +0200419 /* remember the last instance, we will use it in the log message */
420 data = diter;
Radek Krejci2342cf62016-01-29 16:48:23 +0100421 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200422 }
423 }
424
425 /* check the specified constraints */
426 if (node->nodetype == LYS_LIST) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200427 min = ((struct lys_node_list *)node)->min;
428 max = ((struct lys_node_list *)node)->max;
429 } else {
430 min = ((struct lys_node_leaflist *)node)->min;
431 max = ((struct lys_node_leaflist *)node)->max;
432 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200433
Michal Vasko84f821a2016-04-11 11:03:42 +0200434 if (min && (minmax < min)) {
Radek Krejci29ac4f92016-04-12 15:05:53 +0200435 LOGVAL(LYE_NOMIN, LY_VLOG_LYD, toplevel ? NULL : data, node->name);
Michal Vasko84f821a2016-04-11 11:03:42 +0200436 return EXIT_FAILURE;
437 }
438 if (max && (minmax > max)) {
Radek Krejci29ac4f92016-04-12 15:05:53 +0200439 LOGVAL(LYE_NOMAX, LY_VLOG_LYD, toplevel ? NULL : data, node->name);
Michal Vasko84f821a2016-04-11 11:03:42 +0200440 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200441 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200442 }
443
Michal Vasko84f821a2016-04-11 11:03:42 +0200444 return EXIT_SUCCESS;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200445}
446
Michal Vasko84f821a2016-04-11 11:03:42 +0200447int
Michal Vasko98a5a742016-05-11 11:02:56 +0200448ly_check_mandatory(const struct lyd_node *data, const struct lys_node *schema, int status, int rpc_output)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200449{
Michal Vasko84f821a2016-04-11 11:03:42 +0200450 const struct lys_node *siter, *saux, *saux2, *parent = NULL, *parent2;
Michal Vasko1e62a092015-12-01 12:27:20 +0100451 const struct lyd_node *diter;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200452 int found;
453
Radek Krejci2342cf62016-01-29 16:48:23 +0100454 assert(data || schema);
455
Radek Krejci7531aa22016-04-12 13:52:19 +0200456 if (schema) {
457 /* schema is preferred regardless the data */
Radek Krejci2342cf62016-01-29 16:48:23 +0100458 siter = schema;
Radek Krejci7531aa22016-04-12 13:52:19 +0200459 } else {
460 /* !schema && data */
Radek Krejcie2f12212016-02-12 13:50:22 +0100461 schema = data->schema;
462 siter = data->schema->child;
Radek Krejci2342cf62016-01-29 16:48:23 +0100463 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200464
465repeat:
466 while (siter) {
Radek Krejci763122e2016-04-05 16:35:33 +0200467 if (lys_is_disabled(siter, 2) || (!status && (siter->flags & LYS_CONFIG_R))) {
Radek Krejci074bf852015-08-19 14:22:16 +0200468 siter = siter->next;
469 continue;
470 }
471
Radek Krejci7f40ce32015-08-12 20:38:46 +0200472 switch (siter->nodetype) {
473 case LYS_CONTAINER:
474 case LYS_LEAF:
475 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200476 case LYS_LIST:
477 case LYS_LEAFLIST:
478 /* check if there is some mandatory node; first test the siter itself ... */
Michal Vasko84f821a2016-04-11 11:03:42 +0200479 if (check_mand_check(siter, lys_parent(siter), data)) {
480 return EXIT_FAILURE;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200481 }
482 /* ... and then the subtree */
Radek Krejcicf82e932016-04-11 17:52:31 +0200483 if (siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200484 saux = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100485 while ((saux = check_mand_getnext(saux, siter, NULL))) {
Radek Krejcie8da2e02016-04-11 17:53:34 +0200486 if ((status || (saux->flags & LYS_CONFIG_W)) && check_mand_check(saux, lys_parent(siter), data)) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200487 return EXIT_FAILURE;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200488 }
489 }
490 }
491 siter = siter->next;
492 break;
493 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200494 /* search for instance */
495 saux = siter;
496 siter = siter->child;
497 found = 0;
498 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200499repeat_choice:
Radek Krejci2342cf62016-01-29 16:48:23 +0100500 while (siter && data) {
Radek Krejci763122e2016-04-05 16:35:33 +0200501 if (lys_is_disabled(siter, 2) || (!status && (siter->flags & LYS_CONFIG_R))) {
Radek Krejci074bf852015-08-19 14:22:16 +0200502 siter = siter->next;
503 continue;
504 }
505
Radek Krejci14a11a62015-08-17 17:27:38 +0200506 switch (siter->nodetype) {
507 case LYS_CONTAINER:
508 case LYS_LEAF:
509 case LYS_LEAFLIST:
510 case LYS_LIST:
511 case LYS_ANYXML:
512 LY_TREE_FOR(data->child, diter) {
513 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200514 break;
515 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200516 }
517 if (diter) {
518 /* got instance */
519 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200520 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200521 saux2 = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100522 while ((saux2 = check_mand_getnext(saux2, parent2, NULL))) {
Radek Krejci7531aa22016-04-12 13:52:19 +0200523 if (check_mand_check(saux2, lys_parent(saux), data)) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200524 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200525 }
526 }
527 }
528 siter = parent2 = NULL;
529 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200530 break;
531 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200532 siter = siter->next;
533 break;
534 case LYS_CASE:
535 case LYS_CHOICE:
536 case LYS_USES:
537 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200538 if (!parent2) {
539 parent2 = siter;
540 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200541 siter = siter->child;
542 break;
543 case LYS_AUGMENT:
544 case LYS_GROUPING:
545 /* skip */
546 siter = siter->next;
547 break;
548 default:
549 /* error */
550 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200551 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200552 }
553
Radek Krejci14a11a62015-08-17 17:27:38 +0200554 if (parent2) {
555 siter = parent2->next;
Michal Vasko84f821a2016-04-11 11:03:42 +0200556 if (lys_parent(parent2) == saux) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200557 parent2 = NULL;
558 } else {
Michal Vasko84f821a2016-04-11 11:03:42 +0200559 parent2 = lys_parent(parent2);
Radek Krejci14a11a62015-08-17 17:27:38 +0200560 }
561 goto repeat_choice;
562 }
563
Radek Krejci074bf852015-08-19 14:22:16 +0200564 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci7531aa22016-04-12 13:52:19 +0200565 LOGVAL(LYE_MISSELEM, LY_VLOG_LYD, data, saux->name,
566 (lys_parent(saux) ? lys_parent(saux)->name : lys_node_module(saux)->name));
Michal Vasko84f821a2016-04-11 11:03:42 +0200567 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200568 }
569
570 /* go to next */
571 siter = saux->next;
572
Radek Krejci7f40ce32015-08-12 20:38:46 +0200573 break;
Michal Vasko98a5a742016-05-11 11:02:56 +0200574 case LYS_INPUT:
575 if (rpc_output) {
576 /* skip */
577 siter = siter->next;
578 break;
579 }
580 /* fallthrough */
581 case LYS_OUTPUT:
Michal Vasko880f67d2016-06-01 16:12:18 +0200582 if ((siter->nodetype == LYS_OUTPUT) && !rpc_output) {
Michal Vasko98a5a742016-05-11 11:02:56 +0200583 /* skip */
584 siter = siter->next;
585 break;
586 }
587 /* fallthrough */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200588 case LYS_USES:
589 case LYS_CASE:
590 /* go into */
591 parent = siter;
592 siter = siter->child;
593 break;
594 default:
595 /* can ignore, go to next */
596 siter = siter->next;
597 break;
598 }
599 }
600
601 if (parent) {
602 siter = parent->next;
Michal Vasko9eb6dd02016-05-02 14:52:40 +0200603 if (lys_parent(parent) == schema) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200604 parent = NULL;
605 } else {
Michal Vasko84f821a2016-04-11 11:03:42 +0200606 parent = lys_parent(parent);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200607 }
608 goto repeat;
609 }
610
Michal Vasko84f821a2016-04-11 11:03:42 +0200611 return EXIT_SUCCESS;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200612}
613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200614void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200615lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200616{
Radek Krejci76512572015-08-04 09:47:08 +0200617 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100618 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200619
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200620 if (!node) {
621 return;
622 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200623
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200624 /* unlink from data model if necessary */
625 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100626 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100627 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100628 if (main_module->data == node) {
629 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200630 }
631 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200632
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200633 /* store pointers to important nodes */
634 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200635 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200636 /* handle augments - first, unlink it from the augment parent ... */
637 if (parent->child == node) {
638 parent->child = node->next;
639 }
640 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200641 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200642 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200644 /* unlink from parent */
645 if (parent) {
646 if (parent->child == node) {
647 parent->child = node->next;
648 }
649 node->parent = NULL;
650 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200651
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200652 /* unlink from siblings */
653 if (node->prev == node) {
654 /* there are no more siblings */
655 return;
656 }
657 if (node->next) {
658 node->next->prev = node->prev;
659 } else {
660 /* unlinking the last element */
661 if (parent) {
662 first = parent->child;
663 } else {
664 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200665 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200666 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200667 }
668 }
669 first->prev = node->prev;
670 }
671 if (node->prev->next) {
672 node->prev->next = node->next;
673 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200674
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200675 /* clean up the unlinked element */
676 node->next = NULL;
677 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200678}
679
Michal Vasko563ef092015-09-04 13:17:23 +0200680struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100681lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200682{
683 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200684
685 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200686 /* top-level augment, look into module (uses augment is handled correctly below) */
687 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
688 par_iter = par_iter->parent->module->data;
689 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200690 break;
691 }
692 }
693
Michal Vasko6f929da2015-10-02 16:23:25 +0200694 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200695 continue;
696 }
697
698 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
699 if (!stop) {
700 stop = par_iter;
701 } else if (iter == stop) {
702 break;
703 }
704 if (iter->nodetype != LYS_GROUPING) {
705 continue;
706 }
707
Radek Krejcif8426a72015-10-31 23:14:03 +0100708 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200709 return (struct lys_node_grp *)iter;
710 }
711 }
712 }
713
Michal Vasko563ef092015-09-04 13:17:23 +0200714 return NULL;
715}
716
Radek Krejci10c760e2015-08-14 14:45:43 +0200717/*
718 * get next grouping in the root's subtree, in the
719 * first call, tha last is NULL
720 */
721static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200722lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200723{
Radek Krejci10c760e2015-08-14 14:45:43 +0200724 struct lys_node *last = (struct lys_node *)lastgrp;
725 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200726
Radek Krejci10c760e2015-08-14 14:45:43 +0200727 assert(root);
728
729 if (!last) {
730 last = root;
731 }
732
733 while (1) {
734 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
735 next = last->child;
736 } else {
737 next = NULL;
738 }
739 if (!next) {
740 if (last == root) {
741 /* we are done */
742 return NULL;
743 }
744
745 /* no children, go to siblings */
746 next = last->next;
747 }
748 while (!next) {
749 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100750 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200751 /* we are done */
752 return NULL;
753 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200754 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100755 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200756 }
757
758 if (next->nodetype == LYS_GROUPING) {
759 return (struct lys_node_grp *)next;
760 }
761
762 last = next;
763 }
764}
765
Michal Vasko0d343d12015-08-24 14:57:36 +0200766/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200767int
Radek Krejci07911992015-08-14 15:13:31 +0200768lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
769{
Michal Vasko563ef092015-09-04 13:17:23 +0200770 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200771 struct lys_node_grp *grp;
772 int down;
773
774 assert(node);
775
776 if (!parent) {
777 assert(module);
778 } else {
779 module = parent->module;
780 }
781
782 switch (node->nodetype) {
783 case LYS_GROUPING:
784 /* 6.2.1, rule 6 */
785 if (parent) {
786 if (parent->child) {
787 down = 1;
788 start = parent->child;
789 } else {
790 down = 0;
791 start = parent;
792 }
793 } else {
794 down = 1;
795 start = module->data;
796 }
797 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100798 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100799 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200800 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200801 }
802 /* go down, because grouping can be defined after e.g. container in which is collision */
803 if (down) {
804 for (iter = start, stop = NULL; iter; iter = iter->prev) {
805 if (!stop) {
806 stop = start;
807 } else if (iter == stop) {
808 break;
809 }
810 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
811 continue;
812 }
813
814 grp = NULL;
815 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100816 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100817 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200818 return EXIT_FAILURE;
819 }
820 }
821 }
822 }
823 break;
824 case LYS_LEAF:
825 case LYS_LEAFLIST:
826 case LYS_LIST:
827 case LYS_CONTAINER:
828 case LYS_CHOICE:
829 case LYS_ANYXML:
830 /* 6.2.1, rule 7 */
831 if (parent) {
832 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200833 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
834 if (iter->nodetype == LYS_AUGMENT) {
835 if (((struct lys_node_augment *)iter)->target) {
836 /* augment is resolved, go up */
837 iter = ((struct lys_node_augment *)iter)->target;
838 continue;
839 }
840 /* augment is not resolved, this is the final parent */
841 break;
842 }
Radek Krejci07911992015-08-14 15:13:31 +0200843 iter = iter->parent;
844 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200845
Radek Krejci07911992015-08-14 15:13:31 +0200846 if (!iter) {
847 stop = NULL;
848 iter = module->data;
849 } else {
850 stop = iter;
851 iter = iter->child;
852 }
853 } else {
854 stop = NULL;
855 iter = module->data;
856 }
857 while (iter) {
858 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
859 iter = iter->child;
860 continue;
861 }
862
863 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100864 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100865 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200866 return EXIT_FAILURE;
867 }
868 }
869
870 /* special case for choice - we must check the choice's name as
871 * well as the names of nodes under the choice
872 */
873 if (iter->nodetype == LYS_CHOICE) {
874 iter = iter->child;
875 continue;
876 }
877
878 /* go to siblings */
879 if (!iter->next) {
880 /* no sibling, go to parent's sibling */
881 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200882 /* for parent LYS_AUGMENT */
883 if (iter->parent == stop) {
884 iter = stop;
885 break;
886 }
887 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200888 if (iter && iter->next) {
889 break;
890 }
891 } while (iter != stop);
892
893 if (iter == stop) {
894 break;
895 }
896 }
897 iter = iter->next;
898 }
899 break;
900 case LYS_CASE:
901 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100902 if (parent) {
903 start = parent->child;
904 } else {
905 start = module->data;
906 }
907
908 LY_TREE_FOR(start, iter) {
Radek Krejci07911992015-08-14 15:13:31 +0200909 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
910 continue;
911 }
912
Radek Krejci749190d2016-02-18 16:26:25 +0100913 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100914 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200915 return EXIT_FAILURE;
916 }
917 }
918 break;
919 default:
920 /* no check needed */
921 break;
922 }
923
924 return EXIT_SUCCESS;
925}
926
Michal Vasko0d343d12015-08-24 14:57:36 +0200927/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200928int
Radek Krejci10c760e2015-08-14 14:45:43 +0200929lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
930{
Radek Krejci92720552015-10-05 15:28:27 +0200931 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200932 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200933
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200934 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200935
Radek Krejci10c760e2015-08-14 14:45:43 +0200936 if (parent) {
937 type = parent->nodetype;
938 module = parent->module;
939 } else {
940 assert(module);
941 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200942 }
943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200944 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200945 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200946 case LYS_CONTAINER:
947 case LYS_LIST:
948 case LYS_GROUPING:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200949 if (!(child->nodetype &
950 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
951 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
952 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
953 return EXIT_FAILURE;
954 }
955 break;
Radek Krejci76512572015-08-04 09:47:08 +0200956 case LYS_USES:
957 case LYS_INPUT:
958 case LYS_OUTPUT:
959 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200960 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200961 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
962 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100963 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200964 return EXIT_FAILURE;
965 }
966 break;
Radek Krejci76512572015-08-04 09:47:08 +0200967 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200968 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200969 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100970 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200971 return EXIT_FAILURE;
972 }
973 break;
Radek Krejci76512572015-08-04 09:47:08 +0200974 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200975 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200976 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100977 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200978 return EXIT_FAILURE;
979 }
980 break;
Radek Krejci76512572015-08-04 09:47:08 +0200981 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200982 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200983 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100984 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200985 return EXIT_FAILURE;
986 }
987 break;
Radek Krejci76512572015-08-04 09:47:08 +0200988 case LYS_LEAF:
989 case LYS_LEAFLIST:
990 case LYS_ANYXML:
Radek Krejci48464ed2016-03-17 15:44:09 +0100991 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
992 LOGVAL(LYE_SPEC, LY_VLOG_LYS, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100993 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200994 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200995 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200996 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200997 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200998 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100999 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001000 return EXIT_FAILURE;
1001 }
Michal Vasko591e0b22015-08-13 13:53:43 +02001002 break;
1003 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +02001004 /* top level */
1005 if (!(child->nodetype &
1006 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
1007 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001008 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +02001009 return EXIT_FAILURE;
1010 }
1011
Radek Krejcic071c542016-01-27 14:57:51 +01001012 break;
Radek Krejci10c760e2015-08-14 14:45:43 +02001013 }
1014
1015 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +02001016 if (lys_check_id(child, parent, module)) {
1017 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001018 }
Radek Krejcib7155b52015-06-10 17:03:01 +02001019
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001020 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001021 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001022 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001023
Radek Krejci10c760e2015-08-14 14:45:43 +02001024 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +02001025 if (module->data) {
1026 module->data->prev->next = child;
1027 child->prev = module->data->prev;
1028 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001029 } else {
Radek Krejci92720552015-10-05 15:28:27 +02001030 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001031 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001032 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +02001033 if (!parent->child) {
1034 /* the only/first child of the parent */
1035 parent->child = child;
1036 child->parent = parent;
1037 iter = child;
1038 } else {
1039 /* add a new child at the end of parent's child list */
1040 iter = parent->child->prev;
1041 iter->next = child;
1042 child->prev = iter;
1043 }
1044 while (iter->next) {
1045 iter = iter->next;
1046 iter->parent = parent;
1047 }
1048 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001049 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001050
Radek Krejci41771502016-04-14 17:52:32 +02001051 /* propagate information about status data presence */
1052 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML)) &&
1053 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +02001054 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +02001055 /* store it only into container or list - the only data inner nodes */
1056 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
1057 if (iter->flags & LYS_INCL_STATUS) {
1058 /* done, someone else set it already from here */
1059 break;
1060 }
1061 /* set flag about including status data */
1062 iter->flags |= LYS_INCL_STATUS;
1063 }
1064 }
1065 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001066 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001067}
1068
Radek Krejcia1df1682016-04-11 14:56:59 +02001069static const struct lys_module *
1070lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001071{
Radek Krejcia1df1682016-04-11 14:56:59 +02001072 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001073 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +02001074 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001075
Radek Krejcif347abc2016-06-22 10:18:47 +02001076 ly_errno = LY_SUCCESS;
1077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001078 if (!ctx || !data) {
1079 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1080 return NULL;
1081 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001082
Radek Krejcia1df1682016-04-11 14:56:59 +02001083 if (!internal && format == LYS_IN_YANG) {
1084 /* enlarge data by 2 bytes for flex */
1085 len = strlen(data);
1086 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
1087 if (!enlarged_data) {
1088 LOGMEM;
1089 return NULL;
1090 }
1091 memcpy(enlarged_data, data, len);
1092 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1093 data = enlarged_data;
1094 }
1095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001096 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001097 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +01001098 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001099 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001100 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001101 mod = yang_read_module(ctx, data, 0, NULL, 1);
1102 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001103 default:
Radek Krejcia1df1682016-04-11 14:56:59 +02001104 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001105 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001106 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001107
Radek Krejcia1df1682016-04-11 14:56:59 +02001108 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001109 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001110}
1111
Radek Krejcia1df1682016-04-11 14:56:59 +02001112API const struct lys_module *
1113lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
1114{
1115 return lys_parse_mem_(ctx, data, format, 0);
1116}
1117
Michal Vasko5a721fd2016-02-16 12:16:48 +01001118struct lys_submodule *
1119lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001120{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001121 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001122
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001123 assert(module);
1124 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001125
Radek Krejcic071c542016-01-27 14:57:51 +01001126 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +02001127 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001129 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001130 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001131 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001132 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001133 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001134 submod = yang_read_submodule(module, data, 0, unres);
1135 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001136 default:
Radek Krejci90a550a2016-04-13 16:00:58 +02001137 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001138 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001139 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001140
Michal Vasko5a721fd2016-02-16 12:16:48 +01001141 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001142}
1143
Michal Vasko1e62a092015-12-01 12:27:20 +01001144API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001145lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1146{
1147 int fd;
1148 const struct lys_module *ret;
1149
1150 if (!ctx || !path) {
1151 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1152 return NULL;
1153 }
1154
1155 fd = open(path, O_RDONLY);
1156 if (fd == -1) {
1157 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1158 return NULL;
1159 }
1160
1161 ret = lys_parse_fd(ctx, fd, format);
1162 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +01001163
Radek Krejcia77904e2016-02-25 16:23:45 +01001164 if (ret && !ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001165 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +01001166 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +01001167 }
1168
Michal Vasko662610a2015-12-07 11:25:45 +01001169 return ret;
1170}
1171
1172API const struct lys_module *
1173lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001174{
Michal Vasko1e62a092015-12-01 12:27:20 +01001175 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001176 struct stat sb;
1177 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001178 char buf[PATH_MAX];
1179 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001180
1181 if (!ctx || fd < 0) {
1182 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1183 return NULL;
1184 }
1185
Radek Krejci10a833c2015-12-16 15:28:37 +01001186 if (fstat(fd, &sb) == -1) {
1187 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1188 return NULL;
1189 }
Radek Krejcib051f722016-02-25 15:12:21 +01001190 if (!S_ISREG(sb.st_mode)) {
1191 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
1192 return NULL;
1193 }
1194
Michal Vasko164d9012016-04-01 10:16:59 +02001195 if (!sb.st_size) {
1196 LOGERR(LY_EINVAL, "File empty.");
1197 return NULL;
1198 }
1199
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001200 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001201 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001202 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001203 return NULL;
1204 }
Radek Krejcia1df1682016-04-11 14:56:59 +02001205 module = lys_parse_mem_(ctx, addr, format, 1);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001206 munmap(addr, sb.st_size + 2);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001207
Radek Krejcia77904e2016-02-25 16:23:45 +01001208 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001209 /* get URI if there is /proc */
1210 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001211 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1212 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1213 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1214 }
1215 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001216 }
Radek Krejcib051f722016-02-25 15:12:21 +01001217 }
1218
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001219 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001220}
1221
Michal Vasko5a721fd2016-02-16 12:16:48 +01001222struct lys_submodule *
1223lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001224{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001225 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001226 struct stat sb;
1227 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001229 assert(module);
1230 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001231
Radek Krejci10a833c2015-12-16 15:28:37 +01001232 if (fstat(fd, &sb) == -1) {
1233 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001234 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001235 }
Michal Vasko164d9012016-04-01 10:16:59 +02001236
1237 if (!sb.st_size) {
1238 LOGERR(LY_EINVAL, "File empty.");
1239 return NULL;
1240 }
1241
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001242 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001243 if (addr == MAP_FAILED) {
1244 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001245 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001246 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001247 submodule = lys_submodule_parse(module, addr, format, unres);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001248 munmap(addr, sb.st_size + 2);
Radek Krejciefaeba32015-05-27 14:30:57 +02001249
Michal Vasko5a721fd2016-02-16 12:16:48 +01001250 return submodule;
1251
Radek Krejciefaeba32015-05-27 14:30:57 +02001252}
1253
Radek Krejci1d82ef62015-08-07 14:44:40 +02001254static struct lys_restr *
1255lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001256{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001257 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001258 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001259
Radek Krejci3733a802015-06-19 13:43:21 +02001260 if (!size) {
1261 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001262 }
Radek Krejci3733a802015-06-19 13:43:21 +02001263
1264 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001265 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001266 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001267 return NULL;
1268 }
Radek Krejci3733a802015-06-19 13:43:21 +02001269 for (i = 0; i < size; i++) {
1270 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1271 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1272 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1273 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1274 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1275 }
1276
1277 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001278}
1279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001280void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001281lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001282{
1283 assert(ctx);
1284 if (!restr) {
1285 return;
1286 }
1287
1288 lydict_remove(ctx, restr->expr);
1289 lydict_remove(ctx, restr->dsc);
1290 lydict_remove(ctx, restr->ref);
1291 lydict_remove(ctx, restr->eapptag);
1292 lydict_remove(ctx, restr->emsg);
1293}
1294
Michal Vaskob84f88a2015-09-24 13:16:10 +02001295static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001296type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001297 LY_DATA_TYPE base, int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001298{
1299 int i;
1300
1301 switch (base) {
1302 case LY_TYPE_BINARY:
1303 if (old->info.binary.length) {
1304 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
1305 }
1306 break;
1307
1308 case LY_TYPE_BITS:
1309 new->info.bits.count = old->info.bits.count;
1310 if (new->info.bits.count) {
1311 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1312 if (!new->info.bits.bit) {
1313 LOGMEM;
1314 return -1;
1315 }
1316 for (i = 0; i < new->info.bits.count; i++) {
1317 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1318 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1319 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1320 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1321 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1322 }
1323 }
1324 break;
1325
1326 case LY_TYPE_DEC64:
1327 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001328 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001329 if (old->info.dec64.range) {
1330 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
1331 }
1332 break;
1333
1334 case LY_TYPE_ENUM:
1335 new->info.enums.count = old->info.enums.count;
1336 if (new->info.enums.count) {
1337 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1338 if (!new->info.enums.enm) {
1339 LOGMEM;
1340 return -1;
1341 }
1342 for (i = 0; i < new->info.enums.count; i++) {
1343 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1344 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1345 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1346 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1347 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
1348 }
1349 }
1350 break;
1351
1352 case LY_TYPE_IDENT:
1353 if (old->info.ident.ref) {
1354 new->info.ident.ref = old->info.ident.ref;
1355 } else {
1356 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vasko3767fb22016-07-21 12:10:57 +02001357 if (i > -1 && (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001358 return -1;
1359 }
1360 }
1361 break;
1362
1363 case LY_TYPE_INST:
1364 new->info.inst.req = old->info.inst.req;
1365 break;
1366
1367 case LY_TYPE_INT8:
1368 case LY_TYPE_INT16:
1369 case LY_TYPE_INT32:
1370 case LY_TYPE_INT64:
1371 case LY_TYPE_UINT8:
1372 case LY_TYPE_UINT16:
1373 case LY_TYPE_UINT32:
1374 case LY_TYPE_UINT64:
1375 if (old->info.num.range) {
1376 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
1377 }
1378 break;
1379
1380 case LY_TYPE_LEAFREF:
1381 if (old->info.lref.path) {
1382 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko5d631402016-07-21 13:15:15 +02001383 if (!tpdftype && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001384 return -1;
1385 }
1386 }
1387 break;
1388
1389 case LY_TYPE_STRING:
1390 if (old->info.str.length) {
1391 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
1392 }
1393 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
1394 new->info.str.pat_count = old->info.str.pat_count;
1395 break;
1396
1397 case LY_TYPE_UNION:
1398 new->info.uni.count = old->info.uni.count;
1399 if (new->info.uni.count) {
1400 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1401 if (!new->info.uni.types) {
1402 LOGMEM;
1403 return -1;
1404 }
1405 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001406 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001407 return -1;
1408 }
1409 }
1410 }
1411 break;
1412
1413 default:
1414 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1415 break;
1416 }
1417 return EXIT_SUCCESS;
1418}
1419
1420struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001421lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1422 int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001423{
1424 struct yang_type *new;
1425
1426 new = calloc(1, sizeof *new);
1427 if (!new) {
1428 LOGMEM;
1429 return NULL;
1430 }
1431 new->flags = old->flags;
1432 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001433 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001434 new->type = type;
1435 if (!new->name) {
1436 LOGMEM;
1437 goto error;
1438 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001439 if (type_dup(module, parent, type, old->type, new->base, tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001440 new->type->base = new->base;
1441 lys_type_free(module->ctx, new->type);
1442 memset(&new->type->info, 0, sizeof new->type->info);
1443 goto error;
1444 }
1445 return new;
1446
1447 error:
1448 free(new);
1449 return NULL;
1450}
1451
1452static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001453lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001454 int tpdftype, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001455{
1456 int i;
1457
Michal Vasko1dca6882015-10-22 14:29:42 +02001458 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001459 new->base = old->base;
1460 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001461 new->parent = (struct lys_tpdf *)parent;
Radek Krejci3733a802015-06-19 13:43:21 +02001462
Radek Krejci3a5501d2016-07-18 22:03:34 +02001463 i = unres_schema_find(unres, old, tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001464 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001465 /* HACK (serious one) for unres */
1466 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001467 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001468 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, tpdftype, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001469 } else {
1470 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1471 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001472 /* all these unres additions can fail even though they did not before */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001473 if (!new->der || unres_schema_add_node(mod, unres, new,
Michal Vasko5d631402016-07-21 13:15:15 +02001474 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001475 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001476 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001477 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001478 }
1479
Radek Krejci3a5501d2016-07-18 22:03:34 +02001480 return type_dup(mod, parent, new, old, new->base, tpdftype, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001481}
1482
1483void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001484lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001485{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001486 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001488 assert(ctx);
1489 if (!type) {
1490 return;
1491 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001492
Michal Vasko1dca6882015-10-22 14:29:42 +02001493 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001495 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001496 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001497 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001498 free(type->info.binary.length);
1499 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001500 case LY_TYPE_BITS:
1501 for (i = 0; i < type->info.bits.count; i++) {
1502 lydict_remove(ctx, type->info.bits.bit[i].name);
1503 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1504 lydict_remove(ctx, type->info.bits.bit[i].ref);
1505 }
1506 free(type->info.bits.bit);
1507 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001508
1509 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001510 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001511 free(type->info.dec64.range);
1512 break;
1513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001514 case LY_TYPE_ENUM:
1515 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001516 lydict_remove(ctx, type->info.enums.enm[i].name);
1517 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1518 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001519 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001520 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001521 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001522
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001523 case LY_TYPE_INT8:
1524 case LY_TYPE_INT16:
1525 case LY_TYPE_INT32:
1526 case LY_TYPE_INT64:
1527 case LY_TYPE_UINT8:
1528 case LY_TYPE_UINT16:
1529 case LY_TYPE_UINT32:
1530 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001531 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001532 free(type->info.num.range);
1533 break;
1534
Radek Krejcidc4c1412015-06-19 15:39:54 +02001535 case LY_TYPE_LEAFREF:
1536 lydict_remove(ctx, type->info.lref.path);
1537 break;
1538
Radek Krejci3733a802015-06-19 13:43:21 +02001539 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001540 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001541 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001542 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001543 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001544 }
1545 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001546 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001547
Radek Krejcie4c366b2015-07-02 10:11:31 +02001548 case LY_TYPE_UNION:
1549 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001550 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001551 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001552 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001553 break;
1554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001555 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001556 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001557 break;
1558 }
Radek Krejci5a065542015-05-22 15:02:07 +02001559}
1560
Radek Krejci1d82ef62015-08-07 14:44:40 +02001561static void
1562lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001563{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001564 assert(ctx);
1565 if (!tpdf) {
1566 return;
1567 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001569 lydict_remove(ctx, tpdf->name);
1570 lydict_remove(ctx, tpdf->dsc);
1571 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001572
Radek Krejci1d82ef62015-08-07 14:44:40 +02001573 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001575 lydict_remove(ctx, tpdf->units);
1576 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001577}
1578
Michal Vaskob84f88a2015-09-24 13:16:10 +02001579static struct lys_tpdf *
1580lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1581{
1582 struct lys_tpdf *result;
1583 int i, j;
1584
1585 if (!size) {
1586 return NULL;
1587 }
1588
1589 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001590 if (!result) {
1591 LOGMEM;
1592 return NULL;
1593 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001594 for (i = 0; i < size; i++) {
1595 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1596 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1597 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1598 result[i].flags = old[i].flags;
1599 result[i].module = old[i].module;
1600
Radek Krejci3a5501d2016-07-18 22:03:34 +02001601 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), 1, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001602 for (j = 0; j <= i; ++j) {
1603 lys_tpdf_free(mod->ctx, &result[j]);
1604 }
1605 free(result);
1606 return NULL;
1607 }
1608
1609 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1610 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1611 }
1612
1613 return result;
1614}
1615
Radek Krejci1d82ef62015-08-07 14:44:40 +02001616static struct lys_when *
1617lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001618{
Radek Krejci76512572015-08-04 09:47:08 +02001619 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001620
1621 if (!old) {
1622 return NULL;
1623 }
1624
1625 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001626 if (!new) {
1627 LOGMEM;
1628 return NULL;
1629 }
Radek Krejci00768f42015-06-18 17:04:04 +02001630 new->cond = lydict_insert(ctx, old->cond, 0);
1631 new->dsc = lydict_insert(ctx, old->dsc, 0);
1632 new->ref = lydict_insert(ctx, old->ref, 0);
1633
1634 return new;
1635}
1636
Michal Vasko0308dd62015-10-07 09:14:40 +02001637void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001638lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001639{
1640 if (!w) {
1641 return;
1642 }
1643
1644 lydict_remove(ctx, w->cond);
1645 lydict_remove(ctx, w->dsc);
1646 lydict_remove(ctx, w->ref);
1647
1648 free(w);
1649}
1650
Radek Krejcib7f5e412015-08-13 10:15:51 +02001651static void
Radek Krejci9ff0a922016-07-14 13:08:05 +02001652lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size)
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001653{
1654 uint8_t i;
1655
1656 for (i = 0; i < iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02001657 free(iffeature[i].expr);
1658 free(iffeature[i].features);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001659 }
1660 free(iffeature);
1661}
1662
1663static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001664lys_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 +02001665{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001666 struct lys_node *next, *sub;
1667
Radek Krejcic071c542016-01-27 14:57:51 +01001668 /* children from a resolved augment are freed under the target node */
Michal Vaskod2fbade2016-05-02 17:14:00 +02001669 if (!aug->target) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001670 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001671 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001672 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001673 }
1674
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001675 lydict_remove(ctx, aug->target_name);
1676 lydict_remove(ctx, aug->dsc);
1677 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001678
Radek Krejci9ff0a922016-07-14 13:08:05 +02001679 lys_iffeature_free(aug->iffeature, aug->iffeature_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001680
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001681 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001682}
1683
Radek Krejci76512572015-08-04 09:47:08 +02001684static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001685lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001686{
Radek Krejci76512572015-08-04 09:47:08 +02001687 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001688 struct lys_node *old_child, *new_child;
1689 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001691 if (!size) {
1692 return NULL;
1693 }
Radek Krejci106efc02015-06-10 14:36:27 +02001694
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001695 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001696 if (!new) {
1697 LOGMEM;
1698 return NULL;
1699 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001700 for (i = 0; i < size; i++) {
1701 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1702 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1703 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1704 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001705 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001706 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001707
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001708 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001709 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1710 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001711 LOGINT;
1712 free(new);
1713 return NULL;
1714 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001715 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001716
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001717 /* Correct the augment nodes.
1718 * This function can only be called from lys_node_dup() with uses
1719 * being the node duplicated, so we must have a case of grouping
1720 * with a uses with augments. The augmented nodes have already been
1721 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001722 * (it was set to their actual data parent, not an augment), and
1723 * the new augment does not have child pointer to its augment nodes,
1724 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001725 */
1726 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001727 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001728 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001729 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001730 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001731 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001732 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001733 LY_TREE_FOR(old[i].child, old_child) {
1734 /* all augment nodes were connected as siblings, there can be no more after this */
1735 if (old_child->parent != (struct lys_node *)&old[i]) {
1736 break;
1737 }
1738
Radek Krejci749190d2016-02-18 16:26:25 +01001739 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001740
1741 new_child->parent = (struct lys_node *)&new[i];
1742 new_child = new_child->next;
1743 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001744 }
Radek Krejci106efc02015-06-10 14:36:27 +02001745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001746 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001747}
1748
Radek Krejci76512572015-08-04 09:47:08 +02001749static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001750lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001751{
Radek Krejci76512572015-08-04 09:47:08 +02001752 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001753 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001754
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001755 if (!size) {
1756 return NULL;
1757 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001758
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001759 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001760 if (!result) {
1761 LOGMEM;
1762 return NULL;
1763 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001764 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001765 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001766 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1767 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001768 result[i].flags = old[i].flags;
1769 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001771 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001772 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001773
Radek Krejci76512572015-08-04 09:47:08 +02001774 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001775 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001776 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001777 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001778 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001779 result[i].mod.list = old[i].mod.list;
1780 }
1781 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001782
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001783 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001784}
1785
Radek Krejci1d82ef62015-08-07 14:44:40 +02001786static void
1787lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001788{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001789 assert(ctx);
1790 if (!ident) {
1791 return;
1792 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001793
Radek Krejci1b61d0e2016-04-15 13:55:44 +02001794 free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001795 lydict_remove(ctx, ident->name);
1796 lydict_remove(ctx, ident->dsc);
1797 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001798
1799}
1800
Radek Krejci1d82ef62015-08-07 14:44:40 +02001801static void
1802lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001803{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001804 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001805
Radek Krejcid12f57b2015-08-06 10:43:39 +02001806 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001807 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001808 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001809 }
1810 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001811}
1812
Radek Krejci1d82ef62015-08-07 14:44:40 +02001813static void
Michal Vasko44fb6382016-06-29 11:12:27 +02001814lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02001815{
1816 int i;
1817
1818 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1819 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001820 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001821 }
1822 free(io->tpdf);
1823}
1824
Radek Krejci1d82ef62015-08-07 14:44:40 +02001825static void
1826lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001827{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001828 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001830 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001831 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001832 }
1833 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001834
Radek Krejci1d82ef62015-08-07 14:44:40 +02001835 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001836}
1837
Radek Krejci1d82ef62015-08-07 14:44:40 +02001838static void
1839lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001840{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001841 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001842
Radek Krejci46c4cd72016-01-21 15:13:52 +01001843 if (leaf->child) {
1844 /* leafref backlinks */
1845 ly_set_free((struct ly_set *)leaf->child);
1846 }
1847
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001848 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001849 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001850 }
1851 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001852
Radek Krejci1d82ef62015-08-07 14:44:40 +02001853 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001854
Radek Krejci1d82ef62015-08-07 14:44:40 +02001855 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001856 lydict_remove(ctx, leaf->units);
1857 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001858}
1859
Radek Krejci1d82ef62015-08-07 14:44:40 +02001860static void
1861lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001862{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001863 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001864
Radek Krejci46c4cd72016-01-21 15:13:52 +01001865 if (llist->child) {
1866 /* leafref backlinks */
1867 ly_set_free((struct ly_set *)llist->child);
1868 }
1869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001870 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001871 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001872 }
1873 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001874
Radek Krejci1d82ef62015-08-07 14:44:40 +02001875 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001876
Radek Krejci1d82ef62015-08-07 14:44:40 +02001877 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001878 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001879}
1880
Radek Krejci1d82ef62015-08-07 14:44:40 +02001881static void
1882lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001883{
Radek Krejci581ce772015-11-10 17:22:40 +01001884 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001885
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001886 /* handle only specific parts for LY_NODE_LIST */
1887 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001888 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001889 }
1890 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001891
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001892 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001893 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001894 }
1895 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001896
Radek Krejci1d82ef62015-08-07 14:44:40 +02001897 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001899 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02001900 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001901 lydict_remove(ctx, list->unique[i].expr[j]);
1902 }
1903 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001904 }
1905 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001906
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001907 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001908}
1909
Radek Krejci1d82ef62015-08-07 14:44:40 +02001910static void
1911lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001912{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001915 /* handle only specific parts for LY_NODE_CONTAINER */
1916 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001918 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001919 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001920 }
1921 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001922
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001923 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001924 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001925 }
1926 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001927
Radek Krejci1d82ef62015-08-07 14:44:40 +02001928 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001929}
1930
Radek Krejci1d82ef62015-08-07 14:44:40 +02001931static void
1932lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001933{
1934 lydict_remove(ctx, f->name);
1935 lydict_remove(ctx, f->dsc);
1936 lydict_remove(ctx, f->ref);
Radek Krejci9ff0a922016-07-14 13:08:05 +02001937 lys_iffeature_free(f->iffeature, f->iffeature_size);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001938}
1939
Radek Krejci1d82ef62015-08-07 14:44:40 +02001940static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001941lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001942{
Radek Krejci581ce772015-11-10 17:22:40 +01001943 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001944 struct ly_ctx *ctx;
1945 struct lys_node *next, *elem;
1946
1947 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001948
1949 lydict_remove(ctx, dev->target_name);
1950 lydict_remove(ctx, dev->dsc);
1951 lydict_remove(ctx, dev->ref);
1952
Michal Vaskoff006c12016-02-17 11:15:19 +01001953 /* the module was freed, but we only need the context from orig_node, use ours */
1954 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1955 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1956 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1957 elem->module = module;
1958
1959 LY_TREE_DFS_END(dev->orig_node, next, elem);
1960 }
1961 lys_node_free(dev->orig_node, NULL, 0);
1962 } else {
1963 /* it's just a shallow copy, freeing one node */
1964 dev->orig_node->module = module;
1965 lys_node_free(dev->orig_node, NULL, 1);
1966 }
1967
Radek Krejcieb00f512015-07-01 16:44:58 +02001968 for (i = 0; i < dev->deviate_size; i++) {
1969 lydict_remove(ctx, dev->deviate[i].dflt);
1970 lydict_remove(ctx, dev->deviate[i].units);
1971
1972 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1973 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001974 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001975 }
1976 free(dev->deviate[i].must);
1977
1978 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001979 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1980 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1981 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01001982 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001983 }
1984 free(dev->deviate[i].unique);
1985 }
1986 }
1987 free(dev->deviate);
1988}
1989
Radek Krejci1d82ef62015-08-07 14:44:40 +02001990static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001991lys_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 +02001992{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001993 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001994
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001995 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001996 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001997 lydict_remove(ctx, uses->refine[i].dsc);
1998 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001999
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002000 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002001 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002002 }
2003 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002004
Radek Krejci76512572015-08-04 09:47:08 +02002005 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002006 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02002007 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002008 lydict_remove(ctx, uses->refine[i].mod.presence);
2009 }
2010 }
2011 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002013 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002014 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002015 }
2016 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002017
Radek Krejci1d82ef62015-08-07 14:44:40 +02002018 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002019}
2020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002021void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002022lys_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 +02002023{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002024 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002025 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002026
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002027 if (!node) {
2028 return;
2029 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002030
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002031 assert(node->module);
2032 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002033
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002034 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002035
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002036 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002037 if (node->priv && private_destructor) {
2038 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002039 }
2040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002041 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002042 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002043 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002044 lys_iffeature_free(node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002045 lydict_remove(ctx, node->dsc);
2046 lydict_remove(ctx, node->ref);
2047 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002048
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002049 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002050 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002051 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002052 }
2053 }
2054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002055 /* specific part */
2056 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002057 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002058 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002059 break;
Radek Krejci76512572015-08-04 09:47:08 +02002060 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002061 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002062 break;
Radek Krejci76512572015-08-04 09:47:08 +02002063 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002064 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002065 break;
Radek Krejci76512572015-08-04 09:47:08 +02002066 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002067 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 break;
Radek Krejci76512572015-08-04 09:47:08 +02002069 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002070 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002071 break;
Radek Krejci76512572015-08-04 09:47:08 +02002072 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002073 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002074 break;
Radek Krejci76512572015-08-04 09:47:08 +02002075 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002076 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002077 break;
Radek Krejci76512572015-08-04 09:47:08 +02002078 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002079 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002080 break;
Radek Krejci76512572015-08-04 09:47:08 +02002081 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002082 /* do nothing */
2083 break;
Radek Krejci76512572015-08-04 09:47:08 +02002084 case LYS_GROUPING:
2085 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002086 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +02002087 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002088 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002089 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002090
2091 case LYS_INPUT:
2092 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02002093 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002094 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02002095 case LYS_UNKNOWN:
2096 LOGINT;
2097 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 }
Radek Krejci5a065542015-05-22 15:02:07 +02002099
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002100 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002101 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002102 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002103}
2104
Michal Vasko1e62a092015-12-01 12:27:20 +01002105const struct lys_module *
2106lys_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 +02002107{
Radek Krejcic071c542016-01-27 14:57:51 +01002108 const struct lys_module *main_module;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002109 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002110
Michal Vaskoa7789a82016-02-11 15:42:55 +01002111 assert(!prefix || !name);
2112
Michal Vaskob6729c62015-10-21 12:09:47 +02002113 if (prefix && !pref_len) {
2114 pref_len = strlen(prefix);
2115 }
2116 if (name && !name_len) {
2117 name_len = strlen(name);
2118 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002119
Radek Krejcic4283442016-04-22 09:19:27 +02002120 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002121
2122 /* module own prefix, submodule own prefix, (sub)module own name */
2123 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2124 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002125 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002126 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002127 }
2128
Michal Vasko8ce24d72015-10-21 11:27:26 +02002129 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002130 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2131 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002132 return module->imp[i].module;
2133 }
2134 }
2135
2136 return NULL;
2137}
2138
Michal Vasko13b15832015-08-19 11:04:48 +02002139/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002141module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002142{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002144 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002145 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002147 assert(module->ctx);
2148 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002149
Michal Vaskob746fff2016-02-11 11:37:50 +01002150 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002151 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002152 lydict_remove(ctx, module->imp[i].prefix);
Radek Krejci225376f2016-02-16 17:36:22 +01002153 }
Radek Krejcidce51452015-06-16 15:20:08 +02002154 free(module->imp);
2155
Radek Krejcic071c542016-01-27 14:57:51 +01002156 /* submodules don't have data tree, the data nodes
2157 * are placed in the main module altogether */
2158 if (!module->type) {
2159 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002160 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002161 }
Radek Krejci21181962015-06-30 14:11:00 +02002162 }
Radek Krejci5a065542015-05-22 15:02:07 +02002163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 lydict_remove(ctx, module->dsc);
2165 lydict_remove(ctx, module->ref);
2166 lydict_remove(ctx, module->org);
2167 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002168 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002169
Radek Krejcieb00f512015-07-01 16:44:58 +02002170 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002171 for (i = 0; i < module->rev_size; i++) {
2172 lydict_remove(ctx, module->rev[i].dsc);
2173 lydict_remove(ctx, module->rev[i].ref);
2174 }
2175 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002176
Radek Krejcieb00f512015-07-01 16:44:58 +02002177 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002178 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002179 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 }
2181 module->ident_size = 0;
2182 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002183
Radek Krejcieb00f512015-07-01 16:44:58 +02002184 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002185 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002186 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 }
2188 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002189
Radek Krejcieb00f512015-07-01 16:44:58 +02002190 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002191 for (i = 0; i < module->inc_size; i++) {
Radek Krejcic071c542016-01-27 14:57:51 +01002192 /* complete submodule free is done only from main module since
2193 * submodules propagate their includes to the main module */
2194 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002195 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002196 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 }
2198 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002199
Radek Krejcieb00f512015-07-01 16:44:58 +02002200 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002201 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002202 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002203 }
2204 free(module->augment);
2205
Radek Krejcieb00f512015-07-01 16:44:58 +02002206 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002207 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002208 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002209 }
2210 free(module->features);
2211
Radek Krejcieb00f512015-07-01 16:44:58 +02002212 /* deviations */
2213 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002214 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002215 }
2216 free(module->deviation);
2217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002218 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002219 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002220}
2221
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002222void
Michal Vaskob746fff2016-02-11 11:37:50 +01002223lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002224{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 if (!submodule) {
2226 return;
2227 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002230 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002231
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002232 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002235}
2236
Radek Krejci3a5501d2016-07-18 22:03:34 +02002237static int
2238ingrouping(const struct lys_node *node)
2239{
2240 const struct lys_node *iter = node;
2241 assert(node);
2242
2243 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2244 if (!iter) {
2245 return 0;
2246 } else {
2247 return 1;
2248 }
2249}
2250
Radek Krejci76512572015-08-04 09:47:08 +02002251struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002252lys_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 +01002253 uint8_t nacm, struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002254{
Radek Krejcic071c542016-01-27 14:57:51 +01002255 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002257 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002258 unsigned int size, size1, size2;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002259
Michal Vaskoc07187d2015-08-13 15:20:57 +02002260 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002261 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002262 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002263 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002264 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002265 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002266 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002267 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002268 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002269 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002270 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002271 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002272 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002273 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002274 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002275 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002276 struct lys_node_rpc_action *rpc = NULL;
2277 struct lys_node_rpc_action *rpc_orig = (struct lys_node_rpc_action *)node;
2278 struct lys_node_inout *io = NULL;
2279 struct lys_node_inout *io_orig = (struct lys_node_inout *)node;
2280 struct lys_node_rpc_action *ntf = NULL;
2281 struct lys_node_rpc_action *ntf_orig = (struct lys_node_rpc_action *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002282 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002283 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 /* we cannot just duplicate memory since the strings are stored in
2286 * dictionary and we need to update dictionary counters.
2287 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002288
Radek Krejci1d82ef62015-08-07 14:44:40 +02002289 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002290 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002291 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002292 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002293 break;
2294
Radek Krejci76512572015-08-04 09:47:08 +02002295 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002296 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002297 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002298 break;
2299
Radek Krejci76512572015-08-04 09:47:08 +02002300 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002301 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002302 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002303 break;
2304
Radek Krejci76512572015-08-04 09:47:08 +02002305 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002306 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002307 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002308 break;
2309
Radek Krejci76512572015-08-04 09:47:08 +02002310 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002311 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002312 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002313 break;
2314
Radek Krejci76512572015-08-04 09:47:08 +02002315 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002316 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002317 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002318 break;
2319
Radek Krejci76512572015-08-04 09:47:08 +02002320 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002322 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002323 break;
2324
Radek Krejci76512572015-08-04 09:47:08 +02002325 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002326 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002327 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002328 break;
2329
Radek Krejci76512572015-08-04 09:47:08 +02002330 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002331 grp = calloc(1, sizeof *grp);
2332 retval = (struct lys_node *)grp;
2333 break;
2334
Radek Krejci76512572015-08-04 09:47:08 +02002335 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002336 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002337 rpc = calloc(1, sizeof *rpc);
2338 retval = (struct lys_node *)rpc;
2339 break;
2340
Radek Krejci76512572015-08-04 09:47:08 +02002341 case LYS_INPUT:
2342 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002343 io = calloc(1, sizeof *io);
2344 retval = (struct lys_node *)io;
2345 break;
2346
Radek Krejci76512572015-08-04 09:47:08 +02002347 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002348 ntf = calloc(1, sizeof *ntf);
2349 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002350 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002352 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002353 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002354 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002355 }
Radek Krejcib388c152015-06-04 17:03:03 +02002356
Michal Vasko253035f2015-12-17 16:58:13 +01002357 if (!retval) {
2358 LOGMEM;
2359 return NULL;
2360 }
2361
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002362 /*
2363 * duplicate generic part of the structure
2364 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002365 retval->name = lydict_insert(ctx, node->name, 0);
2366 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2367 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002368 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002369 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002370 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002371 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002372 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002373 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002374
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002375 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002376 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002377
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002378 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002379
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002380 retval->iffeature_size = node->iffeature_size;
2381 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2382 if (!retval->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002383 LOGMEM;
2384 goto error;
2385 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002386
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002387 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002388 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002389 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2390 if (size1) {
2391 /* there is something to duplicate */
2392
2393 /* duplicate compiled expression */
2394 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2395 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2396 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2397
2398 /* list of feature pointer must be updated to point to the resulting tree */
2399 retval->iffeature[i].features = malloc(size2 * sizeof *retval->iffeature[i].features);
2400 for (j = 0; (unsigned int)j < size2; j++) {
2401 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2402 &retval->iffeature[i].features[j]);
2403 if (rc == EXIT_SUCCESS) {
2404 /* feature is not resolved, duplicate the expression string */
2405 retval->iffeature[i].features[j] = (void *)strdup((char *)node->iffeature[i].features[j]);
2406 } else if (rc == EXIT_FAILURE) {
2407 /* feature is resolved in origin, so copy it
2408 * - duplication is used for instantiating groupings
2409 * and if-feature inside grouping is supposed to be
2410 * resolved inside the original grouping, so we want
2411 * to keep pointers to features from the grouping
2412 * context */
2413 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2414 } else if (rc == -1) {
2415 goto error;
2416 }
2417 }
2418 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002419 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002420
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002421 /* connect it to the parent */
2422 if (lys_node_addchild(parent, retval->module, retval)) {
2423 goto error;
2424 }
Radek Krejcidce51452015-06-16 15:20:08 +02002425
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002426 /* go recursively */
2427 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2428 LY_TREE_FOR(node->child, child) {
2429 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres, 0)) {
2430 goto error;
2431 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002432 }
2433 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002434 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002435 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002436 }
2437
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002438 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002439 * duplicate specific part of the structure
2440 */
2441 switch (node->nodetype) {
2442 case LYS_CONTAINER:
2443 if (cont_orig->when) {
2444 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002445 }
2446 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002447
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002448 cont->must_size = cont_orig->must_size;
2449 cont->tpdf_size = cont_orig->tpdf_size;
2450
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002451 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskodcf98e62016-05-05 17:53:53 +02002452 cont->tpdf = lys_tpdf_dup(module, lys_parent(node), cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002453 break;
2454
2455 case LYS_CHOICE:
2456 if (choice_orig->when) {
2457 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002458 }
2459
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002460 if (!shallow) {
2461 if (choice_orig->dflt) {
2462 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0, LYS_ANYXML
2463 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
2464 | LYS_LIST, (const struct lys_node **)&choice->dflt);
2465 if (rc) {
2466 if (rc == EXIT_FAILURE) {
2467 LOGINT;
2468 }
2469 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002470 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002471 } else {
2472 /* useless to check return value, we don't know whether
2473 * there really wasn't any default defined or it just hasn't
2474 * been resolved, we just hope for the best :)
2475 */
2476 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002477 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002478 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002479 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002480 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002481 break;
2482
2483 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002484 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002485 goto error;
2486 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002487 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2488
2489 if (leaf_orig->dflt) {
2490 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci48464ed2016-03-17 15:44:09 +01002491 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002492 goto error;
2493 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002494 }
2495
2496 leaf->must_size = leaf_orig->must_size;
2497 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002498
2499 if (leaf_orig->when) {
2500 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002501 }
2502 break;
2503
2504 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002505 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002506 goto error;
2507 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002508 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2509
2510 llist->min = llist_orig->min;
2511 llist->max = llist_orig->max;
2512
2513 llist->must_size = llist_orig->must_size;
2514 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002515
2516 if (llist_orig->when) {
2517 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002518 }
2519 break;
2520
2521 case LYS_LIST:
2522 list->min = list_orig->min;
2523 list->max = list_orig->max;
2524
2525 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002526 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002527
Radek Krejci581ce772015-11-10 17:22:40 +01002528 list->tpdf_size = list_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002529 list->tpdf = lys_tpdf_dup(module, lys_parent(node), list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002530
Radek Krejci581ce772015-11-10 17:22:40 +01002531 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002532 if (list->keys_size) {
2533 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002534 if (!list->keys) {
2535 LOGMEM;
2536 goto error;
2537 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002538
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002539 if (!shallow) {
2540 /* we managed to resolve it before, resolve it again manually */
2541 if (list_orig->keys[0]) {
2542 for (i = 0; i < list->keys_size; ++i) {
2543 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2544 (const struct lys_node **)&list->keys[i]);
2545 if (rc) {
2546 if (rc == EXIT_FAILURE) {
2547 LOGINT;
2548 }
2549 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002550 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002551 }
2552 /* it was not resolved yet, add unres copy */
2553 } else {
2554 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2555 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002556 goto error;
2557 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002558 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002559 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002560 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002561 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002562 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002563
Radek Krejci581ce772015-11-10 17:22:40 +01002564 list->unique_size = list_orig->unique_size;
2565 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002566 if (!list->unique) {
2567 LOGMEM;
2568 goto error;
2569 }
Radek Krejci581ce772015-11-10 17:22:40 +01002570 for (i = 0; i < list->unique_size; ++i) {
2571 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2572 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002573 if (!list->unique[i].expr) {
2574 LOGMEM;
2575 goto error;
2576 }
Radek Krejci581ce772015-11-10 17:22:40 +01002577 for (j = 0; j < list->unique[i].expr_size; j++) {
2578 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2579
2580 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002581 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002582 }
2583 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002585 if (list_orig->when) {
2586 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002587 }
Radek Krejcidce51452015-06-16 15:20:08 +02002588 break;
2589
2590 case LYS_ANYXML:
2591 anyxml->must_size = anyxml_orig->must_size;
2592 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002593
2594 if (anyxml_orig->when) {
2595 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002596 }
2597 break;
2598
2599 case LYS_USES:
2600 uses->grp = uses_orig->grp;
2601
2602 if (uses_orig->when) {
2603 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002604 }
2605
2606 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002607 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002608 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002609 if (!shallow) {
2610 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskocda51712016-05-19 15:22:11 +02002611 if (!uses->grp || uses->grp->nacm) {
2612 assert(!uses->child);
Radek Krejci48464ed2016-03-17 15:44:09 +01002613 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002614 goto error;
2615 }
Michal Vasko49168a22015-08-17 16:35:41 +02002616 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002617 } else {
2618 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002619 }
2620 break;
2621
Radek Krejcidce51452015-06-16 15:20:08 +02002622 case LYS_CASE:
2623 if (cs_orig->when) {
2624 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002625 }
2626 break;
2627
2628 case LYS_GROUPING:
2629 grp->tpdf_size = grp_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002630 grp->tpdf = lys_tpdf_dup(module, lys_parent(node), grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002631 break;
2632
2633 case LYS_RPC:
2634 rpc->tpdf_size = rpc_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002635 rpc->tpdf = lys_tpdf_dup(module, lys_parent(node), rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002636 break;
2637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002638 case LYS_INPUT:
2639 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002640 io->tpdf_size = io_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002641 io->tpdf = lys_tpdf_dup(module, lys_parent(node), io_orig->tpdf, io->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002642 break;
2643
Radek Krejcida04f4a2015-05-21 12:54:09 +02002644 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002645 ntf->tpdf_size = ntf_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002646 ntf->tpdf = lys_tpdf_dup(module, lys_parent(node), ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002647 break;
2648
2649 default:
2650 /* LY_NODE_AUGMENT */
2651 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002652 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002653 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002654
2655 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002656
2657error:
2658
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002659 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002660 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002661}
2662
Michal Vasko13b15832015-08-19 11:04:48 +02002663void
Michal Vaskoff006c12016-02-17 11:15:19 +01002664lys_node_switch(struct lys_node *dst, struct lys_node *src)
2665{
2666 struct lys_node *child;
2667
Michal Vaskob42b6972016-06-06 14:21:30 +02002668 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01002669
2670 /* sibling next */
2671 if (dst->prev != dst) {
2672 dst->prev->next = src;
2673 }
2674
2675 /* sibling prev */
2676 if (dst->next) {
2677 dst->next->prev = src;
2678 }
2679
2680 /* parent child prev */
2681 if (!dst->next && dst->parent) {
2682 dst->parent->child->prev = src;
2683 }
2684
2685 /* next */
2686 src->next = dst->next;
2687 dst->next = NULL;
2688
2689 /* prev */
2690 if (dst->prev != dst) {
2691 src->prev = dst->prev;
2692 }
2693 dst->prev = dst;
2694
2695 /* parent child */
2696 if (dst->parent && (dst->parent->child == dst)) {
2697 dst->parent->child = src;
2698 }
2699
2700 /* parent */
2701 src->parent = dst->parent;
2702 dst->parent = NULL;
2703
2704 /* child parent */
2705 LY_TREE_FOR(dst->child, child) {
2706 if (child->parent == dst) {
2707 child->parent = src;
2708 }
2709 }
2710
2711 /* child */
2712 src->child = dst->child;
2713 dst->child = NULL;
2714}
2715
2716void
Michal Vasko627975a2016-02-11 11:39:03 +01002717lys_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 +02002718{
2719 struct ly_ctx *ctx;
2720 int i;
2721
2722 if (!module) {
2723 return;
2724 }
2725
2726 /* remove schema from the context */
2727 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002728 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002729 for (i = 0; i < ctx->models.used; i++) {
2730 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002731 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002732 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002733 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 +02002734 ctx->models.list[ctx->models.used] = NULL;
2735 /* we are done */
2736 break;
2737 }
2738 }
2739 }
2740
2741 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002742 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002743
2744 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002745 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002746
2747 free(module);
2748}
Radek Krejci7e97c352015-06-19 16:26:34 +02002749
2750/*
2751 * op: 1 - enable, 0 - disable
2752 */
2753static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002754lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002755{
2756 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002757 int i, j, k;
Radek Krejci7e97c352015-06-19 16:26:34 +02002758
2759 if (!module || !name || !strlen(name)) {
2760 return EXIT_FAILURE;
2761 }
2762
2763 if (!strcmp(name, "*")) {
2764 /* enable all */
2765 all = 1;
2766 }
2767
2768 /* module itself */
2769 for (i = 0; i < module->features_size; i++) {
2770 if (all || !strcmp(module->features[i].name, name)) {
2771 if (op) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002772 /* check referenced features if they are enabled */
2773 for (j = 0; j < module->features[i].iffeature_size; j++) {
2774 if (resolve_iffeature(&module->features[i].iffeature[j])) {
2775 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2776 module->features[i].name, j + 1);
2777 return EXIT_FAILURE;
2778 }
2779 }
2780
Radek Krejci1574a8d2015-08-03 14:16:52 +02002781 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002782 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002783 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002784 }
2785 if (!all) {
2786 return EXIT_SUCCESS;
2787 }
2788 }
2789 }
2790
2791 /* submodules */
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002792 for (i = 0; i < module->inc_size; i++) {
2793 for (j = 0; j < module->inc[i].submodule->features_size; j++) {
2794 if (all || !strcmp(module->inc[i].submodule->features[j].name, name)) {
Radek Krejci7e97c352015-06-19 16:26:34 +02002795 if (op) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002796 /* check referenced features if they are enabled */
2797 for (k = 0; k < module->inc[i].submodule->features[j].iffeature_size; k++) {
2798 if (resolve_iffeature(&module->inc[i].submodule->features[j].iffeature[k])) {
2799 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2800 module->inc[i].submodule->features[j].name, k + 1);
2801 return EXIT_FAILURE;
2802 }
2803 }
2804
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002805 module->inc[i].submodule->features[j].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002806 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002807 module->inc[i].submodule->features[j].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002808 }
2809 if (!all) {
2810 return EXIT_SUCCESS;
2811 }
2812 }
2813 }
2814 }
2815
2816 if (all) {
2817 return EXIT_SUCCESS;
2818 } else {
2819 return EXIT_FAILURE;
2820 }
2821}
2822
2823API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002824lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002825{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002826 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002827}
2828
2829API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002830lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002831{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002832 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002833}
2834
2835API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002836lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002837{
2838 int i, j;
2839
2840 if (!module || !feature) {
2841 return -1;
2842 }
2843
2844 /* search for the specified feature */
2845 /* module itself */
2846 for (i = 0; i < module->features_size; i++) {
2847 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002848 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002849 return 1;
2850 } else {
2851 return 0;
2852 }
2853 }
2854 }
2855
2856 /* submodules */
2857 for (j = 0; j < module->inc_size; j++) {
2858 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2859 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002860 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002861 return 1;
2862 } else {
2863 return 0;
2864 }
2865 }
2866 }
2867 }
2868
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002869 /* feature definition not found */
2870 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002871}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002872
Radek Krejci96a10da2015-07-30 11:00:14 +02002873API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002874lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002875{
Radek Krejci96a10da2015-07-30 11:00:14 +02002876 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002877 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002878 unsigned int count;
2879
2880 if (!module) {
2881 return NULL;
2882 }
2883
2884 count = module->features_size;
2885 for (i = 0; i < module->inc_size; i++) {
2886 count += module->inc[i].submodule->features_size;
2887 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002888 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002889 if (!result) {
2890 LOGMEM;
2891 return NULL;
2892 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002893 if (states) {
2894 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002895 if (!(*states)) {
2896 LOGMEM;
2897 free(result);
2898 return NULL;
2899 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002900 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002901 count = 0;
2902
2903 /* module itself */
2904 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002905 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002906 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002907 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002908 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002909 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002910 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002911 }
2912 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002913 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002914 }
2915
2916 /* submodules */
2917 for (j = 0; j < module->inc_size; j++) {
2918 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002919 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002920 if (states) {
2921 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2922 (*states)[count] = 1;
2923 } else {
2924 (*states)[count] = 0;
2925 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002926 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002927 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002928 }
2929 }
2930
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002931 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002932 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002933
2934 return result;
2935}
Michal Vaskobaefb032015-09-24 14:52:10 +02002936
Radek Krejci6910a032016-04-13 10:06:21 +02002937API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002938lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002939{
2940 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2941}
2942
Radek Krejci6910a032016-04-13 10:06:21 +02002943API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02002944lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01002945{
2946 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2947}
2948
Michal Vaskobaefb032015-09-24 14:52:10 +02002949API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002950lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002951{
2952 if (!node || !node->parent) {
2953 return NULL;
2954 }
2955
2956 if (node->parent->nodetype == LYS_AUGMENT) {
2957 return ((struct lys_node_augment *)node->parent)->target;
2958 }
2959
2960 return node->parent;
2961}
Michal Vasko1b229152016-01-13 11:28:38 +01002962
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002963API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002964lys_set_private(const struct lys_node *node, void *priv)
2965{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002966 void *prev;
2967
Michal Vasko1b229152016-01-13 11:28:38 +01002968 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002969 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2970 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002971 }
2972
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002973 prev = node->priv;
2974 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002975
2976 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002977}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002978
Michal Vasko01c6fd22016-05-20 11:43:05 +02002979int
2980lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
2981{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02002982 struct lys_node_leaf *iter = leafref_target;
2983
Michal Vasko48a573d2016-07-01 11:46:02 +02002984 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02002985 LOGINT;
2986 return -1;
2987 }
2988
Radek Krejcid8fb03c2016-06-13 15:52:22 +02002989 /* check for cycles */
2990 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
2991 if ((void *)iter == (void *)leafref) {
2992 /* cycle detected */
2993 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
2994 return -1;
2995 }
2996 iter = iter->type.info.lref.target;
2997 }
2998
2999 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02003000 * leafrefs referencing the leaf(-list) */
Michal Vasko01c6fd22016-05-20 11:43:05 +02003001 if (!leafref_target->child) {
3002 leafref_target->child = (void*)ly_set_new();
3003 if (!leafref_target->child) {
3004 LOGMEM;
3005 return -1;
3006 }
3007 }
Radek Krejci09891a22016-06-10 10:59:22 +02003008 ly_set_add((struct ly_set *)leafref_target->child, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003009
3010 return 0;
3011}
3012
Michal Vasko8548e082016-07-22 12:00:18 +02003013/* not needed currently */
3014#if 0
3015
Michal Vasko5b3492c2016-07-20 09:37:40 +02003016static const char *
3017lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
3018{
3019 struct lys_module *prev_mod;
3020 uint32_t str_len, mod_len, buf_idx;
3021
3022 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
3023 LOGINT;
3024 return NULL;
3025 }
3026
3027 buf_idx = buf_len - 1;
3028 buf[buf_idx] = '\0';
3029
3030 while (node) {
3031 if (lys_parent(node)) {
3032 prev_mod = lys_node_module(lys_parent(node));
3033 } else {
3034 prev_mod = NULL;
3035 }
3036
3037 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
3038 str_len = strlen(node->name);
3039
3040 if (prev_mod != node->module) {
3041 mod_len = strlen(node->module->name);
3042 } else {
3043 mod_len = 0;
3044 }
3045
3046 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
3047 LOGINT;
3048 return NULL;
3049 }
3050
3051 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
3052
3053 buf[buf_idx] = '/';
3054 if (mod_len) {
3055 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
3056 buf[buf_idx + 1 + mod_len] = ':';
3057 }
3058 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
3059 }
3060
3061 node = lys_parent(node);
3062 }
3063
3064 return buf + buf_idx;
3065}
3066
Michal Vasko8548e082016-07-22 12:00:18 +02003067#endif
3068
3069API struct ly_set *
3070lys_xpath_atomize(const struct lys_node *cur_snode, const char *expr, int options)
Michal Vasko5b3492c2016-07-20 09:37:40 +02003071{
Michal Vasko5b3492c2016-07-20 09:37:40 +02003072 struct lyxp_set *set;
Michal Vasko8548e082016-07-22 12:00:18 +02003073 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003074 uint32_t i;
3075
Michal Vasko8548e082016-07-22 12:00:18 +02003076 if (!cur_snode || !expr) {
3077 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003078 }
3079
3080 set = calloc(1, sizeof *set);
3081 if (!set) {
3082 LOGMEM;
Michal Vasko8548e082016-07-22 12:00:18 +02003083 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003084 }
3085
3086 if (options & LYXP_MUST) {
3087 options &= ~LYXP_MUST;
3088 options |= LYXP_SNODE_MUST;
3089 } else if (options & LYXP_WHEN) {
3090 options &= ~LYXP_WHEN;
3091 options |= LYXP_SNODE_WHEN;
3092 } else {
3093 options |= LYXP_SNODE;
3094 }
3095
3096 if (lyxp_atomize(expr, cur_snode, set, options)) {
3097 free(set->val.snodes);
3098 free(set);
Michal Vasko8548e082016-07-22 12:00:18 +02003099 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003100 }
3101
Michal Vasko8548e082016-07-22 12:00:18 +02003102 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003103
Michal Vasko5b3492c2016-07-20 09:37:40 +02003104 for (i = 0; i < set->used; ++i) {
3105 switch (set->val.snodes[i].type) {
3106 case LYXP_NODE_ELEM:
Michal Vasko8548e082016-07-22 12:00:18 +02003107 if (ly_set_add(ret_set, set->val.snodes[i].snode, LY_SET_OPT_USEASLIST)) {
3108 ly_set_free(ret_set);
3109 free(set->val.snodes);
3110 free(set);
3111 return NULL;
3112 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003113 break;
3114 default:
Michal Vasko8548e082016-07-22 12:00:18 +02003115 /* ignore roots, text and attr should not appear ever */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003116 break;
3117 }
3118 }
3119
Michal Vasko5b3492c2016-07-20 09:37:40 +02003120 free(set->val.snodes);
3121 free(set);
Michal Vasko8548e082016-07-22 12:00:18 +02003122 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003123}
3124
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003125static void
3126lys_switch_deviation(struct lys_deviation *dev, struct lys_module *dev_module)
3127{
3128 int ret;
3129 char *parent_path;
3130 struct lys_node *target;
3131 const struct lys_module *target_module;
3132
3133 target_module = lys_get_import_module(dev_module, NULL, 0, dev->target_name + 1,
3134 strcspn(dev->target_name, ":") - 1);
3135
3136 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
3137 if (dev->orig_node) {
3138 /* removing not-supported deviation ... */
3139 if (strrchr(dev->target_name, '/') != dev->target_name) {
3140 /* ... from a parent */
3141 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
3142
3143 target = NULL;
3144 ret = resolve_augment_schema_nodeid(parent_path, NULL, target_module, (const struct lys_node **)&target);
3145 free(parent_path);
3146 if (ret || !target) {
3147 LOGINT;
3148 return;
3149 }
3150
3151 lys_node_addchild(target, NULL, dev->orig_node);
3152 } else {
3153 /* ... from top-level data */
3154 lys_node_addchild(NULL, (struct lys_module *)target_module, dev->orig_node);
3155 }
3156
3157 dev->orig_node = NULL;
3158 } else {
3159 /* adding not-supported deviation */
3160 target = NULL;
3161 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
3162 if (ret || !target) {
3163 LOGINT;
3164 return;
3165 }
3166
3167 lys_node_unlink(target);
3168 dev->orig_node = target;
3169 }
3170 } else {
3171 target = NULL;
3172 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
3173 if (ret || !target) {
3174 LOGINT;
3175 return;
3176 }
3177
3178 lys_node_switch(target, dev->orig_node);
3179 dev->orig_node = target;
3180 }
3181}
3182
3183void
3184lys_deviation_add_ext_imports(struct lys_module *dev_target_module, struct lys_module *dev_module)
3185{
3186 int i, j;
3187
3188 /* mark the target module as deviated */
3189 dev_target_module->deviated = 1;
3190
3191 /* copy our imports to the deviated module (deviations may need them to work) */
3192 for (i = 0; i < dev_module->imp_size; ++i) {
3193 for (j = 0; j < dev_target_module->imp_size; ++j) {
3194 if (dev_module->imp[i].module == dev_target_module->imp[j].module) {
3195 break;
3196 }
3197 }
3198
3199 if (j < dev_target_module->imp_size) {
3200 /* import is already there */
3201 continue;
3202 }
3203
3204 /* copy the import, mark it as external */
3205 ++dev_target_module->imp_size;
3206 dev_target_module->imp = ly_realloc(dev_target_module->imp, dev_target_module->imp_size * sizeof *dev_target_module->imp);
3207 if (!dev_target_module->imp) {
3208 LOGMEM;
3209 return;
3210 }
3211 dev_target_module->imp[dev_target_module->imp_size - 1].module = dev_module->imp[i].module;
3212 dev_target_module->imp[dev_target_module->imp_size - 1].prefix = lydict_insert(dev_module->ctx, dev_module->imp[i].prefix, 0);
3213 memcpy(dev_target_module->imp[dev_target_module->imp_size - 1].rev, dev_module->imp[i].rev, LY_REV_SIZE);
3214 dev_target_module->imp[dev_target_module->imp_size - 1].external = 1;
3215 }
3216
3217 /* copy ourselves to the deviated module as a special import (if we haven't yet, there could be more deviations of the same module) */
3218 for (i = 0; i < dev_target_module->imp_size; ++i) {
3219 if (dev_target_module->imp[i].module == dev_module) {
3220 break;
3221 }
3222 }
3223
3224 if (i == dev_target_module->imp_size) {
3225 ++dev_target_module->imp_size;
3226 dev_target_module->imp = ly_realloc(dev_target_module->imp, dev_target_module->imp_size * sizeof *dev_target_module->imp);
3227 if (!dev_target_module->imp) {
3228 LOGMEM;
3229 return;
3230 }
3231 dev_target_module->imp[dev_target_module->imp_size - 1].module = dev_module;
3232 dev_target_module->imp[dev_target_module->imp_size - 1].prefix = lydict_insert(dev_module->ctx, dev_module->prefix, 0);
3233 if (dev_module->rev_size) {
3234 memcpy(dev_target_module->imp[dev_target_module->imp_size - 1].rev, dev_module->rev[0].date, LY_REV_SIZE);
3235 } else {
3236 memset(dev_target_module->imp[dev_target_module->imp_size - 1].rev, 0, LY_REV_SIZE);
3237 }
3238 dev_target_module->imp[dev_target_module->imp_size - 1].external = 2;
3239 } else {
3240 /* it could have been added by another deviating module that imported this deviating module */
3241 dev_target_module->imp[i].external = 2;
3242 }
3243}
3244
3245/* temporarily removes or applies deviations, updates module deviation flag accordingly */
3246void
3247lys_switch_deviations(struct lys_module *module)
3248{
3249 uint8_t i, j, changes = 0;
3250
3251 for (i = 0; i < module->imp_size; ++i) {
3252 if (module->imp[i].external == 2) {
3253 for (j = 0; j < module->imp[i].module->deviation_size; ++j) {
3254 lys_switch_deviation(&module->imp[i].module->deviation[j], module->imp[i].module);
3255 }
3256
3257 changes = 1;
3258 }
3259 }
3260
3261 if (changes) {
3262 if (module->deviated) {
3263 module->deviated = 0;
3264 } else {
3265 module->deviated = 1;
3266 }
3267 }
3268}
3269
3270/* not needed currently, but tested and working */
3271#if 0
3272
3273void
3274lys_sub_module_apply_devs_augs(struct lys_module *module)
3275{
3276 int i;
3277 struct lys_node_augment *aug;
3278 struct lys_node *last;
3279
3280 /* re-apply deviations */
3281 for (i = 0; i < module->deviation_size; ++i) {
3282 lys_switch_deviation(&module->deviation[i], module);
3283 assert(module->deviation[i].orig_node);
3284 lys_deviation_add_ext_imports(lys_node_module(module->deviation[i].orig_node), module);
3285 }
3286
3287 /* re-apply augments */
3288 for (i = 0; i < module->augment_size; ++i) {
3289 aug = &module->augment[i];
3290 assert(aug->target);
3291
3292 /* reconnect augmenting data into the target - add them to the target child list */
3293 if (aug->target->child) {
3294 last = aug->target->child->prev;
3295 last->next = aug->child;
3296 aug->target->child->prev = aug->child->prev;
3297 aug->child->prev = last;
3298 } else {
3299 aug->target->child = aug->child;
3300 }
3301 }
3302}
3303
3304#endif
3305
3306void
3307lys_sub_module_remove_devs_augs(struct lys_module *module)
3308{
3309 int i, j, flag;
3310 struct lys_node *last, *elem;
3311 struct lys_module *orig_mod;
3312
3313 /* remove applied deviations */
3314 for (i = 0; i < module->deviation_size; ++i) {
3315 lys_switch_deviation(&module->deviation[i], module);
3316
3317 /* remove our deviation import, clear deviated flag is possible */
3318 orig_mod = lys_node_module(module->deviation[i].orig_node);
3319 flag = 0;
3320 for (j = 0; j < orig_mod->imp_size; ++j) {
3321 if (orig_mod->imp[j].external == 2) {
3322 if (orig_mod->imp[j].module == lys_main_module(module)) {
3323 /* our deviation import, remove it */
3324 --orig_mod->imp_size;
3325 if (j < orig_mod->imp_size) {
3326 memcpy(&orig_mod->imp[j], &orig_mod->imp[j + 1], (orig_mod->imp_size - j) * sizeof *orig_mod->imp);
3327 }
3328 --j;
3329 } else {
3330 /* some other deviation, we cannot clear the deviated flag */
3331 flag = 1;
3332 }
3333 }
3334 }
3335 if (!flag) {
3336 /* it's safe to clear the deviated flag */
3337 orig_mod->deviated = 0;
3338 }
3339 }
3340
3341 /* remove applied augments */
3342 for (i = 0; i < module->augment_size; ++i) {
Radek Krejcidbc15262016-06-16 14:58:29 +02003343 if (!module->augment[i].target) {
3344 /* skip not resolved augments */
3345 continue;
3346 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003347
3348 elem = module->augment[i].child;
3349 if (elem) {
3350 LY_TREE_FOR(elem, last) {
3351 if (!last->next || (last->next->parent != (struct lys_node *)&module->augment[i])) {
3352 break;
3353 }
3354 }
3355 /* elem is first augment child, last is the last child */
3356
3357 /* parent child ptr */
3358 if (module->augment[i].target->child == elem) {
3359 module->augment[i].target->child = last->next;
3360 }
3361
3362 /* parent child next ptr */
3363 if (elem->prev->next) {
3364 elem->prev->next = last->next;
3365 }
3366
3367 /* parent child prev ptr */
3368 if (last->next) {
3369 last->next->prev = elem->prev;
3370 } else if (module->augment[i].target->child) {
3371 module->augment[i].target->child->prev = elem->prev;
3372 }
3373
3374 /* update augment children themselves */
3375 elem->prev = last;
3376 last->next = NULL;
3377 }
Michal Vaskob8f71322016-05-03 11:39:56 +02003378
3379 /* needs to be NULL for lys_augment_free() to free the children */
3380 module->augment[i].target = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003381 }
3382}
3383
Michal Vasko26055752016-05-03 11:36:31 +02003384int
3385lys_module_set_implement(struct lys_module *module)
3386{
3387 struct ly_ctx *ctx;
3388 int i;
3389
3390 if (module->implemented) {
3391 return EXIT_SUCCESS;
3392 }
3393
3394 ctx = module->ctx;
3395
3396 for (i = 0; i < ctx->models.used; ++i) {
3397 if (module == ctx->models.list[i]) {
3398 continue;
3399 }
3400
3401 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
3402 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
3403 return EXIT_FAILURE;
3404 }
3405 }
3406
3407 module->implemented = 1;
3408 return EXIT_SUCCESS;
3409}
3410
3411int
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003412lys_sub_module_set_dev_aug_target_implement(struct lys_module *module)
3413{
3414 int i;
3415 struct lys_module *trg_mod;
3416
3417 for (i = 0; i < module->deviation_size; ++i) {
3418 assert(module->deviation[i].orig_node);
3419 trg_mod = lys_node_module(module->deviation[i].orig_node);
Michal Vasko26055752016-05-03 11:36:31 +02003420 if (lys_module_set_implement(trg_mod)) {
3421 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003422 }
3423 }
3424
3425 for (i = 0; i < module->augment_size; ++i) {
3426 assert(module->augment[i].target);
3427 trg_mod = lys_node_module(module->augment[i].target);
Michal Vasko26055752016-05-03 11:36:31 +02003428 if (lys_module_set_implement(trg_mod)) {
3429 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003430 }
3431 }
Michal Vasko26055752016-05-03 11:36:31 +02003432
3433 return EXIT_SUCCESS;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003434}
3435
3436void
3437lys_submodule_module_data_free(struct lys_submodule *submodule)
3438{
3439 struct lys_node *next, *elem;
3440
3441 /* remove parsed data */
3442 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
3443 if (elem->module == (struct lys_module *)submodule) {
3444 lys_node_free(elem, NULL, 0);
3445 }
3446 }
3447}