blob: 2d6a6ae79d735cb4a1100d50e77be80a46a7ea2e [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;
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100141 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | LYS_GETNEXT_WITHINOUT))) {
Radek Krejcic071c542016-01-27 14:57:51 +0100142 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 Vasko0f99d3e2017-01-10 10:50:40 +0100163lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, int nam_len,
164 LYS_NODE type, 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 */
Michal Vasko0f99d3e2017-01-10 10:50:40 +0100190 if (!strncmp(node->name, name, nam_len) && !node->name[nam_len]) {
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 }
Radek Krejcifec2e142017-01-05 15:19:03 +0100348
349 if (parent->flags & LYS_NOTAPPLIED) {
350 /* data are not connected in the target, so we cannot continue with the target as a parent */
351 parent = NULL;
352 } else {
353 /* data are connected in target, so we will continue with the target as a parent */
354 parent = ((struct lys_node_augment *)parent)->target;
355 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200356 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200358 /* unlink from parent */
359 if (parent) {
360 if (parent->child == node) {
361 parent->child = node->next;
362 }
363 node->parent = NULL;
364 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200366 /* unlink from siblings */
367 if (node->prev == node) {
368 /* there are no more siblings */
369 return;
370 }
371 if (node->next) {
372 node->next->prev = node->prev;
373 } else {
374 /* unlinking the last element */
375 if (parent) {
376 first = parent->child;
377 } else {
378 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200379 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200380 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200381 }
382 }
383 first->prev = node->prev;
384 }
385 if (node->prev->next) {
386 node->prev->next = node->next;
387 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200388
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200389 /* clean up the unlinked element */
390 node->next = NULL;
391 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200392}
393
Michal Vasko563ef092015-09-04 13:17:23 +0200394struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100395lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200396{
397 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200398
399 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200400 /* top-level augment, look into module (uses augment is handled correctly below) */
401 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
402 par_iter = par_iter->parent->module->data;
403 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200404 break;
405 }
406 }
407
Michal Vasko6f929da2015-10-02 16:23:25 +0200408 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200409 continue;
410 }
411
412 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
413 if (!stop) {
414 stop = par_iter;
415 } else if (iter == stop) {
416 break;
417 }
418 if (iter->nodetype != LYS_GROUPING) {
419 continue;
420 }
421
Radek Krejcif8426a72015-10-31 23:14:03 +0100422 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200423 return (struct lys_node_grp *)iter;
424 }
425 }
426 }
427
Michal Vasko563ef092015-09-04 13:17:23 +0200428 return NULL;
429}
430
Radek Krejci10c760e2015-08-14 14:45:43 +0200431/*
432 * get next grouping in the root's subtree, in the
433 * first call, tha last is NULL
434 */
435static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200436lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200437{
Radek Krejci10c760e2015-08-14 14:45:43 +0200438 struct lys_node *last = (struct lys_node *)lastgrp;
439 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200440
Radek Krejci10c760e2015-08-14 14:45:43 +0200441 assert(root);
442
443 if (!last) {
444 last = root;
445 }
446
447 while (1) {
448 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
449 next = last->child;
450 } else {
451 next = NULL;
452 }
453 if (!next) {
454 if (last == root) {
455 /* we are done */
456 return NULL;
457 }
458
459 /* no children, go to siblings */
460 next = last->next;
461 }
462 while (!next) {
463 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100464 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200465 /* we are done */
466 return NULL;
467 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200468 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100469 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200470 }
471
472 if (next->nodetype == LYS_GROUPING) {
473 return (struct lys_node_grp *)next;
474 }
475
476 last = next;
477 }
478}
479
Michal Vasko0d343d12015-08-24 14:57:36 +0200480/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200481int
Radek Krejci07911992015-08-14 15:13:31 +0200482lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
483{
Michal Vasko563ef092015-09-04 13:17:23 +0200484 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200485 struct lys_node_grp *grp;
486 int down;
487
488 assert(node);
489
490 if (!parent) {
491 assert(module);
492 } else {
493 module = parent->module;
494 }
495
496 switch (node->nodetype) {
497 case LYS_GROUPING:
498 /* 6.2.1, rule 6 */
499 if (parent) {
500 if (parent->child) {
501 down = 1;
502 start = parent->child;
503 } else {
504 down = 0;
505 start = parent;
506 }
507 } else {
508 down = 1;
509 start = module->data;
510 }
511 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100512 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100513 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200514 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200515 }
516 /* go down, because grouping can be defined after e.g. container in which is collision */
517 if (down) {
518 for (iter = start, stop = NULL; iter; iter = iter->prev) {
519 if (!stop) {
520 stop = start;
521 } else if (iter == stop) {
522 break;
523 }
524 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
525 continue;
526 }
527
528 grp = NULL;
529 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100530 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100531 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200532 return EXIT_FAILURE;
533 }
534 }
535 }
536 }
537 break;
538 case LYS_LEAF:
539 case LYS_LEAFLIST:
540 case LYS_LIST:
541 case LYS_CONTAINER:
542 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200543 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200544 /* 6.2.1, rule 7 */
545 if (parent) {
546 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200547 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
548 if (iter->nodetype == LYS_AUGMENT) {
549 if (((struct lys_node_augment *)iter)->target) {
550 /* augment is resolved, go up */
551 iter = ((struct lys_node_augment *)iter)->target;
552 continue;
553 }
554 /* augment is not resolved, this is the final parent */
555 break;
556 }
Radek Krejci07911992015-08-14 15:13:31 +0200557 iter = iter->parent;
558 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200559
Radek Krejci07911992015-08-14 15:13:31 +0200560 if (!iter) {
561 stop = NULL;
562 iter = module->data;
563 } else {
564 stop = iter;
565 iter = iter->child;
566 }
567 } else {
568 stop = NULL;
569 iter = module->data;
570 }
571 while (iter) {
572 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
573 iter = iter->child;
574 continue;
575 }
576
Radek Krejcibf2abff2016-08-23 15:51:52 +0200577 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100578 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100579 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200580 return EXIT_FAILURE;
581 }
582 }
583
584 /* special case for choice - we must check the choice's name as
585 * well as the names of nodes under the choice
586 */
587 if (iter->nodetype == LYS_CHOICE) {
588 iter = iter->child;
589 continue;
590 }
591
592 /* go to siblings */
593 if (!iter->next) {
594 /* no sibling, go to parent's sibling */
595 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200596 /* for parent LYS_AUGMENT */
597 if (iter->parent == stop) {
598 iter = stop;
599 break;
600 }
601 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200602 if (iter && iter->next) {
603 break;
604 }
605 } while (iter != stop);
606
607 if (iter == stop) {
608 break;
609 }
610 }
611 iter = iter->next;
612 }
613 break;
614 case LYS_CASE:
615 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100616 if (parent) {
617 start = parent->child;
618 } else {
619 start = module->data;
620 }
621
622 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200623 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200624 continue;
625 }
626
Radek Krejci749190d2016-02-18 16:26:25 +0100627 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100628 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200629 return EXIT_FAILURE;
630 }
631 }
632 break;
633 default:
634 /* no check needed */
635 break;
636 }
637
638 return EXIT_SUCCESS;
639}
640
Michal Vasko0d343d12015-08-24 14:57:36 +0200641/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200642int
Radek Krejci10c760e2015-08-14 14:45:43 +0200643lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
644{
Radek Krejci92720552015-10-05 15:28:27 +0200645 struct lys_node *iter;
Radek Krejci41a349b2016-10-24 19:21:59 +0200646 struct lys_node_inout *in, *out, *inout;
Radek Krejci07911992015-08-14 15:13:31 +0200647 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200648
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200649 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200650
Radek Krejci10c760e2015-08-14 14:45:43 +0200651 if (parent) {
652 type = parent->nodetype;
653 module = parent->module;
654 } else {
655 assert(module);
Radek Krejcife3a1382016-11-04 10:30:11 +0100656 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
Radek Krejci10c760e2015-08-14 14:45:43 +0200657 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200658 }
659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200660 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200661 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200662 case LYS_CONTAINER:
663 case LYS_LIST:
664 case LYS_GROUPING:
Radek Krejci96935402016-11-04 16:27:28 +0100665 case LYS_USES:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200666 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200667 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200668 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200669 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
670 return EXIT_FAILURE;
671 }
672 break;
Radek Krejci76512572015-08-04 09:47:08 +0200673 case LYS_INPUT:
674 case LYS_OUTPUT:
675 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200676 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200677 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200678 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100679 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200680 return EXIT_FAILURE;
681 }
682 break;
Radek Krejci76512572015-08-04 09:47:08 +0200683 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200684 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200685 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100686 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200687 return EXIT_FAILURE;
688 }
689 break;
Radek Krejci76512572015-08-04 09:47:08 +0200690 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200691 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200692 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100693 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200694 return EXIT_FAILURE;
695 }
696 break;
Radek Krejci76512572015-08-04 09:47:08 +0200697 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200698 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200699 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100700 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200701 return EXIT_FAILURE;
702 }
703 break;
Radek Krejci76512572015-08-04 09:47:08 +0200704 case LYS_LEAF:
705 case LYS_LEAFLIST:
706 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200707 case LYS_ANYDATA:
Radek Krejci48464ed2016-03-17 15:44:09 +0100708 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vasko51e5c582017-01-19 14:16:39 +0100709 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100710 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200711 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200712 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200713 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200714 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskodb017262017-01-24 13:10:04 +0100715 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100716 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200717 return EXIT_FAILURE;
718 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200719 break;
720 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200721 /* top level */
722 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200723 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200724 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100725 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200726 return EXIT_FAILURE;
727 }
728
Radek Krejcic071c542016-01-27 14:57:51 +0100729 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200730 }
731
732 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200733 if (lys_check_id(child, parent, module)) {
734 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200735 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200736
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200737 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200738 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200739 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200740
Radek Krejci41a349b2016-10-24 19:21:59 +0200741 if (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
742 /* replace the implicit input/output node */
743 if (child->nodetype == LYS_OUTPUT) {
744 inout = (struct lys_node_inout *)parent->child->next;
745 } else { /* LYS_INPUT */
746 inout = (struct lys_node_inout *)parent->child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200747 parent->child = child;
Radek Krejci41a349b2016-10-24 19:21:59 +0200748 }
749 if (inout->next) {
750 child->next = inout->next;
751 inout->next->prev = child;
752 inout->next = NULL;
Radek Krejci10c760e2015-08-14 14:45:43 +0200753 } else {
Radek Krejci41a349b2016-10-24 19:21:59 +0200754 parent->child->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200755 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200756 child->prev = inout->prev;
757 if (inout->prev->next) {
758 inout->prev->next = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200759 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200760 inout->prev = (struct lys_node *)inout;
761 child->parent = parent;
762 inout->parent = NULL;
763 lys_node_free((struct lys_node *)inout, NULL, 0);
764 } else {
765 /* connect the child correctly */
766 if (!parent) {
767 if (module->data) {
768 module->data->prev->next = child;
769 child->prev = module->data->prev;
770 module->data->prev = child;
771 } else {
772 module->data = child;
773 }
774 } else {
775 if (!parent->child) {
776 /* the only/first child of the parent */
777 parent->child = child;
778 child->parent = parent;
779 iter = child;
780 } else {
781 /* add a new child at the end of parent's child list */
782 iter = parent->child->prev;
783 iter->next = child;
784 child->prev = iter;
785 }
786 while (iter->next) {
787 iter = iter->next;
788 iter->parent = parent;
789 }
790 parent->child->prev = iter;
791 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200792 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200793
Michal Vaskoe022a562016-09-27 14:24:15 +0200794 /* check config value (but ignore them in groupings and augments) */
795 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT)); iter = iter->parent);
796 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200797 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
798 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
799 LOGVAL(LYE_INARG, LY_VLOG_LYS, child, "true", "config");
Michal Vasko51e5c582017-01-19 14:16:39 +0100800 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200801 return EXIT_FAILURE;
802 }
803 }
804
Radek Krejci41771502016-04-14 17:52:32 +0200805 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200806 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200807 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200808 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200809 /* store it only into container or list - the only data inner nodes */
810 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
811 if (iter->flags & LYS_INCL_STATUS) {
812 /* done, someone else set it already from here */
813 break;
814 }
815 /* set flag about including status data */
816 iter->flags |= LYS_INCL_STATUS;
817 }
818 }
819 }
Radek Krejci41a349b2016-10-24 19:21:59 +0200820
821 /* create implicit input/output nodes to have available them as possible target for augment */
822 if (child->nodetype & (LYS_RPC | LYS_ACTION)) {
823 in = calloc(1, sizeof *in);
824 in->nodetype = LYS_INPUT;
825 in->name = lydict_insert(child->module->ctx, "input", 5);
826 out = calloc(1, sizeof *out);
827 out->name = lydict_insert(child->module->ctx, "output", 6);
828 out->nodetype = LYS_OUTPUT;
829 in->module = out->module = child->module;
830 in->parent = out->parent = child;
831 in->flags = out->flags = LYS_IMPLICIT;
832 in->next = (struct lys_node *)out;
833 in->prev = (struct lys_node *)out;
834 out->prev = (struct lys_node *)in;
835 child->child = (struct lys_node *)in;
836 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200837 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200838}
839
Radek Krejcia1df1682016-04-11 14:56:59 +0200840static const struct lys_module *
841lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200842{
Radek Krejcia1df1682016-04-11 14:56:59 +0200843 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200844 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200845 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200846
Radek Krejci00a0e712016-10-26 10:24:46 +0200847 ly_err_clean(1);
Radek Krejcif347abc2016-06-22 10:18:47 +0200848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200849 if (!ctx || !data) {
850 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
851 return NULL;
852 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200853
Radek Krejcia1df1682016-04-11 14:56:59 +0200854 if (!internal && format == LYS_IN_YANG) {
855 /* enlarge data by 2 bytes for flex */
856 len = strlen(data);
857 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
858 if (!enlarged_data) {
859 LOGMEM;
860 return NULL;
861 }
862 memcpy(enlarged_data, data, len);
863 enlarged_data[len] = enlarged_data[len + 1] = '\0';
864 data = enlarged_data;
865 }
866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200867 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200868 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +0100869 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200870 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200871 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100872 mod = yang_read_module(ctx, data, 0, NULL, 1);
873 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200874 default:
Radek Krejcia1df1682016-04-11 14:56:59 +0200875 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200876 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200877 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200878
Radek Krejcia1df1682016-04-11 14:56:59 +0200879 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200880 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200881}
882
Radek Krejcia1df1682016-04-11 14:56:59 +0200883API const struct lys_module *
884lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
885{
886 return lys_parse_mem_(ctx, data, format, 0);
887}
888
Michal Vasko5a721fd2016-02-16 12:16:48 +0100889struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +0100890lys_sub_parse_mem(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200891{
Michal Vasko5b998712017-01-26 10:34:06 +0100892 char *enlarged_data = NULL;
Michal Vasko5a721fd2016-02-16 12:16:48 +0100893 struct lys_submodule *submod = NULL;
Michal Vasko5b998712017-01-26 10:34:06 +0100894 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200895
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200896 assert(module);
897 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200898
Michal Vasko5b998712017-01-26 10:34:06 +0100899 if (format == LYS_IN_YANG) {
900 /* enlarge data by 2 bytes for flex */
901 len = strlen(data);
902 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
903 if (!enlarged_data) {
904 LOGMEM;
905 return NULL;
906 }
907 memcpy(enlarged_data, data, len);
908 enlarged_data[len] = enlarged_data[len + 1] = '\0';
909 data = enlarged_data;
910 }
911
Radek Krejcic071c542016-01-27 14:57:51 +0100912 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +0200913 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200915 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200916 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +0100917 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200918 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200919 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100920 submod = yang_read_submodule(module, data, 0, unres);
921 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200922 default:
Radek Krejci90a550a2016-04-13 16:00:58 +0200923 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200924 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200925 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200926
Michal Vasko5b998712017-01-26 10:34:06 +0100927 free(enlarged_data);
Michal Vasko5a721fd2016-02-16 12:16:48 +0100928 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200929}
930
Michal Vasko1e62a092015-12-01 12:27:20 +0100931API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +0100932lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
933{
934 int fd;
935 const struct lys_module *ret;
Radek Krejcid80c8602016-10-25 11:56:03 +0200936 const char *rev, *dot, *filename;
937 size_t len;
Michal Vasko662610a2015-12-07 11:25:45 +0100938
939 if (!ctx || !path) {
940 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
941 return NULL;
942 }
943
944 fd = open(path, O_RDONLY);
945 if (fd == -1) {
946 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
947 return NULL;
948 }
949
950 ret = lys_parse_fd(ctx, fd, format);
951 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +0100952
Radek Krejcid80c8602016-10-25 11:56:03 +0200953 if (!ret) {
954 /* error */
955 return NULL;
956 }
957
958 /* check that name and revision match filename */
959 filename = strrchr(path, '/');
960 if (!filename) {
961 filename = path;
962 } else {
963 filename++;
964 }
965 rev = strchr(filename, '@');
966 dot = strrchr(filename, '.');
967
968 /* name */
969 len = strlen(ret->name);
970 if (strncmp(filename, ret->name, len) ||
971 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
Radek Krejcic0c82302016-10-25 14:21:33 +0200972 LOGWRN("File name \"%s\" does not match module name \"%s\".", filename, ret->name);
Radek Krejcid80c8602016-10-25 11:56:03 +0200973 }
974 if (rev) {
975 len = dot - ++rev;
976 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
977 LOGWRN("File name \"%s\" does not match module revision \"%s\".", filename,
978 ret->rev_size ? ret->rev[0].date : "none");
979 }
980 }
981
982 if (!ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +0100983 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +0100984 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +0100985 }
986
Michal Vasko662610a2015-12-07 11:25:45 +0100987 return ret;
988}
989
990API const struct lys_module *
991lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +0200992{
Michal Vasko1e62a092015-12-01 12:27:20 +0100993 const struct lys_module *module;
Radek Krejci0fb11502017-01-31 16:45:42 +0100994 size_t length;
Radek Krejci63a91a92015-07-29 13:31:04 +0200995 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +0100996 char buf[PATH_MAX];
997 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +0200998
999 if (!ctx || fd < 0) {
1000 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1001 return NULL;
1002 }
1003
Radek Krejci0fb11502017-01-31 16:45:42 +01001004 addr = lyp_mmap(fd, format == LYS_IN_YANG ? 1 : 0, &length);
Pavol Vicane36ea262015-11-12 11:57:47 +01001005 if (addr == MAP_FAILED) {
Radek Krejci0fb11502017-01-31 16:45:42 +01001006 LOGERR(LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001007 return NULL;
1008 }
Radek Krejci0fb11502017-01-31 16:45:42 +01001009
Radek Krejcia1df1682016-04-11 14:56:59 +02001010 module = lys_parse_mem_(ctx, addr, format, 1);
Radek Krejci0fb11502017-01-31 16:45:42 +01001011 lyp_munmap(addr, length);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001012
Radek Krejcia77904e2016-02-25 16:23:45 +01001013 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001014 /* get URI if there is /proc */
1015 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +01001016 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1017 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1018 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1019 }
1020 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001021 }
Radek Krejcib051f722016-02-25 15:12:21 +01001022 }
1023
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001024 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001025}
1026
Michal Vasko5a721fd2016-02-16 12:16:48 +01001027struct lys_submodule *
Michal Vasko5b998712017-01-26 10:34:06 +01001028lys_sub_parse_fd(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001029{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001030 struct lys_submodule *submodule;
Radek Krejci0fb11502017-01-31 16:45:42 +01001031 size_t length;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001032 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001033
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001034 assert(module);
1035 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001036
Radek Krejci0fb11502017-01-31 16:45:42 +01001037 addr = lyp_mmap(fd, format == LYS_IN_YANG ? 1 : 0, &length);
Pavol Vicane36ea262015-11-12 11:57:47 +01001038 if (addr == MAP_FAILED) {
Radek Krejci0fb11502017-01-31 16:45:42 +01001039 LOGERR(LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001040 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001041 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001042
Michal Vasko5b998712017-01-26 10:34:06 +01001043 /* get the main module */
1044 module = lys_main_module(module);
1045
1046 switch (format) {
1047 case LYS_IN_YIN:
1048 submodule = yin_read_submodule(module, addr, unres);
1049 break;
1050 case LYS_IN_YANG:
1051 submodule = yang_read_submodule(module, addr, 0, unres);
1052 break;
1053 default:
1054 assert(0);
1055 break;
1056 }
1057
Radek Krejcic645a3a2017-01-31 16:59:00 +01001058 lyp_munmap(addr, length);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001059 return submodule;
1060
Radek Krejciefaeba32015-05-27 14:30:57 +02001061}
1062
Radek Krejci1d82ef62015-08-07 14:44:40 +02001063static struct lys_restr *
1064lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001065{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001066 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001067 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001068
Radek Krejci3733a802015-06-19 13:43:21 +02001069 if (!size) {
1070 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001071 }
Radek Krejci3733a802015-06-19 13:43:21 +02001072
1073 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001074 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001075 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001076 return NULL;
1077 }
Radek Krejci3733a802015-06-19 13:43:21 +02001078 for (i = 0; i < size; i++) {
1079 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1080 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1081 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1082 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1083 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1084 }
1085
1086 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001087}
1088
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001089void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001090lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001091{
1092 assert(ctx);
1093 if (!restr) {
1094 return;
1095 }
1096
1097 lydict_remove(ctx, restr->expr);
1098 lydict_remove(ctx, restr->dsc);
1099 lydict_remove(ctx, restr->ref);
1100 lydict_remove(ctx, restr->eapptag);
1101 lydict_remove(ctx, restr->emsg);
1102}
1103
Pavol Vican05810b62016-11-23 14:07:22 +01001104void
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001105lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size)
1106{
1107 uint8_t i;
1108
1109 for (i = 0; i < iffeature_size; ++i) {
1110 free(iffeature[i].expr);
1111 free(iffeature[i].features);
1112 }
1113 free(iffeature);
1114}
1115
Michal Vaskob84f88a2015-09-24 13:16:10 +02001116static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001117type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001118 LY_DATA_TYPE base, int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001119{
1120 int i;
1121
1122 switch (base) {
1123 case LY_TYPE_BINARY:
1124 if (old->info.binary.length) {
1125 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
1126 }
1127 break;
1128
1129 case LY_TYPE_BITS:
1130 new->info.bits.count = old->info.bits.count;
1131 if (new->info.bits.count) {
1132 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1133 if (!new->info.bits.bit) {
1134 LOGMEM;
1135 return -1;
1136 }
1137 for (i = 0; i < new->info.bits.count; i++) {
1138 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1139 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1140 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1141 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1142 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1143 }
1144 }
1145 break;
1146
1147 case LY_TYPE_DEC64:
1148 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001149 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001150 if (old->info.dec64.range) {
1151 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
1152 }
1153 break;
1154
1155 case LY_TYPE_ENUM:
1156 new->info.enums.count = old->info.enums.count;
1157 if (new->info.enums.count) {
1158 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1159 if (!new->info.enums.enm) {
1160 LOGMEM;
1161 return -1;
1162 }
1163 for (i = 0; i < new->info.enums.count; i++) {
1164 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1165 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1166 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1167 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1168 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
1169 }
1170 }
1171 break;
1172
1173 case LY_TYPE_IDENT:
Michal Vaskoaffc37f2016-10-10 18:05:03 +00001174 new->info.ident.count = old->info.ident.count;
Michal Vasko878e38d2016-09-05 12:17:53 +02001175 if (old->info.ident.count) {
1176 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
1177 if (!new->info.ident.ref) {
1178 LOGMEM;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001179 return -1;
1180 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001181 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1182 } else {
1183 /* there can be several unresolved base identities, duplicate them all */
1184 i = -1;
Radek Krejciddddd0d2017-01-20 15:20:46 +01001185 do {
1186 i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF);
1187 if (i != -1) {
1188 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
1189 return -1;
1190 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001191 }
1192 --i;
Radek Krejciddddd0d2017-01-20 15:20:46 +01001193 } while (i > -1);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001194 }
1195 break;
1196
1197 case LY_TYPE_INST:
1198 new->info.inst.req = old->info.inst.req;
1199 break;
1200
1201 case LY_TYPE_INT8:
1202 case LY_TYPE_INT16:
1203 case LY_TYPE_INT32:
1204 case LY_TYPE_INT64:
1205 case LY_TYPE_UINT8:
1206 case LY_TYPE_UINT16:
1207 case LY_TYPE_UINT32:
1208 case LY_TYPE_UINT64:
1209 if (old->info.num.range) {
1210 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
1211 }
1212 break;
1213
1214 case LY_TYPE_LEAFREF:
1215 if (old->info.lref.path) {
1216 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko5d631402016-07-21 13:15:15 +02001217 if (!tpdftype && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001218 return -1;
1219 }
1220 }
1221 break;
1222
1223 case LY_TYPE_STRING:
1224 if (old->info.str.length) {
1225 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
1226 }
1227 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
1228 new->info.str.pat_count = old->info.str.pat_count;
1229 break;
1230
1231 case LY_TYPE_UNION:
1232 new->info.uni.count = old->info.uni.count;
1233 if (new->info.uni.count) {
1234 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1235 if (!new->info.uni.types) {
1236 LOGMEM;
1237 return -1;
1238 }
1239 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001240 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 +02001241 return -1;
1242 }
1243 }
1244 }
1245 break;
1246
1247 default:
1248 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1249 break;
1250 }
1251 return EXIT_SUCCESS;
1252}
1253
1254struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001255lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1256 int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001257{
1258 struct yang_type *new;
1259
1260 new = calloc(1, sizeof *new);
1261 if (!new) {
1262 LOGMEM;
1263 return NULL;
1264 }
1265 new->flags = old->flags;
1266 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001267 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001268 new->type = type;
1269 if (!new->name) {
1270 LOGMEM;
1271 goto error;
1272 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001273 if (type_dup(module, parent, type, old->type, new->base, tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001274 new->type->base = new->base;
1275 lys_type_free(module->ctx, new->type);
1276 memset(&new->type->info, 0, sizeof new->type->info);
1277 goto error;
1278 }
1279 return new;
1280
1281 error:
1282 free(new);
1283 return NULL;
1284}
1285
1286static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001287lys_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 +02001288 int tpdftype, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001289{
1290 int i;
1291
Michal Vasko1dca6882015-10-22 14:29:42 +02001292 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001293 new->base = old->base;
1294 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001295 new->parent = (struct lys_tpdf *)parent;
Radek Krejci3733a802015-06-19 13:43:21 +02001296
Michal Vasko878e38d2016-09-05 12:17:53 +02001297 i = unres_schema_find(unres, -1, old, tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001298 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001299 /* HACK (serious one) for unres */
1300 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001301 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001302 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 +02001303 } else {
1304 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1305 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001306 /* all these unres additions can fail even though they did not before */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001307 if (!new->der || unres_schema_add_node(mod, unres, new,
Michal Vasko5d631402016-07-21 13:15:15 +02001308 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001309 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001310 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001311 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001312 }
1313
Radek Krejci3a5501d2016-07-18 22:03:34 +02001314 return type_dup(mod, parent, new, old, new->base, tpdftype, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001315}
1316
1317void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001318lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001319{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001320 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001322 assert(ctx);
1323 if (!type) {
1324 return;
1325 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001326
Michal Vasko1dca6882015-10-22 14:29:42 +02001327 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001329 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001330 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001331 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001332 free(type->info.binary.length);
1333 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001334 case LY_TYPE_BITS:
1335 for (i = 0; i < type->info.bits.count; i++) {
1336 lydict_remove(ctx, type->info.bits.bit[i].name);
1337 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1338 lydict_remove(ctx, type->info.bits.bit[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001339 lys_iffeature_free(type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size);
Radek Krejci994b6f62015-06-18 16:47:27 +02001340 }
1341 free(type->info.bits.bit);
1342 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001343
1344 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001345 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001346 free(type->info.dec64.range);
1347 break;
1348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001349 case LY_TYPE_ENUM:
1350 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001351 lydict_remove(ctx, type->info.enums.enm[i].name);
1352 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1353 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001354 lys_iffeature_free(type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001355 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001356 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001357 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001358
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001359 case LY_TYPE_INT8:
1360 case LY_TYPE_INT16:
1361 case LY_TYPE_INT32:
1362 case LY_TYPE_INT64:
1363 case LY_TYPE_UINT8:
1364 case LY_TYPE_UINT16:
1365 case LY_TYPE_UINT32:
1366 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001367 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001368 free(type->info.num.range);
1369 break;
1370
Radek Krejcidc4c1412015-06-19 15:39:54 +02001371 case LY_TYPE_LEAFREF:
1372 lydict_remove(ctx, type->info.lref.path);
1373 break;
1374
Radek Krejci3733a802015-06-19 13:43:21 +02001375 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001376 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001377 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001378 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001379 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001380 }
1381 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001382 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001383
Radek Krejcie4c366b2015-07-02 10:11:31 +02001384 case LY_TYPE_UNION:
1385 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001386 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001387 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001388 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001389 break;
1390
Michal Vaskod3282192016-09-05 11:27:57 +02001391 case LY_TYPE_IDENT:
1392 free(type->info.ident.ref);
1393 break;
1394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001395 default:
Michal Vaskod3282192016-09-05 11:27:57 +02001396 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001397 break;
1398 }
Radek Krejci5a065542015-05-22 15:02:07 +02001399}
1400
Radek Krejci1d82ef62015-08-07 14:44:40 +02001401static void
1402lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001403{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001404 assert(ctx);
1405 if (!tpdf) {
1406 return;
1407 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001408
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001409 lydict_remove(ctx, tpdf->name);
1410 lydict_remove(ctx, tpdf->dsc);
1411 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001412
Radek Krejci1d82ef62015-08-07 14:44:40 +02001413 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001415 lydict_remove(ctx, tpdf->units);
1416 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001417}
1418
Michal Vaskob84f88a2015-09-24 13:16:10 +02001419static struct lys_tpdf *
1420lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1421{
1422 struct lys_tpdf *result;
1423 int i, j;
1424
1425 if (!size) {
1426 return NULL;
1427 }
1428
1429 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001430 if (!result) {
1431 LOGMEM;
1432 return NULL;
1433 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001434 for (i = 0; i < size; i++) {
1435 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1436 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1437 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1438 result[i].flags = old[i].flags;
1439 result[i].module = old[i].module;
1440
Radek Krejci3a5501d2016-07-18 22:03:34 +02001441 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), 1, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001442 for (j = 0; j <= i; ++j) {
1443 lys_tpdf_free(mod->ctx, &result[j]);
1444 }
1445 free(result);
1446 return NULL;
1447 }
1448
1449 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1450 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1451 }
1452
1453 return result;
1454}
1455
Radek Krejci1d82ef62015-08-07 14:44:40 +02001456static struct lys_when *
1457lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001458{
Radek Krejci76512572015-08-04 09:47:08 +02001459 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001460
1461 if (!old) {
1462 return NULL;
1463 }
1464
1465 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001466 if (!new) {
1467 LOGMEM;
1468 return NULL;
1469 }
Radek Krejci00768f42015-06-18 17:04:04 +02001470 new->cond = lydict_insert(ctx, old->cond, 0);
1471 new->dsc = lydict_insert(ctx, old->dsc, 0);
1472 new->ref = lydict_insert(ctx, old->ref, 0);
1473
1474 return new;
1475}
1476
Michal Vasko0308dd62015-10-07 09:14:40 +02001477void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001478lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001479{
1480 if (!w) {
1481 return;
1482 }
1483
1484 lydict_remove(ctx, w->cond);
1485 lydict_remove(ctx, w->dsc);
1486 lydict_remove(ctx, w->ref);
1487
1488 free(w);
1489}
1490
Radek Krejcib7f5e412015-08-13 10:15:51 +02001491static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001492lys_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 +02001493{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001494 struct lys_node *next, *sub;
1495
Radek Krejcic071c542016-01-27 14:57:51 +01001496 /* children from a resolved augment are freed under the target node */
Radek Krejci0ec51da2016-12-14 16:42:03 +01001497 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001498 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001499 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001500 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001501 }
1502
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001503 lydict_remove(ctx, aug->target_name);
1504 lydict_remove(ctx, aug->dsc);
1505 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001506
Radek Krejci9ff0a922016-07-14 13:08:05 +02001507 lys_iffeature_free(aug->iffeature, aug->iffeature_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001508
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001509 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001510}
1511
Radek Krejci76512572015-08-04 09:47:08 +02001512static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001513lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001514{
Radek Krejci76512572015-08-04 09:47:08 +02001515 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001516 struct lys_node *old_child, *new_child;
1517 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001518
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001519 if (!size) {
1520 return NULL;
1521 }
Radek Krejci106efc02015-06-10 14:36:27 +02001522
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001523 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001524 if (!new) {
1525 LOGMEM;
1526 return NULL;
1527 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001528 for (i = 0; i < size; i++) {
1529 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1530 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1531 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1532 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001533 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001534 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001535
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001536 /* this must succeed, it was already resolved once */
Radek Krejcidf46e222016-11-08 11:57:37 +01001537 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL, 1,
Michal Vasko3edeaf72016-02-11 13:17:43 +01001538 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001539 LOGINT;
1540 free(new);
1541 return NULL;
1542 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001543 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001544
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001545 /* Correct the augment nodes.
1546 * This function can only be called from lys_node_dup() with uses
1547 * being the node duplicated, so we must have a case of grouping
1548 * with a uses with augments. The augmented nodes have already been
1549 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001550 * (it was set to their actual data parent, not an augment), and
1551 * the new augment does not have child pointer to its augment nodes,
1552 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001553 */
1554 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001555 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001556 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001557 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001558 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001559 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001560 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001561 LY_TREE_FOR(old[i].child, old_child) {
1562 /* all augment nodes were connected as siblings, there can be no more after this */
1563 if (old_child->parent != (struct lys_node *)&old[i]) {
1564 break;
1565 }
1566
Radek Krejci749190d2016-02-18 16:26:25 +01001567 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001568
1569 new_child->parent = (struct lys_node *)&new[i];
1570 new_child = new_child->next;
1571 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001572 }
Radek Krejci106efc02015-06-10 14:36:27 +02001573
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001574 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001575}
1576
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001577static const char **
1578lys_dflt_dup(struct ly_ctx *ctx, const char **old, int size)
1579{
1580 int i;
1581 const char **result;
1582
1583 if (!size) {
1584 return NULL;
1585 }
1586
1587 result = calloc(size, sizeof *result);
1588 if (!result) {
1589 LOGMEM;
1590 return NULL;
1591 }
1592
1593 for (i = 0; i < size; i++) {
1594 result[i] = lydict_insert(ctx, old[i], 0);
1595 }
1596 return result;
1597}
1598
Radek Krejci76512572015-08-04 09:47:08 +02001599static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001600lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001601{
Radek Krejci76512572015-08-04 09:47:08 +02001602 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001603 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001604
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001605 if (!size) {
1606 return NULL;
1607 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001608
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001609 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001610 if (!result) {
1611 LOGMEM;
1612 return NULL;
1613 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001614 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001615 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001616 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1617 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001618 result[i].flags = old[i].flags;
1619 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001621 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001622 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001623
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001624 result[i].dflt_size = old[i].dflt_size;
1625 result[i].dflt = lys_dflt_dup(mod->ctx, old[i].dflt, old[i].dflt_size);
1626
1627 if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001628 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001629 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001630 result[i].mod.list = old[i].mod.list;
1631 }
1632 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001633
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001634 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001635}
1636
Radek Krejci1d82ef62015-08-07 14:44:40 +02001637static void
1638lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001639{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001640 assert(ctx);
1641 if (!ident) {
1642 return;
1643 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001644
Radek Krejci018f1f52016-08-03 16:01:20 +02001645 free(ident->base);
Radek Krejci85a54be2016-10-20 12:39:56 +02001646 ly_set_free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001647 lydict_remove(ctx, ident->name);
1648 lydict_remove(ctx, ident->dsc);
1649 lydict_remove(ctx, ident->ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001650 lys_iffeature_free(ident->iffeature, ident->iffeature_size);
Radek Krejci6793db02015-05-22 17:49:54 +02001651
1652}
1653
Radek Krejci1d82ef62015-08-07 14:44:40 +02001654static void
1655lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001656{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001657 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001658
Radek Krejcid12f57b2015-08-06 10:43:39 +02001659 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001660 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001661 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001662 }
1663 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001664}
1665
Radek Krejci1d82ef62015-08-07 14:44:40 +02001666static void
Michal Vasko44fb6382016-06-29 11:12:27 +02001667lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02001668{
1669 int i;
1670
1671 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1672 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001673 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001674 }
1675 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02001676
1677 for (i = 0; i < io->must_size; i++) {
1678 lys_restr_free(ctx, &io->must[i]);
1679 }
1680 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001681}
1682
Radek Krejci1d82ef62015-08-07 14:44:40 +02001683static void
Pavol Vican7cff97e2016-08-09 14:56:08 +02001684lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif)
1685{
1686 int i;
1687
1688 for (i = 0; i < notif->must_size; i++) {
1689 lys_restr_free(ctx, &notif->must[i]);
1690 }
1691 free(notif->must);
1692
1693 for (i = 0; i < notif->tpdf_size; i++) {
1694 lys_tpdf_free(ctx, &notif->tpdf[i]);
1695 }
1696 free(notif->tpdf);
1697}
1698static void
Radek Krejcibf2abff2016-08-23 15:51:52 +02001699lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001700{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001701 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001704 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001705 }
1706 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001707
Radek Krejci1d82ef62015-08-07 14:44:40 +02001708 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001709}
1710
Radek Krejci1d82ef62015-08-07 14:44:40 +02001711static void
1712lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001713{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001714 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001715
Radek Krejci85a54be2016-10-20 12:39:56 +02001716 /* leafref backlinks */
1717 ly_set_free((struct ly_set *)leaf->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001718
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001719 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001720 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001721 }
1722 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001723
Radek Krejci1d82ef62015-08-07 14:44:40 +02001724 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001725
Radek Krejci1d82ef62015-08-07 14:44:40 +02001726 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001727 lydict_remove(ctx, leaf->units);
1728 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001729}
1730
Radek Krejci1d82ef62015-08-07 14:44:40 +02001731static void
1732lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001733{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001734 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001735
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001736 if (llist->backlinks) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001737 /* leafref backlinks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001738 ly_set_free(llist->backlinks);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001739 }
1740
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001741 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001742 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001743 }
1744 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001745
Pavol Vican38321d02016-08-16 14:56:02 +02001746 for (i = 0; i < llist->dflt_size; i++) {
1747 lydict_remove(ctx, llist->dflt[i]);
1748 }
1749 free(llist->dflt);
1750
Radek Krejci1d82ef62015-08-07 14:44:40 +02001751 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001752
Radek Krejci1d82ef62015-08-07 14:44:40 +02001753 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001754 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001755}
1756
Radek Krejci1d82ef62015-08-07 14:44:40 +02001757static void
1758lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001759{
Radek Krejci581ce772015-11-10 17:22:40 +01001760 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001762 /* handle only specific parts for LY_NODE_LIST */
1763 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001764 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001765 }
1766 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001767
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001768 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001769 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001770 }
1771 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001772
Radek Krejci1d82ef62015-08-07 14:44:40 +02001773 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001774
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001775 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02001776 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001777 lydict_remove(ctx, list->unique[i].expr[j]);
1778 }
1779 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001780 }
1781 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001782
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001783 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001784}
1785
Radek Krejci1d82ef62015-08-07 14:44:40 +02001786static void
1787lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001788{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001789 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001790
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001791 /* handle only specific parts for LY_NODE_CONTAINER */
1792 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001793
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001794 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001795 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 }
1797 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001798
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001799 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001800 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001801 }
1802 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001803
Radek Krejci1d82ef62015-08-07 14:44:40 +02001804 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001805}
1806
Radek Krejci1d82ef62015-08-07 14:44:40 +02001807static void
1808lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001809{
1810 lydict_remove(ctx, f->name);
1811 lydict_remove(ctx, f->dsc);
1812 lydict_remove(ctx, f->ref);
Radek Krejci9ff0a922016-07-14 13:08:05 +02001813 lys_iffeature_free(f->iffeature, f->iffeature_size);
Radek Krejci9de2c042016-10-19 16:53:06 +02001814 ly_set_free(f->depfeatures);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001815}
1816
Radek Krejci1d82ef62015-08-07 14:44:40 +02001817static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001818lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001819{
Radek Krejci581ce772015-11-10 17:22:40 +01001820 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001821 struct ly_ctx *ctx;
1822 struct lys_node *next, *elem;
1823
1824 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001825
1826 lydict_remove(ctx, dev->target_name);
1827 lydict_remove(ctx, dev->dsc);
1828 lydict_remove(ctx, dev->ref);
1829
Pavol Vican64d0b762016-08-25 10:44:59 +02001830 if (!dev->deviate) {
1831 return ;
1832 }
1833
Michal Vaskoff006c12016-02-17 11:15:19 +01001834 /* the module was freed, but we only need the context from orig_node, use ours */
1835 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1836 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1837 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1838 elem->module = module;
1839
1840 LY_TREE_DFS_END(dev->orig_node, next, elem);
1841 }
1842 lys_node_free(dev->orig_node, NULL, 0);
1843 } else {
1844 /* it's just a shallow copy, freeing one node */
1845 dev->orig_node->module = module;
1846 lys_node_free(dev->orig_node, NULL, 1);
1847 }
1848
Radek Krejcieb00f512015-07-01 16:44:58 +02001849 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02001850 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02001851 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02001852 }
1853 free(dev->deviate[i].dflt);
1854
Radek Krejcieb00f512015-07-01 16:44:58 +02001855 lydict_remove(ctx, dev->deviate[i].units);
1856
1857 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1858 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001859 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001860 }
1861 free(dev->deviate[i].must);
1862
1863 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001864 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1865 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1866 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01001867 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001868 }
1869 free(dev->deviate[i].unique);
1870 }
1871 }
1872 free(dev->deviate);
1873}
1874
Radek Krejci1d82ef62015-08-07 14:44:40 +02001875static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001876lys_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 +02001877{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001878 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001880 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001881 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001882 lydict_remove(ctx, uses->refine[i].dsc);
1883 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001884
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001885 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001886 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001887 }
1888 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001889
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001890 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02001891 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001892 }
1893 free(uses->refine[i].dflt);
1894
1895 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001896 lydict_remove(ctx, uses->refine[i].mod.presence);
1897 }
1898 }
1899 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001901 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001902 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001903 }
1904 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001905
Radek Krejci1d82ef62015-08-07 14:44:40 +02001906 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001907}
1908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001909void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001910lys_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 +02001911{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001912 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001913 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001915 if (!node) {
1916 return;
1917 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001919 assert(node->module);
1920 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001922 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001923
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001924 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01001925 if (node->priv && private_destructor) {
1926 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001927 }
1928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001929 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02001930 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001931 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02001932 lys_iffeature_free(node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001933 lydict_remove(ctx, node->dsc);
1934 lydict_remove(ctx, node->ref);
1935 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001936
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001937 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001938 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001939 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001940 }
1941 }
1942
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001943 /* specific part */
1944 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001945 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001946 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001947 break;
Radek Krejci76512572015-08-04 09:47:08 +02001948 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001949 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001950 break;
Radek Krejci76512572015-08-04 09:47:08 +02001951 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001952 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001953 break;
Radek Krejci76512572015-08-04 09:47:08 +02001954 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001955 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001956 break;
Radek Krejci76512572015-08-04 09:47:08 +02001957 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001958 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001959 break;
Radek Krejci76512572015-08-04 09:47:08 +02001960 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001961 case LYS_ANYDATA:
1962 lys_anydata_free(ctx, (struct lys_node_anydata *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001963 break;
Radek Krejci76512572015-08-04 09:47:08 +02001964 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001965 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001966 break;
Radek Krejci76512572015-08-04 09:47:08 +02001967 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001968 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001969 break;
Radek Krejci76512572015-08-04 09:47:08 +02001970 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001971 /* do nothing */
1972 break;
Radek Krejci76512572015-08-04 09:47:08 +02001973 case LYS_GROUPING:
1974 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02001975 case LYS_ACTION:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001976 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001977 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02001978 case LYS_NOTIF:
1979 lys_notif_free(ctx, (struct lys_node_notif *)node);
1980 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001981 case LYS_INPUT:
1982 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02001983 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001984 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001985 case LYS_UNKNOWN:
1986 LOGINT;
1987 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001988 }
Radek Krejci5a065542015-05-22 15:02:07 +02001989
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001990 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001991 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001992 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001993}
1994
Radek Krejci2eee5c02016-12-06 19:18:05 +01001995API struct lys_module *
1996lys_implemented_module(const struct lys_module *mod)
Radek Krejci0fa54e92016-09-14 14:01:05 +02001997{
1998 struct ly_ctx *ctx;
1999 int i;
2000
2001 if (!mod || mod->implemented) {
2002 /* invalid argument or the module itself is implemented */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002003 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002004 }
2005
2006 ctx = mod->ctx;
2007 for (i = 0; i < ctx->models.used; i++) {
2008 if (!ctx->models.list[i]->implemented) {
2009 continue;
2010 }
2011
2012 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
2013 /* we have some revision of the module implemented */
2014 return ctx->models.list[i];
2015 }
2016 }
2017
2018 /* we have no revision of the module implemented, return the module itself,
2019 * it is up to the caller to set the module implemented when needed */
Radek Krejci2eee5c02016-12-06 19:18:05 +01002020 return (struct lys_module *)mod;
Radek Krejci0fa54e92016-09-14 14:01:05 +02002021}
2022
2023const struct lys_module *
Michal Vasko1e62a092015-12-01 12:27:20 +01002024lys_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 +02002025{
Radek Krejcic071c542016-01-27 14:57:51 +01002026 const struct lys_module *main_module;
Michal Vasko89563fc2016-07-28 16:19:35 +02002027 char *str;
Michal Vasko3edeaf72016-02-11 13:17:43 +01002028 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02002029
Michal Vaskoa7789a82016-02-11 15:42:55 +01002030 assert(!prefix || !name);
2031
Michal Vaskob6729c62015-10-21 12:09:47 +02002032 if (prefix && !pref_len) {
2033 pref_len = strlen(prefix);
2034 }
2035 if (name && !name_len) {
2036 name_len = strlen(name);
2037 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002038
Radek Krejcic4283442016-04-22 09:19:27 +02002039 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01002040
2041 /* module own prefix, submodule own prefix, (sub)module own name */
2042 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
2043 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01002044 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01002045 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02002046 }
2047
Michal Vasko89563fc2016-07-28 16:19:35 +02002048 /* standard import */
Michal Vasko8ce24d72015-10-21 11:27:26 +02002049 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01002050 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
2051 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002052 return module->imp[i].module;
2053 }
2054 }
2055
Michal Vasko89563fc2016-07-28 16:19:35 +02002056 /* module required by a foreign grouping, deviation, or submodule */
2057 if (name) {
2058 str = strndup(name, name_len);
2059 if (!str) {
2060 LOGMEM;
2061 return NULL;
2062 }
2063 main_module = ly_ctx_get_module(module->ctx, str, NULL);
2064 free(str);
2065 return main_module;
2066 }
2067
Michal Vasko8ce24d72015-10-21 11:27:26 +02002068 return NULL;
2069}
2070
Michal Vasko13b15832015-08-19 11:04:48 +02002071/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002072static void
Michal Vaskob746fff2016-02-11 11:37:50 +01002073module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02002074{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002075 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002076 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002077 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002079 assert(module->ctx);
2080 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002081
Michal Vaskob746fff2016-02-11 11:37:50 +01002082 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01002083 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02002084 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002085 lydict_remove(ctx, module->imp[i].dsc);
2086 lydict_remove(ctx, module->imp[i].ref);
Radek Krejci225376f2016-02-16 17:36:22 +01002087 }
Radek Krejcidce51452015-06-16 15:20:08 +02002088 free(module->imp);
2089
Radek Krejcic071c542016-01-27 14:57:51 +01002090 /* submodules don't have data tree, the data nodes
2091 * are placed in the main module altogether */
2092 if (!module->type) {
2093 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002094 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002095 }
Radek Krejci21181962015-06-30 14:11:00 +02002096 }
Radek Krejci5a065542015-05-22 15:02:07 +02002097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 lydict_remove(ctx, module->dsc);
2099 lydict_remove(ctx, module->ref);
2100 lydict_remove(ctx, module->org);
2101 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002102 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002103
Radek Krejcieb00f512015-07-01 16:44:58 +02002104 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 for (i = 0; i < module->rev_size; i++) {
2106 lydict_remove(ctx, module->rev[i].dsc);
2107 lydict_remove(ctx, module->rev[i].ref);
2108 }
2109 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002110
Radek Krejcieb00f512015-07-01 16:44:58 +02002111 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002113 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 }
2115 module->ident_size = 0;
2116 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002117
Radek Krejcieb00f512015-07-01 16:44:58 +02002118 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002120 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002121 }
2122 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002123
Radek Krejcieb00f512015-07-01 16:44:58 +02002124 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 for (i = 0; i < module->inc_size; i++) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002126 lydict_remove(ctx, module->inc[i].dsc);
2127 lydict_remove(ctx, module->inc[i].ref);
Radek Krejcic071c542016-01-27 14:57:51 +01002128 /* complete submodule free is done only from main module since
2129 * submodules propagate their includes to the main module */
2130 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002131 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002132 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 }
2134 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002135
Radek Krejcieb00f512015-07-01 16:44:58 +02002136 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002137 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002138 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002139 }
2140 free(module->augment);
2141
Radek Krejcieb00f512015-07-01 16:44:58 +02002142 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002143 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002144 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002145 }
2146 free(module->features);
2147
Radek Krejcieb00f512015-07-01 16:44:58 +02002148 /* deviations */
2149 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002150 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002151 }
2152 free(module->deviation);
2153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002155 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002156}
2157
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002158void
Michal Vaskob746fff2016-02-11 11:37:50 +01002159lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002160{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002161 if (!submodule) {
2162 return;
2163 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002165 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002166 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002167
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002168 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002171}
2172
Radek Krejci3a5501d2016-07-18 22:03:34 +02002173static int
2174ingrouping(const struct lys_node *node)
2175{
2176 const struct lys_node *iter = node;
2177 assert(node);
2178
2179 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2180 if (!iter) {
2181 return 0;
2182 } else {
2183 return 1;
2184 }
2185}
2186
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002187/*
2188 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
2189 */
2190static struct lys_node *
2191lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node, uint8_t nacm,
2192 struct unres_schema *unres, int shallow, int finalize)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002193{
Radek Krejci7b9f5662016-11-07 16:28:37 +01002194 struct lys_node *retval = NULL, *iter, *p;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002195 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002196 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002197 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002198 struct unres_list_uniq *unique_info;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002199 uint16_t flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002200
Michal Vaskoc07187d2015-08-13 15:20:57 +02002201 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002202 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002203 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002204 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002205 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002206 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002207 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002208 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002209 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002210 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002211 struct lys_node_anydata *any = NULL;
2212 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002213 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002214 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002215 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002216 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002217 struct lys_node_rpc_action *rpc = NULL;
2218 struct lys_node_rpc_action *rpc_orig = (struct lys_node_rpc_action *)node;
2219 struct lys_node_inout *io = NULL;
2220 struct lys_node_inout *io_orig = (struct lys_node_inout *)node;
2221 struct lys_node_rpc_action *ntf = NULL;
2222 struct lys_node_rpc_action *ntf_orig = (struct lys_node_rpc_action *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002223 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002224 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 /* we cannot just duplicate memory since the strings are stored in
2227 * dictionary and we need to update dictionary counters.
2228 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002229
Radek Krejci1d82ef62015-08-07 14:44:40 +02002230 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002231 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002232 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002233 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 break;
2235
Radek Krejci76512572015-08-04 09:47:08 +02002236 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002238 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239 break;
2240
Radek Krejci76512572015-08-04 09:47:08 +02002241 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002242 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002243 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 break;
2245
Radek Krejci76512572015-08-04 09:47:08 +02002246 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002247 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002248 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 break;
2250
Radek Krejci76512572015-08-04 09:47:08 +02002251 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002252 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002253 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 break;
2255
Radek Krejci76512572015-08-04 09:47:08 +02002256 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002257 case LYS_ANYDATA:
2258 any = calloc(1, sizeof *any);
2259 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 break;
2261
Radek Krejci76512572015-08-04 09:47:08 +02002262 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002263 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002264 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002265 break;
2266
Radek Krejci76512572015-08-04 09:47:08 +02002267 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002268 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002269 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002270 break;
2271
Radek Krejci76512572015-08-04 09:47:08 +02002272 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002273 grp = calloc(1, sizeof *grp);
2274 retval = (struct lys_node *)grp;
2275 break;
2276
Radek Krejci76512572015-08-04 09:47:08 +02002277 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002278 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002279 rpc = calloc(1, sizeof *rpc);
2280 retval = (struct lys_node *)rpc;
2281 break;
2282
Radek Krejci76512572015-08-04 09:47:08 +02002283 case LYS_INPUT:
2284 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002285 io = calloc(1, sizeof *io);
2286 retval = (struct lys_node *)io;
2287 break;
2288
Radek Krejci76512572015-08-04 09:47:08 +02002289 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002290 ntf = calloc(1, sizeof *ntf);
2291 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002292 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002294 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002295 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002296 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 }
Radek Krejcib388c152015-06-04 17:03:03 +02002298
Michal Vasko253035f2015-12-17 16:58:13 +01002299 if (!retval) {
2300 LOGMEM;
2301 return NULL;
2302 }
2303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 /*
2305 * duplicate generic part of the structure
2306 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002307 retval->name = lydict_insert(ctx, node->name, 0);
2308 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2309 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002310 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002311 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002313 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002314 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002316 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002317
Radek Krejci06214042016-11-04 16:25:58 +01002318 if (node->iffeature_size) {
2319 retval->iffeature_size = node->iffeature_size;
2320 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2321 if (!retval->iffeature) {
2322 LOGMEM;
2323 goto error;
2324 }
Michal Vasko253035f2015-12-17 16:58:13 +01002325 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002326
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002327 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002328 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002329 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2330 if (size1) {
2331 /* there is something to duplicate */
2332
2333 /* duplicate compiled expression */
2334 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2335 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2336 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2337
2338 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02002339 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Radek Krejci9ff0a922016-07-14 13:08:05 +02002340 for (j = 0; (unsigned int)j < size2; j++) {
2341 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2342 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02002343 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002344 /* feature is resolved in origin, so copy it
2345 * - duplication is used for instantiating groupings
2346 * and if-feature inside grouping is supposed to be
2347 * resolved inside the original grouping, so we want
2348 * to keep pointers to features from the grouping
2349 * context */
2350 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2351 } else if (rc == -1) {
2352 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02002353 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02002354 }
2355 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002357
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002358 /* inherit config flags */
Radek Krejci7b9f5662016-11-07 16:28:37 +01002359 p = parent;
2360 do {
2361 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
2362 } while (iter && iter->nodetype == LYS_AUGMENT && (p = lys_parent(iter)));
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002363 if (iter) {
2364 flags = iter->flags & LYS_CONFIG_MASK;
2365 } else {
2366 /* default */
2367 flags = LYS_CONFIG_W;
2368 }
2369
2370 switch (finalize) {
2371 case 1:
2372 /* inherit config flags */
2373 if (retval->flags & LYS_CONFIG_SET) {
2374 /* skip nodes with an explicit config value */
2375 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
2376 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
Michal Vasko51e5c582017-01-19 14:16:39 +01002377 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002378 goto error;
2379 }
2380 break;
2381 }
2382
2383 if (retval->nodetype != LYS_USES) {
2384 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
2385 }
2386 break;
2387 case 2:
2388 /* erase config flags */
2389 retval->flags &= ~LYS_CONFIG_MASK;
2390 retval->flags &= ~LYS_CONFIG_SET;
2391 break;
2392 }
2393
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002394 /* connect it to the parent */
2395 if (lys_node_addchild(parent, retval->module, retval)) {
2396 goto error;
2397 }
Radek Krejcidce51452015-06-16 15:20:08 +02002398
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002399 /* go recursively */
2400 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002401 LY_TREE_FOR(node->child, iter) {
2402 if (!lys_node_dup_recursion(module, retval, iter, retval->nacm, unres, 0, finalize)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002403 goto error;
2404 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002405 }
2406 }
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002407
2408 if (finalize == 1) {
2409 /* check that configuration lists have keys
2410 * - we really want to check keys_size in original node, because the keys are
2411 * not yet resolved here, it is done below in nodetype specific part */
2412 if ((retval->nodetype == LYS_LIST) && (retval->flags & LYS_CONFIG_W)
2413 && !((struct lys_node_list *)node)->keys_size) {
2414 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
2415 goto error;
2416 }
2417 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002418 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002419 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002420 }
2421
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002422 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002423 * duplicate specific part of the structure
2424 */
2425 switch (node->nodetype) {
2426 case LYS_CONTAINER:
2427 if (cont_orig->when) {
2428 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002429 }
2430 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002431
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002432 cont->must_size = cont_orig->must_size;
2433 cont->tpdf_size = cont_orig->tpdf_size;
2434
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002435 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskodcf98e62016-05-05 17:53:53 +02002436 cont->tpdf = lys_tpdf_dup(module, lys_parent(node), cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002437 break;
2438
2439 case LYS_CHOICE:
2440 if (choice_orig->when) {
2441 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002442 }
2443
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002444 if (!shallow) {
2445 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002446 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
2447 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
2448 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002449 if (rc) {
2450 if (rc == EXIT_FAILURE) {
2451 LOGINT;
2452 }
2453 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002454 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002455 } else {
2456 /* useless to check return value, we don't know whether
2457 * there really wasn't any default defined or it just hasn't
2458 * been resolved, we just hope for the best :)
2459 */
2460 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002461 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002462 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002463 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002464 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002465 break;
2466
2467 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002468 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002469 goto error;
2470 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002471 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2472
2473 if (leaf_orig->dflt) {
2474 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci51673202016-11-01 17:00:32 +01002475 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
2476 (struct lys_node *)(&leaf->dflt)) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002477 goto error;
2478 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002479 }
2480
2481 leaf->must_size = leaf_orig->must_size;
2482 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002483
2484 if (leaf_orig->when) {
2485 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002486 }
2487 break;
2488
2489 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002490 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002491 goto error;
2492 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002493 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2494
2495 llist->min = llist_orig->min;
2496 llist->max = llist_orig->max;
2497
2498 llist->must_size = llist_orig->must_size;
2499 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002500
Radek Krejci51673202016-11-01 17:00:32 +01002501 llist->dflt_size = llist_orig->dflt_size;
2502 llist->dflt = malloc(llist->dflt_size * sizeof *llist->dflt);
2503 for (i = 0; i < llist->dflt_size; i++) {
2504 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
2505 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2506 (struct lys_node *)(&llist->dflt[i])) == -1) {
2507 goto error;
2508 }
2509 }
2510
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002511 if (llist_orig->when) {
2512 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002513 }
2514 break;
2515
2516 case LYS_LIST:
2517 list->min = list_orig->min;
2518 list->max = list_orig->max;
2519
2520 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002521 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002522
Radek Krejci581ce772015-11-10 17:22:40 +01002523 list->tpdf_size = list_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002524 list->tpdf = lys_tpdf_dup(module, lys_parent(node), list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002525
Radek Krejci581ce772015-11-10 17:22:40 +01002526 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002527 if (list->keys_size) {
2528 list->keys = calloc(list->keys_size, sizeof *list->keys);
Radek Krejci5c08a992016-11-02 13:30:04 +01002529 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
Michal Vasko253035f2015-12-17 16:58:13 +01002530 if (!list->keys) {
2531 LOGMEM;
2532 goto error;
2533 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002534
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002535 if (!shallow) {
Radek Krejci5c08a992016-11-02 13:30:04 +01002536 /* the keys are going to be resolved only if the list is instantiated in data tree, not just
2537 * in another grouping */
2538 for (iter = parent; iter && iter->nodetype != LYS_GROUPING; iter = iter->parent);
2539 if (!iter && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
2540 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02002541 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002542 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002543 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002544 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002545 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002546
Radek Krejci581ce772015-11-10 17:22:40 +01002547 list->unique_size = list_orig->unique_size;
2548 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002549 if (!list->unique) {
2550 LOGMEM;
2551 goto error;
2552 }
Radek Krejci581ce772015-11-10 17:22:40 +01002553 for (i = 0; i < list->unique_size; ++i) {
2554 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2555 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002556 if (!list->unique[i].expr) {
2557 LOGMEM;
2558 goto error;
2559 }
Radek Krejci581ce772015-11-10 17:22:40 +01002560 for (j = 0; j < list->unique[i].expr_size; j++) {
2561 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2562
2563 /* if it stays in unres list, duplicate it also there */
Radek Krejcid09d1a52016-08-11 14:05:45 +02002564 unique_info = malloc(sizeof *unique_info);
2565 unique_info->list = (struct lys_node *)list;
2566 unique_info->expr = list->unique[i].expr[j];
2567 unique_info->trg_type = &list->unique[i].trg_type;
2568 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002569 }
2570 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002572 if (list_orig->when) {
2573 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002574 }
Radek Krejcidce51452015-06-16 15:20:08 +02002575 break;
2576
2577 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002578 case LYS_ANYDATA:
2579 any->must_size = any_orig->must_size;
2580 any->must = lys_restr_dup(ctx, any_orig->must, any->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002581
Radek Krejcibf2abff2016-08-23 15:51:52 +02002582 if (any_orig->when) {
2583 any->when = lys_when_dup(ctx, any_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002584 }
2585 break;
2586
2587 case LYS_USES:
2588 uses->grp = uses_orig->grp;
2589
2590 if (uses_orig->when) {
2591 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002592 }
2593
2594 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002595 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002596 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002597 if (!shallow) {
2598 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskocda51712016-05-19 15:22:11 +02002599 if (!uses->grp || uses->grp->nacm) {
2600 assert(!uses->child);
Radek Krejci48464ed2016-03-17 15:44:09 +01002601 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002602 goto error;
2603 }
Michal Vasko49168a22015-08-17 16:35:41 +02002604 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002605 } else {
2606 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002607 }
2608 break;
2609
Radek Krejcidce51452015-06-16 15:20:08 +02002610 case LYS_CASE:
2611 if (cs_orig->when) {
2612 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002613 }
2614 break;
2615
2616 case LYS_GROUPING:
2617 grp->tpdf_size = grp_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002618 grp->tpdf = lys_tpdf_dup(module, lys_parent(node), grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002619 break;
2620
Radek Krejci96935402016-11-04 16:27:28 +01002621 case LYS_ACTION:
Radek Krejcidce51452015-06-16 15:20:08 +02002622 case LYS_RPC:
2623 rpc->tpdf_size = rpc_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002624 rpc->tpdf = lys_tpdf_dup(module, lys_parent(node), rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002625 break;
2626
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002627 case LYS_INPUT:
2628 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002629 io->tpdf_size = io_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002630 io->tpdf = lys_tpdf_dup(module, lys_parent(node), io_orig->tpdf, io->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002631 break;
2632
Radek Krejcida04f4a2015-05-21 12:54:09 +02002633 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002634 ntf->tpdf_size = ntf_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002635 ntf->tpdf = lys_tpdf_dup(module, lys_parent(node), ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002636 break;
2637
Radek Krejci96935402016-11-04 16:27:28 +01002638
Radek Krejcida04f4a2015-05-21 12:54:09 +02002639 default:
2640 /* LY_NODE_AUGMENT */
2641 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002642 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002643 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002644
2645 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002646
2647error:
2648
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002649 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002650 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002651}
2652
Radek Krejcib3142312016-11-09 11:04:12 +01002653int
2654lys_has_xpath(const struct lys_node *node)
2655{
2656 assert(node);
2657
2658 switch (node->nodetype) {
2659 case LYS_AUGMENT:
2660 if (((struct lys_node_augment *)node)->when) {
2661 return 1;
2662 }
2663 break;
2664 case LYS_CASE:
2665 if (((struct lys_node_case *)node)->when) {
2666 return 1;
2667 }
2668 break;
2669 case LYS_CHOICE:
2670 if (((struct lys_node_choice *)node)->when) {
2671 return 1;
2672 }
2673 break;
2674 case LYS_ANYDATA:
2675 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
2676 return 1;
2677 }
2678 break;
2679 case LYS_LEAF:
2680 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
2681 return 1;
2682 }
2683 break;
2684 case LYS_LEAFLIST:
2685 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
2686 return 1;
2687 }
2688 break;
2689 case LYS_LIST:
2690 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
2691 return 1;
2692 }
2693 break;
2694 case LYS_CONTAINER:
2695 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
2696 return 1;
2697 }
2698 break;
2699 case LYS_INPUT:
2700 case LYS_OUTPUT:
2701 if (((struct lys_node_inout *)node)->must_size) {
2702 return 1;
2703 }
2704 break;
2705 case LYS_NOTIF:
2706 if (((struct lys_node_notif *)node)->must_size) {
2707 return 1;
2708 }
2709 break;
2710 case LYS_USES:
2711 if (((struct lys_node_uses *)node)->when) {
2712 return 1;
2713 }
2714 break;
2715 default:
2716 /* does not have XPath */
2717 break;
2718 }
2719
2720 return 0;
2721}
2722
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002723struct lys_node *
2724lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node, uint8_t nacm,
2725 struct unres_schema *unres, int shallow)
2726{
2727 struct lys_node *p = NULL;
Radek Krejcib3142312016-11-09 11:04:12 +01002728 int finalize = 0;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002729 struct lys_node *result, *iter, *next;
2730
2731 if (!shallow) {
2732 /* get know where in schema tre we are to know what should be done during instantiation of the grouping */
2733 for (p = parent;
2734 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
2735 p = lys_parent(p));
2736 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
2737 }
2738
2739 result = lys_node_dup_recursion(module, parent, node, nacm, unres, shallow, finalize);
2740 if (finalize) {
2741 /* check xpath expressions in the instantiated tree */
2742 for (iter = next = parent->child; iter; iter = next) {
Radek Krejcib3142312016-11-09 11:04:12 +01002743 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
Radek Krejci3c48d042016-11-07 14:42:36 +01002744 /* invalid xpath */
2745 return NULL;
Radek Krejcid2ac35f2016-10-21 23:08:28 +02002746 }
2747
2748 /* select next item */
2749 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
2750 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
2751 next = NULL;
2752 } else {
2753 next = iter->child;
2754 }
2755 if (!next) {
2756 /* no children, try siblings */
2757 next = iter->next;
2758 }
2759 while (!next) {
2760 /* parent is already processed, go to its sibling */
2761 iter = lys_parent(iter);
2762 if (iter == parent) {
2763 /* we are done, no next element to process */
2764 break;
2765 }
2766 next = iter->next;
2767 }
2768 }
2769 }
2770
2771 return result;
2772}
2773
Michal Vasko13b15832015-08-19 11:04:48 +02002774void
Michal Vaskoff006c12016-02-17 11:15:19 +01002775lys_node_switch(struct lys_node *dst, struct lys_node *src)
2776{
2777 struct lys_node *child;
2778
Michal Vaskob42b6972016-06-06 14:21:30 +02002779 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01002780
2781 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02002782 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002783 dst->prev->next = src;
2784 }
2785
2786 /* sibling prev */
2787 if (dst->next) {
2788 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02002789 } else {
2790 for (child = dst->prev; child->prev->next; child = child->prev);
2791 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01002792 }
2793
2794 /* next */
2795 src->next = dst->next;
2796 dst->next = NULL;
2797
2798 /* prev */
2799 if (dst->prev != dst) {
2800 src->prev = dst->prev;
2801 }
2802 dst->prev = dst;
2803
2804 /* parent child */
2805 if (dst->parent && (dst->parent->child == dst)) {
2806 dst->parent->child = src;
2807 }
2808
2809 /* parent */
2810 src->parent = dst->parent;
2811 dst->parent = NULL;
2812
2813 /* child parent */
2814 LY_TREE_FOR(dst->child, child) {
2815 if (child->parent == dst) {
2816 child->parent = src;
2817 }
2818 }
2819
2820 /* child */
2821 src->child = dst->child;
2822 dst->child = NULL;
2823}
2824
2825void
Michal Vasko627975a2016-02-11 11:39:03 +01002826lys_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 +02002827{
2828 struct ly_ctx *ctx;
2829 int i;
2830
2831 if (!module) {
2832 return;
2833 }
2834
2835 /* remove schema from the context */
2836 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002837 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002838 for (i = 0; i < ctx->models.used; i++) {
2839 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002840 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002841 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002842 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 +02002843 ctx->models.list[ctx->models.used] = NULL;
2844 /* we are done */
2845 break;
2846 }
2847 }
2848 }
2849
2850 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002851 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002852
2853 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002854 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002855
2856 free(module);
2857}
Radek Krejci7e97c352015-06-19 16:26:34 +02002858
Radek Krejci9de2c042016-10-19 16:53:06 +02002859static void
2860lys_features_disable_recursive(struct lys_feature *f)
2861{
2862 unsigned int i;
2863 struct lys_feature *depf;
2864
2865 /* disable the feature */
2866 f->flags &= ~LYS_FENABLED;
2867
2868 /* by disabling feature we have to disable also all features that depends on this feature */
2869 if (f->depfeatures) {
2870 for (i = 0; i < f->depfeatures->number; i++) {
2871 depf = (struct lys_feature *)f->depfeatures->set.g[i];
2872 if (depf->flags & LYS_FENABLED) {
2873 lys_features_disable_recursive(depf);
2874 }
2875 }
2876 }
2877}
2878
2879
Radek Krejci7e97c352015-06-19 16:26:34 +02002880/*
2881 * op: 1 - enable, 0 - disable
2882 */
2883static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002884lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002885{
2886 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002887 int i, j, k;
Radek Krejcia889c1f2016-10-19 15:50:11 +02002888 int progress, faili, failj, failk;
2889
2890 uint8_t fsize;
2891 struct lys_feature *f;
Radek Krejci7e97c352015-06-19 16:26:34 +02002892
2893 if (!module || !name || !strlen(name)) {
2894 return EXIT_FAILURE;
2895 }
2896
2897 if (!strcmp(name, "*")) {
2898 /* enable all */
2899 all = 1;
2900 }
2901
Radek Krejcia889c1f2016-10-19 15:50:11 +02002902 progress = failk = 1;
2903 while (progress && failk) {
2904 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
2905 if (i == -1) {
2906 fsize = module->features_size;
2907 f = module->features;
2908 } else {
2909 fsize = module->inc[i].submodule->features_size;
2910 f = module->inc[i].submodule->features;
2911 }
2912
2913 for (j = 0; j < fsize; j++) {
2914 if (all || !strcmp(f[j].name, name)) {
Michal Vasko34c3b552016-11-21 09:07:43 +01002915 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
2916 if (all) {
2917 /* skip already set features */
2918 continue;
2919 } else {
2920 /* feature already set correctly */
2921 return EXIT_SUCCESS;
2922 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02002923 }
2924
2925 if (op) {
2926 /* check referenced features if they are enabled */
2927 for (k = 0; k < f[j].iffeature_size; k++) {
2928 if (!resolve_iffeature(&f[j].iffeature[k])) {
2929 if (all) {
2930 faili = i;
2931 failj = j;
2932 failk = k + 1;
2933 break;
2934 } else {
2935 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2936 f[j].name, k + 1);
2937 return EXIT_FAILURE;
2938 }
2939 }
2940 }
2941
2942 if (k == f[j].iffeature_size) {
2943 /* the last check passed, do the change */
2944 f[j].flags |= LYS_FENABLED;
2945 progress++;
2946 }
2947 } else {
Radek Krejci9de2c042016-10-19 16:53:06 +02002948 lys_features_disable_recursive(&f[j]);
Radek Krejcia889c1f2016-10-19 15:50:11 +02002949 progress++;
2950 }
2951 if (!all) {
2952 /* stop in case changing a single feature */
2953 return EXIT_SUCCESS;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002954 }
2955 }
Radek Krejci7e97c352015-06-19 16:26:34 +02002956 }
2957 }
2958 }
Radek Krejcia889c1f2016-10-19 15:50:11 +02002959 if (failk) {
2960 /* print info about the last failing feature */
2961 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2962 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
2963 return EXIT_FAILURE;
Radek Krejci7e97c352015-06-19 16:26:34 +02002964 }
2965
2966 if (all) {
2967 return EXIT_SUCCESS;
2968 } else {
Radek Krejcia889c1f2016-10-19 15:50:11 +02002969 /* the specified feature not found */
Radek Krejci7e97c352015-06-19 16:26:34 +02002970 return EXIT_FAILURE;
2971 }
2972}
2973
2974API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002975lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002976{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002977 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002978}
2979
2980API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002981lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002982{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002983 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002984}
2985
2986API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002987lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002988{
2989 int i, j;
2990
2991 if (!module || !feature) {
2992 return -1;
2993 }
2994
2995 /* search for the specified feature */
2996 /* module itself */
2997 for (i = 0; i < module->features_size; i++) {
2998 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002999 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003000 return 1;
3001 } else {
3002 return 0;
3003 }
3004 }
3005 }
3006
3007 /* submodules */
3008 for (j = 0; j < module->inc_size; j++) {
3009 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
3010 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003011 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003012 return 1;
3013 } else {
3014 return 0;
3015 }
3016 }
3017 }
3018 }
3019
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003020 /* feature definition not found */
3021 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02003022}
Michal Vasko2367e7c2015-07-07 11:33:44 +02003023
Radek Krejci96a10da2015-07-30 11:00:14 +02003024API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01003025lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02003026{
Radek Krejci96a10da2015-07-30 11:00:14 +02003027 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003028 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003029 unsigned int count;
3030
3031 if (!module) {
3032 return NULL;
3033 }
3034
3035 count = module->features_size;
3036 for (i = 0; i < module->inc_size; i++) {
3037 count += module->inc[i].submodule->features_size;
3038 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003039 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01003040 if (!result) {
3041 LOGMEM;
3042 return NULL;
3043 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003044 if (states) {
3045 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01003046 if (!(*states)) {
3047 LOGMEM;
3048 free(result);
3049 return NULL;
3050 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003051 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003052 count = 0;
3053
3054 /* module itself */
3055 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003056 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003057 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003058 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003059 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003060 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003061 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003062 }
3063 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003064 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003065 }
3066
3067 /* submodules */
3068 for (j = 0; j < module->inc_size; j++) {
3069 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02003070 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02003071 if (states) {
3072 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
3073 (*states)[count] = 1;
3074 } else {
3075 (*states)[count] = 0;
3076 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02003077 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003078 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003079 }
3080 }
3081
Radek Krejcie98bb4b2015-07-30 14:21:41 +02003082 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02003083 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02003084
3085 return result;
3086}
Michal Vaskobaefb032015-09-24 14:52:10 +02003087
Radek Krejci6910a032016-04-13 10:06:21 +02003088API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01003089lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01003090{
Michal Vaskof53187d2017-01-13 13:23:14 +01003091 if (!node) {
3092 return NULL;
3093 }
3094
Radek Krejcic071c542016-01-27 14:57:51 +01003095 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
3096}
3097
Radek Krejci6910a032016-04-13 10:06:21 +02003098API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02003099lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01003100{
Michal Vaskof53187d2017-01-13 13:23:14 +01003101 if (!module) {
3102 return NULL;
3103 }
3104
Michal Vasko320e8532016-02-15 13:11:57 +01003105 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
3106}
3107
Michal Vaskobaefb032015-09-24 14:52:10 +02003108API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01003109lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02003110{
3111 if (!node || !node->parent) {
3112 return NULL;
3113 }
3114
3115 if (node->parent->nodetype == LYS_AUGMENT) {
3116 return ((struct lys_node_augment *)node->parent)->target;
3117 }
3118
3119 return node->parent;
3120}
Michal Vasko1b229152016-01-13 11:28:38 +01003121
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003122API void *
Michal Vasko1b229152016-01-13 11:28:38 +01003123lys_set_private(const struct lys_node *node, void *priv)
3124{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003125 void *prev;
3126
Michal Vasko1b229152016-01-13 11:28:38 +01003127 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003128 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
3129 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01003130 }
3131
Mislav Novakovicb5529e52016-02-29 11:42:43 +01003132 prev = node->priv;
3133 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003134
3135 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01003136}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003137
Michal Vasko01c6fd22016-05-20 11:43:05 +02003138int
3139lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
3140{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003141 struct lys_node_leaf *iter = leafref_target;
3142
Michal Vasko48a573d2016-07-01 11:46:02 +02003143 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003144 LOGINT;
3145 return -1;
3146 }
3147
Pavol Vican93175152016-08-30 15:34:44 +02003148 /* check for config flag */
3149 if ((leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
3150 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leafref,
3151 "The %s is config but refers to a non-config %s.",
3152 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
3153 return -1;
3154 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02003155 /* check for cycles */
3156 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
3157 if ((void *)iter == (void *)leafref) {
3158 /* cycle detected */
3159 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
3160 return -1;
3161 }
3162 iter = iter->type.info.lref.target;
3163 }
3164
3165 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02003166 * leafrefs referencing the leaf(-list) */
Radek Krejci85a54be2016-10-20 12:39:56 +02003167 if (!leafref_target->backlinks) {
3168 leafref_target->backlinks = (void*)ly_set_new();
3169 if (!leafref_target->backlinks) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02003170 LOGMEM;
3171 return -1;
3172 }
3173 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003174 ly_set_add(leafref_target->backlinks, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02003175
3176 return 0;
3177}
3178
Michal Vasko8548e082016-07-22 12:00:18 +02003179/* not needed currently */
3180#if 0
3181
Michal Vasko5b3492c2016-07-20 09:37:40 +02003182static const char *
3183lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
3184{
3185 struct lys_module *prev_mod;
3186 uint32_t str_len, mod_len, buf_idx;
3187
Radek Krejcibf2abff2016-08-23 15:51:52 +02003188 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003189 LOGINT;
3190 return NULL;
3191 }
3192
3193 buf_idx = buf_len - 1;
3194 buf[buf_idx] = '\0';
3195
3196 while (node) {
3197 if (lys_parent(node)) {
3198 prev_mod = lys_node_module(lys_parent(node));
3199 } else {
3200 prev_mod = NULL;
3201 }
3202
Radek Krejcibf2abff2016-08-23 15:51:52 +02003203 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003204 str_len = strlen(node->name);
3205
3206 if (prev_mod != node->module) {
3207 mod_len = strlen(node->module->name);
3208 } else {
3209 mod_len = 0;
3210 }
3211
3212 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
3213 LOGINT;
3214 return NULL;
3215 }
3216
3217 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
3218
3219 buf[buf_idx] = '/';
3220 if (mod_len) {
3221 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
3222 buf[buf_idx + 1 + mod_len] = ':';
3223 }
3224 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
3225 }
3226
3227 node = lys_parent(node);
3228 }
3229
3230 return buf + buf_idx;
3231}
3232
Michal Vasko8548e082016-07-22 12:00:18 +02003233#endif
3234
3235API struct ly_set *
Michal Vasko2611e192017-01-23 10:33:21 +01003236lys_find_xpath(struct ly_ctx *ctx, const struct lys_node *node, const char *expr, int options)
Michal Vasko46a4bf92016-09-08 08:23:49 +02003237{
3238 struct lyxp_set set;
3239 struct ly_set *ret_set;
3240 uint32_t i;
Michal Vaskodb1da032016-09-08 10:07:38 +02003241 int opts;
Michal Vasko46a4bf92016-09-08 08:23:49 +02003242
Michal Vasko2611e192017-01-23 10:33:21 +01003243 if ((!ctx && !node) || !expr) {
Michal Vasko46a4bf92016-09-08 08:23:49 +02003244 ly_errno = LY_EINVAL;
3245 return NULL;
3246 }
3247
Michal Vasko2611e192017-01-23 10:33:21 +01003248 if (!node) {
3249 node = ly_ctx_get_node(ctx, NULL, "/ietf-yang-library:modules-state");
3250 if (!node) {
3251 ly_errno = LY_EINT;
3252 return NULL;
3253 }
3254 }
3255
Michal Vasko46a4bf92016-09-08 08:23:49 +02003256 memset(&set, 0, sizeof set);
3257
Michal Vaskodb1da032016-09-08 10:07:38 +02003258 opts = LYXP_SNODE;
3259 if (options & LYS_FIND_OUTPUT) {
3260 opts |= LYXP_SNODE_OUTPUT;
3261 }
3262
Michal Vaskodb1da032016-09-08 10:07:38 +02003263 if (lyxp_atomize(expr, node, LYXP_NODE_ELEM, &set, opts)) {
Michal Vaskoc90f3ff2017-01-23 13:51:58 +01003264 /* just find a relevant node to put in path, if it fails, use the original one */
3265 for (i = 0; i < set.used; ++i) {
3266 if (set.val.snodes[i].in_ctx == 1) {
3267 node = set.val.snodes[i].snode;
3268 break;
3269 }
3270 }
Michal Vasko46a4bf92016-09-08 08:23:49 +02003271 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003272 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko46a4bf92016-09-08 08:23:49 +02003273 return NULL;
3274 }
3275
3276 ret_set = ly_set_new();
3277
3278 for (i = 0; i < set.used; ++i) {
3279 if (!set.val.snodes[i].in_ctx) {
3280 continue;
3281 }
3282 assert(set.val.snodes[i].in_ctx == 1);
3283
3284 switch (set.val.snodes[i].type) {
3285 case LYXP_NODE_ELEM:
3286 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
3287 ly_set_free(ret_set);
3288 free(set.val.snodes);
3289 return NULL;
3290 }
3291 break;
3292 default:
3293 /* ignore roots, text and attr should not ever appear */
3294 break;
3295 }
3296 }
3297
3298 free(set.val.snodes);
3299 return ret_set;
3300}
3301
3302API struct ly_set *
Michal Vasko508a50d2016-09-07 14:50:33 +02003303lys_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 +02003304{
Michal Vasko508a50d2016-09-07 14:50:33 +02003305 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02003306 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003307 uint32_t i;
3308
Michal Vaskob94a5e42016-09-08 14:01:56 +02003309 if (!cur_snode || !expr) {
Michal Vasko8548e082016-07-22 12:00:18 +02003310 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003311 }
3312
Michal Vaskob94a5e42016-09-08 14:01:56 +02003313 /* adjust the root */
3314 if ((cur_snode_type == LYXP_NODE_ROOT) || (cur_snode_type == LYXP_NODE_ROOT_CONFIG)) {
3315 do {
3316 cur_snode = lys_getnext(NULL, NULL, lys_node_module(cur_snode), 0);
3317 } while ((cur_snode_type == LYXP_NODE_ROOT_CONFIG) && (cur_snode->flags & LYS_CONFIG_R));
3318 }
3319
Michal Vasko508a50d2016-09-07 14:50:33 +02003320 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02003321
3322 if (options & LYXP_MUST) {
3323 options &= ~LYXP_MUST;
3324 options |= LYXP_SNODE_MUST;
3325 } else if (options & LYXP_WHEN) {
3326 options &= ~LYXP_WHEN;
3327 options |= LYXP_SNODE_WHEN;
3328 } else {
3329 options |= LYXP_SNODE;
3330 }
3331
Michal Vasko508a50d2016-09-07 14:50:33 +02003332 if (lyxp_atomize(expr, cur_snode, cur_snode_type, &set, options)) {
3333 free(set.val.snodes);
Radek Krejci9ee20c32016-11-09 00:04:13 +01003334 LOGVAL(LYE_SPEC, LY_VLOG_LYS, cur_snode, "Resolving XPath expression \"%s\" failed.", expr);
Michal Vasko8548e082016-07-22 12:00:18 +02003335 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003336 }
3337
Michal Vasko8548e082016-07-22 12:00:18 +02003338 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02003339
Michal Vasko508a50d2016-09-07 14:50:33 +02003340 for (i = 0; i < set.used; ++i) {
3341 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02003342 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02003343 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02003344 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02003345 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02003346 return NULL;
3347 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02003348 break;
3349 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02003350 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02003351 break;
3352 }
3353 }
3354
Michal Vasko508a50d2016-09-07 14:50:33 +02003355 free(set.val.snodes);
3356 return ret_set;
3357}
3358
3359API struct ly_set *
3360lys_node_xpath_atomize(const struct lys_node *node, int options)
3361{
3362 const struct lys_node *next, *elem, *parent, *tmp;
3363 struct lyxp_set set;
3364 struct ly_set *ret_set;
3365 uint16_t i;
3366
3367 if (!node) {
3368 return NULL;
3369 }
3370
3371 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
3372 if (!parent) {
3373 /* not in input, output, or notification */
3374 return NULL;
3375 }
3376
3377 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02003378 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003379 return NULL;
3380 }
3381
3382 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01003383 if ((options & LYXP_NO_LOCAL) && !(elem->flags & LYS_XPATH_DEP)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003384 /* elem has no dependencies from other subtrees and local nodes get discarded */
3385 goto next_iter;
3386 }
3387
Michal Vasko769f8032017-01-24 13:11:55 +01003388 if (lyxp_node_atomize(elem, &set, 0)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003389 ly_set_free(ret_set);
3390 free(set.val.snodes);
3391 return NULL;
3392 }
3393
3394 for (i = 0; i < set.used; ++i) {
3395 switch (set.val.snodes[i].type) {
3396 case LYXP_NODE_ELEM:
3397 if (options & LYXP_NO_LOCAL) {
3398 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
3399 if (tmp) {
3400 /* in local subtree, discard */
3401 break;
3402 }
3403 }
3404 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
3405 ly_set_free(ret_set);
3406 free(set.val.snodes);
3407 return NULL;
3408 }
3409 break;
3410 default:
3411 /* ignore roots, text and attr should not ever appear */
3412 break;
3413 }
3414 }
3415
3416 free(set.val.snodes);
3417 if (!(options & LYXP_RECURSIVE)) {
3418 break;
3419 }
3420next_iter:
3421 LY_TREE_DFS_END(node, next, elem);
3422 }
3423
Michal Vasko8548e082016-07-22 12:00:18 +02003424 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003425}
3426
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003427static void
Michal Vasko89563fc2016-07-28 16:19:35 +02003428lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *target_module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003429{
3430 int ret;
3431 char *parent_path;
3432 struct lys_node *target;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003433
Pavol Vican64d0b762016-08-25 10:44:59 +02003434 if (!dev->deviate) {
3435 return ;
3436 }
3437
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003438 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
3439 if (dev->orig_node) {
3440 /* removing not-supported deviation ... */
3441 if (strrchr(dev->target_name, '/') != dev->target_name) {
3442 /* ... from a parent */
3443 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
3444
3445 target = NULL;
Radek Krejcidf46e222016-11-08 11:57:37 +01003446 ret = resolve_augment_schema_nodeid(parent_path, NULL, target_module, 1,
3447 (const struct lys_node **)&target);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003448 free(parent_path);
3449 if (ret || !target) {
3450 LOGINT;
3451 return;
3452 }
3453
3454 lys_node_addchild(target, NULL, dev->orig_node);
3455 } else {
3456 /* ... from top-level data */
3457 lys_node_addchild(NULL, (struct lys_module *)target_module, dev->orig_node);
3458 }
3459
3460 dev->orig_node = NULL;
3461 } else {
3462 /* adding not-supported deviation */
3463 target = NULL;
Radek Krejcidf46e222016-11-08 11:57:37 +01003464 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, 1,
3465 (const struct lys_node **)&target);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003466 if (ret || !target) {
3467 LOGINT;
3468 return;
3469 }
3470
3471 lys_node_unlink(target);
3472 dev->orig_node = target;
3473 }
3474 } else {
3475 target = NULL;
Radek Krejcidf46e222016-11-08 11:57:37 +01003476 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, 1,
3477 (const struct lys_node **)&target);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003478 if (ret || !target) {
3479 LOGINT;
3480 return;
3481 }
3482
3483 lys_node_switch(target, dev->orig_node);
3484 dev->orig_node = target;
3485 }
3486}
3487
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003488/* temporarily removes or applies deviations, updates module deviation flag accordingly */
3489void
3490lys_switch_deviations(struct lys_module *module)
3491{
Michal Vasko89563fc2016-07-28 16:19:35 +02003492 uint32_t i = 0, j;
3493 const struct lys_module *mod;
3494 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003495
Michal Vasko89563fc2016-07-28 16:19:35 +02003496 if (module->deviated) {
3497 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3498 if (mod == module) {
3499 continue;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003500 }
3501
Michal Vasko89563fc2016-07-28 16:19:35 +02003502 for (j = 0; j < mod->deviation_size; ++j) {
3503 ptr = strstr(mod->deviation[j].target_name, module->name);
3504 if (ptr && ptr[strlen(module->name)] == ':') {
3505 lys_switch_deviation(&mod->deviation[j], module);
3506 }
3507 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003508 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003509
Michal Vasko89563fc2016-07-28 16:19:35 +02003510 if (module->deviated == 2) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003511 module->deviated = 1;
Michal Vasko89563fc2016-07-28 16:19:35 +02003512 } else {
3513 module->deviated = 2;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003514 }
3515 }
3516}
3517
Radek Krejci0ec51da2016-12-14 16:42:03 +01003518static void
3519apply_dev(struct lys_deviation *dev, const struct lys_module *module)
3520{
3521 lys_switch_deviation(dev, module);
3522
3523 assert(dev->orig_node);
3524 lys_node_module(dev->orig_node)->deviated = 1;
3525}
3526
3527static void
3528apply_aug(struct lys_node_augment *augment)
3529{
3530 struct lys_node *last;
3531
3532 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
3533
3534 /* reconnect augmenting data into the target - add them to the target child list */
3535 if (augment->target->child) {
3536 last = augment->target->child->prev;
3537 last->next = augment->child;
3538 augment->target->child->prev = augment->child->prev;
3539 augment->child->prev = last;
3540 } else {
3541 augment->target->child = augment->child;
3542 }
3543
3544 /* remove the flag about not applicability */
3545 augment->flags &= ~LYS_NOTAPPLIED;
3546}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003547
3548void
3549lys_sub_module_apply_devs_augs(struct lys_module *module)
3550{
Radek Krejci0ec51da2016-12-14 16:42:03 +01003551 uint8_t u, v;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003552
Radek Krejci0ec51da2016-12-14 16:42:03 +01003553 /* remove applied deviations */
3554 for (u = 0; u < module->deviation_size; ++u) {
3555 apply_dev(&module->deviation[u], module);
3556 }
3557 /* remove applied augments */
3558 for (u = 0; u < module->augment_size; ++u) {
3559 apply_aug(&module->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003560 }
3561
Radek Krejci0ec51da2016-12-14 16:42:03 +01003562 /* remove deviation and augments defined in submodules */
3563 for (v = 0; v < module->inc_size; ++v) {
3564 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
3565 apply_dev(&module->inc[v].submodule->deviation[u], module);
3566 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003567
Radek Krejci0ec51da2016-12-14 16:42:03 +01003568 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
3569 apply_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003570 }
3571 }
3572}
3573
Radek Krejcib2541a32016-12-12 16:45:57 +01003574static void
3575remove_dev(struct lys_deviation *dev, const struct lys_module *module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003576{
Radek Krejcib2541a32016-12-12 16:45:57 +01003577 uint32_t idx = 0, j;
Michal Vasko89563fc2016-07-28 16:19:35 +02003578 const struct lys_module *mod;
3579 struct lys_module *target_mod;
3580 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003581
Radek Krejcib2541a32016-12-12 16:45:57 +01003582 if (dev->orig_node) {
3583 target_mod = lys_node_module(dev->orig_node);
3584 } else {
Radek Krejci0ec51da2016-12-14 16:42:03 +01003585 LOGINT;
3586 return;
Radek Krejcib2541a32016-12-12 16:45:57 +01003587 }
3588 lys_switch_deviation(dev, module);
3589
3590 /* clear the deviation flag if possible */
3591 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
3592 if ((mod == module) || (mod == target_mod)) {
3593 continue;
Pavol Vican64d0b762016-08-25 10:44:59 +02003594 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003595
Radek Krejcib2541a32016-12-12 16:45:57 +01003596 for (j = 0; j < mod->deviation_size; ++j) {
3597 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
3598 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
3599 /* some other module deviation targets the inspected module, flag remains */
Michal Vasko89563fc2016-07-28 16:19:35 +02003600 break;
3601 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003602 }
Michal Vasko89563fc2016-07-28 16:19:35 +02003603
Radek Krejcib2541a32016-12-12 16:45:57 +01003604 if (j < mod->deviation_size) {
3605 break;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003606 }
3607 }
3608
Radek Krejcib2541a32016-12-12 16:45:57 +01003609 if (!mod) {
3610 target_mod->deviated = 0;
3611 }
3612}
3613
3614static void
3615remove_aug(struct lys_node_augment *augment)
3616{
3617 struct lys_node *last, *elem;
3618
3619 if (!augment->target) {
3620 /* skip not resolved augments */
3621 return;
3622 }
3623
3624 elem = augment->child;
3625 if (elem) {
3626 LY_TREE_FOR(elem, last) {
3627 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
3628 break;
3629 }
3630 }
3631 /* elem is first augment child, last is the last child */
3632
3633 /* parent child ptr */
3634 if (augment->target->child == elem) {
3635 augment->target->child = last->next;
3636 }
3637
3638 /* parent child next ptr */
3639 if (elem->prev->next) {
3640 elem->prev->next = last->next;
3641 }
3642
3643 /* parent child prev ptr */
3644 if (last->next) {
3645 last->next->prev = elem->prev;
3646 } else if (augment->target->child) {
3647 augment->target->child->prev = elem->prev;
3648 }
3649
3650 /* update augment children themselves */
3651 elem->prev = last;
3652 last->next = NULL;
3653 }
3654
Radek Krejci0ec51da2016-12-14 16:42:03 +01003655 /* augment->target still keeps the resolved target, but for lys_augment_free()
3656 * we have to keep information that this augment is not applied to free its data */
3657 augment->flags |= LYS_NOTAPPLIED;
Radek Krejcib2541a32016-12-12 16:45:57 +01003658}
3659
3660void
3661lys_sub_module_remove_devs_augs(struct lys_module *module)
3662{
3663 uint8_t u, v;
3664
3665 /* remove applied deviations */
3666 for (u = 0; u < module->deviation_size; ++u) {
3667 remove_dev(&module->deviation[u], module);
3668 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003669 /* remove applied augments */
Radek Krejcib2541a32016-12-12 16:45:57 +01003670 for (u = 0; u < module->augment_size; ++u) {
3671 remove_aug(&module->augment[u]);
3672 }
3673
3674 /* remove deviation and augments defined in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003675 for (v = 0; v < module->inc_size && module->inc[v].submodule; ++v) {
Radek Krejcib2541a32016-12-12 16:45:57 +01003676 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
3677 remove_dev(&module->inc[v].submodule->deviation[u], module);
Radek Krejcidbc15262016-06-16 14:58:29 +02003678 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003679
Radek Krejcib2541a32016-12-12 16:45:57 +01003680 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
3681 remove_aug(&module->inc[v].submodule->augment[u]);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003682 }
3683 }
3684}
3685
Radek Krejci27fe55e2016-09-13 17:13:35 +02003686static int
3687lys_set_implemented_recursion(struct lys_module *module, struct unres_schema *unres)
3688{
3689 struct lys_node *root, *next, *node;
3690 uint8_t i;
3691
3692 for (i = 0; i < module->augment_size; i++) {
3693 /* apply augment */
Michal Vaskoa1911b92016-09-19 14:57:34 +02003694 if (!module->augment[i].target
3695 && (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02003696 return -1;
3697 }
3698 }
3699 LY_TREE_FOR(module->data, root) {
3700 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
3701 LY_TREE_DFS_BEGIN(root, next, node) {
3702 if (node->nodetype == LYS_GROUPING) {
3703 goto nextsibling;
3704 }
3705 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
3706 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
3707 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
3708 UNRES_TYPE_LEAFREF, node) == -1) {
3709 return EXIT_FAILURE;
3710 }
3711 }
3712 }
3713
3714 /* modified LY_TREE_DFS_END */
3715 next = node->child;
3716 /* child exception for leafs, leaflists and anyxml without children */
3717 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
3718 next = NULL;
3719 }
3720 if (!next) {
3721nextsibling:
3722 /* no children */
3723 if (node == root) {
3724 /* we are done, root has no children */
3725 break;
3726 }
3727 /* try siblings */
3728 next = node->next;
3729 }
3730 while (!next) {
3731 /* parent is already processed, go to its sibling */
3732 node = lys_parent(node);
3733 /* no siblings, go back through parents */
3734 if (lys_parent(node) == lys_parent(root)) {
3735 /* we are done, no next element to process */
3736 break;
3737 }
3738 next = node->next;
3739 }
3740 }
3741 }
3742
3743 return EXIT_SUCCESS;
3744}
3745
3746API int
3747lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02003748{
3749 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02003750 struct unres_schema *unres;
Radek Krejci0ec51da2016-12-14 16:42:03 +01003751 int i, j, disabled = 0;
Michal Vasko26055752016-05-03 11:36:31 +02003752
Radek Krejci27fe55e2016-09-13 17:13:35 +02003753 if (!module) {
3754 ly_errno = LY_EINVAL;
3755 return EXIT_FAILURE;
3756 }
3757
3758 module = lys_main_module(module);
Radek Krejci0ec51da2016-12-14 16:42:03 +01003759
3760 if (module->disabled) {
3761 disabled = 1;
3762 lys_set_enabled(module);
3763 }
3764
Michal Vasko26055752016-05-03 11:36:31 +02003765 if (module->implemented) {
3766 return EXIT_SUCCESS;
3767 }
3768
3769 ctx = module->ctx;
3770
3771 for (i = 0; i < ctx->models.used; ++i) {
3772 if (module == ctx->models.list[i]) {
3773 continue;
3774 }
3775
3776 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
3777 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
Radek Krejci0ec51da2016-12-14 16:42:03 +01003778 if (disabled) {
3779 /* set it back disabled */
3780 lys_set_disabled(module);
3781 }
Michal Vasko26055752016-05-03 11:36:31 +02003782 return EXIT_FAILURE;
3783 }
3784 }
3785
Radek Krejci27fe55e2016-09-13 17:13:35 +02003786 unres = calloc(1, sizeof *unres);
3787 if (!unres) {
3788 LOGMEM;
Radek Krejci0ec51da2016-12-14 16:42:03 +01003789 if (disabled) {
3790 /* set it back disabled */
3791 lys_set_disabled(module);
3792 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003793 return EXIT_FAILURE;
3794 }
3795 /* recursively make the module implemented */
3796 ((struct lys_module *)module)->implemented = 1;
3797 if (lys_set_implemented_recursion((struct lys_module *)module, unres)) {
3798 goto error;
3799 }
3800 /* process augments in submodules */
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003801 for (i = 0; i < module->inc_size && module->inc[i].submodule; ++i) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02003802 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
3803 /* apply augment */
Radek Krejcic8c22532016-11-09 15:11:24 +01003804 if (!module->inc[i].submodule->augment[j].target
3805 && (unres_schema_add_node((struct lys_module *)module->inc[j].submodule, unres,
3806 &module->inc[i].submodule->augment[j], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci0ec51da2016-12-14 16:42:03 +01003807
Radek Krejci27fe55e2016-09-13 17:13:35 +02003808 goto error;
3809 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003810 }
3811 }
Radek Krejcidf46e222016-11-08 11:57:37 +01003812 /* try again resolve augments in other modules possibly augmenting this one,
3813 * since we have just enabled it
3814 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003815 /* resolve rest of unres items */
3816 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
3817 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003818 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003819 unres_schema_free((struct lys_module *)module, &unres);
Michal Vasko26055752016-05-03 11:36:31 +02003820
3821 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02003822
3823error:
Radek Krejci0ec51da2016-12-14 16:42:03 +01003824
3825 if (disabled) {
3826 /* set it back disabled */
3827 lys_set_disabled(module);
3828 }
3829
Radek Krejci27fe55e2016-09-13 17:13:35 +02003830 ((struct lys_module *)module)->implemented = 0;
3831 unres_schema_free((struct lys_module *)module, &unres);
3832 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003833}
3834
3835void
3836lys_submodule_module_data_free(struct lys_submodule *submodule)
3837{
3838 struct lys_node *next, *elem;
3839
3840 /* remove parsed data */
3841 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
3842 if (elem->module == (struct lys_module *)submodule) {
3843 lys_node_free(elem, NULL, 0);
3844 }
3845 }
3846}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02003847
3848int
3849lys_is_key(struct lys_node_list *list, struct lys_node_leaf *leaf)
3850{
3851 uint8_t i;
3852
3853 for (i = 0; i < list->keys_size; i++) {
3854 if (list->keys[i] == leaf) {
3855 return i + 1;
3856 }
3857 }
3858
3859 return 0;
3860}
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02003861
3862API char *
3863lys_path(const struct lys_node *node)
3864{
3865 char *buf_backup = NULL, *buf = ly_buf(), *result = NULL;
3866 uint16_t index = LY_BUF_SIZE - 1;
3867
3868 if (!node) {
3869 LOGERR(LY_EINVAL, "%s: NULL node parameter", __func__);
3870 return NULL;
3871 }
3872
3873 /* backup the shared internal buffer */
3874 if (ly_buf_used && buf[0]) {
3875 buf_backup = strndup(buf, LY_BUF_SIZE - 1);
3876 }
3877 ly_buf_used++;
3878
3879 /* build the path */
3880 buf[index] = '\0';
Michal Vasko5efa25c2017-01-10 11:34:30 +01003881 ly_vlog_build_path_reverse(LY_VLOG_LYS, node, buf, &index, 0);
Radek Krejci0a0b1fc2016-10-18 15:57:37 +02003882 result = strdup(&buf[index]);
3883
3884 /* restore the shared internal buffer */
3885 if (buf_backup) {
3886 strcpy(buf, buf_backup);
3887 free(buf_backup);
3888 }
3889 ly_buf_used--;
3890
3891 return result;
3892}
Radek Krejci9ad23f42016-10-31 15:46:52 +01003893