blob: ba17cfb886372723accff561d6c693eabe3c319f [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 Krejci69b8d922016-07-27 13:13:41 +020055 if (!resolve_iffeature(&node->iffeature[i])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +020056 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 Krejci8519de02016-07-25 14:54:19 +0200439 LOGVAL(LYE_NOMAX, LY_VLOG_LYD, 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;
Radek Krejci264ae352016-07-26 15:32:55 +0200451 const struct lyd_node *diter, *datasearch;
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 Krejci264ae352016-07-26 15:32:55 +0200459 datasearch = data;
Radek Krejci7531aa22016-04-12 13:52:19 +0200460 } else {
461 /* !schema && data */
Radek Krejcie2f12212016-02-12 13:50:22 +0100462 schema = data->schema;
463 siter = data->schema->child;
Radek Krejci264ae352016-07-26 15:32:55 +0200464 datasearch = data->child;
Radek Krejci2342cf62016-01-29 16:48:23 +0100465 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200466
467repeat:
468 while (siter) {
Radek Krejci763122e2016-04-05 16:35:33 +0200469 if (lys_is_disabled(siter, 2) || (!status && (siter->flags & LYS_CONFIG_R))) {
Radek Krejci074bf852015-08-19 14:22:16 +0200470 siter = siter->next;
471 continue;
472 }
473
Radek Krejci7f40ce32015-08-12 20:38:46 +0200474 switch (siter->nodetype) {
475 case LYS_CONTAINER:
476 case LYS_LEAF:
477 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200478 case LYS_LIST:
479 case LYS_LEAFLIST:
480 /* check if there is some mandatory node; first test the siter itself ... */
Michal Vasko84f821a2016-04-11 11:03:42 +0200481 if (check_mand_check(siter, lys_parent(siter), data)) {
482 return EXIT_FAILURE;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200483 }
484 /* ... and then the subtree */
Radek Krejcicf82e932016-04-11 17:52:31 +0200485 if (siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200486 saux = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100487 while ((saux = check_mand_getnext(saux, siter, NULL))) {
Radek Krejcie8da2e02016-04-11 17:53:34 +0200488 if ((status || (saux->flags & LYS_CONFIG_W)) && check_mand_check(saux, lys_parent(siter), data)) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200489 return EXIT_FAILURE;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200490 }
491 }
492 }
493 siter = siter->next;
494 break;
495 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200496 /* search for instance */
497 saux = siter;
498 siter = siter->child;
499 found = 0;
500 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200501repeat_choice:
Radek Krejci2342cf62016-01-29 16:48:23 +0100502 while (siter && data) {
Radek Krejci763122e2016-04-05 16:35:33 +0200503 if (lys_is_disabled(siter, 2) || (!status && (siter->flags & LYS_CONFIG_R))) {
Radek Krejci074bf852015-08-19 14:22:16 +0200504 siter = siter->next;
505 continue;
506 }
507
Radek Krejci14a11a62015-08-17 17:27:38 +0200508 switch (siter->nodetype) {
509 case LYS_CONTAINER:
510 case LYS_LEAF:
511 case LYS_LEAFLIST:
512 case LYS_LIST:
513 case LYS_ANYXML:
Radek Krejci264ae352016-07-26 15:32:55 +0200514 LY_TREE_FOR(datasearch, diter) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200515 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200516 break;
517 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200518 }
519 if (diter) {
520 /* got instance */
521 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200522 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200523 saux2 = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100524 while ((saux2 = check_mand_getnext(saux2, parent2, NULL))) {
Radek Krejci7531aa22016-04-12 13:52:19 +0200525 if (check_mand_check(saux2, lys_parent(saux), data)) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200526 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200527 }
528 }
529 }
530 siter = parent2 = NULL;
531 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200532 break;
533 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200534 siter = siter->next;
535 break;
536 case LYS_CASE:
537 case LYS_CHOICE:
538 case LYS_USES:
539 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200540 if (!parent2) {
541 parent2 = siter;
542 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200543 siter = siter->child;
544 break;
545 case LYS_AUGMENT:
546 case LYS_GROUPING:
547 /* skip */
548 siter = siter->next;
549 break;
550 default:
551 /* error */
552 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200553 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200554 }
555
Radek Krejci14a11a62015-08-17 17:27:38 +0200556 if (parent2) {
557 siter = parent2->next;
Michal Vasko84f821a2016-04-11 11:03:42 +0200558 if (lys_parent(parent2) == saux) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200559 parent2 = NULL;
560 } else {
Michal Vasko84f821a2016-04-11 11:03:42 +0200561 parent2 = lys_parent(parent2);
Radek Krejci14a11a62015-08-17 17:27:38 +0200562 }
563 goto repeat_choice;
564 }
565
Radek Krejci074bf852015-08-19 14:22:16 +0200566 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci7531aa22016-04-12 13:52:19 +0200567 LOGVAL(LYE_MISSELEM, LY_VLOG_LYD, data, saux->name,
568 (lys_parent(saux) ? lys_parent(saux)->name : lys_node_module(saux)->name));
Michal Vasko84f821a2016-04-11 11:03:42 +0200569 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200570 }
571
572 /* go to next */
573 siter = saux->next;
574
Radek Krejci7f40ce32015-08-12 20:38:46 +0200575 break;
Michal Vasko98a5a742016-05-11 11:02:56 +0200576 case LYS_INPUT:
577 if (rpc_output) {
578 /* skip */
579 siter = siter->next;
580 break;
581 }
582 /* fallthrough */
583 case LYS_OUTPUT:
Michal Vasko880f67d2016-06-01 16:12:18 +0200584 if ((siter->nodetype == LYS_OUTPUT) && !rpc_output) {
Michal Vasko98a5a742016-05-11 11:02:56 +0200585 /* skip */
586 siter = siter->next;
587 break;
588 }
589 /* fallthrough */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200590 case LYS_USES:
591 case LYS_CASE:
592 /* go into */
593 parent = siter;
594 siter = siter->child;
595 break;
596 default:
597 /* can ignore, go to next */
598 siter = siter->next;
599 break;
600 }
601 }
602
603 if (parent) {
604 siter = parent->next;
Michal Vasko9eb6dd02016-05-02 14:52:40 +0200605 if (lys_parent(parent) == schema) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200606 parent = NULL;
607 } else {
Michal Vasko84f821a2016-04-11 11:03:42 +0200608 parent = lys_parent(parent);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200609 }
610 goto repeat;
611 }
612
Michal Vasko84f821a2016-04-11 11:03:42 +0200613 return EXIT_SUCCESS;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200614}
615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200616void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200617lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200618{
Radek Krejci76512572015-08-04 09:47:08 +0200619 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100620 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200622 if (!node) {
623 return;
624 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200626 /* unlink from data model if necessary */
627 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100628 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100629 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100630 if (main_module->data == node) {
631 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200632 }
633 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200635 /* store pointers to important nodes */
636 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200637 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200638 /* handle augments - first, unlink it from the augment parent ... */
639 if (parent->child == node) {
640 parent->child = node->next;
641 }
642 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200643 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200644 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200645
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200646 /* unlink from parent */
647 if (parent) {
648 if (parent->child == node) {
649 parent->child = node->next;
650 }
651 node->parent = NULL;
652 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200654 /* unlink from siblings */
655 if (node->prev == node) {
656 /* there are no more siblings */
657 return;
658 }
659 if (node->next) {
660 node->next->prev = node->prev;
661 } else {
662 /* unlinking the last element */
663 if (parent) {
664 first = parent->child;
665 } else {
666 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200667 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200668 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200669 }
670 }
671 first->prev = node->prev;
672 }
673 if (node->prev->next) {
674 node->prev->next = node->next;
675 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200676
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200677 /* clean up the unlinked element */
678 node->next = NULL;
679 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200680}
681
Michal Vasko563ef092015-09-04 13:17:23 +0200682struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100683lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200684{
685 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200686
687 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200688 /* top-level augment, look into module (uses augment is handled correctly below) */
689 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
690 par_iter = par_iter->parent->module->data;
691 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200692 break;
693 }
694 }
695
Michal Vasko6f929da2015-10-02 16:23:25 +0200696 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200697 continue;
698 }
699
700 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
701 if (!stop) {
702 stop = par_iter;
703 } else if (iter == stop) {
704 break;
705 }
706 if (iter->nodetype != LYS_GROUPING) {
707 continue;
708 }
709
Radek Krejcif8426a72015-10-31 23:14:03 +0100710 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200711 return (struct lys_node_grp *)iter;
712 }
713 }
714 }
715
Michal Vasko563ef092015-09-04 13:17:23 +0200716 return NULL;
717}
718
Radek Krejci10c760e2015-08-14 14:45:43 +0200719/*
720 * get next grouping in the root's subtree, in the
721 * first call, tha last is NULL
722 */
723static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200724lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200725{
Radek Krejci10c760e2015-08-14 14:45:43 +0200726 struct lys_node *last = (struct lys_node *)lastgrp;
727 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200728
Radek Krejci10c760e2015-08-14 14:45:43 +0200729 assert(root);
730
731 if (!last) {
732 last = root;
733 }
734
735 while (1) {
736 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
737 next = last->child;
738 } else {
739 next = NULL;
740 }
741 if (!next) {
742 if (last == root) {
743 /* we are done */
744 return NULL;
745 }
746
747 /* no children, go to siblings */
748 next = last->next;
749 }
750 while (!next) {
751 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100752 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200753 /* we are done */
754 return NULL;
755 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200756 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100757 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200758 }
759
760 if (next->nodetype == LYS_GROUPING) {
761 return (struct lys_node_grp *)next;
762 }
763
764 last = next;
765 }
766}
767
Michal Vasko0d343d12015-08-24 14:57:36 +0200768/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200769int
Radek Krejci07911992015-08-14 15:13:31 +0200770lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
771{
Michal Vasko563ef092015-09-04 13:17:23 +0200772 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200773 struct lys_node_grp *grp;
774 int down;
775
776 assert(node);
777
778 if (!parent) {
779 assert(module);
780 } else {
781 module = parent->module;
782 }
783
784 switch (node->nodetype) {
785 case LYS_GROUPING:
786 /* 6.2.1, rule 6 */
787 if (parent) {
788 if (parent->child) {
789 down = 1;
790 start = parent->child;
791 } else {
792 down = 0;
793 start = parent;
794 }
795 } else {
796 down = 1;
797 start = module->data;
798 }
799 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100800 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100801 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200802 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200803 }
804 /* go down, because grouping can be defined after e.g. container in which is collision */
805 if (down) {
806 for (iter = start, stop = NULL; iter; iter = iter->prev) {
807 if (!stop) {
808 stop = start;
809 } else if (iter == stop) {
810 break;
811 }
812 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
813 continue;
814 }
815
816 grp = NULL;
817 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100818 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100819 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200820 return EXIT_FAILURE;
821 }
822 }
823 }
824 }
825 break;
826 case LYS_LEAF:
827 case LYS_LEAFLIST:
828 case LYS_LIST:
829 case LYS_CONTAINER:
830 case LYS_CHOICE:
831 case LYS_ANYXML:
832 /* 6.2.1, rule 7 */
833 if (parent) {
834 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200835 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
836 if (iter->nodetype == LYS_AUGMENT) {
837 if (((struct lys_node_augment *)iter)->target) {
838 /* augment is resolved, go up */
839 iter = ((struct lys_node_augment *)iter)->target;
840 continue;
841 }
842 /* augment is not resolved, this is the final parent */
843 break;
844 }
Radek Krejci07911992015-08-14 15:13:31 +0200845 iter = iter->parent;
846 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200847
Radek Krejci07911992015-08-14 15:13:31 +0200848 if (!iter) {
849 stop = NULL;
850 iter = module->data;
851 } else {
852 stop = iter;
853 iter = iter->child;
854 }
855 } else {
856 stop = NULL;
857 iter = module->data;
858 }
859 while (iter) {
860 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
861 iter = iter->child;
862 continue;
863 }
864
865 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100866 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100867 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200868 return EXIT_FAILURE;
869 }
870 }
871
872 /* special case for choice - we must check the choice's name as
873 * well as the names of nodes under the choice
874 */
875 if (iter->nodetype == LYS_CHOICE) {
876 iter = iter->child;
877 continue;
878 }
879
880 /* go to siblings */
881 if (!iter->next) {
882 /* no sibling, go to parent's sibling */
883 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200884 /* for parent LYS_AUGMENT */
885 if (iter->parent == stop) {
886 iter = stop;
887 break;
888 }
889 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200890 if (iter && iter->next) {
891 break;
892 }
893 } while (iter != stop);
894
895 if (iter == stop) {
896 break;
897 }
898 }
899 iter = iter->next;
900 }
901 break;
902 case LYS_CASE:
903 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100904 if (parent) {
905 start = parent->child;
906 } else {
907 start = module->data;
908 }
909
910 LY_TREE_FOR(start, iter) {
Radek Krejci07911992015-08-14 15:13:31 +0200911 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
912 continue;
913 }
914
Radek Krejci749190d2016-02-18 16:26:25 +0100915 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100916 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200917 return EXIT_FAILURE;
918 }
919 }
920 break;
921 default:
922 /* no check needed */
923 break;
924 }
925
926 return EXIT_SUCCESS;
927}
928
Michal Vasko0d343d12015-08-24 14:57:36 +0200929/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200930int
Radek Krejci10c760e2015-08-14 14:45:43 +0200931lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
932{
Radek Krejci92720552015-10-05 15:28:27 +0200933 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200934 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200935
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200936 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200937
Radek Krejci10c760e2015-08-14 14:45:43 +0200938 if (parent) {
939 type = parent->nodetype;
940 module = parent->module;
941 } else {
942 assert(module);
943 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200944 }
945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200946 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200947 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200948 case LYS_CONTAINER:
949 case LYS_LIST:
950 case LYS_GROUPING:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200951 if (!(child->nodetype &
952 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
953 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
954 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
955 return EXIT_FAILURE;
956 }
957 break;
Radek Krejci76512572015-08-04 09:47:08 +0200958 case LYS_USES:
959 case LYS_INPUT:
960 case LYS_OUTPUT:
961 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200962 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200963 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
964 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100965 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200966 return EXIT_FAILURE;
967 }
968 break;
Radek Krejci76512572015-08-04 09:47:08 +0200969 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200970 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200971 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100972 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200973 return EXIT_FAILURE;
974 }
975 break;
Radek Krejci76512572015-08-04 09:47:08 +0200976 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200977 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200978 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100979 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200980 return EXIT_FAILURE;
981 }
982 break;
Radek Krejci76512572015-08-04 09:47:08 +0200983 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200984 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200985 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100986 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200987 return EXIT_FAILURE;
988 }
989 break;
Radek Krejci76512572015-08-04 09:47:08 +0200990 case LYS_LEAF:
991 case LYS_LEAFLIST:
992 case LYS_ANYXML:
Radek Krejci48464ed2016-03-17 15:44:09 +0100993 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
994 LOGVAL(LYE_SPEC, LY_VLOG_LYS, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100995 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200996 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200997 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200998 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200999 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskoca7cbc42016-07-01 11:36:53 +02001000 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001001 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001002 return EXIT_FAILURE;
1003 }
Michal Vasko591e0b22015-08-13 13:53:43 +02001004 break;
1005 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +02001006 /* top level */
1007 if (!(child->nodetype &
1008 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
1009 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001010 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +02001011 return EXIT_FAILURE;
1012 }
1013
Radek Krejcic071c542016-01-27 14:57:51 +01001014 break;
Radek Krejci10c760e2015-08-14 14:45:43 +02001015 }
1016
1017 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +02001018 if (lys_check_id(child, parent, module)) {
1019 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001020 }
Radek Krejcib7155b52015-06-10 17:03:01 +02001021
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001022 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001023 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001024 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001025
Radek Krejci10c760e2015-08-14 14:45:43 +02001026 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +02001027 if (module->data) {
1028 module->data->prev->next = child;
1029 child->prev = module->data->prev;
1030 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001031 } else {
Radek Krejci92720552015-10-05 15:28:27 +02001032 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001033 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001034 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +02001035 if (!parent->child) {
1036 /* the only/first child of the parent */
1037 parent->child = child;
1038 child->parent = parent;
1039 iter = child;
1040 } else {
1041 /* add a new child at the end of parent's child list */
1042 iter = parent->child->prev;
1043 iter->next = child;
1044 child->prev = iter;
1045 }
1046 while (iter->next) {
1047 iter = iter->next;
1048 iter->parent = parent;
1049 }
1050 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001051 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001052
Radek Krejci41771502016-04-14 17:52:32 +02001053 /* propagate information about status data presence */
1054 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML)) &&
1055 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +02001056 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +02001057 /* store it only into container or list - the only data inner nodes */
1058 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
1059 if (iter->flags & LYS_INCL_STATUS) {
1060 /* done, someone else set it already from here */
1061 break;
1062 }
1063 /* set flag about including status data */
1064 iter->flags |= LYS_INCL_STATUS;
1065 }
1066 }
1067 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001068 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001069}
1070
Radek Krejcia1df1682016-04-11 14:56:59 +02001071static const struct lys_module *
1072lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001073{
Radek Krejcia1df1682016-04-11 14:56:59 +02001074 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001075 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +02001076 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001077
Radek Krejcif347abc2016-06-22 10:18:47 +02001078 ly_errno = LY_SUCCESS;
1079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 if (!ctx || !data) {
1081 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1082 return NULL;
1083 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001084
Radek Krejcia1df1682016-04-11 14:56:59 +02001085 if (!internal && format == LYS_IN_YANG) {
1086 /* enlarge data by 2 bytes for flex */
1087 len = strlen(data);
1088 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
1089 if (!enlarged_data) {
1090 LOGMEM;
1091 return NULL;
1092 }
1093 memcpy(enlarged_data, data, len);
1094 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1095 data = enlarged_data;
1096 }
1097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001098 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001099 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +01001100 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001101 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001102 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001103 mod = yang_read_module(ctx, data, 0, NULL, 1);
1104 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001105 default:
Radek Krejcia1df1682016-04-11 14:56:59 +02001106 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001107 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001108 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001109
Radek Krejcia1df1682016-04-11 14:56:59 +02001110 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001111 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001112}
1113
Radek Krejcia1df1682016-04-11 14:56:59 +02001114API const struct lys_module *
1115lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
1116{
1117 return lys_parse_mem_(ctx, data, format, 0);
1118}
1119
Michal Vasko5a721fd2016-02-16 12:16:48 +01001120struct lys_submodule *
1121lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001122{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001123 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001125 assert(module);
1126 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001127
Radek Krejcic071c542016-01-27 14:57:51 +01001128 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +02001129 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001130
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001131 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001132 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001133 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001134 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001135 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001136 submod = yang_read_submodule(module, data, 0, unres);
1137 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001138 default:
Radek Krejci90a550a2016-04-13 16:00:58 +02001139 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001140 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001141 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001142
Michal Vasko5a721fd2016-02-16 12:16:48 +01001143 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001144}
1145
Michal Vasko1e62a092015-12-01 12:27:20 +01001146API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001147lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1148{
1149 int fd;
1150 const struct lys_module *ret;
1151
1152 if (!ctx || !path) {
1153 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1154 return NULL;
1155 }
1156
1157 fd = open(path, O_RDONLY);
1158 if (fd == -1) {
1159 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1160 return NULL;
1161 }
1162
1163 ret = lys_parse_fd(ctx, fd, format);
1164 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +01001165
Radek Krejcia77904e2016-02-25 16:23:45 +01001166 if (ret && !ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001167 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +01001168 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +01001169 }
1170
Michal Vasko662610a2015-12-07 11:25:45 +01001171 return ret;
1172}
1173
1174API const struct lys_module *
1175lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001176{
Michal Vasko1e62a092015-12-01 12:27:20 +01001177 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001178 struct stat sb;
1179 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001180 char buf[PATH_MAX];
1181 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001182
1183 if (!ctx || fd < 0) {
1184 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1185 return NULL;
1186 }
1187
Radek Krejci10a833c2015-12-16 15:28:37 +01001188 if (fstat(fd, &sb) == -1) {
1189 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1190 return NULL;
1191 }
Radek Krejcib051f722016-02-25 15:12:21 +01001192 if (!S_ISREG(sb.st_mode)) {
1193 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
1194 return NULL;
1195 }
1196
Michal Vasko164d9012016-04-01 10:16:59 +02001197 if (!sb.st_size) {
1198 LOGERR(LY_EINVAL, "File empty.");
1199 return NULL;
1200 }
1201
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001202 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001203 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001204 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001205 return NULL;
1206 }
Radek Krejcia1df1682016-04-11 14:56:59 +02001207 module = lys_parse_mem_(ctx, addr, format, 1);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001208 munmap(addr, sb.st_size + 2);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001209
Radek Krejcia77904e2016-02-25 16:23:45 +01001210 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001211 /* get URI if there is /proc */
1212 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001213 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1214 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1215 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1216 }
1217 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001218 }
Radek Krejcib051f722016-02-25 15:12:21 +01001219 }
1220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001221 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001222}
1223
Michal Vasko5a721fd2016-02-16 12:16:48 +01001224struct lys_submodule *
1225lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001226{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001227 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001228 struct stat sb;
1229 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001231 assert(module);
1232 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001233
Radek Krejci10a833c2015-12-16 15:28:37 +01001234 if (fstat(fd, &sb) == -1) {
1235 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001236 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001237 }
Michal Vasko164d9012016-04-01 10:16:59 +02001238
1239 if (!sb.st_size) {
1240 LOGERR(LY_EINVAL, "File empty.");
1241 return NULL;
1242 }
1243
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001244 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001245 if (addr == MAP_FAILED) {
1246 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001247 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001248 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001249 submodule = lys_submodule_parse(module, addr, format, unres);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001250 munmap(addr, sb.st_size + 2);
Radek Krejciefaeba32015-05-27 14:30:57 +02001251
Michal Vasko5a721fd2016-02-16 12:16:48 +01001252 return submodule;
1253
Radek Krejciefaeba32015-05-27 14:30:57 +02001254}
1255
Radek Krejci1d82ef62015-08-07 14:44:40 +02001256static struct lys_restr *
1257lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001258{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001259 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001260 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001261
Radek Krejci3733a802015-06-19 13:43:21 +02001262 if (!size) {
1263 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001264 }
Radek Krejci3733a802015-06-19 13:43:21 +02001265
1266 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001267 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001268 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001269 return NULL;
1270 }
Radek Krejci3733a802015-06-19 13:43:21 +02001271 for (i = 0; i < size; i++) {
1272 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1273 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1274 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1275 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1276 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1277 }
1278
1279 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001280}
1281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001282void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001283lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001284{
1285 assert(ctx);
1286 if (!restr) {
1287 return;
1288 }
1289
1290 lydict_remove(ctx, restr->expr);
1291 lydict_remove(ctx, restr->dsc);
1292 lydict_remove(ctx, restr->ref);
1293 lydict_remove(ctx, restr->eapptag);
1294 lydict_remove(ctx, restr->emsg);
1295}
1296
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001297static void
1298lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size)
1299{
1300 uint8_t i;
1301
1302 for (i = 0; i < iffeature_size; ++i) {
1303 free(iffeature[i].expr);
1304 free(iffeature[i].features);
1305 }
1306 free(iffeature);
1307}
1308
Michal Vaskob84f88a2015-09-24 13:16:10 +02001309static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001310type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001311 LY_DATA_TYPE base, int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001312{
1313 int i;
1314
1315 switch (base) {
1316 case LY_TYPE_BINARY:
1317 if (old->info.binary.length) {
1318 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
1319 }
1320 break;
1321
1322 case LY_TYPE_BITS:
1323 new->info.bits.count = old->info.bits.count;
1324 if (new->info.bits.count) {
1325 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1326 if (!new->info.bits.bit) {
1327 LOGMEM;
1328 return -1;
1329 }
1330 for (i = 0; i < new->info.bits.count; i++) {
1331 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1332 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1333 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1334 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1335 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1336 }
1337 }
1338 break;
1339
1340 case LY_TYPE_DEC64:
1341 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001342 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001343 if (old->info.dec64.range) {
1344 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
1345 }
1346 break;
1347
1348 case LY_TYPE_ENUM:
1349 new->info.enums.count = old->info.enums.count;
1350 if (new->info.enums.count) {
1351 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1352 if (!new->info.enums.enm) {
1353 LOGMEM;
1354 return -1;
1355 }
1356 for (i = 0; i < new->info.enums.count; i++) {
1357 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1358 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1359 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1360 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1361 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
1362 }
1363 }
1364 break;
1365
1366 case LY_TYPE_IDENT:
1367 if (old->info.ident.ref) {
1368 new->info.ident.ref = old->info.ident.ref;
1369 } else {
1370 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vasko3767fb22016-07-21 12:10:57 +02001371 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 +02001372 return -1;
1373 }
1374 }
1375 break;
1376
1377 case LY_TYPE_INST:
1378 new->info.inst.req = old->info.inst.req;
1379 break;
1380
1381 case LY_TYPE_INT8:
1382 case LY_TYPE_INT16:
1383 case LY_TYPE_INT32:
1384 case LY_TYPE_INT64:
1385 case LY_TYPE_UINT8:
1386 case LY_TYPE_UINT16:
1387 case LY_TYPE_UINT32:
1388 case LY_TYPE_UINT64:
1389 if (old->info.num.range) {
1390 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
1391 }
1392 break;
1393
1394 case LY_TYPE_LEAFREF:
1395 if (old->info.lref.path) {
1396 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko5d631402016-07-21 13:15:15 +02001397 if (!tpdftype && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001398 return -1;
1399 }
1400 }
1401 break;
1402
1403 case LY_TYPE_STRING:
1404 if (old->info.str.length) {
1405 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
1406 }
1407 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
1408 new->info.str.pat_count = old->info.str.pat_count;
1409 break;
1410
1411 case LY_TYPE_UNION:
1412 new->info.uni.count = old->info.uni.count;
1413 if (new->info.uni.count) {
1414 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1415 if (!new->info.uni.types) {
1416 LOGMEM;
1417 return -1;
1418 }
1419 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001420 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 +02001421 return -1;
1422 }
1423 }
1424 }
1425 break;
1426
1427 default:
1428 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1429 break;
1430 }
1431 return EXIT_SUCCESS;
1432}
1433
1434struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001435lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1436 int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001437{
1438 struct yang_type *new;
1439
1440 new = calloc(1, sizeof *new);
1441 if (!new) {
1442 LOGMEM;
1443 return NULL;
1444 }
1445 new->flags = old->flags;
1446 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001447 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001448 new->type = type;
1449 if (!new->name) {
1450 LOGMEM;
1451 goto error;
1452 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001453 if (type_dup(module, parent, type, old->type, new->base, tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001454 new->type->base = new->base;
1455 lys_type_free(module->ctx, new->type);
1456 memset(&new->type->info, 0, sizeof new->type->info);
1457 goto error;
1458 }
1459 return new;
1460
1461 error:
1462 free(new);
1463 return NULL;
1464}
1465
1466static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001467lys_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 +02001468 int tpdftype, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001469{
1470 int i;
1471
Michal Vasko1dca6882015-10-22 14:29:42 +02001472 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001473 new->base = old->base;
1474 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001475 new->parent = (struct lys_tpdf *)parent;
Radek Krejci3733a802015-06-19 13:43:21 +02001476
Radek Krejci3a5501d2016-07-18 22:03:34 +02001477 i = unres_schema_find(unres, old, tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001478 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001479 /* HACK (serious one) for unres */
1480 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001481 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001482 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 +02001483 } else {
1484 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1485 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001486 /* all these unres additions can fail even though they did not before */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001487 if (!new->der || unres_schema_add_node(mod, unres, new,
Michal Vasko5d631402016-07-21 13:15:15 +02001488 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001489 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001490 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001491 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001492 }
1493
Radek Krejci3a5501d2016-07-18 22:03:34 +02001494 return type_dup(mod, parent, new, old, new->base, tpdftype, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001495}
1496
1497void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001498lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001499{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001500 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001501
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001502 assert(ctx);
1503 if (!type) {
1504 return;
1505 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001506
Michal Vasko1dca6882015-10-22 14:29:42 +02001507 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001509 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001510 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001511 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001512 free(type->info.binary.length);
1513 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001514 case LY_TYPE_BITS:
1515 for (i = 0; i < type->info.bits.count; i++) {
1516 lydict_remove(ctx, type->info.bits.bit[i].name);
1517 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1518 lydict_remove(ctx, type->info.bits.bit[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001519 lys_iffeature_free(type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size);
Radek Krejci994b6f62015-06-18 16:47:27 +02001520 }
1521 free(type->info.bits.bit);
1522 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001523
1524 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001525 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001526 free(type->info.dec64.range);
1527 break;
1528
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001529 case LY_TYPE_ENUM:
1530 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001531 lydict_remove(ctx, type->info.enums.enm[i].name);
1532 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1533 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001534 lys_iffeature_free(type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001535 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001536 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001537 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001538
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001539 case LY_TYPE_INT8:
1540 case LY_TYPE_INT16:
1541 case LY_TYPE_INT32:
1542 case LY_TYPE_INT64:
1543 case LY_TYPE_UINT8:
1544 case LY_TYPE_UINT16:
1545 case LY_TYPE_UINT32:
1546 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001547 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001548 free(type->info.num.range);
1549 break;
1550
Radek Krejcidc4c1412015-06-19 15:39:54 +02001551 case LY_TYPE_LEAFREF:
1552 lydict_remove(ctx, type->info.lref.path);
1553 break;
1554
Radek Krejci3733a802015-06-19 13:43:21 +02001555 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001556 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001557 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001558 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001559 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001560 }
1561 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001562 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001563
Radek Krejcie4c366b2015-07-02 10:11:31 +02001564 case LY_TYPE_UNION:
1565 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001566 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001567 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001568 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001569 break;
1570
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001571 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001572 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001573 break;
1574 }
Radek Krejci5a065542015-05-22 15:02:07 +02001575}
1576
Radek Krejci1d82ef62015-08-07 14:44:40 +02001577static void
1578lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001579{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001580 assert(ctx);
1581 if (!tpdf) {
1582 return;
1583 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001585 lydict_remove(ctx, tpdf->name);
1586 lydict_remove(ctx, tpdf->dsc);
1587 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001588
Radek Krejci1d82ef62015-08-07 14:44:40 +02001589 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001590
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001591 lydict_remove(ctx, tpdf->units);
1592 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001593}
1594
Michal Vaskob84f88a2015-09-24 13:16:10 +02001595static struct lys_tpdf *
1596lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1597{
1598 struct lys_tpdf *result;
1599 int i, j;
1600
1601 if (!size) {
1602 return NULL;
1603 }
1604
1605 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001606 if (!result) {
1607 LOGMEM;
1608 return NULL;
1609 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001610 for (i = 0; i < size; i++) {
1611 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1612 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1613 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1614 result[i].flags = old[i].flags;
1615 result[i].module = old[i].module;
1616
Radek Krejci3a5501d2016-07-18 22:03:34 +02001617 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), 1, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001618 for (j = 0; j <= i; ++j) {
1619 lys_tpdf_free(mod->ctx, &result[j]);
1620 }
1621 free(result);
1622 return NULL;
1623 }
1624
1625 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1626 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1627 }
1628
1629 return result;
1630}
1631
Radek Krejci1d82ef62015-08-07 14:44:40 +02001632static struct lys_when *
1633lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001634{
Radek Krejci76512572015-08-04 09:47:08 +02001635 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001636
1637 if (!old) {
1638 return NULL;
1639 }
1640
1641 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001642 if (!new) {
1643 LOGMEM;
1644 return NULL;
1645 }
Radek Krejci00768f42015-06-18 17:04:04 +02001646 new->cond = lydict_insert(ctx, old->cond, 0);
1647 new->dsc = lydict_insert(ctx, old->dsc, 0);
1648 new->ref = lydict_insert(ctx, old->ref, 0);
1649
1650 return new;
1651}
1652
Michal Vasko0308dd62015-10-07 09:14:40 +02001653void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001654lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001655{
1656 if (!w) {
1657 return;
1658 }
1659
1660 lydict_remove(ctx, w->cond);
1661 lydict_remove(ctx, w->dsc);
1662 lydict_remove(ctx, w->ref);
1663
1664 free(w);
1665}
1666
Radek Krejcib7f5e412015-08-13 10:15:51 +02001667static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001668lys_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 +02001669{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001670 struct lys_node *next, *sub;
1671
Radek Krejcic071c542016-01-27 14:57:51 +01001672 /* children from a resolved augment are freed under the target node */
Michal Vaskod2fbade2016-05-02 17:14:00 +02001673 if (!aug->target) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001674 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001675 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001676 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001677 }
1678
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001679 lydict_remove(ctx, aug->target_name);
1680 lydict_remove(ctx, aug->dsc);
1681 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001682
Radek Krejci9ff0a922016-07-14 13:08:05 +02001683 lys_iffeature_free(aug->iffeature, aug->iffeature_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001684
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001685 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001686}
1687
Radek Krejci76512572015-08-04 09:47:08 +02001688static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001689lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001690{
Radek Krejci76512572015-08-04 09:47:08 +02001691 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001692 struct lys_node *old_child, *new_child;
1693 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001694
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001695 if (!size) {
1696 return NULL;
1697 }
Radek Krejci106efc02015-06-10 14:36:27 +02001698
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001699 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001700 if (!new) {
1701 LOGMEM;
1702 return NULL;
1703 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001704 for (i = 0; i < size; i++) {
1705 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1706 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1707 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1708 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001709 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001710 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001711
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001712 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001713 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1714 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001715 LOGINT;
1716 free(new);
1717 return NULL;
1718 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001719 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001720
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001721 /* Correct the augment nodes.
1722 * This function can only be called from lys_node_dup() with uses
1723 * being the node duplicated, so we must have a case of grouping
1724 * with a uses with augments. The augmented nodes have already been
1725 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001726 * (it was set to their actual data parent, not an augment), and
1727 * the new augment does not have child pointer to its augment nodes,
1728 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001729 */
1730 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001731 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001732 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001733 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001734 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001735 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001736 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001737 LY_TREE_FOR(old[i].child, old_child) {
1738 /* all augment nodes were connected as siblings, there can be no more after this */
1739 if (old_child->parent != (struct lys_node *)&old[i]) {
1740 break;
1741 }
1742
Radek Krejci749190d2016-02-18 16:26:25 +01001743 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001744
1745 new_child->parent = (struct lys_node *)&new[i];
1746 new_child = new_child->next;
1747 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001748 }
Radek Krejci106efc02015-06-10 14:36:27 +02001749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001750 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001751}
1752
Radek Krejci76512572015-08-04 09:47:08 +02001753static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001754lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001755{
Radek Krejci76512572015-08-04 09:47:08 +02001756 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001757 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001758
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001759 if (!size) {
1760 return NULL;
1761 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001762
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001763 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001764 if (!result) {
1765 LOGMEM;
1766 return NULL;
1767 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001768 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001769 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001770 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1771 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001772 result[i].flags = old[i].flags;
1773 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001774
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001775 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001776 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001777
Radek Krejci76512572015-08-04 09:47:08 +02001778 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001779 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001780 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001781 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001782 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001783 result[i].mod.list = old[i].mod.list;
1784 }
1785 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001786
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001787 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001788}
1789
Radek Krejci1d82ef62015-08-07 14:44:40 +02001790static void
1791lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001792{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001793 assert(ctx);
1794 if (!ident) {
1795 return;
1796 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001797
Radek Krejci1b61d0e2016-04-15 13:55:44 +02001798 free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001799 lydict_remove(ctx, ident->name);
1800 lydict_remove(ctx, ident->dsc);
1801 lydict_remove(ctx, ident->ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001802 lys_iffeature_free(ident->iffeature, ident->iffeature_size);
Radek Krejci6793db02015-05-22 17:49:54 +02001803
1804}
1805
Radek Krejci1d82ef62015-08-07 14:44:40 +02001806static void
1807lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001808{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001809 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001810
Radek Krejcid12f57b2015-08-06 10:43:39 +02001811 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001812 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001813 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001814 }
1815 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001816}
1817
Radek Krejci1d82ef62015-08-07 14:44:40 +02001818static void
Michal Vasko44fb6382016-06-29 11:12:27 +02001819lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02001820{
1821 int i;
1822
1823 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1824 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001825 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001826 }
1827 free(io->tpdf);
1828}
1829
Radek Krejci1d82ef62015-08-07 14:44:40 +02001830static void
1831lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001832{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001833 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001835 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001836 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001837 }
1838 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001839
Radek Krejci1d82ef62015-08-07 14:44:40 +02001840 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001841}
1842
Radek Krejci1d82ef62015-08-07 14:44:40 +02001843static void
1844lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001845{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001846 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001847
Radek Krejci46c4cd72016-01-21 15:13:52 +01001848 if (leaf->child) {
1849 /* leafref backlinks */
1850 ly_set_free((struct ly_set *)leaf->child);
1851 }
1852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001853 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001854 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001855 }
1856 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001857
Radek Krejci1d82ef62015-08-07 14:44:40 +02001858 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001859
Radek Krejci1d82ef62015-08-07 14:44:40 +02001860 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001861 lydict_remove(ctx, leaf->units);
1862 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001863}
1864
Radek Krejci1d82ef62015-08-07 14:44:40 +02001865static void
1866lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001867{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001868 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001869
Radek Krejci46c4cd72016-01-21 15:13:52 +01001870 if (llist->child) {
1871 /* leafref backlinks */
1872 ly_set_free((struct ly_set *)llist->child);
1873 }
1874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001875 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001876 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001877 }
1878 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001879
Radek Krejci1d82ef62015-08-07 14:44:40 +02001880 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001881
Radek Krejci1d82ef62015-08-07 14:44:40 +02001882 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001883 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001884}
1885
Radek Krejci1d82ef62015-08-07 14:44:40 +02001886static void
1887lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001888{
Radek Krejci581ce772015-11-10 17:22:40 +01001889 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001891 /* handle only specific parts for LY_NODE_LIST */
1892 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001893 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001894 }
1895 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001897 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001898 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001899 }
1900 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001901
Radek Krejci1d82ef62015-08-07 14:44:40 +02001902 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001904 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02001905 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001906 lydict_remove(ctx, list->unique[i].expr[j]);
1907 }
1908 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001909 }
1910 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001911
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001912 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001913}
1914
Radek Krejci1d82ef62015-08-07 14:44:40 +02001915static void
1916lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001917{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001918 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001919
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001920 /* handle only specific parts for LY_NODE_CONTAINER */
1921 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001922
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001923 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001924 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001925 }
1926 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001928 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001929 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001930 }
1931 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001932
Radek Krejci1d82ef62015-08-07 14:44:40 +02001933 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001934}
1935
Radek Krejci1d82ef62015-08-07 14:44:40 +02001936static void
1937lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001938{
1939 lydict_remove(ctx, f->name);
1940 lydict_remove(ctx, f->dsc);
1941 lydict_remove(ctx, f->ref);
Radek Krejci9ff0a922016-07-14 13:08:05 +02001942 lys_iffeature_free(f->iffeature, f->iffeature_size);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001943}
1944
Radek Krejci1d82ef62015-08-07 14:44:40 +02001945static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001946lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001947{
Radek Krejci581ce772015-11-10 17:22:40 +01001948 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001949 struct ly_ctx *ctx;
1950 struct lys_node *next, *elem;
1951
1952 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001953
1954 lydict_remove(ctx, dev->target_name);
1955 lydict_remove(ctx, dev->dsc);
1956 lydict_remove(ctx, dev->ref);
1957
Michal Vaskoff006c12016-02-17 11:15:19 +01001958 /* the module was freed, but we only need the context from orig_node, use ours */
1959 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1960 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1961 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1962 elem->module = module;
1963
1964 LY_TREE_DFS_END(dev->orig_node, next, elem);
1965 }
1966 lys_node_free(dev->orig_node, NULL, 0);
1967 } else {
1968 /* it's just a shallow copy, freeing one node */
1969 dev->orig_node->module = module;
1970 lys_node_free(dev->orig_node, NULL, 1);
1971 }
1972
Radek Krejcieb00f512015-07-01 16:44:58 +02001973 for (i = 0; i < dev->deviate_size; i++) {
1974 lydict_remove(ctx, dev->deviate[i].dflt);
1975 lydict_remove(ctx, dev->deviate[i].units);
1976
1977 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1978 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001979 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001980 }
1981 free(dev->deviate[i].must);
1982
1983 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001984 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1985 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1986 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01001987 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001988 }
1989 free(dev->deviate[i].unique);
1990 }
1991 }
1992 free(dev->deviate);
1993}
1994
Radek Krejci1d82ef62015-08-07 14:44:40 +02001995static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001996lys_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 +02001997{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001998 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002000 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02002001 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002002 lydict_remove(ctx, uses->refine[i].dsc);
2003 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002004
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002005 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002006 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002007 }
2008 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002009
Radek Krejci76512572015-08-04 09:47:08 +02002010 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002011 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02002012 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002013 lydict_remove(ctx, uses->refine[i].mod.presence);
2014 }
2015 }
2016 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002019 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002020 }
2021 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002022
Radek Krejci1d82ef62015-08-07 14:44:40 +02002023 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002024}
2025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002026void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002027lys_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 +02002028{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002029 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002030 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002032 if (!node) {
2033 return;
2034 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002036 assert(node->module);
2037 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002039 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002040
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002041 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002042 if (node->priv && private_destructor) {
2043 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002044 }
2045
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002046 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002047 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002048 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002049 lys_iffeature_free(node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002050 lydict_remove(ctx, node->dsc);
2051 lydict_remove(ctx, node->ref);
2052 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002053
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002054 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002055 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002056 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002057 }
2058 }
2059
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002060 /* specific part */
2061 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002062 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002063 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002064 break;
Radek Krejci76512572015-08-04 09:47:08 +02002065 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002066 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002067 break;
Radek Krejci76512572015-08-04 09:47:08 +02002068 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002069 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002070 break;
Radek Krejci76512572015-08-04 09:47:08 +02002071 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002072 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002073 break;
Radek Krejci76512572015-08-04 09:47:08 +02002074 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002075 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076 break;
Radek Krejci76512572015-08-04 09:47:08 +02002077 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002078 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002079 break;
Radek Krejci76512572015-08-04 09:47:08 +02002080 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002081 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002082 break;
Radek Krejci76512572015-08-04 09:47:08 +02002083 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002084 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002085 break;
Radek Krejci76512572015-08-04 09:47:08 +02002086 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002087 /* do nothing */
2088 break;
Radek Krejci76512572015-08-04 09:47:08 +02002089 case LYS_GROUPING:
2090 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002091 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +02002092 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002093 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002094 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002095
2096 case LYS_INPUT:
2097 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02002098 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002099 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02002100 case LYS_UNKNOWN:
2101 LOGINT;
2102 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103 }
Radek Krejci5a065542015-05-22 15:02:07 +02002104
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002106 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002107 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002108}
2109
Michal Vasko1e62a092015-12-01 12:27:20 +01002110const struct lys_module *
2111lys_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 +02002112{
Radek Krejcic071c542016-01-27 14:57:51 +01002113 const struct lys_module *main_module;
Michal Vasko89563fc2016-07-28 16:19:35 +02002114 char *str;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002115 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002116
Michal Vaskoa7789a82016-02-11 15:42:55 +01002117 assert(!prefix || !name);
2118
Michal Vaskob6729c62015-10-21 12:09:47 +02002119 if (prefix && !pref_len) {
2120 pref_len = strlen(prefix);
2121 }
2122 if (name && !name_len) {
2123 name_len = strlen(name);
2124 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002125
Radek Krejcic4283442016-04-22 09:19:27 +02002126 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002127
2128 /* module own prefix, submodule own prefix, (sub)module own name */
2129 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2130 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002131 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002132 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002133 }
2134
Michal Vasko89563fc2016-07-28 16:19:35 +02002135 /* standard import */
Michal Vasko8ce24d72015-10-21 11:27:26 +02002136 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002137 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2138 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002139 return module->imp[i].module;
2140 }
2141 }
2142
Michal Vasko89563fc2016-07-28 16:19:35 +02002143 /* module required by a foreign grouping, deviation, or submodule */
2144 if (name) {
2145 str = strndup(name, name_len);
2146 if (!str) {
2147 LOGMEM;
2148 return NULL;
2149 }
2150 main_module = ly_ctx_get_module(module->ctx, str, NULL);
2151 free(str);
2152 return main_module;
2153 }
2154
Michal Vasko8ce24d72015-10-21 11:27:26 +02002155 return NULL;
2156}
2157
Michal Vasko13b15832015-08-19 11:04:48 +02002158/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002160module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002161{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002162 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002163 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002165
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002166 assert(module->ctx);
2167 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002168
Michal Vaskob746fff2016-02-11 11:37:50 +01002169 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002170 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002171 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002172 lydict_remove(ctx, module->imp[i].dsc);
2173 lydict_remove(ctx, module->imp[i].ref);
Radek Krejci225376f2016-02-16 17:36:22 +01002174 }
Radek Krejcidce51452015-06-16 15:20:08 +02002175 free(module->imp);
2176
Radek Krejcic071c542016-01-27 14:57:51 +01002177 /* submodules don't have data tree, the data nodes
2178 * are placed in the main module altogether */
2179 if (!module->type) {
2180 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002181 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002182 }
Radek Krejci21181962015-06-30 14:11:00 +02002183 }
Radek Krejci5a065542015-05-22 15:02:07 +02002184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002185 lydict_remove(ctx, module->dsc);
2186 lydict_remove(ctx, module->ref);
2187 lydict_remove(ctx, module->org);
2188 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002189 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002190
Radek Krejcieb00f512015-07-01 16:44:58 +02002191 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002192 for (i = 0; i < module->rev_size; i++) {
2193 lydict_remove(ctx, module->rev[i].dsc);
2194 lydict_remove(ctx, module->rev[i].ref);
2195 }
2196 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002197
Radek Krejcieb00f512015-07-01 16:44:58 +02002198 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002200 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002201 }
2202 module->ident_size = 0;
2203 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002204
Radek Krejcieb00f512015-07-01 16:44:58 +02002205 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002206 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002207 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002208 }
2209 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002210
Radek Krejcieb00f512015-07-01 16:44:58 +02002211 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002212 for (i = 0; i < module->inc_size; i++) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002213 lydict_remove(ctx, module->inc[i].dsc);
2214 lydict_remove(ctx, module->inc[i].ref);
Radek Krejcic071c542016-01-27 14:57:51 +01002215 /* complete submodule free is done only from main module since
2216 * submodules propagate their includes to the main module */
2217 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002218 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002219 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 }
2221 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002222
Radek Krejcieb00f512015-07-01 16:44:58 +02002223 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002224 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002225 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002226 }
2227 free(module->augment);
2228
Radek Krejcieb00f512015-07-01 16:44:58 +02002229 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002230 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002231 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002232 }
2233 free(module->features);
2234
Radek Krejcieb00f512015-07-01 16:44:58 +02002235 /* deviations */
2236 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002237 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002238 }
2239 free(module->deviation);
2240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002241 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002242 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002243}
2244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002245void
Michal Vaskob746fff2016-02-11 11:37:50 +01002246lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002247{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002248 if (!submodule) {
2249 return;
2250 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002252 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002253 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002255 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002258}
2259
Radek Krejci3a5501d2016-07-18 22:03:34 +02002260static int
2261ingrouping(const struct lys_node *node)
2262{
2263 const struct lys_node *iter = node;
2264 assert(node);
2265
2266 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2267 if (!iter) {
2268 return 0;
2269 } else {
2270 return 1;
2271 }
2272}
2273
Radek Krejci76512572015-08-04 09:47:08 +02002274struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002275lys_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 +01002276 uint8_t nacm, struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002277{
Radek Krejcic071c542016-01-27 14:57:51 +01002278 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002280 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002281 unsigned int size, size1, size2;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002282
Michal Vaskoc07187d2015-08-13 15:20:57 +02002283 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002284 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002285 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002286 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002287 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002288 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002289 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002290 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002291 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002292 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002293 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002294 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002295 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002296 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002297 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002298 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002299 struct lys_node_rpc_action *rpc = NULL;
2300 struct lys_node_rpc_action *rpc_orig = (struct lys_node_rpc_action *)node;
2301 struct lys_node_inout *io = NULL;
2302 struct lys_node_inout *io_orig = (struct lys_node_inout *)node;
2303 struct lys_node_rpc_action *ntf = NULL;
2304 struct lys_node_rpc_action *ntf_orig = (struct lys_node_rpc_action *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002305 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002306 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002308 /* we cannot just duplicate memory since the strings are stored in
2309 * dictionary and we need to update dictionary counters.
2310 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002311
Radek Krejci1d82ef62015-08-07 14:44:40 +02002312 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002313 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002315 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002316 break;
2317
Radek Krejci76512572015-08-04 09:47:08 +02002318 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002319 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002320 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 break;
2322
Radek Krejci76512572015-08-04 09:47:08 +02002323 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002325 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002326 break;
2327
Radek Krejci76512572015-08-04 09:47:08 +02002328 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002329 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002330 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331 break;
2332
Radek Krejci76512572015-08-04 09:47:08 +02002333 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002335 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002336 break;
2337
Radek Krejci76512572015-08-04 09:47:08 +02002338 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002339 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002340 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002341 break;
2342
Radek Krejci76512572015-08-04 09:47:08 +02002343 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002344 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002345 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002346 break;
2347
Radek Krejci76512572015-08-04 09:47:08 +02002348 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002349 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002350 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351 break;
2352
Radek Krejci76512572015-08-04 09:47:08 +02002353 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002354 grp = calloc(1, sizeof *grp);
2355 retval = (struct lys_node *)grp;
2356 break;
2357
Radek Krejci76512572015-08-04 09:47:08 +02002358 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002359 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002360 rpc = calloc(1, sizeof *rpc);
2361 retval = (struct lys_node *)rpc;
2362 break;
2363
Radek Krejci76512572015-08-04 09:47:08 +02002364 case LYS_INPUT:
2365 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002366 io = calloc(1, sizeof *io);
2367 retval = (struct lys_node *)io;
2368 break;
2369
Radek Krejci76512572015-08-04 09:47:08 +02002370 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002371 ntf = calloc(1, sizeof *ntf);
2372 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002373 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002374
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002375 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002376 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002377 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002378 }
Radek Krejcib388c152015-06-04 17:03:03 +02002379
Michal Vasko253035f2015-12-17 16:58:13 +01002380 if (!retval) {
2381 LOGMEM;
2382 return NULL;
2383 }
2384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002385 /*
2386 * duplicate generic part of the structure
2387 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002388 retval->name = lydict_insert(ctx, node->name, 0);
2389 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2390 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002391 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002392 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002393 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002394 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002395 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002396 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002398 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002399 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002401 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002402
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002403 retval->iffeature_size = node->iffeature_size;
2404 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2405 if (!retval->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002406 LOGMEM;
2407 goto error;
2408 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002409
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002410 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002411 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002412 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2413 if (size1) {
2414 /* there is something to duplicate */
2415
2416 /* duplicate compiled expression */
2417 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2418 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2419 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2420
2421 /* list of feature pointer must be updated to point to the resulting tree */
2422 retval->iffeature[i].features = malloc(size2 * sizeof *retval->iffeature[i].features);
2423 for (j = 0; (unsigned int)j < size2; j++) {
2424 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2425 &retval->iffeature[i].features[j]);
2426 if (rc == EXIT_SUCCESS) {
2427 /* feature is not resolved, duplicate the expression string */
2428 retval->iffeature[i].features[j] = (void *)strdup((char *)node->iffeature[i].features[j]);
2429 } else if (rc == EXIT_FAILURE) {
2430 /* feature is resolved in origin, so copy it
2431 * - duplication is used for instantiating groupings
2432 * and if-feature inside grouping is supposed to be
2433 * resolved inside the original grouping, so we want
2434 * to keep pointers to features from the grouping
2435 * context */
2436 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2437 } else if (rc == -1) {
2438 goto error;
2439 }
2440 }
2441 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002442 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002443
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002444 /* connect it to the parent */
2445 if (lys_node_addchild(parent, retval->module, retval)) {
2446 goto error;
2447 }
Radek Krejcidce51452015-06-16 15:20:08 +02002448
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002449 /* go recursively */
2450 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2451 LY_TREE_FOR(node->child, child) {
2452 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres, 0)) {
2453 goto error;
2454 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002455 }
2456 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002457 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002458 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002459 }
2460
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002461 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002462 * duplicate specific part of the structure
2463 */
2464 switch (node->nodetype) {
2465 case LYS_CONTAINER:
2466 if (cont_orig->when) {
2467 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002468 }
2469 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002471 cont->must_size = cont_orig->must_size;
2472 cont->tpdf_size = cont_orig->tpdf_size;
2473
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002474 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskodcf98e62016-05-05 17:53:53 +02002475 cont->tpdf = lys_tpdf_dup(module, lys_parent(node), cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002476 break;
2477
2478 case LYS_CHOICE:
2479 if (choice_orig->when) {
2480 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002481 }
2482
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002483 if (!shallow) {
2484 if (choice_orig->dflt) {
2485 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0, LYS_ANYXML
2486 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
2487 | LYS_LIST, (const struct lys_node **)&choice->dflt);
2488 if (rc) {
2489 if (rc == EXIT_FAILURE) {
2490 LOGINT;
2491 }
2492 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002493 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002494 } else {
2495 /* useless to check return value, we don't know whether
2496 * there really wasn't any default defined or it just hasn't
2497 * been resolved, we just hope for the best :)
2498 */
2499 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002500 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002501 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002502 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002503 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002504 break;
2505
2506 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002507 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002508 goto error;
2509 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002510 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2511
2512 if (leaf_orig->dflt) {
2513 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci48464ed2016-03-17 15:44:09 +01002514 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002515 goto error;
2516 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002517 }
2518
2519 leaf->must_size = leaf_orig->must_size;
2520 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002521
2522 if (leaf_orig->when) {
2523 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002524 }
2525 break;
2526
2527 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002528 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002529 goto error;
2530 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2532
2533 llist->min = llist_orig->min;
2534 llist->max = llist_orig->max;
2535
2536 llist->must_size = llist_orig->must_size;
2537 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002538
2539 if (llist_orig->when) {
2540 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002541 }
2542 break;
2543
2544 case LYS_LIST:
2545 list->min = list_orig->min;
2546 list->max = list_orig->max;
2547
2548 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002549 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002550
Radek Krejci581ce772015-11-10 17:22:40 +01002551 list->tpdf_size = list_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002552 list->tpdf = lys_tpdf_dup(module, lys_parent(node), list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002553
Radek Krejci581ce772015-11-10 17:22:40 +01002554 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002555 if (list->keys_size) {
2556 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002557 if (!list->keys) {
2558 LOGMEM;
2559 goto error;
2560 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002561
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002562 if (!shallow) {
2563 /* we managed to resolve it before, resolve it again manually */
2564 if (list_orig->keys[0]) {
2565 for (i = 0; i < list->keys_size; ++i) {
2566 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2567 (const struct lys_node **)&list->keys[i]);
2568 if (rc) {
2569 if (rc == EXIT_FAILURE) {
2570 LOGINT;
2571 }
2572 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002573 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002574 }
2575 /* it was not resolved yet, add unres copy */
2576 } else {
2577 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2578 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002579 goto error;
2580 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002581 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002582 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002583 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002584 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002585 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002586
Radek Krejci581ce772015-11-10 17:22:40 +01002587 list->unique_size = list_orig->unique_size;
2588 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002589 if (!list->unique) {
2590 LOGMEM;
2591 goto error;
2592 }
Radek Krejci581ce772015-11-10 17:22:40 +01002593 for (i = 0; i < list->unique_size; ++i) {
2594 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2595 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002596 if (!list->unique[i].expr) {
2597 LOGMEM;
2598 goto error;
2599 }
Radek Krejci581ce772015-11-10 17:22:40 +01002600 for (j = 0; j < list->unique[i].expr_size; j++) {
2601 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2602
2603 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002604 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002605 }
2606 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002608 if (list_orig->when) {
2609 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002610 }
Radek Krejcidce51452015-06-16 15:20:08 +02002611 break;
2612
2613 case LYS_ANYXML:
2614 anyxml->must_size = anyxml_orig->must_size;
2615 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002616
2617 if (anyxml_orig->when) {
2618 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002619 }
2620 break;
2621
2622 case LYS_USES:
2623 uses->grp = uses_orig->grp;
2624
2625 if (uses_orig->when) {
2626 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002627 }
2628
2629 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002630 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002631 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002632 if (!shallow) {
2633 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskocda51712016-05-19 15:22:11 +02002634 if (!uses->grp || uses->grp->nacm) {
2635 assert(!uses->child);
Radek Krejci48464ed2016-03-17 15:44:09 +01002636 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002637 goto error;
2638 }
Michal Vasko49168a22015-08-17 16:35:41 +02002639 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002640 } else {
2641 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002642 }
2643 break;
2644
Radek Krejcidce51452015-06-16 15:20:08 +02002645 case LYS_CASE:
2646 if (cs_orig->when) {
2647 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002648 }
2649 break;
2650
2651 case LYS_GROUPING:
2652 grp->tpdf_size = grp_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002653 grp->tpdf = lys_tpdf_dup(module, lys_parent(node), grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002654 break;
2655
2656 case LYS_RPC:
2657 rpc->tpdf_size = rpc_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002658 rpc->tpdf = lys_tpdf_dup(module, lys_parent(node), rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002659 break;
2660
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002661 case LYS_INPUT:
2662 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002663 io->tpdf_size = io_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002664 io->tpdf = lys_tpdf_dup(module, lys_parent(node), io_orig->tpdf, io->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002665 break;
2666
Radek Krejcida04f4a2015-05-21 12:54:09 +02002667 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002668 ntf->tpdf_size = ntf_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002669 ntf->tpdf = lys_tpdf_dup(module, lys_parent(node), ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002670 break;
2671
2672 default:
2673 /* LY_NODE_AUGMENT */
2674 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002675 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002676 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002677
2678 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002679
2680error:
2681
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002682 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002683 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002684}
2685
Michal Vasko13b15832015-08-19 11:04:48 +02002686void
Michal Vaskoff006c12016-02-17 11:15:19 +01002687lys_node_switch(struct lys_node *dst, struct lys_node *src)
2688{
2689 struct lys_node *child;
2690
Michal Vaskob42b6972016-06-06 14:21:30 +02002691 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01002692
2693 /* sibling next */
2694 if (dst->prev != dst) {
2695 dst->prev->next = src;
2696 }
2697
2698 /* sibling prev */
2699 if (dst->next) {
2700 dst->next->prev = src;
2701 }
2702
2703 /* parent child prev */
2704 if (!dst->next && dst->parent) {
2705 dst->parent->child->prev = src;
2706 }
2707
2708 /* next */
2709 src->next = dst->next;
2710 dst->next = NULL;
2711
2712 /* prev */
2713 if (dst->prev != dst) {
2714 src->prev = dst->prev;
2715 }
2716 dst->prev = dst;
2717
2718 /* parent child */
2719 if (dst->parent && (dst->parent->child == dst)) {
2720 dst->parent->child = src;
2721 }
2722
2723 /* parent */
2724 src->parent = dst->parent;
2725 dst->parent = NULL;
2726
2727 /* child parent */
2728 LY_TREE_FOR(dst->child, child) {
2729 if (child->parent == dst) {
2730 child->parent = src;
2731 }
2732 }
2733
2734 /* child */
2735 src->child = dst->child;
2736 dst->child = NULL;
2737}
2738
2739void
Michal Vasko627975a2016-02-11 11:39:03 +01002740lys_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 +02002741{
2742 struct ly_ctx *ctx;
2743 int i;
2744
2745 if (!module) {
2746 return;
2747 }
2748
2749 /* remove schema from the context */
2750 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002751 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002752 for (i = 0; i < ctx->models.used; i++) {
2753 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002754 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002755 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002756 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 +02002757 ctx->models.list[ctx->models.used] = NULL;
2758 /* we are done */
2759 break;
2760 }
2761 }
2762 }
2763
2764 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002765 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002766
2767 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002768 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002769
2770 free(module);
2771}
Radek Krejci7e97c352015-06-19 16:26:34 +02002772
2773/*
2774 * op: 1 - enable, 0 - disable
2775 */
2776static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002777lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002778{
2779 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002780 int i, j, k;
Radek Krejci7e97c352015-06-19 16:26:34 +02002781
2782 if (!module || !name || !strlen(name)) {
2783 return EXIT_FAILURE;
2784 }
2785
2786 if (!strcmp(name, "*")) {
2787 /* enable all */
2788 all = 1;
2789 }
2790
2791 /* module itself */
2792 for (i = 0; i < module->features_size; i++) {
2793 if (all || !strcmp(module->features[i].name, name)) {
2794 if (op) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002795 /* check referenced features if they are enabled */
2796 for (j = 0; j < module->features[i].iffeature_size; j++) {
Radek Krejci69b8d922016-07-27 13:13:41 +02002797 if (!resolve_iffeature(&module->features[i].iffeature[j])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002798 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2799 module->features[i].name, j + 1);
2800 return EXIT_FAILURE;
2801 }
2802 }
2803
Radek Krejci1574a8d2015-08-03 14:16:52 +02002804 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002805 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002806 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002807 }
2808 if (!all) {
2809 return EXIT_SUCCESS;
2810 }
2811 }
2812 }
2813
2814 /* submodules */
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002815 for (i = 0; i < module->inc_size; i++) {
2816 for (j = 0; j < module->inc[i].submodule->features_size; j++) {
2817 if (all || !strcmp(module->inc[i].submodule->features[j].name, name)) {
Radek Krejci7e97c352015-06-19 16:26:34 +02002818 if (op) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002819 /* check referenced features if they are enabled */
2820 for (k = 0; k < module->inc[i].submodule->features[j].iffeature_size; k++) {
Radek Krejci69b8d922016-07-27 13:13:41 +02002821 if (!resolve_iffeature(&module->inc[i].submodule->features[j].iffeature[k])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002822 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2823 module->inc[i].submodule->features[j].name, k + 1);
2824 return EXIT_FAILURE;
2825 }
2826 }
2827
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002828 module->inc[i].submodule->features[j].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002829 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002830 module->inc[i].submodule->features[j].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002831 }
2832 if (!all) {
2833 return EXIT_SUCCESS;
2834 }
2835 }
2836 }
2837 }
2838
2839 if (all) {
2840 return EXIT_SUCCESS;
2841 } else {
2842 return EXIT_FAILURE;
2843 }
2844}
2845
2846API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002847lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002848{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002849 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002850}
2851
2852API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002853lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002854{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002855 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002856}
2857
2858API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002859lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002860{
2861 int i, j;
2862
2863 if (!module || !feature) {
2864 return -1;
2865 }
2866
2867 /* search for the specified feature */
2868 /* module itself */
2869 for (i = 0; i < module->features_size; i++) {
2870 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002871 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002872 return 1;
2873 } else {
2874 return 0;
2875 }
2876 }
2877 }
2878
2879 /* submodules */
2880 for (j = 0; j < module->inc_size; j++) {
2881 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2882 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002883 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002884 return 1;
2885 } else {
2886 return 0;
2887 }
2888 }
2889 }
2890 }
2891
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002892 /* feature definition not found */
2893 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002894}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002895
Radek Krejci96a10da2015-07-30 11:00:14 +02002896API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002897lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002898{
Radek Krejci96a10da2015-07-30 11:00:14 +02002899 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002900 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002901 unsigned int count;
2902
2903 if (!module) {
2904 return NULL;
2905 }
2906
2907 count = module->features_size;
2908 for (i = 0; i < module->inc_size; i++) {
2909 count += module->inc[i].submodule->features_size;
2910 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002911 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002912 if (!result) {
2913 LOGMEM;
2914 return NULL;
2915 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002916 if (states) {
2917 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002918 if (!(*states)) {
2919 LOGMEM;
2920 free(result);
2921 return NULL;
2922 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002923 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002924 count = 0;
2925
2926 /* module itself */
2927 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002928 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002929 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002930 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002931 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002932 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002933 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002934 }
2935 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002936 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002937 }
2938
2939 /* submodules */
2940 for (j = 0; j < module->inc_size; j++) {
2941 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002942 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002943 if (states) {
2944 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2945 (*states)[count] = 1;
2946 } else {
2947 (*states)[count] = 0;
2948 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002949 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002950 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002951 }
2952 }
2953
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002954 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002955 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002956
2957 return result;
2958}
Michal Vaskobaefb032015-09-24 14:52:10 +02002959
Radek Krejci6910a032016-04-13 10:06:21 +02002960API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002961lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002962{
2963 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2964}
2965
Radek Krejci6910a032016-04-13 10:06:21 +02002966API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02002967lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01002968{
2969 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2970}
2971
Michal Vaskobaefb032015-09-24 14:52:10 +02002972API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002973lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002974{
2975 if (!node || !node->parent) {
2976 return NULL;
2977 }
2978
2979 if (node->parent->nodetype == LYS_AUGMENT) {
2980 return ((struct lys_node_augment *)node->parent)->target;
2981 }
2982
2983 return node->parent;
2984}
Michal Vasko1b229152016-01-13 11:28:38 +01002985
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002986API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002987lys_set_private(const struct lys_node *node, void *priv)
2988{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002989 void *prev;
2990
Michal Vasko1b229152016-01-13 11:28:38 +01002991 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002992 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2993 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002994 }
2995
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002996 prev = node->priv;
2997 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002998
2999 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01003000}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003001
Michal Vasko01c6fd22016-05-20 11:43:05 +02003002int
3003lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
3004{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003005 struct lys_node_leaf *iter = leafref_target;
3006
Michal Vasko48a573d2016-07-01 11:46:02 +02003007 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003008 LOGINT;
3009 return -1;
3010 }
3011
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003012 /* check for cycles */
3013 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
3014 if ((void *)iter == (void *)leafref) {
3015 /* cycle detected */
3016 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
3017 return -1;
3018 }
3019 iter = iter->type.info.lref.target;
3020 }
3021
3022 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02003023 * leafrefs referencing the leaf(-list) */
Michal Vasko01c6fd22016-05-20 11:43:05 +02003024 if (!leafref_target->child) {
3025 leafref_target->child = (void*)ly_set_new();
3026 if (!leafref_target->child) {
3027 LOGMEM;
3028 return -1;
3029 }
3030 }
Radek Krejci09891a22016-06-10 10:59:22 +02003031 ly_set_add((struct ly_set *)leafref_target->child, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003032
3033 return 0;
3034}
3035
Michal Vasko8548e082016-07-22 12:00:18 +02003036/* not needed currently */
3037#if 0
3038
Michal Vasko5b3492c2016-07-20 09:37:40 +02003039static const char *
3040lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
3041{
3042 struct lys_module *prev_mod;
3043 uint32_t str_len, mod_len, buf_idx;
3044
3045 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
3046 LOGINT;
3047 return NULL;
3048 }
3049
3050 buf_idx = buf_len - 1;
3051 buf[buf_idx] = '\0';
3052
3053 while (node) {
3054 if (lys_parent(node)) {
3055 prev_mod = lys_node_module(lys_parent(node));
3056 } else {
3057 prev_mod = NULL;
3058 }
3059
3060 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
3061 str_len = strlen(node->name);
3062
3063 if (prev_mod != node->module) {
3064 mod_len = strlen(node->module->name);
3065 } else {
3066 mod_len = 0;
3067 }
3068
3069 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
3070 LOGINT;
3071 return NULL;
3072 }
3073
3074 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
3075
3076 buf[buf_idx] = '/';
3077 if (mod_len) {
3078 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
3079 buf[buf_idx + 1 + mod_len] = ':';
3080 }
3081 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
3082 }
3083
3084 node = lys_parent(node);
3085 }
3086
3087 return buf + buf_idx;
3088}
3089
Michal Vasko8548e082016-07-22 12:00:18 +02003090#endif
3091
3092API struct ly_set *
3093lys_xpath_atomize(const struct lys_node *cur_snode, const char *expr, int options)
Michal Vasko5b3492c2016-07-20 09:37:40 +02003094{
Michal Vasko5b3492c2016-07-20 09:37:40 +02003095 struct lyxp_set *set;
Michal Vasko8548e082016-07-22 12:00:18 +02003096 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003097 uint32_t i;
3098
Michal Vasko8548e082016-07-22 12:00:18 +02003099 if (!cur_snode || !expr) {
3100 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003101 }
3102
3103 set = calloc(1, sizeof *set);
3104 if (!set) {
3105 LOGMEM;
Michal Vasko8548e082016-07-22 12:00:18 +02003106 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003107 }
3108
3109 if (options & LYXP_MUST) {
3110 options &= ~LYXP_MUST;
3111 options |= LYXP_SNODE_MUST;
3112 } else if (options & LYXP_WHEN) {
3113 options &= ~LYXP_WHEN;
3114 options |= LYXP_SNODE_WHEN;
3115 } else {
3116 options |= LYXP_SNODE;
3117 }
3118
3119 if (lyxp_atomize(expr, cur_snode, set, options)) {
3120 free(set->val.snodes);
3121 free(set);
Michal Vasko8548e082016-07-22 12:00:18 +02003122 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003123 }
3124
Michal Vasko8548e082016-07-22 12:00:18 +02003125 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003126
Michal Vasko5b3492c2016-07-20 09:37:40 +02003127 for (i = 0; i < set->used; ++i) {
3128 switch (set->val.snodes[i].type) {
3129 case LYXP_NODE_ELEM:
Michal Vasko8548e082016-07-22 12:00:18 +02003130 if (ly_set_add(ret_set, set->val.snodes[i].snode, LY_SET_OPT_USEASLIST)) {
3131 ly_set_free(ret_set);
3132 free(set->val.snodes);
3133 free(set);
3134 return NULL;
3135 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003136 break;
3137 default:
Michal Vasko8548e082016-07-22 12:00:18 +02003138 /* ignore roots, text and attr should not appear ever */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003139 break;
3140 }
3141 }
3142
Michal Vasko5b3492c2016-07-20 09:37:40 +02003143 free(set->val.snodes);
3144 free(set);
Michal Vasko8548e082016-07-22 12:00:18 +02003145 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003146}
3147
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003148static void
Michal Vasko89563fc2016-07-28 16:19:35 +02003149lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *target_module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003150{
3151 int ret;
3152 char *parent_path;
3153 struct lys_node *target;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003154
3155 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
3156 if (dev->orig_node) {
3157 /* removing not-supported deviation ... */
3158 if (strrchr(dev->target_name, '/') != dev->target_name) {
3159 /* ... from a parent */
3160 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
3161
3162 target = NULL;
3163 ret = resolve_augment_schema_nodeid(parent_path, NULL, target_module, (const struct lys_node **)&target);
3164 free(parent_path);
3165 if (ret || !target) {
3166 LOGINT;
3167 return;
3168 }
3169
3170 lys_node_addchild(target, NULL, dev->orig_node);
3171 } else {
3172 /* ... from top-level data */
3173 lys_node_addchild(NULL, (struct lys_module *)target_module, dev->orig_node);
3174 }
3175
3176 dev->orig_node = NULL;
3177 } else {
3178 /* adding not-supported deviation */
3179 target = NULL;
3180 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
3181 if (ret || !target) {
3182 LOGINT;
3183 return;
3184 }
3185
3186 lys_node_unlink(target);
3187 dev->orig_node = target;
3188 }
3189 } else {
3190 target = NULL;
3191 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
3192 if (ret || !target) {
3193 LOGINT;
3194 return;
3195 }
3196
3197 lys_node_switch(target, dev->orig_node);
3198 dev->orig_node = target;
3199 }
3200}
3201
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003202/* temporarily removes or applies deviations, updates module deviation flag accordingly */
3203void
3204lys_switch_deviations(struct lys_module *module)
3205{
Michal Vasko89563fc2016-07-28 16:19:35 +02003206 uint32_t i = 0, j;
3207 const struct lys_module *mod;
3208 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003209
Michal Vasko89563fc2016-07-28 16:19:35 +02003210 if (module->deviated) {
3211 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3212 if (mod == module) {
3213 continue;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003214 }
3215
Michal Vasko89563fc2016-07-28 16:19:35 +02003216 for (j = 0; j < mod->deviation_size; ++j) {
3217 ptr = strstr(mod->deviation[j].target_name, module->name);
3218 if (ptr && ptr[strlen(module->name)] == ':') {
3219 lys_switch_deviation(&mod->deviation[j], module);
3220 }
3221 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003222 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003223
Michal Vasko89563fc2016-07-28 16:19:35 +02003224 if (module->deviated == 2) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003225 module->deviated = 1;
Michal Vasko89563fc2016-07-28 16:19:35 +02003226 } else {
3227 module->deviated = 2;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003228 }
3229 }
3230}
3231
3232/* not needed currently, but tested and working */
3233#if 0
3234
3235void
3236lys_sub_module_apply_devs_augs(struct lys_module *module)
3237{
3238 int i;
3239 struct lys_node_augment *aug;
3240 struct lys_node *last;
3241
3242 /* re-apply deviations */
3243 for (i = 0; i < module->deviation_size; ++i) {
3244 lys_switch_deviation(&module->deviation[i], module);
3245 assert(module->deviation[i].orig_node);
Michal Vasko89563fc2016-07-28 16:19:35 +02003246 lys_node_module(module->deviation[i].orig_node)->deviated = 1;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003247 }
3248
3249 /* re-apply augments */
3250 for (i = 0; i < module->augment_size; ++i) {
3251 aug = &module->augment[i];
3252 assert(aug->target);
3253
3254 /* reconnect augmenting data into the target - add them to the target child list */
3255 if (aug->target->child) {
3256 last = aug->target->child->prev;
3257 last->next = aug->child;
3258 aug->target->child->prev = aug->child->prev;
3259 aug->child->prev = last;
3260 } else {
3261 aug->target->child = aug->child;
3262 }
3263 }
3264}
3265
3266#endif
3267
3268void
3269lys_sub_module_remove_devs_augs(struct lys_module *module)
3270{
Michal Vasko89563fc2016-07-28 16:19:35 +02003271 uint32_t i = 0, j;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003272 struct lys_node *last, *elem;
Michal Vasko89563fc2016-07-28 16:19:35 +02003273 const struct lys_module *mod;
3274 struct lys_module *target_mod;
3275 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003276
3277 /* remove applied deviations */
3278 for (i = 0; i < module->deviation_size; ++i) {
3279 lys_switch_deviation(&module->deviation[i], module);
Michal Vasko89563fc2016-07-28 16:19:35 +02003280 target_mod = lys_node_module(module->deviation[i].orig_node);
3281 assert(target_mod->deviated == 1);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003282
Michal Vasko89563fc2016-07-28 16:19:35 +02003283 /* clear the deviation flag if possible */
3284 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3285 if ((mod == module) || (mod == target_mod)) {
3286 continue;
3287 }
3288
3289 for (j = 0; j < mod->deviation_size; ++j) {
3290 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
3291 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
3292 /* some other module deviation targets the inspected module, flag remains */
3293 break;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003294 }
3295 }
Michal Vasko89563fc2016-07-28 16:19:35 +02003296
3297 if (j < mod->deviation_size) {
3298 break;
3299 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003300 }
Michal Vasko89563fc2016-07-28 16:19:35 +02003301
3302 if (!mod) {
3303 target_mod->deviated = 0;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003304 }
3305 }
3306
3307 /* remove applied augments */
3308 for (i = 0; i < module->augment_size; ++i) {
Radek Krejcidbc15262016-06-16 14:58:29 +02003309 if (!module->augment[i].target) {
3310 /* skip not resolved augments */
3311 continue;
3312 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003313
3314 elem = module->augment[i].child;
3315 if (elem) {
3316 LY_TREE_FOR(elem, last) {
3317 if (!last->next || (last->next->parent != (struct lys_node *)&module->augment[i])) {
3318 break;
3319 }
3320 }
3321 /* elem is first augment child, last is the last child */
3322
3323 /* parent child ptr */
3324 if (module->augment[i].target->child == elem) {
3325 module->augment[i].target->child = last->next;
3326 }
3327
3328 /* parent child next ptr */
3329 if (elem->prev->next) {
3330 elem->prev->next = last->next;
3331 }
3332
3333 /* parent child prev ptr */
3334 if (last->next) {
3335 last->next->prev = elem->prev;
3336 } else if (module->augment[i].target->child) {
3337 module->augment[i].target->child->prev = elem->prev;
3338 }
3339
3340 /* update augment children themselves */
3341 elem->prev = last;
3342 last->next = NULL;
3343 }
Michal Vaskob8f71322016-05-03 11:39:56 +02003344
3345 /* needs to be NULL for lys_augment_free() to free the children */
3346 module->augment[i].target = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003347 }
3348}
3349
Michal Vasko26055752016-05-03 11:36:31 +02003350int
3351lys_module_set_implement(struct lys_module *module)
3352{
3353 struct ly_ctx *ctx;
3354 int i;
3355
3356 if (module->implemented) {
3357 return EXIT_SUCCESS;
3358 }
3359
3360 ctx = module->ctx;
3361
3362 for (i = 0; i < ctx->models.used; ++i) {
3363 if (module == ctx->models.list[i]) {
3364 continue;
3365 }
3366
3367 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
3368 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
3369 return EXIT_FAILURE;
3370 }
3371 }
3372
3373 module->implemented = 1;
3374 return EXIT_SUCCESS;
3375}
3376
3377int
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003378lys_sub_module_set_dev_aug_target_implement(struct lys_module *module)
3379{
3380 int i;
3381 struct lys_module *trg_mod;
3382
3383 for (i = 0; i < module->deviation_size; ++i) {
3384 assert(module->deviation[i].orig_node);
3385 trg_mod = lys_node_module(module->deviation[i].orig_node);
Michal Vasko26055752016-05-03 11:36:31 +02003386 if (lys_module_set_implement(trg_mod)) {
3387 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003388 }
3389 }
3390
3391 for (i = 0; i < module->augment_size; ++i) {
3392 assert(module->augment[i].target);
3393 trg_mod = lys_node_module(module->augment[i].target);
Michal Vasko26055752016-05-03 11:36:31 +02003394 if (lys_module_set_implement(trg_mod)) {
3395 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003396 }
3397 }
Michal Vasko26055752016-05-03 11:36:31 +02003398
3399 return EXIT_SUCCESS;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003400}
3401
3402void
3403lys_submodule_module_data_free(struct lys_submodule *submodule)
3404{
3405 struct lys_node *next, *elem;
3406
3407 /* remove parsed data */
3408 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
3409 if (elem->module == (struct lys_module *)submodule) {
3410 lys_node_free(elem, NULL, 0);
3411 }
3412 }
3413}