blob: 8adefb9fc500b7da0a755ad7fe7efc1f2e007199 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
Michal Vasko2d162e12015-09-24 14:33:29 +02002 * @file tree_schema.c
Radek Krejcida04f4a2015-05-21 12:54:09 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vasko2d162e12015-09-24 14:33:29 +02004 * @brief Manipulation with libyang schema data structures
Radek Krejcida04f4a2015-05-21 12:54:09 +02005 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
Radek Krejci54f6fb32016-02-24 12:56:39 +010014
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020015#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020016
Radek Krejci812b10a2015-05-28 16:48:25 +020017#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020018#include <ctype.h>
Radek Krejcib051f722016-02-25 15:12:21 +010019#include <limits.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <sys/mman.h>
Michal Vasko662610a2015-12-07 11:25:45 +010022#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020023#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010024#include <fcntl.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020025#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010026#include <unistd.h>
27#include <errno.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020028
29#include "common.h"
30#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020031#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020032#include "resolve.h"
Michal Vasko88c29542015-11-27 14:57:53 +010033#include "xml.h"
Michal Vasko5b3492c2016-07-20 09:37:40 +020034#include "xpath.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020035#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020036#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020037#include "validation.h"
Pavol Vicanf7cc2852016-03-22 23:27:35 +010038#include "parser_yang.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020039
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020040static int
41lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +020042 int tpdftype, struct unres_schema *unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020043
Radek Krejci9ff0a922016-07-14 13:08:05 +020044API const struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +010045lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020046{
Radek Krejci9ff0a922016-07-14 13:08:05 +020047 int i;
Radek Krejci48061fb2015-08-05 15:41:07 +020048
49check:
50 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
51 /* input/output does not have if-feature, so skip them */
52
53 /* check local if-features */
Michal Vaskoc5c26b02016-06-29 11:10:29 +020054 for (i = 0; i < node->iffeature_size; i++) {
Radek Krejci69b8d922016-07-27 13:13:41 +020055 if (!resolve_iffeature(&node->iffeature[i])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +020056 return node;
Radek Krejci48061fb2015-08-05 15:41:07 +020057 }
58 }
59 }
60
61 if (!recursive) {
62 return NULL;
63 }
64
65 /* go through parents */
66 if (node->nodetype == LYS_AUGMENT) {
67 /* go to parent actually means go to the target node */
68 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020069 } else if (node->parent) {
70 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020071 } else {
72 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020073 }
74
Radek Krejci074bf852015-08-19 14:22:16 +020075 if (recursive == 2) {
76 /* continue only if the node cannot have a data instance */
77 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
78 return NULL;
79 }
80 }
81 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020082}
83
Michal Vasko1dca6882015-10-22 14:29:42 +020084int
Michal Vasko36cbaa42015-12-14 13:15:48 +010085lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
86 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020087{
Radek Krejcic071c542016-01-27 14:57:51 +010088 const struct lys_node *node, *parent = NULL;
89 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010090 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020091
Michal Vasko36cbaa42015-12-14 13:15:48 +010092 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020093 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020094
Michal Vasko36cbaa42015-12-14 13:15:48 +010095 /* fill the lengths in case the caller is so indifferent */
96 if (!mod_name_len) {
97 mod_name_len = strlen(mod_name);
98 }
Michal Vasko1dca6882015-10-22 14:29:42 +020099 if (!nam_len) {
100 nam_len = strlen(name);
101 }
102
Michal Vasko36cbaa42015-12-14 13:15:48 +0100103 /* set mod correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100104 parent = lys_parent(siblings);
105 if (!parent) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100106 mod = lys_node_module(siblings);
Michal Vasko1dca6882015-10-22 14:29:42 +0200107 }
108
Radek Krejcic071c542016-01-27 14:57:51 +0100109 /* try to find the node */
110 node = NULL;
111 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
112 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100113 /* module name comparison */
114 node_mod_name = lys_node_module(node)->name;
Michal Vaskob42b6972016-06-06 14:21:30 +0200115 if (!ly_strequal(node_mod_name, mod_name, 1) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100116 continue;
117 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200118
Radek Krejcic071c542016-01-27 14:57:51 +0100119 /* direct name check */
Michal Vaskob42b6972016-06-06 14:21:30 +0200120 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100121 if (ret) {
122 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200123 }
Radek Krejcic071c542016-01-27 14:57:51 +0100124 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200125 }
126 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200127 }
128
129 return EXIT_FAILURE;
130}
131
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200132int
Michal Vasko1e62a092015-12-01 12:27:20 +0100133lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
134 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200135{
Michal Vasko1e62a092015-12-01 12:27:20 +0100136 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200137
138 assert(siblings && name);
139 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
140
141 /* find the beginning */
142 while (siblings->prev->next) {
143 siblings = siblings->prev;
144 }
145
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200146 if (!mod) {
147 mod = siblings->module;
148 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200149
Michal Vasko4f0dad02016-02-15 14:08:23 +0100150 /* try to find the node */
151 node = NULL;
Michal Vaskodcf98e62016-05-05 17:53:53 +0200152 while ((node = lys_getnext(node, lys_parent(siblings), mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100153 if (!type || (node->nodetype & type)) {
154 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200155 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100156 continue;
157 }
158
Michal Vasko4f0dad02016-02-15 14:08:23 +0100159 /* direct name check */
Radek Krejci749190d2016-02-18 16:26:25 +0100160 if (ly_strequal(node->name, name, 0)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100161 if (ret) {
162 *ret = node;
163 }
164 return EXIT_SUCCESS;
165 }
Radek Krejcic071c542016-01-27 14:57:51 +0100166 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200167 }
168
169 return EXIT_FAILURE;
170}
171
Michal Vasko1e62a092015-12-01 12:27:20 +0100172API const struct lys_node *
173lys_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200174{
Michal Vasko1e62a092015-12-01 12:27:20 +0100175 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200176
Radek Krejci8bc87f62015-09-02 16:19:05 +0200177 if (!last) {
178 /* first call */
179
180 /* get know where to start */
181 if (parent) {
182 /* schema subtree */
183 next = last = parent->child;
184 } else {
185 /* top level data */
186 assert(module);
187 next = last = module->data;
188 }
Radek Krejci972724f2016-08-12 15:24:40 +0200189 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
190 /* continue with uses content */
191 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200192 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200193 /* continue after the last returned value */
194 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200195 }
196
197repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200198 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200199 if (options & LYS_GETNEXT_WITHGROUPING) {
200 return next;
201 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200202 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200203 }
204
Radek Krejci972724f2016-08-12 15:24:40 +0200205 if (!next) { /* cover case when parent is augment */
206 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200207 /* no next element */
208 return NULL;
209 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200210 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200211 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200212 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200213 } else {
214 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200215 }
216
217 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200218 case LYS_INPUT:
219 case LYS_OUTPUT:
220 if (options & LYS_GETNEXT_WITHINOUT) {
221 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200222 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200223 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200224 } else {
225 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200226 }
Radek Krejci972724f2016-08-12 15:24:40 +0200227 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200228
Michal Vaskoa5835e92015-10-20 15:07:39 +0200229 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200230 if (options & LYS_GETNEXT_WITHCASE) {
231 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200232 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200233 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200234 } else {
235 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200236 }
Radek Krejci972724f2016-08-12 15:24:40 +0200237 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200238
Michal Vasko1dca6882015-10-22 14:29:42 +0200239 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200240 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200241 if (options & LYS_GETNEXT_WITHUSES) {
242 return next;
243 } else if (next->child) {
244 next = next->child;
245 } else {
246 next = next->next;
247 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200248 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200249
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200250 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200251 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200252 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200253 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200254 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200255 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200256 case LYS_LIST:
257 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200258 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200259
Radek Krejci972724f2016-08-12 15:24:40 +0200260 case LYS_CONTAINER:
261 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
262 if (next->child) {
263 /* go into */
264 next = next->child;
265 } else {
266 next = next->next;
267 }
268 goto repeat;
269 } else {
270 return next;
271 }
272
Radek Krejci8bc87f62015-09-02 16:19:05 +0200273 case LYS_CHOICE:
274 if (options & LYS_GETNEXT_WITHCHOICE) {
275 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200276 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200277 /* go into */
278 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200279 } else {
280 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200281 }
Radek Krejci972724f2016-08-12 15:24:40 +0200282 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200283
Radek Krejci7f40ce32015-08-12 20:38:46 +0200284 default:
285 /* we should not be here */
286 return NULL;
287 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200288
289
290}
291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200292void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200293lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200294{
Radek Krejci76512572015-08-04 09:47:08 +0200295 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100296 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200298 if (!node) {
299 return;
300 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200302 /* unlink from data model if necessary */
303 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100304 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100305 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100306 if (main_module->data == node) {
307 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200308 }
309 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200311 /* store pointers to important nodes */
312 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200313 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200314 /* handle augments - first, unlink it from the augment parent ... */
315 if (parent->child == node) {
316 parent->child = node->next;
317 }
318 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200319 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200320 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200322 /* unlink from parent */
323 if (parent) {
324 if (parent->child == node) {
325 parent->child = node->next;
326 }
327 node->parent = NULL;
328 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200330 /* unlink from siblings */
331 if (node->prev == node) {
332 /* there are no more siblings */
333 return;
334 }
335 if (node->next) {
336 node->next->prev = node->prev;
337 } else {
338 /* unlinking the last element */
339 if (parent) {
340 first = parent->child;
341 } else {
342 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200343 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200344 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200345 }
346 }
347 first->prev = node->prev;
348 }
349 if (node->prev->next) {
350 node->prev->next = node->next;
351 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200353 /* clean up the unlinked element */
354 node->next = NULL;
355 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200356}
357
Michal Vasko563ef092015-09-04 13:17:23 +0200358struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100359lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200360{
361 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200362
363 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200364 /* top-level augment, look into module (uses augment is handled correctly below) */
365 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
366 par_iter = par_iter->parent->module->data;
367 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200368 break;
369 }
370 }
371
Michal Vasko6f929da2015-10-02 16:23:25 +0200372 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200373 continue;
374 }
375
376 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
377 if (!stop) {
378 stop = par_iter;
379 } else if (iter == stop) {
380 break;
381 }
382 if (iter->nodetype != LYS_GROUPING) {
383 continue;
384 }
385
Radek Krejcif8426a72015-10-31 23:14:03 +0100386 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200387 return (struct lys_node_grp *)iter;
388 }
389 }
390 }
391
Michal Vasko563ef092015-09-04 13:17:23 +0200392 return NULL;
393}
394
Radek Krejci10c760e2015-08-14 14:45:43 +0200395/*
396 * get next grouping in the root's subtree, in the
397 * first call, tha last is NULL
398 */
399static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200400lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200401{
Radek Krejci10c760e2015-08-14 14:45:43 +0200402 struct lys_node *last = (struct lys_node *)lastgrp;
403 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200404
Radek Krejci10c760e2015-08-14 14:45:43 +0200405 assert(root);
406
407 if (!last) {
408 last = root;
409 }
410
411 while (1) {
412 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
413 next = last->child;
414 } else {
415 next = NULL;
416 }
417 if (!next) {
418 if (last == root) {
419 /* we are done */
420 return NULL;
421 }
422
423 /* no children, go to siblings */
424 next = last->next;
425 }
426 while (!next) {
427 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100428 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200429 /* we are done */
430 return NULL;
431 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200432 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100433 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200434 }
435
436 if (next->nodetype == LYS_GROUPING) {
437 return (struct lys_node_grp *)next;
438 }
439
440 last = next;
441 }
442}
443
Michal Vasko0d343d12015-08-24 14:57:36 +0200444/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200445int
Radek Krejci07911992015-08-14 15:13:31 +0200446lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
447{
Michal Vasko563ef092015-09-04 13:17:23 +0200448 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200449 struct lys_node_grp *grp;
450 int down;
451
452 assert(node);
453
454 if (!parent) {
455 assert(module);
456 } else {
457 module = parent->module;
458 }
459
460 switch (node->nodetype) {
461 case LYS_GROUPING:
462 /* 6.2.1, rule 6 */
463 if (parent) {
464 if (parent->child) {
465 down = 1;
466 start = parent->child;
467 } else {
468 down = 0;
469 start = parent;
470 }
471 } else {
472 down = 1;
473 start = module->data;
474 }
475 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100476 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100477 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200478 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200479 }
480 /* go down, because grouping can be defined after e.g. container in which is collision */
481 if (down) {
482 for (iter = start, stop = NULL; iter; iter = iter->prev) {
483 if (!stop) {
484 stop = start;
485 } else if (iter == stop) {
486 break;
487 }
488 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
489 continue;
490 }
491
492 grp = NULL;
493 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100494 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100495 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200496 return EXIT_FAILURE;
497 }
498 }
499 }
500 }
501 break;
502 case LYS_LEAF:
503 case LYS_LEAFLIST:
504 case LYS_LIST:
505 case LYS_CONTAINER:
506 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200507 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200508 /* 6.2.1, rule 7 */
509 if (parent) {
510 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200511 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
512 if (iter->nodetype == LYS_AUGMENT) {
513 if (((struct lys_node_augment *)iter)->target) {
514 /* augment is resolved, go up */
515 iter = ((struct lys_node_augment *)iter)->target;
516 continue;
517 }
518 /* augment is not resolved, this is the final parent */
519 break;
520 }
Radek Krejci07911992015-08-14 15:13:31 +0200521 iter = iter->parent;
522 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200523
Radek Krejci07911992015-08-14 15:13:31 +0200524 if (!iter) {
525 stop = NULL;
526 iter = module->data;
527 } else {
528 stop = iter;
529 iter = iter->child;
530 }
531 } else {
532 stop = NULL;
533 iter = module->data;
534 }
535 while (iter) {
536 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
537 iter = iter->child;
538 continue;
539 }
540
Radek Krejcibf2abff2016-08-23 15:51:52 +0200541 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100542 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100543 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200544 return EXIT_FAILURE;
545 }
546 }
547
548 /* special case for choice - we must check the choice's name as
549 * well as the names of nodes under the choice
550 */
551 if (iter->nodetype == LYS_CHOICE) {
552 iter = iter->child;
553 continue;
554 }
555
556 /* go to siblings */
557 if (!iter->next) {
558 /* no sibling, go to parent's sibling */
559 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200560 /* for parent LYS_AUGMENT */
561 if (iter->parent == stop) {
562 iter = stop;
563 break;
564 }
565 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200566 if (iter && iter->next) {
567 break;
568 }
569 } while (iter != stop);
570
571 if (iter == stop) {
572 break;
573 }
574 }
575 iter = iter->next;
576 }
577 break;
578 case LYS_CASE:
579 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100580 if (parent) {
581 start = parent->child;
582 } else {
583 start = module->data;
584 }
585
586 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200587 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200588 continue;
589 }
590
Radek Krejci749190d2016-02-18 16:26:25 +0100591 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100592 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200593 return EXIT_FAILURE;
594 }
595 }
596 break;
597 default:
598 /* no check needed */
599 break;
600 }
601
602 return EXIT_SUCCESS;
603}
604
Michal Vasko0d343d12015-08-24 14:57:36 +0200605/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200606int
Radek Krejci10c760e2015-08-14 14:45:43 +0200607lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
608{
Radek Krejci92720552015-10-05 15:28:27 +0200609 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200610 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200612 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200613
Radek Krejci10c760e2015-08-14 14:45:43 +0200614 if (parent) {
615 type = parent->nodetype;
616 module = parent->module;
617 } else {
618 assert(module);
619 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200620 }
621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200622 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200623 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200624 case LYS_CONTAINER:
625 case LYS_LIST:
626 case LYS_GROUPING:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200627 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200628 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200629 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
630 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
631 return EXIT_FAILURE;
632 }
633 break;
Radek Krejci76512572015-08-04 09:47:08 +0200634 case LYS_USES:
635 case LYS_INPUT:
636 case LYS_OUTPUT:
637 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200638 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200639 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200640 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100641 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200642 return EXIT_FAILURE;
643 }
644 break;
Radek Krejci76512572015-08-04 09:47:08 +0200645 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200646 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200647 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100648 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200649 return EXIT_FAILURE;
650 }
651 break;
Radek Krejci76512572015-08-04 09:47:08 +0200652 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200653 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200654 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100655 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200656 return EXIT_FAILURE;
657 }
658 break;
Radek Krejci76512572015-08-04 09:47:08 +0200659 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200660 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200661 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100662 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200663 return EXIT_FAILURE;
664 }
665 break;
Radek Krejci76512572015-08-04 09:47:08 +0200666 case LYS_LEAF:
667 case LYS_LEAFLIST:
668 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200669 case LYS_ANYDATA:
Radek Krejci48464ed2016-03-17 15:44:09 +0100670 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
671 LOGVAL(LYE_SPEC, LY_VLOG_LYS, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100672 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200673 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200674 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200675 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200676 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200677 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100678 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200679 return EXIT_FAILURE;
680 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200681 break;
682 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200683 /* top level */
684 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200685 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200686 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100687 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200688 return EXIT_FAILURE;
689 }
690
Radek Krejcic071c542016-01-27 14:57:51 +0100691 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200692 }
693
694 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200695 if (lys_check_id(child, parent, module)) {
696 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200697 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200698
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200699 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200700 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200701 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200702
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200703 /* connect the child correctly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200704 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +0200705 if (module->data) {
706 module->data->prev->next = child;
707 child->prev = module->data->prev;
708 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200709 } else {
Radek Krejci92720552015-10-05 15:28:27 +0200710 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200711 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200712 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200713 if (!parent->child) {
714 /* the only/first child of the parent */
715 parent->child = child;
716 child->parent = parent;
717 iter = child;
718 } else {
719 /* add a new child at the end of parent's child list */
720 iter = parent->child->prev;
721 iter->next = child;
722 child->prev = iter;
723 }
724 while (iter->next) {
725 iter = iter->next;
726 iter->parent = parent;
727 }
728 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200729 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200730
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200731 /* check config value */
732 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_AUGMENT))) {
733 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
734 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
735 LOGVAL(LYE_INARG, LY_VLOG_LYS, child, "true", "config");
736 LOGVAL(LYE_SPEC, LY_VLOG_LYS, child, "State nodes cannot have configuration nodes as children.");
737 return EXIT_FAILURE;
738 }
739 }
740
Radek Krejci41771502016-04-14 17:52:32 +0200741 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200742 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200743 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200744 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200745 /* store it only into container or list - the only data inner nodes */
746 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
747 if (iter->flags & LYS_INCL_STATUS) {
748 /* done, someone else set it already from here */
749 break;
750 }
751 /* set flag about including status data */
752 iter->flags |= LYS_INCL_STATUS;
753 }
754 }
755 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200756 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200757}
758
Radek Krejcia1df1682016-04-11 14:56:59 +0200759static const struct lys_module *
760lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200761{
Radek Krejcia1df1682016-04-11 14:56:59 +0200762 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200763 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200764 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200765
Radek Krejcif347abc2016-06-22 10:18:47 +0200766 ly_errno = LY_SUCCESS;
767
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200768 if (!ctx || !data) {
769 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
770 return NULL;
771 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200772
Radek Krejcia1df1682016-04-11 14:56:59 +0200773 if (!internal && format == LYS_IN_YANG) {
774 /* enlarge data by 2 bytes for flex */
775 len = strlen(data);
776 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
777 if (!enlarged_data) {
778 LOGMEM;
779 return NULL;
780 }
781 memcpy(enlarged_data, data, len);
782 enlarged_data[len] = enlarged_data[len + 1] = '\0';
783 data = enlarged_data;
784 }
785
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200786 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200787 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +0100788 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200789 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200790 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100791 mod = yang_read_module(ctx, data, 0, NULL, 1);
792 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200793 default:
Radek Krejcia1df1682016-04-11 14:56:59 +0200794 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200795 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200796 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200797
Radek Krejcia1df1682016-04-11 14:56:59 +0200798 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200799 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200800}
801
Radek Krejcia1df1682016-04-11 14:56:59 +0200802API const struct lys_module *
803lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
804{
805 return lys_parse_mem_(ctx, data, format, 0);
806}
807
Michal Vasko5a721fd2016-02-16 12:16:48 +0100808struct lys_submodule *
809lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200810{
Michal Vasko5a721fd2016-02-16 12:16:48 +0100811 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200812
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200813 assert(module);
814 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200815
Radek Krejcic071c542016-01-27 14:57:51 +0100816 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +0200817 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200819 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200820 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +0100821 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200822 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200823 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100824 submod = yang_read_submodule(module, data, 0, unres);
825 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200826 default:
Radek Krejci90a550a2016-04-13 16:00:58 +0200827 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200828 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200829 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200830
Michal Vasko5a721fd2016-02-16 12:16:48 +0100831 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200832}
833
Michal Vasko1e62a092015-12-01 12:27:20 +0100834API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +0100835lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
836{
837 int fd;
838 const struct lys_module *ret;
839
840 if (!ctx || !path) {
841 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
842 return NULL;
843 }
844
845 fd = open(path, O_RDONLY);
846 if (fd == -1) {
847 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
848 return NULL;
849 }
850
851 ret = lys_parse_fd(ctx, fd, format);
852 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +0100853
Radek Krejcia77904e2016-02-25 16:23:45 +0100854 if (ret && !ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +0100855 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +0100856 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +0100857 }
858
Michal Vasko662610a2015-12-07 11:25:45 +0100859 return ret;
860}
861
862API const struct lys_module *
863lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +0200864{
Michal Vasko1e62a092015-12-01 12:27:20 +0100865 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +0200866 struct stat sb;
867 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +0100868 char buf[PATH_MAX];
869 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +0200870
871 if (!ctx || fd < 0) {
872 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
873 return NULL;
874 }
875
Radek Krejci10a833c2015-12-16 15:28:37 +0100876 if (fstat(fd, &sb) == -1) {
877 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
878 return NULL;
879 }
Radek Krejcib051f722016-02-25 15:12:21 +0100880 if (!S_ISREG(sb.st_mode)) {
881 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
882 return NULL;
883 }
884
Michal Vasko164d9012016-04-01 10:16:59 +0200885 if (!sb.st_size) {
886 LOGERR(LY_EINVAL, "File empty.");
887 return NULL;
888 }
889
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100890 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +0100891 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +0100892 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +0100893 return NULL;
894 }
Radek Krejcia1df1682016-04-11 14:56:59 +0200895 module = lys_parse_mem_(ctx, addr, format, 1);
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100896 munmap(addr, sb.st_size + 2);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200897
Radek Krejcia77904e2016-02-25 16:23:45 +0100898 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +0100899 /* get URI if there is /proc */
900 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +0100901 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
902 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
903 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
904 }
905 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +0100906 }
Radek Krejcib051f722016-02-25 15:12:21 +0100907 }
908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200909 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200910}
911
Michal Vasko5a721fd2016-02-16 12:16:48 +0100912struct lys_submodule *
913lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200914{
Michal Vasko5a721fd2016-02-16 12:16:48 +0100915 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200916 struct stat sb;
917 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200919 assert(module);
920 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200921
Radek Krejci10a833c2015-12-16 15:28:37 +0100922 if (fstat(fd, &sb) == -1) {
923 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +0100924 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +0100925 }
Michal Vasko164d9012016-04-01 10:16:59 +0200926
927 if (!sb.st_size) {
928 LOGERR(LY_EINVAL, "File empty.");
929 return NULL;
930 }
931
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100932 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +0100933 if (addr == MAP_FAILED) {
934 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +0100935 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +0100936 }
Michal Vasko5a721fd2016-02-16 12:16:48 +0100937 submodule = lys_submodule_parse(module, addr, format, unres);
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100938 munmap(addr, sb.st_size + 2);
Radek Krejciefaeba32015-05-27 14:30:57 +0200939
Michal Vasko5a721fd2016-02-16 12:16:48 +0100940 return submodule;
941
Radek Krejciefaeba32015-05-27 14:30:57 +0200942}
943
Radek Krejci1d82ef62015-08-07 14:44:40 +0200944static struct lys_restr *
945lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200946{
Radek Krejci1574a8d2015-08-03 14:16:52 +0200947 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200948 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200949
Radek Krejci3733a802015-06-19 13:43:21 +0200950 if (!size) {
951 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200952 }
Radek Krejci3733a802015-06-19 13:43:21 +0200953
954 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +0100955 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +0100956 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +0100957 return NULL;
958 }
Radek Krejci3733a802015-06-19 13:43:21 +0200959 for (i = 0; i < size; i++) {
960 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
961 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
962 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
963 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
964 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
965 }
966
967 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200968}
969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200970void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200971lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +0200972{
973 assert(ctx);
974 if (!restr) {
975 return;
976 }
977
978 lydict_remove(ctx, restr->expr);
979 lydict_remove(ctx, restr->dsc);
980 lydict_remove(ctx, restr->ref);
981 lydict_remove(ctx, restr->eapptag);
982 lydict_remove(ctx, restr->emsg);
983}
984
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200985static void
986lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size)
987{
988 uint8_t i;
989
990 for (i = 0; i < iffeature_size; ++i) {
991 free(iffeature[i].expr);
992 free(iffeature[i].features);
993 }
994 free(iffeature);
995}
996
Michal Vaskob84f88a2015-09-24 13:16:10 +0200997static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +0200998type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +0200999 LY_DATA_TYPE base, int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001000{
1001 int i;
1002
1003 switch (base) {
1004 case LY_TYPE_BINARY:
1005 if (old->info.binary.length) {
1006 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
1007 }
1008 break;
1009
1010 case LY_TYPE_BITS:
1011 new->info.bits.count = old->info.bits.count;
1012 if (new->info.bits.count) {
1013 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1014 if (!new->info.bits.bit) {
1015 LOGMEM;
1016 return -1;
1017 }
1018 for (i = 0; i < new->info.bits.count; i++) {
1019 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1020 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1021 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1022 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1023 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1024 }
1025 }
1026 break;
1027
1028 case LY_TYPE_DEC64:
1029 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001030 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001031 if (old->info.dec64.range) {
1032 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
1033 }
1034 break;
1035
1036 case LY_TYPE_ENUM:
1037 new->info.enums.count = old->info.enums.count;
1038 if (new->info.enums.count) {
1039 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1040 if (!new->info.enums.enm) {
1041 LOGMEM;
1042 return -1;
1043 }
1044 for (i = 0; i < new->info.enums.count; i++) {
1045 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1046 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1047 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1048 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1049 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
1050 }
1051 }
1052 break;
1053
1054 case LY_TYPE_IDENT:
Michal Vasko878e38d2016-09-05 12:17:53 +02001055 if (old->info.ident.count) {
1056 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
1057 if (!new->info.ident.ref) {
1058 LOGMEM;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001059 return -1;
1060 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001061 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1062 } else {
1063 /* there can be several unresolved base identities, duplicate them all */
1064 i = -1;
1065 while ((i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF)) != -1) {
1066 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
1067 return -1;
1068 }
1069 --i;
1070 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001071 }
1072 break;
1073
1074 case LY_TYPE_INST:
1075 new->info.inst.req = old->info.inst.req;
1076 break;
1077
1078 case LY_TYPE_INT8:
1079 case LY_TYPE_INT16:
1080 case LY_TYPE_INT32:
1081 case LY_TYPE_INT64:
1082 case LY_TYPE_UINT8:
1083 case LY_TYPE_UINT16:
1084 case LY_TYPE_UINT32:
1085 case LY_TYPE_UINT64:
1086 if (old->info.num.range) {
1087 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
1088 }
1089 break;
1090
1091 case LY_TYPE_LEAFREF:
1092 if (old->info.lref.path) {
1093 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko5d631402016-07-21 13:15:15 +02001094 if (!tpdftype && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001095 return -1;
1096 }
1097 }
1098 break;
1099
1100 case LY_TYPE_STRING:
1101 if (old->info.str.length) {
1102 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
1103 }
1104 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
1105 new->info.str.pat_count = old->info.str.pat_count;
1106 break;
1107
1108 case LY_TYPE_UNION:
1109 new->info.uni.count = old->info.uni.count;
1110 if (new->info.uni.count) {
1111 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1112 if (!new->info.uni.types) {
1113 LOGMEM;
1114 return -1;
1115 }
1116 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001117 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001118 return -1;
1119 }
1120 }
1121 }
1122 break;
1123
1124 default:
1125 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1126 break;
1127 }
1128 return EXIT_SUCCESS;
1129}
1130
1131struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001132lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1133 int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001134{
1135 struct yang_type *new;
1136
1137 new = calloc(1, sizeof *new);
1138 if (!new) {
1139 LOGMEM;
1140 return NULL;
1141 }
1142 new->flags = old->flags;
1143 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001144 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001145 new->type = type;
1146 if (!new->name) {
1147 LOGMEM;
1148 goto error;
1149 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001150 if (type_dup(module, parent, type, old->type, new->base, tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001151 new->type->base = new->base;
1152 lys_type_free(module->ctx, new->type);
1153 memset(&new->type->info, 0, sizeof new->type->info);
1154 goto error;
1155 }
1156 return new;
1157
1158 error:
1159 free(new);
1160 return NULL;
1161}
1162
1163static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001164lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001165 int tpdftype, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001166{
1167 int i;
1168
Michal Vasko1dca6882015-10-22 14:29:42 +02001169 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001170 new->base = old->base;
1171 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001172 new->parent = (struct lys_tpdf *)parent;
Radek Krejci3733a802015-06-19 13:43:21 +02001173
Michal Vasko878e38d2016-09-05 12:17:53 +02001174 i = unres_schema_find(unres, -1, old, tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001175 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001176 /* HACK (serious one) for unres */
1177 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001178 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001179 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, tpdftype, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001180 } else {
1181 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1182 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001183 /* all these unres additions can fail even though they did not before */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001184 if (!new->der || unres_schema_add_node(mod, unres, new,
Michal Vasko5d631402016-07-21 13:15:15 +02001185 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001186 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001187 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001188 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001189 }
1190
Radek Krejci3a5501d2016-07-18 22:03:34 +02001191 return type_dup(mod, parent, new, old, new->base, tpdftype, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001192}
1193
1194void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001195lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001196{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001197 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001199 assert(ctx);
1200 if (!type) {
1201 return;
1202 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001203
Michal Vasko1dca6882015-10-22 14:29:42 +02001204 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001205
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001206 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001207 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001208 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001209 free(type->info.binary.length);
1210 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001211 case LY_TYPE_BITS:
1212 for (i = 0; i < type->info.bits.count; i++) {
1213 lydict_remove(ctx, type->info.bits.bit[i].name);
1214 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1215 lydict_remove(ctx, type->info.bits.bit[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001216 lys_iffeature_free(type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size);
Radek Krejci994b6f62015-06-18 16:47:27 +02001217 }
1218 free(type->info.bits.bit);
1219 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001220
1221 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001222 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001223 free(type->info.dec64.range);
1224 break;
1225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001226 case LY_TYPE_ENUM:
1227 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001228 lydict_remove(ctx, type->info.enums.enm[i].name);
1229 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1230 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001231 lys_iffeature_free(type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001232 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001233 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001234 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001235
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001236 case LY_TYPE_INT8:
1237 case LY_TYPE_INT16:
1238 case LY_TYPE_INT32:
1239 case LY_TYPE_INT64:
1240 case LY_TYPE_UINT8:
1241 case LY_TYPE_UINT16:
1242 case LY_TYPE_UINT32:
1243 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001244 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001245 free(type->info.num.range);
1246 break;
1247
Radek Krejcidc4c1412015-06-19 15:39:54 +02001248 case LY_TYPE_LEAFREF:
1249 lydict_remove(ctx, type->info.lref.path);
1250 break;
1251
Radek Krejci3733a802015-06-19 13:43:21 +02001252 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001253 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001254 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001255 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001256 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001257 }
1258 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001259 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001260
Radek Krejcie4c366b2015-07-02 10:11:31 +02001261 case LY_TYPE_UNION:
1262 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001263 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001264 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001265 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001266 break;
1267
Michal Vaskod3282192016-09-05 11:27:57 +02001268 case LY_TYPE_IDENT:
1269 free(type->info.ident.ref);
1270 break;
1271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001272 default:
Michal Vaskod3282192016-09-05 11:27:57 +02001273 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001274 break;
1275 }
Radek Krejci5a065542015-05-22 15:02:07 +02001276}
1277
Radek Krejci1d82ef62015-08-07 14:44:40 +02001278static void
1279lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001280{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001281 assert(ctx);
1282 if (!tpdf) {
1283 return;
1284 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001286 lydict_remove(ctx, tpdf->name);
1287 lydict_remove(ctx, tpdf->dsc);
1288 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001289
Radek Krejci1d82ef62015-08-07 14:44:40 +02001290 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001292 lydict_remove(ctx, tpdf->units);
1293 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001294}
1295
Michal Vaskob84f88a2015-09-24 13:16:10 +02001296static struct lys_tpdf *
1297lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1298{
1299 struct lys_tpdf *result;
1300 int i, j;
1301
1302 if (!size) {
1303 return NULL;
1304 }
1305
1306 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001307 if (!result) {
1308 LOGMEM;
1309 return NULL;
1310 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001311 for (i = 0; i < size; i++) {
1312 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1313 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1314 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1315 result[i].flags = old[i].flags;
1316 result[i].module = old[i].module;
1317
Radek Krejci3a5501d2016-07-18 22:03:34 +02001318 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), 1, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001319 for (j = 0; j <= i; ++j) {
1320 lys_tpdf_free(mod->ctx, &result[j]);
1321 }
1322 free(result);
1323 return NULL;
1324 }
1325
1326 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1327 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1328 }
1329
1330 return result;
1331}
1332
Radek Krejci1d82ef62015-08-07 14:44:40 +02001333static struct lys_when *
1334lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001335{
Radek Krejci76512572015-08-04 09:47:08 +02001336 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001337
1338 if (!old) {
1339 return NULL;
1340 }
1341
1342 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001343 if (!new) {
1344 LOGMEM;
1345 return NULL;
1346 }
Radek Krejci00768f42015-06-18 17:04:04 +02001347 new->cond = lydict_insert(ctx, old->cond, 0);
1348 new->dsc = lydict_insert(ctx, old->dsc, 0);
1349 new->ref = lydict_insert(ctx, old->ref, 0);
1350
1351 return new;
1352}
1353
Michal Vasko0308dd62015-10-07 09:14:40 +02001354void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001355lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001356{
1357 if (!w) {
1358 return;
1359 }
1360
1361 lydict_remove(ctx, w->cond);
1362 lydict_remove(ctx, w->dsc);
1363 lydict_remove(ctx, w->ref);
1364
1365 free(w);
1366}
1367
Radek Krejcib7f5e412015-08-13 10:15:51 +02001368static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001369lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment *aug, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib7f5e412015-08-13 10:15:51 +02001370{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001371 struct lys_node *next, *sub;
1372
Radek Krejcic071c542016-01-27 14:57:51 +01001373 /* children from a resolved augment are freed under the target node */
Michal Vaskod2fbade2016-05-02 17:14:00 +02001374 if (!aug->target) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001375 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001376 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001377 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001378 }
1379
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001380 lydict_remove(ctx, aug->target_name);
1381 lydict_remove(ctx, aug->dsc);
1382 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001383
Radek Krejci9ff0a922016-07-14 13:08:05 +02001384 lys_iffeature_free(aug->iffeature, aug->iffeature_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001385
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001386 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001387}
1388
Radek Krejci76512572015-08-04 09:47:08 +02001389static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001390lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001391{
Radek Krejci76512572015-08-04 09:47:08 +02001392 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001393 struct lys_node *old_child, *new_child;
1394 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001395
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001396 if (!size) {
1397 return NULL;
1398 }
Radek Krejci106efc02015-06-10 14:36:27 +02001399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001400 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001401 if (!new) {
1402 LOGMEM;
1403 return NULL;
1404 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001405 for (i = 0; i < size; i++) {
1406 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1407 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1408 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1409 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001410 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001411 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001412
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001413 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001414 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1415 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001416 LOGINT;
1417 free(new);
1418 return NULL;
1419 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001420 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001421
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001422 /* Correct the augment nodes.
1423 * This function can only be called from lys_node_dup() with uses
1424 * being the node duplicated, so we must have a case of grouping
1425 * with a uses with augments. The augmented nodes have already been
1426 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001427 * (it was set to their actual data parent, not an augment), and
1428 * the new augment does not have child pointer to its augment nodes,
1429 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001430 */
1431 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001432 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001433 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001434 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001435 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001436 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001437 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001438 LY_TREE_FOR(old[i].child, old_child) {
1439 /* all augment nodes were connected as siblings, there can be no more after this */
1440 if (old_child->parent != (struct lys_node *)&old[i]) {
1441 break;
1442 }
1443
Radek Krejci749190d2016-02-18 16:26:25 +01001444 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001445
1446 new_child->parent = (struct lys_node *)&new[i];
1447 new_child = new_child->next;
1448 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001449 }
Radek Krejci106efc02015-06-10 14:36:27 +02001450
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001451 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001452}
1453
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001454static const char **
1455lys_dflt_dup(struct ly_ctx *ctx, const char **old, int size)
1456{
1457 int i;
1458 const char **result;
1459
1460 if (!size) {
1461 return NULL;
1462 }
1463
1464 result = calloc(size, sizeof *result);
1465 if (!result) {
1466 LOGMEM;
1467 return NULL;
1468 }
1469
1470 for (i = 0; i < size; i++) {
1471 result[i] = lydict_insert(ctx, old[i], 0);
1472 }
1473 return result;
1474}
1475
Radek Krejci76512572015-08-04 09:47:08 +02001476static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001477lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001478{
Radek Krejci76512572015-08-04 09:47:08 +02001479 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001480 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001482 if (!size) {
1483 return NULL;
1484 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001485
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001486 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001487 if (!result) {
1488 LOGMEM;
1489 return NULL;
1490 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001491 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001492 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001493 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1494 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001495 result[i].flags = old[i].flags;
1496 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001498 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001499 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001500
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001501 result[i].dflt_size = old[i].dflt_size;
1502 result[i].dflt = lys_dflt_dup(mod->ctx, old[i].dflt, old[i].dflt_size);
1503
1504 if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001505 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001506 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001507 result[i].mod.list = old[i].mod.list;
1508 }
1509 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001510
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001511 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001512}
1513
Radek Krejci1d82ef62015-08-07 14:44:40 +02001514static void
1515lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001516{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001517 assert(ctx);
1518 if (!ident) {
1519 return;
1520 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001521
Radek Krejci018f1f52016-08-03 16:01:20 +02001522 free(ident->base);
Radek Krejci1b61d0e2016-04-15 13:55:44 +02001523 free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001524 lydict_remove(ctx, ident->name);
1525 lydict_remove(ctx, ident->dsc);
1526 lydict_remove(ctx, ident->ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001527 lys_iffeature_free(ident->iffeature, ident->iffeature_size);
Radek Krejci6793db02015-05-22 17:49:54 +02001528
1529}
1530
Radek Krejci1d82ef62015-08-07 14:44:40 +02001531static void
1532lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001533{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001534 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001535
Radek Krejcid12f57b2015-08-06 10:43:39 +02001536 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001537 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001538 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001539 }
1540 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001541}
1542
Radek Krejci1d82ef62015-08-07 14:44:40 +02001543static void
Michal Vasko44fb6382016-06-29 11:12:27 +02001544lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02001545{
1546 int i;
1547
1548 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1549 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001550 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001551 }
1552 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02001553
1554 for (i = 0; i < io->must_size; i++) {
1555 lys_restr_free(ctx, &io->must[i]);
1556 }
1557 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001558}
1559
Radek Krejci1d82ef62015-08-07 14:44:40 +02001560static void
Pavol Vican7cff97e2016-08-09 14:56:08 +02001561lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif)
1562{
1563 int i;
1564
1565 for (i = 0; i < notif->must_size; i++) {
1566 lys_restr_free(ctx, &notif->must[i]);
1567 }
1568 free(notif->must);
1569
1570 for (i = 0; i < notif->tpdf_size; i++) {
1571 lys_tpdf_free(ctx, &notif->tpdf[i]);
1572 }
1573 free(notif->tpdf);
1574}
1575static void
Radek Krejcibf2abff2016-08-23 15:51:52 +02001576lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001577{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001578 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001580 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001581 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001582 }
1583 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001584
Radek Krejci1d82ef62015-08-07 14:44:40 +02001585 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001586}
1587
Radek Krejci1d82ef62015-08-07 14:44:40 +02001588static void
1589lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001590{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001591 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001592
Radek Krejci46c4cd72016-01-21 15:13:52 +01001593 if (leaf->child) {
1594 /* leafref backlinks */
1595 ly_set_free((struct ly_set *)leaf->child);
1596 }
1597
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001598 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001599 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001600 }
1601 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001602
Radek Krejci1d82ef62015-08-07 14:44:40 +02001603 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001604
Radek Krejci1d82ef62015-08-07 14:44:40 +02001605 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001606 lydict_remove(ctx, leaf->units);
1607 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001608}
1609
Radek Krejci1d82ef62015-08-07 14:44:40 +02001610static void
1611lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001612{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001613 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001614
Radek Krejci46c4cd72016-01-21 15:13:52 +01001615 if (llist->child) {
1616 /* leafref backlinks */
1617 ly_set_free((struct ly_set *)llist->child);
1618 }
1619
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001620 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001621 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001622 }
1623 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001624
Pavol Vican38321d02016-08-16 14:56:02 +02001625 for (i = 0; i < llist->dflt_size; i++) {
1626 lydict_remove(ctx, llist->dflt[i]);
1627 }
1628 free(llist->dflt);
1629
Radek Krejci1d82ef62015-08-07 14:44:40 +02001630 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001631
Radek Krejci1d82ef62015-08-07 14:44:40 +02001632 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001633 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001634}
1635
Radek Krejci1d82ef62015-08-07 14:44:40 +02001636static void
1637lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001638{
Radek Krejci581ce772015-11-10 17:22:40 +01001639 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001640
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001641 /* handle only specific parts for LY_NODE_LIST */
1642 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001643 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001644 }
1645 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001646
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001647 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001648 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001649 }
1650 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001651
Radek Krejci1d82ef62015-08-07 14:44:40 +02001652 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001654 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02001655 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001656 lydict_remove(ctx, list->unique[i].expr[j]);
1657 }
1658 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001659 }
1660 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001661
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001662 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001663}
1664
Radek Krejci1d82ef62015-08-07 14:44:40 +02001665static void
1666lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001667{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001668 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001669
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 /* handle only specific parts for LY_NODE_CONTAINER */
1671 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001672
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001673 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001674 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001675 }
1676 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001677
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001678 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001679 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001680 }
1681 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001682
Radek Krejci1d82ef62015-08-07 14:44:40 +02001683 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001684}
1685
Radek Krejci1d82ef62015-08-07 14:44:40 +02001686static void
1687lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001688{
1689 lydict_remove(ctx, f->name);
1690 lydict_remove(ctx, f->dsc);
1691 lydict_remove(ctx, f->ref);
Radek Krejci9ff0a922016-07-14 13:08:05 +02001692 lys_iffeature_free(f->iffeature, f->iffeature_size);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001693}
1694
Radek Krejci1d82ef62015-08-07 14:44:40 +02001695static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001696lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001697{
Radek Krejci581ce772015-11-10 17:22:40 +01001698 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001699 struct ly_ctx *ctx;
1700 struct lys_node *next, *elem;
1701
1702 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001703
1704 lydict_remove(ctx, dev->target_name);
1705 lydict_remove(ctx, dev->dsc);
1706 lydict_remove(ctx, dev->ref);
1707
Pavol Vican64d0b762016-08-25 10:44:59 +02001708 if (!dev->deviate) {
1709 return ;
1710 }
1711
Michal Vaskoff006c12016-02-17 11:15:19 +01001712 /* the module was freed, but we only need the context from orig_node, use ours */
1713 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1714 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1715 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1716 elem->module = module;
1717
1718 LY_TREE_DFS_END(dev->orig_node, next, elem);
1719 }
1720 lys_node_free(dev->orig_node, NULL, 0);
1721 } else {
1722 /* it's just a shallow copy, freeing one node */
1723 dev->orig_node->module = module;
1724 lys_node_free(dev->orig_node, NULL, 1);
1725 }
1726
Radek Krejcieb00f512015-07-01 16:44:58 +02001727 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02001728 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02001729 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02001730 }
1731 free(dev->deviate[i].dflt);
1732
Radek Krejcieb00f512015-07-01 16:44:58 +02001733 lydict_remove(ctx, dev->deviate[i].units);
1734
1735 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1736 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001737 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001738 }
1739 free(dev->deviate[i].must);
1740
1741 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001742 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1743 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1744 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01001745 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001746 }
1747 free(dev->deviate[i].unique);
1748 }
1749 }
1750 free(dev->deviate);
1751}
1752
Radek Krejci1d82ef62015-08-07 14:44:40 +02001753static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001754lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie1fa8582015-06-08 09:46:45 +02001755{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001756 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001757
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001758 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001759 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001760 lydict_remove(ctx, uses->refine[i].dsc);
1761 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001762
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001763 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001764 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001765 }
1766 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001767
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001768 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02001769 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001770 }
1771 free(uses->refine[i].dflt);
1772
1773 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001774 lydict_remove(ctx, uses->refine[i].mod.presence);
1775 }
1776 }
1777 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001779 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001780 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001781 }
1782 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001783
Radek Krejci1d82ef62015-08-07 14:44:40 +02001784 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001785}
1786
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001787void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001788lys_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 +02001789{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001790 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001791 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001793 if (!node) {
1794 return;
1795 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001796
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001797 assert(node->module);
1798 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001800 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001801
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001802 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01001803 if (node->priv && private_destructor) {
1804 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001805 }
1806
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001807 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02001808 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001809 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02001810 lys_iffeature_free(node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001811 lydict_remove(ctx, node->dsc);
1812 lydict_remove(ctx, node->ref);
1813 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001814
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001815 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001816 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001817 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001818 }
1819 }
1820
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001821 /* specific part */
1822 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001823 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001824 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001825 break;
Radek Krejci76512572015-08-04 09:47:08 +02001826 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001827 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001828 break;
Radek Krejci76512572015-08-04 09:47:08 +02001829 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001830 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001831 break;
Radek Krejci76512572015-08-04 09:47:08 +02001832 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001833 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001834 break;
Radek Krejci76512572015-08-04 09:47:08 +02001835 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001836 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001837 break;
Radek Krejci76512572015-08-04 09:47:08 +02001838 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001839 case LYS_ANYDATA:
1840 lys_anydata_free(ctx, (struct lys_node_anydata *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001841 break;
Radek Krejci76512572015-08-04 09:47:08 +02001842 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001843 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001844 break;
Radek Krejci76512572015-08-04 09:47:08 +02001845 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001846 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001847 break;
Radek Krejci76512572015-08-04 09:47:08 +02001848 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001849 /* do nothing */
1850 break;
Radek Krejci76512572015-08-04 09:47:08 +02001851 case LYS_GROUPING:
1852 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02001853 case LYS_ACTION:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001854 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001855 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02001856 case LYS_NOTIF:
1857 lys_notif_free(ctx, (struct lys_node_notif *)node);
1858 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001859 case LYS_INPUT:
1860 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02001861 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001862 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001863 case LYS_UNKNOWN:
1864 LOGINT;
1865 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001866 }
Radek Krejci5a065542015-05-22 15:02:07 +02001867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001868 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001869 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001870 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001871}
1872
Michal Vasko1e62a092015-12-01 12:27:20 +01001873const struct lys_module *
1874lys_get_import_module(const struct lys_module *module, const char *prefix, int pref_len, const char *name, int name_len)
Michal Vasko8ce24d72015-10-21 11:27:26 +02001875{
Radek Krejcic071c542016-01-27 14:57:51 +01001876 const struct lys_module *main_module;
Michal Vasko89563fc2016-07-28 16:19:35 +02001877 char *str;
Michal Vasko3edeaf72016-02-11 13:17:43 +01001878 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02001879
Michal Vaskoa7789a82016-02-11 15:42:55 +01001880 assert(!prefix || !name);
1881
Michal Vaskob6729c62015-10-21 12:09:47 +02001882 if (prefix && !pref_len) {
1883 pref_len = strlen(prefix);
1884 }
1885 if (name && !name_len) {
1886 name_len = strlen(name);
1887 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001888
Radek Krejcic4283442016-04-22 09:19:27 +02001889 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01001890
1891 /* module own prefix, submodule own prefix, (sub)module own name */
1892 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
1893 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01001894 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01001895 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02001896 }
1897
Michal Vasko89563fc2016-07-28 16:19:35 +02001898 /* standard import */
Michal Vasko8ce24d72015-10-21 11:27:26 +02001899 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01001900 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
1901 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001902 return module->imp[i].module;
1903 }
1904 }
1905
Michal Vasko89563fc2016-07-28 16:19:35 +02001906 /* module required by a foreign grouping, deviation, or submodule */
1907 if (name) {
1908 str = strndup(name, name_len);
1909 if (!str) {
1910 LOGMEM;
1911 return NULL;
1912 }
1913 main_module = ly_ctx_get_module(module->ctx, str, NULL);
1914 free(str);
1915 return main_module;
1916 }
1917
Michal Vasko8ce24d72015-10-21 11:27:26 +02001918 return NULL;
1919}
1920
Michal Vasko13b15832015-08-19 11:04:48 +02001921/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001922static void
Michal Vaskob746fff2016-02-11 11:37:50 +01001923module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001924{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001925 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01001926 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001927 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001929 assert(module->ctx);
1930 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001931
Michal Vaskob746fff2016-02-11 11:37:50 +01001932 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01001933 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02001934 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02001935 lydict_remove(ctx, module->imp[i].dsc);
1936 lydict_remove(ctx, module->imp[i].ref);
Radek Krejci225376f2016-02-16 17:36:22 +01001937 }
Radek Krejcidce51452015-06-16 15:20:08 +02001938 free(module->imp);
1939
Radek Krejcic071c542016-01-27 14:57:51 +01001940 /* submodules don't have data tree, the data nodes
1941 * are placed in the main module altogether */
1942 if (!module->type) {
1943 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001944 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001945 }
Radek Krejci21181962015-06-30 14:11:00 +02001946 }
Radek Krejci5a065542015-05-22 15:02:07 +02001947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001948 lydict_remove(ctx, module->dsc);
1949 lydict_remove(ctx, module->ref);
1950 lydict_remove(ctx, module->org);
1951 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01001952 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001953
Radek Krejcieb00f512015-07-01 16:44:58 +02001954 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001955 for (i = 0; i < module->rev_size; i++) {
1956 lydict_remove(ctx, module->rev[i].dsc);
1957 lydict_remove(ctx, module->rev[i].ref);
1958 }
1959 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001960
Radek Krejcieb00f512015-07-01 16:44:58 +02001961 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001962 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001963 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001964 }
1965 module->ident_size = 0;
1966 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001967
Radek Krejcieb00f512015-07-01 16:44:58 +02001968 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001969 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001970 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001971 }
1972 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001973
Radek Krejcieb00f512015-07-01 16:44:58 +02001974 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001975 for (i = 0; i < module->inc_size; i++) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02001976 lydict_remove(ctx, module->inc[i].dsc);
1977 lydict_remove(ctx, module->inc[i].ref);
Radek Krejcic071c542016-01-27 14:57:51 +01001978 /* complete submodule free is done only from main module since
1979 * submodules propagate their includes to the main module */
1980 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01001981 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01001982 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001983 }
1984 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001985
Radek Krejcieb00f512015-07-01 16:44:58 +02001986 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001987 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001988 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02001989 }
1990 free(module->augment);
1991
Radek Krejcieb00f512015-07-01 16:44:58 +02001992 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001993 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001994 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001995 }
1996 free(module->features);
1997
Radek Krejcieb00f512015-07-01 16:44:58 +02001998 /* deviations */
1999 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002000 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002001 }
2002 free(module->deviation);
2003
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002004 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002005 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002006}
2007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002008void
Michal Vaskob746fff2016-02-11 11:37:50 +01002009lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002010{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002011 if (!submodule) {
2012 return;
2013 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002014
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002015 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002016 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002019
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002020 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002021}
2022
Radek Krejci3a5501d2016-07-18 22:03:34 +02002023static int
2024ingrouping(const struct lys_node *node)
2025{
2026 const struct lys_node *iter = node;
2027 assert(node);
2028
2029 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2030 if (!iter) {
2031 return 0;
2032 } else {
2033 return 1;
2034 }
2035}
2036
Radek Krejci76512572015-08-04 09:47:08 +02002037struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002038lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node, uint8_t flags,
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002039 uint8_t nacm, struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002040{
Radek Krejcic071c542016-01-27 14:57:51 +01002041 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002042 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002043 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002044 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002045 struct unres_list_uniq *unique_info;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002046
Michal Vaskoc07187d2015-08-13 15:20:57 +02002047 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002048 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002049 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002050 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002051 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002052 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002053 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002054 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002055 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002056 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002057 struct lys_node_anydata *any = NULL;
2058 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002059 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002060 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002061 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002062 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002063 struct lys_node_rpc_action *rpc = NULL;
2064 struct lys_node_rpc_action *rpc_orig = (struct lys_node_rpc_action *)node;
2065 struct lys_node_inout *io = NULL;
2066 struct lys_node_inout *io_orig = (struct lys_node_inout *)node;
2067 struct lys_node_rpc_action *ntf = NULL;
2068 struct lys_node_rpc_action *ntf_orig = (struct lys_node_rpc_action *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002069 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002070 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002071
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002072 /* we cannot just duplicate memory since the strings are stored in
2073 * dictionary and we need to update dictionary counters.
2074 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002075
Radek Krejci1d82ef62015-08-07 14:44:40 +02002076 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002077 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002078 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002079 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002080 break;
2081
Radek Krejci76512572015-08-04 09:47:08 +02002082 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002083 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002084 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002085 break;
2086
Radek Krejci76512572015-08-04 09:47:08 +02002087 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002088 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002089 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002090 break;
2091
Radek Krejci76512572015-08-04 09:47:08 +02002092 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002094 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002095 break;
2096
Radek Krejci76512572015-08-04 09:47:08 +02002097 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002099 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002100 break;
2101
Radek Krejci76512572015-08-04 09:47:08 +02002102 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002103 case LYS_ANYDATA:
2104 any = calloc(1, sizeof *any);
2105 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002106 break;
2107
Radek Krejci76512572015-08-04 09:47:08 +02002108 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002109 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002110 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 break;
2112
Radek Krejci76512572015-08-04 09:47:08 +02002113 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002115 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 break;
2117
Radek Krejci76512572015-08-04 09:47:08 +02002118 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002119 grp = calloc(1, sizeof *grp);
2120 retval = (struct lys_node *)grp;
2121 break;
2122
Radek Krejci76512572015-08-04 09:47:08 +02002123 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002124 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002125 rpc = calloc(1, sizeof *rpc);
2126 retval = (struct lys_node *)rpc;
2127 break;
2128
Radek Krejci76512572015-08-04 09:47:08 +02002129 case LYS_INPUT:
2130 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002131 io = calloc(1, sizeof *io);
2132 retval = (struct lys_node *)io;
2133 break;
2134
Radek Krejci76512572015-08-04 09:47:08 +02002135 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002136 ntf = calloc(1, sizeof *ntf);
2137 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002138 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002141 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002142 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 }
Radek Krejcib388c152015-06-04 17:03:03 +02002144
Michal Vasko253035f2015-12-17 16:58:13 +01002145 if (!retval) {
2146 LOGMEM;
2147 return NULL;
2148 }
2149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 /*
2151 * duplicate generic part of the structure
2152 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002153 retval->name = lydict_insert(ctx, node->name, 0);
2154 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2155 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002156 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002157 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002158 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002160 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002161 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002162
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002163 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002164 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002165
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002166 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002167
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002168 retval->iffeature_size = node->iffeature_size;
2169 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2170 if (!retval->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002171 LOGMEM;
2172 goto error;
2173 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002174
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002175 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002176 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002177 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2178 if (size1) {
2179 /* there is something to duplicate */
2180
2181 /* duplicate compiled expression */
2182 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2183 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2184 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2185
2186 /* list of feature pointer must be updated to point to the resulting tree */
2187 retval->iffeature[i].features = malloc(size2 * sizeof *retval->iffeature[i].features);
2188 for (j = 0; (unsigned int)j < size2; j++) {
2189 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2190 &retval->iffeature[i].features[j]);
2191 if (rc == EXIT_SUCCESS) {
2192 /* feature is not resolved, duplicate the expression string */
2193 retval->iffeature[i].features[j] = (void *)strdup((char *)node->iffeature[i].features[j]);
2194 } else if (rc == EXIT_FAILURE) {
2195 /* feature is resolved in origin, so copy it
2196 * - duplication is used for instantiating groupings
2197 * and if-feature inside grouping is supposed to be
2198 * resolved inside the original grouping, so we want
2199 * to keep pointers to features from the grouping
2200 * context */
2201 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2202 } else if (rc == -1) {
2203 goto error;
2204 }
2205 }
2206 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002208
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002209 /* connect it to the parent */
2210 if (lys_node_addchild(parent, retval->module, retval)) {
2211 goto error;
2212 }
Radek Krejcidce51452015-06-16 15:20:08 +02002213
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002214 /* go recursively */
2215 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2216 LY_TREE_FOR(node->child, child) {
2217 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres, 0)) {
2218 goto error;
2219 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 }
2221 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002222 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002223 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002224 }
2225
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002226 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 * duplicate specific part of the structure
2228 */
2229 switch (node->nodetype) {
2230 case LYS_CONTAINER:
2231 if (cont_orig->when) {
2232 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002233 }
2234 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002235
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002236 cont->must_size = cont_orig->must_size;
2237 cont->tpdf_size = cont_orig->tpdf_size;
2238
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002239 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskodcf98e62016-05-05 17:53:53 +02002240 cont->tpdf = lys_tpdf_dup(module, lys_parent(node), cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002241 break;
2242
2243 case LYS_CHOICE:
2244 if (choice_orig->when) {
2245 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 }
2247
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002248 if (!shallow) {
2249 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002250 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
2251 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
2252 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002253 if (rc) {
2254 if (rc == EXIT_FAILURE) {
2255 LOGINT;
2256 }
2257 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002258 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002259 } else {
2260 /* useless to check return value, we don't know whether
2261 * there really wasn't any default defined or it just hasn't
2262 * been resolved, we just hope for the best :)
2263 */
2264 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002265 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002266 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002267 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002268 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 break;
2270
2271 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002272 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002273 goto error;
2274 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002275 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2276
2277 if (leaf_orig->dflt) {
2278 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci48464ed2016-03-17 15:44:09 +01002279 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002280 goto error;
2281 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 }
2283
2284 leaf->must_size = leaf_orig->must_size;
2285 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002286
2287 if (leaf_orig->when) {
2288 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002289 }
2290 break;
2291
2292 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002293 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002294 goto error;
2295 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002296 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2297
2298 llist->min = llist_orig->min;
2299 llist->max = llist_orig->max;
2300
2301 llist->must_size = llist_orig->must_size;
2302 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002303
2304 if (llist_orig->when) {
2305 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002306 }
2307 break;
2308
2309 case LYS_LIST:
2310 list->min = list_orig->min;
2311 list->max = list_orig->max;
2312
2313 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002315
Radek Krejci581ce772015-11-10 17:22:40 +01002316 list->tpdf_size = list_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002317 list->tpdf = lys_tpdf_dup(module, lys_parent(node), list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002318
Radek Krejci581ce772015-11-10 17:22:40 +01002319 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002320 if (list->keys_size) {
2321 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002322 if (!list->keys) {
2323 LOGMEM;
2324 goto error;
2325 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002326
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002327 if (!shallow) {
2328 /* we managed to resolve it before, resolve it again manually */
2329 if (list_orig->keys[0]) {
2330 for (i = 0; i < list->keys_size; ++i) {
2331 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2332 (const struct lys_node **)&list->keys[i]);
2333 if (rc) {
2334 if (rc == EXIT_FAILURE) {
2335 LOGINT;
2336 }
2337 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002338 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002339 }
2340 /* it was not resolved yet, add unres copy */
2341 } else {
2342 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2343 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002344 goto error;
2345 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002346 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002347 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002348 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002349 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002350 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351
Radek Krejci581ce772015-11-10 17:22:40 +01002352 list->unique_size = list_orig->unique_size;
2353 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002354 if (!list->unique) {
2355 LOGMEM;
2356 goto error;
2357 }
Radek Krejci581ce772015-11-10 17:22:40 +01002358 for (i = 0; i < list->unique_size; ++i) {
2359 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2360 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002361 if (!list->unique[i].expr) {
2362 LOGMEM;
2363 goto error;
2364 }
Radek Krejci581ce772015-11-10 17:22:40 +01002365 for (j = 0; j < list->unique[i].expr_size; j++) {
2366 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2367
2368 /* if it stays in unres list, duplicate it also there */
Radek Krejcid09d1a52016-08-11 14:05:45 +02002369 unique_info = malloc(sizeof *unique_info);
2370 unique_info->list = (struct lys_node *)list;
2371 unique_info->expr = list->unique[i].expr[j];
2372 unique_info->trg_type = &list->unique[i].trg_type;
2373 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 }
2375 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002376
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002377 if (list_orig->when) {
2378 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002379 }
Radek Krejcidce51452015-06-16 15:20:08 +02002380 break;
2381
2382 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002383 case LYS_ANYDATA:
2384 any->must_size = any_orig->must_size;
2385 any->must = lys_restr_dup(ctx, any_orig->must, any->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002386
Radek Krejcibf2abff2016-08-23 15:51:52 +02002387 if (any_orig->when) {
2388 any->when = lys_when_dup(ctx, any_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002389 }
2390 break;
2391
2392 case LYS_USES:
2393 uses->grp = uses_orig->grp;
2394
2395 if (uses_orig->when) {
2396 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002397 }
2398
2399 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002400 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002401 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002402 if (!shallow) {
2403 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskocda51712016-05-19 15:22:11 +02002404 if (!uses->grp || uses->grp->nacm) {
2405 assert(!uses->child);
Radek Krejci48464ed2016-03-17 15:44:09 +01002406 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002407 goto error;
2408 }
Michal Vasko49168a22015-08-17 16:35:41 +02002409 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002410 } else {
2411 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002412 }
2413 break;
2414
Radek Krejcidce51452015-06-16 15:20:08 +02002415 case LYS_CASE:
2416 if (cs_orig->when) {
2417 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002418 }
2419 break;
2420
2421 case LYS_GROUPING:
2422 grp->tpdf_size = grp_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002423 grp->tpdf = lys_tpdf_dup(module, lys_parent(node), grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002424 break;
2425
2426 case LYS_RPC:
2427 rpc->tpdf_size = rpc_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002428 rpc->tpdf = lys_tpdf_dup(module, lys_parent(node), rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002429 break;
2430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002431 case LYS_INPUT:
2432 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002433 io->tpdf_size = io_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002434 io->tpdf = lys_tpdf_dup(module, lys_parent(node), io_orig->tpdf, io->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002435 break;
2436
Radek Krejcida04f4a2015-05-21 12:54:09 +02002437 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002438 ntf->tpdf_size = ntf_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002439 ntf->tpdf = lys_tpdf_dup(module, lys_parent(node), ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002440 break;
2441
2442 default:
2443 /* LY_NODE_AUGMENT */
2444 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002445 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002446 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002447
2448 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002449
2450error:
2451
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002452 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002453 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002454}
2455
Michal Vasko13b15832015-08-19 11:04:48 +02002456void
Michal Vaskoff006c12016-02-17 11:15:19 +01002457lys_node_switch(struct lys_node *dst, struct lys_node *src)
2458{
2459 struct lys_node *child;
2460
Michal Vaskob42b6972016-06-06 14:21:30 +02002461 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01002462
2463 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02002464 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002465 dst->prev->next = src;
2466 }
2467
2468 /* sibling prev */
2469 if (dst->next) {
2470 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02002471 } else {
2472 for (child = dst->prev; child->prev->next; child = child->prev);
2473 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01002474 }
2475
2476 /* next */
2477 src->next = dst->next;
2478 dst->next = NULL;
2479
2480 /* prev */
2481 if (dst->prev != dst) {
2482 src->prev = dst->prev;
2483 }
2484 dst->prev = dst;
2485
2486 /* parent child */
2487 if (dst->parent && (dst->parent->child == dst)) {
2488 dst->parent->child = src;
2489 }
2490
2491 /* parent */
2492 src->parent = dst->parent;
2493 dst->parent = NULL;
2494
2495 /* child parent */
2496 LY_TREE_FOR(dst->child, child) {
2497 if (child->parent == dst) {
2498 child->parent = src;
2499 }
2500 }
2501
2502 /* child */
2503 src->child = dst->child;
2504 dst->child = NULL;
2505}
2506
2507void
Michal Vasko627975a2016-02-11 11:39:03 +01002508lys_free(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv), int remove_from_ctx)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002509{
2510 struct ly_ctx *ctx;
2511 int i;
2512
2513 if (!module) {
2514 return;
2515 }
2516
2517 /* remove schema from the context */
2518 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002519 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002520 for (i = 0; i < ctx->models.used; i++) {
2521 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002522 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002523 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002524 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 +02002525 ctx->models.list[ctx->models.used] = NULL;
2526 /* we are done */
2527 break;
2528 }
2529 }
2530 }
2531
2532 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002533 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002534
2535 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002536 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002537
2538 free(module);
2539}
Radek Krejci7e97c352015-06-19 16:26:34 +02002540
2541/*
2542 * op: 1 - enable, 0 - disable
2543 */
2544static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002545lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002546{
2547 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002548 int i, j, k;
Radek Krejci7e97c352015-06-19 16:26:34 +02002549
2550 if (!module || !name || !strlen(name)) {
2551 return EXIT_FAILURE;
2552 }
2553
2554 if (!strcmp(name, "*")) {
2555 /* enable all */
2556 all = 1;
2557 }
2558
2559 /* module itself */
2560 for (i = 0; i < module->features_size; i++) {
2561 if (all || !strcmp(module->features[i].name, name)) {
2562 if (op) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002563 /* check referenced features if they are enabled */
2564 for (j = 0; j < module->features[i].iffeature_size; j++) {
Radek Krejci69b8d922016-07-27 13:13:41 +02002565 if (!resolve_iffeature(&module->features[i].iffeature[j])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002566 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2567 module->features[i].name, j + 1);
2568 return EXIT_FAILURE;
2569 }
2570 }
2571
Radek Krejci1574a8d2015-08-03 14:16:52 +02002572 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002573 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002574 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002575 }
2576 if (!all) {
2577 return EXIT_SUCCESS;
2578 }
2579 }
2580 }
2581
2582 /* submodules */
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002583 for (i = 0; i < module->inc_size; i++) {
2584 for (j = 0; j < module->inc[i].submodule->features_size; j++) {
2585 if (all || !strcmp(module->inc[i].submodule->features[j].name, name)) {
Radek Krejci7e97c352015-06-19 16:26:34 +02002586 if (op) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002587 /* check referenced features if they are enabled */
2588 for (k = 0; k < module->inc[i].submodule->features[j].iffeature_size; k++) {
Radek Krejci69b8d922016-07-27 13:13:41 +02002589 if (!resolve_iffeature(&module->inc[i].submodule->features[j].iffeature[k])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002590 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2591 module->inc[i].submodule->features[j].name, k + 1);
2592 return EXIT_FAILURE;
2593 }
2594 }
2595
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002596 module->inc[i].submodule->features[j].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002597 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002598 module->inc[i].submodule->features[j].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002599 }
2600 if (!all) {
2601 return EXIT_SUCCESS;
2602 }
2603 }
2604 }
2605 }
2606
2607 if (all) {
2608 return EXIT_SUCCESS;
2609 } else {
2610 return EXIT_FAILURE;
2611 }
2612}
2613
2614API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002615lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002616{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002617 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002618}
2619
2620API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002621lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002622{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002623 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002624}
2625
2626API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002627lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002628{
2629 int i, j;
2630
2631 if (!module || !feature) {
2632 return -1;
2633 }
2634
2635 /* search for the specified feature */
2636 /* module itself */
2637 for (i = 0; i < module->features_size; i++) {
2638 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002639 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002640 return 1;
2641 } else {
2642 return 0;
2643 }
2644 }
2645 }
2646
2647 /* submodules */
2648 for (j = 0; j < module->inc_size; j++) {
2649 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2650 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002651 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002652 return 1;
2653 } else {
2654 return 0;
2655 }
2656 }
2657 }
2658 }
2659
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002660 /* feature definition not found */
2661 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002662}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002663
Radek Krejci96a10da2015-07-30 11:00:14 +02002664API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002665lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002666{
Radek Krejci96a10da2015-07-30 11:00:14 +02002667 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002668 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002669 unsigned int count;
2670
2671 if (!module) {
2672 return NULL;
2673 }
2674
2675 count = module->features_size;
2676 for (i = 0; i < module->inc_size; i++) {
2677 count += module->inc[i].submodule->features_size;
2678 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002679 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002680 if (!result) {
2681 LOGMEM;
2682 return NULL;
2683 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002684 if (states) {
2685 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002686 if (!(*states)) {
2687 LOGMEM;
2688 free(result);
2689 return NULL;
2690 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002691 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002692 count = 0;
2693
2694 /* module itself */
2695 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002696 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002697 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002698 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002699 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002700 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002701 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002702 }
2703 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002704 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002705 }
2706
2707 /* submodules */
2708 for (j = 0; j < module->inc_size; j++) {
2709 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002710 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002711 if (states) {
2712 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2713 (*states)[count] = 1;
2714 } else {
2715 (*states)[count] = 0;
2716 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002717 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002718 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002719 }
2720 }
2721
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002722 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002723 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002724
2725 return result;
2726}
Michal Vaskobaefb032015-09-24 14:52:10 +02002727
Radek Krejci6910a032016-04-13 10:06:21 +02002728API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002729lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002730{
2731 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2732}
2733
Radek Krejci6910a032016-04-13 10:06:21 +02002734API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02002735lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01002736{
2737 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2738}
2739
Michal Vaskobaefb032015-09-24 14:52:10 +02002740API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002741lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002742{
2743 if (!node || !node->parent) {
2744 return NULL;
2745 }
2746
2747 if (node->parent->nodetype == LYS_AUGMENT) {
2748 return ((struct lys_node_augment *)node->parent)->target;
2749 }
2750
2751 return node->parent;
2752}
Michal Vasko1b229152016-01-13 11:28:38 +01002753
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002754API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002755lys_set_private(const struct lys_node *node, void *priv)
2756{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002757 void *prev;
2758
Michal Vasko1b229152016-01-13 11:28:38 +01002759 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002760 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2761 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002762 }
2763
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002764 prev = node->priv;
2765 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002766
2767 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002768}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002769
Michal Vasko01c6fd22016-05-20 11:43:05 +02002770int
2771lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
2772{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02002773 struct lys_node_leaf *iter = leafref_target;
2774
Michal Vasko48a573d2016-07-01 11:46:02 +02002775 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02002776 LOGINT;
2777 return -1;
2778 }
2779
Pavol Vican93175152016-08-30 15:34:44 +02002780 /* check for config flag */
2781 if ((leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
2782 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leafref,
2783 "The %s is config but refers to a non-config %s.",
2784 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
2785 return -1;
2786 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02002787 /* check for cycles */
2788 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
2789 if ((void *)iter == (void *)leafref) {
2790 /* cycle detected */
2791 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
2792 return -1;
2793 }
2794 iter = iter->type.info.lref.target;
2795 }
2796
2797 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02002798 * leafrefs referencing the leaf(-list) */
Michal Vasko01c6fd22016-05-20 11:43:05 +02002799 if (!leafref_target->child) {
2800 leafref_target->child = (void*)ly_set_new();
2801 if (!leafref_target->child) {
2802 LOGMEM;
2803 return -1;
2804 }
2805 }
Radek Krejci09891a22016-06-10 10:59:22 +02002806 ly_set_add((struct ly_set *)leafref_target->child, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02002807
2808 return 0;
2809}
2810
Michal Vasko8548e082016-07-22 12:00:18 +02002811/* not needed currently */
2812#if 0
2813
Michal Vasko5b3492c2016-07-20 09:37:40 +02002814static const char *
2815lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
2816{
2817 struct lys_module *prev_mod;
2818 uint32_t str_len, mod_len, buf_idx;
2819
Radek Krejcibf2abff2016-08-23 15:51:52 +02002820 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02002821 LOGINT;
2822 return NULL;
2823 }
2824
2825 buf_idx = buf_len - 1;
2826 buf[buf_idx] = '\0';
2827
2828 while (node) {
2829 if (lys_parent(node)) {
2830 prev_mod = lys_node_module(lys_parent(node));
2831 } else {
2832 prev_mod = NULL;
2833 }
2834
Radek Krejcibf2abff2016-08-23 15:51:52 +02002835 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02002836 str_len = strlen(node->name);
2837
2838 if (prev_mod != node->module) {
2839 mod_len = strlen(node->module->name);
2840 } else {
2841 mod_len = 0;
2842 }
2843
2844 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
2845 LOGINT;
2846 return NULL;
2847 }
2848
2849 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
2850
2851 buf[buf_idx] = '/';
2852 if (mod_len) {
2853 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
2854 buf[buf_idx + 1 + mod_len] = ':';
2855 }
2856 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
2857 }
2858
2859 node = lys_parent(node);
2860 }
2861
2862 return buf + buf_idx;
2863}
2864
Michal Vasko8548e082016-07-22 12:00:18 +02002865#endif
2866
2867API struct ly_set *
Michal Vasko508a50d2016-09-07 14:50:33 +02002868lys_xpath_atomize(const struct lys_node *cur_snode, enum lyxp_node_type cur_snode_type, const char *expr, int options)
Michal Vasko5b3492c2016-07-20 09:37:40 +02002869{
Michal Vasko508a50d2016-09-07 14:50:33 +02002870 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02002871 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02002872 uint32_t i;
2873
Michal Vasko508a50d2016-09-07 14:50:33 +02002874 if (!cur_snode || cur_snode->prev->next || !expr) {
Michal Vasko8548e082016-07-22 12:00:18 +02002875 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02002876 }
2877
Michal Vasko508a50d2016-09-07 14:50:33 +02002878 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02002879
2880 if (options & LYXP_MUST) {
2881 options &= ~LYXP_MUST;
2882 options |= LYXP_SNODE_MUST;
2883 } else if (options & LYXP_WHEN) {
2884 options &= ~LYXP_WHEN;
2885 options |= LYXP_SNODE_WHEN;
2886 } else {
2887 options |= LYXP_SNODE;
2888 }
2889
Michal Vasko508a50d2016-09-07 14:50:33 +02002890 if (lyxp_atomize(expr, cur_snode, cur_snode_type, &set, options)) {
2891 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02002892 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02002893 }
2894
Michal Vasko8548e082016-07-22 12:00:18 +02002895 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02002896
Michal Vasko508a50d2016-09-07 14:50:33 +02002897 for (i = 0; i < set.used; ++i) {
2898 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02002899 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02002900 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02002901 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02002902 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02002903 return NULL;
2904 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02002905 break;
2906 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02002907 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02002908 break;
2909 }
2910 }
2911
Michal Vasko508a50d2016-09-07 14:50:33 +02002912 free(set.val.snodes);
2913 return ret_set;
2914}
2915
2916API struct ly_set *
2917lys_node_xpath_atomize(const struct lys_node *node, int options)
2918{
2919 const struct lys_node *next, *elem, *parent, *tmp;
2920 struct lyxp_set set;
2921 struct ly_set *ret_set;
2922 uint16_t i;
2923
2924 if (!node) {
2925 return NULL;
2926 }
2927
2928 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
2929 if (!parent) {
2930 /* not in input, output, or notification */
2931 return NULL;
2932 }
2933
2934 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02002935 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002936 return NULL;
2937 }
2938
2939 LY_TREE_DFS_BEGIN(node, next, elem) {
2940 if ((options & LYXP_NO_LOCAL) && !(elem->flags & LYS_XPATH_DEP)) {
2941 /* elem has no dependencies from other subtrees and local nodes get discarded */
2942 goto next_iter;
2943 }
2944
2945 if (lyxp_node_atomize(elem, &set)) {
2946 ly_set_free(ret_set);
2947 free(set.val.snodes);
2948 return NULL;
2949 }
2950
2951 for (i = 0; i < set.used; ++i) {
2952 switch (set.val.snodes[i].type) {
2953 case LYXP_NODE_ELEM:
2954 if (options & LYXP_NO_LOCAL) {
2955 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
2956 if (tmp) {
2957 /* in local subtree, discard */
2958 break;
2959 }
2960 }
2961 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
2962 ly_set_free(ret_set);
2963 free(set.val.snodes);
2964 return NULL;
2965 }
2966 break;
2967 default:
2968 /* ignore roots, text and attr should not ever appear */
2969 break;
2970 }
2971 }
2972
2973 free(set.val.snodes);
2974 if (!(options & LYXP_RECURSIVE)) {
2975 break;
2976 }
2977next_iter:
2978 LY_TREE_DFS_END(node, next, elem);
2979 }
2980
Michal Vasko8548e082016-07-22 12:00:18 +02002981 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02002982}
2983
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002984static void
Michal Vasko89563fc2016-07-28 16:19:35 +02002985lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *target_module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002986{
2987 int ret;
2988 char *parent_path;
2989 struct lys_node *target;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002990
Pavol Vican64d0b762016-08-25 10:44:59 +02002991 if (!dev->deviate) {
2992 return ;
2993 }
2994
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002995 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2996 if (dev->orig_node) {
2997 /* removing not-supported deviation ... */
2998 if (strrchr(dev->target_name, '/') != dev->target_name) {
2999 /* ... from a parent */
3000 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
3001
3002 target = NULL;
3003 ret = resolve_augment_schema_nodeid(parent_path, NULL, target_module, (const struct lys_node **)&target);
3004 free(parent_path);
3005 if (ret || !target) {
3006 LOGINT;
3007 return;
3008 }
3009
3010 lys_node_addchild(target, NULL, dev->orig_node);
3011 } else {
3012 /* ... from top-level data */
3013 lys_node_addchild(NULL, (struct lys_module *)target_module, dev->orig_node);
3014 }
3015
3016 dev->orig_node = NULL;
3017 } else {
3018 /* adding not-supported deviation */
3019 target = NULL;
3020 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
3021 if (ret || !target) {
3022 LOGINT;
3023 return;
3024 }
3025
3026 lys_node_unlink(target);
3027 dev->orig_node = target;
3028 }
3029 } else {
3030 target = NULL;
3031 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
3032 if (ret || !target) {
3033 LOGINT;
3034 return;
3035 }
3036
3037 lys_node_switch(target, dev->orig_node);
3038 dev->orig_node = target;
3039 }
3040}
3041
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003042/* temporarily removes or applies deviations, updates module deviation flag accordingly */
3043void
3044lys_switch_deviations(struct lys_module *module)
3045{
Michal Vasko89563fc2016-07-28 16:19:35 +02003046 uint32_t i = 0, j;
3047 const struct lys_module *mod;
3048 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003049
Michal Vasko89563fc2016-07-28 16:19:35 +02003050 if (module->deviated) {
3051 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3052 if (mod == module) {
3053 continue;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003054 }
3055
Michal Vasko89563fc2016-07-28 16:19:35 +02003056 for (j = 0; j < mod->deviation_size; ++j) {
3057 ptr = strstr(mod->deviation[j].target_name, module->name);
3058 if (ptr && ptr[strlen(module->name)] == ':') {
3059 lys_switch_deviation(&mod->deviation[j], module);
3060 }
3061 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003062 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003063
Michal Vasko89563fc2016-07-28 16:19:35 +02003064 if (module->deviated == 2) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003065 module->deviated = 1;
Michal Vasko89563fc2016-07-28 16:19:35 +02003066 } else {
3067 module->deviated = 2;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003068 }
3069 }
3070}
3071
3072/* not needed currently, but tested and working */
3073#if 0
3074
3075void
3076lys_sub_module_apply_devs_augs(struct lys_module *module)
3077{
3078 int i;
3079 struct lys_node_augment *aug;
3080 struct lys_node *last;
3081
3082 /* re-apply deviations */
3083 for (i = 0; i < module->deviation_size; ++i) {
3084 lys_switch_deviation(&module->deviation[i], module);
3085 assert(module->deviation[i].orig_node);
Michal Vasko89563fc2016-07-28 16:19:35 +02003086 lys_node_module(module->deviation[i].orig_node)->deviated = 1;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003087 }
3088
3089 /* re-apply augments */
3090 for (i = 0; i < module->augment_size; ++i) {
3091 aug = &module->augment[i];
3092 assert(aug->target);
3093
3094 /* reconnect augmenting data into the target - add them to the target child list */
3095 if (aug->target->child) {
3096 last = aug->target->child->prev;
3097 last->next = aug->child;
3098 aug->target->child->prev = aug->child->prev;
3099 aug->child->prev = last;
3100 } else {
3101 aug->target->child = aug->child;
3102 }
3103 }
3104}
3105
3106#endif
3107
3108void
3109lys_sub_module_remove_devs_augs(struct lys_module *module)
3110{
Michal Vasko89563fc2016-07-28 16:19:35 +02003111 uint32_t i = 0, j;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003112 struct lys_node *last, *elem;
Michal Vasko89563fc2016-07-28 16:19:35 +02003113 const struct lys_module *mod;
3114 struct lys_module *target_mod;
3115 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003116
3117 /* remove applied deviations */
3118 for (i = 0; i < module->deviation_size; ++i) {
Pavol Vican64d0b762016-08-25 10:44:59 +02003119 if (module->deviation[i].orig_node) {
3120 target_mod = lys_node_module(module->deviation[i].orig_node);
3121 } else {
3122 target_mod = (struct lys_module *)lys_get_import_module(module, NULL, 0, module->deviation[i].target_name + 1,
3123 strcspn(module->deviation[i].target_name, ":") - 1);
3124 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003125 lys_switch_deviation(&module->deviation[i], module);
Michal Vasko89563fc2016-07-28 16:19:35 +02003126 assert(target_mod->deviated == 1);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003127
Michal Vasko89563fc2016-07-28 16:19:35 +02003128 /* clear the deviation flag if possible */
3129 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3130 if ((mod == module) || (mod == target_mod)) {
3131 continue;
3132 }
3133
3134 for (j = 0; j < mod->deviation_size; ++j) {
3135 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
3136 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
3137 /* some other module deviation targets the inspected module, flag remains */
3138 break;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003139 }
3140 }
Michal Vasko89563fc2016-07-28 16:19:35 +02003141
3142 if (j < mod->deviation_size) {
3143 break;
3144 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003145 }
Michal Vasko89563fc2016-07-28 16:19:35 +02003146
3147 if (!mod) {
3148 target_mod->deviated = 0;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003149 }
3150 }
3151
3152 /* remove applied augments */
3153 for (i = 0; i < module->augment_size; ++i) {
Radek Krejcidbc15262016-06-16 14:58:29 +02003154 if (!module->augment[i].target) {
3155 /* skip not resolved augments */
3156 continue;
3157 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003158
3159 elem = module->augment[i].child;
3160 if (elem) {
3161 LY_TREE_FOR(elem, last) {
3162 if (!last->next || (last->next->parent != (struct lys_node *)&module->augment[i])) {
3163 break;
3164 }
3165 }
3166 /* elem is first augment child, last is the last child */
3167
3168 /* parent child ptr */
3169 if (module->augment[i].target->child == elem) {
3170 module->augment[i].target->child = last->next;
3171 }
3172
3173 /* parent child next ptr */
3174 if (elem->prev->next) {
3175 elem->prev->next = last->next;
3176 }
3177
3178 /* parent child prev ptr */
3179 if (last->next) {
3180 last->next->prev = elem->prev;
3181 } else if (module->augment[i].target->child) {
3182 module->augment[i].target->child->prev = elem->prev;
3183 }
3184
3185 /* update augment children themselves */
3186 elem->prev = last;
3187 last->next = NULL;
3188 }
Michal Vaskob8f71322016-05-03 11:39:56 +02003189
3190 /* needs to be NULL for lys_augment_free() to free the children */
3191 module->augment[i].target = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003192 }
3193}
3194
Michal Vasko26055752016-05-03 11:36:31 +02003195int
3196lys_module_set_implement(struct lys_module *module)
3197{
3198 struct ly_ctx *ctx;
3199 int i;
3200
3201 if (module->implemented) {
3202 return EXIT_SUCCESS;
3203 }
3204
3205 ctx = module->ctx;
3206
3207 for (i = 0; i < ctx->models.used; ++i) {
3208 if (module == ctx->models.list[i]) {
3209 continue;
3210 }
3211
3212 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
3213 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
3214 return EXIT_FAILURE;
3215 }
3216 }
3217
3218 module->implemented = 1;
3219 return EXIT_SUCCESS;
3220}
3221
3222int
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003223lys_sub_module_set_dev_aug_target_implement(struct lys_module *module)
3224{
3225 int i;
3226 struct lys_module *trg_mod;
3227
3228 for (i = 0; i < module->deviation_size; ++i) {
3229 assert(module->deviation[i].orig_node);
3230 trg_mod = lys_node_module(module->deviation[i].orig_node);
Michal Vasko26055752016-05-03 11:36:31 +02003231 if (lys_module_set_implement(trg_mod)) {
3232 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003233 }
3234 }
3235
3236 for (i = 0; i < module->augment_size; ++i) {
3237 assert(module->augment[i].target);
3238 trg_mod = lys_node_module(module->augment[i].target);
Michal Vasko26055752016-05-03 11:36:31 +02003239 if (lys_module_set_implement(trg_mod)) {
3240 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003241 }
3242 }
Michal Vasko26055752016-05-03 11:36:31 +02003243
3244 return EXIT_SUCCESS;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003245}
3246
3247void
3248lys_submodule_module_data_free(struct lys_submodule *submodule)
3249{
3250 struct lys_node *next, *elem;
3251
3252 /* remove parsed data */
3253 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
3254 if (elem->module == (struct lys_module *)submodule) {
3255 lys_node_free(elem, NULL, 0);
3256 }
3257 }
3258}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02003259
3260int
3261lys_is_key(struct lys_node_list *list, struct lys_node_leaf *leaf)
3262{
3263 uint8_t i;
3264
3265 for (i = 0; i < list->keys_size; i++) {
3266 if (list->keys[i] == leaf) {
3267 return i + 1;
3268 }
3269 }
3270
3271 return 0;
3272}