blob: 6fa1b965e04af7036511532ae9d97b2937585432 [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 *
Michal Vasko53b7da02018-02-13 15:28:42 +01006 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
Radek Krejcida04f4a2015-05-21 12:54:09 +02007 *
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
Michal Vaskob0bbf5f2018-02-16 09:35:59 +010017#ifdef __APPLE__
18# include <sys/param.h>
19#endif
Radek Krejci812b10a2015-05-28 16:48:25 +020020#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020021#include <ctype.h>
Radek Krejcib051f722016-02-25 15:12:21 +010022#include <limits.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020023#include <stdlib.h>
24#include <sys/mman.h>
Michal Vasko662610a2015-12-07 11:25:45 +010025#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020026#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010027#include <fcntl.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020028#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010029#include <unistd.h>
30#include <errno.h>
Radek Krejci72cdfac2018-08-15 14:47:33 +020031#include <dirent.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020032
33#include "common.h"
34#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020035#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020036#include "resolve.h"
Michal Vasko88c29542015-11-27 14:57:53 +010037#include "xml.h"
Michal Vasko5b3492c2016-07-20 09:37:40 +020038#include "xpath.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020039#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020040#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020041#include "validation.h"
Pavol Vicanf7cc2852016-03-22 23:27:35 +010042#include "parser_yang.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020043
Radek Krejci8d6b7422017-02-03 14:42:13 +010044static int lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci5138e9f2017-04-12 13:10:46 +020045 int in_grp, int shallow, struct unres_schema *unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020046
Radek Krejci65aca412018-01-24 11:23:06 +010047API const struct lys_node_list *
48lys_is_key(const struct lys_node_leaf *node, uint8_t *index)
49{
50 struct lys_node *parent = (struct lys_node *)node;
51 struct lys_node_list *list;
52 uint8_t i;
53
54 if (!node || node->nodetype != LYS_LEAF) {
55 return NULL;
56 }
57
58 do {
59 parent = lys_parent(parent);
60 } while (parent && parent->nodetype == LYS_USES);
61
62 if (!parent || parent->nodetype != LYS_LIST) {
63 return NULL;
64 }
65
66 list = (struct lys_node_list*)parent;
67 for (i = 0; i < list->keys_size; i++) {
68 if (list->keys[i] == node) {
69 if (index) {
70 (*index) = i;
71 }
72 return list;
73 }
74 }
75 return NULL;
76}
77
Radek Krejci9ff0a922016-07-14 13:08:05 +020078API const struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +010079lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020080{
Radek Krejci9ff0a922016-07-14 13:08:05 +020081 int i;
Radek Krejci48061fb2015-08-05 15:41:07 +020082
Radek Krejci27fe55e2016-09-13 17:13:35 +020083 if (!node) {
84 return NULL;
85 }
86
Radek Krejci48061fb2015-08-05 15:41:07 +020087check:
88 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
89 /* input/output does not have if-feature, so skip them */
90
91 /* check local if-features */
Michal Vaskoc5c26b02016-06-29 11:10:29 +020092 for (i = 0; i < node->iffeature_size; i++) {
Radek Krejci69b8d922016-07-27 13:13:41 +020093 if (!resolve_iffeature(&node->iffeature[i])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +020094 return node;
Radek Krejci48061fb2015-08-05 15:41:07 +020095 }
96 }
97 }
98
99 if (!recursive) {
100 return NULL;
101 }
102
103 /* go through parents */
104 if (node->nodetype == LYS_AUGMENT) {
105 /* go to parent actually means go to the target node */
106 node = ((struct lys_node_augment *)node)->target;
Michal Vasko17549192017-03-13 10:19:33 +0100107 if (!node) {
108 /* unresolved augment, let's say it's enabled */
109 return NULL;
110 }
Radek Krejci48061fb2015-08-05 15:41:07 +0200111 } else if (node->parent) {
112 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +0200113 } else {
114 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +0200115 }
116
Radek Krejci074bf852015-08-19 14:22:16 +0200117 if (recursive == 2) {
118 /* continue only if the node cannot have a data instance */
119 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
120 return NULL;
121 }
122 }
123 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +0200124}
125
Michal Vaskob69d2432018-09-21 13:26:22 +0200126API const struct lys_type *
127lys_getnext_union_type(const struct lys_type *last, const struct lys_type *type)
128{
129 int found = 0;
130
131 if (!type || (type->base != LY_TYPE_UNION)) {
Michal Vasko79d5d272018-09-21 13:28:22 +0200132 return NULL;
Michal Vaskob69d2432018-09-21 13:26:22 +0200133 }
134
Michal Vasko79d5d272018-09-21 13:28:22 +0200135 return lyp_get_next_union_type((struct lys_type *)type, (struct lys_type *)last, &found);
Michal Vaskob69d2432018-09-21 13:26:22 +0200136}
137
Michal Vasko1dca6882015-10-22 14:29:42 +0200138int
Michal Vasko36cbaa42015-12-14 13:15:48 +0100139lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
140 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +0200141{
Radek Krejcic071c542016-01-27 14:57:51 +0100142 const struct lys_node *node, *parent = NULL;
143 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +0100144 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +0200145
Michal Vasko36cbaa42015-12-14 13:15:48 +0100146 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +0200147 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +0200148
Michal Vasko36cbaa42015-12-14 13:15:48 +0100149 /* fill the lengths in case the caller is so indifferent */
150 if (!mod_name_len) {
151 mod_name_len = strlen(mod_name);
152 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200153 if (!nam_len) {
154 nam_len = strlen(name);
155 }
156
Michal Vasko9e635ac2016-10-17 11:44:09 +0200157 while (siblings && (siblings->nodetype == LYS_USES)) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200158 siblings = siblings->child;
159 }
Michal Vasko9e635ac2016-10-17 11:44:09 +0200160 if (!siblings) {
161 /* unresolved uses */
162 return EXIT_FAILURE;
163 }
164
Michal Vasko680f8b42016-10-17 10:27:37 +0200165 if (siblings->nodetype == LYS_GROUPING) {
166 for (node = siblings; (node->nodetype == LYS_GROUPING) && (node->prev != siblings); node = node->prev);
167 if (node->nodetype == LYS_GROUPING) {
168 /* we went through all the siblings, only groupings there - no valid sibling */
169 return EXIT_FAILURE;
170 }
171 /* update siblings to be valid */
172 siblings = node;
173 }
174
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200175 /* set parent correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100176 parent = lys_parent(siblings);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200177
Michal Vasko680f8b42016-10-17 10:27:37 +0200178 /* go up all uses */
179 while (parent && (parent->nodetype == LYS_USES)) {
180 parent = lys_parent(parent);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200181 }
182
Radek Krejcic071c542016-01-27 14:57:51 +0100183 if (!parent) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200184 /* handle situation when there is a top-level uses referencing a foreign grouping */
185 for (node = siblings; lys_parent(node) && (node->nodetype == LYS_USES); node = lys_parent(node));
186 mod = lys_node_module(node);
Michal Vasko1dca6882015-10-22 14:29:42 +0200187 }
188
Radek Krejcic071c542016-01-27 14:57:51 +0100189 /* try to find the node */
190 node = NULL;
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100191 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | LYS_GETNEXT_WITHINOUT))) {
Radek Krejcic071c542016-01-27 14:57:51 +0100192 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100193 /* module name comparison */
194 node_mod_name = lys_node_module(node)->name;
Michal Vaskob42b6972016-06-06 14:21:30 +0200195 if (!ly_strequal(node_mod_name, mod_name, 1) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100196 continue;
197 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200198
Radek Krejcic071c542016-01-27 14:57:51 +0100199 /* direct name check */
Michal Vaskob42b6972016-06-06 14:21:30 +0200200 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100201 if (ret) {
202 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200203 }
Radek Krejcic071c542016-01-27 14:57:51 +0100204 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200205 }
206 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200207 }
208
209 return EXIT_FAILURE;
210}
211
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200212int
Michal Vaskobb520442017-05-23 10:55:18 +0200213lys_getnext_data(const struct lys_module *mod, const struct lys_node *parent, const char *name, int nam_len,
214 LYS_NODE type, const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200215{
Michal Vaskobb520442017-05-23 10:55:18 +0200216 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200217
Michal Vaskobb520442017-05-23 10:55:18 +0200218 assert((mod || parent) && name);
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200219 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
220
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200221 if (!mod) {
Michal Vaskobb520442017-05-23 10:55:18 +0200222 mod = lys_node_module(parent);
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200223 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200224
Michal Vasko4f0dad02016-02-15 14:08:23 +0100225 /* try to find the node */
226 node = NULL;
Michal Vasko24476fa2017-03-08 12:33:48 +0100227 while ((node = lys_getnext(node, parent, mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100228 if (!type || (node->nodetype & type)) {
229 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200230 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100231 continue;
232 }
233
Michal Vasko4f0dad02016-02-15 14:08:23 +0100234 /* direct name check */
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100235 if (!strncmp(node->name, name, nam_len) && !node->name[nam_len]) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100236 if (ret) {
237 *ret = node;
238 }
239 return EXIT_SUCCESS;
240 }
Radek Krejcic071c542016-01-27 14:57:51 +0100241 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200242 }
243
244 return EXIT_FAILURE;
245}
246
Michal Vasko1e62a092015-12-01 12:27:20 +0100247API const struct lys_node *
248lys_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 +0200249{
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100250 const struct lys_node *next, *aug_parent;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100251 struct lys_node **snode;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200252
Michal Vasko75702cd2018-02-12 11:27:09 +0100253 if ((!parent && !module) || (module && module->type) || (parent && (parent->nodetype == LYS_USES) && !(options & LYS_GETNEXT_PARENTUSES))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100254 LOGARG;
Michal Vasko24476fa2017-03-08 12:33:48 +0100255 return NULL;
256 }
257
Radek Krejci8bc87f62015-09-02 16:19:05 +0200258 if (!last) {
259 /* first call */
260
261 /* get know where to start */
262 if (parent) {
263 /* schema subtree */
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100264 snode = lys_child(parent, LYS_UNKNOWN);
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100265 /* do not return anything if the augment does not have any children */
Radek Krejcibb08db32017-07-03 11:29:17 +0200266 if (!snode || !(*snode) || ((parent->nodetype == LYS_AUGMENT) && ((*snode)->parent != parent))) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100267 return NULL;
268 }
269 next = last = *snode;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200270 } else {
271 /* top level data */
Michal Vaskocb45f472018-02-12 10:47:42 +0100272 if (!(options & LYS_GETNEXT_NOSTATECHECK) && (module->disabled || !module->implemented)) {
273 /* nothing to return from a disabled/imported module */
274 return NULL;
275 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200276 next = last = module->data;
277 }
Radek Krejci972724f2016-08-12 15:24:40 +0200278 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
279 /* continue with uses content */
280 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200281 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200282 /* continue after the last returned value */
283 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200284 }
285
286repeat:
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100287 if (parent && (parent->nodetype == LYS_AUGMENT) && next) {
288 /* do not return anything outside the parent augment */
289 aug_parent = next->parent;
290 do {
291 while (aug_parent && (aug_parent->nodetype != LYS_AUGMENT)) {
292 aug_parent = aug_parent->parent;
293 }
294 if (aug_parent) {
295 if (aug_parent == parent) {
296 break;
297 }
298 aug_parent = ((struct lys_node_augment *)aug_parent)->target;
299 }
300
301 } while (aug_parent);
302 if (!aug_parent) {
303 return NULL;
304 }
305 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200306 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200307 if (options & LYS_GETNEXT_WITHGROUPING) {
308 return next;
309 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200310 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200311 }
312
Radek Krejci972724f2016-08-12 15:24:40 +0200313 if (!next) { /* cover case when parent is augment */
314 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200315 /* no next element */
316 return NULL;
317 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200318 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200319 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200320 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200321 } else {
322 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200323 }
324
Michal Vaskocb45f472018-02-12 10:47:42 +0100325 if (!(options & LYS_GETNEXT_NOSTATECHECK) && lys_is_disabled(next, 0)) {
326 next = next->next;
327 goto repeat;
328 }
329
Radek Krejci7f40ce32015-08-12 20:38:46 +0200330 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200331 case LYS_INPUT:
332 case LYS_OUTPUT:
333 if (options & LYS_GETNEXT_WITHINOUT) {
334 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200335 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200336 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200337 } else {
338 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200339 }
Radek Krejci972724f2016-08-12 15:24:40 +0200340 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200341
Michal Vaskoa5835e92015-10-20 15:07:39 +0200342 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200343 if (options & LYS_GETNEXT_WITHCASE) {
344 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200345 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200346 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200347 } else {
348 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200349 }
Radek Krejci972724f2016-08-12 15:24:40 +0200350 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200351
Michal Vasko1dca6882015-10-22 14:29:42 +0200352 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200353 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200354 if (options & LYS_GETNEXT_WITHUSES) {
355 return next;
356 } else if (next->child) {
357 next = next->child;
358 } else {
359 next = next->next;
360 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200361 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200362
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200363 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200364 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200365 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200366 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200367 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200368 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200369 case LYS_LIST:
370 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200371 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200372
Radek Krejci972724f2016-08-12 15:24:40 +0200373 case LYS_CONTAINER:
374 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
375 if (next->child) {
376 /* go into */
377 next = next->child;
378 } else {
379 next = next->next;
380 }
381 goto repeat;
382 } else {
383 return next;
384 }
385
Radek Krejci8bc87f62015-09-02 16:19:05 +0200386 case LYS_CHOICE:
387 if (options & LYS_GETNEXT_WITHCHOICE) {
388 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200389 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200390 /* go into */
391 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200392 } else {
393 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200394 }
Radek Krejci972724f2016-08-12 15:24:40 +0200395 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200396
Radek Krejci7f40ce32015-08-12 20:38:46 +0200397 default:
398 /* we should not be here */
399 return NULL;
400 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200401}
402
Radek Krejcibf285832017-01-26 16:05:41 +0100403void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200404lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200405{
Michal Vaskof75b2772018-03-14 09:55:33 +0100406 struct lys_node *parent, *first, **pp = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +0100407 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200408
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200409 if (!node) {
410 return;
411 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200412
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200413 /* unlink from data model if necessary */
414 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100415 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100416 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100417 if (main_module->data == node) {
418 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200419 }
420 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200422 /* store pointers to important nodes */
423 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200424 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200425 /* handle augments - first, unlink it from the augment parent ... */
426 if (parent->child == node) {
Radek Krejcic9d78692017-08-24 17:17:18 +0200427 parent->child = (node->next && node->next->parent == parent) ? node->next : NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200428 }
Radek Krejcifec2e142017-01-05 15:19:03 +0100429
430 if (parent->flags & LYS_NOTAPPLIED) {
431 /* data are not connected in the target, so we cannot continue with the target as a parent */
432 parent = NULL;
433 } else {
434 /* data are connected in target, so we will continue with the target as a parent */
435 parent = ((struct lys_node_augment *)parent)->target;
436 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200437 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200439 /* unlink from parent */
440 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100441 if (parent->nodetype == LYS_EXT) {
442 pp = (struct lys_node **)lys_ext_complex_get_substmt(lys_snode2stmt(node->nodetype),
443 (struct lys_ext_instance_complex*)parent, NULL);
444 if (*pp == node) {
445 *pp = node->next;
446 }
447 } else if (parent->child == node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200448 parent->child = node->next;
449 }
450 node->parent = NULL;
451 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200453 /* unlink from siblings */
454 if (node->prev == node) {
455 /* there are no more siblings */
456 return;
457 }
458 if (node->next) {
459 node->next->prev = node->prev;
460 } else {
461 /* unlinking the last element */
462 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100463 if (parent->nodetype == LYS_EXT) {
464 first = *(struct lys_node **)pp;
465 } else {
466 first = parent->child;
467 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200468 } else {
469 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200470 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200471 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200472 }
473 }
474 first->prev = node->prev;
475 }
476 if (node->prev->next) {
477 node->prev->next = node->next;
478 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200480 /* clean up the unlinked element */
481 node->next = NULL;
482 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200483}
484
Michal Vasko563ef092015-09-04 13:17:23 +0200485struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100486lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200487{
488 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200489
490 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200491 /* top-level augment, look into module (uses augment is handled correctly below) */
492 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
Radek Krejci115fa882017-03-01 16:15:07 +0100493 par_iter = lys_main_module(par_iter->parent->module)->data;
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200494 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200495 break;
496 }
497 }
498
Michal Vasko38a00412018-03-14 10:01:50 +0100499 if (par_iter->nodetype == LYS_EXT) {
500 /* we are in a top-level extension, search grouping in top-level groupings */
501 par_iter = lys_main_module(par_iter->module)->data;
502 if (!par_iter) {
503 /* not connected yet, wait */
504 return NULL;
505 }
506 } else if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200507 continue;
508 }
509
510 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
511 if (!stop) {
512 stop = par_iter;
513 } else if (iter == stop) {
514 break;
515 }
516 if (iter->nodetype != LYS_GROUPING) {
517 continue;
518 }
519
Radek Krejcif8426a72015-10-31 23:14:03 +0100520 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200521 return (struct lys_node_grp *)iter;
522 }
523 }
524 }
525
Michal Vasko563ef092015-09-04 13:17:23 +0200526 return NULL;
527}
528
Radek Krejci10c760e2015-08-14 14:45:43 +0200529/*
530 * get next grouping in the root's subtree, in the
531 * first call, tha last is NULL
532 */
533static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200534lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200535{
Radek Krejci10c760e2015-08-14 14:45:43 +0200536 struct lys_node *last = (struct lys_node *)lastgrp;
537 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200538
Radek Krejci10c760e2015-08-14 14:45:43 +0200539 assert(root);
540
541 if (!last) {
542 last = root;
543 }
544
545 while (1) {
546 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
547 next = last->child;
548 } else {
549 next = NULL;
550 }
551 if (!next) {
552 if (last == root) {
553 /* we are done */
554 return NULL;
555 }
556
557 /* no children, go to siblings */
558 next = last->next;
559 }
560 while (!next) {
561 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100562 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200563 /* we are done */
564 return NULL;
565 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200566 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100567 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200568 }
569
570 if (next->nodetype == LYS_GROUPING) {
571 return (struct lys_node_grp *)next;
572 }
573
574 last = next;
575 }
576}
577
Michal Vasko0d343d12015-08-24 14:57:36 +0200578/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200579int
Radek Krejci07911992015-08-14 15:13:31 +0200580lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
581{
Michal Vasko563ef092015-09-04 13:17:23 +0200582 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200583 struct lys_node_grp *grp;
Radek Krejcif95b6292017-02-13 15:57:37 +0100584 int down, up;
Radek Krejci07911992015-08-14 15:13:31 +0200585
586 assert(node);
587
588 if (!parent) {
589 assert(module);
590 } else {
591 module = parent->module;
592 }
Radek Krejci115fa882017-03-01 16:15:07 +0100593 module = lys_main_module(module);
Radek Krejci07911992015-08-14 15:13:31 +0200594
595 switch (node->nodetype) {
596 case LYS_GROUPING:
597 /* 6.2.1, rule 6 */
598 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100599 start = *lys_child(parent, LYS_GROUPING);
600 if (!start) {
Radek Krejci07911992015-08-14 15:13:31 +0200601 down = 0;
602 start = parent;
Radek Krejcif95b6292017-02-13 15:57:37 +0100603 } else {
604 down = 1;
605 }
606 if (parent->nodetype == LYS_EXT) {
607 up = 0;
608 } else {
609 up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200610 }
611 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100612 down = up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200613 start = module->data;
614 }
615 /* go up */
Radek Krejcif95b6292017-02-13 15:57:37 +0100616 if (up && lys_find_grouping_up(node->name, start)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100617 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200618 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200619 }
620 /* go down, because grouping can be defined after e.g. container in which is collision */
621 if (down) {
622 for (iter = start, stop = NULL; iter; iter = iter->prev) {
623 if (!stop) {
624 stop = start;
625 } else if (iter == stop) {
626 break;
627 }
628 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
629 continue;
630 }
631
632 grp = NULL;
633 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100634 if (ly_strequal(node->name, grp->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100635 LOGVAL(module->ctx, LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200636 return EXIT_FAILURE;
637 }
638 }
639 }
640 }
641 break;
642 case LYS_LEAF:
643 case LYS_LEAFLIST:
644 case LYS_LIST:
645 case LYS_CONTAINER:
646 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200647 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200648 /* 6.2.1, rule 7 */
649 if (parent) {
650 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200651 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
652 if (iter->nodetype == LYS_AUGMENT) {
653 if (((struct lys_node_augment *)iter)->target) {
654 /* augment is resolved, go up */
655 iter = ((struct lys_node_augment *)iter)->target;
656 continue;
657 }
658 /* augment is not resolved, this is the final parent */
659 break;
660 }
Radek Krejci07911992015-08-14 15:13:31 +0200661 iter = iter->parent;
662 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200663
Radek Krejci07911992015-08-14 15:13:31 +0200664 if (!iter) {
665 stop = NULL;
666 iter = module->data;
Radek Krejcif95b6292017-02-13 15:57:37 +0100667 } else if (iter->nodetype == LYS_EXT) {
668 stop = iter;
PavolVican9d61d402018-02-05 15:52:48 +0100669 iter = (struct lys_node *)lys_child(iter, node->nodetype);
670 if (iter) {
671 iter = *(struct lys_node **)iter;
672 }
Radek Krejci07911992015-08-14 15:13:31 +0200673 } else {
674 stop = iter;
675 iter = iter->child;
676 }
677 } else {
678 stop = NULL;
679 iter = module->data;
680 }
681 while (iter) {
682 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
683 iter = iter->child;
684 continue;
685 }
686
Radek Krejcibf2abff2016-08-23 15:51:52 +0200687 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100688 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100689 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200690 return EXIT_FAILURE;
691 }
692 }
693
694 /* special case for choice - we must check the choice's name as
695 * well as the names of nodes under the choice
696 */
697 if (iter->nodetype == LYS_CHOICE) {
698 iter = iter->child;
699 continue;
700 }
701
702 /* go to siblings */
703 if (!iter->next) {
704 /* no sibling, go to parent's sibling */
705 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200706 /* for parent LYS_AUGMENT */
707 if (iter->parent == stop) {
708 iter = stop;
709 break;
710 }
711 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200712 if (iter && iter->next) {
713 break;
714 }
715 } while (iter != stop);
716
717 if (iter == stop) {
718 break;
719 }
720 }
721 iter = iter->next;
722 }
723 break;
724 case LYS_CASE:
725 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100726 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100727 start = *lys_child(parent, LYS_CASE);
Radek Krejcic071c542016-01-27 14:57:51 +0100728 } else {
729 start = module->data;
730 }
731
732 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200733 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200734 continue;
735 }
736
Radek Krejci749190d2016-02-18 16:26:25 +0100737 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100738 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200739 return EXIT_FAILURE;
740 }
741 }
742 break;
743 default:
744 /* no check needed */
745 break;
746 }
747
748 return EXIT_SUCCESS;
749}
750
Michal Vasko0d343d12015-08-24 14:57:36 +0200751/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200752int
Michal Vasko8d30dd82018-09-10 10:06:12 +0200753lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child, int options)
Radek Krejci10c760e2015-08-14 14:45:43 +0200754{
Michal Vasko53b7da02018-02-13 15:28:42 +0100755 struct ly_ctx *ctx = child->module->ctx;
Radek Krejcic9d78692017-08-24 17:17:18 +0200756 struct lys_node *iter, **pchild;
Michal Vasko56601c92018-08-06 10:03:06 +0200757 struct lys_node_inout *in, *out;
Radek Krejci744c2d42017-03-26 13:30:00 -0500758 struct lys_node_case *c;
759 int type, shortcase = 0;
Radek Krejcif95b6292017-02-13 15:57:37 +0100760 void *p;
761 struct lyext_substmt *info = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200762
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200763 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200764
Radek Krejci10c760e2015-08-14 14:45:43 +0200765 if (parent) {
766 type = parent->nodetype;
767 module = parent->module;
768 } else {
769 assert(module);
Radek Krejcife3a1382016-11-04 10:30:11 +0100770 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
Radek Krejci10c760e2015-08-14 14:45:43 +0200771 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200772 }
773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200774 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200775 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200776 case LYS_CONTAINER:
777 case LYS_LIST:
778 case LYS_GROUPING:
Radek Krejci96935402016-11-04 16:27:28 +0100779 case LYS_USES:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200780 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200781 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200782 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100783 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200784 return EXIT_FAILURE;
785 }
786 break;
Radek Krejci76512572015-08-04 09:47:08 +0200787 case LYS_INPUT:
788 case LYS_OUTPUT:
789 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200790 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200791 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200792 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100793 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200794 return EXIT_FAILURE;
795 }
796 break;
Radek Krejci76512572015-08-04 09:47:08 +0200797 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200798 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200799 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100800 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200801 return EXIT_FAILURE;
802 }
Radek Krejci744c2d42017-03-26 13:30:00 -0500803 if (child->nodetype != LYS_CASE) {
804 shortcase = 1;
805 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200806 break;
Radek Krejci76512572015-08-04 09:47:08 +0200807 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200808 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200809 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100810 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200811 return EXIT_FAILURE;
812 }
813 break;
Radek Krejci76512572015-08-04 09:47:08 +0200814 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200815 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200816 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100817 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200818 return EXIT_FAILURE;
819 }
820 break;
Radek Krejci76512572015-08-04 09:47:08 +0200821 case LYS_LEAF:
822 case LYS_LEAFLIST:
823 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200824 case LYS_ANYDATA:
Michal Vasko53b7da02018-02-13 15:28:42 +0100825 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
826 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100827 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200828 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200829 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200830 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200831 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskodb017262017-01-24 13:10:04 +0100832 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100833 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200834 return EXIT_FAILURE;
835 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200836 break;
837 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200838 /* top level */
839 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200840 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200841 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100842 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200843 return EXIT_FAILURE;
844 }
Radek Krejcif95b6292017-02-13 15:57:37 +0100845 break;
846 case LYS_EXT:
847 /* plugin-defined */
848 p = lys_ext_complex_get_substmt(lys_snode2stmt(child->nodetype), (struct lys_ext_instance_complex*)parent, &info);
849 if (!p) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100850 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype),
Radek Krejcif95b6292017-02-13 15:57:37 +0100851 ((struct lys_ext_instance_complex*)parent)->def->name);
852 return EXIT_FAILURE;
853 }
854 /* TODO check cardinality */
Radek Krejcic071c542016-01-27 14:57:51 +0100855 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200856 }
857
858 /* check identifier uniqueness */
Michal Vasko15a43372017-09-25 14:12:42 +0200859 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && lys_check_id(child, parent, module)) {
Radek Krejci07911992015-08-14 15:13:31 +0200860 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200861 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200863 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200864 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200865 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200866
Radek Krejcif95b6292017-02-13 15:57:37 +0100867 if ((child->nodetype & (LYS_INPUT | LYS_OUTPUT)) && parent->nodetype != LYS_EXT) {
Michal Vasko56601c92018-08-06 10:03:06 +0200868 /* find the implicit input/output node */
869 LY_TREE_FOR(parent->child, iter) {
870 if (iter->nodetype == child->nodetype) {
871 break;
872 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200873 }
Michal Vasko56601c92018-08-06 10:03:06 +0200874 assert(iter);
875
876 /* switch the old implicit node (iter) with the new one (child) */
877 if (parent->child == iter) {
878 /* first child */
879 parent->child = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200880 } else {
Michal Vasko56601c92018-08-06 10:03:06 +0200881 iter->prev->next = child;
882 }
883 child->prev = iter->prev;
884 child->next = iter->next;
885 if (iter->next) {
886 iter->next->prev = child;
887 } else {
888 /* last child */
Radek Krejci41a349b2016-10-24 19:21:59 +0200889 parent->child->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200890 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200891 child->parent = parent;
Michal Vasko56601c92018-08-06 10:03:06 +0200892
893 /* isolate the node and free it */
894 iter->next = NULL;
895 iter->prev = iter;
896 iter->parent = NULL;
897 lys_node_free(iter, NULL, 0);
Radek Krejci41a349b2016-10-24 19:21:59 +0200898 } else {
Radek Krejci744c2d42017-03-26 13:30:00 -0500899 if (shortcase) {
900 /* create the implicit case to allow it to serve as a target of the augments,
901 * it won't be printed, but it will be present in the tree */
902 c = calloc(1, sizeof *c);
Michal Vasko53b7da02018-02-13 15:28:42 +0100903 LY_CHECK_ERR_RETURN(!c, LOGMEM(ctx), EXIT_FAILURE);
Radek Krejci744c2d42017-03-26 13:30:00 -0500904 c->name = lydict_insert(module->ctx, child->name, 0);
905 c->flags = LYS_IMPLICIT;
Michal Vasko8d30dd82018-09-10 10:06:12 +0200906 if (!(options & (LYS_PARSE_OPT_CFG_IGNORE | LYS_PARSE_OPT_CFG_NOINHERIT))) {
907 /* get config flag from parent */
908 c->flags |= parent->flags & LYS_CONFIG_MASK;
909 }
Radek Krejci744c2d42017-03-26 13:30:00 -0500910 c->module = module;
911 c->nodetype = LYS_CASE;
912 c->prev = (struct lys_node*)c;
Michal Vasko8d30dd82018-09-10 10:06:12 +0200913 lys_node_addchild(parent, module, (struct lys_node*)c, options);
Radek Krejci744c2d42017-03-26 13:30:00 -0500914 parent = (struct lys_node*)c;
915 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200916 /* connect the child correctly */
917 if (!parent) {
918 if (module->data) {
919 module->data->prev->next = child;
920 child->prev = module->data->prev;
921 module->data->prev = child;
922 } else {
923 module->data = child;
924 }
925 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100926 pchild = lys_child(parent, child->nodetype);
927 assert(pchild);
928
Radek Krejcic9d78692017-08-24 17:17:18 +0200929 child->parent = parent;
Radek Krejcif95b6292017-02-13 15:57:37 +0100930 if (!(*pchild)) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200931 /* the only/first child of the parent */
Radek Krejcif95b6292017-02-13 15:57:37 +0100932 *pchild = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200933 iter = child;
934 } else {
935 /* add a new child at the end of parent's child list */
Radek Krejcif95b6292017-02-13 15:57:37 +0100936 iter = (*pchild)->prev;
Radek Krejci41a349b2016-10-24 19:21:59 +0200937 iter->next = child;
938 child->prev = iter;
939 }
940 while (iter->next) {
941 iter = iter->next;
942 iter->parent = parent;
943 }
Radek Krejcic9d78692017-08-24 17:17:18 +0200944 (*pchild)->prev = iter;
Radek Krejci41a349b2016-10-24 19:21:59 +0200945 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200946 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200947
Michal Vaskoe022a562016-09-27 14:24:15 +0200948 /* check config value (but ignore them in groupings and augments) */
Radek Krejcif95b6292017-02-13 15:57:37 +0100949 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); iter = iter->parent);
Michal Vaskoe022a562016-09-27 14:24:15 +0200950 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200951 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
952 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100953 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, child, "true", "config");
954 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200955 return EXIT_FAILURE;
956 }
957 }
958
Radek Krejci41771502016-04-14 17:52:32 +0200959 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200960 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200961 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200962 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200963 /* store it only into container or list - the only data inner nodes */
964 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
965 if (iter->flags & LYS_INCL_STATUS) {
966 /* done, someone else set it already from here */
967 break;
968 }
969 /* set flag about including status data */
970 iter->flags |= LYS_INCL_STATUS;
971 }
972 }
973 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200974
975 /* create implicit input/output nodes to have available them as possible target for augment */
Radek Krejci60251232017-08-24 17:13:08 +0200976 if ((child->nodetype & (LYS_RPC | LYS_ACTION)) && !child->child) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200977 in = calloc(1, sizeof *in);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200978 out = calloc(1, sizeof *out);
979 if (!in || !out) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100980 LOGMEM(ctx);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200981 free(in);
982 free(out);
983 return EXIT_FAILURE;
984 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200985 in->nodetype = LYS_INPUT;
986 in->name = lydict_insert(child->module->ctx, "input", 5);
Radek Krejci41a349b2016-10-24 19:21:59 +0200987 out->nodetype = LYS_OUTPUT;
Radek Krejcia8d111f2017-05-31 13:57:37 +0200988 out->name = lydict_insert(child->module->ctx, "output", 6);
Radek Krejci41a349b2016-10-24 19:21:59 +0200989 in->module = out->module = child->module;
990 in->parent = out->parent = child;
991 in->flags = out->flags = LYS_IMPLICIT;
992 in->next = (struct lys_node *)out;
993 in->prev = (struct lys_node *)out;
994 out->prev = (struct lys_node *)in;
995 child->child = (struct lys_node *)in;
996 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200997 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200998}
999
Michal Vasko29245662017-04-18 15:56:31 +02001000const struct lys_module *
Michal Vaskofb98dc42018-01-11 13:38:28 +01001001lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, const char *revision, int internal, int implement)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001002{
Radek Krejcia1df1682016-04-11 14:56:59 +02001003 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001004 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +02001005 unsigned int len;
Radek Krejcif347abc2016-06-22 10:18:47 +02001006
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001007 if (!ctx || !data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001008 LOGARG;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001009 return NULL;
1010 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001011
Radek Krejcia1df1682016-04-11 14:56:59 +02001012 if (!internal && format == LYS_IN_YANG) {
1013 /* enlarge data by 2 bytes for flex */
1014 len = strlen(data);
1015 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
Michal Vasko53b7da02018-02-13 15:28:42 +01001016 LY_CHECK_ERR_RETURN(!enlarged_data, LOGMEM(ctx), NULL);
Radek Krejcia1df1682016-04-11 14:56:59 +02001017 memcpy(enlarged_data, data, len);
1018 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1019 data = enlarged_data;
1020 }
1021
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001022 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001023 case LYS_IN_YIN:
Michal Vaskofb98dc42018-01-11 13:38:28 +01001024 mod = yin_read_module(ctx, data, revision, implement);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001025 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001026 case LYS_IN_YANG:
Michal Vaskofb98dc42018-01-11 13:38:28 +01001027 mod = yang_read_module(ctx, data, 0, revision, implement);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001028 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001029 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001030 LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001031 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001032 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001033
Radek Krejcia1df1682016-04-11 14:56:59 +02001034 free(enlarged_data);
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001035
1036 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
1037 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
1038 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
1039 * the anotation definitions available in the internal schema structure. There is another hack in schema
1040 * printers to do not print this internally added annotation. */
1041 if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
Radek Krejci5b190662017-04-13 08:56:14 +02001042 if (lyp_add_ietf_netconf_annotations(mod)) {
Michal Vasko10681e82018-01-16 14:54:16 +01001043 lys_free(mod, NULL, 1, 1);
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001044 return NULL;
1045 }
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001046 }
1047
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001048 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001049}
1050
Radek Krejcia1df1682016-04-11 14:56:59 +02001051API const struct lys_module *
1052lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
1053{
Michal Vaskofb98dc42018-01-11 13:38:28 +01001054 return lys_parse_mem_(ctx, data, format, NULL, 0, 1);
Radek Krejcia1df1682016-04-11 14:56:59 +02001055}
1056
Michal Vasko5a721fd2016-02-16 12:16:48 +01001057struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001058lys_sub_parse_mem(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001059{
Michal Vasko5b998712017-01-26 10:34:06 +01001060 char *enlarged_data = NULL;
Michal Vasko5a721fd2016-02-16 12:16:48 +01001061 struct lys_submodule *submod = NULL;
Michal Vasko5b998712017-01-26 10:34:06 +01001062 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001063
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001064 assert(module);
1065 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001066
Michal Vasko5b998712017-01-26 10:34:06 +01001067 if (format == LYS_IN_YANG) {
1068 /* enlarge data by 2 bytes for flex */
1069 len = strlen(data);
1070 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
Michal Vasko53b7da02018-02-13 15:28:42 +01001071 LY_CHECK_ERR_RETURN(!enlarged_data, LOGMEM(module->ctx), NULL);
Michal Vasko5b998712017-01-26 10:34:06 +01001072 memcpy(enlarged_data, data, len);
1073 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1074 data = enlarged_data;
1075 }
1076
Radek Krejcic071c542016-01-27 14:57:51 +01001077 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +02001078 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001081 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001082 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001083 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001084 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001085 submod = yang_read_submodule(module, data, 0, unres);
1086 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001087 default:
Radek Krejci90a550a2016-04-13 16:00:58 +02001088 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001089 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001090 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001091
Michal Vasko5b998712017-01-26 10:34:06 +01001092 free(enlarged_data);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001093 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001094}
1095
Michal Vasko1e62a092015-12-01 12:27:20 +01001096API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001097lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1098{
1099 int fd;
1100 const struct lys_module *ret;
Radek Krejcid80c8602016-10-25 11:56:03 +02001101 const char *rev, *dot, *filename;
1102 size_t len;
Michal Vasko662610a2015-12-07 11:25:45 +01001103
1104 if (!ctx || !path) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001105 LOGARG;
Michal Vasko662610a2015-12-07 11:25:45 +01001106 return NULL;
1107 }
1108
1109 fd = open(path, O_RDONLY);
1110 if (fd == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001111 LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
Michal Vasko662610a2015-12-07 11:25:45 +01001112 return NULL;
1113 }
1114
1115 ret = lys_parse_fd(ctx, fd, format);
1116 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +01001117
Radek Krejcid80c8602016-10-25 11:56:03 +02001118 if (!ret) {
1119 /* error */
1120 return NULL;
1121 }
1122
1123 /* check that name and revision match filename */
1124 filename = strrchr(path, '/');
1125 if (!filename) {
1126 filename = path;
1127 } else {
1128 filename++;
1129 }
1130 rev = strchr(filename, '@');
1131 dot = strrchr(filename, '.');
1132
1133 /* name */
1134 len = strlen(ret->name);
1135 if (strncmp(filename, ret->name, len) ||
1136 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001137 LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, ret->name);
Radek Krejcid80c8602016-10-25 11:56:03 +02001138 }
1139 if (rev) {
1140 len = dot - ++rev;
1141 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001142 LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", filename,
Radek Krejcid80c8602016-10-25 11:56:03 +02001143 ret->rev_size ? ret->rev[0].date : "none");
1144 }
1145 }
1146
1147 if (!ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001148 /* store URI */
Alexandre Snarskii12b22182018-09-04 17:12:28 +03001149 char rpath[PATH_MAX];
1150 if (realpath(path, rpath) != NULL) {
1151 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, rpath, 0);
1152 } else {
1153 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
1154 }
Radek Krejci23f5de52016-02-25 15:53:17 +01001155 }
1156
Michal Vasko662610a2015-12-07 11:25:45 +01001157 return ret;
1158}
1159
1160API const struct lys_module *
1161lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001162{
Michal Vaskofb98dc42018-01-11 13:38:28 +01001163 return lys_parse_fd_(ctx, fd, format, NULL, 1);
1164}
1165
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001166static void
1167lys_parse_set_filename(struct ly_ctx *ctx, const char **filename, int fd)
1168{
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001169#ifdef __APPLE__
1170 char path[MAXPATHLEN];
1171#else
Michal Vasko25601f32018-02-16 09:41:46 +01001172 int len;
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001173 char path[PATH_MAX], proc_path[32];
1174#endif
1175
1176#ifdef __APPLE__
1177 if (fcntl(fd, F_GETPATH, path) != -1) {
1178 *filename = lydict_insert(ctx, path, 0);
1179 }
1180#else
1181 /* get URI if there is /proc */
1182 sprintf(proc_path, "/proc/self/fd/%d", fd);
1183 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
1184 *filename = lydict_insert(ctx, path, len);
1185 }
1186#endif
1187}
1188
Michal Vaskofb98dc42018-01-11 13:38:28 +01001189const struct lys_module *
1190lys_parse_fd_(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, const char *revision, int implement)
1191{
Michal Vasko1e62a092015-12-01 12:27:20 +01001192 const struct lys_module *module;
Radek Krejci0fb11502017-01-31 16:45:42 +01001193 size_t length;
Radek Krejci63a91a92015-07-29 13:31:04 +02001194 char *addr;
1195
1196 if (!ctx || fd < 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001197 LOGARG;
Radek Krejci63a91a92015-07-29 13:31:04 +02001198 return NULL;
1199 }
1200
Michal Vasko53b7da02018-02-13 15:28:42 +01001201 if (lyp_mmap(ctx, fd, format == LYS_IN_YANG ? 1 : 0, &length, (void **)&addr)) {
1202 LOGERR(ctx, LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001203 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001204 } else if (!addr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001205 LOGERR(ctx, LY_EINVAL, "Empty schema file.");
Pavol Vicane36ea262015-11-12 11:57:47 +01001206 return NULL;
1207 }
Radek Krejci0fb11502017-01-31 16:45:42 +01001208
Michal Vaskofb98dc42018-01-11 13:38:28 +01001209 module = lys_parse_mem_(ctx, addr, format, revision, 1, implement);
Radek Krejci0fb11502017-01-31 16:45:42 +01001210 lyp_munmap(addr, length);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001211
Radek Krejcia77904e2016-02-25 16:23:45 +01001212 if (module && !module->filepath) {
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001213 lys_parse_set_filename(ctx, (const char **)&module->filepath, fd);
Radek Krejcib051f722016-02-25 15:12:21 +01001214 }
1215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001216 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001217}
1218
Michal Vasko5a721fd2016-02-16 12:16:48 +01001219struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001220lys_sub_parse_fd(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001221{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001222 struct lys_submodule *submodule;
Radek Krejci0fb11502017-01-31 16:45:42 +01001223 size_t length;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001224 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001226 assert(module);
1227 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001228
Michal Vasko53b7da02018-02-13 15:28:42 +01001229 if (lyp_mmap(module->ctx, fd, format == LYS_IN_YANG ? 1 : 0, &length, (void **)&addr)) {
1230 LOGERR(module->ctx, LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001231 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001232 } else if (!addr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001233 LOGERR(module->ctx, LY_EINVAL, "Empty submodule schema file.");
Michal Vasko2e7241e2016-02-15 16:06:34 +01001234 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001235 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001236
Michal Vasko5b998712017-01-26 10:34:06 +01001237 /* get the main module */
1238 module = lys_main_module(module);
1239
1240 switch (format) {
1241 case LYS_IN_YIN:
1242 submodule = yin_read_submodule(module, addr, unres);
1243 break;
1244 case LYS_IN_YANG:
1245 submodule = yang_read_submodule(module, addr, 0, unres);
1246 break;
1247 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001248 LOGINT(module->ctx);
Michal Vasko85d41522017-02-24 09:49:16 +01001249 return NULL;
Michal Vasko5b998712017-01-26 10:34:06 +01001250 }
1251
Radek Krejcic645a3a2017-01-31 16:59:00 +01001252 lyp_munmap(addr, length);
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001253
1254 if (submodule && !submodule->filepath) {
1255 lys_parse_set_filename(module->ctx, (const char **)&submodule->filepath, fd);
1256 }
1257
Michal Vasko5a721fd2016-02-16 12:16:48 +01001258 return submodule;
1259
Radek Krejciefaeba32015-05-27 14:30:57 +02001260}
1261
Radek Krejci72cdfac2018-08-15 14:47:33 +02001262API int
Radek Krejcicf3b7ca2018-08-17 09:55:06 +02001263lys_search_localfile(const char * const *searchpaths, int cwd, const char *name, const char *revision, char **localfile, LYS_INFORMAT *format)
Radek Krejci72cdfac2018-08-15 14:47:33 +02001264{
1265 size_t len, flen, match_len = 0, dir_len;
1266 int i, implicit_cwd = 0, ret = EXIT_FAILURE;
1267 char *wd, *wn = NULL;
1268 DIR *dir = NULL;
1269 struct dirent *file;
1270 char *match_name = NULL;
1271 LYS_INFORMAT format_aux, match_format = 0;
1272 unsigned int u;
1273 struct ly_set *dirs;
1274 struct stat st;
1275
1276 if (!localfile) {
1277 LOGARG;
1278 return EXIT_FAILURE;
1279 }
1280
1281 /* start to fill the dir fifo with the context's search path (if set)
1282 * and the current working directory */
1283 dirs = ly_set_new();
1284 if (!dirs) {
1285 LOGMEM(NULL);
1286 return EXIT_FAILURE;
1287 }
1288
1289 len = strlen(name);
Radek Krejcicf3b7ca2018-08-17 09:55:06 +02001290 if (cwd) {
1291 wd = get_current_dir_name();
1292 if (!wd) {
1293 LOGMEM(NULL);
Radek Krejci72cdfac2018-08-15 14:47:33 +02001294 goto cleanup;
Radek Krejcicf3b7ca2018-08-17 09:55:06 +02001295 } else {
1296 /* add implicit current working directory (./) to be searched,
1297 * this directory is not searched recursively */
1298 if (ly_set_add(dirs, wd, 0) == -1) {
1299 goto cleanup;
1300 }
1301 implicit_cwd = 1;
Radek Krejci72cdfac2018-08-15 14:47:33 +02001302 }
Radek Krejci72cdfac2018-08-15 14:47:33 +02001303 }
1304 if (searchpaths) {
1305 for (i = 0; searchpaths[i]; i++) {
1306 /* check for duplicities with the implicit current working directory */
1307 if (implicit_cwd && !strcmp(dirs->set.g[0], searchpaths[i])) {
1308 implicit_cwd = 0;
1309 continue;
1310 }
1311 wd = strdup(searchpaths[i]);
1312 if (!wd) {
1313 LOGMEM(NULL);
1314 goto cleanup;
1315 } else if (ly_set_add(dirs, wd, 0) == -1) {
1316 goto cleanup;
1317 }
1318 }
1319 }
1320 wd = NULL;
1321
1322 /* start searching */
1323 while (dirs->number) {
1324 free(wd);
1325 free(wn); wn = NULL;
1326
1327 dirs->number--;
1328 wd = (char *)dirs->set.g[dirs->number];
1329 dirs->set.g[dirs->number] = NULL;
1330 LOGVRB("Searching for \"%s\" in %s.", name, wd);
1331
1332 if (dir) {
1333 closedir(dir);
1334 }
1335 dir = opendir(wd);
1336 dir_len = strlen(wd);
1337 if (!dir) {
1338 LOGWRN(NULL, "Unable to open directory \"%s\" for searching (sub)modules (%s).", wd, strerror(errno));
1339 } else {
1340 while ((file = readdir(dir))) {
1341 if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
1342 /* skip . and .. */
1343 continue;
1344 }
1345 free(wn);
1346 if (asprintf(&wn, "%s/%s", wd, file->d_name) == -1) {
1347 LOGMEM(NULL);
1348 goto cleanup;
1349 }
1350 if (stat(wn, &st) == -1) {
1351 LOGWRN(NULL, "Unable to get information about \"%s\" file in \"%s\" when searching for (sub)modules (%s)",
1352 file->d_name, wd, strerror(errno));
1353 continue;
1354 }
1355 if (S_ISDIR(st.st_mode) && (dirs->number || !implicit_cwd)) {
1356 /* we have another subdirectory in searchpath to explore,
1357 * subdirectories are not taken into account in current working dir (dirs->set.g[0]) */
1358 if (ly_set_add(dirs, wn, 0) == -1) {
1359 goto cleanup;
1360 }
1361 /* continue with the next item in current directory */
1362 wn = NULL;
1363 continue;
1364 } else if (!S_ISREG(st.st_mode)) {
1365 /* not a regular file (note that we see the target of symlinks instead of symlinks */
1366 continue;
1367 }
1368
1369 /* here we know that the item is a file which can contain a module */
1370 if (strncmp(name, file->d_name, len) ||
1371 (file->d_name[len] != '.' && file->d_name[len] != '@')) {
1372 /* different filename than the module we search for */
1373 continue;
1374 }
1375
1376 /* get type according to filename suffix */
1377 flen = strlen(file->d_name);
1378 if (!strcmp(&file->d_name[flen - 4], ".yin")) {
1379 format_aux = LYS_IN_YIN;
1380 } else if (!strcmp(&file->d_name[flen - 5], ".yang")) {
1381 format_aux = LYS_IN_YANG;
1382 } else {
1383 /* not supportde suffix/file format */
1384 continue;
1385 }
1386
1387 if (revision) {
1388 /* we look for the specific revision, try to get it from the filename */
1389 if (file->d_name[len] == '@') {
1390 /* check revision from the filename */
1391 if (strncmp(revision, &file->d_name[len + 1], strlen(revision))) {
1392 /* another revision */
1393 continue;
1394 } else {
1395 /* exact revision */
1396 free(match_name);
1397 match_name = wn;
1398 wn = NULL;
1399 match_len = dir_len + 1 + len;
1400 match_format = format_aux;
1401 goto success;
1402 }
1403 } else {
1404 /* continue trying to find exact revision match, use this only if not found */
1405 free(match_name);
1406 match_name = wn;
1407 wn = NULL;
1408 match_len = dir_len + 1 +len;
1409 match_format = format_aux;
1410 continue;
1411 }
1412 } else {
1413 /* remember the revision and try to find the newest one */
1414 if (match_name) {
1415 if (file->d_name[len] != '@' || lyp_check_date(NULL, &file->d_name[len + 1])) {
1416 continue;
1417 } else if (match_name[match_len] == '@' &&
1418 (strncmp(&match_name[match_len + 1], &file->d_name[len + 1], LY_REV_SIZE - 1) >= 0)) {
1419 continue;
1420 }
1421 free(match_name);
1422 }
1423
1424 match_name = wn;
1425 wn = NULL;
1426 match_len = dir_len + 1 + len;
1427 match_format = format_aux;
1428 continue;
1429 }
1430 }
1431 }
1432 }
1433
1434success:
1435 (*localfile) = match_name;
1436 match_name = NULL;
1437 if (format) {
1438 (*format) = match_format;
1439 }
1440 ret = EXIT_SUCCESS;
1441
1442cleanup:
1443 free(wn);
1444 free(wd);
1445 if (dir) {
1446 closedir(dir);
1447 }
1448 free(match_name);
1449 for (u = 0; u < dirs->number; u++) {
1450 free(dirs->set.g[u]);
1451 }
1452 ly_set_free(dirs);
1453
1454 return ret;
1455}
1456
Radek Krejcibf285832017-01-26 16:05:41 +01001457int
1458lys_ext_iter(struct lys_ext_instance **ext, uint8_t ext_size, uint8_t start, LYEXT_SUBSTMT substmt)
1459{
1460 unsigned int u;
1461
1462 for (u = start; u < ext_size; u++) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001463 if (ext[u]->insubstmt == substmt) {
Radek Krejcibf285832017-01-26 16:05:41 +01001464 return u;
1465 }
1466 }
1467
1468 return -1;
1469}
1470
Radek Krejcifdc0d702017-01-23 15:58:38 +01001471/*
1472 * duplicate extension instance
1473 */
1474int
Michal Vasko17e8ba32018-02-15 10:58:56 +01001475lys_ext_dup(struct ly_ctx *ctx, struct lys_module *mod, struct lys_ext_instance **orig, uint8_t size, void *parent,
1476 LYEXT_PAR parent_type, struct lys_ext_instance ***new, int shallow, struct unres_schema *unres)
Radek Krejcifdc0d702017-01-23 15:58:38 +01001477{
1478 int i;
1479 uint8_t u = 0;
1480 struct lys_ext_instance **result;
1481 struct unres_ext *info, *info_orig;
fanchanghu8d86f6b2017-06-10 12:49:54 +08001482 size_t len;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001483
1484 assert(new);
1485
1486 if (!size) {
1487 if (orig) {
Michal Vasko17e8ba32018-02-15 10:58:56 +01001488 LOGINT(ctx);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001489 return EXIT_FAILURE;
1490 }
1491 (*new) = NULL;
1492 return EXIT_SUCCESS;
1493 }
1494
1495 (*new) = result = calloc(size, sizeof *result);
Michal Vasko17e8ba32018-02-15 10:58:56 +01001496 LY_CHECK_ERR_RETURN(!result, LOGMEM(ctx), EXIT_FAILURE);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001497 for (u = 0; u < size; u++) {
1498 if (orig[u]) {
1499 /* resolved extension instance, just duplicate it */
Radek Krejci8de8f612017-02-16 15:03:32 +01001500 switch(orig[u]->ext_type) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001501 case LYEXT_FLAG:
1502 result[u] = malloc(sizeof(struct lys_ext_instance));
Michal Vasko17e8ba32018-02-15 10:58:56 +01001503 LY_CHECK_ERR_GOTO(!result[u], LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001504 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001505 case LYEXT_COMPLEX:
fanchanghu8d86f6b2017-06-10 12:49:54 +08001506 len = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->instance_size;
1507 result[u] = calloc(1, len);
Michal Vasko17e8ba32018-02-15 10:58:56 +01001508 LY_CHECK_ERR_GOTO(!result[u], LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001509
Radek Krejcifebdad72017-02-06 11:35:51 +01001510 ((struct lys_ext_instance_complex*)result[u])->substmt = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001511 /* TODO duplicate data in extension instance content */
fanchanghu8d86f6b2017-06-10 12:49:54 +08001512 memcpy((void*)result[u] + sizeof(**orig), (void*)orig[u] + sizeof(**orig), len - sizeof(**orig));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001513 break;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001514 }
1515 /* generic part */
1516 result[u]->def = orig[u]->def;
fanchanghu8d86f6b2017-06-10 12:49:54 +08001517 result[u]->flags = LYEXT_OPT_CONTENT;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001518 result[u]->arg_value = lydict_insert(ctx, orig[u]->arg_value, 0);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001519 result[u]->parent = parent;
1520 result[u]->parent_type = parent_type;
Radek Krejcifebdad72017-02-06 11:35:51 +01001521 result[u]->insubstmt = orig[u]->insubstmt;
1522 result[u]->insubstmt_index = orig[u]->insubstmt_index;
Radek Krejci8de8f612017-02-16 15:03:32 +01001523 result[u]->ext_type = orig[u]->ext_type;
Radek Krejci7f1d47e2017-04-12 15:29:02 +02001524 result[u]->priv = NULL;
1525 result[u]->nodetype = LYS_EXT;
1526 result[u]->module = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001527
1528 /* extensions */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001529 result[u]->ext_size = orig[u]->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001530 if (lys_ext_dup(ctx, mod, orig[u]->ext, orig[u]->ext_size, result[u],
Radek Krejci5138e9f2017-04-12 13:10:46 +02001531 LYEXT_PAR_EXTINST, &result[u]->ext, shallow, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001532 goto error;
1533 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02001534
1535 /* in case of shallow copy (duplication for deviation), duplicate only the link to private data
1536 * in a new copy, otherwise (grouping instantiation) do not duplicate the private data */
1537 if (shallow) {
1538 result[u]->priv = orig[u]->priv;
1539 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01001540 } else {
1541 /* original extension is not yet resolved, so duplicate it in unres */
1542 i = unres_schema_find(unres, -1, &orig, UNRES_EXT);
1543 if (i == -1) {
1544 /* extension not found in unres */
Michal Vasko17e8ba32018-02-15 10:58:56 +01001545 LOGINT(ctx);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001546 goto error;
1547 }
1548 info_orig = unres->str_snode[i];
1549 info = malloc(sizeof *info);
Michal Vasko17e8ba32018-02-15 10:58:56 +01001550 LY_CHECK_ERR_GOTO(!info, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001551 info->datatype = info_orig->datatype;
1552 if (info->datatype == LYS_IN_YIN) {
Michal Vasko17e8ba32018-02-15 10:58:56 +01001553 info->data.yin = lyxml_dup_elem(ctx, info_orig->data.yin, NULL, 1);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001554 } /* else TODO YANG */
1555 info->parent = parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001556 info->mod = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001557 info->parent_type = parent_type;
1558 info->ext_index = u;
1559 if (unres_schema_add_node(info->mod, unres, new, UNRES_EXT, (struct lys_node *)info) == -1) {
1560 goto error;
1561 }
1562 }
1563 }
1564
1565 return EXIT_SUCCESS;
1566
1567error:
1568 (*new) = NULL;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001569 lys_extension_instances_free(ctx, result, u, NULL);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001570 return EXIT_FAILURE;
1571}
1572
Radek Krejci1d82ef62015-08-07 14:44:40 +02001573static struct lys_restr *
Radek Krejci5138e9f2017-04-12 13:10:46 +02001574lys_restr_dup(struct lys_module *mod, struct lys_restr *old, int size, int shallow, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001575{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001576 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001577 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001578
Radek Krejci3733a802015-06-19 13:43:21 +02001579 if (!size) {
1580 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001581 }
Radek Krejci3733a802015-06-19 13:43:21 +02001582
1583 result = calloc(size, sizeof *result);
Michal Vasko53b7da02018-02-13 15:28:42 +01001584 LY_CHECK_ERR_RETURN(!result, LOGMEM(mod->ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001585
Radek Krejci3733a802015-06-19 13:43:21 +02001586 for (i = 0; i < size; i++) {
Radek Krejci77f22b22017-01-17 15:23:03 +01001587 result[i].ext_size = old[i].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001588 lys_ext_dup(mod->ctx, mod, old[i].ext, old[i].ext_size, &result[i], LYEXT_PAR_RESTR, &result[i].ext, shallow, unres);
Radek Krejci8d6b7422017-02-03 14:42:13 +01001589 result[i].expr = lydict_insert(mod->ctx, old[i].expr, 0);
1590 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1591 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1592 result[i].eapptag = lydict_insert(mod->ctx, old[i].eapptag, 0);
1593 result[i].emsg = lydict_insert(mod->ctx, old[i].emsg, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001594 }
1595
1596 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001597}
1598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001599void
Radek Krejci5138e9f2017-04-12 13:10:46 +02001600lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr,
1601 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci0bd5db42015-06-19 13:30:07 +02001602{
1603 assert(ctx);
1604 if (!restr) {
1605 return;
1606 }
1607
Radek Krejci5138e9f2017-04-12 13:10:46 +02001608 lys_extension_instances_free(ctx, restr->ext, restr->ext_size, private_destructor);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001609 lydict_remove(ctx, restr->expr);
1610 lydict_remove(ctx, restr->dsc);
1611 lydict_remove(ctx, restr->ref);
1612 lydict_remove(ctx, restr->eapptag);
1613 lydict_remove(ctx, restr->emsg);
1614}
1615
Pavol Vican05810b62016-11-23 14:07:22 +01001616void
Radek Krejci5138e9f2017-04-12 13:10:46 +02001617lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size,
Frank Rimplerc4db1c72017-09-12 12:56:39 +00001618 int shallow, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001619{
1620 uint8_t i;
1621
1622 for (i = 0; i < iffeature_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02001623 lys_extension_instances_free(ctx, iffeature[i].ext, iffeature[i].ext_size, private_destructor);
Michal Vasko15a43372017-09-25 14:12:42 +02001624 if (!shallow) {
Frank Rimpler2a503f52017-09-12 15:21:18 +00001625 free(iffeature[i].expr);
1626 free(iffeature[i].features);
1627 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001628 }
1629 free(iffeature);
1630}
1631
Michal Vaskob84f88a2015-09-24 13:16:10 +02001632static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001633type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001634 LY_DATA_TYPE base, int in_grp, int shallow, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001635{
1636 int i;
Radek Krejcidce5f972017-09-12 15:47:49 +02001637 unsigned int u;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001638
1639 switch (base) {
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001640 case LY_TYPE_BINARY:
1641 if (old->info.binary.length) {
1642 new->info.binary.length = lys_restr_dup(mod, old->info.binary.length, 1, shallow, unres);
1643 }
1644 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001645
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001646 case LY_TYPE_BITS:
1647 new->info.bits.count = old->info.bits.count;
1648 if (new->info.bits.count) {
1649 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
Michal Vasko53b7da02018-02-13 15:28:42 +01001650 LY_CHECK_ERR_RETURN(!new->info.bits.bit, LOGMEM(mod->ctx), -1);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001651
Radek Krejcidce5f972017-09-12 15:47:49 +02001652 for (u = 0; u < new->info.bits.count; u++) {
1653 new->info.bits.bit[u].name = lydict_insert(mod->ctx, old->info.bits.bit[u].name, 0);
1654 new->info.bits.bit[u].dsc = lydict_insert(mod->ctx, old->info.bits.bit[u].dsc, 0);
1655 new->info.bits.bit[u].ref = lydict_insert(mod->ctx, old->info.bits.bit[u].ref, 0);
1656 new->info.bits.bit[u].flags = old->info.bits.bit[u].flags;
1657 new->info.bits.bit[u].pos = old->info.bits.bit[u].pos;
1658 new->info.bits.bit[u].ext_size = old->info.bits.bit[u].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001659 if (lys_ext_dup(mod->ctx, mod, old->info.bits.bit[u].ext, old->info.bits.bit[u].ext_size,
Radek Krejcidce5f972017-09-12 15:47:49 +02001660 &new->info.bits.bit[u], LYEXT_PAR_TYPE_BIT,
1661 &new->info.bits.bit[u].ext, shallow, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001662 return -1;
1663 }
1664 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001665 }
1666 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001667
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001668 case LY_TYPE_DEC64:
1669 new->info.dec64.dig = old->info.dec64.dig;
1670 new->info.dec64.div = old->info.dec64.div;
1671 if (old->info.dec64.range) {
1672 new->info.dec64.range = lys_restr_dup(mod, old->info.dec64.range, 1, shallow, unres);
1673 }
1674 break;
1675
1676 case LY_TYPE_ENUM:
1677 new->info.enums.count = old->info.enums.count;
1678 if (new->info.enums.count) {
1679 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Michal Vasko53b7da02018-02-13 15:28:42 +01001680 LY_CHECK_ERR_RETURN(!new->info.enums.enm, LOGMEM(mod->ctx), -1);
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001681
Radek Krejcidce5f972017-09-12 15:47:49 +02001682 for (u = 0; u < new->info.enums.count; u++) {
1683 new->info.enums.enm[u].name = lydict_insert(mod->ctx, old->info.enums.enm[u].name, 0);
1684 new->info.enums.enm[u].dsc = lydict_insert(mod->ctx, old->info.enums.enm[u].dsc, 0);
1685 new->info.enums.enm[u].ref = lydict_insert(mod->ctx, old->info.enums.enm[u].ref, 0);
1686 new->info.enums.enm[u].flags = old->info.enums.enm[u].flags;
1687 new->info.enums.enm[u].value = old->info.enums.enm[u].value;
1688 new->info.enums.enm[u].ext_size = old->info.enums.enm[u].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001689 if (lys_ext_dup(mod->ctx, mod, old->info.enums.enm[u].ext, old->info.enums.enm[u].ext_size,
Radek Krejcidce5f972017-09-12 15:47:49 +02001690 &new->info.enums.enm[u], LYEXT_PAR_TYPE_ENUM,
1691 &new->info.enums.enm[u].ext, shallow, unres)) {
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001692 return -1;
1693 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001694 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001695 }
1696 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001697
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001698 case LY_TYPE_IDENT:
1699 new->info.ident.count = old->info.ident.count;
1700 if (old->info.ident.count) {
1701 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
Michal Vasko53b7da02018-02-13 15:28:42 +01001702 LY_CHECK_ERR_RETURN(!new->info.ident.ref, LOGMEM(mod->ctx), -1);
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001703 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1704 } else {
1705 /* there can be several unresolved base identities, duplicate them all */
1706 i = -1;
1707 do {
1708 i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF);
1709 if (i != -1) {
1710 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001711 return -1;
1712 }
1713 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001714 --i;
1715 } while (i > -1);
1716 }
1717 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001718
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001719 case LY_TYPE_INST:
1720 new->info.inst.req = old->info.inst.req;
1721 break;
1722
1723 case LY_TYPE_INT8:
1724 case LY_TYPE_INT16:
1725 case LY_TYPE_INT32:
1726 case LY_TYPE_INT64:
1727 case LY_TYPE_UINT8:
1728 case LY_TYPE_UINT16:
1729 case LY_TYPE_UINT32:
1730 case LY_TYPE_UINT64:
1731 if (old->info.num.range) {
1732 new->info.num.range = lys_restr_dup(mod, old->info.num.range, 1, shallow, unres);
1733 }
1734 break;
1735
1736 case LY_TYPE_LEAFREF:
1737 if (old->info.lref.path) {
1738 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko48c73df2018-10-31 09:09:13 +01001739 new->info.lref.req = old->info.lref.req;
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001740 if (!in_grp && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
1741 return -1;
1742 }
1743 }
1744 break;
1745
1746 case LY_TYPE_STRING:
1747 if (old->info.str.length) {
1748 new->info.str.length = lys_restr_dup(mod, old->info.str.length, 1, shallow, unres);
1749 }
Radek Krejcib53154b2017-07-19 09:14:13 +02001750 if (old->info.str.pat_count) {
1751 new->info.str.patterns = lys_restr_dup(mod, old->info.str.patterns, old->info.str.pat_count, shallow, unres);
1752 new->info.str.pat_count = old->info.str.pat_count;
Michal Vaskofcd974b2017-08-22 10:17:49 +02001753#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001754 if (!in_grp) {
1755 new->info.str.patterns_pcre = malloc(new->info.str.pat_count * 2 * sizeof *new->info.str.patterns_pcre);
Michal Vasko53b7da02018-02-13 15:28:42 +01001756 LY_CHECK_ERR_RETURN(!new->info.str.patterns_pcre, LOGMEM(mod->ctx), -1);
Radek Krejcia4c107d2017-10-27 14:19:26 +02001757 for (u = 0; u < new->info.str.pat_count; u++) {
Michal Vaskoa26db302018-02-14 15:22:10 +01001758 if (lyp_precompile_pattern(mod->ctx, &new->info.str.patterns[u].expr[1],
Radek Krejcia4c107d2017-10-27 14:19:26 +02001759 (pcre**)&new->info.str.patterns_pcre[2 * u],
1760 (pcre_extra**)&new->info.str.patterns_pcre[2 * u + 1])) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001761 free(new->info.str.patterns_pcre);
1762 new->info.str.patterns_pcre = NULL;
1763 return -1;
1764 }
1765 }
1766 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001767#endif
Radek Krejcib53154b2017-07-19 09:14:13 +02001768 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001769 break;
1770
1771 case LY_TYPE_UNION:
1772 new->info.uni.has_ptr_type = old->info.uni.has_ptr_type;
1773 new->info.uni.count = old->info.uni.count;
1774 if (new->info.uni.count) {
1775 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001776 LY_CHECK_ERR_RETURN(!new->info.uni.types, LOGMEM(mod->ctx), -1);
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001777
Radek Krejcidce5f972017-09-12 15:47:49 +02001778 for (u = 0; u < new->info.uni.count; u++) {
1779 if (lys_type_dup(mod, parent, &(new->info.uni.types[u]), &(old->info.uni.types[u]), in_grp,
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001780 shallow, unres)) {
1781 return -1;
1782 }
1783 }
1784 }
1785 break;
1786
1787 default:
1788 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1789 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001790 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001791
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001792 return EXIT_SUCCESS;
1793}
1794
1795struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001796lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
Radek Krejci5138e9f2017-04-12 13:10:46 +02001797 int in_grp, int shallow, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001798{
1799 struct yang_type *new;
1800
1801 new = calloc(1, sizeof *new);
Michal Vasko53b7da02018-02-13 15:28:42 +01001802 LY_CHECK_ERR_RETURN(!new, LOGMEM(module->ctx), NULL);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001803 new->flags = old->flags;
1804 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001805 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001806 new->type = type;
1807 if (!new->name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001808 LOGMEM(module->ctx);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001809 goto error;
1810 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02001811 if (type_dup(module, parent, type, old->type, new->base, in_grp, shallow, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001812 new->type->base = new->base;
Radek Krejci5138e9f2017-04-12 13:10:46 +02001813 lys_type_free(module->ctx, new->type, NULL);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001814 memset(&new->type->info, 0, sizeof new->type->info);
1815 goto error;
1816 }
1817 return new;
1818
Michal Vasko53b7da02018-02-13 15:28:42 +01001819error:
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001820 free(new);
1821 return NULL;
1822}
1823
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001824int
1825lys_copy_union_leafrefs(struct lys_module *mod, struct lys_node *parent, struct lys_type *type, struct lys_type *prev_new,
1826 struct unres_schema *unres)
1827{
1828 struct lys_type new;
Radek Krejcidce5f972017-09-12 15:47:49 +02001829 unsigned int i, top_type;
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001830 struct lys_ext_instance **ext;
1831 uint8_t ext_size;
1832 void *reloc;
1833
1834 if (!prev_new) {
1835 /* this is the "top-level" type, meaning it is a real type and no typedef directly above */
1836 top_type = 1;
1837
1838 memset(&new, 0, sizeof new);
1839
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001840 new.base = type->base;
1841 new.parent = (struct lys_tpdf *)parent;
1842
1843 prev_new = &new;
1844 } else {
1845 /* this is not top-level type, just a type of a typedef */
1846 top_type = 0;
1847 }
1848
Radek Krejci9c5cb6d2017-08-09 11:15:23 +02001849 assert(type->der);
1850 if (type->der->module) {
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001851 /* typedef, skip it, but keep the extensions */
1852 ext_size = type->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001853 if (lys_ext_dup(mod->ctx, mod, type->ext, type->ext_size, prev_new, LYEXT_PAR_TYPE, &ext, 0, unres)) {
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001854 return -1;
1855 }
1856 if (prev_new->ext) {
1857 reloc = realloc(prev_new->ext, (prev_new->ext_size + ext_size) * sizeof *prev_new->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001858 LY_CHECK_ERR_RETURN(!reloc, LOGMEM(mod->ctx), -1);
Radek Krejci70379e22017-08-09 11:21:07 +02001859 prev_new->ext = reloc;
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001860
1861 memcpy(prev_new->ext + prev_new->ext_size, ext, ext_size * sizeof *ext);
1862 free(ext);
1863
1864 prev_new->ext_size += ext_size;
1865 } else {
1866 prev_new->ext = ext;
1867 prev_new->ext_size = ext_size;
1868 }
1869
1870 if (lys_copy_union_leafrefs(mod, parent, &type->der->type, prev_new, unres)) {
1871 return -1;
1872 }
1873 } else {
1874 /* type, just make a deep copy */
1875 switch (type->base) {
1876 case LY_TYPE_UNION:
1877 prev_new->info.uni.has_ptr_type = type->info.uni.has_ptr_type;
1878 prev_new->info.uni.count = type->info.uni.count;
1879 /* this cannot be a typedef anymore */
1880 assert(prev_new->info.uni.count);
1881
1882 prev_new->info.uni.types = calloc(prev_new->info.uni.count, sizeof *prev_new->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001883 LY_CHECK_ERR_RETURN(!prev_new->info.uni.types, LOGMEM(mod->ctx), -1);
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001884
1885 for (i = 0; i < prev_new->info.uni.count; i++) {
1886 if (lys_copy_union_leafrefs(mod, parent, &(type->info.uni.types[i]), &(prev_new->info.uni.types[i]), unres)) {
1887 return -1;
1888 }
1889 }
1890
1891 prev_new->der = type->der;
1892 break;
1893 default:
1894 if (lys_type_dup(mod, parent, prev_new, type, 0, 0, unres)) {
1895 return -1;
1896 }
1897 break;
1898 }
1899 }
1900
1901 if (top_type) {
1902 memcpy(type, prev_new, sizeof *type);
1903 }
1904 return EXIT_SUCCESS;
1905}
1906
Radek Krejci43ce4b72017-01-04 11:02:38 +01001907API const void *
1908lys_ext_instance_substmt(const struct lys_ext_instance *ext)
1909{
1910 if (!ext) {
1911 return NULL;
1912 }
1913
Radek Krejcifebdad72017-02-06 11:35:51 +01001914 switch (ext->insubstmt) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001915 case LYEXT_SUBSTMT_SELF:
1916 case LYEXT_SUBSTMT_MODIFIER:
1917 case LYEXT_SUBSTMT_VERSION:
1918 return NULL;
1919 case LYEXT_SUBSTMT_ARGUMENT:
1920 if (ext->parent_type == LYEXT_PAR_EXT) {
1921 return ((struct lys_ext_instance*)ext->parent)->arg_value;
1922 }
1923 break;
1924 case LYEXT_SUBSTMT_BASE:
1925 if (ext->parent_type == LYEXT_PAR_TYPE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001926 return ((struct lys_type*)ext->parent)->info.ident.ref[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001927 } else if (ext->parent_type == LYEXT_PAR_IDENT) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001928 return ((struct lys_ident*)ext->parent)->base[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001929 }
1930 break;
1931 case LYEXT_SUBSTMT_BELONGSTO:
1932 if (ext->parent_type == LYEXT_PAR_MODULE && ((struct lys_module*)ext->parent)->type) {
1933 return ((struct lys_submodule*)ext->parent)->belongsto;
1934 }
1935 break;
1936 case LYEXT_SUBSTMT_CONFIG:
1937 case LYEXT_SUBSTMT_MANDATORY:
1938 if (ext->parent_type == LYEXT_PAR_NODE) {
1939 return &((struct lys_node*)ext->parent)->flags;
1940 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1941 return &((struct lys_deviate*)ext->parent)->flags;
1942 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1943 return &((struct lys_refine*)ext->parent)->flags;
1944 }
1945 break;
1946 case LYEXT_SUBSTMT_CONTACT:
1947 if (ext->parent_type == LYEXT_PAR_MODULE) {
1948 return ((struct lys_module*)ext->parent)->contact;
1949 }
1950 break;
1951 case LYEXT_SUBSTMT_DEFAULT:
1952 if (ext->parent_type == LYEXT_PAR_NODE) {
1953 switch (((struct lys_node*)ext->parent)->nodetype) {
1954 case LYS_LEAF:
1955 case LYS_LEAFLIST:
1956 /* in case of leaf, the index is supposed to be 0, so it will return the
1957 * correct pointer despite the leaf structure does not have dflt as array */
Radek Krejcifebdad72017-02-06 11:35:51 +01001958 return ((struct lys_node_leaflist*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001959 case LYS_CHOICE:
1960 return ((struct lys_node_choice*)ext->parent)->dflt;
1961 default:
1962 /* internal error */
1963 break;
1964 }
1965 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1966 return ((struct lys_tpdf*)ext->parent)->dflt;
1967 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001968 return ((struct lys_deviate*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001969 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001970 return &((struct lys_refine*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001971 }
1972 break;
1973 case LYEXT_SUBSTMT_DESCRIPTION:
1974 switch (ext->parent_type) {
1975 case LYEXT_PAR_NODE:
1976 return ((struct lys_node*)ext->parent)->dsc;
1977 case LYEXT_PAR_MODULE:
1978 return ((struct lys_module*)ext->parent)->dsc;
1979 case LYEXT_PAR_IMPORT:
1980 return ((struct lys_import*)ext->parent)->dsc;
1981 case LYEXT_PAR_INCLUDE:
1982 return ((struct lys_include*)ext->parent)->dsc;
1983 case LYEXT_PAR_EXT:
1984 return ((struct lys_ext*)ext->parent)->dsc;
1985 case LYEXT_PAR_FEATURE:
1986 return ((struct lys_feature*)ext->parent)->dsc;
1987 case LYEXT_PAR_TPDF:
1988 return ((struct lys_tpdf*)ext->parent)->dsc;
1989 case LYEXT_PAR_TYPE_BIT:
1990 return ((struct lys_type_bit*)ext->parent)->dsc;
1991 case LYEXT_PAR_TYPE_ENUM:
1992 return ((struct lys_type_enum*)ext->parent)->dsc;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001993 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001994 return ((struct lys_restr*)ext->parent)->dsc;
1995 case LYEXT_PAR_WHEN:
1996 return ((struct lys_when*)ext->parent)->dsc;
1997 case LYEXT_PAR_IDENT:
1998 return ((struct lys_ident*)ext->parent)->dsc;
1999 case LYEXT_PAR_DEVIATION:
2000 return ((struct lys_deviation*)ext->parent)->dsc;
2001 case LYEXT_PAR_REVISION:
2002 return ((struct lys_revision*)ext->parent)->dsc;
2003 case LYEXT_PAR_REFINE:
2004 return ((struct lys_refine*)ext->parent)->dsc;
2005 default:
2006 break;
2007 }
2008 break;
2009 case LYEXT_SUBSTMT_ERRTAG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01002010 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01002011 return ((struct lys_restr*)ext->parent)->eapptag;
2012 }
2013 break;
2014 case LYEXT_SUBSTMT_ERRMSG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01002015 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01002016 return ((struct lys_restr*)ext->parent)->emsg;
2017 }
2018 break;
2019 case LYEXT_SUBSTMT_DIGITS:
2020 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_DEC64) {
2021 return &((struct lys_type*)ext->parent)->info.dec64.dig;
2022 }
2023 break;
2024 case LYEXT_SUBSTMT_KEY:
2025 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2026 return ((struct lys_node_list*)ext->parent)->keys;
2027 }
2028 break;
2029 case LYEXT_SUBSTMT_MAX:
2030 if (ext->parent_type == LYEXT_PAR_NODE) {
2031 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2032 return &((struct lys_node_list*)ext->parent)->max;
2033 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
2034 return &((struct lys_node_leaflist*)ext->parent)->max;
2035 }
2036 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2037 return &((struct lys_refine*)ext->parent)->mod.list.max;
2038 }
2039 break;
2040 case LYEXT_SUBSTMT_MIN:
2041 if (ext->parent_type == LYEXT_PAR_NODE) {
2042 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2043 return &((struct lys_node_list*)ext->parent)->min;
2044 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
2045 return &((struct lys_node_leaflist*)ext->parent)->min;
2046 }
2047 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2048 return &((struct lys_refine*)ext->parent)->mod.list.min;
2049 }
2050 break;
2051 case LYEXT_SUBSTMT_NAMESPACE:
2052 if (ext->parent_type == LYEXT_PAR_MODULE && !((struct lys_module*)ext->parent)->type) {
2053 return ((struct lys_module*)ext->parent)->ns;
2054 }
2055 break;
2056 case LYEXT_SUBSTMT_ORDEREDBY:
2057 if (ext->parent_type == LYEXT_PAR_NODE &&
2058 (((struct lys_node*)ext->parent)->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
2059 return &((struct lys_node_list*)ext->parent)->flags;
2060 }
2061 break;
2062 case LYEXT_SUBSTMT_ORGANIZATION:
2063 if (ext->parent_type == LYEXT_PAR_MODULE) {
2064 return ((struct lys_module*)ext->parent)->org;
2065 }
2066 break;
2067 case LYEXT_SUBSTMT_PATH:
2068 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
2069 return ((struct lys_type*)ext->parent)->info.lref.path;
2070 }
2071 break;
2072 case LYEXT_SUBSTMT_POSITION:
2073 if (ext->parent_type == LYEXT_PAR_TYPE_BIT) {
2074 return &((struct lys_type_bit*)ext->parent)->pos;
2075 }
2076 break;
2077 case LYEXT_SUBSTMT_PREFIX:
2078 if (ext->parent_type == LYEXT_PAR_MODULE) {
2079 /* covers also lys_submodule */
2080 return ((struct lys_module*)ext->parent)->prefix;
2081 } else if (ext->parent_type == LYEXT_PAR_IMPORT) {
2082 return ((struct lys_import*)ext->parent)->prefix;
2083 }
2084 break;
2085 case LYEXT_SUBSTMT_PRESENCE:
2086 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_CONTAINER) {
2087 return ((struct lys_node_container*)ext->parent)->presence;
2088 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2089 return ((struct lys_refine*)ext->parent)->mod.presence;
2090 }
2091 break;
2092 case LYEXT_SUBSTMT_REFERENCE:
2093 switch (ext->parent_type) {
2094 case LYEXT_PAR_NODE:
2095 return ((struct lys_node*)ext->parent)->ref;
2096 case LYEXT_PAR_MODULE:
2097 return ((struct lys_module*)ext->parent)->ref;
2098 case LYEXT_PAR_IMPORT:
2099 return ((struct lys_import*)ext->parent)->ref;
2100 case LYEXT_PAR_INCLUDE:
2101 return ((struct lys_include*)ext->parent)->ref;
2102 case LYEXT_PAR_EXT:
2103 return ((struct lys_ext*)ext->parent)->ref;
2104 case LYEXT_PAR_FEATURE:
2105 return ((struct lys_feature*)ext->parent)->ref;
2106 case LYEXT_PAR_TPDF:
2107 return ((struct lys_tpdf*)ext->parent)->ref;
2108 case LYEXT_PAR_TYPE_BIT:
2109 return ((struct lys_type_bit*)ext->parent)->ref;
2110 case LYEXT_PAR_TYPE_ENUM:
2111 return ((struct lys_type_enum*)ext->parent)->ref;
Radek Krejcifdc0d702017-01-23 15:58:38 +01002112 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01002113 return ((struct lys_restr*)ext->parent)->ref;
2114 case LYEXT_PAR_WHEN:
2115 return ((struct lys_when*)ext->parent)->ref;
2116 case LYEXT_PAR_IDENT:
2117 return ((struct lys_ident*)ext->parent)->ref;
2118 case LYEXT_PAR_DEVIATION:
2119 return ((struct lys_deviation*)ext->parent)->ref;
2120 case LYEXT_PAR_REVISION:
2121 return ((struct lys_revision*)ext->parent)->ref;
2122 case LYEXT_PAR_REFINE:
2123 return ((struct lys_refine*)ext->parent)->ref;
2124 default:
2125 break;
2126 }
2127 break;
Radek Krejcibe336392017-02-07 10:54:24 +01002128 case LYEXT_SUBSTMT_REQINSTANCE:
Radek Krejci43ce4b72017-01-04 11:02:38 +01002129 if (ext->parent_type == LYEXT_PAR_TYPE) {
2130 if (((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
2131 return &((struct lys_type*)ext->parent)->info.lref.req;
2132 } else if (((struct lys_type*)ext->parent)->base == LY_TYPE_INST) {
2133 return &((struct lys_type*)ext->parent)->info.inst.req;
2134 }
2135 }
2136 break;
2137 case LYEXT_SUBSTMT_REVISIONDATE:
2138 if (ext->parent_type == LYEXT_PAR_IMPORT) {
2139 return ((struct lys_import*)ext->parent)->rev;
2140 } else if (ext->parent_type == LYEXT_PAR_INCLUDE) {
2141 return ((struct lys_include*)ext->parent)->rev;
2142 }
2143 break;
2144 case LYEXT_SUBSTMT_STATUS:
2145 switch (ext->parent_type) {
2146 case LYEXT_PAR_NODE:
2147 case LYEXT_PAR_IDENT:
2148 case LYEXT_PAR_TPDF:
2149 case LYEXT_PAR_EXT:
2150 case LYEXT_PAR_FEATURE:
2151 case LYEXT_PAR_TYPE_ENUM:
2152 case LYEXT_PAR_TYPE_BIT:
2153 /* in all structures the flags member is at the same offset */
2154 return &((struct lys_node*)ext->parent)->flags;
2155 default:
2156 break;
2157 }
2158 break;
2159 case LYEXT_SUBSTMT_UNIQUE:
2160 if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01002161 return &((struct lys_deviate*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01002162 } else if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
Radek Krejcifebdad72017-02-06 11:35:51 +01002163 return &((struct lys_node_list*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01002164 }
2165 break;
2166 case LYEXT_SUBSTMT_UNITS:
2167 if (ext->parent_type == LYEXT_PAR_NODE &&
2168 (((struct lys_node*)ext->parent)->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2169 /* units is at the same offset in both lys_node_leaf and lys_node_leaflist */
2170 return ((struct lys_node_leaf*)ext->parent)->units;
2171 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
2172 return ((struct lys_tpdf*)ext->parent)->units;
2173 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
2174 return ((struct lys_deviate*)ext->parent)->units;
2175 }
2176 break;
2177 case LYEXT_SUBSTMT_VALUE:
2178 if (ext->parent_type == LYEXT_PAR_TYPE_ENUM) {
2179 return &((struct lys_type_enum*)ext->parent)->value;
2180 }
2181 break;
2182 case LYEXT_SUBSTMT_YINELEM:
2183 if (ext->parent_type == LYEXT_PAR_EXT) {
2184 return &((struct lys_ext*)ext->parent)->flags;
2185 }
2186 break;
2187 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002188 LOGINT(ext->module->ctx);
Radek Krejci43ce4b72017-01-04 11:02:38 +01002189 return NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01002190}
2191
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02002192static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002193lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci5138e9f2017-04-12 13:10:46 +02002194 int in_grp, int shallow, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02002195{
2196 int i;
2197
Radek Krejci3733a802015-06-19 13:43:21 +02002198 new->base = old->base;
2199 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02002200 new->parent = (struct lys_tpdf *)parent;
Radek Krejcif0bb3602017-01-25 17:05:08 +01002201 new->ext_size = old->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01002202 if (lys_ext_dup(mod->ctx, mod, old->ext, old->ext_size, new, LYEXT_PAR_TYPE, &new->ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01002203 return -1;
Radek Krejcie534c132016-11-23 13:32:31 +01002204 }
Radek Krejci3733a802015-06-19 13:43:21 +02002205
Michal Vasko1c007172017-03-10 10:20:44 +01002206 i = unres_schema_find(unres, -1, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002207 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01002208 /* HACK (serious one) for unres */
2209 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02002210 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002211 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, in_grp,
2212 shallow, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02002213 } else {
2214 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
2215 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02002216 /* all these unres additions can fail even though they did not before */
Michal Vasko1c007172017-03-10 10:20:44 +01002217 if (!new->der || (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent) == -1)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002218 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02002219 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02002220 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002221 }
2222
Radek Krejci5138e9f2017-04-12 13:10:46 +02002223 return type_dup(mod, parent, new, old, new->base, in_grp, shallow, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02002224}
2225
2226void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002227lys_type_free(struct ly_ctx *ctx, struct lys_type *type,
2228 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002229{
Radek Krejcidce5f972017-09-12 15:47:49 +02002230 unsigned int i;
Radek Krejci5a065542015-05-22 15:02:07 +02002231
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002232 assert(ctx);
2233 if (!type) {
2234 return;
2235 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002236
Radek Krejci5138e9f2017-04-12 13:10:46 +02002237 lys_extension_instances_free(ctx, type->ext, type->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02002240 case LY_TYPE_BINARY:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002241 lys_restr_free(ctx, type->info.binary.length, private_destructor);
Radek Krejci0bd5db42015-06-19 13:30:07 +02002242 free(type->info.binary.length);
2243 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02002244 case LY_TYPE_BITS:
2245 for (i = 0; i < type->info.bits.count; i++) {
2246 lydict_remove(ctx, type->info.bits.bit[i].name);
2247 lydict_remove(ctx, type->info.bits.bit[i].dsc);
2248 lydict_remove(ctx, type->info.bits.bit[i].ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002249 lys_iffeature_free(ctx, type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size, 0,
Radek Krejci5138e9f2017-04-12 13:10:46 +02002250 private_destructor);
2251 lys_extension_instances_free(ctx, type->info.bits.bit[i].ext, type->info.bits.bit[i].ext_size,
2252 private_destructor);
Radek Krejci994b6f62015-06-18 16:47:27 +02002253 }
2254 free(type->info.bits.bit);
2255 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02002256
2257 case LY_TYPE_DEC64:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002258 lys_restr_free(ctx, type->info.dec64.range, private_destructor);
Radek Krejcif9401c32015-06-26 16:47:36 +02002259 free(type->info.dec64.range);
2260 break;
2261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 case LY_TYPE_ENUM:
2263 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002264 lydict_remove(ctx, type->info.enums.enm[i].name);
2265 lydict_remove(ctx, type->info.enums.enm[i].dsc);
2266 lydict_remove(ctx, type->info.enums.enm[i].ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002267 lys_iffeature_free(ctx, type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size, 0,
Radek Krejci5138e9f2017-04-12 13:10:46 +02002268 private_destructor);
2269 lys_extension_instances_free(ctx, type->info.enums.enm[i].ext, type->info.enums.enm[i].ext_size,
2270 private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002271 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02002272 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002273 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02002274
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02002275 case LY_TYPE_INT8:
2276 case LY_TYPE_INT16:
2277 case LY_TYPE_INT32:
2278 case LY_TYPE_INT64:
2279 case LY_TYPE_UINT8:
2280 case LY_TYPE_UINT16:
2281 case LY_TYPE_UINT32:
2282 case LY_TYPE_UINT64:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002283 lys_restr_free(ctx, type->info.num.range, private_destructor);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02002284 free(type->info.num.range);
2285 break;
2286
Radek Krejcidc4c1412015-06-19 15:39:54 +02002287 case LY_TYPE_LEAFREF:
2288 lydict_remove(ctx, type->info.lref.path);
2289 break;
2290
Radek Krejci3733a802015-06-19 13:43:21 +02002291 case LY_TYPE_STRING:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002292 lys_restr_free(ctx, type->info.str.length, private_destructor);
Radek Krejci3733a802015-06-19 13:43:21 +02002293 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02002294 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002295 lys_restr_free(ctx, &type->info.str.patterns[i], private_destructor);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002296#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02002297 if (type->info.str.patterns_pcre) {
2298 pcre_free((pcre*)type->info.str.patterns_pcre[2 * i]);
2299 pcre_free_study((pcre_extra*)type->info.str.patterns_pcre[2 * i + 1]);
2300 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02002301#endif
Radek Krejci5fbc9162015-06-19 14:11:11 +02002302 }
2303 free(type->info.str.patterns);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002304#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02002305 free(type->info.str.patterns_pcre);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002306#endif
Radek Krejci3733a802015-06-19 13:43:21 +02002307 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02002308
Radek Krejcie4c366b2015-07-02 10:11:31 +02002309 case LY_TYPE_UNION:
2310 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002311 lys_type_free(ctx, &type->info.uni.types[i], private_destructor);
Radek Krejcie4c366b2015-07-02 10:11:31 +02002312 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02002313 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02002314 break;
2315
Michal Vaskod3282192016-09-05 11:27:57 +02002316 case LY_TYPE_IDENT:
2317 free(type->info.ident.ref);
2318 break;
2319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002320 default:
Michal Vaskod3282192016-09-05 11:27:57 +02002321 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 break;
2323 }
Radek Krejci5a065542015-05-22 15:02:07 +02002324}
2325
Radek Krejci1d82ef62015-08-07 14:44:40 +02002326static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002327lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf,
2328 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002329{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002330 assert(ctx);
2331 if (!tpdf) {
2332 return;
2333 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002335 lydict_remove(ctx, tpdf->name);
2336 lydict_remove(ctx, tpdf->dsc);
2337 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002338
Radek Krejci5138e9f2017-04-12 13:10:46 +02002339 lys_type_free(ctx, &tpdf->type, private_destructor);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002341 lydict_remove(ctx, tpdf->units);
2342 lydict_remove(ctx, tpdf->dflt);
Radek Krejcie534c132016-11-23 13:32:31 +01002343
Radek Krejci5138e9f2017-04-12 13:10:46 +02002344 lys_extension_instances_free(ctx, tpdf->ext, tpdf->ext_size, private_destructor);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002345}
2346
Radek Krejci1d82ef62015-08-07 14:44:40 +02002347static struct lys_when *
Radek Krejci5138e9f2017-04-12 13:10:46 +02002348lys_when_dup(struct lys_module *mod, struct lys_when *old, int shallow, struct unres_schema *unres)
Radek Krejci00768f42015-06-18 17:04:04 +02002349{
Radek Krejci76512572015-08-04 09:47:08 +02002350 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02002351
2352 if (!old) {
2353 return NULL;
2354 }
2355
2356 new = calloc(1, sizeof *new);
Michal Vasko53b7da02018-02-13 15:28:42 +01002357 LY_CHECK_ERR_RETURN(!new, LOGMEM(mod->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01002358 new->cond = lydict_insert(mod->ctx, old->cond, 0);
2359 new->dsc = lydict_insert(mod->ctx, old->dsc, 0);
2360 new->ref = lydict_insert(mod->ctx, old->ref, 0);
Radek Krejcif0bb3602017-01-25 17:05:08 +01002361 new->ext_size = old->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01002362 lys_ext_dup(mod->ctx, mod, old->ext, old->ext_size, new, LYEXT_PAR_WHEN, &new->ext, shallow, unres);
Radek Krejci00768f42015-06-18 17:04:04 +02002363
2364 return new;
2365}
2366
Michal Vasko0308dd62015-10-07 09:14:40 +02002367void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002368lys_when_free(struct ly_ctx *ctx, struct lys_when *w,
2369 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002370{
2371 if (!w) {
2372 return;
2373 }
2374
Radek Krejci5138e9f2017-04-12 13:10:46 +02002375 lys_extension_instances_free(ctx, w->ext, w->ext_size, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002376 lydict_remove(ctx, w->cond);
2377 lydict_remove(ctx, w->dsc);
2378 lydict_remove(ctx, w->ref);
2379
2380 free(w);
2381}
2382
Radek Krejcib7f5e412015-08-13 10:15:51 +02002383static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002384lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment *aug,
2385 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib7f5e412015-08-13 10:15:51 +02002386{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02002387 struct lys_node *next, *sub;
2388
Radek Krejcic071c542016-01-27 14:57:51 +01002389 /* children from a resolved augment are freed under the target node */
Radek Krejci0ec51da2016-12-14 16:42:03 +01002390 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002391 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002392 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002393 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02002394 }
2395
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002396 lydict_remove(ctx, aug->target_name);
2397 lydict_remove(ctx, aug->dsc);
2398 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002399
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002400 lys_iffeature_free(ctx, aug->iffeature, aug->iffeature_size, 0, private_destructor);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002401 lys_extension_instances_free(ctx, aug->ext, aug->ext_size, private_destructor);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002402
Radek Krejci5138e9f2017-04-12 13:10:46 +02002403 lys_when_free(ctx, aug->when, private_destructor);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002404}
2405
Radek Krejci1d82ef62015-08-07 14:44:40 +02002406static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002407lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident,
2408 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci6793db02015-05-22 17:49:54 +02002409{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002410 assert(ctx);
2411 if (!ident) {
2412 return;
2413 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002414
Radek Krejci018f1f52016-08-03 16:01:20 +02002415 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02002416 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002417 lydict_remove(ctx, ident->name);
2418 lydict_remove(ctx, ident->dsc);
2419 lydict_remove(ctx, ident->ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002420 lys_iffeature_free(ctx, ident->iffeature, ident->iffeature_size, 0, private_destructor);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002421 lys_extension_instances_free(ctx, ident->ext, ident->ext_size, private_destructor);
Radek Krejci6793db02015-05-22 17:49:54 +02002422
2423}
2424
Radek Krejci1d82ef62015-08-07 14:44:40 +02002425static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002426lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp,
2427 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002428{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002429 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002430
Radek Krejcid12f57b2015-08-06 10:43:39 +02002431 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002432 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002433 lys_tpdf_free(ctx, &grp->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002434 }
2435 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002436}
2437
Radek Krejci1d82ef62015-08-07 14:44:40 +02002438static void
Michal Vasko1e82a3b2018-07-03 12:16:58 +02002439lys_rpc_action_free(struct ly_ctx *ctx, struct lys_node_rpc_action *rpc_act,
2440 void (*private_destructor)(const struct lys_node *node, void *priv))
2441{
2442 int i;
2443
2444 /* handle only specific parts for LYS_GROUPING */
2445 for (i = 0; i < rpc_act->tpdf_size; i++) {
2446 lys_tpdf_free(ctx, &rpc_act->tpdf[i], private_destructor);
2447 }
2448 free(rpc_act->tpdf);
2449}
2450
2451static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002452lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io,
2453 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcid12f57b2015-08-06 10:43:39 +02002454{
2455 int i;
2456
2457 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
2458 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002459 lys_tpdf_free(ctx, &io->tpdf[i], private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002460 }
2461 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002462
2463 for (i = 0; i < io->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002464 lys_restr_free(ctx, &io->must[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002465 }
2466 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002467}
2468
Radek Krejci1d82ef62015-08-07 14:44:40 +02002469static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002470lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif,
2471 void (*private_destructor)(const struct lys_node *node, void *priv))
Pavol Vican7cff97e2016-08-09 14:56:08 +02002472{
2473 int i;
2474
2475 for (i = 0; i < notif->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002476 lys_restr_free(ctx, &notif->must[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002477 }
2478 free(notif->must);
2479
2480 for (i = 0; i < notif->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002481 lys_tpdf_free(ctx, &notif->tpdf[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002482 }
2483 free(notif->tpdf);
2484}
2485static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002486lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml,
2487 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci537cf382015-06-04 11:07:01 +02002488{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002489 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002490
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002491 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002492 lys_restr_free(ctx, &anyxml->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002493 }
2494 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002495
Radek Krejci5138e9f2017-04-12 13:10:46 +02002496 lys_when_free(ctx, anyxml->when, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002497}
2498
Radek Krejci1d82ef62015-08-07 14:44:40 +02002499static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002500lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf,
2501 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002502{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002503 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002504
Radek Krejci85a54be2016-10-20 12:39:56 +02002505 /* leafref backlinks */
2506 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002507
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002508 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002509 lys_restr_free(ctx, &leaf->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002510 }
2511 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002512
Radek Krejci5138e9f2017-04-12 13:10:46 +02002513 lys_when_free(ctx, leaf->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002514
Radek Krejci5138e9f2017-04-12 13:10:46 +02002515 lys_type_free(ctx, &leaf->type, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002516 lydict_remove(ctx, leaf->units);
2517 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02002518}
2519
Radek Krejci1d82ef62015-08-07 14:44:40 +02002520static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002521lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist,
2522 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002523{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002524 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002525
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002526 if (llist->backlinks) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002527 /* leafref backlinks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002528 ly_set_free(llist->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002529 }
2530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531 for (i = 0; i < llist->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002532 lys_restr_free(ctx, &llist->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002533 }
2534 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002535
Pavol Vican38321d02016-08-16 14:56:02 +02002536 for (i = 0; i < llist->dflt_size; i++) {
2537 lydict_remove(ctx, llist->dflt[i]);
2538 }
2539 free(llist->dflt);
2540
Radek Krejci5138e9f2017-04-12 13:10:46 +02002541 lys_when_free(ctx, llist->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002542
Radek Krejci5138e9f2017-04-12 13:10:46 +02002543 lys_type_free(ctx, &llist->type, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002544 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02002545}
2546
Radek Krejci1d82ef62015-08-07 14:44:40 +02002547static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002548lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list,
2549 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002550{
Radek Krejci581ce772015-11-10 17:22:40 +01002551 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002553 /* handle only specific parts for LY_NODE_LIST */
Michal Vaskoaaeab1d2018-02-16 09:36:46 +01002554 lys_when_free(ctx, list->when, private_destructor);
Radek Krejci537cf382015-06-04 11:07:01 +02002555
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002556 for (i = 0; i < list->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002557 lys_restr_free(ctx, &list->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002558 }
2559 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002560
Michal Vaskoaaeab1d2018-02-16 09:36:46 +01002561 for (i = 0; i < list->tpdf_size; i++) {
2562 lys_tpdf_free(ctx, &list->tpdf[i], private_destructor);
2563 }
2564 free(list->tpdf);
2565
2566 free(list->keys);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002568 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02002569 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002570 lydict_remove(ctx, list->unique[i].expr[j]);
2571 }
2572 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002573 }
2574 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02002575
Michal Vaskoaaeab1d2018-02-16 09:36:46 +01002576 lydict_remove(ctx, list->keys_str);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002577}
2578
Radek Krejci1d82ef62015-08-07 14:44:40 +02002579static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002580lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont,
2581 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002582{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002583 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002585 /* handle only specific parts for LY_NODE_CONTAINER */
2586 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02002587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002588 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002589 lys_tpdf_free(ctx, &cont->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002590 }
2591 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02002592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002593 for (i = 0; i < cont->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002594 lys_restr_free(ctx, &cont->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002595 }
2596 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002597
Radek Krejci5138e9f2017-04-12 13:10:46 +02002598 lys_when_free(ctx, cont->when, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002599}
2600
Radek Krejci1d82ef62015-08-07 14:44:40 +02002601static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002602lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f,
2603 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci3cf9e222015-06-18 11:37:50 +02002604{
2605 lydict_remove(ctx, f->name);
2606 lydict_remove(ctx, f->dsc);
2607 lydict_remove(ctx, f->ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002608 lys_iffeature_free(ctx, f->iffeature, f->iffeature_size, 0, private_destructor);
Radek Krejci9de2c042016-10-19 16:53:06 +02002609 ly_set_free(f->depfeatures);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002610 lys_extension_instances_free(ctx, f->ext, f->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002611}
2612
2613static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002614lys_extension_free(struct ly_ctx *ctx, struct lys_ext *e,
2615 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie534c132016-11-23 13:32:31 +01002616{
2617 lydict_remove(ctx, e->name);
2618 lydict_remove(ctx, e->dsc);
2619 lydict_remove(ctx, e->ref);
2620 lydict_remove(ctx, e->argument);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002621 lys_extension_instances_free(ctx, e->ext, e->ext_size, private_destructor);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002622}
2623
Radek Krejci1d82ef62015-08-07 14:44:40 +02002624static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002625lys_deviation_free(struct lys_module *module, struct lys_deviation *dev,
2626 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcieb00f512015-07-01 16:44:58 +02002627{
Radek Krejci581ce772015-11-10 17:22:40 +01002628 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01002629 struct ly_ctx *ctx;
2630 struct lys_node *next, *elem;
2631
2632 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002633
2634 lydict_remove(ctx, dev->target_name);
2635 lydict_remove(ctx, dev->dsc);
2636 lydict_remove(ctx, dev->ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002637 lys_extension_instances_free(ctx, dev->ext, dev->ext_size, private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002638
Pavol Vican64d0b762016-08-25 10:44:59 +02002639 if (!dev->deviate) {
Michal Vasko7427b262018-05-14 15:23:55 +02002640 return;
Pavol Vican64d0b762016-08-25 10:44:59 +02002641 }
2642
Michal Vasko7427b262018-05-14 15:23:55 +02002643 /* it could not be applied because it failed to be applied */
2644 if (dev->orig_node) {
2645 /* the module was freed, but we only need the context from orig_node, use ours */
2646 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2647 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
2648 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
2649 elem->module = module;
Michal Vaskoff006c12016-02-17 11:15:19 +01002650
Michal Vasko7427b262018-05-14 15:23:55 +02002651 LY_TREE_DFS_END(dev->orig_node, next, elem);
2652 }
2653 lys_node_free(dev->orig_node, NULL, 0);
2654 } else {
2655 /* it's just a shallow copy, freeing one node */
2656 dev->orig_node->module = module;
2657 lys_node_free(dev->orig_node, NULL, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002658 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002659 }
2660
Radek Krejcieb00f512015-07-01 16:44:58 +02002661 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002662 lys_extension_instances_free(ctx, dev->deviate[i].ext, dev->deviate[i].ext_size, private_destructor);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002663
Radek Krejcid5a5c282016-08-15 15:38:08 +02002664 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02002665 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002666 }
2667 free(dev->deviate[i].dflt);
2668
Radek Krejcieb00f512015-07-01 16:44:58 +02002669 lydict_remove(ctx, dev->deviate[i].units);
2670
2671 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2672 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002673 lys_restr_free(ctx, &dev->deviate[i].must[j], private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002674 }
2675 free(dev->deviate[i].must);
2676
2677 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002678 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
2679 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
2680 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01002681 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002682 }
2683 free(dev->deviate[i].unique);
2684 }
2685 }
2686 free(dev->deviate);
2687}
2688
Radek Krejci1d82ef62015-08-07 14:44:40 +02002689static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002690lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses,
2691 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie1fa8582015-06-08 09:46:45 +02002692{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002693 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02002694
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002695 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02002696 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002697 lydict_remove(ctx, uses->refine[i].dsc);
2698 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002699
Radek Krejcifde04bd2017-09-13 16:38:38 +02002700 lys_iffeature_free(ctx, uses->refine[i].iffeature, uses->refine[i].iffeature_size, 0, private_destructor);
2701
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002702 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002703 lys_restr_free(ctx, &uses->refine[i].must[j], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002704 }
2705 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002706
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002707 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02002708 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002709 }
2710 free(uses->refine[i].dflt);
2711
Radek Krejci5138e9f2017-04-12 13:10:46 +02002712 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002713
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002714 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002715 lydict_remove(ctx, uses->refine[i].mod.presence);
2716 }
2717 }
2718 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002719
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002720 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002721 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002722 }
2723 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002724
Radek Krejci5138e9f2017-04-12 13:10:46 +02002725 lys_when_free(ctx, uses->when, private_destructor);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002726}
2727
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002728void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002729lys_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 +02002730{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002732 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002734 if (!node) {
2735 return;
2736 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002738 assert(node->module);
2739 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002740
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002741 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002742
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002743 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002744 if (node->priv && private_destructor) {
2745 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002746 }
2747
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002748 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002749 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002750 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002751 lys_iffeature_free(ctx, node->iffeature, node->iffeature_size, shallow, private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002752 lydict_remove(ctx, node->dsc);
2753 lydict_remove(ctx, node->ref);
2754 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002755
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002756 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002757 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002758 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002759 }
2760 }
2761
Radek Krejci5138e9f2017-04-12 13:10:46 +02002762 lys_extension_instances_free(ctx, node->ext, node->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002763
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002764 /* specific part */
2765 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002766 case LYS_CONTAINER:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002767 lys_container_free(ctx, (struct lys_node_container *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002768 break;
Radek Krejci76512572015-08-04 09:47:08 +02002769 case LYS_CHOICE:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002770 lys_when_free(ctx, ((struct lys_node_choice *)node)->when, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002771 break;
Radek Krejci76512572015-08-04 09:47:08 +02002772 case LYS_LEAF:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002773 lys_leaf_free(ctx, (struct lys_node_leaf *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002774 break;
Radek Krejci76512572015-08-04 09:47:08 +02002775 case LYS_LEAFLIST:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002776 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002777 break;
Radek Krejci76512572015-08-04 09:47:08 +02002778 case LYS_LIST:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002779 lys_list_free(ctx, (struct lys_node_list *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002780 break;
Radek Krejci76512572015-08-04 09:47:08 +02002781 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002782 case LYS_ANYDATA:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002783 lys_anydata_free(ctx, (struct lys_node_anydata *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002784 break;
Radek Krejci76512572015-08-04 09:47:08 +02002785 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002786 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002787 break;
Radek Krejci76512572015-08-04 09:47:08 +02002788 case LYS_CASE:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002789 lys_when_free(ctx, ((struct lys_node_case *)node)->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002790 break;
Radek Krejci76512572015-08-04 09:47:08 +02002791 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002792 /* do nothing */
2793 break;
Radek Krejci76512572015-08-04 09:47:08 +02002794 case LYS_GROUPING:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02002795 lys_grp_free(ctx, (struct lys_node_grp *)node, private_destructor);
2796 break;
Radek Krejci76512572015-08-04 09:47:08 +02002797 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002798 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02002799 lys_rpc_action_free(ctx, (struct lys_node_rpc_action *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002800 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02002801 case LYS_NOTIF:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002802 lys_notif_free(ctx, (struct lys_node_notif *)node, private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002803 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002804 case LYS_INPUT:
2805 case LYS_OUTPUT:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002806 lys_inout_free(ctx, (struct lys_node_inout *)node, private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002807 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01002808 case LYS_EXT:
Michal Vasko591e0b22015-08-13 13:53:43 +02002809 case LYS_UNKNOWN:
Michal Vasko53b7da02018-02-13 15:28:42 +01002810 LOGINT(ctx);
Michal Vasko591e0b22015-08-13 13:53:43 +02002811 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002812 }
Radek Krejci5a065542015-05-22 15:02:07 +02002813
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002814 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002815 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002816 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002817}
2818
Radek Krejci2eee5c02016-12-06 19:18:05 +01002819API struct lys_module *
2820lys_implemented_module(const struct lys_module *mod)
Radek Krejci0fa54e92016-09-14 14:01:05 +02002821{
2822 struct ly_ctx *ctx;
2823 int i;
2824
2825 if (!mod || mod->implemented) {
2826 /* invalid argument or the module itself is implemented */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002827 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002828 }
2829
2830 ctx = mod->ctx;
2831 for (i = 0; i < ctx->models.used; i++) {
2832 if (!ctx->models.list[i]->implemented) {
2833 continue;
2834 }
2835
2836 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
2837 /* we have some revision of the module implemented */
2838 return ctx->models.list[i];
2839 }
2840 }
2841
2842 /* we have no revision of the module implemented, return the module itself,
2843 * it is up to the caller to set the module implemented when needed */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002844 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002845}
2846
Michal Vasko13b15832015-08-19 11:04:48 +02002847/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002848static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002849module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002850{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002851 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002852 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002853 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002855 assert(module->ctx);
2856 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002857
Michal Vaskob746fff2016-02-11 11:37:50 +01002858 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002859 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002860 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002861 lydict_remove(ctx, module->imp[i].dsc);
2862 lydict_remove(ctx, module->imp[i].ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002863 lys_extension_instances_free(ctx, module->imp[i].ext, module->imp[i].ext_size, private_destructor);
Radek Krejci225376f2016-02-16 17:36:22 +01002864 }
Radek Krejcidce51452015-06-16 15:20:08 +02002865 free(module->imp);
2866
Radek Krejcic071c542016-01-27 14:57:51 +01002867 /* submodules don't have data tree, the data nodes
2868 * are placed in the main module altogether */
2869 if (!module->type) {
2870 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002871 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002872 }
Radek Krejci21181962015-06-30 14:11:00 +02002873 }
Radek Krejci5a065542015-05-22 15:02:07 +02002874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002875 lydict_remove(ctx, module->dsc);
2876 lydict_remove(ctx, module->ref);
2877 lydict_remove(ctx, module->org);
2878 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002879 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002880
Radek Krejcieb00f512015-07-01 16:44:58 +02002881 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002882 for (i = 0; i < module->rev_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002883 lys_extension_instances_free(ctx, module->rev[i].ext, module->rev[i].ext_size, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002884 lydict_remove(ctx, module->rev[i].dsc);
2885 lydict_remove(ctx, module->rev[i].ref);
2886 }
2887 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002888
Radek Krejcieb00f512015-07-01 16:44:58 +02002889 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002890 for (i = 0; i < module->ident_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002891 lys_ident_free(ctx, &module->ident[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002892 }
2893 module->ident_size = 0;
2894 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002895
Radek Krejcieb00f512015-07-01 16:44:58 +02002896 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002897 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002898 lys_tpdf_free(ctx, &module->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002899 }
2900 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002901
Radek Krejcie534c132016-11-23 13:32:31 +01002902 /* extension instances */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002903 lys_extension_instances_free(ctx, module->ext, module->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002904
Radek Krejcieb00f512015-07-01 16:44:58 +02002905 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002906 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002907 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002908 }
2909 free(module->augment);
2910
Radek Krejcieb00f512015-07-01 16:44:58 +02002911 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002912 for (i = 0; i < module->features_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002913 lys_feature_free(ctx, &module->features[i], private_destructor);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002914 }
2915 free(module->features);
2916
Radek Krejcieb00f512015-07-01 16:44:58 +02002917 /* deviations */
2918 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002919 lys_deviation_free(module, &module->deviation[i], private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002920 }
2921 free(module->deviation);
2922
Radek Krejcie534c132016-11-23 13:32:31 +01002923 /* extensions */
2924 for (i = 0; i < module->extensions_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002925 lys_extension_free(ctx, &module->extensions[i], private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002926 }
2927 free(module->extensions);
2928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002930 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002931}
2932
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002933void
Michal Vaskob746fff2016-02-11 11:37:50 +01002934lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002935{
Michal Vasko10681e82018-01-16 14:54:16 +01002936 int i;
2937
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002938 if (!submodule) {
2939 return;
2940 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002941
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002942 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002943 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002944
Michal Vasko10681e82018-01-16 14:54:16 +01002945 /* include */
2946 for (i = 0; i < submodule->inc_size; i++) {
2947 lydict_remove(submodule->ctx, submodule->inc[i].dsc);
2948 lydict_remove(submodule->ctx, submodule->inc[i].ref);
2949 lys_extension_instances_free(submodule->ctx, submodule->inc[i].ext, submodule->inc[i].ext_size, private_destructor);
2950 /* complete submodule free is done only from main module since
2951 * submodules propagate their includes to the main module */
2952 }
2953 free(submodule->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002954
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002955 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002956}
2957
Radek Krejcib53154b2017-07-19 09:14:13 +02002958int
2959lys_ingrouping(const struct lys_node *node)
Radek Krejci3a5501d2016-07-18 22:03:34 +02002960{
2961 const struct lys_node *iter = node;
2962 assert(node);
2963
2964 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2965 if (!iter) {
2966 return 0;
2967 } else {
2968 return 1;
2969 }
2970}
2971
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002972/*
2973 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
2974 */
2975static struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01002976lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002977 struct unres_schema *unres, int shallow, int finalize)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002978{
Radek Krejci7b9f5662016-11-07 16:28:37 +01002979 struct lys_node *retval = NULL, *iter, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002980 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002981 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002982 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002983 struct unres_list_uniq *unique_info;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002984 uint16_t flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002985
Michal Vaskoc07187d2015-08-13 15:20:57 +02002986 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002987 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002988 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002989 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002990 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002991 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002992 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002993 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002994 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002995 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002996 struct lys_node_anydata *any = NULL;
2997 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002998 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002999 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02003000 struct lys_node_rpc_action *rpc = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02003001 struct lys_node_inout *io = NULL;
Radek Krejcic43151c2017-03-12 07:10:52 +01003002 struct lys_node_notif *ntf = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02003003 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003004 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003005
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003006 /* we cannot just duplicate memory since the strings are stored in
3007 * dictionary and we need to update dictionary counters.
3008 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003009
Radek Krejci1d82ef62015-08-07 14:44:40 +02003010 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02003011 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003012 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003013 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003014 break;
3015
Radek Krejci76512572015-08-04 09:47:08 +02003016 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003017 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02003018 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003019 break;
3020
Radek Krejci76512572015-08-04 09:47:08 +02003021 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003022 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02003023 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003024 break;
3025
Radek Krejci76512572015-08-04 09:47:08 +02003026 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003028 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003029 break;
3030
Radek Krejci76512572015-08-04 09:47:08 +02003031 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003032 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003033 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003034 break;
3035
Radek Krejci76512572015-08-04 09:47:08 +02003036 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02003037 case LYS_ANYDATA:
3038 any = calloc(1, sizeof *any);
3039 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003040 break;
3041
Radek Krejci76512572015-08-04 09:47:08 +02003042 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003043 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02003044 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003045 break;
3046
Radek Krejci76512572015-08-04 09:47:08 +02003047 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003048 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02003049 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003050 break;
3051
Radek Krejci76512572015-08-04 09:47:08 +02003052 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02003053 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02003054 rpc = calloc(1, sizeof *rpc);
3055 retval = (struct lys_node *)rpc;
3056 break;
3057
Radek Krejci76512572015-08-04 09:47:08 +02003058 case LYS_INPUT:
3059 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02003060 io = calloc(1, sizeof *io);
3061 retval = (struct lys_node *)io;
3062 break;
3063
Radek Krejci76512572015-08-04 09:47:08 +02003064 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02003065 ntf = calloc(1, sizeof *ntf);
3066 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02003067 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01003070 LOGINT(ctx);
Michal Vasko49168a22015-08-17 16:35:41 +02003071 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003072 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003073 LY_CHECK_ERR_RETURN(!retval, LOGMEM(ctx), NULL);
Michal Vasko253035f2015-12-17 16:58:13 +01003074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003075 /*
3076 * duplicate generic part of the structure
3077 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003078 retval->name = lydict_insert(ctx, node->name, 0);
3079 retval->dsc = lydict_insert(ctx, node->dsc, 0);
3080 retval->ref = lydict_insert(ctx, node->ref, 0);
3081 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003084 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003086 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003087
Radek Krejcif0bb3602017-01-25 17:05:08 +01003088 retval->ext_size = node->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01003089 if (lys_ext_dup(ctx, module, node->ext, node->ext_size, retval, LYEXT_PAR_NODE, &retval->ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003090 goto error;
3091 }
3092
Radek Krejci06214042016-11-04 16:25:58 +01003093 if (node->iffeature_size) {
3094 retval->iffeature_size = node->iffeature_size;
3095 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003096 LY_CHECK_ERR_GOTO(!retval->iffeature, LOGMEM(ctx), error);
Michal Vasko253035f2015-12-17 16:58:13 +01003097 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003098
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003099 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003100 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02003101 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
3102 if (size1) {
3103 /* there is something to duplicate */
3104
3105 /* duplicate compiled expression */
3106 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
3107 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01003108 LY_CHECK_ERR_GOTO(!retval->iffeature[i].expr, LOGMEM(ctx), error);
Radek Krejci9ff0a922016-07-14 13:08:05 +02003109 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
3110
3111 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02003112 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Michal Vasko53b7da02018-02-13 15:28:42 +01003113 LY_CHECK_ERR_GOTO(!retval->iffeature[i].features, LOGMEM(ctx); free(retval->iffeature[i].expr), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003114
Radek Krejci9ff0a922016-07-14 13:08:05 +02003115 for (j = 0; (unsigned int)j < size2; j++) {
3116 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
3117 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02003118 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02003119 /* feature is resolved in origin, so copy it
3120 * - duplication is used for instantiating groupings
3121 * and if-feature inside grouping is supposed to be
3122 * resolved inside the original grouping, so we want
3123 * to keep pointers to features from the grouping
3124 * context */
3125 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
3126 } else if (rc == -1) {
3127 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02003128 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02003129 }
3130 }
Radek Krejcif0bb3602017-01-25 17:05:08 +01003131
3132 /* duplicate if-feature's extensions */
3133 retval->iffeature[i].ext_size = node->iffeature[i].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01003134 if (lys_ext_dup(ctx, module, node->iffeature[i].ext, node->iffeature[i].ext_size,
Radek Krejci5138e9f2017-04-12 13:10:46 +02003135 &retval->iffeature[i], LYEXT_PAR_IFFEATURE, &retval->iffeature[i].ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003136 goto error;
3137 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003138 }
Michal Vaskoff006c12016-02-17 11:15:19 +01003139
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003140 /* inherit config flags */
Radek Krejci7b9f5662016-11-07 16:28:37 +01003141 p = parent;
3142 do {
3143 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
3144 } while (iter && iter->nodetype == LYS_AUGMENT && (p = lys_parent(iter)));
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003145 if (iter) {
3146 flags = iter->flags & LYS_CONFIG_MASK;
3147 } else {
3148 /* default */
3149 flags = LYS_CONFIG_W;
3150 }
3151
3152 switch (finalize) {
3153 case 1:
3154 /* inherit config flags */
3155 if (retval->flags & LYS_CONFIG_SET) {
3156 /* skip nodes with an explicit config value */
3157 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003158 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
3159 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003160 goto error;
3161 }
3162 break;
3163 }
3164
3165 if (retval->nodetype != LYS_USES) {
3166 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
3167 }
Radek Krejci2cc25322017-09-06 16:32:02 +02003168
3169 /* inherit status */
Radek Krejcie2807ea2017-09-07 10:52:21 +02003170 if ((parent->flags & LYS_STATUS_MASK) > (retval->flags & LYS_STATUS_MASK)) {
3171 /* but do it only in case the parent has a stonger status */
3172 retval->flags &= ~LYS_STATUS_MASK;
3173 retval->flags |= (parent->flags & LYS_STATUS_MASK);
3174 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003175 break;
3176 case 2:
3177 /* erase config flags */
3178 retval->flags &= ~LYS_CONFIG_MASK;
3179 retval->flags &= ~LYS_CONFIG_SET;
3180 break;
3181 }
3182
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003183 /* connect it to the parent */
Michal Vasko8d30dd82018-09-10 10:06:12 +02003184 if (lys_node_addchild(parent, retval->module, retval, 0)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003185 goto error;
3186 }
Radek Krejcidce51452015-06-16 15:20:08 +02003187
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003188 /* go recursively */
3189 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003190 LY_TREE_FOR(node->child, iter) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003191 if (iter->nodetype & LYS_GROUPING) {
3192 /* do not instantiate groupings */
3193 continue;
3194 }
Radek Krejci6ff885d2017-01-03 14:06:22 +01003195 if (!lys_node_dup_recursion(module, retval, iter, unres, 0, finalize)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003196 goto error;
3197 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 }
3199 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003200
3201 if (finalize == 1) {
3202 /* check that configuration lists have keys
3203 * - we really want to check keys_size in original node, because the keys are
3204 * not yet resolved here, it is done below in nodetype specific part */
3205 if ((retval->nodetype == LYS_LIST) && (retval->flags & LYS_CONFIG_W)
3206 && !((struct lys_node_list *)node)->keys_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003207 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003208 goto error;
3209 }
3210 }
Michal Vaskoff006c12016-02-17 11:15:19 +01003211 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003212 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003213 }
3214
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003215 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003216 * duplicate specific part of the structure
3217 */
3218 switch (node->nodetype) {
3219 case LYS_CONTAINER:
3220 if (cont_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003221 cont->when = lys_when_dup(module, cont_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003222 LY_CHECK_GOTO(!cont->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003223 }
3224 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003225
Radek Krejcia8d111f2017-05-31 13:57:37 +02003226 if (cont_orig->must) {
3227 cont->must = lys_restr_dup(module, cont_orig->must, cont_orig->must_size, shallow, unres);
3228 LY_CHECK_GOTO(!cont->must, error);
3229 cont->must_size = cont_orig->must_size;
3230 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003231
Radek Krejcif0bb3602017-01-25 17:05:08 +01003232 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
3233
3234 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003235 case LYS_CHOICE:
3236 if (choice_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003237 choice->when = lys_when_dup(module, choice_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003238 LY_CHECK_GOTO(!choice->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003239 }
3240
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003241 if (!shallow) {
3242 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003243 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
3244 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
3245 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003246 if (rc) {
3247 if (rc == EXIT_FAILURE) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003248 LOGINT(ctx);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003249 }
3250 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02003251 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003252 } else {
3253 /* useless to check return value, we don't know whether
3254 * there really wasn't any default defined or it just hasn't
3255 * been resolved, we just hope for the best :)
3256 */
3257 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02003258 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003259 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003260 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003261 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003262 break;
3263
3264 case LYS_LEAF:
Radek Krejcib53154b2017-07-19 09:14:13 +02003265 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), lys_ingrouping(retval), shallow, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02003266 goto error;
3267 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003268 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
3269
3270 if (leaf_orig->dflt) {
3271 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003272 }
3273
Radek Krejcia8d111f2017-05-31 13:57:37 +02003274 if (leaf_orig->must) {
3275 leaf->must = lys_restr_dup(module, leaf_orig->must, leaf_orig->must_size, shallow, unres);
3276 LY_CHECK_GOTO(!leaf->must, error);
3277 leaf->must_size = leaf_orig->must_size;
3278 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003279
3280 if (leaf_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003281 leaf->when = lys_when_dup(module, leaf_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003282 LY_CHECK_GOTO(!leaf->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003283 }
3284 break;
3285
3286 case LYS_LEAFLIST:
Radek Krejcib53154b2017-07-19 09:14:13 +02003287 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), lys_ingrouping(retval), shallow, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02003288 goto error;
3289 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003290 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
3291
3292 llist->min = llist_orig->min;
3293 llist->max = llist_orig->max;
3294
Radek Krejcia8d111f2017-05-31 13:57:37 +02003295 if (llist_orig->must) {
3296 llist->must = lys_restr_dup(module, llist_orig->must, llist_orig->must_size, shallow, unres);
3297 LY_CHECK_GOTO(!llist->must, error);
3298 llist->must_size = llist_orig->must_size;
3299 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003300
Radek Krejcia8d111f2017-05-31 13:57:37 +02003301 if (llist_orig->dflt) {
3302 llist->dflt = malloc(llist_orig->dflt_size * sizeof *llist->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01003303 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003304 llist->dflt_size = llist_orig->dflt_size;
Radek Krejcia8d111f2017-05-31 13:57:37 +02003305
Radek Krejcic699e422017-06-02 15:18:58 +02003306 for (i = 0; i < llist->dflt_size; i++) {
3307 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
Radek Krejci51673202016-11-01 17:00:32 +01003308 }
3309 }
3310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003311 if (llist_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003312 llist->when = lys_when_dup(module, llist_orig->when, shallow, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003313 }
3314 break;
3315
3316 case LYS_LIST:
3317 list->min = list_orig->min;
3318 list->max = list_orig->max;
3319
Radek Krejcia8d111f2017-05-31 13:57:37 +02003320 if (list_orig->must) {
3321 list->must = lys_restr_dup(module, list_orig->must, list_orig->must_size, shallow, unres);
3322 LY_CHECK_GOTO(!list->must, error);
3323 list->must_size = list_orig->must_size;
3324 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325
Radek Krejcif0bb3602017-01-25 17:05:08 +01003326 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Michal Vasko38d01f72015-06-15 09:41:06 +02003327
Radek Krejcia8d111f2017-05-31 13:57:37 +02003328 if (list_orig->keys_size) {
3329 list->keys = calloc(list_orig->keys_size, sizeof *list->keys);
Michal Vasko53b7da02018-02-13 15:28:42 +01003330 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
Radek Krejci5c08a992016-11-02 13:30:04 +01003331 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003332 list->keys_size = list_orig->keys_size;
Michal Vasko0ea41032015-06-16 08:53:55 +02003333
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003334 if (!shallow) {
Radek Krejci7a1e6072018-08-13 14:59:16 +02003335 if (unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci5c08a992016-11-02 13:30:04 +01003336 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003337 }
Michal Vasko0ea41032015-06-16 08:53:55 +02003338 } else {
Radek Krejcia8d111f2017-05-31 13:57:37 +02003339 memcpy(list->keys, list_orig->keys, list_orig->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02003340 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003341 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003342
Radek Krejcia8d111f2017-05-31 13:57:37 +02003343 if (list_orig->unique) {
3344 list->unique = malloc(list_orig->unique_size * sizeof *list->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01003345 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003346 list->unique_size = list_orig->unique_size;
Radek Krejci581ce772015-11-10 17:22:40 +01003347
Radek Krejcic699e422017-06-02 15:18:58 +02003348 for (i = 0; i < list->unique_size; ++i) {
3349 list->unique[i].expr = malloc(list_orig->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01003350 LY_CHECK_ERR_GOTO(!list->unique[i].expr, LOGMEM(ctx), error);
Radek Krejcic699e422017-06-02 15:18:58 +02003351 list->unique[i].expr_size = list_orig->unique[i].expr_size;
3352 for (j = 0; j < list->unique[i].expr_size; j++) {
3353 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
3354
3355 /* if it stays in unres list, duplicate it also there */
3356 unique_info = malloc(sizeof *unique_info);
Michal Vasko53b7da02018-02-13 15:28:42 +01003357 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM(ctx), error);
Radek Krejcic699e422017-06-02 15:18:58 +02003358 unique_info->list = (struct lys_node *)list;
3359 unique_info->expr = list->unique[i].expr[j];
3360 unique_info->trg_type = &list->unique[i].trg_type;
3361 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
3362 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003363 }
3364 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003366 if (list_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003367 list->when = lys_when_dup(module, list_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003368 LY_CHECK_GOTO(!list->when, error);
Radek Krejciefaeba32015-05-27 14:30:57 +02003369 }
Radek Krejcidce51452015-06-16 15:20:08 +02003370 break;
3371
3372 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02003373 case LYS_ANYDATA:
Radek Krejcia8d111f2017-05-31 13:57:37 +02003374 if (any_orig->must) {
3375 any->must = lys_restr_dup(module, any_orig->must, any_orig->must_size, shallow, unres);
3376 LY_CHECK_GOTO(!any->must, error);
3377 any->must_size = any_orig->must_size;
3378 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003379
Radek Krejcibf2abff2016-08-23 15:51:52 +02003380 if (any_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003381 any->when = lys_when_dup(module, any_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003382 LY_CHECK_GOTO(!any->when, error);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003383 }
3384 break;
3385
3386 case LYS_USES:
3387 uses->grp = uses_orig->grp;
3388
3389 if (uses_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003390 uses->when = lys_when_dup(module, uses_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003391 LY_CHECK_GOTO(!uses->when, error);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003392 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003393 /* it is not needed to duplicate refine, nor augment. They are already applied to the uses children */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003394 break;
3395
3396 case LYS_CASE:
3397 if (cs_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003398 cs->when = lys_when_dup(module, cs_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003399 LY_CHECK_GOTO(!cs->when, error);
Radek Krejcidce51452015-06-16 15:20:08 +02003400 }
3401 break;
3402
Radek Krejci96935402016-11-04 16:27:28 +01003403 case LYS_ACTION:
Radek Krejcidce51452015-06-16 15:20:08 +02003404 case LYS_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003405 case LYS_INPUT:
3406 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02003407 case LYS_NOTIF:
Radek Krejcif0bb3602017-01-25 17:05:08 +01003408 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003409 break;
3410
3411 default:
3412 /* LY_NODE_AUGMENT */
Michal Vasko53b7da02018-02-13 15:28:42 +01003413 LOGINT(ctx);
Michal Vasko49168a22015-08-17 16:35:41 +02003414 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003415 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003416
3417 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02003418
3419error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003420 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02003421 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003422}
3423
Radek Krejcib3142312016-11-09 11:04:12 +01003424int
3425lys_has_xpath(const struct lys_node *node)
3426{
3427 assert(node);
3428
3429 switch (node->nodetype) {
3430 case LYS_AUGMENT:
3431 if (((struct lys_node_augment *)node)->when) {
3432 return 1;
3433 }
3434 break;
3435 case LYS_CASE:
3436 if (((struct lys_node_case *)node)->when) {
3437 return 1;
3438 }
3439 break;
3440 case LYS_CHOICE:
3441 if (((struct lys_node_choice *)node)->when) {
3442 return 1;
3443 }
3444 break;
3445 case LYS_ANYDATA:
3446 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
3447 return 1;
3448 }
3449 break;
3450 case LYS_LEAF:
3451 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
3452 return 1;
3453 }
3454 break;
3455 case LYS_LEAFLIST:
3456 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
3457 return 1;
3458 }
3459 break;
3460 case LYS_LIST:
3461 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
3462 return 1;
3463 }
3464 break;
3465 case LYS_CONTAINER:
3466 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
3467 return 1;
3468 }
3469 break;
3470 case LYS_INPUT:
3471 case LYS_OUTPUT:
3472 if (((struct lys_node_inout *)node)->must_size) {
3473 return 1;
3474 }
3475 break;
3476 case LYS_NOTIF:
3477 if (((struct lys_node_notif *)node)->must_size) {
3478 return 1;
3479 }
3480 break;
3481 case LYS_USES:
3482 if (((struct lys_node_uses *)node)->when) {
3483 return 1;
3484 }
3485 break;
3486 default:
3487 /* does not have XPath */
3488 break;
3489 }
3490
3491 return 0;
3492}
3493
Michal Vasko568b1952018-01-30 15:53:30 +01003494int
3495lys_type_is_local(const struct lys_type *type)
3496{
3497 if (!type->der->module) {
3498 /* build-in type */
3499 return 1;
3500 }
3501 /* type->parent can be either a typedef or leaf/leaf-list, but module pointers are compatible */
3502 return (lys_main_module(type->der->module) == lys_main_module(((struct lys_tpdf *)type->parent)->module));
3503}
3504
Radek Krejci2cc25322017-09-06 16:32:02 +02003505/*
3506 * shallow -
3507 * - do not inherit status from the parent
3508 */
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003509struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01003510lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003511 struct unres_schema *unres, int shallow)
3512{
3513 struct lys_node *p = NULL;
Radek Krejcib3142312016-11-09 11:04:12 +01003514 int finalize = 0;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003515 struct lys_node *result, *iter, *next;
3516
3517 if (!shallow) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003518 /* get know where in schema tree we are to know what should be done during instantiation of the grouping */
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003519 for (p = parent;
3520 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
3521 p = lys_parent(p));
3522 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
3523 }
3524
Radek Krejci6ff885d2017-01-03 14:06:22 +01003525 result = lys_node_dup_recursion(module, parent, node, unres, shallow, finalize);
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003526 if (finalize) {
3527 /* check xpath expressions in the instantiated tree */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003528 for (iter = next = result; iter; iter = next) {
Radek Krejcib3142312016-11-09 11:04:12 +01003529 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
Radek Krejci3c48d042016-11-07 14:42:36 +01003530 /* invalid xpath */
3531 return NULL;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003532 }
3533
3534 /* select next item */
3535 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
3536 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
3537 next = NULL;
3538 } else {
3539 next = iter->child;
3540 }
3541 if (!next) {
3542 /* no children, try siblings */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003543 if (iter == result) {
3544 /* we are done, no next element to process */
3545 break;
3546 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003547 next = iter->next;
3548 }
3549 while (!next) {
3550 /* parent is already processed, go to its sibling */
3551 iter = lys_parent(iter);
Radek Krejci7212e0a2017-03-08 15:58:22 +01003552 if (lys_parent(iter) == lys_parent(result)) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003553 /* we are done, no next element to process */
3554 break;
3555 }
3556 next = iter->next;
3557 }
3558 }
3559 }
3560
3561 return result;
3562}
3563
Michal Vasko81c71442018-08-03 12:56:53 +02003564/**
3565 * @brief Switch contents of two same schema nodes. One of the nodes
3566 * is expected to be ashallow copy of the other.
3567 *
3568 * @param[in] node1 Node whose contents will be switched with \p node2.
3569 * @param[in] node2 Node whose contents will be switched with \p node1.
3570 */
3571static void
3572lys_node_switch(struct lys_node *node1, struct lys_node *node2)
Michal Vaskoff006c12016-02-17 11:15:19 +01003573{
Michal Vasko81c71442018-08-03 12:56:53 +02003574 const size_t mem_size = 104;
3575 uint8_t mem[mem_size];
3576 size_t offset, size;
Michal Vaskoff006c12016-02-17 11:15:19 +01003577
Michal Vasko81c71442018-08-03 12:56:53 +02003578 assert((node1->module == node2->module) && ly_strequal(node1->name, node2->name, 1) && (node1->nodetype == node2->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01003579
Michal Vasko81c71442018-08-03 12:56:53 +02003580 /*
3581 * Initially, the nodes were really switched in the tree which
3582 * caused problems for some other nodes with pointers (augments, leafrefs, ...)
3583 * because their pointers were not being updated. Code kept in case there is
3584 * a use of it in future (it took some debugging to cover all the cases).
3585
3586 * sibling next *
3587 if (node1->prev->next) {
3588 node1->prev->next = node2;
Michal Vaskoff006c12016-02-17 11:15:19 +01003589 }
3590
Michal Vasko81c71442018-08-03 12:56:53 +02003591 * sibling prev *
3592 if (node1->next) {
3593 node1->next->prev = node2;
Michal Vasko8328da82016-08-25 09:27:22 +02003594 } else {
Michal Vasko81c71442018-08-03 12:56:53 +02003595 for (child = node1->prev; child->prev->next; child = child->prev);
3596 child->prev = node2;
Michal Vaskoff006c12016-02-17 11:15:19 +01003597 }
3598
Michal Vasko81c71442018-08-03 12:56:53 +02003599 * next *
3600 node2->next = node1->next;
3601 node1->next = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01003602
Michal Vasko81c71442018-08-03 12:56:53 +02003603 * prev *
3604 if (node1->prev != node1) {
3605 node2->prev = node1->prev;
Michal Vaskoff006c12016-02-17 11:15:19 +01003606 }
Michal Vasko81c71442018-08-03 12:56:53 +02003607 node1->prev = node1;
Michal Vaskoff006c12016-02-17 11:15:19 +01003608
Michal Vasko81c71442018-08-03 12:56:53 +02003609 * parent child *
3610 if (node1->parent) {
3611 if (node1->parent->child == node1) {
3612 node1->parent->child = node2;
Radek Krejci30bfcd22017-01-27 16:54:48 +01003613 }
Michal Vasko81c71442018-08-03 12:56:53 +02003614 } else if (lys_main_module(node1->module)->data == node1) {
3615 lys_main_module(node1->module)->data = node2;
Michal Vaskoff006c12016-02-17 11:15:19 +01003616 }
3617
Michal Vasko81c71442018-08-03 12:56:53 +02003618 * parent *
3619 node2->parent = node1->parent;
3620 node1->parent = NULL;
Radek Krejci30bfcd22017-01-27 16:54:48 +01003621
Michal Vasko81c71442018-08-03 12:56:53 +02003622 * child parent *
3623 LY_TREE_FOR(node1->child, child) {
3624 if (child->parent == node1) {
3625 child->parent = node2;
Michal Vaskoff006c12016-02-17 11:15:19 +01003626 }
3627 }
3628
Michal Vasko81c71442018-08-03 12:56:53 +02003629 * child *
3630 node2->child = node1->child;
3631 node1->child = NULL;
3632 */
Radek Krejcif0bb3602017-01-25 17:05:08 +01003633
Michal Vasko81c71442018-08-03 12:56:53 +02003634 /* switch common node part */
3635 offset = 3 * sizeof(char *);
3636 size = sizeof(uint16_t) + 6 * sizeof(uint8_t) + sizeof(struct lys_ext_instance **) + sizeof(struct lys_iffeature *);
3637 memcpy(mem, ((uint8_t *)node1) + offset, size);
3638 memcpy(((uint8_t *)node1) + offset, ((uint8_t *)node2) + offset, size);
3639 memcpy(((uint8_t *)node2) + offset, mem, size);
3640
3641 /* switch node-specific data */
3642 offset = sizeof(struct lys_node);
3643 switch (node1->nodetype) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003644 case LYS_CONTAINER:
Michal Vasko81c71442018-08-03 12:56:53 +02003645 size = sizeof(struct lys_node_container) - offset;
3646 break;
3647 case LYS_CHOICE:
3648 size = sizeof(struct lys_node_choice) - offset;
3649 break;
3650 case LYS_LEAF:
3651 size = sizeof(struct lys_node_leaf) - offset;
3652 break;
3653 case LYS_LEAFLIST:
3654 size = sizeof(struct lys_node_leaflist) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003655 break;
3656 case LYS_LIST:
Michal Vasko81c71442018-08-03 12:56:53 +02003657 size = sizeof(struct lys_node_list) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003658 break;
Michal Vasko81c71442018-08-03 12:56:53 +02003659 case LYS_ANYDATA:
3660 case LYS_ANYXML:
3661 size = sizeof(struct lys_node_anydata) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003662 break;
Michal Vasko81c71442018-08-03 12:56:53 +02003663 case LYS_CASE:
3664 size = sizeof(struct lys_node_case) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003665 break;
3666 case LYS_INPUT:
3667 case LYS_OUTPUT:
Michal Vasko81c71442018-08-03 12:56:53 +02003668 size = sizeof(struct lys_node_inout) - offset;
3669 break;
3670 case LYS_NOTIF:
3671 size = sizeof(struct lys_node_notif) - offset;
3672 break;
3673 case LYS_RPC:
3674 case LYS_ACTION:
3675 size = sizeof(struct lys_node_rpc_action) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003676 break;
3677 default:
Michal Vasko81c71442018-08-03 12:56:53 +02003678 assert(0);
3679 LOGINT(node1->module->ctx);
3680 return;
3681 }
3682 assert(size <= mem_size);
3683 memcpy(mem, ((uint8_t *)node1) + offset, size);
3684 memcpy(((uint8_t *)node1) + offset, ((uint8_t *)node2) + offset, size);
3685 memcpy(((uint8_t *)node2) + offset, mem, size);
3686
Michal Vasko114ffd42018-08-03 14:30:36 +02003687 /* typedefs were not copied to the backup node, so always reuse them,
3688 * in leaves/leaf-lists we must correct the type parent pointer */
Michal Vasko81c71442018-08-03 12:56:53 +02003689 switch (node1->nodetype) {
3690 case LYS_CONTAINER:
3691 ((struct lys_node_container *)node1)->tpdf_size = ((struct lys_node_container *)node2)->tpdf_size;
3692 ((struct lys_node_container *)node1)->tpdf = ((struct lys_node_container *)node2)->tpdf;
3693 ((struct lys_node_container *)node2)->tpdf_size = 0;
3694 ((struct lys_node_container *)node2)->tpdf = NULL;
3695 break;
3696 case LYS_LIST:
3697 ((struct lys_node_list *)node1)->tpdf_size = ((struct lys_node_list *)node2)->tpdf_size;
3698 ((struct lys_node_list *)node1)->tpdf = ((struct lys_node_list *)node2)->tpdf;
3699 ((struct lys_node_list *)node2)->tpdf_size = 0;
3700 ((struct lys_node_list *)node2)->tpdf = NULL;
3701 break;
3702 case LYS_RPC:
3703 case LYS_ACTION:
3704 ((struct lys_node_rpc_action *)node1)->tpdf_size = ((struct lys_node_rpc_action *)node2)->tpdf_size;
3705 ((struct lys_node_rpc_action *)node1)->tpdf = ((struct lys_node_rpc_action *)node2)->tpdf;
3706 ((struct lys_node_rpc_action *)node2)->tpdf_size = 0;
3707 ((struct lys_node_rpc_action *)node2)->tpdf = NULL;
3708 break;
3709 case LYS_NOTIF:
3710 ((struct lys_node_notif *)node1)->tpdf_size = ((struct lys_node_notif *)node2)->tpdf_size;
3711 ((struct lys_node_notif *)node1)->tpdf = ((struct lys_node_notif *)node2)->tpdf;
3712 ((struct lys_node_notif *)node2)->tpdf_size = 0;
3713 ((struct lys_node_notif *)node2)->tpdf = NULL;
3714 break;
3715 case LYS_INPUT:
3716 case LYS_OUTPUT:
3717 ((struct lys_node_inout *)node1)->tpdf_size = ((struct lys_node_inout *)node2)->tpdf_size;
3718 ((struct lys_node_inout *)node1)->tpdf = ((struct lys_node_inout *)node2)->tpdf;
3719 ((struct lys_node_inout *)node2)->tpdf_size = 0;
3720 ((struct lys_node_inout *)node2)->tpdf = NULL;
3721 break;
Michal Vasko114ffd42018-08-03 14:30:36 +02003722 case LYS_LEAF:
3723 case LYS_LEAFLIST:
3724 ((struct lys_node_leaf *)node1)->type.parent = (struct lys_tpdf *)node1;
3725 ((struct lys_node_leaf *)node2)->type.parent = (struct lys_tpdf *)node2;
Michal Vasko81c71442018-08-03 12:56:53 +02003726 default:
Radek Krejcif0bb3602017-01-25 17:05:08 +01003727 break;
3728 }
Michal Vaskoff006c12016-02-17 11:15:19 +01003729}
3730
3731void
Michal Vasko10681e82018-01-16 14:54:16 +01003732lys_free(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv), int free_subs, int remove_from_ctx)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003733{
3734 struct ly_ctx *ctx;
3735 int i;
3736
3737 if (!module) {
3738 return;
3739 }
3740
3741 /* remove schema from the context */
3742 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01003743 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02003744 for (i = 0; i < ctx->models.used; i++) {
3745 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01003746 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003747 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01003748 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 +02003749 ctx->models.list[ctx->models.used] = NULL;
3750 /* we are done */
3751 break;
3752 }
3753 }
3754 }
3755
3756 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01003757 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003758
Michal Vasko10681e82018-01-16 14:54:16 +01003759 /* include */
3760 for (i = 0; i < module->inc_size; i++) {
3761 lydict_remove(ctx, module->inc[i].dsc);
3762 lydict_remove(ctx, module->inc[i].ref);
3763 lys_extension_instances_free(ctx, module->inc[i].ext, module->inc[i].ext_size, private_destructor);
3764 /* complete submodule free is done only from main module since
3765 * submodules propagate their includes to the main module */
3766 if (free_subs) {
3767 lys_submodule_free(module->inc[i].submodule, private_destructor);
3768 }
3769 }
3770 free(module->inc);
3771
Radek Krejcida04f4a2015-05-21 12:54:09 +02003772 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01003773 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003774
3775 free(module);
3776}
Radek Krejci7e97c352015-06-19 16:26:34 +02003777
Radek Krejci9de2c042016-10-19 16:53:06 +02003778static void
3779lys_features_disable_recursive(struct lys_feature *f)
3780{
3781 unsigned int i;
3782 struct lys_feature *depf;
3783
3784 /* disable the feature */
3785 f->flags &= ~LYS_FENABLED;
3786
3787 /* by disabling feature we have to disable also all features that depends on this feature */
3788 if (f->depfeatures) {
3789 for (i = 0; i < f->depfeatures->number; i++) {
3790 depf = (struct lys_feature *)f->depfeatures->set.g[i];
3791 if (depf->flags & LYS_FENABLED) {
3792 lys_features_disable_recursive(depf);
3793 }
3794 }
3795 }
3796}
3797
Radek Krejci7e97c352015-06-19 16:26:34 +02003798/*
3799 * op: 1 - enable, 0 - disable
3800 */
3801static int
Michal Vasko1e62a092015-12-01 12:27:20 +01003802lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02003803{
3804 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003805 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02003806 int progress, faili, failj, failk;
3807
3808 uint8_t fsize;
3809 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02003810
3811 if (!module || !name || !strlen(name)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003812 LOGARG;
Radek Krejci7e97c352015-06-19 16:26:34 +02003813 return EXIT_FAILURE;
3814 }
3815
3816 if (!strcmp(name, "*")) {
3817 /* enable all */
3818 all = 1;
3819 }
3820
Radek Krejcia889c1f2016-10-19 15:50:11 +02003821 progress = failk = 1;
3822 while (progress && failk) {
3823 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
3824 if (i == -1) {
3825 fsize = module->features_size;
3826 f = module->features;
3827 } else {
3828 fsize = module->inc[i].submodule->features_size;
3829 f = module->inc[i].submodule->features;
3830 }
3831
3832 for (j = 0; j < fsize; j++) {
3833 if (all || !strcmp(f[j].name, name)) {
Michal Vasko34c3b552016-11-21 09:07:43 +01003834 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
3835 if (all) {
3836 /* skip already set features */
3837 continue;
3838 } else {
3839 /* feature already set correctly */
3840 return EXIT_SUCCESS;
3841 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003842 }
3843
3844 if (op) {
3845 /* check referenced features if they are enabled */
3846 for (k = 0; k < f[j].iffeature_size; k++) {
3847 if (!resolve_iffeature(&f[j].iffeature[k])) {
3848 if (all) {
3849 faili = i;
3850 failj = j;
3851 failk = k + 1;
3852 break;
3853 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003854 LOGERR(module->ctx, LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
Radek Krejcia889c1f2016-10-19 15:50:11 +02003855 f[j].name, k + 1);
3856 return EXIT_FAILURE;
3857 }
3858 }
3859 }
3860
3861 if (k == f[j].iffeature_size) {
3862 /* the last check passed, do the change */
3863 f[j].flags |= LYS_FENABLED;
3864 progress++;
3865 }
3866 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02003867 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02003868 progress++;
3869 }
3870 if (!all) {
3871 /* stop in case changing a single feature */
3872 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003873 }
3874 }
Radek Krejci7e97c352015-06-19 16:26:34 +02003875 }
3876 }
3877 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003878 if (failk) {
3879 /* print info about the last failing feature */
Michal Vasko53b7da02018-02-13 15:28:42 +01003880 LOGERR(module->ctx, LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
Radek Krejcia889c1f2016-10-19 15:50:11 +02003881 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
3882 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02003883 }
3884
3885 if (all) {
3886 return EXIT_SUCCESS;
3887 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02003888 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02003889 return EXIT_FAILURE;
3890 }
3891}
3892
3893API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003894lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003895{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003896 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02003897}
3898
3899API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003900lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003901{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003902 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003903}
3904
3905API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003906lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003907{
3908 int i, j;
3909
3910 if (!module || !feature) {
3911 return -1;
3912 }
3913
3914 /* search for the specified feature */
3915 /* module itself */
3916 for (i = 0; i < module->features_size; i++) {
3917 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003918 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003919 return 1;
3920 } else {
3921 return 0;
3922 }
3923 }
3924 }
3925
3926 /* submodules */
3927 for (j = 0; j < module->inc_size; j++) {
3928 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
3929 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003930 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003931 return 1;
3932 } else {
3933 return 0;
3934 }
3935 }
3936 }
3937 }
3938
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003939 /* feature definition not found */
3940 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02003941}
Michal Vasko2367e7c2015-07-07 11:33:44 +02003942
Radek Krejci96a10da2015-07-30 11:00:14 +02003943API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01003944lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02003945{
Radek Krejci96a10da2015-07-30 11:00:14 +02003946 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003947 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003948 unsigned int count;
3949
3950 if (!module) {
3951 return NULL;
3952 }
3953
3954 count = module->features_size;
3955 for (i = 0; i < module->inc_size; i++) {
3956 count += module->inc[i].submodule->features_size;
3957 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003958 result = malloc((count + 1) * sizeof *result);
Michal Vasko53b7da02018-02-13 15:28:42 +01003959 LY_CHECK_ERR_RETURN(!result, LOGMEM(module->ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003960
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003961 if (states) {
3962 *states = malloc((count + 1) * sizeof **states);
Michal Vasko53b7da02018-02-13 15:28:42 +01003963 LY_CHECK_ERR_RETURN(!(*states), LOGMEM(module->ctx); free(result), NULL);
Michal Vasko2367e7c2015-07-07 11:33:44 +02003964 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003965 count = 0;
3966
3967 /* module itself */
3968 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003969 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003970 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003971 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003972 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003973 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003974 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003975 }
3976 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003977 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003978 }
3979
3980 /* submodules */
3981 for (j = 0; j < module->inc_size; j++) {
3982 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003983 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003984 if (states) {
3985 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3986 (*states)[count] = 1;
3987 } else {
3988 (*states)[count] = 0;
3989 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003990 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003991 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003992 }
3993 }
3994
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003995 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003996 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003997
3998 return result;
3999}
Michal Vaskobaefb032015-09-24 14:52:10 +02004000
Radek Krejci6910a032016-04-13 10:06:21 +02004001API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01004002lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01004003{
Michal Vaskof53187d2017-01-13 13:23:14 +01004004 if (!node) {
4005 return NULL;
4006 }
4007
Radek Krejcic071c542016-01-27 14:57:51 +01004008 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
4009}
4010
Radek Krejci6910a032016-04-13 10:06:21 +02004011API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02004012lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01004013{
Michal Vaskof53187d2017-01-13 13:23:14 +01004014 if (!module) {
4015 return NULL;
4016 }
4017
Michal Vasko320e8532016-02-15 13:11:57 +01004018 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
4019}
4020
Michal Vaskobaefb032015-09-24 14:52:10 +02004021API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01004022lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02004023{
Radek Krejcif95b6292017-02-13 15:57:37 +01004024 struct lys_node *parent;
4025
4026 if (!node) {
Michal Vaskobaefb032015-09-24 14:52:10 +02004027 return NULL;
4028 }
4029
Radek Krejcif95b6292017-02-13 15:57:37 +01004030 if (node->nodetype == LYS_EXT) {
4031 if (((struct lys_ext_instance_complex*)node)->parent_type != LYEXT_PAR_NODE) {
4032 return NULL;
4033 }
4034 parent = (struct lys_node*)((struct lys_ext_instance_complex*)node)->parent;
4035 } else if (!node->parent) {
4036 return NULL;
4037 } else {
4038 parent = node->parent;
Michal Vaskobaefb032015-09-24 14:52:10 +02004039 }
4040
Radek Krejcif95b6292017-02-13 15:57:37 +01004041 if (parent->nodetype == LYS_AUGMENT) {
4042 return ((struct lys_node_augment *)parent)->target;
4043 } else {
4044 return parent;
4045 }
4046}
4047
4048struct lys_node **
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01004049lys_child(const struct lys_node *node, LYS_NODE nodetype)
Radek Krejcif95b6292017-02-13 15:57:37 +01004050{
4051 void *pp;
4052 assert(node);
4053
4054 if (node->nodetype == LYS_EXT) {
4055 pp = lys_ext_complex_get_substmt(lys_snode2stmt(nodetype), (struct lys_ext_instance_complex*)node, NULL);
4056 if (!pp) {
4057 return NULL;
4058 }
4059 return (struct lys_node **)pp;
Michal Vasko54d4c202017-08-09 14:09:18 +02004060 } else if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Radek Krejcif7fe2cb2017-08-09 10:27:12 +02004061 return NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +01004062 } else {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01004063 return (struct lys_node **)&node->child;
Radek Krejcif95b6292017-02-13 15:57:37 +01004064 }
Michal Vaskobaefb032015-09-24 14:52:10 +02004065}
Michal Vasko1b229152016-01-13 11:28:38 +01004066
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004067API void *
Michal Vasko1b229152016-01-13 11:28:38 +01004068lys_set_private(const struct lys_node *node, void *priv)
4069{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004070 void *prev;
4071
Michal Vasko1b229152016-01-13 11:28:38 +01004072 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004073 LOGARG;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004074 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01004075 }
4076
Mislav Novakovicb5529e52016-02-29 11:42:43 +01004077 prev = node->priv;
4078 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004079
4080 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01004081}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004082
Michal Vasko01c6fd22016-05-20 11:43:05 +02004083int
4084lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
4085{
Michal Vasko53b7da02018-02-13 15:28:42 +01004086 struct lys_node_leaf *iter;
4087 struct ly_ctx *ctx = leafref_target->module->ctx;
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004088
Michal Vasko48a573d2016-07-01 11:46:02 +02004089 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004090 LOGINT(ctx);
Michal Vasko01c6fd22016-05-20 11:43:05 +02004091 return -1;
4092 }
4093
Pavol Vican93175152016-08-30 15:34:44 +02004094 /* check for config flag */
Radek Krejcic688ca02017-03-20 12:54:39 +01004095 if (((struct lys_node_leaf*)leafref)->type.info.lref.req != -1 &&
4096 (leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004097 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, leafref,
Radek Krejcid831dd42017-03-16 12:59:30 +01004098 "The leafref %s is config but refers to a non-config %s.",
Pavol Vican93175152016-08-30 15:34:44 +02004099 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
4100 return -1;
4101 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004102 /* check for cycles */
Michal Vasko53b7da02018-02-13 15:28:42 +01004103 for (iter = leafref_target; iter && iter->type.base == LY_TYPE_LEAFREF; iter = iter->type.info.lref.target) {
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004104 if ((void *)iter == (void *)leafref) {
4105 /* cycle detected */
Michal Vasko53b7da02018-02-13 15:28:42 +01004106 LOGVAL(ctx, LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004107 return -1;
4108 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004109 }
4110
4111 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02004112 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02004113 if (!leafref_target->backlinks) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004114 leafref_target->backlinks = (void *)ly_set_new();
Radek Krejci85a54be2016-10-20 12:39:56 +02004115 if (!leafref_target->backlinks) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004116 LOGMEM(ctx);
Michal Vasko01c6fd22016-05-20 11:43:05 +02004117 return -1;
4118 }
4119 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01004120 ly_set_add(leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02004121
4122 return 0;
4123}
4124
Michal Vasko8548e082016-07-22 12:00:18 +02004125/* not needed currently */
4126#if 0
4127
Michal Vasko5b3492c2016-07-20 09:37:40 +02004128static const char *
4129lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
4130{
4131 struct lys_module *prev_mod;
4132 uint32_t str_len, mod_len, buf_idx;
4133
Radek Krejcibf2abff2016-08-23 15:51:52 +02004134 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02004135 LOGINT;
4136 return NULL;
4137 }
4138
4139 buf_idx = buf_len - 1;
4140 buf[buf_idx] = '\0';
4141
4142 while (node) {
4143 if (lys_parent(node)) {
4144 prev_mod = lys_node_module(lys_parent(node));
4145 } else {
4146 prev_mod = NULL;
4147 }
4148
Radek Krejcibf2abff2016-08-23 15:51:52 +02004149 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02004150 str_len = strlen(node->name);
4151
4152 if (prev_mod != node->module) {
4153 mod_len = strlen(node->module->name);
4154 } else {
4155 mod_len = 0;
4156 }
4157
4158 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
4159 LOGINT;
4160 return NULL;
4161 }
4162
4163 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
4164
4165 buf[buf_idx] = '/';
4166 if (mod_len) {
4167 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
4168 buf[buf_idx + 1 + mod_len] = ':';
4169 }
4170 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
4171 }
4172
4173 node = lys_parent(node);
4174 }
4175
4176 return buf + buf_idx;
4177}
4178
Michal Vasko8548e082016-07-22 12:00:18 +02004179#endif
4180
4181API struct ly_set *
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004182lys_xpath_atomize(const struct lys_node *ctx_node, enum lyxp_node_type ctx_node_type, const char *expr, int options)
Michal Vasko5b3492c2016-07-20 09:37:40 +02004183{
Michal Vasko508a50d2016-09-07 14:50:33 +02004184 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02004185 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004186 uint32_t i;
4187
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004188 if (!ctx_node || !expr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004189 LOGARG;
Michal Vasko8548e082016-07-22 12:00:18 +02004190 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004191 }
4192
Michal Vaskob94a5e42016-09-08 14:01:56 +02004193 /* adjust the root */
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004194 if ((ctx_node_type == LYXP_NODE_ROOT) || (ctx_node_type == LYXP_NODE_ROOT_CONFIG)) {
Michal Vaskob94a5e42016-09-08 14:01:56 +02004195 do {
Michal Vaskocb45f472018-02-12 10:47:42 +01004196 ctx_node = lys_getnext(NULL, NULL, lys_node_module(ctx_node), LYS_GETNEXT_NOSTATECHECK);
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004197 } while ((ctx_node_type == LYXP_NODE_ROOT_CONFIG) && (ctx_node->flags & LYS_CONFIG_R));
Michal Vaskob94a5e42016-09-08 14:01:56 +02004198 }
4199
Michal Vasko508a50d2016-09-07 14:50:33 +02004200 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02004201
4202 if (options & LYXP_MUST) {
4203 options &= ~LYXP_MUST;
4204 options |= LYXP_SNODE_MUST;
4205 } else if (options & LYXP_WHEN) {
4206 options &= ~LYXP_WHEN;
4207 options |= LYXP_SNODE_WHEN;
4208 } else {
4209 options |= LYXP_SNODE;
4210 }
4211
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004212 if (lyxp_atomize(expr, ctx_node, ctx_node_type, &set, options, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004213 free(set.val.snodes);
Michal Vasko53b7da02018-02-13 15:28:42 +01004214 LOGVAL(ctx_node->module->ctx, LYE_SPEC, LY_VLOG_LYS, ctx_node, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko8548e082016-07-22 12:00:18 +02004215 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004216 }
4217
Michal Vasko8548e082016-07-22 12:00:18 +02004218 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02004219
Michal Vasko508a50d2016-09-07 14:50:33 +02004220 for (i = 0; i < set.used; ++i) {
4221 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02004222 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02004223 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02004224 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02004225 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02004226 return NULL;
4227 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02004228 break;
4229 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02004230 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02004231 break;
4232 }
4233 }
4234
Michal Vasko508a50d2016-09-07 14:50:33 +02004235 free(set.val.snodes);
4236 return ret_set;
4237}
4238
4239API struct ly_set *
4240lys_node_xpath_atomize(const struct lys_node *node, int options)
4241{
4242 const struct lys_node *next, *elem, *parent, *tmp;
4243 struct lyxp_set set;
4244 struct ly_set *ret_set;
4245 uint16_t i;
4246
4247 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004248 LOGARG;
Michal Vasko508a50d2016-09-07 14:50:33 +02004249 return NULL;
4250 }
4251
4252 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
4253 if (!parent) {
4254 /* not in input, output, or notification */
4255 return NULL;
4256 }
4257
4258 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02004259 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004260 return NULL;
4261 }
4262
4263 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoc04173b2018-03-09 10:43:22 +01004264 if ((options & LYXP_NO_LOCAL) && !(elem->flags & (LYS_XPCONF_DEP | LYS_XPSTATE_DEP))) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004265 /* elem has no dependencies from other subtrees and local nodes get discarded */
4266 goto next_iter;
4267 }
4268
Michal Vaskof96dfb62017-08-17 12:23:49 +02004269 if (lyxp_node_atomize(elem, &set, 0)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004270 ly_set_free(ret_set);
4271 free(set.val.snodes);
4272 return NULL;
4273 }
4274
4275 for (i = 0; i < set.used; ++i) {
4276 switch (set.val.snodes[i].type) {
4277 case LYXP_NODE_ELEM:
4278 if (options & LYXP_NO_LOCAL) {
4279 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
4280 if (tmp) {
4281 /* in local subtree, discard */
4282 break;
4283 }
4284 }
4285 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
4286 ly_set_free(ret_set);
4287 free(set.val.snodes);
4288 return NULL;
4289 }
4290 break;
4291 default:
4292 /* ignore roots, text and attr should not ever appear */
4293 break;
4294 }
4295 }
4296
4297 free(set.val.snodes);
4298 if (!(options & LYXP_RECURSIVE)) {
4299 break;
4300 }
4301next_iter:
4302 LY_TREE_DFS_END(node, next, elem);
4303 }
4304
Michal Vasko8548e082016-07-22 12:00:18 +02004305 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004306}
4307
Michal Vasko44ab1462017-05-18 13:18:36 +02004308/* logs */
4309int
4310apply_aug(struct lys_node_augment *augment, struct unres_schema *unres)
Radek Krejci0ec51da2016-12-14 16:42:03 +01004311{
Michal Vasko44ab1462017-05-18 13:18:36 +02004312 struct lys_node *child, *parent;
4313 int clear_config;
4314 unsigned int u;
Michal Vaskod02e30e2018-01-22 13:35:48 +01004315 uint8_t *v;
Michal Vasko44ab1462017-05-18 13:18:36 +02004316 struct lys_ext_instance *ext;
Adam Weast4ca7edd2018-06-14 08:59:22 -05004317
Radek Krejci0ec51da2016-12-14 16:42:03 +01004318 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
4319
Radek Krejcic9d78692017-08-24 17:17:18 +02004320 if (!augment->child) {
4321 /* nothing to apply */
4322 goto success;
4323 }
4324
Radek Krejci0ec51da2016-12-14 16:42:03 +01004325 /* reconnect augmenting data into the target - add them to the target child list */
4326 if (augment->target->child) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004327 child = augment->target->child->prev;
4328 child->next = augment->child;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004329 augment->target->child->prev = augment->child->prev;
Michal Vasko44ab1462017-05-18 13:18:36 +02004330 augment->child->prev = child;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004331 } else {
4332 augment->target->child = augment->child;
4333 }
4334
Michal Vasko44ab1462017-05-18 13:18:36 +02004335 /* inherit config information from actual parent */
4336 for (parent = augment->target; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); parent = lys_parent(parent));
4337 clear_config = (parent) ? 1 : 0;
4338 LY_TREE_FOR(augment->child, child) {
4339 if (inherit_config_flag(child, augment->target->flags & LYS_CONFIG_MASK, clear_config)) {
4340 return -1;
4341 }
4342 }
4343
4344 /* inherit extensions if any */
4345 for (u = 0; u < augment->target->ext_size; u++) {
4346 ext = augment->target->ext[u]; /* shortcut */
4347 if (ext && ext->def->plugin && (ext->def->plugin->flags & LYEXT_OPT_INHERIT)) {
Michal Vaskod02e30e2018-01-22 13:35:48 +01004348 v = malloc(sizeof *v);
Michal Vasko53b7da02018-02-13 15:28:42 +01004349 LY_CHECK_ERR_RETURN(!v, LOGMEM(augment->module->ctx), -1);
Michal Vaskod02e30e2018-01-22 13:35:48 +01004350 *v = u;
4351 if (unres_schema_add_node(lys_main_module(augment->module), unres, &augment->target->ext,
4352 UNRES_EXT_FINALIZE, (struct lys_node *)v) == -1) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004353 /* something really bad happend since the extension finalization is not actually
4354 * being resolved while adding into unres, so something more serious with the unres
4355 * list itself must happened */
4356 return -1;
4357 }
4358 }
4359 }
4360
Radek Krejcic9d78692017-08-24 17:17:18 +02004361success:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004362 /* remove the flag about not applicability */
4363 augment->flags &= ~LYS_NOTAPPLIED;
Michal Vasko44ab1462017-05-18 13:18:36 +02004364 return EXIT_SUCCESS;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004365}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004366
Radek Krejcib2541a32016-12-12 16:45:57 +01004367static void
4368remove_aug(struct lys_node_augment *augment)
4369{
4370 struct lys_node *last, *elem;
4371
Michal Vaskof1aa47d2017-09-21 12:09:29 +02004372 if ((augment->flags & LYS_NOTAPPLIED) || !augment->target) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004373 /* skip already not applied augment */
Radek Krejcib2541a32016-12-12 16:45:57 +01004374 return;
4375 }
4376
4377 elem = augment->child;
4378 if (elem) {
4379 LY_TREE_FOR(elem, last) {
4380 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
4381 break;
4382 }
4383 }
4384 /* elem is first augment child, last is the last child */
4385
4386 /* parent child ptr */
4387 if (augment->target->child == elem) {
4388 augment->target->child = last->next;
4389 }
4390
4391 /* parent child next ptr */
4392 if (elem->prev->next) {
4393 elem->prev->next = last->next;
4394 }
4395
4396 /* parent child prev ptr */
4397 if (last->next) {
4398 last->next->prev = elem->prev;
4399 } else if (augment->target->child) {
4400 augment->target->child->prev = elem->prev;
4401 }
4402
4403 /* update augment children themselves */
4404 elem->prev = last;
4405 last->next = NULL;
4406 }
4407
Radek Krejci0ec51da2016-12-14 16:42:03 +01004408 /* augment->target still keeps the resolved target, but for lys_augment_free()
4409 * we have to keep information that this augment is not applied to free its data */
4410 augment->flags |= LYS_NOTAPPLIED;
Radek Krejcib2541a32016-12-12 16:45:57 +01004411}
4412
Radek Krejci30bfcd22017-01-27 16:54:48 +01004413/*
4414 * @param[in] module - the module where the deviation is defined
4415 */
4416static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004417lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004418{
Radek Krejcic9d78692017-08-24 17:17:18 +02004419 int ret, reapply = 0;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004420 char *parent_path;
4421 struct lys_node *target = NULL, *parent;
Michal Vasko5df038e2018-08-02 09:41:26 +02004422 struct lys_node_inout *inout;
Michal Vasko50576712017-07-28 12:28:33 +02004423 struct ly_set *set;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004424
4425 if (!dev->deviate) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004426 return;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004427 }
4428
4429 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
4430 if (dev->orig_node) {
4431 /* removing not-supported deviation ... */
4432 if (strrchr(dev->target_name, '/') != dev->target_name) {
4433 /* ... from a parent */
4434
4435 /* reconnect to its previous position */
4436 parent = dev->orig_node->parent;
Michal Vaskoa1074a52018-01-03 12:18:53 +01004437 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejcic9d78692017-08-24 17:17:18 +02004438 dev->orig_node->parent = NULL;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004439 /* the original node was actually from augment, we have to get know if the augment is
4440 * applied (its module is enabled and implemented). If yes, the node will be connected
4441 * to the augment and the linkage with the target will be fixed if needed, otherwise
4442 * it will be connected only to the augment */
Radek Krejcic9d78692017-08-24 17:17:18 +02004443 if (!(parent->flags & LYS_NOTAPPLIED)) {
4444 /* start with removing augment if applied before adding nodes, we have to make sure
4445 * that everything will be connect correctly */
4446 remove_aug((struct lys_node_augment *)parent);
4447 reapply = 1;
4448 }
4449 /* connect the deviated node back into the augment */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004450 lys_node_addchild(parent, NULL, dev->orig_node, 0);
Radek Krejcic9d78692017-08-24 17:17:18 +02004451 if (reapply) {
Radek Krejci30bfcd22017-01-27 16:54:48 +01004452 /* augment is supposed to be applied, so fix pointers in target and the status of the original node */
Michal Vasko74083ec2018-06-15 10:00:12 +02004453 assert(lys_node_module(parent)->implemented);
Michal Vasko823fbe02017-12-14 11:01:40 +01004454 parent->flags |= LYS_NOTAPPLIED; /* allow apply_aug() */
4455 apply_aug((struct lys_node_augment *)parent, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004456 }
Michal Vaskoa1074a52018-01-03 12:18:53 +01004457 } else if (parent && (parent->nodetype == LYS_USES)) {
4458 /* uses child */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004459 lys_node_addchild(parent, NULL, dev->orig_node, 0);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004460 } else {
4461 /* non-augment, non-toplevel */
4462 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
Michal Vasko50576712017-07-28 12:28:33 +02004463 ret = resolve_schema_nodeid(parent_path, NULL, module, &set, 0, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004464 free(parent_path);
Michal Vasko50576712017-07-28 12:28:33 +02004465 if (ret == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004466 LOGINT(module->ctx);
Michal Vasko50576712017-07-28 12:28:33 +02004467 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004468 return;
4469 }
Michal Vasko50576712017-07-28 12:28:33 +02004470 target = set->set.s[0];
4471 ly_set_free(set);
4472
Michal Vasko8d30dd82018-09-10 10:06:12 +02004473 lys_node_addchild(target, NULL, dev->orig_node, 0);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004474 }
4475 } else {
4476 /* ... from top-level data */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004477 lys_node_addchild(NULL, (struct lys_module *)dev->orig_node->module, dev->orig_node, 0);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004478 }
4479
4480 dev->orig_node = NULL;
4481 } else {
4482 /* adding not-supported deviation */
Michal Vasko50576712017-07-28 12:28:33 +02004483 ret = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4484 if (ret == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004485 LOGINT(module->ctx);
Michal Vasko50576712017-07-28 12:28:33 +02004486 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004487 return;
4488 }
Michal Vasko50576712017-07-28 12:28:33 +02004489 target = set->set.s[0];
4490 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004491
4492 /* unlink and store the original node */
4493 parent = target->parent;
4494 lys_node_unlink(target);
Michal Vasko5df038e2018-08-02 09:41:26 +02004495 if (parent) {
4496 if (parent->nodetype & (LYS_AUGMENT | LYS_USES)) {
4497 /* hack for augment, because when the original will be sometime reconnected back, we actually need
4498 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
4499 * path), so we need to remember the augment as an addition */
4500 /* we also need to remember the parent uses so that we connect it back to it when switching deviation state */
4501 target->parent = parent;
4502 } else if (parent->nodetype & (LYS_RPC | LYS_ACTION)) {
4503 /* re-create implicit node */
4504 inout = calloc(1, sizeof *inout);
4505 LY_CHECK_ERR_RETURN(!inout, LOGMEM(module->ctx), );
4506
4507 inout->nodetype = target->nodetype;
4508 inout->name = lydict_insert(module->ctx, (inout->nodetype == LYS_INPUT) ? "input" : "output", 0);
4509 inout->module = target->module;
4510 inout->flags = LYS_IMPLICIT;
4511
4512 /* insert it manually */
4513 assert(parent->child && !parent->child->next
4514 && (parent->child->nodetype == (inout->nodetype == LYS_INPUT ? LYS_OUTPUT : LYS_INPUT)));
4515 parent->child->next = (struct lys_node *)inout;
4516 inout->prev = parent->child;
4517 parent->child->prev = (struct lys_node *)inout;
4518 inout->parent = parent;
4519 }
Radek Krejci30bfcd22017-01-27 16:54:48 +01004520 }
4521 dev->orig_node = target;
4522 }
4523 } else {
Michal Vasko50576712017-07-28 12:28:33 +02004524 ret = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4525 if (ret == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004526 LOGINT(module->ctx);
Michal Vasko50576712017-07-28 12:28:33 +02004527 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004528 return;
4529 }
Michal Vasko50576712017-07-28 12:28:33 +02004530 target = set->set.s[0];
4531 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004532
Michal Vasko81c71442018-08-03 12:56:53 +02004533 /* contents are switched */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004534 lys_node_switch(target, dev->orig_node);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004535 }
4536}
4537
4538/* temporarily removes or applies deviations, updates module deviation flag accordingly */
4539void
Michal Vasko5a65f212018-03-19 15:08:08 +01004540lys_enable_deviations(struct lys_module *module)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004541{
4542 uint32_t i = 0, j;
4543 const struct lys_module *mod;
4544 const char *ptr;
Michal Vasko44ab1462017-05-18 13:18:36 +02004545 struct unres_schema *unres;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004546
4547 if (module->deviated) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004548 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01004549 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
Michal Vasko44ab1462017-05-18 13:18:36 +02004550
Radek Krejci30bfcd22017-01-27 16:54:48 +01004551 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
4552 if (mod == module) {
4553 continue;
4554 }
4555
4556 for (j = 0; j < mod->deviation_size; ++j) {
4557 ptr = strstr(mod->deviation[j].target_name, module->name);
4558 if (ptr && ptr[strlen(module->name)] == ':') {
Michal Vasko44ab1462017-05-18 13:18:36 +02004559 lys_switch_deviation(&mod->deviation[j], mod, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004560 }
4561 }
4562 }
4563
Michal Vasko5a65f212018-03-19 15:08:08 +01004564 assert(module->deviated == 2);
4565 module->deviated = 1;
4566
4567 for (j = 0; j < module->inc_size; j++) {
4568 if (module->inc[j].submodule->deviated) {
4569 module->inc[j].submodule->deviated = module->deviated;
4570 }
Radek Krejci30bfcd22017-01-27 16:54:48 +01004571 }
Michal Vasko5a65f212018-03-19 15:08:08 +01004572
4573 if (unres->count) {
4574 resolve_unres_schema(module, unres);
4575 }
4576 unres_schema_free(module, &unres, 1);
4577 }
4578}
4579
4580void
4581lys_disable_deviations(struct lys_module *module)
4582{
4583 uint32_t i, j;
4584 const struct lys_module *mod;
4585 const char *ptr;
4586 struct unres_schema *unres;
4587
4588 if (module->deviated) {
4589 unres = calloc(1, sizeof *unres);
4590 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
4591
4592 i = module->ctx->models.used;
4593 while (i--) {
4594 mod = module->ctx->models.list[i];
4595
4596 if (mod == module) {
4597 continue;
4598 }
4599
4600 j = mod->deviation_size;
4601 while (j--) {
4602 ptr = strstr(mod->deviation[j].target_name, module->name);
4603 if (ptr && ptr[strlen(module->name)] == ':') {
4604 lys_switch_deviation(&mod->deviation[j], mod, unres);
4605 }
4606 }
4607 }
4608
4609 assert(module->deviated == 1);
4610 module->deviated = 2;
4611
Radek Krejci29eac3d2017-06-01 16:50:02 +02004612 for (j = 0; j < module->inc_size; j++) {
4613 if (module->inc[j].submodule->deviated) {
4614 module->inc[j].submodule->deviated = module->deviated;
4615 }
4616 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004617
4618 if (unres->count) {
4619 resolve_unres_schema(module, unres);
4620 }
4621 unres_schema_free(module, &unres, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004622 }
4623}
4624
4625static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004626apply_dev(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004627{
Michal Vasko44ab1462017-05-18 13:18:36 +02004628 lys_switch_deviation(dev, module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004629
4630 assert(dev->orig_node);
Radek Krejci29eac3d2017-06-01 16:50:02 +02004631 lys_node_module(dev->orig_node)->deviated = 1; /* main module */
4632 dev->orig_node->module->deviated = 1; /* possible submodule */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004633}
4634
4635static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004636remove_dev(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004637{
4638 uint32_t idx = 0, j;
4639 const struct lys_module *mod;
Radek Krejci29eac3d2017-06-01 16:50:02 +02004640 struct lys_module *target_mod, *target_submod;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004641 const char *ptr;
4642
4643 if (dev->orig_node) {
4644 target_mod = lys_node_module(dev->orig_node);
Radek Krejci29eac3d2017-06-01 16:50:02 +02004645 target_submod = dev->orig_node->module;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004646 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004647 LOGINT(module->ctx);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004648 return;
4649 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004650 lys_switch_deviation(dev, module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004651
4652 /* clear the deviation flag if possible */
4653 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
4654 if ((mod == module) || (mod == target_mod)) {
4655 continue;
4656 }
4657
4658 for (j = 0; j < mod->deviation_size; ++j) {
4659 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
4660 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
4661 /* some other module deviation targets the inspected module, flag remains */
4662 break;
4663 }
4664 }
4665
4666 if (j < mod->deviation_size) {
4667 break;
4668 }
4669 }
4670
4671 if (!mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02004672 target_mod->deviated = 0; /* main module */
4673 target_submod->deviated = 0; /* possible submodule */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004674 }
4675}
4676
4677void
4678lys_sub_module_apply_devs_augs(struct lys_module *module)
4679{
4680 uint8_t u, v;
Michal Vasko44ab1462017-05-18 13:18:36 +02004681 struct unres_schema *unres;
4682
Michal Vasko74083ec2018-06-15 10:00:12 +02004683 assert(module->implemented);
4684
Michal Vasko44ab1462017-05-18 13:18:36 +02004685 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01004686 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
Radek Krejci30bfcd22017-01-27 16:54:48 +01004687
Michal Vasko1e82a3b2018-07-03 12:16:58 +02004688 /* apply deviations */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004689 for (u = 0; u < module->deviation_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004690 apply_dev(&module->deviation[u], module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004691 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02004692 /* apply augments */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004693 for (u = 0; u < module->augment_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004694 apply_aug(&module->augment[u], unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004695 }
4696
Michal Vasko1e82a3b2018-07-03 12:16:58 +02004697 /* apply deviations and augments defined in submodules */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004698 for (v = 0; v < module->inc_size; ++v) {
4699 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004700 apply_dev(&module->inc[v].submodule->deviation[u], module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004701 }
4702
4703 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004704 apply_aug(&module->inc[v].submodule->augment[u], unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004705 }
4706 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004707
4708 if (unres->count) {
4709 resolve_unres_schema(module, unres);
4710 }
4711 /* nothing else left to do even if something is not resolved */
4712 unres_schema_free(module, &unres, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004713}
4714
Radek Krejcib2541a32016-12-12 16:45:57 +01004715void
4716lys_sub_module_remove_devs_augs(struct lys_module *module)
4717{
Andrew Langefeldf9763242018-09-16 22:23:50 -05004718 uint8_t u, v, w;
Michal Vasko44ab1462017-05-18 13:18:36 +02004719 struct unres_schema *unres;
4720
4721 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01004722 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
Radek Krejcib2541a32016-12-12 16:45:57 +01004723
4724 /* remove applied deviations */
4725 for (u = 0; u < module->deviation_size; ++u) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02004726 /* the deviation could not be applied because it failed to be applied in the first place*/
Michal Vasko7427b262018-05-14 15:23:55 +02004727 if (module->deviation[u].orig_node) {
4728 remove_dev(&module->deviation[u], module, unres);
4729 }
Andrew Langefeldf9763242018-09-16 22:23:50 -05004730
4731 /* Free the deviation's must array(s). These are shallow copies of the arrays
4732 on the target node(s), so a deep free is not needed. */
4733 for (v = 0; v < module->deviation[u].deviate_size; ++v) {
4734 if (module->deviation[u].deviate[v].mod == LY_DEVIATE_ADD) {
4735 free(module->deviation[u].deviate[v].must);
4736 }
4737 }
Radek Krejcib2541a32016-12-12 16:45:57 +01004738 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004739 /* remove applied augments */
Radek Krejcib2541a32016-12-12 16:45:57 +01004740 for (u = 0; u < module->augment_size; ++u) {
4741 remove_aug(&module->augment[u]);
4742 }
4743
4744 /* remove deviation and augments defined in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004745 for (v = 0; v < module->inc_size && module->inc[v].submodule; ++v) {
Radek Krejcib2541a32016-12-12 16:45:57 +01004746 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
Michal Vasko7427b262018-05-14 15:23:55 +02004747 if (module->inc[v].submodule->deviation[u].orig_node) {
4748 remove_dev(&module->inc[v].submodule->deviation[u], module, unres);
4749 }
Andrew Langefeldf9763242018-09-16 22:23:50 -05004750
4751 /* Free the deviation's must array(s). These are shallow copies of the arrays
4752 on the target node(s), so a deep free is not needed. */
4753 for (w = 0; w < module->inc[v].submodule->deviation[u].deviate_size; ++w) {
4754 if (module->inc[v].submodule->deviation[u].deviate[w].mod == LY_DEVIATE_ADD) {
4755 free(module->inc[v].submodule->deviation[u].deviate[w].must);
4756 }
4757 }
Radek Krejcidbc15262016-06-16 14:58:29 +02004758 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004759
Radek Krejcib2541a32016-12-12 16:45:57 +01004760 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4761 remove_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004762 }
4763 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004764
4765 if (unres->count) {
4766 resolve_unres_schema(module, unres);
4767 }
4768 /* nothing else left to do even if something is not resolved */
4769 unres_schema_free(module, &unres, 1);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004770}
4771
Michal Vasko0f437062018-06-08 15:52:39 +02004772int
4773lys_make_implemented_r(struct lys_module *module, struct unres_schema *unres)
Radek Krejci27fe55e2016-09-13 17:13:35 +02004774{
Michal Vasko0f437062018-06-08 15:52:39 +02004775 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004776 struct lys_node *root, *next, *node;
Michal Vasko74083ec2018-06-15 10:00:12 +02004777 struct lys_module *target_module;
Michal Vasko0f437062018-06-08 15:52:39 +02004778 uint16_t i, j, k;
4779
4780 assert(module->implemented);
4781 ctx = module->ctx;
4782
4783 for (i = 0; i < ctx->models.used; ++i) {
4784 if (module == ctx->models.list[i]) {
4785 continue;
4786 }
4787
4788 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
4789 LOGERR(ctx, LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
4790 return EXIT_FAILURE;
4791 }
4792 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004793
4794 for (i = 0; i < module->augment_size; i++) {
Michal Vasko74083ec2018-06-15 10:00:12 +02004795
4796 /* make target module implemented if was not */
4797 assert(module->augment[i].target);
4798 target_module = lys_node_module(module->augment[i].target);
4799 if (!target_module->implemented) {
4800 target_module->implemented = 1;
4801 if (unres_schema_add_node(target_module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
4802 return -1;
4803 }
4804 }
4805
Radek Krejci27fe55e2016-09-13 17:13:35 +02004806 /* apply augment */
Adam Weast368fd582018-06-14 13:32:35 -05004807 if ((module->augment[i].flags & LYS_NOTAPPLIED) && apply_aug(&module->augment[i], unres)) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004808 return EXIT_FAILURE;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004809 }
4810 }
Adam Weast4ca7edd2018-06-14 08:59:22 -05004811
Radek Krejci9e6af732017-04-27 14:40:25 +02004812 /* identities */
4813 for (i = 0; i < module->ident_size; i++) {
4814 for (j = 0; j < module->ident[i].base_size; j++) {
4815 resolve_identity_backlink_update(&module->ident[i], module->ident[i].base[j]);
4816 }
4817 }
4818
Michal Vasko0f437062018-06-08 15:52:39 +02004819 /* process augments in submodules */
4820 for (i = 0; i < module->inc_size && module->inc[i].submodule; ++i) {
4821 module->inc[i].submodule->implemented = 1;
4822
4823 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
Michal Vasko74083ec2018-06-15 10:00:12 +02004824
4825 /* make target module implemented if it was not */
Michal Vaskoda267cb2018-06-15 11:18:00 +02004826 assert(module->inc[i].submodule->augment[j].target);
Michal Vasko74083ec2018-06-15 10:00:12 +02004827 target_module = lys_node_module(module->inc[i].submodule->augment[j].target);
4828 if (!target_module->implemented) {
4829 target_module->implemented = 1;
4830 if (unres_schema_add_node(target_module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
4831 return -1;
4832 }
4833 }
4834
Michal Vasko0f437062018-06-08 15:52:39 +02004835 /* apply augment */
Adam Weast368fd582018-06-14 13:32:35 -05004836 if ((module->inc[i].submodule->augment[j].flags & LYS_NOTAPPLIED) && apply_aug(&module->inc[i].submodule->augment[j], unres)) {
Michal Vasko0f437062018-06-08 15:52:39 +02004837 return EXIT_FAILURE;
4838 }
4839 }
4840
4841 /* identities */
4842 for (j = 0; j < module->inc[i].submodule->ident_size; j++) {
4843 for (k = 0; k < module->inc[i].submodule->ident[j].base_size; k++) {
4844 resolve_identity_backlink_update(&module->inc[i].submodule->ident[j],
4845 module->inc[i].submodule->ident[j].base[k]);
4846 }
4847 }
4848 }
4849
Radek Krejci27fe55e2016-09-13 17:13:35 +02004850 LY_TREE_FOR(module->data, root) {
4851 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
4852 LY_TREE_DFS_BEGIN(root, next, node) {
4853 if (node->nodetype == LYS_GROUPING) {
4854 goto nextsibling;
4855 }
4856 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
4857 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
4858 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
4859 UNRES_TYPE_LEAFREF, node) == -1) {
4860 return EXIT_FAILURE;
4861 }
4862 }
4863 }
4864
4865 /* modified LY_TREE_DFS_END */
4866 next = node->child;
4867 /* child exception for leafs, leaflists and anyxml without children */
4868 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4869 next = NULL;
4870 }
4871 if (!next) {
4872nextsibling:
4873 /* no children */
4874 if (node == root) {
4875 /* we are done, root has no children */
4876 break;
4877 }
4878 /* try siblings */
4879 next = node->next;
4880 }
4881 while (!next) {
4882 /* parent is already processed, go to its sibling */
4883 node = lys_parent(node);
4884 /* no siblings, go back through parents */
4885 if (lys_parent(node) == lys_parent(root)) {
4886 /* we are done, no next element to process */
4887 break;
4888 }
4889 next = node->next;
4890 }
4891 }
4892 }
4893
4894 return EXIT_SUCCESS;
4895}
4896
4897API int
4898lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02004899{
Radek Krejci27fe55e2016-09-13 17:13:35 +02004900 struct unres_schema *unres;
Michal Vasko0f437062018-06-08 15:52:39 +02004901 int disabled = 0;
Michal Vasko26055752016-05-03 11:36:31 +02004902
Radek Krejci27fe55e2016-09-13 17:13:35 +02004903 if (!module) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004904 LOGARG;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004905 return EXIT_FAILURE;
4906 }
4907
4908 module = lys_main_module(module);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004909
4910 if (module->disabled) {
4911 disabled = 1;
4912 lys_set_enabled(module);
4913 }
4914
Michal Vasko26055752016-05-03 11:36:31 +02004915 if (module->implemented) {
4916 return EXIT_SUCCESS;
4917 }
4918
Radek Krejci27fe55e2016-09-13 17:13:35 +02004919 unres = calloc(1, sizeof *unres);
4920 if (!unres) {
Michal Vasko0f437062018-06-08 15:52:39 +02004921 LOGMEM(module->ctx);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004922 if (disabled) {
4923 /* set it back disabled */
4924 lys_set_disabled(module);
4925 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004926 return EXIT_FAILURE;
4927 }
4928 /* recursively make the module implemented */
4929 ((struct lys_module *)module)->implemented = 1;
Michal Vasko0f437062018-06-08 15:52:39 +02004930 if (lys_make_implemented_r((struct lys_module *)module, unres)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004931 goto error;
4932 }
Radek Krejci9e6af732017-04-27 14:40:25 +02004933
Radek Krejcidf46e222016-11-08 11:57:37 +01004934 /* try again resolve augments in other modules possibly augmenting this one,
4935 * since we have just enabled it
4936 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02004937 /* resolve rest of unres items */
4938 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
4939 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004940 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004941 unres_schema_free(NULL, &unres, 0);
Michal Vasko26055752016-05-03 11:36:31 +02004942
Michal Vaskobe136f62017-09-21 12:08:39 +02004943 LOGVRB("Module \"%s%s%s\" now implemented.", module->name, (module->rev_size ? "@" : ""),
4944 (module->rev_size ? module->rev[0].date : ""));
Michal Vasko26055752016-05-03 11:36:31 +02004945 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004946
4947error:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004948 if (disabled) {
4949 /* set it back disabled */
4950 lys_set_disabled(module);
4951 }
4952
Radek Krejci27fe55e2016-09-13 17:13:35 +02004953 ((struct lys_module *)module)->implemented = 0;
Michal Vasko44ab1462017-05-18 13:18:36 +02004954 unres_schema_free((struct lys_module *)module, &unres, 1);
Radek Krejci27fe55e2016-09-13 17:13:35 +02004955 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004956}
4957
4958void
4959lys_submodule_module_data_free(struct lys_submodule *submodule)
4960{
4961 struct lys_node *next, *elem;
4962
4963 /* remove parsed data */
4964 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
4965 if (elem->module == (struct lys_module *)submodule) {
4966 lys_node_free(elem, NULL, 0);
4967 }
4968 }
4969}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02004970
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004971API char *
Michal Vasko395b0a02018-01-22 09:36:20 +01004972lys_path(const struct lys_node *node, int options)
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004973{
Michal Vasko53b7da02018-02-13 15:28:42 +01004974 char *buf = NULL;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004975
4976 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004977 LOGARG;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004978 return NULL;
4979 }
4980
Michal Vasko185b5272018-09-13 14:26:12 +02004981 if (ly_vlog_build_path(LY_VLOG_LYS, node, &buf, !options, 0)) {
Michal Vasko59631dd2017-10-02 11:56:11 +02004982 return NULL;
4983 }
4984
Michal Vasko53b7da02018-02-13 15:28:42 +01004985 return buf;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004986}
Radek Krejci9ad23f42016-10-31 15:46:52 +01004987
Michal Vasko50576712017-07-28 12:28:33 +02004988API char *
4989lys_data_path(const struct lys_node *node)
4990{
Michal Vasko53b7da02018-02-13 15:28:42 +01004991 char *result = NULL, buf[1024];
PavolVicanb28bbff2018-02-21 00:44:02 +01004992 const char *separator, *name;
Michal Vasko50576712017-07-28 12:28:33 +02004993 int i, used;
4994 struct ly_set *set;
4995 const struct lys_module *prev_mod;
4996
4997 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004998 LOGARG;
Michal Vasko50576712017-07-28 12:28:33 +02004999 return NULL;
5000 }
5001
Michal Vaskod60a1a32018-05-23 16:31:22 +02005002 buf[0] = '\0';
Michal Vasko50576712017-07-28 12:28:33 +02005003 set = ly_set_new();
Michal Vasko53b7da02018-02-13 15:28:42 +01005004 LY_CHECK_ERR_GOTO(!set, LOGMEM(node->module->ctx), cleanup);
Michal Vasko50576712017-07-28 12:28:33 +02005005
5006 while (node) {
5007 ly_set_add(set, (void *)node, 0);
5008 do {
5009 node = lys_parent(node);
5010 } while (node && (node->nodetype & (LYS_USES | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
5011 }
5012
5013 prev_mod = NULL;
5014 used = 0;
5015 for (i = set->number - 1; i > -1; --i) {
5016 node = set->set.s[i];
PavolVicanb28bbff2018-02-21 00:44:02 +01005017 if (node->nodetype == LYS_EXT) {
5018 if (strcmp(((struct lys_ext_instance *)node)->def->name, "yang-data")) {
5019 continue;
5020 }
5021 name = ((struct lys_ext_instance *)node)->arg_value;
5022 separator = ":#";
5023 } else {
5024 name = node->name;
5025 separator = ":";
5026 }
Michal Vasko50576712017-07-28 12:28:33 +02005027 used += sprintf(buf + used, "/%s%s%s", (lys_node_module(node) == prev_mod ? "" : lys_node_module(node)->name),
PavolVicanb28bbff2018-02-21 00:44:02 +01005028 (lys_node_module(node) == prev_mod ? "" : separator), name);
Michal Vasko50576712017-07-28 12:28:33 +02005029 prev_mod = lys_node_module(node);
5030 }
5031
5032 result = strdup(buf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005033 LY_CHECK_ERR_GOTO(!result, LOGMEM(node->module->ctx), cleanup);
Michal Vasko50576712017-07-28 12:28:33 +02005034
Michal Vasko53b7da02018-02-13 15:28:42 +01005035cleanup:
Michal Vasko50576712017-07-28 12:28:33 +02005036 ly_set_free(set);
Michal Vasko50576712017-07-28 12:28:33 +02005037 return result;
5038}
5039
Michal Vaskobb520442017-05-23 10:55:18 +02005040struct lys_node_augment *
5041lys_getnext_target_aug(struct lys_node_augment *last, const struct lys_module *mod, const struct lys_node *aug_target)
5042{
5043 int i, j, last_found;
5044
Michal Vaskob6906872018-03-12 11:35:09 +01005045 assert(mod && aug_target);
5046
Michal Vaskobb520442017-05-23 10:55:18 +02005047 if (!last) {
5048 last_found = 1;
5049 } else {
5050 last_found = 0;
5051 }
5052
5053 /* search module augments */
5054 for (i = 0; i < mod->augment_size; ++i) {
5055 if (!mod->augment[i].target) {
5056 /* still unresolved, skip */
5057 continue;
5058 }
5059
5060 if (mod->augment[i].target == aug_target) {
5061 if (last_found) {
5062 /* next match after last */
5063 return &mod->augment[i];
5064 }
5065
5066 if (&mod->augment[i] == last) {
5067 last_found = 1;
5068 }
5069 }
5070 }
5071
5072 /* search submodule augments */
5073 for (i = 0; i < mod->inc_size; ++i) {
5074 for (j = 0; j < mod->inc[i].submodule->augment_size; ++j) {
5075 if (!mod->inc[i].submodule->augment[j].target) {
5076 continue;
5077 }
5078
5079 if (mod->inc[i].submodule->augment[j].target == aug_target) {
5080 if (last_found) {
5081 /* next match after last */
5082 return &mod->inc[i].submodule->augment[j];
5083 }
5084
5085 if (&mod->inc[i].submodule->augment[j] == last) {
5086 last_found = 1;
5087 }
5088 }
5089 }
5090 }
5091
5092 return NULL;
5093}
5094
Michal Vasko50576712017-07-28 12:28:33 +02005095API struct ly_set *
5096lys_find_path(const struct lys_module *cur_module, const struct lys_node *cur_node, const char *path)
5097{
5098 struct ly_set *ret;
5099 int rc;
5100
5101 if ((!cur_module && !cur_node) || !path) {
5102 return NULL;
5103 }
5104
5105 rc = resolve_schema_nodeid(path, cur_node, cur_module, &ret, 1, 1);
5106 if (rc == -1) {
5107 return NULL;
5108 }
5109
5110 return ret;
5111}
5112
Radek Krejci8d6b7422017-02-03 14:42:13 +01005113static void
5114lys_extcomplex_free_str(struct ly_ctx *ctx, struct lys_ext_instance_complex *ext, LY_STMT stmt)
5115{
5116 struct lyext_substmt *info;
Radek Krejcib71243e2017-02-08 16:20:08 +01005117 const char **str, ***a;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005118 int c;
5119
5120 str = lys_ext_complex_get_substmt(stmt, ext, &info);
5121 if (!str || !(*str)) {
5122 return;
5123 }
5124 if (info->cardinality >= LY_STMT_CARD_SOME) {
5125 /* we have array */
Radek Krejcib71243e2017-02-08 16:20:08 +01005126 a = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01005127 for (str = (*(const char ***)str), c = 0; str[c]; c++) {
5128 lydict_remove(ctx, str[c]);
Radek Krejci8d6b7422017-02-03 14:42:13 +01005129 }
Radek Krejci56c80412017-02-09 10:44:16 +01005130 free(a[0]);
5131 if (stmt == LY_STMT_BELONGSTO) {
5132 for (str = a[1], c = 0; str[c]; c++) {
5133 lydict_remove(ctx, str[c]);
5134 }
5135 free(a[1]);
PavolVican99c70722017-02-18 17:25:52 +01005136 } else if (stmt == LY_STMT_ARGUMENT) {
5137 free(a[1]);
Radek Krejci56c80412017-02-09 10:44:16 +01005138 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005139 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01005140 lydict_remove(ctx, str[0]);
5141 if (stmt == LY_STMT_BELONGSTO) {
5142 lydict_remove(ctx, str[1]);
5143 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005144 }
5145}
Michal Vasko1e82a3b2018-07-03 12:16:58 +02005146
Radek Krejci8d6b7422017-02-03 14:42:13 +01005147void
Radek Krejci5138e9f2017-04-12 13:10:46 +02005148lys_extension_instances_free(struct ly_ctx *ctx, struct lys_ext_instance **e, unsigned int size,
5149 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci8d6b7422017-02-03 14:42:13 +01005150{
Radek Krejcif8d05c22017-02-10 15:33:35 +01005151 unsigned int i, j, k;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005152 struct lyext_substmt *substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005153 void **pp, **start;
Radek Krejcif95b6292017-02-13 15:57:37 +01005154 struct lys_node *siter, *snext;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005155
5156#define EXTCOMPLEX_FREE_STRUCT(STMT, TYPE, FUNC, FREE, ARGS...) \
Radek Krejcib84686f2017-02-09 16:04:55 +01005157 pp = lys_ext_complex_get_substmt(STMT, (struct lys_ext_instance_complex *)e[i], NULL); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01005158 if (!pp || !(*pp)) { break; } \
Radek Krejcib84686f2017-02-09 16:04:55 +01005159 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */ \
Radek Krejci8d6b7422017-02-03 14:42:13 +01005160 for (start = pp = *pp; *pp; pp++) { \
Radek Krejci5138e9f2017-04-12 13:10:46 +02005161 FUNC(ctx, (TYPE *)(*pp), ##ARGS, private_destructor); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01005162 if (FREE) { free(*pp); } \
5163 } \
5164 free(start); \
5165 } else { /* single item */ \
Radek Krejci5138e9f2017-04-12 13:10:46 +02005166 FUNC(ctx, (TYPE *)(*pp), ##ARGS, private_destructor); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01005167 if (FREE) { free(*pp); } \
5168 }
5169
PavolVican9d61d402018-02-05 15:52:48 +01005170 if (!size || !e) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01005171 return;
5172 }
5173
5174 for (i = 0; i < size; i++) {
5175 if (!e[i]) {
5176 continue;
5177 }
5178
5179 if (e[i]->flags & (LYEXT_OPT_INHERIT)) {
5180 /* no free, this is just a shadow copy of the original extension instance */
5181 } else {
5182 if (e[i]->flags & (LYEXT_OPT_YANG)) {
5183 free(e[i]->def); /* remove name of instance extension */
PavolVican19dc6152017-02-06 12:04:15 +01005184 e[i]->def = NULL;
PavolVicandb0e8172017-02-20 00:46:09 +01005185 yang_free_ext_data((struct yang_ext_substmt *)e[i]->parent); /* remove backup part of yang file */
Radek Krejci8d6b7422017-02-03 14:42:13 +01005186 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02005187 /* remove private object */
5188 if (e[i]->priv && private_destructor) {
5189 private_destructor((struct lys_node*)e[i], e[i]->priv);
5190 }
5191 lys_extension_instances_free(ctx, e[i]->ext, e[i]->ext_size, private_destructor);
Radek Krejci8d6b7422017-02-03 14:42:13 +01005192 lydict_remove(ctx, e[i]->arg_value);
5193 }
5194
fanchanghu8d86f6b2017-06-10 12:49:54 +08005195 if (e[i]->def && e[i]->def->plugin && e[i]->def->plugin->type == LYEXT_COMPLEX
5196 && ((e[i]->flags & LYEXT_OPT_CONTENT) == 0)) {
Radek Krejcifebdad72017-02-06 11:35:51 +01005197 substmt = ((struct lys_ext_instance_complex *)e[i])->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005198 for (j = 0; substmt[j].stmt; j++) {
5199 switch(substmt[j].stmt) {
5200 case LY_STMT_DESCRIPTION:
5201 case LY_STMT_REFERENCE:
5202 case LY_STMT_UNITS:
Radek Krejcib71243e2017-02-08 16:20:08 +01005203 case LY_STMT_ARGUMENT:
5204 case LY_STMT_DEFAULT:
5205 case LY_STMT_ERRTAG:
5206 case LY_STMT_ERRMSG:
5207 case LY_STMT_PREFIX:
5208 case LY_STMT_NAMESPACE:
5209 case LY_STMT_PRESENCE:
5210 case LY_STMT_REVISIONDATE:
5211 case LY_STMT_KEY:
5212 case LY_STMT_BASE:
5213 case LY_STMT_BELONGSTO:
5214 case LY_STMT_CONTACT:
5215 case LY_STMT_ORGANIZATION:
5216 case LY_STMT_PATH:
Radek Krejci8d6b7422017-02-03 14:42:13 +01005217 lys_extcomplex_free_str(ctx, (struct lys_ext_instance_complex *)e[i], substmt[j].stmt);
5218 break;
5219 case LY_STMT_TYPE:
5220 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPE, struct lys_type, lys_type_free, 1);
5221 break;
Radek Krejci63fc0962017-02-15 13:20:18 +01005222 case LY_STMT_TYPEDEF:
5223 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPEDEF, struct lys_tpdf, lys_tpdf_free, 1);
5224 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005225 case LY_STMT_IFFEATURE:
Frank Rimplerc4db1c72017-09-12 12:56:39 +00005226 EXTCOMPLEX_FREE_STRUCT(LY_STMT_IFFEATURE, struct lys_iffeature, lys_iffeature_free, 0, 1, 0);
Radek Krejci8d6b7422017-02-03 14:42:13 +01005227 break;
Radek Krejci5496fae2017-02-10 13:26:48 +01005228 case LY_STMT_MAX:
5229 case LY_STMT_MIN:
5230 case LY_STMT_POSITION:
PavolVican2ed9f4e2017-02-16 00:08:45 +01005231 case LY_STMT_VALUE:
Radek Krejcif8d05c22017-02-10 15:33:35 +01005232 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
Radek Krejci716cd7a2017-02-15 12:23:41 +01005233 if (substmt[j].cardinality >= LY_STMT_CARD_SOME && *pp) {
Radek Krejcif8d05c22017-02-10 15:33:35 +01005234 for(k = 0; ((uint32_t**)(*pp))[k]; k++) {
5235 free(((uint32_t**)(*pp))[k]);
5236 }
5237 }
5238 free(*pp);
5239 break;
5240 case LY_STMT_DIGITS:
Radek Krejcib84686f2017-02-09 16:04:55 +01005241 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
5242 /* free the array */
5243 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5244 free(*pp);
5245 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005246 break;
Radek Krejci37f9ba32017-02-10 16:50:35 +01005247 case LY_STMT_MODULE:
5248 /* modules are part of the context, so they will be freed there */
5249 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
5250 /* free the array */
5251 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5252 free(*pp);
5253 }
5254 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01005255 case LY_STMT_ACTION:
Radek Krejcib31762b2017-02-15 10:48:42 +01005256 case LY_STMT_ANYDATA:
5257 case LY_STMT_ANYXML:
5258 case LY_STMT_CASE:
5259 case LY_STMT_CHOICE:
5260 case LY_STMT_CONTAINER:
5261 case LY_STMT_GROUPING:
5262 case LY_STMT_INPUT:
5263 case LY_STMT_LEAF:
5264 case LY_STMT_LEAFLIST:
5265 case LY_STMT_LIST:
5266 case LY_STMT_NOTIFICATION:
5267 case LY_STMT_OUTPUT:
5268 case LY_STMT_RPC:
5269 case LY_STMT_USES:
Radek Krejcif95b6292017-02-13 15:57:37 +01005270 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5271 LY_TREE_FOR_SAFE((struct lys_node *)(*pp), snext, siter) {
5272 lys_node_free(siter, NULL, 0);
5273 }
Radek Krejcib31762b2017-02-15 10:48:42 +01005274 *pp = NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +01005275 break;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01005276 case LY_STMT_UNIQUE:
5277 pp = lys_ext_complex_get_substmt(LY_STMT_UNIQUE, (struct lys_ext_instance_complex *)e[i], NULL);
5278 if (!pp || !(*pp)) {
5279 break;
5280 }
5281 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
5282 for (start = pp = *pp; *pp; pp++) {
5283 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
5284 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
5285 }
5286 free((*(struct lys_unique**)pp)->expr);
5287 free(*pp);
5288 }
5289 free(start);
5290 } else { /* single item */
5291 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
5292 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
5293 }
5294 free((*(struct lys_unique**)pp)->expr);
5295 free(*pp);
5296 }
5297 break;
Radek Krejciaa9c5202017-02-15 16:10:14 +01005298 case LY_STMT_LENGTH:
5299 case LY_STMT_MUST:
5300 case LY_STMT_PATTERN:
5301 case LY_STMT_RANGE:
5302 EXTCOMPLEX_FREE_STRUCT(substmt[j].stmt, struct lys_restr, lys_restr_free, 1);
5303 break;
Radek Krejcic5cc5302017-02-16 10:07:46 +01005304 case LY_STMT_WHEN:
5305 EXTCOMPLEX_FREE_STRUCT(LY_STMT_WHEN, struct lys_when, lys_when_free, 0);
5306 break;
Radek Krejci7417a082017-02-16 11:07:59 +01005307 case LY_STMT_REVISION:
5308 pp = lys_ext_complex_get_substmt(LY_STMT_REVISION, (struct lys_ext_instance_complex *)e[i], NULL);
5309 if (!pp || !(*pp)) {
5310 break;
5311 }
5312 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
5313 for (start = pp = *pp; *pp; pp++) {
5314 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
5315 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
5316 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
Radek Krejci5138e9f2017-04-12 13:10:46 +02005317 (*(struct lys_revision**)pp)->ext_size, private_destructor);
Radek Krejci7417a082017-02-16 11:07:59 +01005318 free(*pp);
5319 }
5320 free(start);
5321 } else { /* single item */
5322 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
5323 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
5324 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
Radek Krejci5138e9f2017-04-12 13:10:46 +02005325 (*(struct lys_revision**)pp)->ext_size, private_destructor);
Radek Krejci7417a082017-02-16 11:07:59 +01005326 free(*pp);
5327 }
5328 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005329 default:
Radek Krejcib84686f2017-02-09 16:04:55 +01005330 /* nothing to free */
Radek Krejci8d6b7422017-02-03 14:42:13 +01005331 break;
5332 }
5333 }
5334 }
5335
5336 free(e[i]);
5337 }
5338 free(e);
5339
5340#undef EXTCOMPLEX_FREE_STRUCT
5341}