blob: ad0dd4a05c75d661b0e093b72985ce819dacd7dc [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 }
David Lamparter1c19bcd2018-12-05 22:58:03 +0100111 } else if (node->nodetype == LYS_EXT) {
112 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +0200113 } else if (node->parent) {
114 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +0200115 } else {
116 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +0200117 }
118
Radek Krejci074bf852015-08-19 14:22:16 +0200119 if (recursive == 2) {
120 /* continue only if the node cannot have a data instance */
121 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
122 return NULL;
123 }
124 }
125 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +0200126}
127
Michal Vaskob69d2432018-09-21 13:26:22 +0200128API const struct lys_type *
129lys_getnext_union_type(const struct lys_type *last, const struct lys_type *type)
130{
131 int found = 0;
132
133 if (!type || (type->base != LY_TYPE_UNION)) {
Michal Vasko79d5d272018-09-21 13:28:22 +0200134 return NULL;
Michal Vaskob69d2432018-09-21 13:26:22 +0200135 }
136
Michal Vasko79d5d272018-09-21 13:28:22 +0200137 return lyp_get_next_union_type((struct lys_type *)type, (struct lys_type *)last, &found);
Michal Vaskob69d2432018-09-21 13:26:22 +0200138}
139
Michal Vasko1dca6882015-10-22 14:29:42 +0200140int
Michal Vasko36cbaa42015-12-14 13:15:48 +0100141lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
142 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +0200143{
Radek Krejcic071c542016-01-27 14:57:51 +0100144 const struct lys_node *node, *parent = NULL;
145 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +0100146 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +0200147
Michal Vasko36cbaa42015-12-14 13:15:48 +0100148 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +0200149 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +0200150
Michal Vasko36cbaa42015-12-14 13:15:48 +0100151 /* fill the lengths in case the caller is so indifferent */
152 if (!mod_name_len) {
153 mod_name_len = strlen(mod_name);
154 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200155 if (!nam_len) {
156 nam_len = strlen(name);
157 }
158
Michal Vasko9e635ac2016-10-17 11:44:09 +0200159 while (siblings && (siblings->nodetype == LYS_USES)) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200160 siblings = siblings->child;
161 }
Michal Vasko9e635ac2016-10-17 11:44:09 +0200162 if (!siblings) {
163 /* unresolved uses */
164 return EXIT_FAILURE;
165 }
166
Michal Vasko680f8b42016-10-17 10:27:37 +0200167 if (siblings->nodetype == LYS_GROUPING) {
168 for (node = siblings; (node->nodetype == LYS_GROUPING) && (node->prev != siblings); node = node->prev);
169 if (node->nodetype == LYS_GROUPING) {
170 /* we went through all the siblings, only groupings there - no valid sibling */
171 return EXIT_FAILURE;
172 }
173 /* update siblings to be valid */
174 siblings = node;
175 }
176
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200177 /* set parent correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100178 parent = lys_parent(siblings);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200179
Michal Vasko680f8b42016-10-17 10:27:37 +0200180 /* go up all uses */
181 while (parent && (parent->nodetype == LYS_USES)) {
182 parent = lys_parent(parent);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200183 }
184
Radek Krejcic071c542016-01-27 14:57:51 +0100185 if (!parent) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200186 /* handle situation when there is a top-level uses referencing a foreign grouping */
187 for (node = siblings; lys_parent(node) && (node->nodetype == LYS_USES); node = lys_parent(node));
188 mod = lys_node_module(node);
Michal Vasko1dca6882015-10-22 14:29:42 +0200189 }
190
Radek Krejcic071c542016-01-27 14:57:51 +0100191 /* try to find the node */
192 node = NULL;
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100193 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | LYS_GETNEXT_WITHINOUT))) {
Radek Krejcic071c542016-01-27 14:57:51 +0100194 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100195 /* module name comparison */
196 node_mod_name = lys_node_module(node)->name;
Michal Vaskob42b6972016-06-06 14:21:30 +0200197 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 +0100198 continue;
199 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200200
Radek Krejcic071c542016-01-27 14:57:51 +0100201 /* direct name check */
Michal Vaskob42b6972016-06-06 14:21:30 +0200202 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100203 if (ret) {
204 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200205 }
Radek Krejcic071c542016-01-27 14:57:51 +0100206 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200207 }
208 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200209 }
210
211 return EXIT_FAILURE;
212}
213
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200214int
Michal Vaskobb520442017-05-23 10:55:18 +0200215lys_getnext_data(const struct lys_module *mod, const struct lys_node *parent, const char *name, int nam_len,
216 LYS_NODE type, const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200217{
Michal Vaskobb520442017-05-23 10:55:18 +0200218 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200219
Michal Vaskobb520442017-05-23 10:55:18 +0200220 assert((mod || parent) && name);
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200221 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
222
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200223 if (!mod) {
Michal Vaskobb520442017-05-23 10:55:18 +0200224 mod = lys_node_module(parent);
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200225 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200226
Michal Vasko4f0dad02016-02-15 14:08:23 +0100227 /* try to find the node */
228 node = NULL;
Michal Vasko24476fa2017-03-08 12:33:48 +0100229 while ((node = lys_getnext(node, parent, mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100230 if (!type || (node->nodetype & type)) {
231 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200232 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100233 continue;
234 }
235
Michal Vasko4f0dad02016-02-15 14:08:23 +0100236 /* direct name check */
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100237 if (!strncmp(node->name, name, nam_len) && !node->name[nam_len]) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100238 if (ret) {
239 *ret = node;
240 }
241 return EXIT_SUCCESS;
242 }
Radek Krejcic071c542016-01-27 14:57:51 +0100243 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200244 }
245
246 return EXIT_FAILURE;
247}
248
Michal Vasko1e62a092015-12-01 12:27:20 +0100249API const struct lys_node *
250lys_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 +0200251{
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100252 const struct lys_node *next, *aug_parent;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100253 struct lys_node **snode;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200254
Michal Vasko75702cd2018-02-12 11:27:09 +0100255 if ((!parent && !module) || (module && module->type) || (parent && (parent->nodetype == LYS_USES) && !(options & LYS_GETNEXT_PARENTUSES))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100256 LOGARG;
Michal Vasko24476fa2017-03-08 12:33:48 +0100257 return NULL;
258 }
259
Radek Krejci8bc87f62015-09-02 16:19:05 +0200260 if (!last) {
261 /* first call */
262
263 /* get know where to start */
264 if (parent) {
265 /* schema subtree */
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100266 snode = lys_child(parent, LYS_UNKNOWN);
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100267 /* do not return anything if the augment does not have any children */
Radek Krejcibb08db32017-07-03 11:29:17 +0200268 if (!snode || !(*snode) || ((parent->nodetype == LYS_AUGMENT) && ((*snode)->parent != parent))) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +0100269 return NULL;
270 }
271 next = last = *snode;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200272 } else {
273 /* top level data */
Michal Vaskocb45f472018-02-12 10:47:42 +0100274 if (!(options & LYS_GETNEXT_NOSTATECHECK) && (module->disabled || !module->implemented)) {
275 /* nothing to return from a disabled/imported module */
276 return NULL;
277 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200278 next = last = module->data;
279 }
Radek Krejci972724f2016-08-12 15:24:40 +0200280 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
281 /* continue with uses content */
282 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200283 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200284 /* continue after the last returned value */
285 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200286 }
287
288repeat:
Michal Vasko5a9c24b2017-03-13 09:25:58 +0100289 if (parent && (parent->nodetype == LYS_AUGMENT) && next) {
290 /* do not return anything outside the parent augment */
291 aug_parent = next->parent;
292 do {
293 while (aug_parent && (aug_parent->nodetype != LYS_AUGMENT)) {
294 aug_parent = aug_parent->parent;
295 }
296 if (aug_parent) {
297 if (aug_parent == parent) {
298 break;
299 }
300 aug_parent = ((struct lys_node_augment *)aug_parent)->target;
301 }
302
303 } while (aug_parent);
304 if (!aug_parent) {
305 return NULL;
306 }
307 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200308 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200309 if (options & LYS_GETNEXT_WITHGROUPING) {
310 return next;
311 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200312 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200313 }
314
Radek Krejci972724f2016-08-12 15:24:40 +0200315 if (!next) { /* cover case when parent is augment */
316 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200317 /* no next element */
318 return NULL;
319 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200320 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200321 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200322 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200323 } else {
324 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200325 }
326
Michal Vaskocb45f472018-02-12 10:47:42 +0100327 if (!(options & LYS_GETNEXT_NOSTATECHECK) && lys_is_disabled(next, 0)) {
328 next = next->next;
329 goto repeat;
330 }
331
Radek Krejci7f40ce32015-08-12 20:38:46 +0200332 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200333 case LYS_INPUT:
334 case LYS_OUTPUT:
335 if (options & LYS_GETNEXT_WITHINOUT) {
336 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200337 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200338 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200339 } else {
340 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200341 }
Radek Krejci972724f2016-08-12 15:24:40 +0200342 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200343
Michal Vaskoa5835e92015-10-20 15:07:39 +0200344 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200345 if (options & LYS_GETNEXT_WITHCASE) {
346 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200347 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200348 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200349 } else {
350 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200351 }
Radek Krejci972724f2016-08-12 15:24:40 +0200352 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200353
Michal Vasko1dca6882015-10-22 14:29:42 +0200354 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200355 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200356 if (options & LYS_GETNEXT_WITHUSES) {
357 return next;
358 } else if (next->child) {
359 next = next->child;
360 } else {
361 next = next->next;
362 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200363 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200364
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200365 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200366 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200367 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200368 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200369 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200370 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200371 case LYS_LIST:
372 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200373 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200374
Radek Krejci972724f2016-08-12 15:24:40 +0200375 case LYS_CONTAINER:
376 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
377 if (next->child) {
378 /* go into */
379 next = next->child;
380 } else {
381 next = next->next;
382 }
383 goto repeat;
384 } else {
385 return next;
386 }
387
Radek Krejci8bc87f62015-09-02 16:19:05 +0200388 case LYS_CHOICE:
389 if (options & LYS_GETNEXT_WITHCHOICE) {
390 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200391 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200392 /* go into */
393 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200394 } else {
395 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200396 }
Radek Krejci972724f2016-08-12 15:24:40 +0200397 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200398
Radek Krejci7f40ce32015-08-12 20:38:46 +0200399 default:
400 /* we should not be here */
401 return NULL;
402 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200403}
404
Radek Krejcibf285832017-01-26 16:05:41 +0100405void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200406lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200407{
Michal Vaskof75b2772018-03-14 09:55:33 +0100408 struct lys_node *parent, *first, **pp = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +0100409 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200410
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200411 if (!node) {
412 return;
413 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200415 /* unlink from data model if necessary */
416 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100417 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100418 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100419 if (main_module->data == node) {
420 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200421 }
422 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200423
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200424 /* store pointers to important nodes */
425 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200426 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200427 /* handle augments - first, unlink it from the augment parent ... */
428 if (parent->child == node) {
Radek Krejcic9d78692017-08-24 17:17:18 +0200429 parent->child = (node->next && node->next->parent == parent) ? node->next : NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200430 }
Radek Krejcifec2e142017-01-05 15:19:03 +0100431
432 if (parent->flags & LYS_NOTAPPLIED) {
433 /* data are not connected in the target, so we cannot continue with the target as a parent */
434 parent = NULL;
435 } else {
436 /* data are connected in target, so we will continue with the target as a parent */
437 parent = ((struct lys_node_augment *)parent)->target;
438 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200439 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200441 /* unlink from parent */
442 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100443 if (parent->nodetype == LYS_EXT) {
444 pp = (struct lys_node **)lys_ext_complex_get_substmt(lys_snode2stmt(node->nodetype),
445 (struct lys_ext_instance_complex*)parent, NULL);
446 if (*pp == node) {
447 *pp = node->next;
448 }
449 } else if (parent->child == node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200450 parent->child = node->next;
451 }
452 node->parent = NULL;
453 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200454
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200455 /* unlink from siblings */
456 if (node->prev == node) {
457 /* there are no more siblings */
458 return;
459 }
460 if (node->next) {
461 node->next->prev = node->prev;
462 } else {
463 /* unlinking the last element */
464 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100465 if (parent->nodetype == LYS_EXT) {
466 first = *(struct lys_node **)pp;
467 } else {
468 first = parent->child;
469 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200470 } else {
471 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200472 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200473 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200474 }
475 }
476 first->prev = node->prev;
477 }
478 if (node->prev->next) {
479 node->prev->next = node->next;
480 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200482 /* clean up the unlinked element */
483 node->next = NULL;
484 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200485}
486
Michal Vasko563ef092015-09-04 13:17:23 +0200487struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100488lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200489{
490 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200491
492 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200493 /* top-level augment, look into module (uses augment is handled correctly below) */
494 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
Radek Krejci115fa882017-03-01 16:15:07 +0100495 par_iter = lys_main_module(par_iter->parent->module)->data;
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200496 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200497 break;
498 }
499 }
500
Michal Vasko38a00412018-03-14 10:01:50 +0100501 if (par_iter->nodetype == LYS_EXT) {
502 /* we are in a top-level extension, search grouping in top-level groupings */
503 par_iter = lys_main_module(par_iter->module)->data;
504 if (!par_iter) {
505 /* not connected yet, wait */
506 return NULL;
507 }
508 } else if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200509 continue;
510 }
511
512 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
513 if (!stop) {
514 stop = par_iter;
515 } else if (iter == stop) {
516 break;
517 }
518 if (iter->nodetype != LYS_GROUPING) {
519 continue;
520 }
521
Radek Krejcif8426a72015-10-31 23:14:03 +0100522 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200523 return (struct lys_node_grp *)iter;
524 }
525 }
526 }
527
Michal Vasko563ef092015-09-04 13:17:23 +0200528 return NULL;
529}
530
Radek Krejci10c760e2015-08-14 14:45:43 +0200531/*
532 * get next grouping in the root's subtree, in the
533 * first call, tha last is NULL
534 */
535static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200536lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200537{
Radek Krejci10c760e2015-08-14 14:45:43 +0200538 struct lys_node *last = (struct lys_node *)lastgrp;
539 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200540
Radek Krejci10c760e2015-08-14 14:45:43 +0200541 assert(root);
542
543 if (!last) {
544 last = root;
545 }
546
547 while (1) {
548 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
549 next = last->child;
550 } else {
551 next = NULL;
552 }
553 if (!next) {
554 if (last == root) {
555 /* we are done */
556 return NULL;
557 }
558
559 /* no children, go to siblings */
560 next = last->next;
561 }
562 while (!next) {
563 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100564 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200565 /* we are done */
566 return NULL;
567 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200568 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100569 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200570 }
571
572 if (next->nodetype == LYS_GROUPING) {
573 return (struct lys_node_grp *)next;
574 }
575
576 last = next;
577 }
578}
579
Michal Vasko0d343d12015-08-24 14:57:36 +0200580/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200581int
Radek Krejci07911992015-08-14 15:13:31 +0200582lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
583{
Michal Vasko563ef092015-09-04 13:17:23 +0200584 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200585 struct lys_node_grp *grp;
Radek Krejcif95b6292017-02-13 15:57:37 +0100586 int down, up;
Radek Krejci07911992015-08-14 15:13:31 +0200587
588 assert(node);
589
590 if (!parent) {
591 assert(module);
592 } else {
593 module = parent->module;
594 }
Radek Krejci115fa882017-03-01 16:15:07 +0100595 module = lys_main_module(module);
Radek Krejci07911992015-08-14 15:13:31 +0200596
597 switch (node->nodetype) {
598 case LYS_GROUPING:
599 /* 6.2.1, rule 6 */
600 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100601 start = *lys_child(parent, LYS_GROUPING);
602 if (!start) {
Radek Krejci07911992015-08-14 15:13:31 +0200603 down = 0;
604 start = parent;
Radek Krejcif95b6292017-02-13 15:57:37 +0100605 } else {
606 down = 1;
607 }
608 if (parent->nodetype == LYS_EXT) {
609 up = 0;
610 } else {
611 up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200612 }
613 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100614 down = up = 1;
Radek Krejci07911992015-08-14 15:13:31 +0200615 start = module->data;
616 }
617 /* go up */
Radek Krejcif95b6292017-02-13 15:57:37 +0100618 if (up && lys_find_grouping_up(node->name, start)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100619 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200620 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200621 }
622 /* go down, because grouping can be defined after e.g. container in which is collision */
623 if (down) {
624 for (iter = start, stop = NULL; iter; iter = iter->prev) {
625 if (!stop) {
626 stop = start;
627 } else if (iter == stop) {
628 break;
629 }
630 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
631 continue;
632 }
633
634 grp = NULL;
635 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100636 if (ly_strequal(node->name, grp->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100637 LOGVAL(module->ctx, LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200638 return EXIT_FAILURE;
639 }
640 }
641 }
642 }
643 break;
644 case LYS_LEAF:
645 case LYS_LEAFLIST:
646 case LYS_LIST:
647 case LYS_CONTAINER:
648 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200649 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200650 /* 6.2.1, rule 7 */
651 if (parent) {
652 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200653 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
654 if (iter->nodetype == LYS_AUGMENT) {
655 if (((struct lys_node_augment *)iter)->target) {
656 /* augment is resolved, go up */
657 iter = ((struct lys_node_augment *)iter)->target;
658 continue;
659 }
660 /* augment is not resolved, this is the final parent */
661 break;
662 }
Radek Krejci07911992015-08-14 15:13:31 +0200663 iter = iter->parent;
664 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200665
Radek Krejci07911992015-08-14 15:13:31 +0200666 if (!iter) {
667 stop = NULL;
668 iter = module->data;
Radek Krejcif95b6292017-02-13 15:57:37 +0100669 } else if (iter->nodetype == LYS_EXT) {
670 stop = iter;
PavolVican9d61d402018-02-05 15:52:48 +0100671 iter = (struct lys_node *)lys_child(iter, node->nodetype);
672 if (iter) {
673 iter = *(struct lys_node **)iter;
674 }
Radek Krejci07911992015-08-14 15:13:31 +0200675 } else {
676 stop = iter;
677 iter = iter->child;
678 }
679 } else {
680 stop = NULL;
681 iter = module->data;
682 }
683 while (iter) {
684 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
685 iter = iter->child;
686 continue;
687 }
688
Radek Krejcibf2abff2016-08-23 15:51:52 +0200689 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100690 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100691 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200692 return EXIT_FAILURE;
693 }
694 }
695
696 /* special case for choice - we must check the choice's name as
697 * well as the names of nodes under the choice
698 */
699 if (iter->nodetype == LYS_CHOICE) {
700 iter = iter->child;
701 continue;
702 }
703
704 /* go to siblings */
705 if (!iter->next) {
706 /* no sibling, go to parent's sibling */
707 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200708 /* for parent LYS_AUGMENT */
709 if (iter->parent == stop) {
710 iter = stop;
711 break;
712 }
713 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200714 if (iter && iter->next) {
715 break;
716 }
717 } while (iter != stop);
718
719 if (iter == stop) {
720 break;
721 }
722 }
723 iter = iter->next;
724 }
725 break;
726 case LYS_CASE:
727 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100728 if (parent) {
Radek Krejcif95b6292017-02-13 15:57:37 +0100729 start = *lys_child(parent, LYS_CASE);
Radek Krejcic071c542016-01-27 14:57:51 +0100730 } else {
731 start = module->data;
732 }
733
734 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200735 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200736 continue;
737 }
738
Radek Krejci749190d2016-02-18 16:26:25 +0100739 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100740 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200741 return EXIT_FAILURE;
742 }
743 }
744 break;
745 default:
746 /* no check needed */
747 break;
748 }
749
750 return EXIT_SUCCESS;
751}
752
Michal Vasko0d343d12015-08-24 14:57:36 +0200753/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200754int
Michal Vasko8d30dd82018-09-10 10:06:12 +0200755lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child, int options)
Radek Krejci10c760e2015-08-14 14:45:43 +0200756{
Michal Vasko53b7da02018-02-13 15:28:42 +0100757 struct ly_ctx *ctx = child->module->ctx;
Radek Krejcic9d78692017-08-24 17:17:18 +0200758 struct lys_node *iter, **pchild;
Michal Vasko56601c92018-08-06 10:03:06 +0200759 struct lys_node_inout *in, *out;
Radek Krejci744c2d42017-03-26 13:30:00 -0500760 struct lys_node_case *c;
761 int type, shortcase = 0;
Radek Krejcif95b6292017-02-13 15:57:37 +0100762 void *p;
763 struct lyext_substmt *info = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200765 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200766
Radek Krejci10c760e2015-08-14 14:45:43 +0200767 if (parent) {
768 type = parent->nodetype;
769 module = parent->module;
770 } else {
771 assert(module);
Radek Krejcife3a1382016-11-04 10:30:11 +0100772 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
Radek Krejci10c760e2015-08-14 14:45:43 +0200773 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200774 }
775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200776 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200777 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200778 case LYS_CONTAINER:
779 case LYS_LIST:
780 case LYS_GROUPING:
Radek Krejci96935402016-11-04 16:27:28 +0100781 case LYS_USES:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200782 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200783 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200784 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100785 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200786 return EXIT_FAILURE;
787 }
788 break;
Radek Krejci76512572015-08-04 09:47:08 +0200789 case LYS_INPUT:
790 case LYS_OUTPUT:
791 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200792 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200793 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200794 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100795 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200796 return EXIT_FAILURE;
797 }
798 break;
Radek Krejci76512572015-08-04 09:47:08 +0200799 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200800 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200801 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100802 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200803 return EXIT_FAILURE;
804 }
Radek Krejci744c2d42017-03-26 13:30:00 -0500805 if (child->nodetype != LYS_CASE) {
806 shortcase = 1;
807 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200808 break;
Radek Krejci76512572015-08-04 09:47:08 +0200809 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200810 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200811 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100812 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200813 return EXIT_FAILURE;
814 }
815 break;
Radek Krejci76512572015-08-04 09:47:08 +0200816 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200817 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200818 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100819 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200820 return EXIT_FAILURE;
821 }
822 break;
Radek Krejci76512572015-08-04 09:47:08 +0200823 case LYS_LEAF:
824 case LYS_LEAFLIST:
825 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200826 case LYS_ANYDATA:
Michal Vasko53b7da02018-02-13 15:28:42 +0100827 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
828 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100829 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200830 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200831 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200832 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200833 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskodb017262017-01-24 13:10:04 +0100834 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100835 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200836 return EXIT_FAILURE;
837 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200838 break;
839 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200840 /* top level */
841 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200842 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200843 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100844 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200845 return EXIT_FAILURE;
846 }
Radek Krejcif95b6292017-02-13 15:57:37 +0100847 break;
848 case LYS_EXT:
849 /* plugin-defined */
850 p = lys_ext_complex_get_substmt(lys_snode2stmt(child->nodetype), (struct lys_ext_instance_complex*)parent, &info);
851 if (!p) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100852 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype),
Radek Krejcif95b6292017-02-13 15:57:37 +0100853 ((struct lys_ext_instance_complex*)parent)->def->name);
854 return EXIT_FAILURE;
855 }
856 /* TODO check cardinality */
Radek Krejcic071c542016-01-27 14:57:51 +0100857 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200858 }
859
860 /* check identifier uniqueness */
Michal Vasko15a43372017-09-25 14:12:42 +0200861 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && lys_check_id(child, parent, module)) {
Radek Krejci07911992015-08-14 15:13:31 +0200862 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200863 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200864
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200865 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200866 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200867 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200868
Radek Krejcif95b6292017-02-13 15:57:37 +0100869 if ((child->nodetype & (LYS_INPUT | LYS_OUTPUT)) && parent->nodetype != LYS_EXT) {
Michal Vasko56601c92018-08-06 10:03:06 +0200870 /* find the implicit input/output node */
871 LY_TREE_FOR(parent->child, iter) {
872 if (iter->nodetype == child->nodetype) {
873 break;
874 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200875 }
Michal Vasko56601c92018-08-06 10:03:06 +0200876 assert(iter);
877
878 /* switch the old implicit node (iter) with the new one (child) */
879 if (parent->child == iter) {
880 /* first child */
881 parent->child = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200882 } else {
Michal Vasko56601c92018-08-06 10:03:06 +0200883 iter->prev->next = child;
884 }
885 child->prev = iter->prev;
886 child->next = iter->next;
887 if (iter->next) {
888 iter->next->prev = child;
889 } else {
890 /* last child */
Radek Krejci41a349b2016-10-24 19:21:59 +0200891 parent->child->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200892 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200893 child->parent = parent;
Michal Vasko56601c92018-08-06 10:03:06 +0200894
895 /* isolate the node and free it */
896 iter->next = NULL;
897 iter->prev = iter;
898 iter->parent = NULL;
899 lys_node_free(iter, NULL, 0);
Radek Krejci41a349b2016-10-24 19:21:59 +0200900 } else {
Radek Krejci744c2d42017-03-26 13:30:00 -0500901 if (shortcase) {
902 /* create the implicit case to allow it to serve as a target of the augments,
903 * it won't be printed, but it will be present in the tree */
904 c = calloc(1, sizeof *c);
Michal Vasko53b7da02018-02-13 15:28:42 +0100905 LY_CHECK_ERR_RETURN(!c, LOGMEM(ctx), EXIT_FAILURE);
Radek Krejci744c2d42017-03-26 13:30:00 -0500906 c->name = lydict_insert(module->ctx, child->name, 0);
907 c->flags = LYS_IMPLICIT;
Michal Vasko8d30dd82018-09-10 10:06:12 +0200908 if (!(options & (LYS_PARSE_OPT_CFG_IGNORE | LYS_PARSE_OPT_CFG_NOINHERIT))) {
909 /* get config flag from parent */
910 c->flags |= parent->flags & LYS_CONFIG_MASK;
911 }
Radek Krejci744c2d42017-03-26 13:30:00 -0500912 c->module = module;
913 c->nodetype = LYS_CASE;
914 c->prev = (struct lys_node*)c;
Michal Vasko8d30dd82018-09-10 10:06:12 +0200915 lys_node_addchild(parent, module, (struct lys_node*)c, options);
Radek Krejci744c2d42017-03-26 13:30:00 -0500916 parent = (struct lys_node*)c;
917 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200918 /* connect the child correctly */
919 if (!parent) {
920 if (module->data) {
921 module->data->prev->next = child;
922 child->prev = module->data->prev;
923 module->data->prev = child;
924 } else {
925 module->data = child;
926 }
927 } else {
Radek Krejcif95b6292017-02-13 15:57:37 +0100928 pchild = lys_child(parent, child->nodetype);
929 assert(pchild);
930
Radek Krejcic9d78692017-08-24 17:17:18 +0200931 child->parent = parent;
Radek Krejcif95b6292017-02-13 15:57:37 +0100932 if (!(*pchild)) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200933 /* the only/first child of the parent */
Radek Krejcif95b6292017-02-13 15:57:37 +0100934 *pchild = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200935 iter = child;
936 } else {
937 /* add a new child at the end of parent's child list */
Radek Krejcif95b6292017-02-13 15:57:37 +0100938 iter = (*pchild)->prev;
Radek Krejci41a349b2016-10-24 19:21:59 +0200939 iter->next = child;
940 child->prev = iter;
941 }
942 while (iter->next) {
943 iter = iter->next;
944 iter->parent = parent;
945 }
Radek Krejcic9d78692017-08-24 17:17:18 +0200946 (*pchild)->prev = iter;
Radek Krejci41a349b2016-10-24 19:21:59 +0200947 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200948 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200949
Michal Vaskoe022a562016-09-27 14:24:15 +0200950 /* check config value (but ignore them in groupings and augments) */
Radek Krejcif95b6292017-02-13 15:57:37 +0100951 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); iter = iter->parent);
Michal Vaskoe022a562016-09-27 14:24:15 +0200952 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200953 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
954 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100955 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, child, "true", "config");
956 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200957 return EXIT_FAILURE;
958 }
959 }
960
Radek Krejci41771502016-04-14 17:52:32 +0200961 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200962 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200963 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200964 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200965 /* store it only into container or list - the only data inner nodes */
966 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
967 if (iter->flags & LYS_INCL_STATUS) {
968 /* done, someone else set it already from here */
969 break;
970 }
971 /* set flag about including status data */
972 iter->flags |= LYS_INCL_STATUS;
973 }
974 }
975 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200976
977 /* create implicit input/output nodes to have available them as possible target for augment */
Radek Krejci60251232017-08-24 17:13:08 +0200978 if ((child->nodetype & (LYS_RPC | LYS_ACTION)) && !child->child) {
Radek Krejci41a349b2016-10-24 19:21:59 +0200979 in = calloc(1, sizeof *in);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200980 out = calloc(1, sizeof *out);
981 if (!in || !out) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100982 LOGMEM(ctx);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200983 free(in);
984 free(out);
985 return EXIT_FAILURE;
986 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200987 in->nodetype = LYS_INPUT;
988 in->name = lydict_insert(child->module->ctx, "input", 5);
Radek Krejci41a349b2016-10-24 19:21:59 +0200989 out->nodetype = LYS_OUTPUT;
Radek Krejcia8d111f2017-05-31 13:57:37 +0200990 out->name = lydict_insert(child->module->ctx, "output", 6);
Radek Krejci41a349b2016-10-24 19:21:59 +0200991 in->module = out->module = child->module;
992 in->parent = out->parent = child;
993 in->flags = out->flags = LYS_IMPLICIT;
994 in->next = (struct lys_node *)out;
995 in->prev = (struct lys_node *)out;
996 out->prev = (struct lys_node *)in;
997 child->child = (struct lys_node *)in;
998 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200999 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001000}
1001
Michal Vasko29245662017-04-18 15:56:31 +02001002const struct lys_module *
Michal Vaskofb98dc42018-01-11 13:38:28 +01001003lys_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 +02001004{
Radek Krejcia1df1682016-04-11 14:56:59 +02001005 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001006 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +02001007 unsigned int len;
Radek Krejcif347abc2016-06-22 10:18:47 +02001008
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001009 if (!ctx || !data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001010 LOGARG;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001011 return NULL;
1012 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001013
Radek Krejcia1df1682016-04-11 14:56:59 +02001014 if (!internal && format == LYS_IN_YANG) {
1015 /* enlarge data by 2 bytes for flex */
1016 len = strlen(data);
1017 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
Michal Vasko53b7da02018-02-13 15:28:42 +01001018 LY_CHECK_ERR_RETURN(!enlarged_data, LOGMEM(ctx), NULL);
Radek Krejcia1df1682016-04-11 14:56:59 +02001019 memcpy(enlarged_data, data, len);
1020 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1021 data = enlarged_data;
1022 }
1023
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001024 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001025 case LYS_IN_YIN:
Michal Vaskofb98dc42018-01-11 13:38:28 +01001026 mod = yin_read_module(ctx, data, revision, implement);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001027 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001028 case LYS_IN_YANG:
Michal Vaskofb98dc42018-01-11 13:38:28 +01001029 mod = yang_read_module(ctx, data, 0, revision, implement);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001030 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001031 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001032 LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001033 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001034 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001035
Radek Krejcia1df1682016-04-11 14:56:59 +02001036 free(enlarged_data);
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001037
1038 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
1039 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
1040 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
1041 * the anotation definitions available in the internal schema structure. There is another hack in schema
1042 * printers to do not print this internally added annotation. */
1043 if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
Michal Vaskob3d6d192018-11-05 10:02:10 +01001044 if (lyp_add_ietf_netconf_annotations_config(mod)) {
Michal Vasko10681e82018-01-16 14:54:16 +01001045 lys_free(mod, NULL, 1, 1);
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001046 return NULL;
1047 }
Radek Krejcia68ddeb2017-02-24 12:49:44 +01001048 }
1049
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001050 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001051}
1052
Radek Krejcia1df1682016-04-11 14:56:59 +02001053API const struct lys_module *
1054lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
1055{
Michal Vaskofb98dc42018-01-11 13:38:28 +01001056 return lys_parse_mem_(ctx, data, format, NULL, 0, 1);
Radek Krejcia1df1682016-04-11 14:56:59 +02001057}
1058
Michal Vasko5a721fd2016-02-16 12:16:48 +01001059struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001060lys_sub_parse_mem(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001061{
Michal Vasko5b998712017-01-26 10:34:06 +01001062 char *enlarged_data = NULL;
Michal Vasko5a721fd2016-02-16 12:16:48 +01001063 struct lys_submodule *submod = NULL;
Michal Vasko5b998712017-01-26 10:34:06 +01001064 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001066 assert(module);
1067 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001068
Michal Vasko5b998712017-01-26 10:34:06 +01001069 if (format == LYS_IN_YANG) {
1070 /* enlarge data by 2 bytes for flex */
1071 len = strlen(data);
1072 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
Michal Vasko53b7da02018-02-13 15:28:42 +01001073 LY_CHECK_ERR_RETURN(!enlarged_data, LOGMEM(module->ctx), NULL);
Michal Vasko5b998712017-01-26 10:34:06 +01001074 memcpy(enlarged_data, data, len);
1075 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1076 data = enlarged_data;
1077 }
1078
Radek Krejcic071c542016-01-27 14:57:51 +01001079 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +02001080 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001082 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001083 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001084 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001085 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001086 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001087 submod = yang_read_submodule(module, data, 0, unres);
1088 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001089 default:
Radek Krejci90a550a2016-04-13 16:00:58 +02001090 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001091 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001092 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001093
Michal Vasko5b998712017-01-26 10:34:06 +01001094 free(enlarged_data);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001095 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001096}
1097
Michal Vasko1e62a092015-12-01 12:27:20 +01001098API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001099lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1100{
1101 int fd;
1102 const struct lys_module *ret;
Radek Krejcid80c8602016-10-25 11:56:03 +02001103 const char *rev, *dot, *filename;
1104 size_t len;
Michal Vasko662610a2015-12-07 11:25:45 +01001105
1106 if (!ctx || !path) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001107 LOGARG;
Michal Vasko662610a2015-12-07 11:25:45 +01001108 return NULL;
1109 }
1110
1111 fd = open(path, O_RDONLY);
1112 if (fd == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001113 LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
Michal Vasko662610a2015-12-07 11:25:45 +01001114 return NULL;
1115 }
1116
1117 ret = lys_parse_fd(ctx, fd, format);
1118 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +01001119
Radek Krejcid80c8602016-10-25 11:56:03 +02001120 if (!ret) {
1121 /* error */
1122 return NULL;
1123 }
1124
1125 /* check that name and revision match filename */
1126 filename = strrchr(path, '/');
1127 if (!filename) {
1128 filename = path;
1129 } else {
1130 filename++;
1131 }
1132 rev = strchr(filename, '@');
1133 dot = strrchr(filename, '.');
1134
1135 /* name */
1136 len = strlen(ret->name);
1137 if (strncmp(filename, ret->name, len) ||
1138 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001139 LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, ret->name);
Radek Krejcid80c8602016-10-25 11:56:03 +02001140 }
1141 if (rev) {
1142 len = dot - ++rev;
1143 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001144 LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", filename,
Radek Krejcid80c8602016-10-25 11:56:03 +02001145 ret->rev_size ? ret->rev[0].date : "none");
1146 }
1147 }
1148
1149 if (!ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001150 /* store URI */
Alexandre Snarskii12b22182018-09-04 17:12:28 +03001151 char rpath[PATH_MAX];
1152 if (realpath(path, rpath) != NULL) {
1153 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, rpath, 0);
1154 } else {
1155 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
1156 }
Radek Krejci23f5de52016-02-25 15:53:17 +01001157 }
1158
Michal Vasko662610a2015-12-07 11:25:45 +01001159 return ret;
1160}
1161
1162API const struct lys_module *
1163lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001164{
Michal Vaskofb98dc42018-01-11 13:38:28 +01001165 return lys_parse_fd_(ctx, fd, format, NULL, 1);
1166}
1167
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001168static void
1169lys_parse_set_filename(struct ly_ctx *ctx, const char **filename, int fd)
1170{
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001171#ifdef __APPLE__
1172 char path[MAXPATHLEN];
1173#else
Michal Vasko25601f32018-02-16 09:41:46 +01001174 int len;
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001175 char path[PATH_MAX], proc_path[32];
1176#endif
1177
1178#ifdef __APPLE__
1179 if (fcntl(fd, F_GETPATH, path) != -1) {
1180 *filename = lydict_insert(ctx, path, 0);
1181 }
1182#else
1183 /* get URI if there is /proc */
1184 sprintf(proc_path, "/proc/self/fd/%d", fd);
1185 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
1186 *filename = lydict_insert(ctx, path, len);
1187 }
1188#endif
1189}
1190
Michal Vaskofb98dc42018-01-11 13:38:28 +01001191const struct lys_module *
1192lys_parse_fd_(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, const char *revision, int implement)
1193{
Michal Vasko1e62a092015-12-01 12:27:20 +01001194 const struct lys_module *module;
Radek Krejci0fb11502017-01-31 16:45:42 +01001195 size_t length;
Radek Krejci63a91a92015-07-29 13:31:04 +02001196 char *addr;
1197
1198 if (!ctx || fd < 0) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001199 LOGARG;
Radek Krejci63a91a92015-07-29 13:31:04 +02001200 return NULL;
1201 }
1202
Michal Vasko53b7da02018-02-13 15:28:42 +01001203 if (lyp_mmap(ctx, fd, format == LYS_IN_YANG ? 1 : 0, &length, (void **)&addr)) {
1204 LOGERR(ctx, LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001205 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001206 } else if (!addr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001207 LOGERR(ctx, LY_EINVAL, "Empty schema file.");
Pavol Vicane36ea262015-11-12 11:57:47 +01001208 return NULL;
1209 }
Radek Krejci0fb11502017-01-31 16:45:42 +01001210
Michal Vaskofb98dc42018-01-11 13:38:28 +01001211 module = lys_parse_mem_(ctx, addr, format, revision, 1, implement);
Radek Krejci0fb11502017-01-31 16:45:42 +01001212 lyp_munmap(addr, length);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001213
Radek Krejcia77904e2016-02-25 16:23:45 +01001214 if (module && !module->filepath) {
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001215 lys_parse_set_filename(ctx, (const char **)&module->filepath, fd);
Radek Krejcib051f722016-02-25 15:12:21 +01001216 }
1217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001218 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001219}
1220
Michal Vasko5a721fd2016-02-16 12:16:48 +01001221struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001222lys_sub_parse_fd(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001223{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001224 struct lys_submodule *submodule;
Radek Krejci0fb11502017-01-31 16:45:42 +01001225 size_t length;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001226 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001228 assert(module);
1229 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001230
Michal Vasko53b7da02018-02-13 15:28:42 +01001231 if (lyp_mmap(module->ctx, fd, format == LYS_IN_YANG ? 1 : 0, &length, (void **)&addr)) {
1232 LOGERR(module->ctx, LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001233 return NULL;
Radek Krejci10c216a2017-02-01 10:36:00 +01001234 } else if (!addr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001235 LOGERR(module->ctx, LY_EINVAL, "Empty submodule schema file.");
Michal Vasko2e7241e2016-02-15 16:06:34 +01001236 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001237 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001238
Michal Vasko5b998712017-01-26 10:34:06 +01001239 /* get the main module */
1240 module = lys_main_module(module);
1241
1242 switch (format) {
1243 case LYS_IN_YIN:
1244 submodule = yin_read_submodule(module, addr, unres);
1245 break;
1246 case LYS_IN_YANG:
1247 submodule = yang_read_submodule(module, addr, 0, unres);
1248 break;
1249 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001250 LOGINT(module->ctx);
Michal Vasko85d41522017-02-24 09:49:16 +01001251 return NULL;
Michal Vasko5b998712017-01-26 10:34:06 +01001252 }
1253
Radek Krejcic645a3a2017-01-31 16:59:00 +01001254 lyp_munmap(addr, length);
Michal Vaskob0bbf5f2018-02-16 09:35:59 +01001255
1256 if (submodule && !submodule->filepath) {
1257 lys_parse_set_filename(module->ctx, (const char **)&submodule->filepath, fd);
1258 }
1259
Michal Vasko5a721fd2016-02-16 12:16:48 +01001260 return submodule;
1261
Radek Krejciefaeba32015-05-27 14:30:57 +02001262}
1263
Radek Krejci72cdfac2018-08-15 14:47:33 +02001264API int
Radek Krejcicf3b7ca2018-08-17 09:55:06 +02001265lys_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 +02001266{
1267 size_t len, flen, match_len = 0, dir_len;
1268 int i, implicit_cwd = 0, ret = EXIT_FAILURE;
1269 char *wd, *wn = NULL;
1270 DIR *dir = NULL;
1271 struct dirent *file;
1272 char *match_name = NULL;
1273 LYS_INFORMAT format_aux, match_format = 0;
1274 unsigned int u;
1275 struct ly_set *dirs;
1276 struct stat st;
1277
1278 if (!localfile) {
1279 LOGARG;
1280 return EXIT_FAILURE;
1281 }
1282
1283 /* start to fill the dir fifo with the context's search path (if set)
1284 * and the current working directory */
1285 dirs = ly_set_new();
1286 if (!dirs) {
1287 LOGMEM(NULL);
1288 return EXIT_FAILURE;
1289 }
1290
1291 len = strlen(name);
Radek Krejcicf3b7ca2018-08-17 09:55:06 +02001292 if (cwd) {
1293 wd = get_current_dir_name();
1294 if (!wd) {
1295 LOGMEM(NULL);
Radek Krejci72cdfac2018-08-15 14:47:33 +02001296 goto cleanup;
Radek Krejcicf3b7ca2018-08-17 09:55:06 +02001297 } else {
1298 /* add implicit current working directory (./) to be searched,
1299 * this directory is not searched recursively */
1300 if (ly_set_add(dirs, wd, 0) == -1) {
1301 goto cleanup;
1302 }
1303 implicit_cwd = 1;
Radek Krejci72cdfac2018-08-15 14:47:33 +02001304 }
Radek Krejci72cdfac2018-08-15 14:47:33 +02001305 }
1306 if (searchpaths) {
1307 for (i = 0; searchpaths[i]; i++) {
1308 /* check for duplicities with the implicit current working directory */
1309 if (implicit_cwd && !strcmp(dirs->set.g[0], searchpaths[i])) {
1310 implicit_cwd = 0;
1311 continue;
1312 }
1313 wd = strdup(searchpaths[i]);
1314 if (!wd) {
1315 LOGMEM(NULL);
1316 goto cleanup;
1317 } else if (ly_set_add(dirs, wd, 0) == -1) {
1318 goto cleanup;
1319 }
1320 }
1321 }
1322 wd = NULL;
1323
1324 /* start searching */
1325 while (dirs->number) {
1326 free(wd);
1327 free(wn); wn = NULL;
1328
1329 dirs->number--;
1330 wd = (char *)dirs->set.g[dirs->number];
1331 dirs->set.g[dirs->number] = NULL;
1332 LOGVRB("Searching for \"%s\" in %s.", name, wd);
1333
1334 if (dir) {
1335 closedir(dir);
1336 }
1337 dir = opendir(wd);
1338 dir_len = strlen(wd);
1339 if (!dir) {
1340 LOGWRN(NULL, "Unable to open directory \"%s\" for searching (sub)modules (%s).", wd, strerror(errno));
1341 } else {
1342 while ((file = readdir(dir))) {
1343 if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
1344 /* skip . and .. */
1345 continue;
1346 }
1347 free(wn);
1348 if (asprintf(&wn, "%s/%s", wd, file->d_name) == -1) {
1349 LOGMEM(NULL);
1350 goto cleanup;
1351 }
1352 if (stat(wn, &st) == -1) {
1353 LOGWRN(NULL, "Unable to get information about \"%s\" file in \"%s\" when searching for (sub)modules (%s)",
1354 file->d_name, wd, strerror(errno));
1355 continue;
1356 }
1357 if (S_ISDIR(st.st_mode) && (dirs->number || !implicit_cwd)) {
1358 /* we have another subdirectory in searchpath to explore,
1359 * subdirectories are not taken into account in current working dir (dirs->set.g[0]) */
1360 if (ly_set_add(dirs, wn, 0) == -1) {
1361 goto cleanup;
1362 }
1363 /* continue with the next item in current directory */
1364 wn = NULL;
1365 continue;
1366 } else if (!S_ISREG(st.st_mode)) {
1367 /* not a regular file (note that we see the target of symlinks instead of symlinks */
1368 continue;
1369 }
1370
1371 /* here we know that the item is a file which can contain a module */
1372 if (strncmp(name, file->d_name, len) ||
1373 (file->d_name[len] != '.' && file->d_name[len] != '@')) {
1374 /* different filename than the module we search for */
1375 continue;
1376 }
1377
1378 /* get type according to filename suffix */
1379 flen = strlen(file->d_name);
1380 if (!strcmp(&file->d_name[flen - 4], ".yin")) {
1381 format_aux = LYS_IN_YIN;
1382 } else if (!strcmp(&file->d_name[flen - 5], ".yang")) {
1383 format_aux = LYS_IN_YANG;
1384 } else {
1385 /* not supportde suffix/file format */
1386 continue;
1387 }
1388
1389 if (revision) {
1390 /* we look for the specific revision, try to get it from the filename */
1391 if (file->d_name[len] == '@') {
1392 /* check revision from the filename */
1393 if (strncmp(revision, &file->d_name[len + 1], strlen(revision))) {
1394 /* another revision */
1395 continue;
1396 } else {
1397 /* exact revision */
1398 free(match_name);
1399 match_name = wn;
1400 wn = NULL;
1401 match_len = dir_len + 1 + len;
1402 match_format = format_aux;
1403 goto success;
1404 }
1405 } else {
1406 /* continue trying to find exact revision match, use this only if not found */
1407 free(match_name);
1408 match_name = wn;
1409 wn = NULL;
1410 match_len = dir_len + 1 +len;
1411 match_format = format_aux;
1412 continue;
1413 }
1414 } else {
1415 /* remember the revision and try to find the newest one */
1416 if (match_name) {
1417 if (file->d_name[len] != '@' || lyp_check_date(NULL, &file->d_name[len + 1])) {
1418 continue;
1419 } else if (match_name[match_len] == '@' &&
1420 (strncmp(&match_name[match_len + 1], &file->d_name[len + 1], LY_REV_SIZE - 1) >= 0)) {
1421 continue;
1422 }
1423 free(match_name);
1424 }
1425
1426 match_name = wn;
1427 wn = NULL;
1428 match_len = dir_len + 1 + len;
1429 match_format = format_aux;
1430 continue;
1431 }
1432 }
1433 }
1434 }
1435
1436success:
1437 (*localfile) = match_name;
1438 match_name = NULL;
1439 if (format) {
1440 (*format) = match_format;
1441 }
1442 ret = EXIT_SUCCESS;
1443
1444cleanup:
1445 free(wn);
1446 free(wd);
1447 if (dir) {
1448 closedir(dir);
1449 }
1450 free(match_name);
1451 for (u = 0; u < dirs->number; u++) {
1452 free(dirs->set.g[u]);
1453 }
1454 ly_set_free(dirs);
1455
1456 return ret;
1457}
1458
Radek Krejcibf285832017-01-26 16:05:41 +01001459int
1460lys_ext_iter(struct lys_ext_instance **ext, uint8_t ext_size, uint8_t start, LYEXT_SUBSTMT substmt)
1461{
1462 unsigned int u;
1463
1464 for (u = start; u < ext_size; u++) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001465 if (ext[u]->insubstmt == substmt) {
Radek Krejcibf285832017-01-26 16:05:41 +01001466 return u;
1467 }
1468 }
1469
1470 return -1;
1471}
1472
Radek Krejcifdc0d702017-01-23 15:58:38 +01001473/*
1474 * duplicate extension instance
1475 */
1476int
Michal Vasko17e8ba32018-02-15 10:58:56 +01001477lys_ext_dup(struct ly_ctx *ctx, struct lys_module *mod, struct lys_ext_instance **orig, uint8_t size, void *parent,
1478 LYEXT_PAR parent_type, struct lys_ext_instance ***new, int shallow, struct unres_schema *unres)
Radek Krejcifdc0d702017-01-23 15:58:38 +01001479{
1480 int i;
1481 uint8_t u = 0;
1482 struct lys_ext_instance **result;
1483 struct unres_ext *info, *info_orig;
fanchanghu8d86f6b2017-06-10 12:49:54 +08001484 size_t len;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001485
1486 assert(new);
1487
1488 if (!size) {
1489 if (orig) {
Michal Vasko17e8ba32018-02-15 10:58:56 +01001490 LOGINT(ctx);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001491 return EXIT_FAILURE;
1492 }
1493 (*new) = NULL;
1494 return EXIT_SUCCESS;
1495 }
1496
1497 (*new) = result = calloc(size, sizeof *result);
Michal Vasko17e8ba32018-02-15 10:58:56 +01001498 LY_CHECK_ERR_RETURN(!result, LOGMEM(ctx), EXIT_FAILURE);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001499 for (u = 0; u < size; u++) {
1500 if (orig[u]) {
1501 /* resolved extension instance, just duplicate it */
Radek Krejci8de8f612017-02-16 15:03:32 +01001502 switch(orig[u]->ext_type) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001503 case LYEXT_FLAG:
1504 result[u] = malloc(sizeof(struct lys_ext_instance));
Michal Vasko17e8ba32018-02-15 10:58:56 +01001505 LY_CHECK_ERR_GOTO(!result[u], LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001506 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001507 case LYEXT_COMPLEX:
fanchanghu8d86f6b2017-06-10 12:49:54 +08001508 len = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->instance_size;
1509 result[u] = calloc(1, len);
Michal Vasko17e8ba32018-02-15 10:58:56 +01001510 LY_CHECK_ERR_GOTO(!result[u], LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001511
Radek Krejcifebdad72017-02-06 11:35:51 +01001512 ((struct lys_ext_instance_complex*)result[u])->substmt = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001513 /* TODO duplicate data in extension instance content */
fanchanghu8d86f6b2017-06-10 12:49:54 +08001514 memcpy((void*)result[u] + sizeof(**orig), (void*)orig[u] + sizeof(**orig), len - sizeof(**orig));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001515 break;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001516 }
1517 /* generic part */
1518 result[u]->def = orig[u]->def;
fanchanghu8d86f6b2017-06-10 12:49:54 +08001519 result[u]->flags = LYEXT_OPT_CONTENT;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001520 result[u]->arg_value = lydict_insert(ctx, orig[u]->arg_value, 0);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001521 result[u]->parent = parent;
1522 result[u]->parent_type = parent_type;
Radek Krejcifebdad72017-02-06 11:35:51 +01001523 result[u]->insubstmt = orig[u]->insubstmt;
1524 result[u]->insubstmt_index = orig[u]->insubstmt_index;
Radek Krejci8de8f612017-02-16 15:03:32 +01001525 result[u]->ext_type = orig[u]->ext_type;
Radek Krejci7f1d47e2017-04-12 15:29:02 +02001526 result[u]->priv = NULL;
1527 result[u]->nodetype = LYS_EXT;
1528 result[u]->module = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001529
1530 /* extensions */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001531 result[u]->ext_size = orig[u]->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001532 if (lys_ext_dup(ctx, mod, orig[u]->ext, orig[u]->ext_size, result[u],
Radek Krejci5138e9f2017-04-12 13:10:46 +02001533 LYEXT_PAR_EXTINST, &result[u]->ext, shallow, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01001534 goto error;
1535 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02001536
1537 /* in case of shallow copy (duplication for deviation), duplicate only the link to private data
1538 * in a new copy, otherwise (grouping instantiation) do not duplicate the private data */
1539 if (shallow) {
1540 result[u]->priv = orig[u]->priv;
1541 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01001542 } else {
1543 /* original extension is not yet resolved, so duplicate it in unres */
1544 i = unres_schema_find(unres, -1, &orig, UNRES_EXT);
1545 if (i == -1) {
1546 /* extension not found in unres */
Michal Vasko17e8ba32018-02-15 10:58:56 +01001547 LOGINT(ctx);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001548 goto error;
1549 }
1550 info_orig = unres->str_snode[i];
1551 info = malloc(sizeof *info);
Michal Vasko17e8ba32018-02-15 10:58:56 +01001552 LY_CHECK_ERR_GOTO(!info, LOGMEM(ctx), error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001553 info->datatype = info_orig->datatype;
1554 if (info->datatype == LYS_IN_YIN) {
Michal Vasko17e8ba32018-02-15 10:58:56 +01001555 info->data.yin = lyxml_dup_elem(ctx, info_orig->data.yin, NULL, 1);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001556 } /* else TODO YANG */
1557 info->parent = parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001558 info->mod = mod;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001559 info->parent_type = parent_type;
1560 info->ext_index = u;
1561 if (unres_schema_add_node(info->mod, unres, new, UNRES_EXT, (struct lys_node *)info) == -1) {
1562 goto error;
1563 }
1564 }
1565 }
1566
1567 return EXIT_SUCCESS;
1568
1569error:
1570 (*new) = NULL;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001571 lys_extension_instances_free(ctx, result, u, NULL);
Radek Krejcifdc0d702017-01-23 15:58:38 +01001572 return EXIT_FAILURE;
1573}
1574
Radek Krejci1d82ef62015-08-07 14:44:40 +02001575static struct lys_restr *
Radek Krejci5138e9f2017-04-12 13:10:46 +02001576lys_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 +02001577{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001578 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001579 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001580
Radek Krejci3733a802015-06-19 13:43:21 +02001581 if (!size) {
1582 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001583 }
Radek Krejci3733a802015-06-19 13:43:21 +02001584
1585 result = calloc(size, sizeof *result);
Michal Vasko53b7da02018-02-13 15:28:42 +01001586 LY_CHECK_ERR_RETURN(!result, LOGMEM(mod->ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001587
Radek Krejci3733a802015-06-19 13:43:21 +02001588 for (i = 0; i < size; i++) {
Radek Krejci77f22b22017-01-17 15:23:03 +01001589 result[i].ext_size = old[i].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001590 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 +01001591 result[i].expr = lydict_insert(mod->ctx, old[i].expr, 0);
1592 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1593 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1594 result[i].eapptag = lydict_insert(mod->ctx, old[i].eapptag, 0);
1595 result[i].emsg = lydict_insert(mod->ctx, old[i].emsg, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001596 }
1597
1598 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001599}
1600
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001601void
Radek Krejci5138e9f2017-04-12 13:10:46 +02001602lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr,
1603 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci0bd5db42015-06-19 13:30:07 +02001604{
1605 assert(ctx);
1606 if (!restr) {
1607 return;
1608 }
1609
Radek Krejci5138e9f2017-04-12 13:10:46 +02001610 lys_extension_instances_free(ctx, restr->ext, restr->ext_size, private_destructor);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001611 lydict_remove(ctx, restr->expr);
1612 lydict_remove(ctx, restr->dsc);
1613 lydict_remove(ctx, restr->ref);
1614 lydict_remove(ctx, restr->eapptag);
1615 lydict_remove(ctx, restr->emsg);
1616}
1617
Michal Vaskoe41dfe62018-11-08 13:28:07 +01001618API void
Radek Krejci5138e9f2017-04-12 13:10:46 +02001619lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size,
Frank Rimplerc4db1c72017-09-12 12:56:39 +00001620 int shallow, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001621{
1622 uint8_t i;
1623
1624 for (i = 0; i < iffeature_size; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02001625 lys_extension_instances_free(ctx, iffeature[i].ext, iffeature[i].ext_size, private_destructor);
Michal Vasko15a43372017-09-25 14:12:42 +02001626 if (!shallow) {
Frank Rimpler2a503f52017-09-12 15:21:18 +00001627 free(iffeature[i].expr);
1628 free(iffeature[i].features);
1629 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001630 }
1631 free(iffeature);
1632}
1633
Michal Vaskob84f88a2015-09-24 13:16:10 +02001634static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001635type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001636 LY_DATA_TYPE base, int in_grp, int shallow, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001637{
1638 int i;
Radek Krejcidce5f972017-09-12 15:47:49 +02001639 unsigned int u;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001640
1641 switch (base) {
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001642 case LY_TYPE_BINARY:
1643 if (old->info.binary.length) {
1644 new->info.binary.length = lys_restr_dup(mod, old->info.binary.length, 1, shallow, unres);
1645 }
1646 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001647
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001648 case LY_TYPE_BITS:
1649 new->info.bits.count = old->info.bits.count;
1650 if (new->info.bits.count) {
1651 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
Michal Vasko53b7da02018-02-13 15:28:42 +01001652 LY_CHECK_ERR_RETURN(!new->info.bits.bit, LOGMEM(mod->ctx), -1);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001653
Radek Krejcidce5f972017-09-12 15:47:49 +02001654 for (u = 0; u < new->info.bits.count; u++) {
1655 new->info.bits.bit[u].name = lydict_insert(mod->ctx, old->info.bits.bit[u].name, 0);
1656 new->info.bits.bit[u].dsc = lydict_insert(mod->ctx, old->info.bits.bit[u].dsc, 0);
1657 new->info.bits.bit[u].ref = lydict_insert(mod->ctx, old->info.bits.bit[u].ref, 0);
1658 new->info.bits.bit[u].flags = old->info.bits.bit[u].flags;
1659 new->info.bits.bit[u].pos = old->info.bits.bit[u].pos;
1660 new->info.bits.bit[u].ext_size = old->info.bits.bit[u].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001661 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 +02001662 &new->info.bits.bit[u], LYEXT_PAR_TYPE_BIT,
1663 &new->info.bits.bit[u].ext, shallow, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001664 return -1;
1665 }
1666 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001667 }
1668 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001669
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001670 case LY_TYPE_DEC64:
1671 new->info.dec64.dig = old->info.dec64.dig;
1672 new->info.dec64.div = old->info.dec64.div;
1673 if (old->info.dec64.range) {
1674 new->info.dec64.range = lys_restr_dup(mod, old->info.dec64.range, 1, shallow, unres);
1675 }
1676 break;
1677
1678 case LY_TYPE_ENUM:
1679 new->info.enums.count = old->info.enums.count;
1680 if (new->info.enums.count) {
1681 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Michal Vasko53b7da02018-02-13 15:28:42 +01001682 LY_CHECK_ERR_RETURN(!new->info.enums.enm, LOGMEM(mod->ctx), -1);
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001683
Radek Krejcidce5f972017-09-12 15:47:49 +02001684 for (u = 0; u < new->info.enums.count; u++) {
1685 new->info.enums.enm[u].name = lydict_insert(mod->ctx, old->info.enums.enm[u].name, 0);
1686 new->info.enums.enm[u].dsc = lydict_insert(mod->ctx, old->info.enums.enm[u].dsc, 0);
1687 new->info.enums.enm[u].ref = lydict_insert(mod->ctx, old->info.enums.enm[u].ref, 0);
1688 new->info.enums.enm[u].flags = old->info.enums.enm[u].flags;
1689 new->info.enums.enm[u].value = old->info.enums.enm[u].value;
1690 new->info.enums.enm[u].ext_size = old->info.enums.enm[u].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001691 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 +02001692 &new->info.enums.enm[u], LYEXT_PAR_TYPE_ENUM,
1693 &new->info.enums.enm[u].ext, shallow, unres)) {
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001694 return -1;
1695 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001696 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001697 }
1698 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001699
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001700 case LY_TYPE_IDENT:
1701 new->info.ident.count = old->info.ident.count;
1702 if (old->info.ident.count) {
1703 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
Michal Vasko53b7da02018-02-13 15:28:42 +01001704 LY_CHECK_ERR_RETURN(!new->info.ident.ref, LOGMEM(mod->ctx), -1);
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001705 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1706 } else {
1707 /* there can be several unresolved base identities, duplicate them all */
1708 i = -1;
1709 do {
1710 i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF);
1711 if (i != -1) {
1712 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001713 return -1;
1714 }
1715 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001716 --i;
1717 } while (i > -1);
1718 }
1719 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001720
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001721 case LY_TYPE_INST:
1722 new->info.inst.req = old->info.inst.req;
1723 break;
1724
1725 case LY_TYPE_INT8:
1726 case LY_TYPE_INT16:
1727 case LY_TYPE_INT32:
1728 case LY_TYPE_INT64:
1729 case LY_TYPE_UINT8:
1730 case LY_TYPE_UINT16:
1731 case LY_TYPE_UINT32:
1732 case LY_TYPE_UINT64:
1733 if (old->info.num.range) {
1734 new->info.num.range = lys_restr_dup(mod, old->info.num.range, 1, shallow, unres);
1735 }
1736 break;
1737
1738 case LY_TYPE_LEAFREF:
1739 if (old->info.lref.path) {
1740 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko48c73df2018-10-31 09:09:13 +01001741 new->info.lref.req = old->info.lref.req;
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001742 if (!in_grp && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
1743 return -1;
1744 }
1745 }
1746 break;
1747
1748 case LY_TYPE_STRING:
1749 if (old->info.str.length) {
1750 new->info.str.length = lys_restr_dup(mod, old->info.str.length, 1, shallow, unres);
1751 }
Radek Krejcib53154b2017-07-19 09:14:13 +02001752 if (old->info.str.pat_count) {
1753 new->info.str.patterns = lys_restr_dup(mod, old->info.str.patterns, old->info.str.pat_count, shallow, unres);
1754 new->info.str.pat_count = old->info.str.pat_count;
Michal Vaskofcd974b2017-08-22 10:17:49 +02001755#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001756 if (!in_grp) {
1757 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 +01001758 LY_CHECK_ERR_RETURN(!new->info.str.patterns_pcre, LOGMEM(mod->ctx), -1);
Radek Krejcia4c107d2017-10-27 14:19:26 +02001759 for (u = 0; u < new->info.str.pat_count; u++) {
Michal Vaskoa26db302018-02-14 15:22:10 +01001760 if (lyp_precompile_pattern(mod->ctx, &new->info.str.patterns[u].expr[1],
Radek Krejcia4c107d2017-10-27 14:19:26 +02001761 (pcre**)&new->info.str.patterns_pcre[2 * u],
1762 (pcre_extra**)&new->info.str.patterns_pcre[2 * u + 1])) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001763 free(new->info.str.patterns_pcre);
1764 new->info.str.patterns_pcre = NULL;
1765 return -1;
1766 }
1767 }
1768 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001769#endif
Radek Krejcib53154b2017-07-19 09:14:13 +02001770 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001771 break;
1772
1773 case LY_TYPE_UNION:
1774 new->info.uni.has_ptr_type = old->info.uni.has_ptr_type;
1775 new->info.uni.count = old->info.uni.count;
1776 if (new->info.uni.count) {
1777 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001778 LY_CHECK_ERR_RETURN(!new->info.uni.types, LOGMEM(mod->ctx), -1);
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001779
Radek Krejcidce5f972017-09-12 15:47:49 +02001780 for (u = 0; u < new->info.uni.count; u++) {
1781 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 +02001782 shallow, unres)) {
1783 return -1;
1784 }
1785 }
1786 }
1787 break;
1788
1789 default:
1790 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1791 break;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001792 }
Michal Vaskob4ab1cb2017-06-30 13:14:54 +02001793
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001794 return EXIT_SUCCESS;
1795}
1796
1797struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001798lys_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 +02001799 int in_grp, int shallow, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001800{
1801 struct yang_type *new;
1802
1803 new = calloc(1, sizeof *new);
Michal Vasko53b7da02018-02-13 15:28:42 +01001804 LY_CHECK_ERR_RETURN(!new, LOGMEM(module->ctx), NULL);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001805 new->flags = old->flags;
1806 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001807 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001808 new->type = type;
1809 if (!new->name) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001810 LOGMEM(module->ctx);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001811 goto error;
1812 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02001813 if (type_dup(module, parent, type, old->type, new->base, in_grp, shallow, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001814 new->type->base = new->base;
Radek Krejci5138e9f2017-04-12 13:10:46 +02001815 lys_type_free(module->ctx, new->type, NULL);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001816 memset(&new->type->info, 0, sizeof new->type->info);
1817 goto error;
1818 }
1819 return new;
1820
Michal Vasko53b7da02018-02-13 15:28:42 +01001821error:
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001822 free(new);
1823 return NULL;
1824}
1825
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001826int
1827lys_copy_union_leafrefs(struct lys_module *mod, struct lys_node *parent, struct lys_type *type, struct lys_type *prev_new,
1828 struct unres_schema *unres)
1829{
1830 struct lys_type new;
Radek Krejcidce5f972017-09-12 15:47:49 +02001831 unsigned int i, top_type;
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001832 struct lys_ext_instance **ext;
1833 uint8_t ext_size;
1834 void *reloc;
1835
1836 if (!prev_new) {
1837 /* this is the "top-level" type, meaning it is a real type and no typedef directly above */
1838 top_type = 1;
1839
1840 memset(&new, 0, sizeof new);
1841
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001842 new.base = type->base;
1843 new.parent = (struct lys_tpdf *)parent;
1844
1845 prev_new = &new;
1846 } else {
1847 /* this is not top-level type, just a type of a typedef */
1848 top_type = 0;
1849 }
1850
Radek Krejci9c5cb6d2017-08-09 11:15:23 +02001851 assert(type->der);
1852 if (type->der->module) {
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001853 /* typedef, skip it, but keep the extensions */
1854 ext_size = type->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01001855 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 +02001856 return -1;
1857 }
1858 if (prev_new->ext) {
1859 reloc = realloc(prev_new->ext, (prev_new->ext_size + ext_size) * sizeof *prev_new->ext);
Michal Vasko53b7da02018-02-13 15:28:42 +01001860 LY_CHECK_ERR_RETURN(!reloc, LOGMEM(mod->ctx), -1);
Radek Krejci70379e22017-08-09 11:21:07 +02001861 prev_new->ext = reloc;
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001862
1863 memcpy(prev_new->ext + prev_new->ext_size, ext, ext_size * sizeof *ext);
1864 free(ext);
1865
1866 prev_new->ext_size += ext_size;
1867 } else {
1868 prev_new->ext = ext;
1869 prev_new->ext_size = ext_size;
1870 }
1871
1872 if (lys_copy_union_leafrefs(mod, parent, &type->der->type, prev_new, unres)) {
1873 return -1;
1874 }
1875 } else {
1876 /* type, just make a deep copy */
1877 switch (type->base) {
1878 case LY_TYPE_UNION:
1879 prev_new->info.uni.has_ptr_type = type->info.uni.has_ptr_type;
1880 prev_new->info.uni.count = type->info.uni.count;
1881 /* this cannot be a typedef anymore */
1882 assert(prev_new->info.uni.count);
1883
1884 prev_new->info.uni.types = calloc(prev_new->info.uni.count, sizeof *prev_new->info.uni.types);
Michal Vasko53b7da02018-02-13 15:28:42 +01001885 LY_CHECK_ERR_RETURN(!prev_new->info.uni.types, LOGMEM(mod->ctx), -1);
Michal Vaskoc5c55ca2017-06-30 13:15:18 +02001886
1887 for (i = 0; i < prev_new->info.uni.count; i++) {
1888 if (lys_copy_union_leafrefs(mod, parent, &(type->info.uni.types[i]), &(prev_new->info.uni.types[i]), unres)) {
1889 return -1;
1890 }
1891 }
1892
1893 prev_new->der = type->der;
1894 break;
1895 default:
1896 if (lys_type_dup(mod, parent, prev_new, type, 0, 0, unres)) {
1897 return -1;
1898 }
1899 break;
1900 }
1901 }
1902
1903 if (top_type) {
1904 memcpy(type, prev_new, sizeof *type);
1905 }
1906 return EXIT_SUCCESS;
1907}
1908
Radek Krejci43ce4b72017-01-04 11:02:38 +01001909API const void *
1910lys_ext_instance_substmt(const struct lys_ext_instance *ext)
1911{
1912 if (!ext) {
1913 return NULL;
1914 }
1915
Radek Krejcifebdad72017-02-06 11:35:51 +01001916 switch (ext->insubstmt) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01001917 case LYEXT_SUBSTMT_SELF:
1918 case LYEXT_SUBSTMT_MODIFIER:
1919 case LYEXT_SUBSTMT_VERSION:
1920 return NULL;
1921 case LYEXT_SUBSTMT_ARGUMENT:
1922 if (ext->parent_type == LYEXT_PAR_EXT) {
1923 return ((struct lys_ext_instance*)ext->parent)->arg_value;
1924 }
1925 break;
1926 case LYEXT_SUBSTMT_BASE:
1927 if (ext->parent_type == LYEXT_PAR_TYPE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001928 return ((struct lys_type*)ext->parent)->info.ident.ref[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001929 } else if (ext->parent_type == LYEXT_PAR_IDENT) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001930 return ((struct lys_ident*)ext->parent)->base[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001931 }
1932 break;
1933 case LYEXT_SUBSTMT_BELONGSTO:
1934 if (ext->parent_type == LYEXT_PAR_MODULE && ((struct lys_module*)ext->parent)->type) {
1935 return ((struct lys_submodule*)ext->parent)->belongsto;
1936 }
1937 break;
1938 case LYEXT_SUBSTMT_CONFIG:
1939 case LYEXT_SUBSTMT_MANDATORY:
1940 if (ext->parent_type == LYEXT_PAR_NODE) {
1941 return &((struct lys_node*)ext->parent)->flags;
1942 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
1943 return &((struct lys_deviate*)ext->parent)->flags;
1944 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
1945 return &((struct lys_refine*)ext->parent)->flags;
1946 }
1947 break;
1948 case LYEXT_SUBSTMT_CONTACT:
1949 if (ext->parent_type == LYEXT_PAR_MODULE) {
1950 return ((struct lys_module*)ext->parent)->contact;
1951 }
1952 break;
1953 case LYEXT_SUBSTMT_DEFAULT:
1954 if (ext->parent_type == LYEXT_PAR_NODE) {
1955 switch (((struct lys_node*)ext->parent)->nodetype) {
1956 case LYS_LEAF:
1957 case LYS_LEAFLIST:
1958 /* in case of leaf, the index is supposed to be 0, so it will return the
1959 * correct pointer despite the leaf structure does not have dflt as array */
Radek Krejcifebdad72017-02-06 11:35:51 +01001960 return ((struct lys_node_leaflist*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001961 case LYS_CHOICE:
1962 return ((struct lys_node_choice*)ext->parent)->dflt;
1963 default:
1964 /* internal error */
1965 break;
1966 }
1967 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
1968 return ((struct lys_tpdf*)ext->parent)->dflt;
1969 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001970 return ((struct lys_deviate*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001971 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01001972 return &((struct lys_refine*)ext->parent)->dflt[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01001973 }
1974 break;
1975 case LYEXT_SUBSTMT_DESCRIPTION:
1976 switch (ext->parent_type) {
1977 case LYEXT_PAR_NODE:
1978 return ((struct lys_node*)ext->parent)->dsc;
1979 case LYEXT_PAR_MODULE:
1980 return ((struct lys_module*)ext->parent)->dsc;
1981 case LYEXT_PAR_IMPORT:
1982 return ((struct lys_import*)ext->parent)->dsc;
1983 case LYEXT_PAR_INCLUDE:
1984 return ((struct lys_include*)ext->parent)->dsc;
1985 case LYEXT_PAR_EXT:
1986 return ((struct lys_ext*)ext->parent)->dsc;
1987 case LYEXT_PAR_FEATURE:
1988 return ((struct lys_feature*)ext->parent)->dsc;
1989 case LYEXT_PAR_TPDF:
1990 return ((struct lys_tpdf*)ext->parent)->dsc;
1991 case LYEXT_PAR_TYPE_BIT:
1992 return ((struct lys_type_bit*)ext->parent)->dsc;
1993 case LYEXT_PAR_TYPE_ENUM:
1994 return ((struct lys_type_enum*)ext->parent)->dsc;
Radek Krejcifdc0d702017-01-23 15:58:38 +01001995 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01001996 return ((struct lys_restr*)ext->parent)->dsc;
1997 case LYEXT_PAR_WHEN:
1998 return ((struct lys_when*)ext->parent)->dsc;
1999 case LYEXT_PAR_IDENT:
2000 return ((struct lys_ident*)ext->parent)->dsc;
2001 case LYEXT_PAR_DEVIATION:
2002 return ((struct lys_deviation*)ext->parent)->dsc;
2003 case LYEXT_PAR_REVISION:
2004 return ((struct lys_revision*)ext->parent)->dsc;
2005 case LYEXT_PAR_REFINE:
2006 return ((struct lys_refine*)ext->parent)->dsc;
2007 default:
2008 break;
2009 }
2010 break;
2011 case LYEXT_SUBSTMT_ERRTAG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01002012 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01002013 return ((struct lys_restr*)ext->parent)->eapptag;
2014 }
2015 break;
2016 case LYEXT_SUBSTMT_ERRMSG:
Radek Krejcifdc0d702017-01-23 15:58:38 +01002017 if (ext->parent_type == LYEXT_PAR_RESTR) {
Radek Krejci43ce4b72017-01-04 11:02:38 +01002018 return ((struct lys_restr*)ext->parent)->emsg;
2019 }
2020 break;
2021 case LYEXT_SUBSTMT_DIGITS:
2022 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_DEC64) {
2023 return &((struct lys_type*)ext->parent)->info.dec64.dig;
2024 }
2025 break;
2026 case LYEXT_SUBSTMT_KEY:
2027 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2028 return ((struct lys_node_list*)ext->parent)->keys;
2029 }
2030 break;
2031 case LYEXT_SUBSTMT_MAX:
2032 if (ext->parent_type == LYEXT_PAR_NODE) {
2033 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2034 return &((struct lys_node_list*)ext->parent)->max;
2035 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
2036 return &((struct lys_node_leaflist*)ext->parent)->max;
2037 }
2038 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2039 return &((struct lys_refine*)ext->parent)->mod.list.max;
2040 }
2041 break;
2042 case LYEXT_SUBSTMT_MIN:
2043 if (ext->parent_type == LYEXT_PAR_NODE) {
2044 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2045 return &((struct lys_node_list*)ext->parent)->min;
2046 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
2047 return &((struct lys_node_leaflist*)ext->parent)->min;
2048 }
2049 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2050 return &((struct lys_refine*)ext->parent)->mod.list.min;
2051 }
2052 break;
2053 case LYEXT_SUBSTMT_NAMESPACE:
2054 if (ext->parent_type == LYEXT_PAR_MODULE && !((struct lys_module*)ext->parent)->type) {
2055 return ((struct lys_module*)ext->parent)->ns;
2056 }
2057 break;
2058 case LYEXT_SUBSTMT_ORDEREDBY:
2059 if (ext->parent_type == LYEXT_PAR_NODE &&
2060 (((struct lys_node*)ext->parent)->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
2061 return &((struct lys_node_list*)ext->parent)->flags;
2062 }
2063 break;
2064 case LYEXT_SUBSTMT_ORGANIZATION:
2065 if (ext->parent_type == LYEXT_PAR_MODULE) {
2066 return ((struct lys_module*)ext->parent)->org;
2067 }
2068 break;
2069 case LYEXT_SUBSTMT_PATH:
2070 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
2071 return ((struct lys_type*)ext->parent)->info.lref.path;
2072 }
2073 break;
2074 case LYEXT_SUBSTMT_POSITION:
2075 if (ext->parent_type == LYEXT_PAR_TYPE_BIT) {
2076 return &((struct lys_type_bit*)ext->parent)->pos;
2077 }
2078 break;
2079 case LYEXT_SUBSTMT_PREFIX:
2080 if (ext->parent_type == LYEXT_PAR_MODULE) {
2081 /* covers also lys_submodule */
2082 return ((struct lys_module*)ext->parent)->prefix;
2083 } else if (ext->parent_type == LYEXT_PAR_IMPORT) {
2084 return ((struct lys_import*)ext->parent)->prefix;
2085 }
2086 break;
2087 case LYEXT_SUBSTMT_PRESENCE:
2088 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_CONTAINER) {
2089 return ((struct lys_node_container*)ext->parent)->presence;
2090 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2091 return ((struct lys_refine*)ext->parent)->mod.presence;
2092 }
2093 break;
2094 case LYEXT_SUBSTMT_REFERENCE:
2095 switch (ext->parent_type) {
2096 case LYEXT_PAR_NODE:
2097 return ((struct lys_node*)ext->parent)->ref;
2098 case LYEXT_PAR_MODULE:
2099 return ((struct lys_module*)ext->parent)->ref;
2100 case LYEXT_PAR_IMPORT:
2101 return ((struct lys_import*)ext->parent)->ref;
2102 case LYEXT_PAR_INCLUDE:
2103 return ((struct lys_include*)ext->parent)->ref;
2104 case LYEXT_PAR_EXT:
2105 return ((struct lys_ext*)ext->parent)->ref;
2106 case LYEXT_PAR_FEATURE:
2107 return ((struct lys_feature*)ext->parent)->ref;
2108 case LYEXT_PAR_TPDF:
2109 return ((struct lys_tpdf*)ext->parent)->ref;
2110 case LYEXT_PAR_TYPE_BIT:
2111 return ((struct lys_type_bit*)ext->parent)->ref;
2112 case LYEXT_PAR_TYPE_ENUM:
2113 return ((struct lys_type_enum*)ext->parent)->ref;
Radek Krejcifdc0d702017-01-23 15:58:38 +01002114 case LYEXT_PAR_RESTR:
Radek Krejci43ce4b72017-01-04 11:02:38 +01002115 return ((struct lys_restr*)ext->parent)->ref;
2116 case LYEXT_PAR_WHEN:
2117 return ((struct lys_when*)ext->parent)->ref;
2118 case LYEXT_PAR_IDENT:
2119 return ((struct lys_ident*)ext->parent)->ref;
2120 case LYEXT_PAR_DEVIATION:
2121 return ((struct lys_deviation*)ext->parent)->ref;
2122 case LYEXT_PAR_REVISION:
2123 return ((struct lys_revision*)ext->parent)->ref;
2124 case LYEXT_PAR_REFINE:
2125 return ((struct lys_refine*)ext->parent)->ref;
2126 default:
2127 break;
2128 }
2129 break;
Radek Krejcibe336392017-02-07 10:54:24 +01002130 case LYEXT_SUBSTMT_REQINSTANCE:
Radek Krejci43ce4b72017-01-04 11:02:38 +01002131 if (ext->parent_type == LYEXT_PAR_TYPE) {
2132 if (((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
2133 return &((struct lys_type*)ext->parent)->info.lref.req;
2134 } else if (((struct lys_type*)ext->parent)->base == LY_TYPE_INST) {
2135 return &((struct lys_type*)ext->parent)->info.inst.req;
2136 }
2137 }
2138 break;
2139 case LYEXT_SUBSTMT_REVISIONDATE:
2140 if (ext->parent_type == LYEXT_PAR_IMPORT) {
2141 return ((struct lys_import*)ext->parent)->rev;
2142 } else if (ext->parent_type == LYEXT_PAR_INCLUDE) {
2143 return ((struct lys_include*)ext->parent)->rev;
2144 }
2145 break;
2146 case LYEXT_SUBSTMT_STATUS:
2147 switch (ext->parent_type) {
2148 case LYEXT_PAR_NODE:
2149 case LYEXT_PAR_IDENT:
2150 case LYEXT_PAR_TPDF:
2151 case LYEXT_PAR_EXT:
2152 case LYEXT_PAR_FEATURE:
2153 case LYEXT_PAR_TYPE_ENUM:
2154 case LYEXT_PAR_TYPE_BIT:
2155 /* in all structures the flags member is at the same offset */
2156 return &((struct lys_node*)ext->parent)->flags;
2157 default:
2158 break;
2159 }
2160 break;
2161 case LYEXT_SUBSTMT_UNIQUE:
2162 if (ext->parent_type == LYEXT_PAR_DEVIATE) {
Radek Krejcifebdad72017-02-06 11:35:51 +01002163 return &((struct lys_deviate*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01002164 } else if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
Radek Krejcifebdad72017-02-06 11:35:51 +01002165 return &((struct lys_node_list*)ext->parent)->unique[ext->insubstmt_index];
Radek Krejci43ce4b72017-01-04 11:02:38 +01002166 }
2167 break;
2168 case LYEXT_SUBSTMT_UNITS:
2169 if (ext->parent_type == LYEXT_PAR_NODE &&
2170 (((struct lys_node*)ext->parent)->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2171 /* units is at the same offset in both lys_node_leaf and lys_node_leaflist */
2172 return ((struct lys_node_leaf*)ext->parent)->units;
2173 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
2174 return ((struct lys_tpdf*)ext->parent)->units;
2175 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
2176 return ((struct lys_deviate*)ext->parent)->units;
2177 }
2178 break;
2179 case LYEXT_SUBSTMT_VALUE:
2180 if (ext->parent_type == LYEXT_PAR_TYPE_ENUM) {
2181 return &((struct lys_type_enum*)ext->parent)->value;
2182 }
2183 break;
2184 case LYEXT_SUBSTMT_YINELEM:
2185 if (ext->parent_type == LYEXT_PAR_EXT) {
2186 return &((struct lys_ext*)ext->parent)->flags;
2187 }
2188 break;
2189 }
Michal Vasko53b7da02018-02-13 15:28:42 +01002190 LOGINT(ext->module->ctx);
Radek Krejci43ce4b72017-01-04 11:02:38 +01002191 return NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01002192}
2193
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02002194static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002195lys_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 +02002196 int in_grp, int shallow, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02002197{
2198 int i;
2199
Radek Krejci3733a802015-06-19 13:43:21 +02002200 new->base = old->base;
2201 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02002202 new->parent = (struct lys_tpdf *)parent;
Radek Krejcif0bb3602017-01-25 17:05:08 +01002203 new->ext_size = old->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01002204 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 +01002205 return -1;
Radek Krejcie534c132016-11-23 13:32:31 +01002206 }
Radek Krejci3733a802015-06-19 13:43:21 +02002207
Michal Vasko1c007172017-03-10 10:20:44 +01002208 i = unres_schema_find(unres, -1, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002209 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01002210 /* HACK (serious one) for unres */
2211 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02002212 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002213 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, in_grp,
2214 shallow, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02002215 } else {
2216 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
2217 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02002218 /* all these unres additions can fail even though they did not before */
Michal Vasko1c007172017-03-10 10:20:44 +01002219 if (!new->der || (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent) == -1)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002220 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02002221 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02002222 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002223 }
2224
Radek Krejci5138e9f2017-04-12 13:10:46 +02002225 return type_dup(mod, parent, new, old, new->base, in_grp, shallow, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02002226}
2227
2228void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002229lys_type_free(struct ly_ctx *ctx, struct lys_type *type,
2230 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002231{
Radek Krejcidce5f972017-09-12 15:47:49 +02002232 unsigned int i;
Radek Krejci5a065542015-05-22 15:02:07 +02002233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 assert(ctx);
2235 if (!type) {
2236 return;
2237 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002238
Radek Krejci5138e9f2017-04-12 13:10:46 +02002239 lys_extension_instances_free(ctx, type->ext, type->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002241 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02002242 case LY_TYPE_BINARY:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002243 lys_restr_free(ctx, type->info.binary.length, private_destructor);
Radek Krejci0bd5db42015-06-19 13:30:07 +02002244 free(type->info.binary.length);
2245 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02002246 case LY_TYPE_BITS:
2247 for (i = 0; i < type->info.bits.count; i++) {
2248 lydict_remove(ctx, type->info.bits.bit[i].name);
2249 lydict_remove(ctx, type->info.bits.bit[i].dsc);
2250 lydict_remove(ctx, type->info.bits.bit[i].ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002251 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 +02002252 private_destructor);
2253 lys_extension_instances_free(ctx, type->info.bits.bit[i].ext, type->info.bits.bit[i].ext_size,
2254 private_destructor);
Radek Krejci994b6f62015-06-18 16:47:27 +02002255 }
2256 free(type->info.bits.bit);
2257 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02002258
2259 case LY_TYPE_DEC64:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002260 lys_restr_free(ctx, type->info.dec64.range, private_destructor);
Radek Krejcif9401c32015-06-26 16:47:36 +02002261 free(type->info.dec64.range);
2262 break;
2263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002264 case LY_TYPE_ENUM:
2265 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002266 lydict_remove(ctx, type->info.enums.enm[i].name);
2267 lydict_remove(ctx, type->info.enums.enm[i].dsc);
2268 lydict_remove(ctx, type->info.enums.enm[i].ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002269 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 +02002270 private_destructor);
2271 lys_extension_instances_free(ctx, type->info.enums.enm[i].ext, type->info.enums.enm[i].ext_size,
2272 private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002273 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02002274 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002275 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02002276
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02002277 case LY_TYPE_INT8:
2278 case LY_TYPE_INT16:
2279 case LY_TYPE_INT32:
2280 case LY_TYPE_INT64:
2281 case LY_TYPE_UINT8:
2282 case LY_TYPE_UINT16:
2283 case LY_TYPE_UINT32:
2284 case LY_TYPE_UINT64:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002285 lys_restr_free(ctx, type->info.num.range, private_destructor);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02002286 free(type->info.num.range);
2287 break;
2288
Radek Krejcidc4c1412015-06-19 15:39:54 +02002289 case LY_TYPE_LEAFREF:
2290 lydict_remove(ctx, type->info.lref.path);
2291 break;
2292
Radek Krejci3733a802015-06-19 13:43:21 +02002293 case LY_TYPE_STRING:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002294 lys_restr_free(ctx, type->info.str.length, private_destructor);
Radek Krejci3733a802015-06-19 13:43:21 +02002295 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02002296 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002297 lys_restr_free(ctx, &type->info.str.patterns[i], private_destructor);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002298#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02002299 if (type->info.str.patterns_pcre) {
2300 pcre_free((pcre*)type->info.str.patterns_pcre[2 * i]);
2301 pcre_free_study((pcre_extra*)type->info.str.patterns_pcre[2 * i + 1]);
2302 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02002303#endif
Radek Krejci5fbc9162015-06-19 14:11:11 +02002304 }
2305 free(type->info.str.patterns);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002306#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02002307 free(type->info.str.patterns_pcre);
Michal Vaskofcd974b2017-08-22 10:17:49 +02002308#endif
Radek Krejci3733a802015-06-19 13:43:21 +02002309 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02002310
Radek Krejcie4c366b2015-07-02 10:11:31 +02002311 case LY_TYPE_UNION:
2312 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002313 lys_type_free(ctx, &type->info.uni.types[i], private_destructor);
Radek Krejcie4c366b2015-07-02 10:11:31 +02002314 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02002315 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02002316 break;
2317
Michal Vaskod3282192016-09-05 11:27:57 +02002318 case LY_TYPE_IDENT:
2319 free(type->info.ident.ref);
2320 break;
2321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 default:
Michal Vaskod3282192016-09-05 11:27:57 +02002323 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 break;
2325 }
Radek Krejci5a065542015-05-22 15:02:07 +02002326}
2327
Radek Krejci1d82ef62015-08-07 14:44:40 +02002328static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002329lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf,
2330 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002331{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002332 assert(ctx);
2333 if (!tpdf) {
2334 return;
2335 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 lydict_remove(ctx, tpdf->name);
2338 lydict_remove(ctx, tpdf->dsc);
2339 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002340
Radek Krejci5138e9f2017-04-12 13:10:46 +02002341 lys_type_free(ctx, &tpdf->type, private_destructor);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002342
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002343 lydict_remove(ctx, tpdf->units);
2344 lydict_remove(ctx, tpdf->dflt);
Radek Krejcie534c132016-11-23 13:32:31 +01002345
Radek Krejci5138e9f2017-04-12 13:10:46 +02002346 lys_extension_instances_free(ctx, tpdf->ext, tpdf->ext_size, private_destructor);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002347}
2348
Radek Krejci1d82ef62015-08-07 14:44:40 +02002349static struct lys_when *
Radek Krejci5138e9f2017-04-12 13:10:46 +02002350lys_when_dup(struct lys_module *mod, struct lys_when *old, int shallow, struct unres_schema *unres)
Radek Krejci00768f42015-06-18 17:04:04 +02002351{
Radek Krejci76512572015-08-04 09:47:08 +02002352 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02002353
2354 if (!old) {
2355 return NULL;
2356 }
2357
2358 new = calloc(1, sizeof *new);
Michal Vasko53b7da02018-02-13 15:28:42 +01002359 LY_CHECK_ERR_RETURN(!new, LOGMEM(mod->ctx), NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01002360 new->cond = lydict_insert(mod->ctx, old->cond, 0);
2361 new->dsc = lydict_insert(mod->ctx, old->dsc, 0);
2362 new->ref = lydict_insert(mod->ctx, old->ref, 0);
Radek Krejcif0bb3602017-01-25 17:05:08 +01002363 new->ext_size = old->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01002364 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 +02002365
2366 return new;
2367}
2368
Michal Vasko0308dd62015-10-07 09:14:40 +02002369void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002370lys_when_free(struct ly_ctx *ctx, struct lys_when *w,
2371 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002372{
2373 if (!w) {
2374 return;
2375 }
2376
Radek Krejci5138e9f2017-04-12 13:10:46 +02002377 lys_extension_instances_free(ctx, w->ext, w->ext_size, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002378 lydict_remove(ctx, w->cond);
2379 lydict_remove(ctx, w->dsc);
2380 lydict_remove(ctx, w->ref);
2381
2382 free(w);
2383}
2384
Radek Krejcib7f5e412015-08-13 10:15:51 +02002385static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002386lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment *aug,
2387 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib7f5e412015-08-13 10:15:51 +02002388{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02002389 struct lys_node *next, *sub;
2390
Radek Krejcic071c542016-01-27 14:57:51 +01002391 /* children from a resolved augment are freed under the target node */
Radek Krejci0ec51da2016-12-14 16:42:03 +01002392 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002393 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002394 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002395 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02002396 }
2397
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002398 lydict_remove(ctx, aug->target_name);
2399 lydict_remove(ctx, aug->dsc);
2400 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002401
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002402 lys_iffeature_free(ctx, aug->iffeature, aug->iffeature_size, 0, private_destructor);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002403 lys_extension_instances_free(ctx, aug->ext, aug->ext_size, private_destructor);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002404
Radek Krejci5138e9f2017-04-12 13:10:46 +02002405 lys_when_free(ctx, aug->when, private_destructor);
Radek Krejcib7f5e412015-08-13 10:15:51 +02002406}
2407
Radek Krejci1d82ef62015-08-07 14:44:40 +02002408static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002409lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident,
2410 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci6793db02015-05-22 17:49:54 +02002411{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002412 assert(ctx);
2413 if (!ident) {
2414 return;
2415 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002416
Radek Krejci018f1f52016-08-03 16:01:20 +02002417 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02002418 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002419 lydict_remove(ctx, ident->name);
2420 lydict_remove(ctx, ident->dsc);
2421 lydict_remove(ctx, ident->ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002422 lys_iffeature_free(ctx, ident->iffeature, ident->iffeature_size, 0, private_destructor);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002423 lys_extension_instances_free(ctx, ident->ext, ident->ext_size, private_destructor);
Radek Krejci6793db02015-05-22 17:49:54 +02002424
2425}
2426
Radek Krejci1d82ef62015-08-07 14:44:40 +02002427static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002428lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp,
2429 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002430{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002431 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002432
Radek Krejcid12f57b2015-08-06 10:43:39 +02002433 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002434 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002435 lys_tpdf_free(ctx, &grp->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002436 }
2437 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02002438}
2439
Radek Krejci1d82ef62015-08-07 14:44:40 +02002440static void
Michal Vasko1e82a3b2018-07-03 12:16:58 +02002441lys_rpc_action_free(struct ly_ctx *ctx, struct lys_node_rpc_action *rpc_act,
2442 void (*private_destructor)(const struct lys_node *node, void *priv))
2443{
2444 int i;
2445
2446 /* handle only specific parts for LYS_GROUPING */
2447 for (i = 0; i < rpc_act->tpdf_size; i++) {
2448 lys_tpdf_free(ctx, &rpc_act->tpdf[i], private_destructor);
2449 }
2450 free(rpc_act->tpdf);
2451}
2452
2453static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002454lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io,
2455 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcid12f57b2015-08-06 10:43:39 +02002456{
2457 int i;
2458
2459 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
2460 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002461 lys_tpdf_free(ctx, &io->tpdf[i], private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002462 }
2463 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002464
2465 for (i = 0; i < io->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002466 lys_restr_free(ctx, &io->must[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002467 }
2468 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002469}
2470
Radek Krejci1d82ef62015-08-07 14:44:40 +02002471static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002472lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif,
2473 void (*private_destructor)(const struct lys_node *node, void *priv))
Pavol Vican7cff97e2016-08-09 14:56:08 +02002474{
2475 int i;
2476
2477 for (i = 0; i < notif->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002478 lys_restr_free(ctx, &notif->must[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002479 }
2480 free(notif->must);
2481
2482 for (i = 0; i < notif->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002483 lys_tpdf_free(ctx, &notif->tpdf[i], private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002484 }
2485 free(notif->tpdf);
2486}
2487static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002488lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml,
2489 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci537cf382015-06-04 11:07:01 +02002490{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002491 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002493 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002494 lys_restr_free(ctx, &anyxml->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002495 }
2496 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002497
Radek Krejci5138e9f2017-04-12 13:10:46 +02002498 lys_when_free(ctx, anyxml->when, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002499}
2500
Radek Krejci1d82ef62015-08-07 14:44:40 +02002501static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002502lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf,
2503 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002504{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002505 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002506
Radek Krejci85a54be2016-10-20 12:39:56 +02002507 /* leafref backlinks */
2508 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002509
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002510 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002511 lys_restr_free(ctx, &leaf->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002512 }
2513 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002514
Radek Krejci5138e9f2017-04-12 13:10:46 +02002515 lys_when_free(ctx, leaf->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002516
Radek Krejci5138e9f2017-04-12 13:10:46 +02002517 lys_type_free(ctx, &leaf->type, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002518 lydict_remove(ctx, leaf->units);
2519 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02002520}
2521
Radek Krejci1d82ef62015-08-07 14:44:40 +02002522static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002523lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist,
2524 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci5a065542015-05-22 15:02:07 +02002525{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002526 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02002527
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002528 if (llist->backlinks) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002529 /* leafref backlinks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002530 ly_set_free(llist->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002531 }
2532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002533 for (i = 0; i < llist->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002534 lys_restr_free(ctx, &llist->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002535 }
2536 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002537
Pavol Vican38321d02016-08-16 14:56:02 +02002538 for (i = 0; i < llist->dflt_size; i++) {
2539 lydict_remove(ctx, llist->dflt[i]);
2540 }
2541 free(llist->dflt);
2542
Radek Krejci5138e9f2017-04-12 13:10:46 +02002543 lys_when_free(ctx, llist->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002544
Radek Krejci5138e9f2017-04-12 13:10:46 +02002545 lys_type_free(ctx, &llist->type, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002546 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02002547}
2548
Radek Krejci1d82ef62015-08-07 14:44:40 +02002549static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002550lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list,
2551 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002552{
Radek Krejci581ce772015-11-10 17:22:40 +01002553 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002555 /* handle only specific parts for LY_NODE_LIST */
Michal Vaskoaaeab1d2018-02-16 09:36:46 +01002556 lys_when_free(ctx, list->when, private_destructor);
Radek Krejci537cf382015-06-04 11:07:01 +02002557
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002558 for (i = 0; i < list->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002559 lys_restr_free(ctx, &list->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002560 }
2561 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02002562
Michal Vaskoaaeab1d2018-02-16 09:36:46 +01002563 for (i = 0; i < list->tpdf_size; i++) {
2564 lys_tpdf_free(ctx, &list->tpdf[i], private_destructor);
2565 }
2566 free(list->tpdf);
2567
2568 free(list->keys);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002569
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002570 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02002571 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002572 lydict_remove(ctx, list->unique[i].expr[j]);
2573 }
2574 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002575 }
2576 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02002577
Michal Vaskoaaeab1d2018-02-16 09:36:46 +01002578 lydict_remove(ctx, list->keys_str);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002579}
2580
Radek Krejci1d82ef62015-08-07 14:44:40 +02002581static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002582lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont,
2583 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002584{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002585 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002587 /* handle only specific parts for LY_NODE_CONTAINER */
2588 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02002589
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002590 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002591 lys_tpdf_free(ctx, &cont->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002592 }
2593 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02002594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002595 for (i = 0; i < cont->must_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002596 lys_restr_free(ctx, &cont->must[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002597 }
2598 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002599
Radek Krejci5138e9f2017-04-12 13:10:46 +02002600 lys_when_free(ctx, cont->when, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002601}
2602
Radek Krejci1d82ef62015-08-07 14:44:40 +02002603static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002604lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f,
2605 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci3cf9e222015-06-18 11:37:50 +02002606{
2607 lydict_remove(ctx, f->name);
2608 lydict_remove(ctx, f->dsc);
2609 lydict_remove(ctx, f->ref);
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002610 lys_iffeature_free(ctx, f->iffeature, f->iffeature_size, 0, private_destructor);
Radek Krejci9de2c042016-10-19 16:53:06 +02002611 ly_set_free(f->depfeatures);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002612 lys_extension_instances_free(ctx, f->ext, f->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002613}
2614
2615static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002616lys_extension_free(struct ly_ctx *ctx, struct lys_ext *e,
2617 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie534c132016-11-23 13:32:31 +01002618{
2619 lydict_remove(ctx, e->name);
2620 lydict_remove(ctx, e->dsc);
2621 lydict_remove(ctx, e->ref);
2622 lydict_remove(ctx, e->argument);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002623 lys_extension_instances_free(ctx, e->ext, e->ext_size, private_destructor);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002624}
2625
Radek Krejci1d82ef62015-08-07 14:44:40 +02002626static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002627lys_deviation_free(struct lys_module *module, struct lys_deviation *dev,
2628 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcieb00f512015-07-01 16:44:58 +02002629{
Radek Krejci581ce772015-11-10 17:22:40 +01002630 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01002631 struct ly_ctx *ctx;
2632 struct lys_node *next, *elem;
2633
2634 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02002635
2636 lydict_remove(ctx, dev->target_name);
2637 lydict_remove(ctx, dev->dsc);
2638 lydict_remove(ctx, dev->ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002639 lys_extension_instances_free(ctx, dev->ext, dev->ext_size, private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002640
Pavol Vican64d0b762016-08-25 10:44:59 +02002641 if (!dev->deviate) {
Michal Vasko7427b262018-05-14 15:23:55 +02002642 return;
Pavol Vican64d0b762016-08-25 10:44:59 +02002643 }
2644
Michal Vasko7427b262018-05-14 15:23:55 +02002645 /* it could not be applied because it failed to be applied */
2646 if (dev->orig_node) {
2647 /* the module was freed, but we only need the context from orig_node, use ours */
2648 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2649 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
2650 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
2651 elem->module = module;
Michal Vaskoff006c12016-02-17 11:15:19 +01002652
Michal Vasko7427b262018-05-14 15:23:55 +02002653 LY_TREE_DFS_END(dev->orig_node, next, elem);
2654 }
2655 lys_node_free(dev->orig_node, NULL, 0);
2656 } else {
2657 /* it's just a shallow copy, freeing one node */
2658 dev->orig_node->module = module;
2659 lys_node_free(dev->orig_node, NULL, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002660 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002661 }
2662
Radek Krejcieb00f512015-07-01 16:44:58 +02002663 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002664 lys_extension_instances_free(ctx, dev->deviate[i].ext, dev->deviate[i].ext_size, private_destructor);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002665
Radek Krejcid5a5c282016-08-15 15:38:08 +02002666 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02002667 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002668 }
2669 free(dev->deviate[i].dflt);
2670
Radek Krejcieb00f512015-07-01 16:44:58 +02002671 lydict_remove(ctx, dev->deviate[i].units);
2672
2673 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2674 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002675 lys_restr_free(ctx, &dev->deviate[i].must[j], private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002676 }
2677 free(dev->deviate[i].must);
2678
2679 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002680 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
2681 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
2682 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01002683 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002684 }
2685 free(dev->deviate[i].unique);
2686 }
2687 }
2688 free(dev->deviate);
2689}
2690
Radek Krejci1d82ef62015-08-07 14:44:40 +02002691static void
Radek Krejci5138e9f2017-04-12 13:10:46 +02002692lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses,
2693 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie1fa8582015-06-08 09:46:45 +02002694{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002695 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02002696
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002697 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02002698 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002699 lydict_remove(ctx, uses->refine[i].dsc);
2700 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002701
Radek Krejcifde04bd2017-09-13 16:38:38 +02002702 lys_iffeature_free(ctx, uses->refine[i].iffeature, uses->refine[i].iffeature_size, 0, private_destructor);
2703
Michal Vaskoa275c0a2015-09-24 09:55:42 +02002704 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002705 lys_restr_free(ctx, &uses->refine[i].must[j], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002706 }
2707 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002708
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002709 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02002710 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002711 }
2712 free(uses->refine[i].dflt);
2713
Radek Krejci5138e9f2017-04-12 13:10:46 +02002714 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002715
Pavol Vican3e7c73a2016-08-17 10:24:11 +02002716 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002717 lydict_remove(ctx, uses->refine[i].mod.presence);
2718 }
2719 }
2720 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002721
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002722 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002723 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002724 }
2725 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002726
Radek Krejci5138e9f2017-04-12 13:10:46 +02002727 lys_when_free(ctx, uses->when, private_destructor);
Radek Krejcie1fa8582015-06-08 09:46:45 +02002728}
2729
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002730void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002731lys_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 +02002732{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002733 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002734 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002735
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002736 if (!node) {
2737 return;
2738 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002739
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002740 assert(node->module);
2741 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02002742
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002743 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002744
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002745 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002746 if (node->priv && private_destructor) {
2747 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002748 }
2749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002750 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02002751 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002752 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Frank Rimplerc4db1c72017-09-12 12:56:39 +00002753 lys_iffeature_free(ctx, node->iffeature, node->iffeature_size, shallow, private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002754 lydict_remove(ctx, node->dsc);
2755 lydict_remove(ctx, node->ref);
2756 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002757
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002758 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01002759 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002760 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01002761 }
2762 }
2763
Radek Krejci5138e9f2017-04-12 13:10:46 +02002764 lys_extension_instances_free(ctx, node->ext, node->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002765
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002766 /* specific part */
2767 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002768 case LYS_CONTAINER:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002769 lys_container_free(ctx, (struct lys_node_container *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002770 break;
Radek Krejci76512572015-08-04 09:47:08 +02002771 case LYS_CHOICE:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002772 lys_when_free(ctx, ((struct lys_node_choice *)node)->when, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002773 break;
Radek Krejci76512572015-08-04 09:47:08 +02002774 case LYS_LEAF:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002775 lys_leaf_free(ctx, (struct lys_node_leaf *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002776 break;
Radek Krejci76512572015-08-04 09:47:08 +02002777 case LYS_LEAFLIST:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002778 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002779 break;
Radek Krejci76512572015-08-04 09:47:08 +02002780 case LYS_LIST:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002781 lys_list_free(ctx, (struct lys_node_list *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002782 break;
Radek Krejci76512572015-08-04 09:47:08 +02002783 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002784 case LYS_ANYDATA:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002785 lys_anydata_free(ctx, (struct lys_node_anydata *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002786 break;
Radek Krejci76512572015-08-04 09:47:08 +02002787 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002788 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002789 break;
Radek Krejci76512572015-08-04 09:47:08 +02002790 case LYS_CASE:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002791 lys_when_free(ctx, ((struct lys_node_case *)node)->when, private_destructor);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002792 break;
Radek Krejci76512572015-08-04 09:47:08 +02002793 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002794 /* do nothing */
2795 break;
Radek Krejci76512572015-08-04 09:47:08 +02002796 case LYS_GROUPING:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02002797 lys_grp_free(ctx, (struct lys_node_grp *)node, private_destructor);
2798 break;
Radek Krejci76512572015-08-04 09:47:08 +02002799 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002800 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02002801 lys_rpc_action_free(ctx, (struct lys_node_rpc_action *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002802 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02002803 case LYS_NOTIF:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002804 lys_notif_free(ctx, (struct lys_node_notif *)node, private_destructor);
Pavol Vican7cff97e2016-08-09 14:56:08 +02002805 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02002806 case LYS_INPUT:
2807 case LYS_OUTPUT:
Radek Krejci5138e9f2017-04-12 13:10:46 +02002808 lys_inout_free(ctx, (struct lys_node_inout *)node, private_destructor);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002809 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01002810 case LYS_EXT:
Michal Vasko591e0b22015-08-13 13:53:43 +02002811 case LYS_UNKNOWN:
Michal Vasko53b7da02018-02-13 15:28:42 +01002812 LOGINT(ctx);
Michal Vasko591e0b22015-08-13 13:53:43 +02002813 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002814 }
Radek Krejci5a065542015-05-22 15:02:07 +02002815
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002816 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002817 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002818 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002819}
2820
Radek Krejci2eee5c02016-12-06 19:18:05 +01002821API struct lys_module *
2822lys_implemented_module(const struct lys_module *mod)
Radek Krejci0fa54e92016-09-14 14:01:05 +02002823{
2824 struct ly_ctx *ctx;
2825 int i;
2826
2827 if (!mod || mod->implemented) {
2828 /* invalid argument or the module itself is implemented */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002829 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002830 }
2831
2832 ctx = mod->ctx;
2833 for (i = 0; i < ctx->models.used; i++) {
2834 if (!ctx->models.list[i]->implemented) {
2835 continue;
2836 }
2837
2838 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
2839 /* we have some revision of the module implemented */
2840 return ctx->models.list[i];
2841 }
2842 }
2843
2844 /* we have no revision of the module implemented, return the module itself,
2845 * it is up to the caller to set the module implemented when needed */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002846 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002847}
2848
Michal Vasko13b15832015-08-19 11:04:48 +02002849/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002850static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002851module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002852{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002853 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002854 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002855 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002856
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002857 assert(module->ctx);
2858 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002859
Michal Vaskob746fff2016-02-11 11:37:50 +01002860 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002861 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002862 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002863 lydict_remove(ctx, module->imp[i].dsc);
2864 lydict_remove(ctx, module->imp[i].ref);
Radek Krejci5138e9f2017-04-12 13:10:46 +02002865 lys_extension_instances_free(ctx, module->imp[i].ext, module->imp[i].ext_size, private_destructor);
Radek Krejci225376f2016-02-16 17:36:22 +01002866 }
Radek Krejcidce51452015-06-16 15:20:08 +02002867 free(module->imp);
2868
Radek Krejcic071c542016-01-27 14:57:51 +01002869 /* submodules don't have data tree, the data nodes
2870 * are placed in the main module altogether */
2871 if (!module->type) {
2872 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002873 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002874 }
Radek Krejci21181962015-06-30 14:11:00 +02002875 }
Radek Krejci5a065542015-05-22 15:02:07 +02002876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002877 lydict_remove(ctx, module->dsc);
2878 lydict_remove(ctx, module->ref);
2879 lydict_remove(ctx, module->org);
2880 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002881 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002882
Radek Krejcieb00f512015-07-01 16:44:58 +02002883 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002884 for (i = 0; i < module->rev_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002885 lys_extension_instances_free(ctx, module->rev[i].ext, module->rev[i].ext_size, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002886 lydict_remove(ctx, module->rev[i].dsc);
2887 lydict_remove(ctx, module->rev[i].ref);
2888 }
2889 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002890
Radek Krejcieb00f512015-07-01 16:44:58 +02002891 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002892 for (i = 0; i < module->ident_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002893 lys_ident_free(ctx, &module->ident[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002894 }
2895 module->ident_size = 0;
2896 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002897
Radek Krejcieb00f512015-07-01 16:44:58 +02002898 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002899 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002900 lys_tpdf_free(ctx, &module->tpdf[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002901 }
2902 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002903
Radek Krejcie534c132016-11-23 13:32:31 +01002904 /* extension instances */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002905 lys_extension_instances_free(ctx, module->ext, module->ext_size, private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002906
Radek Krejcieb00f512015-07-01 16:44:58 +02002907 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002908 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002909 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002910 }
2911 free(module->augment);
2912
Radek Krejcieb00f512015-07-01 16:44:58 +02002913 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002914 for (i = 0; i < module->features_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002915 lys_feature_free(ctx, &module->features[i], private_destructor);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002916 }
2917 free(module->features);
2918
Radek Krejcieb00f512015-07-01 16:44:58 +02002919 /* deviations */
2920 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002921 lys_deviation_free(module, &module->deviation[i], private_destructor);
Radek Krejcieb00f512015-07-01 16:44:58 +02002922 }
2923 free(module->deviation);
2924
Radek Krejcie534c132016-11-23 13:32:31 +01002925 /* extensions */
2926 for (i = 0; i < module->extensions_size; i++) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02002927 lys_extension_free(ctx, &module->extensions[i], private_destructor);
Radek Krejcie534c132016-11-23 13:32:31 +01002928 }
2929 free(module->extensions);
2930
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002931 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002932 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002933}
2934
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002935void
Michal Vaskob746fff2016-02-11 11:37:50 +01002936lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002937{
Michal Vasko10681e82018-01-16 14:54:16 +01002938 int i;
2939
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002940 if (!submodule) {
2941 return;
2942 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002944 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002945 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002946
Michal Vasko10681e82018-01-16 14:54:16 +01002947 /* include */
2948 for (i = 0; i < submodule->inc_size; i++) {
2949 lydict_remove(submodule->ctx, submodule->inc[i].dsc);
2950 lydict_remove(submodule->ctx, submodule->inc[i].ref);
2951 lys_extension_instances_free(submodule->ctx, submodule->inc[i].ext, submodule->inc[i].ext_size, private_destructor);
2952 /* complete submodule free is done only from main module since
2953 * submodules propagate their includes to the main module */
2954 }
2955 free(submodule->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002956
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002957 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002958}
2959
Radek Krejcib53154b2017-07-19 09:14:13 +02002960int
2961lys_ingrouping(const struct lys_node *node)
Radek Krejci3a5501d2016-07-18 22:03:34 +02002962{
2963 const struct lys_node *iter = node;
2964 assert(node);
2965
2966 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2967 if (!iter) {
2968 return 0;
2969 } else {
2970 return 1;
2971 }
2972}
2973
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002974/*
2975 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
2976 */
2977static struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01002978lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002979 struct unres_schema *unres, int shallow, int finalize)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002980{
Radek Krejci7b9f5662016-11-07 16:28:37 +01002981 struct lys_node *retval = NULL, *iter, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002982 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002983 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002984 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002985 struct unres_list_uniq *unique_info;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002986 uint16_t flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002987
Michal Vaskoc07187d2015-08-13 15:20:57 +02002988 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002989 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002990 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002991 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002992 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002993 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002994 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002995 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002996 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002997 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002998 struct lys_node_anydata *any = NULL;
2999 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02003000 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003001 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02003002 struct lys_node_rpc_action *rpc = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02003003 struct lys_node_inout *io = NULL;
Radek Krejcic43151c2017-03-12 07:10:52 +01003004 struct lys_node_notif *ntf = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02003005 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003006 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003008 /* we cannot just duplicate memory since the strings are stored in
3009 * dictionary and we need to update dictionary counters.
3010 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003011
Radek Krejci1d82ef62015-08-07 14:44:40 +02003012 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02003013 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003014 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003015 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003016 break;
3017
Radek Krejci76512572015-08-04 09:47:08 +02003018 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003019 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02003020 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003021 break;
3022
Radek Krejci76512572015-08-04 09:47:08 +02003023 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003024 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02003025 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003026 break;
3027
Radek Krejci76512572015-08-04 09:47:08 +02003028 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003029 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003030 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003031 break;
3032
Radek Krejci76512572015-08-04 09:47:08 +02003033 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003034 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003035 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003036 break;
3037
Radek Krejci76512572015-08-04 09:47:08 +02003038 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02003039 case LYS_ANYDATA:
3040 any = calloc(1, sizeof *any);
3041 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003042 break;
3043
Radek Krejci76512572015-08-04 09:47:08 +02003044 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003045 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02003046 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003047 break;
3048
Radek Krejci76512572015-08-04 09:47:08 +02003049 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003050 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02003051 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003052 break;
3053
Radek Krejci76512572015-08-04 09:47:08 +02003054 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02003055 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02003056 rpc = calloc(1, sizeof *rpc);
3057 retval = (struct lys_node *)rpc;
3058 break;
3059
Radek Krejci76512572015-08-04 09:47:08 +02003060 case LYS_INPUT:
3061 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02003062 io = calloc(1, sizeof *io);
3063 retval = (struct lys_node *)io;
3064 break;
3065
Radek Krejci76512572015-08-04 09:47:08 +02003066 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02003067 ntf = calloc(1, sizeof *ntf);
3068 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02003069 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003070
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003071 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01003072 LOGINT(ctx);
Michal Vasko49168a22015-08-17 16:35:41 +02003073 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003074 }
Michal Vasko53b7da02018-02-13 15:28:42 +01003075 LY_CHECK_ERR_RETURN(!retval, LOGMEM(ctx), NULL);
Michal Vasko253035f2015-12-17 16:58:13 +01003076
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003077 /*
3078 * duplicate generic part of the structure
3079 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003080 retval->name = lydict_insert(ctx, node->name, 0);
3081 retval->dsc = lydict_insert(ctx, node->dsc, 0);
3082 retval->ref = lydict_insert(ctx, node->ref, 0);
3083 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003084
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003085 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003086 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003087
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003088 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003089
Radek Krejcif0bb3602017-01-25 17:05:08 +01003090 retval->ext_size = node->ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01003091 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 +01003092 goto error;
3093 }
3094
Radek Krejci06214042016-11-04 16:25:58 +01003095 if (node->iffeature_size) {
3096 retval->iffeature_size = node->iffeature_size;
3097 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
Michal Vasko53b7da02018-02-13 15:28:42 +01003098 LY_CHECK_ERR_GOTO(!retval->iffeature, LOGMEM(ctx), error);
Michal Vasko253035f2015-12-17 16:58:13 +01003099 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003100
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003101 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003102 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02003103 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
3104 if (size1) {
3105 /* there is something to duplicate */
3106
3107 /* duplicate compiled expression */
3108 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
3109 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01003110 LY_CHECK_ERR_GOTO(!retval->iffeature[i].expr, LOGMEM(ctx), error);
Radek Krejci9ff0a922016-07-14 13:08:05 +02003111 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
3112
3113 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02003114 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Michal Vasko53b7da02018-02-13 15:28:42 +01003115 LY_CHECK_ERR_GOTO(!retval->iffeature[i].features, LOGMEM(ctx); free(retval->iffeature[i].expr), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003116
Radek Krejci9ff0a922016-07-14 13:08:05 +02003117 for (j = 0; (unsigned int)j < size2; j++) {
3118 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
3119 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02003120 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02003121 /* feature is resolved in origin, so copy it
3122 * - duplication is used for instantiating groupings
3123 * and if-feature inside grouping is supposed to be
3124 * resolved inside the original grouping, so we want
3125 * to keep pointers to features from the grouping
3126 * context */
3127 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
3128 } else if (rc == -1) {
3129 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02003130 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02003131 }
3132 }
Radek Krejcif0bb3602017-01-25 17:05:08 +01003133
3134 /* duplicate if-feature's extensions */
3135 retval->iffeature[i].ext_size = node->iffeature[i].ext_size;
Michal Vasko17e8ba32018-02-15 10:58:56 +01003136 if (lys_ext_dup(ctx, module, node->iffeature[i].ext, node->iffeature[i].ext_size,
Radek Krejci5138e9f2017-04-12 13:10:46 +02003137 &retval->iffeature[i], LYEXT_PAR_IFFEATURE, &retval->iffeature[i].ext, shallow, unres)) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003138 goto error;
3139 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003140 }
Michal Vaskoff006c12016-02-17 11:15:19 +01003141
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003142 /* inherit config flags */
Radek Krejci7b9f5662016-11-07 16:28:37 +01003143 p = parent;
3144 do {
3145 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
3146 } while (iter && iter->nodetype == LYS_AUGMENT && (p = lys_parent(iter)));
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003147 if (iter) {
3148 flags = iter->flags & LYS_CONFIG_MASK;
3149 } else {
3150 /* default */
3151 flags = LYS_CONFIG_W;
3152 }
3153
3154 switch (finalize) {
3155 case 1:
3156 /* inherit config flags */
3157 if (retval->flags & LYS_CONFIG_SET) {
3158 /* skip nodes with an explicit config value */
3159 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003160 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
3161 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003162 goto error;
3163 }
3164 break;
3165 }
3166
3167 if (retval->nodetype != LYS_USES) {
3168 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
3169 }
Radek Krejci2cc25322017-09-06 16:32:02 +02003170
3171 /* inherit status */
Radek Krejcie2807ea2017-09-07 10:52:21 +02003172 if ((parent->flags & LYS_STATUS_MASK) > (retval->flags & LYS_STATUS_MASK)) {
3173 /* but do it only in case the parent has a stonger status */
3174 retval->flags &= ~LYS_STATUS_MASK;
3175 retval->flags |= (parent->flags & LYS_STATUS_MASK);
3176 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003177 break;
3178 case 2:
3179 /* erase config flags */
3180 retval->flags &= ~LYS_CONFIG_MASK;
3181 retval->flags &= ~LYS_CONFIG_SET;
3182 break;
3183 }
3184
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003185 /* connect it to the parent */
Michal Vasko8d30dd82018-09-10 10:06:12 +02003186 if (lys_node_addchild(parent, retval->module, retval, 0)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003187 goto error;
3188 }
Radek Krejcidce51452015-06-16 15:20:08 +02003189
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003190 /* go recursively */
3191 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003192 LY_TREE_FOR(node->child, iter) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003193 if (iter->nodetype & LYS_GROUPING) {
3194 /* do not instantiate groupings */
3195 continue;
3196 }
Radek Krejci6ff885d2017-01-03 14:06:22 +01003197 if (!lys_node_dup_recursion(module, retval, iter, unres, 0, finalize)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003198 goto error;
3199 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003200 }
3201 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003202
3203 if (finalize == 1) {
3204 /* check that configuration lists have keys
3205 * - we really want to check keys_size in original node, because the keys are
3206 * not yet resolved here, it is done below in nodetype specific part */
3207 if ((retval->nodetype == LYS_LIST) && (retval->flags & LYS_CONFIG_W)
3208 && !((struct lys_node_list *)node)->keys_size) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003209 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003210 goto error;
3211 }
3212 }
Michal Vaskoff006c12016-02-17 11:15:19 +01003213 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003214 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 }
3216
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003217 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003218 * duplicate specific part of the structure
3219 */
3220 switch (node->nodetype) {
3221 case LYS_CONTAINER:
3222 if (cont_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003223 cont->when = lys_when_dup(module, cont_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003224 LY_CHECK_GOTO(!cont->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 }
3226 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003227
Radek Krejcia8d111f2017-05-31 13:57:37 +02003228 if (cont_orig->must) {
3229 cont->must = lys_restr_dup(module, cont_orig->must, cont_orig->must_size, shallow, unres);
3230 LY_CHECK_GOTO(!cont->must, error);
3231 cont->must_size = cont_orig->must_size;
3232 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003233
Radek Krejcif0bb3602017-01-25 17:05:08 +01003234 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
3235
3236 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003237 case LYS_CHOICE:
3238 if (choice_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003239 choice->when = lys_when_dup(module, choice_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003240 LY_CHECK_GOTO(!choice->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003241 }
3242
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003243 if (!shallow) {
3244 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003245 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
3246 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
3247 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003248 if (rc) {
3249 if (rc == EXIT_FAILURE) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003250 LOGINT(ctx);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003251 }
3252 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02003253 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003254 } else {
3255 /* useless to check return value, we don't know whether
3256 * there really wasn't any default defined or it just hasn't
3257 * been resolved, we just hope for the best :)
3258 */
3259 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02003260 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003261 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003262 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003263 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003264 break;
3265
3266 case LYS_LEAF:
Radek Krejcib53154b2017-07-19 09:14:13 +02003267 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), lys_ingrouping(retval), shallow, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02003268 goto error;
3269 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003270 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
3271
3272 if (leaf_orig->dflt) {
3273 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003274 }
3275
Radek Krejcia8d111f2017-05-31 13:57:37 +02003276 if (leaf_orig->must) {
3277 leaf->must = lys_restr_dup(module, leaf_orig->must, leaf_orig->must_size, shallow, unres);
3278 LY_CHECK_GOTO(!leaf->must, error);
3279 leaf->must_size = leaf_orig->must_size;
3280 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003281
3282 if (leaf_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003283 leaf->when = lys_when_dup(module, leaf_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003284 LY_CHECK_GOTO(!leaf->when, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003285 }
3286 break;
3287
3288 case LYS_LEAFLIST:
Radek Krejcib53154b2017-07-19 09:14:13 +02003289 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), lys_ingrouping(retval), shallow, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02003290 goto error;
3291 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003292 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
3293
3294 llist->min = llist_orig->min;
3295 llist->max = llist_orig->max;
3296
Radek Krejcia8d111f2017-05-31 13:57:37 +02003297 if (llist_orig->must) {
3298 llist->must = lys_restr_dup(module, llist_orig->must, llist_orig->must_size, shallow, unres);
3299 LY_CHECK_GOTO(!llist->must, error);
3300 llist->must_size = llist_orig->must_size;
3301 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003302
Radek Krejcia8d111f2017-05-31 13:57:37 +02003303 if (llist_orig->dflt) {
3304 llist->dflt = malloc(llist_orig->dflt_size * sizeof *llist->dflt);
Michal Vasko53b7da02018-02-13 15:28:42 +01003305 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003306 llist->dflt_size = llist_orig->dflt_size;
Radek Krejcia8d111f2017-05-31 13:57:37 +02003307
Radek Krejcic699e422017-06-02 15:18:58 +02003308 for (i = 0; i < llist->dflt_size; i++) {
3309 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
Radek Krejci51673202016-11-01 17:00:32 +01003310 }
3311 }
3312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003313 if (llist_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003314 llist->when = lys_when_dup(module, llist_orig->when, shallow, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003315 }
3316 break;
3317
3318 case LYS_LIST:
3319 list->min = list_orig->min;
3320 list->max = list_orig->max;
3321
Radek Krejcia8d111f2017-05-31 13:57:37 +02003322 if (list_orig->must) {
3323 list->must = lys_restr_dup(module, list_orig->must, list_orig->must_size, shallow, unres);
3324 LY_CHECK_GOTO(!list->must, error);
3325 list->must_size = list_orig->must_size;
3326 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003327
Radek Krejcif0bb3602017-01-25 17:05:08 +01003328 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Michal Vasko38d01f72015-06-15 09:41:06 +02003329
Radek Krejcia8d111f2017-05-31 13:57:37 +02003330 if (list_orig->keys_size) {
3331 list->keys = calloc(list_orig->keys_size, sizeof *list->keys);
Michal Vasko53b7da02018-02-13 15:28:42 +01003332 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
Radek Krejci5c08a992016-11-02 13:30:04 +01003333 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003334 list->keys_size = list_orig->keys_size;
Michal Vasko0ea41032015-06-16 08:53:55 +02003335
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003336 if (!shallow) {
Radek Krejci7a1e6072018-08-13 14:59:16 +02003337 if (unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci5c08a992016-11-02 13:30:04 +01003338 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003339 }
Michal Vasko0ea41032015-06-16 08:53:55 +02003340 } else {
Radek Krejcia8d111f2017-05-31 13:57:37 +02003341 memcpy(list->keys, list_orig->keys, list_orig->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02003342 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02003343 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003344
Radek Krejcia8d111f2017-05-31 13:57:37 +02003345 if (list_orig->unique) {
3346 list->unique = malloc(list_orig->unique_size * sizeof *list->unique);
Michal Vasko53b7da02018-02-13 15:28:42 +01003347 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM(ctx), error);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003348 list->unique_size = list_orig->unique_size;
Radek Krejci581ce772015-11-10 17:22:40 +01003349
Radek Krejcic699e422017-06-02 15:18:58 +02003350 for (i = 0; i < list->unique_size; ++i) {
3351 list->unique[i].expr = malloc(list_orig->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko53b7da02018-02-13 15:28:42 +01003352 LY_CHECK_ERR_GOTO(!list->unique[i].expr, LOGMEM(ctx), error);
Radek Krejcic699e422017-06-02 15:18:58 +02003353 list->unique[i].expr_size = list_orig->unique[i].expr_size;
3354 for (j = 0; j < list->unique[i].expr_size; j++) {
3355 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
3356
3357 /* if it stays in unres list, duplicate it also there */
3358 unique_info = malloc(sizeof *unique_info);
Michal Vasko53b7da02018-02-13 15:28:42 +01003359 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM(ctx), error);
Radek Krejcic699e422017-06-02 15:18:58 +02003360 unique_info->list = (struct lys_node *)list;
3361 unique_info->expr = list->unique[i].expr[j];
3362 unique_info->trg_type = &list->unique[i].trg_type;
3363 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
3364 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003365 }
3366 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003368 if (list_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003369 list->when = lys_when_dup(module, list_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003370 LY_CHECK_GOTO(!list->when, error);
Radek Krejciefaeba32015-05-27 14:30:57 +02003371 }
Radek Krejcidce51452015-06-16 15:20:08 +02003372 break;
3373
3374 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02003375 case LYS_ANYDATA:
Radek Krejcia8d111f2017-05-31 13:57:37 +02003376 if (any_orig->must) {
3377 any->must = lys_restr_dup(module, any_orig->must, any_orig->must_size, shallow, unres);
3378 LY_CHECK_GOTO(!any->must, error);
3379 any->must_size = any_orig->must_size;
3380 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003381
Radek Krejcibf2abff2016-08-23 15:51:52 +02003382 if (any_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003383 any->when = lys_when_dup(module, any_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003384 LY_CHECK_GOTO(!any->when, error);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003385 }
3386 break;
3387
3388 case LYS_USES:
3389 uses->grp = uses_orig->grp;
3390
3391 if (uses_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003392 uses->when = lys_when_dup(module, uses_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003393 LY_CHECK_GOTO(!uses->when, error);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003394 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003395 /* it is not needed to duplicate refine, nor augment. They are already applied to the uses children */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003396 break;
3397
3398 case LYS_CASE:
3399 if (cs_orig->when) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02003400 cs->when = lys_when_dup(module, cs_orig->when, shallow, unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003401 LY_CHECK_GOTO(!cs->when, error);
Radek Krejcidce51452015-06-16 15:20:08 +02003402 }
3403 break;
3404
Radek Krejci96935402016-11-04 16:27:28 +01003405 case LYS_ACTION:
Radek Krejcidce51452015-06-16 15:20:08 +02003406 case LYS_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003407 case LYS_INPUT:
3408 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02003409 case LYS_NOTIF:
Radek Krejcif0bb3602017-01-25 17:05:08 +01003410 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003411 break;
3412
3413 default:
3414 /* LY_NODE_AUGMENT */
Michal Vasko53b7da02018-02-13 15:28:42 +01003415 LOGINT(ctx);
Michal Vasko49168a22015-08-17 16:35:41 +02003416 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003417 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003418
3419 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02003420
3421error:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003422 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02003423 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003424}
3425
Radek Krejcib3142312016-11-09 11:04:12 +01003426int
3427lys_has_xpath(const struct lys_node *node)
3428{
3429 assert(node);
3430
3431 switch (node->nodetype) {
3432 case LYS_AUGMENT:
3433 if (((struct lys_node_augment *)node)->when) {
3434 return 1;
3435 }
3436 break;
3437 case LYS_CASE:
3438 if (((struct lys_node_case *)node)->when) {
3439 return 1;
3440 }
3441 break;
3442 case LYS_CHOICE:
3443 if (((struct lys_node_choice *)node)->when) {
3444 return 1;
3445 }
3446 break;
3447 case LYS_ANYDATA:
3448 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
3449 return 1;
3450 }
3451 break;
3452 case LYS_LEAF:
3453 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
3454 return 1;
3455 }
3456 break;
3457 case LYS_LEAFLIST:
3458 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
3459 return 1;
3460 }
3461 break;
3462 case LYS_LIST:
3463 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
3464 return 1;
3465 }
3466 break;
3467 case LYS_CONTAINER:
3468 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
3469 return 1;
3470 }
3471 break;
3472 case LYS_INPUT:
3473 case LYS_OUTPUT:
3474 if (((struct lys_node_inout *)node)->must_size) {
3475 return 1;
3476 }
3477 break;
3478 case LYS_NOTIF:
3479 if (((struct lys_node_notif *)node)->must_size) {
3480 return 1;
3481 }
3482 break;
3483 case LYS_USES:
3484 if (((struct lys_node_uses *)node)->when) {
3485 return 1;
3486 }
3487 break;
3488 default:
3489 /* does not have XPath */
3490 break;
3491 }
3492
3493 return 0;
3494}
3495
Michal Vasko568b1952018-01-30 15:53:30 +01003496int
3497lys_type_is_local(const struct lys_type *type)
3498{
3499 if (!type->der->module) {
3500 /* build-in type */
3501 return 1;
3502 }
3503 /* type->parent can be either a typedef or leaf/leaf-list, but module pointers are compatible */
3504 return (lys_main_module(type->der->module) == lys_main_module(((struct lys_tpdf *)type->parent)->module));
3505}
3506
Radek Krejci2cc25322017-09-06 16:32:02 +02003507/*
3508 * shallow -
3509 * - do not inherit status from the parent
3510 */
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003511struct lys_node *
Radek Krejci6ff885d2017-01-03 14:06:22 +01003512lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003513 struct unres_schema *unres, int shallow)
3514{
3515 struct lys_node *p = NULL;
Radek Krejcib3142312016-11-09 11:04:12 +01003516 int finalize = 0;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003517 struct lys_node *result, *iter, *next;
3518
3519 if (!shallow) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003520 /* 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 +02003521 for (p = parent;
3522 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
3523 p = lys_parent(p));
3524 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
3525 }
3526
Radek Krejci6ff885d2017-01-03 14:06:22 +01003527 result = lys_node_dup_recursion(module, parent, node, unres, shallow, finalize);
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003528 if (finalize) {
3529 /* check xpath expressions in the instantiated tree */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003530 for (iter = next = result; iter; iter = next) {
Radek Krejcib3142312016-11-09 11:04:12 +01003531 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
Radek Krejci3c48d042016-11-07 14:42:36 +01003532 /* invalid xpath */
3533 return NULL;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003534 }
3535
3536 /* select next item */
3537 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
3538 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
3539 next = NULL;
3540 } else {
3541 next = iter->child;
3542 }
3543 if (!next) {
3544 /* no children, try siblings */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003545 if (iter == result) {
3546 /* we are done, no next element to process */
3547 break;
3548 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003549 next = iter->next;
3550 }
3551 while (!next) {
3552 /* parent is already processed, go to its sibling */
3553 iter = lys_parent(iter);
Radek Krejci7212e0a2017-03-08 15:58:22 +01003554 if (lys_parent(iter) == lys_parent(result)) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02003555 /* we are done, no next element to process */
3556 break;
3557 }
3558 next = iter->next;
3559 }
3560 }
3561 }
3562
3563 return result;
3564}
3565
Michal Vasko81c71442018-08-03 12:56:53 +02003566/**
3567 * @brief Switch contents of two same schema nodes. One of the nodes
3568 * is expected to be ashallow copy of the other.
3569 *
3570 * @param[in] node1 Node whose contents will be switched with \p node2.
3571 * @param[in] node2 Node whose contents will be switched with \p node1.
3572 */
3573static void
3574lys_node_switch(struct lys_node *node1, struct lys_node *node2)
Michal Vaskoff006c12016-02-17 11:15:19 +01003575{
Michal Vasko81c71442018-08-03 12:56:53 +02003576 const size_t mem_size = 104;
3577 uint8_t mem[mem_size];
3578 size_t offset, size;
Michal Vaskoff006c12016-02-17 11:15:19 +01003579
Michal Vasko81c71442018-08-03 12:56:53 +02003580 assert((node1->module == node2->module) && ly_strequal(node1->name, node2->name, 1) && (node1->nodetype == node2->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01003581
Michal Vasko81c71442018-08-03 12:56:53 +02003582 /*
3583 * Initially, the nodes were really switched in the tree which
3584 * caused problems for some other nodes with pointers (augments, leafrefs, ...)
3585 * because their pointers were not being updated. Code kept in case there is
3586 * a use of it in future (it took some debugging to cover all the cases).
3587
3588 * sibling next *
3589 if (node1->prev->next) {
3590 node1->prev->next = node2;
Michal Vaskoff006c12016-02-17 11:15:19 +01003591 }
3592
Michal Vasko81c71442018-08-03 12:56:53 +02003593 * sibling prev *
3594 if (node1->next) {
3595 node1->next->prev = node2;
Michal Vasko8328da82016-08-25 09:27:22 +02003596 } else {
Michal Vasko81c71442018-08-03 12:56:53 +02003597 for (child = node1->prev; child->prev->next; child = child->prev);
3598 child->prev = node2;
Michal Vaskoff006c12016-02-17 11:15:19 +01003599 }
3600
Michal Vasko81c71442018-08-03 12:56:53 +02003601 * next *
3602 node2->next = node1->next;
3603 node1->next = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01003604
Michal Vasko81c71442018-08-03 12:56:53 +02003605 * prev *
3606 if (node1->prev != node1) {
3607 node2->prev = node1->prev;
Michal Vaskoff006c12016-02-17 11:15:19 +01003608 }
Michal Vasko81c71442018-08-03 12:56:53 +02003609 node1->prev = node1;
Michal Vaskoff006c12016-02-17 11:15:19 +01003610
Michal Vasko81c71442018-08-03 12:56:53 +02003611 * parent child *
3612 if (node1->parent) {
3613 if (node1->parent->child == node1) {
3614 node1->parent->child = node2;
Radek Krejci30bfcd22017-01-27 16:54:48 +01003615 }
Michal Vasko81c71442018-08-03 12:56:53 +02003616 } else if (lys_main_module(node1->module)->data == node1) {
3617 lys_main_module(node1->module)->data = node2;
Michal Vaskoff006c12016-02-17 11:15:19 +01003618 }
3619
Michal Vasko81c71442018-08-03 12:56:53 +02003620 * parent *
3621 node2->parent = node1->parent;
3622 node1->parent = NULL;
Radek Krejci30bfcd22017-01-27 16:54:48 +01003623
Michal Vasko81c71442018-08-03 12:56:53 +02003624 * child parent *
3625 LY_TREE_FOR(node1->child, child) {
3626 if (child->parent == node1) {
3627 child->parent = node2;
Michal Vaskoff006c12016-02-17 11:15:19 +01003628 }
3629 }
3630
Michal Vasko81c71442018-08-03 12:56:53 +02003631 * child *
3632 node2->child = node1->child;
3633 node1->child = NULL;
3634 */
Radek Krejcif0bb3602017-01-25 17:05:08 +01003635
Michal Vasko81c71442018-08-03 12:56:53 +02003636 /* switch common node part */
3637 offset = 3 * sizeof(char *);
3638 size = sizeof(uint16_t) + 6 * sizeof(uint8_t) + sizeof(struct lys_ext_instance **) + sizeof(struct lys_iffeature *);
3639 memcpy(mem, ((uint8_t *)node1) + offset, size);
3640 memcpy(((uint8_t *)node1) + offset, ((uint8_t *)node2) + offset, size);
3641 memcpy(((uint8_t *)node2) + offset, mem, size);
3642
3643 /* switch node-specific data */
3644 offset = sizeof(struct lys_node);
3645 switch (node1->nodetype) {
Radek Krejcif0bb3602017-01-25 17:05:08 +01003646 case LYS_CONTAINER:
Michal Vasko81c71442018-08-03 12:56:53 +02003647 size = sizeof(struct lys_node_container) - offset;
3648 break;
3649 case LYS_CHOICE:
3650 size = sizeof(struct lys_node_choice) - offset;
3651 break;
3652 case LYS_LEAF:
3653 size = sizeof(struct lys_node_leaf) - offset;
3654 break;
3655 case LYS_LEAFLIST:
3656 size = sizeof(struct lys_node_leaflist) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003657 break;
3658 case LYS_LIST:
Michal Vasko81c71442018-08-03 12:56:53 +02003659 size = sizeof(struct lys_node_list) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003660 break;
Michal Vasko81c71442018-08-03 12:56:53 +02003661 case LYS_ANYDATA:
3662 case LYS_ANYXML:
3663 size = sizeof(struct lys_node_anydata) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003664 break;
Michal Vasko81c71442018-08-03 12:56:53 +02003665 case LYS_CASE:
3666 size = sizeof(struct lys_node_case) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003667 break;
3668 case LYS_INPUT:
3669 case LYS_OUTPUT:
Michal Vasko81c71442018-08-03 12:56:53 +02003670 size = sizeof(struct lys_node_inout) - offset;
3671 break;
3672 case LYS_NOTIF:
3673 size = sizeof(struct lys_node_notif) - offset;
3674 break;
3675 case LYS_RPC:
3676 case LYS_ACTION:
3677 size = sizeof(struct lys_node_rpc_action) - offset;
Radek Krejcif0bb3602017-01-25 17:05:08 +01003678 break;
3679 default:
Michal Vasko81c71442018-08-03 12:56:53 +02003680 assert(0);
3681 LOGINT(node1->module->ctx);
3682 return;
3683 }
3684 assert(size <= mem_size);
3685 memcpy(mem, ((uint8_t *)node1) + offset, size);
3686 memcpy(((uint8_t *)node1) + offset, ((uint8_t *)node2) + offset, size);
3687 memcpy(((uint8_t *)node2) + offset, mem, size);
3688
Michal Vasko114ffd42018-08-03 14:30:36 +02003689 /* typedefs were not copied to the backup node, so always reuse them,
3690 * in leaves/leaf-lists we must correct the type parent pointer */
Michal Vasko81c71442018-08-03 12:56:53 +02003691 switch (node1->nodetype) {
3692 case LYS_CONTAINER:
3693 ((struct lys_node_container *)node1)->tpdf_size = ((struct lys_node_container *)node2)->tpdf_size;
3694 ((struct lys_node_container *)node1)->tpdf = ((struct lys_node_container *)node2)->tpdf;
3695 ((struct lys_node_container *)node2)->tpdf_size = 0;
3696 ((struct lys_node_container *)node2)->tpdf = NULL;
3697 break;
3698 case LYS_LIST:
3699 ((struct lys_node_list *)node1)->tpdf_size = ((struct lys_node_list *)node2)->tpdf_size;
3700 ((struct lys_node_list *)node1)->tpdf = ((struct lys_node_list *)node2)->tpdf;
3701 ((struct lys_node_list *)node2)->tpdf_size = 0;
3702 ((struct lys_node_list *)node2)->tpdf = NULL;
3703 break;
3704 case LYS_RPC:
3705 case LYS_ACTION:
3706 ((struct lys_node_rpc_action *)node1)->tpdf_size = ((struct lys_node_rpc_action *)node2)->tpdf_size;
3707 ((struct lys_node_rpc_action *)node1)->tpdf = ((struct lys_node_rpc_action *)node2)->tpdf;
3708 ((struct lys_node_rpc_action *)node2)->tpdf_size = 0;
3709 ((struct lys_node_rpc_action *)node2)->tpdf = NULL;
3710 break;
3711 case LYS_NOTIF:
3712 ((struct lys_node_notif *)node1)->tpdf_size = ((struct lys_node_notif *)node2)->tpdf_size;
3713 ((struct lys_node_notif *)node1)->tpdf = ((struct lys_node_notif *)node2)->tpdf;
3714 ((struct lys_node_notif *)node2)->tpdf_size = 0;
3715 ((struct lys_node_notif *)node2)->tpdf = NULL;
3716 break;
3717 case LYS_INPUT:
3718 case LYS_OUTPUT:
3719 ((struct lys_node_inout *)node1)->tpdf_size = ((struct lys_node_inout *)node2)->tpdf_size;
3720 ((struct lys_node_inout *)node1)->tpdf = ((struct lys_node_inout *)node2)->tpdf;
3721 ((struct lys_node_inout *)node2)->tpdf_size = 0;
3722 ((struct lys_node_inout *)node2)->tpdf = NULL;
3723 break;
Michal Vasko114ffd42018-08-03 14:30:36 +02003724 case LYS_LEAF:
3725 case LYS_LEAFLIST:
3726 ((struct lys_node_leaf *)node1)->type.parent = (struct lys_tpdf *)node1;
3727 ((struct lys_node_leaf *)node2)->type.parent = (struct lys_tpdf *)node2;
Michal Vasko81c71442018-08-03 12:56:53 +02003728 default:
Radek Krejcif0bb3602017-01-25 17:05:08 +01003729 break;
3730 }
Michal Vaskoff006c12016-02-17 11:15:19 +01003731}
3732
3733void
Michal Vasko10681e82018-01-16 14:54:16 +01003734lys_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 +02003735{
3736 struct ly_ctx *ctx;
3737 int i;
3738
3739 if (!module) {
3740 return;
3741 }
3742
3743 /* remove schema from the context */
3744 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01003745 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02003746 for (i = 0; i < ctx->models.used; i++) {
3747 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01003748 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02003749 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01003750 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 +02003751 ctx->models.list[ctx->models.used] = NULL;
3752 /* we are done */
3753 break;
3754 }
3755 }
3756 }
3757
3758 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01003759 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003760
Michal Vasko10681e82018-01-16 14:54:16 +01003761 /* include */
3762 for (i = 0; i < module->inc_size; i++) {
3763 lydict_remove(ctx, module->inc[i].dsc);
3764 lydict_remove(ctx, module->inc[i].ref);
3765 lys_extension_instances_free(ctx, module->inc[i].ext, module->inc[i].ext_size, private_destructor);
3766 /* complete submodule free is done only from main module since
3767 * submodules propagate their includes to the main module */
3768 if (free_subs) {
3769 lys_submodule_free(module->inc[i].submodule, private_destructor);
3770 }
3771 }
3772 free(module->inc);
3773
Radek Krejcida04f4a2015-05-21 12:54:09 +02003774 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01003775 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003776
3777 free(module);
3778}
Radek Krejci7e97c352015-06-19 16:26:34 +02003779
Radek Krejci9de2c042016-10-19 16:53:06 +02003780static void
3781lys_features_disable_recursive(struct lys_feature *f)
3782{
3783 unsigned int i;
3784 struct lys_feature *depf;
3785
3786 /* disable the feature */
3787 f->flags &= ~LYS_FENABLED;
3788
3789 /* by disabling feature we have to disable also all features that depends on this feature */
3790 if (f->depfeatures) {
3791 for (i = 0; i < f->depfeatures->number; i++) {
3792 depf = (struct lys_feature *)f->depfeatures->set.g[i];
3793 if (depf->flags & LYS_FENABLED) {
3794 lys_features_disable_recursive(depf);
3795 }
3796 }
3797 }
3798}
3799
Radek Krejci7e97c352015-06-19 16:26:34 +02003800/*
3801 * op: 1 - enable, 0 - disable
3802 */
3803static int
Michal Vasko1e62a092015-12-01 12:27:20 +01003804lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02003805{
3806 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003807 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02003808 int progress, faili, failj, failk;
3809
3810 uint8_t fsize;
3811 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02003812
3813 if (!module || !name || !strlen(name)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01003814 LOGARG;
Radek Krejci7e97c352015-06-19 16:26:34 +02003815 return EXIT_FAILURE;
3816 }
3817
3818 if (!strcmp(name, "*")) {
3819 /* enable all */
3820 all = 1;
3821 }
3822
Radek Krejcia889c1f2016-10-19 15:50:11 +02003823 progress = failk = 1;
3824 while (progress && failk) {
3825 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
3826 if (i == -1) {
3827 fsize = module->features_size;
3828 f = module->features;
3829 } else {
3830 fsize = module->inc[i].submodule->features_size;
3831 f = module->inc[i].submodule->features;
3832 }
3833
3834 for (j = 0; j < fsize; j++) {
3835 if (all || !strcmp(f[j].name, name)) {
Michal Vasko34c3b552016-11-21 09:07:43 +01003836 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
3837 if (all) {
3838 /* skip already set features */
3839 continue;
3840 } else {
3841 /* feature already set correctly */
3842 return EXIT_SUCCESS;
3843 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003844 }
3845
3846 if (op) {
3847 /* check referenced features if they are enabled */
3848 for (k = 0; k < f[j].iffeature_size; k++) {
3849 if (!resolve_iffeature(&f[j].iffeature[k])) {
3850 if (all) {
3851 faili = i;
3852 failj = j;
3853 failk = k + 1;
3854 break;
3855 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01003856 LOGERR(module->ctx, LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
Radek Krejcia889c1f2016-10-19 15:50:11 +02003857 f[j].name, k + 1);
3858 return EXIT_FAILURE;
3859 }
3860 }
3861 }
3862
3863 if (k == f[j].iffeature_size) {
3864 /* the last check passed, do the change */
3865 f[j].flags |= LYS_FENABLED;
3866 progress++;
3867 }
3868 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02003869 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02003870 progress++;
3871 }
3872 if (!all) {
3873 /* stop in case changing a single feature */
3874 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02003875 }
3876 }
Radek Krejci7e97c352015-06-19 16:26:34 +02003877 }
3878 }
3879 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02003880 if (failk) {
3881 /* print info about the last failing feature */
Michal Vasko53b7da02018-02-13 15:28:42 +01003882 LOGERR(module->ctx, LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
Radek Krejcia889c1f2016-10-19 15:50:11 +02003883 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
3884 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02003885 }
3886
3887 if (all) {
3888 return EXIT_SUCCESS;
3889 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02003890 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02003891 return EXIT_FAILURE;
3892 }
3893}
3894
3895API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003896lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003897{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003898 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02003899}
3900
3901API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003902lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02003903{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003904 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003905}
3906
3907API int
Michal Vasko1e62a092015-12-01 12:27:20 +01003908lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003909{
3910 int i, j;
3911
3912 if (!module || !feature) {
3913 return -1;
3914 }
3915
3916 /* search for the specified feature */
3917 /* module itself */
3918 for (i = 0; i < module->features_size; i++) {
3919 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003920 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003921 return 1;
3922 } else {
3923 return 0;
3924 }
3925 }
3926 }
3927
3928 /* submodules */
3929 for (j = 0; j < module->inc_size; j++) {
3930 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
3931 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003932 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003933 return 1;
3934 } else {
3935 return 0;
3936 }
3937 }
3938 }
3939 }
3940
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003941 /* feature definition not found */
3942 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02003943}
Michal Vasko2367e7c2015-07-07 11:33:44 +02003944
Radek Krejci96a10da2015-07-30 11:00:14 +02003945API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01003946lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02003947{
Radek Krejci96a10da2015-07-30 11:00:14 +02003948 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003949 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003950 unsigned int count;
3951
3952 if (!module) {
3953 return NULL;
3954 }
3955
3956 count = module->features_size;
3957 for (i = 0; i < module->inc_size; i++) {
3958 count += module->inc[i].submodule->features_size;
3959 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003960 result = malloc((count + 1) * sizeof *result);
Michal Vasko53b7da02018-02-13 15:28:42 +01003961 LY_CHECK_ERR_RETURN(!result, LOGMEM(module->ctx), NULL);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003962
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003963 if (states) {
3964 *states = malloc((count + 1) * sizeof **states);
Michal Vasko53b7da02018-02-13 15:28:42 +01003965 LY_CHECK_ERR_RETURN(!(*states), LOGMEM(module->ctx); free(result), NULL);
Michal Vasko2367e7c2015-07-07 11:33:44 +02003966 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003967 count = 0;
3968
3969 /* module itself */
3970 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003971 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003972 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003973 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003974 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003975 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003976 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003977 }
3978 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003979 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003980 }
3981
3982 /* submodules */
3983 for (j = 0; j < module->inc_size; j++) {
3984 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003985 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003986 if (states) {
3987 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3988 (*states)[count] = 1;
3989 } else {
3990 (*states)[count] = 0;
3991 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003992 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003993 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003994 }
3995 }
3996
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003997 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003998 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003999
4000 return result;
4001}
Michal Vaskobaefb032015-09-24 14:52:10 +02004002
Radek Krejci6910a032016-04-13 10:06:21 +02004003API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01004004lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01004005{
Michal Vaskof53187d2017-01-13 13:23:14 +01004006 if (!node) {
4007 return NULL;
4008 }
4009
Radek Krejcic071c542016-01-27 14:57:51 +01004010 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
4011}
4012
Radek Krejci6910a032016-04-13 10:06:21 +02004013API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02004014lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01004015{
Michal Vaskof53187d2017-01-13 13:23:14 +01004016 if (!module) {
4017 return NULL;
4018 }
4019
Michal Vasko320e8532016-02-15 13:11:57 +01004020 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
4021}
4022
Michal Vaskobaefb032015-09-24 14:52:10 +02004023API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01004024lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02004025{
Radek Krejcif95b6292017-02-13 15:57:37 +01004026 struct lys_node *parent;
4027
4028 if (!node) {
Michal Vaskobaefb032015-09-24 14:52:10 +02004029 return NULL;
4030 }
4031
Radek Krejcif95b6292017-02-13 15:57:37 +01004032 if (node->nodetype == LYS_EXT) {
4033 if (((struct lys_ext_instance_complex*)node)->parent_type != LYEXT_PAR_NODE) {
4034 return NULL;
4035 }
4036 parent = (struct lys_node*)((struct lys_ext_instance_complex*)node)->parent;
4037 } else if (!node->parent) {
4038 return NULL;
4039 } else {
4040 parent = node->parent;
Michal Vaskobaefb032015-09-24 14:52:10 +02004041 }
4042
Radek Krejcif95b6292017-02-13 15:57:37 +01004043 if (parent->nodetype == LYS_AUGMENT) {
4044 return ((struct lys_node_augment *)parent)->target;
4045 } else {
4046 return parent;
4047 }
4048}
4049
4050struct lys_node **
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01004051lys_child(const struct lys_node *node, LYS_NODE nodetype)
Radek Krejcif95b6292017-02-13 15:57:37 +01004052{
4053 void *pp;
4054 assert(node);
4055
4056 if (node->nodetype == LYS_EXT) {
4057 pp = lys_ext_complex_get_substmt(lys_snode2stmt(nodetype), (struct lys_ext_instance_complex*)node, NULL);
4058 if (!pp) {
4059 return NULL;
4060 }
4061 return (struct lys_node **)pp;
Michal Vasko54d4c202017-08-09 14:09:18 +02004062 } else if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Radek Krejcif7fe2cb2017-08-09 10:27:12 +02004063 return NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +01004064 } else {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01004065 return (struct lys_node **)&node->child;
Radek Krejcif95b6292017-02-13 15:57:37 +01004066 }
Michal Vaskobaefb032015-09-24 14:52:10 +02004067}
Michal Vasko1b229152016-01-13 11:28:38 +01004068
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004069API void *
Michal Vasko1b229152016-01-13 11:28:38 +01004070lys_set_private(const struct lys_node *node, void *priv)
4071{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004072 void *prev;
4073
Michal Vasko1b229152016-01-13 11:28:38 +01004074 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004075 LOGARG;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004076 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01004077 }
4078
Mislav Novakovicb5529e52016-02-29 11:42:43 +01004079 prev = node->priv;
4080 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004081
4082 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01004083}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004084
Michal Vasko01c6fd22016-05-20 11:43:05 +02004085int
4086lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
4087{
Michal Vasko53b7da02018-02-13 15:28:42 +01004088 struct lys_node_leaf *iter;
4089 struct ly_ctx *ctx = leafref_target->module->ctx;
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004090
Michal Vasko48a573d2016-07-01 11:46:02 +02004091 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004092 LOGINT(ctx);
Michal Vasko01c6fd22016-05-20 11:43:05 +02004093 return -1;
4094 }
4095
Pavol Vican93175152016-08-30 15:34:44 +02004096 /* check for config flag */
Radek Krejcic688ca02017-03-20 12:54:39 +01004097 if (((struct lys_node_leaf*)leafref)->type.info.lref.req != -1 &&
4098 (leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004099 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, leafref,
Radek Krejcid831dd42017-03-16 12:59:30 +01004100 "The leafref %s is config but refers to a non-config %s.",
Pavol Vican93175152016-08-30 15:34:44 +02004101 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
4102 return -1;
4103 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004104 /* check for cycles */
Michal Vasko53b7da02018-02-13 15:28:42 +01004105 for (iter = leafref_target; iter && iter->type.base == LY_TYPE_LEAFREF; iter = iter->type.info.lref.target) {
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004106 if ((void *)iter == (void *)leafref) {
4107 /* cycle detected */
Michal Vasko53b7da02018-02-13 15:28:42 +01004108 LOGVAL(ctx, LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004109 return -1;
4110 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02004111 }
4112
4113 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02004114 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02004115 if (!leafref_target->backlinks) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004116 leafref_target->backlinks = (void *)ly_set_new();
Radek Krejci85a54be2016-10-20 12:39:56 +02004117 if (!leafref_target->backlinks) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004118 LOGMEM(ctx);
Michal Vasko01c6fd22016-05-20 11:43:05 +02004119 return -1;
4120 }
4121 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01004122 ly_set_add(leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02004123
4124 return 0;
4125}
4126
Michal Vasko8548e082016-07-22 12:00:18 +02004127/* not needed currently */
4128#if 0
4129
Michal Vasko5b3492c2016-07-20 09:37:40 +02004130static const char *
4131lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
4132{
4133 struct lys_module *prev_mod;
4134 uint32_t str_len, mod_len, buf_idx;
4135
Radek Krejcibf2abff2016-08-23 15:51:52 +02004136 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02004137 LOGINT;
4138 return NULL;
4139 }
4140
4141 buf_idx = buf_len - 1;
4142 buf[buf_idx] = '\0';
4143
4144 while (node) {
4145 if (lys_parent(node)) {
4146 prev_mod = lys_node_module(lys_parent(node));
4147 } else {
4148 prev_mod = NULL;
4149 }
4150
Radek Krejcibf2abff2016-08-23 15:51:52 +02004151 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02004152 str_len = strlen(node->name);
4153
4154 if (prev_mod != node->module) {
4155 mod_len = strlen(node->module->name);
4156 } else {
4157 mod_len = 0;
4158 }
4159
4160 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
4161 LOGINT;
4162 return NULL;
4163 }
4164
4165 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
4166
4167 buf[buf_idx] = '/';
4168 if (mod_len) {
4169 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
4170 buf[buf_idx + 1 + mod_len] = ':';
4171 }
4172 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
4173 }
4174
4175 node = lys_parent(node);
4176 }
4177
4178 return buf + buf_idx;
4179}
4180
Michal Vasko8548e082016-07-22 12:00:18 +02004181#endif
4182
4183API struct ly_set *
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004184lys_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 +02004185{
Michal Vasko508a50d2016-09-07 14:50:33 +02004186 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02004187 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004188 uint32_t i;
4189
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004190 if (!ctx_node || !expr) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004191 LOGARG;
Michal Vasko8548e082016-07-22 12:00:18 +02004192 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004193 }
4194
Michal Vaskob94a5e42016-09-08 14:01:56 +02004195 /* adjust the root */
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004196 if ((ctx_node_type == LYXP_NODE_ROOT) || (ctx_node_type == LYXP_NODE_ROOT_CONFIG)) {
Michal Vaskob94a5e42016-09-08 14:01:56 +02004197 do {
Michal Vaskocb45f472018-02-12 10:47:42 +01004198 ctx_node = lys_getnext(NULL, NULL, lys_node_module(ctx_node), LYS_GETNEXT_NOSTATECHECK);
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004199 } while ((ctx_node_type == LYXP_NODE_ROOT_CONFIG) && (ctx_node->flags & LYS_CONFIG_R));
Michal Vaskob94a5e42016-09-08 14:01:56 +02004200 }
4201
Michal Vasko508a50d2016-09-07 14:50:33 +02004202 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02004203
4204 if (options & LYXP_MUST) {
4205 options &= ~LYXP_MUST;
4206 options |= LYXP_SNODE_MUST;
4207 } else if (options & LYXP_WHEN) {
4208 options &= ~LYXP_WHEN;
4209 options |= LYXP_SNODE_WHEN;
4210 } else {
4211 options |= LYXP_SNODE;
4212 }
4213
Michal Vasko9ff79aa2017-07-03 14:10:32 +02004214 if (lyxp_atomize(expr, ctx_node, ctx_node_type, &set, options, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004215 free(set.val.snodes);
Michal Vasko53b7da02018-02-13 15:28:42 +01004216 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 +02004217 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004218 }
4219
Michal Vasko8548e082016-07-22 12:00:18 +02004220 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02004221
Michal Vasko508a50d2016-09-07 14:50:33 +02004222 for (i = 0; i < set.used; ++i) {
4223 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02004224 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02004225 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02004226 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02004227 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02004228 return NULL;
4229 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02004230 break;
4231 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02004232 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02004233 break;
4234 }
4235 }
4236
Michal Vasko508a50d2016-09-07 14:50:33 +02004237 free(set.val.snodes);
4238 return ret_set;
4239}
4240
4241API struct ly_set *
4242lys_node_xpath_atomize(const struct lys_node *node, int options)
4243{
4244 const struct lys_node *next, *elem, *parent, *tmp;
4245 struct lyxp_set set;
4246 struct ly_set *ret_set;
4247 uint16_t i;
4248
4249 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004250 LOGARG;
Michal Vasko508a50d2016-09-07 14:50:33 +02004251 return NULL;
4252 }
4253
4254 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
4255 if (!parent) {
4256 /* not in input, output, or notification */
4257 return NULL;
4258 }
4259
4260 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02004261 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004262 return NULL;
4263 }
4264
4265 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoc04173b2018-03-09 10:43:22 +01004266 if ((options & LYXP_NO_LOCAL) && !(elem->flags & (LYS_XPCONF_DEP | LYS_XPSTATE_DEP))) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004267 /* elem has no dependencies from other subtrees and local nodes get discarded */
4268 goto next_iter;
4269 }
4270
Michal Vaskof96dfb62017-08-17 12:23:49 +02004271 if (lyxp_node_atomize(elem, &set, 0)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004272 ly_set_free(ret_set);
4273 free(set.val.snodes);
4274 return NULL;
4275 }
4276
4277 for (i = 0; i < set.used; ++i) {
4278 switch (set.val.snodes[i].type) {
4279 case LYXP_NODE_ELEM:
4280 if (options & LYXP_NO_LOCAL) {
4281 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
4282 if (tmp) {
4283 /* in local subtree, discard */
4284 break;
4285 }
4286 }
4287 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
4288 ly_set_free(ret_set);
4289 free(set.val.snodes);
4290 return NULL;
4291 }
4292 break;
4293 default:
4294 /* ignore roots, text and attr should not ever appear */
4295 break;
4296 }
4297 }
4298
4299 free(set.val.snodes);
4300 if (!(options & LYXP_RECURSIVE)) {
4301 break;
4302 }
4303next_iter:
4304 LY_TREE_DFS_END(node, next, elem);
4305 }
4306
Michal Vasko8548e082016-07-22 12:00:18 +02004307 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02004308}
4309
Michal Vasko44ab1462017-05-18 13:18:36 +02004310/* logs */
4311int
4312apply_aug(struct lys_node_augment *augment, struct unres_schema *unres)
Radek Krejci0ec51da2016-12-14 16:42:03 +01004313{
Michal Vasko44ab1462017-05-18 13:18:36 +02004314 struct lys_node *child, *parent;
4315 int clear_config;
4316 unsigned int u;
Michal Vaskod02e30e2018-01-22 13:35:48 +01004317 uint8_t *v;
Michal Vasko44ab1462017-05-18 13:18:36 +02004318 struct lys_ext_instance *ext;
Adam Weast4ca7edd2018-06-14 08:59:22 -05004319
Radek Krejci0ec51da2016-12-14 16:42:03 +01004320 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
4321
Radek Krejcic9d78692017-08-24 17:17:18 +02004322 if (!augment->child) {
4323 /* nothing to apply */
4324 goto success;
4325 }
4326
Radek Krejci0ec51da2016-12-14 16:42:03 +01004327 /* reconnect augmenting data into the target - add them to the target child list */
4328 if (augment->target->child) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004329 child = augment->target->child->prev;
4330 child->next = augment->child;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004331 augment->target->child->prev = augment->child->prev;
Michal Vasko44ab1462017-05-18 13:18:36 +02004332 augment->child->prev = child;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004333 } else {
4334 augment->target->child = augment->child;
4335 }
4336
Michal Vasko44ab1462017-05-18 13:18:36 +02004337 /* inherit config information from actual parent */
4338 for (parent = augment->target; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); parent = lys_parent(parent));
4339 clear_config = (parent) ? 1 : 0;
4340 LY_TREE_FOR(augment->child, child) {
4341 if (inherit_config_flag(child, augment->target->flags & LYS_CONFIG_MASK, clear_config)) {
4342 return -1;
4343 }
4344 }
4345
4346 /* inherit extensions if any */
4347 for (u = 0; u < augment->target->ext_size; u++) {
4348 ext = augment->target->ext[u]; /* shortcut */
4349 if (ext && ext->def->plugin && (ext->def->plugin->flags & LYEXT_OPT_INHERIT)) {
Michal Vaskod02e30e2018-01-22 13:35:48 +01004350 v = malloc(sizeof *v);
Michal Vasko53b7da02018-02-13 15:28:42 +01004351 LY_CHECK_ERR_RETURN(!v, LOGMEM(augment->module->ctx), -1);
Michal Vaskod02e30e2018-01-22 13:35:48 +01004352 *v = u;
4353 if (unres_schema_add_node(lys_main_module(augment->module), unres, &augment->target->ext,
4354 UNRES_EXT_FINALIZE, (struct lys_node *)v) == -1) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004355 /* something really bad happend since the extension finalization is not actually
4356 * being resolved while adding into unres, so something more serious with the unres
4357 * list itself must happened */
4358 return -1;
4359 }
4360 }
4361 }
4362
Radek Krejcic9d78692017-08-24 17:17:18 +02004363success:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004364 /* remove the flag about not applicability */
4365 augment->flags &= ~LYS_NOTAPPLIED;
Michal Vasko44ab1462017-05-18 13:18:36 +02004366 return EXIT_SUCCESS;
Radek Krejci0ec51da2016-12-14 16:42:03 +01004367}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004368
Radek Krejcib2541a32016-12-12 16:45:57 +01004369static void
4370remove_aug(struct lys_node_augment *augment)
4371{
4372 struct lys_node *last, *elem;
4373
Michal Vaskof1aa47d2017-09-21 12:09:29 +02004374 if ((augment->flags & LYS_NOTAPPLIED) || !augment->target) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004375 /* skip already not applied augment */
Radek Krejcib2541a32016-12-12 16:45:57 +01004376 return;
4377 }
4378
4379 elem = augment->child;
4380 if (elem) {
4381 LY_TREE_FOR(elem, last) {
4382 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
4383 break;
4384 }
4385 }
4386 /* elem is first augment child, last is the last child */
4387
4388 /* parent child ptr */
4389 if (augment->target->child == elem) {
4390 augment->target->child = last->next;
4391 }
4392
4393 /* parent child next ptr */
4394 if (elem->prev->next) {
4395 elem->prev->next = last->next;
4396 }
4397
4398 /* parent child prev ptr */
4399 if (last->next) {
4400 last->next->prev = elem->prev;
4401 } else if (augment->target->child) {
4402 augment->target->child->prev = elem->prev;
4403 }
4404
4405 /* update augment children themselves */
4406 elem->prev = last;
4407 last->next = NULL;
4408 }
4409
Radek Krejci0ec51da2016-12-14 16:42:03 +01004410 /* augment->target still keeps the resolved target, but for lys_augment_free()
4411 * we have to keep information that this augment is not applied to free its data */
4412 augment->flags |= LYS_NOTAPPLIED;
Radek Krejcib2541a32016-12-12 16:45:57 +01004413}
4414
Radek Krejci30bfcd22017-01-27 16:54:48 +01004415/*
4416 * @param[in] module - the module where the deviation is defined
4417 */
4418static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004419lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004420{
Radek Krejcic9d78692017-08-24 17:17:18 +02004421 int ret, reapply = 0;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004422 char *parent_path;
4423 struct lys_node *target = NULL, *parent;
Michal Vasko5df038e2018-08-02 09:41:26 +02004424 struct lys_node_inout *inout;
Michal Vasko50576712017-07-28 12:28:33 +02004425 struct ly_set *set;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004426
4427 if (!dev->deviate) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004428 return;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004429 }
4430
4431 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
4432 if (dev->orig_node) {
4433 /* removing not-supported deviation ... */
4434 if (strrchr(dev->target_name, '/') != dev->target_name) {
4435 /* ... from a parent */
4436
4437 /* reconnect to its previous position */
4438 parent = dev->orig_node->parent;
Michal Vaskoa1074a52018-01-03 12:18:53 +01004439 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejcic9d78692017-08-24 17:17:18 +02004440 dev->orig_node->parent = NULL;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004441 /* the original node was actually from augment, we have to get know if the augment is
4442 * applied (its module is enabled and implemented). If yes, the node will be connected
4443 * to the augment and the linkage with the target will be fixed if needed, otherwise
4444 * it will be connected only to the augment */
Radek Krejcic9d78692017-08-24 17:17:18 +02004445 if (!(parent->flags & LYS_NOTAPPLIED)) {
4446 /* start with removing augment if applied before adding nodes, we have to make sure
4447 * that everything will be connect correctly */
4448 remove_aug((struct lys_node_augment *)parent);
4449 reapply = 1;
4450 }
4451 /* connect the deviated node back into the augment */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004452 lys_node_addchild(parent, NULL, dev->orig_node, 0);
Radek Krejcic9d78692017-08-24 17:17:18 +02004453 if (reapply) {
Radek Krejci30bfcd22017-01-27 16:54:48 +01004454 /* 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 +02004455 assert(lys_node_module(parent)->implemented);
Michal Vasko823fbe02017-12-14 11:01:40 +01004456 parent->flags |= LYS_NOTAPPLIED; /* allow apply_aug() */
4457 apply_aug((struct lys_node_augment *)parent, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004458 }
Michal Vaskoa1074a52018-01-03 12:18:53 +01004459 } else if (parent && (parent->nodetype == LYS_USES)) {
4460 /* uses child */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004461 lys_node_addchild(parent, NULL, dev->orig_node, 0);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004462 } else {
4463 /* non-augment, non-toplevel */
4464 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
Michal Vasko50576712017-07-28 12:28:33 +02004465 ret = resolve_schema_nodeid(parent_path, NULL, module, &set, 0, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004466 free(parent_path);
Michal Vasko50576712017-07-28 12:28:33 +02004467 if (ret == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004468 LOGINT(module->ctx);
Michal Vasko50576712017-07-28 12:28:33 +02004469 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004470 return;
4471 }
Michal Vasko50576712017-07-28 12:28:33 +02004472 target = set->set.s[0];
4473 ly_set_free(set);
4474
Michal Vasko8d30dd82018-09-10 10:06:12 +02004475 lys_node_addchild(target, NULL, dev->orig_node, 0);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004476 }
4477 } else {
4478 /* ... from top-level data */
Michal Vasko8d30dd82018-09-10 10:06:12 +02004479 lys_node_addchild(NULL, (struct lys_module *)dev->orig_node->module, dev->orig_node, 0);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004480 }
4481
4482 dev->orig_node = NULL;
4483 } else {
4484 /* adding not-supported deviation */
Michal Vasko50576712017-07-28 12:28:33 +02004485 ret = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4486 if (ret == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004487 LOGINT(module->ctx);
Michal Vasko50576712017-07-28 12:28:33 +02004488 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004489 return;
4490 }
Michal Vasko50576712017-07-28 12:28:33 +02004491 target = set->set.s[0];
4492 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004493
4494 /* unlink and store the original node */
4495 parent = target->parent;
4496 lys_node_unlink(target);
Michal Vasko5df038e2018-08-02 09:41:26 +02004497 if (parent) {
4498 if (parent->nodetype & (LYS_AUGMENT | LYS_USES)) {
4499 /* hack for augment, because when the original will be sometime reconnected back, we actually need
4500 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
4501 * path), so we need to remember the augment as an addition */
4502 /* we also need to remember the parent uses so that we connect it back to it when switching deviation state */
4503 target->parent = parent;
4504 } else if (parent->nodetype & (LYS_RPC | LYS_ACTION)) {
4505 /* re-create implicit node */
4506 inout = calloc(1, sizeof *inout);
4507 LY_CHECK_ERR_RETURN(!inout, LOGMEM(module->ctx), );
4508
4509 inout->nodetype = target->nodetype;
4510 inout->name = lydict_insert(module->ctx, (inout->nodetype == LYS_INPUT) ? "input" : "output", 0);
4511 inout->module = target->module;
4512 inout->flags = LYS_IMPLICIT;
4513
4514 /* insert it manually */
4515 assert(parent->child && !parent->child->next
4516 && (parent->child->nodetype == (inout->nodetype == LYS_INPUT ? LYS_OUTPUT : LYS_INPUT)));
4517 parent->child->next = (struct lys_node *)inout;
4518 inout->prev = parent->child;
4519 parent->child->prev = (struct lys_node *)inout;
4520 inout->parent = parent;
4521 }
Radek Krejci30bfcd22017-01-27 16:54:48 +01004522 }
4523 dev->orig_node = target;
4524 }
4525 } else {
Michal Vasko50576712017-07-28 12:28:33 +02004526 ret = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4527 if (ret == -1) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004528 LOGINT(module->ctx);
Michal Vasko50576712017-07-28 12:28:33 +02004529 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004530 return;
4531 }
Michal Vasko50576712017-07-28 12:28:33 +02004532 target = set->set.s[0];
4533 ly_set_free(set);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004534
Michal Vasko81c71442018-08-03 12:56:53 +02004535 /* contents are switched */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004536 lys_node_switch(target, dev->orig_node);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004537 }
4538}
4539
4540/* temporarily removes or applies deviations, updates module deviation flag accordingly */
4541void
Michal Vasko5a65f212018-03-19 15:08:08 +01004542lys_enable_deviations(struct lys_module *module)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004543{
4544 uint32_t i = 0, j;
4545 const struct lys_module *mod;
4546 const char *ptr;
Michal Vasko44ab1462017-05-18 13:18:36 +02004547 struct unres_schema *unres;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004548
4549 if (module->deviated) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004550 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01004551 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
Michal Vasko44ab1462017-05-18 13:18:36 +02004552
Radek Krejci30bfcd22017-01-27 16:54:48 +01004553 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
4554 if (mod == module) {
4555 continue;
4556 }
4557
4558 for (j = 0; j < mod->deviation_size; ++j) {
4559 ptr = strstr(mod->deviation[j].target_name, module->name);
4560 if (ptr && ptr[strlen(module->name)] == ':') {
Michal Vasko44ab1462017-05-18 13:18:36 +02004561 lys_switch_deviation(&mod->deviation[j], mod, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004562 }
4563 }
4564 }
4565
Michal Vasko5a65f212018-03-19 15:08:08 +01004566 assert(module->deviated == 2);
4567 module->deviated = 1;
4568
4569 for (j = 0; j < module->inc_size; j++) {
4570 if (module->inc[j].submodule->deviated) {
4571 module->inc[j].submodule->deviated = module->deviated;
4572 }
Radek Krejci30bfcd22017-01-27 16:54:48 +01004573 }
Michal Vasko5a65f212018-03-19 15:08:08 +01004574
4575 if (unres->count) {
4576 resolve_unres_schema(module, unres);
4577 }
4578 unres_schema_free(module, &unres, 1);
4579 }
4580}
4581
4582void
4583lys_disable_deviations(struct lys_module *module)
4584{
4585 uint32_t i, j;
4586 const struct lys_module *mod;
4587 const char *ptr;
4588 struct unres_schema *unres;
4589
4590 if (module->deviated) {
4591 unres = calloc(1, sizeof *unres);
4592 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
4593
4594 i = module->ctx->models.used;
4595 while (i--) {
4596 mod = module->ctx->models.list[i];
4597
4598 if (mod == module) {
4599 continue;
4600 }
4601
4602 j = mod->deviation_size;
4603 while (j--) {
4604 ptr = strstr(mod->deviation[j].target_name, module->name);
4605 if (ptr && ptr[strlen(module->name)] == ':') {
4606 lys_switch_deviation(&mod->deviation[j], mod, unres);
4607 }
4608 }
4609 }
4610
4611 assert(module->deviated == 1);
4612 module->deviated = 2;
4613
Radek Krejci29eac3d2017-06-01 16:50:02 +02004614 for (j = 0; j < module->inc_size; j++) {
4615 if (module->inc[j].submodule->deviated) {
4616 module->inc[j].submodule->deviated = module->deviated;
4617 }
4618 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004619
4620 if (unres->count) {
4621 resolve_unres_schema(module, unres);
4622 }
4623 unres_schema_free(module, &unres, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004624 }
4625}
4626
4627static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004628apply_dev(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004629{
Michal Vasko44ab1462017-05-18 13:18:36 +02004630 lys_switch_deviation(dev, module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004631
4632 assert(dev->orig_node);
Radek Krejci29eac3d2017-06-01 16:50:02 +02004633 lys_node_module(dev->orig_node)->deviated = 1; /* main module */
4634 dev->orig_node->module->deviated = 1; /* possible submodule */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004635}
4636
4637static void
Michal Vasko44ab1462017-05-18 13:18:36 +02004638remove_dev(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
Radek Krejci30bfcd22017-01-27 16:54:48 +01004639{
4640 uint32_t idx = 0, j;
4641 const struct lys_module *mod;
Radek Krejci29eac3d2017-06-01 16:50:02 +02004642 struct lys_module *target_mod, *target_submod;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004643 const char *ptr;
4644
4645 if (dev->orig_node) {
4646 target_mod = lys_node_module(dev->orig_node);
Radek Krejci29eac3d2017-06-01 16:50:02 +02004647 target_submod = dev->orig_node->module;
Radek Krejci30bfcd22017-01-27 16:54:48 +01004648 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +01004649 LOGINT(module->ctx);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004650 return;
4651 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004652 lys_switch_deviation(dev, module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004653
4654 /* clear the deviation flag if possible */
4655 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
4656 if ((mod == module) || (mod == target_mod)) {
4657 continue;
4658 }
4659
4660 for (j = 0; j < mod->deviation_size; ++j) {
4661 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
4662 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
4663 /* some other module deviation targets the inspected module, flag remains */
4664 break;
4665 }
4666 }
4667
4668 if (j < mod->deviation_size) {
4669 break;
4670 }
4671 }
4672
4673 if (!mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02004674 target_mod->deviated = 0; /* main module */
4675 target_submod->deviated = 0; /* possible submodule */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004676 }
4677}
4678
4679void
4680lys_sub_module_apply_devs_augs(struct lys_module *module)
4681{
4682 uint8_t u, v;
Michal Vasko44ab1462017-05-18 13:18:36 +02004683 struct unres_schema *unres;
4684
Michal Vasko74083ec2018-06-15 10:00:12 +02004685 assert(module->implemented);
4686
Michal Vasko44ab1462017-05-18 13:18:36 +02004687 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01004688 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
Radek Krejci30bfcd22017-01-27 16:54:48 +01004689
Michal Vasko1e82a3b2018-07-03 12:16:58 +02004690 /* apply deviations */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004691 for (u = 0; u < module->deviation_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004692 apply_dev(&module->deviation[u], module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004693 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02004694 /* apply augments */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004695 for (u = 0; u < module->augment_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004696 apply_aug(&module->augment[u], unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004697 }
4698
Michal Vasko1e82a3b2018-07-03 12:16:58 +02004699 /* apply deviations and augments defined in submodules */
Radek Krejci30bfcd22017-01-27 16:54:48 +01004700 for (v = 0; v < module->inc_size; ++v) {
4701 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004702 apply_dev(&module->inc[v].submodule->deviation[u], module, unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004703 }
4704
4705 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004706 apply_aug(&module->inc[v].submodule->augment[u], unres);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004707 }
4708 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004709
4710 if (unres->count) {
4711 resolve_unres_schema(module, unres);
4712 }
4713 /* nothing else left to do even if something is not resolved */
4714 unres_schema_free(module, &unres, 1);
Radek Krejci30bfcd22017-01-27 16:54:48 +01004715}
4716
Radek Krejcib2541a32016-12-12 16:45:57 +01004717void
4718lys_sub_module_remove_devs_augs(struct lys_module *module)
4719{
Andrew Langefeldf9763242018-09-16 22:23:50 -05004720 uint8_t u, v, w;
Michal Vasko44ab1462017-05-18 13:18:36 +02004721 struct unres_schema *unres;
4722
4723 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01004724 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
Radek Krejcib2541a32016-12-12 16:45:57 +01004725
4726 /* remove applied deviations */
4727 for (u = 0; u < module->deviation_size; ++u) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02004728 /* the deviation could not be applied because it failed to be applied in the first place*/
Michal Vasko7427b262018-05-14 15:23:55 +02004729 if (module->deviation[u].orig_node) {
4730 remove_dev(&module->deviation[u], module, unres);
4731 }
Andrew Langefeldf9763242018-09-16 22:23:50 -05004732
4733 /* Free the deviation's must array(s). These are shallow copies of the arrays
4734 on the target node(s), so a deep free is not needed. */
4735 for (v = 0; v < module->deviation[u].deviate_size; ++v) {
4736 if (module->deviation[u].deviate[v].mod == LY_DEVIATE_ADD) {
4737 free(module->deviation[u].deviate[v].must);
4738 }
4739 }
Radek Krejcib2541a32016-12-12 16:45:57 +01004740 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004741 /* remove applied augments */
Radek Krejcib2541a32016-12-12 16:45:57 +01004742 for (u = 0; u < module->augment_size; ++u) {
4743 remove_aug(&module->augment[u]);
4744 }
4745
4746 /* remove deviation and augments defined in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01004747 for (v = 0; v < module->inc_size && module->inc[v].submodule; ++v) {
Radek Krejcib2541a32016-12-12 16:45:57 +01004748 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
Michal Vasko7427b262018-05-14 15:23:55 +02004749 if (module->inc[v].submodule->deviation[u].orig_node) {
4750 remove_dev(&module->inc[v].submodule->deviation[u], module, unres);
4751 }
Andrew Langefeldf9763242018-09-16 22:23:50 -05004752
4753 /* Free the deviation's must array(s). These are shallow copies of the arrays
4754 on the target node(s), so a deep free is not needed. */
4755 for (w = 0; w < module->inc[v].submodule->deviation[u].deviate_size; ++w) {
4756 if (module->inc[v].submodule->deviation[u].deviate[w].mod == LY_DEVIATE_ADD) {
4757 free(module->inc[v].submodule->deviation[u].deviate[w].must);
4758 }
4759 }
Radek Krejcidbc15262016-06-16 14:58:29 +02004760 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004761
Radek Krejcib2541a32016-12-12 16:45:57 +01004762 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4763 remove_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004764 }
4765 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004766
4767 if (unres->count) {
4768 resolve_unres_schema(module, unres);
4769 }
4770 /* nothing else left to do even if something is not resolved */
4771 unres_schema_free(module, &unres, 1);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004772}
4773
Michal Vasko0f437062018-06-08 15:52:39 +02004774int
4775lys_make_implemented_r(struct lys_module *module, struct unres_schema *unres)
Radek Krejci27fe55e2016-09-13 17:13:35 +02004776{
Michal Vasko0f437062018-06-08 15:52:39 +02004777 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004778 struct lys_node *root, *next, *node;
Michal Vasko74083ec2018-06-15 10:00:12 +02004779 struct lys_module *target_module;
Michal Vasko0f437062018-06-08 15:52:39 +02004780 uint16_t i, j, k;
4781
4782 assert(module->implemented);
4783 ctx = module->ctx;
4784
4785 for (i = 0; i < ctx->models.used; ++i) {
4786 if (module == ctx->models.list[i]) {
4787 continue;
4788 }
4789
4790 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
4791 LOGERR(ctx, LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
4792 return EXIT_FAILURE;
4793 }
4794 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004795
4796 for (i = 0; i < module->augment_size; i++) {
Michal Vasko74083ec2018-06-15 10:00:12 +02004797
4798 /* make target module implemented if was not */
4799 assert(module->augment[i].target);
4800 target_module = lys_node_module(module->augment[i].target);
4801 if (!target_module->implemented) {
4802 target_module->implemented = 1;
4803 if (unres_schema_add_node(target_module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
4804 return -1;
4805 }
4806 }
4807
Radek Krejci27fe55e2016-09-13 17:13:35 +02004808 /* apply augment */
Adam Weast368fd582018-06-14 13:32:35 -05004809 if ((module->augment[i].flags & LYS_NOTAPPLIED) && apply_aug(&module->augment[i], unres)) {
Michal Vasko44ab1462017-05-18 13:18:36 +02004810 return EXIT_FAILURE;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004811 }
4812 }
Adam Weast4ca7edd2018-06-14 08:59:22 -05004813
Radek Krejci9e6af732017-04-27 14:40:25 +02004814 /* identities */
4815 for (i = 0; i < module->ident_size; i++) {
4816 for (j = 0; j < module->ident[i].base_size; j++) {
4817 resolve_identity_backlink_update(&module->ident[i], module->ident[i].base[j]);
4818 }
4819 }
4820
Michal Vasko0f437062018-06-08 15:52:39 +02004821 /* process augments in submodules */
4822 for (i = 0; i < module->inc_size && module->inc[i].submodule; ++i) {
4823 module->inc[i].submodule->implemented = 1;
4824
4825 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
Michal Vasko74083ec2018-06-15 10:00:12 +02004826
4827 /* make target module implemented if it was not */
Michal Vaskoda267cb2018-06-15 11:18:00 +02004828 assert(module->inc[i].submodule->augment[j].target);
Michal Vasko74083ec2018-06-15 10:00:12 +02004829 target_module = lys_node_module(module->inc[i].submodule->augment[j].target);
4830 if (!target_module->implemented) {
4831 target_module->implemented = 1;
4832 if (unres_schema_add_node(target_module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
4833 return -1;
4834 }
4835 }
4836
Michal Vasko0f437062018-06-08 15:52:39 +02004837 /* apply augment */
Adam Weast368fd582018-06-14 13:32:35 -05004838 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 +02004839 return EXIT_FAILURE;
4840 }
4841 }
4842
4843 /* identities */
4844 for (j = 0; j < module->inc[i].submodule->ident_size; j++) {
4845 for (k = 0; k < module->inc[i].submodule->ident[j].base_size; k++) {
4846 resolve_identity_backlink_update(&module->inc[i].submodule->ident[j],
4847 module->inc[i].submodule->ident[j].base[k]);
4848 }
4849 }
4850 }
4851
Radek Krejci27fe55e2016-09-13 17:13:35 +02004852 LY_TREE_FOR(module->data, root) {
4853 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
4854 LY_TREE_DFS_BEGIN(root, next, node) {
4855 if (node->nodetype == LYS_GROUPING) {
4856 goto nextsibling;
4857 }
4858 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
4859 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
4860 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
4861 UNRES_TYPE_LEAFREF, node) == -1) {
4862 return EXIT_FAILURE;
4863 }
4864 }
4865 }
4866
4867 /* modified LY_TREE_DFS_END */
4868 next = node->child;
4869 /* child exception for leafs, leaflists and anyxml without children */
4870 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4871 next = NULL;
4872 }
4873 if (!next) {
4874nextsibling:
4875 /* no children */
4876 if (node == root) {
4877 /* we are done, root has no children */
4878 break;
4879 }
4880 /* try siblings */
4881 next = node->next;
4882 }
4883 while (!next) {
4884 /* parent is already processed, go to its sibling */
4885 node = lys_parent(node);
4886 /* no siblings, go back through parents */
4887 if (lys_parent(node) == lys_parent(root)) {
4888 /* we are done, no next element to process */
4889 break;
4890 }
4891 next = node->next;
4892 }
4893 }
4894 }
4895
4896 return EXIT_SUCCESS;
4897}
4898
4899API int
4900lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02004901{
Radek Krejci27fe55e2016-09-13 17:13:35 +02004902 struct unres_schema *unres;
Michal Vasko0f437062018-06-08 15:52:39 +02004903 int disabled = 0;
Michal Vasko26055752016-05-03 11:36:31 +02004904
Radek Krejci27fe55e2016-09-13 17:13:35 +02004905 if (!module) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004906 LOGARG;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004907 return EXIT_FAILURE;
4908 }
4909
4910 module = lys_main_module(module);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004911
4912 if (module->disabled) {
4913 disabled = 1;
4914 lys_set_enabled(module);
4915 }
4916
Michal Vasko26055752016-05-03 11:36:31 +02004917 if (module->implemented) {
4918 return EXIT_SUCCESS;
4919 }
4920
Radek Krejci27fe55e2016-09-13 17:13:35 +02004921 unres = calloc(1, sizeof *unres);
4922 if (!unres) {
Michal Vasko0f437062018-06-08 15:52:39 +02004923 LOGMEM(module->ctx);
Radek Krejci0ec51da2016-12-14 16:42:03 +01004924 if (disabled) {
4925 /* set it back disabled */
4926 lys_set_disabled(module);
4927 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02004928 return EXIT_FAILURE;
4929 }
4930 /* recursively make the module implemented */
4931 ((struct lys_module *)module)->implemented = 1;
Michal Vasko0f437062018-06-08 15:52:39 +02004932 if (lys_make_implemented_r((struct lys_module *)module, unres)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02004933 goto error;
4934 }
Radek Krejci9e6af732017-04-27 14:40:25 +02004935
Radek Krejcidf46e222016-11-08 11:57:37 +01004936 /* try again resolve augments in other modules possibly augmenting this one,
4937 * since we have just enabled it
4938 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02004939 /* resolve rest of unres items */
4940 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
4941 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004942 }
Michal Vasko44ab1462017-05-18 13:18:36 +02004943 unres_schema_free(NULL, &unres, 0);
Michal Vasko26055752016-05-03 11:36:31 +02004944
Michal Vaskobe136f62017-09-21 12:08:39 +02004945 LOGVRB("Module \"%s%s%s\" now implemented.", module->name, (module->rev_size ? "@" : ""),
4946 (module->rev_size ? module->rev[0].date : ""));
Michal Vasko26055752016-05-03 11:36:31 +02004947 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02004948
4949error:
Radek Krejci0ec51da2016-12-14 16:42:03 +01004950 if (disabled) {
4951 /* set it back disabled */
4952 lys_set_disabled(module);
4953 }
4954
Radek Krejci27fe55e2016-09-13 17:13:35 +02004955 ((struct lys_module *)module)->implemented = 0;
Michal Vasko44ab1462017-05-18 13:18:36 +02004956 unres_schema_free((struct lys_module *)module, &unres, 1);
Radek Krejci27fe55e2016-09-13 17:13:35 +02004957 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02004958}
4959
4960void
4961lys_submodule_module_data_free(struct lys_submodule *submodule)
4962{
4963 struct lys_node *next, *elem;
4964
4965 /* remove parsed data */
4966 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
4967 if (elem->module == (struct lys_module *)submodule) {
4968 lys_node_free(elem, NULL, 0);
4969 }
4970 }
4971}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02004972
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004973API char *
Michal Vasko395b0a02018-01-22 09:36:20 +01004974lys_path(const struct lys_node *node, int options)
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004975{
Michal Vasko53b7da02018-02-13 15:28:42 +01004976 char *buf = NULL;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004977
4978 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01004979 LOGARG;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004980 return NULL;
4981 }
4982
Michal Vasko185b5272018-09-13 14:26:12 +02004983 if (ly_vlog_build_path(LY_VLOG_LYS, node, &buf, !options, 0)) {
Michal Vasko59631dd2017-10-02 11:56:11 +02004984 return NULL;
4985 }
4986
Michal Vasko53b7da02018-02-13 15:28:42 +01004987 return buf;
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02004988}
Radek Krejci9ad23f42016-10-31 15:46:52 +01004989
Michal Vasko50576712017-07-28 12:28:33 +02004990API char *
4991lys_data_path(const struct lys_node *node)
4992{
Michal Vasko53b7da02018-02-13 15:28:42 +01004993 char *result = NULL, buf[1024];
PavolVicanb28bbff2018-02-21 00:44:02 +01004994 const char *separator, *name;
Michal Vasko50576712017-07-28 12:28:33 +02004995 int i, used;
4996 struct ly_set *set;
4997 const struct lys_module *prev_mod;
4998
4999 if (!node) {
Michal Vasko53b7da02018-02-13 15:28:42 +01005000 LOGARG;
Michal Vasko50576712017-07-28 12:28:33 +02005001 return NULL;
5002 }
5003
Michal Vaskod60a1a32018-05-23 16:31:22 +02005004 buf[0] = '\0';
Michal Vasko50576712017-07-28 12:28:33 +02005005 set = ly_set_new();
Michal Vasko53b7da02018-02-13 15:28:42 +01005006 LY_CHECK_ERR_GOTO(!set, LOGMEM(node->module->ctx), cleanup);
Michal Vasko50576712017-07-28 12:28:33 +02005007
5008 while (node) {
5009 ly_set_add(set, (void *)node, 0);
5010 do {
5011 node = lys_parent(node);
5012 } while (node && (node->nodetype & (LYS_USES | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
5013 }
5014
5015 prev_mod = NULL;
5016 used = 0;
5017 for (i = set->number - 1; i > -1; --i) {
5018 node = set->set.s[i];
PavolVicanb28bbff2018-02-21 00:44:02 +01005019 if (node->nodetype == LYS_EXT) {
5020 if (strcmp(((struct lys_ext_instance *)node)->def->name, "yang-data")) {
5021 continue;
5022 }
5023 name = ((struct lys_ext_instance *)node)->arg_value;
5024 separator = ":#";
5025 } else {
5026 name = node->name;
5027 separator = ":";
5028 }
Michal Vasko50576712017-07-28 12:28:33 +02005029 used += sprintf(buf + used, "/%s%s%s", (lys_node_module(node) == prev_mod ? "" : lys_node_module(node)->name),
PavolVicanb28bbff2018-02-21 00:44:02 +01005030 (lys_node_module(node) == prev_mod ? "" : separator), name);
Michal Vasko50576712017-07-28 12:28:33 +02005031 prev_mod = lys_node_module(node);
5032 }
5033
5034 result = strdup(buf);
Michal Vasko53b7da02018-02-13 15:28:42 +01005035 LY_CHECK_ERR_GOTO(!result, LOGMEM(node->module->ctx), cleanup);
Michal Vasko50576712017-07-28 12:28:33 +02005036
Michal Vasko53b7da02018-02-13 15:28:42 +01005037cleanup:
Michal Vasko50576712017-07-28 12:28:33 +02005038 ly_set_free(set);
Michal Vasko50576712017-07-28 12:28:33 +02005039 return result;
5040}
5041
Michal Vaskobb520442017-05-23 10:55:18 +02005042struct lys_node_augment *
5043lys_getnext_target_aug(struct lys_node_augment *last, const struct lys_module *mod, const struct lys_node *aug_target)
5044{
Michal Vaskofc0b9602018-12-04 10:07:11 +01005045 struct lys_node *child;
5046 struct lys_node_augment *aug;
Michal Vaskobb520442017-05-23 10:55:18 +02005047 int i, j, last_found;
5048
Michal Vaskob6906872018-03-12 11:35:09 +01005049 assert(mod && aug_target);
5050
Michal Vaskobb520442017-05-23 10:55:18 +02005051 if (!last) {
5052 last_found = 1;
5053 } else {
5054 last_found = 0;
5055 }
5056
5057 /* search module augments */
5058 for (i = 0; i < mod->augment_size; ++i) {
5059 if (!mod->augment[i].target) {
5060 /* still unresolved, skip */
5061 continue;
5062 }
5063
5064 if (mod->augment[i].target == aug_target) {
5065 if (last_found) {
5066 /* next match after last */
5067 return &mod->augment[i];
5068 }
5069
5070 if (&mod->augment[i] == last) {
5071 last_found = 1;
5072 }
5073 }
5074 }
5075
5076 /* search submodule augments */
5077 for (i = 0; i < mod->inc_size; ++i) {
5078 for (j = 0; j < mod->inc[i].submodule->augment_size; ++j) {
5079 if (!mod->inc[i].submodule->augment[j].target) {
5080 continue;
5081 }
5082
5083 if (mod->inc[i].submodule->augment[j].target == aug_target) {
5084 if (last_found) {
5085 /* next match after last */
5086 return &mod->inc[i].submodule->augment[j];
5087 }
5088
5089 if (&mod->inc[i].submodule->augment[j] == last) {
5090 last_found = 1;
5091 }
5092 }
5093 }
5094 }
5095
Michal Vaskofc0b9602018-12-04 10:07:11 +01005096 /* we also need to check possible augments to choices */
5097 LY_TREE_FOR(aug_target->child, child) {
5098 if (child->nodetype == LYS_CHOICE) {
5099 aug = lys_getnext_target_aug(last, mod, child);
5100 if (aug) {
5101 return aug;
5102 }
5103 }
5104 }
5105
Michal Vaskobb520442017-05-23 10:55:18 +02005106 return NULL;
5107}
5108
Michal Vasko50576712017-07-28 12:28:33 +02005109API struct ly_set *
5110lys_find_path(const struct lys_module *cur_module, const struct lys_node *cur_node, const char *path)
5111{
5112 struct ly_set *ret;
5113 int rc;
5114
5115 if ((!cur_module && !cur_node) || !path) {
5116 return NULL;
5117 }
5118
5119 rc = resolve_schema_nodeid(path, cur_node, cur_module, &ret, 1, 1);
5120 if (rc == -1) {
5121 return NULL;
5122 }
5123
5124 return ret;
5125}
5126
Radek Krejci8d6b7422017-02-03 14:42:13 +01005127static void
5128lys_extcomplex_free_str(struct ly_ctx *ctx, struct lys_ext_instance_complex *ext, LY_STMT stmt)
5129{
5130 struct lyext_substmt *info;
Radek Krejcib71243e2017-02-08 16:20:08 +01005131 const char **str, ***a;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005132 int c;
5133
5134 str = lys_ext_complex_get_substmt(stmt, ext, &info);
5135 if (!str || !(*str)) {
5136 return;
5137 }
5138 if (info->cardinality >= LY_STMT_CARD_SOME) {
5139 /* we have array */
Radek Krejcib71243e2017-02-08 16:20:08 +01005140 a = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01005141 for (str = (*(const char ***)str), c = 0; str[c]; c++) {
5142 lydict_remove(ctx, str[c]);
Radek Krejci8d6b7422017-02-03 14:42:13 +01005143 }
Radek Krejci56c80412017-02-09 10:44:16 +01005144 free(a[0]);
5145 if (stmt == LY_STMT_BELONGSTO) {
5146 for (str = a[1], c = 0; str[c]; c++) {
5147 lydict_remove(ctx, str[c]);
5148 }
5149 free(a[1]);
PavolVican99c70722017-02-18 17:25:52 +01005150 } else if (stmt == LY_STMT_ARGUMENT) {
5151 free(a[1]);
Radek Krejci56c80412017-02-09 10:44:16 +01005152 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005153 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01005154 lydict_remove(ctx, str[0]);
5155 if (stmt == LY_STMT_BELONGSTO) {
5156 lydict_remove(ctx, str[1]);
5157 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005158 }
5159}
Michal Vasko1e82a3b2018-07-03 12:16:58 +02005160
Radek Krejci8d6b7422017-02-03 14:42:13 +01005161void
Radek Krejci5138e9f2017-04-12 13:10:46 +02005162lys_extension_instances_free(struct ly_ctx *ctx, struct lys_ext_instance **e, unsigned int size,
5163 void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejci8d6b7422017-02-03 14:42:13 +01005164{
Radek Krejcif8d05c22017-02-10 15:33:35 +01005165 unsigned int i, j, k;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005166 struct lyext_substmt *substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005167 void **pp, **start;
Radek Krejcif95b6292017-02-13 15:57:37 +01005168 struct lys_node *siter, *snext;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005169
5170#define EXTCOMPLEX_FREE_STRUCT(STMT, TYPE, FUNC, FREE, ARGS...) \
Radek Krejcib84686f2017-02-09 16:04:55 +01005171 pp = lys_ext_complex_get_substmt(STMT, (struct lys_ext_instance_complex *)e[i], NULL); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01005172 if (!pp || !(*pp)) { break; } \
Radek Krejcib84686f2017-02-09 16:04:55 +01005173 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */ \
Radek Krejci8d6b7422017-02-03 14:42:13 +01005174 for (start = pp = *pp; *pp; pp++) { \
Radek Krejci5138e9f2017-04-12 13:10:46 +02005175 FUNC(ctx, (TYPE *)(*pp), ##ARGS, private_destructor); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01005176 if (FREE) { free(*pp); } \
5177 } \
5178 free(start); \
5179 } else { /* single item */ \
Radek Krejci5138e9f2017-04-12 13:10:46 +02005180 FUNC(ctx, (TYPE *)(*pp), ##ARGS, private_destructor); \
Radek Krejci8d6b7422017-02-03 14:42:13 +01005181 if (FREE) { free(*pp); } \
5182 }
5183
PavolVican9d61d402018-02-05 15:52:48 +01005184 if (!size || !e) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01005185 return;
5186 }
5187
5188 for (i = 0; i < size; i++) {
5189 if (!e[i]) {
5190 continue;
5191 }
5192
5193 if (e[i]->flags & (LYEXT_OPT_INHERIT)) {
5194 /* no free, this is just a shadow copy of the original extension instance */
5195 } else {
5196 if (e[i]->flags & (LYEXT_OPT_YANG)) {
5197 free(e[i]->def); /* remove name of instance extension */
PavolVican19dc6152017-02-06 12:04:15 +01005198 e[i]->def = NULL;
PavolVicandb0e8172017-02-20 00:46:09 +01005199 yang_free_ext_data((struct yang_ext_substmt *)e[i]->parent); /* remove backup part of yang file */
Radek Krejci8d6b7422017-02-03 14:42:13 +01005200 }
Radek Krejci5138e9f2017-04-12 13:10:46 +02005201 /* remove private object */
5202 if (e[i]->priv && private_destructor) {
5203 private_destructor((struct lys_node*)e[i], e[i]->priv);
5204 }
5205 lys_extension_instances_free(ctx, e[i]->ext, e[i]->ext_size, private_destructor);
Radek Krejci8d6b7422017-02-03 14:42:13 +01005206 lydict_remove(ctx, e[i]->arg_value);
5207 }
5208
fanchanghu8d86f6b2017-06-10 12:49:54 +08005209 if (e[i]->def && e[i]->def->plugin && e[i]->def->plugin->type == LYEXT_COMPLEX
5210 && ((e[i]->flags & LYEXT_OPT_CONTENT) == 0)) {
Radek Krejcifebdad72017-02-06 11:35:51 +01005211 substmt = ((struct lys_ext_instance_complex *)e[i])->substmt;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005212 for (j = 0; substmt[j].stmt; j++) {
5213 switch(substmt[j].stmt) {
5214 case LY_STMT_DESCRIPTION:
5215 case LY_STMT_REFERENCE:
5216 case LY_STMT_UNITS:
Radek Krejcib71243e2017-02-08 16:20:08 +01005217 case LY_STMT_ARGUMENT:
5218 case LY_STMT_DEFAULT:
5219 case LY_STMT_ERRTAG:
5220 case LY_STMT_ERRMSG:
5221 case LY_STMT_PREFIX:
5222 case LY_STMT_NAMESPACE:
5223 case LY_STMT_PRESENCE:
5224 case LY_STMT_REVISIONDATE:
5225 case LY_STMT_KEY:
5226 case LY_STMT_BASE:
5227 case LY_STMT_BELONGSTO:
5228 case LY_STMT_CONTACT:
5229 case LY_STMT_ORGANIZATION:
5230 case LY_STMT_PATH:
Radek Krejci8d6b7422017-02-03 14:42:13 +01005231 lys_extcomplex_free_str(ctx, (struct lys_ext_instance_complex *)e[i], substmt[j].stmt);
5232 break;
5233 case LY_STMT_TYPE:
5234 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPE, struct lys_type, lys_type_free, 1);
5235 break;
Radek Krejci63fc0962017-02-15 13:20:18 +01005236 case LY_STMT_TYPEDEF:
5237 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPEDEF, struct lys_tpdf, lys_tpdf_free, 1);
5238 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005239 case LY_STMT_IFFEATURE:
Frank Rimplerc4db1c72017-09-12 12:56:39 +00005240 EXTCOMPLEX_FREE_STRUCT(LY_STMT_IFFEATURE, struct lys_iffeature, lys_iffeature_free, 0, 1, 0);
Radek Krejci8d6b7422017-02-03 14:42:13 +01005241 break;
Radek Krejci5496fae2017-02-10 13:26:48 +01005242 case LY_STMT_MAX:
5243 case LY_STMT_MIN:
5244 case LY_STMT_POSITION:
PavolVican2ed9f4e2017-02-16 00:08:45 +01005245 case LY_STMT_VALUE:
Radek Krejcif8d05c22017-02-10 15:33:35 +01005246 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
Radek Krejci716cd7a2017-02-15 12:23:41 +01005247 if (substmt[j].cardinality >= LY_STMT_CARD_SOME && *pp) {
Radek Krejcif8d05c22017-02-10 15:33:35 +01005248 for(k = 0; ((uint32_t**)(*pp))[k]; k++) {
5249 free(((uint32_t**)(*pp))[k]);
5250 }
5251 }
5252 free(*pp);
5253 break;
5254 case LY_STMT_DIGITS:
Radek Krejcib84686f2017-02-09 16:04:55 +01005255 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
5256 /* free the array */
5257 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5258 free(*pp);
5259 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005260 break;
Radek Krejci37f9ba32017-02-10 16:50:35 +01005261 case LY_STMT_MODULE:
5262 /* modules are part of the context, so they will be freed there */
5263 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
5264 /* free the array */
5265 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5266 free(*pp);
5267 }
5268 break;
Radek Krejcif95b6292017-02-13 15:57:37 +01005269 case LY_STMT_ACTION:
Radek Krejcib31762b2017-02-15 10:48:42 +01005270 case LY_STMT_ANYDATA:
5271 case LY_STMT_ANYXML:
5272 case LY_STMT_CASE:
5273 case LY_STMT_CHOICE:
5274 case LY_STMT_CONTAINER:
5275 case LY_STMT_GROUPING:
5276 case LY_STMT_INPUT:
5277 case LY_STMT_LEAF:
5278 case LY_STMT_LEAFLIST:
5279 case LY_STMT_LIST:
5280 case LY_STMT_NOTIFICATION:
5281 case LY_STMT_OUTPUT:
5282 case LY_STMT_RPC:
5283 case LY_STMT_USES:
Radek Krejcif95b6292017-02-13 15:57:37 +01005284 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5285 LY_TREE_FOR_SAFE((struct lys_node *)(*pp), snext, siter) {
5286 lys_node_free(siter, NULL, 0);
5287 }
Radek Krejcib31762b2017-02-15 10:48:42 +01005288 *pp = NULL;
Radek Krejcif95b6292017-02-13 15:57:37 +01005289 break;
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01005290 case LY_STMT_UNIQUE:
5291 pp = lys_ext_complex_get_substmt(LY_STMT_UNIQUE, (struct lys_ext_instance_complex *)e[i], NULL);
5292 if (!pp || !(*pp)) {
5293 break;
5294 }
5295 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
5296 for (start = pp = *pp; *pp; pp++) {
5297 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
5298 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
5299 }
5300 free((*(struct lys_unique**)pp)->expr);
5301 free(*pp);
5302 }
5303 free(start);
5304 } else { /* single item */
5305 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
5306 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
5307 }
5308 free((*(struct lys_unique**)pp)->expr);
5309 free(*pp);
5310 }
5311 break;
Radek Krejciaa9c5202017-02-15 16:10:14 +01005312 case LY_STMT_LENGTH:
5313 case LY_STMT_MUST:
5314 case LY_STMT_PATTERN:
5315 case LY_STMT_RANGE:
5316 EXTCOMPLEX_FREE_STRUCT(substmt[j].stmt, struct lys_restr, lys_restr_free, 1);
5317 break;
Radek Krejcic5cc5302017-02-16 10:07:46 +01005318 case LY_STMT_WHEN:
5319 EXTCOMPLEX_FREE_STRUCT(LY_STMT_WHEN, struct lys_when, lys_when_free, 0);
5320 break;
Radek Krejci7417a082017-02-16 11:07:59 +01005321 case LY_STMT_REVISION:
5322 pp = lys_ext_complex_get_substmt(LY_STMT_REVISION, (struct lys_ext_instance_complex *)e[i], NULL);
5323 if (!pp || !(*pp)) {
5324 break;
5325 }
5326 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
5327 for (start = pp = *pp; *pp; pp++) {
5328 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
5329 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
5330 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
Radek Krejci5138e9f2017-04-12 13:10:46 +02005331 (*(struct lys_revision**)pp)->ext_size, private_destructor);
Radek Krejci7417a082017-02-16 11:07:59 +01005332 free(*pp);
5333 }
5334 free(start);
5335 } else { /* single item */
5336 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
5337 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
5338 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
Radek Krejci5138e9f2017-04-12 13:10:46 +02005339 (*(struct lys_revision**)pp)->ext_size, private_destructor);
Radek Krejci7417a082017-02-16 11:07:59 +01005340 free(*pp);
5341 }
5342 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +01005343 default:
Radek Krejcib84686f2017-02-09 16:04:55 +01005344 /* nothing to free */
Radek Krejci8d6b7422017-02-03 14:42:13 +01005345 break;
5346 }
5347 }
5348 }
5349
5350 free(e[i]);
5351 }
5352 free(e);
5353
5354#undef EXTCOMPLEX_FREE_STRUCT
5355}