blob: a7f866cca4c4301a5bc6e1434963d0f196b17594 [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 Krejci41a349b2016-10-24 19:21:59 +0200640 struct lys_node_inout *in, *out, *inout;
Radek Krejci07911992015-08-14 15:13:31 +0200641 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200642
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200643 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200644
Radek Krejci10c760e2015-08-14 14:45:43 +0200645 if (parent) {
646 type = parent->nodetype;
647 module = parent->module;
648 } else {
649 assert(module);
Radek Krejcife3a1382016-11-04 10:30:11 +0100650 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
Radek Krejci10c760e2015-08-14 14:45:43 +0200651 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200652 }
653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200654 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200655 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200656 case LYS_CONTAINER:
657 case LYS_LIST:
658 case LYS_GROUPING:
Radek Krejci96935402016-11-04 16:27:28 +0100659 case LYS_USES:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200660 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200661 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200662 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200663 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
664 return EXIT_FAILURE;
665 }
666 break;
Radek Krejci76512572015-08-04 09:47:08 +0200667 case LYS_INPUT:
668 case LYS_OUTPUT:
669 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200670 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200671 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200672 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100673 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200674 return EXIT_FAILURE;
675 }
676 break;
Radek Krejci76512572015-08-04 09:47:08 +0200677 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200678 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200679 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100680 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200681 return EXIT_FAILURE;
682 }
683 break;
Radek Krejci76512572015-08-04 09:47:08 +0200684 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200685 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200686 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100687 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200688 return EXIT_FAILURE;
689 }
690 break;
Radek Krejci76512572015-08-04 09:47:08 +0200691 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200692 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200693 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100694 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200695 return EXIT_FAILURE;
696 }
697 break;
Radek Krejci76512572015-08-04 09:47:08 +0200698 case LYS_LEAF:
699 case LYS_LEAFLIST:
700 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200701 case LYS_ANYDATA:
Radek Krejci48464ed2016-03-17 15:44:09 +0100702 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
703 LOGVAL(LYE_SPEC, LY_VLOG_LYS, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100704 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200705 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200706 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200707 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200708 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200709 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100710 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200711 return EXIT_FAILURE;
712 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200713 break;
714 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200715 /* top level */
716 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200717 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200718 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100719 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200720 return EXIT_FAILURE;
721 }
722
Radek Krejcic071c542016-01-27 14:57:51 +0100723 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200724 }
725
726 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200727 if (lys_check_id(child, parent, module)) {
728 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200729 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200731 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200732 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200733 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200734
Radek Krejci41a349b2016-10-24 19:21:59 +0200735 if (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
736 /* replace the implicit input/output node */
737 if (child->nodetype == LYS_OUTPUT) {
738 inout = (struct lys_node_inout *)parent->child->next;
739 } else { /* LYS_INPUT */
740 inout = (struct lys_node_inout *)parent->child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200741 parent->child = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200742 }
743 if (inout->next) {
744 child->next = inout->next;
745 inout->next->prev = child;
746 inout->next = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200747 } else {
Radek Krejci41a349b2016-10-24 19:21:59 +0200748 parent->child->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200749 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200750 child->prev = inout->prev;
751 if (inout->prev->next) {
752 inout->prev->next = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200753 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200754 inout->prev = (struct lys_node *)inout;
755 child->parent = parent;
756 inout->parent = NULL;
757 lys_node_free((struct lys_node *)inout, NULL, 0);
758 } else {
759 /* connect the child correctly */
760 if (!parent) {
761 if (module->data) {
762 module->data->prev->next = child;
763 child->prev = module->data->prev;
764 module->data->prev = child;
765 } else {
766 module->data = child;
767 }
768 } else {
769 if (!parent->child) {
770 /* the only/first child of the parent */
771 parent->child = child;
772 child->parent = parent;
773 iter = child;
774 } else {
775 /* add a new child at the end of parent's child list */
776 iter = parent->child->prev;
777 iter->next = child;
778 child->prev = iter;
779 }
780 while (iter->next) {
781 iter = iter->next;
782 iter->parent = parent;
783 }
784 parent->child->prev = iter;
785 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200786 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200787
Michal Vaskoe022a562016-09-27 14:24:15 +0200788 /* check config value (but ignore them in groupings and augments) */
789 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT)); iter = iter->parent);
790 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200791 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
792 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
793 LOGVAL(LYE_INARG, LY_VLOG_LYS, child, "true", "config");
794 LOGVAL(LYE_SPEC, LY_VLOG_LYS, child, "State nodes cannot have configuration nodes as children.");
795 return EXIT_FAILURE;
796 }
797 }
798
Radek Krejci41771502016-04-14 17:52:32 +0200799 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200800 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200801 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200802 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200803 /* store it only into container or list - the only data inner nodes */
804 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
805 if (iter->flags & LYS_INCL_STATUS) {
806 /* done, someone else set it already from here */
807 break;
808 }
809 /* set flag about including status data */
810 iter->flags |= LYS_INCL_STATUS;
811 }
812 }
813 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200814
815 /* create implicit input/output nodes to have available them as possible target for augment */
816 if (child->nodetype & (LYS_RPC | LYS_ACTION)) {
817 in = calloc(1, sizeof *in);
818 in->nodetype = LYS_INPUT;
819 in->name = lydict_insert(child->module->ctx, "input", 5);
820 out = calloc(1, sizeof *out);
821 out->name = lydict_insert(child->module->ctx, "output", 6);
822 out->nodetype = LYS_OUTPUT;
823 in->module = out->module = child->module;
824 in->parent = out->parent = child;
825 in->flags = out->flags = LYS_IMPLICIT;
826 in->next = (struct lys_node *)out;
827 in->prev = (struct lys_node *)out;
828 out->prev = (struct lys_node *)in;
829 child->child = (struct lys_node *)in;
830 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200831 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200832}
833
Radek Krejcia1df1682016-04-11 14:56:59 +0200834static const struct lys_module *
835lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200836{
Radek Krejcia1df1682016-04-11 14:56:59 +0200837 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200838 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200839 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200840
Radek Krejci00a0e712016-10-26 10:24:46 +0200841 ly_err_clean(1);
Radek Krejcif347abc2016-06-22 10:18:47 +0200842
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200843 if (!ctx || !data) {
844 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
845 return NULL;
846 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200847
Radek Krejcia1df1682016-04-11 14:56:59 +0200848 if (!internal && format == LYS_IN_YANG) {
849 /* enlarge data by 2 bytes for flex */
850 len = strlen(data);
851 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
852 if (!enlarged_data) {
853 LOGMEM;
854 return NULL;
855 }
856 memcpy(enlarged_data, data, len);
857 enlarged_data[len] = enlarged_data[len + 1] = '\0';
858 data = enlarged_data;
859 }
860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200861 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200862 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +0100863 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200864 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200865 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100866 mod = yang_read_module(ctx, data, 0, NULL, 1);
867 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200868 default:
Radek Krejcia1df1682016-04-11 14:56:59 +0200869 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200870 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200871 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200872
Radek Krejcia1df1682016-04-11 14:56:59 +0200873 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200874 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200875}
876
Radek Krejcia1df1682016-04-11 14:56:59 +0200877API const struct lys_module *
878lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
879{
880 return lys_parse_mem_(ctx, data, format, 0);
881}
882
Michal Vasko5a721fd2016-02-16 12:16:48 +0100883struct lys_submodule *
884lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200885{
Michal Vasko5a721fd2016-02-16 12:16:48 +0100886 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200887
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200888 assert(module);
889 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200890
Radek Krejcic071c542016-01-27 14:57:51 +0100891 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +0200892 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200893
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200894 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200895 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +0100896 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200897 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200898 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100899 submod = yang_read_submodule(module, data, 0, unres);
900 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200901 default:
Radek Krejci90a550a2016-04-13 16:00:58 +0200902 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200903 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200904 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200905
Michal Vasko5a721fd2016-02-16 12:16:48 +0100906 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200907}
908
Michal Vasko1e62a092015-12-01 12:27:20 +0100909API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +0100910lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
911{
912 int fd;
913 const struct lys_module *ret;
Radek Krejcid80c8602016-10-25 11:56:03 +0200914 const char *rev, *dot, *filename;
915 size_t len;
Michal Vasko662610a2015-12-07 11:25:45 +0100916
917 if (!ctx || !path) {
918 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
919 return NULL;
920 }
921
922 fd = open(path, O_RDONLY);
923 if (fd == -1) {
924 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
925 return NULL;
926 }
927
928 ret = lys_parse_fd(ctx, fd, format);
929 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +0100930
Radek Krejcid80c8602016-10-25 11:56:03 +0200931 if (!ret) {
932 /* error */
933 return NULL;
934 }
935
936 /* check that name and revision match filename */
937 filename = strrchr(path, '/');
938 if (!filename) {
939 filename = path;
940 } else {
941 filename++;
942 }
943 rev = strchr(filename, '@');
944 dot = strrchr(filename, '.');
945
946 /* name */
947 len = strlen(ret->name);
948 if (strncmp(filename, ret->name, len) ||
949 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Radek Krejcic0c82302016-10-25 14:21:33 +0200950 LOGWRN("File name \"%s\" does not match module name \"%s\".", filename, ret->name);
Radek Krejcid80c8602016-10-25 11:56:03 +0200951 }
952 if (rev) {
953 len = dot - ++rev;
954 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
955 LOGWRN("File name \"%s\" does not match module revision \"%s\".", filename,
956 ret->rev_size ? ret->rev[0].date : "none");
957 }
958 }
959
960 if (!ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +0100961 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +0100962 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +0100963 }
964
Michal Vasko662610a2015-12-07 11:25:45 +0100965 return ret;
966}
967
968API const struct lys_module *
969lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +0200970{
Michal Vasko1e62a092015-12-01 12:27:20 +0100971 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +0200972 struct stat sb;
973 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +0100974 char buf[PATH_MAX];
975 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +0200976
977 if (!ctx || fd < 0) {
978 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
979 return NULL;
980 }
981
Radek Krejci10a833c2015-12-16 15:28:37 +0100982 if (fstat(fd, &sb) == -1) {
983 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
984 return NULL;
985 }
Radek Krejcib051f722016-02-25 15:12:21 +0100986 if (!S_ISREG(sb.st_mode)) {
987 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
988 return NULL;
989 }
990
Michal Vasko164d9012016-04-01 10:16:59 +0200991 if (!sb.st_size) {
992 LOGERR(LY_EINVAL, "File empty.");
993 return NULL;
994 }
995
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100996 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +0100997 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +0100998 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +0100999 return NULL;
1000 }
Radek Krejcia1df1682016-04-11 14:56:59 +02001001 module = lys_parse_mem_(ctx, addr, format, 1);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001002 munmap(addr, sb.st_size + 2);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001003
Radek Krejcia77904e2016-02-25 16:23:45 +01001004 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001005 /* get URI if there is /proc */
1006 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001007 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1008 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1009 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1010 }
1011 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001012 }
Radek Krejcib051f722016-02-25 15:12:21 +01001013 }
1014
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001015 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001016}
1017
Michal Vasko5a721fd2016-02-16 12:16:48 +01001018struct lys_submodule *
1019lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001020{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001021 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001022 struct stat sb;
1023 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001024
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001025 assert(module);
1026 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001027
Radek Krejci10a833c2015-12-16 15:28:37 +01001028 if (fstat(fd, &sb) == -1) {
1029 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001030 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001031 }
Michal Vasko164d9012016-04-01 10:16:59 +02001032
1033 if (!sb.st_size) {
1034 LOGERR(LY_EINVAL, "File empty.");
1035 return NULL;
1036 }
1037
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001038 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001039 if (addr == MAP_FAILED) {
1040 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001041 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001042 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001043 submodule = lys_submodule_parse(module, addr, format, unres);
Pavol Vicanf7cc2852016-03-22 23:27:35 +01001044 munmap(addr, sb.st_size + 2);
Radek Krejciefaeba32015-05-27 14:30:57 +02001045
Michal Vasko5a721fd2016-02-16 12:16:48 +01001046 return submodule;
1047
Radek Krejciefaeba32015-05-27 14:30:57 +02001048}
1049
Radek Krejci1d82ef62015-08-07 14:44:40 +02001050static struct lys_restr *
1051lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001052{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001053 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001054 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001055
Radek Krejci3733a802015-06-19 13:43:21 +02001056 if (!size) {
1057 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001058 }
Radek Krejci3733a802015-06-19 13:43:21 +02001059
1060 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001061 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001062 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001063 return NULL;
1064 }
Radek Krejci3733a802015-06-19 13:43:21 +02001065 for (i = 0; i < size; i++) {
1066 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1067 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1068 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1069 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1070 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1071 }
1072
1073 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001074}
1075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001076void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001077lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001078{
1079 assert(ctx);
1080 if (!restr) {
1081 return;
1082 }
1083
1084 lydict_remove(ctx, restr->expr);
1085 lydict_remove(ctx, restr->dsc);
1086 lydict_remove(ctx, restr->ref);
1087 lydict_remove(ctx, restr->eapptag);
1088 lydict_remove(ctx, restr->emsg);
1089}
1090
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001091static void
1092lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size)
1093{
1094 uint8_t i;
1095
1096 for (i = 0; i < iffeature_size; ++i) {
1097 free(iffeature[i].expr);
1098 free(iffeature[i].features);
1099 }
1100 free(iffeature);
1101}
1102
Michal Vaskob84f88a2015-09-24 13:16:10 +02001103static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001104type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001105 LY_DATA_TYPE base, int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001106{
1107 int i;
1108
1109 switch (base) {
1110 case LY_TYPE_BINARY:
1111 if (old->info.binary.length) {
1112 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
1113 }
1114 break;
1115
1116 case LY_TYPE_BITS:
1117 new->info.bits.count = old->info.bits.count;
1118 if (new->info.bits.count) {
1119 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1120 if (!new->info.bits.bit) {
1121 LOGMEM;
1122 return -1;
1123 }
1124 for (i = 0; i < new->info.bits.count; i++) {
1125 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1126 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1127 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1128 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1129 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1130 }
1131 }
1132 break;
1133
1134 case LY_TYPE_DEC64:
1135 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001136 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001137 if (old->info.dec64.range) {
1138 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
1139 }
1140 break;
1141
1142 case LY_TYPE_ENUM:
1143 new->info.enums.count = old->info.enums.count;
1144 if (new->info.enums.count) {
1145 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1146 if (!new->info.enums.enm) {
1147 LOGMEM;
1148 return -1;
1149 }
1150 for (i = 0; i < new->info.enums.count; i++) {
1151 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1152 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1153 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1154 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1155 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
1156 }
1157 }
1158 break;
1159
1160 case LY_TYPE_IDENT:
Michal Vaskoaffc37f2016-10-10 18:05:03 +00001161 new->info.ident.count = old->info.ident.count;
Michal Vasko878e38d2016-09-05 12:17:53 +02001162 if (old->info.ident.count) {
1163 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
1164 if (!new->info.ident.ref) {
1165 LOGMEM;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001166 return -1;
1167 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001168 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1169 } else {
1170 /* there can be several unresolved base identities, duplicate them all */
1171 i = -1;
1172 while ((i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF)) != -1) {
1173 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
1174 return -1;
1175 }
1176 --i;
1177 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001178 }
1179 break;
1180
1181 case LY_TYPE_INST:
1182 new->info.inst.req = old->info.inst.req;
1183 break;
1184
1185 case LY_TYPE_INT8:
1186 case LY_TYPE_INT16:
1187 case LY_TYPE_INT32:
1188 case LY_TYPE_INT64:
1189 case LY_TYPE_UINT8:
1190 case LY_TYPE_UINT16:
1191 case LY_TYPE_UINT32:
1192 case LY_TYPE_UINT64:
1193 if (old->info.num.range) {
1194 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
1195 }
1196 break;
1197
1198 case LY_TYPE_LEAFREF:
1199 if (old->info.lref.path) {
1200 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko5d631402016-07-21 13:15:15 +02001201 if (!tpdftype && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001202 return -1;
1203 }
1204 }
1205 break;
1206
1207 case LY_TYPE_STRING:
1208 if (old->info.str.length) {
1209 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
1210 }
1211 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
1212 new->info.str.pat_count = old->info.str.pat_count;
1213 break;
1214
1215 case LY_TYPE_UNION:
1216 new->info.uni.count = old->info.uni.count;
1217 if (new->info.uni.count) {
1218 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1219 if (!new->info.uni.types) {
1220 LOGMEM;
1221 return -1;
1222 }
1223 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001224 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 +02001225 return -1;
1226 }
1227 }
1228 }
1229 break;
1230
1231 default:
1232 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1233 break;
1234 }
1235 return EXIT_SUCCESS;
1236}
1237
1238struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001239lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1240 int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001241{
1242 struct yang_type *new;
1243
1244 new = calloc(1, sizeof *new);
1245 if (!new) {
1246 LOGMEM;
1247 return NULL;
1248 }
1249 new->flags = old->flags;
1250 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001251 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001252 new->type = type;
1253 if (!new->name) {
1254 LOGMEM;
1255 goto error;
1256 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001257 if (type_dup(module, parent, type, old->type, new->base, tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001258 new->type->base = new->base;
1259 lys_type_free(module->ctx, new->type);
1260 memset(&new->type->info, 0, sizeof new->type->info);
1261 goto error;
1262 }
1263 return new;
1264
1265 error:
1266 free(new);
1267 return NULL;
1268}
1269
1270static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001271lys_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 +02001272 int tpdftype, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001273{
1274 int i;
1275
Michal Vasko1dca6882015-10-22 14:29:42 +02001276 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001277 new->base = old->base;
1278 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001279 new->parent = (struct lys_tpdf *)parent;
Radek Krejci3733a802015-06-19 13:43:21 +02001280
Michal Vasko878e38d2016-09-05 12:17:53 +02001281 i = unres_schema_find(unres, -1, old, tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001282 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001283 /* HACK (serious one) for unres */
1284 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001285 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001286 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 +02001287 } else {
1288 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1289 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001290 /* all these unres additions can fail even though they did not before */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001291 if (!new->der || unres_schema_add_node(mod, unres, new,
Michal Vasko5d631402016-07-21 13:15:15 +02001292 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001293 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001294 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001295 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001296 }
1297
Radek Krejci3a5501d2016-07-18 22:03:34 +02001298 return type_dup(mod, parent, new, old, new->base, tpdftype, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001299}
1300
1301void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001302lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001303{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001304 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001306 assert(ctx);
1307 if (!type) {
1308 return;
1309 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001310
Michal Vasko1dca6882015-10-22 14:29:42 +02001311 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001313 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001314 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001315 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001316 free(type->info.binary.length);
1317 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001318 case LY_TYPE_BITS:
1319 for (i = 0; i < type->info.bits.count; i++) {
1320 lydict_remove(ctx, type->info.bits.bit[i].name);
1321 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1322 lydict_remove(ctx, type->info.bits.bit[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001323 lys_iffeature_free(type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size);
Radek Krejci994b6f62015-06-18 16:47:27 +02001324 }
1325 free(type->info.bits.bit);
1326 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001327
1328 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001329 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001330 free(type->info.dec64.range);
1331 break;
1332
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001333 case LY_TYPE_ENUM:
1334 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001335 lydict_remove(ctx, type->info.enums.enm[i].name);
1336 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1337 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001338 lys_iffeature_free(type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001339 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001340 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001341 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001342
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001343 case LY_TYPE_INT8:
1344 case LY_TYPE_INT16:
1345 case LY_TYPE_INT32:
1346 case LY_TYPE_INT64:
1347 case LY_TYPE_UINT8:
1348 case LY_TYPE_UINT16:
1349 case LY_TYPE_UINT32:
1350 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001351 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001352 free(type->info.num.range);
1353 break;
1354
Radek Krejcidc4c1412015-06-19 15:39:54 +02001355 case LY_TYPE_LEAFREF:
1356 lydict_remove(ctx, type->info.lref.path);
1357 break;
1358
Radek Krejci3733a802015-06-19 13:43:21 +02001359 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001360 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001361 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001362 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001363 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001364 }
1365 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001366 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001367
Radek Krejcie4c366b2015-07-02 10:11:31 +02001368 case LY_TYPE_UNION:
1369 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001370 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001371 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001372 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001373 break;
1374
Michal Vaskod3282192016-09-05 11:27:57 +02001375 case LY_TYPE_IDENT:
1376 free(type->info.ident.ref);
1377 break;
1378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001379 default:
Michal Vaskod3282192016-09-05 11:27:57 +02001380 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001381 break;
1382 }
Radek Krejci5a065542015-05-22 15:02:07 +02001383}
1384
Radek Krejci1d82ef62015-08-07 14:44:40 +02001385static void
1386lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001387{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001388 assert(ctx);
1389 if (!tpdf) {
1390 return;
1391 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001393 lydict_remove(ctx, tpdf->name);
1394 lydict_remove(ctx, tpdf->dsc);
1395 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001396
Radek Krejci1d82ef62015-08-07 14:44:40 +02001397 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001398
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001399 lydict_remove(ctx, tpdf->units);
1400 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001401}
1402
Michal Vaskob84f88a2015-09-24 13:16:10 +02001403static struct lys_tpdf *
1404lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1405{
1406 struct lys_tpdf *result;
1407 int i, j;
1408
1409 if (!size) {
1410 return NULL;
1411 }
1412
1413 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001414 if (!result) {
1415 LOGMEM;
1416 return NULL;
1417 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001418 for (i = 0; i < size; i++) {
1419 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1420 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1421 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1422 result[i].flags = old[i].flags;
1423 result[i].module = old[i].module;
1424
Radek Krejci3a5501d2016-07-18 22:03:34 +02001425 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), 1, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001426 for (j = 0; j <= i; ++j) {
1427 lys_tpdf_free(mod->ctx, &result[j]);
1428 }
1429 free(result);
1430 return NULL;
1431 }
1432
1433 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1434 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1435 }
1436
1437 return result;
1438}
1439
Radek Krejci1d82ef62015-08-07 14:44:40 +02001440static struct lys_when *
1441lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001442{
Radek Krejci76512572015-08-04 09:47:08 +02001443 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001444
1445 if (!old) {
1446 return NULL;
1447 }
1448
1449 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001450 if (!new) {
1451 LOGMEM;
1452 return NULL;
1453 }
Radek Krejci00768f42015-06-18 17:04:04 +02001454 new->cond = lydict_insert(ctx, old->cond, 0);
1455 new->dsc = lydict_insert(ctx, old->dsc, 0);
1456 new->ref = lydict_insert(ctx, old->ref, 0);
1457
1458 return new;
1459}
1460
Michal Vasko0308dd62015-10-07 09:14:40 +02001461void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001462lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001463{
1464 if (!w) {
1465 return;
1466 }
1467
1468 lydict_remove(ctx, w->cond);
1469 lydict_remove(ctx, w->dsc);
1470 lydict_remove(ctx, w->ref);
1471
1472 free(w);
1473}
1474
Radek Krejcib7f5e412015-08-13 10:15:51 +02001475static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001476lys_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 +02001477{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001478 struct lys_node *next, *sub;
1479
Radek Krejcic071c542016-01-27 14:57:51 +01001480 /* children from a resolved augment are freed under the target node */
Radek Krejci0ec51da2016-12-14 16:42:03 +01001481 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001482 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001483 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001484 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001485 }
1486
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001487 lydict_remove(ctx, aug->target_name);
1488 lydict_remove(ctx, aug->dsc);
1489 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001490
Radek Krejci9ff0a922016-07-14 13:08:05 +02001491 lys_iffeature_free(aug->iffeature, aug->iffeature_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001492
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001493 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001494}
1495
Radek Krejci76512572015-08-04 09:47:08 +02001496static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001497lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001498{
Radek Krejci76512572015-08-04 09:47:08 +02001499 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001500 struct lys_node *old_child, *new_child;
1501 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001502
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001503 if (!size) {
1504 return NULL;
1505 }
Radek Krejci106efc02015-06-10 14:36:27 +02001506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001507 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001508 if (!new) {
1509 LOGMEM;
1510 return NULL;
1511 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001512 for (i = 0; i < size; i++) {
1513 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1514 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1515 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1516 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001517 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001518 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001519
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001520 /* this must succeed, it was already resolved once */
Radek Krejcidf46e222016-11-08 11:57:37 +01001521 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL, 1,
Michal Vasko3edeaf72016-02-11 13:17:43 +01001522 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001523 LOGINT;
1524 free(new);
1525 return NULL;
1526 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001527 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001528
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001529 /* Correct the augment nodes.
1530 * This function can only be called from lys_node_dup() with uses
1531 * being the node duplicated, so we must have a case of grouping
1532 * with a uses with augments. The augmented nodes have already been
1533 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001534 * (it was set to their actual data parent, not an augment), and
1535 * the new augment does not have child pointer to its augment nodes,
1536 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001537 */
1538 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001539 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001540 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001541 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001542 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001543 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001544 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001545 LY_TREE_FOR(old[i].child, old_child) {
1546 /* all augment nodes were connected as siblings, there can be no more after this */
1547 if (old_child->parent != (struct lys_node *)&old[i]) {
1548 break;
1549 }
1550
Radek Krejci749190d2016-02-18 16:26:25 +01001551 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001552
1553 new_child->parent = (struct lys_node *)&new[i];
1554 new_child = new_child->next;
1555 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001556 }
Radek Krejci106efc02015-06-10 14:36:27 +02001557
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001558 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001559}
1560
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001561static const char **
1562lys_dflt_dup(struct ly_ctx *ctx, const char **old, int size)
1563{
1564 int i;
1565 const char **result;
1566
1567 if (!size) {
1568 return NULL;
1569 }
1570
1571 result = calloc(size, sizeof *result);
1572 if (!result) {
1573 LOGMEM;
1574 return NULL;
1575 }
1576
1577 for (i = 0; i < size; i++) {
1578 result[i] = lydict_insert(ctx, old[i], 0);
1579 }
1580 return result;
1581}
1582
Radek Krejci76512572015-08-04 09:47:08 +02001583static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001584lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001585{
Radek Krejci76512572015-08-04 09:47:08 +02001586 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001587 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001588
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001589 if (!size) {
1590 return NULL;
1591 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001593 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001594 if (!result) {
1595 LOGMEM;
1596 return NULL;
1597 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001598 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001599 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001600 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1601 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001602 result[i].flags = old[i].flags;
1603 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001604
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001605 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001606 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001607
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001608 result[i].dflt_size = old[i].dflt_size;
1609 result[i].dflt = lys_dflt_dup(mod->ctx, old[i].dflt, old[i].dflt_size);
1610
1611 if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001612 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001613 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001614 result[i].mod.list = old[i].mod.list;
1615 }
1616 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001617
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001618 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001619}
1620
Radek Krejci1d82ef62015-08-07 14:44:40 +02001621static void
1622lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001623{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001624 assert(ctx);
1625 if (!ident) {
1626 return;
1627 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001628
Radek Krejci018f1f52016-08-03 16:01:20 +02001629 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02001630 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001631 lydict_remove(ctx, ident->name);
1632 lydict_remove(ctx, ident->dsc);
1633 lydict_remove(ctx, ident->ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001634 lys_iffeature_free(ident->iffeature, ident->iffeature_size);
Radek Krejci6793db02015-05-22 17:49:54 +02001635
1636}
1637
Radek Krejci1d82ef62015-08-07 14:44:40 +02001638static void
1639lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001640{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001641 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001642
Radek Krejcid12f57b2015-08-06 10:43:39 +02001643 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001644 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001645 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001646 }
1647 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001648}
1649
Radek Krejci1d82ef62015-08-07 14:44:40 +02001650static void
Michal Vasko44fb6382016-06-29 11:12:27 +02001651lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02001652{
1653 int i;
1654
1655 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1656 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001657 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001658 }
1659 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02001660
1661 for (i = 0; i < io->must_size; i++) {
1662 lys_restr_free(ctx, &io->must[i]);
1663 }
1664 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001665}
1666
Radek Krejci1d82ef62015-08-07 14:44:40 +02001667static void
Pavol Vican7cff97e2016-08-09 14:56:08 +02001668lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif)
1669{
1670 int i;
1671
1672 for (i = 0; i < notif->must_size; i++) {
1673 lys_restr_free(ctx, &notif->must[i]);
1674 }
1675 free(notif->must);
1676
1677 for (i = 0; i < notif->tpdf_size; i++) {
1678 lys_tpdf_free(ctx, &notif->tpdf[i]);
1679 }
1680 free(notif->tpdf);
1681}
1682static void
Radek Krejcibf2abff2016-08-23 15:51:52 +02001683lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001684{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001685 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001687 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001688 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001689 }
1690 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001691
Radek Krejci1d82ef62015-08-07 14:44:40 +02001692 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001693}
1694
Radek Krejci1d82ef62015-08-07 14:44:40 +02001695static void
1696lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001697{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001698 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001699
Radek Krejci85a54be2016-10-20 12:39:56 +02001700 /* leafref backlinks */
1701 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001704 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001705 }
1706 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001707
Radek Krejci1d82ef62015-08-07 14:44:40 +02001708 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001709
Radek Krejci1d82ef62015-08-07 14:44:40 +02001710 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001711 lydict_remove(ctx, leaf->units);
1712 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001713}
1714
Radek Krejci1d82ef62015-08-07 14:44:40 +02001715static void
1716lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001717{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001718 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001719
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001720 if (llist->backlinks) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001721 /* leafref backlinks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001722 ly_set_free(llist->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001723 }
1724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001725 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001726 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001727 }
1728 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001729
Pavol Vican38321d02016-08-16 14:56:02 +02001730 for (i = 0; i < llist->dflt_size; i++) {
1731 lydict_remove(ctx, llist->dflt[i]);
1732 }
1733 free(llist->dflt);
1734
Radek Krejci1d82ef62015-08-07 14:44:40 +02001735 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001736
Radek Krejci1d82ef62015-08-07 14:44:40 +02001737 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001738 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001739}
1740
Radek Krejci1d82ef62015-08-07 14:44:40 +02001741static void
1742lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001743{
Radek Krejci581ce772015-11-10 17:22:40 +01001744 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001746 /* handle only specific parts for LY_NODE_LIST */
1747 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001748 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001749 }
1750 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001751
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001752 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001753 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001754 }
1755 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001756
Radek Krejci1d82ef62015-08-07 14:44:40 +02001757 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001758
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001759 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02001760 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001761 lydict_remove(ctx, list->unique[i].expr[j]);
1762 }
1763 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001764 }
1765 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001766
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001767 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001768}
1769
Radek Krejci1d82ef62015-08-07 14:44:40 +02001770static void
1771lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001772{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001773 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001774
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001775 /* handle only specific parts for LY_NODE_CONTAINER */
1776 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001777
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001778 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001779 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001780 }
1781 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001782
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001783 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001784 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001785 }
1786 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001787
Radek Krejci1d82ef62015-08-07 14:44:40 +02001788 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001789}
1790
Radek Krejci1d82ef62015-08-07 14:44:40 +02001791static void
1792lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001793{
1794 lydict_remove(ctx, f->name);
1795 lydict_remove(ctx, f->dsc);
1796 lydict_remove(ctx, f->ref);
Radek Krejci9ff0a922016-07-14 13:08:05 +02001797 lys_iffeature_free(f->iffeature, f->iffeature_size);
Radek Krejci9de2c042016-10-19 16:53:06 +02001798 ly_set_free(f->depfeatures);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001799}
1800
Radek Krejci1d82ef62015-08-07 14:44:40 +02001801static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001802lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001803{
Radek Krejci581ce772015-11-10 17:22:40 +01001804 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001805 struct ly_ctx *ctx;
1806 struct lys_node *next, *elem;
1807
1808 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001809
1810 lydict_remove(ctx, dev->target_name);
1811 lydict_remove(ctx, dev->dsc);
1812 lydict_remove(ctx, dev->ref);
1813
Pavol Vican64d0b762016-08-25 10:44:59 +02001814 if (!dev->deviate) {
1815 return ;
1816 }
1817
Michal Vaskoff006c12016-02-17 11:15:19 +01001818 /* the module was freed, but we only need the context from orig_node, use ours */
1819 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1820 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1821 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1822 elem->module = module;
1823
1824 LY_TREE_DFS_END(dev->orig_node, next, elem);
1825 }
1826 lys_node_free(dev->orig_node, NULL, 0);
1827 } else {
1828 /* it's just a shallow copy, freeing one node */
1829 dev->orig_node->module = module;
1830 lys_node_free(dev->orig_node, NULL, 1);
1831 }
1832
Radek Krejcieb00f512015-07-01 16:44:58 +02001833 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02001834 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02001835 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02001836 }
1837 free(dev->deviate[i].dflt);
1838
Radek Krejcieb00f512015-07-01 16:44:58 +02001839 lydict_remove(ctx, dev->deviate[i].units);
1840
1841 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1842 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001843 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001844 }
1845 free(dev->deviate[i].must);
1846
1847 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001848 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1849 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1850 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01001851 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001852 }
1853 free(dev->deviate[i].unique);
1854 }
1855 }
1856 free(dev->deviate);
1857}
1858
Radek Krejci1d82ef62015-08-07 14:44:40 +02001859static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001860lys_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 +02001861{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001862 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001863
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001864 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001865 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001866 lydict_remove(ctx, uses->refine[i].dsc);
1867 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001868
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001869 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001870 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001871 }
1872 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001873
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001874 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02001875 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001876 }
1877 free(uses->refine[i].dflt);
1878
1879 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001880 lydict_remove(ctx, uses->refine[i].mod.presence);
1881 }
1882 }
1883 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001885 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001886 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001887 }
1888 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001889
Radek Krejci1d82ef62015-08-07 14:44:40 +02001890 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001891}
1892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001893void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001894lys_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 +02001895{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001896 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001897 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001899 if (!node) {
1900 return;
1901 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001902
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001903 assert(node->module);
1904 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001905
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001906 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001907
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001908 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01001909 if (node->priv && private_destructor) {
1910 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001911 }
1912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02001914 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001915 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02001916 lys_iffeature_free(node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001917 lydict_remove(ctx, node->dsc);
1918 lydict_remove(ctx, node->ref);
1919 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001920
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001921 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001922 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001923 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001924 }
1925 }
1926
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001927 /* specific part */
1928 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001929 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001930 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001931 break;
Radek Krejci76512572015-08-04 09:47:08 +02001932 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001933 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001934 break;
Radek Krejci76512572015-08-04 09:47:08 +02001935 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001936 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001937 break;
Radek Krejci76512572015-08-04 09:47:08 +02001938 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001939 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001940 break;
Radek Krejci76512572015-08-04 09:47:08 +02001941 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001942 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001943 break;
Radek Krejci76512572015-08-04 09:47:08 +02001944 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001945 case LYS_ANYDATA:
1946 lys_anydata_free(ctx, (struct lys_node_anydata *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001947 break;
Radek Krejci76512572015-08-04 09:47:08 +02001948 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001949 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001950 break;
Radek Krejci76512572015-08-04 09:47:08 +02001951 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001952 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001953 break;
Radek Krejci76512572015-08-04 09:47:08 +02001954 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001955 /* do nothing */
1956 break;
Radek Krejci76512572015-08-04 09:47:08 +02001957 case LYS_GROUPING:
1958 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02001959 case LYS_ACTION:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001960 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001961 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02001962 case LYS_NOTIF:
1963 lys_notif_free(ctx, (struct lys_node_notif *)node);
1964 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001965 case LYS_INPUT:
1966 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02001967 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001968 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001969 case LYS_UNKNOWN:
1970 LOGINT;
1971 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001972 }
Radek Krejci5a065542015-05-22 15:02:07 +02001973
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001974 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001975 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001976 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001977}
1978
Radek Krejci2eee5c02016-12-06 19:18:05 +01001979API struct lys_module *
1980lys_implemented_module(const struct lys_module *mod)
Radek Krejci0fa54e92016-09-14 14:01:05 +02001981{
1982 struct ly_ctx *ctx;
1983 int i;
1984
1985 if (!mod || mod->implemented) {
1986 /* invalid argument or the module itself is implemented */
Radek Krejci2eee5c02016-12-06 19:18:05 +01001987 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02001988 }
1989
1990 ctx = mod->ctx;
1991 for (i = 0; i < ctx->models.used; i++) {
1992 if (!ctx->models.list[i]->implemented) {
1993 continue;
1994 }
1995
1996 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
1997 /* we have some revision of the module implemented */
1998 return ctx->models.list[i];
1999 }
2000 }
2001
2002 /* we have no revision of the module implemented, return the module itself,
2003 * it is up to the caller to set the module implemented when needed */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002004 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002005}
2006
2007const struct lys_module *
Michal Vasko1e62a092015-12-01 12:27:20 +01002008lys_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 +02002009{
Radek Krejcic071c542016-01-27 14:57:51 +01002010 const struct lys_module *main_module;
Michal Vasko89563fc2016-07-28 16:19:35 +02002011 char *str;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002012 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002013
Michal Vaskoa7789a82016-02-11 15:42:55 +01002014 assert(!prefix || !name);
2015
Michal Vaskob6729c62015-10-21 12:09:47 +02002016 if (prefix && !pref_len) {
2017 pref_len = strlen(prefix);
2018 }
2019 if (name && !name_len) {
2020 name_len = strlen(name);
2021 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002022
Radek Krejcic4283442016-04-22 09:19:27 +02002023 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002024
2025 /* module own prefix, submodule own prefix, (sub)module own name */
2026 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2027 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002028 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002029 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002030 }
2031
Michal Vasko89563fc2016-07-28 16:19:35 +02002032 /* standard import */
Michal Vasko8ce24d72015-10-21 11:27:26 +02002033 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002034 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2035 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002036 return module->imp[i].module;
2037 }
2038 }
2039
Michal Vasko89563fc2016-07-28 16:19:35 +02002040 /* module required by a foreign grouping, deviation, or submodule */
2041 if (name) {
2042 str = strndup(name, name_len);
2043 if (!str) {
2044 LOGMEM;
2045 return NULL;
2046 }
2047 main_module = ly_ctx_get_module(module->ctx, str, NULL);
2048 free(str);
2049 return main_module;
2050 }
2051
Michal Vasko8ce24d72015-10-21 11:27:26 +02002052 return NULL;
2053}
2054
Michal Vasko13b15832015-08-19 11:04:48 +02002055/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002056static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002057module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002058{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002059 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002060 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002061 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002063 assert(module->ctx);
2064 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002065
Michal Vaskob746fff2016-02-11 11:37:50 +01002066 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002067 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002068 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002069 lydict_remove(ctx, module->imp[i].dsc);
2070 lydict_remove(ctx, module->imp[i].ref);
Radek Krejci225376f2016-02-16 17:36:22 +01002071 }
Radek Krejcidce51452015-06-16 15:20:08 +02002072 free(module->imp);
2073
Radek Krejcic071c542016-01-27 14:57:51 +01002074 /* submodules don't have data tree, the data nodes
2075 * are placed in the main module altogether */
2076 if (!module->type) {
2077 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002078 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002079 }
Radek Krejci21181962015-06-30 14:11:00 +02002080 }
Radek Krejci5a065542015-05-22 15:02:07 +02002081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002082 lydict_remove(ctx, module->dsc);
2083 lydict_remove(ctx, module->ref);
2084 lydict_remove(ctx, module->org);
2085 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002086 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002087
Radek Krejcieb00f512015-07-01 16:44:58 +02002088 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002089 for (i = 0; i < module->rev_size; i++) {
2090 lydict_remove(ctx, module->rev[i].dsc);
2091 lydict_remove(ctx, module->rev[i].ref);
2092 }
2093 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002094
Radek Krejcieb00f512015-07-01 16:44:58 +02002095 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002096 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002097 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 }
2099 module->ident_size = 0;
2100 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002101
Radek Krejcieb00f512015-07-01 16:44:58 +02002102 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002104 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 }
2106 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002107
Radek Krejcieb00f512015-07-01 16:44:58 +02002108 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002109 for (i = 0; i < module->inc_size; i++) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002110 lydict_remove(ctx, module->inc[i].dsc);
2111 lydict_remove(ctx, module->inc[i].ref);
Radek Krejcic071c542016-01-27 14:57:51 +01002112 /* complete submodule free is done only from main module since
2113 * submodules propagate their includes to the main module */
2114 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002115 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002116 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002117 }
2118 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002119
Radek Krejcieb00f512015-07-01 16:44:58 +02002120 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002121 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002122 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002123 }
2124 free(module->augment);
2125
Radek Krejcieb00f512015-07-01 16:44:58 +02002126 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002127 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002128 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002129 }
2130 free(module->features);
2131
Radek Krejcieb00f512015-07-01 16:44:58 +02002132 /* deviations */
2133 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002134 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002135 }
2136 free(module->deviation);
2137
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002138 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002139 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002140}
2141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142void
Michal Vaskob746fff2016-02-11 11:37:50 +01002143lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002144{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002145 if (!submodule) {
2146 return;
2147 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002150 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002151
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002152 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002155}
2156
Radek Krejci3a5501d2016-07-18 22:03:34 +02002157static int
2158ingrouping(const struct lys_node *node)
2159{
2160 const struct lys_node *iter = node;
2161 assert(node);
2162
2163 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2164 if (!iter) {
2165 return 0;
2166 } else {
2167 return 1;
2168 }
2169}
2170
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002171/*
2172 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
2173 */
2174static struct lys_node *
2175lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node, uint8_t nacm,
2176 struct unres_schema *unres, int shallow, int finalize)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002177{
Radek Krejci7b9f5662016-11-07 16:28:37 +01002178 struct lys_node *retval = NULL, *iter, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002180 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002181 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002182 struct unres_list_uniq *unique_info;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002183 uint16_t flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002184
Michal Vaskoc07187d2015-08-13 15:20:57 +02002185 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002186 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002187 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002188 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002189 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002190 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002191 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002192 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002193 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002194 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002195 struct lys_node_anydata *any = NULL;
2196 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002197 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002198 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002199 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002200 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002201 struct lys_node_rpc_action *rpc = NULL;
2202 struct lys_node_rpc_action *rpc_orig = (struct lys_node_rpc_action *)node;
2203 struct lys_node_inout *io = NULL;
2204 struct lys_node_inout *io_orig = (struct lys_node_inout *)node;
2205 struct lys_node_rpc_action *ntf = NULL;
2206 struct lys_node_rpc_action *ntf_orig = (struct lys_node_rpc_action *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002207 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002208 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 /* we cannot just duplicate memory since the strings are stored in
2211 * dictionary and we need to update dictionary counters.
2212 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002213
Radek Krejci1d82ef62015-08-07 14:44:40 +02002214 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002215 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002216 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002217 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002218 break;
2219
Radek Krejci76512572015-08-04 09:47:08 +02002220 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002221 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002222 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002223 break;
2224
Radek Krejci76512572015-08-04 09:47:08 +02002225 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002227 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002228 break;
2229
Radek Krejci76512572015-08-04 09:47:08 +02002230 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002232 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002233 break;
2234
Radek Krejci76512572015-08-04 09:47:08 +02002235 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002236 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002237 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002238 break;
2239
Radek Krejci76512572015-08-04 09:47:08 +02002240 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002241 case LYS_ANYDATA:
2242 any = calloc(1, sizeof *any);
2243 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 break;
2245
Radek Krejci76512572015-08-04 09:47:08 +02002246 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002247 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002248 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 break;
2250
Radek Krejci76512572015-08-04 09:47:08 +02002251 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002252 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002253 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 break;
2255
Radek Krejci76512572015-08-04 09:47:08 +02002256 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002257 grp = calloc(1, sizeof *grp);
2258 retval = (struct lys_node *)grp;
2259 break;
2260
Radek Krejci76512572015-08-04 09:47:08 +02002261 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002262 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002263 rpc = calloc(1, sizeof *rpc);
2264 retval = (struct lys_node *)rpc;
2265 break;
2266
Radek Krejci76512572015-08-04 09:47:08 +02002267 case LYS_INPUT:
2268 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002269 io = calloc(1, sizeof *io);
2270 retval = (struct lys_node *)io;
2271 break;
2272
Radek Krejci76512572015-08-04 09:47:08 +02002273 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002274 ntf = calloc(1, sizeof *ntf);
2275 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002276 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002278 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002279 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002280 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 }
Radek Krejcib388c152015-06-04 17:03:03 +02002282
Michal Vasko253035f2015-12-17 16:58:13 +01002283 if (!retval) {
2284 LOGMEM;
2285 return NULL;
2286 }
2287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002288 /*
2289 * duplicate generic part of the structure
2290 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002291 retval->name = lydict_insert(ctx, node->name, 0);
2292 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2293 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002294 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002295 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002296
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002298 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002299
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002300 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002301
Radek Krejci06214042016-11-04 16:25:58 +01002302 if (node->iffeature_size) {
2303 retval->iffeature_size = node->iffeature_size;
2304 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2305 if (!retval->iffeature) {
2306 LOGMEM;
2307 goto error;
2308 }
Michal Vasko253035f2015-12-17 16:58:13 +01002309 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002310
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002311 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002312 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002313 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2314 if (size1) {
2315 /* there is something to duplicate */
2316
2317 /* duplicate compiled expression */
2318 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2319 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2320 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2321
2322 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02002323 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Radek Krejci9ff0a922016-07-14 13:08:05 +02002324 for (j = 0; (unsigned int)j < size2; j++) {
2325 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2326 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02002327 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002328 /* feature is resolved in origin, so copy it
2329 * - duplication is used for instantiating groupings
2330 * and if-feature inside grouping is supposed to be
2331 * resolved inside the original grouping, so we want
2332 * to keep pointers to features from the grouping
2333 * context */
2334 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2335 } else if (rc == -1) {
2336 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02002337 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02002338 }
2339 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002340 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002341
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002342 /* inherit config flags */
Radek Krejci7b9f5662016-11-07 16:28:37 +01002343 p = parent;
2344 do {
2345 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
2346 } while (iter && iter->nodetype == LYS_AUGMENT && (p = lys_parent(iter)));
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002347 if (iter) {
2348 flags = iter->flags & LYS_CONFIG_MASK;
2349 } else {
2350 /* default */
2351 flags = LYS_CONFIG_W;
2352 }
2353
2354 switch (finalize) {
2355 case 1:
2356 /* inherit config flags */
2357 if (retval->flags & LYS_CONFIG_SET) {
2358 /* skip nodes with an explicit config value */
2359 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
2360 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
2361 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "State nodes cannot have configuration nodes as children.");
2362 goto error;
2363 }
2364 break;
2365 }
2366
2367 if (retval->nodetype != LYS_USES) {
2368 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
2369 }
2370 break;
2371 case 2:
2372 /* erase config flags */
2373 retval->flags &= ~LYS_CONFIG_MASK;
2374 retval->flags &= ~LYS_CONFIG_SET;
2375 break;
2376 }
2377
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002378 /* connect it to the parent */
2379 if (lys_node_addchild(parent, retval->module, retval)) {
2380 goto error;
2381 }
Radek Krejcidce51452015-06-16 15:20:08 +02002382
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002383 /* go recursively */
2384 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002385 LY_TREE_FOR(node->child, iter) {
2386 if (!lys_node_dup_recursion(module, retval, iter, retval->nacm, unres, 0, finalize)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002387 goto error;
2388 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002389 }
2390 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002391
2392 if (finalize == 1) {
2393 /* check that configuration lists have keys
2394 * - we really want to check keys_size in original node, because the keys are
2395 * not yet resolved here, it is done below in nodetype specific part */
2396 if ((retval->nodetype == LYS_LIST) && (retval->flags & LYS_CONFIG_W)
2397 && !((struct lys_node_list *)node)->keys_size) {
2398 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
2399 goto error;
2400 }
2401 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002402 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002403 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002404 }
2405
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002406 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002407 * duplicate specific part of the structure
2408 */
2409 switch (node->nodetype) {
2410 case LYS_CONTAINER:
2411 if (cont_orig->when) {
2412 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002413 }
2414 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002415
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002416 cont->must_size = cont_orig->must_size;
2417 cont->tpdf_size = cont_orig->tpdf_size;
2418
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002419 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskodcf98e62016-05-05 17:53:53 +02002420 cont->tpdf = lys_tpdf_dup(module, lys_parent(node), cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002421 break;
2422
2423 case LYS_CHOICE:
2424 if (choice_orig->when) {
2425 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002426 }
2427
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002428 if (!shallow) {
2429 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002430 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
2431 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
2432 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002433 if (rc) {
2434 if (rc == EXIT_FAILURE) {
2435 LOGINT;
2436 }
2437 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002438 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002439 } else {
2440 /* useless to check return value, we don't know whether
2441 * there really wasn't any default defined or it just hasn't
2442 * been resolved, we just hope for the best :)
2443 */
2444 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002445 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002446 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002447 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002448 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002449 break;
2450
2451 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002452 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002453 goto error;
2454 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002455 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2456
2457 if (leaf_orig->dflt) {
2458 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci51673202016-11-01 17:00:32 +01002459 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
2460 (struct lys_node *)(&leaf->dflt)) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002461 goto error;
2462 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002463 }
2464
2465 leaf->must_size = leaf_orig->must_size;
2466 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002467
2468 if (leaf_orig->when) {
2469 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002470 }
2471 break;
2472
2473 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002474 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002475 goto error;
2476 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002477 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2478
2479 llist->min = llist_orig->min;
2480 llist->max = llist_orig->max;
2481
2482 llist->must_size = llist_orig->must_size;
2483 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002484
Radek Krejci51673202016-11-01 17:00:32 +01002485 llist->dflt_size = llist_orig->dflt_size;
2486 llist->dflt = malloc(llist->dflt_size * sizeof *llist->dflt);
2487 for (i = 0; i < llist->dflt_size; i++) {
2488 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
2489 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2490 (struct lys_node *)(&llist->dflt[i])) == -1) {
2491 goto error;
2492 }
2493 }
2494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002495 if (llist_orig->when) {
2496 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002497 }
2498 break;
2499
2500 case LYS_LIST:
2501 list->min = list_orig->min;
2502 list->max = list_orig->max;
2503
2504 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002505 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002506
Radek Krejci581ce772015-11-10 17:22:40 +01002507 list->tpdf_size = list_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002508 list->tpdf = lys_tpdf_dup(module, lys_parent(node), list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002509
Radek Krejci581ce772015-11-10 17:22:40 +01002510 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002511 if (list->keys_size) {
2512 list->keys = calloc(list->keys_size, sizeof *list->keys);
Radek Krejci5c08a992016-11-02 13:30:04 +01002513 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
Michal Vasko253035f2015-12-17 16:58:13 +01002514 if (!list->keys) {
2515 LOGMEM;
2516 goto error;
2517 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002518
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002519 if (!shallow) {
Radek Krejci5c08a992016-11-02 13:30:04 +01002520 /* the keys are going to be resolved only if the list is instantiated in data tree, not just
2521 * in another grouping */
2522 for (iter = parent; iter && iter->nodetype != LYS_GROUPING; iter = iter->parent);
2523 if (!iter && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
2524 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02002525 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002526 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002527 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002528 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002529 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002530
Radek Krejci581ce772015-11-10 17:22:40 +01002531 list->unique_size = list_orig->unique_size;
2532 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002533 if (!list->unique) {
2534 LOGMEM;
2535 goto error;
2536 }
Radek Krejci581ce772015-11-10 17:22:40 +01002537 for (i = 0; i < list->unique_size; ++i) {
2538 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2539 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002540 if (!list->unique[i].expr) {
2541 LOGMEM;
2542 goto error;
2543 }
Radek Krejci581ce772015-11-10 17:22:40 +01002544 for (j = 0; j < list->unique[i].expr_size; j++) {
2545 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2546
2547 /* if it stays in unres list, duplicate it also there */
Radek Krejcid09d1a52016-08-11 14:05:45 +02002548 unique_info = malloc(sizeof *unique_info);
2549 unique_info->list = (struct lys_node *)list;
2550 unique_info->expr = list->unique[i].expr[j];
2551 unique_info->trg_type = &list->unique[i].trg_type;
2552 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002553 }
2554 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002555
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002556 if (list_orig->when) {
2557 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002558 }
Radek Krejcidce51452015-06-16 15:20:08 +02002559 break;
2560
2561 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002562 case LYS_ANYDATA:
2563 any->must_size = any_orig->must_size;
2564 any->must = lys_restr_dup(ctx, any_orig->must, any->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002565
Radek Krejcibf2abff2016-08-23 15:51:52 +02002566 if (any_orig->when) {
2567 any->when = lys_when_dup(ctx, any_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002568 }
2569 break;
2570
2571 case LYS_USES:
2572 uses->grp = uses_orig->grp;
2573
2574 if (uses_orig->when) {
2575 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002576 }
2577
2578 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002579 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002580 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002581 if (!shallow) {
2582 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskocda51712016-05-19 15:22:11 +02002583 if (!uses->grp || uses->grp->nacm) {
2584 assert(!uses->child);
Radek Krejci48464ed2016-03-17 15:44:09 +01002585 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002586 goto error;
2587 }
Michal Vasko49168a22015-08-17 16:35:41 +02002588 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002589 } else {
2590 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002591 }
2592 break;
2593
Radek Krejcidce51452015-06-16 15:20:08 +02002594 case LYS_CASE:
2595 if (cs_orig->when) {
2596 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002597 }
2598 break;
2599
2600 case LYS_GROUPING:
2601 grp->tpdf_size = grp_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002602 grp->tpdf = lys_tpdf_dup(module, lys_parent(node), grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002603 break;
2604
Radek Krejci96935402016-11-04 16:27:28 +01002605 case LYS_ACTION:
Radek Krejcidce51452015-06-16 15:20:08 +02002606 case LYS_RPC:
2607 rpc->tpdf_size = rpc_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002608 rpc->tpdf = lys_tpdf_dup(module, lys_parent(node), rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002609 break;
2610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002611 case LYS_INPUT:
2612 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002613 io->tpdf_size = io_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002614 io->tpdf = lys_tpdf_dup(module, lys_parent(node), io_orig->tpdf, io->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002615 break;
2616
Radek Krejcida04f4a2015-05-21 12:54:09 +02002617 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002618 ntf->tpdf_size = ntf_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002619 ntf->tpdf = lys_tpdf_dup(module, lys_parent(node), ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002620 break;
2621
Radek Krejci96935402016-11-04 16:27:28 +01002622
Radek Krejcida04f4a2015-05-21 12:54:09 +02002623 default:
2624 /* LY_NODE_AUGMENT */
2625 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002626 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002627 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002628
2629 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002630
2631error:
2632
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002633 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002634 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002635}
2636
Radek Krejcib3142312016-11-09 11:04:12 +01002637int
2638lys_has_xpath(const struct lys_node *node)
2639{
2640 assert(node);
2641
2642 switch (node->nodetype) {
2643 case LYS_AUGMENT:
2644 if (((struct lys_node_augment *)node)->when) {
2645 return 1;
2646 }
2647 break;
2648 case LYS_CASE:
2649 if (((struct lys_node_case *)node)->when) {
2650 return 1;
2651 }
2652 break;
2653 case LYS_CHOICE:
2654 if (((struct lys_node_choice *)node)->when) {
2655 return 1;
2656 }
2657 break;
2658 case LYS_ANYDATA:
2659 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
2660 return 1;
2661 }
2662 break;
2663 case LYS_LEAF:
2664 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
2665 return 1;
2666 }
2667 break;
2668 case LYS_LEAFLIST:
2669 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
2670 return 1;
2671 }
2672 break;
2673 case LYS_LIST:
2674 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
2675 return 1;
2676 }
2677 break;
2678 case LYS_CONTAINER:
2679 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
2680 return 1;
2681 }
2682 break;
2683 case LYS_INPUT:
2684 case LYS_OUTPUT:
2685 if (((struct lys_node_inout *)node)->must_size) {
2686 return 1;
2687 }
2688 break;
2689 case LYS_NOTIF:
2690 if (((struct lys_node_notif *)node)->must_size) {
2691 return 1;
2692 }
2693 break;
2694 case LYS_USES:
2695 if (((struct lys_node_uses *)node)->when) {
2696 return 1;
2697 }
2698 break;
2699 default:
2700 /* does not have XPath */
2701 break;
2702 }
2703
2704 return 0;
2705}
2706
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002707struct lys_node *
2708lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node, uint8_t nacm,
2709 struct unres_schema *unres, int shallow)
2710{
2711 struct lys_node *p = NULL;
Radek Krejcib3142312016-11-09 11:04:12 +01002712 int finalize = 0;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002713 struct lys_node *result, *iter, *next;
2714
2715 if (!shallow) {
2716 /* get know where in schema tre we are to know what should be done during instantiation of the grouping */
2717 for (p = parent;
2718 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
2719 p = lys_parent(p));
2720 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
2721 }
2722
2723 result = lys_node_dup_recursion(module, parent, node, nacm, unres, shallow, finalize);
2724 if (finalize) {
2725 /* check xpath expressions in the instantiated tree */
2726 for (iter = next = parent->child; iter; iter = next) {
Radek Krejcib3142312016-11-09 11:04:12 +01002727 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
Radek Krejci3c48d042016-11-07 14:42:36 +01002728 /* invalid xpath */
2729 return NULL;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002730 }
2731
2732 /* select next item */
2733 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
2734 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
2735 next = NULL;
2736 } else {
2737 next = iter->child;
2738 }
2739 if (!next) {
2740 /* no children, try siblings */
2741 next = iter->next;
2742 }
2743 while (!next) {
2744 /* parent is already processed, go to its sibling */
2745 iter = lys_parent(iter);
2746 if (iter == parent) {
2747 /* we are done, no next element to process */
2748 break;
2749 }
2750 next = iter->next;
2751 }
2752 }
2753 }
2754
2755 return result;
2756}
2757
Michal Vasko13b15832015-08-19 11:04:48 +02002758void
Michal Vaskoff006c12016-02-17 11:15:19 +01002759lys_node_switch(struct lys_node *dst, struct lys_node *src)
2760{
2761 struct lys_node *child;
2762
Michal Vaskob42b6972016-06-06 14:21:30 +02002763 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01002764
2765 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02002766 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002767 dst->prev->next = src;
2768 }
2769
2770 /* sibling prev */
2771 if (dst->next) {
2772 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02002773 } else {
2774 for (child = dst->prev; child->prev->next; child = child->prev);
2775 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01002776 }
2777
2778 /* next */
2779 src->next = dst->next;
2780 dst->next = NULL;
2781
2782 /* prev */
2783 if (dst->prev != dst) {
2784 src->prev = dst->prev;
2785 }
2786 dst->prev = dst;
2787
2788 /* parent child */
2789 if (dst->parent && (dst->parent->child == dst)) {
2790 dst->parent->child = src;
2791 }
2792
2793 /* parent */
2794 src->parent = dst->parent;
2795 dst->parent = NULL;
2796
2797 /* child parent */
2798 LY_TREE_FOR(dst->child, child) {
2799 if (child->parent == dst) {
2800 child->parent = src;
2801 }
2802 }
2803
2804 /* child */
2805 src->child = dst->child;
2806 dst->child = NULL;
2807}
2808
2809void
Michal Vasko627975a2016-02-11 11:39:03 +01002810lys_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 +02002811{
2812 struct ly_ctx *ctx;
2813 int i;
2814
2815 if (!module) {
2816 return;
2817 }
2818
2819 /* remove schema from the context */
2820 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002821 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002822 for (i = 0; i < ctx->models.used; i++) {
2823 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002824 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002825 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002826 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 +02002827 ctx->models.list[ctx->models.used] = NULL;
2828 /* we are done */
2829 break;
2830 }
2831 }
2832 }
2833
2834 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002835 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002836
2837 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002838 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002839
2840 free(module);
2841}
Radek Krejci7e97c352015-06-19 16:26:34 +02002842
Radek Krejci9de2c042016-10-19 16:53:06 +02002843static void
2844lys_features_disable_recursive(struct lys_feature *f)
2845{
2846 unsigned int i;
2847 struct lys_feature *depf;
2848
2849 /* disable the feature */
2850 f->flags &= ~LYS_FENABLED;
2851
2852 /* by disabling feature we have to disable also all features that depends on this feature */
2853 if (f->depfeatures) {
2854 for (i = 0; i < f->depfeatures->number; i++) {
2855 depf = (struct lys_feature *)f->depfeatures->set.g[i];
2856 if (depf->flags & LYS_FENABLED) {
2857 lys_features_disable_recursive(depf);
2858 }
2859 }
2860 }
2861}
2862
2863
Radek Krejci7e97c352015-06-19 16:26:34 +02002864/*
2865 * op: 1 - enable, 0 - disable
2866 */
2867static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002868lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002869{
2870 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002871 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02002872 int progress, faili, failj, failk;
2873
2874 uint8_t fsize;
2875 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02002876
2877 if (!module || !name || !strlen(name)) {
2878 return EXIT_FAILURE;
2879 }
2880
2881 if (!strcmp(name, "*")) {
2882 /* enable all */
2883 all = 1;
2884 }
2885
Radek Krejcia889c1f2016-10-19 15:50:11 +02002886 progress = failk = 1;
2887 while (progress && failk) {
2888 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
2889 if (i == -1) {
2890 fsize = module->features_size;
2891 f = module->features;
2892 } else {
2893 fsize = module->inc[i].submodule->features_size;
2894 f = module->inc[i].submodule->features;
2895 }
2896
2897 for (j = 0; j < fsize; j++) {
2898 if (all || !strcmp(f[j].name, name)) {
Michal Vasko34c3b552016-11-21 09:07:43 +01002899 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
2900 if (all) {
2901 /* skip already set features */
2902 continue;
2903 } else {
2904 /* feature already set correctly */
2905 return EXIT_SUCCESS;
2906 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02002907 }
2908
2909 if (op) {
2910 /* check referenced features if they are enabled */
2911 for (k = 0; k < f[j].iffeature_size; k++) {
2912 if (!resolve_iffeature(&f[j].iffeature[k])) {
2913 if (all) {
2914 faili = i;
2915 failj = j;
2916 failk = k + 1;
2917 break;
2918 } else {
2919 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2920 f[j].name, k + 1);
2921 return EXIT_FAILURE;
2922 }
2923 }
2924 }
2925
2926 if (k == f[j].iffeature_size) {
2927 /* the last check passed, do the change */
2928 f[j].flags |= LYS_FENABLED;
2929 progress++;
2930 }
2931 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02002932 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02002933 progress++;
2934 }
2935 if (!all) {
2936 /* stop in case changing a single feature */
2937 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002938 }
2939 }
Radek Krejci7e97c352015-06-19 16:26:34 +02002940 }
2941 }
2942 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02002943 if (failk) {
2944 /* print info about the last failing feature */
2945 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2946 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
2947 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02002948 }
2949
2950 if (all) {
2951 return EXIT_SUCCESS;
2952 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02002953 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02002954 return EXIT_FAILURE;
2955 }
2956}
2957
2958API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002959lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002960{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002961 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002962}
2963
2964API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002965lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002966{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002967 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002968}
2969
2970API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002971lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002972{
2973 int i, j;
2974
2975 if (!module || !feature) {
2976 return -1;
2977 }
2978
2979 /* search for the specified feature */
2980 /* module itself */
2981 for (i = 0; i < module->features_size; i++) {
2982 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002983 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002984 return 1;
2985 } else {
2986 return 0;
2987 }
2988 }
2989 }
2990
2991 /* submodules */
2992 for (j = 0; j < module->inc_size; j++) {
2993 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2994 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002995 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002996 return 1;
2997 } else {
2998 return 0;
2999 }
3000 }
3001 }
3002 }
3003
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003004 /* feature definition not found */
3005 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02003006}
Michal Vasko2367e7c2015-07-07 11:33:44 +02003007
Radek Krejci96a10da2015-07-30 11:00:14 +02003008API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01003009lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02003010{
Radek Krejci96a10da2015-07-30 11:00:14 +02003011 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003012 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003013 unsigned int count;
3014
3015 if (!module) {
3016 return NULL;
3017 }
3018
3019 count = module->features_size;
3020 for (i = 0; i < module->inc_size; i++) {
3021 count += module->inc[i].submodule->features_size;
3022 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003023 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01003024 if (!result) {
3025 LOGMEM;
3026 return NULL;
3027 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003028 if (states) {
3029 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01003030 if (!(*states)) {
3031 LOGMEM;
3032 free(result);
3033 return NULL;
3034 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003035 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003036 count = 0;
3037
3038 /* module itself */
3039 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003040 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003041 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003042 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003043 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003044 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003045 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003046 }
3047 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003048 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003049 }
3050
3051 /* submodules */
3052 for (j = 0; j < module->inc_size; j++) {
3053 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003054 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003055 if (states) {
3056 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3057 (*states)[count] = 1;
3058 } else {
3059 (*states)[count] = 0;
3060 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003061 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003062 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003063 }
3064 }
3065
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003066 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003067 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003068
3069 return result;
3070}
Michal Vaskobaefb032015-09-24 14:52:10 +02003071
Radek Krejci6910a032016-04-13 10:06:21 +02003072API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01003073lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01003074{
3075 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
3076}
3077
Radek Krejci6910a032016-04-13 10:06:21 +02003078API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02003079lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01003080{
3081 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
3082}
3083
Michal Vaskobaefb032015-09-24 14:52:10 +02003084API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01003085lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02003086{
3087 if (!node || !node->parent) {
3088 return NULL;
3089 }
3090
3091 if (node->parent->nodetype == LYS_AUGMENT) {
3092 return ((struct lys_node_augment *)node->parent)->target;
3093 }
3094
3095 return node->parent;
3096}
Michal Vasko1b229152016-01-13 11:28:38 +01003097
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003098API void *
Michal Vasko1b229152016-01-13 11:28:38 +01003099lys_set_private(const struct lys_node *node, void *priv)
3100{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003101 void *prev;
3102
Michal Vasko1b229152016-01-13 11:28:38 +01003103 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003104 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
3105 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01003106 }
3107
Mislav Novakovicb5529e52016-02-29 11:42:43 +01003108 prev = node->priv;
3109 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003110
3111 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01003112}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003113
Michal Vasko01c6fd22016-05-20 11:43:05 +02003114int
3115lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
3116{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003117 struct lys_node_leaf *iter = leafref_target;
3118
Michal Vasko48a573d2016-07-01 11:46:02 +02003119 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003120 LOGINT;
3121 return -1;
3122 }
3123
Pavol Vican93175152016-08-30 15:34:44 +02003124 /* check for config flag */
3125 if ((leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
3126 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leafref,
3127 "The %s is config but refers to a non-config %s.",
3128 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
3129 return -1;
3130 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003131 /* check for cycles */
3132 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
3133 if ((void *)iter == (void *)leafref) {
3134 /* cycle detected */
3135 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
3136 return -1;
3137 }
3138 iter = iter->type.info.lref.target;
3139 }
3140
3141 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02003142 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02003143 if (!leafref_target->backlinks) {
3144 leafref_target->backlinks = (void*)ly_set_new();
3145 if (!leafref_target->backlinks) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003146 LOGMEM;
3147 return -1;
3148 }
3149 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003150 ly_set_add(leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003151
3152 return 0;
3153}
3154
Michal Vasko8548e082016-07-22 12:00:18 +02003155/* not needed currently */
3156#if 0
3157
Michal Vasko5b3492c2016-07-20 09:37:40 +02003158static const char *
3159lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
3160{
3161 struct lys_module *prev_mod;
3162 uint32_t str_len, mod_len, buf_idx;
3163
Radek Krejcibf2abff2016-08-23 15:51:52 +02003164 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003165 LOGINT;
3166 return NULL;
3167 }
3168
3169 buf_idx = buf_len - 1;
3170 buf[buf_idx] = '\0';
3171
3172 while (node) {
3173 if (lys_parent(node)) {
3174 prev_mod = lys_node_module(lys_parent(node));
3175 } else {
3176 prev_mod = NULL;
3177 }
3178
Radek Krejcibf2abff2016-08-23 15:51:52 +02003179 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003180 str_len = strlen(node->name);
3181
3182 if (prev_mod != node->module) {
3183 mod_len = strlen(node->module->name);
3184 } else {
3185 mod_len = 0;
3186 }
3187
3188 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
3189 LOGINT;
3190 return NULL;
3191 }
3192
3193 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
3194
3195 buf[buf_idx] = '/';
3196 if (mod_len) {
3197 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
3198 buf[buf_idx + 1 + mod_len] = ':';
3199 }
3200 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
3201 }
3202
3203 node = lys_parent(node);
3204 }
3205
3206 return buf + buf_idx;
3207}
3208
Michal Vasko8548e082016-07-22 12:00:18 +02003209#endif
3210
3211API struct ly_set *
Michal Vaskof06fb5b2016-09-08 10:05:56 +02003212lys_find_xpath(const struct lys_node *node, const char *expr, int options)
Michal Vasko46a4bf92016-09-08 08:23:49 +02003213{
3214 struct lyxp_set set;
3215 struct ly_set *ret_set;
3216 uint32_t i;
Michal Vaskodb1da032016-09-08 10:07:38 +02003217 int opts;
Michal Vasko46a4bf92016-09-08 08:23:49 +02003218
3219 if (!node || !expr) {
3220 ly_errno = LY_EINVAL;
3221 return NULL;
3222 }
3223
3224 memset(&set, 0, sizeof set);
3225
Michal Vaskodb1da032016-09-08 10:07:38 +02003226 opts = LYXP_SNODE;
3227 if (options & LYS_FIND_OUTPUT) {
3228 opts |= LYXP_SNODE_OUTPUT;
3229 }
3230
Michal Vasko46a4bf92016-09-08 08:23:49 +02003231 /* node and nodetype won't matter at all since it is absolute */
Michal Vaskodb1da032016-09-08 10:07:38 +02003232 if (lyxp_atomize(expr, node, LYXP_NODE_ELEM, &set, opts)) {
Michal Vasko46a4bf92016-09-08 08:23:49 +02003233 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003234 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko46a4bf92016-09-08 08:23:49 +02003235 return NULL;
3236 }
3237
3238 ret_set = ly_set_new();
3239
3240 for (i = 0; i < set.used; ++i) {
3241 if (!set.val.snodes[i].in_ctx) {
3242 continue;
3243 }
3244 assert(set.val.snodes[i].in_ctx == 1);
3245
3246 switch (set.val.snodes[i].type) {
3247 case LYXP_NODE_ELEM:
3248 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
3249 ly_set_free(ret_set);
3250 free(set.val.snodes);
3251 return NULL;
3252 }
3253 break;
3254 default:
3255 /* ignore roots, text and attr should not ever appear */
3256 break;
3257 }
3258 }
3259
3260 free(set.val.snodes);
3261 return ret_set;
3262}
3263
3264API struct ly_set *
Michal Vasko508a50d2016-09-07 14:50:33 +02003265lys_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 +02003266{
Michal Vasko508a50d2016-09-07 14:50:33 +02003267 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02003268 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003269 uint32_t i;
3270
Michal Vaskob94a5e42016-09-08 14:01:56 +02003271 if (!cur_snode || !expr) {
Michal Vasko8548e082016-07-22 12:00:18 +02003272 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003273 }
3274
Michal Vaskob94a5e42016-09-08 14:01:56 +02003275 /* adjust the root */
3276 if ((cur_snode_type == LYXP_NODE_ROOT) || (cur_snode_type == LYXP_NODE_ROOT_CONFIG)) {
3277 do {
3278 cur_snode = lys_getnext(NULL, NULL, lys_node_module(cur_snode), 0);
3279 } while ((cur_snode_type == LYXP_NODE_ROOT_CONFIG) && (cur_snode->flags & LYS_CONFIG_R));
3280 }
3281
Michal Vasko508a50d2016-09-07 14:50:33 +02003282 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02003283
3284 if (options & LYXP_MUST) {
3285 options &= ~LYXP_MUST;
3286 options |= LYXP_SNODE_MUST;
3287 } else if (options & LYXP_WHEN) {
3288 options &= ~LYXP_WHEN;
3289 options |= LYXP_SNODE_WHEN;
3290 } else {
3291 options |= LYXP_SNODE;
3292 }
3293
Michal Vasko508a50d2016-09-07 14:50:33 +02003294 if (lyxp_atomize(expr, cur_snode, cur_snode_type, &set, options)) {
3295 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003296 LOGVAL(LYE_SPEC, LY_VLOG_LYS, cur_snode, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko8548e082016-07-22 12:00:18 +02003297 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003298 }
3299
Michal Vasko8548e082016-07-22 12:00:18 +02003300 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003301
Michal Vasko508a50d2016-09-07 14:50:33 +02003302 for (i = 0; i < set.used; ++i) {
3303 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003304 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02003305 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02003306 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02003307 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02003308 return NULL;
3309 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003310 break;
3311 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02003312 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003313 break;
3314 }
3315 }
3316
Michal Vasko508a50d2016-09-07 14:50:33 +02003317 free(set.val.snodes);
3318 return ret_set;
3319}
3320
3321API struct ly_set *
3322lys_node_xpath_atomize(const struct lys_node *node, int options)
3323{
3324 const struct lys_node *next, *elem, *parent, *tmp;
3325 struct lyxp_set set;
3326 struct ly_set *ret_set;
3327 uint16_t i;
3328
3329 if (!node) {
3330 return NULL;
3331 }
3332
3333 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
3334 if (!parent) {
3335 /* not in input, output, or notification */
3336 return NULL;
3337 }
3338
3339 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02003340 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003341 return NULL;
3342 }
3343
3344 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003345 if ((options & LYXP_NO_LOCAL) && !(elem->flags & LYS_XPATH_DEP)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003346 /* elem has no dependencies from other subtrees and local nodes get discarded */
3347 goto next_iter;
3348 }
3349
3350 if (lyxp_node_atomize(elem, &set)) {
3351 ly_set_free(ret_set);
3352 free(set.val.snodes);
3353 return NULL;
3354 }
3355
3356 for (i = 0; i < set.used; ++i) {
3357 switch (set.val.snodes[i].type) {
3358 case LYXP_NODE_ELEM:
3359 if (options & LYXP_NO_LOCAL) {
3360 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
3361 if (tmp) {
3362 /* in local subtree, discard */
3363 break;
3364 }
3365 }
3366 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
3367 ly_set_free(ret_set);
3368 free(set.val.snodes);
3369 return NULL;
3370 }
3371 break;
3372 default:
3373 /* ignore roots, text and attr should not ever appear */
3374 break;
3375 }
3376 }
3377
3378 free(set.val.snodes);
3379 if (!(options & LYXP_RECURSIVE)) {
3380 break;
3381 }
3382next_iter:
3383 LY_TREE_DFS_END(node, next, elem);
3384 }
3385
Michal Vasko8548e082016-07-22 12:00:18 +02003386 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003387}
3388
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003389static void
Michal Vasko89563fc2016-07-28 16:19:35 +02003390lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *target_module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003391{
3392 int ret;
3393 char *parent_path;
3394 struct lys_node *target;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003395
Pavol Vican64d0b762016-08-25 10:44:59 +02003396 if (!dev->deviate) {
3397 return ;
3398 }
3399
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003400 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
3401 if (dev->orig_node) {
3402 /* removing not-supported deviation ... */
3403 if (strrchr(dev->target_name, '/') != dev->target_name) {
3404 /* ... from a parent */
3405 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
3406
3407 target = NULL;
Radek Krejcidf46e222016-11-08 11:57:37 +01003408 ret = resolve_augment_schema_nodeid(parent_path, NULL, target_module, 1,
3409 (const struct lys_node **)&target);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003410 free(parent_path);
3411 if (ret || !target) {
3412 LOGINT;
3413 return;
3414 }
3415
3416 lys_node_addchild(target, NULL, dev->orig_node);
3417 } else {
3418 /* ... from top-level data */
3419 lys_node_addchild(NULL, (struct lys_module *)target_module, dev->orig_node);
3420 }
3421
3422 dev->orig_node = NULL;
3423 } else {
3424 /* adding not-supported deviation */
3425 target = NULL;
Radek Krejcidf46e222016-11-08 11:57:37 +01003426 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, 1,
3427 (const struct lys_node **)&target);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003428 if (ret || !target) {
3429 LOGINT;
3430 return;
3431 }
3432
3433 lys_node_unlink(target);
3434 dev->orig_node = target;
3435 }
3436 } else {
3437 target = NULL;
Radek Krejcidf46e222016-11-08 11:57:37 +01003438 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, 1,
3439 (const struct lys_node **)&target);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003440 if (ret || !target) {
3441 LOGINT;
3442 return;
3443 }
3444
3445 lys_node_switch(target, dev->orig_node);
3446 dev->orig_node = target;
3447 }
3448}
3449
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003450/* temporarily removes or applies deviations, updates module deviation flag accordingly */
3451void
3452lys_switch_deviations(struct lys_module *module)
3453{
Michal Vasko89563fc2016-07-28 16:19:35 +02003454 uint32_t i = 0, j;
3455 const struct lys_module *mod;
3456 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003457
Michal Vasko89563fc2016-07-28 16:19:35 +02003458 if (module->deviated) {
3459 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3460 if (mod == module) {
3461 continue;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003462 }
3463
Michal Vasko89563fc2016-07-28 16:19:35 +02003464 for (j = 0; j < mod->deviation_size; ++j) {
3465 ptr = strstr(mod->deviation[j].target_name, module->name);
3466 if (ptr && ptr[strlen(module->name)] == ':') {
3467 lys_switch_deviation(&mod->deviation[j], module);
3468 }
3469 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003470 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003471
Michal Vasko89563fc2016-07-28 16:19:35 +02003472 if (module->deviated == 2) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003473 module->deviated = 1;
Michal Vasko89563fc2016-07-28 16:19:35 +02003474 } else {
3475 module->deviated = 2;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003476 }
3477 }
3478}
3479
Radek Krejci0ec51da2016-12-14 16:42:03 +01003480static void
3481apply_dev(struct lys_deviation *dev, const struct lys_module *module)
3482{
3483 lys_switch_deviation(dev, module);
3484
3485 assert(dev->orig_node);
3486 lys_node_module(dev->orig_node)->deviated = 1;
3487}
3488
3489static void
3490apply_aug(struct lys_node_augment *augment)
3491{
3492 struct lys_node *last;
3493
3494 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
3495
3496 /* reconnect augmenting data into the target - add them to the target child list */
3497 if (augment->target->child) {
3498 last = augment->target->child->prev;
3499 last->next = augment->child;
3500 augment->target->child->prev = augment->child->prev;
3501 augment->child->prev = last;
3502 } else {
3503 augment->target->child = augment->child;
3504 }
3505
3506 /* remove the flag about not applicability */
3507 augment->flags &= ~LYS_NOTAPPLIED;
3508}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003509
3510void
3511lys_sub_module_apply_devs_augs(struct lys_module *module)
3512{
Radek Krejci0ec51da2016-12-14 16:42:03 +01003513 uint8_t u, v;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003514
Radek Krejci0ec51da2016-12-14 16:42:03 +01003515 /* remove applied deviations */
3516 for (u = 0; u < module->deviation_size; ++u) {
3517 apply_dev(&module->deviation[u], module);
3518 }
3519 /* remove applied augments */
3520 for (u = 0; u < module->augment_size; ++u) {
3521 apply_aug(&module->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003522 }
3523
Radek Krejci0ec51da2016-12-14 16:42:03 +01003524 /* remove deviation and augments defined in submodules */
3525 for (v = 0; v < module->inc_size; ++v) {
3526 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
3527 apply_dev(&module->inc[v].submodule->deviation[u], module);
3528 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003529
Radek Krejci0ec51da2016-12-14 16:42:03 +01003530 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
3531 apply_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003532 }
3533 }
3534}
3535
Radek Krejcib2541a32016-12-12 16:45:57 +01003536static void
3537remove_dev(struct lys_deviation *dev, const struct lys_module *module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003538{
Radek Krejcib2541a32016-12-12 16:45:57 +01003539 uint32_t idx = 0, j;
Michal Vasko89563fc2016-07-28 16:19:35 +02003540 const struct lys_module *mod;
3541 struct lys_module *target_mod;
3542 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003543
Radek Krejcib2541a32016-12-12 16:45:57 +01003544 if (dev->orig_node) {
3545 target_mod = lys_node_module(dev->orig_node);
3546 } else {
Radek Krejci0ec51da2016-12-14 16:42:03 +01003547 LOGINT;
3548 return;
Radek Krejcib2541a32016-12-12 16:45:57 +01003549 }
3550 lys_switch_deviation(dev, module);
3551
3552 /* clear the deviation flag if possible */
3553 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
3554 if ((mod == module) || (mod == target_mod)) {
3555 continue;
Pavol Vican64d0b762016-08-25 10:44:59 +02003556 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003557
Radek Krejcib2541a32016-12-12 16:45:57 +01003558 for (j = 0; j < mod->deviation_size; ++j) {
3559 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
3560 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
3561 /* some other module deviation targets the inspected module, flag remains */
Michal Vasko89563fc2016-07-28 16:19:35 +02003562 break;
3563 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003564 }
Michal Vasko89563fc2016-07-28 16:19:35 +02003565
Radek Krejcib2541a32016-12-12 16:45:57 +01003566 if (j < mod->deviation_size) {
3567 break;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003568 }
3569 }
3570
Radek Krejcib2541a32016-12-12 16:45:57 +01003571 if (!mod) {
3572 target_mod->deviated = 0;
3573 }
3574}
3575
3576static void
3577remove_aug(struct lys_node_augment *augment)
3578{
3579 struct lys_node *last, *elem;
3580
3581 if (!augment->target) {
3582 /* skip not resolved augments */
3583 return;
3584 }
3585
3586 elem = augment->child;
3587 if (elem) {
3588 LY_TREE_FOR(elem, last) {
3589 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
3590 break;
3591 }
3592 }
3593 /* elem is first augment child, last is the last child */
3594
3595 /* parent child ptr */
3596 if (augment->target->child == elem) {
3597 augment->target->child = last->next;
3598 }
3599
3600 /* parent child next ptr */
3601 if (elem->prev->next) {
3602 elem->prev->next = last->next;
3603 }
3604
3605 /* parent child prev ptr */
3606 if (last->next) {
3607 last->next->prev = elem->prev;
3608 } else if (augment->target->child) {
3609 augment->target->child->prev = elem->prev;
3610 }
3611
3612 /* update augment children themselves */
3613 elem->prev = last;
3614 last->next = NULL;
3615 }
3616
Radek Krejci0ec51da2016-12-14 16:42:03 +01003617 /* augment->target still keeps the resolved target, but for lys_augment_free()
3618 * we have to keep information that this augment is not applied to free its data */
3619 augment->flags |= LYS_NOTAPPLIED;
Radek Krejcib2541a32016-12-12 16:45:57 +01003620}
3621
3622void
3623lys_sub_module_remove_devs_augs(struct lys_module *module)
3624{
3625 uint8_t u, v;
3626
3627 /* remove applied deviations */
3628 for (u = 0; u < module->deviation_size; ++u) {
3629 remove_dev(&module->deviation[u], module);
3630 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003631 /* remove applied augments */
Radek Krejcib2541a32016-12-12 16:45:57 +01003632 for (u = 0; u < module->augment_size; ++u) {
3633 remove_aug(&module->augment[u]);
3634 }
3635
3636 /* remove deviation and augments defined in submodules */
3637 for (v = 0; v < module->inc_size; ++v) {
3638 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
3639 remove_dev(&module->inc[v].submodule->deviation[u], module);
Radek Krejcidbc15262016-06-16 14:58:29 +02003640 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003641
Radek Krejcib2541a32016-12-12 16:45:57 +01003642 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
3643 remove_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003644 }
3645 }
3646}
3647
Radek Krejci27fe55e2016-09-13 17:13:35 +02003648static int
3649lys_set_implemented_recursion(struct lys_module *module, struct unres_schema *unres)
3650{
3651 struct lys_node *root, *next, *node;
3652 uint8_t i;
3653
3654 for (i = 0; i < module->augment_size; i++) {
3655 /* apply augment */
Michal Vaskoa1911b92016-09-19 14:57:34 +02003656 if (!module->augment[i].target
3657 && (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02003658 return -1;
3659 }
3660 }
3661 LY_TREE_FOR(module->data, root) {
3662 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
3663 LY_TREE_DFS_BEGIN(root, next, node) {
3664 if (node->nodetype == LYS_GROUPING) {
3665 goto nextsibling;
3666 }
3667 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
3668 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
3669 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
3670 UNRES_TYPE_LEAFREF, node) == -1) {
3671 return EXIT_FAILURE;
3672 }
3673 }
3674 }
3675
3676 /* modified LY_TREE_DFS_END */
3677 next = node->child;
3678 /* child exception for leafs, leaflists and anyxml without children */
3679 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
3680 next = NULL;
3681 }
3682 if (!next) {
3683nextsibling:
3684 /* no children */
3685 if (node == root) {
3686 /* we are done, root has no children */
3687 break;
3688 }
3689 /* try siblings */
3690 next = node->next;
3691 }
3692 while (!next) {
3693 /* parent is already processed, go to its sibling */
3694 node = lys_parent(node);
3695 /* no siblings, go back through parents */
3696 if (lys_parent(node) == lys_parent(root)) {
3697 /* we are done, no next element to process */
3698 break;
3699 }
3700 next = node->next;
3701 }
3702 }
3703 }
3704
3705 return EXIT_SUCCESS;
3706}
3707
3708API int
3709lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02003710{
3711 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02003712 struct unres_schema *unres;
Radek Krejci0ec51da2016-12-14 16:42:03 +01003713 int i, j, disabled = 0;
Michal Vasko26055752016-05-03 11:36:31 +02003714
Radek Krejci27fe55e2016-09-13 17:13:35 +02003715 if (!module) {
3716 ly_errno = LY_EINVAL;
3717 return EXIT_FAILURE;
3718 }
3719
3720 module = lys_main_module(module);
Radek Krejci0ec51da2016-12-14 16:42:03 +01003721
3722 if (module->disabled) {
3723 disabled = 1;
3724 lys_set_enabled(module);
3725 }
3726
Michal Vasko26055752016-05-03 11:36:31 +02003727 if (module->implemented) {
3728 return EXIT_SUCCESS;
3729 }
3730
3731 ctx = module->ctx;
3732
3733 for (i = 0; i < ctx->models.used; ++i) {
3734 if (module == ctx->models.list[i]) {
3735 continue;
3736 }
3737
3738 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
3739 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
Radek Krejci0ec51da2016-12-14 16:42:03 +01003740 if (disabled) {
3741 /* set it back disabled */
3742 lys_set_disabled(module);
3743 }
Michal Vasko26055752016-05-03 11:36:31 +02003744 return EXIT_FAILURE;
3745 }
3746 }
3747
Radek Krejci27fe55e2016-09-13 17:13:35 +02003748 unres = calloc(1, sizeof *unres);
3749 if (!unres) {
3750 LOGMEM;
Radek Krejci0ec51da2016-12-14 16:42:03 +01003751 if (disabled) {
3752 /* set it back disabled */
3753 lys_set_disabled(module);
3754 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003755 return EXIT_FAILURE;
3756 }
3757 /* recursively make the module implemented */
3758 ((struct lys_module *)module)->implemented = 1;
3759 if (lys_set_implemented_recursion((struct lys_module *)module, unres)) {
3760 goto error;
3761 }
3762 /* process augments in submodules */
3763 for (i = 0; i < module->inc_size; ++i) {
3764 if (!module->inc[i].submodule) {
3765 continue;
3766 }
3767 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
3768 /* apply augment */
Radek Krejcic8c22532016-11-09 15:11:24 +01003769 if (!module->inc[i].submodule->augment[j].target
3770 && (unres_schema_add_node((struct lys_module *)module->inc[j].submodule, unres,
3771 &module->inc[i].submodule->augment[j], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci0ec51da2016-12-14 16:42:03 +01003772
Radek Krejci27fe55e2016-09-13 17:13:35 +02003773 goto error;
3774 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003775 }
3776 }
Radek Krejcidf46e222016-11-08 11:57:37 +01003777 /* try again resolve augments in other modules possibly augmenting this one,
3778 * since we have just enabled it
3779 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003780 /* resolve rest of unres items */
3781 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
3782 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003783 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003784 unres_schema_free((struct lys_module *)module, &unres);
Michal Vasko26055752016-05-03 11:36:31 +02003785
3786 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02003787
3788error:
Radek Krejci0ec51da2016-12-14 16:42:03 +01003789
3790 if (disabled) {
3791 /* set it back disabled */
3792 lys_set_disabled(module);
3793 }
3794
Radek Krejci27fe55e2016-09-13 17:13:35 +02003795 ((struct lys_module *)module)->implemented = 0;
3796 unres_schema_free((struct lys_module *)module, &unres);
3797 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003798}
3799
3800void
3801lys_submodule_module_data_free(struct lys_submodule *submodule)
3802{
3803 struct lys_node *next, *elem;
3804
3805 /* remove parsed data */
3806 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
3807 if (elem->module == (struct lys_module *)submodule) {
3808 lys_node_free(elem, NULL, 0);
3809 }
3810 }
3811}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02003812
3813int
3814lys_is_key(struct lys_node_list *list, struct lys_node_leaf *leaf)
3815{
3816 uint8_t i;
3817
3818 for (i = 0; i < list->keys_size; i++) {
3819 if (list->keys[i] == leaf) {
3820 return i + 1;
3821 }
3822 }
3823
3824 return 0;
3825}
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02003826
3827API char *
3828lys_path(const struct lys_node *node)
3829{
3830 char *buf_backup = NULL, *buf = ly_buf(), *result = NULL;
3831 uint16_t index = LY_BUF_SIZE - 1;
3832
3833 if (!node) {
3834 LOGERR(LY_EINVAL, "%s: NULL node parameter", __func__);
3835 return NULL;
3836 }
3837
3838 /* backup the shared internal buffer */
3839 if (ly_buf_used && buf[0]) {
3840 buf_backup = strndup(buf, LY_BUF_SIZE - 1);
3841 }
3842 ly_buf_used++;
3843
3844 /* build the path */
3845 buf[index] = '\0';
3846 ly_vlog_build_path_reverse(LY_VLOG_LYS, node, buf, &index);
3847 result = strdup(&buf[index]);
3848
3849 /* restore the shared internal buffer */
3850 if (buf_backup) {
3851 strcpy(buf, buf_backup);
3852 free(buf_backup);
3853 }
3854 ly_buf_used--;
3855
3856 return result;
3857}
Radek Krejci9ad23f42016-10-31 15:46:52 +01003858