blob: 312c1d22d846637742478b5c8f0f8bce07173fdd [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 Krejci972724f2016-08-12 15:24:40 +0200189 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
190 /* continue with uses content */
191 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200192 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200193 /* continue after the last returned value */
194 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200195 }
196
197repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200198 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200199 if (options & LYS_GETNEXT_WITHGROUPING) {
200 return next;
201 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200202 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200203 }
204
Radek Krejci972724f2016-08-12 15:24:40 +0200205 if (!next) { /* cover case when parent is augment */
206 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200207 /* no next element */
208 return NULL;
209 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200210 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200211 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200212 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200213 } else {
214 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200215 }
216
217 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200218 case LYS_INPUT:
219 case LYS_OUTPUT:
220 if (options & LYS_GETNEXT_WITHINOUT) {
221 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200222 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200223 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200224 } else {
225 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200226 }
Radek Krejci972724f2016-08-12 15:24:40 +0200227 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200228
Michal Vaskoa5835e92015-10-20 15:07:39 +0200229 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200230 if (options & LYS_GETNEXT_WITHCASE) {
231 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200232 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200233 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200234 } else {
235 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200236 }
Radek Krejci972724f2016-08-12 15:24:40 +0200237 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200238
Michal Vasko1dca6882015-10-22 14:29:42 +0200239 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200240 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200241 if (options & LYS_GETNEXT_WITHUSES) {
242 return next;
243 } else if (next->child) {
244 next = next->child;
245 } else {
246 next = next->next;
247 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200248 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200249
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200250 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200251 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200252 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200253 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200254 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200255 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200256 case LYS_LIST:
257 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200258 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200259
Radek Krejci972724f2016-08-12 15:24:40 +0200260 case LYS_CONTAINER:
261 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
262 if (next->child) {
263 /* go into */
264 next = next->child;
265 } else {
266 next = next->next;
267 }
268 goto repeat;
269 } else {
270 return next;
271 }
272
Radek Krejci8bc87f62015-09-02 16:19:05 +0200273 case LYS_CHOICE:
274 if (options & LYS_GETNEXT_WITHCHOICE) {
275 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200276 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200277 /* go into */
278 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200279 } else {
280 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200281 }
Radek Krejci972724f2016-08-12 15:24:40 +0200282 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200283
Radek Krejci7f40ce32015-08-12 20:38:46 +0200284 default:
285 /* we should not be here */
286 return NULL;
287 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200288
289
290}
291
Michal Vasko1e62a092015-12-01 12:27:20 +0100292static const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100293check_mand_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module)
Radek Krejci8bc87f62015-09-02 16:19:05 +0200294{
Michal Vasko1e62a092015-12-01 12:27:20 +0100295 const struct lys_node *next;
296
Radek Krejci2342cf62016-01-29 16:48:23 +0100297 next = lys_getnext(last, parent, module, LYS_GETNEXT_WITHCHOICE);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200298
Radek Krejci4b6c2112015-10-06 12:48:34 +0200299repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200300 if (next && next->nodetype == LYS_CONTAINER) {
301 if (((struct lys_node_container *)next)->presence) {
302 /* mandatory elements under the non-existing presence
303 * container are not mandatory - 7.6.5, rule 1 */
304 next = next->next;
305 } else {
306 /* go into */
307 next = next->child;
308 }
309 goto repeat;
310 }
311
312 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200313}
314
Michal Vasko84f821a2016-04-11 11:03:42 +0200315static int
Michal Vasko1e62a092015-12-01 12:27:20 +0100316check_mand_check(const struct lys_node *node, const struct lys_node *stop, const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200317{
Radek Krejci7531aa22016-04-12 13:52:19 +0200318 const struct lys_node *siter = NULL, *missing_parent = NULL;
Radek Krejci96e20852016-04-11 17:51:26 +0200319 struct lys_node *parent = NULL;
Radek Krejci7531aa22016-04-12 13:52:19 +0200320 const struct lyd_node *diter = NULL;
Radek Krejcidc154432016-01-21 11:10:59 +0100321 struct ly_set *set = NULL;
Michal Vaskof610fd42016-04-19 10:38:20 +0200322 unsigned int i, toplevel = (stop && stop->nodetype != LYS_OUTPUT) ? 0 : 1;
Michal Vasko84f821a2016-04-11 11:03:42 +0200323 uint32_t minmax, min, max;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200324
Radek Krejci7531aa22016-04-12 13:52:19 +0200325 if (data) {
326 /* go to the correct data level */
327 for (parent = lys_parent(node); parent && parent != stop; parent = lys_parent(parent)) {
328 /* 7.6.5, rule 1 (presence container), checking presence
329 * is not needed since it is done in check_mand_getnext()
330 */
331
332 if (parent->nodetype != LYS_CONTAINER) {
333 /* not interested in LYS_USES, LYS_CASE or LYS_CHOICE,
334 * because they are not instantiated in data tree */
335 continue;
336 }
337 /* add the parent to the list for searching in data tree */
338 if (!set) {
339 set = ly_set_new();
340 }
341 /* ignore return - memory error is logged and we will
342 * check at least the rest of nodes we have */
Radek Krejci09891a22016-06-10 10:59:22 +0200343 (void)ly_set_add(set, parent, LY_SET_OPT_USEASLIST);
Radek Krejci7531aa22016-04-12 13:52:19 +0200344 }
345 if (set) {
346 for (i = set->number; i > 0; ) {
347 i--;
348 LY_TREE_FOR(toplevel ? data : data->child, diter) {
349 if (diter->schema == set->set.s[i]) {
350 break;
351 }
352 }
353 if (!diter) {
354 /* instance not found */
355 missing_parent = set->set.s[i];
356 break;
357 }
358 data = diter;
359 toplevel = 0;
360 if (data->validity == LYD_VAL_OK) {
361 /* already checked */
362 ly_set_free(set);
363 return EXIT_SUCCESS;
364 }
365 }
366 ly_set_free(set);
367 }
368 } else {
369 missing_parent = node;
370 }
371
Radek Krejci7f40ce32015-08-12 20:38:46 +0200372 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci7531aa22016-04-12 13:52:19 +0200373 if (missing_parent) {
Michal Vaskob68d4b42016-05-20 11:44:45 +0200374 LOGVAL(LYE_MISSELEM, LY_VLOG_LYD, toplevel ? NULL : data, node->name,
Radek Krejci29ac4f92016-04-12 15:05:53 +0200375 (lys_parent(node) ? lys_parent(node)->name : lys_node_module(node)->name));
Michal Vasko84f821a2016-04-11 11:03:42 +0200376 return EXIT_FAILURE;
Radek Krejci2342cf62016-01-29 16:48:23 +0100377 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200378
Radek Krejci2342cf62016-01-29 16:48:23 +0100379 switch (node->nodetype) {
380 case LYS_LEAF:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200381 case LYS_ANYDATA:
Radek Krejci2342cf62016-01-29 16:48:23 +0100382 case LYS_CHOICE:
Michal Vasko84f821a2016-04-11 11:03:42 +0200383 if (lys_parent(node) && lys_parent(node)->nodetype == LYS_CASE) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100384 /* 7.6.5, rule 2 */
385 /* 7.9.4, rule 1 */
Radek Krejci7531aa22016-04-12 13:52:19 +0200386
387 /* try to find the node's siblings in data */
388 LY_TREE_FOR(toplevel ? data : data->child, diter) {
389 LY_TREE_FOR(lys_parent(node)->child, siter) {
390 if (siter == diter->schema) {
391 /* some sibling exists, rule applies */
Radek Krejci2342cf62016-01-29 16:48:23 +0100392 break;
393 }
394 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200395 if (siter) {
396 break;
397 }
Radek Krejci2342cf62016-01-29 16:48:23 +0100398 }
399 if (!siter) {
400 /* no sibling exists */
Michal Vasko84f821a2016-04-11 11:03:42 +0200401 return EXIT_SUCCESS;
Radek Krejci2342cf62016-01-29 16:48:23 +0100402 }
Radek Krejci2342cf62016-01-29 16:48:23 +0100403 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200404
Radek Krejci96e20852016-04-11 17:51:26 +0200405 if (node->nodetype == LYS_CHOICE) {
406 siter = NULL;
Radek Krejci7531aa22016-04-12 13:52:19 +0200407 LY_TREE_FOR(toplevel ? data : data->child, diter) {
Radek Krejci96e20852016-04-11 17:51:26 +0200408 while ((siter = lys_getnext(siter, node, NULL, 0))) {
409 if (diter->schema == siter) {
410 return EXIT_SUCCESS;
411 }
412 }
413 }
414 } else {
Radek Krejci7531aa22016-04-12 13:52:19 +0200415 LY_TREE_FOR(toplevel ? data : data->child, diter) {
Radek Krejci96e20852016-04-11 17:51:26 +0200416 if (diter->schema == node) {
417 return EXIT_SUCCESS;
418 }
Radek Krejci2342cf62016-01-29 16:48:23 +0100419 }
420 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200421
Radek Krejci2342cf62016-01-29 16:48:23 +0100422 /* instance not found */
423 /* 7.6.5, rule 3 (or 2) */
424 /* 7.9.4, rule 2 */
Michal Vasko84f821a2016-04-11 11:03:42 +0200425 if (node->nodetype == LYS_CHOICE) {
Radek Krejci29ac4f92016-04-12 15:05:53 +0200426 LOGVAL(LYE_NOMANDCHOICE, LY_VLOG_LYD, toplevel ? NULL : data, node->name);
Michal Vasko84f821a2016-04-11 11:03:42 +0200427 } else {
Radek Krejci29ac4f92016-04-12 15:05:53 +0200428 LOGVAL(LYE_MISSELEM, LY_VLOG_LYD, toplevel ? NULL : data, node->name,
Michal Vasko84f821a2016-04-11 11:03:42 +0200429 (lys_parent(node) ? lys_parent(node)->name : lys_node_module(node)->name));
430 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200431 break;
Radek Krejci2342cf62016-01-29 16:48:23 +0100432 default:
433 /* error */
Radek Krejci7531aa22016-04-12 13:52:19 +0200434 LOGINT;
Radek Krejci2342cf62016-01-29 16:48:23 +0100435 break;
436 }
Radek Krejci7531aa22016-04-12 13:52:19 +0200437 return EXIT_FAILURE;
438
Radek Krejci14a11a62015-08-17 17:27:38 +0200439 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
440 /* search for number of instances */
441 minmax = 0;
Radek Krejci7531aa22016-04-12 13:52:19 +0200442 if (!missing_parent) {
443 LY_TREE_FOR(toplevel ? data : data->child, diter) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100444 if (diter->schema == node) {
445 minmax++;
Michal Vasko05ed8422016-04-12 11:38:24 +0200446 /* remember the last instance, we will use it in the log message */
447 data = diter;
Radek Krejci2342cf62016-01-29 16:48:23 +0100448 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200449 }
450 }
451
452 /* check the specified constraints */
453 if (node->nodetype == LYS_LIST) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200454 min = ((struct lys_node_list *)node)->min;
455 max = ((struct lys_node_list *)node)->max;
456 } else {
457 min = ((struct lys_node_leaflist *)node)->min;
458 max = ((struct lys_node_leaflist *)node)->max;
459 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200460
Michal Vasko84f821a2016-04-11 11:03:42 +0200461 if (min && (minmax < min)) {
Radek Krejci29ac4f92016-04-12 15:05:53 +0200462 LOGVAL(LYE_NOMIN, LY_VLOG_LYD, toplevel ? NULL : data, node->name);
Michal Vasko84f821a2016-04-11 11:03:42 +0200463 return EXIT_FAILURE;
464 }
465 if (max && (minmax > max)) {
Radek Krejci8519de02016-07-25 14:54:19 +0200466 LOGVAL(LYE_NOMAX, LY_VLOG_LYD, data, node->name);
Michal Vasko84f821a2016-04-11 11:03:42 +0200467 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200468 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200469 }
470
Michal Vasko84f821a2016-04-11 11:03:42 +0200471 return EXIT_SUCCESS;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200472}
473
Michal Vasko84f821a2016-04-11 11:03:42 +0200474int
Michal Vasko98a5a742016-05-11 11:02:56 +0200475ly_check_mandatory(const struct lyd_node *data, const struct lys_node *schema, int status, int rpc_output)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200476{
Michal Vasko84f821a2016-04-11 11:03:42 +0200477 const struct lys_node *siter, *saux, *saux2, *parent = NULL, *parent2;
Radek Krejci264ae352016-07-26 15:32:55 +0200478 const struct lyd_node *diter, *datasearch;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200479 int found;
480
Radek Krejci2342cf62016-01-29 16:48:23 +0100481 assert(data || schema);
482
Radek Krejci7531aa22016-04-12 13:52:19 +0200483 if (schema) {
484 /* schema is preferred regardless the data */
Radek Krejci2342cf62016-01-29 16:48:23 +0100485 siter = schema;
Radek Krejci264ae352016-07-26 15:32:55 +0200486 datasearch = data;
Radek Krejci7531aa22016-04-12 13:52:19 +0200487 } else {
488 /* !schema && data */
Radek Krejcie2f12212016-02-12 13:50:22 +0100489 schema = data->schema;
490 siter = data->schema->child;
Radek Krejci264ae352016-07-26 15:32:55 +0200491 datasearch = data->child;
Radek Krejci2342cf62016-01-29 16:48:23 +0100492 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200493
494repeat:
495 while (siter) {
Radek Krejci763122e2016-04-05 16:35:33 +0200496 if (lys_is_disabled(siter, 2) || (!status && (siter->flags & LYS_CONFIG_R))) {
Radek Krejci074bf852015-08-19 14:22:16 +0200497 siter = siter->next;
498 continue;
499 }
500
Radek Krejci7f40ce32015-08-12 20:38:46 +0200501 switch (siter->nodetype) {
502 case LYS_CONTAINER:
503 case LYS_LEAF:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200504 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200505 case LYS_LIST:
506 case LYS_LEAFLIST:
507 /* check if there is some mandatory node; first test the siter itself ... */
Michal Vasko84f821a2016-04-11 11:03:42 +0200508 if (check_mand_check(siter, lys_parent(siter), data)) {
509 return EXIT_FAILURE;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200510 }
511 /* ... and then the subtree */
Radek Krejcicf82e932016-04-11 17:52:31 +0200512 if (siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200513 saux = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100514 while ((saux = check_mand_getnext(saux, siter, NULL))) {
Radek Krejcie8da2e02016-04-11 17:53:34 +0200515 if ((status || (saux->flags & LYS_CONFIG_W)) && check_mand_check(saux, lys_parent(siter), data)) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200516 return EXIT_FAILURE;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200517 }
518 }
519 }
520 siter = siter->next;
521 break;
522 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200523 /* search for instance */
524 saux = siter;
525 siter = siter->child;
526 found = 0;
527 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200528repeat_choice:
Radek Krejci2342cf62016-01-29 16:48:23 +0100529 while (siter && data) {
Radek Krejci763122e2016-04-05 16:35:33 +0200530 if (lys_is_disabled(siter, 2) || (!status && (siter->flags & LYS_CONFIG_R))) {
Radek Krejci074bf852015-08-19 14:22:16 +0200531 siter = siter->next;
532 continue;
533 }
534
Radek Krejci14a11a62015-08-17 17:27:38 +0200535 switch (siter->nodetype) {
536 case LYS_CONTAINER:
537 case LYS_LEAF:
538 case LYS_LEAFLIST:
539 case LYS_LIST:
Radek Krejci45826012016-08-24 15:07:57 +0200540 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200541 case LYS_ANYDATA:
Radek Krejci264ae352016-07-26 15:32:55 +0200542 LY_TREE_FOR(datasearch, diter) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200543 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200544 break;
545 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200546 }
547 if (diter) {
548 /* got instance */
549 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200550 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200551 saux2 = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100552 while ((saux2 = check_mand_getnext(saux2, parent2, NULL))) {
Radek Krejci7531aa22016-04-12 13:52:19 +0200553 if (check_mand_check(saux2, lys_parent(saux), data)) {
Michal Vasko84f821a2016-04-11 11:03:42 +0200554 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200555 }
556 }
557 }
558 siter = parent2 = NULL;
559 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200560 break;
561 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200562 siter = siter->next;
563 break;
564 case LYS_CASE:
565 case LYS_CHOICE:
566 case LYS_USES:
567 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200568 if (!parent2) {
569 parent2 = siter;
570 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200571 siter = siter->child;
572 break;
573 case LYS_AUGMENT:
574 case LYS_GROUPING:
575 /* skip */
576 siter = siter->next;
577 break;
578 default:
579 /* error */
580 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200581 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200582 }
583
Radek Krejci14a11a62015-08-17 17:27:38 +0200584 if (parent2) {
585 siter = parent2->next;
Michal Vasko84f821a2016-04-11 11:03:42 +0200586 if (lys_parent(parent2) == saux) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200587 parent2 = NULL;
588 } else {
Michal Vasko84f821a2016-04-11 11:03:42 +0200589 parent2 = lys_parent(parent2);
Radek Krejci14a11a62015-08-17 17:27:38 +0200590 }
591 goto repeat_choice;
592 }
593
Radek Krejci074bf852015-08-19 14:22:16 +0200594 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci7531aa22016-04-12 13:52:19 +0200595 LOGVAL(LYE_MISSELEM, LY_VLOG_LYD, data, saux->name,
596 (lys_parent(saux) ? lys_parent(saux)->name : lys_node_module(saux)->name));
Michal Vasko84f821a2016-04-11 11:03:42 +0200597 return EXIT_FAILURE;
Radek Krejci14a11a62015-08-17 17:27:38 +0200598 }
599
600 /* go to next */
601 siter = saux->next;
602
Radek Krejci7f40ce32015-08-12 20:38:46 +0200603 break;
Michal Vasko98a5a742016-05-11 11:02:56 +0200604 case LYS_INPUT:
605 if (rpc_output) {
606 /* skip */
607 siter = siter->next;
608 break;
609 }
610 /* fallthrough */
611 case LYS_OUTPUT:
Michal Vasko880f67d2016-06-01 16:12:18 +0200612 if ((siter->nodetype == LYS_OUTPUT) && !rpc_output) {
Michal Vasko98a5a742016-05-11 11:02:56 +0200613 /* skip */
614 siter = siter->next;
615 break;
616 }
617 /* fallthrough */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200618 case LYS_USES:
619 case LYS_CASE:
620 /* go into */
621 parent = siter;
622 siter = siter->child;
623 break;
624 default:
625 /* can ignore, go to next */
626 siter = siter->next;
627 break;
628 }
629 }
630
631 if (parent) {
632 siter = parent->next;
Michal Vasko9eb6dd02016-05-02 14:52:40 +0200633 if (lys_parent(parent) == schema) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200634 parent = NULL;
635 } else {
Michal Vasko84f821a2016-04-11 11:03:42 +0200636 parent = lys_parent(parent);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200637 }
638 goto repeat;
639 }
640
Michal Vasko84f821a2016-04-11 11:03:42 +0200641 return EXIT_SUCCESS;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200642}
643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200644void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200645lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200646{
Radek Krejci76512572015-08-04 09:47:08 +0200647 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100648 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200650 if (!node) {
651 return;
652 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200654 /* unlink from data model if necessary */
655 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100656 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100657 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100658 if (main_module->data == node) {
659 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200660 }
661 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200663 /* store pointers to important nodes */
664 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200665 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200666 /* handle augments - first, unlink it from the augment parent ... */
667 if (parent->child == node) {
668 parent->child = node->next;
669 }
670 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200671 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200672 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200674 /* unlink from parent */
675 if (parent) {
676 if (parent->child == node) {
677 parent->child = node->next;
678 }
679 node->parent = NULL;
680 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200682 /* unlink from siblings */
683 if (node->prev == node) {
684 /* there are no more siblings */
685 return;
686 }
687 if (node->next) {
688 node->next->prev = node->prev;
689 } else {
690 /* unlinking the last element */
691 if (parent) {
692 first = parent->child;
693 } else {
694 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200695 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200696 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200697 }
698 }
699 first->prev = node->prev;
700 }
701 if (node->prev->next) {
702 node->prev->next = node->next;
703 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200704
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200705 /* clean up the unlinked element */
706 node->next = NULL;
707 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200708}
709
Michal Vasko563ef092015-09-04 13:17:23 +0200710struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100711lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200712{
713 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200714
715 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200716 /* top-level augment, look into module (uses augment is handled correctly below) */
717 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
718 par_iter = par_iter->parent->module->data;
719 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200720 break;
721 }
722 }
723
Michal Vasko6f929da2015-10-02 16:23:25 +0200724 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200725 continue;
726 }
727
728 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
729 if (!stop) {
730 stop = par_iter;
731 } else if (iter == stop) {
732 break;
733 }
734 if (iter->nodetype != LYS_GROUPING) {
735 continue;
736 }
737
Radek Krejcif8426a72015-10-31 23:14:03 +0100738 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200739 return (struct lys_node_grp *)iter;
740 }
741 }
742 }
743
Michal Vasko563ef092015-09-04 13:17:23 +0200744 return NULL;
745}
746
Radek Krejci10c760e2015-08-14 14:45:43 +0200747/*
748 * get next grouping in the root's subtree, in the
749 * first call, tha last is NULL
750 */
751static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200752lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200753{
Radek Krejci10c760e2015-08-14 14:45:43 +0200754 struct lys_node *last = (struct lys_node *)lastgrp;
755 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200756
Radek Krejci10c760e2015-08-14 14:45:43 +0200757 assert(root);
758
759 if (!last) {
760 last = root;
761 }
762
763 while (1) {
764 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
765 next = last->child;
766 } else {
767 next = NULL;
768 }
769 if (!next) {
770 if (last == root) {
771 /* we are done */
772 return NULL;
773 }
774
775 /* no children, go to siblings */
776 next = last->next;
777 }
778 while (!next) {
779 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100780 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200781 /* we are done */
782 return NULL;
783 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200784 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100785 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200786 }
787
788 if (next->nodetype == LYS_GROUPING) {
789 return (struct lys_node_grp *)next;
790 }
791
792 last = next;
793 }
794}
795
Michal Vasko0d343d12015-08-24 14:57:36 +0200796/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200797int
Radek Krejci07911992015-08-14 15:13:31 +0200798lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
799{
Michal Vasko563ef092015-09-04 13:17:23 +0200800 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200801 struct lys_node_grp *grp;
802 int down;
803
804 assert(node);
805
806 if (!parent) {
807 assert(module);
808 } else {
809 module = parent->module;
810 }
811
812 switch (node->nodetype) {
813 case LYS_GROUPING:
814 /* 6.2.1, rule 6 */
815 if (parent) {
816 if (parent->child) {
817 down = 1;
818 start = parent->child;
819 } else {
820 down = 0;
821 start = parent;
822 }
823 } else {
824 down = 1;
825 start = module->data;
826 }
827 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100828 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100829 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200830 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200831 }
832 /* go down, because grouping can be defined after e.g. container in which is collision */
833 if (down) {
834 for (iter = start, stop = NULL; iter; iter = iter->prev) {
835 if (!stop) {
836 stop = start;
837 } else if (iter == stop) {
838 break;
839 }
840 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
841 continue;
842 }
843
844 grp = NULL;
845 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100846 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100847 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200848 return EXIT_FAILURE;
849 }
850 }
851 }
852 }
853 break;
854 case LYS_LEAF:
855 case LYS_LEAFLIST:
856 case LYS_LIST:
857 case LYS_CONTAINER:
858 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200859 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200860 /* 6.2.1, rule 7 */
861 if (parent) {
862 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200863 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
864 if (iter->nodetype == LYS_AUGMENT) {
865 if (((struct lys_node_augment *)iter)->target) {
866 /* augment is resolved, go up */
867 iter = ((struct lys_node_augment *)iter)->target;
868 continue;
869 }
870 /* augment is not resolved, this is the final parent */
871 break;
872 }
Radek Krejci07911992015-08-14 15:13:31 +0200873 iter = iter->parent;
874 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200875
Radek Krejci07911992015-08-14 15:13:31 +0200876 if (!iter) {
877 stop = NULL;
878 iter = module->data;
879 } else {
880 stop = iter;
881 iter = iter->child;
882 }
883 } else {
884 stop = NULL;
885 iter = module->data;
886 }
887 while (iter) {
888 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
889 iter = iter->child;
890 continue;
891 }
892
Radek Krejcibf2abff2016-08-23 15:51:52 +0200893 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100894 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100895 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200896 return EXIT_FAILURE;
897 }
898 }
899
900 /* special case for choice - we must check the choice's name as
901 * well as the names of nodes under the choice
902 */
903 if (iter->nodetype == LYS_CHOICE) {
904 iter = iter->child;
905 continue;
906 }
907
908 /* go to siblings */
909 if (!iter->next) {
910 /* no sibling, go to parent's sibling */
911 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200912 /* for parent LYS_AUGMENT */
913 if (iter->parent == stop) {
914 iter = stop;
915 break;
916 }
917 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200918 if (iter && iter->next) {
919 break;
920 }
921 } while (iter != stop);
922
923 if (iter == stop) {
924 break;
925 }
926 }
927 iter = iter->next;
928 }
929 break;
930 case LYS_CASE:
931 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100932 if (parent) {
933 start = parent->child;
934 } else {
935 start = module->data;
936 }
937
938 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200939 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200940 continue;
941 }
942
Radek Krejci749190d2016-02-18 16:26:25 +0100943 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100944 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200945 return EXIT_FAILURE;
946 }
947 }
948 break;
949 default:
950 /* no check needed */
951 break;
952 }
953
954 return EXIT_SUCCESS;
955}
956
Michal Vasko0d343d12015-08-24 14:57:36 +0200957/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200958int
Radek Krejci10c760e2015-08-14 14:45:43 +0200959lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
960{
Radek Krejci92720552015-10-05 15:28:27 +0200961 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200962 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200964 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200965
Radek Krejci10c760e2015-08-14 14:45:43 +0200966 if (parent) {
967 type = parent->nodetype;
968 module = parent->module;
969 } else {
970 assert(module);
971 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200972 }
973
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200974 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200975 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200976 case LYS_CONTAINER:
977 case LYS_LIST:
978 case LYS_GROUPING:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200979 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200980 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200981 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
982 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
983 return EXIT_FAILURE;
984 }
985 break;
Radek Krejci76512572015-08-04 09:47:08 +0200986 case LYS_USES:
987 case LYS_INPUT:
988 case LYS_OUTPUT:
989 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200990 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200991 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200992 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100993 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200994 return EXIT_FAILURE;
995 }
996 break;
Radek Krejci76512572015-08-04 09:47:08 +0200997 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200998 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200999 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001000 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001001 return EXIT_FAILURE;
1002 }
1003 break;
Radek Krejci76512572015-08-04 09:47:08 +02001004 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001005 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +02001006 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001007 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001008 return EXIT_FAILURE;
1009 }
1010 break;
Radek Krejci76512572015-08-04 09:47:08 +02001011 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +02001012 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +02001013 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001014 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +02001015 return EXIT_FAILURE;
1016 }
1017 break;
Radek Krejci76512572015-08-04 09:47:08 +02001018 case LYS_LEAF:
1019 case LYS_LEAFLIST:
1020 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001021 case LYS_ANYDATA:
Radek Krejci48464ed2016-03-17 15:44:09 +01001022 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
1023 LOGVAL(LYE_SPEC, LY_VLOG_LYS, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +01001024 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001025 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +02001026 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001027 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +02001028 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskoca7cbc42016-07-01 11:36:53 +02001029 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001030 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001031 return EXIT_FAILURE;
1032 }
Michal Vasko591e0b22015-08-13 13:53:43 +02001033 break;
1034 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +02001035 /* top level */
1036 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +02001037 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +02001038 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001039 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +02001040 return EXIT_FAILURE;
1041 }
1042
Radek Krejcic071c542016-01-27 14:57:51 +01001043 break;
Radek Krejci10c760e2015-08-14 14:45:43 +02001044 }
1045
1046 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +02001047 if (lys_check_id(child, parent, module)) {
1048 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001049 }
Radek Krejcib7155b52015-06-10 17:03:01 +02001050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001051 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001052 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001053 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001054
Radek Krejci10c760e2015-08-14 14:45:43 +02001055 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +02001056 if (module->data) {
1057 module->data->prev->next = child;
1058 child->prev = module->data->prev;
1059 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001060 } else {
Radek Krejci92720552015-10-05 15:28:27 +02001061 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001062 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001063 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +02001064 if (!parent->child) {
1065 /* the only/first child of the parent */
1066 parent->child = child;
1067 child->parent = parent;
1068 iter = child;
1069 } else {
1070 /* add a new child at the end of parent's child list */
1071 iter = parent->child->prev;
1072 iter->next = child;
1073 child->prev = iter;
1074 }
1075 while (iter->next) {
1076 iter = iter->next;
1077 iter->parent = parent;
1078 }
1079 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001081
Radek Krejci41771502016-04-14 17:52:32 +02001082 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +02001083 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +02001084 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +02001085 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +02001086 /* store it only into container or list - the only data inner nodes */
1087 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
1088 if (iter->flags & LYS_INCL_STATUS) {
1089 /* done, someone else set it already from here */
1090 break;
1091 }
1092 /* set flag about including status data */
1093 iter->flags |= LYS_INCL_STATUS;
1094 }
1095 }
1096 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001097 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001098}
1099
Radek Krejcia1df1682016-04-11 14:56:59 +02001100static const struct lys_module *
1101lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001102{
Radek Krejcia1df1682016-04-11 14:56:59 +02001103 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001104 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +02001105 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001106
Radek Krejcif347abc2016-06-22 10:18:47 +02001107 ly_errno = LY_SUCCESS;
1108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001109 if (!ctx || !data) {
1110 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1111 return NULL;
1112 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001113
Radek Krejcia1df1682016-04-11 14:56:59 +02001114 if (!internal && format == LYS_IN_YANG) {
1115 /* enlarge data by 2 bytes for flex */
1116 len = strlen(data);
1117 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
1118 if (!enlarged_data) {
1119 LOGMEM;
1120 return NULL;
1121 }
1122 memcpy(enlarged_data, data, len);
1123 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1124 data = enlarged_data;
1125 }
1126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001127 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001128 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +01001129 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001130 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001131 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001132 mod = yang_read_module(ctx, data, 0, NULL, 1);
1133 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001134 default:
Radek Krejcia1df1682016-04-11 14:56:59 +02001135 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001136 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001137 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001138
Radek Krejcia1df1682016-04-11 14:56:59 +02001139 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001140 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001141}
1142
Radek Krejcia1df1682016-04-11 14:56:59 +02001143API const struct lys_module *
1144lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
1145{
1146 return lys_parse_mem_(ctx, data, format, 0);
1147}
1148
Michal Vasko5a721fd2016-02-16 12:16:48 +01001149struct lys_submodule *
1150lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001151{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001152 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001154 assert(module);
1155 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001156
Radek Krejcic071c542016-01-27 14:57:51 +01001157 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +02001158 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001160 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001161 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001162 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001163 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001164 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001165 submod = yang_read_submodule(module, data, 0, unres);
1166 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001167 default:
Radek Krejci90a550a2016-04-13 16:00:58 +02001168 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001169 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001170 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001171
Michal Vasko5a721fd2016-02-16 12:16:48 +01001172 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001173}
1174
Michal Vasko1e62a092015-12-01 12:27:20 +01001175API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001176lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1177{
1178 int fd;
1179 const struct lys_module *ret;
1180
1181 if (!ctx || !path) {
1182 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1183 return NULL;
1184 }
1185
1186 fd = open(path, O_RDONLY);
1187 if (fd == -1) {
1188 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1189 return NULL;
1190 }
1191
1192 ret = lys_parse_fd(ctx, fd, format);
1193 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +01001194
Radek Krejcia77904e2016-02-25 16:23:45 +01001195 if (ret && !ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001196 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +01001197 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +01001198 }
1199
Michal Vasko662610a2015-12-07 11:25:45 +01001200 return ret;
1201}
1202
1203API const struct lys_module *
1204lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001205{
Michal Vasko1e62a092015-12-01 12:27:20 +01001206 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001207 struct stat sb;
1208 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001209 char buf[PATH_MAX];
1210 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001211
1212 if (!ctx || fd < 0) {
1213 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1214 return NULL;
1215 }
1216
Radek Krejci10a833c2015-12-16 15:28:37 +01001217 if (fstat(fd, &sb) == -1) {
1218 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1219 return NULL;
1220 }
Radek Krejcib051f722016-02-25 15:12:21 +01001221 if (!S_ISREG(sb.st_mode)) {
1222 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
1223 return NULL;
1224 }
1225
Michal Vasko164d9012016-04-01 10:16:59 +02001226 if (!sb.st_size) {
1227 LOGERR(LY_EINVAL, "File empty.");
1228 return NULL;
1229 }
1230
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001231 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001232 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001233 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001234 return NULL;
1235 }
Radek Krejcia1df1682016-04-11 14:56:59 +02001236 module = lys_parse_mem_(ctx, addr, format, 1);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001237 munmap(addr, sb.st_size + 2);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001238
Radek Krejcia77904e2016-02-25 16:23:45 +01001239 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001240 /* get URI if there is /proc */
1241 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001242 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1243 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1244 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1245 }
1246 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001247 }
Radek Krejcib051f722016-02-25 15:12:21 +01001248 }
1249
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001250 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001251}
1252
Michal Vasko5a721fd2016-02-16 12:16:48 +01001253struct lys_submodule *
1254lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001255{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001256 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001257 struct stat sb;
1258 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001259
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001260 assert(module);
1261 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001262
Radek Krejci10a833c2015-12-16 15:28:37 +01001263 if (fstat(fd, &sb) == -1) {
1264 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001265 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001266 }
Michal Vasko164d9012016-04-01 10:16:59 +02001267
1268 if (!sb.st_size) {
1269 LOGERR(LY_EINVAL, "File empty.");
1270 return NULL;
1271 }
1272
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001273 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001274 if (addr == MAP_FAILED) {
1275 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001276 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001277 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001278 submodule = lys_submodule_parse(module, addr, format, unres);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001279 munmap(addr, sb.st_size + 2);
Radek Krejciefaeba32015-05-27 14:30:57 +02001280
Michal Vasko5a721fd2016-02-16 12:16:48 +01001281 return submodule;
1282
Radek Krejciefaeba32015-05-27 14:30:57 +02001283}
1284
Radek Krejci1d82ef62015-08-07 14:44:40 +02001285static struct lys_restr *
1286lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001287{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001288 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001289 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001290
Radek Krejci3733a802015-06-19 13:43:21 +02001291 if (!size) {
1292 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001293 }
Radek Krejci3733a802015-06-19 13:43:21 +02001294
1295 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001296 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001297 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001298 return NULL;
1299 }
Radek Krejci3733a802015-06-19 13:43:21 +02001300 for (i = 0; i < size; i++) {
1301 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1302 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1303 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1304 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1305 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1306 }
1307
1308 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001309}
1310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001311void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001312lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001313{
1314 assert(ctx);
1315 if (!restr) {
1316 return;
1317 }
1318
1319 lydict_remove(ctx, restr->expr);
1320 lydict_remove(ctx, restr->dsc);
1321 lydict_remove(ctx, restr->ref);
1322 lydict_remove(ctx, restr->eapptag);
1323 lydict_remove(ctx, restr->emsg);
1324}
1325
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001326static void
1327lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size)
1328{
1329 uint8_t i;
1330
1331 for (i = 0; i < iffeature_size; ++i) {
1332 free(iffeature[i].expr);
1333 free(iffeature[i].features);
1334 }
1335 free(iffeature);
1336}
1337
Michal Vaskob84f88a2015-09-24 13:16:10 +02001338static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001339type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001340 LY_DATA_TYPE base, int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001341{
1342 int i;
1343
1344 switch (base) {
1345 case LY_TYPE_BINARY:
1346 if (old->info.binary.length) {
1347 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
1348 }
1349 break;
1350
1351 case LY_TYPE_BITS:
1352 new->info.bits.count = old->info.bits.count;
1353 if (new->info.bits.count) {
1354 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1355 if (!new->info.bits.bit) {
1356 LOGMEM;
1357 return -1;
1358 }
1359 for (i = 0; i < new->info.bits.count; i++) {
1360 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1361 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1362 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1363 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1364 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1365 }
1366 }
1367 break;
1368
1369 case LY_TYPE_DEC64:
1370 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001371 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001372 if (old->info.dec64.range) {
1373 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
1374 }
1375 break;
1376
1377 case LY_TYPE_ENUM:
1378 new->info.enums.count = old->info.enums.count;
1379 if (new->info.enums.count) {
1380 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1381 if (!new->info.enums.enm) {
1382 LOGMEM;
1383 return -1;
1384 }
1385 for (i = 0; i < new->info.enums.count; i++) {
1386 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1387 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1388 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1389 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1390 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
1391 }
1392 }
1393 break;
1394
1395 case LY_TYPE_IDENT:
1396 if (old->info.ident.ref) {
1397 new->info.ident.ref = old->info.ident.ref;
1398 } else {
1399 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vasko3767fb22016-07-21 12:10:57 +02001400 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 +02001401 return -1;
1402 }
1403 }
1404 break;
1405
1406 case LY_TYPE_INST:
1407 new->info.inst.req = old->info.inst.req;
1408 break;
1409
1410 case LY_TYPE_INT8:
1411 case LY_TYPE_INT16:
1412 case LY_TYPE_INT32:
1413 case LY_TYPE_INT64:
1414 case LY_TYPE_UINT8:
1415 case LY_TYPE_UINT16:
1416 case LY_TYPE_UINT32:
1417 case LY_TYPE_UINT64:
1418 if (old->info.num.range) {
1419 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
1420 }
1421 break;
1422
1423 case LY_TYPE_LEAFREF:
1424 if (old->info.lref.path) {
1425 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko5d631402016-07-21 13:15:15 +02001426 if (!tpdftype && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001427 return -1;
1428 }
1429 }
1430 break;
1431
1432 case LY_TYPE_STRING:
1433 if (old->info.str.length) {
1434 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
1435 }
1436 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
1437 new->info.str.pat_count = old->info.str.pat_count;
1438 break;
1439
1440 case LY_TYPE_UNION:
1441 new->info.uni.count = old->info.uni.count;
1442 if (new->info.uni.count) {
1443 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1444 if (!new->info.uni.types) {
1445 LOGMEM;
1446 return -1;
1447 }
1448 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001449 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 +02001450 return -1;
1451 }
1452 }
1453 }
1454 break;
1455
1456 default:
1457 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1458 break;
1459 }
1460 return EXIT_SUCCESS;
1461}
1462
1463struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001464lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1465 int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001466{
1467 struct yang_type *new;
1468
1469 new = calloc(1, sizeof *new);
1470 if (!new) {
1471 LOGMEM;
1472 return NULL;
1473 }
1474 new->flags = old->flags;
1475 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001476 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001477 new->type = type;
1478 if (!new->name) {
1479 LOGMEM;
1480 goto error;
1481 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001482 if (type_dup(module, parent, type, old->type, new->base, tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001483 new->type->base = new->base;
1484 lys_type_free(module->ctx, new->type);
1485 memset(&new->type->info, 0, sizeof new->type->info);
1486 goto error;
1487 }
1488 return new;
1489
1490 error:
1491 free(new);
1492 return NULL;
1493}
1494
1495static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001496lys_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 +02001497 int tpdftype, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001498{
1499 int i;
1500
Michal Vasko1dca6882015-10-22 14:29:42 +02001501 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001502 new->base = old->base;
1503 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001504 new->parent = (struct lys_tpdf *)parent;
Radek Krejci3733a802015-06-19 13:43:21 +02001505
Radek Krejci3a5501d2016-07-18 22:03:34 +02001506 i = unres_schema_find(unres, old, tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001507 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001508 /* HACK (serious one) for unres */
1509 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001510 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001511 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 +02001512 } else {
1513 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1514 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001515 /* all these unres additions can fail even though they did not before */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001516 if (!new->der || unres_schema_add_node(mod, unres, new,
Michal Vasko5d631402016-07-21 13:15:15 +02001517 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001518 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001519 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001520 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001521 }
1522
Radek Krejci3a5501d2016-07-18 22:03:34 +02001523 return type_dup(mod, parent, new, old, new->base, tpdftype, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001524}
1525
1526void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001527lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001528{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001529 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001531 assert(ctx);
1532 if (!type) {
1533 return;
1534 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001535
Michal Vasko1dca6882015-10-22 14:29:42 +02001536 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001537
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001538 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001539 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001540 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001541 free(type->info.binary.length);
1542 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001543 case LY_TYPE_BITS:
1544 for (i = 0; i < type->info.bits.count; i++) {
1545 lydict_remove(ctx, type->info.bits.bit[i].name);
1546 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1547 lydict_remove(ctx, type->info.bits.bit[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001548 lys_iffeature_free(type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size);
Radek Krejci994b6f62015-06-18 16:47:27 +02001549 }
1550 free(type->info.bits.bit);
1551 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001552
1553 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001554 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001555 free(type->info.dec64.range);
1556 break;
1557
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001558 case LY_TYPE_ENUM:
1559 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001560 lydict_remove(ctx, type->info.enums.enm[i].name);
1561 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1562 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001563 lys_iffeature_free(type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001564 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001565 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001566 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001567
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001568 case LY_TYPE_INT8:
1569 case LY_TYPE_INT16:
1570 case LY_TYPE_INT32:
1571 case LY_TYPE_INT64:
1572 case LY_TYPE_UINT8:
1573 case LY_TYPE_UINT16:
1574 case LY_TYPE_UINT32:
1575 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001576 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001577 free(type->info.num.range);
1578 break;
1579
Radek Krejcidc4c1412015-06-19 15:39:54 +02001580 case LY_TYPE_LEAFREF:
1581 lydict_remove(ctx, type->info.lref.path);
1582 break;
1583
Radek Krejci3733a802015-06-19 13:43:21 +02001584 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001585 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001586 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001587 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001588 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001589 }
1590 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001591 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001592
Radek Krejcie4c366b2015-07-02 10:11:31 +02001593 case LY_TYPE_UNION:
1594 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001595 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001596 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001597 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001598 break;
1599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001600 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001601 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001602 break;
1603 }
Radek Krejci5a065542015-05-22 15:02:07 +02001604}
1605
Radek Krejci1d82ef62015-08-07 14:44:40 +02001606static void
1607lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001608{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001609 assert(ctx);
1610 if (!tpdf) {
1611 return;
1612 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001614 lydict_remove(ctx, tpdf->name);
1615 lydict_remove(ctx, tpdf->dsc);
1616 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001617
Radek Krejci1d82ef62015-08-07 14:44:40 +02001618 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001619
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001620 lydict_remove(ctx, tpdf->units);
1621 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001622}
1623
Michal Vaskob84f88a2015-09-24 13:16:10 +02001624static struct lys_tpdf *
1625lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1626{
1627 struct lys_tpdf *result;
1628 int i, j;
1629
1630 if (!size) {
1631 return NULL;
1632 }
1633
1634 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001635 if (!result) {
1636 LOGMEM;
1637 return NULL;
1638 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001639 for (i = 0; i < size; i++) {
1640 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1641 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1642 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1643 result[i].flags = old[i].flags;
1644 result[i].module = old[i].module;
1645
Radek Krejci3a5501d2016-07-18 22:03:34 +02001646 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), 1, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001647 for (j = 0; j <= i; ++j) {
1648 lys_tpdf_free(mod->ctx, &result[j]);
1649 }
1650 free(result);
1651 return NULL;
1652 }
1653
1654 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1655 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1656 }
1657
1658 return result;
1659}
1660
Radek Krejci1d82ef62015-08-07 14:44:40 +02001661static struct lys_when *
1662lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001663{
Radek Krejci76512572015-08-04 09:47:08 +02001664 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001665
1666 if (!old) {
1667 return NULL;
1668 }
1669
1670 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001671 if (!new) {
1672 LOGMEM;
1673 return NULL;
1674 }
Radek Krejci00768f42015-06-18 17:04:04 +02001675 new->cond = lydict_insert(ctx, old->cond, 0);
1676 new->dsc = lydict_insert(ctx, old->dsc, 0);
1677 new->ref = lydict_insert(ctx, old->ref, 0);
1678
1679 return new;
1680}
1681
Michal Vasko0308dd62015-10-07 09:14:40 +02001682void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001683lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001684{
1685 if (!w) {
1686 return;
1687 }
1688
1689 lydict_remove(ctx, w->cond);
1690 lydict_remove(ctx, w->dsc);
1691 lydict_remove(ctx, w->ref);
1692
1693 free(w);
1694}
1695
Radek Krejcib7f5e412015-08-13 10:15:51 +02001696static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001697lys_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 +02001698{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001699 struct lys_node *next, *sub;
1700
Radek Krejcic071c542016-01-27 14:57:51 +01001701 /* children from a resolved augment are freed under the target node */
Michal Vaskod2fbade2016-05-02 17:14:00 +02001702 if (!aug->target) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001703 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001704 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001705 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001706 }
1707
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001708 lydict_remove(ctx, aug->target_name);
1709 lydict_remove(ctx, aug->dsc);
1710 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001711
Radek Krejci9ff0a922016-07-14 13:08:05 +02001712 lys_iffeature_free(aug->iffeature, aug->iffeature_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001713
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001714 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001715}
1716
Radek Krejci76512572015-08-04 09:47:08 +02001717static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001718lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001719{
Radek Krejci76512572015-08-04 09:47:08 +02001720 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001721 struct lys_node *old_child, *new_child;
1722 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001724 if (!size) {
1725 return NULL;
1726 }
Radek Krejci106efc02015-06-10 14:36:27 +02001727
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001728 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001729 if (!new) {
1730 LOGMEM;
1731 return NULL;
1732 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001733 for (i = 0; i < size; i++) {
1734 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1735 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1736 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1737 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001738 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001739 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001740
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001741 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001742 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1743 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001744 LOGINT;
1745 free(new);
1746 return NULL;
1747 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001748 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001749
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001750 /* Correct the augment nodes.
1751 * This function can only be called from lys_node_dup() with uses
1752 * being the node duplicated, so we must have a case of grouping
1753 * with a uses with augments. The augmented nodes have already been
1754 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001755 * (it was set to their actual data parent, not an augment), and
1756 * the new augment does not have child pointer to its augment nodes,
1757 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001758 */
1759 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001760 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001761 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001762 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001763 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001764 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001765 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001766 LY_TREE_FOR(old[i].child, old_child) {
1767 /* all augment nodes were connected as siblings, there can be no more after this */
1768 if (old_child->parent != (struct lys_node *)&old[i]) {
1769 break;
1770 }
1771
Radek Krejci749190d2016-02-18 16:26:25 +01001772 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001773
1774 new_child->parent = (struct lys_node *)&new[i];
1775 new_child = new_child->next;
1776 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001777 }
Radek Krejci106efc02015-06-10 14:36:27 +02001778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001779 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001780}
1781
Radek Krejci76512572015-08-04 09:47:08 +02001782static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001783lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001784{
Radek Krejci76512572015-08-04 09:47:08 +02001785 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001786 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001787
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001788 if (!size) {
1789 return NULL;
1790 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001791
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001792 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001793 if (!result) {
1794 LOGMEM;
1795 return NULL;
1796 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001797 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001798 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001799 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1800 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001801 result[i].flags = old[i].flags;
1802 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001803
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001804 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001805 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001806
Radek Krejci76512572015-08-04 09:47:08 +02001807 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001808 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001809 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001810 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001811 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001812 result[i].mod.list = old[i].mod.list;
1813 }
1814 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001815
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001816 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001817}
1818
Radek Krejci1d82ef62015-08-07 14:44:40 +02001819static void
1820lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001821{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001822 assert(ctx);
1823 if (!ident) {
1824 return;
1825 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001826
Radek Krejci018f1f52016-08-03 16:01:20 +02001827 free(ident->base);
Radek Krejci1b61d0e2016-04-15 13:55:44 +02001828 free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001829 lydict_remove(ctx, ident->name);
1830 lydict_remove(ctx, ident->dsc);
1831 lydict_remove(ctx, ident->ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001832 lys_iffeature_free(ident->iffeature, ident->iffeature_size);
Radek Krejci6793db02015-05-22 17:49:54 +02001833
1834}
1835
Radek Krejci1d82ef62015-08-07 14:44:40 +02001836static void
1837lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001838{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001839 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001840
Radek Krejcid12f57b2015-08-06 10:43:39 +02001841 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001842 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001843 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001844 }
1845 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001846}
1847
Radek Krejci1d82ef62015-08-07 14:44:40 +02001848static void
Michal Vasko44fb6382016-06-29 11:12:27 +02001849lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02001850{
1851 int i;
1852
1853 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1854 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001855 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001856 }
1857 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02001858
1859 for (i = 0; i < io->must_size; i++) {
1860 lys_restr_free(ctx, &io->must[i]);
1861 }
1862 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001863}
1864
Radek Krejci1d82ef62015-08-07 14:44:40 +02001865static void
Pavol Vican7cff97e2016-08-09 14:56:08 +02001866lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif)
1867{
1868 int i;
1869
1870 for (i = 0; i < notif->must_size; i++) {
1871 lys_restr_free(ctx, &notif->must[i]);
1872 }
1873 free(notif->must);
1874
1875 for (i = 0; i < notif->tpdf_size; i++) {
1876 lys_tpdf_free(ctx, &notif->tpdf[i]);
1877 }
1878 free(notif->tpdf);
1879}
1880static void
Radek Krejcibf2abff2016-08-23 15:51:52 +02001881lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001882{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001883 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001885 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001886 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001887 }
1888 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001889
Radek Krejci1d82ef62015-08-07 14:44:40 +02001890 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001891}
1892
Radek Krejci1d82ef62015-08-07 14:44:40 +02001893static void
1894lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001895{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001896 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001897
Radek Krejci46c4cd72016-01-21 15:13:52 +01001898 if (leaf->child) {
1899 /* leafref backlinks */
1900 ly_set_free((struct ly_set *)leaf->child);
1901 }
1902
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001903 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001904 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001905 }
1906 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001907
Radek Krejci1d82ef62015-08-07 14:44:40 +02001908 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001909
Radek Krejci1d82ef62015-08-07 14:44:40 +02001910 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001911 lydict_remove(ctx, leaf->units);
1912 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001913}
1914
Radek Krejci1d82ef62015-08-07 14:44:40 +02001915static void
1916lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001917{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001918 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001919
Radek Krejci46c4cd72016-01-21 15:13:52 +01001920 if (llist->child) {
1921 /* leafref backlinks */
1922 ly_set_free((struct ly_set *)llist->child);
1923 }
1924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001925 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001926 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001927 }
1928 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001929
Radek Krejci1d82ef62015-08-07 14:44:40 +02001930 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001931
Radek Krejci1d82ef62015-08-07 14:44:40 +02001932 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001933 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001934}
1935
Radek Krejci1d82ef62015-08-07 14:44:40 +02001936static void
1937lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001938{
Radek Krejci581ce772015-11-10 17:22:40 +01001939 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001940
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001941 /* handle only specific parts for LY_NODE_LIST */
1942 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001943 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001944 }
1945 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001947 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001948 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001949 }
1950 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001951
Radek Krejci1d82ef62015-08-07 14:44:40 +02001952 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001953
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001954 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02001955 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001956 lydict_remove(ctx, list->unique[i].expr[j]);
1957 }
1958 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001959 }
1960 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001961
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001962 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001963}
1964
Radek Krejci1d82ef62015-08-07 14:44:40 +02001965static void
1966lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001967{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001968 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001970 /* handle only specific parts for LY_NODE_CONTAINER */
1971 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001973 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001974 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001975 }
1976 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001977
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001978 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001979 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001980 }
1981 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001982
Radek Krejci1d82ef62015-08-07 14:44:40 +02001983 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001984}
1985
Radek Krejci1d82ef62015-08-07 14:44:40 +02001986static void
1987lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001988{
1989 lydict_remove(ctx, f->name);
1990 lydict_remove(ctx, f->dsc);
1991 lydict_remove(ctx, f->ref);
Radek Krejci9ff0a922016-07-14 13:08:05 +02001992 lys_iffeature_free(f->iffeature, f->iffeature_size);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001993}
1994
Radek Krejci1d82ef62015-08-07 14:44:40 +02001995static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001996lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001997{
Radek Krejci581ce772015-11-10 17:22:40 +01001998 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001999 struct ly_ctx *ctx;
2000 struct lys_node *next, *elem;
2001
2002 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002003
2004 lydict_remove(ctx, dev->target_name);
2005 lydict_remove(ctx, dev->dsc);
2006 lydict_remove(ctx, dev->ref);
2007
Michal Vaskoff006c12016-02-17 11:15:19 +01002008 /* the module was freed, but we only need the context from orig_node, use ours */
2009 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2010 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
2011 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
2012 elem->module = module;
2013
2014 LY_TREE_DFS_END(dev->orig_node, next, elem);
2015 }
2016 lys_node_free(dev->orig_node, NULL, 0);
2017 } else {
2018 /* it's just a shallow copy, freeing one node */
2019 dev->orig_node->module = module;
2020 lys_node_free(dev->orig_node, NULL, 1);
2021 }
2022
Radek Krejcieb00f512015-07-01 16:44:58 +02002023 for (i = 0; i < dev->deviate_size; i++) {
2024 lydict_remove(ctx, dev->deviate[i].dflt);
2025 lydict_remove(ctx, dev->deviate[i].units);
2026
2027 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2028 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002029 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002030 }
2031 free(dev->deviate[i].must);
2032
2033 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002034 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
2035 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
2036 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01002037 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002038 }
2039 free(dev->deviate[i].unique);
2040 }
2041 }
2042 free(dev->deviate);
2043}
2044
Radek Krejci1d82ef62015-08-07 14:44:40 +02002045static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002046lys_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 +02002047{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002048 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02002049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002050 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02002051 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002052 lydict_remove(ctx, uses->refine[i].dsc);
2053 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002054
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002055 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002056 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002057 }
2058 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002059
Radek Krejci76512572015-08-04 09:47:08 +02002060 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002061 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02002062 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002063 lydict_remove(ctx, uses->refine[i].mod.presence);
2064 }
2065 }
2066 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002067
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002069 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002070 }
2071 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002072
Radek Krejci1d82ef62015-08-07 14:44:40 +02002073 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002074}
2075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002077lys_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 +02002078{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002079 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002080 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002082 if (!node) {
2083 return;
2084 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 assert(node->module);
2087 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002088
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002089 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002090
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002091 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002092 if (node->priv && private_destructor) {
2093 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002094 }
2095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002096 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002097 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002098 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002099 lys_iffeature_free(node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002100 lydict_remove(ctx, node->dsc);
2101 lydict_remove(ctx, node->ref);
2102 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002103
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002104 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002105 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002106 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002107 }
2108 }
2109
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002110 /* specific part */
2111 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002112 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002113 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 break;
Radek Krejci76512572015-08-04 09:47:08 +02002115 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002116 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002117 break;
Radek Krejci76512572015-08-04 09:47:08 +02002118 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002119 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120 break;
Radek Krejci76512572015-08-04 09:47:08 +02002121 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002122 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002123 break;
Radek Krejci76512572015-08-04 09:47:08 +02002124 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002125 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 break;
Radek Krejci76512572015-08-04 09:47:08 +02002127 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002128 case LYS_ANYDATA:
2129 lys_anydata_free(ctx, (struct lys_node_anydata *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002130 break;
Radek Krejci76512572015-08-04 09:47:08 +02002131 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002132 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 break;
Radek Krejci76512572015-08-04 09:47:08 +02002134 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002135 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002136 break;
Radek Krejci76512572015-08-04 09:47:08 +02002137 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002138 /* do nothing */
2139 break;
Radek Krejci76512572015-08-04 09:47:08 +02002140 case LYS_GROUPING:
2141 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002142 case LYS_ACTION:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002143 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02002145 case LYS_NOTIF:
2146 lys_notif_free(ctx, (struct lys_node_notif *)node);
2147 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002148 case LYS_INPUT:
2149 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02002150 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002151 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02002152 case LYS_UNKNOWN:
2153 LOGINT;
2154 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002155 }
Radek Krejci5a065542015-05-22 15:02:07 +02002156
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002157 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002158 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002160}
2161
Michal Vasko1e62a092015-12-01 12:27:20 +01002162const struct lys_module *
2163lys_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 +02002164{
Radek Krejcic071c542016-01-27 14:57:51 +01002165 const struct lys_module *main_module;
Michal Vasko89563fc2016-07-28 16:19:35 +02002166 char *str;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002167 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002168
Michal Vaskoa7789a82016-02-11 15:42:55 +01002169 assert(!prefix || !name);
2170
Michal Vaskob6729c62015-10-21 12:09:47 +02002171 if (prefix && !pref_len) {
2172 pref_len = strlen(prefix);
2173 }
2174 if (name && !name_len) {
2175 name_len = strlen(name);
2176 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002177
Radek Krejcic4283442016-04-22 09:19:27 +02002178 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002179
2180 /* module own prefix, submodule own prefix, (sub)module own name */
2181 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2182 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002183 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002184 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002185 }
2186
Michal Vasko89563fc2016-07-28 16:19:35 +02002187 /* standard import */
Michal Vasko8ce24d72015-10-21 11:27:26 +02002188 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002189 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2190 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002191 return module->imp[i].module;
2192 }
2193 }
2194
Michal Vasko89563fc2016-07-28 16:19:35 +02002195 /* module required by a foreign grouping, deviation, or submodule */
2196 if (name) {
2197 str = strndup(name, name_len);
2198 if (!str) {
2199 LOGMEM;
2200 return NULL;
2201 }
2202 main_module = ly_ctx_get_module(module->ctx, str, NULL);
2203 free(str);
2204 return main_module;
2205 }
2206
Michal Vasko8ce24d72015-10-21 11:27:26 +02002207 return NULL;
2208}
2209
Michal Vasko13b15832015-08-19 11:04:48 +02002210/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002211static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002212module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002213{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002214 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002215 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002216 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002218 assert(module->ctx);
2219 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002220
Michal Vaskob746fff2016-02-11 11:37:50 +01002221 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002222 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002223 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002224 lydict_remove(ctx, module->imp[i].dsc);
2225 lydict_remove(ctx, module->imp[i].ref);
Radek Krejci225376f2016-02-16 17:36:22 +01002226 }
Radek Krejcidce51452015-06-16 15:20:08 +02002227 free(module->imp);
2228
Radek Krejcic071c542016-01-27 14:57:51 +01002229 /* submodules don't have data tree, the data nodes
2230 * are placed in the main module altogether */
2231 if (!module->type) {
2232 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002233 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002234 }
Radek Krejci21181962015-06-30 14:11:00 +02002235 }
Radek Krejci5a065542015-05-22 15:02:07 +02002236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 lydict_remove(ctx, module->dsc);
2238 lydict_remove(ctx, module->ref);
2239 lydict_remove(ctx, module->org);
2240 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002241 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002242
Radek Krejcieb00f512015-07-01 16:44:58 +02002243 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 for (i = 0; i < module->rev_size; i++) {
2245 lydict_remove(ctx, module->rev[i].dsc);
2246 lydict_remove(ctx, module->rev[i].ref);
2247 }
2248 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002249
Radek Krejcieb00f512015-07-01 16:44:58 +02002250 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002252 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 }
2254 module->ident_size = 0;
2255 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002256
Radek Krejcieb00f512015-07-01 16:44:58 +02002257 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002258 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002259 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 }
2261 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002262
Radek Krejcieb00f512015-07-01 16:44:58 +02002263 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002264 for (i = 0; i < module->inc_size; i++) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002265 lydict_remove(ctx, module->inc[i].dsc);
2266 lydict_remove(ctx, module->inc[i].ref);
Radek Krejcic071c542016-01-27 14:57:51 +01002267 /* complete submodule free is done only from main module since
2268 * submodules propagate their includes to the main module */
2269 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002270 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002271 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002272 }
2273 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002274
Radek Krejcieb00f512015-07-01 16:44:58 +02002275 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002276 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002277 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002278 }
2279 free(module->augment);
2280
Radek Krejcieb00f512015-07-01 16:44:58 +02002281 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002282 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002283 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002284 }
2285 free(module->features);
2286
Radek Krejcieb00f512015-07-01 16:44:58 +02002287 /* deviations */
2288 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002289 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002290 }
2291 free(module->deviation);
2292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002293 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002294 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002295}
2296
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297void
Michal Vaskob746fff2016-02-11 11:37:50 +01002298lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002299{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002300 if (!submodule) {
2301 return;
2302 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002305 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002308
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002309 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002310}
2311
Radek Krejci3a5501d2016-07-18 22:03:34 +02002312static int
2313ingrouping(const struct lys_node *node)
2314{
2315 const struct lys_node *iter = node;
2316 assert(node);
2317
2318 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2319 if (!iter) {
2320 return 0;
2321 } else {
2322 return 1;
2323 }
2324}
2325
Radek Krejci76512572015-08-04 09:47:08 +02002326struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002327lys_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 +01002328 uint8_t nacm, struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002329{
Radek Krejcic071c542016-01-27 14:57:51 +01002330 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002332 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002333 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002334 struct unres_list_uniq *unique_info;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002335
Michal Vaskoc07187d2015-08-13 15:20:57 +02002336 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002337 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002338 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002339 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002340 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002341 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002342 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002343 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002344 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002345 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002346 struct lys_node_anydata *any = NULL;
2347 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002348 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002349 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002350 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002351 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002352 struct lys_node_rpc_action *rpc = NULL;
2353 struct lys_node_rpc_action *rpc_orig = (struct lys_node_rpc_action *)node;
2354 struct lys_node_inout *io = NULL;
2355 struct lys_node_inout *io_orig = (struct lys_node_inout *)node;
2356 struct lys_node_rpc_action *ntf = NULL;
2357 struct lys_node_rpc_action *ntf_orig = (struct lys_node_rpc_action *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002358 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002359 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002361 /* we cannot just duplicate memory since the strings are stored in
2362 * dictionary and we need to update dictionary counters.
2363 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002364
Radek Krejci1d82ef62015-08-07 14:44:40 +02002365 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002366 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002367 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002368 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002369 break;
2370
Radek Krejci76512572015-08-04 09:47:08 +02002371 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002372 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002373 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 break;
2375
Radek Krejci76512572015-08-04 09:47:08 +02002376 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002377 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002378 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002379 break;
2380
Radek Krejci76512572015-08-04 09:47:08 +02002381 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002382 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002383 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002384 break;
2385
Radek Krejci76512572015-08-04 09:47:08 +02002386 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002387 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002388 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002389 break;
2390
Radek Krejci76512572015-08-04 09:47:08 +02002391 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002392 case LYS_ANYDATA:
2393 any = calloc(1, sizeof *any);
2394 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002395 break;
2396
Radek Krejci76512572015-08-04 09:47:08 +02002397 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002398 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002399 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002400 break;
2401
Radek Krejci76512572015-08-04 09:47:08 +02002402 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002403 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002404 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002405 break;
2406
Radek Krejci76512572015-08-04 09:47:08 +02002407 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002408 grp = calloc(1, sizeof *grp);
2409 retval = (struct lys_node *)grp;
2410 break;
2411
Radek Krejci76512572015-08-04 09:47:08 +02002412 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002413 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002414 rpc = calloc(1, sizeof *rpc);
2415 retval = (struct lys_node *)rpc;
2416 break;
2417
Radek Krejci76512572015-08-04 09:47:08 +02002418 case LYS_INPUT:
2419 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002420 io = calloc(1, sizeof *io);
2421 retval = (struct lys_node *)io;
2422 break;
2423
Radek Krejci76512572015-08-04 09:47:08 +02002424 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002425 ntf = calloc(1, sizeof *ntf);
2426 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002427 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002429 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002430 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002431 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002432 }
Radek Krejcib388c152015-06-04 17:03:03 +02002433
Michal Vasko253035f2015-12-17 16:58:13 +01002434 if (!retval) {
2435 LOGMEM;
2436 return NULL;
2437 }
2438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002439 /*
2440 * duplicate generic part of the structure
2441 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002442 retval->name = lydict_insert(ctx, node->name, 0);
2443 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2444 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002445 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002446 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002447 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002448 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002449 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002450 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002452 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002453 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002454
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002455 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002456
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002457 retval->iffeature_size = node->iffeature_size;
2458 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2459 if (!retval->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002460 LOGMEM;
2461 goto error;
2462 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002463
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002464 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002465 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002466 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2467 if (size1) {
2468 /* there is something to duplicate */
2469
2470 /* duplicate compiled expression */
2471 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2472 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2473 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2474
2475 /* list of feature pointer must be updated to point to the resulting tree */
2476 retval->iffeature[i].features = malloc(size2 * sizeof *retval->iffeature[i].features);
2477 for (j = 0; (unsigned int)j < size2; j++) {
2478 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2479 &retval->iffeature[i].features[j]);
2480 if (rc == EXIT_SUCCESS) {
2481 /* feature is not resolved, duplicate the expression string */
2482 retval->iffeature[i].features[j] = (void *)strdup((char *)node->iffeature[i].features[j]);
2483 } else if (rc == EXIT_FAILURE) {
2484 /* feature is resolved in origin, so copy it
2485 * - duplication is used for instantiating groupings
2486 * and if-feature inside grouping is supposed to be
2487 * resolved inside the original grouping, so we want
2488 * to keep pointers to features from the grouping
2489 * context */
2490 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2491 } else if (rc == -1) {
2492 goto error;
2493 }
2494 }
2495 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002496 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002497
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002498 /* connect it to the parent */
2499 if (lys_node_addchild(parent, retval->module, retval)) {
2500 goto error;
2501 }
Radek Krejcidce51452015-06-16 15:20:08 +02002502
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002503 /* go recursively */
2504 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2505 LY_TREE_FOR(node->child, child) {
2506 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres, 0)) {
2507 goto error;
2508 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002509 }
2510 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002511 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002512 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002513 }
2514
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002515 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002516 * duplicate specific part of the structure
2517 */
2518 switch (node->nodetype) {
2519 case LYS_CONTAINER:
2520 if (cont_orig->when) {
2521 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002522 }
2523 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002525 cont->must_size = cont_orig->must_size;
2526 cont->tpdf_size = cont_orig->tpdf_size;
2527
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002528 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskodcf98e62016-05-05 17:53:53 +02002529 cont->tpdf = lys_tpdf_dup(module, lys_parent(node), cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002530 break;
2531
2532 case LYS_CHOICE:
2533 if (choice_orig->when) {
2534 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002535 }
2536
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002537 if (!shallow) {
2538 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002539 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
2540 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
2541 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002542 if (rc) {
2543 if (rc == EXIT_FAILURE) {
2544 LOGINT;
2545 }
2546 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002547 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002548 } else {
2549 /* useless to check return value, we don't know whether
2550 * there really wasn't any default defined or it just hasn't
2551 * been resolved, we just hope for the best :)
2552 */
2553 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002554 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002555 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002556 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002557 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002558 break;
2559
2560 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002561 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002562 goto error;
2563 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2565
2566 if (leaf_orig->dflt) {
2567 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci48464ed2016-03-17 15:44:09 +01002568 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002569 goto error;
2570 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002571 }
2572
2573 leaf->must_size = leaf_orig->must_size;
2574 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002575
2576 if (leaf_orig->when) {
2577 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002578 }
2579 break;
2580
2581 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002582 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002583 goto error;
2584 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002585 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2586
2587 llist->min = llist_orig->min;
2588 llist->max = llist_orig->max;
2589
2590 llist->must_size = llist_orig->must_size;
2591 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002592
2593 if (llist_orig->when) {
2594 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002595 }
2596 break;
2597
2598 case LYS_LIST:
2599 list->min = list_orig->min;
2600 list->max = list_orig->max;
2601
2602 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002603 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002604
Radek Krejci581ce772015-11-10 17:22:40 +01002605 list->tpdf_size = list_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002606 list->tpdf = lys_tpdf_dup(module, lys_parent(node), list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002607
Radek Krejci581ce772015-11-10 17:22:40 +01002608 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002609 if (list->keys_size) {
2610 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002611 if (!list->keys) {
2612 LOGMEM;
2613 goto error;
2614 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002615
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002616 if (!shallow) {
2617 /* we managed to resolve it before, resolve it again manually */
2618 if (list_orig->keys[0]) {
2619 for (i = 0; i < list->keys_size; ++i) {
2620 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2621 (const struct lys_node **)&list->keys[i]);
2622 if (rc) {
2623 if (rc == EXIT_FAILURE) {
2624 LOGINT;
2625 }
2626 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002627 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002628 }
2629 /* it was not resolved yet, add unres copy */
2630 } else {
2631 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2632 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002633 goto error;
2634 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002635 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002636 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002637 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002638 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002639 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002640
Radek Krejci581ce772015-11-10 17:22:40 +01002641 list->unique_size = list_orig->unique_size;
2642 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002643 if (!list->unique) {
2644 LOGMEM;
2645 goto error;
2646 }
Radek Krejci581ce772015-11-10 17:22:40 +01002647 for (i = 0; i < list->unique_size; ++i) {
2648 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2649 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002650 if (!list->unique[i].expr) {
2651 LOGMEM;
2652 goto error;
2653 }
Radek Krejci581ce772015-11-10 17:22:40 +01002654 for (j = 0; j < list->unique[i].expr_size; j++) {
2655 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2656
2657 /* if it stays in unres list, duplicate it also there */
Radek Krejcid09d1a52016-08-11 14:05:45 +02002658 unique_info = malloc(sizeof *unique_info);
2659 unique_info->list = (struct lys_node *)list;
2660 unique_info->expr = list->unique[i].expr[j];
2661 unique_info->trg_type = &list->unique[i].trg_type;
2662 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002663 }
2664 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002666 if (list_orig->when) {
2667 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002668 }
Radek Krejcidce51452015-06-16 15:20:08 +02002669 break;
2670
2671 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002672 case LYS_ANYDATA:
2673 any->must_size = any_orig->must_size;
2674 any->must = lys_restr_dup(ctx, any_orig->must, any->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002675
Radek Krejcibf2abff2016-08-23 15:51:52 +02002676 if (any_orig->when) {
2677 any->when = lys_when_dup(ctx, any_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002678 }
2679 break;
2680
2681 case LYS_USES:
2682 uses->grp = uses_orig->grp;
2683
2684 if (uses_orig->when) {
2685 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002686 }
2687
2688 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002689 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002690 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002691 if (!shallow) {
2692 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskocda51712016-05-19 15:22:11 +02002693 if (!uses->grp || uses->grp->nacm) {
2694 assert(!uses->child);
Radek Krejci48464ed2016-03-17 15:44:09 +01002695 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002696 goto error;
2697 }
Michal Vasko49168a22015-08-17 16:35:41 +02002698 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002699 } else {
2700 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002701 }
2702 break;
2703
Radek Krejcidce51452015-06-16 15:20:08 +02002704 case LYS_CASE:
2705 if (cs_orig->when) {
2706 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002707 }
2708 break;
2709
2710 case LYS_GROUPING:
2711 grp->tpdf_size = grp_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002712 grp->tpdf = lys_tpdf_dup(module, lys_parent(node), grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002713 break;
2714
2715 case LYS_RPC:
2716 rpc->tpdf_size = rpc_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002717 rpc->tpdf = lys_tpdf_dup(module, lys_parent(node), rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002718 break;
2719
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002720 case LYS_INPUT:
2721 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002722 io->tpdf_size = io_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002723 io->tpdf = lys_tpdf_dup(module, lys_parent(node), io_orig->tpdf, io->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002724 break;
2725
Radek Krejcida04f4a2015-05-21 12:54:09 +02002726 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002727 ntf->tpdf_size = ntf_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002728 ntf->tpdf = lys_tpdf_dup(module, lys_parent(node), ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002729 break;
2730
2731 default:
2732 /* LY_NODE_AUGMENT */
2733 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002734 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002735 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002736
2737 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002738
2739error:
2740
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002741 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002742 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002743}
2744
Michal Vasko13b15832015-08-19 11:04:48 +02002745void
Michal Vaskoff006c12016-02-17 11:15:19 +01002746lys_node_switch(struct lys_node *dst, struct lys_node *src)
2747{
2748 struct lys_node *child;
2749
Michal Vaskob42b6972016-06-06 14:21:30 +02002750 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01002751
2752 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02002753 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002754 dst->prev->next = src;
2755 }
2756
2757 /* sibling prev */
2758 if (dst->next) {
2759 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02002760 } else {
2761 for (child = dst->prev; child->prev->next; child = child->prev);
2762 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01002763 }
2764
2765 /* next */
2766 src->next = dst->next;
2767 dst->next = NULL;
2768
2769 /* prev */
2770 if (dst->prev != dst) {
2771 src->prev = dst->prev;
2772 }
2773 dst->prev = dst;
2774
2775 /* parent child */
2776 if (dst->parent && (dst->parent->child == dst)) {
2777 dst->parent->child = src;
2778 }
2779
2780 /* parent */
2781 src->parent = dst->parent;
2782 dst->parent = NULL;
2783
2784 /* child parent */
2785 LY_TREE_FOR(dst->child, child) {
2786 if (child->parent == dst) {
2787 child->parent = src;
2788 }
2789 }
2790
2791 /* child */
2792 src->child = dst->child;
2793 dst->child = NULL;
2794}
2795
2796void
Michal Vasko627975a2016-02-11 11:39:03 +01002797lys_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 +02002798{
2799 struct ly_ctx *ctx;
2800 int i;
2801
2802 if (!module) {
2803 return;
2804 }
2805
2806 /* remove schema from the context */
2807 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002808 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002809 for (i = 0; i < ctx->models.used; i++) {
2810 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002811 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002812 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002813 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 +02002814 ctx->models.list[ctx->models.used] = NULL;
2815 /* we are done */
2816 break;
2817 }
2818 }
2819 }
2820
2821 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002822 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002823
2824 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002825 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002826
2827 free(module);
2828}
Radek Krejci7e97c352015-06-19 16:26:34 +02002829
2830/*
2831 * op: 1 - enable, 0 - disable
2832 */
2833static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002834lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002835{
2836 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002837 int i, j, k;
Radek Krejci7e97c352015-06-19 16:26:34 +02002838
2839 if (!module || !name || !strlen(name)) {
2840 return EXIT_FAILURE;
2841 }
2842
2843 if (!strcmp(name, "*")) {
2844 /* enable all */
2845 all = 1;
2846 }
2847
2848 /* module itself */
2849 for (i = 0; i < module->features_size; i++) {
2850 if (all || !strcmp(module->features[i].name, name)) {
2851 if (op) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002852 /* check referenced features if they are enabled */
2853 for (j = 0; j < module->features[i].iffeature_size; j++) {
Radek Krejci69b8d922016-07-27 13:13:41 +02002854 if (!resolve_iffeature(&module->features[i].iffeature[j])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002855 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2856 module->features[i].name, j + 1);
2857 return EXIT_FAILURE;
2858 }
2859 }
2860
Radek Krejci1574a8d2015-08-03 14:16:52 +02002861 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002862 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002863 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002864 }
2865 if (!all) {
2866 return EXIT_SUCCESS;
2867 }
2868 }
2869 }
2870
2871 /* submodules */
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002872 for (i = 0; i < module->inc_size; i++) {
2873 for (j = 0; j < module->inc[i].submodule->features_size; j++) {
2874 if (all || !strcmp(module->inc[i].submodule->features[j].name, name)) {
Radek Krejci7e97c352015-06-19 16:26:34 +02002875 if (op) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002876 /* check referenced features if they are enabled */
2877 for (k = 0; k < module->inc[i].submodule->features[j].iffeature_size; k++) {
Radek Krejci69b8d922016-07-27 13:13:41 +02002878 if (!resolve_iffeature(&module->inc[i].submodule->features[j].iffeature[k])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002879 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2880 module->inc[i].submodule->features[j].name, k + 1);
2881 return EXIT_FAILURE;
2882 }
2883 }
2884
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002885 module->inc[i].submodule->features[j].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002886 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002887 module->inc[i].submodule->features[j].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002888 }
2889 if (!all) {
2890 return EXIT_SUCCESS;
2891 }
2892 }
2893 }
2894 }
2895
2896 if (all) {
2897 return EXIT_SUCCESS;
2898 } else {
2899 return EXIT_FAILURE;
2900 }
2901}
2902
2903API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002904lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002905{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002906 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002907}
2908
2909API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002910lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002911{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002912 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002913}
2914
2915API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002916lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002917{
2918 int i, j;
2919
2920 if (!module || !feature) {
2921 return -1;
2922 }
2923
2924 /* search for the specified feature */
2925 /* module itself */
2926 for (i = 0; i < module->features_size; i++) {
2927 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002928 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002929 return 1;
2930 } else {
2931 return 0;
2932 }
2933 }
2934 }
2935
2936 /* submodules */
2937 for (j = 0; j < module->inc_size; j++) {
2938 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2939 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002940 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002941 return 1;
2942 } else {
2943 return 0;
2944 }
2945 }
2946 }
2947 }
2948
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002949 /* feature definition not found */
2950 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002951}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002952
Radek Krejci96a10da2015-07-30 11:00:14 +02002953API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002954lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002955{
Radek Krejci96a10da2015-07-30 11:00:14 +02002956 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002957 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002958 unsigned int count;
2959
2960 if (!module) {
2961 return NULL;
2962 }
2963
2964 count = module->features_size;
2965 for (i = 0; i < module->inc_size; i++) {
2966 count += module->inc[i].submodule->features_size;
2967 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002968 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002969 if (!result) {
2970 LOGMEM;
2971 return NULL;
2972 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002973 if (states) {
2974 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002975 if (!(*states)) {
2976 LOGMEM;
2977 free(result);
2978 return NULL;
2979 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002980 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002981 count = 0;
2982
2983 /* module itself */
2984 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002985 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002986 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002987 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002988 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002989 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002990 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002991 }
2992 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002993 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002994 }
2995
2996 /* submodules */
2997 for (j = 0; j < module->inc_size; j++) {
2998 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002999 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003000 if (states) {
3001 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3002 (*states)[count] = 1;
3003 } else {
3004 (*states)[count] = 0;
3005 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003006 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003007 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003008 }
3009 }
3010
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003011 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003012 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003013
3014 return result;
3015}
Michal Vaskobaefb032015-09-24 14:52:10 +02003016
Radek Krejci6910a032016-04-13 10:06:21 +02003017API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01003018lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01003019{
3020 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
3021}
3022
Radek Krejci6910a032016-04-13 10:06:21 +02003023API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02003024lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01003025{
3026 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
3027}
3028
Michal Vaskobaefb032015-09-24 14:52:10 +02003029API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01003030lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02003031{
3032 if (!node || !node->parent) {
3033 return NULL;
3034 }
3035
3036 if (node->parent->nodetype == LYS_AUGMENT) {
3037 return ((struct lys_node_augment *)node->parent)->target;
3038 }
3039
3040 return node->parent;
3041}
Michal Vasko1b229152016-01-13 11:28:38 +01003042
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003043API void *
Michal Vasko1b229152016-01-13 11:28:38 +01003044lys_set_private(const struct lys_node *node, void *priv)
3045{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003046 void *prev;
3047
Michal Vasko1b229152016-01-13 11:28:38 +01003048 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003049 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
3050 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01003051 }
3052
Mislav Novakovicb5529e52016-02-29 11:42:43 +01003053 prev = node->priv;
3054 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003055
3056 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01003057}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003058
Michal Vasko01c6fd22016-05-20 11:43:05 +02003059int
3060lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
3061{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003062 struct lys_node_leaf *iter = leafref_target;
3063
Michal Vasko48a573d2016-07-01 11:46:02 +02003064 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003065 LOGINT;
3066 return -1;
3067 }
3068
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003069 /* check for cycles */
3070 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
3071 if ((void *)iter == (void *)leafref) {
3072 /* cycle detected */
3073 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
3074 return -1;
3075 }
3076 iter = iter->type.info.lref.target;
3077 }
3078
3079 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02003080 * leafrefs referencing the leaf(-list) */
Michal Vasko01c6fd22016-05-20 11:43:05 +02003081 if (!leafref_target->child) {
3082 leafref_target->child = (void*)ly_set_new();
3083 if (!leafref_target->child) {
3084 LOGMEM;
3085 return -1;
3086 }
3087 }
Radek Krejci09891a22016-06-10 10:59:22 +02003088 ly_set_add((struct ly_set *)leafref_target->child, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003089
3090 return 0;
3091}
3092
Michal Vasko8548e082016-07-22 12:00:18 +02003093/* not needed currently */
3094#if 0
3095
Michal Vasko5b3492c2016-07-20 09:37:40 +02003096static const char *
3097lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
3098{
3099 struct lys_module *prev_mod;
3100 uint32_t str_len, mod_len, buf_idx;
3101
Radek Krejcibf2abff2016-08-23 15:51:52 +02003102 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003103 LOGINT;
3104 return NULL;
3105 }
3106
3107 buf_idx = buf_len - 1;
3108 buf[buf_idx] = '\0';
3109
3110 while (node) {
3111 if (lys_parent(node)) {
3112 prev_mod = lys_node_module(lys_parent(node));
3113 } else {
3114 prev_mod = NULL;
3115 }
3116
Radek Krejcibf2abff2016-08-23 15:51:52 +02003117 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003118 str_len = strlen(node->name);
3119
3120 if (prev_mod != node->module) {
3121 mod_len = strlen(node->module->name);
3122 } else {
3123 mod_len = 0;
3124 }
3125
3126 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
3127 LOGINT;
3128 return NULL;
3129 }
3130
3131 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
3132
3133 buf[buf_idx] = '/';
3134 if (mod_len) {
3135 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
3136 buf[buf_idx + 1 + mod_len] = ':';
3137 }
3138 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
3139 }
3140
3141 node = lys_parent(node);
3142 }
3143
3144 return buf + buf_idx;
3145}
3146
Michal Vasko8548e082016-07-22 12:00:18 +02003147#endif
3148
3149API struct ly_set *
3150lys_xpath_atomize(const struct lys_node *cur_snode, const char *expr, int options)
Michal Vasko5b3492c2016-07-20 09:37:40 +02003151{
Michal Vasko5b3492c2016-07-20 09:37:40 +02003152 struct lyxp_set *set;
Michal Vasko8548e082016-07-22 12:00:18 +02003153 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003154 uint32_t i;
3155
Michal Vasko8548e082016-07-22 12:00:18 +02003156 if (!cur_snode || !expr) {
3157 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003158 }
3159
3160 set = calloc(1, sizeof *set);
3161 if (!set) {
3162 LOGMEM;
Michal Vasko8548e082016-07-22 12:00:18 +02003163 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003164 }
3165
3166 if (options & LYXP_MUST) {
3167 options &= ~LYXP_MUST;
3168 options |= LYXP_SNODE_MUST;
3169 } else if (options & LYXP_WHEN) {
3170 options &= ~LYXP_WHEN;
3171 options |= LYXP_SNODE_WHEN;
3172 } else {
3173 options |= LYXP_SNODE;
3174 }
3175
3176 if (lyxp_atomize(expr, cur_snode, set, options)) {
3177 free(set->val.snodes);
3178 free(set);
Michal Vasko8548e082016-07-22 12:00:18 +02003179 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003180 }
3181
Michal Vasko8548e082016-07-22 12:00:18 +02003182 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003183
Michal Vasko5b3492c2016-07-20 09:37:40 +02003184 for (i = 0; i < set->used; ++i) {
3185 switch (set->val.snodes[i].type) {
3186 case LYXP_NODE_ELEM:
Radek Krejci98a55842016-08-16 08:42:54 +02003187 if (ly_set_add(ret_set, set->val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02003188 ly_set_free(ret_set);
3189 free(set->val.snodes);
3190 free(set);
3191 return NULL;
3192 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003193 break;
3194 default:
Michal Vasko8548e082016-07-22 12:00:18 +02003195 /* ignore roots, text and attr should not appear ever */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003196 break;
3197 }
3198 }
3199
Michal Vasko5b3492c2016-07-20 09:37:40 +02003200 free(set->val.snodes);
3201 free(set);
Michal Vasko8548e082016-07-22 12:00:18 +02003202 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003203}
3204
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003205static void
Michal Vasko89563fc2016-07-28 16:19:35 +02003206lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *target_module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003207{
3208 int ret;
3209 char *parent_path;
3210 struct lys_node *target;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003211
3212 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
3213 if (dev->orig_node) {
3214 /* removing not-supported deviation ... */
3215 if (strrchr(dev->target_name, '/') != dev->target_name) {
3216 /* ... from a parent */
3217 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
3218
3219 target = NULL;
3220 ret = resolve_augment_schema_nodeid(parent_path, NULL, target_module, (const struct lys_node **)&target);
3221 free(parent_path);
3222 if (ret || !target) {
3223 LOGINT;
3224 return;
3225 }
3226
3227 lys_node_addchild(target, NULL, dev->orig_node);
3228 } else {
3229 /* ... from top-level data */
3230 lys_node_addchild(NULL, (struct lys_module *)target_module, dev->orig_node);
3231 }
3232
3233 dev->orig_node = NULL;
3234 } else {
3235 /* adding not-supported deviation */
3236 target = NULL;
3237 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
3238 if (ret || !target) {
3239 LOGINT;
3240 return;
3241 }
3242
3243 lys_node_unlink(target);
3244 dev->orig_node = target;
3245 }
3246 } else {
3247 target = NULL;
3248 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
3249 if (ret || !target) {
3250 LOGINT;
3251 return;
3252 }
3253
3254 lys_node_switch(target, dev->orig_node);
3255 dev->orig_node = target;
3256 }
3257}
3258
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003259/* temporarily removes or applies deviations, updates module deviation flag accordingly */
3260void
3261lys_switch_deviations(struct lys_module *module)
3262{
Michal Vasko89563fc2016-07-28 16:19:35 +02003263 uint32_t i = 0, j;
3264 const struct lys_module *mod;
3265 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003266
Michal Vasko89563fc2016-07-28 16:19:35 +02003267 if (module->deviated) {
3268 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3269 if (mod == module) {
3270 continue;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003271 }
3272
Michal Vasko89563fc2016-07-28 16:19:35 +02003273 for (j = 0; j < mod->deviation_size; ++j) {
3274 ptr = strstr(mod->deviation[j].target_name, module->name);
3275 if (ptr && ptr[strlen(module->name)] == ':') {
3276 lys_switch_deviation(&mod->deviation[j], module);
3277 }
3278 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003279 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003280
Michal Vasko89563fc2016-07-28 16:19:35 +02003281 if (module->deviated == 2) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003282 module->deviated = 1;
Michal Vasko89563fc2016-07-28 16:19:35 +02003283 } else {
3284 module->deviated = 2;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003285 }
3286 }
3287}
3288
3289/* not needed currently, but tested and working */
3290#if 0
3291
3292void
3293lys_sub_module_apply_devs_augs(struct lys_module *module)
3294{
3295 int i;
3296 struct lys_node_augment *aug;
3297 struct lys_node *last;
3298
3299 /* re-apply deviations */
3300 for (i = 0; i < module->deviation_size; ++i) {
3301 lys_switch_deviation(&module->deviation[i], module);
3302 assert(module->deviation[i].orig_node);
Michal Vasko89563fc2016-07-28 16:19:35 +02003303 lys_node_module(module->deviation[i].orig_node)->deviated = 1;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003304 }
3305
3306 /* re-apply augments */
3307 for (i = 0; i < module->augment_size; ++i) {
3308 aug = &module->augment[i];
3309 assert(aug->target);
3310
3311 /* reconnect augmenting data into the target - add them to the target child list */
3312 if (aug->target->child) {
3313 last = aug->target->child->prev;
3314 last->next = aug->child;
3315 aug->target->child->prev = aug->child->prev;
3316 aug->child->prev = last;
3317 } else {
3318 aug->target->child = aug->child;
3319 }
3320 }
3321}
3322
3323#endif
3324
3325void
3326lys_sub_module_remove_devs_augs(struct lys_module *module)
3327{
Michal Vasko89563fc2016-07-28 16:19:35 +02003328 uint32_t i = 0, j;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003329 struct lys_node *last, *elem;
Michal Vasko89563fc2016-07-28 16:19:35 +02003330 const struct lys_module *mod;
3331 struct lys_module *target_mod;
3332 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003333
3334 /* remove applied deviations */
3335 for (i = 0; i < module->deviation_size; ++i) {
3336 lys_switch_deviation(&module->deviation[i], module);
Michal Vasko89563fc2016-07-28 16:19:35 +02003337 target_mod = lys_node_module(module->deviation[i].orig_node);
3338 assert(target_mod->deviated == 1);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003339
Michal Vasko89563fc2016-07-28 16:19:35 +02003340 /* clear the deviation flag if possible */
3341 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3342 if ((mod == module) || (mod == target_mod)) {
3343 continue;
3344 }
3345
3346 for (j = 0; j < mod->deviation_size; ++j) {
3347 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
3348 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
3349 /* some other module deviation targets the inspected module, flag remains */
3350 break;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003351 }
3352 }
Michal Vasko89563fc2016-07-28 16:19:35 +02003353
3354 if (j < mod->deviation_size) {
3355 break;
3356 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003357 }
Michal Vasko89563fc2016-07-28 16:19:35 +02003358
3359 if (!mod) {
3360 target_mod->deviated = 0;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003361 }
3362 }
3363
3364 /* remove applied augments */
3365 for (i = 0; i < module->augment_size; ++i) {
Radek Krejcidbc15262016-06-16 14:58:29 +02003366 if (!module->augment[i].target) {
3367 /* skip not resolved augments */
3368 continue;
3369 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003370
3371 elem = module->augment[i].child;
3372 if (elem) {
3373 LY_TREE_FOR(elem, last) {
3374 if (!last->next || (last->next->parent != (struct lys_node *)&module->augment[i])) {
3375 break;
3376 }
3377 }
3378 /* elem is first augment child, last is the last child */
3379
3380 /* parent child ptr */
3381 if (module->augment[i].target->child == elem) {
3382 module->augment[i].target->child = last->next;
3383 }
3384
3385 /* parent child next ptr */
3386 if (elem->prev->next) {
3387 elem->prev->next = last->next;
3388 }
3389
3390 /* parent child prev ptr */
3391 if (last->next) {
3392 last->next->prev = elem->prev;
3393 } else if (module->augment[i].target->child) {
3394 module->augment[i].target->child->prev = elem->prev;
3395 }
3396
3397 /* update augment children themselves */
3398 elem->prev = last;
3399 last->next = NULL;
3400 }
Michal Vaskob8f71322016-05-03 11:39:56 +02003401
3402 /* needs to be NULL for lys_augment_free() to free the children */
3403 module->augment[i].target = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003404 }
3405}
3406
Michal Vasko26055752016-05-03 11:36:31 +02003407int
3408lys_module_set_implement(struct lys_module *module)
3409{
3410 struct ly_ctx *ctx;
3411 int i;
3412
3413 if (module->implemented) {
3414 return EXIT_SUCCESS;
3415 }
3416
3417 ctx = module->ctx;
3418
3419 for (i = 0; i < ctx->models.used; ++i) {
3420 if (module == ctx->models.list[i]) {
3421 continue;
3422 }
3423
3424 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
3425 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
3426 return EXIT_FAILURE;
3427 }
3428 }
3429
3430 module->implemented = 1;
3431 return EXIT_SUCCESS;
3432}
3433
3434int
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003435lys_sub_module_set_dev_aug_target_implement(struct lys_module *module)
3436{
3437 int i;
3438 struct lys_module *trg_mod;
3439
3440 for (i = 0; i < module->deviation_size; ++i) {
3441 assert(module->deviation[i].orig_node);
3442 trg_mod = lys_node_module(module->deviation[i].orig_node);
Michal Vasko26055752016-05-03 11:36:31 +02003443 if (lys_module_set_implement(trg_mod)) {
3444 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003445 }
3446 }
3447
3448 for (i = 0; i < module->augment_size; ++i) {
3449 assert(module->augment[i].target);
3450 trg_mod = lys_node_module(module->augment[i].target);
Michal Vasko26055752016-05-03 11:36:31 +02003451 if (lys_module_set_implement(trg_mod)) {
3452 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003453 }
3454 }
Michal Vasko26055752016-05-03 11:36:31 +02003455
3456 return EXIT_SUCCESS;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003457}
3458
3459void
3460lys_submodule_module_data_free(struct lys_submodule *submodule)
3461{
3462 struct lys_node *next, *elem;
3463
3464 /* remove parsed data */
3465 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
3466 if (elem->module == (struct lys_module *)submodule) {
3467 lys_node_free(elem, NULL, 0);
3468 }
3469 }
3470}