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, &notif->must[i], private_destructor);
2552     }
2553     free(notif->must);
2554 
2555     for (i = 0; i < notif->tpdf_size; i++) {
2556         lys_tpdf_free(ctx, &notif->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