blob: cd90453b7b14d6c2c2707757ed54f4bd4118b738 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
Michal Vasko2d162e12015-09-24 14:33:29 +02002 * @file tree_schema.c
Radek Krejcida04f4a2015-05-21 12:54:09 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vasko2d162e12015-09-24 14:33:29 +02004 * @brief Manipulation with libyang schema data structures
Radek Krejcida04f4a2015-05-21 12:54:09 +02005 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
Radek Krejci54f6fb32016-02-24 12:56:39 +010014
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020015#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020016
Radek Krejci812b10a2015-05-28 16:48:25 +020017#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020018#include <ctype.h>
Radek Krejcib051f722016-02-25 15:12:21 +010019#include <limits.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <sys/mman.h>
Michal Vasko662610a2015-12-07 11:25:45 +010022#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020023#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010024#include <fcntl.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020025#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010026#include <unistd.h>
27#include <errno.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020028
29#include "common.h"
30#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020031#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020032#include "resolve.h"
Michal Vasko88c29542015-11-27 14:57:53 +010033#include "xml.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020034#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020035#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020036#include "validation.h"
Pavol Vicanf7cc2852016-03-22 23:27:35 +010037#include "parser_yang.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020038
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020039static int
40lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
41 struct unres_schema *unres);
42
Michal Vasko1e62a092015-12-01 12:27:20 +010043API const struct lys_feature *
44lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020045{
46 int i;
47
48check:
49 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
50 /* input/output does not have if-feature, so skip them */
51
52 /* check local if-features */
53 for (i = 0; i < node->features_size; i++) {
54 if (!(node->features[i]->flags & LYS_FENABLED)) {
55 return node->features[i];
56 }
57 }
58 }
59
60 if (!recursive) {
61 return NULL;
62 }
63
64 /* go through parents */
65 if (node->nodetype == LYS_AUGMENT) {
66 /* go to parent actually means go to the target node */
67 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020068 } else if (node->parent) {
69 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020070 } else {
71 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020072 }
73
Radek Krejci074bf852015-08-19 14:22:16 +020074 if (recursive == 2) {
75 /* continue only if the node cannot have a data instance */
76 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
77 return NULL;
78 }
79 }
80 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020081}
82
Michal Vasko1dca6882015-10-22 14:29:42 +020083int
Michal Vasko36cbaa42015-12-14 13:15:48 +010084lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
85 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020086{
Radek Krejcic071c542016-01-27 14:57:51 +010087 const struct lys_node *node, *parent = NULL;
88 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010089 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020090
Michal Vasko36cbaa42015-12-14 13:15:48 +010091 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020092 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020093
Michal Vasko36cbaa42015-12-14 13:15:48 +010094 /* fill the lengths in case the caller is so indifferent */
95 if (!mod_name_len) {
96 mod_name_len = strlen(mod_name);
97 }
Michal Vasko1dca6882015-10-22 14:29:42 +020098 if (!nam_len) {
99 nam_len = strlen(name);
100 }
101
Michal Vasko36cbaa42015-12-14 13:15:48 +0100102 /* set mod correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100103 parent = lys_parent(siblings);
104 if (!parent) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100105 mod = lys_node_module(siblings);
Michal Vasko1dca6882015-10-22 14:29:42 +0200106 }
107
Radek Krejcic071c542016-01-27 14:57:51 +0100108 /* try to find the node */
109 node = NULL;
110 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
111 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100112 /* module name comparison */
113 node_mod_name = lys_node_module(node)->name;
114 if ((node_mod_name != mod_name) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100115 continue;
116 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200117
Radek Krejcic071c542016-01-27 14:57:51 +0100118 /* direct name check */
119 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
120 if (ret) {
121 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200122 }
Radek Krejcic071c542016-01-27 14:57:51 +0100123 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200124 }
125 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200126 }
127
128 return EXIT_FAILURE;
129}
130
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200131int
Michal Vasko1e62a092015-12-01 12:27:20 +0100132lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
133 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200134{
Michal Vasko1e62a092015-12-01 12:27:20 +0100135 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200136
137 assert(siblings && name);
138 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
139
140 /* find the beginning */
141 while (siblings->prev->next) {
142 siblings = siblings->prev;
143 }
144
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200145 if (!mod) {
146 mod = siblings->module;
147 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200148
Michal Vasko4f0dad02016-02-15 14:08:23 +0100149 /* try to find the node */
150 node = NULL;
151 while ((node = lys_getnext(node, siblings->parent, mod, 0))) {
152 if (!type || (node->nodetype & type)) {
153 /* module check */
154 if (lys_node_module(node) != lys_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100155 continue;
156 }
157
Michal Vasko4f0dad02016-02-15 14:08:23 +0100158 /* direct name check */
Radek Krejci749190d2016-02-18 16:26:25 +0100159 if (ly_strequal(node->name, name, 0)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100160 if (ret) {
161 *ret = node;
162 }
163 return EXIT_SUCCESS;
164 }
Radek Krejcic071c542016-01-27 14:57:51 +0100165 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200166 }
167
168 return EXIT_FAILURE;
169}
170
Michal Vasko1e62a092015-12-01 12:27:20 +0100171API const struct lys_node *
172lys_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200173{
Michal Vasko1e62a092015-12-01 12:27:20 +0100174 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200175
Radek Krejci8bc87f62015-09-02 16:19:05 +0200176 if (!last) {
177 /* first call */
178
179 /* get know where to start */
180 if (parent) {
181 /* schema subtree */
182 next = last = parent->child;
183 } else {
184 /* top level data */
185 assert(module);
186 next = last = module->data;
187 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200188 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200189 /* continue after the last returned value */
190 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200191 }
192
193repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200194 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200195 if (options & LYS_GETNEXT_WITHGROUPING) {
196 return next;
197 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200198 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200199 }
200
Radek Krejcic4ccbd92016-01-07 13:13:33 +0100201 if (!next) {
Radek Krejci63318e82016-02-12 09:43:12 +0100202 if (!last || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200203 /* no next element */
204 return NULL;
205 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200206 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200207 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200208 goto repeat;
209 }
210
211 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200212 case LYS_INPUT:
213 case LYS_OUTPUT:
214 if (options & LYS_GETNEXT_WITHINOUT) {
215 return next;
216 } else {
217 next = next->child;
218 goto repeat;
219 }
220 break;
221
Michal Vaskoa5835e92015-10-20 15:07:39 +0200222 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200223 if (options & LYS_GETNEXT_WITHCASE) {
224 return next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200225 } else {
226 next = next->child;
227 goto repeat;
Michal Vasko1dca6882015-10-22 14:29:42 +0200228 }
Michal Vaskob6eedf02015-10-22 16:07:03 +0200229 break;
230
Michal Vasko1dca6882015-10-22 14:29:42 +0200231 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200232 /* go into */
233 next = next->child;
234 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200235
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200236 case LYS_RPC:
237 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200238 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200239 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200240 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200241 case LYS_LIST:
242 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200243 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200244
245 case LYS_CHOICE:
246 if (options & LYS_GETNEXT_WITHCHOICE) {
247 return next;
248 } else {
249 /* go into */
250 next = next->child;
251 goto repeat;
252 }
253 break;
254
Radek Krejci7f40ce32015-08-12 20:38:46 +0200255 default:
256 /* we should not be here */
257 return NULL;
258 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200259
260
261}
262
Michal Vasko1e62a092015-12-01 12:27:20 +0100263static const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100264check_mand_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module)
Radek Krejci8bc87f62015-09-02 16:19:05 +0200265{
Michal Vasko1e62a092015-12-01 12:27:20 +0100266 const struct lys_node *next;
267
Radek Krejci2342cf62016-01-29 16:48:23 +0100268 next = lys_getnext(last, parent, module, LYS_GETNEXT_WITHCHOICE);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200269
Radek Krejci4b6c2112015-10-06 12:48:34 +0200270repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200271 if (next && next->nodetype == LYS_CONTAINER) {
272 if (((struct lys_node_container *)next)->presence) {
273 /* mandatory elements under the non-existing presence
274 * container are not mandatory - 7.6.5, rule 1 */
275 next = next->next;
276 } else {
277 /* go into */
278 next = next->child;
279 }
280 goto repeat;
281 }
282
283 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200284}
285
Michal Vasko1e62a092015-12-01 12:27:20 +0100286static const struct lys_node *
287check_mand_check(const struct lys_node *node, const struct lys_node *stop, const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200288{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200289 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200290 struct lyd_node *diter = NULL;
Radek Krejcidc154432016-01-21 11:10:59 +0100291 struct ly_set *set = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200292 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200293 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200294
295 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100296 if (!data) {
297 /* we have no data but a mandatory node */
298 return node;
299 }
300 switch (node->nodetype) {
301 case LYS_LEAF:
302 case LYS_ANYXML:
303 case LYS_CHOICE:
304 if (node->parent && node->parent->nodetype == LYS_CASE) {
305 /* 7.6.5, rule 2 */
306 /* 7.9.4, rule 1 */
307 if (node->parent->parent->parent == data->schema) {
308 /* the only case the node's siblings can exist is that the
309 * data node passed originally to ly_check_mandatory()
310 * had this choice as a child
311 */
312 /* try to find the node's siblings in data */
313 LY_TREE_FOR(data->child, diter) {
314 LY_TREE_FOR(node->parent->child, siter) {
315 if (siter == diter->schema) {
316 /* some sibling exists, rule applies */
317 break;
318 }
319 }
320 if (siter) {
321 break;
322 }
323 }
324 }
325 if (!siter) {
326 /* no sibling exists */
327 return NULL;
328 }
329 } else {
Radek Krejci7eb12132016-02-01 10:55:23 +0100330 for (parent = node->parent; parent && parent != stop; parent = parent->parent) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100331 if (parent->nodetype != LYS_CONTAINER) {
332 /* 7.6.5, rule 1, checking presence is not needed
333 * since it is done in check_mand_getnext()
334 */
335 ly_set_free(set);
336 return NULL;
337 }
338 /* add the parent to the list for searching in data tree */
339 if (!set) {
340 set = ly_set_new();
341 }
342 /* ignore return - memory error is logged and we will
343 * check at least the rest of nodes we have */
344 (void)ly_set_add(set, parent);
345 }
346 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200347
Radek Krejci2342cf62016-01-29 16:48:23 +0100348 /* search for instance */
349 if (set) {
350 for (i = 0; i < set->number; i++) {
351 LY_TREE_FOR(data->child, diter) {
Radek Krejci8f08df12016-03-21 11:11:30 +0100352 if (diter->schema == set->set.s[i]) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100353 break;
354 }
355 }
356 if (!diter) {
357 /* instance not found */
Radek Krejci8f08df12016-03-21 11:11:30 +0100358 node = set->set.s[i];
Radek Krejci2342cf62016-01-29 16:48:23 +0100359 ly_set_free(set);
360 return node;
361 }
362 data = diter;
363 }
364 ly_set_free(set);
365 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200366
Radek Krejci2342cf62016-01-29 16:48:23 +0100367 LY_TREE_FOR(data->child, diter) {
368 if (diter->schema == node) {
369 return NULL;
370 }
371 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200372
Radek Krejci2342cf62016-01-29 16:48:23 +0100373 /* instance not found */
374 /* 7.6.5, rule 3 (or 2) */
375 /* 7.9.4, rule 2 */
376 return node;
377 default:
378 /* error */
379 break;
380 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200381 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
382 /* search for number of instances */
383 minmax = 0;
Radek Krejci2342cf62016-01-29 16:48:23 +0100384 if (data) {
385 LY_TREE_FOR(data->child, diter) {
386 if (diter->schema == node) {
387 minmax++;
388 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200389 }
390 }
391
392 /* check the specified constraints */
393 if (node->nodetype == LYS_LIST) {
394 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
395 return node;
396 }
397
398 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
399 return node;
400 }
401 } else if (node->nodetype == LYS_LEAFLIST) {
402 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
403 return node;
404 }
405
406 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
407 return node;
408 }
409 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200410 }
411
412 return NULL;
413}
414
Michal Vasko1e62a092015-12-01 12:27:20 +0100415const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100416ly_check_mandatory(const struct lyd_node *data, const struct lys_node *schema)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200417{
Michal Vasko1e62a092015-12-01 12:27:20 +0100418 const struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
419 const struct lyd_node *diter;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200420 int found;
421
Radek Krejci2342cf62016-01-29 16:48:23 +0100422 assert(data || schema);
423
424 if (!data) { /* !data && schema */
425 siter = schema;
426 } else { /* data && !schema */
Radek Krejcie2f12212016-02-12 13:50:22 +0100427 schema = data->schema;
428 siter = data->schema->child;
Radek Krejci2342cf62016-01-29 16:48:23 +0100429 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200430
431repeat:
432 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200433 if (lys_is_disabled(siter, 2)) {
434 siter = siter->next;
435 continue;
436 }
437
Radek Krejci7f40ce32015-08-12 20:38:46 +0200438 switch (siter->nodetype) {
439 case LYS_CONTAINER:
440 case LYS_LEAF:
441 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200442 case LYS_LIST:
443 case LYS_LEAFLIST:
444 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200445 result = check_mand_check(siter, siter->parent, data);
446 if (result) {
447 return result;
448 }
449 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200450 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
451 saux = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100452 while ((saux = check_mand_getnext(saux, siter, NULL))) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200453 result = check_mand_check(saux, siter, data);
454 if (result) {
455 return result;
456 }
457 }
458 }
459 siter = siter->next;
460 break;
461 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200462 /* search for instance */
463 saux = siter;
464 siter = siter->child;
465 found = 0;
466 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200467repeat_choice:
Radek Krejci2342cf62016-01-29 16:48:23 +0100468 while (siter && data) {
Radek Krejci074bf852015-08-19 14:22:16 +0200469 if (lys_is_disabled(siter, 2)) {
470 siter = siter->next;
471 continue;
472 }
473
Radek Krejci14a11a62015-08-17 17:27:38 +0200474 switch (siter->nodetype) {
475 case LYS_CONTAINER:
476 case LYS_LEAF:
477 case LYS_LEAFLIST:
478 case LYS_LIST:
479 case LYS_ANYXML:
480 LY_TREE_FOR(data->child, diter) {
481 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200482 break;
483 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200484 }
485 if (diter) {
486 /* got instance */
487 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200488 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200489 saux2 = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100490 while ((saux2 = check_mand_getnext(saux2, parent2, NULL))) {
Radek Krejci37bda002015-08-27 11:23:56 +0200491 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200492 if (result) {
493 return result;
494 }
495 }
496 }
497 siter = parent2 = NULL;
498 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200499 break;
500 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200501 siter = siter->next;
502 break;
503 case LYS_CASE:
504 case LYS_CHOICE:
505 case LYS_USES:
506 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200507 if (!parent2) {
508 parent2 = siter;
509 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200510 siter = siter->child;
511 break;
512 case LYS_AUGMENT:
513 case LYS_GROUPING:
514 /* skip */
515 siter = siter->next;
516 break;
517 default:
518 /* error */
519 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200520 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200521 }
522
Radek Krejci14a11a62015-08-17 17:27:38 +0200523 if (parent2) {
524 siter = parent2->next;
525 if (parent2->parent == saux) {
526 parent2 = NULL;
527 } else {
528 parent2 = parent2->parent;
529 }
530 goto repeat_choice;
531 }
532
Radek Krejci074bf852015-08-19 14:22:16 +0200533 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200534 return saux;
535 }
536
537 /* go to next */
538 siter = saux->next;
539
Radek Krejci7f40ce32015-08-12 20:38:46 +0200540 break;
541 case LYS_USES:
542 case LYS_CASE:
543 /* go into */
544 parent = siter;
545 siter = siter->child;
546 break;
547 default:
548 /* can ignore, go to next */
549 siter = siter->next;
550 break;
551 }
552 }
553
554 if (parent) {
555 siter = parent->next;
Radek Krejci2342cf62016-01-29 16:48:23 +0100556 if (parent->parent == schema) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200557 parent = NULL;
558 } else {
559 parent = parent->parent;
560 }
561 goto repeat;
562 }
563
564 return NULL;
565}
566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200567void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200568lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200569{
Radek Krejci76512572015-08-04 09:47:08 +0200570 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100571 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200573 if (!node) {
574 return;
575 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200576
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200577 /* unlink from data model if necessary */
578 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100579 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100580 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100581 if (main_module->data == node) {
582 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200583 }
584 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200585
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200586 /* store pointers to important nodes */
587 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200588 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200589 /* handle augments - first, unlink it from the augment parent ... */
590 if (parent->child == node) {
591 parent->child = node->next;
592 }
593 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200594 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200595 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200597 /* unlink from parent */
598 if (parent) {
599 if (parent->child == node) {
600 parent->child = node->next;
601 }
602 node->parent = NULL;
603 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200604
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200605 /* unlink from siblings */
606 if (node->prev == node) {
607 /* there are no more siblings */
608 return;
609 }
610 if (node->next) {
611 node->next->prev = node->prev;
612 } else {
613 /* unlinking the last element */
614 if (parent) {
615 first = parent->child;
616 } else {
617 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200618 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200619 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200620 }
621 }
622 first->prev = node->prev;
623 }
624 if (node->prev->next) {
625 node->prev->next = node->next;
626 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200628 /* clean up the unlinked element */
629 node->next = NULL;
630 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200631}
632
Michal Vasko563ef092015-09-04 13:17:23 +0200633struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100634lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200635{
636 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200637
638 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200639 /* top-level augment, look into module (uses augment is handled correctly below) */
640 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
641 par_iter = par_iter->parent->module->data;
642 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200643 break;
644 }
645 }
646
Michal Vasko6f929da2015-10-02 16:23:25 +0200647 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200648 continue;
649 }
650
651 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
652 if (!stop) {
653 stop = par_iter;
654 } else if (iter == stop) {
655 break;
656 }
657 if (iter->nodetype != LYS_GROUPING) {
658 continue;
659 }
660
Radek Krejcif8426a72015-10-31 23:14:03 +0100661 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200662 return (struct lys_node_grp *)iter;
663 }
664 }
665 }
666
Michal Vasko563ef092015-09-04 13:17:23 +0200667 return NULL;
668}
669
Radek Krejci10c760e2015-08-14 14:45:43 +0200670/*
671 * get next grouping in the root's subtree, in the
672 * first call, tha last is NULL
673 */
674static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200675lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200676{
Radek Krejci10c760e2015-08-14 14:45:43 +0200677 struct lys_node *last = (struct lys_node *)lastgrp;
678 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200679
Radek Krejci10c760e2015-08-14 14:45:43 +0200680 assert(root);
681
682 if (!last) {
683 last = root;
684 }
685
686 while (1) {
687 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
688 next = last->child;
689 } else {
690 next = NULL;
691 }
692 if (!next) {
693 if (last == root) {
694 /* we are done */
695 return NULL;
696 }
697
698 /* no children, go to siblings */
699 next = last->next;
700 }
701 while (!next) {
702 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100703 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200704 /* we are done */
705 return NULL;
706 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200707 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100708 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200709 }
710
711 if (next->nodetype == LYS_GROUPING) {
712 return (struct lys_node_grp *)next;
713 }
714
715 last = next;
716 }
717}
718
Michal Vasko0d343d12015-08-24 14:57:36 +0200719/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200720int
Radek Krejci07911992015-08-14 15:13:31 +0200721lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
722{
Michal Vasko563ef092015-09-04 13:17:23 +0200723 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200724 struct lys_node_grp *grp;
725 int down;
726
727 assert(node);
728
729 if (!parent) {
730 assert(module);
731 } else {
732 module = parent->module;
733 }
734
735 switch (node->nodetype) {
736 case LYS_GROUPING:
737 /* 6.2.1, rule 6 */
738 if (parent) {
739 if (parent->child) {
740 down = 1;
741 start = parent->child;
742 } else {
743 down = 0;
744 start = parent;
745 }
746 } else {
747 down = 1;
748 start = module->data;
749 }
750 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100751 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100752 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200753 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200754 }
755 /* go down, because grouping can be defined after e.g. container in which is collision */
756 if (down) {
757 for (iter = start, stop = NULL; iter; iter = iter->prev) {
758 if (!stop) {
759 stop = start;
760 } else if (iter == stop) {
761 break;
762 }
763 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
764 continue;
765 }
766
767 grp = NULL;
768 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100769 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100770 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200771 return EXIT_FAILURE;
772 }
773 }
774 }
775 }
776 break;
777 case LYS_LEAF:
778 case LYS_LEAFLIST:
779 case LYS_LIST:
780 case LYS_CONTAINER:
781 case LYS_CHOICE:
782 case LYS_ANYXML:
783 /* 6.2.1, rule 7 */
784 if (parent) {
785 iter = parent;
786 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
787 iter = iter->parent;
788 }
789 if (!iter) {
790 stop = NULL;
791 iter = module->data;
792 } else {
793 stop = iter;
794 iter = iter->child;
795 }
796 } else {
797 stop = NULL;
798 iter = module->data;
799 }
800 while (iter) {
801 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
802 iter = iter->child;
803 continue;
804 }
805
806 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100807 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100808 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200809 return EXIT_FAILURE;
810 }
811 }
812
813 /* special case for choice - we must check the choice's name as
814 * well as the names of nodes under the choice
815 */
816 if (iter->nodetype == LYS_CHOICE) {
817 iter = iter->child;
818 continue;
819 }
820
821 /* go to siblings */
822 if (!iter->next) {
823 /* no sibling, go to parent's sibling */
824 do {
825 iter = iter->parent;
826 if (iter && iter->next) {
827 break;
828 }
829 } while (iter != stop);
830
831 if (iter == stop) {
832 break;
833 }
834 }
835 iter = iter->next;
836 }
837 break;
838 case LYS_CASE:
839 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100840 if (parent) {
841 start = parent->child;
842 } else {
843 start = module->data;
844 }
845
846 LY_TREE_FOR(start, iter) {
Radek Krejci07911992015-08-14 15:13:31 +0200847 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
848 continue;
849 }
850
Radek Krejci749190d2016-02-18 16:26:25 +0100851 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100852 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200853 return EXIT_FAILURE;
854 }
855 }
856 break;
857 default:
858 /* no check needed */
859 break;
860 }
861
862 return EXIT_SUCCESS;
863}
864
Michal Vasko0d343d12015-08-24 14:57:36 +0200865/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200866int
Radek Krejci10c760e2015-08-14 14:45:43 +0200867lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
868{
Radek Krejci92720552015-10-05 15:28:27 +0200869 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200870 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200871
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200872 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200873
Radek Krejci10c760e2015-08-14 14:45:43 +0200874 if (parent) {
875 type = parent->nodetype;
876 module = parent->module;
877 } else {
878 assert(module);
879 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200880 }
881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200882 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200883 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200884 case LYS_CONTAINER:
885 case LYS_LIST:
886 case LYS_GROUPING:
887 case LYS_USES:
888 case LYS_INPUT:
889 case LYS_OUTPUT:
890 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200891 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200892 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
893 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100894 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200895 return EXIT_FAILURE;
896 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200897
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200898 break;
Radek Krejci76512572015-08-04 09:47:08 +0200899 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200900 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200901 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100902 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200903 return EXIT_FAILURE;
904 }
905 break;
Radek Krejci76512572015-08-04 09:47:08 +0200906 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200907 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200908 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100909 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200910 return EXIT_FAILURE;
911 }
912 break;
Radek Krejci76512572015-08-04 09:47:08 +0200913 case LYS_RPC:
914 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100915 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200916 return EXIT_FAILURE;
917 }
918 break;
Radek Krejci76512572015-08-04 09:47:08 +0200919 case LYS_LEAF:
920 case LYS_LEAFLIST:
921 case LYS_ANYXML:
Radek Krejci48464ed2016-03-17 15:44:09 +0100922 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
923 LOGVAL(LYE_SPEC, LY_VLOG_LYS, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100924 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200925 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200926 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200927 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200928 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
929 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100930 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200931 return EXIT_FAILURE;
932 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200933 break;
934 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200935 /* top level */
936 if (!(child->nodetype &
937 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
938 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100939 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200940 return EXIT_FAILURE;
941 }
942
Radek Krejcic071c542016-01-27 14:57:51 +0100943 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200944 }
945
946 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200947 if (lys_check_id(child, parent, module)) {
948 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200949 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200950
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200951 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200952 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200953 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200954
Radek Krejci10c760e2015-08-14 14:45:43 +0200955 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +0200956 if (module->data) {
957 module->data->prev->next = child;
958 child->prev = module->data->prev;
959 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200960 } else {
Radek Krejci92720552015-10-05 15:28:27 +0200961 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200962 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200963 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200964 if (!parent->child) {
965 /* the only/first child of the parent */
966 parent->child = child;
967 child->parent = parent;
968 iter = child;
969 } else {
970 /* add a new child at the end of parent's child list */
971 iter = parent->child->prev;
972 iter->next = child;
973 child->prev = iter;
974 }
975 while (iter->next) {
976 iter = iter->next;
977 iter->parent = parent;
978 }
979 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200980 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200981
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200982 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200983}
984
Michal Vasko1e62a092015-12-01 12:27:20 +0100985API const struct lys_module *
Radek Krejci722b0072016-02-01 17:09:45 +0100986lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200987{
Radek Krejci0b5805d2015-08-13 09:38:02 +0200988 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200989
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200990 if (!ctx || !data) {
991 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
992 return NULL;
993 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200994
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200995 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200996 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +0100997 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200998 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200999 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001000 mod = yang_read_module(ctx, data, 0, NULL, 1);
1001 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001002 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001003 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001004 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001005 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001006
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001007 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001008}
1009
Michal Vasko5a721fd2016-02-16 12:16:48 +01001010struct lys_submodule *
1011lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001012{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001013 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001014
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001015 assert(module);
1016 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001017
Radek Krejcic071c542016-01-27 14:57:51 +01001018 /* get the main module */
Michal Vasko4f0dad02016-02-15 14:08:23 +01001019 module = lys_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001021 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001022 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001023 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001024 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001025 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001026 submod = yang_read_submodule(module, data, 0, unres);
1027 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001028 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001029 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001030 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001031 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001032
Michal Vasko5a721fd2016-02-16 12:16:48 +01001033 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001034}
1035
Michal Vasko1e62a092015-12-01 12:27:20 +01001036API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001037lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1038{
1039 int fd;
1040 const struct lys_module *ret;
1041
1042 if (!ctx || !path) {
1043 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1044 return NULL;
1045 }
1046
1047 fd = open(path, O_RDONLY);
1048 if (fd == -1) {
1049 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1050 return NULL;
1051 }
1052
1053 ret = lys_parse_fd(ctx, fd, format);
1054 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +01001055
Radek Krejcia77904e2016-02-25 16:23:45 +01001056 if (ret && !ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001057 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +01001058 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +01001059 }
1060
Michal Vasko662610a2015-12-07 11:25:45 +01001061 return ret;
1062}
1063
1064API const struct lys_module *
1065lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001066{
Michal Vasko1e62a092015-12-01 12:27:20 +01001067 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001068 struct stat sb;
1069 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001070 char buf[PATH_MAX];
1071 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001072
1073 if (!ctx || fd < 0) {
1074 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1075 return NULL;
1076 }
1077
Radek Krejci10a833c2015-12-16 15:28:37 +01001078 if (fstat(fd, &sb) == -1) {
1079 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1080 return NULL;
1081 }
Radek Krejcib051f722016-02-25 15:12:21 +01001082 if (!S_ISREG(sb.st_mode)) {
1083 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
1084 return NULL;
1085 }
1086
Michal Vasko164d9012016-04-01 10:16:59 +02001087 if (!sb.st_size) {
1088 LOGERR(LY_EINVAL, "File empty.");
1089 return NULL;
1090 }
1091
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001092 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001093 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001094 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001095 return NULL;
1096 }
Radek Krejci722b0072016-02-01 17:09:45 +01001097 module = lys_parse_mem(ctx, addr, format);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001098 munmap(addr, sb.st_size + 2);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001099
Radek Krejcia77904e2016-02-25 16:23:45 +01001100 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001101 /* get URI if there is /proc */
1102 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001103 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1104 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1105 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1106 }
1107 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001108 }
Radek Krejcib051f722016-02-25 15:12:21 +01001109 }
1110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001111 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001112}
1113
Michal Vasko5a721fd2016-02-16 12:16:48 +01001114struct lys_submodule *
1115lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001116{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001117 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001118 struct stat sb;
1119 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001120
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001121 assert(module);
1122 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001123
Radek Krejci10a833c2015-12-16 15:28:37 +01001124 if (fstat(fd, &sb) == -1) {
1125 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001126 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001127 }
Michal Vasko164d9012016-04-01 10:16:59 +02001128
1129 if (!sb.st_size) {
1130 LOGERR(LY_EINVAL, "File empty.");
1131 return NULL;
1132 }
1133
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001134 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001135 if (addr == MAP_FAILED) {
1136 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001137 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001138 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001139 submodule = lys_submodule_parse(module, addr, format, unres);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001140 munmap(addr, sb.st_size + 2);
Radek Krejciefaeba32015-05-27 14:30:57 +02001141
Michal Vasko5a721fd2016-02-16 12:16:48 +01001142 return submodule;
1143
Radek Krejciefaeba32015-05-27 14:30:57 +02001144}
1145
Radek Krejci1d82ef62015-08-07 14:44:40 +02001146static struct lys_restr *
1147lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001148{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001149 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001150 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001151
Radek Krejci3733a802015-06-19 13:43:21 +02001152 if (!size) {
1153 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001154 }
Radek Krejci3733a802015-06-19 13:43:21 +02001155
1156 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001157 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001158 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001159 return NULL;
1160 }
Radek Krejci3733a802015-06-19 13:43:21 +02001161 for (i = 0; i < size; i++) {
1162 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1163 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1164 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1165 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1166 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1167 }
1168
1169 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001170}
1171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001172void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001173lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001174{
1175 assert(ctx);
1176 if (!restr) {
1177 return;
1178 }
1179
1180 lydict_remove(ctx, restr->expr);
1181 lydict_remove(ctx, restr->dsc);
1182 lydict_remove(ctx, restr->ref);
1183 lydict_remove(ctx, restr->eapptag);
1184 lydict_remove(ctx, restr->emsg);
1185}
1186
Michal Vaskob84f88a2015-09-24 13:16:10 +02001187static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001188type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
1189 LY_DATA_TYPE base, struct unres_schema *unres)
1190{
1191 int i;
1192
1193 switch (base) {
1194 case LY_TYPE_BINARY:
1195 if (old->info.binary.length) {
1196 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
1197 }
1198 break;
1199
1200 case LY_TYPE_BITS:
1201 new->info.bits.count = old->info.bits.count;
1202 if (new->info.bits.count) {
1203 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1204 if (!new->info.bits.bit) {
1205 LOGMEM;
1206 return -1;
1207 }
1208 for (i = 0; i < new->info.bits.count; i++) {
1209 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1210 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1211 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1212 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1213 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1214 }
1215 }
1216 break;
1217
1218 case LY_TYPE_DEC64:
1219 new->info.dec64.dig = old->info.dec64.dig;
1220 if (old->info.dec64.range) {
1221 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
1222 }
1223 break;
1224
1225 case LY_TYPE_ENUM:
1226 new->info.enums.count = old->info.enums.count;
1227 if (new->info.enums.count) {
1228 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1229 if (!new->info.enums.enm) {
1230 LOGMEM;
1231 return -1;
1232 }
1233 for (i = 0; i < new->info.enums.count; i++) {
1234 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1235 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1236 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1237 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1238 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
1239 }
1240 }
1241 break;
1242
1243 case LY_TYPE_IDENT:
1244 if (old->info.ident.ref) {
1245 new->info.ident.ref = old->info.ident.ref;
1246 } else {
1247 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
1248 if (i > -1 && unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i])) {
1249 return -1;
1250 }
1251 }
1252 break;
1253
1254 case LY_TYPE_INST:
1255 new->info.inst.req = old->info.inst.req;
1256 break;
1257
1258 case LY_TYPE_INT8:
1259 case LY_TYPE_INT16:
1260 case LY_TYPE_INT32:
1261 case LY_TYPE_INT64:
1262 case LY_TYPE_UINT8:
1263 case LY_TYPE_UINT16:
1264 case LY_TYPE_UINT32:
1265 case LY_TYPE_UINT64:
1266 if (old->info.num.range) {
1267 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
1268 }
1269 break;
1270
1271 case LY_TYPE_LEAFREF:
1272 if (old->info.lref.path) {
1273 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
1274 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent)) {
1275 return -1;
1276 }
1277 }
1278 break;
1279
1280 case LY_TYPE_STRING:
1281 if (old->info.str.length) {
1282 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
1283 }
1284 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
1285 new->info.str.pat_count = old->info.str.pat_count;
1286 break;
1287
1288 case LY_TYPE_UNION:
1289 new->info.uni.count = old->info.uni.count;
1290 if (new->info.uni.count) {
1291 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1292 if (!new->info.uni.types) {
1293 LOGMEM;
1294 return -1;
1295 }
1296 for (i = 0; i < new->info.uni.count; i++) {
1297 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1298 return -1;
1299 }
1300 }
1301 }
1302 break;
1303
1304 default:
1305 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1306 break;
1307 }
1308 return EXIT_SUCCESS;
1309}
1310
1311struct yang_type *
1312lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type, struct unres_schema *unres)
1313{
1314 struct yang_type *new;
1315
1316 new = calloc(1, sizeof *new);
1317 if (!new) {
1318 LOGMEM;
1319 return NULL;
1320 }
1321 new->flags = old->flags;
1322 new->base = old->base;
1323 new->name = strdup(old->name);
1324 new->type = type;
1325 if (!new->name) {
1326 LOGMEM;
1327 goto error;
1328 }
1329 if (type_dup(module, parent, type, old->type, new->base, unres)) {
1330 new->type->base = new->base;
1331 lys_type_free(module->ctx, new->type);
1332 memset(&new->type->info, 0, sizeof new->type->info);
1333 goto error;
1334 }
1335 return new;
1336
1337 error:
1338 free(new);
1339 return NULL;
1340}
1341
1342static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001343lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vaskof02e3742015-08-05 16:27:02 +02001344 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001345{
1346 int i;
1347
Michal Vasko1dca6882015-10-22 14:29:42 +02001348 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001349 new->base = old->base;
1350 new->der = old->der;
1351
Michal Vasko0bd29d12015-08-19 11:45:49 +02001352 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001353 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001354 /* HACK (serious one) for unres */
1355 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001356 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
1357 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, unres);
1358 } else {
1359 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1360 }
Radek Krejcic071c542016-01-27 14:57:51 +01001361 new->parent = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001362 /* all these unres additions can fail even though they did not before */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001363 if (!new->der || unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001364 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001365 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001366 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001367 }
1368
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001369 return type_dup(mod, parent, new, old, new->base, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001370}
1371
1372void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001373lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001374{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001375 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001376
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001377 assert(ctx);
1378 if (!type) {
1379 return;
1380 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001381
Michal Vasko1dca6882015-10-22 14:29:42 +02001382 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001384 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001385 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001386 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001387 free(type->info.binary.length);
1388 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001389 case LY_TYPE_BITS:
1390 for (i = 0; i < type->info.bits.count; i++) {
1391 lydict_remove(ctx, type->info.bits.bit[i].name);
1392 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1393 lydict_remove(ctx, type->info.bits.bit[i].ref);
1394 }
1395 free(type->info.bits.bit);
1396 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001397
1398 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001399 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001400 free(type->info.dec64.range);
1401 break;
1402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001403 case LY_TYPE_ENUM:
1404 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001405 lydict_remove(ctx, type->info.enums.enm[i].name);
1406 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1407 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001408 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001409 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001410 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001411
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001412 case LY_TYPE_INT8:
1413 case LY_TYPE_INT16:
1414 case LY_TYPE_INT32:
1415 case LY_TYPE_INT64:
1416 case LY_TYPE_UINT8:
1417 case LY_TYPE_UINT16:
1418 case LY_TYPE_UINT32:
1419 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001420 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001421 free(type->info.num.range);
1422 break;
1423
Radek Krejcidc4c1412015-06-19 15:39:54 +02001424 case LY_TYPE_LEAFREF:
1425 lydict_remove(ctx, type->info.lref.path);
1426 break;
1427
Radek Krejci3733a802015-06-19 13:43:21 +02001428 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001429 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001430 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001431 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001432 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001433 }
1434 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001435 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001436
Radek Krejcie4c366b2015-07-02 10:11:31 +02001437 case LY_TYPE_UNION:
1438 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001439 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001440 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001441 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001442 break;
1443
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001444 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001445 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001446 break;
1447 }
Radek Krejci5a065542015-05-22 15:02:07 +02001448}
1449
Radek Krejci1d82ef62015-08-07 14:44:40 +02001450static void
1451lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001452{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001453 assert(ctx);
1454 if (!tpdf) {
1455 return;
1456 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001458 lydict_remove(ctx, tpdf->name);
1459 lydict_remove(ctx, tpdf->dsc);
1460 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001461
Radek Krejci1d82ef62015-08-07 14:44:40 +02001462 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001463
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001464 lydict_remove(ctx, tpdf->units);
1465 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001466}
1467
Michal Vaskob84f88a2015-09-24 13:16:10 +02001468static struct lys_tpdf *
1469lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1470{
1471 struct lys_tpdf *result;
1472 int i, j;
1473
1474 if (!size) {
1475 return NULL;
1476 }
1477
1478 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001479 if (!result) {
1480 LOGMEM;
1481 return NULL;
1482 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001483 for (i = 0; i < size; i++) {
1484 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1485 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1486 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1487 result[i].flags = old[i].flags;
1488 result[i].module = old[i].module;
1489
1490 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1491 for (j = 0; j <= i; ++j) {
1492 lys_tpdf_free(mod->ctx, &result[j]);
1493 }
1494 free(result);
1495 return NULL;
1496 }
1497
1498 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1499 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1500 }
1501
1502 return result;
1503}
1504
Radek Krejci1d82ef62015-08-07 14:44:40 +02001505static struct lys_when *
1506lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001507{
Radek Krejci76512572015-08-04 09:47:08 +02001508 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001509
1510 if (!old) {
1511 return NULL;
1512 }
1513
1514 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001515 if (!new) {
1516 LOGMEM;
1517 return NULL;
1518 }
Radek Krejci00768f42015-06-18 17:04:04 +02001519 new->cond = lydict_insert(ctx, old->cond, 0);
1520 new->dsc = lydict_insert(ctx, old->dsc, 0);
1521 new->ref = lydict_insert(ctx, old->ref, 0);
1522
1523 return new;
1524}
1525
Michal Vasko0308dd62015-10-07 09:14:40 +02001526void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001527lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001528{
1529 if (!w) {
1530 return;
1531 }
1532
1533 lydict_remove(ctx, w->cond);
1534 lydict_remove(ctx, w->dsc);
1535 lydict_remove(ctx, w->ref);
1536
1537 free(w);
1538}
1539
Radek Krejcib7f5e412015-08-13 10:15:51 +02001540static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001541lys_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 +02001542{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001543 struct lys_node *next, *sub;
1544
Radek Krejcic071c542016-01-27 14:57:51 +01001545 /* children from a resolved augment are freed under the target node */
1546 if (!aug.target) {
1547 LY_TREE_FOR_SAFE(aug.child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001548 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001549 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001550 }
1551
Radek Krejcib7f5e412015-08-13 10:15:51 +02001552 lydict_remove(ctx, aug.target_name);
1553 lydict_remove(ctx, aug.dsc);
1554 lydict_remove(ctx, aug.ref);
1555
1556 free(aug.features);
1557
1558 lys_when_free(ctx, aug.when);
1559
Michal Vasko7d356a52015-08-19 15:06:31 +02001560 /* Do not free the children, they were appended somewhere and their
1561 * new parent will take care of them.
1562 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001563}
1564
Radek Krejci76512572015-08-04 09:47:08 +02001565static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001566lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001567{
Radek Krejci76512572015-08-04 09:47:08 +02001568 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001569 struct lys_node *old_child, *new_child;
1570 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001572 if (!size) {
1573 return NULL;
1574 }
Radek Krejci106efc02015-06-10 14:36:27 +02001575
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001576 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001577 if (!new) {
1578 LOGMEM;
1579 return NULL;
1580 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001581 for (i = 0; i < size; i++) {
1582 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1583 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1584 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1585 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001586 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001587 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001588
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001589 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001590 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1591 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001592 LOGINT;
1593 free(new);
1594 return NULL;
1595 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001596 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001597
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001598 /* Correct the augment nodes.
1599 * This function can only be called from lys_node_dup() with uses
1600 * being the node duplicated, so we must have a case of grouping
1601 * with a uses with augments. The augmented nodes have already been
1602 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001603 * (it was set to their actual data parent, not an augment), and
1604 * the new augment does not have child pointer to its augment nodes,
1605 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001606 */
1607 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001608 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001609 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001610 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001611 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001612 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001613 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001614 LY_TREE_FOR(old[i].child, old_child) {
1615 /* all augment nodes were connected as siblings, there can be no more after this */
1616 if (old_child->parent != (struct lys_node *)&old[i]) {
1617 break;
1618 }
1619
Radek Krejci749190d2016-02-18 16:26:25 +01001620 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001621
1622 new_child->parent = (struct lys_node *)&new[i];
1623 new_child = new_child->next;
1624 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001625 }
Radek Krejci106efc02015-06-10 14:36:27 +02001626
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001627 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001628}
1629
Radek Krejci76512572015-08-04 09:47:08 +02001630static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001631lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001632{
Radek Krejci76512572015-08-04 09:47:08 +02001633 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001634 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001635
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001636 if (!size) {
1637 return NULL;
1638 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001640 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001641 if (!result) {
1642 LOGMEM;
1643 return NULL;
1644 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001645 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001646 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001647 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1648 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001649 result[i].flags = old[i].flags;
1650 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001651
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001652 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001653 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001654
Radek Krejci76512572015-08-04 09:47:08 +02001655 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001656 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001657 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001658 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001659 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001660 result[i].mod.list = old[i].mod.list;
1661 }
1662 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001663
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001664 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001665}
1666
Radek Krejci1d82ef62015-08-07 14:44:40 +02001667static void
1668lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001669{
Radek Krejcia52656e2015-08-05 13:41:50 +02001670 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001672 assert(ctx);
1673 if (!ident) {
1674 return;
1675 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001676
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001677 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001678 * if caller free only a single data model which is used (its identity is
1679 * reference from identity in another module), this silly freeing can lead
1680 * to segmentation fault. But without noting if the module is used by some
1681 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001682 *
1683 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001684 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001685 */
1686 while (ident->der) {
1687 der = ident->der;
1688 ident->der = der->next;
1689 free(der);
1690 }
Radek Krejci6793db02015-05-22 17:49:54 +02001691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001692 lydict_remove(ctx, ident->name);
1693 lydict_remove(ctx, ident->dsc);
1694 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001695
1696}
1697
Radek Krejci1d82ef62015-08-07 14:44:40 +02001698static void
1699lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001700{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001701 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001702
Radek Krejcid12f57b2015-08-06 10:43:39 +02001703 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001704 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001705 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001706 }
1707 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001708}
1709
Radek Krejci1d82ef62015-08-07 14:44:40 +02001710static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001711lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1712{
1713 int i;
1714
1715 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1716 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001717 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001718 }
1719 free(io->tpdf);
1720}
1721
Radek Krejci1d82ef62015-08-07 14:44:40 +02001722static void
1723lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001724{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001725 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001727 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001728 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001729 }
1730 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001731
Radek Krejci1d82ef62015-08-07 14:44:40 +02001732 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001733}
1734
Radek Krejci1d82ef62015-08-07 14:44:40 +02001735static void
1736lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001737{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001738 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001739
Radek Krejci46c4cd72016-01-21 15:13:52 +01001740 if (leaf->child) {
1741 /* leafref backlinks */
1742 ly_set_free((struct ly_set *)leaf->child);
1743 }
1744
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001745 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001746 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001747 }
1748 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001749
Radek Krejci1d82ef62015-08-07 14:44:40 +02001750 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001751
Radek Krejci1d82ef62015-08-07 14:44:40 +02001752 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001753 lydict_remove(ctx, leaf->units);
1754 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001755}
1756
Radek Krejci1d82ef62015-08-07 14:44:40 +02001757static void
1758lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001759{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001760 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001761
Radek Krejci46c4cd72016-01-21 15:13:52 +01001762 if (llist->child) {
1763 /* leafref backlinks */
1764 ly_set_free((struct ly_set *)llist->child);
1765 }
1766
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001767 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001768 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001769 }
1770 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001771
Radek Krejci1d82ef62015-08-07 14:44:40 +02001772 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001773
Radek Krejci1d82ef62015-08-07 14:44:40 +02001774 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001775 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001776}
1777
Radek Krejci1d82ef62015-08-07 14:44:40 +02001778static void
1779lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001780{
Radek Krejci581ce772015-11-10 17:22:40 +01001781 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001782
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001783 /* handle only specific parts for LY_NODE_LIST */
1784 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001785 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001786 }
1787 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001789 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001790 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001791 }
1792 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001793
Radek Krejci1d82ef62015-08-07 14:44:40 +02001794 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001795
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001797 for (j = 0; j > list->unique[i].expr_size; j++) {
1798 lydict_remove(ctx, list->unique[i].expr[j]);
1799 }
1800 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001801 }
1802 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001803
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001804 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001805}
1806
Radek Krejci1d82ef62015-08-07 14:44:40 +02001807static void
1808lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001809{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001810 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001812 /* handle only specific parts for LY_NODE_CONTAINER */
1813 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001815 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001816 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001817 }
1818 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001819
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001820 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001821 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001822 }
1823 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001824
Radek Krejci1d82ef62015-08-07 14:44:40 +02001825 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001826}
1827
Radek Krejci1d82ef62015-08-07 14:44:40 +02001828static void
1829lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001830{
1831 lydict_remove(ctx, f->name);
1832 lydict_remove(ctx, f->dsc);
1833 lydict_remove(ctx, f->ref);
1834 free(f->features);
1835}
1836
Radek Krejci1d82ef62015-08-07 14:44:40 +02001837static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001838lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001839{
Radek Krejci581ce772015-11-10 17:22:40 +01001840 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001841 struct ly_ctx *ctx;
1842 struct lys_node *next, *elem;
1843
1844 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001845
1846 lydict_remove(ctx, dev->target_name);
1847 lydict_remove(ctx, dev->dsc);
1848 lydict_remove(ctx, dev->ref);
1849
Michal Vaskoff006c12016-02-17 11:15:19 +01001850 /* the module was freed, but we only need the context from orig_node, use ours */
1851 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1852 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1853 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1854 elem->module = module;
1855
1856 LY_TREE_DFS_END(dev->orig_node, next, elem);
1857 }
1858 lys_node_free(dev->orig_node, NULL, 0);
1859 } else {
1860 /* it's just a shallow copy, freeing one node */
1861 dev->orig_node->module = module;
1862 lys_node_free(dev->orig_node, NULL, 1);
1863 }
1864
Radek Krejcieb00f512015-07-01 16:44:58 +02001865 for (i = 0; i < dev->deviate_size; i++) {
1866 lydict_remove(ctx, dev->deviate[i].dflt);
1867 lydict_remove(ctx, dev->deviate[i].units);
1868
1869 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1870 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001871 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001872 }
1873 free(dev->deviate[i].must);
1874
1875 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001876 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1877 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1878 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01001879 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001880 }
1881 free(dev->deviate[i].unique);
1882 }
1883 }
1884 free(dev->deviate);
1885}
1886
Radek Krejci1d82ef62015-08-07 14:44:40 +02001887static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001888lys_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 +02001889{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001890 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001891
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001892 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001893 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001894 lydict_remove(ctx, uses->refine[i].dsc);
1895 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001896
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001897 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001898 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001899 }
1900 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001901
Radek Krejci76512572015-08-04 09:47:08 +02001902 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001903 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001904 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001905 lydict_remove(ctx, uses->refine[i].mod.presence);
1906 }
1907 }
1908 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001910 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001911 lys_augment_free(ctx, uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001912 }
1913 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001914
Radek Krejci1d82ef62015-08-07 14:44:40 +02001915 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001916}
1917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001918void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001919lys_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 +02001920{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001921 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001922 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001924 if (!node) {
1925 return;
1926 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001928 assert(node->module);
1929 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001930
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001931 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001932
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001933 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01001934 if (node->priv && private_destructor) {
1935 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001936 }
1937
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001938 /* common part */
Radek Krejcid12f57b2015-08-06 10:43:39 +02001939 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1940 free(node->features);
1941 lydict_remove(ctx, node->name);
1942 lydict_remove(ctx, node->dsc);
1943 lydict_remove(ctx, node->ref);
1944 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001945
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001946 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001947 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001948 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001949 }
1950 }
1951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001952 /* specific part */
1953 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001954 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001955 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001956 break;
Radek Krejci76512572015-08-04 09:47:08 +02001957 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001958 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001959 break;
Radek Krejci76512572015-08-04 09:47:08 +02001960 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001961 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001962 break;
Radek Krejci76512572015-08-04 09:47:08 +02001963 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001964 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001965 break;
Radek Krejci76512572015-08-04 09:47:08 +02001966 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001967 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001968 break;
Radek Krejci76512572015-08-04 09:47:08 +02001969 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001970 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001971 break;
Radek Krejci76512572015-08-04 09:47:08 +02001972 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001973 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001974 break;
Radek Krejci76512572015-08-04 09:47:08 +02001975 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001976 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001977 break;
Radek Krejci76512572015-08-04 09:47:08 +02001978 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001979 /* do nothing */
1980 break;
Radek Krejci76512572015-08-04 09:47:08 +02001981 case LYS_GROUPING:
1982 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001983 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001984 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001985 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001986
1987 case LYS_INPUT:
1988 case LYS_OUTPUT:
1989 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1990 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001991 case LYS_UNKNOWN:
1992 LOGINT;
1993 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001994 }
Radek Krejci5a065542015-05-22 15:02:07 +02001995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001996 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001997 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001998 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001999}
2000
Michal Vasko1e62a092015-12-01 12:27:20 +01002001const struct lys_module *
2002lys_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 +02002003{
Radek Krejcic071c542016-01-27 14:57:51 +01002004 const struct lys_module *main_module;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002005 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002006
Michal Vaskoa7789a82016-02-11 15:42:55 +01002007 assert(!prefix || !name);
2008
Michal Vaskob6729c62015-10-21 12:09:47 +02002009 if (prefix && !pref_len) {
2010 pref_len = strlen(prefix);
2011 }
2012 if (name && !name_len) {
2013 name_len = strlen(name);
2014 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002015
Michal Vasko4f0dad02016-02-15 14:08:23 +01002016 main_module = lys_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002017
2018 /* module own prefix, submodule own prefix, (sub)module own name */
2019 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2020 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002021 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002022 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002023 }
2024
Michal Vasko8ce24d72015-10-21 11:27:26 +02002025 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002026 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2027 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002028 return module->imp[i].module;
2029 }
2030 }
2031
2032 return NULL;
2033}
2034
Michal Vasko13b15832015-08-19 11:04:48 +02002035/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002036static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002037module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002038{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002039 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002040 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002041 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002042
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002043 assert(module->ctx);
2044 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002045
Michal Vaskob746fff2016-02-11 11:37:50 +01002046 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002047 for (i = 0; i < module->imp_size; i++) {
Radek Krejci4f78b532016-02-17 13:43:00 +01002048 if (!module->imp[i].external) {
2049 lydict_remove(ctx, module->imp[i].prefix);
2050 }
Radek Krejci225376f2016-02-16 17:36:22 +01002051 }
Radek Krejcidce51452015-06-16 15:20:08 +02002052 free(module->imp);
2053
Radek Krejcic071c542016-01-27 14:57:51 +01002054 /* submodules don't have data tree, the data nodes
2055 * are placed in the main module altogether */
2056 if (!module->type) {
2057 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002058 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002059 }
Radek Krejci21181962015-06-30 14:11:00 +02002060 }
Radek Krejci5a065542015-05-22 15:02:07 +02002061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002062 lydict_remove(ctx, module->dsc);
2063 lydict_remove(ctx, module->ref);
2064 lydict_remove(ctx, module->org);
2065 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002066 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002067
Radek Krejcieb00f512015-07-01 16:44:58 +02002068 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002069 for (i = 0; i < module->rev_size; i++) {
2070 lydict_remove(ctx, module->rev[i].dsc);
2071 lydict_remove(ctx, module->rev[i].ref);
2072 }
2073 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002074
Radek Krejcieb00f512015-07-01 16:44:58 +02002075 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002077 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002078 }
2079 module->ident_size = 0;
2080 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002081
Radek Krejcieb00f512015-07-01 16:44:58 +02002082 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002083 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002084 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002085 }
2086 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002087
Radek Krejcieb00f512015-07-01 16:44:58 +02002088 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002089 for (i = 0; i < module->inc_size; i++) {
Radek Krejcic071c542016-01-27 14:57:51 +01002090 /* complete submodule free is done only from main module since
2091 * submodules propagate their includes to the main module */
2092 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002093 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002094 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002095 }
2096 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002097
Radek Krejcieb00f512015-07-01 16:44:58 +02002098 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002099 for (i = 0; i < module->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002100 lys_augment_free(ctx, module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002101 }
2102 free(module->augment);
2103
Radek Krejcieb00f512015-07-01 16:44:58 +02002104 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002105 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002106 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002107 }
2108 free(module->features);
2109
Radek Krejcieb00f512015-07-01 16:44:58 +02002110 /* deviations */
2111 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002112 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002113 }
2114 free(module->deviation);
2115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002117 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002118}
2119
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120void
Michal Vaskob746fff2016-02-11 11:37:50 +01002121lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002122{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002123 if (!submodule) {
2124 return;
2125 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002128 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002129
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002130 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002132 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002133}
2134
Radek Krejci76512572015-08-04 09:47:08 +02002135struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002136lys_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 +01002137 uint8_t nacm, struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002138{
Radek Krejcic071c542016-01-27 14:57:51 +01002139 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002141 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002142
Michal Vaskoc07187d2015-08-13 15:20:57 +02002143 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002144 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002145 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002146 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002147 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002148 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002149 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002150 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002151 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002152 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002153 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002154 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002155 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002156 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002157 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002158 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002159 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002160 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002161 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002162 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002163 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002164 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002165 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002166 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002167
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002168 /* we cannot just duplicate memory since the strings are stored in
2169 * dictionary and we need to update dictionary counters.
2170 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002171
Radek Krejci1d82ef62015-08-07 14:44:40 +02002172 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002173 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002174 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002175 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 break;
2177
Radek Krejci76512572015-08-04 09:47:08 +02002178 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002180 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002181 break;
2182
Radek Krejci76512572015-08-04 09:47:08 +02002183 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002184 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002185 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002186 break;
2187
Radek Krejci76512572015-08-04 09:47:08 +02002188 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002190 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002191 break;
2192
Radek Krejci76512572015-08-04 09:47:08 +02002193 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002195 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 break;
2197
Radek Krejci76512572015-08-04 09:47:08 +02002198 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002200 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002201 break;
2202
Radek Krejci76512572015-08-04 09:47:08 +02002203 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002204 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002205 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002206 break;
2207
Radek Krejci76512572015-08-04 09:47:08 +02002208 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002210 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002211 break;
2212
Radek Krejci76512572015-08-04 09:47:08 +02002213 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002214 grp = calloc(1, sizeof *grp);
2215 retval = (struct lys_node *)grp;
2216 break;
2217
Radek Krejci76512572015-08-04 09:47:08 +02002218 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002219 rpc = calloc(1, sizeof *rpc);
2220 retval = (struct lys_node *)rpc;
2221 break;
2222
Radek Krejci76512572015-08-04 09:47:08 +02002223 case LYS_INPUT:
2224 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002225 io = calloc(1, sizeof *io);
2226 retval = (struct lys_node *)io;
2227 break;
2228
Radek Krejci76512572015-08-04 09:47:08 +02002229 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002230 ntf = calloc(1, sizeof *ntf);
2231 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002232 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002235 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002236 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 }
Radek Krejcib388c152015-06-04 17:03:03 +02002238
Michal Vasko253035f2015-12-17 16:58:13 +01002239 if (!retval) {
2240 LOGMEM;
2241 return NULL;
2242 }
2243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 /*
2245 * duplicate generic part of the structure
2246 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002247 retval->name = lydict_insert(ctx, node->name, 0);
2248 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2249 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002250 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002251 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002252 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002254 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002255 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002258 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002259
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002261
Radek Krejci1d82ef62015-08-07 14:44:40 +02002262 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002263 retval->features = calloc(retval->features_size, sizeof *retval->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002264 if (!retval->features) {
2265 LOGMEM;
2266 goto error;
2267 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002268
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002269 if (!shallow) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002270 for (i = 0; i < node->features_size; ++i) {
2271 retval->features[i] = (struct lys_feature *)retval;
2272 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
2273 retval->features[i] = node->features[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002274 }
2275 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002276
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002277 /* connect it to the parent */
2278 if (lys_node_addchild(parent, retval->module, retval)) {
2279 goto error;
2280 }
Radek Krejcidce51452015-06-16 15:20:08 +02002281
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002282 /* go recursively */
2283 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2284 LY_TREE_FOR(node->child, child) {
2285 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres, 0)) {
2286 goto error;
2287 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002288 }
2289 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002290 } else {
2291 memcpy(retval->features, node->features, retval->features_size * sizeof *retval->features);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 }
2293
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002294 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002295 * duplicate specific part of the structure
2296 */
2297 switch (node->nodetype) {
2298 case LYS_CONTAINER:
2299 if (cont_orig->when) {
2300 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002301 }
2302 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 cont->must_size = cont_orig->must_size;
2305 cont->tpdf_size = cont_orig->tpdf_size;
2306
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002307 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002308 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
2309 break;
2310
2311 case LYS_CHOICE:
2312 if (choice_orig->when) {
2313 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314 }
2315
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002316 if (!shallow) {
2317 if (choice_orig->dflt) {
2318 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0, LYS_ANYXML
2319 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
2320 | LYS_LIST, (const struct lys_node **)&choice->dflt);
2321 if (rc) {
2322 if (rc == EXIT_FAILURE) {
2323 LOGINT;
2324 }
2325 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002326 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002327 } else {
2328 /* useless to check return value, we don't know whether
2329 * there really wasn't any default defined or it just hasn't
2330 * been resolved, we just hope for the best :)
2331 */
2332 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002333 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002335 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002336 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 break;
2338
2339 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002340 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2341 goto error;
2342 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002343 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2344
2345 if (leaf_orig->dflt) {
2346 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci48464ed2016-03-17 15:44:09 +01002347 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002348 goto error;
2349 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002350 }
2351
2352 leaf->must_size = leaf_orig->must_size;
2353 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002354
2355 if (leaf_orig->when) {
2356 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002357 }
2358 break;
2359
2360 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002361 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2362 goto error;
2363 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002364 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2365
2366 llist->min = llist_orig->min;
2367 llist->max = llist_orig->max;
2368
2369 llist->must_size = llist_orig->must_size;
2370 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002371
2372 if (llist_orig->when) {
2373 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 }
2375 break;
2376
2377 case LYS_LIST:
2378 list->min = list_orig->min;
2379 list->max = list_orig->max;
2380
2381 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002382 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383
Radek Krejci581ce772015-11-10 17:22:40 +01002384 list->tpdf_size = list_orig->tpdf_size;
Michal Vasko0ea41032015-06-16 08:53:55 +02002385 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002386
Radek Krejci581ce772015-11-10 17:22:40 +01002387 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002388 if (list->keys_size) {
2389 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002390 if (!list->keys) {
2391 LOGMEM;
2392 goto error;
2393 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002394
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002395 if (!shallow) {
2396 /* we managed to resolve it before, resolve it again manually */
2397 if (list_orig->keys[0]) {
2398 for (i = 0; i < list->keys_size; ++i) {
2399 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2400 (const struct lys_node **)&list->keys[i]);
2401 if (rc) {
2402 if (rc == EXIT_FAILURE) {
2403 LOGINT;
2404 }
2405 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002406 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002407 }
2408 /* it was not resolved yet, add unres copy */
2409 } else {
2410 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2411 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002412 goto error;
2413 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002414 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002415 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002416 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002417 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002418 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002419
Radek Krejci581ce772015-11-10 17:22:40 +01002420 list->unique_size = list_orig->unique_size;
2421 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002422 if (!list->unique) {
2423 LOGMEM;
2424 goto error;
2425 }
Radek Krejci581ce772015-11-10 17:22:40 +01002426 for (i = 0; i < list->unique_size; ++i) {
2427 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2428 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002429 if (!list->unique[i].expr) {
2430 LOGMEM;
2431 goto error;
2432 }
Radek Krejci581ce772015-11-10 17:22:40 +01002433 for (j = 0; j < list->unique[i].expr_size; j++) {
2434 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2435
2436 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002437 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002438 }
2439 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002441 if (list_orig->when) {
2442 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002443 }
Radek Krejcidce51452015-06-16 15:20:08 +02002444 break;
2445
2446 case LYS_ANYXML:
2447 anyxml->must_size = anyxml_orig->must_size;
2448 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002449
2450 if (anyxml_orig->when) {
2451 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002452 }
2453 break;
2454
2455 case LYS_USES:
2456 uses->grp = uses_orig->grp;
2457
2458 if (uses_orig->when) {
2459 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002460 }
2461
2462 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002463 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002464 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002465 if (!shallow) {
2466 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
2467 if (!uses->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002468 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002469 goto error;
2470 }
Michal Vasko49168a22015-08-17 16:35:41 +02002471 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002472 } else {
2473 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002474 }
2475 break;
2476
Radek Krejcidce51452015-06-16 15:20:08 +02002477 case LYS_CASE:
2478 if (cs_orig->when) {
2479 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002480 }
2481 break;
2482
2483 case LYS_GROUPING:
2484 grp->tpdf_size = grp_orig->tpdf_size;
2485 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
2486 break;
2487
2488 case LYS_RPC:
2489 rpc->tpdf_size = rpc_orig->tpdf_size;
2490 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
2491 break;
2492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002493 case LYS_INPUT:
2494 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002495 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002496 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
2497 break;
2498
Radek Krejcida04f4a2015-05-21 12:54:09 +02002499 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002500 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002501 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejci7e97c352015-06-19 16:26:34 +02002502 break;
2503
2504 default:
2505 /* LY_NODE_AUGMENT */
2506 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002507 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002508 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002509
2510 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002511
2512error:
2513
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002514 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002515 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002516}
2517
Michal Vasko13b15832015-08-19 11:04:48 +02002518void
Michal Vaskoff006c12016-02-17 11:15:19 +01002519lys_node_switch(struct lys_node *dst, struct lys_node *src)
2520{
2521 struct lys_node *child;
2522
2523 assert((dst->module == src->module) && (dst->name == src->name) && (dst->nodetype == src->nodetype));
2524
2525 /* sibling next */
2526 if (dst->prev != dst) {
2527 dst->prev->next = src;
2528 }
2529
2530 /* sibling prev */
2531 if (dst->next) {
2532 dst->next->prev = src;
2533 }
2534
2535 /* parent child prev */
2536 if (!dst->next && dst->parent) {
2537 dst->parent->child->prev = src;
2538 }
2539
2540 /* next */
2541 src->next = dst->next;
2542 dst->next = NULL;
2543
2544 /* prev */
2545 if (dst->prev != dst) {
2546 src->prev = dst->prev;
2547 }
2548 dst->prev = dst;
2549
2550 /* parent child */
2551 if (dst->parent && (dst->parent->child == dst)) {
2552 dst->parent->child = src;
2553 }
2554
2555 /* parent */
2556 src->parent = dst->parent;
2557 dst->parent = NULL;
2558
2559 /* child parent */
2560 LY_TREE_FOR(dst->child, child) {
2561 if (child->parent == dst) {
2562 child->parent = src;
2563 }
2564 }
2565
2566 /* child */
2567 src->child = dst->child;
2568 dst->child = NULL;
2569}
2570
2571void
Michal Vasko627975a2016-02-11 11:39:03 +01002572lys_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 +02002573{
2574 struct ly_ctx *ctx;
2575 int i;
2576
2577 if (!module) {
2578 return;
2579 }
2580
2581 /* remove schema from the context */
2582 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002583 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002584 for (i = 0; i < ctx->models.used; i++) {
2585 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002586 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002587 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002588 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 +02002589 ctx->models.list[ctx->models.used] = NULL;
2590 /* we are done */
2591 break;
2592 }
2593 }
2594 }
2595
2596 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002597 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002598
2599 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002600 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002601
2602 free(module);
2603}
Radek Krejci7e97c352015-06-19 16:26:34 +02002604
2605/*
2606 * op: 1 - enable, 0 - disable
2607 */
2608static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002609lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002610{
2611 int all = 0;
2612 int i, j, k;
2613
2614 if (!module || !name || !strlen(name)) {
2615 return EXIT_FAILURE;
2616 }
2617
2618 if (!strcmp(name, "*")) {
2619 /* enable all */
2620 all = 1;
2621 }
2622
2623 /* module itself */
2624 for (i = 0; i < module->features_size; i++) {
2625 if (all || !strcmp(module->features[i].name, name)) {
2626 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002627 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002628 /* enable referenced features (recursion) */
2629 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002630 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002631 module->features[i].features[k]->name, op);
2632 }
2633 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002634 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002635 }
2636 if (!all) {
2637 return EXIT_SUCCESS;
2638 }
2639 }
2640 }
2641
2642 /* submodules */
2643 for (j = 0; j < module->inc_size; j++) {
2644 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2645 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2646 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002647 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002648 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002649 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002650 }
2651 if (!all) {
2652 return EXIT_SUCCESS;
2653 }
2654 }
2655 }
2656 }
2657
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002658 /* TODO submodules of submodules ... */
2659
Radek Krejci7e97c352015-06-19 16:26:34 +02002660 if (all) {
2661 return EXIT_SUCCESS;
2662 } else {
2663 return EXIT_FAILURE;
2664 }
2665}
2666
2667API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002668lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002669{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002670 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002671}
2672
2673API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002674lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002675{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002676 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002677}
2678
2679API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002680lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002681{
2682 int i, j;
2683
2684 if (!module || !feature) {
2685 return -1;
2686 }
2687
2688 /* search for the specified feature */
2689 /* module itself */
2690 for (i = 0; i < module->features_size; i++) {
2691 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002692 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002693 return 1;
2694 } else {
2695 return 0;
2696 }
2697 }
2698 }
2699
2700 /* submodules */
2701 for (j = 0; j < module->inc_size; j++) {
2702 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2703 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002704 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002705 return 1;
2706 } else {
2707 return 0;
2708 }
2709 }
2710 }
2711 }
2712
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002713 /* feature definition not found */
2714 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002715}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002716
Radek Krejci96a10da2015-07-30 11:00:14 +02002717API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002718lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002719{
Radek Krejci96a10da2015-07-30 11:00:14 +02002720 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002721 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002722 unsigned int count;
2723
2724 if (!module) {
2725 return NULL;
2726 }
2727
2728 count = module->features_size;
2729 for (i = 0; i < module->inc_size; i++) {
2730 count += module->inc[i].submodule->features_size;
2731 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002732 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002733 if (!result) {
2734 LOGMEM;
2735 return NULL;
2736 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002737 if (states) {
2738 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002739 if (!(*states)) {
2740 LOGMEM;
2741 free(result);
2742 return NULL;
2743 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002744 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002745 count = 0;
2746
2747 /* module itself */
2748 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002749 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002750 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002751 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002752 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002753 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002754 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002755 }
2756 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002757 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002758 }
2759
2760 /* submodules */
2761 for (j = 0; j < module->inc_size; j++) {
2762 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002763 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002764 if (states) {
2765 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2766 (*states)[count] = 1;
2767 } else {
2768 (*states)[count] = 0;
2769 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002770 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002771 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002772 }
2773 }
2774
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002775 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002776 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002777
2778 return result;
2779}
Michal Vaskobaefb032015-09-24 14:52:10 +02002780
Radek Krejcic071c542016-01-27 14:57:51 +01002781struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002782lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002783{
2784 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2785}
2786
Michal Vasko320e8532016-02-15 13:11:57 +01002787struct lys_module *
2788lys_module(const struct lys_module *module)
2789{
2790 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2791}
2792
Michal Vaskobaefb032015-09-24 14:52:10 +02002793API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002794lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002795{
2796 if (!node || !node->parent) {
2797 return NULL;
2798 }
2799
2800 if (node->parent->nodetype == LYS_AUGMENT) {
2801 return ((struct lys_node_augment *)node->parent)->target;
2802 }
2803
2804 return node->parent;
2805}
Michal Vasko1b229152016-01-13 11:28:38 +01002806
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002807API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002808lys_set_private(const struct lys_node *node, void *priv)
2809{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002810 void *prev;
2811
Michal Vasko1b229152016-01-13 11:28:38 +01002812 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002813 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2814 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002815 }
2816
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002817 prev = node->priv;
2818 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002819
2820 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002821}