blob: 3ea561304618ac359ca37f885e55e34ba95bef72 [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
Radek Krejci27fe55e2016-09-13 17:13:35 +020049 if (!node) {
50 return NULL;
51 }
52
Radek Krejci48061fb2015-08-05 15:41:07 +020053check:
54 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
55 /* input/output does not have if-feature, so skip them */
56
57 /* check local if-features */
Michal Vaskoc5c26b02016-06-29 11:10:29 +020058 for (i = 0; i < node->iffeature_size; i++) {
Radek Krejci69b8d922016-07-27 13:13:41 +020059 if (!resolve_iffeature(&node->iffeature[i])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +020060 return node;
Radek Krejci48061fb2015-08-05 15:41:07 +020061 }
62 }
63 }
64
65 if (!recursive) {
66 return NULL;
67 }
68
69 /* go through parents */
70 if (node->nodetype == LYS_AUGMENT) {
71 /* go to parent actually means go to the target node */
72 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020073 } else if (node->parent) {
74 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020075 } else {
76 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020077 }
78
Radek Krejci074bf852015-08-19 14:22:16 +020079 if (recursive == 2) {
80 /* continue only if the node cannot have a data instance */
81 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
82 return NULL;
83 }
84 }
85 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020086}
87
Michal Vasko1dca6882015-10-22 14:29:42 +020088int
Michal Vasko36cbaa42015-12-14 13:15:48 +010089lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
90 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020091{
Radek Krejcic071c542016-01-27 14:57:51 +010092 const struct lys_node *node, *parent = NULL;
93 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010094 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020095
Michal Vasko36cbaa42015-12-14 13:15:48 +010096 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020097 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020098
Michal Vasko36cbaa42015-12-14 13:15:48 +010099 /* fill the lengths in case the caller is so indifferent */
100 if (!mod_name_len) {
101 mod_name_len = strlen(mod_name);
102 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200103 if (!nam_len) {
104 nam_len = strlen(name);
105 }
106
Michal Vasko9e635ac2016-10-17 11:44:09 +0200107 while (siblings && (siblings->nodetype == LYS_USES)) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200108 siblings = siblings->child;
109 }
Michal Vasko9e635ac2016-10-17 11:44:09 +0200110 if (!siblings) {
111 /* unresolved uses */
112 return EXIT_FAILURE;
113 }
114
Michal Vasko680f8b42016-10-17 10:27:37 +0200115 if (siblings->nodetype == LYS_GROUPING) {
116 for (node = siblings; (node->nodetype == LYS_GROUPING) && (node->prev != siblings); node = node->prev);
117 if (node->nodetype == LYS_GROUPING) {
118 /* we went through all the siblings, only groupings there - no valid sibling */
119 return EXIT_FAILURE;
120 }
121 /* update siblings to be valid */
122 siblings = node;
123 }
124
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200125 /* set parent correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100126 parent = lys_parent(siblings);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200127
Michal Vasko680f8b42016-10-17 10:27:37 +0200128 /* go up all uses */
129 while (parent && (parent->nodetype == LYS_USES)) {
130 parent = lys_parent(parent);
Michal Vasko4cf7dba2016-10-14 09:42:01 +0200131 }
132
Radek Krejcic071c542016-01-27 14:57:51 +0100133 if (!parent) {
Michal Vasko680f8b42016-10-17 10:27:37 +0200134 /* handle situation when there is a top-level uses referencing a foreign grouping */
135 for (node = siblings; lys_parent(node) && (node->nodetype == LYS_USES); node = lys_parent(node));
136 mod = lys_node_module(node);
Michal Vasko1dca6882015-10-22 14:29:42 +0200137 }
138
Radek Krejcic071c542016-01-27 14:57:51 +0100139 /* try to find the node */
140 node = NULL;
141 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
142 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100143 /* module name comparison */
144 node_mod_name = lys_node_module(node)->name;
Michal Vaskob42b6972016-06-06 14:21:30 +0200145 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 +0100146 continue;
147 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200148
Radek Krejcic071c542016-01-27 14:57:51 +0100149 /* direct name check */
Michal Vaskob42b6972016-06-06 14:21:30 +0200150 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100151 if (ret) {
152 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200153 }
Radek Krejcic071c542016-01-27 14:57:51 +0100154 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200155 }
156 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200157 }
158
159 return EXIT_FAILURE;
160}
161
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200162int
Michal Vasko1e62a092015-12-01 12:27:20 +0100163lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
164 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200165{
Michal Vasko1e62a092015-12-01 12:27:20 +0100166 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200167
168 assert(siblings && name);
169 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
170
171 /* find the beginning */
172 while (siblings->prev->next) {
173 siblings = siblings->prev;
174 }
175
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200176 if (!mod) {
177 mod = siblings->module;
178 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200179
Michal Vasko4f0dad02016-02-15 14:08:23 +0100180 /* try to find the node */
181 node = NULL;
Michal Vaskodcf98e62016-05-05 17:53:53 +0200182 while ((node = lys_getnext(node, lys_parent(siblings), mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100183 if (!type || (node->nodetype & type)) {
184 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200185 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100186 continue;
187 }
188
Michal Vasko4f0dad02016-02-15 14:08:23 +0100189 /* direct name check */
Radek Krejci749190d2016-02-18 16:26:25 +0100190 if (ly_strequal(node->name, name, 0)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100191 if (ret) {
192 *ret = node;
193 }
194 return EXIT_SUCCESS;
195 }
Radek Krejcic071c542016-01-27 14:57:51 +0100196 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200197 }
198
199 return EXIT_FAILURE;
200}
201
Michal Vasko1e62a092015-12-01 12:27:20 +0100202API const struct lys_node *
203lys_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 +0200204{
Michal Vasko1e62a092015-12-01 12:27:20 +0100205 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200206
Radek Krejci8bc87f62015-09-02 16:19:05 +0200207 if (!last) {
208 /* first call */
209
210 /* get know where to start */
211 if (parent) {
212 /* schema subtree */
213 next = last = parent->child;
214 } else {
215 /* top level data */
216 assert(module);
217 next = last = module->data;
218 }
Radek Krejci972724f2016-08-12 15:24:40 +0200219 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
220 /* continue with uses content */
221 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200222 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200223 /* continue after the last returned value */
224 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200225 }
226
227repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200228 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200229 if (options & LYS_GETNEXT_WITHGROUPING) {
230 return next;
231 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200232 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200233 }
234
Radek Krejci972724f2016-08-12 15:24:40 +0200235 if (!next) { /* cover case when parent is augment */
236 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200237 /* no next element */
238 return NULL;
239 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200240 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200241 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200242 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200243 } else {
244 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200245 }
246
247 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200248 case LYS_INPUT:
249 case LYS_OUTPUT:
250 if (options & LYS_GETNEXT_WITHINOUT) {
251 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200252 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200253 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200254 } else {
255 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200256 }
Radek Krejci972724f2016-08-12 15:24:40 +0200257 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200258
Michal Vaskoa5835e92015-10-20 15:07:39 +0200259 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200260 if (options & LYS_GETNEXT_WITHCASE) {
261 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200262 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200263 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200264 } else {
265 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200266 }
Radek Krejci972724f2016-08-12 15:24:40 +0200267 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200268
Michal Vasko1dca6882015-10-22 14:29:42 +0200269 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200270 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200271 if (options & LYS_GETNEXT_WITHUSES) {
272 return next;
273 } else if (next->child) {
274 next = next->child;
275 } else {
276 next = next->next;
277 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200278 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200279
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200280 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200281 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200282 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200283 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200284 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200285 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200286 case LYS_LIST:
287 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200288 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200289
Radek Krejci972724f2016-08-12 15:24:40 +0200290 case LYS_CONTAINER:
291 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
292 if (next->child) {
293 /* go into */
294 next = next->child;
295 } else {
296 next = next->next;
297 }
298 goto repeat;
299 } else {
300 return next;
301 }
302
Radek Krejci8bc87f62015-09-02 16:19:05 +0200303 case LYS_CHOICE:
304 if (options & LYS_GETNEXT_WITHCHOICE) {
305 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200306 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200307 /* go into */
308 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200309 } else {
310 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200311 }
Radek Krejci972724f2016-08-12 15:24:40 +0200312 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200313
Radek Krejci7f40ce32015-08-12 20:38:46 +0200314 default:
315 /* we should not be here */
316 return NULL;
317 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200318
319
320}
321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200322void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200323lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200324{
Radek Krejci76512572015-08-04 09:47:08 +0200325 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100326 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200328 if (!node) {
329 return;
330 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200331
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200332 /* unlink from data model if necessary */
333 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100334 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100335 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100336 if (main_module->data == node) {
337 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200338 }
339 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200341 /* store pointers to important nodes */
342 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200343 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200344 /* handle augments - first, unlink it from the augment parent ... */
345 if (parent->child == node) {
346 parent->child = node->next;
347 }
348 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200349 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200350 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200352 /* unlink from parent */
353 if (parent) {
354 if (parent->child == node) {
355 parent->child = node->next;
356 }
357 node->parent = NULL;
358 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200360 /* unlink from siblings */
361 if (node->prev == node) {
362 /* there are no more siblings */
363 return;
364 }
365 if (node->next) {
366 node->next->prev = node->prev;
367 } else {
368 /* unlinking the last element */
369 if (parent) {
370 first = parent->child;
371 } else {
372 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200373 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200374 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200375 }
376 }
377 first->prev = node->prev;
378 }
379 if (node->prev->next) {
380 node->prev->next = node->next;
381 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200383 /* clean up the unlinked element */
384 node->next = NULL;
385 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200386}
387
Michal Vasko563ef092015-09-04 13:17:23 +0200388struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100389lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200390{
391 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200392
393 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200394 /* top-level augment, look into module (uses augment is handled correctly below) */
395 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
396 par_iter = par_iter->parent->module->data;
397 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200398 break;
399 }
400 }
401
Michal Vasko6f929da2015-10-02 16:23:25 +0200402 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200403 continue;
404 }
405
406 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
407 if (!stop) {
408 stop = par_iter;
409 } else if (iter == stop) {
410 break;
411 }
412 if (iter->nodetype != LYS_GROUPING) {
413 continue;
414 }
415
Radek Krejcif8426a72015-10-31 23:14:03 +0100416 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200417 return (struct lys_node_grp *)iter;
418 }
419 }
420 }
421
Michal Vasko563ef092015-09-04 13:17:23 +0200422 return NULL;
423}
424
Radek Krejci10c760e2015-08-14 14:45:43 +0200425/*
426 * get next grouping in the root's subtree, in the
427 * first call, tha last is NULL
428 */
429static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200430lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200431{
Radek Krejci10c760e2015-08-14 14:45:43 +0200432 struct lys_node *last = (struct lys_node *)lastgrp;
433 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200434
Radek Krejci10c760e2015-08-14 14:45:43 +0200435 assert(root);
436
437 if (!last) {
438 last = root;
439 }
440
441 while (1) {
442 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
443 next = last->child;
444 } else {
445 next = NULL;
446 }
447 if (!next) {
448 if (last == root) {
449 /* we are done */
450 return NULL;
451 }
452
453 /* no children, go to siblings */
454 next = last->next;
455 }
456 while (!next) {
457 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100458 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200459 /* we are done */
460 return NULL;
461 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200462 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100463 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200464 }
465
466 if (next->nodetype == LYS_GROUPING) {
467 return (struct lys_node_grp *)next;
468 }
469
470 last = next;
471 }
472}
473
Michal Vasko0d343d12015-08-24 14:57:36 +0200474/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200475int
Radek Krejci07911992015-08-14 15:13:31 +0200476lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
477{
Michal Vasko563ef092015-09-04 13:17:23 +0200478 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200479 struct lys_node_grp *grp;
480 int down;
481
482 assert(node);
483
484 if (!parent) {
485 assert(module);
486 } else {
487 module = parent->module;
488 }
489
490 switch (node->nodetype) {
491 case LYS_GROUPING:
492 /* 6.2.1, rule 6 */
493 if (parent) {
494 if (parent->child) {
495 down = 1;
496 start = parent->child;
497 } else {
498 down = 0;
499 start = parent;
500 }
501 } else {
502 down = 1;
503 start = module->data;
504 }
505 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100506 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100507 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200508 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200509 }
510 /* go down, because grouping can be defined after e.g. container in which is collision */
511 if (down) {
512 for (iter = start, stop = NULL; iter; iter = iter->prev) {
513 if (!stop) {
514 stop = start;
515 } else if (iter == stop) {
516 break;
517 }
518 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
519 continue;
520 }
521
522 grp = NULL;
523 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100524 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100525 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200526 return EXIT_FAILURE;
527 }
528 }
529 }
530 }
531 break;
532 case LYS_LEAF:
533 case LYS_LEAFLIST:
534 case LYS_LIST:
535 case LYS_CONTAINER:
536 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200537 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200538 /* 6.2.1, rule 7 */
539 if (parent) {
540 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200541 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
542 if (iter->nodetype == LYS_AUGMENT) {
543 if (((struct lys_node_augment *)iter)->target) {
544 /* augment is resolved, go up */
545 iter = ((struct lys_node_augment *)iter)->target;
546 continue;
547 }
548 /* augment is not resolved, this is the final parent */
549 break;
550 }
Radek Krejci07911992015-08-14 15:13:31 +0200551 iter = iter->parent;
552 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200553
Radek Krejci07911992015-08-14 15:13:31 +0200554 if (!iter) {
555 stop = NULL;
556 iter = module->data;
557 } else {
558 stop = iter;
559 iter = iter->child;
560 }
561 } else {
562 stop = NULL;
563 iter = module->data;
564 }
565 while (iter) {
566 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
567 iter = iter->child;
568 continue;
569 }
570
Radek Krejcibf2abff2016-08-23 15:51:52 +0200571 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100572 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100573 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200574 return EXIT_FAILURE;
575 }
576 }
577
578 /* special case for choice - we must check the choice's name as
579 * well as the names of nodes under the choice
580 */
581 if (iter->nodetype == LYS_CHOICE) {
582 iter = iter->child;
583 continue;
584 }
585
586 /* go to siblings */
587 if (!iter->next) {
588 /* no sibling, go to parent's sibling */
589 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200590 /* for parent LYS_AUGMENT */
591 if (iter->parent == stop) {
592 iter = stop;
593 break;
594 }
595 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200596 if (iter && iter->next) {
597 break;
598 }
599 } while (iter != stop);
600
601 if (iter == stop) {
602 break;
603 }
604 }
605 iter = iter->next;
606 }
607 break;
608 case LYS_CASE:
609 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100610 if (parent) {
611 start = parent->child;
612 } else {
613 start = module->data;
614 }
615
616 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200617 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200618 continue;
619 }
620
Radek Krejci749190d2016-02-18 16:26:25 +0100621 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100622 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200623 return EXIT_FAILURE;
624 }
625 }
626 break;
627 default:
628 /* no check needed */
629 break;
630 }
631
632 return EXIT_SUCCESS;
633}
634
Michal Vasko0d343d12015-08-24 14:57:36 +0200635/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200636int
Radek Krejci10c760e2015-08-14 14:45:43 +0200637lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
638{
Radek Krejci92720552015-10-05 15:28:27 +0200639 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200640 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200641
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200642 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200643
Radek Krejci10c760e2015-08-14 14:45:43 +0200644 if (parent) {
645 type = parent->nodetype;
646 module = parent->module;
647 } else {
648 assert(module);
649 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200650 }
651
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200652 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200653 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200654 case LYS_CONTAINER:
655 case LYS_LIST:
656 case LYS_GROUPING:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200657 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200658 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200659 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200660 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
661 return EXIT_FAILURE;
662 }
663 break;
Radek Krejci76512572015-08-04 09:47:08 +0200664 case LYS_USES:
665 case LYS_INPUT:
666 case LYS_OUTPUT:
667 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200668 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200669 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200670 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100671 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200672 return EXIT_FAILURE;
673 }
674 break;
Radek Krejci76512572015-08-04 09:47:08 +0200675 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200676 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200677 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100678 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200679 return EXIT_FAILURE;
680 }
681 break;
Radek Krejci76512572015-08-04 09:47:08 +0200682 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200683 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200684 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100685 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200686 return EXIT_FAILURE;
687 }
688 break;
Radek Krejci76512572015-08-04 09:47:08 +0200689 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200690 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200691 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100692 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200693 return EXIT_FAILURE;
694 }
695 break;
Radek Krejci76512572015-08-04 09:47:08 +0200696 case LYS_LEAF:
697 case LYS_LEAFLIST:
698 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200699 case LYS_ANYDATA:
Radek Krejci48464ed2016-03-17 15:44:09 +0100700 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
701 LOGVAL(LYE_SPEC, LY_VLOG_LYS, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100702 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200703 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200704 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200705 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200706 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200707 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100708 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200709 return EXIT_FAILURE;
710 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200711 break;
712 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200713 /* top level */
714 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200715 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200716 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100717 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200718 return EXIT_FAILURE;
719 }
720
Radek Krejcic071c542016-01-27 14:57:51 +0100721 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200722 }
723
724 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200725 if (lys_check_id(child, parent, module)) {
726 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200727 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200729 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200730 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200731 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200732
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200733 /* connect the child correctly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200734 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +0200735 if (module->data) {
736 module->data->prev->next = child;
737 child->prev = module->data->prev;
738 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200739 } else {
Radek Krejci92720552015-10-05 15:28:27 +0200740 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200741 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200742 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200743 if (!parent->child) {
744 /* the only/first child of the parent */
745 parent->child = child;
746 child->parent = parent;
747 iter = child;
748 } else {
749 /* add a new child at the end of parent's child list */
750 iter = parent->child->prev;
751 iter->next = child;
752 child->prev = iter;
753 }
754 while (iter->next) {
755 iter = iter->next;
756 iter->parent = parent;
757 }
758 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200759 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200760
Michal Vaskoe022a562016-09-27 14:24:15 +0200761 /* check config value (but ignore them in groupings and augments) */
762 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT)); iter = iter->parent);
763 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200764 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
765 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
766 LOGVAL(LYE_INARG, LY_VLOG_LYS, child, "true", "config");
767 LOGVAL(LYE_SPEC, LY_VLOG_LYS, child, "State nodes cannot have configuration nodes as children.");
768 return EXIT_FAILURE;
769 }
770 }
771
Radek Krejci41771502016-04-14 17:52:32 +0200772 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200773 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200774 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200775 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200776 /* store it only into container or list - the only data inner nodes */
777 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
778 if (iter->flags & LYS_INCL_STATUS) {
779 /* done, someone else set it already from here */
780 break;
781 }
782 /* set flag about including status data */
783 iter->flags |= LYS_INCL_STATUS;
784 }
785 }
786 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200787 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200788}
789
Radek Krejcia1df1682016-04-11 14:56:59 +0200790static const struct lys_module *
791lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200792{
Radek Krejcia1df1682016-04-11 14:56:59 +0200793 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200794 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200795 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200796
Radek Krejcif347abc2016-06-22 10:18:47 +0200797 ly_errno = LY_SUCCESS;
798
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200799 if (!ctx || !data) {
800 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
801 return NULL;
802 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200803
Radek Krejcia1df1682016-04-11 14:56:59 +0200804 if (!internal && format == LYS_IN_YANG) {
805 /* enlarge data by 2 bytes for flex */
806 len = strlen(data);
807 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
808 if (!enlarged_data) {
809 LOGMEM;
810 return NULL;
811 }
812 memcpy(enlarged_data, data, len);
813 enlarged_data[len] = enlarged_data[len + 1] = '\0';
814 data = enlarged_data;
815 }
816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200817 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200818 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +0100819 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200820 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200821 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100822 mod = yang_read_module(ctx, data, 0, NULL, 1);
823 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200824 default:
Radek Krejcia1df1682016-04-11 14:56:59 +0200825 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200826 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200827 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200828
Radek Krejcia1df1682016-04-11 14:56:59 +0200829 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200830 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200831}
832
Radek Krejcia1df1682016-04-11 14:56:59 +0200833API const struct lys_module *
834lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
835{
836 return lys_parse_mem_(ctx, data, format, 0);
837}
838
Michal Vasko5a721fd2016-02-16 12:16:48 +0100839struct lys_submodule *
840lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200841{
Michal Vasko5a721fd2016-02-16 12:16:48 +0100842 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200843
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200844 assert(module);
845 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200846
Radek Krejcic071c542016-01-27 14:57:51 +0100847 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +0200848 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200850 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200851 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +0100852 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200853 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200854 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100855 submod = yang_read_submodule(module, data, 0, unres);
856 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200857 default:
Radek Krejci90a550a2016-04-13 16:00:58 +0200858 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200859 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200860 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200861
Michal Vasko5a721fd2016-02-16 12:16:48 +0100862 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200863}
864
Michal Vasko1e62a092015-12-01 12:27:20 +0100865API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +0100866lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
867{
868 int fd;
869 const struct lys_module *ret;
870
871 if (!ctx || !path) {
872 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
873 return NULL;
874 }
875
876 fd = open(path, O_RDONLY);
877 if (fd == -1) {
878 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
879 return NULL;
880 }
881
882 ret = lys_parse_fd(ctx, fd, format);
883 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +0100884
Radek Krejcia77904e2016-02-25 16:23:45 +0100885 if (ret && !ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +0100886 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +0100887 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +0100888 }
889
Michal Vasko662610a2015-12-07 11:25:45 +0100890 return ret;
891}
892
893API const struct lys_module *
894lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +0200895{
Michal Vasko1e62a092015-12-01 12:27:20 +0100896 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +0200897 struct stat sb;
898 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +0100899 char buf[PATH_MAX];
900 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +0200901
902 if (!ctx || fd < 0) {
903 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
904 return NULL;
905 }
906
Radek Krejci10a833c2015-12-16 15:28:37 +0100907 if (fstat(fd, &sb) == -1) {
908 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
909 return NULL;
910 }
Radek Krejcib051f722016-02-25 15:12:21 +0100911 if (!S_ISREG(sb.st_mode)) {
912 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
913 return NULL;
914 }
915
Michal Vasko164d9012016-04-01 10:16:59 +0200916 if (!sb.st_size) {
917 LOGERR(LY_EINVAL, "File empty.");
918 return NULL;
919 }
920
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100921 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +0100922 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +0100923 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +0100924 return NULL;
925 }
Radek Krejcia1df1682016-04-11 14:56:59 +0200926 module = lys_parse_mem_(ctx, addr, format, 1);
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100927 munmap(addr, sb.st_size + 2);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200928
Radek Krejcia77904e2016-02-25 16:23:45 +0100929 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +0100930 /* get URI if there is /proc */
931 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +0100932 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
933 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
934 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
935 }
936 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +0100937 }
Radek Krejcib051f722016-02-25 15:12:21 +0100938 }
939
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200940 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200941}
942
Michal Vasko5a721fd2016-02-16 12:16:48 +0100943struct lys_submodule *
944lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200945{
Michal Vasko5a721fd2016-02-16 12:16:48 +0100946 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200947 struct stat sb;
948 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 assert(module);
951 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200952
Radek Krejci10a833c2015-12-16 15:28:37 +0100953 if (fstat(fd, &sb) == -1) {
954 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +0100955 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +0100956 }
Michal Vasko164d9012016-04-01 10:16:59 +0200957
958 if (!sb.st_size) {
959 LOGERR(LY_EINVAL, "File empty.");
960 return NULL;
961 }
962
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100963 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +0100964 if (addr == MAP_FAILED) {
965 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +0100966 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +0100967 }
Michal Vasko5a721fd2016-02-16 12:16:48 +0100968 submodule = lys_submodule_parse(module, addr, format, unres);
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100969 munmap(addr, sb.st_size + 2);
Radek Krejciefaeba32015-05-27 14:30:57 +0200970
Michal Vasko5a721fd2016-02-16 12:16:48 +0100971 return submodule;
972
Radek Krejciefaeba32015-05-27 14:30:57 +0200973}
974
Radek Krejci1d82ef62015-08-07 14:44:40 +0200975static struct lys_restr *
976lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200977{
Radek Krejci1574a8d2015-08-03 14:16:52 +0200978 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200979 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200980
Radek Krejci3733a802015-06-19 13:43:21 +0200981 if (!size) {
982 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200983 }
Radek Krejci3733a802015-06-19 13:43:21 +0200984
985 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +0100986 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +0100987 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +0100988 return NULL;
989 }
Radek Krejci3733a802015-06-19 13:43:21 +0200990 for (i = 0; i < size; i++) {
991 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
992 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
993 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
994 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
995 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
996 }
997
998 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200999}
1000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001001void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001002lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001003{
1004 assert(ctx);
1005 if (!restr) {
1006 return;
1007 }
1008
1009 lydict_remove(ctx, restr->expr);
1010 lydict_remove(ctx, restr->dsc);
1011 lydict_remove(ctx, restr->ref);
1012 lydict_remove(ctx, restr->eapptag);
1013 lydict_remove(ctx, restr->emsg);
1014}
1015
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001016static void
1017lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size)
1018{
1019 uint8_t i;
1020
1021 for (i = 0; i < iffeature_size; ++i) {
1022 free(iffeature[i].expr);
1023 free(iffeature[i].features);
1024 }
1025 free(iffeature);
1026}
1027
Michal Vaskob84f88a2015-09-24 13:16:10 +02001028static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001029type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001030 LY_DATA_TYPE base, int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001031{
1032 int i;
1033
1034 switch (base) {
1035 case LY_TYPE_BINARY:
1036 if (old->info.binary.length) {
1037 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
1038 }
1039 break;
1040
1041 case LY_TYPE_BITS:
1042 new->info.bits.count = old->info.bits.count;
1043 if (new->info.bits.count) {
1044 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1045 if (!new->info.bits.bit) {
1046 LOGMEM;
1047 return -1;
1048 }
1049 for (i = 0; i < new->info.bits.count; i++) {
1050 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1051 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1052 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1053 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1054 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1055 }
1056 }
1057 break;
1058
1059 case LY_TYPE_DEC64:
1060 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001061 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001062 if (old->info.dec64.range) {
1063 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
1064 }
1065 break;
1066
1067 case LY_TYPE_ENUM:
1068 new->info.enums.count = old->info.enums.count;
1069 if (new->info.enums.count) {
1070 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1071 if (!new->info.enums.enm) {
1072 LOGMEM;
1073 return -1;
1074 }
1075 for (i = 0; i < new->info.enums.count; i++) {
1076 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1077 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1078 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1079 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1080 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
1081 }
1082 }
1083 break;
1084
1085 case LY_TYPE_IDENT:
Michal Vaskoaffc37f2016-10-10 18:05:03 +00001086 new->info.ident.count = old->info.ident.count;
Michal Vasko878e38d2016-09-05 12:17:53 +02001087 if (old->info.ident.count) {
1088 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
1089 if (!new->info.ident.ref) {
1090 LOGMEM;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001091 return -1;
1092 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001093 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1094 } else {
1095 /* there can be several unresolved base identities, duplicate them all */
1096 i = -1;
1097 while ((i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF)) != -1) {
1098 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
1099 return -1;
1100 }
1101 --i;
1102 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001103 }
1104 break;
1105
1106 case LY_TYPE_INST:
1107 new->info.inst.req = old->info.inst.req;
1108 break;
1109
1110 case LY_TYPE_INT8:
1111 case LY_TYPE_INT16:
1112 case LY_TYPE_INT32:
1113 case LY_TYPE_INT64:
1114 case LY_TYPE_UINT8:
1115 case LY_TYPE_UINT16:
1116 case LY_TYPE_UINT32:
1117 case LY_TYPE_UINT64:
1118 if (old->info.num.range) {
1119 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
1120 }
1121 break;
1122
1123 case LY_TYPE_LEAFREF:
1124 if (old->info.lref.path) {
1125 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko5d631402016-07-21 13:15:15 +02001126 if (!tpdftype && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001127 return -1;
1128 }
1129 }
1130 break;
1131
1132 case LY_TYPE_STRING:
1133 if (old->info.str.length) {
1134 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
1135 }
1136 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
1137 new->info.str.pat_count = old->info.str.pat_count;
1138 break;
1139
1140 case LY_TYPE_UNION:
1141 new->info.uni.count = old->info.uni.count;
1142 if (new->info.uni.count) {
1143 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1144 if (!new->info.uni.types) {
1145 LOGMEM;
1146 return -1;
1147 }
1148 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001149 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 +02001150 return -1;
1151 }
1152 }
1153 }
1154 break;
1155
1156 default:
1157 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1158 break;
1159 }
1160 return EXIT_SUCCESS;
1161}
1162
1163struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001164lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1165 int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001166{
1167 struct yang_type *new;
1168
1169 new = calloc(1, sizeof *new);
1170 if (!new) {
1171 LOGMEM;
1172 return NULL;
1173 }
1174 new->flags = old->flags;
1175 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001176 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001177 new->type = type;
1178 if (!new->name) {
1179 LOGMEM;
1180 goto error;
1181 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001182 if (type_dup(module, parent, type, old->type, new->base, tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001183 new->type->base = new->base;
1184 lys_type_free(module->ctx, new->type);
1185 memset(&new->type->info, 0, sizeof new->type->info);
1186 goto error;
1187 }
1188 return new;
1189
1190 error:
1191 free(new);
1192 return NULL;
1193}
1194
1195static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001196lys_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 +02001197 int tpdftype, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001198{
1199 int i;
1200
Michal Vasko1dca6882015-10-22 14:29:42 +02001201 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001202 new->base = old->base;
1203 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001204 new->parent = (struct lys_tpdf *)parent;
Radek Krejci3733a802015-06-19 13:43:21 +02001205
Michal Vasko878e38d2016-09-05 12:17:53 +02001206 i = unres_schema_find(unres, -1, old, tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001207 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001208 /* HACK (serious one) for unres */
1209 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001210 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001211 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 +02001212 } else {
1213 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1214 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001215 /* all these unres additions can fail even though they did not before */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001216 if (!new->der || unres_schema_add_node(mod, unres, new,
Michal Vasko5d631402016-07-21 13:15:15 +02001217 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001218 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001219 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001220 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001221 }
1222
Radek Krejci3a5501d2016-07-18 22:03:34 +02001223 return type_dup(mod, parent, new, old, new->base, tpdftype, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001224}
1225
1226void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001227lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001228{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001229 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001231 assert(ctx);
1232 if (!type) {
1233 return;
1234 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001235
Michal Vasko1dca6882015-10-22 14:29:42 +02001236 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001238 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001239 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001240 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001241 free(type->info.binary.length);
1242 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001243 case LY_TYPE_BITS:
1244 for (i = 0; i < type->info.bits.count; i++) {
1245 lydict_remove(ctx, type->info.bits.bit[i].name);
1246 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1247 lydict_remove(ctx, type->info.bits.bit[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001248 lys_iffeature_free(type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size);
Radek Krejci994b6f62015-06-18 16:47:27 +02001249 }
1250 free(type->info.bits.bit);
1251 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001252
1253 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001254 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001255 free(type->info.dec64.range);
1256 break;
1257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001258 case LY_TYPE_ENUM:
1259 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001260 lydict_remove(ctx, type->info.enums.enm[i].name);
1261 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1262 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001263 lys_iffeature_free(type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001264 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001265 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001266 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001267
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001268 case LY_TYPE_INT8:
1269 case LY_TYPE_INT16:
1270 case LY_TYPE_INT32:
1271 case LY_TYPE_INT64:
1272 case LY_TYPE_UINT8:
1273 case LY_TYPE_UINT16:
1274 case LY_TYPE_UINT32:
1275 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001276 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001277 free(type->info.num.range);
1278 break;
1279
Radek Krejcidc4c1412015-06-19 15:39:54 +02001280 case LY_TYPE_LEAFREF:
1281 lydict_remove(ctx, type->info.lref.path);
1282 break;
1283
Radek Krejci3733a802015-06-19 13:43:21 +02001284 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001285 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001286 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001287 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001288 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001289 }
1290 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001291 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001292
Radek Krejcie4c366b2015-07-02 10:11:31 +02001293 case LY_TYPE_UNION:
1294 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001295 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001296 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001297 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001298 break;
1299
Michal Vaskod3282192016-09-05 11:27:57 +02001300 case LY_TYPE_IDENT:
1301 free(type->info.ident.ref);
1302 break;
1303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001304 default:
Michal Vaskod3282192016-09-05 11:27:57 +02001305 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001306 break;
1307 }
Radek Krejci5a065542015-05-22 15:02:07 +02001308}
1309
Radek Krejci1d82ef62015-08-07 14:44:40 +02001310static void
1311lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001312{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001313 assert(ctx);
1314 if (!tpdf) {
1315 return;
1316 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001318 lydict_remove(ctx, tpdf->name);
1319 lydict_remove(ctx, tpdf->dsc);
1320 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001321
Radek Krejci1d82ef62015-08-07 14:44:40 +02001322 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001324 lydict_remove(ctx, tpdf->units);
1325 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001326}
1327
Michal Vaskob84f88a2015-09-24 13:16:10 +02001328static struct lys_tpdf *
1329lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1330{
1331 struct lys_tpdf *result;
1332 int i, j;
1333
1334 if (!size) {
1335 return NULL;
1336 }
1337
1338 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001339 if (!result) {
1340 LOGMEM;
1341 return NULL;
1342 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001343 for (i = 0; i < size; i++) {
1344 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1345 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1346 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1347 result[i].flags = old[i].flags;
1348 result[i].module = old[i].module;
1349
Radek Krejci3a5501d2016-07-18 22:03:34 +02001350 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), 1, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001351 for (j = 0; j <= i; ++j) {
1352 lys_tpdf_free(mod->ctx, &result[j]);
1353 }
1354 free(result);
1355 return NULL;
1356 }
1357
1358 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1359 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1360 }
1361
1362 return result;
1363}
1364
Radek Krejci1d82ef62015-08-07 14:44:40 +02001365static struct lys_when *
1366lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001367{
Radek Krejci76512572015-08-04 09:47:08 +02001368 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001369
1370 if (!old) {
1371 return NULL;
1372 }
1373
1374 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001375 if (!new) {
1376 LOGMEM;
1377 return NULL;
1378 }
Radek Krejci00768f42015-06-18 17:04:04 +02001379 new->cond = lydict_insert(ctx, old->cond, 0);
1380 new->dsc = lydict_insert(ctx, old->dsc, 0);
1381 new->ref = lydict_insert(ctx, old->ref, 0);
1382
1383 return new;
1384}
1385
Michal Vasko0308dd62015-10-07 09:14:40 +02001386void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001387lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001388{
1389 if (!w) {
1390 return;
1391 }
1392
1393 lydict_remove(ctx, w->cond);
1394 lydict_remove(ctx, w->dsc);
1395 lydict_remove(ctx, w->ref);
1396
1397 free(w);
1398}
1399
Radek Krejcib7f5e412015-08-13 10:15:51 +02001400static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001401lys_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 +02001402{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001403 struct lys_node *next, *sub;
1404
Radek Krejcic071c542016-01-27 14:57:51 +01001405 /* children from a resolved augment are freed under the target node */
Michal Vaskod2fbade2016-05-02 17:14:00 +02001406 if (!aug->target) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001407 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001408 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001409 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001410 }
1411
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001412 lydict_remove(ctx, aug->target_name);
1413 lydict_remove(ctx, aug->dsc);
1414 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001415
Radek Krejci9ff0a922016-07-14 13:08:05 +02001416 lys_iffeature_free(aug->iffeature, aug->iffeature_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001417
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001418 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001419}
1420
Radek Krejci76512572015-08-04 09:47:08 +02001421static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001422lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001423{
Radek Krejci76512572015-08-04 09:47:08 +02001424 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001425 struct lys_node *old_child, *new_child;
1426 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001427
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001428 if (!size) {
1429 return NULL;
1430 }
Radek Krejci106efc02015-06-10 14:36:27 +02001431
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001432 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001433 if (!new) {
1434 LOGMEM;
1435 return NULL;
1436 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001437 for (i = 0; i < size; i++) {
1438 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1439 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1440 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1441 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001442 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001443 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001444
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001445 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001446 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1447 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001448 LOGINT;
1449 free(new);
1450 return NULL;
1451 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001452 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001453
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001454 /* Correct the augment nodes.
1455 * This function can only be called from lys_node_dup() with uses
1456 * being the node duplicated, so we must have a case of grouping
1457 * with a uses with augments. The augmented nodes have already been
1458 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001459 * (it was set to their actual data parent, not an augment), and
1460 * the new augment does not have child pointer to its augment nodes,
1461 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001462 */
1463 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001464 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001465 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001466 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001467 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001468 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001469 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001470 LY_TREE_FOR(old[i].child, old_child) {
1471 /* all augment nodes were connected as siblings, there can be no more after this */
1472 if (old_child->parent != (struct lys_node *)&old[i]) {
1473 break;
1474 }
1475
Radek Krejci749190d2016-02-18 16:26:25 +01001476 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001477
1478 new_child->parent = (struct lys_node *)&new[i];
1479 new_child = new_child->next;
1480 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001481 }
Radek Krejci106efc02015-06-10 14:36:27 +02001482
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001483 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001484}
1485
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001486static const char **
1487lys_dflt_dup(struct ly_ctx *ctx, const char **old, int size)
1488{
1489 int i;
1490 const char **result;
1491
1492 if (!size) {
1493 return NULL;
1494 }
1495
1496 result = calloc(size, sizeof *result);
1497 if (!result) {
1498 LOGMEM;
1499 return NULL;
1500 }
1501
1502 for (i = 0; i < size; i++) {
1503 result[i] = lydict_insert(ctx, old[i], 0);
1504 }
1505 return result;
1506}
1507
Radek Krejci76512572015-08-04 09:47:08 +02001508static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001509lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001510{
Radek Krejci76512572015-08-04 09:47:08 +02001511 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001512 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001514 if (!size) {
1515 return NULL;
1516 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001517
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001518 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001519 if (!result) {
1520 LOGMEM;
1521 return NULL;
1522 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001523 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001524 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001525 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1526 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001527 result[i].flags = old[i].flags;
1528 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001529
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001530 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001531 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001532
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001533 result[i].dflt_size = old[i].dflt_size;
1534 result[i].dflt = lys_dflt_dup(mod->ctx, old[i].dflt, old[i].dflt_size);
1535
1536 if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001537 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001538 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001539 result[i].mod.list = old[i].mod.list;
1540 }
1541 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001543 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001544}
1545
Radek Krejci1d82ef62015-08-07 14:44:40 +02001546static void
1547lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001548{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001549 assert(ctx);
1550 if (!ident) {
1551 return;
1552 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001553
Radek Krejci018f1f52016-08-03 16:01:20 +02001554 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02001555 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001556 lydict_remove(ctx, ident->name);
1557 lydict_remove(ctx, ident->dsc);
1558 lydict_remove(ctx, ident->ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001559 lys_iffeature_free(ident->iffeature, ident->iffeature_size);
Radek Krejci6793db02015-05-22 17:49:54 +02001560
1561}
1562
Radek Krejci1d82ef62015-08-07 14:44:40 +02001563static void
1564lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001565{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001566 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001567
Radek Krejcid12f57b2015-08-06 10:43:39 +02001568 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001569 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001570 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001571 }
1572 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001573}
1574
Radek Krejci1d82ef62015-08-07 14:44:40 +02001575static void
Michal Vasko44fb6382016-06-29 11:12:27 +02001576lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02001577{
1578 int i;
1579
1580 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1581 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001582 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001583 }
1584 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02001585
1586 for (i = 0; i < io->must_size; i++) {
1587 lys_restr_free(ctx, &io->must[i]);
1588 }
1589 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001590}
1591
Radek Krejci1d82ef62015-08-07 14:44:40 +02001592static void
Pavol Vican7cff97e2016-08-09 14:56:08 +02001593lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif)
1594{
1595 int i;
1596
1597 for (i = 0; i < notif->must_size; i++) {
1598 lys_restr_free(ctx, &notif->must[i]);
1599 }
1600 free(notif->must);
1601
1602 for (i = 0; i < notif->tpdf_size; i++) {
1603 lys_tpdf_free(ctx, &notif->tpdf[i]);
1604 }
1605 free(notif->tpdf);
1606}
1607static void
Radek Krejcibf2abff2016-08-23 15:51:52 +02001608lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001609{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001610 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001612 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001613 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001614 }
1615 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001616
Radek Krejci1d82ef62015-08-07 14:44:40 +02001617 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001618}
1619
Radek Krejci1d82ef62015-08-07 14:44:40 +02001620static void
1621lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001622{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001623 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001624
Radek Krejci85a54be2016-10-20 12:39:56 +02001625 /* leafref backlinks */
1626 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001628 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001629 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001630 }
1631 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001632
Radek Krejci1d82ef62015-08-07 14:44:40 +02001633 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001634
Radek Krejci1d82ef62015-08-07 14:44:40 +02001635 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001636 lydict_remove(ctx, leaf->units);
1637 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001638}
1639
Radek Krejci1d82ef62015-08-07 14:44:40 +02001640static void
1641lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001642{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001643 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001644
Radek Krejci46c4cd72016-01-21 15:13:52 +01001645 if (llist->child) {
1646 /* leafref backlinks */
1647 ly_set_free((struct ly_set *)llist->child);
1648 }
1649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001650 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001651 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001652 }
1653 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001654
Pavol Vican38321d02016-08-16 14:56:02 +02001655 for (i = 0; i < llist->dflt_size; i++) {
1656 lydict_remove(ctx, llist->dflt[i]);
1657 }
1658 free(llist->dflt);
1659
Radek Krejci1d82ef62015-08-07 14:44:40 +02001660 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001661
Radek Krejci1d82ef62015-08-07 14:44:40 +02001662 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001663 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001664}
1665
Radek Krejci1d82ef62015-08-07 14:44:40 +02001666static void
1667lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001668{
Radek Krejci581ce772015-11-10 17:22:40 +01001669 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001671 /* handle only specific parts for LY_NODE_LIST */
1672 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001673 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001674 }
1675 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001676
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001677 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001678 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001679 }
1680 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001681
Radek Krejci1d82ef62015-08-07 14:44:40 +02001682 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001684 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02001685 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001686 lydict_remove(ctx, list->unique[i].expr[j]);
1687 }
1688 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001689 }
1690 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001692 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001693}
1694
Radek Krejci1d82ef62015-08-07 14:44:40 +02001695static void
1696lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001697{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001698 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001699
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001700 /* handle only specific parts for LY_NODE_CONTAINER */
1701 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001704 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001705 }
1706 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001707
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001708 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001709 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001710 }
1711 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001712
Radek Krejci1d82ef62015-08-07 14:44:40 +02001713 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001714}
1715
Radek Krejci1d82ef62015-08-07 14:44:40 +02001716static void
1717lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001718{
1719 lydict_remove(ctx, f->name);
1720 lydict_remove(ctx, f->dsc);
1721 lydict_remove(ctx, f->ref);
Radek Krejci9ff0a922016-07-14 13:08:05 +02001722 lys_iffeature_free(f->iffeature, f->iffeature_size);
Radek Krejci9de2c042016-10-19 16:53:06 +02001723 ly_set_free(f->depfeatures);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001724}
1725
Radek Krejci1d82ef62015-08-07 14:44:40 +02001726static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001727lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001728{
Radek Krejci581ce772015-11-10 17:22:40 +01001729 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001730 struct ly_ctx *ctx;
1731 struct lys_node *next, *elem;
1732
1733 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001734
1735 lydict_remove(ctx, dev->target_name);
1736 lydict_remove(ctx, dev->dsc);
1737 lydict_remove(ctx, dev->ref);
1738
Pavol Vican64d0b762016-08-25 10:44:59 +02001739 if (!dev->deviate) {
1740 return ;
1741 }
1742
Michal Vaskoff006c12016-02-17 11:15:19 +01001743 /* the module was freed, but we only need the context from orig_node, use ours */
1744 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1745 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1746 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1747 elem->module = module;
1748
1749 LY_TREE_DFS_END(dev->orig_node, next, elem);
1750 }
1751 lys_node_free(dev->orig_node, NULL, 0);
1752 } else {
1753 /* it's just a shallow copy, freeing one node */
1754 dev->orig_node->module = module;
1755 lys_node_free(dev->orig_node, NULL, 1);
1756 }
1757
Radek Krejcieb00f512015-07-01 16:44:58 +02001758 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02001759 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02001760 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02001761 }
1762 free(dev->deviate[i].dflt);
1763
Radek Krejcieb00f512015-07-01 16:44:58 +02001764 lydict_remove(ctx, dev->deviate[i].units);
1765
1766 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1767 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001768 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001769 }
1770 free(dev->deviate[i].must);
1771
1772 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001773 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1774 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1775 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01001776 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001777 }
1778 free(dev->deviate[i].unique);
1779 }
1780 }
1781 free(dev->deviate);
1782}
1783
Radek Krejci1d82ef62015-08-07 14:44:40 +02001784static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001785lys_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 +02001786{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001787 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001789 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001790 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001791 lydict_remove(ctx, uses->refine[i].dsc);
1792 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001793
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001794 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001795 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 }
1797 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001798
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001799 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02001800 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001801 }
1802 free(uses->refine[i].dflt);
1803
1804 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001805 lydict_remove(ctx, uses->refine[i].mod.presence);
1806 }
1807 }
1808 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001810 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001811 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001812 }
1813 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001814
Radek Krejci1d82ef62015-08-07 14:44:40 +02001815 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001816}
1817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001818void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001819lys_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 +02001820{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001821 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001822 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001824 if (!node) {
1825 return;
1826 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001827
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001828 assert(node->module);
1829 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001831 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001832
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001833 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01001834 if (node->priv && private_destructor) {
1835 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001836 }
1837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001838 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02001839 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001840 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02001841 lys_iffeature_free(node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001842 lydict_remove(ctx, node->dsc);
1843 lydict_remove(ctx, node->ref);
1844 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001845
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001846 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001847 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001848 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001849 }
1850 }
1851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001852 /* specific part */
1853 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001854 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001855 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001856 break;
Radek Krejci76512572015-08-04 09:47:08 +02001857 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001858 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001859 break;
Radek Krejci76512572015-08-04 09:47:08 +02001860 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001861 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001862 break;
Radek Krejci76512572015-08-04 09:47:08 +02001863 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001864 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001865 break;
Radek Krejci76512572015-08-04 09:47:08 +02001866 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001867 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001868 break;
Radek Krejci76512572015-08-04 09:47:08 +02001869 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001870 case LYS_ANYDATA:
1871 lys_anydata_free(ctx, (struct lys_node_anydata *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001872 break;
Radek Krejci76512572015-08-04 09:47:08 +02001873 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001874 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001875 break;
Radek Krejci76512572015-08-04 09:47:08 +02001876 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001877 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001878 break;
Radek Krejci76512572015-08-04 09:47:08 +02001879 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001880 /* do nothing */
1881 break;
Radek Krejci76512572015-08-04 09:47:08 +02001882 case LYS_GROUPING:
1883 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02001884 case LYS_ACTION:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001885 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001886 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02001887 case LYS_NOTIF:
1888 lys_notif_free(ctx, (struct lys_node_notif *)node);
1889 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001890 case LYS_INPUT:
1891 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02001892 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001893 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001894 case LYS_UNKNOWN:
1895 LOGINT;
1896 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001897 }
Radek Krejci5a065542015-05-22 15:02:07 +02001898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001899 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001900 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001901 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001902}
1903
Michal Vasko1e62a092015-12-01 12:27:20 +01001904const struct lys_module *
Radek Krejci0fa54e92016-09-14 14:01:05 +02001905lys_get_implemented_module(const struct lys_module *mod)
1906{
1907 struct ly_ctx *ctx;
1908 int i;
1909
1910 if (!mod || mod->implemented) {
1911 /* invalid argument or the module itself is implemented */
1912 return mod;
1913 }
1914
1915 ctx = mod->ctx;
1916 for (i = 0; i < ctx->models.used; i++) {
1917 if (!ctx->models.list[i]->implemented) {
1918 continue;
1919 }
1920
1921 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
1922 /* we have some revision of the module implemented */
1923 return ctx->models.list[i];
1924 }
1925 }
1926
1927 /* we have no revision of the module implemented, return the module itself,
1928 * it is up to the caller to set the module implemented when needed */
1929 return mod;
1930}
1931
1932const struct lys_module *
Michal Vasko1e62a092015-12-01 12:27:20 +01001933lys_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 +02001934{
Radek Krejcic071c542016-01-27 14:57:51 +01001935 const struct lys_module *main_module;
Michal Vasko89563fc2016-07-28 16:19:35 +02001936 char *str;
Michal Vasko3edeaf72016-02-11 13:17:43 +01001937 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02001938
Michal Vaskoa7789a82016-02-11 15:42:55 +01001939 assert(!prefix || !name);
1940
Michal Vaskob6729c62015-10-21 12:09:47 +02001941 if (prefix && !pref_len) {
1942 pref_len = strlen(prefix);
1943 }
1944 if (name && !name_len) {
1945 name_len = strlen(name);
1946 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001947
Radek Krejcic4283442016-04-22 09:19:27 +02001948 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01001949
1950 /* module own prefix, submodule own prefix, (sub)module own name */
1951 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
1952 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01001953 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01001954 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02001955 }
1956
Michal Vasko89563fc2016-07-28 16:19:35 +02001957 /* standard import */
Michal Vasko8ce24d72015-10-21 11:27:26 +02001958 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01001959 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
1960 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001961 return module->imp[i].module;
1962 }
1963 }
1964
Michal Vasko89563fc2016-07-28 16:19:35 +02001965 /* module required by a foreign grouping, deviation, or submodule */
1966 if (name) {
1967 str = strndup(name, name_len);
1968 if (!str) {
1969 LOGMEM;
1970 return NULL;
1971 }
1972 main_module = ly_ctx_get_module(module->ctx, str, NULL);
1973 free(str);
1974 return main_module;
1975 }
1976
Michal Vasko8ce24d72015-10-21 11:27:26 +02001977 return NULL;
1978}
1979
Michal Vasko13b15832015-08-19 11:04:48 +02001980/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001981static void
Michal Vaskob746fff2016-02-11 11:37:50 +01001982module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001983{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001984 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01001985 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001986 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001987
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001988 assert(module->ctx);
1989 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001990
Michal Vaskob746fff2016-02-11 11:37:50 +01001991 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01001992 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02001993 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02001994 lydict_remove(ctx, module->imp[i].dsc);
1995 lydict_remove(ctx, module->imp[i].ref);
Radek Krejci225376f2016-02-16 17:36:22 +01001996 }
Radek Krejcidce51452015-06-16 15:20:08 +02001997 free(module->imp);
1998
Radek Krejcic071c542016-01-27 14:57:51 +01001999 /* submodules don't have data tree, the data nodes
2000 * are placed in the main module altogether */
2001 if (!module->type) {
2002 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002003 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002004 }
Radek Krejci21181962015-06-30 14:11:00 +02002005 }
Radek Krejci5a065542015-05-22 15:02:07 +02002006
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002007 lydict_remove(ctx, module->dsc);
2008 lydict_remove(ctx, module->ref);
2009 lydict_remove(ctx, module->org);
2010 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002011 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002012
Radek Krejcieb00f512015-07-01 16:44:58 +02002013 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002014 for (i = 0; i < module->rev_size; i++) {
2015 lydict_remove(ctx, module->rev[i].dsc);
2016 lydict_remove(ctx, module->rev[i].ref);
2017 }
2018 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002019
Radek Krejcieb00f512015-07-01 16:44:58 +02002020 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002021 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002022 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002023 }
2024 module->ident_size = 0;
2025 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002026
Radek Krejcieb00f512015-07-01 16:44:58 +02002027 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002028 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002029 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002030 }
2031 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002032
Radek Krejcieb00f512015-07-01 16:44:58 +02002033 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002034 for (i = 0; i < module->inc_size; i++) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002035 lydict_remove(ctx, module->inc[i].dsc);
2036 lydict_remove(ctx, module->inc[i].ref);
Radek Krejcic071c542016-01-27 14:57:51 +01002037 /* complete submodule free is done only from main module since
2038 * submodules propagate their includes to the main module */
2039 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002040 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002041 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002042 }
2043 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002044
Radek Krejcieb00f512015-07-01 16:44:58 +02002045 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002046 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002047 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002048 }
2049 free(module->augment);
2050
Radek Krejcieb00f512015-07-01 16:44:58 +02002051 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002052 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002053 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002054 }
2055 free(module->features);
2056
Radek Krejcieb00f512015-07-01 16:44:58 +02002057 /* deviations */
2058 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002059 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002060 }
2061 free(module->deviation);
2062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002063 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002064 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002065}
2066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002067void
Michal Vaskob746fff2016-02-11 11:37:50 +01002068lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002069{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002070 if (!submodule) {
2071 return;
2072 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002073
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002074 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002075 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002076
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002077 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002079 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002080}
2081
Radek Krejci3a5501d2016-07-18 22:03:34 +02002082static int
2083ingrouping(const struct lys_node *node)
2084{
2085 const struct lys_node *iter = node;
2086 assert(node);
2087
2088 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2089 if (!iter) {
2090 return 0;
2091 } else {
2092 return 1;
2093 }
2094}
2095
Radek Krejci76512572015-08-04 09:47:08 +02002096struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02002097lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node, uint8_t nacm,
2098 struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002099{
Radek Krejcic071c542016-01-27 14:57:51 +01002100 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002101 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002102 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002103 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002104 struct unres_list_uniq *unique_info;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002105
Michal Vaskoc07187d2015-08-13 15:20:57 +02002106 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002107 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002108 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002109 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002110 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002111 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002112 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002113 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002114 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002115 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002116 struct lys_node_anydata *any = NULL;
2117 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002118 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002119 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002120 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002121 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002122 struct lys_node_rpc_action *rpc = NULL;
2123 struct lys_node_rpc_action *rpc_orig = (struct lys_node_rpc_action *)node;
2124 struct lys_node_inout *io = NULL;
2125 struct lys_node_inout *io_orig = (struct lys_node_inout *)node;
2126 struct lys_node_rpc_action *ntf = NULL;
2127 struct lys_node_rpc_action *ntf_orig = (struct lys_node_rpc_action *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002128 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002129 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002130
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002131 /* we cannot just duplicate memory since the strings are stored in
2132 * dictionary and we need to update dictionary counters.
2133 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002134
Radek Krejci1d82ef62015-08-07 14:44:40 +02002135 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002136 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002138 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 break;
2140
Radek Krejci76512572015-08-04 09:47:08 +02002141 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002143 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 break;
2145
Radek Krejci76512572015-08-04 09:47:08 +02002146 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002147 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002148 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 break;
2150
Radek Krejci76512572015-08-04 09:47:08 +02002151 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002152 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002153 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 break;
2155
Radek Krejci76512572015-08-04 09:47:08 +02002156 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002157 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002158 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 break;
2160
Radek Krejci76512572015-08-04 09:47:08 +02002161 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002162 case LYS_ANYDATA:
2163 any = calloc(1, sizeof *any);
2164 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002165 break;
2166
Radek Krejci76512572015-08-04 09:47:08 +02002167 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002168 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002169 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 break;
2171
Radek Krejci76512572015-08-04 09:47:08 +02002172 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002174 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002175 break;
2176
Radek Krejci76512572015-08-04 09:47:08 +02002177 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002178 grp = calloc(1, sizeof *grp);
2179 retval = (struct lys_node *)grp;
2180 break;
2181
Radek Krejci76512572015-08-04 09:47:08 +02002182 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002183 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002184 rpc = calloc(1, sizeof *rpc);
2185 retval = (struct lys_node *)rpc;
2186 break;
2187
Radek Krejci76512572015-08-04 09:47:08 +02002188 case LYS_INPUT:
2189 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002190 io = calloc(1, sizeof *io);
2191 retval = (struct lys_node *)io;
2192 break;
2193
Radek Krejci76512572015-08-04 09:47:08 +02002194 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002195 ntf = calloc(1, sizeof *ntf);
2196 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002197 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002200 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002201 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 }
Radek Krejcib388c152015-06-04 17:03:03 +02002203
Michal Vasko253035f2015-12-17 16:58:13 +01002204 if (!retval) {
2205 LOGMEM;
2206 return NULL;
2207 }
2208
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 /*
2210 * duplicate generic part of the structure
2211 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002212 retval->name = lydict_insert(ctx, node->name, 0);
2213 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2214 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002215 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002216 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002218 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002219 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002221 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002222
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002223 retval->iffeature_size = node->iffeature_size;
2224 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2225 if (!retval->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002226 LOGMEM;
2227 goto error;
2228 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002229
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002230 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002231 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002232 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2233 if (size1) {
2234 /* there is something to duplicate */
2235
2236 /* duplicate compiled expression */
2237 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2238 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2239 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2240
2241 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02002242 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Radek Krejci9ff0a922016-07-14 13:08:05 +02002243 for (j = 0; (unsigned int)j < size2; j++) {
2244 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2245 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02002246 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002247 /* feature is resolved in origin, so copy it
2248 * - duplication is used for instantiating groupings
2249 * and if-feature inside grouping is supposed to be
2250 * resolved inside the original grouping, so we want
2251 * to keep pointers to features from the grouping
2252 * context */
2253 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2254 } else if (rc == -1) {
2255 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02002256 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02002257 }
2258 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002259 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002260
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002261 /* connect it to the parent */
2262 if (lys_node_addchild(parent, retval->module, retval)) {
2263 goto error;
2264 }
Radek Krejcidce51452015-06-16 15:20:08 +02002265
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002266 /* go recursively */
2267 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2268 LY_TREE_FOR(node->child, child) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002269 if (!lys_node_dup(module, retval, child, retval->nacm, unres, 0)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002270 goto error;
2271 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002272 }
2273 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002274 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002275 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002276 }
2277
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002278 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 * duplicate specific part of the structure
2280 */
2281 switch (node->nodetype) {
2282 case LYS_CONTAINER:
2283 if (cont_orig->when) {
2284 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 }
2286 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002288 cont->must_size = cont_orig->must_size;
2289 cont->tpdf_size = cont_orig->tpdf_size;
2290
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002291 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskodcf98e62016-05-05 17:53:53 +02002292 cont->tpdf = lys_tpdf_dup(module, lys_parent(node), cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002293 break;
2294
2295 case LYS_CHOICE:
2296 if (choice_orig->when) {
2297 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002298 }
2299
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002300 if (!shallow) {
2301 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002302 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
2303 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
2304 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002305 if (rc) {
2306 if (rc == EXIT_FAILURE) {
2307 LOGINT;
2308 }
2309 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002310 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002311 } else {
2312 /* useless to check return value, we don't know whether
2313 * there really wasn't any default defined or it just hasn't
2314 * been resolved, we just hope for the best :)
2315 */
2316 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002317 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002318 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002319 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002320 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 break;
2322
2323 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002324 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002325 goto error;
2326 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002327 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2328
2329 if (leaf_orig->dflt) {
2330 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci48464ed2016-03-17 15:44:09 +01002331 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002332 goto error;
2333 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 }
2335
2336 leaf->must_size = leaf_orig->must_size;
2337 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002338
2339 if (leaf_orig->when) {
2340 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002341 }
2342 break;
2343
2344 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002345 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002346 goto error;
2347 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002348 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2349
2350 llist->min = llist_orig->min;
2351 llist->max = llist_orig->max;
2352
2353 llist->must_size = llist_orig->must_size;
2354 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002355
2356 if (llist_orig->when) {
2357 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002358 }
2359 break;
2360
2361 case LYS_LIST:
2362 list->min = list_orig->min;
2363 list->max = list_orig->max;
2364
2365 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002366 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002367
Radek Krejci581ce772015-11-10 17:22:40 +01002368 list->tpdf_size = list_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002369 list->tpdf = lys_tpdf_dup(module, lys_parent(node), list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002370
Radek Krejci581ce772015-11-10 17:22:40 +01002371 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002372 if (list->keys_size) {
2373 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002374 if (!list->keys) {
2375 LOGMEM;
2376 goto error;
2377 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002378
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002379 if (!shallow) {
2380 /* we managed to resolve it before, resolve it again manually */
2381 if (list_orig->keys[0]) {
2382 for (i = 0; i < list->keys_size; ++i) {
2383 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2384 (const struct lys_node **)&list->keys[i]);
2385 if (rc) {
2386 if (rc == EXIT_FAILURE) {
2387 LOGINT;
2388 }
2389 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002390 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002391 }
2392 /* it was not resolved yet, add unres copy */
2393 } else {
2394 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2395 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002396 goto error;
2397 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002398 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002399 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002400 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002401 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002402 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002403
Radek Krejci581ce772015-11-10 17:22:40 +01002404 list->unique_size = list_orig->unique_size;
2405 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002406 if (!list->unique) {
2407 LOGMEM;
2408 goto error;
2409 }
Radek Krejci581ce772015-11-10 17:22:40 +01002410 for (i = 0; i < list->unique_size; ++i) {
2411 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2412 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002413 if (!list->unique[i].expr) {
2414 LOGMEM;
2415 goto error;
2416 }
Radek Krejci581ce772015-11-10 17:22:40 +01002417 for (j = 0; j < list->unique[i].expr_size; j++) {
2418 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2419
2420 /* if it stays in unres list, duplicate it also there */
Radek Krejcid09d1a52016-08-11 14:05:45 +02002421 unique_info = malloc(sizeof *unique_info);
2422 unique_info->list = (struct lys_node *)list;
2423 unique_info->expr = list->unique[i].expr[j];
2424 unique_info->trg_type = &list->unique[i].trg_type;
2425 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002426 }
2427 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002429 if (list_orig->when) {
2430 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002431 }
Radek Krejcidce51452015-06-16 15:20:08 +02002432 break;
2433
2434 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002435 case LYS_ANYDATA:
2436 any->must_size = any_orig->must_size;
2437 any->must = lys_restr_dup(ctx, any_orig->must, any->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002438
Radek Krejcibf2abff2016-08-23 15:51:52 +02002439 if (any_orig->when) {
2440 any->when = lys_when_dup(ctx, any_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002441 }
2442 break;
2443
2444 case LYS_USES:
2445 uses->grp = uses_orig->grp;
2446
2447 if (uses_orig->when) {
2448 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002449 }
2450
2451 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002452 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002453 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002454 if (!shallow) {
2455 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskocda51712016-05-19 15:22:11 +02002456 if (!uses->grp || uses->grp->nacm) {
2457 assert(!uses->child);
Radek Krejci48464ed2016-03-17 15:44:09 +01002458 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002459 goto error;
2460 }
Michal Vasko49168a22015-08-17 16:35:41 +02002461 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002462 } else {
2463 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002464 }
2465 break;
2466
Radek Krejcidce51452015-06-16 15:20:08 +02002467 case LYS_CASE:
2468 if (cs_orig->when) {
2469 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002470 }
2471 break;
2472
2473 case LYS_GROUPING:
2474 grp->tpdf_size = grp_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002475 grp->tpdf = lys_tpdf_dup(module, lys_parent(node), grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002476 break;
2477
2478 case LYS_RPC:
2479 rpc->tpdf_size = rpc_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002480 rpc->tpdf = lys_tpdf_dup(module, lys_parent(node), rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002481 break;
2482
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002483 case LYS_INPUT:
2484 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002485 io->tpdf_size = io_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002486 io->tpdf = lys_tpdf_dup(module, lys_parent(node), io_orig->tpdf, io->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002487 break;
2488
Radek Krejcida04f4a2015-05-21 12:54:09 +02002489 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002490 ntf->tpdf_size = ntf_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002491 ntf->tpdf = lys_tpdf_dup(module, lys_parent(node), ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002492 break;
2493
2494 default:
2495 /* LY_NODE_AUGMENT */
2496 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002497 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002498 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002499
2500 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002501
2502error:
2503
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002504 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002505 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002506}
2507
Michal Vasko13b15832015-08-19 11:04:48 +02002508void
Michal Vaskoff006c12016-02-17 11:15:19 +01002509lys_node_switch(struct lys_node *dst, struct lys_node *src)
2510{
2511 struct lys_node *child;
2512
Michal Vaskob42b6972016-06-06 14:21:30 +02002513 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01002514
2515 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02002516 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002517 dst->prev->next = src;
2518 }
2519
2520 /* sibling prev */
2521 if (dst->next) {
2522 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02002523 } else {
2524 for (child = dst->prev; child->prev->next; child = child->prev);
2525 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01002526 }
2527
2528 /* next */
2529 src->next = dst->next;
2530 dst->next = NULL;
2531
2532 /* prev */
2533 if (dst->prev != dst) {
2534 src->prev = dst->prev;
2535 }
2536 dst->prev = dst;
2537
2538 /* parent child */
2539 if (dst->parent && (dst->parent->child == dst)) {
2540 dst->parent->child = src;
2541 }
2542
2543 /* parent */
2544 src->parent = dst->parent;
2545 dst->parent = NULL;
2546
2547 /* child parent */
2548 LY_TREE_FOR(dst->child, child) {
2549 if (child->parent == dst) {
2550 child->parent = src;
2551 }
2552 }
2553
2554 /* child */
2555 src->child = dst->child;
2556 dst->child = NULL;
2557}
2558
2559void
Michal Vasko627975a2016-02-11 11:39:03 +01002560lys_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 +02002561{
2562 struct ly_ctx *ctx;
2563 int i;
2564
2565 if (!module) {
2566 return;
2567 }
2568
2569 /* remove schema from the context */
2570 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002571 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002572 for (i = 0; i < ctx->models.used; i++) {
2573 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002574 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002575 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002576 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 +02002577 ctx->models.list[ctx->models.used] = NULL;
2578 /* we are done */
2579 break;
2580 }
2581 }
2582 }
2583
2584 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002585 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002586
2587 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002588 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002589
2590 free(module);
2591}
Radek Krejci7e97c352015-06-19 16:26:34 +02002592
Radek Krejci9de2c042016-10-19 16:53:06 +02002593static void
2594lys_features_disable_recursive(struct lys_feature *f)
2595{
2596 unsigned int i;
2597 struct lys_feature *depf;
2598
2599 /* disable the feature */
2600 f->flags &= ~LYS_FENABLED;
2601
2602 /* by disabling feature we have to disable also all features that depends on this feature */
2603 if (f->depfeatures) {
2604 for (i = 0; i < f->depfeatures->number; i++) {
2605 depf = (struct lys_feature *)f->depfeatures->set.g[i];
2606 if (depf->flags & LYS_FENABLED) {
2607 lys_features_disable_recursive(depf);
2608 }
2609 }
2610 }
2611}
2612
2613
Radek Krejci7e97c352015-06-19 16:26:34 +02002614/*
2615 * op: 1 - enable, 0 - disable
2616 */
2617static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002618lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002619{
2620 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002621 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02002622 int progress, faili, failj, failk;
2623
2624 uint8_t fsize;
2625 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02002626
2627 if (!module || !name || !strlen(name)) {
2628 return EXIT_FAILURE;
2629 }
2630
2631 if (!strcmp(name, "*")) {
2632 /* enable all */
2633 all = 1;
2634 }
2635
Radek Krejcia889c1f2016-10-19 15:50:11 +02002636 progress = failk = 1;
2637 while (progress && failk) {
2638 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
2639 if (i == -1) {
2640 fsize = module->features_size;
2641 f = module->features;
2642 } else {
2643 fsize = module->inc[i].submodule->features_size;
2644 f = module->inc[i].submodule->features;
2645 }
2646
2647 for (j = 0; j < fsize; j++) {
2648 if (all || !strcmp(f[j].name, name)) {
2649 /* skip already set features */
2650 if (op && (f[j].flags & LYS_FENABLED)) {
2651 continue;
2652 } else if (!op && !(f[j].flags & LYS_FENABLED)) {
2653 continue;
2654 }
2655
2656 if (op) {
2657 /* check referenced features if they are enabled */
2658 for (k = 0; k < f[j].iffeature_size; k++) {
2659 if (!resolve_iffeature(&f[j].iffeature[k])) {
2660 if (all) {
2661 faili = i;
2662 failj = j;
2663 failk = k + 1;
2664 break;
2665 } else {
2666 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2667 f[j].name, k + 1);
2668 return EXIT_FAILURE;
2669 }
2670 }
2671 }
2672
2673 if (k == f[j].iffeature_size) {
2674 /* the last check passed, do the change */
2675 f[j].flags |= LYS_FENABLED;
2676 progress++;
2677 }
2678 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02002679 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02002680 progress++;
2681 }
2682 if (!all) {
2683 /* stop in case changing a single feature */
2684 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002685 }
2686 }
Radek Krejci7e97c352015-06-19 16:26:34 +02002687 }
2688 }
2689 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02002690 if (failk) {
2691 /* print info about the last failing feature */
2692 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2693 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
2694 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02002695 }
2696
2697 if (all) {
2698 return EXIT_SUCCESS;
2699 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02002700 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02002701 return EXIT_FAILURE;
2702 }
2703}
2704
2705API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002706lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002707{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002708 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002709}
2710
2711API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002712lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002713{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002714 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002715}
2716
2717API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002718lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002719{
2720 int i, j;
2721
2722 if (!module || !feature) {
2723 return -1;
2724 }
2725
2726 /* search for the specified feature */
2727 /* module itself */
2728 for (i = 0; i < module->features_size; i++) {
2729 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002730 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002731 return 1;
2732 } else {
2733 return 0;
2734 }
2735 }
2736 }
2737
2738 /* submodules */
2739 for (j = 0; j < module->inc_size; j++) {
2740 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2741 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002742 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002743 return 1;
2744 } else {
2745 return 0;
2746 }
2747 }
2748 }
2749 }
2750
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002751 /* feature definition not found */
2752 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002753}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002754
Radek Krejci96a10da2015-07-30 11:00:14 +02002755API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002756lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002757{
Radek Krejci96a10da2015-07-30 11:00:14 +02002758 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002759 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002760 unsigned int count;
2761
2762 if (!module) {
2763 return NULL;
2764 }
2765
2766 count = module->features_size;
2767 for (i = 0; i < module->inc_size; i++) {
2768 count += module->inc[i].submodule->features_size;
2769 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002770 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002771 if (!result) {
2772 LOGMEM;
2773 return NULL;
2774 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002775 if (states) {
2776 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002777 if (!(*states)) {
2778 LOGMEM;
2779 free(result);
2780 return NULL;
2781 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002782 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002783 count = 0;
2784
2785 /* module itself */
2786 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002787 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002788 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002789 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002790 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002791 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002792 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002793 }
2794 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002795 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002796 }
2797
2798 /* submodules */
2799 for (j = 0; j < module->inc_size; j++) {
2800 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002801 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002802 if (states) {
2803 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2804 (*states)[count] = 1;
2805 } else {
2806 (*states)[count] = 0;
2807 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002808 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002809 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002810 }
2811 }
2812
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002813 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002814 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002815
2816 return result;
2817}
Michal Vaskobaefb032015-09-24 14:52:10 +02002818
Radek Krejci6910a032016-04-13 10:06:21 +02002819API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002820lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002821{
2822 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2823}
2824
Radek Krejci6910a032016-04-13 10:06:21 +02002825API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02002826lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01002827{
2828 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2829}
2830
Michal Vaskobaefb032015-09-24 14:52:10 +02002831API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002832lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002833{
2834 if (!node || !node->parent) {
2835 return NULL;
2836 }
2837
2838 if (node->parent->nodetype == LYS_AUGMENT) {
2839 return ((struct lys_node_augment *)node->parent)->target;
2840 }
2841
2842 return node->parent;
2843}
Michal Vasko1b229152016-01-13 11:28:38 +01002844
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002845API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002846lys_set_private(const struct lys_node *node, void *priv)
2847{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002848 void *prev;
2849
Michal Vasko1b229152016-01-13 11:28:38 +01002850 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002851 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2852 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002853 }
2854
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002855 prev = node->priv;
2856 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002857
2858 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002859}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002860
Michal Vasko01c6fd22016-05-20 11:43:05 +02002861int
2862lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
2863{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02002864 struct lys_node_leaf *iter = leafref_target;
2865
Michal Vasko48a573d2016-07-01 11:46:02 +02002866 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02002867 LOGINT;
2868 return -1;
2869 }
2870
Pavol Vican93175152016-08-30 15:34:44 +02002871 /* check for config flag */
2872 if ((leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
2873 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leafref,
2874 "The %s is config but refers to a non-config %s.",
2875 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
2876 return -1;
2877 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02002878 /* check for cycles */
2879 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
2880 if ((void *)iter == (void *)leafref) {
2881 /* cycle detected */
2882 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
2883 return -1;
2884 }
2885 iter = iter->type.info.lref.target;
2886 }
2887
2888 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02002889 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02002890 if (!leafref_target->backlinks) {
2891 leafref_target->backlinks = (void*)ly_set_new();
2892 if (!leafref_target->backlinks) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02002893 LOGMEM;
2894 return -1;
2895 }
2896 }
Radek Krejci85a54be2016-10-20 12:39:56 +02002897 ly_set_add((struct ly_set *)leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02002898
2899 return 0;
2900}
2901
Michal Vasko8548e082016-07-22 12:00:18 +02002902/* not needed currently */
2903#if 0
2904
Michal Vasko5b3492c2016-07-20 09:37:40 +02002905static const char *
2906lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
2907{
2908 struct lys_module *prev_mod;
2909 uint32_t str_len, mod_len, buf_idx;
2910
Radek Krejcibf2abff2016-08-23 15:51:52 +02002911 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02002912 LOGINT;
2913 return NULL;
2914 }
2915
2916 buf_idx = buf_len - 1;
2917 buf[buf_idx] = '\0';
2918
2919 while (node) {
2920 if (lys_parent(node)) {
2921 prev_mod = lys_node_module(lys_parent(node));
2922 } else {
2923 prev_mod = NULL;
2924 }
2925
Radek Krejcibf2abff2016-08-23 15:51:52 +02002926 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02002927 str_len = strlen(node->name);
2928
2929 if (prev_mod != node->module) {
2930 mod_len = strlen(node->module->name);
2931 } else {
2932 mod_len = 0;
2933 }
2934
2935 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
2936 LOGINT;
2937 return NULL;
2938 }
2939
2940 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
2941
2942 buf[buf_idx] = '/';
2943 if (mod_len) {
2944 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
2945 buf[buf_idx + 1 + mod_len] = ':';
2946 }
2947 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
2948 }
2949
2950 node = lys_parent(node);
2951 }
2952
2953 return buf + buf_idx;
2954}
2955
Michal Vasko8548e082016-07-22 12:00:18 +02002956#endif
2957
2958API struct ly_set *
Michal Vaskof06fb5b2016-09-08 10:05:56 +02002959lys_find_xpath(const struct lys_node *node, const char *expr, int options)
Michal Vasko46a4bf92016-09-08 08:23:49 +02002960{
2961 struct lyxp_set set;
2962 struct ly_set *ret_set;
2963 uint32_t i;
Michal Vaskodb1da032016-09-08 10:07:38 +02002964 int opts;
Michal Vasko46a4bf92016-09-08 08:23:49 +02002965
2966 if (!node || !expr) {
2967 ly_errno = LY_EINVAL;
2968 return NULL;
2969 }
2970
2971 memset(&set, 0, sizeof set);
2972
Michal Vaskodb1da032016-09-08 10:07:38 +02002973 opts = LYXP_SNODE;
2974 if (options & LYS_FIND_OUTPUT) {
2975 opts |= LYXP_SNODE_OUTPUT;
2976 }
2977
Michal Vasko46a4bf92016-09-08 08:23:49 +02002978 /* node and nodetype won't matter at all since it is absolute */
Michal Vaskodb1da032016-09-08 10:07:38 +02002979 if (lyxp_atomize(expr, node, LYXP_NODE_ELEM, &set, opts)) {
Michal Vasko46a4bf92016-09-08 08:23:49 +02002980 free(set.val.snodes);
2981 return NULL;
2982 }
2983
2984 ret_set = ly_set_new();
2985
2986 for (i = 0; i < set.used; ++i) {
2987 if (!set.val.snodes[i].in_ctx) {
2988 continue;
2989 }
2990 assert(set.val.snodes[i].in_ctx == 1);
2991
2992 switch (set.val.snodes[i].type) {
2993 case LYXP_NODE_ELEM:
2994 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
2995 ly_set_free(ret_set);
2996 free(set.val.snodes);
2997 return NULL;
2998 }
2999 break;
3000 default:
3001 /* ignore roots, text and attr should not ever appear */
3002 break;
3003 }
3004 }
3005
3006 free(set.val.snodes);
3007 return ret_set;
3008}
3009
3010API struct ly_set *
Michal Vasko508a50d2016-09-07 14:50:33 +02003011lys_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 +02003012{
Michal Vasko508a50d2016-09-07 14:50:33 +02003013 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02003014 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003015 uint32_t i;
3016
Michal Vaskob94a5e42016-09-08 14:01:56 +02003017 if (!cur_snode || !expr) {
Michal Vasko8548e082016-07-22 12:00:18 +02003018 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003019 }
3020
Michal Vaskob94a5e42016-09-08 14:01:56 +02003021 /* adjust the root */
3022 if ((cur_snode_type == LYXP_NODE_ROOT) || (cur_snode_type == LYXP_NODE_ROOT_CONFIG)) {
3023 do {
3024 cur_snode = lys_getnext(NULL, NULL, lys_node_module(cur_snode), 0);
3025 } while ((cur_snode_type == LYXP_NODE_ROOT_CONFIG) && (cur_snode->flags & LYS_CONFIG_R));
3026 }
3027
Michal Vasko508a50d2016-09-07 14:50:33 +02003028 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02003029
3030 if (options & LYXP_MUST) {
3031 options &= ~LYXP_MUST;
3032 options |= LYXP_SNODE_MUST;
3033 } else if (options & LYXP_WHEN) {
3034 options &= ~LYXP_WHEN;
3035 options |= LYXP_SNODE_WHEN;
3036 } else {
3037 options |= LYXP_SNODE;
3038 }
3039
Michal Vasko508a50d2016-09-07 14:50:33 +02003040 if (lyxp_atomize(expr, cur_snode, cur_snode_type, &set, options)) {
3041 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02003042 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003043 }
3044
Michal Vasko8548e082016-07-22 12:00:18 +02003045 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003046
Michal Vasko508a50d2016-09-07 14:50:33 +02003047 for (i = 0; i < set.used; ++i) {
3048 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003049 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02003050 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02003051 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02003052 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02003053 return NULL;
3054 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003055 break;
3056 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02003057 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003058 break;
3059 }
3060 }
3061
Michal Vasko508a50d2016-09-07 14:50:33 +02003062 free(set.val.snodes);
3063 return ret_set;
3064}
3065
3066API struct ly_set *
3067lys_node_xpath_atomize(const struct lys_node *node, int options)
3068{
3069 const struct lys_node *next, *elem, *parent, *tmp;
3070 struct lyxp_set set;
3071 struct ly_set *ret_set;
3072 uint16_t i;
3073
3074 if (!node) {
3075 return NULL;
3076 }
3077
3078 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
3079 if (!parent) {
3080 /* not in input, output, or notification */
3081 return NULL;
3082 }
3083
3084 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02003085 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003086 return NULL;
3087 }
3088
3089 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoe9914d12016-10-07 14:32:37 +02003090 if ((options & LYXP_NO_LOCAL) && !(elem->flags & LYS_VALID_DEP)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003091 /* elem has no dependencies from other subtrees and local nodes get discarded */
3092 goto next_iter;
3093 }
3094
3095 if (lyxp_node_atomize(elem, &set)) {
3096 ly_set_free(ret_set);
3097 free(set.val.snodes);
3098 return NULL;
3099 }
3100
3101 for (i = 0; i < set.used; ++i) {
3102 switch (set.val.snodes[i].type) {
3103 case LYXP_NODE_ELEM:
3104 if (options & LYXP_NO_LOCAL) {
3105 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
3106 if (tmp) {
3107 /* in local subtree, discard */
3108 break;
3109 }
3110 }
3111 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
3112 ly_set_free(ret_set);
3113 free(set.val.snodes);
3114 return NULL;
3115 }
3116 break;
3117 default:
3118 /* ignore roots, text and attr should not ever appear */
3119 break;
3120 }
3121 }
3122
3123 free(set.val.snodes);
3124 if (!(options & LYXP_RECURSIVE)) {
3125 break;
3126 }
3127next_iter:
3128 LY_TREE_DFS_END(node, next, elem);
3129 }
3130
Michal Vasko8548e082016-07-22 12:00:18 +02003131 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003132}
3133
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003134static void
Michal Vasko89563fc2016-07-28 16:19:35 +02003135lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *target_module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003136{
3137 int ret;
3138 char *parent_path;
3139 struct lys_node *target;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003140
Pavol Vican64d0b762016-08-25 10:44:59 +02003141 if (!dev->deviate) {
3142 return ;
3143 }
3144
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003145 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
3146 if (dev->orig_node) {
3147 /* removing not-supported deviation ... */
3148 if (strrchr(dev->target_name, '/') != dev->target_name) {
3149 /* ... from a parent */
3150 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
3151
3152 target = NULL;
3153 ret = resolve_augment_schema_nodeid(parent_path, NULL, target_module, (const struct lys_node **)&target);
3154 free(parent_path);
3155 if (ret || !target) {
3156 LOGINT;
3157 return;
3158 }
3159
3160 lys_node_addchild(target, NULL, dev->orig_node);
3161 } else {
3162 /* ... from top-level data */
3163 lys_node_addchild(NULL, (struct lys_module *)target_module, dev->orig_node);
3164 }
3165
3166 dev->orig_node = NULL;
3167 } else {
3168 /* adding not-supported deviation */
3169 target = NULL;
3170 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
3171 if (ret || !target) {
3172 LOGINT;
3173 return;
3174 }
3175
3176 lys_node_unlink(target);
3177 dev->orig_node = target;
3178 }
3179 } else {
3180 target = NULL;
3181 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
3182 if (ret || !target) {
3183 LOGINT;
3184 return;
3185 }
3186
3187 lys_node_switch(target, dev->orig_node);
3188 dev->orig_node = target;
3189 }
3190}
3191
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003192/* temporarily removes or applies deviations, updates module deviation flag accordingly */
3193void
3194lys_switch_deviations(struct lys_module *module)
3195{
Michal Vasko89563fc2016-07-28 16:19:35 +02003196 uint32_t i = 0, j;
3197 const struct lys_module *mod;
3198 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003199
Michal Vasko89563fc2016-07-28 16:19:35 +02003200 if (module->deviated) {
3201 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3202 if (mod == module) {
3203 continue;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003204 }
3205
Michal Vasko89563fc2016-07-28 16:19:35 +02003206 for (j = 0; j < mod->deviation_size; ++j) {
3207 ptr = strstr(mod->deviation[j].target_name, module->name);
3208 if (ptr && ptr[strlen(module->name)] == ':') {
3209 lys_switch_deviation(&mod->deviation[j], module);
3210 }
3211 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003212 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003213
Michal Vasko89563fc2016-07-28 16:19:35 +02003214 if (module->deviated == 2) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003215 module->deviated = 1;
Michal Vasko89563fc2016-07-28 16:19:35 +02003216 } else {
3217 module->deviated = 2;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003218 }
3219 }
3220}
3221
3222/* not needed currently, but tested and working */
3223#if 0
3224
3225void
3226lys_sub_module_apply_devs_augs(struct lys_module *module)
3227{
3228 int i;
3229 struct lys_node_augment *aug;
3230 struct lys_node *last;
3231
3232 /* re-apply deviations */
3233 for (i = 0; i < module->deviation_size; ++i) {
3234 lys_switch_deviation(&module->deviation[i], module);
3235 assert(module->deviation[i].orig_node);
Michal Vasko89563fc2016-07-28 16:19:35 +02003236 lys_node_module(module->deviation[i].orig_node)->deviated = 1;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003237 }
3238
3239 /* re-apply augments */
3240 for (i = 0; i < module->augment_size; ++i) {
3241 aug = &module->augment[i];
3242 assert(aug->target);
3243
3244 /* reconnect augmenting data into the target - add them to the target child list */
3245 if (aug->target->child) {
3246 last = aug->target->child->prev;
3247 last->next = aug->child;
3248 aug->target->child->prev = aug->child->prev;
3249 aug->child->prev = last;
3250 } else {
3251 aug->target->child = aug->child;
3252 }
3253 }
3254}
3255
3256#endif
3257
3258void
3259lys_sub_module_remove_devs_augs(struct lys_module *module)
3260{
Michal Vasko89563fc2016-07-28 16:19:35 +02003261 uint32_t i = 0, j;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003262 struct lys_node *last, *elem;
Michal Vasko89563fc2016-07-28 16:19:35 +02003263 const struct lys_module *mod;
3264 struct lys_module *target_mod;
3265 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003266
3267 /* remove applied deviations */
3268 for (i = 0; i < module->deviation_size; ++i) {
Pavol Vican64d0b762016-08-25 10:44:59 +02003269 if (module->deviation[i].orig_node) {
3270 target_mod = lys_node_module(module->deviation[i].orig_node);
3271 } else {
3272 target_mod = (struct lys_module *)lys_get_import_module(module, NULL, 0, module->deviation[i].target_name + 1,
3273 strcspn(module->deviation[i].target_name, ":") - 1);
Radek Krejci0fa54e92016-09-14 14:01:05 +02003274 target_mod = (struct lys_module *)lys_get_implemented_module(target_mod);
Pavol Vican64d0b762016-08-25 10:44:59 +02003275 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003276 lys_switch_deviation(&module->deviation[i], module);
3277
Michal Vasko89563fc2016-07-28 16:19:35 +02003278 /* clear the deviation flag if possible */
3279 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3280 if ((mod == module) || (mod == target_mod)) {
3281 continue;
3282 }
3283
3284 for (j = 0; j < mod->deviation_size; ++j) {
3285 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
3286 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
3287 /* some other module deviation targets the inspected module, flag remains */
3288 break;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003289 }
3290 }
Michal Vasko89563fc2016-07-28 16:19:35 +02003291
3292 if (j < mod->deviation_size) {
3293 break;
3294 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003295 }
Michal Vasko89563fc2016-07-28 16:19:35 +02003296
3297 if (!mod) {
3298 target_mod->deviated = 0;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003299 }
3300 }
3301
3302 /* remove applied augments */
3303 for (i = 0; i < module->augment_size; ++i) {
Radek Krejcidbc15262016-06-16 14:58:29 +02003304 if (!module->augment[i].target) {
3305 /* skip not resolved augments */
3306 continue;
3307 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003308
3309 elem = module->augment[i].child;
3310 if (elem) {
3311 LY_TREE_FOR(elem, last) {
3312 if (!last->next || (last->next->parent != (struct lys_node *)&module->augment[i])) {
3313 break;
3314 }
3315 }
3316 /* elem is first augment child, last is the last child */
3317
3318 /* parent child ptr */
3319 if (module->augment[i].target->child == elem) {
3320 module->augment[i].target->child = last->next;
3321 }
3322
3323 /* parent child next ptr */
3324 if (elem->prev->next) {
3325 elem->prev->next = last->next;
3326 }
3327
3328 /* parent child prev ptr */
3329 if (last->next) {
3330 last->next->prev = elem->prev;
3331 } else if (module->augment[i].target->child) {
3332 module->augment[i].target->child->prev = elem->prev;
3333 }
3334
3335 /* update augment children themselves */
3336 elem->prev = last;
3337 last->next = NULL;
3338 }
Michal Vaskob8f71322016-05-03 11:39:56 +02003339
3340 /* needs to be NULL for lys_augment_free() to free the children */
3341 module->augment[i].target = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003342 }
3343}
3344
Radek Krejci27fe55e2016-09-13 17:13:35 +02003345static int
3346lys_set_implemented_recursion(struct lys_module *module, struct unres_schema *unres)
3347{
3348 struct lys_node *root, *next, *node;
3349 uint8_t i;
3350
3351 for (i = 0; i < module->augment_size; i++) {
3352 /* apply augment */
Michal Vaskoa1911b92016-09-19 14:57:34 +02003353 if (!module->augment[i].target
3354 && (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02003355 return -1;
3356 }
3357 }
3358 LY_TREE_FOR(module->data, root) {
3359 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
3360 LY_TREE_DFS_BEGIN(root, next, node) {
3361 if (node->nodetype == LYS_GROUPING) {
3362 goto nextsibling;
3363 }
3364 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
3365 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
3366 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
3367 UNRES_TYPE_LEAFREF, node) == -1) {
3368 return EXIT_FAILURE;
3369 }
3370 }
3371 }
3372
3373 /* modified LY_TREE_DFS_END */
3374 next = node->child;
3375 /* child exception for leafs, leaflists and anyxml without children */
3376 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
3377 next = NULL;
3378 }
3379 if (!next) {
3380nextsibling:
3381 /* no children */
3382 if (node == root) {
3383 /* we are done, root has no children */
3384 break;
3385 }
3386 /* try siblings */
3387 next = node->next;
3388 }
3389 while (!next) {
3390 /* parent is already processed, go to its sibling */
3391 node = lys_parent(node);
3392 /* no siblings, go back through parents */
3393 if (lys_parent(node) == lys_parent(root)) {
3394 /* we are done, no next element to process */
3395 break;
3396 }
3397 next = node->next;
3398 }
3399 }
3400 }
3401
3402 return EXIT_SUCCESS;
3403}
3404
3405API int
3406lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02003407{
3408 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02003409 struct unres_schema *unres;
3410 int i, j;
Michal Vasko26055752016-05-03 11:36:31 +02003411
Radek Krejci27fe55e2016-09-13 17:13:35 +02003412 if (!module) {
3413 ly_errno = LY_EINVAL;
3414 return EXIT_FAILURE;
3415 }
3416
3417 module = lys_main_module(module);
Michal Vasko26055752016-05-03 11:36:31 +02003418 if (module->implemented) {
3419 return EXIT_SUCCESS;
3420 }
3421
3422 ctx = module->ctx;
3423
3424 for (i = 0; i < ctx->models.used; ++i) {
3425 if (module == ctx->models.list[i]) {
3426 continue;
3427 }
3428
3429 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
3430 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
3431 return EXIT_FAILURE;
3432 }
3433 }
3434
Radek Krejci27fe55e2016-09-13 17:13:35 +02003435 unres = calloc(1, sizeof *unres);
3436 if (!unres) {
3437 LOGMEM;
3438 return EXIT_FAILURE;
3439 }
3440 /* recursively make the module implemented */
3441 ((struct lys_module *)module)->implemented = 1;
3442 if (lys_set_implemented_recursion((struct lys_module *)module, unres)) {
3443 goto error;
3444 }
3445 /* process augments in submodules */
3446 for (i = 0; i < module->inc_size; ++i) {
3447 if (!module->inc[i].submodule) {
3448 continue;
3449 }
3450 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
3451 /* apply augment */
Michal Vaskoa1911b92016-09-19 14:57:34 +02003452 if (!module->inc[i].submodule->augment[i].target
3453 && (unres_schema_add_node((struct lys_module *)module->inc[i].submodule, unres,
3454 &module->inc[i].submodule->augment[i], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02003455 goto error;
3456 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003457 }
3458 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003459 /* resolve rest of unres items */
3460 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
3461 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003462 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003463 unres_schema_free((struct lys_module *)module, &unres);
Michal Vasko26055752016-05-03 11:36:31 +02003464
3465 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02003466
3467error:
3468 ((struct lys_module *)module)->implemented = 0;
3469 unres_schema_free((struct lys_module *)module, &unres);
3470 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003471}
3472
3473void
3474lys_submodule_module_data_free(struct lys_submodule *submodule)
3475{
3476 struct lys_node *next, *elem;
3477
3478 /* remove parsed data */
3479 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
3480 if (elem->module == (struct lys_module *)submodule) {
3481 lys_node_free(elem, NULL, 0);
3482 }
3483 }
3484}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02003485
3486int
3487lys_is_key(struct lys_node_list *list, struct lys_node_leaf *leaf)
3488{
3489 uint8_t i;
3490
3491 for (i = 0; i < list->keys_size; i++) {
3492 if (list->keys[i] == leaf) {
3493 return i + 1;
3494 }
3495 }
3496
3497 return 0;
3498}
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02003499
3500API char *
3501lys_path(const struct lys_node *node)
3502{
3503 char *buf_backup = NULL, *buf = ly_buf(), *result = NULL;
3504 uint16_t index = LY_BUF_SIZE - 1;
3505
3506 if (!node) {
3507 LOGERR(LY_EINVAL, "%s: NULL node parameter", __func__);
3508 return NULL;
3509 }
3510
3511 /* backup the shared internal buffer */
3512 if (ly_buf_used && buf[0]) {
3513 buf_backup = strndup(buf, LY_BUF_SIZE - 1);
3514 }
3515 ly_buf_used++;
3516
3517 /* build the path */
3518 buf[index] = '\0';
3519 ly_vlog_build_path_reverse(LY_VLOG_LYS, node, buf, &index);
3520 result = strdup(&buf[index]);
3521
3522 /* restore the shared internal buffer */
3523 if (buf_backup) {
3524 strcpy(buf, buf_backup);
3525 free(buf_backup);
3526 }
3527 ly_buf_used--;
3528
3529 return result;
3530}