1 /**
2 * @file tree_schema.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Manipulation with libyang schema data structures
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * 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
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15 #define _GNU_SOURCE
16
17 #ifdef __APPLE__
18 # include <sys/param.h>
19 #endif
20 #include <assert.h>
21 #include <ctype.h>
22 #include <limits.h>
23 #include <stdlib.h>
24 #include <sys/mman.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <dirent.h>
32
33 #include "common.h"
34 #include "context.h"
35 #include "parser.h"
36 #include "resolve.h"
37 #include "xml.h"
38 #include "xpath.h"
39 #include "xml_internal.h"
40 #include "tree_internal.h"
41 #include "validation.h"
42 #include "parser_yang.h"
43
44 static int lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
45 int in_grp, int shallow, struct unres_schema *unres);
46
47 API const struct lys_node_list *
lys_is_key(const struct lys_node_leaf * node,uint8_t * index)48 lys_is_key(const struct lys_node_leaf *node, uint8_t *index)
49 {
50 FUN_IN;
51
52 struct lys_node *parent = (struct lys_node *)node;
53 struct lys_node_list *list;
54 uint8_t i;
55
56 if (!node || node->nodetype != LYS_LEAF) {
57 return NULL;
58 }
59
60 do {
61 parent = lys_parent(parent);
62 } while (parent && parent->nodetype == LYS_USES);
63
64 if (!parent || parent->nodetype != LYS_LIST) {
65 return NULL;
66 }
67
68 list = (struct lys_node_list*)parent;
69 for (i = 0; i < list->keys_size; i++) {
70 if (list->keys[i] == node) {
71 if (index) {
72 (*index) = i;
73 }
74 return list;
75 }
76 }
77 return NULL;
78 }
79
80 API const struct lys_node *
lys_is_disabled(const struct lys_node * node,int recursive)81 lys_is_disabled(const struct lys_node *node, int recursive)
82 {
83 FUN_IN;
84
85 int i;
86
87 if (!node) {
88 return NULL;
89 }
90
91 check:
92 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
93 /* input/output does not have if-feature, so skip them */
94
95 /* check local if-features */
96 for (i = 0; i < node->iffeature_size; i++) {
97 if (!resolve_iffeature(&node->iffeature[i])) {
98 return node;
99 }
100 }
101 }
102
103 if (!recursive) {
104 return NULL;
105 }
106
107 /* go through parents */
108 if (node->nodetype == LYS_AUGMENT) {
109 /* go to parent actually means go to the target node */
110 node = ((struct lys_node_augment *)node)->target;
111 if (!node) {
112 /* unresolved augment, let's say it's enabled */
113 return NULL;
114 }
115 } else if (node->nodetype == LYS_EXT) {
116 return NULL;
117 } else if (node->parent) {
118 node = node->parent;
119 } else {
120 return NULL;
121 }
122
123 if (recursive == 2) {
124 /* continue only if the node cannot have a data instance */
125 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
126 return NULL;
127 }
128 }
129 goto check;
130 }
131
132 API int
lys_iffeature_value(const struct lys_iffeature * iff)133 lys_iffeature_value(const struct lys_iffeature *iff)
134 {
135 return resolve_iffeature((struct lys_iffeature *)iff);
136 }
137
138 API const struct lys_type *
lys_getnext_union_type(const struct lys_type * last,const struct lys_type * type)139 lys_getnext_union_type(const struct lys_type *last, const struct lys_type *type)
140 {
141 FUN_IN;
142
143 int found = 0;
144
145 if (!type || (type->base != LY_TYPE_UNION)) {
146 return NULL;
147 }
148
149 return lyp_get_next_union_type((struct lys_type *)type, (struct lys_type *)last, &found);
150 }
151
152 int
lys_get_sibling(const struct lys_node * siblings,const char * mod_name,int mod_name_len,const char * name,int nam_len,LYS_NODE type,const struct lys_node ** ret)153 lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
154 int nam_len, LYS_NODE type, const struct lys_node **ret)
155 {
156 const struct lys_node *node, *parent = NULL;
157 const struct lys_module *mod = NULL;
158 const char *node_mod_name;
159
160 assert(siblings && mod_name && name);
161 assert(!(type & (LYS_USES | LYS_GROUPING)));
162
163 /* fill the lengths in case the caller is so indifferent */
164 if (!mod_name_len) {
165 mod_name_len = strlen(mod_name);
166 }
167 if (!nam_len) {
168 nam_len = strlen(name);
169 }
170
171 while (siblings && (siblings->nodetype == LYS_USES)) {
172 siblings = siblings->child;
173 }
174 if (!siblings) {
175 /* unresolved uses */
176 return EXIT_FAILURE;
177 }
178
179 if (siblings->nodetype == LYS_GROUPING) {
180 for (node = siblings; (node->nodetype == LYS_GROUPING) && (node->prev != siblings); node = node->prev);
181 if (node->nodetype == LYS_GROUPING) {
182 /* we went through all the siblings, only groupings there - no valid sibling */
183 return EXIT_FAILURE;
184 }
185 /* update siblings to be valid */
186 siblings = node;
187 }
188
189 /* set parent correctly */
190 parent = lys_parent(siblings);
191
192 /* go up all uses */
193 while (parent && (parent->nodetype == LYS_USES)) {
194 parent = lys_parent(parent);
195 }
196
197 if (!parent) {
198 /* handle situation when there is a top-level uses referencing a foreign grouping */
199 for (node = siblings; lys_parent(node) && (node->nodetype == LYS_USES); node = lys_parent(node));
200 mod = lys_node_module(node);
201 }
202
203 /* try to find the node */
204 node = NULL;
205 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | LYS_GETNEXT_WITHINOUT))) {
206 if (!type || (node->nodetype & type)) {
207 /* module name comparison */
208 node_mod_name = lys_node_module(node)->name;
209 if (!ly_strequal(node_mod_name, mod_name, 1) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
210 continue;
211 }
212
213 /* direct name check */
214 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
215 if (ret) {
216 *ret = node;
217 }
218 return EXIT_SUCCESS;
219 }
220 }
221 }
222
223 return EXIT_FAILURE;
224 }
225
226 int
lys_getnext_data(const struct lys_module * mod,const struct lys_node * parent,const char * name,int nam_len,LYS_NODE type,int getnext_opts,const struct lys_node ** ret)227 lys_getnext_data(const struct lys_module *mod, const struct lys_node *parent, const char *name, int nam_len,
228 LYS_NODE type, int getnext_opts, const struct lys_node **ret)
229 {
230 const struct lys_node *node;
231
232 assert((mod || parent) && name);
233 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
234
235 if (!mod) {
236 mod = lys_node_module(parent);
237 }
238
239 /* try to find the node */
240 node = NULL;
241 while ((node = lys_getnext(node, parent, mod, getnext_opts))) {
242 if (!type || (node->nodetype & type)) {
243 /* module check */
244 if (lys_node_module(node) != lys_main_module(mod)) {
245 continue;
246 }
247
248 /* direct name check */
249 if (!strncmp(node->name, name, nam_len) && !node->name[nam_len]) {
250 if (ret) {
251 *ret = node;
252 }
253 return EXIT_SUCCESS;
254 }
255 }
256 }
257
258 return EXIT_FAILURE;
259 }
260
261 API const struct lys_node *
lys_getnext(const struct lys_node * last,const struct lys_node * parent,const struct lys_module * module,int options)262 lys_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module, int options)
263 {
264 FUN_IN;
265
266 const struct lys_node *next, *aug_parent;
267 struct lys_node **snode;
268
269 if ((!parent && !module) || (module && module->type) || (parent && (parent->nodetype == LYS_USES) && !(options & LYS_GETNEXT_PARENTUSES))) {
270 LOGARG;
271 return NULL;
272 }
273
274 if (!last) {
275 /* first call */
276
277 /* get know where to start */
278 if (parent) {
279 /* schema subtree */
280 snode = lys_child(parent, LYS_UNKNOWN);
281 /* do not return anything if the augment does not have any children */
282 if (!snode || !(*snode) || ((parent->nodetype == LYS_AUGMENT) && ((*snode)->parent != parent))) {
283 return NULL;
284 }
285 next = last = *snode;
286 } else {
287 /* top level data */
288 if (!(options & LYS_GETNEXT_NOSTATECHECK) && (module->disabled || !module->implemented)) {
289 /* nothing to return from a disabled/imported module */
290 return NULL;
291 }
292 next = last = module->data;
293 }
294 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
295 /* continue with uses content */
296 next = last->child;
297 } else {
298 /* continue after the last returned value */
299 next = last->next;
300 }
301
302 repeat:
303 if (parent && (parent->nodetype == LYS_AUGMENT) && next) {
304 /* do not return anything outside the parent augment */
305 aug_parent = next->parent;
306 do {
307 while (aug_parent && (aug_parent->nodetype != LYS_AUGMENT)) {
308 aug_parent = aug_parent->parent;
309 }
310 if (aug_parent) {
311 if (aug_parent == parent) {
312 break;
313 }
314 aug_parent = ((struct lys_node_augment *)aug_parent)->target;
315 }
316
317 } while (aug_parent);
318 if (!aug_parent) {
319 return NULL;
320 }
321 }
322 while (next && (next->nodetype == LYS_GROUPING)) {
323 if (options & LYS_GETNEXT_WITHGROUPING) {
324 return next;
325 }
326 next = next->next;
327 }
328
329 if (!next) { /* cover case when parent is augment */
330 if (!last || last->parent == parent || lys_parent(last) == parent) {
331 /* no next element */
332 return NULL;
333 }
334 last = lys_parent(last);
335 next = last->next;
336 goto repeat;
337 } else {
338 last = next;
339 }
340
341 if (!(options & LYS_GETNEXT_NOSTATECHECK) && lys_is_disabled(next, 0)) {
342 next = next->next;
343 goto repeat;
344 }
345
346 switch (next->nodetype) {
347 case LYS_INPUT:
348 case LYS_OUTPUT:
349 if (options & LYS_GETNEXT_WITHINOUT) {
350 return next;
351 } else if (next->child) {
352 next = next->child;
353 } else {
354 next = next->next;
355 }
356 goto repeat;
357
358 case LYS_CASE:
359 if (options & LYS_GETNEXT_WITHCASE) {
360 return next;
361 } else if (next->child) {
362 next = next->child;
363 } else {
364 next = next->next;
365 }
366 goto repeat;
367
368 case LYS_USES:
369 /* go into */
370 if (options & LYS_GETNEXT_WITHUSES) {
371 return next;
372 } else if (next->child) {
373 next = next->child;
374 } else {
375 next = next->next;
376 }
377 goto repeat;
378
379 case LYS_RPC:
380 case LYS_ACTION:
381 case LYS_NOTIF:
382 case LYS_LEAF:
383 case LYS_ANYXML:
384 case LYS_ANYDATA:
385 case LYS_LIST:
386 case LYS_LEAFLIST:
387 return next;
388
389 case LYS_CONTAINER:
390 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
391 if (next->child) {
392 /* go into */
393 next = next->child;
394 } else {
395 next = next->next;
396 }
397 goto repeat;
398 } else {
399 return next;
400 }
401
402 case LYS_CHOICE:
403 if (options & LYS_GETNEXT_WITHCHOICE) {
404 return next;
405 } else if (next->child) {
406 /* go into */
407 next = next->child;
408 } else {
409 next = next->next;
410 }
411 goto repeat;
412
413 default:
414 /* we should not be here */
415 return NULL;
416 }
417 }
418
419 void
lys_node_unlink(struct lys_node * node)420 lys_node_unlink(struct lys_node *node)
421 {
422 struct lys_node *parent, *first, **pp = NULL;
423 struct lys_module *main_module;
424
425 if (!node) {
426 return;
427 }
428
429 /* unlink from data model if necessary */
430 if (node->module) {
431 /* get main module with data tree */
432 main_module = lys_node_module(node);
433 if (main_module->data == node) {
434 main_module->data = node->next;
435 }
436 }
437
438 /* store pointers to important nodes */
439 parent = node->parent;
440 if (parent && (parent->nodetype == LYS_AUGMENT)) {
441 /* handle augments - first, unlink it from the augment parent ... */
442 if (parent->child == node) {
443 parent->child = (node->next && node->next->parent == parent) ? node->next : NULL;
444 }
445
446 if (parent->flags & LYS_NOTAPPLIED) {
447 /* data are not connected in the target, so we cannot continue with the target as a parent */
448 parent = NULL;
449 } else {
450 /* data are connected in target, so we will continue with the target as a parent */
451 parent = ((struct lys_node_augment *)parent)->target;
452 }
453 }
454
455 /* unlink from parent */
456 if (parent) {
457 if (parent->nodetype == LYS_EXT) {
458 pp = (struct lys_node **)lys_ext_complex_get_substmt(lys_snode2stmt(node->nodetype),
459 (struct lys_ext_instance_complex*)parent, NULL);
460 if (*pp == node) {
461 *pp = node->next;
462 }
463 } else if (parent->child == node) {
464 parent->child = node->next;
465 }
466 node->parent = NULL;
467 }
468
469 /* unlink from siblings */
470 if (node->prev == node) {
471 /* there are no more siblings */
472 return;
473 }
474 if (node->next) {
475 node->next->prev = node->prev;
476 } else {
477 /* unlinking the last element */
478 if (parent) {
479 if (parent->nodetype == LYS_EXT) {
480 first = *(struct lys_node **)pp;
481 } else {
482 first = parent->child;
483 }
484 } else {
485 first = node;
486 while (first->prev->next) {
487 first = first->prev;
488 }
489 }
490 first->prev = node->prev;
491 }
492 if (node->prev->next) {
493 node->prev->next = node->next;
494 }
495
496 /* clean up the unlinked element */
497 node->next = NULL;
498 node->prev = node;
499 }
500
501 struct lys_node_grp *
lys_find_grouping_up(const char * name,struct lys_node * start)502 lys_find_grouping_up(const char *name, struct lys_node *start)
503 {
504 struct lys_node *par_iter, *iter, *stop;
505
506 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
507 /* top-level augment, look into module (uses augment is handled correctly below) */
508 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
509 par_iter = lys_main_module(par_iter->parent->module)->data;
510 if (!par_iter) {
511 break;
512 }
513 }
514
515 if (par_iter->nodetype == LYS_EXT) {
516 /* we are in a top-level extension, search grouping in top-level groupings */
517 par_iter = lys_main_module(par_iter->module)->data;
518 if (!par_iter) {
519 /* not connected yet, wait */
520 return NULL;
521 }
522 } else if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
523 continue;
524 }
525
526 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
527 if (!stop) {
528 stop = par_iter;
529 } else if (iter == stop) {
530 break;
531 }
532 if (iter->nodetype != LYS_GROUPING) {
533 continue;
534 }
535
536 if (!strcmp(name, iter->name)) {
537 return (struct lys_node_grp *)iter;
538 }
539 }
540 }
541
542 return NULL;
543 }
544
545 /*
546 * get next grouping in the root's subtree, in the
547 * first call, tha last is NULL
548 */
549 static struct lys_node_grp *
lys_get_next_grouping(struct lys_node_grp * lastgrp,struct lys_node * root)550 lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
551 {
552 struct lys_node *last = (struct lys_node *)lastgrp;
553 struct lys_node *next;
554
555 assert(root);
556
557 if (!last) {
558 last = root;
559 }
560
561 while (1) {
562 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
563 next = last->child;
564 } else {
565 next = NULL;
566 }
567 if (!next) {
568 if (last == root) {
569 /* we are done */
570 return NULL;
571 }
572
573 /* no children, go to siblings */
574 next = last->next;
575 }
576 while (!next) {
577 /* go back through parents */
578 if (lys_parent(last) == root) {
579 /* we are done */
580 return NULL;
581 }
582 next = last->next;
583 last = lys_parent(last);
584 }
585
586 if (next->nodetype == LYS_GROUPING) {
587 return (struct lys_node_grp *)next;
588 }
589
590 last = next;
591 }
592 }
593
594 /* logs directly */
595 int
lys_check_id(struct lys_node * node,struct lys_node * parent,struct lys_module * module)596 lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
597 {
598 struct lys_node *start, *stop, *iter;
599 struct lys_node_grp *grp;
600 int down, up;
601 struct ly_set excluded_parents = {0};
602
603 assert(node);
604
605 if (!parent) {
606 assert(module);
607 } else {
608 module = parent->module;
609 }
610 module = lys_main_module(module);
611
612 switch (node->nodetype) {
613 case LYS_GROUPING:
614 /* 6.2.1, rule 6 */
615 if (parent) {
616 start = *lys_child(parent, LYS_GROUPING);
617 if (!start) {
618 down = 0;
619 start = parent;
620 } else {
621 down = 1;
622 }
623 if (parent->nodetype == LYS_EXT) {
624 up = 0;
625 } else {
626 up = 1;
627 }
628 } else {
629 down = up = 1;
630 start = module->data;
631 }
632 /* go up */
633 if (up && lys_find_grouping_up(node->name, start)) {
634 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
635 return EXIT_FAILURE;
636 }
637 /* go down, because grouping can be defined after e.g. container in which is collision */
638 if (down) {
639 for (iter = start, stop = NULL; iter; iter = iter->prev) {
640 if (!stop) {
641 stop = start;
642 } else if (iter == stop) {
643 break;
644 }
645 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
646 continue;
647 }
648
649 grp = NULL;
650 while ((grp = lys_get_next_grouping(grp, iter))) {
651 if (ly_strequal(node->name, grp->name, 1)) {
652 LOGVAL(module->ctx, LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
653 return EXIT_FAILURE;
654 }
655 }
656 }
657 }
658 break;
659 case LYS_LEAF:
660 case LYS_LEAFLIST:
661 case LYS_LIST:
662 case LYS_CONTAINER:
663 case LYS_CHOICE:
664 case LYS_RPC:
665 case LYS_NOTIF:
666 case LYS_ACTION:
667 case LYS_ANYDATA:
668 /* 6.2.1, rule 7 */
669 if (parent) {
670 iter = parent;
671 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
672 if (iter->nodetype == LYS_AUGMENT) {
673 if (((struct lys_node_augment *)iter)->target) {
674 /* augment is resolved, go up */
675 iter = ((struct lys_node_augment *)iter)->target;
676 continue;
677 }
678 /* augment is not resolved, this is the final parent */
679 break;
680 }
681 ly_set_add(&excluded_parents, (void *)iter, LY_SET_OPT_USEASLIST);
682 iter = iter->parent;
683 }
684
685 if (!iter) {
686 stop = NULL;
687 iter = module->data;
688 } else if (iter->nodetype == LYS_EXT) {
689 stop = iter;
690 iter = (struct lys_node *)lys_child(iter, node->nodetype);
691 if (iter) {
692 iter = *(struct lys_node **)iter;
693 }
694 } else {
695 stop = iter;
696 iter = iter->child;
697 }
698 } else {
699 stop = NULL;
700 iter = module->data;
701 }
702 while (iter) {
703 if ((ly_set_contains(&excluded_parents, (void *)iter) != -1) || iter->nodetype & (LYS_USES | LYS_CASE)) {
704 iter = iter->child;
705 continue;
706 }
707
708 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_RPC | LYS_NOTIF | LYS_ACTION | LYS_ANYDATA)) {
709 if (lys_node_module(iter) == lys_node_module(node) && ly_strequal(iter->name, node->name, 1)) {
710 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
711 ly_set_clean(&excluded_parents);
712 return EXIT_FAILURE;
713 }
714 }
715
716 /* special case for choice - we must check the choice's name as
717 * well as the names of nodes under the choice
718 */
719 if (iter->nodetype == LYS_CHOICE) {
720 iter = iter->child;
721 continue;
722 }
723
724 /* go to siblings */
725 if (!iter->next) {
726 /* no sibling, go to parent's sibling */
727 do {
728 /* for parent LYS_AUGMENT */
729 if (iter->parent == stop) {
730 iter = stop;
731 break;
732 }
733 iter = lys_parent(iter);
734 if (iter && iter->next) {
735 break;
736 }
737 } while (iter != stop);
738
739 if (iter == stop) {
740 break;
741 }
742 }
743 iter = iter->next;
744 }
745 ly_set_clean(&excluded_parents);
746 break;
747 case LYS_CASE:
748 /* 6.2.1, rule 8 */
749 if (parent) {
750 start = *lys_child(parent, LYS_CASE);
751 } else {
752 start = module->data;
753 }
754
755 LY_TREE_FOR(start, iter) {
756 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
757 continue;
758 }
759
760 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
761 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
762 return EXIT_FAILURE;
763 }
764 }
765 break;
766 default:
767 /* no check needed */
768 break;
769 }
770
771 return EXIT_SUCCESS;
772 }
773
774 /* logs directly */
775 int
lys_node_addchild(struct lys_node * parent,struct lys_module * module,struct lys_node * child,int options)776 lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child, int options)
777 {
778 struct ly_ctx *ctx = child->module->ctx;
779 struct lys_node *iter, **pchild, *log_parent;
780 struct lys_node_inout *in, *out;
781 struct lys_node_case *c;
782 struct lys_node_augment *aug;
783 int type, shortcase = 0;
784 void *p;
785 struct lyext_substmt *info = NULL;
786
787 assert(child);
788
789 if (parent) {
790 type = parent->nodetype;
791 module = parent->module;
792 log_parent = parent;
793
794 if (type == LYS_USES) {
795 /* we are adding children to uses -> we must be copying grouping contents into it, so properly check the parent */
796 while (log_parent && (log_parent->nodetype == LYS_USES)) {
797 if (log_parent->nodetype == LYS_AUGMENT) {
798 aug = (struct lys_node_augment *)log_parent;
799 if (!aug->target) {
800 /* unresolved augment, just pass the node type check */
801 goto skip_nodetype_check;
802 }
803 log_parent = aug->target;
804 } else {
805 log_parent = log_parent->parent;
806 }
807 }
808 if (log_parent) {
809 type = log_parent->nodetype;
810 } else {
811 type = 0;
812 }
813 }
814 } else {
815 assert(module);
816 assert(!(child->nodetype & (LYS_INPUT | LYS_OUTPUT)));
817 type = 0;
818 log_parent = NULL;
819 }
820
821 /* checks */
822 switch (type) {
823 case LYS_CONTAINER:
824 case LYS_LIST:
825 case LYS_GROUPING:
826 case LYS_USES:
827 if (!(child->nodetype &
828 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
829 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
830 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, log_parent, strnodetype(child->nodetype), strnodetype(log_parent->nodetype));
831 return EXIT_FAILURE;
832 }
833 break;
834 case LYS_INPUT:
835 case LYS_OUTPUT:
836 case LYS_NOTIF:
837 if (!(child->nodetype &
838 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
839 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
840 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, log_parent, strnodetype(child->nodetype), strnodetype(log_parent->nodetype));
841 return EXIT_FAILURE;
842 }
843 break;
844 case LYS_CHOICE:
845 if (!(child->nodetype &
846 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
847 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, log_parent, strnodetype(child->nodetype), "choice");
848 return EXIT_FAILURE;
849 }
850 if (child->nodetype != LYS_CASE) {
851 shortcase = 1;
852 }
853 break;
854 case LYS_CASE:
855 if (!(child->nodetype &
856 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
857 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, log_parent, strnodetype(child->nodetype), "case");
858 return EXIT_FAILURE;
859 }
860 break;
861 case LYS_RPC:
862 case LYS_ACTION:
863 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
864 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, log_parent, strnodetype(child->nodetype), "rpc");
865 return EXIT_FAILURE;
866 }
867 break;
868 case LYS_LEAF:
869 case LYS_LEAFLIST:
870 case LYS_ANYXML:
871 case LYS_ANYDATA:
872 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, log_parent, strnodetype(child->nodetype), strnodetype(log_parent->nodetype));
873 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "The \"%s\" statement cannot have any data substatement.",
874 strnodetype(log_parent->nodetype));
875 return EXIT_FAILURE;
876 case LYS_AUGMENT:
877 if (!(child->nodetype &
878 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
879 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
880 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, log_parent, strnodetype(child->nodetype), strnodetype(log_parent->nodetype));
881 return EXIT_FAILURE;
882 }
883 break;
884 case LYS_UNKNOWN:
885 /* top level */
886 if (!(child->nodetype &
887 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
888 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
889 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, log_parent, strnodetype(child->nodetype), "(sub)module");
890 return EXIT_FAILURE;
891 }
892 break;
893 case LYS_EXT:
894 /* plugin-defined */
895 p = lys_ext_complex_get_substmt(lys_snode2stmt(child->nodetype), (struct lys_ext_instance_complex*)log_parent, &info);
896 if (!p) {
897 LOGVAL(ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, log_parent, strnodetype(child->nodetype),
898 ((struct lys_ext_instance_complex*)log_parent)->def->name);
899 return EXIT_FAILURE;
900 }
901 /* TODO check cardinality */
902 break;
903 }
904
905 skip_nodetype_check:
906 /* check identifier uniqueness */
907 if (!(module->ctx->models.flags & LY_CTX_TRUSTED) && lys_check_id(child, parent, module)) {
908 return EXIT_FAILURE;
909 }
910
911 if (child->parent) {
912 lys_node_unlink(child);
913 }
914
915 if ((child->nodetype & (LYS_INPUT | LYS_OUTPUT)) && parent->nodetype != LYS_EXT) {
916 /* find the implicit input/output node */
917 LY_TREE_FOR(parent->child, iter) {
918 if (iter->nodetype == child->nodetype) {
919 break;
920 }
921 }
922 assert(iter);
923
924 /* switch the old implicit node (iter) with the new one (child) */
925 if (parent->child == iter) {
926 /* first child */
927 parent->child = child;
928 } else {
929 iter->prev->next = child;
930 }
931 child->prev = iter->prev;
932 child->next = iter->next;
933 if (iter->next) {
934 iter->next->prev = child;
935 } else {
936 /* last child */
937 parent->child->prev = child;
938 }
939 child->parent = parent;
940
941 /* isolate the node and free it */
942 iter->next = NULL;
943 iter->prev = iter;
944 iter->parent = NULL;
945 lys_node_free(ctx, iter, NULL, 0);
946 } else {
947 if (shortcase) {
948 /* create the implicit case to allow it to serve as a target of the augments,
949 * it won't be printed, but it will be present in the tree */
950 c = calloc(1, sizeof *c);
951 LY_CHECK_ERR_RETURN(!c, LOGMEM(ctx), EXIT_FAILURE);
952 c->name = lydict_insert(module->ctx, child->name, 0);
953 c->flags = LYS_IMPLICIT;
954 if (!(options & (LYS_PARSE_OPT_CFG_IGNORE | LYS_PARSE_OPT_CFG_NOINHERIT))) {
955 /* get config flag from parent */
956 c->flags |= parent->flags & LYS_CONFIG_MASK;
957 }
958 c->module = module;
959 c->nodetype = LYS_CASE;
960 c->prev = (struct lys_node*)c;
961 lys_node_addchild(parent, module, (struct lys_node*)c, options);
962 parent = (struct lys_node*)c;
963 }
964 /* connect the child correctly */
965 if (!parent) {
966 if (module->data) {
967 module->data->prev->next = child;
968 child->prev = module->data->prev;
969 module->data->prev = child;
970 } else {
971 module->data = child;
972 }
973 } else {
974 pchild = lys_child(parent, child->nodetype);
975 assert(pchild);
976
977 child->parent = parent;
978 if (!(*pchild)) {
979 /* the only/first child of the parent */
980 *pchild = child;
981 iter = child;
982 } else {
983 /* add a new child at the end of parent's child list */
984 iter = (*pchild)->prev;
985 iter->next = child;
986 child->prev = iter;
987 }
988 while (iter->next) {
989 iter = iter->next;
990 iter->parent = parent;
991 }
992 (*pchild)->prev = iter;
993 }
994 }
995
996 /* check config value (but ignore them in groupings and augments) */
997 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); iter = iter->parent);
998 if (parent && !iter) {
999 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
1000 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
1001 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, child, "true", "config");
1002 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
1003 return EXIT_FAILURE;
1004 }
1005 }
1006
1007 /* propagate information about status data presence */
1008 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
1009 (child->flags & LYS_INCL_STATUS)) {
1010 for(iter = parent; iter; iter = lys_parent(iter)) {
1011 /* store it only into container or list - the only data inner nodes */
1012 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
1013 if (iter->flags & LYS_INCL_STATUS) {
1014 /* done, someone else set it already from here */
1015 break;
1016 }
1017 /* set flag about including status data */
1018 iter->flags |= LYS_INCL_STATUS;
1019 }
1020 }
1021 }
1022
1023 /* create implicit input/output nodes to have available them as possible target for augment */
1024 if (child->nodetype & (LYS_RPC | LYS_ACTION)) {
1025 if (child->nodetype == LYS_ACTION) {
1026 for (iter = child->parent; iter; iter = lys_parent(iter)) {
1027 if ((iter->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
1028 || ((iter->nodetype == LYS_LIST) && !((struct lys_node_list *)iter)->keys)) {
1029 LOGVAL(module->ctx, LYE_INPAR, LY_VLOG_LYS, iter, strnodetype(iter->nodetype), "action");
1030 return EXIT_FAILURE;
1031 }
1032 }
1033 }
1034
1035 if (!child->child) {
1036 in = calloc(1, sizeof *in);
1037 out = calloc(1, sizeof *out);
1038 if (!in || !out) {
1039 LOGMEM(ctx);
1040 free(in);
1041 free(out);
1042 return EXIT_FAILURE;
1043 }
1044 in->nodetype = LYS_INPUT;
1045 in->name = lydict_insert(child->module->ctx, "input", 5);
1046 out->nodetype = LYS_OUTPUT;
1047 out->name = lydict_insert(child->module->ctx, "output", 6);
1048 in->module = out->module = child->module;
1049 in->parent = out->parent = child;
1050 in->flags = out->flags = LYS_IMPLICIT;
1051 in->next = (struct lys_node *)out;
1052 in->prev = (struct lys_node *)out;
1053 out->prev = (struct lys_node *)in;
1054 child->child = (struct lys_node *)in;
1055 }
1056 }
1057 return EXIT_SUCCESS;
1058 }
1059
1060 const struct lys_module *
lys_parse_mem_(struct ly_ctx * ctx,const char * data,LYS_INFORMAT format,const char * revision,int internal,int implement)1061 lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, const char *revision, int internal, int implement)
1062 {
1063 char *enlarged_data = NULL;
1064 struct lys_module *mod = NULL;
1065 unsigned int len;
1066
1067 if (!ctx || !data) {
1068 LOGARG;
1069 return NULL;
1070 }
1071
1072 if (!internal && format == LYS_IN_YANG) {
1073 /* enlarge data by 2 bytes for flex */
1074 len = strlen(data);
1075 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
1076 LY_CHECK_ERR_RETURN(!enlarged_data, LOGMEM(ctx), NULL);
1077 memcpy(enlarged_data, data, len);
1078 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1079 data = enlarged_data;
1080 }
1081
1082 switch (format) {
1083 case LYS_IN_YIN:
1084 mod = yin_read_module(ctx, data, revision, implement);
1085 break;
1086 case LYS_IN_YANG:
1087 mod = yang_read_module(ctx, data, 0, revision, implement);
1088 break;
1089 default:
1090 LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
1091 break;
1092 }
1093
1094 free(enlarged_data);
1095
1096 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
1097 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
1098 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
1099 * the anotation definitions available in the internal schema structure. There is another hack in schema
1100 * printers to do not print this internally added annotation. */
1101 if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
1102 if (lyp_add_ietf_netconf_annotations_config(mod)) {
1103 lys_free(mod, NULL, 1, 1);
1104 return NULL;
1105 }
1106 }
1107
1108 return mod;
1109 }
1110
1111 API const struct lys_module *
lys_parse_mem(struct ly_ctx * ctx,const char * data,LYS_INFORMAT format)1112 lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
1113 {
1114 FUN_IN;
1115
1116 return lys_parse_mem_(ctx, data, format, NULL, 0, 1);
1117 }
1118
1119 struct lys_submodule *
lys_sub_parse_mem(struct lys_module * module,const char * data,LYS_INFORMAT format,struct unres_schema * unres)1120 lys_sub_parse_mem(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
1121 {
1122 char *enlarged_data = NULL;
1123 struct lys_submodule *submod = NULL;
1124 unsigned int len;
1125
1126 assert(module);
1127 assert(data);
1128
1129 if (format == LYS_IN_YANG) {
1130 /* enlarge data by 2 bytes for flex */
1131 len = strlen(data);
1132 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
1133 LY_CHECK_ERR_RETURN(!enlarged_data, LOGMEM(module->ctx), NULL);
1134 memcpy(enlarged_data, data, len);
1135 enlarged_data[len] = enlarged_data[len + 1] = '\0';
1136 data = enlarged_data;
1137 }
1138
1139 /* get the main module */
1140 module = lys_main_module(module);
1141
1142 switch (format) {
1143 case LYS_IN_YIN:
1144 submod = yin_read_submodule(module, data, unres);
1145 break;
1146 case LYS_IN_YANG:
1147 submod = yang_read_submodule(module, data, 0, unres);
1148 break;
1149 default:
1150 assert(0);
1151 break;
1152 }
1153
1154 free(enlarged_data);
1155 return submod;
1156 }
1157
1158 API const struct lys_module *
lys_parse_path(struct ly_ctx * ctx,const char * path,LYS_INFORMAT format)1159 lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1160 {
1161 FUN_IN;
1162
1163 int fd;
1164 const struct lys_module *ret;
1165 const char *rev, *dot, *filename;
1166 size_t len;
1167
1168 if (!ctx || !path) {
1169 LOGARG;
1170 return NULL;
1171 }
1172
1173 fd = open(path, O_RDONLY);
1174 if (fd == -1) {
1175 LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1176 return NULL;
1177 }
1178
1179 ret = lys_parse_fd(ctx, fd, format);
1180 close(fd);
1181
1182 if (!ret) {
1183 /* error */
1184 return NULL;
1185 }
1186
1187 /* check that name and revision match filename */
1188 filename = strrchr(path, '/');
1189 if (!filename) {
1190 filename = path;
1191 } else {
1192 filename++;
1193 }
1194 rev = strchr(filename, '@');
1195 dot = strrchr(filename, '.');
1196
1197 /* name */
1198 len = strlen(ret->name);
1199 if (strncmp(filename, ret->name, len) ||
1200 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
1201 LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, ret->name);
1202 }
1203 if (rev) {
1204 len = dot - ++rev;
1205 if (!ret->rev_size || len != 10 || strncmp(ret->rev[0].date, rev, len)) {
1206 LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", filename,
1207 ret->rev_size ? ret->rev[0].date : "none");
1208 }
1209 }
1210
1211 if (!ret->filepath) {
1212 /* store URI */
1213 char rpath[PATH_MAX];
1214 if (realpath(path, rpath) != NULL) {
1215 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, rpath, 0);
1216 } else {
1217 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
1218 }
1219 }
1220
1221 return ret;
1222 }
1223
1224 API const struct lys_module *
lys_parse_fd(struct ly_ctx * ctx,int fd,LYS_INFORMAT format)1225 lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
1226 {
1227 FUN_IN;
1228
1229 return lys_parse_fd_(ctx, fd, format, NULL, 1);
1230 }
1231
1232 static void
lys_parse_set_filename(struct ly_ctx * ctx,const char ** filename,int fd)1233 lys_parse_set_filename(struct ly_ctx *ctx, const char **filename, int fd)
1234 {
1235 #ifdef __APPLE__
1236 char path[MAXPATHLEN];
1237 #else
1238 int len;
1239 char path[PATH_MAX], proc_path[32];
1240 #endif
1241
1242 #ifdef __APPLE__
1243 if (fcntl(fd, F_GETPATH, path) != -1) {
1244 *filename = lydict_insert(ctx, path, 0);
1245 }
1246 #else
1247 /* get URI if there is /proc */
1248 sprintf(proc_path, "/proc/self/fd/%d", fd);
1249 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
1250 *filename = lydict_insert(ctx, path, len);
1251 }
1252 #endif
1253 }
1254
1255 const struct lys_module *
lys_parse_fd_(struct ly_ctx * ctx,int fd,LYS_INFORMAT format,const char * revision,int implement)1256 lys_parse_fd_(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, const char *revision, int implement)
1257 {
1258 const struct lys_module *module;
1259 size_t length;
1260 char *addr;
1261
1262 if (!ctx || fd < 0) {
1263 LOGARG;
1264 return NULL;
1265 }
1266
1267 if (lyp_mmap(ctx, fd, format == LYS_IN_YANG ? 1 : 0, &length, (void **)&addr)) {
1268 LOGERR(ctx, LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
1269 return NULL;
1270 } else if (!addr) {
1271 LOGERR(ctx, LY_EINVAL, "Empty schema file.");
1272 return NULL;
1273 }
1274
1275 module = lys_parse_mem_(ctx, addr, format, revision, 1, implement);
1276 lyp_munmap(addr, length);
1277
1278 if (module && !module->filepath) {
1279 lys_parse_set_filename(ctx, (const char **)&module->filepath, fd);
1280 }
1281
1282 return module;
1283 }
1284
1285 struct lys_submodule *
lys_sub_parse_fd(struct lys_module * module,int fd,LYS_INFORMAT format,struct unres_schema * unres)1286 lys_sub_parse_fd(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
1287 {
1288 struct lys_submodule *submodule;
1289 size_t length;
1290 char *addr;
1291
1292 assert(module);
1293 assert(fd >= 0);
1294
1295 if (lyp_mmap(module->ctx, fd, format == LYS_IN_YANG ? 1 : 0, &length, (void **)&addr)) {
1296 LOGERR(module->ctx, LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
1297 return NULL;
1298 } else if (!addr) {
1299 LOGERR(module->ctx, LY_EINVAL, "Empty submodule schema file.");
1300 return NULL;
1301 }
1302
1303 /* get the main module */
1304 module = lys_main_module(module);
1305
1306 switch (format) {
1307 case LYS_IN_YIN:
1308 submodule = yin_read_submodule(module, addr, unres);
1309 break;
1310 case LYS_IN_YANG:
1311 submodule = yang_read_submodule(module, addr, 0, unres);
1312 break;
1313 default:
1314 LOGINT(module->ctx);
1315 return NULL;
1316 }
1317
1318 lyp_munmap(addr, length);
1319
1320 if (submodule && !submodule->filepath) {
1321 lys_parse_set_filename(module->ctx, (const char **)&submodule->filepath, fd);
1322 }
1323
1324 return submodule;
1325
1326 }
1327
1328 API int
lys_search_localfile(const char * const * searchpaths,int cwd,const char * name,const char * revision,char ** localfile,LYS_INFORMAT * format)1329 lys_search_localfile(const char * const *searchpaths, int cwd, const char *name, const char *revision, char **localfile, LYS_INFORMAT *format)
1330 {
1331 FUN_IN;
1332
1333 size_t len, flen, match_len = 0, dir_len;
1334 int i, implicit_cwd = 0, ret = EXIT_FAILURE;
1335 char *wd, *wn = NULL;
1336 DIR *dir = NULL;
1337 struct dirent *file;
1338 char *match_name = NULL;
1339 LYS_INFORMAT format_aux, match_format = 0;
1340 unsigned int u;
1341 struct ly_set *dirs;
1342 struct stat st;
1343
1344 if (!localfile) {
1345 LOGARG;
1346 return EXIT_FAILURE;
1347 }
1348
1349 /* start to fill the dir fifo with the context's search path (if set)
1350 * and the current working directory */
1351 dirs = ly_set_new();
1352 if (!dirs) {
1353 LOGMEM(NULL);
1354 return EXIT_FAILURE;
1355 }
1356
1357 len = strlen(name);
1358 if (cwd) {
1359 wd = get_current_dir_name();
1360 if (!wd) {
1361 LOGMEM(NULL);
1362 goto cleanup;
1363 } else {
1364 /* add implicit current working directory (./) to be searched,
1365 * this directory is not searched recursively */
1366 if (ly_set_add(dirs, wd, 0) == -1) {
1367 goto cleanup;
1368 }
1369 implicit_cwd = 1;
1370 }
1371 }
1372 if (searchpaths) {
1373 for (i = 0; searchpaths[i]; i++) {
1374 /* check for duplicities with the implicit current working directory */
1375 if (implicit_cwd && !strcmp(dirs->set.g[0], searchpaths[i])) {
1376 implicit_cwd = 0;
1377 continue;
1378 }
1379 wd = strdup(searchpaths[i]);
1380 if (!wd) {
1381 LOGMEM(NULL);
1382 goto cleanup;
1383 } else if (ly_set_add(dirs, wd, 0) == -1) {
1384 goto cleanup;
1385 }
1386 }
1387 }
1388 wd = NULL;
1389
1390 /* start searching */
1391 while (dirs->number) {
1392 free(wd);
1393 free(wn); wn = NULL;
1394
1395 dirs->number--;
1396 wd = (char *)dirs->set.g[dirs->number];
1397 dirs->set.g[dirs->number] = NULL;
1398 LOGVRB("Searching for \"%s\" in %s.", name, wd);
1399
1400 if (dir) {
1401 closedir(dir);
1402 }
1403 dir = opendir(wd);
1404 dir_len = strlen(wd);
1405 if (!dir) {
1406 LOGWRN(NULL, "Unable to open directory \"%s\" for searching (sub)modules (%s).", wd, strerror(errno));
1407 } else {
1408 while ((file = readdir(dir))) {
1409 if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
1410 /* skip . and .. */
1411 continue;
1412 }
1413 free(wn);
1414 if (asprintf(&wn, "%s/%s", wd, file->d_name) == -1) {
1415 LOGMEM(NULL);
1416 goto cleanup;
1417 }
1418 if (stat(wn, &st) == -1) {
1419 LOGWRN(NULL, "Unable to get information about \"%s\" file in \"%s\" when searching for (sub)modules (%s)",
1420 file->d_name, wd, strerror(errno));
1421 continue;
1422 }
1423 if (S_ISDIR(st.st_mode) && (dirs->number || !implicit_cwd)) {
1424 /* we have another subdirectory in searchpath to explore,
1425 * subdirectories are not taken into account in current working dir (dirs->set.g[0]) */
1426 if (ly_set_add(dirs, wn, 0) == -1) {
1427 goto cleanup;
1428 }
1429 /* continue with the next item in current directory */
1430 wn = NULL;
1431 continue;
1432 } else if (!S_ISREG(st.st_mode)) {
1433 /* not a regular file (note that we see the target of symlinks instead of symlinks */
1434 continue;
1435 }
1436
1437 /* here we know that the item is a file which can contain a module */
1438 if (strncmp(name, file->d_name, len) ||
1439 (file->d_name[len] != '.' && file->d_name[len] != '@')) {
1440 /* different filename than the module we search for */
1441 continue;
1442 }
1443
1444 /* get type according to filename suffix */
1445 flen = strlen(file->d_name);
1446 if (!strcmp(&file->d_name[flen - 4], ".yin")) {
1447 format_aux = LYS_IN_YIN;
1448 } else if (!strcmp(&file->d_name[flen - 5], ".yang")) {
1449 format_aux = LYS_IN_YANG;
1450 } else {
1451 /* not supportde suffix/file format */
1452 continue;
1453 }
1454
1455 if (revision) {
1456 /* we look for the specific revision, try to get it from the filename */
1457 if (file->d_name[len] == '@') {
1458 /* check revision from the filename */
1459 if (strncmp(revision, &file->d_name[len + 1], strlen(revision))) {
1460 /* another revision */
1461 continue;
1462 } else {
1463 /* exact revision */
1464 free(match_name);
1465 match_name = wn;
1466 wn = NULL;
1467 match_len = dir_len + 1 + len;
1468 match_format = format_aux;
1469 goto success;
1470 }
1471 } else {
1472 /* continue trying to find exact revision match, use this only if not found */
1473 free(match_name);
1474 match_name = wn;
1475 wn = NULL;
1476 match_len = dir_len + 1 +len;
1477 match_format = format_aux;
1478 continue;
1479 }
1480 } else {
1481 /* remember the revision and try to find the newest one */
1482 if (match_name) {
1483 if (file->d_name[len] != '@' || lyp_check_date(NULL, &file->d_name[len + 1])) {
1484 continue;
1485 } else if (match_name[match_len] == '@' &&
1486 (strncmp(&match_name[match_len + 1], &file->d_name[len + 1], LY_REV_SIZE - 1) >= 0)) {
1487 continue;
1488 }
1489 free(match_name);
1490 }
1491
1492 match_name = wn;
1493 wn = NULL;
1494 match_len = dir_len + 1 + len;
1495 match_format = format_aux;
1496 continue;
1497 }
1498 }
1499 }
1500 }
1501
1502 success:
1503 (*localfile) = match_name;
1504 match_name = NULL;
1505 if (format) {
1506 (*format) = match_format;
1507 }
1508 ret = EXIT_SUCCESS;
1509
1510 cleanup:
1511 free(wn);
1512 free(wd);
1513 if (dir) {
1514 closedir(dir);
1515 }
1516 free(match_name);
1517 for (u = 0; u < dirs->number; u++) {
1518 free(dirs->set.g[u]);
1519 }
1520 ly_set_free(dirs);
1521
1522 return ret;
1523 }
1524
1525 int
lys_ext_iter(struct lys_ext_instance ** ext,uint8_t ext_size,uint8_t start,LYEXT_SUBSTMT substmt)1526 lys_ext_iter(struct lys_ext_instance **ext, uint8_t ext_size, uint8_t start, LYEXT_SUBSTMT substmt)
1527 {
1528 unsigned int u;
1529
1530 for (u = start; u < ext_size; u++) {
1531 if (ext[u]->insubstmt == substmt) {
1532 return u;
1533 }
1534 }
1535
1536 return -1;
1537 }
1538
1539 /*
1540 * duplicate extension instance
1541 */
1542 int
lys_ext_dup(struct ly_ctx * ctx,struct lys_module * mod,struct lys_ext_instance ** orig,uint8_t size,void * parent,LYEXT_PAR parent_type,struct lys_ext_instance *** new,int shallow,struct unres_schema * unres)1543 lys_ext_dup(struct ly_ctx *ctx, struct lys_module *mod, struct lys_ext_instance **orig, uint8_t size, void *parent,
1544 LYEXT_PAR parent_type, struct lys_ext_instance ***new, int shallow, struct unres_schema *unres)
1545 {
1546 int i;
1547 uint8_t u = 0;
1548 struct lys_ext_instance **result;
1549 struct unres_ext *info, *info_orig;
1550 size_t len;
1551
1552 assert(new);
1553
1554 if (!size) {
1555 if (orig) {
1556 LOGINT(ctx);
1557 return EXIT_FAILURE;
1558 }
1559 (*new) = NULL;
1560 return EXIT_SUCCESS;
1561 }
1562
1563 (*new) = result = calloc(size, sizeof *result);
1564 LY_CHECK_ERR_RETURN(!result, LOGMEM(ctx), EXIT_FAILURE);
1565 for (u = 0; u < size; u++) {
1566 if (orig[u]) {
1567 /* resolved extension instance, just duplicate it */
1568 switch(orig[u]->ext_type) {
1569 case LYEXT_FLAG:
1570 result[u] = malloc(sizeof(struct lys_ext_instance));
1571 LY_CHECK_ERR_GOTO(!result[u], LOGMEM(ctx), error);
1572 break;
1573 case LYEXT_COMPLEX:
1574 len = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->instance_size;
1575 result[u] = calloc(1, len);
1576 LY_CHECK_ERR_GOTO(!result[u], LOGMEM(ctx), error);
1577
1578 ((struct lys_ext_instance_complex*)result[u])->substmt = ((struct lyext_plugin_complex*)orig[u]->def->plugin)->substmt;
1579 /* TODO duplicate data in extension instance content */
1580 memcpy((char *)result[u] + sizeof(**orig), (char *)orig[u] + sizeof(**orig), len - sizeof(**orig));
1581 break;
1582 }
1583 /* generic part */
1584 result[u]->def = orig[u]->def;
1585 result[u]->flags = LYEXT_OPT_CONTENT;
1586 result[u]->arg_value = lydict_insert(ctx, orig[u]->arg_value, 0);
1587 result[u]->parent = parent;
1588 result[u]->parent_type = parent_type;
1589 result[u]->insubstmt = orig[u]->insubstmt;
1590 result[u]->insubstmt_index = orig[u]->insubstmt_index;
1591 result[u]->ext_type = orig[u]->ext_type;
1592 result[u]->priv = NULL;
1593 result[u]->nodetype = LYS_EXT;
1594 result[u]->module = mod;
1595
1596 /* extensions */
1597 result[u]->ext_size = orig[u]->ext_size;
1598 if (lys_ext_dup(ctx, mod, orig[u]->ext, orig[u]->ext_size, result[u],
1599 LYEXT_PAR_EXTINST, &result[u]->ext, shallow, unres)) {
1600 goto error;
1601 }
1602
1603 /* in case of shallow copy (duplication for deviation), duplicate only the link to private data
1604 * in a new copy, otherwise (grouping instantiation) do not duplicate the private data */
1605 if (shallow) {
1606 result[u]->priv = orig[u]->priv;
1607 }
1608 } else {
1609 /* original extension is not yet resolved, so duplicate it in unres */
1610 i = unres_schema_find(unres, -1, &orig, UNRES_EXT);
1611 if (i == -1) {
1612 /* extension not found in unres */
1613 LOGINT(ctx);
1614 goto error;
1615 }
1616 info_orig = unres->str_snode[i];
1617 info = malloc(sizeof *info);
1618 LY_CHECK_ERR_GOTO(!info, LOGMEM(ctx), error);
1619 info->datatype = info_orig->datatype;
1620 if (info->datatype == LYS_IN_YIN) {
1621 info->data.yin = lyxml_dup_elem(ctx, info_orig->data.yin, NULL, 1, 0);
1622 } /* else TODO YANG */
1623 info->parent = parent;
1624 info->mod = mod;
1625 info->parent_type = parent_type;
1626 info->ext_index = u;
1627 if (unres_schema_add_node(info->mod, unres, new, UNRES_EXT, (struct lys_node *)info) == -1) {
1628 goto error;
1629 }
1630 }
1631 }
1632
1633 return EXIT_SUCCESS;
1634
1635 error:
1636 (*new) = NULL;
1637 lys_extension_instances_free(ctx, result, u, NULL);
1638 return EXIT_FAILURE;
1639 }
1640
1641 static struct lys_restr *
lys_restr_dup(struct lys_module * mod,struct lys_restr * old,int size,int shallow,struct unres_schema * unres)1642 lys_restr_dup(struct lys_module *mod, struct lys_restr *old, int size, int shallow, struct unres_schema *unres)
1643 {
1644 struct lys_restr *result;
1645 int i;
1646
1647 if (!size) {
1648 return NULL;
1649 }
1650
1651 result = calloc(size, sizeof *result);
1652 LY_CHECK_ERR_RETURN(!result, LOGMEM(mod->ctx), NULL);
1653
1654 for (i = 0; i < size; i++) {
1655 /* copying unresolved extensions is not supported */
1656 if (unres_schema_find(unres, -1, (void *)&old[i].ext, UNRES_EXT) == -1) {
1657 result[i].ext_size = old[i].ext_size;
1658 lys_ext_dup(mod->ctx, mod, old[i].ext, old[i].ext_size, &result[i], LYEXT_PAR_RESTR, &result[i].ext, shallow, unres);
1659 }
1660 result[i].expr = lydict_insert(mod->ctx, old[i].expr, 0);
1661 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1662 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1663 result[i].eapptag = lydict_insert(mod->ctx, old[i].eapptag, 0);
1664 result[i].emsg = lydict_insert(mod->ctx, old[i].emsg, 0);
1665 }
1666
1667 return result;
1668 }
1669
1670 void
lys_restr_free(struct ly_ctx * ctx,struct lys_restr * restr,void (* private_destructor)(const struct lys_node * node,void * priv))1671 lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr,
1672 void (*private_destructor)(const struct lys_node *node, void *priv))
1673 {
1674 assert(ctx);
1675 if (!restr) {
1676 return;
1677 }
1678
1679 lys_extension_instances_free(ctx, restr->ext, restr->ext_size, private_destructor);
1680 lydict_remove(ctx, restr->expr);
1681 lydict_remove(ctx, restr->dsc);
1682 lydict_remove(ctx, restr->ref);
1683 lydict_remove(ctx, restr->eapptag);
1684 lydict_remove(ctx, restr->emsg);
1685 }
1686
1687 API void
lys_iffeature_free(struct ly_ctx * ctx,struct lys_iffeature * iffeature,uint8_t iffeature_size,int shallow,void (* private_destructor)(const struct lys_node * node,void * priv))1688 lys_iffeature_free(struct ly_ctx *ctx, struct lys_iffeature *iffeature, uint8_t iffeature_size,
1689 int shallow, void (*private_destructor)(const struct lys_node *node, void *priv))
1690 {
1691 FUN_IN;
1692
1693 uint8_t i;
1694
1695 for (i = 0; i < iffeature_size; ++i) {
1696 lys_extension_instances_free(ctx, iffeature[i].ext, iffeature[i].ext_size, private_destructor);
1697 if (!shallow) {
1698 free(iffeature[i].expr);
1699 free(iffeature[i].features);
1700 }
1701 }
1702 free(iffeature);
1703 }
1704
1705 static int
type_dup(struct lys_module * mod,struct lys_node * parent,struct lys_type * new,struct lys_type * old,LY_DATA_TYPE base,int in_grp,int shallow,struct unres_schema * unres)1706 type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
1707 LY_DATA_TYPE base, int in_grp, int shallow, struct unres_schema *unres)
1708 {
1709 int i;
1710 unsigned int u;
1711
1712 switch (base) {
1713 case LY_TYPE_BINARY:
1714 if (old->info.binary.length) {
1715 new->info.binary.length = lys_restr_dup(mod, old->info.binary.length, 1, shallow, unres);
1716 }
1717 break;
1718
1719 case LY_TYPE_BITS:
1720 new->info.bits.count = old->info.bits.count;
1721 if (new->info.bits.count) {
1722 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1723 LY_CHECK_ERR_RETURN(!new->info.bits.bit, LOGMEM(mod->ctx), -1);
1724
1725 for (u = 0; u < new->info.bits.count; u++) {
1726 new->info.bits.bit[u].name = lydict_insert(mod->ctx, old->info.bits.bit[u].name, 0);
1727 new->info.bits.bit[u].dsc = lydict_insert(mod->ctx, old->info.bits.bit[u].dsc, 0);
1728 new->info.bits.bit[u].ref = lydict_insert(mod->ctx, old->info.bits.bit[u].ref, 0);
1729 new->info.bits.bit[u].flags = old->info.bits.bit[u].flags;
1730 new->info.bits.bit[u].pos = old->info.bits.bit[u].pos;
1731 new->info.bits.bit[u].ext_size = old->info.bits.bit[u].ext_size;
1732 if (lys_ext_dup(mod->ctx, mod, old->info.bits.bit[u].ext, old->info.bits.bit[u].ext_size,
1733 &new->info.bits.bit[u], LYEXT_PAR_TYPE_BIT,
1734 &new->info.bits.bit[u].ext, shallow, unres)) {
1735 return -1;
1736 }
1737 }
1738 }
1739 break;
1740
1741 case LY_TYPE_DEC64:
1742 new->info.dec64.dig = old->info.dec64.dig;
1743 new->info.dec64.div = old->info.dec64.div;
1744 if (old->info.dec64.range) {
1745 new->info.dec64.range = lys_restr_dup(mod, old->info.dec64.range, 1, shallow, unres);
1746 }
1747 break;
1748
1749 case LY_TYPE_ENUM:
1750 new->info.enums.count = old->info.enums.count;
1751 if (new->info.enums.count) {
1752 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1753 LY_CHECK_ERR_RETURN(!new->info.enums.enm, LOGMEM(mod->ctx), -1);
1754
1755 for (u = 0; u < new->info.enums.count; u++) {
1756 new->info.enums.enm[u].name = lydict_insert(mod->ctx, old->info.enums.enm[u].name, 0);
1757 new->info.enums.enm[u].dsc = lydict_insert(mod->ctx, old->info.enums.enm[u].dsc, 0);
1758 new->info.enums.enm[u].ref = lydict_insert(mod->ctx, old->info.enums.enm[u].ref, 0);
1759 new->info.enums.enm[u].flags = old->info.enums.enm[u].flags;
1760 new->info.enums.enm[u].value = old->info.enums.enm[u].value;
1761 new->info.enums.enm[u].ext_size = old->info.enums.enm[u].ext_size;
1762 if (lys_ext_dup(mod->ctx, mod, old->info.enums.enm[u].ext, old->info.enums.enm[u].ext_size,
1763 &new->info.enums.enm[u], LYEXT_PAR_TYPE_ENUM,
1764 &new->info.enums.enm[u].ext, shallow, unres)) {
1765 return -1;
1766 }
1767 }
1768 }
1769 break;
1770
1771 case LY_TYPE_IDENT:
1772 new->info.ident.count = old->info.ident.count;
1773 if (old->info.ident.count) {
1774 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
1775 LY_CHECK_ERR_RETURN(!new->info.ident.ref, LOGMEM(mod->ctx), -1);
1776 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1777 } else {
1778 /* there can be several unresolved base identities, duplicate them all */
1779 i = -1;
1780 do {
1781 i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF);
1782 if (i != -1) {
1783 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
1784 return -1;
1785 }
1786 }
1787 --i;
1788 } while (i > -1);
1789 }
1790 break;
1791
1792 case LY_TYPE_INST:
1793 new->info.inst.req = old->info.inst.req;
1794 break;
1795
1796 case LY_TYPE_INT8:
1797 case LY_TYPE_INT16:
1798 case LY_TYPE_INT32:
1799 case LY_TYPE_INT64:
1800 case LY_TYPE_UINT8:
1801 case LY_TYPE_UINT16:
1802 case LY_TYPE_UINT32:
1803 case LY_TYPE_UINT64:
1804 if (old->info.num.range) {
1805 new->info.num.range = lys_restr_dup(mod, old->info.num.range, 1, shallow, unres);
1806 }
1807 break;
1808
1809 case LY_TYPE_LEAFREF:
1810 if (old->info.lref.path) {
1811 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
1812 new->info.lref.req = old->info.lref.req;
1813 if (!in_grp && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
1814 return -1;
1815 }
1816 }
1817 break;
1818
1819 case LY_TYPE_STRING:
1820 if (old->info.str.length) {
1821 new->info.str.length = lys_restr_dup(mod, old->info.str.length, 1, shallow, unres);
1822 }
1823 if (old->info.str.pat_count) {
1824 new->info.str.patterns = lys_restr_dup(mod, old->info.str.patterns, old->info.str.pat_count, shallow, unres);
1825 new->info.str.pat_count = old->info.str.pat_count;
1826 #ifdef LY_ENABLED_CACHE
1827 if (!in_grp) {
1828 new->info.str.patterns_pcre = malloc(new->info.str.pat_count * 2 * sizeof *new->info.str.patterns_pcre);
1829 LY_CHECK_ERR_RETURN(!new->info.str.patterns_pcre, LOGMEM(mod->ctx), -1);
1830 for (u = 0; u < new->info.str.pat_count; u++) {
1831 if (lyp_precompile_pattern(mod->ctx, &new->info.str.patterns[u].expr[1],
1832 (pcre**)&new->info.str.patterns_pcre[2 * u],
1833 (pcre_extra**)&new->info.str.patterns_pcre[2 * u + 1])) {
1834 free(new->info.str.patterns_pcre);
1835 new->info.str.patterns_pcre = NULL;
1836 return -1;
1837 }
1838 }
1839 }
1840 #endif
1841 }
1842 break;
1843
1844 case LY_TYPE_UNION:
1845 new->info.uni.has_ptr_type = old->info.uni.has_ptr_type;
1846 new->info.uni.count = old->info.uni.count;
1847 if (new->info.uni.count) {
1848 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1849 LY_CHECK_ERR_RETURN(!new->info.uni.types, LOGMEM(mod->ctx), -1);
1850
1851 for (u = 0; u < new->info.uni.count; u++) {
1852 if (lys_type_dup(mod, parent, &(new->info.uni.types[u]), &(old->info.uni.types[u]), in_grp,
1853 shallow, unres)) {
1854 return -1;
1855 }
1856 }
1857 }
1858 break;
1859
1860 default:
1861 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1862 break;
1863 }
1864
1865 return EXIT_SUCCESS;
1866 }
1867
1868 struct yang_type *
lys_yang_type_dup(struct lys_module * module,struct lys_node * parent,struct yang_type * old,struct lys_type * type,int in_grp,int shallow,struct unres_schema * unres)1869 lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1870 int in_grp, int shallow, struct unres_schema *unres)
1871 {
1872 struct yang_type *new;
1873
1874 new = calloc(1, sizeof *new);
1875 LY_CHECK_ERR_RETURN(!new, LOGMEM(module->ctx), NULL);
1876 new->flags = old->flags;
1877 new->base = old->base;
1878 new->name = lydict_insert(module->ctx, old->name, 0);
1879 new->type = type;
1880 if (!new->name) {
1881 LOGMEM(module->ctx);
1882 goto error;
1883 }
1884 if (type_dup(module, parent, type, old->type, new->base, in_grp, shallow, unres)) {
1885 new->type->base = new->base;
1886 lys_type_free(module->ctx, new->type, NULL);
1887 memset(&new->type->info, 0, sizeof new->type->info);
1888 goto error;
1889 }
1890 return new;
1891
1892 error:
1893 free(new);
1894 return NULL;
1895 }
1896
1897 int
lys_copy_union_leafrefs(struct lys_module * mod,struct lys_node * parent,struct lys_type * type,struct lys_type * prev_new,struct unres_schema * unres)1898 lys_copy_union_leafrefs(struct lys_module *mod, struct lys_node *parent, struct lys_type *type, struct lys_type *prev_new,
1899 struct unres_schema *unres)
1900 {
1901 struct lys_type new;
1902 unsigned int i, top_type;
1903 struct lys_ext_instance **ext;
1904 uint8_t ext_size;
1905 void *reloc;
1906
1907 if (!prev_new) {
1908 /* this is the "top-level" type, meaning it is a real type and no typedef directly above */
1909 top_type = 1;
1910
1911 memset(&new, 0, sizeof new);
1912
1913 new.base = type->base;
1914 new.parent = (struct lys_tpdf *)parent;
1915
1916 prev_new = &new;
1917 } else {
1918 /* this is not top-level type, just a type of a typedef */
1919 top_type = 0;
1920 }
1921
1922 assert(type->der);
1923 if (type->der->module) {
1924 /* typedef, skip it, but keep the extensions */
1925 ext_size = type->ext_size;
1926 if (lys_ext_dup(mod->ctx, mod, type->ext, type->ext_size, prev_new, LYEXT_PAR_TYPE, &ext, 0, unres)) {
1927 return -1;
1928 }
1929 if (prev_new->ext) {
1930 reloc = realloc(prev_new->ext, (prev_new->ext_size + ext_size) * sizeof *prev_new->ext);
1931 LY_CHECK_ERR_RETURN(!reloc, LOGMEM(mod->ctx), -1);
1932 prev_new->ext = reloc;
1933
1934 memcpy(prev_new->ext + prev_new->ext_size, ext, ext_size * sizeof *ext);
1935 free(ext);
1936
1937 prev_new->ext_size += ext_size;
1938 } else {
1939 prev_new->ext = ext;
1940 prev_new->ext_size = ext_size;
1941 }
1942
1943 if (lys_copy_union_leafrefs(mod, parent, &type->der->type, prev_new, unres)) {
1944 return -1;
1945 }
1946 } else {
1947 /* type, just make a deep copy */
1948 switch (type->base) {
1949 case LY_TYPE_UNION:
1950 prev_new->info.uni.has_ptr_type = type->info.uni.has_ptr_type;
1951 prev_new->info.uni.count = type->info.uni.count;
1952 /* this cannot be a typedef anymore */
1953 assert(prev_new->info.uni.count);
1954
1955 prev_new->info.uni.types = calloc(prev_new->info.uni.count, sizeof *prev_new->info.uni.types);
1956 LY_CHECK_ERR_RETURN(!prev_new->info.uni.types, LOGMEM(mod->ctx), -1);
1957
1958 for (i = 0; i < prev_new->info.uni.count; i++) {
1959 if (lys_copy_union_leafrefs(mod, parent, &(type->info.uni.types[i]), &(prev_new->info.uni.types[i]), unres)) {
1960 return -1;
1961 }
1962 }
1963
1964 prev_new->der = type->der;
1965 break;
1966 default:
1967 if (lys_type_dup(mod, parent, prev_new, type, 0, 0, unres)) {
1968 return -1;
1969 }
1970 break;
1971 }
1972 }
1973
1974 if (top_type) {
1975 memcpy(type, prev_new, sizeof *type);
1976 }
1977 return EXIT_SUCCESS;
1978 }
1979
1980 API const void *
lys_ext_instance_substmt(const struct lys_ext_instance * ext)1981 lys_ext_instance_substmt(const struct lys_ext_instance *ext)
1982 {
1983 FUN_IN;
1984
1985 if (!ext) {
1986 return NULL;
1987 }
1988
1989 switch (ext->insubstmt) {
1990 case LYEXT_SUBSTMT_SELF:
1991 case LYEXT_SUBSTMT_MODIFIER:
1992 case LYEXT_SUBSTMT_VERSION:
1993 return NULL;
1994 case LYEXT_SUBSTMT_ARGUMENT:
1995 if (ext->parent_type == LYEXT_PAR_EXT) {
1996 return ((struct lys_ext_instance*)ext->parent)->arg_value;
1997 }
1998 break;
1999 case LYEXT_SUBSTMT_BASE:
2000 if (ext->parent_type == LYEXT_PAR_TYPE) {
2001 return ((struct lys_type*)ext->parent)->info.ident.ref[ext->insubstmt_index];
2002 } else if (ext->parent_type == LYEXT_PAR_IDENT) {
2003 return ((struct lys_ident*)ext->parent)->base[ext->insubstmt_index];
2004 }
2005 break;
2006 case LYEXT_SUBSTMT_BELONGSTO:
2007 if (ext->parent_type == LYEXT_PAR_MODULE && ((struct lys_module*)ext->parent)->type) {
2008 return ((struct lys_submodule*)ext->parent)->belongsto;
2009 }
2010 break;
2011 case LYEXT_SUBSTMT_CONFIG:
2012 case LYEXT_SUBSTMT_MANDATORY:
2013 if (ext->parent_type == LYEXT_PAR_NODE) {
2014 return &((struct lys_node*)ext->parent)->flags;
2015 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
2016 return &((struct lys_deviate*)ext->parent)->flags;
2017 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2018 return &((struct lys_refine*)ext->parent)->flags;
2019 }
2020 break;
2021 case LYEXT_SUBSTMT_CONTACT:
2022 if (ext->parent_type == LYEXT_PAR_MODULE) {
2023 return ((struct lys_module*)ext->parent)->contact;
2024 }
2025 break;
2026 case LYEXT_SUBSTMT_DEFAULT:
2027 if (ext->parent_type == LYEXT_PAR_NODE) {
2028 switch (((struct lys_node*)ext->parent)->nodetype) {
2029 case LYS_LEAF:
2030 case LYS_LEAFLIST:
2031 /* in case of leaf, the index is supposed to be 0, so it will return the
2032 * correct pointer despite the leaf structure does not have dflt as array */
2033 return ((struct lys_node_leaflist*)ext->parent)->dflt[ext->insubstmt_index];
2034 case LYS_CHOICE:
2035 return ((struct lys_node_choice*)ext->parent)->dflt;
2036 default:
2037 /* internal error */
2038 break;
2039 }
2040 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
2041 return ((struct lys_tpdf*)ext->parent)->dflt;
2042 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
2043 return ((struct lys_deviate*)ext->parent)->dflt[ext->insubstmt_index];
2044 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2045 return &((struct lys_refine*)ext->parent)->dflt[ext->insubstmt_index];
2046 }
2047 break;
2048 case LYEXT_SUBSTMT_DESCRIPTION:
2049 switch (ext->parent_type) {
2050 case LYEXT_PAR_NODE:
2051 return ((struct lys_node*)ext->parent)->dsc;
2052 case LYEXT_PAR_MODULE:
2053 return ((struct lys_module*)ext->parent)->dsc;
2054 case LYEXT_PAR_IMPORT:
2055 return ((struct lys_import*)ext->parent)->dsc;
2056 case LYEXT_PAR_INCLUDE:
2057 return ((struct lys_include*)ext->parent)->dsc;
2058 case LYEXT_PAR_EXT:
2059 return ((struct lys_ext*)ext->parent)->dsc;
2060 case LYEXT_PAR_FEATURE:
2061 return ((struct lys_feature*)ext->parent)->dsc;
2062 case LYEXT_PAR_TPDF:
2063 return ((struct lys_tpdf*)ext->parent)->dsc;
2064 case LYEXT_PAR_TYPE_BIT:
2065 return ((struct lys_type_bit*)ext->parent)->dsc;
2066 case LYEXT_PAR_TYPE_ENUM:
2067 return ((struct lys_type_enum*)ext->parent)->dsc;
2068 case LYEXT_PAR_RESTR:
2069 return ((struct lys_restr*)ext->parent)->dsc;
2070 case LYEXT_PAR_WHEN:
2071 return ((struct lys_when*)ext->parent)->dsc;
2072 case LYEXT_PAR_IDENT:
2073 return ((struct lys_ident*)ext->parent)->dsc;
2074 case LYEXT_PAR_DEVIATION:
2075 return ((struct lys_deviation*)ext->parent)->dsc;
2076 case LYEXT_PAR_REVISION:
2077 return ((struct lys_revision*)ext->parent)->dsc;
2078 case LYEXT_PAR_REFINE:
2079 return ((struct lys_refine*)ext->parent)->dsc;
2080 default:
2081 break;
2082 }
2083 break;
2084 case LYEXT_SUBSTMT_ERRTAG:
2085 if (ext->parent_type == LYEXT_PAR_RESTR) {
2086 return ((struct lys_restr*)ext->parent)->eapptag;
2087 }
2088 break;
2089 case LYEXT_SUBSTMT_ERRMSG:
2090 if (ext->parent_type == LYEXT_PAR_RESTR) {
2091 return ((struct lys_restr*)ext->parent)->emsg;
2092 }
2093 break;
2094 case LYEXT_SUBSTMT_DIGITS:
2095 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_DEC64) {
2096 return &((struct lys_type*)ext->parent)->info.dec64.dig;
2097 }
2098 break;
2099 case LYEXT_SUBSTMT_KEY:
2100 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2101 return ((struct lys_node_list*)ext->parent)->keys;
2102 }
2103 break;
2104 case LYEXT_SUBSTMT_MAX:
2105 if (ext->parent_type == LYEXT_PAR_NODE) {
2106 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2107 return &((struct lys_node_list*)ext->parent)->max;
2108 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
2109 return &((struct lys_node_leaflist*)ext->parent)->max;
2110 }
2111 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2112 return &((struct lys_refine*)ext->parent)->mod.list.max;
2113 }
2114 break;
2115 case LYEXT_SUBSTMT_MIN:
2116 if (ext->parent_type == LYEXT_PAR_NODE) {
2117 if (((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2118 return &((struct lys_node_list*)ext->parent)->min;
2119 } else if (((struct lys_node*)ext->parent)->nodetype == LYS_LEAFLIST) {
2120 return &((struct lys_node_leaflist*)ext->parent)->min;
2121 }
2122 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2123 return &((struct lys_refine*)ext->parent)->mod.list.min;
2124 }
2125 break;
2126 case LYEXT_SUBSTMT_NAMESPACE:
2127 if (ext->parent_type == LYEXT_PAR_MODULE && !((struct lys_module*)ext->parent)->type) {
2128 return ((struct lys_module*)ext->parent)->ns;
2129 }
2130 break;
2131 case LYEXT_SUBSTMT_ORDEREDBY:
2132 if (ext->parent_type == LYEXT_PAR_NODE &&
2133 (((struct lys_node*)ext->parent)->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
2134 return &((struct lys_node_list*)ext->parent)->flags;
2135 }
2136 break;
2137 case LYEXT_SUBSTMT_ORGANIZATION:
2138 if (ext->parent_type == LYEXT_PAR_MODULE) {
2139 return ((struct lys_module*)ext->parent)->org;
2140 }
2141 break;
2142 case LYEXT_SUBSTMT_PATH:
2143 if (ext->parent_type == LYEXT_PAR_TYPE && ((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
2144 return ((struct lys_type*)ext->parent)->info.lref.path;
2145 }
2146 break;
2147 case LYEXT_SUBSTMT_POSITION:
2148 if (ext->parent_type == LYEXT_PAR_TYPE_BIT) {
2149 return &((struct lys_type_bit*)ext->parent)->pos;
2150 }
2151 break;
2152 case LYEXT_SUBSTMT_PREFIX:
2153 if (ext->parent_type == LYEXT_PAR_MODULE) {
2154 /* covers also lys_submodule */
2155 return ((struct lys_module*)ext->parent)->prefix;
2156 } else if (ext->parent_type == LYEXT_PAR_IMPORT) {
2157 return ((struct lys_import*)ext->parent)->prefix;
2158 }
2159 break;
2160 case LYEXT_SUBSTMT_PRESENCE:
2161 if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_CONTAINER) {
2162 return ((struct lys_node_container*)ext->parent)->presence;
2163 } else if (ext->parent_type == LYEXT_PAR_REFINE) {
2164 return ((struct lys_refine*)ext->parent)->mod.presence;
2165 }
2166 break;
2167 case LYEXT_SUBSTMT_REFERENCE:
2168 switch (ext->parent_type) {
2169 case LYEXT_PAR_NODE:
2170 return ((struct lys_node*)ext->parent)->ref;
2171 case LYEXT_PAR_MODULE:
2172 return ((struct lys_module*)ext->parent)->ref;
2173 case LYEXT_PAR_IMPORT:
2174 return ((struct lys_import*)ext->parent)->ref;
2175 case LYEXT_PAR_INCLUDE:
2176 return ((struct lys_include*)ext->parent)->ref;
2177 case LYEXT_PAR_EXT:
2178 return ((struct lys_ext*)ext->parent)->ref;
2179 case LYEXT_PAR_FEATURE:
2180 return ((struct lys_feature*)ext->parent)->ref;
2181 case LYEXT_PAR_TPDF:
2182 return ((struct lys_tpdf*)ext->parent)->ref;
2183 case LYEXT_PAR_TYPE_BIT:
2184 return ((struct lys_type_bit*)ext->parent)->ref;
2185 case LYEXT_PAR_TYPE_ENUM:
2186 return ((struct lys_type_enum*)ext->parent)->ref;
2187 case LYEXT_PAR_RESTR:
2188 return ((struct lys_restr*)ext->parent)->ref;
2189 case LYEXT_PAR_WHEN:
2190 return ((struct lys_when*)ext->parent)->ref;
2191 case LYEXT_PAR_IDENT:
2192 return ((struct lys_ident*)ext->parent)->ref;
2193 case LYEXT_PAR_DEVIATION:
2194 return ((struct lys_deviation*)ext->parent)->ref;
2195 case LYEXT_PAR_REVISION:
2196 return ((struct lys_revision*)ext->parent)->ref;
2197 case LYEXT_PAR_REFINE:
2198 return ((struct lys_refine*)ext->parent)->ref;
2199 default:
2200 break;
2201 }
2202 break;
2203 case LYEXT_SUBSTMT_REQINSTANCE:
2204 if (ext->parent_type == LYEXT_PAR_TYPE) {
2205 if (((struct lys_type*)ext->parent)->base == LY_TYPE_LEAFREF) {
2206 return &((struct lys_type*)ext->parent)->info.lref.req;
2207 } else if (((struct lys_type*)ext->parent)->base == LY_TYPE_INST) {
2208 return &((struct lys_type*)ext->parent)->info.inst.req;
2209 }
2210 }
2211 break;
2212 case LYEXT_SUBSTMT_REVISIONDATE:
2213 if (ext->parent_type == LYEXT_PAR_IMPORT) {
2214 return ((struct lys_import*)ext->parent)->rev;
2215 } else if (ext->parent_type == LYEXT_PAR_INCLUDE) {
2216 return ((struct lys_include*)ext->parent)->rev;
2217 }
2218 break;
2219 case LYEXT_SUBSTMT_STATUS:
2220 switch (ext->parent_type) {
2221 case LYEXT_PAR_NODE:
2222 case LYEXT_PAR_IDENT:
2223 case LYEXT_PAR_TPDF:
2224 case LYEXT_PAR_EXT:
2225 case LYEXT_PAR_FEATURE:
2226 case LYEXT_PAR_TYPE_ENUM:
2227 case LYEXT_PAR_TYPE_BIT:
2228 /* in all structures the flags member is at the same offset */
2229 return &((struct lys_node*)ext->parent)->flags;
2230 default:
2231 break;
2232 }
2233 break;
2234 case LYEXT_SUBSTMT_UNIQUE:
2235 if (ext->parent_type == LYEXT_PAR_DEVIATE) {
2236 return &((struct lys_deviate*)ext->parent)->unique[ext->insubstmt_index];
2237 } else if (ext->parent_type == LYEXT_PAR_NODE && ((struct lys_node*)ext->parent)->nodetype == LYS_LIST) {
2238 return &((struct lys_node_list*)ext->parent)->unique[ext->insubstmt_index];
2239 }
2240 break;
2241 case LYEXT_SUBSTMT_UNITS:
2242 if (ext->parent_type == LYEXT_PAR_NODE &&
2243 (((struct lys_node*)ext->parent)->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2244 /* units is at the same offset in both lys_node_leaf and lys_node_leaflist */
2245 return ((struct lys_node_leaf*)ext->parent)->units;
2246 } else if (ext->parent_type == LYEXT_PAR_TPDF) {
2247 return ((struct lys_tpdf*)ext->parent)->units;
2248 } else if (ext->parent_type == LYEXT_PAR_DEVIATE) {
2249 return ((struct lys_deviate*)ext->parent)->units;
2250 }
2251 break;
2252 case LYEXT_SUBSTMT_VALUE:
2253 if (ext->parent_type == LYEXT_PAR_TYPE_ENUM) {
2254 return &((struct lys_type_enum*)ext->parent)->value;
2255 }
2256 break;
2257 case LYEXT_SUBSTMT_YINELEM:
2258 if (ext->parent_type == LYEXT_PAR_EXT) {
2259 return &((struct lys_ext*)ext->parent)->flags;
2260 }
2261 break;
2262 }
2263 LOGINT(ext->module->ctx);
2264 return NULL;
2265 }
2266
2267 static int
lys_type_dup(struct lys_module * mod,struct lys_node * parent,struct lys_type * new,struct lys_type * old,int in_grp,int shallow,struct unres_schema * unres)2268 lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
2269 int in_grp, int shallow, struct unres_schema *unres)
2270 {
2271 int i;
2272
2273 new->base = old->base;
2274 new->der = old->der;
2275 new->parent = (struct lys_tpdf *)parent;
2276 new->ext_size = old->ext_size;
2277 if (lys_ext_dup(mod->ctx, mod, old->ext, old->ext_size, new, LYEXT_PAR_TYPE, &new->ext, shallow, unres)) {
2278 return -1;
2279 }
2280
2281 i = unres_schema_find(unres, -1, old, UNRES_TYPE_DER);
2282 if (i != -1) {
2283 /* HACK (serious one) for unres */
2284 /* nothing else we can do but duplicate it immediately */
2285 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
2286 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, in_grp,
2287 shallow, unres);
2288 } else {
2289 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1, 0);
2290 }
2291 /* all these unres additions can fail even though they did not before */
2292 if (!new->der || (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent) == -1)) {
2293 return -1;
2294 }
2295 return EXIT_SUCCESS;
2296 }
2297
2298 return type_dup(mod, parent, new, old, new->base, in_grp, shallow, unres);
2299 }
2300
2301 void
lys_type_free(struct ly_ctx * ctx,struct lys_type * type,void (* private_destructor)(const struct lys_node * node,void * priv))2302 lys_type_free(struct ly_ctx *ctx, struct lys_type *type,
2303 void (*private_destructor)(const struct lys_node *node, void *priv))
2304 {
2305 unsigned int i;
2306
2307 assert(ctx);
2308 if (!type) {
2309 return;
2310 }
2311
2312 lys_extension_instances_free(ctx, type->ext, type->ext_size, private_destructor);
2313
2314 switch (type->base) {
2315 case LY_TYPE_BINARY:
2316 lys_restr_free(ctx, type->info.binary.length, private_destructor);
2317 free(type->info.binary.length);
2318 break;
2319 case LY_TYPE_BITS:
2320 for (i = 0; i < type->info.bits.count; i++) {
2321 lydict_remove(ctx, type->info.bits.bit[i].name);
2322 lydict_remove(ctx, type->info.bits.bit[i].dsc);
2323 lydict_remove(ctx, type->info.bits.bit[i].ref);
2324 lys_iffeature_free(ctx, type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size, 0,
2325 private_destructor);
2326 lys_extension_instances_free(ctx, type->info.bits.bit[i].ext, type->info.bits.bit[i].ext_size,
2327 private_destructor);
2328 }
2329 free(type->info.bits.bit);
2330 break;
2331
2332 case LY_TYPE_DEC64:
2333 lys_restr_free(ctx, type->info.dec64.range, private_destructor);
2334 free(type->info.dec64.range);
2335 break;
2336
2337 case LY_TYPE_ENUM:
2338 for (i = 0; i < type->info.enums.count; i++) {
2339 lydict_remove(ctx, type->info.enums.enm[i].name);
2340 lydict_remove(ctx, type->info.enums.enm[i].dsc);
2341 lydict_remove(ctx, type->info.enums.enm[i].ref);
2342 lys_iffeature_free(ctx, type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size, 0,
2343 private_destructor);
2344 lys_extension_instances_free(ctx, type->info.enums.enm[i].ext, type->info.enums.enm[i].ext_size,
2345 private_destructor);
2346 }
2347 free(type->info.enums.enm);
2348 break;
2349
2350 case LY_TYPE_INT8:
2351 case LY_TYPE_INT16:
2352 case LY_TYPE_INT32:
2353 case LY_TYPE_INT64:
2354 case LY_TYPE_UINT8:
2355 case LY_TYPE_UINT16:
2356 case LY_TYPE_UINT32:
2357 case LY_TYPE_UINT64:
2358 lys_restr_free(ctx, type->info.num.range, private_destructor);
2359 free(type->info.num.range);
2360 break;
2361
2362 case LY_TYPE_LEAFREF:
2363 lydict_remove(ctx, type->info.lref.path);
2364 break;
2365
2366 case LY_TYPE_STRING:
2367 lys_restr_free(ctx, type->info.str.length, private_destructor);
2368 free(type->info.str.length);
2369 for (i = 0; i < type->info.str.pat_count; i++) {
2370 lys_restr_free(ctx, &type->info.str.patterns[i], private_destructor);
2371 #ifdef LY_ENABLED_CACHE
2372 if (type->info.str.patterns_pcre) {
2373 pcre_free((pcre*)type->info.str.patterns_pcre[2 * i]);
2374 pcre_free_study((pcre_extra*)type->info.str.patterns_pcre[2 * i + 1]);
2375 }
2376 #endif
2377 }
2378 free(type->info.str.patterns);
2379 #ifdef LY_ENABLED_CACHE
2380 free(type->info.str.patterns_pcre);
2381 #endif
2382 break;
2383
2384 case LY_TYPE_UNION:
2385 for (i = 0; i < type->info.uni.count; i++) {
2386 lys_type_free(ctx, &type->info.uni.types[i], private_destructor);
2387 }
2388 free(type->info.uni.types);
2389 break;
2390
2391 case LY_TYPE_IDENT:
2392 free(type->info.ident.ref);
2393 break;
2394
2395 default:
2396 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
2397 break;
2398 }
2399 }
2400
2401 static void
lys_tpdf_free(struct ly_ctx * ctx,struct lys_tpdf * tpdf,void (* private_destructor)(const struct lys_node * node,void * priv))2402 lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf,
2403 void (*private_destructor)(const struct lys_node *node, void *priv))
2404 {
2405 assert(ctx);
2406 if (!tpdf) {
2407 return;
2408 }
2409
2410 lydict_remove(ctx, tpdf->name);
2411 lydict_remove(ctx, tpdf->dsc);
2412 lydict_remove(ctx, tpdf->ref);
2413
2414 lys_type_free(ctx, &tpdf->type, private_destructor);
2415
2416 lydict_remove(ctx, tpdf->units);
2417 lydict_remove(ctx, tpdf->dflt);
2418
2419 lys_extension_instances_free(ctx, tpdf->ext, tpdf->ext_size, private_destructor);
2420 }
2421
2422 static struct lys_when *
lys_when_dup(struct lys_module * mod,struct lys_when * old,int shallow,struct unres_schema * unres)2423 lys_when_dup(struct lys_module *mod, struct lys_when *old, int shallow, struct unres_schema *unres)
2424 {
2425 struct lys_when *new;
2426
2427 if (!old) {
2428 return NULL;
2429 }
2430
2431 new = calloc(1, sizeof *new);
2432 LY_CHECK_ERR_RETURN(!new, LOGMEM(mod->ctx), NULL);
2433 new->cond = lydict_insert(mod->ctx, old->cond, 0);
2434 new->dsc = lydict_insert(mod->ctx, old->dsc, 0);
2435 new->ref = lydict_insert(mod->ctx, old->ref, 0);
2436 new->ext_size = old->ext_size;
2437 lys_ext_dup(mod->ctx, mod, old->ext, old->ext_size, new, LYEXT_PAR_WHEN, &new->ext, shallow, unres);
2438
2439 return new;
2440 }
2441
2442 void
lys_when_free(struct ly_ctx * ctx,struct lys_when * w,void (* private_destructor)(const struct lys_node * node,void * priv))2443 lys_when_free(struct ly_ctx *ctx, struct lys_when *w,
2444 void (*private_destructor)(const struct lys_node *node, void *priv))
2445 {
2446 if (!w) {
2447 return;
2448 }
2449
2450 lys_extension_instances_free(ctx, w->ext, w->ext_size, private_destructor);
2451 lydict_remove(ctx, w->cond);
2452 lydict_remove(ctx, w->dsc);
2453 lydict_remove(ctx, w->ref);
2454
2455 free(w);
2456 }
2457
2458 static void
lys_augment_free(struct ly_ctx * ctx,struct lys_node_augment * aug,void (* private_destructor)(const struct lys_node * node,void * priv))2459 lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment *aug,
2460 void (*private_destructor)(const struct lys_node *node, void *priv))
2461 {
2462 struct lys_node *next, *sub;
2463
2464 /* children from a resolved augment are freed under the target node */
2465 if (!aug->target || (aug->flags & LYS_NOTAPPLIED)) {
2466 LY_TREE_FOR_SAFE(aug->child, next, sub) {
2467 lys_node_free(ctx, sub, private_destructor, 0);
2468 }
2469 }
2470
2471 lydict_remove(ctx, aug->target_name);
2472 lydict_remove(ctx, aug->dsc);
2473 lydict_remove(ctx, aug->ref);
2474
2475 lys_iffeature_free(ctx, aug->iffeature, aug->iffeature_size, 0, private_destructor);
2476 lys_extension_instances_free(ctx, aug->ext, aug->ext_size, private_destructor);
2477
2478 lys_when_free(ctx, aug->when, private_destructor);
2479 }
2480
2481 static void
lys_ident_free(struct ly_ctx * ctx,struct lys_ident * ident,void (* private_destructor)(const struct lys_node * node,void * priv))2482 lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident,
2483 void (*private_destructor)(const struct lys_node *node, void *priv))
2484 {
2485 assert(ctx);
2486 if (!ident) {
2487 return;
2488 }
2489
2490 free(ident->base);
2491 ly_set_free(ident->der);
2492 lydict_remove(ctx, ident->name);
2493 lydict_remove(ctx, ident->dsc);
2494 lydict_remove(ctx, ident->ref);
2495 lys_iffeature_free(ctx, ident->iffeature, ident->iffeature_size, 0, private_destructor);
2496 lys_extension_instances_free(ctx, ident->ext, ident->ext_size, private_destructor);
2497
2498 }
2499
2500 static void
lys_grp_free(struct ly_ctx * ctx,struct lys_node_grp * grp,void (* private_destructor)(const struct lys_node * node,void * priv))2501 lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp,
2502 void (*private_destructor)(const struct lys_node *node, void *priv))
2503 {
2504 int i;
2505
2506 /* handle only specific parts for LYS_GROUPING */
2507 for (i = 0; i < grp->tpdf_size; i++) {
2508 lys_tpdf_free(ctx, &grp->tpdf[i], private_destructor);
2509 }
2510 free(grp->tpdf);
2511 }
2512
2513 static void
lys_rpc_action_free(struct ly_ctx * ctx,struct lys_node_rpc_action * rpc_act,void (* private_destructor)(const struct lys_node * node,void * priv))2514 lys_rpc_action_free(struct ly_ctx *ctx, struct lys_node_rpc_action *rpc_act,
2515 void (*private_destructor)(const struct lys_node *node, void *priv))
2516 {
2517 int i;
2518
2519 /* handle only specific parts for LYS_GROUPING */
2520 for (i = 0; i < rpc_act->tpdf_size; i++) {
2521 lys_tpdf_free(ctx, &rpc_act->tpdf[i], private_destructor);
2522 }
2523 free(rpc_act->tpdf);
2524 }
2525
2526 static void
lys_inout_free(struct ly_ctx * ctx,struct lys_node_inout * io,void (* private_destructor)(const struct lys_node * node,void * priv))2527 lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io,
2528 void (*private_destructor)(const struct lys_node *node, void *priv))
2529 {
2530 int i;
2531
2532 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
2533 for (i = 0; i < io->tpdf_size; i++) {
2534 lys_tpdf_free(ctx, &io->tpdf[i], private_destructor);
2535 }
2536 free(io->tpdf);
2537
2538 for (i = 0; i < io->must_size; i++) {
2539 lys_restr_free(ctx, &io->must[i], private_destructor);
2540 }
2541 free(io->must);
2542 }
2543
2544 static void
lys_notif_free(struct ly_ctx * ctx,struct lys_node_notif * notif,void (* private_destructor)(const struct lys_node * node,void * priv))2545 lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif,
2546 void (*private_destructor)(const struct lys_node *node, void *priv))
2547 {
2548 int i;
2549
2550 for (i = 0; i < notif->must_size; i++) {
2551 lys_restr_free(ctx, ¬if->must[i], private_destructor);
2552 }
2553 free(notif->must);
2554
2555 for (i = 0; i < notif->tpdf_size; i++) {
2556 lys_tpdf_free(ctx, ¬if->tpdf[i], private_destructor);
2557 }
2558 free(notif->tpdf);
2559 }
2560 static void
lys_anydata_free(struct ly_ctx * ctx,struct lys_node_anydata * anyxml,void (* private_destructor)(const struct lys_node * node,void * priv))2561 lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml,
2562 void (*private_destructor)(const struct lys_node *node, void *priv))
2563 {
2564 int i;
2565
2566 for (i = 0; i < anyxml->must_size; i++) {
2567 lys_restr_free(ctx, &anyxml->must[i], private_destructor);
2568 }
2569 free(anyxml->must);
2570
2571 lys_when_free(ctx, anyxml->when, private_destructor);
2572 }
2573
2574 static void
lys_leaf_free(struct ly_ctx * ctx,struct lys_node_leaf * leaf,void (* private_destructor)(const struct lys_node * node,void * priv))2575 lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf,
2576 void (*private_destructor)(const struct lys_node *node, void *priv))
2577 {
2578 int i;
2579
2580 for (i = 0; i < leaf->must_size; i++) {
2581 lys_restr_free(ctx, &leaf->must[i], private_destructor);
2582 }
2583 free(leaf->must);
2584
2585 lys_when_free(ctx, leaf->when, private_destructor);
2586
2587 lys_type_free(ctx, &leaf->type, private_destructor);
2588 lydict_remove(ctx, leaf->units);
2589 lydict_remove(ctx, leaf->dflt);
2590 }
2591
2592 static void
lys_leaflist_free(struct ly_ctx * ctx,struct lys_node_leaflist * llist,void (* private_destructor)(const struct lys_node * node,void * priv))2593 lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist,
2594 void (*private_destructor)(const struct lys_node *node, void *priv))
2595 {
2596 int i;
2597
2598 if (llist->backlinks) {
2599 /* leafref backlinks */
2600 ly_set_free(llist->backlinks);
2601 }
2602
2603 for (i = 0; i < llist->must_size; i++) {
2604 lys_restr_free(ctx, &llist->must[i], private_destructor);
2605 }
2606 free(llist->must);
2607
2608 for (i = 0; i < llist->dflt_size; i++) {
2609 lydict_remove(ctx, llist->dflt[i]);
2610 }
2611 free(llist->dflt);
2612
2613 lys_when_free(ctx, llist->when, private_destructor);
2614
2615 lys_type_free(ctx, &llist->type, private_destructor);
2616 lydict_remove(ctx, llist->units);
2617 }
2618
2619 static void
lys_list_free(struct ly_ctx * ctx,struct lys_node_list * list,void (* private_destructor)(const struct lys_node * node,void * priv))2620 lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list,
2621 void (*private_destructor)(const struct lys_node *node, void *priv))
2622 {
2623 int i, j;
2624
2625 /* handle only specific parts for LY_NODE_LIST */
2626 lys_when_free(ctx, list->when, private_destructor);
2627
2628 for (i = 0; i < list->must_size; i++) {
2629 lys_restr_free(ctx, &list->must[i], private_destructor);
2630 }
2631 free(list->must);
2632
2633 for (i = 0; i < list->tpdf_size; i++) {
2634 lys_tpdf_free(ctx, &list->tpdf[i], private_destructor);
2635 }
2636 free(list->tpdf);
2637
2638 free(list->keys);
2639
2640 for (i = 0; i < list->unique_size; i++) {
2641 for (j = 0; j < list->unique[i].expr_size; j++) {
2642 lydict_remove(ctx, list->unique[i].expr[j]);
2643 }
2644 free(list->unique[i].expr);
2645 }
2646 free(list->unique);
2647
2648 lydict_remove(ctx, list->keys_str);
2649 }
2650
2651 static void
lys_container_free(struct ly_ctx * ctx,struct lys_node_container * cont,void (* private_destructor)(const struct lys_node * node,void * priv))2652 lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont,
2653 void (*private_destructor)(const struct lys_node *node, void *priv))
2654 {
2655 int i;
2656
2657 /* handle only specific parts for LY_NODE_CONTAINER */
2658 lydict_remove(ctx, cont->presence);
2659
2660 for (i = 0; i < cont->tpdf_size; i++) {
2661 lys_tpdf_free(ctx, &cont->tpdf[i], private_destructor);
2662 }
2663 free(cont->tpdf);
2664
2665 for (i = 0; i < cont->must_size; i++) {
2666 lys_restr_free(ctx, &cont->must[i], private_destructor);
2667 }
2668 free(cont->must);
2669
2670 lys_when_free(ctx, cont->when, private_destructor);
2671 }
2672
2673 static void
lys_feature_free(struct ly_ctx * ctx,struct lys_feature * f,void (* private_destructor)(const struct lys_node * node,void * priv))2674 lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f,
2675 void (*private_destructor)(const struct lys_node *node, void *priv))
2676 {
2677 lydict_remove(ctx, f->name);
2678 lydict_remove(ctx, f->dsc);
2679 lydict_remove(ctx, f->ref);
2680 lys_iffeature_free(ctx, f->iffeature, f->iffeature_size, 0, private_destructor);
2681 ly_set_free(f->depfeatures);
2682 lys_extension_instances_free(ctx, f->ext, f->ext_size, private_destructor);
2683 }
2684
2685 static void
lys_extension_free(struct ly_ctx * ctx,struct lys_ext * e,void (* private_destructor)(const struct lys_node * node,void * priv))2686 lys_extension_free(struct ly_ctx *ctx, struct lys_ext *e,
2687 void (*private_destructor)(const struct lys_node *node, void *priv))
2688 {
2689 lydict_remove(ctx, e->name);
2690 lydict_remove(ctx, e->dsc);
2691 lydict_remove(ctx, e->ref);
2692 lydict_remove(ctx, e->argument);
2693 lys_extension_instances_free(ctx, e->ext, e->ext_size, private_destructor);
2694 }
2695
2696 static void
lys_deviation_free(struct lys_module * module,struct lys_deviation * dev,void (* private_destructor)(const struct lys_node * node,void * priv))2697 lys_deviation_free(struct lys_module *module, struct lys_deviation *dev,
2698 void (*private_destructor)(const struct lys_node *node, void *priv))
2699 {
2700 int i, j, k;
2701 struct ly_ctx *ctx;
2702 struct lys_node *next, *elem;
2703
2704 ctx = module->ctx;
2705
2706 lydict_remove(ctx, dev->target_name);
2707 lydict_remove(ctx, dev->dsc);
2708 lydict_remove(ctx, dev->ref);
2709 lys_extension_instances_free(ctx, dev->ext, dev->ext_size, private_destructor);
2710
2711 if (!dev->deviate) {
2712 return;
2713 }
2714
2715 /* it could not be applied because it failed to be applied */
2716 if (dev->orig_node) {
2717 /* the module was freed, but we only need the context from orig_node, use ours */
2718 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
2719 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
2720 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
2721 elem->module = module;
2722
2723 LY_TREE_DFS_END(dev->orig_node, next, elem);
2724 }
2725 lys_node_free(ctx, dev->orig_node, NULL, 0);
2726 } else {
2727 /* it's just a shallow copy, freeing one node */
2728 dev->orig_node->module = module;
2729 lys_node_free(ctx, dev->orig_node, NULL, 1);
2730 }
2731 }
2732
2733 for (i = 0; i < dev->deviate_size; i++) {
2734 lys_extension_instances_free(ctx, dev->deviate[i].ext, dev->deviate[i].ext_size, private_destructor);
2735
2736 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
2737 lydict_remove(ctx, dev->deviate[i].dflt[j]);
2738 }
2739 free(dev->deviate[i].dflt);
2740
2741 lydict_remove(ctx, dev->deviate[i].units);
2742
2743 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2744 for (j = 0; j < dev->deviate[i].must_size; j++) {
2745 lys_restr_free(ctx, &dev->deviate[i].must[j], private_destructor);
2746 }
2747 free(dev->deviate[i].must);
2748
2749 for (j = 0; j < dev->deviate[i].unique_size; j++) {
2750 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
2751 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
2752 }
2753 free(dev->deviate[i].unique[j].expr);
2754 }
2755 free(dev->deviate[i].unique);
2756 }
2757 }
2758 free(dev->deviate);
2759 }
2760
2761 static void
lys_uses_free(struct ly_ctx * ctx,struct lys_node_uses * uses,void (* private_destructor)(const struct lys_node * node,void * priv))2762 lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses,
2763 void (*private_destructor)(const struct lys_node *node, void *priv))
2764 {
2765 int i, j;
2766
2767 for (i = 0; i < uses->refine_size; i++) {
2768 lydict_remove(ctx, uses->refine[i].target_name);
2769 lydict_remove(ctx, uses->refine[i].dsc);
2770 lydict_remove(ctx, uses->refine[i].ref);
2771
2772 lys_iffeature_free(ctx, uses->refine[i].iffeature, uses->refine[i].iffeature_size, 0, private_destructor);
2773
2774 for (j = 0; j < uses->refine[i].must_size; j++) {
2775 lys_restr_free(ctx, &uses->refine[i].must[j], private_destructor);
2776 }
2777 free(uses->refine[i].must);
2778
2779 for (j = 0; j < uses->refine[i].dflt_size; j++) {
2780 lydict_remove(ctx, uses->refine[i].dflt[j]);
2781 }
2782 free(uses->refine[i].dflt);
2783
2784 lys_extension_instances_free(ctx, uses->refine[i].ext, uses->refine[i].ext_size, private_destructor);
2785
2786 if (uses->refine[i].target_type & LYS_CONTAINER) {
2787 lydict_remove(ctx, uses->refine[i].mod.presence);
2788 }
2789 }
2790 free(uses->refine);
2791
2792 for (i = 0; i < uses->augment_size; i++) {
2793 lys_augment_free(ctx, &uses->augment[i], private_destructor);
2794 }
2795 free(uses->augment);
2796
2797 lys_when_free(ctx, uses->when, private_destructor);
2798 }
2799
2800 void
lys_node_free(struct ly_ctx * ctx,struct lys_node * node,void (* private_destructor)(const struct lys_node * node,void * priv),int shallow)2801 lys_node_free(struct ly_ctx *ctx, struct lys_node *node,
2802 void (*private_destructor)(const struct lys_node *node, void *priv), int shallow)
2803 {
2804 struct lys_node *sub, *next;
2805
2806 if (!node) {
2807 return;
2808 }
2809
2810 /* remove private object */
2811 if (node->priv && private_destructor) {
2812 private_destructor(node, node->priv);
2813 }
2814
2815 /* common part */
2816 lydict_remove(ctx, node->name);
2817 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
2818 lys_iffeature_free(ctx, node->iffeature, node->iffeature_size, shallow, private_destructor);
2819 lydict_remove(ctx, node->dsc);
2820 lydict_remove(ctx, node->ref);
2821 }
2822
2823 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2824 LY_TREE_FOR_SAFE(node->child, next, sub) {
2825 lys_node_free(ctx, sub, private_destructor, 0);
2826 }
2827 }
2828
2829 lys_extension_instances_free(ctx, node->ext, node->ext_size, private_destructor);
2830
2831 /* specific part */
2832 switch (node->nodetype) {
2833 case LYS_CONTAINER:
2834 lys_container_free(ctx, (struct lys_node_container *)node, private_destructor);
2835 break;
2836 case LYS_CHOICE:
2837 lys_when_free(ctx, ((struct lys_node_choice *)node)->when, private_destructor);
2838 break;
2839 case LYS_LEAF:
2840 lys_leaf_free(ctx, (struct lys_node_leaf *)node, private_destructor);
2841 break;
2842 case LYS_LEAFLIST:
2843 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node, private_destructor);
2844 break;
2845 case LYS_LIST:
2846 lys_list_free(ctx, (struct lys_node_list *)node, private_destructor);
2847 break;
2848 case LYS_ANYXML:
2849 case LYS_ANYDATA:
2850 lys_anydata_free(ctx, (struct lys_node_anydata *)node, private_destructor);
2851 break;
2852 case LYS_USES:
2853 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
2854 break;
2855 case LYS_CASE:
2856 lys_when_free(ctx, ((struct lys_node_case *)node)->when, private_destructor);
2857 break;
2858 case LYS_AUGMENT:
2859 /* do nothing */
2860 break;
2861 case LYS_GROUPING:
2862 lys_grp_free(ctx, (struct lys_node_grp *)node, private_destructor);
2863 break;
2864 case LYS_RPC:
2865 case LYS_ACTION:
2866 lys_rpc_action_free(ctx, (struct lys_node_rpc_action *)node, private_destructor);
2867 break;
2868 case LYS_NOTIF:
2869 lys_notif_free(ctx, (struct lys_node_notif *)node, private_destructor);
2870 break;
2871 case LYS_INPUT:
2872 case LYS_OUTPUT:
2873 lys_inout_free(ctx, (struct lys_node_inout *)node, private_destructor);
2874 break;
2875 case LYS_EXT:
2876 case LYS_UNKNOWN:
2877 LOGINT(ctx);
2878 break;
2879 }
2880
2881 /* again common part */
2882 lys_node_unlink(node);
2883 free(node);
2884 }
2885
2886 API struct lys_module *
lys_implemented_module(const struct lys_module * mod)2887 lys_implemented_module(const struct lys_module *mod)
2888 {
2889 FUN_IN;
2890
2891 struct ly_ctx *ctx;
2892 int i;
2893
2894 if (!mod || mod->implemented) {
2895 /* invalid argument or the module itself is implemented */
2896 return (struct lys_module *)mod;
2897 }
2898
2899 ctx = mod->ctx;
2900 for (i = 0; i < ctx->models.used; i++) {
2901 if (!ctx->models.list[i]->implemented) {
2902 continue;
2903 }
2904
2905 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
2906 /* we have some revision of the module implemented */
2907 return ctx->models.list[i];
2908 }
2909 }
2910
2911 /* we have no revision of the module implemented, return the module itself,
2912 * it is up to the caller to set the module implemented when needed */
2913 return (struct lys_module *)mod;
2914 }
2915
2916 /* free_int_mods - flag whether to free the internal modules as well */
2917 static void
module_free_common(struct lys_module * module,void (* private_destructor)(const struct lys_node * node,void * priv))2918 module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
2919 {
2920 struct ly_ctx *ctx;
2921 struct lys_node *next, *iter;
2922 unsigned int i;
2923
2924 assert(module->ctx);
2925 ctx = module->ctx;
2926
2927 /* just free the import array, imported modules will stay in the context */
2928 for (i = 0; i < module->imp_size; i++) {
2929 lydict_remove(ctx, module->imp[i].prefix);
2930 lydict_remove(ctx, module->imp[i].dsc);
2931 lydict_remove(ctx, module->imp[i].ref);
2932 lys_extension_instances_free(ctx, module->imp[i].ext, module->imp[i].ext_size, private_destructor);
2933 }
2934 free(module->imp);
2935
2936 /* submodules don't have data tree, the data nodes
2937 * are placed in the main module altogether */
2938 if (!module->type) {
2939 LY_TREE_FOR_SAFE(module->data, next, iter) {
2940 lys_node_free(ctx, iter, private_destructor, 0);
2941 }
2942 }
2943
2944 lydict_remove(ctx, module->dsc);
2945 lydict_remove(ctx, module->ref);
2946 lydict_remove(ctx, module->org);
2947 lydict_remove(ctx, module->contact);
2948 lydict_remove(ctx, module->filepath);
2949
2950 /* revisions */
2951 for (i = 0; i < module->rev_size; i++) {
2952 lys_extension_instances_free(ctx, module->rev[i].ext, module->rev[i].ext_size, private_destructor);
2953 lydict_remove(ctx, module->rev[i].dsc);
2954 lydict_remove(ctx, module->rev[i].ref);
2955 }
2956 free(module->rev);
2957
2958 /* identities */
2959 for (i = 0; i < module->ident_size; i++) {
2960 lys_ident_free(ctx, &module->ident[i], private_destructor);
2961 }
2962 module->ident_size = 0;
2963 free(module->ident);
2964
2965 /* typedefs */
2966 for (i = 0; i < module->tpdf_size; i++) {
2967 lys_tpdf_free(ctx, &module->tpdf[i], private_destructor);
2968 }
2969 free(module->tpdf);
2970
2971 /* extension instances */
2972 lys_extension_instances_free(ctx, module->ext, module->ext_size, private_destructor);
2973
2974 /* augment */
2975 for (i = 0; i < module->augment_size; i++) {
2976 lys_augment_free(ctx, &module->augment[i], private_destructor);
2977 }
2978 free(module->augment);
2979
2980 /* features */
2981 for (i = 0; i < module->features_size; i++) {
2982 lys_feature_free(ctx, &module->features[i], private_destructor);
2983 }
2984 free(module->features);
2985
2986 /* deviations */
2987 for (i = 0; i < module->deviation_size; i++) {
2988 lys_deviation_free(module, &module->deviation[i], private_destructor);
2989 }
2990 free(module->deviation);
2991
2992 /* extensions */
2993 for (i = 0; i < module->extensions_size; i++) {
2994 lys_extension_free(ctx, &module->extensions[i], private_destructor);
2995 }
2996 free(module->extensions);
2997
2998 lydict_remove(ctx, module->name);
2999 lydict_remove(ctx, module->prefix);
3000 }
3001
3002 void
lys_submodule_free(struct lys_submodule * submodule,void (* private_destructor)(const struct lys_node * node,void * priv))3003 lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
3004 {
3005 int i;
3006
3007 if (!submodule) {
3008 return;
3009 }
3010
3011 /* common part with struct ly_module */
3012 module_free_common((struct lys_module *)submodule, private_destructor);
3013
3014 /* include */
3015 for (i = 0; i < submodule->inc_size; i++) {
3016 lydict_remove(submodule->ctx, submodule->inc[i].dsc);
3017 lydict_remove(submodule->ctx, submodule->inc[i].ref);
3018 lys_extension_instances_free(submodule->ctx, submodule->inc[i].ext, submodule->inc[i].ext_size, private_destructor);
3019 /* complete submodule free is done only from main module since
3020 * submodules propagate their includes to the main module */
3021 }
3022 free(submodule->inc);
3023
3024 free(submodule);
3025 }
3026
3027 int
lys_ingrouping(const struct lys_node * node)3028 lys_ingrouping(const struct lys_node *node)
3029 {
3030 const struct lys_node *iter = node;
3031 assert(node);
3032
3033 iter = node;
3034 while (iter && iter->nodetype != LYS_GROUPING) {
3035 if (iter->parent && (iter->parent->nodetype == LYS_AUGMENT) && iter->parent->parent) {
3036 /* for augments in uses, we do not care about the target */
3037 iter = iter->parent->parent;
3038 } else {
3039 iter = lys_parent(iter);
3040 }
3041 }
3042 if (!iter) {
3043 return 0;
3044 } else {
3045 return 1;
3046 }
3047 }
3048
3049 /*
3050 * final: 0 - do not change config flags; 1 - inherit config flags from the parent; 2 - remove config flags
3051 */
3052 static struct lys_node *
lys_node_dup_recursion(struct lys_module * module,struct lys_node * parent,const struct lys_node * node,struct unres_schema * unres,int shallow,int finalize)3053 lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
3054 struct unres_schema *unres, int shallow, int finalize)
3055 {
3056 struct lys_node *retval = NULL, *iter, *p;
3057 struct ly_ctx *ctx = module->ctx;
3058 enum int_log_opts prev_ilo;
3059 int i, j, rc;
3060 unsigned int size, size1, size2;
3061 struct unres_list_uniq *unique_info;
3062 uint16_t flags;
3063
3064 struct lys_node_container *cont = NULL;
3065 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
3066 struct lys_node_choice *choice = NULL;
3067 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
3068 struct lys_node_leaf *leaf = NULL;
3069 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
3070 struct lys_node_leaflist *llist = NULL;
3071 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
3072 struct lys_node_list *list = NULL;
3073 struct lys_node_list *list_orig = (struct lys_node_list *)node;
3074 struct lys_node_anydata *any = NULL;
3075 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
3076 struct lys_node_uses *uses = NULL;
3077 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
3078 struct lys_node_rpc_action *rpc = NULL;
3079 struct lys_node_inout *io = NULL;
3080 struct lys_node_notif *ntf = NULL;
3081 struct lys_node_case *cs = NULL;
3082 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
3083
3084 /* we cannot just duplicate memory since the strings are stored in
3085 * dictionary and we need to update dictionary counters.
3086 */
3087
3088 switch (node->nodetype) {
3089 case LYS_CONTAINER:
3090 cont = calloc(1, sizeof *cont);
3091 retval = (struct lys_node *)cont;
3092 break;
3093
3094 case LYS_CHOICE:
3095 choice = calloc(1, sizeof *choice);
3096 retval = (struct lys_node *)choice;
3097 break;
3098
3099 case LYS_LEAF:
3100 leaf = calloc(1, sizeof *leaf);
3101 retval = (struct lys_node *)leaf;
3102 break;
3103
3104 case LYS_LEAFLIST:
3105 llist = calloc(1, sizeof *llist);
3106 retval = (struct lys_node *)llist;
3107 break;
3108
3109 case LYS_LIST:
3110 list = calloc(1, sizeof *list);
3111 /* copy keys now so that when adding children, it can be properly checked in this parent */
3112 list->keys = calloc(list_orig->keys_size, sizeof *list->keys);
3113 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
3114 list->keys_size = list_orig->keys_size;
3115
3116 retval = (struct lys_node *)list;
3117 break;
3118
3119 case LYS_ANYXML:
3120 case LYS_ANYDATA:
3121 any = calloc(1, sizeof *any);
3122 retval = (struct lys_node *)any;
3123 break;
3124
3125 case LYS_USES:
3126 uses = calloc(1, sizeof *uses);
3127 retval = (struct lys_node *)uses;
3128 break;
3129
3130 case LYS_CASE:
3131 cs = calloc(1, sizeof *cs);
3132 retval = (struct lys_node *)cs;
3133 break;
3134
3135 case LYS_RPC:
3136 case LYS_ACTION:
3137 rpc = calloc(1, sizeof *rpc);
3138 retval = (struct lys_node *)rpc;
3139 break;
3140
3141 case LYS_INPUT:
3142 case LYS_OUTPUT:
3143 io = calloc(1, sizeof *io);
3144 retval = (struct lys_node *)io;
3145 break;
3146
3147 case LYS_NOTIF:
3148 ntf = calloc(1, sizeof *ntf);
3149 retval = (struct lys_node *)ntf;
3150 break;
3151
3152 default:
3153 LOGINT(ctx);
3154 goto error;
3155 }
3156 LY_CHECK_ERR_RETURN(!retval, LOGMEM(ctx), NULL);
3157
3158 /*
3159 * duplicate generic part of the structure
3160 */
3161 retval->name = lydict_insert(ctx, node->name, 0);
3162 retval->dsc = lydict_insert(ctx, node->dsc, 0);
3163 retval->ref = lydict_insert(ctx, node->ref, 0);
3164 retval->flags = node->flags;
3165
3166 retval->module = module;
3167 retval->nodetype = node->nodetype;
3168
3169 retval->prev = retval;
3170
3171 /* copying unresolved extensions is not supported */
3172 if (unres_schema_find(unres, -1, (void *)&node->ext, UNRES_EXT) == -1) {
3173 retval->ext_size = node->ext_size;
3174 if (lys_ext_dup(ctx, module, node->ext, node->ext_size, retval, LYEXT_PAR_NODE, &retval->ext, shallow, unres)) {
3175 goto error;
3176 }
3177 }
3178
3179 if (node->iffeature_size) {
3180 retval->iffeature_size = node->iffeature_size;
3181 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
3182 LY_CHECK_ERR_GOTO(!retval->iffeature, LOGMEM(ctx), error);
3183 }
3184
3185 if (!shallow) {
3186 for (i = 0; i < node->iffeature_size; ++i) {
3187 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
3188 if (size1) {
3189 /* there is something to duplicate */
3190
3191 /* duplicate compiled expression */
3192 size = (size1 / 4) + ((size1 % 4) ? 1 : 0);
3193 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
3194 LY_CHECK_ERR_GOTO(!retval->iffeature[i].expr, LOGMEM(ctx), error);
3195 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
3196
3197 /* list of feature pointer must be updated to point to the resulting tree */
3198 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
3199 LY_CHECK_ERR_GOTO(!retval->iffeature[i].features, LOGMEM(ctx); free(retval->iffeature[i].expr), error);
3200
3201 for (j = 0; (unsigned int)j < size2; j++) {
3202 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
3203 &retval->iffeature[i].features[j]);
3204 if (rc == EXIT_FAILURE) {
3205 /* feature is resolved in origin, so copy it
3206 * - duplication is used for instantiating groupings
3207 * and if-feature inside grouping is supposed to be
3208 * resolved inside the original grouping, so we want
3209 * to keep pointers to features from the grouping
3210 * context */
3211 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
3212 } else if (rc == -1) {
3213 goto error;
3214 } /* else unres was duplicated */
3215 }
3216 }
3217
3218 /* duplicate if-feature's extensions */
3219 retval->iffeature[i].ext_size = node->iffeature[i].ext_size;
3220 if (lys_ext_dup(ctx, module, node->iffeature[i].ext, node->iffeature[i].ext_size,
3221 &retval->iffeature[i], LYEXT_PAR_IFFEATURE, &retval->iffeature[i].ext, shallow, unres)) {
3222 goto error;
3223 }
3224 }
3225
3226 /* inherit config flags */
3227 p = parent;
3228 do {
3229 for (iter = p; iter && (iter->nodetype == LYS_USES); iter = iter->parent);
3230 } while (iter && iter->nodetype == LYS_AUGMENT && (p = ((struct lys_node_augment *)iter)->target));
3231 if (iter) {
3232 flags = iter->flags & LYS_CONFIG_MASK;
3233 } else {
3234 /* default */
3235 flags = LYS_CONFIG_W;
3236 }
3237
3238 switch (finalize) {
3239 case 1:
3240 /* inherit config flags */
3241 if (retval->flags & LYS_CONFIG_SET) {
3242 /* skip nodes with an explicit config value */
3243 if ((flags & LYS_CONFIG_R) && (retval->flags & LYS_CONFIG_W)) {
3244 LOGVAL(ctx, LYE_INARG, LY_VLOG_LYS, retval, "true", "config");
3245 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "State nodes cannot have configuration nodes as children.");
3246 goto error;
3247 }
3248 break;
3249 }
3250
3251 if (retval->nodetype != LYS_USES) {
3252 retval->flags = (retval->flags & ~LYS_CONFIG_MASK) | flags;
3253 }
3254
3255 /* inherit status */
3256 if ((parent->flags & LYS_STATUS_MASK) > (retval->flags & LYS_STATUS_MASK)) {
3257 /* but do it only in case the parent has a stonger status */
3258 retval->flags &= ~LYS_STATUS_MASK;
3259 retval->flags |= (parent->flags & LYS_STATUS_MASK);
3260 }
3261 break;
3262 case 2:
3263 /* erase config flags */
3264 retval->flags &= ~LYS_CONFIG_MASK;
3265 retval->flags &= ~LYS_CONFIG_SET;
3266 break;
3267 }
3268
3269 /* connect it to the parent */
3270 if (lys_node_addchild(parent, retval->module, retval, 0)) {
3271 goto error;
3272 }
3273
3274 /* go recursively */
3275 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
3276 LY_TREE_FOR(node->child, iter) {
3277 if (iter->nodetype & LYS_GROUPING) {
3278 /* do not instantiate groupings */
3279 continue;
3280 }
3281 if (!lys_node_dup_recursion(module, retval, iter, unres, 0, finalize)) {
3282 goto error;
3283 }
3284 }
3285 }
3286 } else {
3287 if (node->iffeature_size) {
3288 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
3289 }
3290 }
3291
3292 /*
3293 * duplicate specific part of the structure
3294 */
3295 switch (node->nodetype) {
3296 case LYS_CONTAINER:
3297 if (cont_orig->when) {
3298 cont->when = lys_when_dup(module, cont_orig->when, shallow, unres);
3299 LY_CHECK_GOTO(!cont->when, error);
3300 }
3301 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
3302
3303 if (cont_orig->must) {
3304 cont->must = lys_restr_dup(module, cont_orig->must, cont_orig->must_size, shallow, unres);
3305 LY_CHECK_GOTO(!cont->must, error);
3306 cont->must_size = cont_orig->must_size;
3307 }
3308
3309 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
3310
3311 break;
3312 case LYS_CHOICE:
3313 if (choice_orig->when) {
3314 choice->when = lys_when_dup(module, choice_orig->when, shallow, unres);
3315 LY_CHECK_GOTO(!choice->when, error);
3316 }
3317
3318 if (!shallow) {
3319 if (choice_orig->dflt) {
3320 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
3321 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
3322 (const struct lys_node **)&choice->dflt);
3323 if (rc) {
3324 if (rc == EXIT_FAILURE) {
3325 LOGINT(ctx);
3326 }
3327 goto error;
3328 }
3329 } else {
3330 /* useless to check return value, we don't know whether
3331 * there really wasn't any default defined or it just hasn't
3332 * been resolved, we just hope for the best :)
3333 */
3334 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
3335 }
3336 } else {
3337 choice->dflt = choice_orig->dflt;
3338 }
3339 break;
3340
3341 case LYS_LEAF:
3342 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), lys_ingrouping(retval), shallow, unres)) {
3343 goto error;
3344 }
3345 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
3346
3347 if (leaf_orig->dflt) {
3348 /* transform into JSON format, may not be possible later */
3349 ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
3350 leaf->dflt = transform_schema2json(lys_main_module(leaf_orig->module), leaf_orig->dflt);
3351 ly_ilo_restore(NULL, prev_ilo, NULL, 0);
3352 if (!leaf->dflt) {
3353 /* invalid identityref format or it was already transformed, so ignore the error here */
3354 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
3355 }
3356 }
3357
3358 if (leaf_orig->must) {
3359 leaf->must = lys_restr_dup(module, leaf_orig->must, leaf_orig->must_size, shallow, unres);
3360 LY_CHECK_GOTO(!leaf->must, error);
3361 leaf->must_size = leaf_orig->must_size;
3362 }
3363
3364 if (leaf_orig->when) {
3365 leaf->when = lys_when_dup(module, leaf_orig->when, shallow, unres);
3366 LY_CHECK_GOTO(!leaf->when, error);
3367 }
3368 break;
3369
3370 case LYS_LEAFLIST:
3371 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), lys_ingrouping(retval), shallow, unres)) {
3372 goto error;
3373 }
3374 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
3375
3376 llist->min = llist_orig->min;
3377 llist->max = llist_orig->max;
3378
3379 if (llist_orig->must) {
3380 llist->must = lys_restr_dup(module, llist_orig->must, llist_orig->must_size, shallow, unres);
3381 LY_CHECK_GOTO(!llist->must, error);
3382 llist->must_size = llist_orig->must_size;
3383 }
3384
3385 if (llist_orig->dflt) {
3386 llist->dflt = malloc(llist_orig->dflt_size * sizeof *llist->dflt);
3387 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM(ctx), error);
3388 llist->dflt_size = llist_orig->dflt_size;
3389
3390 for (i = 0; i < llist->dflt_size; i++) {
3391 llist->dflt[i] = lydict_insert(ctx, llist_orig->dflt[i], 0);
3392 }
3393 }
3394
3395 if (llist_orig->when) {
3396 llist->when = lys_when_dup(module, llist_orig->when, shallow, unres);
3397 }
3398 break;
3399
3400 case LYS_LIST:
3401 list->min = list_orig->min;
3402 list->max = list_orig->max;
3403
3404 if (list_orig->must) {
3405 list->must = lys_restr_dup(module, list_orig->must, list_orig->must_size, shallow, unres);
3406 LY_CHECK_GOTO(!list->must, error);
3407 list->must_size = list_orig->must_size;
3408 }
3409
3410 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
3411
3412 if (list_orig->keys_size) {
3413 /* already done */
3414 /*list->keys = calloc(list_orig->keys_size, sizeof *list->keys);
3415 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM(ctx), error);
3416 list->keys_size = list_orig->keys_size;*/
3417 list->keys_str = lydict_insert(ctx, list_orig->keys_str, 0);
3418
3419 if (!shallow) {
3420 if (unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
3421 goto error;
3422 }
3423 } else {
3424 memcpy(list->keys, list_orig->keys, list_orig->keys_size * sizeof *list->keys);
3425 }
3426 }
3427
3428 if (list_orig->unique) {
3429 list->unique = malloc(list_orig->unique_size * sizeof *list->unique);
3430 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM(ctx), error);
3431 list->unique_size = list_orig->unique_size;
3432
3433 for (i = 0; i < list->unique_size; ++i) {
3434 list->unique[i].expr = malloc(list_orig->unique[i].expr_size * sizeof *list->unique[i].expr);
3435 LY_CHECK_ERR_GOTO(!list->unique[i].expr, LOGMEM(ctx), error);
3436 list->unique[i].expr_size = list_orig->unique[i].expr_size;
3437 for (j = 0; j < list->unique[i].expr_size; j++) {
3438 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
3439
3440 /* if it stays in unres list, duplicate it also there */
3441 unique_info = malloc(sizeof *unique_info);
3442 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM(ctx), error);
3443 unique_info->list = (struct lys_node *)list;
3444 unique_info->expr = list->unique[i].expr[j];
3445 unique_info->trg_type = &list->unique[i].trg_type;
3446 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
3447 }
3448 }
3449 }
3450
3451 if (list_orig->when) {
3452 list->when = lys_when_dup(module, list_orig->when, shallow, unres);
3453 LY_CHECK_GOTO(!list->when, error);
3454 }
3455 break;
3456
3457 case LYS_ANYXML:
3458 case LYS_ANYDATA:
3459 if (any_orig->must) {
3460 any->must = lys_restr_dup(module, any_orig->must, any_orig->must_size, shallow, unres);
3461 LY_CHECK_GOTO(!any->must, error);
3462 any->must_size = any_orig->must_size;
3463 }
3464
3465 if (any_orig->when) {
3466 any->when = lys_when_dup(module, any_orig->when, shallow, unres);
3467 LY_CHECK_GOTO(!any->when, error);
3468 }
3469 break;
3470
3471 case LYS_USES:
3472 uses->grp = uses_orig->grp;
3473
3474 if (uses_orig->when) {
3475 uses->when = lys_when_dup(module, uses_orig->when, shallow, unres);
3476 LY_CHECK_GOTO(!uses->when, error);
3477 }
3478 /* it is not needed to duplicate refine, nor augment. They are already applied to the uses children */
3479 break;
3480
3481 case LYS_CASE:
3482 if (cs_orig->when) {
3483 cs->when = lys_when_dup(module, cs_orig->when, shallow, unres);
3484 LY_CHECK_GOTO(!cs->when, error);
3485 }
3486 break;
3487
3488 case LYS_ACTION:
3489 case LYS_RPC:
3490 case LYS_INPUT:
3491 case LYS_OUTPUT:
3492 case LYS_NOTIF:
3493 /* typedefs are not needed in instantiated grouping, nor the deviation's shallow copy */
3494 break;
3495
3496 default:
3497 /* LY_NODE_AUGMENT */
3498 LOGINT(ctx);
3499 goto error;
3500 }
3501
3502 return retval;
3503
3504 error:
3505 lys_node_free(ctx, retval, NULL, 0);
3506 return NULL;
3507 }
3508
3509 int
lys_has_xpath(const struct lys_node * node)3510 lys_has_xpath(const struct lys_node *node)
3511 {
3512 assert(node);
3513
3514 switch (node->nodetype) {
3515 case LYS_AUGMENT:
3516 if (((struct lys_node_augment *)node)->when) {
3517 return 1;
3518 }
3519 break;
3520 case LYS_CASE:
3521 if (((struct lys_node_case *)node)->when) {
3522 return 1;
3523 }
3524 break;
3525 case LYS_CHOICE:
3526 if (((struct lys_node_choice *)node)->when) {
3527 return 1;
3528 }
3529 break;
3530 case LYS_ANYDATA:
3531 if (((struct lys_node_anydata *)node)->when || ((struct lys_node_anydata *)node)->must_size) {
3532 return 1;
3533 }
3534 break;
3535 case LYS_LEAF:
3536 if (((struct lys_node_leaf *)node)->when || ((struct lys_node_leaf *)node)->must_size) {
3537 return 1;
3538 }
3539 break;
3540 case LYS_LEAFLIST:
3541 if (((struct lys_node_leaflist *)node)->when || ((struct lys_node_leaflist *)node)->must_size) {
3542 return 1;
3543 }
3544 break;
3545 case LYS_LIST:
3546 if (((struct lys_node_list *)node)->when || ((struct lys_node_list *)node)->must_size) {
3547 return 1;
3548 }
3549 break;
3550 case LYS_CONTAINER:
3551 if (((struct lys_node_container *)node)->when || ((struct lys_node_container *)node)->must_size) {
3552 return 1;
3553 }
3554 break;
3555 case LYS_INPUT:
3556 case LYS_OUTPUT:
3557 if (((struct lys_node_inout *)node)->must_size) {
3558 return 1;
3559 }
3560 break;
3561 case LYS_NOTIF:
3562 if (((struct lys_node_notif *)node)->must_size) {
3563 return 1;
3564 }
3565 break;
3566 case LYS_USES:
3567 if (((struct lys_node_uses *)node)->when) {
3568 return 1;
3569 }
3570 break;
3571 default:
3572 /* does not have XPath */
3573 break;
3574 }
3575
3576 return 0;
3577 }
3578
3579 int
lys_type_is_local(const struct lys_type * type)3580 lys_type_is_local(const struct lys_type *type)
3581 {
3582 if (!type->der->module) {
3583 /* build-in type */
3584 return 1;
3585 }
3586 /* type->parent can be either a typedef or leaf/leaf-list, but module pointers are compatible */
3587 return (lys_main_module(type->der->module) == lys_main_module(((struct lys_tpdf *)type->parent)->module));
3588 }
3589
3590 /*
3591 * shallow -
3592 * - do not inherit status from the parent
3593 */
3594 struct lys_node *
lys_node_dup(struct lys_module * module,struct lys_node * parent,const struct lys_node * node,struct unres_schema * unres,int shallow)3595 lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node,
3596 struct unres_schema *unres, int shallow)
3597 {
3598 struct lys_node *p = NULL;
3599 int finalize = 0;
3600 struct lys_node *result, *iter, *next;
3601
3602 if (!shallow) {
3603 /* get know where in schema tree we are to know what should be done during instantiation of the grouping */
3604 for (p = parent;
3605 p && !(p->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC | LYS_ACTION | LYS_GROUPING));
3606 p = lys_parent(p));
3607 finalize = p ? ((p->nodetype == LYS_GROUPING) ? 0 : 2) : 1;
3608 }
3609
3610 result = lys_node_dup_recursion(module, parent, node, unres, shallow, finalize);
3611 if (finalize) {
3612 /* check xpath expressions in the instantiated tree */
3613 for (iter = next = result; iter; iter = next) {
3614 if (lys_has_xpath(iter) && unres_schema_add_node(module, unres, iter, UNRES_XPATH, NULL) == -1) {
3615 /* invalid xpath */
3616 return NULL;
3617 }
3618
3619 /* select next item */
3620 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
3621 /* child exception for leafs, leaflists and anyxml without children, ignore groupings */
3622 next = NULL;
3623 } else {
3624 next = iter->child;
3625 }
3626 if (!next) {
3627 /* no children, try siblings */
3628 if (iter == result) {
3629 /* we are done, no next element to process */
3630 break;
3631 }
3632 next = iter->next;
3633 }
3634 while (!next) {
3635 /* parent is already processed, go to its sibling */
3636 iter = lys_parent(iter);
3637 if (lys_parent(iter) == lys_parent(result)) {
3638 /* we are done, no next element to process */
3639 break;
3640 }
3641 next = iter->next;
3642 }
3643 }
3644 }
3645
3646 return result;
3647 }
3648
3649 /**
3650 * @brief Switch contents of two same schema nodes. One of the nodes
3651 * is expected to be ashallow copy of the other.
3652 *
3653 * @param[in] node1 Node whose contents will be switched with \p node2.
3654 * @param[in] node2 Node whose contents will be switched with \p node1.
3655 */
3656 static void
lys_node_switch(struct lys_node * node1,struct lys_node * node2)3657 lys_node_switch(struct lys_node *node1, struct lys_node *node2)
3658 {
3659 const size_t mem_size = 104;
3660 uint8_t mem[mem_size];
3661 size_t offset, size;
3662
3663 assert((node1->module == node2->module) && ly_strequal(node1->name, node2->name, 1) && (node1->nodetype == node2->nodetype));
3664
3665 /*
3666 * Initially, the nodes were really switched in the tree which
3667 * caused problems for some other nodes with pointers (augments, leafrefs, ...)
3668 * because their pointers were not being updated. Code kept in case there is
3669 * a use of it in future (it took some debugging to cover all the cases).
3670
3671 * sibling next *
3672 if (node1->prev->next) {
3673 node1->prev->next = node2;
3674 }
3675
3676 * sibling prev *
3677 if (node1->next) {
3678 node1->next->prev = node2;
3679 } else {
3680 for (child = node1->prev; child->prev->next; child = child->prev);
3681 child->prev = node2;
3682 }
3683
3684 * next *
3685 node2->next = node1->next;
3686 node1->next = NULL;
3687
3688 * prev *
3689 if (node1->prev != node1) {
3690 node2->prev = node1->prev;
3691 }
3692 node1->prev = node1;
3693
3694 * parent child *
3695 if (node1->parent) {
3696 if (node1->parent->child == node1) {
3697 node1->parent->child = node2;
3698 }
3699 } else if (lys_main_module(node1->module)->data == node1) {
3700 lys_main_module(node1->module)->data = node2;
3701 }
3702
3703 * parent *
3704 node2->parent = node1->parent;
3705 node1->parent = NULL;
3706
3707 * child parent *
3708 LY_TREE_FOR(node1->child, child) {
3709 if (child->parent == node1) {
3710 child->parent = node2;
3711 }
3712 }
3713
3714 * child *
3715 node2->child = node1->child;
3716 node1->child = NULL;
3717 */
3718
3719 /* switch common node part */
3720 offset = 3 * sizeof(char *);
3721 size = sizeof(uint16_t) + 6 * sizeof(uint8_t) + sizeof(struct lys_ext_instance **) + sizeof(struct lys_iffeature *);
3722 memcpy(mem, ((uint8_t *)node1) + offset, size);
3723 memcpy(((uint8_t *)node1) + offset, ((uint8_t *)node2) + offset, size);
3724 memcpy(((uint8_t *)node2) + offset, mem, size);
3725
3726 /* switch node-specific data */
3727 offset = sizeof(struct lys_node);
3728 switch (node1->nodetype) {
3729 case LYS_CONTAINER:
3730 size = sizeof(struct lys_node_container) - offset;
3731 break;
3732 case LYS_CHOICE:
3733 size = sizeof(struct lys_node_choice) - offset;
3734 break;
3735 case LYS_LEAF:
3736 size = sizeof(struct lys_node_leaf) - offset;
3737 break;
3738 case LYS_LEAFLIST:
3739 size = sizeof(struct lys_node_leaflist) - offset;
3740 break;
3741 case LYS_LIST:
3742 size = sizeof(struct lys_node_list) - offset;
3743 break;
3744 case LYS_ANYDATA:
3745 case LYS_ANYXML:
3746 size = sizeof(struct lys_node_anydata) - offset;
3747 break;
3748 case LYS_CASE:
3749 size = sizeof(struct lys_node_case) - offset;
3750 break;
3751 case LYS_INPUT:
3752 case LYS_OUTPUT:
3753 size = sizeof(struct lys_node_inout) - offset;
3754 break;
3755 case LYS_NOTIF:
3756 size = sizeof(struct lys_node_notif) - offset;
3757 break;
3758 case LYS_RPC:
3759 case LYS_ACTION:
3760 size = sizeof(struct lys_node_rpc_action) - offset;
3761 break;
3762 default:
3763 assert(0);
3764 LOGINT(node1->module->ctx);
3765 return;
3766 }
3767 assert(size <= mem_size);
3768 memcpy(mem, ((uint8_t *)node1) + offset, size);
3769 memcpy(((uint8_t *)node1) + offset, ((uint8_t *)node2) + offset, size);
3770 memcpy(((uint8_t *)node2) + offset, mem, size);
3771
3772 /* typedefs were not copied to the backup node, so always reuse them,
3773 * in leaves/leaf-lists we must correct the type parent pointer */
3774 switch (node1->nodetype) {
3775 case LYS_CONTAINER:
3776 ((struct lys_node_container *)node1)->tpdf_size = ((struct lys_node_container *)node2)->tpdf_size;
3777 ((struct lys_node_container *)node1)->tpdf = ((struct lys_node_container *)node2)->tpdf;
3778 ((struct lys_node_container *)node2)->tpdf_size = 0;
3779 ((struct lys_node_container *)node2)->tpdf = NULL;
3780 break;
3781 case LYS_LIST:
3782 ((struct lys_node_list *)node1)->tpdf_size = ((struct lys_node_list *)node2)->tpdf_size;
3783 ((struct lys_node_list *)node1)->tpdf = ((struct lys_node_list *)node2)->tpdf;
3784 ((struct lys_node_list *)node2)->tpdf_size = 0;
3785 ((struct lys_node_list *)node2)->tpdf = NULL;
3786 break;
3787 case LYS_RPC:
3788 case LYS_ACTION:
3789 ((struct lys_node_rpc_action *)node1)->tpdf_size = ((struct lys_node_rpc_action *)node2)->tpdf_size;
3790 ((struct lys_node_rpc_action *)node1)->tpdf = ((struct lys_node_rpc_action *)node2)->tpdf;
3791 ((struct lys_node_rpc_action *)node2)->tpdf_size = 0;
3792 ((struct lys_node_rpc_action *)node2)->tpdf = NULL;
3793 break;
3794 case LYS_NOTIF:
3795 ((struct lys_node_notif *)node1)->tpdf_size = ((struct lys_node_notif *)node2)->tpdf_size;
3796 ((struct lys_node_notif *)node1)->tpdf = ((struct lys_node_notif *)node2)->tpdf;
3797 ((struct lys_node_notif *)node2)->tpdf_size = 0;
3798 ((struct lys_node_notif *)node2)->tpdf = NULL;
3799 break;
3800 case LYS_INPUT:
3801 case LYS_OUTPUT:
3802 ((struct lys_node_inout *)node1)->tpdf_size = ((struct lys_node_inout *)node2)->tpdf_size;
3803 ((struct lys_node_inout *)node1)->tpdf = ((struct lys_node_inout *)node2)->tpdf;
3804 ((struct lys_node_inout *)node2)->tpdf_size = 0;
3805 ((struct lys_node_inout *)node2)->tpdf = NULL;
3806 break;
3807 case LYS_LEAF:
3808 case LYS_LEAFLIST:
3809 ((struct lys_node_leaf *)node1)->type.parent = (struct lys_tpdf *)node1;
3810 ((struct lys_node_leaf *)node2)->type.parent = (struct lys_tpdf *)node2;
3811 default:
3812 break;
3813 }
3814 }
3815
3816 void
lys_free(struct lys_module * module,void (* private_destructor)(const struct lys_node * node,void * priv),int free_subs,int remove_from_ctx)3817 lys_free(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv), int free_subs, int remove_from_ctx)
3818 {
3819 struct ly_ctx *ctx;
3820 int i;
3821
3822 if (!module) {
3823 return;
3824 }
3825
3826 /* remove schema from the context */
3827 ctx = module->ctx;
3828 if (remove_from_ctx && ctx->models.used) {
3829 for (i = 0; i < ctx->models.used; i++) {
3830 if (ctx->models.list[i] == module) {
3831 /* move all the models to not change the order in the list */
3832 ctx->models.used--;
3833 if (i < ctx->models.used) {
3834 memmove(&ctx->models.list[i], ctx->models.list[i + 1], (ctx->models.used - i) * sizeof *ctx->models.list);
3835 }
3836 ctx->models.list[ctx->models.used] = NULL;
3837 /* we are done */
3838 break;
3839 }
3840 }
3841 }
3842
3843 /* common part with struct ly_submodule */
3844 module_free_common(module, private_destructor);
3845
3846 /* include */
3847 for (i = 0; i < module->inc_size; i++) {
3848 lydict_remove(ctx, module->inc[i].dsc);
3849 lydict_remove(ctx, module->inc[i].ref);
3850 lys_extension_instances_free(ctx, module->inc[i].ext, module->inc[i].ext_size, private_destructor);
3851 /* complete submodule free is done only from main module since
3852 * submodules propagate their includes to the main module */
3853 if (free_subs) {
3854 lys_submodule_free(module->inc[i].submodule, private_destructor);
3855 }
3856 }
3857 free(module->inc);
3858
3859 /* specific items to free */
3860 lydict_remove(ctx, module->ns);
3861
3862 free(module);
3863 }
3864
3865 static void
lys_features_disable_recursive(struct lys_feature * f)3866 lys_features_disable_recursive(struct lys_feature *f)
3867 {
3868 unsigned int i;
3869 struct lys_feature *depf;
3870
3871 /* disable the feature */
3872 f->flags &= ~LYS_FENABLED;
3873
3874 /* by disabling feature we have to disable also all features that depends on this feature */
3875 if (f->depfeatures) {
3876 for (i = 0; i < f->depfeatures->number; i++) {
3877 depf = (struct lys_feature *)f->depfeatures->set.g[i];
3878 if (depf->flags & LYS_FENABLED) {
3879 lys_features_disable_recursive(depf);
3880 }
3881 }
3882 }
3883 }
3884
3885 /*
3886 * op: 1 - enable, 0 - disable
3887 */
3888 static int
lys_features_change(const struct lys_module * module,const char * name,int op,int skip_checks)3889 lys_features_change(const struct lys_module *module, const char *name, int op, int skip_checks)
3890 {
3891 int all = 0;
3892 int i, j, k;
3893 int progress, faili = 0, failj = 0, failk = 0;
3894
3895 uint8_t fsize;
3896 struct lys_feature *f;
3897
3898 if (!module || !name || !strlen(name)) {
3899 LOGARG;
3900 return EXIT_FAILURE;
3901 }
3902
3903 if (!strcmp(name, "*")) {
3904 /* enable all */
3905 all = 1;
3906 }
3907
3908 progress = failk = 1;
3909 while (progress && failk) {
3910 for (i = -1, failk = progress = 0; i < module->inc_size; i++) {
3911 if (i == -1) {
3912 fsize = module->features_size;
3913 f = module->features;
3914 } else {
3915 fsize = module->inc[i].submodule->features_size;
3916 f = module->inc[i].submodule->features;
3917 }
3918
3919 for (j = 0; j < fsize; j++) {
3920 if (all || !strcmp(f[j].name, name)) {
3921 if ((op && (f[j].flags & LYS_FENABLED)) || (!op && !(f[j].flags & LYS_FENABLED))) {
3922 if (all) {
3923 /* skip already set features */
3924 continue;
3925 } else {
3926 /* feature already set correctly */
3927 return EXIT_SUCCESS;
3928 }
3929 }
3930
3931 if (skip_checks) {
3932 if (op) {
3933 f[j].flags |= LYS_FENABLED;
3934 } else {
3935 f[j].flags &= ~LYS_FENABLED;
3936 }
3937 progress++;
3938 } else {
3939 if (op) {
3940 /* check referenced features if they are enabled */
3941 for (k = 0; k < f[j].iffeature_size; k++) {
3942 if (!resolve_iffeature(&f[j].iffeature[k])) {
3943 if (all) {
3944 faili = i;
3945 failj = j;
3946 failk = k + 1;
3947 break;
3948 } else {
3949 LOGERR(module->ctx, LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3950 f[j].name, k + 1);
3951 return EXIT_FAILURE;
3952 }
3953 }
3954 }
3955
3956 if (k == f[j].iffeature_size) {
3957 /* the last check passed, do the change */
3958 f[j].flags |= LYS_FENABLED;
3959 progress++;
3960 }
3961 } else {
3962 lys_features_disable_recursive(&f[j]);
3963 progress++;
3964 }
3965 }
3966 if (!all) {
3967 /* stop in case changing a single feature */
3968 return EXIT_SUCCESS;
3969 }
3970 }
3971 }
3972 }
3973 }
3974 if (failk) {
3975 /* print info about the last failing feature */
3976 LOGERR(module->ctx, LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
3977 faili == -1 ? module->features[failj].name : module->inc[faili].submodule->features[failj].name, failk);
3978 return EXIT_FAILURE;
3979 }
3980
3981 if (all) {
3982 return EXIT_SUCCESS;
3983 } else {
3984 /* the specified feature not found */
3985 return EXIT_FAILURE;
3986 }
3987 }
3988
3989 API int
lys_features_enable(const struct lys_module * module,const char * feature)3990 lys_features_enable(const struct lys_module *module, const char *feature)
3991 {
3992 FUN_IN;
3993
3994 return lys_features_change(module, feature, 1, 0);
3995 }
3996
3997 API int
lys_features_disable(const struct lys_module * module,const char * feature)3998 lys_features_disable(const struct lys_module *module, const char *feature)
3999 {
4000 FUN_IN;
4001
4002 return lys_features_change(module, feature, 0, 0);
4003 }
4004
4005 API int
lys_features_enable_force(const struct lys_module * module,const char * feature)4006 lys_features_enable_force(const struct lys_module *module, const char *feature)
4007 {
4008 FUN_IN;
4009
4010 return lys_features_change(module, feature, 1, 1);
4011 }
4012
4013 API int
lys_features_disable_force(const struct lys_module * module,const char * feature)4014 lys_features_disable_force(const struct lys_module *module, const char *feature)
4015 {
4016 FUN_IN;
4017
4018 return lys_features_change(module, feature, 0, 1);
4019 }
4020
4021 static struct lys_feature *
lys_features_find(const struct lys_module * module,const char * name)4022 lys_features_find(const struct lys_module *module, const char *name)
4023 {
4024 int i, j;
4025
4026 /* module itself */
4027 for (i = 0; i < module->features_size; i++) {
4028 if (!strcmp(name, module->features[i].name)) {
4029 return &module->features[i];
4030 }
4031 }
4032
4033 /* submodules */
4034 for (j = 0; j < module->inc_size; j++) {
4035 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
4036 if (!strcmp(name, module->inc[j].submodule->features[i].name)) {
4037 return &module->inc[j].submodule->features[i];
4038 }
4039 }
4040 }
4041
4042 return NULL;
4043 }
4044
4045 API int
lys_features_state(const struct lys_module * module,const char * feature)4046 lys_features_state(const struct lys_module *module, const char *feature)
4047 {
4048 FUN_IN;
4049
4050 struct lys_feature *f;
4051 int i;
4052
4053 if (!module || !feature) {
4054 return -1;
4055 }
4056
4057 /* search for the specified feature */
4058 f = lys_features_find(module, feature);
4059 if (!f) {
4060 return -1;
4061 }
4062
4063 if (!(f->flags & LYS_FENABLED)) {
4064 /* disabled for sure */
4065 return 0;
4066 }
4067
4068 /* check referenced features if they are enabled */
4069 for (i = 0; i < f->iffeature_size; ++i) {
4070 if (!resolve_iffeature(&f->iffeature[i])) {
4071 /* if-feature disabled */
4072 return 0;
4073 }
4074 }
4075
4076 return 1;
4077 }
4078
4079 API const char **
lys_features_list(const struct lys_module * module,uint8_t ** states)4080 lys_features_list(const struct lys_module *module, uint8_t **states)
4081 {
4082 FUN_IN;
4083
4084 const char **result = NULL;
4085 int i, j;
4086 unsigned int count;
4087
4088 if (!module) {
4089 return NULL;
4090 }
4091
4092 count = module->features_size;
4093 for (i = 0; i < module->inc_size; i++) {
4094 count += module->inc[i].submodule->features_size;
4095 }
4096 result = malloc((count + 1) * sizeof *result);
4097 LY_CHECK_ERR_RETURN(!result, LOGMEM(module->ctx), NULL);
4098
4099 if (states) {
4100 *states = malloc((count + 1) * sizeof **states);
4101 LY_CHECK_ERR_RETURN(!(*states), LOGMEM(module->ctx); free(result), NULL);
4102 }
4103 count = 0;
4104
4105 /* module itself */
4106 for (i = 0; i < module->features_size; i++) {
4107 result[count] = module->features[i].name;
4108 if (states) {
4109 if (module->features[i].flags & LYS_FENABLED) {
4110 (*states)[count] = 1;
4111 } else {
4112 (*states)[count] = 0;
4113 }
4114 }
4115 count++;
4116 }
4117
4118 /* submodules */
4119 for (j = 0; j < module->inc_size; j++) {
4120 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
4121 result[count] = module->inc[j].submodule->features[i].name;
4122 if (states) {
4123 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
4124 (*states)[count] = 1;
4125 } else {
4126 (*states)[count] = 0;
4127 }
4128 }
4129 count++;
4130 }
4131 }
4132
4133 /* terminating NULL byte */
4134 result[count] = NULL;
4135
4136 return result;
4137 }
4138
4139 API struct lys_module *
lys_node_module(const struct lys_node * node)4140 lys_node_module(const struct lys_node *node)
4141 {
4142 FUN_IN;
4143
4144 if (!node) {
4145 return NULL;
4146 }
4147
4148 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
4149 }
4150
4151 API struct lys_module *
lys_main_module(const struct lys_module * module)4152 lys_main_module(const struct lys_module *module)
4153 {
4154 FUN_IN;
4155
4156 if (!module) {
4157 return NULL;
4158 }
4159
4160 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
4161 }
4162
4163 API struct lys_node *
lys_parent(const struct lys_node * node)4164 lys_parent(const struct lys_node *node)
4165 {
4166 FUN_IN;
4167
4168 struct lys_node *parent;
4169
4170 if (!node) {
4171 return NULL;
4172 }
4173
4174 if (node->nodetype == LYS_EXT) {
4175 if (((struct lys_ext_instance_complex*)node)->parent_type != LYEXT_PAR_NODE) {
4176 return NULL;
4177 }
4178 parent = (struct lys_node*)((struct lys_ext_instance_complex*)node)->parent;
4179 } else if (!node->parent) {
4180 return NULL;
4181 } else {
4182 parent = node->parent;
4183 }
4184
4185 if (parent->nodetype == LYS_AUGMENT) {
4186 return ((struct lys_node_augment *)parent)->target;
4187 } else {
4188 return parent;
4189 }
4190 }
4191
4192 struct lys_node **
lys_child(const struct lys_node * node,LYS_NODE nodetype)4193 lys_child(const struct lys_node *node, LYS_NODE nodetype)
4194 {
4195 void *pp;
4196 assert(node);
4197
4198 if (node->nodetype == LYS_EXT) {
4199 pp = lys_ext_complex_get_substmt(lys_snode2stmt(nodetype), (struct lys_ext_instance_complex*)node, NULL);
4200 if (!pp) {
4201 return NULL;
4202 }
4203 return (struct lys_node **)pp;
4204 } else if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4205 return NULL;
4206 } else {
4207 return (struct lys_node **)&node->child;
4208 }
4209 }
4210
4211 API void *
lys_set_private(const struct lys_node * node,void * priv)4212 lys_set_private(const struct lys_node *node, void *priv)
4213 {
4214 FUN_IN;
4215
4216 void *prev;
4217
4218 if (!node) {
4219 LOGARG;
4220 return NULL;
4221 }
4222
4223 prev = node->priv;
4224 ((struct lys_node *)node)->priv = priv;
4225
4226 return prev;
4227 }
4228
4229 int
lys_leaf_check_leafref(struct lys_node_leaf * leafref_target,struct lys_node * leafref)4230 lys_leaf_check_leafref(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
4231 {
4232 struct lys_node_leaf *iter;
4233 struct lys_node *op;
4234 struct ly_ctx *ctx = leafref_target->module->ctx;
4235
4236 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
4237 LOGINT(ctx);
4238 return -1;
4239 }
4240
4241 /* find the operation node if we are in one */
4242 for (op = leafref; op && !(op->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)); op = lys_parent(op));
4243
4244 /* check for config flag */
4245 if (!op && ((struct lys_node_leaf*)leafref)->type.info.lref.req != -1 &&
4246 (leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
4247 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, leafref,
4248 "The leafref %s is config but refers to a non-config %s.",
4249 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
4250 return -1;
4251 }
4252 /* check for cycles */
4253 for (iter = leafref_target; iter && iter->type.base == LY_TYPE_LEAFREF; iter = iter->type.info.lref.target) {
4254 if ((void *)iter == (void *)leafref) {
4255 /* cycle detected */
4256 LOGVAL(ctx, LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
4257 return -1;
4258 }
4259 }
4260
4261 return 0;
4262 }
4263
4264 /* not needed currently */
4265 #if 0
4266
4267 static const char *
4268 lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
4269 {
4270 struct lys_module *prev_mod;
4271 uint32_t str_len, mod_len, buf_idx;
4272
4273 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
4274 LOGINT;
4275 return NULL;
4276 }
4277
4278 buf_idx = buf_len - 1;
4279 buf[buf_idx] = '\0';
4280
4281 while (node) {
4282 if (lys_parent(node)) {
4283 prev_mod = lys_node_module(lys_parent(node));
4284 } else {
4285 prev_mod = NULL;
4286 }
4287
4288 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4289 str_len = strlen(node->name);
4290
4291 if (prev_mod != node->module) {
4292 mod_len = strlen(node->module->name);
4293 } else {
4294 mod_len = 0;
4295 }
4296
4297 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
4298 LOGINT;
4299 return NULL;
4300 }
4301
4302 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
4303
4304 buf[buf_idx] = '/';
4305 if (mod_len) {
4306 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
4307 buf[buf_idx + 1 + mod_len] = ':';
4308 }
4309 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
4310 }
4311
4312 node = lys_parent(node);
4313 }
4314
4315 return buf + buf_idx;
4316 }
4317
4318 #endif
4319
4320 API struct ly_set *
lys_xpath_atomize(const struct lys_node * ctx_node,enum lyxp_node_type ctx_node_type,const char * expr,int options)4321 lys_xpath_atomize(const struct lys_node *ctx_node, enum lyxp_node_type ctx_node_type, const char *expr, int options)
4322 {
4323 FUN_IN;
4324
4325 struct lyxp_set set;
4326 const struct lys_node *parent;
4327 struct ly_set *ret_set;
4328 uint32_t i;
4329
4330 if (!ctx_node || !expr) {
4331 LOGARG;
4332 return NULL;
4333 }
4334
4335 /* adjust the root */
4336 if ((ctx_node_type == LYXP_NODE_ROOT) || (ctx_node_type == LYXP_NODE_ROOT_CONFIG)) {
4337 do {
4338 ctx_node = lys_getnext(NULL, NULL, lys_node_module(ctx_node), LYS_GETNEXT_NOSTATECHECK);
4339 } while ((ctx_node_type == LYXP_NODE_ROOT_CONFIG) && (ctx_node->flags & LYS_CONFIG_R));
4340 }
4341
4342 memset(&set, 0, sizeof set);
4343
4344 for (parent = ctx_node; parent && (parent->nodetype != LYS_OUTPUT); parent = lys_parent(parent));
4345 if (parent) {
4346 options &= ~(LYXP_MUST | LYXP_WHEN);
4347 options |= LYXP_SNODE_OUTPUT;
4348 } else if (options & LYXP_MUST) {
4349 options &= ~LYXP_MUST;
4350 options |= LYXP_SNODE_MUST;
4351 } else if (options & LYXP_WHEN) {
4352 options &= ~LYXP_WHEN;
4353 options |= LYXP_SNODE_WHEN;
4354 } else {
4355 options |= LYXP_SNODE;
4356 }
4357
4358 if (lyxp_atomize(expr, ctx_node, ctx_node_type, &set, options, NULL)) {
4359 free(set.val.snodes);
4360 LOGVAL(ctx_node->module->ctx, LYE_SPEC, LY_VLOG_LYS, ctx_node, "Resolving XPath expression \"%s\" failed.", expr);
4361 return NULL;
4362 }
4363
4364 ret_set = ly_set_new();
4365
4366 for (i = 0; i < set.used; ++i) {
4367 switch (set.val.snodes[i].type) {
4368 case LYXP_NODE_ELEM:
4369 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
4370 ly_set_free(ret_set);
4371 free(set.val.snodes);
4372 return NULL;
4373 }
4374 break;
4375 default:
4376 /* ignore roots, text and attr should not ever appear */
4377 break;
4378 }
4379 }
4380
4381 free(set.val.snodes);
4382 return ret_set;
4383 }
4384
4385 API struct ly_set *
lys_node_xpath_atomize(const struct lys_node * node,int options)4386 lys_node_xpath_atomize(const struct lys_node *node, int options)
4387 {
4388 FUN_IN;
4389
4390 const struct lys_node *next, *elem, *parent, *tmp;
4391 struct lyxp_set set;
4392 struct ly_set *ret_set;
4393 uint16_t i;
4394
4395 if (!node) {
4396 LOGARG;
4397 return NULL;
4398 }
4399
4400 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
4401 if (!parent) {
4402 /* not in input, output, or notification */
4403 return NULL;
4404 }
4405
4406 ret_set = ly_set_new();
4407 if (!ret_set) {
4408 return NULL;
4409 }
4410
4411 LY_TREE_DFS_BEGIN(node, next, elem) {
4412 if ((options & LYXP_NO_LOCAL) && !(elem->flags & (LYS_XPCONF_DEP | LYS_XPSTATE_DEP))) {
4413 /* elem has no dependencies from other subtrees and local nodes get discarded */
4414 goto next_iter;
4415 }
4416
4417 if (lyxp_node_atomize(elem, &set, 0)) {
4418 ly_set_free(ret_set);
4419 free(set.val.snodes);
4420 return NULL;
4421 }
4422
4423 for (i = 0; i < set.used; ++i) {
4424 switch (set.val.snodes[i].type) {
4425 case LYXP_NODE_ELEM:
4426 if (options & LYXP_NO_LOCAL) {
4427 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
4428 if (tmp) {
4429 /* in local subtree, discard */
4430 break;
4431 }
4432 }
4433 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
4434 ly_set_free(ret_set);
4435 free(set.val.snodes);
4436 return NULL;
4437 }
4438 break;
4439 default:
4440 /* ignore roots, text and attr should not ever appear */
4441 break;
4442 }
4443 }
4444
4445 free(set.val.snodes);
4446 if (!(options & LYXP_RECURSIVE)) {
4447 break;
4448 }
4449 next_iter:
4450 LY_TREE_DFS_END(node, next, elem);
4451 }
4452
4453 return ret_set;
4454 }
4455
4456 /* logs */
4457 int
apply_aug(struct lys_node_augment * augment,struct unres_schema * unres)4458 apply_aug(struct lys_node_augment *augment, struct unres_schema *unres)
4459 {
4460 struct lys_node *child, *parent;
4461 struct lys_module *mod;
4462 struct lys_type *type;
4463 int clear_config;
4464 unsigned int u;
4465 uint8_t *v;
4466 struct lys_ext_instance *ext;
4467
4468 assert(augment->target && (augment->flags & LYS_NOTAPPLIED));
4469
4470 if (!augment->child) {
4471 /* nothing to apply */
4472 goto success;
4473 }
4474
4475 /* inherit config information from actual parent */
4476 for (parent = augment->target; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); parent = lys_parent(parent));
4477 clear_config = (parent) ? 1 : 0;
4478 LY_TREE_FOR(augment->child, child) {
4479 if (inherit_config_flag(child, augment->target->flags & LYS_CONFIG_MASK, clear_config)) {
4480 return -1;
4481 }
4482 }
4483
4484 /* inherit extensions if any */
4485 for (u = 0; u < augment->target->ext_size; u++) {
4486 ext = augment->target->ext[u]; /* shortcut */
4487 if (ext && ext->def->plugin && (ext->def->plugin->flags & LYEXT_OPT_INHERIT)) {
4488 v = malloc(sizeof *v);
4489 LY_CHECK_ERR_RETURN(!v, LOGMEM(augment->module->ctx), -1);
4490 *v = u;
4491 if (unres_schema_add_node(lys_main_module(augment->module), unres, &augment->target->ext,
4492 UNRES_EXT_FINALIZE, (struct lys_node *)v) == -1) {
4493 /* something really bad happened since the extension finalization is not actually
4494 * being resolved while adding into unres, so something more serious with the unres
4495 * list itself must happened */
4496 return -1;
4497 }
4498 }
4499 }
4500
4501 if (lys_node_module((struct lys_node *)augment)->implemented) {
4502 /* check that all leafrefs point to implemented modules */
4503 LY_TREE_DFS_BEGIN((struct lys_node *)augment, parent, child) {
4504 if (child->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
4505 type = &((struct lys_node_leaf *)child)->type;
4506 if (type->base == LY_TYPE_LEAFREF) {
4507 /* must be resolved or in unres */
4508 if (!type->info.lref.target) {
4509 if (unres_schema_find(unres, -1, type, UNRES_TYPE_LEAFREF) > -1) {
4510 if (unres_schema_add_node(lys_node_module(child), unres, type, UNRES_TYPE_LEAFREF, child) == -1) {
4511 return -1;
4512 }
4513 }
4514 } else {
4515 mod = lys_node_module((struct lys_node *)type->info.lref.target);
4516 if (!mod->implemented) {
4517 mod->implemented = 1;
4518 if (unres_schema_add_node(mod, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
4519 return -1;
4520 }
4521 }
4522 }
4523 }
4524 }
4525
4526 LY_TREE_DFS_END((struct lys_node *)augment, parent, child);
4527 }
4528 }
4529
4530 /* reconnect augmenting data into the target - add them to the target child list */
4531 if (augment->target->child) {
4532 child = augment->target->child->prev;
4533 child->next = augment->child;
4534 augment->target->child->prev = augment->child->prev;
4535 augment->child->prev = child;
4536 } else {
4537 augment->target->child = augment->child;
4538 }
4539
4540 success:
4541 /* remove the flag about not applicability */
4542 augment->flags &= ~LYS_NOTAPPLIED;
4543 return EXIT_SUCCESS;
4544 }
4545
4546 static void
remove_aug(struct lys_node_augment * augment)4547 remove_aug(struct lys_node_augment *augment)
4548 {
4549 struct lys_node *last, *elem;
4550
4551 if ((augment->flags & LYS_NOTAPPLIED) || !augment->target) {
4552 /* skip already not applied augment */
4553 return;
4554 }
4555
4556 elem = augment->child;
4557 if (elem) {
4558 LY_TREE_FOR(elem, last) {
4559 if (!last->next || (last->next->parent != (struct lys_node *)augment)) {
4560 break;
4561 }
4562 }
4563 /* elem is first augment child, last is the last child */
4564
4565 /* parent child ptr */
4566 if (augment->target->child == elem) {
4567 augment->target->child = last->next;
4568 }
4569
4570 /* parent child next ptr */
4571 if (elem->prev->next) {
4572 elem->prev->next = last->next;
4573 }
4574
4575 /* parent child prev ptr */
4576 if (last->next) {
4577 last->next->prev = elem->prev;
4578 } else if (augment->target->child) {
4579 augment->target->child->prev = elem->prev;
4580 }
4581
4582 /* update augment children themselves */
4583 elem->prev = last;
4584 last->next = NULL;
4585 }
4586
4587 /* augment->target still keeps the resolved target, but for lys_augment_free()
4588 * we have to keep information that this augment is not applied to free its data */
4589 augment->flags |= LYS_NOTAPPLIED;
4590 }
4591
4592 /*
4593 * @param[in] module - the module where the deviation is defined
4594 */
4595 static void
lys_switch_deviation(struct lys_deviation * dev,const struct lys_module * module,struct unres_schema * unres)4596 lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
4597 {
4598 int ret, reapply = 0;
4599 char *parent_path;
4600 struct lys_node *target = NULL, *parent;
4601 struct lys_node_inout *inout;
4602 struct ly_set *set;
4603
4604 if (!dev->deviate) {
4605 return;
4606 }
4607
4608 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
4609 if (dev->orig_node) {
4610 /* removing not-supported deviation ... */
4611 if (strrchr(dev->target_name, '/') != dev->target_name) {
4612 /* ... from a parent */
4613
4614 /* reconnect to its previous position */
4615 parent = dev->orig_node->parent;
4616 if (parent && (parent->nodetype == LYS_AUGMENT)) {
4617 dev->orig_node->parent = NULL;
4618 /* the original node was actually from augment, we have to get know if the augment is
4619 * applied (its module is enabled and implemented). If yes, the node will be connected
4620 * to the augment and the linkage with the target will be fixed if needed, otherwise
4621 * it will be connected only to the augment */
4622 if (!(parent->flags & LYS_NOTAPPLIED)) {
4623 /* start with removing augment if applied before adding nodes, we have to make sure
4624 * that everything will be connect correctly */
4625 remove_aug((struct lys_node_augment *)parent);
4626 reapply = 1;
4627 }
4628 /* connect the deviated node back into the augment */
4629 lys_node_addchild(parent, NULL, dev->orig_node, 0);
4630 if (reapply) {
4631 /* augment is supposed to be applied, so fix pointers in target and the status of the original node */
4632 assert(lys_node_module(parent)->implemented);
4633 parent->flags |= LYS_NOTAPPLIED; /* allow apply_aug() */
4634 apply_aug((struct lys_node_augment *)parent, unres);
4635 }
4636 } else if (parent && (parent->nodetype == LYS_USES)) {
4637 /* uses child */
4638 lys_node_addchild(parent, NULL, dev->orig_node, 0);
4639 } else {
4640 /* non-augment, non-toplevel */
4641 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
4642 ret = resolve_schema_nodeid(parent_path, NULL, module, &set, 0, 1);
4643 free(parent_path);
4644 if (ret == -1) {
4645 LOGINT(module->ctx);
4646 ly_set_free(set);
4647 return;
4648 }
4649 target = set->set.s[0];
4650 ly_set_free(set);
4651
4652 lys_node_addchild(target, NULL, dev->orig_node, 0);
4653 }
4654 } else {
4655 /* ... from top-level data */
4656 lys_node_addchild(NULL, lys_node_module(dev->orig_node), dev->orig_node, 0);
4657 }
4658
4659 dev->orig_node = NULL;
4660 } else {
4661 /* adding not-supported deviation */
4662 ret = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4663 if (ret == -1) {
4664 LOGINT(module->ctx);
4665 ly_set_free(set);
4666 return;
4667 }
4668 target = set->set.s[0];
4669 ly_set_free(set);
4670
4671 /* unlink and store the original node */
4672 parent = target->parent;
4673 lys_node_unlink(target);
4674 if (parent) {
4675 if (parent->nodetype & (LYS_AUGMENT | LYS_USES)) {
4676 /* hack for augment, because when the original will be sometime reconnected back, we actually need
4677 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
4678 * path), so we need to remember the augment as an addition */
4679 /* we also need to remember the parent uses so that we connect it back to it when switching deviation state */
4680 target->parent = parent;
4681 } else if (parent->nodetype & (LYS_RPC | LYS_ACTION)) {
4682 /* re-create implicit node */
4683 inout = calloc(1, sizeof *inout);
4684 LY_CHECK_ERR_RETURN(!inout, LOGMEM(module->ctx), );
4685
4686 inout->nodetype = target->nodetype;
4687 inout->name = lydict_insert(module->ctx, (inout->nodetype == LYS_INPUT) ? "input" : "output", 0);
4688 inout->module = target->module;
4689 inout->flags = LYS_IMPLICIT;
4690
4691 /* insert it manually */
4692 assert(parent->child && !parent->child->next
4693 && (parent->child->nodetype == (inout->nodetype == LYS_INPUT ? LYS_OUTPUT : LYS_INPUT)));
4694 parent->child->next = (struct lys_node *)inout;
4695 inout->prev = parent->child;
4696 parent->child->prev = (struct lys_node *)inout;
4697 inout->parent = parent;
4698 }
4699 }
4700 dev->orig_node = target;
4701 }
4702 } else {
4703 ret = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
4704 if (ret == -1) {
4705 LOGINT(module->ctx);
4706 ly_set_free(set);
4707 return;
4708 }
4709 target = set->set.s[0];
4710 ly_set_free(set);
4711
4712 /* contents are switched */
4713 lys_node_switch(target, dev->orig_node);
4714 }
4715 }
4716
4717 /* temporarily removes or applies deviations, updates module deviation flag accordingly */
4718 void
lys_enable_deviations(struct lys_module * module)4719 lys_enable_deviations(struct lys_module *module)
4720 {
4721 uint32_t i = 0, j;
4722 const struct lys_module *mod;
4723 const char *ptr;
4724 struct unres_schema *unres;
4725
4726 if (module->deviated) {
4727 unres = calloc(1, sizeof *unres);
4728 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
4729
4730 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
4731 if (mod == module) {
4732 continue;
4733 }
4734
4735 for (j = 0; j < mod->deviation_size; ++j) {
4736 ptr = strstr(mod->deviation[j].target_name, module->name);
4737 if (ptr && ptr[strlen(module->name)] == ':') {
4738 lys_switch_deviation(&mod->deviation[j], mod, unres);
4739 }
4740 }
4741 }
4742
4743 assert(module->deviated == 2);
4744 module->deviated = 1;
4745
4746 for (j = 0; j < module->inc_size; j++) {
4747 if (module->inc[j].submodule->deviated) {
4748 module->inc[j].submodule->deviated = module->deviated;
4749 }
4750 }
4751
4752 if (unres->count) {
4753 resolve_unres_schema(module, unres);
4754 }
4755 unres_schema_free(module, &unres, 1);
4756 }
4757 }
4758
4759 void
lys_disable_deviations(struct lys_module * module)4760 lys_disable_deviations(struct lys_module *module)
4761 {
4762 uint32_t i, j;
4763 const struct lys_module *mod;
4764 const char *ptr;
4765 struct unres_schema *unres;
4766
4767 if (module->deviated) {
4768 unres = calloc(1, sizeof *unres);
4769 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
4770
4771 i = module->ctx->models.used;
4772 while (i--) {
4773 mod = module->ctx->models.list[i];
4774
4775 if (mod == module) {
4776 continue;
4777 }
4778
4779 j = mod->deviation_size;
4780 while (j--) {
4781 ptr = strstr(mod->deviation[j].target_name, module->name);
4782 if (ptr && ptr[strlen(module->name)] == ':') {
4783 lys_switch_deviation(&mod->deviation[j], mod, unres);
4784 }
4785 }
4786 }
4787
4788 assert(module->deviated == 1);
4789 module->deviated = 2;
4790
4791 for (j = 0; j < module->inc_size; j++) {
4792 if (module->inc[j].submodule->deviated) {
4793 module->inc[j].submodule->deviated = module->deviated;
4794 }
4795 }
4796
4797 if (unres->count) {
4798 resolve_unres_schema(module, unres);
4799 }
4800 unres_schema_free(module, &unres, 1);
4801 }
4802 }
4803
4804 static void
apply_dev(struct lys_deviation * dev,const struct lys_module * module,struct unres_schema * unres)4805 apply_dev(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
4806 {
4807 lys_switch_deviation(dev, module, unres);
4808
4809 assert(dev->orig_node);
4810 lys_node_module(dev->orig_node)->deviated = 1; /* main module */
4811 dev->orig_node->module->deviated = 1; /* possible submodule */
4812 }
4813
4814 static void
remove_dev(struct lys_deviation * dev,const struct lys_module * module,struct unres_schema * unres)4815 remove_dev(struct lys_deviation *dev, const struct lys_module *module, struct unres_schema *unres)
4816 {
4817 uint32_t idx = 0, j;
4818 const struct lys_module *mod;
4819 struct lys_module *target_mod, *target_submod;
4820 const char *ptr;
4821
4822 if (dev->orig_node) {
4823 target_mod = lys_node_module(dev->orig_node);
4824 target_submod = dev->orig_node->module;
4825 } else {
4826 LOGINT(module->ctx);
4827 return;
4828 }
4829 lys_switch_deviation(dev, module, unres);
4830
4831 /* clear the deviation flag if possible */
4832 while ((mod = ly_ctx_get_module_iter(module->ctx, &idx))) {
4833 if ((mod == module) || (mod == target_mod)) {
4834 continue;
4835 }
4836
4837 for (j = 0; j < mod->deviation_size; ++j) {
4838 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
4839 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
4840 /* some other module deviation targets the inspected module, flag remains */
4841 break;
4842 }
4843 }
4844
4845 if (j < mod->deviation_size) {
4846 break;
4847 }
4848 }
4849
4850 if (!mod) {
4851 target_mod->deviated = 0; /* main module */
4852 target_submod->deviated = 0; /* possible submodule */
4853 }
4854 }
4855
4856 void
lys_sub_module_apply_devs_augs(struct lys_module * module)4857 lys_sub_module_apply_devs_augs(struct lys_module *module)
4858 {
4859 uint8_t u, v;
4860 struct unres_schema *unres;
4861
4862 assert(module->implemented);
4863
4864 unres = calloc(1, sizeof *unres);
4865 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
4866
4867 /* apply deviations */
4868 for (u = 0; u < module->deviation_size; ++u) {
4869 apply_dev(&module->deviation[u], module, unres);
4870 }
4871 /* apply augments */
4872 for (u = 0; u < module->augment_size; ++u) {
4873 apply_aug(&module->augment[u], unres);
4874 }
4875
4876 /* apply deviations and augments defined in submodules */
4877 for (v = 0; v < module->inc_size; ++v) {
4878 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
4879 apply_dev(&module->inc[v].submodule->deviation[u], module, unres);
4880 }
4881
4882 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4883 apply_aug(&module->inc[v].submodule->augment[u], unres);
4884 }
4885 }
4886
4887 if (unres->count) {
4888 resolve_unres_schema(module, unres);
4889 }
4890 /* nothing else left to do even if something is not resolved */
4891 unres_schema_free(module, &unres, 1);
4892 }
4893
4894 void
lys_sub_module_remove_devs_augs(struct lys_module * module)4895 lys_sub_module_remove_devs_augs(struct lys_module *module)
4896 {
4897 uint8_t u, v, w;
4898 struct unres_schema *unres;
4899
4900 unres = calloc(1, sizeof *unres);
4901 LY_CHECK_ERR_RETURN(!unres, LOGMEM(module->ctx), );
4902
4903 /* remove applied deviations */
4904 for (u = 0; u < module->deviation_size; ++u) {
4905 /* the deviation could not be applied because it failed to be applied in the first place*/
4906 if (module->deviation[u].orig_node) {
4907 remove_dev(&module->deviation[u], module, unres);
4908 }
4909
4910 /* Free the deviation's must array(s). These are shallow copies of the arrays
4911 on the target node(s), so a deep free is not needed. */
4912 for (v = 0; v < module->deviation[u].deviate_size; ++v) {
4913 if (module->deviation[u].deviate[v].mod == LY_DEVIATE_ADD) {
4914 free(module->deviation[u].deviate[v].must);
4915 }
4916 }
4917 }
4918 /* remove applied augments */
4919 for (u = 0; u < module->augment_size; ++u) {
4920 remove_aug(&module->augment[u]);
4921 }
4922
4923 /* remove deviation and augments defined in submodules */
4924 for (v = 0; v < module->inc_size && module->inc[v].submodule; ++v) {
4925 for (u = 0; u < module->inc[v].submodule->deviation_size; ++u) {
4926 if (module->inc[v].submodule->deviation[u].orig_node) {
4927 remove_dev(&module->inc[v].submodule->deviation[u], module, unres);
4928 }
4929
4930 /* Free the deviation's must array(s). These are shallow copies of the arrays
4931 on the target node(s), so a deep free is not needed. */
4932 for (w = 0; w < module->inc[v].submodule->deviation[u].deviate_size; ++w) {
4933 if (module->inc[v].submodule->deviation[u].deviate[w].mod == LY_DEVIATE_ADD) {
4934 free(module->inc[v].submodule->deviation[u].deviate[w].must);
4935 }
4936 }
4937 }
4938
4939 for (u = 0; u < module->inc[v].submodule->augment_size; ++u) {
4940 remove_aug(&module->inc[v].submodule->augment[u]);
4941 }
4942 }
4943
4944 if (unres->count) {
4945 resolve_unres_schema(module, unres);
4946 }
4947 /* nothing else left to do even if something is not resolved */
4948 unres_schema_free(module, &unres, 1);
4949 }
4950
4951 int
lys_make_implemented_r(struct lys_module * module,struct unres_schema * unres)4952 lys_make_implemented_r(struct lys_module *module, struct unres_schema *unres)
4953 {
4954 struct ly_ctx *ctx;
4955 struct lys_node *root, *next, *node;
4956 struct lys_module *target_module;
4957 uint16_t i, j, k;
4958
4959 assert(module->implemented);
4960 ctx = module->ctx;
4961
4962 for (i = 0; i < ctx->models.used; ++i) {
4963 if (module == ctx->models.list[i]) {
4964 continue;
4965 }
4966
4967 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
4968 LOGERR(ctx, LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
4969 return EXIT_FAILURE;
4970 }
4971 }
4972
4973 for (i = 0; i < module->augment_size; i++) {
4974
4975 /* make target module implemented if was not */
4976 assert(module->augment[i].target);
4977 target_module = lys_node_module(module->augment[i].target);
4978 if (!target_module->implemented) {
4979 target_module->implemented = 1;
4980 if (unres_schema_add_node(target_module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
4981 return -1;
4982 }
4983 }
4984
4985 /* apply augment */
4986 if ((module->augment[i].flags & LYS_NOTAPPLIED) && apply_aug(&module->augment[i], unres)) {
4987 return -1;
4988 }
4989 }
4990
4991 /* identities */
4992 for (i = 0; i < module->ident_size; i++) {
4993 for (j = 0; j < module->ident[i].base_size; j++) {
4994 resolve_identity_backlink_update(&module->ident[i], module->ident[i].base[j]);
4995 }
4996 }
4997
4998 /* process augments in submodules */
4999 for (i = 0; i < module->inc_size && module->inc[i].submodule; ++i) {
5000 module->inc[i].submodule->implemented = 1;
5001
5002 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
5003
5004 /* make target module implemented if it was not */
5005 assert(module->inc[i].submodule->augment[j].target);
5006 target_module = lys_node_module(module->inc[i].submodule->augment[j].target);
5007 if (!target_module->implemented) {
5008 target_module->implemented = 1;
5009 if (unres_schema_add_node(target_module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
5010 return -1;
5011 }
5012 }
5013
5014 /* apply augment */
5015 if ((module->inc[i].submodule->augment[j].flags & LYS_NOTAPPLIED) && apply_aug(&module->inc[i].submodule->augment[j], unres)) {
5016 return -1;
5017 }
5018 }
5019
5020 /* identities */
5021 for (j = 0; j < module->inc[i].submodule->ident_size; j++) {
5022 for (k = 0; k < module->inc[i].submodule->ident[j].base_size; k++) {
5023 resolve_identity_backlink_update(&module->inc[i].submodule->ident[j],
5024 module->inc[i].submodule->ident[j].base[k]);
5025 }
5026 }
5027 }
5028
5029 LY_TREE_FOR(module->data, root) {
5030 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
5031 LY_TREE_DFS_BEGIN(root, next, node) {
5032 if (node->nodetype == LYS_GROUPING) {
5033 goto nextsibling;
5034 }
5035 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
5036 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
5037 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
5038 UNRES_TYPE_LEAFREF, node) == -1) {
5039 return -1;
5040 }
5041 }
5042 }
5043
5044 /* modified LY_TREE_DFS_END */
5045 next = node->child;
5046 /* child exception for leafs, leaflists and anyxml without children */
5047 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
5048 next = NULL;
5049 }
5050 if (!next) {
5051 nextsibling:
5052 /* no children */
5053 if (node == root) {
5054 /* we are done, root has no children */
5055 break;
5056 }
5057 /* try siblings */
5058 next = node->next;
5059 }
5060 while (!next) {
5061 /* parent is already processed, go to its sibling */
5062 node = lys_parent(node);
5063 /* no siblings, go back through parents */
5064 if (lys_parent(node) == lys_parent(root)) {
5065 /* we are done, no next element to process */
5066 break;
5067 }
5068 next = node->next;
5069 }
5070 }
5071 }
5072
5073 return EXIT_SUCCESS;
5074 }
5075
5076 API int
lys_set_implemented(const struct lys_module * module)5077 lys_set_implemented(const struct lys_module *module)
5078 {
5079 FUN_IN;
5080
5081 struct unres_schema *unres;
5082 int disabled = 0;
5083
5084 if (!module) {
5085 LOGARG;
5086 return EXIT_FAILURE;
5087 }
5088
5089 module = lys_main_module(module);
5090
5091 if (module->disabled) {
5092 disabled = 1;
5093 lys_set_enabled(module);
5094 }
5095
5096 if (module->implemented) {
5097 return EXIT_SUCCESS;
5098 }
5099
5100 unres = calloc(1, sizeof *unres);
5101 if (!unres) {
5102 LOGMEM(module->ctx);
5103 if (disabled) {
5104 /* set it back disabled */
5105 lys_set_disabled(module);
5106 }
5107 return EXIT_FAILURE;
5108 }
5109 /* recursively make the module implemented */
5110 ((struct lys_module *)module)->implemented = 1;
5111 if (lys_make_implemented_r((struct lys_module *)module, unres)) {
5112 goto error;
5113 }
5114
5115 /* try again resolve augments in other modules possibly augmenting this one,
5116 * since we have just enabled it
5117 */
5118 /* resolve rest of unres items */
5119 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
5120 goto error;
5121 }
5122 unres_schema_free(NULL, &unres, 0);
5123
5124 LOGVRB("Module \"%s%s%s\" now implemented.", module->name, (module->rev_size ? "@" : ""),
5125 (module->rev_size ? module->rev[0].date : ""));
5126 return EXIT_SUCCESS;
5127
5128 error:
5129 if (disabled) {
5130 /* set it back disabled */
5131 lys_set_disabled(module);
5132 }
5133
5134 ((struct lys_module *)module)->implemented = 0;
5135 unres_schema_free((struct lys_module *)module, &unres, 1);
5136 return EXIT_FAILURE;
5137 }
5138
5139 void
lys_submodule_module_data_free(struct lys_submodule * submodule)5140 lys_submodule_module_data_free(struct lys_submodule *submodule)
5141 {
5142 struct lys_node *next, *elem;
5143
5144 /* remove parsed data */
5145 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
5146 if (elem->module == (struct lys_module *)submodule) {
5147 lys_node_free(submodule->ctx, elem, NULL, 0);
5148 }
5149 }
5150 }
5151
5152 API char *
lys_path(const struct lys_node * node,int options)5153 lys_path(const struct lys_node *node, int options)
5154 {
5155 FUN_IN;
5156
5157 char *buf = NULL;
5158
5159 if (!node) {
5160 LOGARG;
5161 return NULL;
5162 }
5163
5164 if (ly_vlog_build_path(LY_VLOG_LYS, node, &buf, (options & LYS_PATH_FIRST_PREFIX) ? 0 : 1, 0)) {
5165 return NULL;
5166 }
5167
5168 return buf;
5169 }
5170
5171 API char *
lys_data_path(const struct lys_node * node)5172 lys_data_path(const struct lys_node *node)
5173 {
5174 FUN_IN;
5175
5176 char *result = NULL, buf[1024];
5177 const char *separator, *name;
5178 int i, used;
5179 struct ly_set *set;
5180 const struct lys_module *prev_mod;
5181
5182 if (!node) {
5183 LOGARG;
5184 return NULL;
5185 }
5186
5187 buf[0] = '\0';
5188 set = ly_set_new();
5189 LY_CHECK_ERR_GOTO(!set, LOGMEM(node->module->ctx), cleanup);
5190
5191 while (node) {
5192 ly_set_add(set, (void *)node, 0);
5193 do {
5194 node = lys_parent(node);
5195 } while (node && (node->nodetype & (LYS_USES | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
5196 }
5197
5198 prev_mod = NULL;
5199 used = 0;
5200 for (i = set->number - 1; i > -1; --i) {
5201 node = set->set.s[i];
5202 if (node->nodetype == LYS_EXT) {
5203 if (strcmp(((struct lys_ext_instance *)node)->def->name, "yang-data")) {
5204 continue;
5205 }
5206 name = ((struct lys_ext_instance *)node)->arg_value;
5207 separator = ":#";
5208 } else {
5209 name = node->name;
5210 separator = ":";
5211 }
5212 used += sprintf(buf + used, "/%s%s%s", (lys_node_module(node) == prev_mod ? "" : lys_node_module(node)->name),
5213 (lys_node_module(node) == prev_mod ? "" : separator), name);
5214 prev_mod = lys_node_module(node);
5215 }
5216
5217 result = strdup(buf);
5218 LY_CHECK_ERR_GOTO(!result, LOGMEM(node->module->ctx), cleanup);
5219
5220 cleanup:
5221 ly_set_free(set);
5222 return result;
5223 }
5224
5225 API char *
lys_data_path_pattern(const struct lys_node * node,const char * placeholder)5226 lys_data_path_pattern(const struct lys_node *node, const char *placeholder)
5227 {
5228 FUN_IN;
5229
5230 const struct lys_module *prev_mod, *mod;
5231 char *result = NULL, keys[512], buf[2048];
5232 const char *name, *separator;
5233 struct ly_set *set;
5234 size_t x;
5235 int i;
5236
5237 if (!node || !placeholder) {
5238 LOGARG;
5239 return NULL;
5240 }
5241
5242 buf[0] = '\0';
5243 set = ly_set_new();
5244 LY_CHECK_ERR_GOTO(!set, LOGMEM(node->module->ctx), cleanup);
5245
5246 /* collect all schema nodes that can be instantiated into a set */
5247 while (node) {
5248 ly_set_add(set, (void *)node, 0);
5249 do {
5250 node = lys_parent(node);
5251 } while (node && (node->nodetype & (LYS_USES | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
5252 }
5253
5254 x = 0;
5255 prev_mod = NULL;
5256
5257 /* build path for all the collected nodes */
5258 for (i = set->number - 1; i > -1; --i) {
5259 size_t k = 0;
5260 keys[0] = '\0';
5261 node = set->set.s[i];
5262 if (node->nodetype == LYS_EXT) {
5263 if (strcmp(((struct lys_ext_instance *)node)->def->name, "yang-data")) {
5264 continue;
5265 }
5266 name = ((struct lys_ext_instance *)node)->arg_value;
5267 separator = ":#";
5268 } else {
5269 name = node->name;
5270 separator = ":";
5271 }
5272 if (node->nodetype == LYS_LIST) {
5273 /* add specific key values (placeholders) for list */
5274 const struct lys_node_list *list;
5275 uint8_t j;
5276 list = (const struct lys_node_list *)node;
5277 for (j = 0; j < list->keys_size; j++) {
5278 k += sprintf(keys + k, "[%s=%s]", list->keys[j]->name, placeholder);
5279 }
5280 }
5281 mod = lys_node_module(node);
5282 if (mod && mod != prev_mod) {
5283 prev_mod = mod;
5284 x += sprintf(buf + x, "/%s%s%s%s", mod->name, separator, name, keys);
5285 } else {
5286 x += sprintf(buf + x, "/%s%s", name, keys);
5287 }
5288 }
5289
5290 result = strdup(buf);
5291 LY_CHECK_ERR_GOTO(!result, LOGMEM(node->module->ctx), cleanup);
5292
5293 cleanup:
5294 ly_set_free(set);
5295 return result;
5296 }
5297
5298 struct lys_node_augment *
lys_getnext_target_aug(struct lys_node_augment * last,const struct lys_module * mod,const struct lys_node * aug_target)5299 lys_getnext_target_aug(struct lys_node_augment *last, const struct lys_module *mod, const struct lys_node *aug_target)
5300 {
5301 struct lys_node *child;
5302 struct lys_node_augment *aug;
5303 int i, j, last_found;
5304
5305 assert(mod && aug_target);
5306
5307 if (!last) {
5308 last_found = 1;
5309 } else {
5310 last_found = 0;
5311 }
5312
5313 /* search module augments */
5314 for (i = 0; i < mod->augment_size; ++i) {
5315 if (!mod->augment[i].target) {
5316 /* still unresolved, skip */
5317 continue;
5318 }
5319
5320 if (mod->augment[i].target == aug_target) {
5321 if (last_found) {
5322 /* next match after last */
5323 return &mod->augment[i];
5324 }
5325
5326 if (&mod->augment[i] == last) {
5327 last_found = 1;
5328 }
5329 }
5330 }
5331
5332 /* search submodule augments */
5333 for (i = 0; i < mod->inc_size; ++i) {
5334 for (j = 0; j < mod->inc[i].submodule->augment_size; ++j) {
5335 if (!mod->inc[i].submodule->augment[j].target) {
5336 continue;
5337 }
5338
5339 if (mod->inc[i].submodule->augment[j].target == aug_target) {
5340 if (last_found) {
5341 /* next match after last */
5342 return &mod->inc[i].submodule->augment[j];
5343 }
5344
5345 if (&mod->inc[i].submodule->augment[j] == last) {
5346 last_found = 1;
5347 }
5348 }
5349 }
5350 }
5351
5352 /* we also need to check possible augments to choices */
5353 LY_TREE_FOR(aug_target->child, child) {
5354 if (child->nodetype == LYS_CHOICE) {
5355 aug = lys_getnext_target_aug(last, mod, child);
5356 if (aug) {
5357 return aug;
5358 }
5359 }
5360 }
5361
5362 return NULL;
5363 }
5364
5365 API struct ly_set *
lys_find_path(const struct lys_module * cur_module,const struct lys_node * cur_node,const char * path)5366 lys_find_path(const struct lys_module *cur_module, const struct lys_node *cur_node, const char *path)
5367 {
5368 FUN_IN;
5369
5370 struct ly_set *ret;
5371 int rc;
5372
5373 if ((!cur_module && !cur_node) || !path) {
5374 return NULL;
5375 }
5376
5377 rc = resolve_schema_nodeid(path, cur_node, cur_module, &ret, 1, 1);
5378 if (rc == -1) {
5379 return NULL;
5380 }
5381
5382 return ret;
5383 }
5384
5385 static void
lys_extcomplex_free_str(struct ly_ctx * ctx,struct lys_ext_instance_complex * ext,LY_STMT stmt)5386 lys_extcomplex_free_str(struct ly_ctx *ctx, struct lys_ext_instance_complex *ext, LY_STMT stmt)
5387 {
5388 struct lyext_substmt *info;
5389 const char **str, ***a;
5390 int c;
5391
5392 str = lys_ext_complex_get_substmt(stmt, ext, &info);
5393 if (!str || !(*str)) {
5394 return;
5395 }
5396 if (info->cardinality >= LY_STMT_CARD_SOME) {
5397 /* we have array */
5398 a = (const char ***)str;
5399 for (str = (*(const char ***)str), c = 0; str[c]; c++) {
5400 lydict_remove(ctx, str[c]);
5401 }
5402 free(a[0]);
5403 if (stmt == LY_STMT_BELONGSTO) {
5404 for (str = a[1], c = 0; str[c]; c++) {
5405 lydict_remove(ctx, str[c]);
5406 }
5407 free(a[1]);
5408 } else if (stmt == LY_STMT_ARGUMENT) {
5409 free(a[1]);
5410 }
5411 } else {
5412 lydict_remove(ctx, str[0]);
5413 if (stmt == LY_STMT_BELONGSTO) {
5414 lydict_remove(ctx, str[1]);
5415 }
5416 }
5417 }
5418
5419 void
lys_extension_instances_free(struct ly_ctx * ctx,struct lys_ext_instance ** e,unsigned int size,void (* private_destructor)(const struct lys_node * node,void * priv))5420 lys_extension_instances_free(struct ly_ctx *ctx, struct lys_ext_instance **e, unsigned int size,
5421 void (*private_destructor)(const struct lys_node *node, void *priv))
5422 {
5423 unsigned int i, j, k;
5424 struct lyext_substmt *substmt;
5425 void **pp, **start;
5426 struct lys_node *siter, *snext;
5427
5428 #define EXTCOMPLEX_FREE_STRUCT(STMT, TYPE, FUNC, FREE, ARGS...) \
5429 pp = lys_ext_complex_get_substmt(STMT, (struct lys_ext_instance_complex *)e[i], NULL); \
5430 if (!pp || !(*pp)) { break; } \
5431 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */ \
5432 for (start = pp = *pp; *pp; pp++) { \
5433 FUNC(ctx, (TYPE *)(*pp), ##ARGS, private_destructor); \
5434 if (FREE) { free(*pp); } \
5435 } \
5436 free(start); \
5437 } else { /* single item */ \
5438 FUNC(ctx, (TYPE *)(*pp), ##ARGS, private_destructor); \
5439 if (FREE) { free(*pp); } \
5440 }
5441
5442 if (!size || !e) {
5443 return;
5444 }
5445
5446 for (i = 0; i < size; i++) {
5447 if (!e[i]) {
5448 continue;
5449 }
5450
5451 if (e[i]->flags & (LYEXT_OPT_INHERIT)) {
5452 /* no free, this is just a shadow copy of the original extension instance */
5453 } else {
5454 if (e[i]->flags & (LYEXT_OPT_YANG)) {
5455 free(e[i]->def); /* remove name of instance extension */
5456 e[i]->def = NULL;
5457 yang_free_ext_data((struct yang_ext_substmt *)e[i]->parent); /* remove backup part of yang file */
5458 }
5459 /* remove private object */
5460 if (e[i]->priv && private_destructor) {
5461 private_destructor((struct lys_node*)e[i], e[i]->priv);
5462 }
5463 lys_extension_instances_free(ctx, e[i]->ext, e[i]->ext_size, private_destructor);
5464 lydict_remove(ctx, e[i]->arg_value);
5465 }
5466
5467 if (e[i]->def && e[i]->def->plugin && e[i]->def->plugin->type == LYEXT_COMPLEX
5468 && ((e[i]->flags & LYEXT_OPT_CONTENT) == 0)) {
5469 substmt = ((struct lys_ext_instance_complex *)e[i])->substmt;
5470 for (j = 0; substmt[j].stmt; j++) {
5471 switch(substmt[j].stmt) {
5472 case LY_STMT_DESCRIPTION:
5473 case LY_STMT_REFERENCE:
5474 case LY_STMT_UNITS:
5475 case LY_STMT_ARGUMENT:
5476 case LY_STMT_DEFAULT:
5477 case LY_STMT_ERRTAG:
5478 case LY_STMT_ERRMSG:
5479 case LY_STMT_PREFIX:
5480 case LY_STMT_NAMESPACE:
5481 case LY_STMT_PRESENCE:
5482 case LY_STMT_REVISIONDATE:
5483 case LY_STMT_KEY:
5484 case LY_STMT_BASE:
5485 case LY_STMT_BELONGSTO:
5486 case LY_STMT_CONTACT:
5487 case LY_STMT_ORGANIZATION:
5488 case LY_STMT_PATH:
5489 lys_extcomplex_free_str(ctx, (struct lys_ext_instance_complex *)e[i], substmt[j].stmt);
5490 break;
5491 case LY_STMT_TYPE:
5492 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPE, struct lys_type, lys_type_free, 1);
5493 break;
5494 case LY_STMT_TYPEDEF:
5495 EXTCOMPLEX_FREE_STRUCT(LY_STMT_TYPEDEF, struct lys_tpdf, lys_tpdf_free, 1);
5496 break;
5497 case LY_STMT_IFFEATURE:
5498 EXTCOMPLEX_FREE_STRUCT(LY_STMT_IFFEATURE, struct lys_iffeature, lys_iffeature_free, 0, 1, 0);
5499 break;
5500 case LY_STMT_MAX:
5501 case LY_STMT_MIN:
5502 case LY_STMT_POSITION:
5503 case LY_STMT_VALUE:
5504 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5505 if (substmt[j].cardinality >= LY_STMT_CARD_SOME && *pp) {
5506 for(k = 0; ((uint32_t**)(*pp))[k]; k++) {
5507 free(((uint32_t**)(*pp))[k]);
5508 }
5509 }
5510 free(*pp);
5511 break;
5512 case LY_STMT_DIGITS:
5513 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
5514 /* free the array */
5515 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5516 free(*pp);
5517 }
5518 break;
5519 case LY_STMT_MODULE:
5520 /* modules are part of the context, so they will be freed there */
5521 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) {
5522 /* free the array */
5523 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5524 free(*pp);
5525 }
5526 break;
5527 case LY_STMT_ACTION:
5528 case LY_STMT_ANYDATA:
5529 case LY_STMT_ANYXML:
5530 case LY_STMT_CASE:
5531 case LY_STMT_CHOICE:
5532 case LY_STMT_CONTAINER:
5533 case LY_STMT_GROUPING:
5534 case LY_STMT_INPUT:
5535 case LY_STMT_LEAF:
5536 case LY_STMT_LEAFLIST:
5537 case LY_STMT_LIST:
5538 case LY_STMT_NOTIFICATION:
5539 case LY_STMT_OUTPUT:
5540 case LY_STMT_RPC:
5541 case LY_STMT_USES:
5542 pp = (void**)&((struct lys_ext_instance_complex *)e[i])->content[substmt[j].offset];
5543 LY_TREE_FOR_SAFE((struct lys_node *)(*pp), snext, siter) {
5544 lys_node_free(ctx, siter, NULL, 0);
5545 }
5546 *pp = NULL;
5547 break;
5548 case LY_STMT_UNIQUE:
5549 pp = lys_ext_complex_get_substmt(LY_STMT_UNIQUE, (struct lys_ext_instance_complex *)e[i], NULL);
5550 if (!pp || !(*pp)) {
5551 break;
5552 }
5553 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
5554 for (start = pp = *pp; *pp; pp++) {
5555 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
5556 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
5557 }
5558 free((*(struct lys_unique**)pp)->expr);
5559 free(*pp);
5560 }
5561 free(start);
5562 } else { /* single item */
5563 for (k = 0; k < (*(struct lys_unique**)pp)->expr_size; k++) {
5564 lydict_remove(ctx, (*(struct lys_unique**)pp)->expr[k]);
5565 }
5566 free((*(struct lys_unique**)pp)->expr);
5567 free(*pp);
5568 }
5569 break;
5570 case LY_STMT_LENGTH:
5571 case LY_STMT_MUST:
5572 case LY_STMT_PATTERN:
5573 case LY_STMT_RANGE:
5574 EXTCOMPLEX_FREE_STRUCT(substmt[j].stmt, struct lys_restr, lys_restr_free, 1);
5575 break;
5576 case LY_STMT_WHEN:
5577 EXTCOMPLEX_FREE_STRUCT(LY_STMT_WHEN, struct lys_when, lys_when_free, 0);
5578 break;
5579 case LY_STMT_REVISION:
5580 pp = lys_ext_complex_get_substmt(LY_STMT_REVISION, (struct lys_ext_instance_complex *)e[i], NULL);
5581 if (!pp || !(*pp)) {
5582 break;
5583 }
5584 if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
5585 for (start = pp = *pp; *pp; pp++) {
5586 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
5587 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
5588 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
5589 (*(struct lys_revision**)pp)->ext_size, private_destructor);
5590 free(*pp);
5591 }
5592 free(start);
5593 } else { /* single item */
5594 lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
5595 lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
5596 lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
5597 (*(struct lys_revision**)pp)->ext_size, private_destructor);
5598 free(*pp);
5599 }
5600 break;
5601 default:
5602 /* nothing to free */
5603 break;
5604 }
5605 }
5606 }
5607
5608 free(e[i]);
5609 }
5610 free(e);
5611
5612 #undef EXTCOMPLEX_FREE_STRUCT
5613 }
5614