1 /**
2  * @file tree_data.c
3  * @author Radek Krejci <rkrejci@cesnet.cz>
4  * @brief Manipulation with libyang 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 #include <assert.h>
18 #include <ctype.h>
19 #include <limits.h>
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <sys/mman.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <errno.h>
29 
30 #include "libyang.h"
31 #include "common.h"
32 #include "context.h"
33 #include "tree_data.h"
34 #include "parser.h"
35 #include "resolve.h"
36 #include "xml_internal.h"
37 #include "tree_internal.h"
38 #include "validation.h"
39 #include "xpath.h"
40 
41 static struct lys_node *lyd_get_schema_inctx(const struct lyd_node *node, struct ly_ctx *ctx);
42 
43 static struct lyd_node *lyd_dup_withsiblings_to_ctx(const struct lyd_node *node, int options, struct ly_ctx *ctx);
44 
45 static struct lyd_node *lyd_new_dummy(struct lyd_node *root, struct lyd_node *parent, const struct lys_node *schema,
46                                       const char *value, int dflt);
47 
48 static int
lyd_anydata_equal(struct lyd_node * first,struct lyd_node * second)49 lyd_anydata_equal(struct lyd_node *first, struct lyd_node *second)
50 {
51     char *str1 = NULL, *str2 = NULL;
52     struct lyd_node_anydata *anydata;
53 
54     assert(first->schema->nodetype & LYS_ANYDATA);
55     assert(first->schema->nodetype == second->schema->nodetype);
56 
57     anydata = (struct lyd_node_anydata *)first;
58     if (!anydata->value.str) {
59         lyxml_print_mem(&str1, anydata->value.xml, LYXML_PRINT_SIBLINGS);
60         anydata->value.str = lydict_insert_zc(anydata->schema->module->ctx, str1);
61     }
62     str1 = (char *)anydata->value.str;
63 
64     anydata = (struct lyd_node_anydata *)second;
65     if (!anydata->value.str) {
66         lyxml_print_mem(&str2, anydata->value.xml, LYXML_PRINT_SIBLINGS);
67         anydata->value.str = lydict_insert_zc(anydata->schema->module->ctx, str2);
68     }
69     str2 = (char *)anydata->value.str;
70 
71     if (first->schema->module->ctx != second->schema->module->ctx) {
72         return ly_strequal(str1, str2, 0);
73     } else {
74         return ly_strequal(str1, str2, 1);
75     }
76 }
77 
78 /* used in tests */
79 int
lyd_list_has_keys(struct lyd_node * list)80 lyd_list_has_keys(struct lyd_node *list)
81 {
82     struct lyd_node *iter;
83     struct lys_node_list *slist;
84     int i;
85 
86     assert(list->schema->nodetype == LYS_LIST);
87 
88     /* even though hash is 0, it may be a valid hash, that is what we are going to check */
89 
90     slist = (struct lys_node_list *)list->schema;
91     if (!slist->keys_size) {
92         /* always has keys */
93         return 1;
94     }
95 
96     i = 0;
97     iter = list->child;
98     while (iter && (i < slist->keys_size)) {
99         if (iter->schema != (struct lys_node *)slist->keys[i]) {
100             /* missing key */
101             return 0;
102         }
103 
104         ++i;
105         iter = iter->next;
106     }
107     if (i < slist->keys_size) {
108         /* missing key */
109         return 0;
110     }
111 
112     /* all keys found */
113     return 1;
114 }
115 
116 static int
lyd_leaf_val_equal(struct lyd_node * node1,struct lyd_node * node2,int diff_ctx)117 lyd_leaf_val_equal(struct lyd_node *node1, struct lyd_node *node2, int diff_ctx)
118 {
119     assert(node1->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST));
120     assert(node1->schema->nodetype == node2->schema->nodetype);
121 
122     if (diff_ctx) {
123         return ly_strequal(((struct lyd_node_leaf_list *)node1)->value_str, ((struct lyd_node_leaf_list *)node2)->value_str, 0);
124     } else {
125         return ly_strequal(((struct lyd_node_leaf_list *)node1)->value_str, ((struct lyd_node_leaf_list *)node2)->value_str, 1);
126     }
127 }
128 
129 /*
130  * withdefaults (only for leaf-list):
131  * 0 - treat default nodes are normal nodes
132  * 1 - only change is that if 2 nodes have the same value, but one is default, the other not, they are considered non-equal
133  */
134 int
lyd_list_equal(struct lyd_node * node1,struct lyd_node * node2,int with_defaults)135 lyd_list_equal(struct lyd_node *node1, struct lyd_node *node2, int with_defaults)
136 {
137     int i, diff_ctx;
138     struct lyd_node *elem1, *next1, *elem2, *next2;
139     struct lys_node *elem1_sch;
140     struct ly_ctx *ctx = node2->schema->module->ctx;
141 
142     diff_ctx = (node1->schema->module->ctx != node2->schema->module->ctx);
143 
144     switch (node2->schema->nodetype) {
145     case LYS_LEAFLIST:
146         if (lyd_leaf_val_equal(node1, node2, diff_ctx) && (!with_defaults || (node1->dflt == node2->dflt))) {
147             return 1;
148         }
149         break;
150     case LYS_LIST:
151         if (((struct lys_node_list *)node1->schema)->keys_size) {
152             /* lists with keys, their equivalence is based on their keys */
153             elem1 = node1->child;
154             elem2 = node2->child;
155             elem1_sch = NULL;
156             /* the exact data order is guaranteed */
157             for (i = 0; i < ((struct lys_node_list *)node1->schema)->keys_size; ++i) {
158                 if (diff_ctx && elem1) {
159                     /* we have different contexts */
160                     if (!elem1_sch) {
161                         elem1_sch = lyd_get_schema_inctx(elem1, ctx);
162                         if (!elem1_sch) {
163                             LOGERR(ctx, LY_EINVAL, "Target context does not contain a required schema node (%s:%s).",
164                                    lyd_node_module(elem1)->name, elem1->schema->name);
165                             return -1;
166                         }
167                     } else {
168                         /* just move to the next schema node */
169                         elem1_sch = elem1_sch->next;
170                     }
171                 }
172                 if (!elem1 || !elem2 || ((elem1_sch ? elem1_sch : elem1->schema) != elem2->schema)
173                         || !lyd_leaf_val_equal(elem1, elem2, diff_ctx)) {
174                     break;
175                 }
176                 elem1 = elem1->next;
177                 elem2 = elem2->next;
178             }
179             if (i == ((struct lys_node_list *)node1->schema)->keys_size) {
180                 return 1;
181             }
182         } else {
183             /* lists wihtout keys, their equivalence is based on values of all the children (both direct and indirect) */
184             if (!node1->child && !node2->child) {
185                 /* no children, nothing to compare */
186                 return 1;
187             }
188 
189             /* status lists without keys, we need to compare all the children :( */
190 
191             /* LY_TREE_DFS_BEGIN for 2 data trees */
192             elem1 = next1 = node1->child;
193             elem2 = next2 = node2->child;
194             while (elem1 && elem2) {
195                 /* node comparison */
196 #ifdef LY_ENABLED_CACHE
197                 if (elem1->hash != elem2->hash) {
198                     break;
199                 }
200 #endif
201                 if (diff_ctx) {
202                     elem1_sch = lyd_get_schema_inctx(elem1, ctx);
203                     if (!elem1_sch) {
204                         LOGERR(ctx, LY_EINVAL, "Target context does not contain a required schema node (%s:%s).",
205                                lyd_node_module(elem1)->name, elem1->schema->name);
206                         return -1;
207                     }
208                 } else {
209                     elem1_sch = elem1->schema;
210                 }
211                 if (elem1_sch != elem2->schema) {
212                     break;
213                 }
214                 if (elem2->schema->nodetype == LYS_LIST) {
215                     if (!lyd_list_has_keys(elem1) && !lyd_list_has_keys(elem2)) {
216                         /* we encountered lists without keys (but have some defined in schema), ignore them for comparison */
217                         next1 = NULL;
218                         next2 = NULL;
219                         goto next_sibling;
220                     }
221                     /* we will compare all the children of this list instance, not just keys */
222                 } else if (elem2->schema->nodetype & (LYS_LEAFLIST | LYS_LEAF)) {
223                     if (!lyd_leaf_val_equal(elem1, elem2, diff_ctx) && (!with_defaults || (elem1->dflt == elem2->dflt))) {
224                         break;
225                     }
226                 } else if (elem2->schema->nodetype & LYS_ANYDATA) {
227                     if (!lyd_anydata_equal(elem1, elem2)) {
228                         break;
229                     }
230                 }
231 
232                 /* LY_TREE_DFS_END for 2 data trees */
233                 if (elem2->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
234                     next1 = NULL;
235                     next2 = NULL;
236                 } else {
237                     next1 = elem1->child;
238                     next2 = elem2->child;
239                 }
240 
241 next_sibling:
242                 if (!next1) {
243                     next1 = elem1->next;
244                 }
245                 if (!next2) {
246                     next2 = elem2->next;
247                 }
248 
249                 while (!next1) {
250                     elem1 = elem1->parent;
251                     if (elem1 == node1) {
252                         break;
253                     }
254                     next1 = elem1->next;
255                 }
256                 while (!next2) {
257                     elem2 = elem2->parent;
258                     if (elem2 == node2) {
259                         break;
260                     }
261                     next2 = elem2->next;
262                 }
263 
264                 elem1 = next1;
265                 elem2 = next2;
266             }
267 
268             if (!elem1 && !elem2) {
269                 /* all children were successfully compared */
270                 return 1;
271             }
272         }
273         break;
274     default:
275         LOGINT(ctx);
276         return -1;
277     }
278 
279     return 0;
280 }
281 
282 #ifdef LY_ENABLED_CACHE
283 
284 static int
lyd_hash_table_val_equal(void * val1_p,void * val2_p,int mod,void * UNUSED (cb_data))285 lyd_hash_table_val_equal(void *val1_p, void *val2_p, int mod, void *UNUSED(cb_data))
286 {
287     struct lyd_node *val1, *val2;
288 
289     val1 = *((struct lyd_node **)val1_p);
290     val2 = *((struct lyd_node **)val2_p);
291 
292     if (mod) {
293         if (val1 == val2) {
294             return 1;
295         } else {
296             return 0;
297         }
298     }
299 
300     if (val1->schema != val2->schema) {
301         return 0;
302     }
303 
304     switch (val1->schema->nodetype) {
305     case LYS_CONTAINER:
306     case LYS_LEAF:
307     case LYS_ANYXML:
308     case LYS_ANYDATA:
309         return 1;
310     case LYS_LEAFLIST:
311     case LYS_LIST:
312         return lyd_list_equal(val1, val2, 0);
313     default:
314         break;
315     }
316 
317     LOGINT(val1->schema->module->ctx);
318     return 0;
319 }
320 
321 static void
lyd_hash_keyless_list_dfs(struct lyd_node * child,uint32_t * hash)322 lyd_hash_keyless_list_dfs(struct lyd_node *child, uint32_t *hash)
323 {
324     LY_TREE_FOR(child, child) {
325         switch (child->schema->nodetype) {
326         case LYS_CONTAINER:
327             lyd_hash_keyless_list_dfs(child->child, hash);
328             break;
329         case LYS_LIST:
330             /* ignore lists with missing keys */
331             if (lyd_list_has_keys(child)) {
332                 lyd_hash_keyless_list_dfs(child->child, hash);
333             }
334             break;
335         case LYS_LEAFLIST:
336         case LYS_ANYXML:
337         case LYS_ANYDATA:
338         case LYS_LEAF:
339             *hash = dict_hash_multi(*hash, (char *)&child->hash, sizeof child->hash);
340             break;
341         default:
342             assert(0);
343         }
344     }
345 }
346 
347 int
lyd_hash(struct lyd_node * node)348 lyd_hash(struct lyd_node *node)
349 {
350     struct lyd_node *iter;
351     int i;
352 
353     if ((node->schema->nodetype != LYS_LIST) || lyd_list_has_keys(node)) {
354         node->hash = dict_hash_multi(0, lyd_node_module(node)->name, strlen(lyd_node_module(node)->name));
355         node->hash = dict_hash_multi(node->hash, node->schema->name, strlen(node->schema->name));
356         if (node->schema->nodetype == LYS_LEAFLIST) {
357             node->hash = dict_hash_multi(node->hash, ((struct lyd_node_leaf_list *)node)->value_str,
358                                         strlen(((struct lyd_node_leaf_list *)node)->value_str));
359         } else if (node->schema->nodetype == LYS_LIST) {
360             if (((struct lys_node_list *)node->schema)->keys_size) {
361                 for (i = 0, iter = node->child; i < ((struct lys_node_list *)node->schema)->keys_size; ++i, iter = iter->next) {
362                     assert(iter);
363                     node->hash = dict_hash_multi(node->hash, ((struct lyd_node_leaf_list *)iter)->value_str,
364                                                  strlen(((struct lyd_node_leaf_list *)iter)->value_str));
365                 }
366             } else {
367                 /* no-keys list */
368                 lyd_hash_keyless_list_dfs(node->child, &node->hash);
369             }
370         }
371         node->hash = dict_hash_multi(node->hash, NULL, 0);
372         return 0;
373     }
374 
375     return 1;
376 }
377 
378 static void
lyd_keyless_list_hash_change(struct lyd_node * parent)379 lyd_keyless_list_hash_change(struct lyd_node *parent)
380 {
381     int r;
382 
383     while (parent && !(parent->schema->flags & LYS_CONFIG_W)) {
384         if (parent->schema->nodetype == LYS_LIST) {
385             if (parent->hash && !((struct lys_node_list *)parent->schema)->keys_size) {
386                 if (parent->parent && parent->parent->ht) {
387                     /* remove the list from the parent */
388                     r = lyht_remove(parent->parent->ht, &parent, parent->hash);
389                     assert(!r);
390                     (void)r;
391                 }
392                 /* recalculate the hash */
393                 lyd_hash(parent);
394                 if (parent->parent && parent->parent->ht) {
395                     /* re-add the list again */
396                     r = lyht_insert(parent->parent->ht, &parent, parent->hash, NULL);
397                     assert(!r);
398                     (void)r;
399                 }
400             } else if (!lyd_list_has_keys(parent)) {
401                 /* a parent is a list without keys so it cannot be a part of any parent hash */
402                 break;
403             }
404         }
405 
406         parent = parent->parent;
407     }
408 }
409 
410 static void
_lyd_insert_hash(struct lyd_node * node,int keyless_list_check)411 _lyd_insert_hash(struct lyd_node *node, int keyless_list_check)
412 {
413     struct lyd_node *iter;
414     int i;
415 
416     if (node->parent) {
417         if ((node->schema->nodetype != LYS_LIST) || lyd_list_has_keys(node)) {
418             if ((node->schema->nodetype == LYS_LEAF) && lys_is_key((struct lys_node_leaf *)node->schema, NULL)) {
419                 /* we are adding a key which means that it may be the last missing key for our parent's hash */
420                 if (!lyd_hash(node->parent)) {
421                     /* yep, we successfully hashed node->parent so it is technically now added to its parent (hash-wise) */
422                     _lyd_insert_hash(node->parent, 0);
423                 }
424             }
425 
426             /* create parent hash table if required, otherwise just add the new child */
427             if (!node->parent->ht) {
428                 for (i = 0, iter = node->parent->child; iter; ++i, iter = iter->next) {
429                     if ((iter->schema->nodetype == LYS_LIST) && !lyd_list_has_keys(iter)) {
430                         /* it will either never have keys and will never be hashed or has not all keys created yet */
431                         --i;
432                     }
433                 }
434                 assert(i <= LY_CACHE_HT_MIN_CHILDREN);
435                 if (i == LY_CACHE_HT_MIN_CHILDREN) {
436                     /* create hash table, insert all the children */
437                     node->parent->ht = lyht_new(1, sizeof(struct lyd_node *), lyd_hash_table_val_equal, NULL, 1);
438                     LY_TREE_FOR(node->parent->child, iter) {
439                         if ((iter->schema->nodetype == LYS_LIST) && !lyd_list_has_keys(iter)) {
440                             /* skip lists without keys */
441                             continue;
442                         }
443 
444                         if (lyht_insert(node->parent->ht, &iter, iter->hash, NULL)) {
445                             assert(0);
446                         }
447                     }
448                 }
449             } else {
450                 if (lyht_insert(node->parent->ht, &node, node->hash, NULL)) {
451                     assert(0);
452                 }
453             }
454 
455             /* if node was in a state data subtree, wasn't it a part of a key-less list hash? */
456             if (keyless_list_check) {
457                 lyd_keyless_list_hash_change(node->parent);
458             }
459         }
460     }
461 }
462 
463 /* we have inserted node into a parent */
464 void
lyd_insert_hash(struct lyd_node * node)465 lyd_insert_hash(struct lyd_node *node)
466 {
467     _lyd_insert_hash(node, 1);
468 }
469 
470 static void
_lyd_unlink_hash(struct lyd_node * node,struct lyd_node * orig_parent,int keyless_list_check)471 _lyd_unlink_hash(struct lyd_node *node, struct lyd_node *orig_parent, int keyless_list_check)
472 {
473 #ifndef NDEBUG
474     struct lyd_node *iter;
475 
476     /* it must already be unlinked otherwise keyless lists would get wrong hash */
477     if (keyless_list_check && orig_parent) {
478         LY_TREE_FOR(orig_parent->child, iter) {
479             assert(iter != node);
480         }
481     }
482 #endif
483 
484     if (orig_parent && node->hash && ((node->schema->nodetype != LYS_LIST) || lyd_list_has_keys(node))) {
485         if (orig_parent->ht) {
486             if (lyht_remove(orig_parent->ht, &node, node->hash)) {
487                 assert(0);
488             }
489 
490             /* if no longer enough children, free the whole hash table */
491             if (orig_parent->ht->used < LY_CACHE_HT_MIN_CHILDREN) {
492                 lyht_free(orig_parent->ht);
493                 orig_parent->ht = NULL;
494             }
495         }
496 
497         /* if the parent is missing a key now, remove hash, also from parent */
498         if (lys_is_key((struct lys_node_leaf *)node->schema, NULL) && orig_parent->hash) {
499             _lyd_unlink_hash(orig_parent, orig_parent->parent, 0);
500             orig_parent->hash = 0;
501         }
502 
503         /* if node was in a state data subtree, shouldn't it be a part of a key-less list hash? */
504         if (keyless_list_check) {
505             lyd_keyless_list_hash_change(orig_parent);
506         }
507     }
508 }
509 
510 /* we are unlinking a child from a parent */
511 void
lyd_unlink_hash(struct lyd_node * node,struct lyd_node * orig_parent)512 lyd_unlink_hash(struct lyd_node *node, struct lyd_node *orig_parent)
513 {
514     _lyd_unlink_hash(node, orig_parent, 1);
515 }
516 
517 #endif
518 
519 /**
520  * @brief get the list of \p data's siblings of the given schema
521  */
522 static int
lyd_get_node_siblings(const struct lyd_node * data,const struct lys_node * schema,struct ly_set * set)523 lyd_get_node_siblings(const struct lyd_node *data, const struct lys_node *schema, struct ly_set *set)
524 {
525     const struct lyd_node *iter;
526 
527     assert(set && !set->number);
528     assert(schema);
529     assert(schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYDATA | LYS_NOTIF | LYS_RPC |
530                                LYS_ACTION));
531 
532     if (!data) {
533         return 0;
534     }
535 
536     LY_TREE_FOR(data, iter) {
537         if (iter->schema == schema) {
538             ly_set_add(set, (void*)iter, LY_SET_OPT_USEASLIST);
539         }
540     }
541 
542     return set->number;
543 }
544 
545 /**
546  * Check whether there are any "when" statements on a \p schema node and evaluate them.
547  *
548  * @return -1 on error, 0 on no when or evaluated to true, 1 on when evaluated to false
549  */
550 static int
lyd_is_when_false(struct lyd_node * root,struct lyd_node * last_parent,struct lys_node * schema,int options)551 lyd_is_when_false(struct lyd_node *root, struct lyd_node *last_parent, struct lys_node *schema, int options)
552 {
553     enum int_log_opts prev_ilo;
554     struct lyd_node *current, *dummy;
555 
556     if ((!(options & LYD_OPT_TYPEMASK) || (options & (LYD_OPT_CONFIG | LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF | LYD_OPT_DATA_TEMPLATE)))
557             && resolve_applies_when(schema, 1, last_parent ? last_parent->schema : NULL)) {
558         /* evaluate when statements on a dummy data node */
559         if (schema->nodetype == LYS_CHOICE) {
560             schema = (struct lys_node *)lys_getnext(NULL, schema, NULL, LYS_GETNEXT_NOSTATECHECK);
561         }
562         if (!schema) {
563             /* choice has no descendant data nodes */
564             return 0;
565         }
566         dummy = lyd_new_dummy(root, last_parent, schema, NULL, 0);
567         if (!dummy) {
568             return -1;
569         }
570         if (!dummy->parent && root) {
571             /* connect dummy nodes into the data tree, insert it before the root
572              * to optimize later unlinking (lyd_free()) */
573             lyd_insert_before(root, dummy);
574         }
575         for (current = dummy; current; current = current->child) {
576             ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
577             resolve_when(current, 0, NULL);
578             ly_ilo_restore(NULL, prev_ilo, NULL, 0);
579 
580             if (current->when_status & LYD_WHEN_FALSE) {
581                 /* when evaluates to false */
582                 lyd_free(dummy);
583                 return 1;
584             }
585 
586             if (current->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
587                 /* termination node without a child */
588                 break;
589             }
590         }
591         lyd_free(dummy);
592     }
593 
594     return 0;
595 }
596 
597 /**
598  * @param[in] root Root node to be able search the data tree in case of no instance
599  * @return
600  *  0 - all restrictions met
601  *  1 - restrictions not met
602  *  2 - schema node not enabled
603  */
604 static int
lyd_check_mandatory_data(struct lyd_node * root,struct lyd_node * last_parent,struct ly_set * instances,struct lys_node * schema,int options)605 lyd_check_mandatory_data(struct lyd_node *root, struct lyd_node *last_parent,
606                          struct ly_set *instances, struct lys_node *schema, int options)
607 {
608     struct ly_ctx *ctx = schema->module->ctx;
609     uint32_t limit;
610     uint16_t status;
611 
612     if (!instances->number) {
613         /* no instance in the data tree - check if the instantiating is enabled
614          * (check: if-feature, when, status data in non-status data tree)
615          */
616         status = (schema->flags & LYS_STATUS_MASK);
617         if (lys_is_disabled(schema, 2) || (status && status != LYS_STATUS_CURR)) {
618             /* disabled by if-feature */
619             return EXIT_SUCCESS;
620         } else if ((options & LYD_OPT_TRUSTED) || ((options & LYD_OPT_TYPEMASK) && (schema->flags & LYS_CONFIG_R))) {
621             /* status schema node in non-status data tree */
622             return EXIT_SUCCESS;
623         } else if (lyd_is_when_false(root, last_parent, schema, options)) {
624             return EXIT_SUCCESS;
625         }
626         /* the schema instance is not disabled by anything, continue with checking */
627     }
628 
629     /* checking various mandatory conditions */
630     switch (schema->nodetype) {
631     case LYS_LEAF:
632     case LYS_ANYXML:
633     case LYS_ANYDATA:
634         /* mandatory */
635         if ((schema->flags & LYS_MAND_TRUE) && !instances->number) {
636             LOGVAL(ctx, LYE_MISSELEM, LY_VLOG_LYD, last_parent, schema->name,
637                    last_parent ? last_parent->schema->name : lys_node_module(schema)->name);
638             return EXIT_FAILURE;
639         }
640         break;
641     case LYS_LIST:
642         /* min-elements */
643         limit = ((struct lys_node_list *)schema)->min;
644         if (limit && limit > instances->number) {
645             LOGVAL(ctx, LYE_NOMIN, LY_VLOG_LYD, last_parent, schema->name);
646             return EXIT_FAILURE;
647         }
648         /* max elements */
649         limit = ((struct lys_node_list *)schema)->max;
650         if (limit && limit < instances->number) {
651             LOGVAL(ctx, LYE_NOMAX, LY_VLOG_LYD, instances->set.d[limit], schema->name);
652             return EXIT_FAILURE;
653         }
654 
655         break;
656 
657     case LYS_LEAFLIST:
658         /* min-elements */
659         limit = ((struct lys_node_leaflist *)schema)->min;
660         if (limit && limit > instances->number) {
661             LOGVAL(ctx, LYE_NOMIN, LY_VLOG_LYD, last_parent, schema->name);
662             return EXIT_FAILURE;
663         }
664         /* max elements */
665         limit = ((struct lys_node_leaflist *)schema)->max;
666         if (limit && limit < instances->number) {
667             LOGVAL(ctx, LYE_NOMAX, LY_VLOG_LYD, instances->set.d[limit], schema->name);
668             return EXIT_FAILURE;
669         }
670         break;
671     default:
672         /* we cannot get here */
673         assert(0);
674         break;
675     }
676 
677     return EXIT_SUCCESS;
678 }
679 
680 /**
681  * @brief Check the specific subtree, specified by \p schema node, for presence of mandatory nodes. Function goes
682  * recursively into the subtree.
683  *
684  * What is being checked:
685  * - mandatory statement in leaf, choice, anyxml and anydata
686  * - min-elements and max-elements in list and leaf-list
687  *
688  * @param[in] tree Data tree, needed for case that subtree is NULL (in case of not existing data nodes to explore)
689  * @param[in] subtree Depend ons \p toplevel flag:
690  *                 toplevel = 1, then subtree is ignored, instead the tree is taken to search in top level data elements (if any)
691  *                 toplevel = 0, subtree is the parent data node of the possible instances of the schema node being checked
692  * @param[in] last_parent The last present parent data node (so it does not need to be a direct parent) of the possible
693  *                 instances of the schema node being checked
694  * @param[in] schema The schema node being checked for mandatory nodes
695  * @param[in] toplevel, see the \p root parameter description
696  * @param[in] options @ref parseroptions to specify the type of the data tree.
697  * @return EXIT_SUCCESS or EXIT_FAILURE if there are missing mandatory nodes
698  */
699 static int
lyd_check_mandatory_subtree(struct lyd_node * tree,struct lyd_node * subtree,struct lyd_node * last_parent,struct lys_node * schema,int toplevel,int options)700 lyd_check_mandatory_subtree(struct lyd_node *tree, struct lyd_node *subtree, struct lyd_node *last_parent,
701                             struct lys_node *schema, int toplevel, int options)
702 {
703     struct lys_node *siter, *siter_prev;
704     struct lyd_node *iter;
705     struct ly_set *present = NULL;
706     unsigned int u;
707     int ret = EXIT_FAILURE;
708 
709     assert(schema);
710 
711     if (lys_is_disabled(schema, 0)) {
712         return EXIT_SUCCESS;
713     }
714 
715     if (schema->nodetype & (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYDATA | LYS_CONTAINER)) {
716         /* data node */
717         present = ly_set_new();
718         if (!present) {
719             goto error;
720         }
721         if ((toplevel && tree) || (!toplevel && subtree)) {
722             if (toplevel) {
723                 lyd_get_node_siblings(tree, schema, present);
724             } else {
725                 lyd_get_node_siblings(subtree->child, schema, present);
726             }
727         }
728     }
729 
730     switch (schema->nodetype) {
731     case LYS_LEAF:
732     case LYS_LEAFLIST:
733     case LYS_ANYXML:
734     case LYS_ANYDATA:
735         /* check the schema item */
736         if (lyd_check_mandatory_data(tree, last_parent, present, schema, options)) {
737             goto error;
738         }
739         break;
740     case LYS_LIST:
741         /* check the schema item */
742         if (lyd_check_mandatory_data(tree, last_parent, present, schema, options)) {
743             goto error;
744         }
745 
746         /* go recursively */
747         for (u = 0; u < present->number; u++) {
748             LY_TREE_FOR(schema->child, siter) {
749                 if (lyd_check_mandatory_subtree(tree, present->set.d[u], present->set.d[u], siter, 0, options)) {
750                     goto error;
751                 }
752             }
753         }
754         break;
755 
756     case LYS_CONTAINER:
757         if (present->number || !((struct lys_node_container *)schema)->presence) {
758             /* if we have existing or non-presence container, go recursively */
759             LY_TREE_FOR(schema->child, siter) {
760                 if (lyd_check_mandatory_subtree(tree, present->number ? present->set.d[0] : NULL,
761                                                 present->number ? present->set.d[0] : last_parent,
762                                                 siter, 0, options)) {
763                     goto error;
764                 }
765             }
766         }
767         break;
768     case LYS_CHOICE:
769         /* get existing node in the data tree from the choice */
770         iter = NULL;
771         if ((toplevel && tree) || (!toplevel && subtree)) {
772             LY_TREE_FOR(toplevel ? tree : subtree->child, iter) {
773                 for (siter = lys_parent(iter->schema), siter_prev = iter->schema;
774                         siter && (siter->nodetype & (LYS_CASE | LYS_USES | LYS_CHOICE));
775                         siter_prev = siter, siter = lys_parent(siter)) {
776                     if (siter == schema) {
777                         /* we have the choice instance */
778                         break;
779                     }
780                 }
781                 if (siter == schema) {
782                     /* we have the choice instance;
783                      * the condition must be the same as in the loop because of
784                      * choice's sibling nodes that break the loop, so siter is not NULL,
785                      * but it is not the same as schema */
786                     break;
787                 }
788             }
789         }
790         if (!iter) {
791             if (lyd_is_when_false(tree, last_parent, schema, options)) {
792                 /* nothing to check */
793                 break;
794             }
795             if (((struct lys_node_choice *)schema)->dflt) {
796                 /* there is a default case */
797                 if (lyd_check_mandatory_subtree(tree, subtree, last_parent, ((struct lys_node_choice *)schema)->dflt,
798                                                 toplevel, options)) {
799                     goto error;
800                 }
801             } else if (schema->flags & LYS_MAND_TRUE) {
802                 /* choice requires some data to be instantiated */
803                 LOGVAL(schema->module->ctx, LYE_NOMANDCHOICE, LY_VLOG_LYD, last_parent, schema->name);
804                 goto error;
805             }
806         } else {
807             /* one of the choice's cases is instantiated, continue into this case */
808             /* since iter != NULL, siter must be also != NULL and we also know siter_prev
809              * which points to the child of schema leading towards the instantiated data */
810             assert(siter && siter_prev);
811             if (lyd_check_mandatory_subtree(tree, subtree, last_parent, siter_prev, toplevel, options)) {
812                 goto error;
813             }
814         }
815         break;
816     case LYS_NOTIF:
817         /* skip if validating a notification */
818         if (!(options & LYD_OPT_NOTIF)) {
819             break;
820         }
821         /* fallthrough */
822     case LYS_CASE:
823     case LYS_USES:
824     case LYS_INPUT:
825     case LYS_OUTPUT:
826         /* go recursively */
827         LY_TREE_FOR(schema->child, siter) {
828             if (lyd_check_mandatory_subtree(tree, subtree, last_parent, siter, toplevel, options)) {
829                 goto error;
830             }
831         }
832         break;
833     default:
834         /* stop */
835         break;
836     }
837 
838     ret = EXIT_SUCCESS;
839 
840 error:
841     ly_set_free(present);
842     return ret;
843 }
844 
845 int
lyd_check_mandatory_tree(struct lyd_node * root,struct ly_ctx * ctx,const struct lys_module ** modules,int mod_count,int options)846 lyd_check_mandatory_tree(struct lyd_node *root, struct ly_ctx *ctx, const struct lys_module **modules, int mod_count,
847                          int options)
848 {
849     struct lys_node *siter;
850     int i;
851 
852     assert(root || ctx);
853     assert(!(options & LYD_OPT_ACT_NOTIF));
854 
855     if (options & (LYD_OPT_TRUSTED | LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG)) {
856         /* no check is needed */
857         return EXIT_SUCCESS;
858     }
859 
860     if (!ctx) {
861         /* get context */
862         ctx = root->schema->module->ctx;
863     }
864 
865     if (!(options & LYD_OPT_TYPEMASK) || (options & LYD_OPT_CONFIG)) {
866         if (options & LYD_OPT_NOSIBLINGS) {
867             if (root && lyd_check_mandatory_subtree(root, NULL, NULL, root->schema, 1, options)) {
868                 return EXIT_FAILURE;
869             }
870         } else if (modules && mod_count) {
871             for (i = 0; i < mod_count; ++i) {
872                 LY_TREE_FOR(modules[i]->data, siter) {
873                     if (!(siter->nodetype & (LYS_RPC | LYS_NOTIF)) &&
874                             lyd_check_mandatory_subtree(root, NULL, NULL, siter, 1, options)) {
875                         return EXIT_FAILURE;
876                     }
877                 }
878             }
879         } else {
880             for (i = 0; i < ctx->models.used; i++) {
881                 /* skip not implemented and disabled modules */
882                 if (!ctx->models.list[i]->implemented || ctx->models.list[i]->disabled) {
883                     continue;
884                 }
885                 if ((options & LYD_OPT_DATA_NO_YANGLIB) && !strcmp(ctx->models.list[i]->name, "ietf-yang-library")) {
886                     /* skip ietf-yang-library */
887                     continue;
888                 }
889                 LY_TREE_FOR(ctx->models.list[i]->data, siter) {
890                     if (!(siter->nodetype & (LYS_RPC | LYS_NOTIF)) &&
891                             lyd_check_mandatory_subtree(root, NULL, NULL, siter, 1, options)) {
892                         return EXIT_FAILURE;
893                     }
894                 }
895             }
896         }
897     } else if (options & LYD_OPT_NOTIF) {
898         if (!root || (root->schema->nodetype != LYS_NOTIF)) {
899             LOGERR(ctx, LY_EINVAL, "Subtree is not a single notification.");
900             return EXIT_FAILURE;
901         }
902         if (root->schema->child && lyd_check_mandatory_subtree(root, root, root, root->schema, 0, options)) {
903             return EXIT_FAILURE;
904         }
905     } else if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) {
906         if (!root || !(root->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
907             LOGERR(ctx, LY_EINVAL, "Subtree is not a single RPC/action/reply.");
908             return EXIT_FAILURE;
909         }
910         if (options & LYD_OPT_RPC) {
911             for (siter = root->schema->child; siter && siter->nodetype != LYS_INPUT; siter = siter->next);
912         } else { /* LYD_OPT_RPCREPLY */
913             for (siter = root->schema->child; siter && siter->nodetype != LYS_OUTPUT; siter = siter->next);
914         }
915         if (siter && lyd_check_mandatory_subtree(root, root, root, siter, 0, options)) {
916             return EXIT_FAILURE;
917         }
918     } else if (options & LYD_OPT_DATA_TEMPLATE) {
919         if (root && lyd_check_mandatory_subtree(root, NULL, NULL, root->schema, 1, options)) {
920             return EXIT_FAILURE;
921         }
922     } else {
923         LOGINT(ctx);
924         return EXIT_FAILURE;
925     }
926 
927     return EXIT_SUCCESS;
928 }
929 
930 static struct lyd_node *
lyd_parse_(struct ly_ctx * ctx,const struct lyd_node * rpc_act,const char * data,LYD_FORMAT format,int options,const struct lyd_node * data_tree,const char * yang_data_name)931 lyd_parse_(struct ly_ctx *ctx, const struct lyd_node *rpc_act, const char *data, LYD_FORMAT format, int options,
932            const struct lyd_node *data_tree, const char *yang_data_name)
933 {
934     struct lyxml_elem *xml;
935     struct lyd_node *result = NULL;
936     int xmlopt = LYXML_PARSE_MULTIROOT;
937 
938     if (!ctx) {
939         LOGARG;
940         return NULL;
941     }
942 
943     if (options & LYD_OPT_NOSIBLINGS) {
944         xmlopt = 0;
945     }
946 
947     /* we must free all the errors, otherwise we are unable to properly check returned ly_errno :-/ */
948     ly_errno = LY_SUCCESS;
949     switch (format) {
950     case LYD_XML:
951         xml = lyxml_parse_mem(ctx, data, xmlopt);
952         if (ly_errno) {
953             break;
954         }
955         if (options & LYD_OPT_RPCREPLY) {
956             result = lyd_parse_xml(ctx, &xml, options, rpc_act, data_tree);
957         } else if (options & (LYD_OPT_RPC | LYD_OPT_NOTIF)) {
958             result = lyd_parse_xml(ctx, &xml, options, data_tree);
959         } else if (options & LYD_OPT_DATA_TEMPLATE) {
960             result = lyd_parse_xml(ctx, &xml, options, yang_data_name);
961         } else {
962             result = lyd_parse_xml(ctx, &xml, options);
963         }
964         lyxml_free_withsiblings(ctx, xml);
965         break;
966     case LYD_JSON:
967         result = lyd_parse_json(ctx, data, options, rpc_act, data_tree, yang_data_name);
968         break;
969     case LYD_LYB:
970         result = lyd_parse_lyb(ctx, data, options, data_tree, yang_data_name, NULL);
971         break;
972     default:
973         /* error */
974         break;
975     }
976 
977     if (ly_errno) {
978         lyd_free_withsiblings(result);
979         return NULL;
980     }
981 
982     if ((options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) && lyd_schema_sort(result, 1)) {
983         /* rpc and rpc-reply must be sorted */
984         lyd_free_withsiblings(result);
985         return NULL;
986     }
987 
988     return result;
989 }
990 
991 static struct lyd_node *
lyd_parse_data_(struct ly_ctx * ctx,const char * data,LYD_FORMAT format,int options,va_list ap)992 lyd_parse_data_(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options, va_list ap)
993 {
994     const struct lyd_node *rpc_act = NULL, *data_tree = NULL, *iter;
995     const char *yang_data_name = NULL;
996 
997     if (lyp_data_check_options(ctx, options, __func__)) {
998         return NULL;
999     }
1000 
1001     if (options & LYD_OPT_RPCREPLY) {
1002         rpc_act = va_arg(ap, const struct lyd_node *);
1003         if (!rpc_act || rpc_act->parent || !(rpc_act->schema->nodetype & (LYS_RPC | LYS_LIST | LYS_CONTAINER))) {
1004             LOGERR(ctx, LY_EINVAL, "%s: invalid variable parameter (const struct lyd_node *rpc_act).", __func__);
1005             return NULL;
1006         }
1007     }
1008     if (options & (LYD_OPT_RPC | LYD_OPT_NOTIF | LYD_OPT_RPCREPLY)) {
1009         data_tree = va_arg(ap, const struct lyd_node *);
1010         if (data_tree) {
1011             if (options & LYD_OPT_NOEXTDEPS) {
1012                 LOGERR(ctx, LY_EINVAL, "%s: invalid parameter (variable arg const struct lyd_node *data_tree and LYD_OPT_NOEXTDEPS set).",
1013                        __func__);
1014                 return NULL;
1015             }
1016 
1017             LY_TREE_FOR(data_tree, iter) {
1018                 if (iter->parent) {
1019                     /* a sibling is not top-level */
1020                     LOGERR(ctx, LY_EINVAL, "%s: invalid variable parameter (const struct lyd_node *data_tree).", __func__);
1021                     return NULL;
1022                 }
1023             }
1024 
1025             /* move it to the beginning */
1026             for (; data_tree->prev->next; data_tree = data_tree->prev);
1027 
1028             /* LYD_OPT_NOSIBLINGS cannot be set in this case */
1029             if (options & LYD_OPT_NOSIBLINGS) {
1030                 LOGERR(ctx, LY_EINVAL, "%s: invalid parameter (variable arg const struct lyd_node *data_tree with LYD_OPT_NOSIBLINGS).", __func__);
1031                 return NULL;
1032             }
1033         }
1034     }
1035     if (options & LYD_OPT_DATA_TEMPLATE) {
1036         yang_data_name = va_arg(ap, const char *);
1037     }
1038 
1039     return lyd_parse_(ctx, rpc_act, data, format, options, data_tree, yang_data_name);
1040 }
1041 
1042 API struct lyd_node *
lyd_parse_mem(struct ly_ctx * ctx,const char * data,LYD_FORMAT format,int options,...)1043 lyd_parse_mem(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options, ...)
1044 {
1045     FUN_IN;
1046 
1047     va_list ap;
1048     struct lyd_node *result;
1049 
1050     va_start(ap, options);
1051     result = lyd_parse_data_(ctx, data, format, options, ap);
1052     va_end(ap);
1053 
1054     return result;
1055 }
1056 
1057 static struct lyd_node *
lyd_parse_fd_(struct ly_ctx * ctx,int fd,LYD_FORMAT format,int options,va_list ap)1058 lyd_parse_fd_(struct ly_ctx *ctx, int fd, LYD_FORMAT format, int options, va_list ap)
1059 {
1060     struct lyd_node *ret;
1061     size_t length;
1062     char *data;
1063 
1064     if (!ctx || (fd == -1)) {
1065         LOGARG;
1066         return NULL;
1067     }
1068 
1069     if (lyp_mmap(ctx, fd, 0, &length, (void **)&data)) {
1070         LOGERR(ctx, LY_ESYS, "Mapping file descriptor into memory failed (%s()).", __func__);
1071         return NULL;
1072     }
1073 
1074     ret = lyd_parse_data_(ctx, data, format, options, ap);
1075 
1076     lyp_munmap(data, length);
1077 
1078     return ret;
1079 }
1080 
1081 API struct lyd_node *
lyd_parse_fd(struct ly_ctx * ctx,int fd,LYD_FORMAT format,int options,...)1082 lyd_parse_fd(struct ly_ctx *ctx, int fd, LYD_FORMAT format, int options, ...)
1083 {
1084     FUN_IN;
1085 
1086     struct lyd_node *ret;
1087     va_list ap;
1088 
1089     va_start(ap, options);
1090     ret = lyd_parse_fd_(ctx, fd, format, options, ap);
1091     va_end(ap);
1092 
1093     return ret;
1094 }
1095 
1096 API struct lyd_node *
lyd_parse_path(struct ly_ctx * ctx,const char * path,LYD_FORMAT format,int options,...)1097 lyd_parse_path(struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int options, ...)
1098 {
1099     FUN_IN;
1100 
1101     int fd;
1102     struct lyd_node *ret;
1103     va_list ap;
1104 
1105     if (!ctx || !path) {
1106         LOGARG;
1107         return NULL;
1108     }
1109 
1110     fd = open(path, O_RDONLY);
1111     if (fd == -1) {
1112         LOGERR(ctx, LY_ESYS, "Failed to open data file \"%s\" (%s).", path, strerror(errno));
1113         return NULL;
1114     }
1115 
1116     va_start(ap, options);
1117     ret = lyd_parse_fd_(ctx, fd, format, options, ap);
1118 
1119     va_end(ap);
1120     close(fd);
1121 
1122     return ret;
1123 }
1124 
1125 static struct lys_node *
lyd_new_find_schema(struct lyd_node * parent,const struct lys_module * module,int rpc_output)1126 lyd_new_find_schema(struct lyd_node *parent, const struct lys_module *module, int rpc_output)
1127 {
1128     struct lys_node *siblings;
1129 
1130     if (!parent) {
1131         siblings = module->data;
1132     } else {
1133         if (!parent->schema) {
1134             return NULL;
1135         }
1136         siblings = parent->schema->child;
1137         if (siblings && (siblings->nodetype == (rpc_output ? LYS_INPUT : LYS_OUTPUT))) {
1138             siblings = siblings->next;
1139         }
1140         if (siblings && (siblings->nodetype == (rpc_output ? LYS_OUTPUT : LYS_INPUT))) {
1141             siblings = siblings->child;
1142         }
1143     }
1144 
1145     return siblings;
1146 }
1147 
1148 struct lyd_node *
_lyd_new(struct lyd_node * parent,const struct lys_node * schema,int dflt)1149 _lyd_new(struct lyd_node *parent, const struct lys_node *schema, int dflt)
1150 {
1151     struct lyd_node *ret;
1152 
1153     ret = calloc(1, sizeof *ret);
1154     LY_CHECK_ERR_RETURN(!ret, LOGMEM(schema->module->ctx), NULL);
1155 
1156     ret->schema = (struct lys_node *)schema;
1157     ret->validity = ly_new_node_validity(schema);
1158     if (resolve_applies_when(schema, 0, NULL)) {
1159         ret->when_status = LYD_WHEN;
1160     }
1161     ret->prev = ret;
1162     ret->dflt = dflt;
1163 
1164 #ifdef LY_ENABLED_CACHE
1165     lyd_hash(ret);
1166 #endif
1167 
1168     if (parent) {
1169         if (lyd_insert(parent, ret)) {
1170             lyd_free(ret);
1171             return NULL;
1172         }
1173     }
1174     return ret;
1175 }
1176 
1177 API struct lyd_node *
lyd_new(struct lyd_node * parent,const struct lys_module * module,const char * name)1178 lyd_new(struct lyd_node *parent, const struct lys_module *module, const char *name)
1179 {
1180     FUN_IN;
1181 
1182     const struct lys_node *snode = NULL, *siblings;
1183 
1184     if ((!parent && !module) || !name) {
1185         LOGARG;
1186         return NULL;
1187     }
1188 
1189     if (module) {
1190         module = lys_main_module(module);
1191     }
1192 
1193     siblings = lyd_new_find_schema(parent, module, 0);
1194     if (!siblings) {
1195         LOGARG;
1196         return NULL;
1197     }
1198 
1199     if (lys_getnext_data(module, lys_parent(siblings), name, strlen(name), LYS_CONTAINER | LYS_LIST | LYS_NOTIF
1200                          | LYS_RPC | LYS_ACTION, 0, &snode) || !snode) {
1201         LOGERR(siblings->module->ctx, LY_EINVAL, "Failed to find \"%s\" as a sibling to \"%s:%s\".",
1202                name, lys_node_module(siblings)->name, siblings->name);
1203         return NULL;
1204     }
1205 
1206     return _lyd_new(parent, snode, 0);
1207 }
1208 
1209 static struct lyd_node *
lyd_create_leaf(const struct lys_node * schema,const char * val_str,int dflt,int edit_leaf)1210 lyd_create_leaf(const struct lys_node *schema, const char *val_str, int dflt, int edit_leaf)
1211 {
1212     struct lyd_node_leaf_list *ret;
1213 
1214     ret = calloc(1, sizeof *ret);
1215     LY_CHECK_ERR_RETURN(!ret, LOGMEM(schema->module->ctx), NULL);
1216 
1217     ret->schema = (struct lys_node *)schema;
1218     ret->validity = ly_new_node_validity(schema);
1219     if (resolve_applies_when(schema, 0, NULL)) {
1220         ret->when_status = LYD_WHEN;
1221     }
1222     ret->prev = (struct lyd_node *)ret;
1223     ret->value_type = ((struct lys_node_leaf *)schema)->type.base;
1224     ret->value_str = lydict_insert(schema->module->ctx, val_str ? val_str : "", 0);
1225     ret->dflt = dflt;
1226 
1227     if (edit_leaf && !val_str) {
1228         /* empty edit leaf, it is fine */
1229         ((struct lyd_node_leaf_list *)ret)->value_type = LY_TYPE_UNKNOWN;
1230     } else if (!lyp_parse_value(&((struct lys_node_leaf *)schema)->type, &ret->value_str, NULL, ret, NULL, NULL, 1, dflt)) {
1231         lyd_free((struct lyd_node *)ret);
1232         return NULL;
1233     }
1234 
1235 #ifdef LY_ENABLED_CACHE
1236     lyd_hash((struct lyd_node *)ret);
1237 #endif
1238 
1239     return (struct lyd_node *)ret;
1240 }
1241 
1242 static struct lyd_node *
_lyd_new_leaf(struct lyd_node * parent,const struct lys_node * schema,const char * val_str,int dflt,int edit_leaf)1243 _lyd_new_leaf(struct lyd_node *parent, const struct lys_node *schema, const char *val_str, int dflt, int edit_leaf)
1244 {
1245     struct lyd_node *ret;
1246 
1247     ret = lyd_create_leaf(schema, val_str, dflt, edit_leaf);
1248     if (!ret) {
1249         return NULL;
1250     }
1251 
1252     /* connect to parent */
1253     if (parent) {
1254         if (lyd_insert(parent, ret)) {
1255             lyd_free(ret);
1256             return NULL;
1257         }
1258     }
1259 
1260     if ((ret->schema->nodetype == LYS_LEAF) && (ret->schema->flags & LYS_UNIQUE)) {
1261         for (; parent && (parent->schema->nodetype != LYS_LIST); parent = parent->parent);
1262         if (parent) {
1263             parent->validity |= LYD_VAL_UNIQUE;
1264         } else {
1265             LOGINT(schema->module->ctx);
1266         }
1267     }
1268 
1269     return ret;
1270 }
1271 
1272 API struct lyd_node *
lyd_new_leaf(struct lyd_node * parent,const struct lys_module * module,const char * name,const char * val_str)1273 lyd_new_leaf(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str)
1274 {
1275     FUN_IN;
1276 
1277     const struct lys_node *snode = NULL, *siblings;
1278 
1279     if ((!parent && !module) || !name) {
1280         LOGARG;
1281         return NULL;
1282     }
1283 
1284     if (module) {
1285         module = lys_main_module(module);
1286     }
1287 
1288     siblings = lyd_new_find_schema(parent, module, 0);
1289     if (!siblings) {
1290         LOGARG;
1291         return NULL;
1292     }
1293 
1294     if (lys_getnext_data(module, lys_parent(siblings), name, strlen(name), LYS_LEAFLIST | LYS_LEAF, 0, &snode) || !snode) {
1295         LOGERR(siblings->module->ctx, LY_EINVAL, "Failed to find \"%s\" as a sibling to \"%s:%s\".",
1296                name, lys_node_module(siblings)->name, siblings->name);
1297         return NULL;
1298     }
1299 
1300     return _lyd_new_leaf(parent, snode, val_str, 0, 0);
1301 }
1302 
1303 /**
1304  * @brief Update (add) default flag of the parents of the added node.
1305  *
1306  * @param[in] node Added node
1307  */
1308 static void
lyd_wd_update_parents(struct lyd_node * node)1309 lyd_wd_update_parents(struct lyd_node *node)
1310 {
1311     struct lyd_node *parent = node->parent, *iter;
1312 
1313     for (parent = node->parent; parent; parent = node->parent) {
1314         if (parent->dflt || parent->schema->nodetype != LYS_CONTAINER ||
1315                 ((struct lys_node_container *)parent->schema)->presence) {
1316             /* parent is already default and there is nothing to update or
1317              * it is not a non-presence container -> stop the loop */
1318             break;
1319         }
1320         /* check that there is still some non default sibling */
1321         for (iter = node->prev; iter != node; iter = iter->prev) {
1322             if (!iter->dflt) {
1323                 break;
1324             }
1325         }
1326         if (iter == node && node->prev != node) {
1327             /* all siblings are implicit default nodes, propagate it to the parent */
1328             node = node->parent;
1329             node->dflt = 1;
1330             continue;
1331         } else {
1332             /* stop the loop */
1333             break;
1334         }
1335     }
1336 }
1337 
1338 API int
lyd_change_leaf(struct lyd_node_leaf_list * leaf,const char * val_str)1339 lyd_change_leaf(struct lyd_node_leaf_list *leaf, const char *val_str)
1340 {
1341     FUN_IN;
1342 
1343     const char *backup, *new_val;
1344     int val_change, dflt_change;
1345     struct lyd_node *parent;
1346 
1347     if (!leaf || (leaf->schema->nodetype != LYS_LEAF)) {
1348         LOGARG;
1349         return -1;
1350     }
1351 
1352     backup = leaf->value_str;
1353     new_val = lydict_insert(leaf->schema->module->ctx, val_str ? val_str : "", 0);
1354 
1355     /* parse the type correctly, makes the value canonical if needed */
1356     if (!lyp_parse_value(&((struct lys_node_leaf *)leaf->schema)->type, &new_val, NULL, leaf, NULL, NULL, 1, 0)) {
1357         lydict_remove(leaf->schema->module->ctx, new_val);
1358         return -1;
1359     }
1360 
1361     if (!strcmp(backup, new_val)) {
1362         /* the value remains the same */
1363         val_change = 0;
1364     } else {
1365         val_change = 1;
1366     }
1367 
1368     /* value is correct, replace it */
1369     lydict_remove(leaf->schema->module->ctx, leaf->value_str);
1370     leaf->value_str = new_val;
1371 
1372     /* clear the default flag, the value is different */
1373     if (leaf->dflt) {
1374         for (parent = (struct lyd_node *)leaf; parent; parent = parent->parent) {
1375             parent->dflt = 0;
1376         }
1377         dflt_change = 1;
1378     } else {
1379         dflt_change = 0;
1380     }
1381 
1382     if (val_change) {
1383         /* make the node non-validated */
1384         leaf->validity = ly_new_node_validity(leaf->schema);
1385 
1386         /* set unique validation flag for parent list */
1387         if (leaf->schema->flags & LYS_UNIQUE) {
1388             for (parent = leaf->parent; parent && (parent->schema->nodetype != LYS_LIST); parent = parent->parent);
1389             if (parent) {
1390                 parent->validity |= LYD_VAL_UNIQUE;
1391             }
1392         }
1393 
1394 #ifdef LY_ENABLED_CACHE
1395         /* rehash list if it's key was changed */
1396         if (lys_is_key((struct lys_node_leaf *)leaf->schema, NULL)) {
1397             _lyd_unlink_hash((struct lyd_node *)leaf, leaf->parent, 0);
1398             if (leaf->parent) {
1399                 lyd_hash(leaf->parent);
1400             }
1401             lyd_insert_hash((struct lyd_node *)leaf);
1402         }
1403 #endif
1404     }
1405 
1406     return (val_change || dflt_change ? 0 : 1);
1407 }
1408 
1409 static struct lyd_node *
lyd_create_anydata(struct lyd_node * parent,const struct lys_node * schema,void * value,LYD_ANYDATA_VALUETYPE value_type)1410 lyd_create_anydata(struct lyd_node *parent, const struct lys_node *schema, void *value,
1411                    LYD_ANYDATA_VALUETYPE value_type)
1412 {
1413     struct lyd_node *iter;
1414     struct lyd_node_anydata *ret;
1415     int len;
1416 
1417     ret = calloc(1, sizeof *ret);
1418     LY_CHECK_ERR_RETURN(!ret, LOGMEM(schema->module->ctx), NULL);
1419 
1420     ret->schema = (struct lys_node *)schema;
1421     ret->validity = ly_new_node_validity(schema);
1422     if (resolve_applies_when(schema, 0, NULL)) {
1423         ret->when_status = LYD_WHEN;
1424     }
1425     ret->prev = (struct lyd_node *)ret;
1426 
1427     /* set the value */
1428     switch (value_type) {
1429     case LYD_ANYDATA_CONSTSTRING:
1430     case LYD_ANYDATA_SXML:
1431     case LYD_ANYDATA_JSON:
1432         ret->value.str = lydict_insert(schema->module->ctx, (const char *)value, 0);
1433         break;
1434     case LYD_ANYDATA_STRING:
1435     case LYD_ANYDATA_SXMLD:
1436     case LYD_ANYDATA_JSOND:
1437         ret->value.str = lydict_insert_zc(schema->module->ctx, (char *)value);
1438         value_type &= ~LYD_ANYDATA_STRING; /* make const string from string */
1439         break;
1440     case LYD_ANYDATA_DATATREE:
1441         ret->value.tree = (struct lyd_node *)value;
1442         break;
1443     case LYD_ANYDATA_XML:
1444         ret->value.xml = (struct lyxml_elem *)value;
1445         break;
1446     case LYD_ANYDATA_LYB:
1447         len = lyd_lyb_data_length(value);
1448         if (len == -1) {
1449             LOGERR(schema->module->ctx, LY_EINVAL, "Invalid LYB data.");
1450             return NULL;
1451         }
1452         ret->value.mem = malloc(len);
1453         LY_CHECK_ERR_RETURN(!ret->value.mem, LOGMEM(schema->module->ctx); free(ret), NULL);
1454         memcpy(ret->value.mem, value, len);
1455         break;
1456     case LYD_ANYDATA_LYBD:
1457         ret->value.mem = value;
1458         value_type &= ~LYD_ANYDATA_STRING; /* make const string from string */
1459         break;
1460     }
1461     ret->value_type = value_type;
1462 
1463 #ifdef LY_ENABLED_CACHE
1464     lyd_hash((struct lyd_node *)ret);
1465 #endif
1466 
1467     /* connect to parent */
1468     if (parent) {
1469         if (lyd_insert(parent, (struct lyd_node*)ret)) {
1470             lyd_free((struct lyd_node*)ret);
1471             return NULL;
1472         }
1473 
1474         /* remove the flag from parents */
1475         for (iter = parent; iter && iter->dflt; iter = iter->parent) {
1476             iter->dflt = 0;
1477         }
1478     }
1479 
1480     return (struct lyd_node*)ret;
1481 }
1482 
1483 API struct lyd_node *
lyd_new_anydata(struct lyd_node * parent,const struct lys_module * module,const char * name,void * value,LYD_ANYDATA_VALUETYPE value_type)1484 lyd_new_anydata(struct lyd_node *parent, const struct lys_module *module, const char *name,
1485                 void *value, LYD_ANYDATA_VALUETYPE value_type)
1486 {
1487     FUN_IN;
1488 
1489     const struct lys_node *siblings, *snode;
1490 
1491     if ((!parent && !module) || !name) {
1492         LOGARG;
1493         return NULL;
1494     }
1495 
1496     if (module) {
1497         module = lys_main_module(module);
1498     }
1499 
1500     siblings = lyd_new_find_schema(parent, module, 0);
1501     if (!siblings) {
1502         LOGARG;
1503         return NULL;
1504     }
1505 
1506     if (lys_getnext_data(module, lys_parent(siblings), name, strlen(name), LYS_ANYDATA, 0, &snode) || !snode) {
1507         LOGERR(siblings->module->ctx, LY_EINVAL, "Failed to find \"%s\" as a sibling to \"%s:%s\".",
1508                name, lys_node_module(siblings)->name, siblings->name);
1509         return NULL;
1510     }
1511 
1512     return lyd_create_anydata(parent, snode, value, value_type);
1513 }
1514 
1515 API struct lyd_node *
lyd_new_yangdata(const struct lys_module * module,const char * name_template,const char * name)1516 lyd_new_yangdata(const struct lys_module *module, const char *name_template, const char *name)
1517 {
1518     FUN_IN;
1519 
1520     const struct lys_node *schema = NULL, *snode;
1521 
1522     if (!module || !name_template || !name) {
1523         LOGARG;
1524         return NULL;
1525     }
1526 
1527     module = lys_main_module(module);
1528 
1529     schema = lyp_get_yang_data_template(module, name_template, strlen(name_template));
1530     if (!schema) {
1531         LOGERR(module->ctx, LY_EINVAL, "Failed to find yang-data template \"%s\".", name_template);
1532         return NULL;
1533     }
1534 
1535     if (lys_getnext_data(module, schema, name, strlen(name), LYS_CONTAINER, 0, &snode) || !snode) {
1536         LOGERR(module->ctx, LY_EINVAL, "Failed to find \"%s\" as a container child of \"%s:%s\".",
1537                name, module->name, schema->name);
1538         return NULL;
1539     }
1540 
1541     return _lyd_new(NULL, snode, 0);
1542 }
1543 
1544 API struct lyd_node *
lyd_new_output(struct lyd_node * parent,const struct lys_module * module,const char * name)1545 lyd_new_output(struct lyd_node *parent, const struct lys_module *module, const char *name)
1546 {
1547     FUN_IN;
1548 
1549     const struct lys_node *snode = NULL, *siblings;
1550 
1551     if ((!parent && !module) || !name) {
1552         LOGARG;
1553         return NULL;
1554     }
1555 
1556     if (module) {
1557         module = lys_main_module(module);
1558     }
1559 
1560     siblings = lyd_new_find_schema(parent, module, 1);
1561     if (!siblings) {
1562         LOGARG;
1563         return NULL;
1564     }
1565 
1566     if (lys_getnext_data(module, lys_parent(siblings), name, strlen(name), LYS_CONTAINER | LYS_LIST | LYS_NOTIF
1567                          | LYS_RPC | LYS_ACTION, 0, &snode) || !snode) {
1568         LOGERR(siblings->module->ctx, LY_EINVAL, "Failed to find \"%s\" as a sibling to \"%s:%s\".",
1569                name, lys_node_module(siblings)->name, siblings->name);
1570         return NULL;
1571     }
1572 
1573     return _lyd_new(parent, snode, 0);
1574 }
1575 
1576 API struct lyd_node *
lyd_new_output_leaf(struct lyd_node * parent,const struct lys_module * module,const char * name,const char * val_str)1577 lyd_new_output_leaf(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str)
1578 {
1579     FUN_IN;
1580 
1581     const struct lys_node *snode = NULL, *siblings;
1582 
1583     if ((!parent && !module) || !name) {
1584         LOGARG;
1585         return NULL;
1586     }
1587 
1588     if (module) {
1589         module = lys_main_module(module);
1590     }
1591 
1592     siblings = lyd_new_find_schema(parent, module, 1);
1593     if (!siblings) {
1594         LOGARG;
1595         return NULL;
1596     }
1597 
1598     if (lys_getnext_data(module, lys_parent(siblings), name, strlen(name), LYS_LEAFLIST | LYS_LEAF, 0, &snode) || !snode) {
1599         LOGERR(siblings->module->ctx, LY_EINVAL, "Failed to find \"%s\" as a sibling to \"%s:%s\".",
1600                name, lys_node_module(siblings)->name, siblings->name);
1601         return NULL;
1602     }
1603 
1604     return _lyd_new_leaf(parent, snode, val_str, 0, 0);
1605 }
1606 
1607 API struct lyd_node *
lyd_new_output_anydata(struct lyd_node * parent,const struct lys_module * module,const char * name,void * value,LYD_ANYDATA_VALUETYPE value_type)1608 lyd_new_output_anydata(struct lyd_node *parent, const struct lys_module *module, const char *name,
1609                        void *value, LYD_ANYDATA_VALUETYPE value_type)
1610 {
1611     FUN_IN;
1612 
1613     const struct lys_node *siblings, *snode;
1614 
1615     if ((!parent && !module) || !name) {
1616         LOGARG;
1617         return NULL;
1618     }
1619 
1620     if (module) {
1621         module = lys_main_module(module);
1622     }
1623 
1624     siblings = lyd_new_find_schema(parent, module, 1);
1625     if (!siblings) {
1626         LOGARG;
1627         return NULL;
1628     }
1629 
1630     if (lys_getnext_data(module, lys_parent(siblings), name, strlen(name), LYS_ANYDATA, 0, &snode) || !snode) {
1631         LOGERR(siblings->module->ctx, LY_EINVAL, "Failed to find \"%s\" as a sibling to \"%s:%s\".",
1632                name, lys_node_module(siblings)->name, siblings->name);
1633         return NULL;
1634     }
1635 
1636     return lyd_create_anydata(parent, snode, value, value_type);
1637 }
1638 
1639 char *
lyd_make_canonical(const struct lys_node * schema,const char * val_str,int val_str_len)1640 lyd_make_canonical(const struct lys_node *schema, const char *val_str, int val_str_len)
1641 {
1642     struct lyd_node *node;
1643     char *str;
1644 
1645     assert(schema->nodetype & (LYS_LEAF | LYS_LEAFLIST));
1646 
1647     /* parse the value into a fake leaf */
1648     struct lyd_node_leaf_list *node_leaf_list;
1649 
1650     node_leaf_list = calloc(1, sizeof *node_leaf_list);
1651     LY_CHECK_ERR_RETURN(!node_leaf_list, LOGMEM(schema->module->ctx), NULL);
1652 
1653     node_leaf_list->schema = (struct lys_node *)schema;
1654     node_leaf_list->prev = (struct lyd_node *)node_leaf_list;
1655     node_leaf_list->value_type = ((struct lys_node_leaf *)schema)->type.base;
1656     node_leaf_list->value_str = lydict_insert(schema->module->ctx, val_str ? val_str : "", val_str_len);
1657     node_leaf_list->dflt = 0;
1658 
1659     if (!lyp_parse_value(&((struct lys_node_leaf *)schema)->type, &node_leaf_list->value_str, NULL, node_leaf_list,
1660             NULL, NULL, 1, 0)) {
1661         lyd_free((struct lyd_node *)node_leaf_list);
1662         return NULL;
1663     }
1664 
1665     node = (struct lyd_node *)node_leaf_list;
1666 
1667     if (!node) {
1668         return NULL;
1669     }
1670 
1671     str = strdup(((struct lyd_node_leaf_list *)node)->value_str);
1672     lyd_free(node);
1673     if (!str) {
1674         LOGMEM(schema->module->ctx);
1675         return NULL;
1676     }
1677 
1678     return str;
1679 }
1680 
1681 static int
lyd_new_path_list_predicate(struct lyd_node * list,const char * list_name,const char * predicate,int * parsed)1682 lyd_new_path_list_predicate(struct lyd_node *list, const char *list_name, const char *predicate, int *parsed)
1683 {
1684     const char *mod_name, *name, *value;
1685     char *key_val;
1686     int r, i, mod_name_len, nam_len, val_len, has_predicate;
1687     struct lys_node_list *slist;
1688     struct lys_node *key;
1689 
1690     slist = (struct lys_node_list *)list->schema;
1691 
1692     /* is the predicate a number? */
1693     if (((r = parse_schema_json_predicate(predicate, &mod_name, &mod_name_len, &name, &nam_len, &value, &val_len, &has_predicate)) < 1)
1694             || !strncmp(name, ".", nam_len)) {
1695         LOGVAL(slist->module->ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, predicate[-r], &predicate[-r]);
1696         return -1;
1697     }
1698 
1699     if (isdigit(name[0])) {
1700         /* position index - creating without keys */
1701         *parsed += r;
1702         return 0;
1703     }
1704 
1705     /* it's not a number, so there must be some keys */
1706     if (!slist->keys_size) {
1707         /* there are none, so pretend we did not parse anything to get invalid char error later */
1708         return 0;
1709     }
1710 
1711     /* go through all the keys */
1712     i = 0;
1713     goto check_parsed_values;
1714 
1715     for (; i < slist->keys_size; ++i) {
1716         if (!has_predicate) {
1717             LOGVAL(slist->module->ctx, LYE_PATH_MISSKEY, LY_VLOG_NONE, NULL, list_name);
1718             return -1;
1719         }
1720 
1721         if (((r = parse_schema_json_predicate(predicate, &mod_name, &mod_name_len, &name, &nam_len, &value, &val_len, &has_predicate)) < 1)
1722                 || !strncmp(name, ".", nam_len)) {
1723             LOGVAL(slist->module->ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, predicate[-r], &predicate[-r]);
1724             return -1;
1725         }
1726 
1727 check_parsed_values:
1728         key = (struct lys_node *)slist->keys[i];
1729         *parsed += r;
1730         predicate += r;
1731 
1732         if (!value || (!mod_name && (lys_node_module(key) != lys_node_module((struct lys_node *)slist)))
1733                 || (mod_name && (strncmp(lys_node_module(key)->name, mod_name, mod_name_len) || lys_node_module(key)->name[mod_name_len]))
1734                 || strncmp(key->name, name, nam_len) || key->name[nam_len]) {
1735             LOGVAL(slist->module->ctx, LYE_PATH_INKEY, LY_VLOG_NONE, NULL, name);
1736             return -1;
1737         }
1738 
1739         key_val = malloc((val_len + 1) * sizeof(char));
1740         LY_CHECK_ERR_RETURN(!key_val, LOGMEM(slist->module->ctx), -1);
1741         strncpy(key_val, value, val_len);
1742         key_val[val_len] = '\0';
1743 
1744         if (!_lyd_new_leaf(list, key, key_val, 0, 0)) {
1745             free(key_val);
1746             return -1;
1747         }
1748         free(key_val);
1749     }
1750 
1751     return 0;
1752 }
1753 
1754 static struct lyd_node *
lyd_new_path_update(struct lyd_node * node,void * value,LYD_ANYDATA_VALUETYPE value_type,int dflt)1755 lyd_new_path_update(struct lyd_node *node, void *value, LYD_ANYDATA_VALUETYPE value_type, int dflt)
1756 {
1757     struct ly_ctx *ctx = node->schema->module->ctx;
1758     struct lyd_node_anydata *any;
1759     int len;
1760 
1761     switch (node->schema->nodetype) {
1762     case LYS_LEAF:
1763         if (value_type > LYD_ANYDATA_STRING) {
1764             LOGARG;
1765             return NULL;
1766         }
1767 
1768         if (lyd_change_leaf((struct lyd_node_leaf_list *)node, value) == 0) {
1769             /* there was an actual change */
1770             if (dflt) {
1771                 node->dflt = 1;
1772             }
1773             return node;
1774         }
1775 
1776         if (dflt) {
1777             /* maybe the value is the same, but the node is default now */
1778             node->dflt = 1;
1779             return node;
1780         }
1781 
1782         break;
1783     case LYS_ANYXML:
1784     case LYS_ANYDATA:
1785         /* the nodes are the same if:
1786          * 1) the value types are strings (LYD_ANYDATA_STRING and LYD_ANYDATA_CONSTSTRING equals)
1787          *    and the strings equals
1788          * 2) the value types are the same, but not strings and the pointers (not the content) are the
1789          *    same
1790          */
1791         any = (struct lyd_node_anydata *)node;
1792         if (any->value_type <= LYD_ANYDATA_STRING && value_type <= LYD_ANYDATA_STRING) {
1793             if (ly_strequal(any->value.str, (char *)value, 0)) {
1794                 /* values are the same */
1795                 return NULL;
1796             }
1797         } else if (any->value_type == value_type) {
1798             /* compare pointers */
1799             if ((void *)any->value.tree == value) {
1800                 /* values are the same */
1801                 return NULL;
1802             }
1803         }
1804 
1805         /* values are not the same - 1) remove the old one ... */
1806         switch (any->value_type) {
1807         case LYD_ANYDATA_CONSTSTRING:
1808         case LYD_ANYDATA_SXML:
1809         case LYD_ANYDATA_JSON:
1810             lydict_remove(ctx, any->value.str);
1811             break;
1812         case LYD_ANYDATA_DATATREE:
1813             lyd_free_withsiblings(any->value.tree);
1814             break;
1815         case LYD_ANYDATA_XML:
1816             lyxml_free_withsiblings(ctx, any->value.xml);
1817             break;
1818         case LYD_ANYDATA_LYB:
1819             free(any->value.mem);
1820             break;
1821         case LYD_ANYDATA_STRING:
1822         case LYD_ANYDATA_SXMLD:
1823         case LYD_ANYDATA_JSOND:
1824         case LYD_ANYDATA_LYBD:
1825             /* dynamic strings are used only as input parameters */
1826             assert(0);
1827             break;
1828         }
1829         /* ... and 2) store the new one */
1830         switch (value_type) {
1831         case LYD_ANYDATA_CONSTSTRING:
1832         case LYD_ANYDATA_SXML:
1833         case LYD_ANYDATA_JSON:
1834             any->value.str = lydict_insert(ctx, (const char *)value, 0);
1835             break;
1836         case LYD_ANYDATA_STRING:
1837         case LYD_ANYDATA_SXMLD:
1838         case LYD_ANYDATA_JSOND:
1839             any->value.str = lydict_insert_zc(ctx, (char *)value);
1840             value_type &= ~LYD_ANYDATA_STRING; /* make const string from string */
1841             break;
1842         case LYD_ANYDATA_DATATREE:
1843             any->value.tree = value;
1844             break;
1845         case LYD_ANYDATA_XML:
1846             any->value.xml = value;
1847             break;
1848         case LYD_ANYDATA_LYB:
1849             len = lyd_lyb_data_length(value);
1850             if (len == -1) {
1851                 LOGERR(ctx, LY_EINVAL, "Invalid LYB data.");
1852                 return NULL;
1853             }
1854             any->value.mem = malloc(len);
1855             LY_CHECK_ERR_RETURN(!any->value.mem, LOGMEM(ctx), NULL);
1856             memcpy(any->value.mem, value, len);
1857             break;
1858         case LYD_ANYDATA_LYBD:
1859             any->value.mem = value;
1860             value_type &= ~LYD_ANYDATA_STRING; /* make const string from string */
1861             break;
1862         }
1863         return node;
1864     default:
1865         /* nothing needed - containers, lists and leaf-lists do not have value or it cannot be changed */
1866         break;
1867     }
1868 
1869     /* not updated */
1870     return NULL;
1871 }
1872 
1873 API struct lyd_node *
lyd_new_path(struct lyd_node * data_tree,const struct ly_ctx * ctx,const char * path,void * value,LYD_ANYDATA_VALUETYPE value_type,int options)1874 lyd_new_path(struct lyd_node *data_tree, const struct ly_ctx *ctx, const char *path, void *value,
1875              LYD_ANYDATA_VALUETYPE value_type, int options)
1876 {
1877     FUN_IN;
1878 
1879     char *str;
1880     const char *mod_name, *name, *val_name, *val, *node_mod_name, *id, *backup_mod_name = NULL, *yang_data_name = NULL;
1881     struct lyd_node *ret = NULL, *node, *parent = NULL;
1882     const struct lys_node *schild, *sparent, *tmp;
1883     const struct lys_node_list *slist;
1884     const struct lys_module *module, *prev_mod;
1885     int r, i, parsed = 0, mod_name_len, nam_len, val_name_len, val_len;
1886     int is_relative = -1, has_predicate, first_iter = 1;
1887     int backup_is_relative, backup_mod_name_len, yang_data_name_len = 0;
1888 
1889     if (!path || (!data_tree && !ctx)
1890             || (!data_tree && (path[0] != '/'))) {
1891         LOGARG;
1892         return NULL;
1893     }
1894 
1895     if (!ctx) {
1896         ctx = data_tree->schema->module->ctx;
1897     }
1898 
1899     id = path;
1900 
1901     if (data_tree) {
1902         if (path[0] == '/') {
1903             /* absolute path, go through all the siblings and try to find the right parent, if exists,
1904              * first go through all the next siblings keeping the original order, for positional predicates */
1905             for (node = data_tree; !parsed && node; node = node->next) {
1906                 parent = resolve_partial_json_data_nodeid(id, value_type > LYD_ANYDATA_STRING ? NULL : value, node,
1907                                                           options, &parsed);
1908             }
1909             if (!parsed) {
1910                 for (node = data_tree->prev; !parsed && node->next; node = node->prev) {
1911                     parent = resolve_partial_json_data_nodeid(id, value_type > LYD_ANYDATA_STRING ? NULL : value, node,
1912                                                               options, &parsed);
1913                 }
1914             }
1915         } else {
1916             /* relative path, use only the provided data tree root */
1917             parent = resolve_partial_json_data_nodeid(id, value_type > LYD_ANYDATA_STRING ? NULL : value, data_tree,
1918                                                       options, &parsed);
1919         }
1920         if (parsed == -1) {
1921             return NULL;
1922         }
1923         if (parsed) {
1924             assert(parent);
1925             /* if we parsed something we have a relative path now for sure, otherwise we don't know */
1926             is_relative = 1;
1927 
1928             id += parsed;
1929 
1930             if (!id[0]) {
1931                 /* the node exists, are we supposed to update it or is it default? */
1932                 if (!(options & LYD_PATH_OPT_UPDATE) && (!parent->dflt || (options & LYD_PATH_OPT_DFLT))) {
1933                     LOGVAL(ctx, LYE_PATH_EXISTS, LY_VLOG_STR, path);
1934                     return NULL;
1935                 }
1936 
1937                 /* no change, the default node already exists */
1938                 if (parent->dflt && (options & LYD_PATH_OPT_DFLT)) {
1939                     return NULL;
1940                 }
1941 
1942                 return lyd_new_path_update(parent, value, value_type, options & LYD_PATH_OPT_DFLT);
1943             }
1944         }
1945     }
1946 
1947     backup_is_relative = is_relative;
1948     if ((r = parse_schema_nodeid(id, &mod_name, &mod_name_len, &name, &nam_len, &is_relative, NULL, NULL, 1)) < 1) {
1949         LOGVAL(ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, id[-r], &id[-r]);
1950         return NULL;
1951     }
1952 
1953     if (name[0] == '#') {
1954         if (is_relative) {
1955             LOGVAL(ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, '#', name);
1956             return NULL;
1957         }
1958         yang_data_name = name + 1;
1959         yang_data_name_len = nam_len - 1;
1960         backup_mod_name = mod_name;
1961         backup_mod_name_len = mod_name_len;
1962         /* move to the next node in the path */
1963         id += r;
1964     } else {
1965         is_relative = backup_is_relative;
1966     }
1967 
1968     if ((r = parse_schema_nodeid(id, &mod_name, &mod_name_len, &name, &nam_len, &is_relative, &has_predicate, NULL, 0)) < 1) {
1969         LOGVAL(ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, id[-r], &id[-r]);
1970         return NULL;
1971     }
1972     /* move to the next node in the path */
1973     id += r;
1974 
1975     if (backup_mod_name) {
1976         mod_name = backup_mod_name;
1977         mod_name_len = backup_mod_name_len;
1978     }
1979 
1980     /* prepare everything for the schema search loop */
1981     if (is_relative) {
1982         /* we are relative to data_tree or parent if some part of the path already exists */
1983         if (!data_tree) {
1984             LOGERR(ctx, LY_EINVAL, "%s: provided relative path (%s) without context node.", __func__, path);
1985             return NULL;
1986         } else if (!parent) {
1987             parent = data_tree;
1988         }
1989         sparent = parent->schema;
1990         module = prev_mod = lys_node_module(sparent);
1991     } else {
1992         /* we are starting from scratch, absolute path */
1993         assert(!parent);
1994         if (!mod_name) {
1995             str = strndup(path, (name + nam_len) - path);
1996             LOGVAL(ctx, LYE_PATH_MISSMOD, LY_VLOG_STR, str);
1997             free(str);
1998             return NULL;
1999         }
2000 
2001         module = ly_ctx_nget_module(ctx, mod_name, mod_name_len, NULL, 1);
2002 
2003         if (!module) {
2004             str = strndup(path, (mod_name + mod_name_len) - path);
2005             LOGVAL(ctx, LYE_PATH_INMOD, LY_VLOG_STR, str);
2006             free(str);
2007             return NULL;
2008         }
2009         mod_name = NULL;
2010         mod_name_len = 0;
2011         prev_mod = module;
2012 
2013         sparent = NULL;
2014         if (yang_data_name) {
2015             sparent = lyp_get_yang_data_template(module, yang_data_name, yang_data_name_len);
2016             if (!sparent) {
2017                 str = strndup(path, (yang_data_name + yang_data_name_len) - path);
2018                 LOGVAL(ctx, LYE_PATH_INNODE, LY_VLOG_STR, str);
2019                 free(str);
2020                 return NULL;
2021             }
2022         }
2023     }
2024 
2025     /* create nodes in a loop */
2026     while (1) {
2027         /* find the schema node */
2028         schild = NULL;
2029         while ((schild = lys_getnext(schild, sparent, module, 0))) {
2030             if (schild->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST
2031                                     | LYS_ANYDATA | LYS_NOTIF | LYS_RPC | LYS_ACTION)) {
2032                 /* module comparison */
2033                 if (mod_name) {
2034                     node_mod_name = lys_node_module(schild)->name;
2035                     if (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len]) {
2036                         continue;
2037                     }
2038                 } else if (lys_node_module(schild) != prev_mod) {
2039                     continue;
2040                 }
2041 
2042                 /* name check */
2043                 if (strncmp(schild->name, name, nam_len) || schild->name[nam_len]) {
2044                     continue;
2045                 }
2046 
2047                 /* RPC/action in/out check */
2048                 for (tmp = lys_parent(schild); tmp && (tmp->nodetype == LYS_USES); tmp = lys_parent(tmp));
2049                 if (tmp) {
2050                     if (options & LYD_PATH_OPT_OUTPUT) {
2051                         if (tmp->nodetype == LYS_INPUT) {
2052                             continue;
2053                         }
2054                     } else {
2055                         if (tmp->nodetype == LYS_OUTPUT) {
2056                             continue;
2057                         }
2058                     }
2059                 }
2060 
2061                 break;
2062             }
2063         }
2064 
2065         if (!schild) {
2066             str = strndup(path, (name + nam_len) - path);
2067             LOGVAL(ctx, LYE_PATH_INNODE, LY_VLOG_STR, str);
2068             free(str);
2069             lyd_free(ret);
2070             return NULL;
2071         }
2072 
2073         /* we have the right schema node */
2074         switch (schild->nodetype) {
2075         case LYS_CONTAINER:
2076         case LYS_LIST:
2077         case LYS_NOTIF:
2078         case LYS_RPC:
2079         case LYS_ACTION:
2080             if (options & LYD_PATH_OPT_NOPARENT) {
2081                 /* these were supposed to exist */
2082                 str = strndup(path, (name + nam_len) - path);
2083                 LOGVAL(ctx, LYE_PATH_MISSPAR, LY_VLOG_STR, str);
2084                 free(str);
2085                 lyd_free(ret);
2086                 return NULL;
2087             }
2088             node = _lyd_new(is_relative ? parent : NULL, schild, (options & LYD_PATH_OPT_DFLT) ? 1 : 0);
2089             break;
2090         case LYS_LEAF:
2091         case LYS_LEAFLIST:
2092             str = NULL;
2093             if (has_predicate) {
2094                 if ((r = parse_schema_json_predicate(id, NULL, NULL, &val_name, &val_name_len, &val, &val_len, &has_predicate)) < 1) {
2095                     LOGVAL(ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, id[-r], &id[-r]);
2096                     lyd_free(ret);
2097                     return NULL;
2098                 }
2099                 id += r;
2100 
2101                 if ((val_name[0] != '.') || (val_name_len != 1)) {
2102                     LOGVAL(ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, val_name[0], val_name);
2103                     lyd_free(ret);
2104                     return NULL;
2105                 }
2106 
2107                 str = strndup(val, val_len);
2108                 if (!str) {
2109                     LOGMEM(ctx);
2110                     lyd_free(ret);
2111                     return NULL;
2112                 }
2113             }
2114             if (id[0]) {
2115                 LOGVAL(ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, id[0], id);
2116                 free(str);
2117                 lyd_free(ret);
2118                 return NULL;
2119             }
2120 
2121             node = _lyd_new_leaf(is_relative ? parent : NULL, schild, (str ? str : value),
2122                                  (options & LYD_PATH_OPT_DFLT) ? 1 : 0, options & LYD_PATH_OPT_EDIT);
2123             free(str);
2124             break;
2125         case LYS_ANYXML:
2126         case LYS_ANYDATA:
2127             if (id[0]) {
2128                 LOGVAL(ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, id[0], id);
2129                 lyd_free(ret);
2130                 return NULL;
2131             }
2132             if (value_type <= LYD_ANYDATA_STRING && !value) {
2133                 value_type = LYD_ANYDATA_CONSTSTRING;
2134                 value = "";
2135             }
2136             node = lyd_create_anydata(is_relative ? parent : NULL, schild, value, value_type);
2137             break;
2138         default:
2139             LOGINT(ctx);
2140             node = NULL;
2141             break;
2142         }
2143 
2144         if (!node) {
2145             str = strndup(path, id - path);
2146             if (is_relative) {
2147                 LOGVAL(ctx, LYE_SPEC, LY_VLOG_STR, str, "Failed to create node \"%s\" as a child of \"%s\".",
2148                        schild->name, parent->schema->name);
2149             } else {
2150                 LOGVAL(ctx, LYE_SPEC, LY_VLOG_STR, str, "Failed to create node \"%s\".", schild->name);
2151             }
2152             free(str);
2153             lyd_free(ret);
2154             return NULL;
2155         }
2156         /* special case when we are creating a sibling of a top-level data node */
2157         if (!is_relative) {
2158             if (data_tree) {
2159                 for (; data_tree->next; data_tree = data_tree->next);
2160                 if (lyd_insert_after(data_tree, node)) {
2161                     lyd_free(ret);
2162                     return NULL;
2163                 }
2164             }
2165             is_relative = 1;
2166         }
2167 
2168         if (first_iter) {
2169             /* sort if needed, but only when inserted somewhere */
2170             sparent = node->schema;
2171             do {
2172                 sparent = lys_parent(sparent);
2173             } while (sparent && (sparent->nodetype != ((options & LYD_PATH_OPT_OUTPUT) ? LYS_OUTPUT : LYS_INPUT)));
2174             if (sparent && lyd_schema_sort(node, 0)) {
2175                 lyd_free(ret);
2176                 return NULL;
2177             }
2178 
2179             /* set first created node */
2180             ret = node;
2181             first_iter = 0;
2182         }
2183 
2184         parsed = 0;
2185         if ((schild->nodetype == LYS_LIST) && has_predicate && lyd_new_path_list_predicate(node, name, id, &parsed)) {
2186             lyd_free(ret);
2187             return NULL;
2188         }
2189         id += parsed;
2190 
2191         if (!id[0]) {
2192             /* we are done */
2193             if (options & LYD_PATH_OPT_NOPARENTRET) {
2194                 /* last created node */
2195                 return node;
2196             }
2197             return ret;
2198         }
2199 
2200         /* prepare for another iteration */
2201         parent = node;
2202         sparent = schild;
2203         prev_mod = lys_node_module(schild);
2204 
2205         /* parse another node */
2206         if ((r = parse_schema_nodeid(id, &mod_name, &mod_name_len, &name, &nam_len, &is_relative, &has_predicate, NULL, 0)) < 1) {
2207             LOGVAL(ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, id[-r], &id[-r]);
2208             lyd_free(ret);
2209             return NULL;
2210         }
2211         id += r;
2212 
2213         /* if a key of a list was supposed to be created, it is created as a part of the list instance creation */
2214         if ((schild->nodetype == LYS_LIST) && !mod_name) {
2215             slist = (const struct lys_node_list *)schild;
2216             for (i = 0; i < slist->keys_size; ++i) {
2217                 if (!strncmp(slist->keys[i]->name, name, nam_len) && !slist->keys[i]->name[nam_len]) {
2218                     /* the path continues? there cannot be anything after a key (leaf) */
2219                     if (id[0]) {
2220                         LOGVAL(ctx, LYE_PATH_INCHAR, LY_VLOG_NONE, NULL, id[0], id);
2221                         lyd_free(ret);
2222                         return NULL;
2223                     }
2224                     return ret;
2225                 }
2226             }
2227         }
2228     }
2229 
2230     LOGINT(ctx);
2231     return NULL;
2232 }
2233 
2234 API unsigned int
lyd_list_pos(const struct lyd_node * node)2235 lyd_list_pos(const struct lyd_node *node)
2236 {
2237     FUN_IN;
2238 
2239     unsigned int pos;
2240     struct lys_node *schema;
2241 
2242     if (!node || ((node->schema->nodetype != LYS_LIST) && (node->schema->nodetype != LYS_LEAFLIST))) {
2243         return 0;
2244     }
2245 
2246     schema = node->schema;
2247     pos = 0;
2248     do {
2249         if (node->schema == schema) {
2250             ++pos;
2251         }
2252         node = node->prev;
2253     } while (node->next);
2254 
2255     return pos;
2256 }
2257 
2258 static struct lyd_node *
lyd_new_dummy(struct lyd_node * root,struct lyd_node * parent,const struct lys_node * schema,const char * value,int dflt)2259 lyd_new_dummy(struct lyd_node *root, struct lyd_node *parent, const struct lys_node *schema, const char *value, int dflt)
2260 {
2261     unsigned int index;
2262     struct ly_set *spath;
2263     const struct lys_node *siter;
2264     struct lyd_node *iter, *dummy = NULL;
2265 
2266     assert(schema);
2267     assert(schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYDATA | LYS_NOTIF |
2268                                LYS_RPC | LYS_ACTION));
2269 
2270     spath = ly_set_new();
2271     if (!spath) {
2272         LOGMEM(schema->module->ctx);
2273         return NULL;
2274     }
2275 
2276     if (!parent && root) {
2277         /* find data root */
2278         for (; root->parent; root = root->parent);   /* vertical move (up) */
2279         for (; root->prev->next; root = root->prev); /* horizontal move (left) */
2280     }
2281 
2282     /* build schema path */
2283     for (siter = schema; siter; siter = lys_parent(siter)) {
2284         /* stop if we know some of the parents */
2285         if (parent && parent->schema == siter) {
2286             break;
2287         }
2288 
2289         if (siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYDATA | LYS_NOTIF |
2290                                LYS_RPC | LYS_ACTION)) {
2291             /* we have a node that can appear in data tree */
2292             ly_set_add(spath, (void*)siter, LY_SET_OPT_USEASLIST);
2293         } /* else skip the rest node types */
2294     }
2295 
2296     assert(spath->number > 0);
2297     index = spath->number;
2298     if (!parent && !(spath->set.s[index - 1]->nodetype & LYS_LEAFLIST)) {
2299         /* start by searching for the top-level parent */
2300         LY_TREE_FOR(root, iter) {
2301             if (iter->schema == spath->set.s[index - 1]) {
2302                 parent = iter;
2303                 index--;
2304                 break;
2305             }
2306         }
2307     }
2308 
2309     iter = parent;
2310     while (iter && index && !(spath->set.s[index - 1]->nodetype & LYS_LEAFLIST)) {
2311         /* search for closer parent on the path */
2312         LY_TREE_FOR(parent->child, iter) {
2313             if (iter->schema == spath->set.s[index - 1]) {
2314                 index--;
2315                 parent = iter;
2316                 break;
2317             }
2318         }
2319     }
2320     while (index) {
2321         /* create the missing part of the path */
2322         switch (spath->set.s[index - 1]->nodetype) {
2323         case LYS_LEAF:
2324         case LYS_LEAFLIST:
2325             iter = _lyd_new_leaf(parent, spath->set.s[index - 1], value, dflt, 1);
2326             break;
2327         case LYS_CONTAINER:
2328         case LYS_LIST:
2329             iter = _lyd_new(parent, spath->set.s[index - 1], dflt);
2330             break;
2331         case LYS_ANYXML:
2332         case LYS_ANYDATA:
2333             iter = lyd_create_anydata(parent, spath->set.s[index - 1], "", LYD_ANYDATA_CONSTSTRING);
2334             break;
2335         default:
2336             goto error;
2337         }
2338         if (!iter) {
2339             LOGINT(schema->module->ctx);
2340             goto error;
2341         }
2342 
2343         /* we say it is valid and it is dummy */
2344         iter->validity = LYD_VAL_INUSE;
2345 
2346         if (!dummy) {
2347             dummy = iter;
2348         }
2349 
2350         /* continue */
2351         parent = iter;
2352         index--;
2353     }
2354 
2355     ly_set_free(spath);
2356 
2357     return dummy;
2358 
2359 error:
2360     ly_set_free(spath);
2361     lyd_free(dummy);
2362     return NULL;
2363 }
2364 
2365 static struct lys_node *
lys_get_schema_inctx(struct lys_node * schema,struct ly_ctx * ctx)2366 lys_get_schema_inctx(struct lys_node *schema, struct ly_ctx *ctx)
2367 {
2368     const struct lys_module *mod, *trg_mod = NULL;
2369     struct lys_node *parent, *first_sibling = NULL, *iter = NULL;
2370     struct ly_set *parents;
2371     unsigned int index;
2372     uint32_t idx;
2373     void **ptr;
2374 
2375     if (!ctx || schema->module->ctx == ctx) {
2376         /* we have the same context */
2377         return schema;
2378     }
2379 
2380     /* store the parents chain */
2381     parents = ly_set_new();
2382     for (parent = schema; parent; parent = lys_parent(parent)) {
2383         /* note - augments are skipped so we will work only with the implemented modules
2384          * (where the augments are applied) */
2385         if (parent->nodetype != LYS_USES) {
2386             ly_set_add(parents, parent, LY_SET_OPT_USEASLIST);
2387         }
2388     }
2389     assert(parents->number);
2390     index = parents->number - 1;
2391 
2392     /* process the parents from the top level */
2393     /* for the top-level node, we have to locate the module first */
2394     parent = parents->set.s[index];
2395     if (parent->nodetype == LYS_EXT) {
2396         ptr = lys_ext_complex_get_substmt(LY_STMT_NODE, (struct lys_ext_instance_complex *)parent, NULL);
2397         if (!ptr) {
2398             ly_set_free(parents);
2399             return NULL;
2400         }
2401         first_sibling = *(struct lys_node **)ptr;
2402         parent = parents->set.s[--index];
2403     }
2404     idx = 0;
2405     while ((mod = ly_ctx_get_module_iter(ctx, &idx))) {
2406         trg_mod = lys_node_module(parent);
2407         /* check module name */
2408         if (strcmp(mod->name, trg_mod->name)) {
2409             continue;
2410         }
2411 
2412         /* check revision */
2413         if ((!mod->rev_size && !trg_mod->rev_size) ||
2414                 (mod->rev_size && trg_mod->rev_size && !strcmp(mod->rev[0].date, trg_mod->rev[0].date))) {
2415             /* we have match */
2416             break;
2417         }
2418     }
2419     /* try data callback */
2420     if (!mod && trg_mod && ctx->data_clb) {
2421         LOGDBG(LY_LDGYANG, "Attempting to load '%s' into context using callback ...", trg_mod->name);
2422         mod = ctx->data_clb(ctx, trg_mod->name, NULL, 0, ctx->data_clb_data);
2423     }
2424     if (!mod) {
2425         ly_set_free(parents);
2426         return NULL;
2427     }
2428     if (!first_sibling) {
2429         first_sibling = mod->data;
2430     }
2431 
2432     /* now search in the schema tree for the matching node */
2433     while (1) {
2434         lys_get_sibling(first_sibling, trg_mod->name, 0, parent->name, 0, parent->nodetype,
2435                         (const struct lys_node **)&iter);
2436         if (!iter) {
2437             /* not found, iter will be used as NULL result */
2438             break;
2439         }
2440 
2441         if (index == 0) {
2442             /* we are done, iter is the result */
2443             break;
2444         } else {
2445             /* we are going to continue, so update variables for the next loop */
2446             first_sibling = iter->child;
2447             parent = parents->set.s[--index];
2448             iter = NULL;
2449         }
2450     }
2451 
2452     ly_set_free(parents);
2453     return iter;
2454 }
2455 
2456 static struct lys_node *
lyd_get_schema_inctx(const struct lyd_node * node,struct ly_ctx * ctx)2457 lyd_get_schema_inctx(const struct lyd_node *node, struct ly_ctx *ctx)
2458 {
2459     assert(node);
2460 
2461     return lys_get_schema_inctx(node->schema, ctx);
2462 }
2463 
2464 /* both target and source were validated */
2465 static void
lyd_merge_node_update(struct lyd_node * target,struct lyd_node * source,int options)2466 lyd_merge_node_update(struct lyd_node *target, struct lyd_node *source, int options)
2467 {
2468     struct ly_ctx *ctx;
2469     struct lyd_node_leaf_list *trg_leaf, *src_leaf;
2470     struct lyd_node_anydata *trg_any, *src_any;
2471     int len;
2472 
2473     assert(target->schema->nodetype & (LYS_LEAF | LYS_ANYDATA));
2474     ctx = target->schema->module->ctx;
2475 
2476     if (source->dflt && (options & LYD_OPT_EXPLICIT)) {
2477         /* keep the target node whatever it is */
2478         return;
2479     }
2480 
2481     if (ctx == source->schema->module->ctx) {
2482         /* source and targets are in the same context */
2483         if (target->schema->nodetype == LYS_LEAF) {
2484             trg_leaf = (struct lyd_node_leaf_list *)target;
2485             src_leaf = (struct lyd_node_leaf_list *)source;
2486 
2487             lydict_remove(ctx, trg_leaf->value_str);
2488             trg_leaf->value_str = lydict_insert(ctx, src_leaf->value_str, 0);
2489             trg_leaf->value_type = src_leaf->value_type;
2490             if (trg_leaf->value_type == LY_TYPE_LEAFREF) {
2491                 lyp_parse_value(&((struct lys_node_leaf *)trg_leaf->schema)->type, &trg_leaf->value_str,
2492                                 NULL, trg_leaf, NULL, NULL, 1, src_leaf->dflt);
2493             } else {
2494                 lyd_free_value(trg_leaf->value, trg_leaf->value_type, trg_leaf->value_flags,
2495                                &((struct lys_node_leaf *)trg_leaf->schema)->type, trg_leaf->value_str, NULL, NULL, NULL);
2496                 trg_leaf->value = src_leaf->value;
2497                 /* so that it is not freed */
2498                 src_leaf->value.uint64 = 0;
2499             }
2500             trg_leaf->dflt = src_leaf->dflt;
2501         } else { /* ANYDATA */
2502             trg_any = (struct lyd_node_anydata *)target;
2503             src_any = (struct lyd_node_anydata *)source;
2504 
2505             switch(trg_any->value_type) {
2506             case LYD_ANYDATA_CONSTSTRING:
2507             case LYD_ANYDATA_SXML:
2508             case LYD_ANYDATA_JSON:
2509                 lydict_remove(ctx, trg_any->value.str);
2510                 break;
2511             case LYD_ANYDATA_DATATREE:
2512                 lyd_free_withsiblings(trg_any->value.tree);
2513                 break;
2514             case LYD_ANYDATA_XML:
2515                 lyxml_free_withsiblings(ctx, trg_any->value.xml);
2516                 break;
2517             case LYD_ANYDATA_LYB:
2518                 free(trg_any->value.mem);
2519                 break;
2520             case LYD_ANYDATA_STRING:
2521             case LYD_ANYDATA_SXMLD:
2522             case LYD_ANYDATA_JSOND:
2523             case LYD_ANYDATA_LYBD:
2524                 /* dynamic strings are used only as input parameters */
2525                 assert(0);
2526                 break;
2527             }
2528 
2529             trg_any->value_type = src_any->value_type;
2530             trg_any->value = src_any->value;
2531 
2532             src_any->value_type = LYD_ANYDATA_DATATREE;
2533             src_any->value.tree = NULL;
2534         }
2535     } else {
2536         /* we have different contexts for the target and source */
2537         if (target->schema->nodetype == LYS_LEAF) {
2538             trg_leaf = (struct lyd_node_leaf_list *)target;
2539             src_leaf = (struct lyd_node_leaf_list *)source;
2540 
2541             lydict_remove(ctx, trg_leaf->value_str);
2542             trg_leaf->value_str = lydict_insert(ctx, src_leaf->value_str, 0);
2543             lyd_free_value(trg_leaf->value, trg_leaf->value_type, trg_leaf->value_flags,
2544                            &((struct lys_node_leaf *)trg_leaf->schema)->type, trg_leaf->value_str, NULL, NULL, NULL);
2545             trg_leaf->value_type = src_leaf->value_type;
2546             trg_leaf->dflt = src_leaf->dflt;
2547 
2548             switch (trg_leaf->value_type) {
2549             case LY_TYPE_BINARY:
2550             case LY_TYPE_STRING:
2551                 /* value_str pointer is shared in these cases */
2552                 trg_leaf->value.string = trg_leaf->value_str;
2553                 break;
2554             case LY_TYPE_LEAFREF:
2555                 lyp_parse_value(&((struct lys_node_leaf *)trg_leaf->schema)->type, &trg_leaf->value_str,
2556                                 NULL, trg_leaf, NULL, NULL, 1, trg_leaf->dflt);
2557                 break;
2558             case LY_TYPE_INST:
2559                 trg_leaf->value.instance = NULL;
2560                 break;
2561             case LY_TYPE_UNION:
2562                 /* unresolved union (this must be non-validated tree), duplicate the stored string (duplicated
2563                  * because of possible change of the value in case of instance-identifier) */
2564                 trg_leaf->value.string = lydict_insert(ctx, src_leaf->value.string, 0);
2565                 break;
2566             case LY_TYPE_BITS:
2567             case LY_TYPE_ENUM:
2568             case LY_TYPE_IDENT:
2569                 /* in case of duplicating bits (no matter if in the same context or not) or enum and identityref into
2570                  * a different context, searching for the type and duplicating the data is almost as same as resolving
2571                  * the string value, so due to a simplicity, parse the value for the duplicated leaf */
2572                 lyp_parse_value(&((struct lys_node_leaf *)trg_leaf->schema)->type, &trg_leaf->value_str, NULL,
2573                                 trg_leaf, NULL, NULL, 1, trg_leaf->dflt);
2574                 break;
2575             default:
2576                 trg_leaf->value = src_leaf->value;
2577                 break;
2578             }
2579         } else { /* ANYDATA */
2580             trg_any = (struct lyd_node_anydata *)target;
2581             src_any = (struct lyd_node_anydata *)source;
2582 
2583             switch(trg_any->value_type) {
2584             case LYD_ANYDATA_CONSTSTRING:
2585             case LYD_ANYDATA_SXML:
2586             case LYD_ANYDATA_JSON:
2587                 lydict_remove(ctx, trg_any->value.str);
2588                 break;
2589             case LYD_ANYDATA_DATATREE:
2590                 lyd_free_withsiblings(trg_any->value.tree);
2591                 break;
2592             case LYD_ANYDATA_XML:
2593                 lyxml_free_withsiblings(ctx, trg_any->value.xml);
2594                 break;
2595             case LYD_ANYDATA_LYB:
2596                 free(trg_any->value.mem);
2597                 break;
2598             case LYD_ANYDATA_STRING:
2599             case LYD_ANYDATA_SXMLD:
2600             case LYD_ANYDATA_JSOND:
2601             case LYD_ANYDATA_LYBD:
2602                 /* dynamic strings are used only as input parameters */
2603                 assert(0);
2604                 break;
2605             }
2606 
2607             trg_any->value_type = src_any->value_type;
2608             if ((void*)src_any->value.tree) {
2609                 /* there is a value to duplicate */
2610                 switch (trg_any->value_type) {
2611                 case LYD_ANYDATA_CONSTSTRING:
2612                 case LYD_ANYDATA_SXML:
2613                 case LYD_ANYDATA_JSON:
2614                     trg_any->value.str = lydict_insert(ctx, src_any->value.str, 0);
2615                     break;
2616                 case LYD_ANYDATA_DATATREE:
2617                     trg_any->value.tree = lyd_dup_withsiblings_to_ctx(src_any->value.tree, 1, ctx);
2618                     break;
2619                 case LYD_ANYDATA_XML:
2620                     trg_any->value.xml = lyxml_dup_elem(ctx, src_any->value.xml, NULL, 1, 1);
2621                     break;
2622                 case LYD_ANYDATA_LYB:
2623                     len = lyd_lyb_data_length(src_any->value.mem);
2624                     if (len == -1) {
2625                         LOGERR(ctx, LY_EINVAL, "Invalid LYB data.");
2626                         return;
2627                     }
2628                     trg_any->value.mem = malloc(len);
2629                     LY_CHECK_ERR_RETURN(!trg_any->value.mem, LOGMEM(ctx), );
2630                     memcpy(trg_any->value.mem, src_any->value.mem, len);
2631                     break;
2632                 case LYD_ANYDATA_STRING:
2633                 case LYD_ANYDATA_SXMLD:
2634                 case LYD_ANYDATA_JSOND:
2635                 case LYD_ANYDATA_LYBD:
2636                     /* dynamic strings are used only as input parameters */
2637                     assert(0);
2638                     break;
2639                 }
2640             }
2641         }
2642     }
2643 }
2644 
2645 /* return: 0 (not equal), 1 (equal), -1 (error) */
2646 static int
lyd_merge_node_schema_equal(struct lyd_node * node1,struct lyd_node * node2)2647 lyd_merge_node_schema_equal(struct lyd_node *node1, struct lyd_node *node2)
2648 {
2649     struct lys_node *sch1;
2650 
2651     if (node1->schema->module->ctx == node2->schema->module->ctx) {
2652         if (node1->schema != node2->schema) {
2653             return 0;
2654         }
2655     } else {
2656         /* the nodes are in different contexts, get the appropriate schema nodes from the
2657          * same context */
2658         sch1 = lyd_get_schema_inctx(node1, node2->schema->module->ctx);
2659         if (!sch1) {
2660             LOGERR(node2->schema->module->ctx, LY_EINVAL, "Target context does not contain a required schema node (%s:%s).",
2661                    lyd_node_module(node1)->name, node1->schema->name);
2662             return -1;
2663         } else if (sch1 != node2->schema) {
2664             /* not matching nodes */
2665             return 0;
2666         }
2667     }
2668 
2669     return 1;
2670 }
2671 
2672 /* return: 0 (not equal), 1 (equal), 2 (equal and state leaf-/list marked), -1 (error) */
2673 static int
lyd_merge_node_equal(struct lyd_node * node1,struct lyd_node * node2)2674 lyd_merge_node_equal(struct lyd_node *node1, struct lyd_node *node2)
2675 {
2676     int ret;
2677 
2678     switch (node1->schema->nodetype) {
2679     case LYS_CONTAINER:
2680     case LYS_LEAF:
2681     case LYS_ANYXML:
2682     case LYS_ANYDATA:
2683     case LYS_RPC:
2684     case LYS_ACTION:
2685     case LYS_NOTIF:
2686         return 1;
2687     case LYS_LEAFLIST:
2688         if (node1->validity & LYD_VAL_INUSE) {
2689             /* this instance was already matched, we want to find another so that the number of the istances matches */
2690             assert(node1->schema->flags & LYS_CONFIG_R);
2691             return 0;
2692         }
2693 
2694         ret = lyd_list_equal(node1, node2, 1);
2695         if ((ret == 1) && (node1->schema->flags & LYS_CONFIG_R)) {
2696             /* mark it as matched */
2697             node1->validity |= LYD_VAL_INUSE;
2698             ret = 2;
2699         }
2700         return ret;
2701     case LYS_LIST:
2702         if (node1->validity & LYD_VAL_INUSE) {
2703             /* this instance was already matched, we want to find another so that the number of the istances matches */
2704             assert(!((struct lys_node_list *)node1->schema)->keys_size);
2705             return 0;
2706         }
2707 
2708         ret = lyd_list_equal(node1, node2, 1);
2709         if ((ret == 1) && !((struct lys_node_list *)node1->schema)->keys_size) {
2710             /* mark it as matched */
2711             node1->validity |= LYD_VAL_INUSE;
2712             ret = 2;
2713         }
2714         return ret;
2715     default:
2716         break;
2717     }
2718 
2719     LOGINT(node2->schema->module->ctx);
2720     return -1;
2721 }
2722 
2723 /* spends source */
2724 static int
lyd_merge_parent_children(struct lyd_node * target,struct lyd_node * source,int options)2725 lyd_merge_parent_children(struct lyd_node *target, struct lyd_node *source, int options)
2726 {
2727     struct lyd_node *trg_parent, *src, *src_backup, *src_elem, *src_elem_backup, *src_next, *trg_child, *trg_parent_backup;
2728     int ret, clear_flag = 0;
2729     struct ly_ctx *ctx = target->schema->module->ctx; /* shortcut */
2730 
2731     LY_TREE_FOR_SAFE(source, src_backup, src) {
2732         for (src_elem = src_next = src, trg_parent = target;
2733             src_elem;
2734             src_elem = src_next) {
2735 
2736             ret = 0;
2737 
2738 #ifdef LY_ENABLED_CACHE
2739             struct lyd_node **trg_child_p;
2740 
2741             /* trees are supposed to be validated so all nodes must have their hash, but lets not be that strict */
2742             if (!src_elem->hash) {
2743                 lyd_hash(src_elem);
2744             }
2745 
2746             if (trg_parent->ht) {
2747                 trg_child = NULL;
2748                 if (!lyht_find(trg_parent->ht, &src_elem, src_elem->hash, (void **)&trg_child_p)) {
2749                     trg_child = *trg_child_p;
2750                     ret = 1;
2751 
2752                     /* it is a bit more difficult with keyless state lists and leaf-lists */
2753                     if (((trg_child->schema->nodetype == LYS_LIST) && !((struct lys_node_list *)trg_child->schema)->keys_size)
2754                             || ((trg_child->schema->nodetype == LYS_LEAFLIST) && (trg_child->schema->flags & LYS_CONFIG_R))) {
2755                         assert(trg_child->schema->flags & LYS_CONFIG_R);
2756 
2757                         while (trg_child && (trg_child->validity & LYD_VAL_INUSE)) {
2758                             /* state lists, find one not-already-found */
2759                             if (lyht_find_next(trg_parent->ht, &trg_child, trg_child->hash, (void **)&trg_child_p)) {
2760                                 trg_child = NULL;
2761                             } else {
2762                                 trg_child = *trg_child_p;
2763                             }
2764                         }
2765                         if (trg_child) {
2766                             /* mark it as matched */
2767                             trg_child->validity |= LYD_VAL_INUSE;
2768                             ret = 2;
2769                         } else {
2770                             /* actually, it was matched already and no other instance found, so now not a match */
2771                             ret = 0;
2772                         }
2773                     }
2774                 }
2775             } else
2776 #endif
2777             {
2778                 LY_TREE_FOR(trg_parent->child, trg_child) {
2779                     /* schema match, data match? */
2780                     ret = lyd_merge_node_schema_equal(trg_child, src_elem);
2781                     if (ret == 1) {
2782                         ret = lyd_merge_node_equal(trg_child, src_elem);
2783                     }
2784                     if (ret != 0) {
2785                         /* even data match */
2786                         break;
2787                     }
2788                 }
2789             }
2790 
2791             if (ret > 0) {
2792                 if (trg_child->schema->nodetype & (LYS_LEAF | LYS_ANYDATA)) {
2793                     lyd_merge_node_update(trg_child, src_elem, options);
2794                 } else if (ret == 2) {
2795                     clear_flag = 1;
2796                 }
2797             } else if (ret == -1) {
2798                 /* error */
2799                 lyd_free_withsiblings(source);
2800                 return 1;
2801             }
2802 
2803             /* first prepare for the next iteration */
2804             src_elem_backup = src_elem;
2805             trg_parent_backup = trg_parent;
2806             if (((src_elem->schema->nodetype == LYS_CONTAINER) || ((src_elem->schema->nodetype == LYS_LIST)
2807                     && ((struct lys_node_list *)src_elem->schema)->keys_size)) && src_elem->child && trg_child) {
2808                 /* go into children */
2809                 src_next = src_elem->child;
2810                 trg_parent = trg_child;
2811             } else {
2812                 /* no children (or the whole subtree will be inserted), try siblings */
2813                 if (src_elem == src) {
2814                     /* we are done with this subtree */
2815                     if (trg_child) {
2816                         /* it's an empty container, list without keys, or an already-updated leaf/anydata, nothing else to do */
2817                         break;
2818                     } else {
2819                         /* ... but we still need to insert it */
2820                         src_next = NULL;
2821                         goto src_insert;
2822                     }
2823                 } else {
2824                     src_next = src_elem->next;
2825                     /* trg_parent does not change */
2826                 }
2827             }
2828             while (!src_next) {
2829                 src_elem = src_elem->parent;
2830                 if (src_elem->parent == src->parent) {
2831                     /* we are done, no next element to process */
2832                     break;
2833                 }
2834 
2835                 /* parent is already processed, go to its sibling */
2836                 src_next = src_elem->next;
2837                 trg_parent = trg_parent->parent;
2838             }
2839 
2840             if (!trg_child) {
2841 src_insert:
2842                 /* we need to insert the whole subtree */
2843                 if (ctx == src_elem_backup->schema->module->ctx) {
2844                     /* same context - unlink the subtree and insert it into the target */
2845                     lyd_unlink(src_elem_backup);
2846                 } else {
2847                     /* different contexts - before inserting subtree, instead of unlinking, duplicate it into the
2848                      * target context */
2849                     src_elem_backup = lyd_dup_to_ctx(src_elem_backup, 1, ctx);
2850                 }
2851 
2852                 if (src_elem == source) {
2853                     /* it will be linked into another data tree and the pointers changed */
2854                     source = source->next;
2855                 }
2856 
2857                 /* insert subtree into the target */
2858                 if (lyd_insert(trg_parent_backup, src_elem_backup)) {
2859                     LOGINT(ctx);
2860                     lyd_free_withsiblings(source);
2861                     return 1;
2862                 }
2863                 if (src_elem == src) {
2864                     /* we are finished for this src */
2865                     break;
2866                 }
2867             }
2868         }
2869     }
2870 
2871     lyd_free_withsiblings(source);
2872     if (clear_flag) {
2873         return 2;
2874     }
2875     return 0;
2876 }
2877 
2878 /* spends source */
2879 static int
lyd_merge_siblings(struct lyd_node * target,struct lyd_node * source,int options)2880 lyd_merge_siblings(struct lyd_node *target, struct lyd_node *source, int options)
2881 {
2882     struct lyd_node *trg, *src, *src_backup, *ins;
2883     int ret, clear_flag = 0;
2884     struct ly_ctx *ctx = target->schema->module->ctx; /* shortcut */
2885 
2886     while (target->prev->next) {
2887         target = target->prev;
2888     }
2889 
2890     LY_TREE_FOR_SAFE(source, src_backup, src) {
2891         LY_TREE_FOR(target, trg) {
2892             /* sibling found, merge it */
2893             ret = lyd_merge_node_schema_equal(trg, src);
2894             if (ret == 1) {
2895                 ret = lyd_merge_node_equal(trg, src);
2896             }
2897             if (ret > 0) {
2898                 if (ret == 2) {
2899                     clear_flag = 1;
2900                 }
2901 
2902                 switch (trg->schema->nodetype) {
2903                 case LYS_LEAF:
2904                 case LYS_ANYXML:
2905                 case LYS_ANYDATA:
2906                     lyd_merge_node_update(trg, src, options);
2907                     break;
2908                 case LYS_LEAFLIST:
2909                     /* it's already there, nothing to do */
2910                     break;
2911                 case LYS_LIST:
2912                 case LYS_CONTAINER:
2913                 case LYS_NOTIF:
2914                 case LYS_RPC:
2915                 case LYS_INPUT:
2916                 case LYS_OUTPUT:
2917                     ret = lyd_merge_parent_children(trg, src->child, options);
2918                     if (ret == 2) {
2919                         clear_flag = 1;
2920                     } else if (ret) {
2921                         lyd_free_withsiblings(source);
2922                         return 1;
2923                     }
2924                     break;
2925                 default:
2926                     LOGINT(ctx);
2927                     lyd_free_withsiblings(source);
2928                     return 1;
2929                 }
2930                 break;
2931             } else if (ret == -1) {
2932                 lyd_free_withsiblings(source);
2933                 return 1;
2934             } /* else not equal, nothing to do */
2935         }
2936 
2937         /* sibling not found, insert it */
2938         if (!trg) {
2939             if (ctx != src->schema->module->ctx) {
2940                 ins = lyd_dup_to_ctx(src, 1, ctx);
2941             } else {
2942                 lyd_unlink(src);
2943                 if (src == source) {
2944                     /* just so source is not freed, we inserted it and need it further */
2945                     source = src_backup;
2946                 }
2947                 ins = src;
2948             }
2949             lyd_insert_after(target->prev, ins);
2950         }
2951     }
2952 
2953     lyd_free_withsiblings(source);
2954     if (clear_flag) {
2955         return 2;
2956     }
2957     return 0;
2958 }
2959 
2960 API int
lyd_merge_to_ctx(struct lyd_node ** trg,const struct lyd_node * src,int options,struct ly_ctx * ctx)2961 lyd_merge_to_ctx(struct lyd_node **trg, const struct lyd_node *src, int options, struct ly_ctx *ctx)
2962 {
2963     FUN_IN;
2964 
2965     struct lyd_node *node = NULL, *node2, *target, *trg_merge_start, *src_merge_start = NULL;
2966     const struct lyd_node *iter;
2967     struct lys_node *src_snode, *sch = NULL;
2968     int i, src_depth, depth, first_iter, ret, dflt = 1;
2969     const struct lys_node *parent = NULL;
2970 
2971     if (!trg || !(*trg) || !src) {
2972         LOGARG;
2973         return -1;
2974     }
2975     target = *trg;
2976 
2977     parent = lys_parent(target->schema);
2978 
2979     /* go up all uses */
2980     while (parent && (parent->nodetype == LYS_USES)) {
2981         parent = lys_parent(parent);
2982     }
2983 
2984     if (parent && !lyp_get_yang_data_template_name(target)) {
2985         LOGERR(parent->module->ctx, LY_EINVAL, "Target not a top-level data tree.");
2986         return -1;
2987     }
2988 
2989     /* get know if we are converting data into a different context */
2990     if (ctx && target->schema->module->ctx != ctx) {
2991         /* target's data tree context differs from the target context, move the target
2992          * data tree into the target context */
2993 
2994         /* get the first target's top-level and store it as the result */
2995         for (; target->prev->next; target = target->prev);
2996         *trg = target;
2997 
2998         for (node = NULL, trg_merge_start = target; target; target = target->next) {
2999             node2 = lyd_dup_to_ctx(target, 1, ctx);
3000             if (!node2) {
3001                 goto error;
3002             }
3003             if (node) {
3004                 if (lyd_insert_after(node->prev, node2)) {
3005                     goto error;
3006                 }
3007             } else {
3008                 node = node2;
3009             }
3010         }
3011         target = node;
3012         node = NULL;
3013     } else if (src->schema->module->ctx != target->schema->module->ctx) {
3014         /* the source data will be converted into the target's context during the merge */
3015         ctx = target->schema->module->ctx;
3016     } else if (ctx == src->schema->module->ctx) {
3017         /* no conversion is needed */
3018         ctx = NULL;
3019     }
3020 
3021     /* find source top-level schema node */
3022     for (src_snode = src->schema, src_depth = 0;
3023          (src_snode = lys_parent(src_snode)) && src_snode->nodetype != LYS_EXT;
3024          ++src_depth);
3025 
3026     /* find first shared missing schema parent of the subtrees */
3027     trg_merge_start = target;
3028     depth = 0;
3029     first_iter = 1;
3030     if (src_depth) {
3031         /* we are going to create missing parents in the following loop,
3032          * but we will need to know a dflt flag for them. In case the newly
3033          * created parent is going to have at least one non-default child,
3034          * it will be also non-default, otherwise it will be the default node */
3035         if (options & LYD_OPT_NOSIBLINGS) {
3036             dflt = src->dflt;
3037         } else {
3038             LY_TREE_FOR(src, iter) {
3039                 if (!iter->dflt) {
3040                     /* non default sibling -> parent is going to be
3041                      * created also as non-default */
3042                     dflt = 0;
3043                     break;
3044                 }
3045             }
3046         }
3047     }
3048     while (1) {
3049         /* going from down (source root) to up (top-level or the common node with target */
3050         do {
3051             for (src_snode = src->schema, i = 0; i < src_depth - depth; src_snode = lys_parent(src_snode), ++i);
3052             ++depth;
3053         } while (src_snode != src->schema && (src_snode->nodetype & (LYS_CHOICE | LYS_CASE | LYS_USES)));
3054 
3055         if (src_snode == src->schema) {
3056             break;
3057         }
3058 
3059         if (src_snode->nodetype != LYS_CONTAINER) {
3060             /* we would have to create a list (the only data node with children except container), impossible */
3061             LOGERR(ctx, LY_EINVAL, "Cannot create %s \"%s\" for the merge.", strnodetype(src_snode->nodetype), src_snode->name);
3062             goto error;
3063         }
3064 
3065         /* have we created any missing containers already? if we did,
3066          * it is totally useless to search for match, there won't ever be */
3067         if (!src_merge_start) {
3068             if (first_iter) {
3069                 node = trg_merge_start;
3070                 first_iter = 0;
3071             } else {
3072                 node = trg_merge_start->child;
3073             }
3074 
3075             /* find it in target data nodes */
3076             LY_TREE_FOR(node, node) {
3077                 if (ctx) {
3078                     /* we have the schema nodes in the different context */
3079                     sch = lys_get_schema_inctx(src_snode, ctx);
3080                     if (!sch) {
3081                         LOGERR(ctx, LY_EINVAL, "Target context does not contain schema node for the data node being "
3082                                "merged (%s:%s).", lys_node_module(src_snode)->name, src_snode->name);
3083                         goto error;
3084                     }
3085                 } else {
3086                     /* the context is same and comparison of the schema nodes will works fine */
3087                     sch = src_snode;
3088                 }
3089 
3090                 if (node->schema == sch) {
3091                     trg_merge_start = node;
3092                     break;
3093                 }
3094             }
3095 
3096             if (!(options & LYD_OPT_DESTRUCT)) {
3097                 /* the source tree will be duplicated, so to save some work in case
3098                  * of different target context, create also the parents nodes in the
3099                  * correct context */
3100                 src_snode = sch;
3101             }
3102         } else if (ctx && !(options & LYD_OPT_DESTRUCT)) {
3103             /* get the schema node in the correct (target) context, same as above,
3104              * this is done to save some work and have the source in the same context
3105              * when the provided source tree is below duplicated in the target context
3106              * and connected into the parents created here */
3107             src_snode = lys_get_schema_inctx(src_snode, ctx);
3108             if (!src_snode) {
3109                 LOGERR(ctx, LY_EINVAL, "Target context does not contain schema node for the data node being "
3110                        "merged (%s:%s).", lys_node_module(src_snode)->name, src_snode->name);
3111                 goto error;
3112             }
3113         }
3114 
3115         if (!node) {
3116             /* it is not there, create it */
3117             node2 = _lyd_new(NULL, src_snode, dflt);
3118             if (!src_merge_start) {
3119                 src_merge_start = node2;
3120             } else {
3121                 if (lyd_insert(node2, src_merge_start)) {
3122                     goto error;
3123                 }
3124                 src_merge_start = node2;
3125             }
3126         }
3127     }
3128 
3129     /* process source according to options */
3130     if (options & LYD_OPT_DESTRUCT) {
3131         node = (struct lyd_node *)src;
3132         if ((node->prev != node) && (options & LYD_OPT_NOSIBLINGS)) {
3133             node2 = node->prev;
3134             lyd_unlink(node);
3135             lyd_free_withsiblings(node2);
3136         }
3137     } else {
3138         node = NULL;
3139         for (; src; src = src->next) {
3140             /* because we already have to duplicate it, do it in the correct context */
3141             node2 = lyd_dup_to_ctx(src, 1, ctx);
3142             if (!node2) {
3143                 lyd_free_withsiblings(node);
3144                 goto error;
3145             }
3146             if (node) {
3147                 if (lyd_insert_after(node->prev, node2)) {
3148                     lyd_free_withsiblings(node);
3149                     goto error;
3150                 }
3151             } else {
3152                 node = node2;
3153             }
3154 
3155             if (options & LYD_OPT_NOSIBLINGS) {
3156                 break;
3157             }
3158         }
3159     }
3160 
3161     if (src_merge_start) {
3162         /* insert data into the created parents */
3163         /* first, get the lowest created parent, we don't have to check the nodetype since we are
3164          * creating only a simple chain of containers */
3165         for (node2 = src_merge_start; node2->child; node2 = node2->child);
3166         node2->child = node;
3167         LY_TREE_FOR(node, node) {
3168             node->parent = node2;
3169         }
3170     } else {
3171         src_merge_start = node;
3172     }
3173 
3174     if (!first_iter) {
3175         /* !! src_merge start is a child(ren) of trg_merge_start */
3176         ret = lyd_merge_parent_children(trg_merge_start, src_merge_start, options);
3177     } else {
3178         /* !! src_merge start is a (top-level) sibling(s) of trg_merge_start */
3179         ret = lyd_merge_siblings(trg_merge_start, src_merge_start, options);
3180     }
3181     /* it was freed whatever the return value */
3182     src_merge_start = NULL;
3183     if (ret == 2) {
3184         /* clear remporary LYD_VAL_INUSE validation flags */
3185         LY_TREE_DFS_BEGIN(target, node2, node) {
3186             node->validity &= ~LYD_VAL_INUSE;
3187             LY_TREE_DFS_END(target, node2, node);
3188         }
3189         ret = 0;
3190     } else if (ret) {
3191         goto error;
3192     }
3193 
3194     if (target->schema->nodetype == LYS_RPC) {
3195         lyd_schema_sort(target, 1);
3196     }
3197 
3198     /* update the pointer to the target tree if needed */
3199     if (*trg != target) {
3200         lyd_free_withsiblings(*trg);
3201         (*trg) = target;
3202     }
3203     return ret;
3204 
3205 error:
3206     if (*trg != target) {
3207         /* target is duplication of the original target in different context,
3208          * free it due to the error */
3209         lyd_free_withsiblings(target);
3210     }
3211     lyd_free_withsiblings(src_merge_start);
3212     return -1;
3213 }
3214 
3215 API int
lyd_merge(struct lyd_node * target,const struct lyd_node * source,int options)3216 lyd_merge(struct lyd_node *target, const struct lyd_node *source, int options)
3217 {
3218     FUN_IN;
3219 
3220     if (!target || !source) {
3221         LOGARG;
3222         return -1;
3223     }
3224 
3225     return lyd_merge_to_ctx(&target, source, options, target->schema->module->ctx);
3226 }
3227 
3228 API void
lyd_free_diff(struct lyd_difflist * diff)3229 lyd_free_diff(struct lyd_difflist *diff)
3230 {
3231     FUN_IN;
3232 
3233     if (diff) {
3234         free(diff->type);
3235         free(diff->first);
3236         free(diff->second);
3237         free(diff);
3238     }
3239 }
3240 
3241 static int
lyd_difflist_add(struct lyd_difflist * diff,unsigned int * size,unsigned int index,LYD_DIFFTYPE type,struct lyd_node * first,struct lyd_node * second)3242 lyd_difflist_add(struct lyd_difflist *diff, unsigned int *size, unsigned int index,
3243                  LYD_DIFFTYPE type, struct lyd_node *first, struct lyd_node *second)
3244 {
3245     void *new;
3246     struct ly_ctx *ctx;
3247 
3248     assert(diff);
3249     assert(size && *size);
3250     assert(first || second);
3251 
3252     ctx = (first ? first->schema->module->ctx : (second ? second->schema->module->ctx : NULL));
3253 
3254     if (index + 1 == *size) {
3255         /* it's time to enlarge */
3256         *size = *size + 16;
3257         new = realloc(diff->type, *size * sizeof *diff->type);
3258         LY_CHECK_ERR_RETURN(!new, LOGMEM(ctx), EXIT_FAILURE);
3259         diff->type = new;
3260 
3261         new = realloc(diff->first, *size * sizeof *diff->first);
3262         LY_CHECK_ERR_RETURN(!new, LOGMEM(ctx), EXIT_FAILURE);
3263         diff->first = new;
3264 
3265         new = realloc(diff->second, *size * sizeof *diff->second);
3266         LY_CHECK_ERR_RETURN(!new, LOGMEM(ctx), EXIT_FAILURE);
3267         diff->second = new;
3268     }
3269 
3270     /* insert the item */
3271     diff->type[index] = type;
3272     diff->first[index] = first;
3273     diff->second[index] = second;
3274 
3275     /* terminate the arrays */
3276     index++;
3277     diff->type[index] = LYD_DIFF_END;
3278     diff->first[index] = NULL;
3279     diff->second[index] = NULL;
3280 
3281     return EXIT_SUCCESS;
3282 }
3283 
3284 struct diff_ordered_dist {
3285     struct diff_ordered_dist *next;
3286     int dist;
3287 };
3288 struct diff_ordered_item {
3289     struct lyd_node *first;
3290     struct lyd_node *second;
3291     struct diff_ordered_dist *dist;
3292 };
3293 struct diff_ordered {
3294     struct lys_node *schema;
3295     struct lyd_node *parent;
3296     unsigned int count;
3297     struct diff_ordered_item *items; /* array */
3298     struct diff_ordered_dist *dist;  /* linked list (1-way, ring) */
3299     struct diff_ordered_dist *dist_last;  /* aux pointer for faster insertion sort */
3300 };
3301 
3302 static int
diff_ordset_insert(struct lyd_node * node,struct ly_set * ordset)3303 diff_ordset_insert(struct lyd_node *node, struct ly_set *ordset)
3304 {
3305     unsigned int i;
3306     struct diff_ordered *new_ordered, *iter;
3307 
3308     for (i = 0; i < ordset->number; i++) {
3309         iter = (struct diff_ordered *)ordset->set.g[i];
3310         if (iter->schema == node->schema && iter->parent == node->parent) {
3311             break;
3312         }
3313     }
3314     if (i == ordset->number) {
3315         /* not seen user-ordered list */
3316         new_ordered = calloc(1, sizeof *new_ordered);
3317         LY_CHECK_ERR_RETURN(!new_ordered, LOGMEM(node->schema->module->ctx), EXIT_FAILURE);
3318         new_ordered->schema = node->schema;
3319         new_ordered->parent = node->parent;
3320 
3321         ly_set_add(ordset, new_ordered, LY_SET_OPT_USEASLIST);
3322     }
3323     ((struct diff_ordered *)ordset->set.g[i])->count++;
3324 
3325     return EXIT_SUCCESS;
3326 }
3327 
3328 static void
diff_ordset_free(struct ly_set * set)3329 diff_ordset_free(struct ly_set *set)
3330 {
3331     unsigned int i, j;
3332     struct diff_ordered *ord;
3333 
3334     if (!set) {
3335         return;
3336     }
3337 
3338     for (i = 0; i < set->number; i++) {
3339         ord = (struct diff_ordered *)set->set.g[i];
3340         for (j = 0; j < ord->count; j++) {
3341             free(ord->items[j].dist);
3342         }
3343         free(ord->items);
3344         free(ord);
3345     }
3346 
3347     ly_set_free(set);
3348 }
3349 
3350 /*
3351  * -1 - error
3352  *  0 - ok
3353  *  1 - first and second not the same
3354  */
3355 static int
lyd_diff_compare(struct lyd_node * first,struct lyd_node * second,int options)3356 lyd_diff_compare(struct lyd_node *first, struct lyd_node *second, int options)
3357 {
3358     int rc;
3359 
3360     if (first->dflt && !(options & LYD_DIFFOPT_WITHDEFAULTS)) {
3361         /* the second one cannot be default (see lyd_diff()),
3362          * so the nodes differs (first one is default node) */
3363         return 1;
3364     }
3365 
3366     if (first->schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) {
3367         if (first->validity & LYD_VAL_INUSE) {
3368             /* this node was already matched, it cannot be matched twice (except for state leaf-/lists,
3369              * which we want to keep the count on this way) */
3370             return 1;
3371         }
3372 
3373         rc = lyd_list_equal(first, second, (options & LYD_DIFFOPT_WITHDEFAULTS ? 1 : 0));
3374         if (rc == -1) {
3375             return -1;
3376         } else if (!rc) {
3377             /* list instances differs */
3378             return 1;
3379         }
3380         /* matches */
3381     }
3382 
3383     return 0;
3384 }
3385 
3386 /*
3387  * -1 - error
3388  *  0 - ok
3389  */
3390 static int
lyd_diff_match(struct lyd_node * first,struct lyd_node * second,struct lyd_difflist * diff,unsigned int * size,unsigned int * i,struct ly_set * matchset,struct ly_set * ordset,int options)3391 lyd_diff_match(struct lyd_node *first, struct lyd_node *second, struct lyd_difflist *diff, unsigned int *size,
3392                unsigned int *i, struct ly_set *matchset, struct ly_set *ordset, int options)
3393 {
3394     switch (first->schema->nodetype) {
3395     case LYS_LEAFLIST:
3396     case LYS_LIST:
3397         /* additional work for future move matching in case of user ordered lists */
3398         if (first->schema->flags & LYS_USERORDERED) {
3399             diff_ordset_insert(first, ordset);
3400         }
3401 
3402         /* falls through */
3403     case LYS_CONTAINER:
3404     case LYS_RPC:
3405     case LYS_ACTION:
3406     case LYS_NOTIF:
3407         assert(!(second->validity & LYD_VAL_INUSE));
3408         second->validity |= LYD_VAL_INUSE;
3409         /* remember the matching node in first for keeping correct pointer in first
3410          * for comparing when passing through the second tree in lyd_diff().
3411          * Duplicities are not allowed actually, but they cannot happen since single
3412          * node can match only one node in the other tree */
3413         ly_set_add(matchset, first, LY_SET_OPT_USEASLIST);
3414         break;
3415     case LYS_LEAF:
3416         /* check for leaf's modification */
3417         if (!lyd_leaf_val_equal(first, second, 0) || ((options & LYD_DIFFOPT_WITHDEFAULTS) && (first->dflt != second->dflt))) {
3418             if (lyd_difflist_add(diff, size, (*i)++, LYD_DIFF_CHANGED, first, second)) {
3419                return -1;
3420             }
3421         }
3422         break;
3423     case LYS_ANYXML:
3424     case LYS_ANYDATA:
3425         /* check for anydata/anyxml's modification */
3426         if (!lyd_anydata_equal(first, second) && lyd_difflist_add(diff, size, (*i)++, LYD_DIFF_CHANGED, first, second)) {
3427             return -1;
3428         }
3429         break;
3430     default:
3431         LOGINT(first->schema->module->ctx);
3432         return -1;
3433     }
3434 
3435     /* mark both that they have matching instance in the other tree */
3436     assert(!(first->validity & LYD_VAL_INUSE));
3437     first->validity |= LYD_VAL_INUSE;
3438 
3439     return 0;
3440 }
3441 
3442 /* @brief compare if the nodes are equivalent including checking the list's keys
3443  * Go through the nodes and their parents and in the case of list, compare its keys.
3444  *
3445  * @return 0 different, 1 equivalent
3446  */
3447 static int
lyd_diff_equivnode(struct lyd_node * first,struct lyd_node * second)3448 lyd_diff_equivnode(struct lyd_node *first, struct lyd_node *second)
3449 {
3450     struct lyd_node *iter1, *iter2;
3451 
3452     for (iter1 = first, iter2 = second; iter1 && iter2; iter1 = iter1->parent, iter2 = iter2->parent) {
3453         if (iter1->schema->module->ctx == iter2->schema->module->ctx) {
3454             if (iter1->schema != iter2->schema) {
3455                 return 0;
3456             }
3457         } else {
3458             if (!ly_strequal(iter1->schema->name, iter2->schema->name, 0)) {
3459                 /* comparing the names is fine, even if they are, in fact, 2 different nodes
3460                  * with equal names, some of their parents will differ */
3461                 return 0;
3462             }
3463         }
3464         if (iter1->schema->nodetype == LYS_LIST) {
3465             /* compare keys */
3466             if (lyd_list_equal(iter1, iter2, 0) != 1) {
3467                 return 0;
3468             }
3469         }
3470     }
3471 
3472     if (iter1 != iter2) {
3473         /* we are supposed to be in root (NULL) in both trees */
3474         return 0;
3475     }
3476 
3477     return 1;
3478 }
3479 
3480 static int
lyd_diff_move_preprocess(struct diff_ordered * ordered,struct lyd_node * first,struct lyd_node * second)3481 lyd_diff_move_preprocess(struct diff_ordered *ordered, struct lyd_node *first, struct lyd_node *second)
3482 {
3483     struct ly_ctx *ctx = first->schema->module->ctx;
3484     struct lyd_node *iter;
3485     unsigned int pos = 0;
3486     int abs_dist;
3487     struct diff_ordered_dist *dist_aux;
3488     struct diff_ordered_dist *dist_iter, *dist_last;
3489     char *str = NULL;
3490 
3491     /* ordered->count was zeroed and now it is incremented with each added
3492      * item's information, so it is actually position of the second node
3493      */
3494 
3495     /* get the position of the first node */
3496     for (iter = first->prev; iter->next; iter = iter->prev) {
3497         if (!(iter->validity & LYD_VAL_INUSE)) {
3498             /* skip deleted nodes */
3499             continue;
3500         }
3501         if (iter->schema == first->schema) {
3502             pos++;
3503         }
3504     }
3505     if (pos != ordered->count) {
3506         LOGDBG(LY_LDGDIFF, "detected moved element \"%s\" from %d to %d (distance %d)",
3507                str = lyd_path(first), pos, ordered->count, ordered->count - pos);
3508         free(str);
3509     }
3510 
3511     /* store information, count distance */
3512     ordered->items[pos].dist = dist_aux = calloc(1, sizeof *dist_aux);
3513     LY_CHECK_ERR_RETURN(!dist_aux, LOGMEM(ctx), EXIT_FAILURE);
3514     ordered->items[pos].dist->dist = ordered->count - pos;
3515     abs_dist = abs(ordered->items[pos].dist->dist);
3516     ordered->items[pos].first = first;
3517     ordered->items[pos].second = second;
3518     ordered->count++;
3519 
3520     /* insert sort of distances, higher first */
3521     for (dist_iter = ordered->dist, dist_last = NULL;
3522             dist_iter;
3523             dist_last = dist_iter, dist_iter = dist_iter->next) {
3524         if (abs_dist >= abs(dist_iter->dist)) {
3525             /* found correct place */
3526             dist_aux->next = dist_iter;
3527             if (dist_last) {
3528                 dist_last->next = dist_aux;
3529             }
3530             break;
3531         } else if (dist_iter->next == ordered->dist) {
3532             /* last item */
3533             dist_aux->next = ordered->dist; /* ring list */
3534             ordered->dist_last = dist_aux;
3535             dist_iter->next = dist_aux;
3536             break;
3537         }
3538     }
3539     if (dist_aux->next == ordered->dist) {
3540         if (ordered->dist_last == dist_aux) {
3541             /* last item */
3542             if (!ordered->dist) {
3543                 /* the only item */
3544                 dist_aux->next = dist_aux;
3545                 ordered->dist = ordered->dist_last = dist_aux;
3546             }
3547         } else {
3548             /* first item */
3549             ordered->dist = dist_aux;
3550             if (dist_aux->next) {
3551                 /* more than one item, update the last one's next */
3552                 ordered->dist_last->next = dist_aux;
3553             } else {
3554                 /* the only item */
3555                 ordered->dist_last = dist_aux;
3556                 dist_aux->next = dist_aux; /* ring list */
3557             }
3558         }
3559     }
3560 
3561     return 0;
3562 }
3563 
3564 static struct lyd_difflist *
lyd_diff_init_difflist(struct ly_ctx * ctx,unsigned int * size)3565 lyd_diff_init_difflist(struct ly_ctx *ctx, unsigned int *size)
3566 {
3567     struct lyd_difflist *result;
3568 
3569     result = malloc(sizeof *result);
3570     LY_CHECK_ERR_RETURN(!result, LOGMEM(ctx); *size = 0, NULL);
3571 
3572     *size = 1;
3573     result->type = calloc(*size, sizeof *result->type);
3574     result->first = calloc(*size, sizeof *result->first);
3575     result->second = calloc(*size, sizeof *result->second);
3576     if (!result->type || !result->first || !result->second) {
3577         LOGMEM(ctx);
3578         free(result->second);
3579         free(result->first);
3580         free(result->type);
3581         free(result);
3582         *size = 0;
3583         return NULL;
3584     }
3585 
3586     return result;
3587 }
3588 
3589 API struct lyd_difflist *
lyd_diff(struct lyd_node * first,struct lyd_node * second,int options)3590 lyd_diff(struct lyd_node *first, struct lyd_node *second, int options)
3591 {
3592     FUN_IN;
3593 
3594     struct ly_ctx *ctx;
3595     int rc;
3596     struct lyd_node *elem1, *elem2, *iter, *aux, *parent = NULL, *next1, *next2;
3597     struct lyd_difflist *result, *result2 = NULL;
3598     void *new;
3599     unsigned int size, size2, index = 0, index2 = 0, i, j, k;
3600     struct matchlist_s {
3601         struct matchlist_s *prev;
3602         struct ly_set *match;
3603         unsigned int i;
3604     } *matchlist = NULL, *mlaux;
3605     struct ly_set *ordset = NULL;
3606     struct diff_ordered *ordered;
3607     struct diff_ordered_dist *dist_aux, *dist_iter;
3608     struct diff_ordered_item item_aux;
3609 
3610     if (!first) {
3611         /* all nodes in second were created,
3612          * but the second must be top level */
3613         if (second && second->parent) {
3614             LOGERR(second->schema->module->ctx, LY_EINVAL, "%s: \"first\" parameter is NULL and \"second\" is not top level.", __func__);
3615             return NULL;
3616         }
3617         result = lyd_diff_init_difflist(NULL, &size);
3618         LY_TREE_FOR(second, iter) {
3619             if (!iter->dflt || (options & LYD_DIFFOPT_WITHDEFAULTS)) { /* skip the implicit nodes */
3620                 if (lyd_difflist_add(result, &size, index++, LYD_DIFF_CREATED, NULL, iter)) {
3621                     goto error;
3622                 }
3623             }
3624             if (options & LYD_DIFFOPT_NOSIBLINGS) {
3625                 break;
3626             }
3627         }
3628         return result;
3629     } else if (!second) {
3630         /* all nodes from first were deleted */
3631         result = lyd_diff_init_difflist(first->schema->module->ctx, &size);
3632         LY_TREE_FOR(first, iter) {
3633             if (!iter->dflt || (options & LYD_DIFFOPT_WITHDEFAULTS)) { /* skip the implicit nodes */
3634                 if (lyd_difflist_add(result, &size, index++, LYD_DIFF_DELETED, iter, NULL)) {
3635                     goto error;
3636                 }
3637             }
3638             if (options & LYD_DIFFOPT_NOSIBLINGS) {
3639                 break;
3640             }
3641         }
3642         return result;
3643     }
3644 
3645     ctx = first->schema->module->ctx;
3646 
3647     if (options & LYD_DIFFOPT_NOSIBLINGS) {
3648         /* both trees must start at the same (schema) node */
3649         if (first->schema != second->schema) {
3650             LOGERR(ctx, LY_EINVAL, "%s: incompatible trees to compare with LYD_OPT_NOSIBLINGS option.", __func__);
3651             return NULL;
3652         }
3653         /* use first's and second's child to make comparison the same as without LYD_OPT_NOSIBLINGS */
3654         first = first->child;
3655         second = second->child;
3656     } else {
3657         /* go to the first sibling in both trees */
3658         if (first->parent) {
3659             first = first->parent->child;
3660         } else {
3661             while (first->prev->next) {
3662                 first = first->prev;
3663             }
3664         }
3665 
3666         if (second->parent) {
3667             second = second->parent->child;
3668         } else {
3669             for (; second->prev->next; second = second->prev);
3670         }
3671 
3672         /* check that both has the same (schema) parent or that they are top-level nodes */
3673         if ((first->parent && second->parent && first->parent->schema != second->parent->schema) ||
3674                 (!first->parent && first->parent != second->parent)) {
3675             LOGERR(ctx, LY_EINVAL, "%s: incompatible trees with different parents.", __func__);
3676             return NULL;
3677         }
3678     }
3679     if (first == second) {
3680         LOGERR(ctx, LY_EINVAL, "%s: comparing the same tree does not make sense.", __func__);
3681         return NULL;
3682     }
3683 
3684     /* initiate resulting structure */
3685     result = lyd_diff_init_difflist(ctx, &size);
3686     LY_CHECK_ERR_GOTO(!result, , error);
3687 
3688     /* the records about created and moved items are created in
3689      * bad order, so the records about created nodes (and their
3690      * possible moving) is stored separately and added to the
3691      * main result at the end.
3692      */
3693     result2 = lyd_diff_init_difflist(ctx, &size2);
3694     LY_CHECK_ERR_GOTO(!result2, , error);
3695 
3696     matchlist = malloc(sizeof *matchlist);
3697     LY_CHECK_ERR_GOTO(!matchlist, LOGMEM(ctx), error);
3698 
3699     matchlist->i = 0;
3700     matchlist->match = ly_set_new();
3701     matchlist->prev = NULL;
3702 
3703     ordset = ly_set_new();
3704     LY_CHECK_ERR_GOTO(!ordset, , error);
3705 
3706     /*
3707      * compare trees
3708      */
3709     /* 1) newly created nodes + changed leafs/anyxmls */
3710     next1 = first;
3711     for (elem2 = next2 = second; elem2; elem2 = next2) {
3712         /* keep right pointer for searching in the first tree */
3713         elem1 = next1;
3714 
3715         if (elem2->dflt && !(options & LYD_DIFFOPT_WITHDEFAULTS)) {
3716             /* skip default elements, they could not be created or changed, just deleted */
3717             goto cmp_continue;
3718         }
3719 
3720 #ifdef LY_ENABLED_CACHE
3721         struct lyd_node **iter_p;
3722 
3723         if (elem1 && elem1->parent && elem1->parent->ht) {
3724             iter = NULL;
3725             if (!lyht_find(elem1->parent->ht, &elem2, elem2->hash, (void **)&iter_p)) {
3726                 iter = *iter_p;
3727                 /* we found a match */
3728                 if (iter->dflt && !(options & LYD_DIFFOPT_WITHDEFAULTS)) {
3729                     /* the second one cannot be default (see lyd_diff()),
3730                      * so the nodes differs (first one is default node) */
3731                     iter = NULL;
3732                 }
3733                 while (iter && (iter->validity & LYD_VAL_INUSE)) {
3734                     /* state lists, find one not-already-found */
3735                     assert((iter->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) && (iter->schema->flags & LYS_CONFIG_R));
3736                     if (lyht_find_next(elem1->parent->ht, &iter, iter->hash, (void **)&iter_p)) {
3737                         iter = NULL;
3738                     } else {
3739                         iter = *iter_p;
3740                     }
3741                 }
3742             }
3743         } else
3744 #endif
3745         {
3746             /* search for elem2 instance in the first */
3747             LY_TREE_FOR(elem1, iter) {
3748                 if (iter->schema != elem2->schema) {
3749                     continue;
3750                 }
3751 
3752                 /* elem2 instance found */
3753                 rc = lyd_diff_compare(iter, elem2, options);
3754                 if (rc == -1) {
3755                     goto error;
3756                 } else if (rc == 0) {
3757                     /* match */
3758                     break;
3759                 } /* else, continue */
3760             }
3761         }
3762         /* we have a match */
3763         if (iter && lyd_diff_match(iter, elem2, result, &size, &index, matchlist->match, ordset, options)) {
3764             goto error;
3765         }
3766 
3767         if (!iter) {
3768             /* elem2 not found in the first tree */
3769             if (lyd_difflist_add(result2, &size2, index2++, LYD_DIFF_CREATED, elem1 ? elem1->parent : parent, elem2)) {
3770                 goto error;
3771             }
3772 
3773             if (elem1 && (elem2->schema->flags & LYS_USERORDERED)) {
3774                 /* store the correct place where the node is supposed to be moved after creation */
3775                 /* if elem1 does not exist, all nodes were created and they will be created in
3776                  * correct order, so it is not needed to detect moves */
3777                 for (aux = elem2->prev; aux->next; aux = aux->prev) {
3778                     if (aux->schema == elem2->schema) {
3779                         /* predecessor found */
3780                         break;
3781                     }
3782                 }
3783                 if (!aux->next) {
3784                     /* predecessor not found */
3785                     aux = NULL;
3786                 }
3787                 if (lyd_difflist_add(result2, &size2, index2++, LYD_DIFF_MOVEDAFTER2, aux, elem2)) {
3788                     goto error;
3789                 }
3790             }
3791         }
3792 
3793 cmp_continue:
3794         /* select element for the next run                                    1     2
3795          * - first, process all siblings of a single parent                  / \   / \
3796          * - then, go to children (deep)                                    3   4 7   8
3797          * - return to the parent's next sibling children                  / \
3798          *                                                                5   6
3799          */
3800         /* siblings first */
3801         next1 = elem1;
3802         next2 = elem2->next;
3803 
3804         if (!next2) {
3805             /* children */
3806 
3807             /* first pass of the siblings done, some additional work for future
3808              * detection of move may be needed */
3809             for (i = ordset->number; i > 0; i--) {
3810                 ordered = (struct diff_ordered *)ordset->set.g[i - 1];
3811                 if (ordered->items) {
3812                     /* already preprocessed ordered structure */
3813                     break;
3814                 }
3815                 ordered->items = calloc(ordered->count, sizeof *ordered->items);
3816                 LY_CHECK_ERR_GOTO(!ordered->items, LOGMEM(ctx), error);
3817                 ordered->dist = NULL;
3818                 /* zero the count to be used as a node position in lyd_diff_move_preprocess() */
3819                 ordered->count = 0;
3820             }
3821 
3822             /* first, get the first sibling */
3823             if (elem2->parent == second->parent) {
3824                 elem2 = second;
3825             } else {
3826                 elem2 = elem2->parent->child;
3827             }
3828 
3829             /* and then find the first child */
3830             LY_TREE_FOR(elem2, iter) {
3831                 if (!(iter->validity & LYD_VAL_INUSE)) {
3832                     /* the iter is not present in both trees */
3833                     continue;
3834                 } else if (matchlist->i == matchlist->match->number) {
3835                     if (iter == elem2) {
3836                         /* we already went through all the matching nodes and now we are just supposed to stop
3837                          * the loop with no iter */
3838                         iter = NULL;
3839                         break;
3840                     } else {
3841                         /* we have started with some not processed data in matchlist, but now we have
3842                          * the INUSE iter and no nodes in matchlist to find its equivalent,
3843                          * so something went wrong somewhere */
3844                         LOGINT(ctx);
3845                         goto error;
3846                     }
3847                 }
3848 
3849                 iter->validity &= ~LYD_VAL_INUSE;
3850                 if ((iter->schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) && (iter->schema->flags & LYS_USERORDERED)) {
3851                     for (j = ordset->number; j > 0; j--) {
3852                         ordered = (struct diff_ordered *)ordset->set.g[j - 1];
3853                         if (ordered->schema != iter->schema || !lyd_diff_equivnode(ordered->parent, iter->parent)) {
3854                             continue;
3855                         }
3856 
3857                         /* store necessary information for move detection */
3858                         lyd_diff_move_preprocess(ordered, matchlist->match->set.d[matchlist->i], iter);
3859                         break;
3860                     }
3861                 }
3862 
3863                 if (((iter->schema->nodetype == LYS_CONTAINER) || ((iter->schema->nodetype == LYS_LIST)
3864                         && ((struct lys_node_list *)iter->schema)->keys_size)) && iter->child) {
3865                     while (matchlist->i < matchlist->match->number && matchlist->match->set.d[matchlist->i]->schema != iter->schema) {
3866                         matchlist->i++;
3867                     }
3868                     if (matchlist->i == matchlist->match->number) {
3869                         /* we have the INUSE iter, so we have to find its equivalent in match list */
3870                         LOGINT(ctx);
3871                         goto error;
3872                     }
3873                     next1 = matchlist->match->set.d[matchlist->i]->child;
3874                     if (!next1) {
3875                         parent = matchlist->match->set.d[matchlist->i];
3876                     }
3877                     matchlist->i++;
3878                     next2 = iter->child;
3879                     break;
3880                 }
3881                 matchlist->i++;
3882             }
3883 
3884             if (!iter) {
3885                 /* no child/data on next level */
3886                 if (elem2 == second) {
3887                     /* done */
3888                     break;
3889                 }
3890             } else {
3891                 /* create new matchlist item */
3892                 mlaux = malloc(sizeof *mlaux);
3893                 LY_CHECK_ERR_GOTO(!mlaux, LOGMEM(ctx), error);
3894                 mlaux->i = 0;
3895                 mlaux->match = ly_set_new();
3896                 mlaux->prev = matchlist;
3897                 matchlist = mlaux;
3898             }
3899         }
3900 
3901         while (!next2) {
3902             /* parent */
3903 
3904             /* clean the last match set */
3905             ly_set_clean(matchlist->match);
3906             matchlist->i = 0;
3907 
3908             /* try to go to a cousin - child of the next parent's sibling */
3909             mlaux = matchlist->prev;
3910             LY_TREE_FOR(elem2->parent->next, iter) {
3911                 if (!(iter->validity & LYD_VAL_INUSE)) {
3912                     continue;
3913                 } else if (mlaux->i == mlaux->match->number) {
3914                     if (iter == elem2->parent->next) {
3915                         /* we already went through all the matching nodes and now we are just supposed to stop
3916                          * the loop with no iter */
3917                         iter = NULL;
3918                         break;
3919                     } else {
3920                         /* we have started with some not processed data in matchlist, but now we have
3921                          * the INUSE iter and no nodes in matchlist to find its equivalent,
3922                          * so something went wrong somewhere */
3923                         LOGINT(ctx);
3924                         goto error;
3925                     }
3926                 }
3927 
3928                 iter->validity &= ~LYD_VAL_INUSE;
3929                 if ((iter->schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) && (iter->schema->flags & LYS_USERORDERED)) {
3930                     for (j = ordset->number ; j > 0; j--) {
3931                         ordered = (struct diff_ordered *)ordset->set.g[j - 1];
3932                         if (ordered->schema != iter->schema || !lyd_diff_equivnode(ordered->parent, iter->parent)) {
3933                             continue;
3934                         }
3935 
3936                         /* store necessary information for move detection */
3937                         lyd_diff_move_preprocess(ordered, mlaux->match->set.d[mlaux->i], iter);
3938                         break;
3939                     }
3940                 }
3941 
3942                 if (((iter->schema->nodetype == LYS_CONTAINER) || ((iter->schema->nodetype == LYS_LIST)
3943                         && ((struct lys_node_list *)iter->schema)->keys_size)) && iter->child) {
3944                     while (mlaux->i < mlaux->match->number && mlaux->match->set.d[mlaux->i]->schema != iter->schema) {
3945                         mlaux->i++;
3946                     }
3947                     if (mlaux->i == mlaux->match->number) {
3948                         /* we have the INUSE iter, so we have to find its equivalent in match list */
3949                         LOGINT(ctx);
3950                         goto error;
3951                     }
3952                     next1 = mlaux->match->set.d[mlaux->i]->child;
3953                     if (!next1) {
3954                         parent = mlaux->match->set.d[mlaux->i];
3955                     }
3956                     mlaux->i++;
3957                     next2 = iter->child;
3958                     break;
3959                 }
3960                 mlaux->i++;
3961             }
3962 
3963             /* if no cousin exists, continue next loop on higher level */
3964             if (!iter) {
3965                 elem2 = elem2->parent;
3966 
3967                 /* remove matchlist item */
3968                 ly_set_free(matchlist->match);
3969                 mlaux = matchlist;
3970                 matchlist = matchlist->prev;
3971                 free(mlaux);
3972 
3973                 if (!matchlist->prev) { /* elem2->parent == second->parent */
3974                     /* done */
3975                     break;
3976                 }
3977             }
3978         }
3979     }
3980 
3981     ly_set_free(matchlist->match);
3982     free(matchlist);
3983     matchlist = NULL;
3984 
3985     /* 2) deleted nodes */
3986     LY_TREE_DFS_BEGIN(first, next1, elem1) {
3987         /* search for elem1s deleted in the second */
3988         if (elem1->validity & LYD_VAL_INUSE) {
3989             /* erase temporary LYD_VAL_INUSE flag and continue into children */
3990             elem1->validity &= ~LYD_VAL_INUSE;
3991         } else if (!elem1->dflt || (options & LYD_DIFFOPT_WITHDEFAULTS)) {
3992             /* elem1 has no matching node in second, add it into result */
3993             if (lyd_difflist_add(result, &size, index++, LYD_DIFF_DELETED, elem1, NULL)) {
3994                 goto error;
3995             }
3996 
3997             /* skip subtree processing of data missing in the second tree */
3998             goto dfs_nextsibling;
3999         }
4000 
4001         /* modified LY_TREE_DFS_END() */
4002         /* select element for the next run - children first */
4003         if ((elem1->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) || ((elem1->schema->nodetype == LYS_LIST)
4004                 && !((struct lys_node_list *)elem1->schema)->keys_size)) {
4005             next1 = NULL;
4006         } else {
4007             next1 = elem1->child;
4008         }
4009         if (!next1) {
4010 dfs_nextsibling:
4011             /* try siblings */
4012             next1 = elem1->next;
4013         }
4014         while (!next1) {
4015             /* parent is already processed, go to its sibling */
4016 
4017             elem1 = elem1->parent;
4018             if (elem1 == first->parent) {
4019                 /* we are done, no next element to process */
4020                 break;
4021             }
4022 
4023             next1 = elem1->next;
4024         }
4025     }
4026 
4027     /* 3) moved nodes (when user-ordered) */
4028     for (i = 0; i < ordset->number; i++) {
4029         ordered = (struct diff_ordered *)ordset->set.g[i];
4030         if (!ordered->dist->dist) {
4031             /* the dist list is sorted here, but the biggest dist is 0,
4032              * so nothing changed in order of these items between first
4033              * and second. We can continue with another user-ordered list.
4034              */
4035             continue;
4036         }
4037 
4038         /* get needed movements
4039          * - from the biggest distances try to apply node movements
4040          * on first tree node until they will be ordered as in the
4041          * second tree - i.e. until there will be no position difference
4042          */
4043 
4044         for (dist_iter = ordered->dist; ; dist_iter = dist_iter->next) {
4045             /* dist list is sorted at the beginning, since applying a move causes
4046              * just a small change in other distances, we assume that the biggest
4047              * dist is the next one (note that dist list is implemented as ring
4048              * list). This way we avoid sorting distances after each move. The loop
4049              * stops when all distances are zero.
4050              */
4051             dist_aux = dist_iter;
4052             while (!dist_iter->dist) {
4053                 /* no dist, so no move. Try another, but when
4054                  * there is no dist at all, stop the loop
4055                  */
4056                 dist_iter = dist_iter->next;
4057                 if (dist_iter == dist_aux) {
4058                     /* all dist we zeroed */
4059                     goto movedone;
4060                 }
4061             }
4062             /* something to move */
4063 
4064             /* get the item to move */
4065             for (k = 0; k < ordered->count; k++) {
4066                 if (ordered->items[k].dist == dist_iter) {
4067                     break;
4068                 }
4069             }
4070 
4071             /* apply the move (distance) */
4072             memcpy(&item_aux, &ordered->items[k], sizeof item_aux);
4073             if (dist_iter->dist > 0) {
4074                 /* move to right (other move to left) */
4075                 while (dist_iter->dist) {
4076                     memcpy(&ordered->items[k], &ordered->items[k + 1], sizeof *ordered->items);
4077                     ordered->items[k].dist->dist++; /* update moved item distance */
4078                     dist_iter->dist--;
4079                     k++;
4080                 }
4081             } else {
4082                 /* move to left (other move to right) */
4083                 while (dist_iter->dist) {
4084                     memcpy(&ordered->items[k], &ordered->items[k - 1], sizeof *ordered->items);
4085                     ordered->items[k].dist->dist--; /* update moved item distance */
4086                     dist_iter->dist++;
4087                     k--;
4088                 }
4089             }
4090             memcpy(&ordered->items[k], &item_aux, sizeof *ordered->items);
4091 
4092             /* store the transaction into the difflist */
4093             if (lyd_difflist_add(result, &size, index++, LYD_DIFF_MOVEDAFTER1, item_aux.first,
4094                                  (k > 0) ? ordered->items[k - 1].first : NULL)) {
4095                 goto error;
4096             }
4097             continue;
4098 
4099 movedone:
4100             break;
4101         }
4102     }
4103 
4104     diff_ordset_free(ordset);
4105     ordset = NULL;
4106 
4107     if (index2) {
4108         /* append result2 with newly created
4109          * (and possibly moved) nodes */
4110         if (index + index2 + 1 >= size) {
4111             /* result must be enlarged */
4112             size = index + index2 + 1;
4113             new = realloc(result->type, size * sizeof *result->type);
4114             LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx), error);
4115             result->type = new;
4116 
4117             new = realloc(result->first, size * sizeof *result->first);
4118             LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx), error);
4119             result->first = new;
4120 
4121             new = realloc(result->second, size * sizeof *result->second);
4122             LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx), error);
4123             result->second = new;
4124         }
4125 
4126         /* append */
4127         memcpy(&result->type[index], result2->type, (index2 + 1) * sizeof *result->type);
4128         memcpy(&result->first[index], result2->first, (index2 + 1) * sizeof *result->first);
4129         memcpy(&result->second[index], result2->second, (index2 + 1) * sizeof *result->second);
4130     }
4131     lyd_free_diff(result2);
4132 
4133     return result;
4134 
4135 error:
4136     while (matchlist) {
4137         mlaux = matchlist;
4138         matchlist = mlaux->prev;
4139         ly_set_free(mlaux->match);
4140         free(mlaux);
4141 
4142     }
4143     diff_ordset_free(ordset);
4144 
4145     lyd_free_diff(result);
4146     lyd_free_diff(result2);
4147 
4148     return NULL;
4149 }
4150 
4151 static void
lyd_insert_setinvalid(struct lyd_node * node)4152 lyd_insert_setinvalid(struct lyd_node *node)
4153 {
4154     struct lyd_node *next, *elem, *parent_list;
4155 
4156     assert(node);
4157 
4158     /* overall validity of the node itself */
4159     node->validity = ly_new_node_validity(node->schema);
4160 
4161     /* explore changed unique leaves */
4162     /* first, get know if there is a list in parents chain */
4163     for (parent_list = node->parent;
4164          parent_list && parent_list->schema->nodetype != LYS_LIST;
4165          parent_list = parent_list->parent);
4166     if (parent_list && !(parent_list->validity & LYD_VAL_UNIQUE)) {
4167         /* there is a list, so check if we inserted a leaf supposed to be unique */
4168         LY_TREE_DFS_BEGIN(node, next, elem) {
4169             if (elem->schema->nodetype == LYS_LIST) {
4170                 /* stop searching to the depth, children would be unique to a list in subtree */
4171                 goto nextsibling;
4172             }
4173 
4174             if (elem->schema->nodetype == LYS_LEAF && (elem->schema->flags & LYS_UNIQUE)) {
4175                 /* set flag to list for future validation */
4176                 parent_list->validity |= LYD_VAL_UNIQUE;
4177                 break;
4178             }
4179 
4180             /* LY_TREE_DFS_END */
4181             if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
4182                 next = NULL;
4183             } else {
4184                 next = elem->child;
4185             }
4186 
4187             if (!next) {
4188 nextsibling:
4189                 /* no children */
4190                 if (elem == node) {
4191                     /* we are done, (START) has no children */
4192                     break;
4193                 }
4194                 /* try siblings */
4195                 next = elem->next;
4196             }
4197             while (!next) {
4198                 /* parent is already processed, go to its sibling */
4199                 elem = elem->parent;
4200 
4201                 /* no siblings, go back through parents */
4202                 if (elem->parent == node->parent) {
4203                     /* we are done, no next element to process */
4204                     break;
4205                 }
4206                 next = elem->next;
4207             }
4208         }
4209     }
4210 
4211     if (node->parent) {
4212         /* if the inserted node is list/leaflist with constraint on max instances or extension validation callback,
4213          * invalidate the parent to make it validate this */
4214         if ((node->schema->nodetype & LYS_LEAFLIST) && ((struct lys_node_leaflist *)node->schema)->max) {
4215             node->parent->validity |= LYD_VAL_MAND;
4216         } else if ((node->schema->nodetype & LYS_LIST) && ((struct lys_node_list *)node->schema)->max) {
4217             node->parent->validity |= LYD_VAL_MAND;
4218         } else {
4219             /* invalidate all parents that have an extension with a validation
4220              * callback for their whole subtree */
4221             next = node->parent;
4222             while (next) {
4223                 if ((next->schema->flags & LYS_VALID_EXT) && (next->schema->flags & LYS_VALID_EXT_SUBTREE))
4224                     next->validity |= LYD_VAL_MAND;
4225                 next = next->parent;
4226             }
4227         }
4228     }
4229 }
4230 
4231 static void
lyd_replace(struct lyd_node * orig,struct lyd_node * repl)4232 lyd_replace(struct lyd_node *orig, struct lyd_node *repl)
4233 {
4234     struct lyd_node *iter, *last;
4235 
4236     if (!repl) {
4237         /* remove the old one */
4238         goto finish;
4239     }
4240 
4241     if (repl->parent || repl->prev->next) {
4242         /* isolate the new node */
4243         repl->next = NULL;
4244         repl->prev = repl;
4245         last = repl;
4246     } else {
4247         /* get the last node of a possible list of nodes to be inserted */
4248         for (last = repl; last->next; last = last->next) {
4249             /* part of the parent changes */
4250             last->parent = orig->parent;
4251         }
4252     }
4253 
4254     /* parent */
4255     if (orig->parent && (orig->parent->child == orig)) {
4256         orig->parent->child = repl;
4257     }
4258 
4259     orig->parent = NULL;
4260 
4261     /* predecessor */
4262     if (orig->prev == orig) {
4263         /* the old was alone */
4264         goto finish;
4265     }
4266     if (orig->prev->next) {
4267         orig->prev->next = repl;
4268     }
4269     repl->prev = orig->prev;
4270     orig->prev = orig;
4271 
4272     /* successor */
4273     if (orig->next) {
4274         orig->next->prev = last;
4275         last->next = orig->next;
4276         orig->next = NULL;
4277     } else {
4278         /* fix the last pointer */
4279         if (repl->parent) {
4280             repl->parent->child->prev = last;
4281         } else {
4282             /* get the first sibling */
4283             for (iter = repl; iter->prev != orig; iter = iter->prev);
4284             iter->prev = last;
4285         }
4286     }
4287 
4288     /* the node is already unlinked, remove it from parent's hash table. */
4289 #ifdef LY_ENABLED_CACHE
4290     lyd_unlink_hash(orig, repl->parent);
4291 #endif
4292 
4293 finish:
4294     lyd_free(orig);
4295 }
4296 
4297 int
lyd_insert_common(struct lyd_node * parent,struct lyd_node ** sibling,struct lyd_node * node,int invalidate)4298 lyd_insert_common(struct lyd_node *parent, struct lyd_node **sibling, struct lyd_node *node, int invalidate)
4299 {
4300     struct lys_node *par1, *par2;
4301     const struct lys_node *siter;
4302     struct lyd_node *start, *iter, *ins, *next1, *next2;
4303     int invalid = 0, isrpc = 0, clrdflt = 0;
4304     struct ly_set *llists = NULL;
4305     int i;
4306     uint8_t pos;
4307     int stype = LYS_INPUT | LYS_OUTPUT;
4308 
4309     assert(parent || sibling);
4310 
4311     /* get first sibling */
4312     if (parent) {
4313         start = parent->child;
4314     } else {
4315         for (start = *sibling; start->prev->next; start = start->prev);
4316     }
4317 
4318     /* check placing the node to the appropriate place according to the schema */
4319     if (!start) {
4320         if (!parent) {
4321             /* empty tree to insert */
4322             if (node->parent || node->prev->next) {
4323                 /* unlink the node first */
4324                 lyd_unlink_internal(node, 1);
4325             } /* else insert also node's siblings */
4326             *sibling = node;
4327             return EXIT_SUCCESS;
4328         }
4329         par1 = parent->schema;
4330         if (par1->nodetype & (LYS_RPC | LYS_ACTION)) {
4331             /* it is not clear if the tree being created is going to
4332              * be rpc (LYS_INPUT) or rpc-reply (LYS_OUTPUT) so we have to
4333              * compare against LYS_RPC or LYS_ACTION in par2
4334              */
4335             stype = LYS_RPC | LYS_ACTION;
4336         }
4337     } else if (parent && (parent->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
4338         par1 = parent->schema;
4339         stype = LYS_RPC | LYS_ACTION;
4340     } else {
4341         for (par1 = lys_parent(start->schema);
4342              par1 && !(par1->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF));
4343              par1 = lys_parent(par1));
4344     }
4345     for (par2 = lys_parent(node->schema);
4346          par2 && !(par2->nodetype & (LYS_CONTAINER | LYS_LIST | stype | LYS_NOTIF));
4347          par2 = lys_parent(par2));
4348     if (par1 != par2) {
4349         LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert, different parents (\"%s\" and \"%s\").",
4350                (par1 ? par1->name : "<top-lvl>"), (par2 ? par2->name : "<top-lvl>"));
4351         return EXIT_FAILURE;
4352     }
4353 
4354     if (invalidate) {
4355         invalid = isrpc = lyp_is_rpc_action(node->schema);
4356         if (!parent || node->parent != parent || isrpc) {
4357             /* it is not just moving under a parent node or it is in an RPC where
4358              * nodes order matters, so the validation will be necessary */
4359             invalid++;
4360         }
4361     }
4362 
4363     /* unlink only if it is not a list of siblings without a parent and node is not the first sibling */
4364     if (node->parent || node->prev->next) {
4365         /* do it permanent if the parents are not exact same or if it is top-level */
4366         lyd_unlink_internal(node, invalid);
4367     }
4368 
4369     llists = ly_set_new();
4370 
4371     /* process the nodes to insert one by one */
4372     LY_TREE_FOR_SAFE(node, next1, ins) {
4373         if (invalid == 1) {
4374             /* auto delete nodes from other cases, if any;
4375              * this is done only if node->parent != parent */
4376             if (lyv_multicases(ins, NULL, &start, 1, NULL)) {
4377                 goto error;
4378             }
4379         }
4380 
4381         /* isolate the node to be handled separately */
4382         ins->prev = ins;
4383         ins->next = NULL;
4384 
4385         iter = NULL;
4386         if (!ins->dflt) {
4387             clrdflt = 1;
4388         }
4389 
4390         /* are we inserting list key? */
4391         if (!ins->dflt && ins->schema->nodetype == LYS_LEAF && lys_is_key((struct lys_node_leaf *)ins->schema, &pos)) {
4392             /* yes, we have a key, get know its position */
4393             for (i = 0, iter = parent->child;
4394                     iter && i < pos && iter->schema->nodetype == LYS_LEAF;
4395                     i++, iter = iter->next);
4396             if (iter) {
4397                 /* insert list's key to the correct position - before the iter */
4398                 if (parent->child == iter) {
4399                     parent->child = ins;
4400                 }
4401                 if (iter->prev->next) {
4402                     iter->prev->next = ins;
4403                 }
4404                 ins->prev = iter->prev;
4405                 iter->prev = ins;
4406                 ins->next = iter;
4407 
4408                 /* update start element */
4409                 if (parent->child != start) {
4410                     start = parent->child;
4411                 }
4412             }
4413 
4414             /* try to find previously present default instance to replace */
4415         } else if (ins->schema->nodetype == LYS_LEAFLIST) {
4416             i = (int)llists->number;
4417             if ((ly_set_add(llists, ins->schema, 0) != i) || ins->dflt) {
4418                 /* each leaf-list must be cleared only once (except when looking for exact same existing dflt nodes) */
4419                 LY_TREE_FOR_SAFE(start, next2, iter) {
4420                     if (iter->schema == ins->schema) {
4421                         if ((ins->dflt && (!iter->dflt || ((iter->schema->flags & LYS_CONFIG_W) &&
4422                                                            !strcmp(((struct lyd_node_leaf_list *)iter)->value_str,
4423                                                                   ((struct lyd_node_leaf_list *)ins)->value_str))))
4424                                 || (!ins->dflt && iter->dflt)) {
4425                             if (iter == start) {
4426                                 start = next2;
4427                             }
4428                             lyd_free(iter);
4429                         }
4430                     }
4431                 }
4432             }
4433         } else if (ins->schema->nodetype == LYS_LEAF || (ins->schema->nodetype == LYS_CONTAINER
4434                         && !((struct lys_node_container *)ins->schema)->presence)) {
4435             LY_TREE_FOR(start, iter) {
4436                 if (iter->schema == ins->schema) {
4437                     if (ins->dflt || iter->dflt) {
4438                         /* replace existing (either explicit or default) node with the new (either explicit or default) node */
4439                         lyd_replace(iter, ins);
4440                     } else {
4441                         /* keep both explicit nodes, let the caller solve it later */
4442                         iter = NULL;
4443                     }
4444                     break;
4445                 }
4446             }
4447         }
4448 
4449         if (!iter) {
4450             if (!start) {
4451                 /* add as the only child of the parent */
4452                 start = ins;
4453                 if (parent) {
4454                     parent->child = ins;
4455                 }
4456             } else if (isrpc) {
4457                 /* add to the specific position in rpc/rpc-reply/action */
4458                 for (par1 = lys_parent(ins->schema); !(par1->nodetype & (LYS_INPUT | LYS_OUTPUT)); par1 = lys_parent(par1));
4459                 siter = NULL;
4460                 LY_TREE_FOR(start, iter) {
4461                     while ((siter = lys_getnext(siter, par1, lys_node_module(par1), 0))) {
4462                         if (iter->schema == siter || ins->schema == siter) {
4463                             break;
4464                         }
4465                     }
4466                     if (ins->schema == siter) {
4467                         if ((siter->nodetype & (LYS_LEAFLIST | LYS_LIST)) && iter->schema == siter) {
4468                             /* we are inserting leaflist/list instance, but since there are already
4469                              * some instances of the same leaflist/list, we want to insert the new one
4470                              * as the last instance, so here we have to move on */
4471                             while (iter && iter->schema == siter) {
4472                                 iter = iter->next;
4473                             }
4474                             if (!iter) {
4475                                 break;
4476                             }
4477                         }
4478                         /* we have the correct place for new node (before the iter) */
4479                         if (iter == start) {
4480                             start = ins;
4481                             if (parent) {
4482                                 parent->child = ins;
4483                             }
4484                         } else {
4485                             iter->prev->next = ins;
4486                         }
4487                         ins->prev = iter->prev;
4488                         iter->prev = ins;
4489                         ins->next = iter;
4490 
4491                         /* we are done */
4492                         break;
4493                     }
4494                 }
4495                 if (!iter) {
4496                     /* add as the last child of the parent */
4497                     start->prev->next = ins;
4498                     ins->prev = start->prev;
4499                     start->prev = ins;
4500                 }
4501             } else {
4502                 /* add as the last child of the parent */
4503                 start->prev->next = ins;
4504                 ins->prev = start->prev;
4505                 start->prev = ins;
4506             }
4507         }
4508 
4509 #ifdef LY_ENABLED_CACHE
4510         lyd_unlink_hash(ins, ins->parent);
4511 #endif
4512 
4513         ins->parent = parent;
4514 
4515 #ifdef LY_ENABLED_CACHE
4516         lyd_insert_hash(ins);
4517 #endif
4518 
4519         if (invalid) {
4520             lyd_insert_setinvalid(ins);
4521         }
4522     }
4523     ly_set_free(llists);
4524 
4525     if (clrdflt) {
4526         /* remove the dflt flag from parents */
4527         for (iter = parent; iter && iter->dflt; iter = iter->parent) {
4528             iter->dflt = 0;
4529         }
4530     }
4531 
4532     if (sibling) {
4533         *sibling = start;
4534     }
4535     return EXIT_SUCCESS;
4536 
4537 error:
4538     ly_set_free(llists);
4539     return EXIT_FAILURE;
4540 }
4541 
4542 API int
lyd_insert(struct lyd_node * parent,struct lyd_node * node)4543 lyd_insert(struct lyd_node *parent, struct lyd_node *node)
4544 {
4545     FUN_IN;
4546 
4547     if (!node || !parent || (parent->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
4548         LOGARG;
4549         return EXIT_FAILURE;
4550     }
4551 
4552     return lyd_insert_common(parent, NULL, node, 1);
4553 }
4554 
4555 API int
lyd_insert_sibling(struct lyd_node ** sibling,struct lyd_node * node)4556 lyd_insert_sibling(struct lyd_node **sibling, struct lyd_node *node)
4557 {
4558     FUN_IN;
4559 
4560     if (!sibling || !node) {
4561         LOGARG;
4562         return EXIT_FAILURE;
4563     }
4564 
4565     return lyd_insert_common((*sibling) ? (*sibling)->parent : NULL, sibling, node, 1);
4566 
4567 }
4568 
4569 int
lyd_insert_nextto(struct lyd_node * sibling,struct lyd_node * node,int before,int invalidate)4570 lyd_insert_nextto(struct lyd_node *sibling, struct lyd_node *node, int before, int invalidate)
4571 {
4572     struct ly_ctx *ctx;
4573     struct lys_node *par1, *par2;
4574     struct lyd_node *iter, *start = NULL, *ins, *next1, *next2, *last = NULL;
4575     struct lyd_node *orig_parent = NULL, *orig_prev = NULL, *orig_next = NULL;
4576     int invalid = 0;
4577     char *str;
4578 
4579     assert(sibling);
4580     assert(node);
4581 
4582     ctx = sibling->schema->module->ctx;
4583 
4584     if (sibling == node) {
4585         return EXIT_SUCCESS;
4586     }
4587 
4588     /* check placing the node to the appropriate place according to the schema */
4589     for (par1 = lys_parent(sibling->schema);
4590          par1 && !(par1->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_ACTION | LYS_NOTIF));
4591          par1 = lys_parent(par1));
4592     for (par2 = lys_parent(node->schema);
4593          par2 && !(par2->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_ACTION | LYS_NOTIF));
4594          par2 = lys_parent(par2));
4595     if (par1 != par2) {
4596         LOGERR(ctx, LY_EINVAL, "Cannot insert, different parents (\"%s\" and \"%s\").",
4597                (par1 ? par1->name : "<top-lvl>"), (par2 ? par2->name : "<top-lvl>"));
4598         return EXIT_FAILURE;
4599     }
4600 
4601     if (invalidate && ((node->parent != sibling->parent) || (invalid = lyp_is_rpc_action(node->schema)) || !node->parent)) {
4602         /* a) it is not just moving under a parent node (invalid = 1) or
4603          * b) it is in an RPC where nodes order matters (invalid = 2) or
4604          * c) it is top-level where we don't know if it is the same tree (invalid = 1),
4605          * so the validation will be necessary */
4606         if (!node->parent && !invalid) {
4607             /* c) search in siblings */
4608             for (iter = node->prev; iter != node; iter = iter->prev) {
4609                 if (iter == sibling) {
4610                     break;
4611                 }
4612             }
4613             if (iter == node) {
4614                 /* node and siblings are not currently in the same data tree */
4615                 invalid++;
4616             }
4617         } else { /* a) and b) */
4618             invalid++;
4619         }
4620     }
4621 
4622     /* unlink only if it is not a list of siblings without a parent or node is not the first sibling,
4623      * always unlink if just moving a node */
4624     if ((!invalid) || node->parent || node->prev->next) {
4625         /* remember the original position to be able to revert
4626          * unlink in case of error */
4627         orig_parent = node->parent;
4628         if (node->prev != node) {
4629             orig_prev = node->prev;
4630         }
4631         orig_next = node->next;
4632         lyd_unlink_internal(node, invalid);
4633     }
4634 
4635     /* find first sibling node */
4636     if (sibling->parent) {
4637         start = sibling->parent->child;
4638     } else {
4639         for (start = sibling; start->prev->next; start = start->prev);
4640     }
4641 
4642     /* process the nodes one by one to clean the current tree */
4643     if (!invalid) {
4644         /* just moving one sibling */
4645         last = node;
4646         node->parent = sibling->parent;
4647     } else {
4648         LY_TREE_FOR_SAFE(node, next1, ins) {
4649             lyd_insert_setinvalid(ins);
4650 
4651             if (invalid == 1) {
4652                 /* auto delete nodes from other cases */
4653                 if (lyv_multicases(ins, NULL, &start, 1, sibling) == 2) {
4654                     LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYD, sibling, "Insert request refers node (%s) that is going to be auto-deleted.",
4655                         ly_errpath(ctx));
4656                     goto error;
4657                 }
4658             }
4659 
4660             /* try to find previously present default instance to remove because of
4661             * inserting the specified node */
4662             if (ins->schema->nodetype == LYS_LEAFLIST) {
4663                 LY_TREE_FOR_SAFE(start, next2, iter) {
4664                     if (iter->schema == ins->schema) {
4665                         if ((ins->dflt && (!iter->dflt || ((iter->schema->flags & LYS_CONFIG_W) &&
4666                                                         !strcmp(((struct lyd_node_leaf_list *)iter)->value_str,
4667                                                                 ((struct lyd_node_leaf_list *)ins)->value_str))))
4668                                 || (!ins->dflt && iter->dflt)) {
4669                             /* iter will get deleted */
4670                             if (iter == sibling) {
4671                                 LOGERR(ctx, LY_EINVAL, "Insert request refers node (%s) that is going to be auto-deleted.",
4672                                     str = lyd_path(sibling));
4673                                 free(str);
4674                                 goto error;
4675                             }
4676                             if (iter == start) {
4677                                 start = next2;
4678                             }
4679                             lyd_free(iter);
4680                         }
4681                     }
4682                 }
4683             } else if (ins->schema->nodetype == LYS_LEAF ||
4684                     (ins->schema->nodetype == LYS_CONTAINER && !((struct lys_node_container *)ins->schema)->presence)) {
4685                 LY_TREE_FOR(start, iter) {
4686                     if (iter->schema == ins->schema) {
4687                         if (iter->dflt || ins->dflt) {
4688                             /* iter gets deleted */
4689                             if (iter == sibling) {
4690                                 LOGERR(ctx, LY_EINVAL, "Insert request refers node (%s) that is going to be auto-deleted.",
4691                                     str = lyd_path(sibling));
4692                                 free(str);
4693                                 goto error;
4694                             }
4695                             if (iter == start) {
4696                                 start = iter->next;
4697                             }
4698                             lyd_free(iter);
4699                         }
4700                         break;
4701                     }
4702                 }
4703             }
4704 
4705             ins->parent = sibling->parent;
4706             last = ins;
4707         }
4708     }
4709 
4710     /* insert the (list of) node(s) to the specified position */
4711     if (before) {
4712         if (sibling->prev->next) {
4713             /* adding into the middle */
4714             sibling->prev->next = node;
4715         } else if (sibling->parent) {
4716             /* at the beginning */
4717             sibling->parent->child = node;
4718         }
4719         node->prev = sibling->prev;
4720         sibling->prev = last;
4721         last->next = sibling;
4722     } else { /* after */
4723         if (sibling->next) {
4724             /* adding into the middle - fix the prev pointer of the node after inserted nodes */
4725             last->next = sibling->next;
4726             sibling->next->prev = last;
4727         } else {
4728             /* at the end - fix the prev pointer of the first node */
4729             start->prev = last;
4730         }
4731         sibling->next = node;
4732         node->prev = sibling;
4733     }
4734 
4735 #ifdef LY_ENABLED_CACHE
4736     /* now that all the nodes are correctly inserted, fix hashes (node was already unlinked) */
4737     lyd_insert_hash(node);
4738 
4739     /* relink all following nodes */
4740     iter = node;
4741     for (iter = node; iter != last; iter = iter->next) {
4742         lyd_unlink_hash(iter, iter->parent);
4743         lyd_insert_hash(iter);
4744     }
4745 #endif
4746 
4747     return EXIT_SUCCESS;
4748 
4749 error:
4750     /* insert back to the original position */
4751     if (orig_prev) {
4752         lyd_insert_after(orig_prev, node);
4753     } else if (orig_next) {
4754         lyd_insert_before(orig_next, node);
4755     } else if (orig_parent) {
4756         /* there were no siblings */
4757         orig_parent->child = node;
4758         node->parent = orig_parent;
4759     }
4760     return EXIT_FAILURE;
4761 }
4762 
4763 API int
lyd_insert_before(struct lyd_node * sibling,struct lyd_node * node)4764 lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
4765 {
4766     FUN_IN;
4767 
4768     if (!node || !sibling) {
4769         LOGARG;
4770         return EXIT_FAILURE;
4771     }
4772 
4773     return lyd_insert_nextto(sibling, node, 1, 1);
4774 }
4775 
4776 API int
lyd_insert_after(struct lyd_node * sibling,struct lyd_node * node)4777 lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
4778 {
4779     FUN_IN;
4780 
4781     if (!node || !sibling) {
4782         LOGARG;
4783         return EXIT_FAILURE;
4784     }
4785 
4786     return lyd_insert_nextto(sibling, node, 0, 1);
4787 }
4788 
4789 static uint32_t
lys_module_pos(struct lys_module * module)4790 lys_module_pos(struct lys_module *module)
4791 {
4792     int i;
4793     uint32_t pos = 1;
4794 
4795     for (i = 0; i < module->ctx->models.used; ++i) {
4796         if (module->ctx->models.list[i] == module) {
4797             return pos;
4798         }
4799         ++pos;
4800     }
4801 
4802     LOGINT(module->ctx);
4803     return 0;
4804 }
4805 
4806 static int
lys_module_node_pos_r(struct lys_node * first_sibling,struct lys_node * target,uint32_t * pos)4807 lys_module_node_pos_r(struct lys_node *first_sibling, struct lys_node *target, uint32_t *pos)
4808 {
4809     const struct lys_node *next = NULL;
4810 
4811     /* the schema nodes are actually from data, lys_getnext skips non-data schema nodes for us (we know the parent will not be uses) */
4812     while ((next = lys_getnext(next, lys_parent(first_sibling), lys_node_module(first_sibling), LYS_GETNEXT_NOSTATECHECK))) {
4813         ++(*pos);
4814         if (target == next) {
4815             return 0;
4816         }
4817     }
4818 
4819     LOGINT(first_sibling->module->ctx);
4820     return 1;
4821 }
4822 
4823 static int
lyd_node_pos_cmp(const void * item1,const void * item2)4824 lyd_node_pos_cmp(const void *item1, const void *item2)
4825 {
4826     uint32_t mpos1, mpos2;
4827     struct lyd_node_pos *np1, *np2;
4828 
4829     np1 = (struct lyd_node_pos *)item1;
4830     np2 = (struct lyd_node_pos *)item2;
4831 
4832     /* different modules? */
4833     if (lys_node_module(np1->node->schema) != lys_node_module(np2->node->schema)) {
4834         mpos1 = lys_module_pos(lys_node_module(np1->node->schema));
4835         mpos2 = lys_module_pos(lys_node_module(np2->node->schema));
4836         /* if lys_module_pos failed, there is nothing we can do anyway,
4837          * at least internal error will be printed */
4838 
4839         if (mpos1 > mpos2) {
4840             return 1;
4841         } else {
4842             return -1;
4843         }
4844     }
4845 
4846     if (np1->pos > np2->pos) {
4847         return 1;
4848     } else if (np1->pos < np2->pos) {
4849         return -1;
4850     }
4851     return 0;
4852 }
4853 
4854 API int
lyd_schema_sort(struct lyd_node * sibling,int recursive)4855 lyd_schema_sort(struct lyd_node *sibling, int recursive)
4856 {
4857     FUN_IN;
4858 
4859     uint32_t len, i;
4860     struct lyd_node *node;
4861     struct lys_node *first_ssibling = NULL;
4862     struct lyd_node_pos *array;
4863 
4864     if (!sibling) {
4865         LOGARG;
4866         return -1;
4867     }
4868 
4869     /* something actually to sort */
4870     if (sibling->prev != sibling) {
4871 
4872         /* find the beginning */
4873         sibling = lyd_first_sibling(sibling);
4874 
4875         /* count siblings */
4876         len = 0;
4877         for (node = sibling; node; node = node->next) {
4878             ++len;
4879         }
4880 
4881         array = malloc(len * sizeof *array);
4882         LY_CHECK_ERR_RETURN(!array, LOGMEM(sibling->schema->module->ctx), -1);
4883 
4884         /* fill arrays with positions and corresponding nodes */
4885         for (i = 0, node = sibling; i < len; ++i, node = node->next) {
4886             array[i].pos = 0;
4887 
4888             /* we need to repeat this for every module */
4889             if (!first_ssibling || (lyd_node_module(node) != lys_node_module(first_ssibling))) {
4890                 /* find the data node schema parent */
4891                 first_ssibling = node->schema;
4892                 while (lys_parent(first_ssibling)
4893                         && (lys_parent(first_ssibling)->nodetype & (LYS_CHOICE | LYS_CASE | LYS_USES))) {
4894                     first_ssibling = lys_parent(first_ssibling);
4895                 }
4896 
4897                 /* find the beginning */
4898                 if (lys_parent(first_ssibling)) {
4899                     first_ssibling = lys_parent(first_ssibling)->child;
4900                 } else {
4901                     while (first_ssibling->prev->next) {
4902                         first_ssibling = first_ssibling->prev;
4903                     }
4904                 }
4905             }
4906 
4907             if (lys_module_node_pos_r(first_ssibling, node->schema, &array[i].pos)) {
4908                 free(array);
4909                 return -1;
4910             }
4911 
4912             array[i].node = node;
4913         }
4914 
4915         /* sort the arrays */
4916         qsort(array, len, sizeof *array, lyd_node_pos_cmp);
4917 
4918         /* adjust siblings based on the sorted array */
4919         for (i = 0; i < len; ++i) {
4920             /* parent child */
4921             if (i == 0) {
4922                 /* adjust sibling so that it still points to the beginning */
4923                 sibling = array[i].node;
4924                 if (array[i].node->parent) {
4925                     array[i].node->parent->child = array[i].node;
4926                 }
4927             }
4928 
4929             /* prev */
4930             if (i > 0) {
4931                 array[i].node->prev = array[i - 1].node;
4932             } else {
4933                 array[i].node->prev = array[len - 1].node;
4934             }
4935 
4936             /* next */
4937             if (i < len - 1) {
4938                 array[i].node->next = array[i + 1].node;
4939             } else {
4940                 array[i].node->next = NULL;
4941             }
4942         }
4943         free(array);
4944     }
4945 
4946     /* sort all the children recursively */
4947     if (recursive) {
4948         LY_TREE_FOR(sibling, node) {
4949             if ((node->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_ACTION | LYS_NOTIF))
4950                     && node->child && lyd_schema_sort(node->child, recursive)) {
4951                 return -1;
4952             }
4953         }
4954     }
4955 
4956     return EXIT_SUCCESS;
4957 }
4958 
4959 static int
_lyd_validate(struct lyd_node ** node,struct lyd_node * data_tree,struct ly_ctx * ctx,const struct lys_module ** modules,int mod_count,struct lyd_difflist ** diff,int options)4960 _lyd_validate(struct lyd_node **node, struct lyd_node *data_tree, struct ly_ctx *ctx, const struct lys_module **modules,
4961               int mod_count, struct lyd_difflist **diff, int options)
4962 {
4963     struct lyd_node *root, *next1, *next2, *iter, *act_notif = NULL;
4964     int ret = EXIT_FAILURE;
4965     unsigned int i;
4966     struct unres_data *unres = NULL;
4967     const struct lys_module *yanglib_mod;
4968 
4969     unres = calloc(1, sizeof *unres);
4970     LY_CHECK_ERR_RETURN(!unres, LOGMEM(NULL), EXIT_FAILURE);
4971 
4972     if (diff) {
4973         unres->store_diff = 1;
4974         unres->diff = lyd_diff_init_difflist(ctx, &unres->diff_size);
4975     }
4976 
4977     if ((options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) && *node && ((*node)->schema->nodetype != LYS_RPC)) {
4978         options |= LYD_OPT_ACT_NOTIF;
4979     }
4980     if ((options & (LYD_OPT_NOTIF | LYD_OPT_NOTIF_FILTER)) && *node && ((*node)->schema->nodetype != LYS_NOTIF)) {
4981         options |= LYD_OPT_ACT_NOTIF;
4982     }
4983 
4984     LY_TREE_FOR_SAFE(*node, next1, root) {
4985         if (modules) {
4986             for (i = 0; i < (unsigned)mod_count; ++i) {
4987                 if (lyd_node_module(root) == modules[i]) {
4988                     break;
4989                 }
4990             }
4991             if (i == (unsigned)mod_count) {
4992                 /* skip data that should not be validated */
4993                 continue;
4994             }
4995         }
4996 
4997         LY_TREE_DFS_BEGIN(root, next2, iter) {
4998             if (iter->parent && (iter->schema->nodetype & (LYS_ACTION | LYS_NOTIF))) {
4999                 if (!(options & LYD_OPT_ACT_NOTIF) || act_notif) {
5000                     LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, iter, iter->schema->name);
5001                     LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Unexpected %s node \"%s\".",
5002                            (options & LYD_OPT_RPC ? "action" : "notification"), iter->schema->name);
5003                     goto cleanup;
5004                 }
5005                 act_notif = iter;
5006             }
5007 
5008             if (lyv_data_context(iter, options, 1, unres) || lyv_data_content(iter, options, unres)) {
5009                 goto cleanup;
5010             }
5011 
5012             /* empty non-default, non-presence container without attributes, make it default */
5013             if (!iter->dflt && (iter->schema->nodetype == LYS_CONTAINER) && !iter->child
5014                         && !((struct lys_node_container *)iter->schema)->presence && !iter->attr) {
5015                 iter->dflt = 1;
5016             }
5017 
5018             LY_TREE_DFS_END(root, next2, iter);
5019         }
5020 
5021         if (options & LYD_OPT_NOSIBLINGS) {
5022             break;
5023         }
5024 
5025     }
5026 
5027     if (options & LYD_OPT_ACT_NOTIF) {
5028         if (!act_notif) {
5029             LOGVAL(ctx, LYE_MISSELEM, LY_VLOG_LYD, *node, (options & LYD_OPT_RPC ? "action" : "notification"), (*node)->schema->name);
5030             goto cleanup;
5031         }
5032         options &= ~LYD_OPT_ACT_NOTIF;
5033     }
5034 
5035     if (*node) {
5036         /* check for uniqueness of top-level lists/leaflists because
5037          * only the inner instances were tested in lyv_data_content() */
5038         yanglib_mod = ly_ctx_get_module(ctx ? ctx : (*node)->schema->module->ctx, "ietf-yang-library", NULL, 1);
5039         LY_TREE_FOR(*node, root) {
5040             if ((options & LYD_OPT_DATA_ADD_YANGLIB) && yanglib_mod && (root->schema->module == yanglib_mod)) {
5041                 /* ietf-yang-library data present, so ignore the option to add them */
5042                 options &= ~LYD_OPT_DATA_ADD_YANGLIB;
5043             }
5044 
5045             if (!(root->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(root->validity & LYD_VAL_DUP)) {
5046                 continue;
5047             }
5048 
5049             if (options & LYD_OPT_TRUSTED) {
5050                 /* just clear the flag */
5051                 root->validity &= ~LYD_VAL_DUP;
5052                 continue;
5053             }
5054 
5055             if (lyv_data_dup(root, *node)) {
5056                 goto cleanup;
5057             }
5058         }
5059     }
5060 
5061     /* add missing ietf-yang-library if requested */
5062     if (options & LYD_OPT_DATA_ADD_YANGLIB) {
5063         if (!(*node)) {
5064             (*node) = ly_ctx_info(ctx);
5065         } else if (lyd_merge((*node), ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
5066             LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
5067             goto cleanup;
5068         }
5069     }
5070 
5071     /* add default values, resolve unres and check for mandatory nodes in final tree */
5072     if (lyd_defaults_add_unres(node, options, ctx, modules, mod_count, data_tree, act_notif, unres, 1)) {
5073         goto cleanup;
5074     }
5075     if (act_notif) {
5076         if (lyd_check_mandatory_tree(act_notif, ctx, modules, mod_count, options)) {
5077             goto cleanup;
5078         }
5079     } else {
5080         if (lyd_check_mandatory_tree(*node, ctx, modules, mod_count, options)) {
5081             goto cleanup;
5082         }
5083     }
5084 
5085     if ((options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) && *node && lyd_schema_sort(*node, 1)) {
5086         /* rpc and rpc-reply must be sorted */
5087         goto cleanup;
5088     }
5089 
5090     /* consolidate diff if created */
5091     if (diff) {
5092         assert(unres->store_diff);
5093 
5094         for (i = 0; i < unres->diff_idx; ++i) {
5095             if (unres->diff->type[i] == LYD_DIFF_CREATED) {
5096                 if (unres->diff->second[i]->parent) {
5097                     unres->diff->first[i] = (struct lyd_node *)lyd_path(unres->diff->second[i]->parent);
5098                 }
5099                 unres->diff->second[i] = lyd_dup(unres->diff->second[i], LYD_DUP_OPT_RECURSIVE);
5100             }
5101         }
5102 
5103         *diff = unres->diff;
5104         unres->diff = 0;
5105         unres->diff_idx = 0;
5106     }
5107 
5108     ret = EXIT_SUCCESS;
5109 
5110 cleanup:
5111     if (unres) {
5112         free(unres->node);
5113         free(unres->type);
5114         for (i = 0; i < unres->diff_idx; ++i) {
5115             if (unres->diff->type[i] == LYD_DIFF_DELETED) {
5116                 lyd_free_withsiblings(unres->diff->first[i]);
5117                 free(unres->diff->second[i]);
5118             }
5119         }
5120         lyd_free_diff(unres->diff);
5121         free(unres);
5122     }
5123 
5124     return ret;
5125 }
5126 
5127 API int
lyd_validate(struct lyd_node ** node,int options,void * var_arg,...)5128 lyd_validate(struct lyd_node **node, int options, void *var_arg, ...)
5129 {
5130     FUN_IN;
5131 
5132     struct lyd_node *iter, *data_tree = NULL;
5133     struct lyd_difflist **diff = NULL;
5134     struct ly_ctx *ctx = NULL;
5135     va_list ap;
5136 
5137     if (!node) {
5138         LOGARG;
5139         return EXIT_FAILURE;
5140     }
5141 
5142     if (lyp_data_check_options(NULL, options, __func__)) {
5143         return EXIT_FAILURE;
5144     }
5145 
5146     data_tree = *node;
5147 
5148     if ((!(options & LYD_OPT_TYPEMASK)
5149             || (options & (LYD_OPT_CONFIG | LYD_OPT_GET | LYD_OPT_GETCONFIG | LYD_OPT_EDIT))) && !(*node)) {
5150         /* get context with schemas from the var_arg */
5151         ctx = (struct ly_ctx *)var_arg;
5152         if (!ctx) {
5153             LOGERR(NULL, LY_EINVAL, "%s: invalid variable parameter (struct ly_ctx *ctx).", __func__);
5154             return EXIT_FAILURE;
5155         }
5156 
5157         /* LYD_OPT_NOSIBLINGS has no meaning here */
5158         options &= ~LYD_OPT_NOSIBLINGS;
5159     } else if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
5160         /* LYD_OPT_NOSIBLINGS cannot be set in this case */
5161         if (options & LYD_OPT_NOSIBLINGS) {
5162             LOGERR(NULL, LY_EINVAL, "%s: invalid parameter (variable arg const struct lyd_node *data_tree with LYD_OPT_NOSIBLINGS).", __func__);
5163             return EXIT_FAILURE;
5164         } else if (!(*node)) {
5165             LOGARG;
5166             return EXIT_FAILURE;
5167         }
5168 
5169         /* get the additional data tree if given */
5170         data_tree = (struct lyd_node *)var_arg;
5171         if (data_tree) {
5172             if (options & LYD_OPT_NOEXTDEPS) {
5173                 LOGERR(NULL, LY_EINVAL, "%s: invalid parameter (variable arg const struct lyd_node *data_tree and LYD_OPT_NOEXTDEPS set).",
5174                        __func__);
5175                 return EXIT_FAILURE;
5176             }
5177 
5178             LY_TREE_FOR(data_tree, iter) {
5179                 if (iter->parent) {
5180                     /* a sibling is not top-level */
5181                     LOGERR(NULL, LY_EINVAL, "%s: invalid variable parameter (const struct lyd_node *data_tree).", __func__);
5182                     return EXIT_FAILURE;
5183                 }
5184             }
5185 
5186             /* move it to the beginning */
5187             for (; data_tree->prev->next; data_tree = data_tree->prev);
5188         }
5189     } else if (options & LYD_OPT_DATA_TEMPLATE) {
5190         /* get context with schemas from the var_arg */
5191         if (*node && ((*node)->prev->next || (*node)->next)) {
5192             /* not allow sibling in top-level */
5193             LOGERR(NULL, LY_EINVAL, "%s: invalid variable parameter (struct lyd_node *node).", __func__);
5194             return EXIT_FAILURE;
5195         }
5196     }
5197 
5198     if (options & LYD_OPT_VAL_DIFF) {
5199         va_start(ap, var_arg);
5200         diff = va_arg(ap, struct lyd_difflist **);
5201         va_end(ap);
5202         if (!diff) {
5203             LOGERR(ctx, LY_EINVAL, "%s: invalid variable parameter (struct lyd_difflist **).", __func__);
5204             return EXIT_FAILURE;
5205         }
5206     }
5207 
5208     if (*node) {
5209         if (!ctx) {
5210             ctx = (*node)->schema->module->ctx;
5211         }
5212         if (!(options & LYD_OPT_NOSIBLINGS)) {
5213             /* check that the node is the first sibling */
5214             while ((*node)->prev->next) {
5215                 *node = (*node)->prev;
5216             }
5217         }
5218     }
5219 
5220     return _lyd_validate(node, data_tree, ctx, NULL, 0, diff, options);
5221 }
5222 
5223 API int
lyd_validate_modules(struct lyd_node ** node,const struct lys_module ** modules,int mod_count,int options,...)5224 lyd_validate_modules(struct lyd_node **node, const struct lys_module **modules, int mod_count, int options, ...)
5225 {
5226     FUN_IN;
5227 
5228     struct ly_ctx *ctx;
5229     struct lyd_difflist **diff = NULL;
5230     va_list ap;
5231 
5232     if (!node || !modules || !mod_count) {
5233         LOGARG;
5234         return EXIT_FAILURE;
5235     }
5236 
5237     ctx = modules[0]->ctx;
5238 
5239     if (*node && !(options & LYD_OPT_NOSIBLINGS)) {
5240         /* check that the node is the first sibling */
5241         while ((*node)->prev->next) {
5242             *node = (*node)->prev;
5243         }
5244     }
5245 
5246     if (lyp_data_check_options(ctx, options, __func__)) {
5247         return EXIT_FAILURE;
5248     }
5249 
5250     if ((options & LYD_OPT_TYPEMASK) && !(options & (LYD_OPT_CONFIG | LYD_OPT_GET | LYD_OPT_GETCONFIG | LYD_OPT_EDIT))) {
5251         LOGERR(NULL, LY_EINVAL, "%s: options include a forbidden data type.", __func__);
5252         return EXIT_FAILURE;
5253     }
5254 
5255     if (options & LYD_OPT_VAL_DIFF) {
5256         va_start(ap, options);
5257         diff = va_arg(ap, struct lyd_difflist **);
5258         va_end(ap);
5259         if (!diff) {
5260             LOGERR(ctx, LY_EINVAL, "%s: invalid variable parameter (struct lyd_difflist **).", __func__);
5261             return EXIT_FAILURE;
5262         }
5263     }
5264 
5265     return _lyd_validate(node, *node, ctx, modules, mod_count, diff, options);
5266 }
5267 
5268 API int
lyd_validate_value(struct lys_node * node,const char * value)5269 lyd_validate_value(struct lys_node *node, const char *value)
5270 {
5271     return lyd_value_type(node, value, NULL);
5272 }
5273 
5274 int
lyd_value_type_internal(struct lys_node * node,const char * value,const struct lys_module * local_mod,struct lys_type ** type)5275 lyd_value_type_internal(struct lys_node *node, const char *value, const struct lys_module *local_mod,
5276                         struct lys_type **type)
5277 {
5278     FUN_IN;
5279 
5280     struct lyd_node_leaf_list leaf;
5281     struct lys_node_leaf *sleaf = (struct lys_node_leaf*)node;
5282     struct lys_type *t = NULL;
5283 
5284     if (!node || !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
5285         LOGARG;
5286         return EXIT_FAILURE;
5287     }
5288 
5289     if (!value) {
5290         value = "";
5291     }
5292 
5293     /* dummy leaf */
5294     memset(&leaf, 0, sizeof leaf);
5295     leaf.value_str = lydict_insert(node->module->ctx, value, 0);
5296 
5297 repeat:
5298     leaf.value_type = sleaf->type.base;
5299     leaf.schema = node;
5300 
5301     if (leaf.value_type == LY_TYPE_LEAFREF) {
5302         if (!sleaf->type.info.lref.target) {
5303             /* it should either be unresolved leafref (leaf.value_type are ORed flags) or it will be resolved */
5304             LOGINT(node->module->ctx);
5305             goto cleanup;
5306         }
5307         sleaf = sleaf->type.info.lref.target;
5308         goto repeat;
5309     } else {
5310         t = lyp_parse_value(&sleaf->type, &leaf.value_str, NULL, &leaf, NULL, (struct lys_module *)local_mod, 0,
5311                             local_mod ? 1 : 0);
5312     }
5313 
5314 cleanup:
5315     lydict_remove(node->module->ctx, leaf.value_str);
5316     if (type) {
5317         *type = t;
5318     }
5319     return t ? EXIT_SUCCESS : EXIT_FAILURE;
5320 }
5321 
5322 API int
lyd_value_type(struct lys_node * node,const char * value,struct lys_type ** type)5323 lyd_value_type(struct lys_node *node, const char *value, struct lys_type **type)
5324 {
5325     return lyd_value_type_internal(node, value, NULL, type);
5326 }
5327 
5328 /* create an attribute copy */
5329 static struct lyd_attr *
lyd_dup_attr(struct ly_ctx * ctx,struct lyd_node * parent,struct lyd_attr * attr)5330 lyd_dup_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr)
5331 {
5332     struct lyd_attr *ret;
5333 
5334     /* allocate new attr */
5335     if (!parent->attr) {
5336         parent->attr = calloc(1, sizeof *ret);
5337         ret = parent->attr;
5338     } else {
5339         for (ret = parent->attr; ret->next; ret = ret->next);
5340         ret->next = calloc(1, sizeof *ret);
5341         ret = ret->next;
5342     }
5343     LY_CHECK_ERR_RETURN(!ret, LOGMEM(ctx), NULL);
5344 
5345     /* fill new attr except */
5346     ret->parent = parent;
5347     ret->annotation = attr->annotation;
5348     ret->name = lydict_insert(ctx, attr->name, 0);
5349     ret->value_str = lydict_insert(ctx, attr->value_str, 0);
5350     ret->value_type = attr->value_type;
5351     ret->value_flags = attr->value_flags;
5352     switch (ret->value_type) {
5353     case LY_TYPE_BINARY:
5354     case LY_TYPE_STRING:
5355         /* value_str pointer is shared in these cases */
5356         ret->value.string = ret->value_str;
5357         break;
5358     case LY_TYPE_LEAFREF:
5359         lyp_parse_value(*((struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, ret->annotation, NULL)),
5360                              &ret->value_str, NULL, NULL, ret, NULL, 1, 0);
5361         break;
5362     case LY_TYPE_INST:
5363         ret->value.instance = NULL;
5364         break;
5365     case LY_TYPE_UNION:
5366         /* unresolved union (this must be non-validated tree), duplicate the stored string (duplicated
5367          * because of possible change of the value in case of instance-identifier) */
5368         ret->value.string = lydict_insert(ctx, attr->value.string, 0);
5369         break;
5370     case LY_TYPE_ENUM:
5371     case LY_TYPE_IDENT:
5372     case LY_TYPE_BITS:
5373         /* in case of duplicating bits (no matter if in the same context or not) or enum and identityref into
5374          * a different context, searching for the type and duplicating the data is almost as same as resolving
5375          * the string value, so due to a simplicity, parse the value for the duplicated leaf */
5376         lyp_parse_value(*((struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, ret->annotation, NULL)),
5377                              &ret->value_str, NULL, NULL, ret, NULL, 1, 0);
5378         break;
5379     default:
5380         ret->value = attr->value;
5381         break;
5382     }
5383     return ret;
5384 }
5385 
5386 int
lyd_unlink_internal(struct lyd_node * node,int permanent)5387 lyd_unlink_internal(struct lyd_node *node, int permanent)
5388 {
5389     struct lyd_node *iter;
5390     (void)permanent;
5391 
5392     if (!node) {
5393         LOGARG;
5394         return EXIT_FAILURE;
5395     }
5396 
5397     /* unlink from siblings */
5398     if (node->prev->next) {
5399         node->prev->next = node->next;
5400     }
5401     if (node->next) {
5402         node->next->prev = node->prev;
5403     } else {
5404         /* unlinking the last node */
5405         if (node->parent) {
5406             iter = node->parent->child;
5407         } else {
5408             iter = node->prev;
5409             while (iter->prev != node) {
5410                 iter = iter->prev;
5411             }
5412         }
5413         /* update the "last" pointer from the first node */
5414         iter->prev = node->prev;
5415     }
5416 
5417     /* unlink from parent */
5418     if (node->parent) {
5419         if (node->parent->child == node) {
5420             /* the node is the first child */
5421             node->parent->child = node->next;
5422         }
5423 
5424 #ifdef LY_ENABLED_CACHE
5425         /* do not remove from parent hash table if freeing the whole subtree */
5426         if (permanent != 2) {
5427             lyd_unlink_hash(node, node->parent);
5428         }
5429 #endif
5430 
5431         node->parent = NULL;
5432     }
5433 
5434     node->next = NULL;
5435     node->prev = node;
5436 
5437     return EXIT_SUCCESS;
5438 }
5439 
5440 API int
lyd_unlink(struct lyd_node * node)5441 lyd_unlink(struct lyd_node *node)
5442 {
5443     FUN_IN;
5444 
5445     return lyd_unlink_internal(node, 1);
5446 }
5447 
5448 /*
5449  * - in leaflist it must be added with value_str
5450  */
5451 static int
_lyd_dup_node_common(struct lyd_node * new_node,const struct lyd_node * orig,struct ly_ctx * ctx,int options)5452 _lyd_dup_node_common(struct lyd_node *new_node, const struct lyd_node *orig, struct ly_ctx *ctx, int options)
5453 {
5454     struct lyd_attr *attr;
5455 
5456     new_node->attr = NULL;
5457     if (!(options & LYD_DUP_OPT_NO_ATTR)) {
5458         LY_TREE_FOR(orig->attr, attr) {
5459             lyd_dup_attr(ctx, new_node, attr);
5460         }
5461     }
5462     new_node->next = NULL;
5463     new_node->prev = new_node;
5464     new_node->parent = NULL;
5465     new_node->validity = ly_new_node_validity(new_node->schema);
5466     new_node->dflt = orig->dflt;
5467     if (options & LYD_DUP_OPT_WITH_WHEN) {
5468         new_node->when_status = orig->when_status;
5469     } else {
5470         new_node->when_status = orig->when_status & LYD_WHEN;
5471     }
5472 #ifdef LY_ENABLED_CACHE
5473     /* just copy the hash, it will not change */
5474     if ((new_node->schema->nodetype != LYS_LIST) || lyd_list_has_keys(new_node)) {
5475         new_node->hash = orig->hash;
5476     }
5477 #endif
5478 
5479 #ifdef LY_ENABLED_LYD_PRIV
5480     if (ctx->priv_dup_clb) {
5481         new_node->priv = ctx->priv_dup_clb(orig->priv);
5482     }
5483 #endif
5484 
5485     return EXIT_SUCCESS;
5486 }
5487 
5488 static struct lyd_node *
_lyd_dup_node(const struct lyd_node * node,const struct lys_node * schema,struct ly_ctx * ctx,int options)5489 _lyd_dup_node(const struct lyd_node *node, const struct lys_node *schema, struct ly_ctx *ctx, int options)
5490 {
5491     struct lyd_node *new_node = NULL;
5492     struct lys_node_leaf *sleaf;
5493     struct lyd_node_leaf_list *new_leaf;
5494     struct lyd_node_anydata *new_any, *old_any;
5495     const struct lys_type *type;
5496     int r;
5497 
5498     /* fill specific part */
5499     switch (node->schema->nodetype) {
5500     case LYS_LEAF:
5501     case LYS_LEAFLIST:
5502         new_leaf = calloc(1, sizeof *new_leaf);
5503         new_node = (struct lyd_node *)new_leaf;
5504         LY_CHECK_ERR_GOTO(!new_node, LOGMEM(ctx), error);
5505         new_leaf->schema = (struct lys_node *)schema;
5506 
5507         new_leaf->value_str = lydict_insert(ctx, ((struct lyd_node_leaf_list *)node)->value_str, 0);
5508         new_leaf->value_type = ((struct lyd_node_leaf_list *)node)->value_type;
5509         new_leaf->value_flags = ((struct lyd_node_leaf_list *)node)->value_flags;
5510         if (_lyd_dup_node_common(new_node, node, ctx, options)) {
5511             goto error;
5512         }
5513 
5514         /* get schema from the correct context */
5515         sleaf = (struct lys_node_leaf *)new_leaf->schema;
5516 
5517         switch (new_leaf->value_type) {
5518         case LY_TYPE_BINARY:
5519         case LY_TYPE_STRING:
5520             /* value_str pointer is shared in these cases */
5521             new_leaf->value.string = new_leaf->value_str;
5522             break;
5523         case LY_TYPE_LEAFREF:
5524             lyp_parse_value(&sleaf->type, &new_leaf->value_str, NULL, new_leaf, NULL, NULL, 1, node->dflt);
5525             break;
5526         case LY_TYPE_INST:
5527             new_leaf->value.instance = NULL;
5528             break;
5529         case LY_TYPE_UNION:
5530             /* unresolved union (this must be non-validated tree), duplicate the stored string (duplicated
5531              * because of possible change of the value in case of instance-identifier) */
5532             new_leaf->value.string = lydict_insert(ctx, ((struct lyd_node_leaf_list *)node)->value.string, 0);
5533             break;
5534         case LY_TYPE_ENUM:
5535         case LY_TYPE_IDENT:
5536         case LY_TYPE_BITS:
5537             /* in case of duplicating bits (no matter if in the same context or not) or enum and identityref into
5538              * a different context, searching for the type and duplicating the data is almost as same as resolving
5539              * the string value, so due to a simplicity, parse the value for the duplicated leaf */
5540             if (!lyp_parse_value(&sleaf->type, &new_leaf->value_str, NULL, new_leaf, NULL, NULL, 1, node->dflt)) {
5541                 goto error;
5542             }
5543             break;
5544         default:
5545             new_leaf->value = ((struct lyd_node_leaf_list *)node)->value;
5546             break;
5547         }
5548 
5549         if (new_leaf->value_flags & LY_VALUE_USER) {
5550             /* get the real type */
5551             type = lyd_leaf_type(new_leaf);
5552             if (!type || !type->der || !type->der->module) {
5553                 LOGINT(ctx);
5554                 goto error;
5555             }
5556 
5557             r = lytype_store(type->der->module, type->der->name, &new_leaf->value_str, &new_leaf->value);
5558             if (r == -1) {
5559                 goto error;
5560             } else if (r) {
5561                 LOGINT(ctx);
5562                 goto error;
5563             }
5564         }
5565         break;
5566     case LYS_ANYXML:
5567     case LYS_ANYDATA:
5568         old_any = (struct lyd_node_anydata *)node;
5569         new_any = calloc(1, sizeof *new_any);
5570         new_node = (struct lyd_node *)new_any;
5571         LY_CHECK_ERR_GOTO(!new_node, LOGMEM(ctx), error);
5572         new_any->schema = (struct lys_node *)schema;
5573 
5574         if (_lyd_dup_node_common(new_node, node, ctx, options)) {
5575             goto error;
5576         }
5577 
5578         new_any->value_type = old_any->value_type;
5579         if (!(void*)old_any->value.tree) {
5580             /* no value to duplicate */
5581             break;
5582         }
5583         /* duplicate the value */
5584         switch (old_any->value_type) {
5585         case LYD_ANYDATA_CONSTSTRING:
5586         case LYD_ANYDATA_SXML:
5587         case LYD_ANYDATA_JSON:
5588             new_any->value.str = lydict_insert(ctx, old_any->value.str, 0);
5589             break;
5590         case LYD_ANYDATA_DATATREE:
5591             new_any->value.tree = lyd_dup_withsiblings_to_ctx(old_any->value.tree, 1, ctx);
5592             break;
5593         case LYD_ANYDATA_XML:
5594             new_any->value.xml = lyxml_dup_elem(ctx, old_any->value.xml, NULL, 1, 1);
5595             break;
5596         case LYD_ANYDATA_LYB:
5597             r = lyd_lyb_data_length(old_any->value.mem);
5598             if (r == -1) {
5599                 LOGERR(ctx, LY_EINVAL, "Invalid LYB data.");
5600                 goto error;
5601             }
5602             new_any->value.mem = malloc(r);
5603             LY_CHECK_ERR_GOTO(!new_any->value.mem, LOGMEM(ctx), error);
5604             memcpy(new_any->value.mem, old_any->value.mem, r);
5605             break;
5606         case LYD_ANYDATA_STRING:
5607         case LYD_ANYDATA_SXMLD:
5608         case LYD_ANYDATA_JSOND:
5609         case LYD_ANYDATA_LYBD:
5610             /* dynamic strings are used only as input parameters */
5611             assert(0);
5612             break;
5613         }
5614         break;
5615     case LYS_CONTAINER:
5616     case LYS_LIST:
5617     case LYS_NOTIF:
5618     case LYS_RPC:
5619     case LYS_ACTION:
5620         new_node = calloc(1, sizeof *new_node);
5621         LY_CHECK_ERR_GOTO(!new_node, LOGMEM(ctx), error);
5622         new_node->schema = (struct lys_node *)schema;
5623 
5624         if (_lyd_dup_node_common(new_node, node, ctx, options)) {
5625             goto error;
5626         }
5627         break;
5628     default:
5629         LOGINT(ctx);
5630         goto error;
5631     }
5632 
5633     return new_node;
5634 
5635 error:
5636     lyd_free(new_node);
5637     return NULL;
5638 }
5639 
5640 static int
lyd_dup_keys(struct lyd_node * new_list,const struct lyd_node * old_list,struct lys_node * skip_key,struct ly_ctx * log_ctx,int options)5641 lyd_dup_keys(struct lyd_node *new_list, const struct lyd_node *old_list, struct lys_node *skip_key,
5642         struct ly_ctx *log_ctx, int options)
5643 {
5644     struct lys_node_list *slist;
5645     struct lyd_node *key, *key_dup;
5646     uint16_t i;
5647 
5648     if (new_list->schema->nodetype != LYS_LIST) {
5649         return 0;
5650     }
5651 
5652     slist = (struct lys_node_list *)new_list->schema;
5653     for (key = old_list->child, i = 0; key && (i < slist->keys_size); ++i, key = key->next) {
5654         if (key->schema != (struct lys_node *)slist->keys[i]) {
5655             LOGVAL(log_ctx, LYE_PATH_INKEY, LY_VLOG_LYD, new_list, slist->keys[i]->name);
5656             return -1;
5657         }
5658         if (key->schema == skip_key) {
5659             continue;
5660         }
5661 
5662         key_dup = lyd_dup(key, options & LYD_DUP_OPT_NO_ATTR);
5663         LY_CHECK_ERR_RETURN(!key_dup, LOGMEM(log_ctx), -1);
5664 
5665         if (lyd_insert(new_list, key_dup)) {
5666             lyd_free(key_dup);
5667             return -1;
5668         }
5669     }
5670     if (!key && (i < slist->keys_size)) {
5671         LOGVAL(log_ctx, LYE_PATH_INKEY, LY_VLOG_LYD, new_list, slist->keys[i]->name);
5672         return -1;
5673     }
5674 
5675     return 0;
5676 }
5677 
5678 API struct lyd_node *
lyd_dup_to_ctx(const struct lyd_node * node,int options,struct ly_ctx * ctx)5679 lyd_dup_to_ctx(const struct lyd_node *node, int options, struct ly_ctx *ctx)
5680 {
5681     FUN_IN;
5682 
5683     struct ly_ctx *log_ctx;
5684     struct lys_node *schema;
5685     const char *yang_data_name;
5686     const struct lys_module *trg_mod;
5687     const struct lyd_node *next, *elem;
5688     struct lyd_node *ret, *parent, *new_node = NULL;
5689 
5690     if (!node) {
5691         LOGARG;
5692         return NULL;
5693     }
5694 
5695     /* fix options */
5696     if ((options & LYD_DUP_OPT_RECURSIVE) && (options & LYD_DUP_OPT_WITH_KEYS)) {
5697         options &= ~LYD_DUP_OPT_WITH_KEYS;
5698     }
5699 
5700     log_ctx = (ctx ? ctx : node->schema->module->ctx);
5701     if (ctx == node->schema->module->ctx) {
5702         /* target context is actually the same as the source context,
5703          * ignore the target context */
5704         ctx = NULL;
5705     }
5706 
5707     ret = NULL;
5708     parent = NULL;
5709 
5710     /* LY_TREE_DFS */
5711     for (elem = next = node; elem; elem = next) {
5712 
5713         /* find the correct schema */
5714         if (ctx) {
5715             schema = NULL;
5716             if (parent) {
5717                 trg_mod = lyp_get_module(parent->schema->module, NULL, 0, lyd_node_module(elem)->name,
5718                                          strlen(lyd_node_module(elem)->name), 1);
5719                 if (!trg_mod) {
5720                     LOGERR(log_ctx, LY_EINVAL, "Target context does not contain model for the data node being duplicated (%s).",
5721                                 lyd_node_module(elem)->name);
5722                     goto error;
5723                 }
5724                 /* we know its parent, so we can start with it */
5725                 lys_getnext_data(trg_mod, parent->schema, elem->schema->name, strlen(elem->schema->name),
5726                                  elem->schema->nodetype, 0, (const struct lys_node **)&schema);
5727             } else {
5728                 /* we have to search in complete context */
5729                 schema = lyd_get_schema_inctx(elem, ctx);
5730             }
5731 
5732             if (!schema) {
5733                 yang_data_name = lyp_get_yang_data_template_name(elem);
5734                 if (yang_data_name) {
5735                     LOGERR(log_ctx, LY_EINVAL, "Target context does not contain schema node for the data node being duplicated "
5736                                         "(%s:#%s/%s).", lyd_node_module(elem)->name, yang_data_name, elem->schema->name);
5737                 } else {
5738                     LOGERR(log_ctx, LY_EINVAL, "Target context does not contain schema node for the data node being duplicated "
5739                                         "(%s:%s).", lyd_node_module(elem)->name, elem->schema->name);
5740                 }
5741                 goto error;
5742             }
5743         } else {
5744             schema = elem->schema;
5745         }
5746 
5747         /* make node copy */
5748         new_node = _lyd_dup_node(elem, schema, log_ctx, options);
5749         if (!new_node) {
5750             goto error;
5751         }
5752 
5753         if (parent && lyd_insert(parent, new_node)) {
5754             goto error;
5755         }
5756 
5757         if (!ret) {
5758             ret = new_node;
5759         }
5760 
5761         if (!(options & (LYD_DUP_OPT_RECURSIVE | LYD_DUP_OPT_WITH_KEYS))) {
5762             /* no more descendants copied */
5763             break;
5764         }
5765 
5766         if (options & LYD_DUP_OPT_WITH_KEYS) {
5767             /* copy only descendant keys */
5768             if (lyd_dup_keys(new_node, elem, NULL, log_ctx, options)) {
5769                 goto error;
5770             }
5771             break;
5772         }
5773 
5774         /* LY_TREE_DFS_END */
5775         /* select element for the next run - children first,
5776          * child exception for lyd_node_leaf and lyd_node_leaflist */
5777         if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
5778             next = NULL;
5779         } else {
5780             next = elem->child;
5781         }
5782         if (!next) {
5783             if (elem->parent == node->parent) {
5784                 break;
5785             }
5786             /* no children, so try siblings */
5787             next = elem->next;
5788         } else {
5789             parent = new_node;
5790         }
5791         new_node = NULL;
5792 
5793         while (!next) {
5794             /* no siblings, go back through parents */
5795             elem = elem->parent;
5796             if (elem->parent == node->parent) {
5797                 break;
5798             }
5799             if (!parent) {
5800                 LOGINT(log_ctx);
5801                 goto error;
5802             }
5803             parent = parent->parent;
5804             /* parent is already processed, go to its sibling */
5805             next = elem->next;
5806         }
5807     }
5808 
5809     /* dup all the parents */
5810     if (options & LYD_DUP_OPT_WITH_PARENTS) {
5811         parent = ret;
5812         if (lys_is_key((struct lys_node_leaf *)ret->schema, NULL)) {
5813             /* this key was being duplicated so do not add it twice */
5814             schema = ret->schema;
5815         } else {
5816             schema = NULL;
5817         }
5818         for (elem = node->parent; elem; elem = elem->parent) {
5819             new_node = lyd_dup(elem, options & LYD_DUP_OPT_NO_ATTR);
5820             LY_CHECK_ERR_GOTO(!new_node, LOGMEM(log_ctx), error);
5821 
5822             /* dup all list keys */
5823             if (lyd_dup_keys(new_node, elem, schema, log_ctx, options)) {
5824                 goto error;
5825             }
5826 
5827             /* link together */
5828             if (lyd_insert(new_node, parent)) {
5829                 ret = parent;
5830                 goto error;
5831             }
5832             parent = new_node;
5833         }
5834     }
5835 
5836     return ret;
5837 
5838 error:
5839     lyd_free(ret);
5840     return NULL;
5841 }
5842 
5843 API struct lyd_node *
lyd_dup(const struct lyd_node * node,int options)5844 lyd_dup(const struct lyd_node *node, int options)
5845 {
5846     FUN_IN;
5847 
5848     return lyd_dup_to_ctx(node, options, NULL);
5849 }
5850 
5851 static struct lyd_node *
lyd_dup_withsiblings_r(const struct lyd_node * first,struct lyd_node * parent_dup,int options,struct ly_ctx * ctx)5852 lyd_dup_withsiblings_r(const struct lyd_node *first, struct lyd_node *parent_dup, int options, struct ly_ctx *ctx)
5853 {
5854     struct lyd_node *first_dup = NULL, *prev_dup = NULL, *last_dup;
5855     const struct lyd_node *next;
5856 
5857     assert(first);
5858 
5859     /* duplicate and connect all siblings */
5860     LY_TREE_FOR(first, next) {
5861         last_dup = _lyd_dup_node(next, next->schema, ctx, options);
5862         if (!last_dup) {
5863             goto error;
5864         }
5865 
5866         /* the whole data tree is exactly the same so we can safely copy the validation flags */
5867         last_dup->validity = next->validity;
5868         last_dup->when_status = next->when_status;
5869 
5870         last_dup->parent = parent_dup;
5871         /* connect to the parent or the siblings */
5872         if (!first_dup) {
5873             first_dup = last_dup;
5874             if (parent_dup) {
5875                 parent_dup->child = first_dup;
5876             }
5877         } else {
5878             assert(prev_dup);
5879             prev_dup->next = last_dup;
5880             last_dup->prev = prev_dup;
5881         }
5882 
5883 #ifdef LY_ENABLED_CACHE
5884         /* copy hash */
5885         if ((last_dup->schema->nodetype != LYS_LIST) || lyd_list_has_keys(last_dup)) {
5886             last_dup->hash = next->hash;
5887         }
5888 
5889         /* insert into parent */
5890         lyd_insert_hash(last_dup);
5891 #endif
5892 
5893         if ((next->schema->nodetype & (LYS_LIST | LYS_CONTAINER | LYS_RPC | LYS_ACTION | LYS_NOTIF)) && next->child) {
5894             /* recursively duplicate all children */
5895             if (!lyd_dup_withsiblings_r(next->child, last_dup, options, ctx)) {
5896                 goto error;
5897             }
5898         }
5899 
5900         prev_dup = last_dup;
5901     }
5902 
5903     /* correctly set last sibling */
5904     assert(!prev_dup->next);
5905     first_dup->prev = prev_dup;
5906 
5907     return first_dup;
5908 
5909 error:
5910     /* disconnect and free */
5911     if (first_dup) {
5912         first_dup->parent = NULL;
5913         lyd_free_withsiblings(first_dup);
5914     }
5915     return NULL;
5916 }
5917 
5918 static struct lyd_node *
lyd_dup_withsiblings_to_ctx(const struct lyd_node * node,int options,struct ly_ctx * ctx)5919 lyd_dup_withsiblings_to_ctx(const struct lyd_node *node, int options, struct ly_ctx *ctx)
5920 {
5921     const struct lyd_node *iter;
5922     struct lyd_node *ret, *ret_iter, *tmp;
5923 
5924     if (!node) {
5925         return NULL;
5926     }
5927 
5928     /* find first sibling */
5929     while (node->prev->next) {
5930         node = node->prev;
5931     }
5932 
5933     if (node->parent) {
5934         ret = lyd_dup_to_ctx(node, options, ctx);
5935         if (!ret) {
5936             return NULL;
5937         }
5938 
5939         /* copy following siblings */
5940         ret_iter = ret;
5941         LY_TREE_FOR(node->next, iter) {
5942             tmp = lyd_dup_to_ctx(iter, options, ctx);
5943             if (!tmp) {
5944                 lyd_free_withsiblings(ret);
5945                 return NULL;
5946             }
5947 
5948             if (lyd_insert_after(ret_iter, tmp)) {
5949                 lyd_free_withsiblings(ret);
5950                 return NULL;
5951             }
5952             ret_iter = ret_iter->next;
5953             assert(ret_iter == tmp);
5954         }
5955     } else {
5956         /* duplicating top-level siblings, we can duplicate much more efficiently */
5957         ret = lyd_dup_withsiblings_r(node, NULL, options, ctx);
5958     }
5959 
5960     return ret;
5961 }
5962 
5963 API struct lyd_node *
lyd_dup_withsiblings(const struct lyd_node * node,int options)5964 lyd_dup_withsiblings(const struct lyd_node *node, int options)
5965 {
5966     FUN_IN;
5967 
5968     if (!node) {
5969         return NULL;
5970     }
5971 
5972     return lyd_dup_withsiblings_to_ctx(node, options, lyd_node_module(node)->ctx);
5973 }
5974 
5975 API void
lyd_free_attr(struct ly_ctx * ctx,struct lyd_node * parent,struct lyd_attr * attr,int recursive)5976 lyd_free_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr, int recursive)
5977 {
5978     FUN_IN;
5979 
5980     struct lyd_attr *iter;
5981     struct lys_type **type;
5982 
5983     if (!ctx || !attr) {
5984         return;
5985     }
5986 
5987     if (parent) {
5988         if (parent->attr == attr) {
5989             if (recursive) {
5990                 parent->attr = NULL;
5991             } else {
5992                 parent->attr = attr->next;
5993             }
5994         } else {
5995             for (iter = parent->attr; iter->next != attr; iter = iter->next);
5996             if (iter->next) {
5997                 if (recursive) {
5998                     iter->next = NULL;
5999                 } else {
6000                     iter->next = attr->next;
6001                 }
6002             }
6003         }
6004     }
6005 
6006     if (!recursive) {
6007         attr->next = NULL;
6008     }
6009 
6010     for(iter = attr; iter; ) {
6011         attr = iter;
6012         iter = iter->next;
6013 
6014         lydict_remove(ctx, attr->name);
6015         type = lys_ext_complex_get_substmt(LY_STMT_TYPE, attr->annotation, NULL);
6016         assert(type);
6017         lyd_free_value(attr->value, attr->value_type, attr->value_flags, *type, attr->value_str, NULL, NULL, NULL);
6018         lydict_remove(ctx, attr->value_str);
6019         free(attr);
6020     }
6021 }
6022 
6023 const struct lyd_node *
lyd_attr_parent(const struct lyd_node * root,struct lyd_attr * attr)6024 lyd_attr_parent(const struct lyd_node *root, struct lyd_attr *attr)
6025 {
6026     const struct lyd_node *next, *elem;
6027     struct lyd_attr *node_attr;
6028 
6029     LY_TREE_DFS_BEGIN(root, next, elem) {
6030         for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
6031             if (node_attr == attr) {
6032                 return elem;
6033             }
6034         }
6035         LY_TREE_DFS_END(root, next, elem)
6036     }
6037 
6038     return NULL;
6039 }
6040 
6041 API struct lyd_attr *
lyd_insert_attr(struct lyd_node * parent,const struct lys_module * mod,const char * name,const char * value)6042 lyd_insert_attr(struct lyd_node *parent, const struct lys_module *mod, const char *name, const char *value)
6043 {
6044     FUN_IN;
6045 
6046     struct lyd_attr *a, *iter;
6047     struct ly_ctx *ctx;
6048     const struct lys_module *module;
6049     const char *p;
6050     char *aux;
6051     int pos, i;
6052 
6053     if (!parent || !name || !value) {
6054         LOGARG;
6055         return NULL;
6056     }
6057     ctx = parent->schema->module->ctx;
6058 
6059     if ((p = strchr(name, ':'))) {
6060         /* search for the namespace */
6061         aux = strndup(name, p - name);
6062         if (!aux) {
6063             LOGMEM(ctx);
6064             return NULL;
6065         }
6066         module = ly_ctx_get_module(ctx, aux, NULL, 1);
6067         free(aux);
6068         name = p + 1;
6069 
6070         if (!module) {
6071             /* module not found */
6072             LOGERR(ctx, LY_EINVAL, "Attribute prefix does not match any implemented schema in the context.");
6073             return NULL;
6074         }
6075     } else if (mod) {
6076         module = mod;
6077     } else if (!mod && (!strcmp(name, "type") || !strcmp(name, "select")) && !strcmp(parent->schema->name, "filter")) {
6078         /* special case of inserting unqualified filter attributes "type" and "select" */
6079         module = ly_ctx_get_module(ctx, "ietf-netconf", NULL, 1);
6080         if (!module) {
6081             LOGERR(ctx, LY_EINVAL, "Attribute prefix does not match any implemented schema in the context.");
6082             return NULL;
6083         }
6084     } else {
6085         /* no prefix -> module is the same as for the parent */
6086         module = lyd_node_module(parent);
6087     }
6088 
6089     pos = -1;
6090     do {
6091         if ((unsigned int)(pos + 1) < module->ext_size) {
6092             i = lys_ext_instance_presence(&ctx->models.list[0]->extensions[0],
6093                                           &module->ext[pos + 1], module->ext_size - (pos + 1));
6094             pos = (i == -1) ? -1 : pos + 1 + i;
6095         } else {
6096             pos = -1;
6097         }
6098         if (pos == -1) {
6099             LOGERR(ctx, LY_EINVAL, "Attribute does not match any annotation instance definition.");
6100             return NULL;
6101         }
6102     } while (!ly_strequal(module->ext[pos]->arg_value, name, 0));
6103 
6104     a = calloc(1, sizeof *a);
6105     LY_CHECK_ERR_RETURN(!a, LOGMEM(ctx), NULL);
6106     a->parent = parent;
6107     a->next = NULL;
6108     a->annotation = (struct lys_ext_instance_complex *)module->ext[pos];
6109     a->name = lydict_insert(ctx, name, 0);
6110     a->value_str = lydict_insert(ctx, value, 0);
6111     if (!lyp_parse_value(*((struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, a->annotation, NULL)),
6112                          &a->value_str, NULL, NULL, a, NULL, 1, 0)) {
6113         lyd_free_attr(ctx, NULL, a, 0);
6114         return NULL;
6115     }
6116 
6117     if (!parent->attr) {
6118         parent->attr = a;
6119     } else {
6120         for (iter = parent->attr; iter->next; iter = iter->next);
6121         iter->next = a;
6122     }
6123 
6124     return a;
6125 }
6126 
6127 void
lyd_free_value(lyd_val value,LY_DATA_TYPE value_type,uint8_t value_flags,struct lys_type * type,const char * value_str,lyd_val * old_val,LY_DATA_TYPE * old_val_type,uint8_t * old_val_flags)6128 lyd_free_value(lyd_val value, LY_DATA_TYPE value_type, uint8_t value_flags, struct lys_type *type, const char *value_str,
6129                lyd_val *old_val, LY_DATA_TYPE *old_val_type, uint8_t *old_val_flags)
6130 {
6131     if (old_val) {
6132         *old_val = value;
6133         *old_val_type = value_type;
6134         *old_val_flags = value_flags;
6135         /* we only backup the values for now */
6136         return;
6137     }
6138 
6139     /* otherwise the value is correctly freed */
6140     if (value_flags & LY_VALUE_USER) {
6141         lytype_free(type, value, value_str);
6142     } else {
6143         switch (value_type) {
6144         case LY_TYPE_BITS:
6145             if (value.bit) {
6146                 free(value.bit);
6147             }
6148             break;
6149         case LY_TYPE_INST:
6150             if (!(value_flags & LY_VALUE_UNRES)) {
6151                 break;
6152             }
6153             /* fallthrough */
6154         case LY_TYPE_UNION:
6155             /* unresolved union leaf */
6156             lydict_remove(type->parent->module->ctx, value.string);
6157             break;
6158         default:
6159             break;
6160         }
6161     }
6162 }
6163 
6164 static void
_lyd_free_node(struct lyd_node * node)6165 _lyd_free_node(struct lyd_node *node)
6166 {
6167     struct lyd_node_leaf_list *leaf;
6168 
6169     if (!node) {
6170         return;
6171     }
6172 
6173     switch (node->schema->nodetype) {
6174     case LYS_CONTAINER:
6175     case LYS_LIST:
6176     case LYS_RPC:
6177     case LYS_ACTION:
6178     case LYS_NOTIF:
6179 #ifdef LY_ENABLED_CACHE
6180         /* it should be empty because all the children are freed already (only if in debug mode) */
6181         lyht_free(node->ht);
6182 #endif
6183         break;
6184     case LYS_ANYDATA:
6185     case LYS_ANYXML:
6186         switch (((struct lyd_node_anydata *)node)->value_type) {
6187         case LYD_ANYDATA_CONSTSTRING:
6188         case LYD_ANYDATA_SXML:
6189         case LYD_ANYDATA_JSON:
6190             lydict_remove(node->schema->module->ctx, ((struct lyd_node_anydata *)node)->value.str);
6191             break;
6192         case LYD_ANYDATA_DATATREE:
6193             lyd_free_withsiblings(((struct lyd_node_anydata *)node)->value.tree);
6194             break;
6195         case LYD_ANYDATA_XML:
6196             lyxml_free_withsiblings(node->schema->module->ctx, ((struct lyd_node_anydata *)node)->value.xml);
6197             break;
6198         case LYD_ANYDATA_LYB:
6199             free(((struct lyd_node_anydata *)node)->value.mem);
6200             break;
6201         case LYD_ANYDATA_STRING:
6202         case LYD_ANYDATA_SXMLD:
6203         case LYD_ANYDATA_JSOND:
6204         case LYD_ANYDATA_LYBD:
6205             /* dynamic strings are used only as input parameters */
6206             assert(0);
6207             break;
6208         }
6209         break;
6210     case LYS_LEAF:
6211     case LYS_LEAFLIST:
6212         leaf = (struct lyd_node_leaf_list *)node;
6213         lyd_free_value(leaf->value, leaf->value_type, leaf->value_flags, &((struct lys_node_leaf *)leaf->schema)->type,
6214                        leaf->value_str, NULL, NULL, NULL);
6215         lydict_remove(leaf->schema->module->ctx, leaf->value_str);
6216         break;
6217     default:
6218         assert(0);
6219     }
6220 
6221     lyd_free_attr(node->schema->module->ctx, node, node->attr, 1);
6222     free(node);
6223 }
6224 
6225 static void
lyd_free_internal_r(struct lyd_node * node,int top)6226 lyd_free_internal_r(struct lyd_node *node, int top)
6227 {
6228     struct lyd_node *next, *iter;
6229 
6230     if (!node) {
6231         return;
6232     }
6233 
6234     /* if freeing top-level, always remove it from the parent hash table */
6235     lyd_unlink_internal(node, (top ? 1 : 2));
6236 
6237     if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
6238         /* free children */
6239         LY_TREE_FOR_SAFE(node->child, next, iter) {
6240             lyd_free_internal_r(iter, 0);
6241         }
6242     }
6243 
6244     _lyd_free_node(node);
6245 }
6246 
6247 API void
lyd_free(struct lyd_node * node)6248 lyd_free(struct lyd_node *node)
6249 {
6250     FUN_IN;
6251 
6252     lyd_free_internal_r(node, 1);
6253 }
6254 
6255 static void
lyd_free_withsiblings_r(struct lyd_node * first)6256 lyd_free_withsiblings_r(struct lyd_node *first)
6257 {
6258     struct lyd_node *next, *node;
6259 
6260     LY_TREE_FOR_SAFE(first, next, node) {
6261         if (node->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
6262             lyd_free_withsiblings_r(node->child);
6263         }
6264         _lyd_free_node(node);
6265     }
6266 }
6267 
6268 API void
lyd_free_withsiblings(struct lyd_node * node)6269 lyd_free_withsiblings(struct lyd_node *node)
6270 {
6271     FUN_IN;
6272 
6273     struct lyd_node *iter, *aux;
6274 
6275     if (!node) {
6276         return;
6277     }
6278 
6279     if (node->parent) {
6280         /* optimization - avoid freeing (unlinking) the last node of the siblings list */
6281         /* so, first, free the node's predecessors to the beginning of the list ... */
6282         for(iter = node->prev; iter->next; iter = aux) {
6283             aux = iter->prev;
6284             lyd_free(iter);
6285         }
6286         /* ... then, the node is the first in the siblings list, so free them all */
6287         LY_TREE_FOR_SAFE(node, aux, iter) {
6288             lyd_free(iter);
6289         }
6290     } else {
6291         /* node is top-level so we are freeing the whole data tree, we can just free nodes without any unlinking */
6292         while (node->prev->next) {
6293             /* find the first sibling */
6294             node = node->prev;
6295         }
6296 
6297         /* free it all */
6298         lyd_free_withsiblings_r(node);
6299     }
6300 }
6301 
6302 /**
6303  * Expectations:
6304  * - list exists in data tree
6305  * - the leaf (defined by the unique_expr) is not instantiated under the list
6306  */
6307 int
lyd_get_unique_default(const char * unique_expr,struct lyd_node * list,const char ** dflt)6308 lyd_get_unique_default(const char* unique_expr, struct lyd_node *list, const char **dflt)
6309 {
6310     struct ly_ctx *ctx = list->schema->module->ctx;
6311     const struct lys_node *parent;
6312     const struct lys_node_leaf *sleaf = NULL;
6313     struct lys_tpdf *tpdf;
6314     struct lyd_node *last, *node;
6315     struct ly_set *s, *r;
6316     unsigned int i;
6317     enum int_log_opts prev_ilo;
6318 
6319     assert(unique_expr && list && dflt);
6320     *dflt = NULL;
6321 
6322     if (resolve_descendant_schema_nodeid(unique_expr, list->schema->child, LYS_LEAF, 1, &parent) || !parent) {
6323         /* error, but unique expression was checked when the schema was parsed so this should not happened */
6324         LOGINT(ctx);
6325         return -1;
6326     }
6327 
6328     sleaf = (struct lys_node_leaf *)parent;
6329     if (sleaf->dflt) {
6330         /* leaf has a default value */
6331         *dflt = sleaf->dflt;
6332     } else if (!(sleaf->flags & LYS_MAND_TRUE)) {
6333         /* get the default value from the type */
6334         for (tpdf = sleaf->type.der; tpdf && !(*dflt); tpdf = tpdf->type.der) {
6335             *dflt = tpdf->dflt;
6336         }
6337     }
6338 
6339     if (!(*dflt)) {
6340         return 0;
6341     }
6342 
6343     /* it has default value, but check if it can appear in the data tree under the list */
6344     s = ly_set_new();
6345     for (parent = lys_parent((struct lys_node *)sleaf); parent != list->schema; parent = lys_parent(parent)) {
6346         if (!(parent->nodetype & (LYS_CONTAINER | LYS_CASE | LYS_CHOICE | LYS_USES))) {
6347             /* This should be already detected when parsing schema */
6348             LOGINT(ctx);
6349             ly_set_free(s);
6350             return -1;
6351         }
6352         ly_set_add(s, (void *)parent, LY_SET_OPT_USEASLIST);
6353     }
6354 
6355     ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
6356     for (i = 0, last = list; i < s->number; i++) {
6357         parent = s->set.s[i]; /* shortcut */
6358 
6359         switch (parent->nodetype) {
6360         case LYS_CONTAINER:
6361             if (last) {
6362                 /* find instance in the data */
6363                 r = lyd_find_path(last, parent->name);
6364                 if (!r || r->number > 1) {
6365                     ly_set_free(r);
6366                     *dflt = NULL;
6367                     goto end;
6368                 }
6369                 if (r->number) {
6370                     last = r->set.d[0];
6371                 } else {
6372                     last = NULL;
6373                 }
6374                 ly_set_free(r);
6375             }
6376             if (((struct lys_node_container *)parent)->presence) {
6377                 /* not-instantiated presence container on path */
6378                 *dflt = NULL;
6379                 goto end;
6380             }
6381             break;
6382         case LYS_CHOICE :
6383             /* check presence of another case */
6384             if (!last) {
6385                 continue;
6386             }
6387 
6388             /* remember the case to be searched in choice by lyv_multicases() */
6389             if (i + 1 == s->number) {
6390                 parent = (struct lys_node *)sleaf;
6391             } else if (s->set.s[i + 1]->nodetype == LYS_CASE && (i + 2 < s->number) &&
6392                     s->set.s[i + 2]->nodetype == LYS_CHOICE) {
6393                 /* nested choices are covered by lyv_multicases, we just have to pass
6394                  * the lowest choice */
6395                 i++;
6396                 continue;
6397             } else {
6398                 parent = s->set.s[i + 1];
6399             }
6400             node = last->child;
6401             if (lyv_multicases(NULL, (struct lys_node *)parent, &node, 0, NULL)) {
6402                 /* another case is present */
6403                 *dflt = NULL;
6404                 goto end;
6405             }
6406             break;
6407         default:
6408             /* LYS_CASE, LYS_USES */
6409             continue;
6410         }
6411     }
6412 
6413 end:
6414     ly_ilo_restore(NULL, prev_ilo, NULL, 0);
6415     ly_set_free(s);
6416     return 0;
6417 }
6418 
6419 API char *
lyd_path(const struct lyd_node * node)6420 lyd_path(const struct lyd_node *node)
6421 {
6422     FUN_IN;
6423 
6424     char *buf = NULL;
6425 
6426     if (!node) {
6427         LOGARG;
6428         return NULL;
6429     }
6430 
6431     if (ly_vlog_build_path(LY_VLOG_LYD, node, &buf, 0, 0)) {
6432         return NULL;
6433     }
6434 
6435     return buf;
6436 }
6437 
6438 int
lyd_build_relative_data_path(const struct lys_module * module,const struct lyd_node * node,const char * schema_id,char * buf)6439 lyd_build_relative_data_path(const struct lys_module *module, const struct lyd_node *node, const char *schema_id,
6440                              char *buf)
6441 {
6442     const struct lys_node *snode, *schema;
6443     const char *mod_name, *name;
6444     int mod_name_len, name_len, len = 0;
6445     int r, is_relative = -1;
6446 
6447     assert(schema_id && buf);
6448     schema = node->schema;
6449 
6450     while (*schema_id) {
6451         if ((r = parse_schema_nodeid(schema_id, &mod_name, &mod_name_len, &name, &name_len, &is_relative, NULL, NULL, 0)) < 1) {
6452             LOGINT(module->ctx);
6453             return -1;
6454         }
6455         schema_id += r;
6456 
6457         snode = NULL;
6458         while ((snode = lys_getnext(snode, schema, NULL, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE | LYS_GETNEXT_NOSTATECHECK))) {
6459             r = schema_nodeid_siblingcheck(snode, module, mod_name, mod_name_len, name, name_len);
6460             if (r == 0) {
6461                 schema = snode;
6462                 break;
6463             } else if (r == 1) {
6464                 continue;
6465             } else {
6466                 return -1;
6467             }
6468         }
6469         /* no match */
6470         if (!snode || (!schema_id[0] && snode->nodetype != LYS_LEAF)) {
6471             LOGINT(module->ctx);
6472             return -1;
6473         }
6474 
6475         if (!(snode->nodetype & (LYS_CHOICE | LYS_CASE))) {
6476             len += sprintf(&buf[len], "%s%s", (len ? "/" : ""), snode->name);
6477         }
6478     }
6479 
6480     return len;
6481 }
6482 
6483 API struct ly_set *
lyd_find_path(const struct lyd_node * ctx_node,const char * path)6484 lyd_find_path(const struct lyd_node *ctx_node, const char *path)
6485 {
6486     FUN_IN;
6487 
6488     struct lyxp_set xp_set;
6489     struct ly_set *set;
6490     char *yang_xpath;
6491     const char * node_mod_name, *mod_name, *name;
6492     int mod_name_len, name_len, is_relative = -1;
6493     uint32_t i;
6494 
6495     if (!ctx_node || !path) {
6496         LOGARG;
6497         return NULL;
6498     }
6499 
6500     if (parse_schema_nodeid(path, &mod_name, &mod_name_len, &name, &name_len, &is_relative, NULL, NULL, 1) > 0) {
6501         if (name[0] == '#' && !is_relative) {
6502             node_mod_name = lyd_node_module(ctx_node)->name;
6503             if (strncmp(mod_name, node_mod_name, mod_name_len) || node_mod_name[mod_name_len]) {
6504                 return NULL;
6505             }
6506             path = name + name_len;
6507         }
6508     }
6509 
6510     /* transform JSON into YANG XPATH */
6511     yang_xpath = transform_json2xpath(lyd_node_module(ctx_node), path);
6512     if (!yang_xpath) {
6513         return NULL;
6514     }
6515 
6516     memset(&xp_set, 0, sizeof xp_set);
6517 
6518     if (lyxp_eval(yang_xpath, ctx_node, LYXP_NODE_ELEM, lyd_node_module(ctx_node), &xp_set, 0) != EXIT_SUCCESS) {
6519         free(yang_xpath);
6520         return NULL;
6521     }
6522     free(yang_xpath);
6523 
6524     set = ly_set_new();
6525     LY_CHECK_ERR_RETURN(!set, LOGMEM(ctx_node->schema->module->ctx), NULL);
6526 
6527     if (xp_set.type == LYXP_SET_NODE_SET) {
6528         for (i = 0; i < xp_set.used; ++i) {
6529             if (xp_set.val.nodes[i].type == LYXP_NODE_ELEM) {
6530                 if (ly_set_add(set, xp_set.val.nodes[i].node, LY_SET_OPT_USEASLIST) < 0) {
6531                     ly_set_free(set);
6532                     set = NULL;
6533                     break;
6534                 }
6535             }
6536         }
6537     }
6538     /* free xp_set content */
6539     lyxp_set_cast(&xp_set, LYXP_SET_EMPTY, ctx_node, NULL, 0);
6540 
6541     return set;
6542 }
6543 
6544 API struct ly_set *
lyd_find_instance(const struct lyd_node * data,const struct lys_node * schema)6545 lyd_find_instance(const struct lyd_node *data, const struct lys_node *schema)
6546 {
6547     FUN_IN;
6548 
6549     struct ly_set *ret, *ret_aux, *spath;
6550     const struct lys_node *siter;
6551     struct lyd_node *iter;
6552     unsigned int i, j;
6553 
6554     if (!data || !schema ||
6555             !(schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYDATA | LYS_NOTIF | LYS_RPC | LYS_ACTION))) {
6556         LOGARG;
6557         return NULL;
6558     }
6559 
6560     ret = ly_set_new();
6561     spath = ly_set_new();
6562     if (!ret || !spath) {
6563         LOGMEM(schema->module->ctx);
6564         goto error;
6565     }
6566 
6567     /* find data root */
6568     while (data->parent) {
6569         /* vertical move (up) */
6570         data = data->parent;
6571     }
6572     while (data->prev->next) {
6573         /* horizontal move (left) */
6574         data = data->prev;
6575     }
6576 
6577     /* build schema path */
6578     for (siter = schema; siter; ) {
6579         if (siter->nodetype == LYS_AUGMENT) {
6580             siter = ((struct lys_node_augment *)siter)->target;
6581             continue;
6582         } else if (siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYDATA | LYS_NOTIF | LYS_RPC | LYS_ACTION)) {
6583             /* standard data node */
6584             ly_set_add(spath, (void*)siter, LY_SET_OPT_USEASLIST);
6585 
6586         } /* else skip the rest node types */
6587         siter = siter->parent;
6588     }
6589     if (!spath->number) {
6590         /* no valid path */
6591         goto error;
6592     }
6593 
6594     /* start searching */
6595     LY_TREE_FOR((struct lyd_node *)data, iter) {
6596         if (iter->schema == spath->set.s[spath->number - 1]) {
6597             ly_set_add(ret, iter, LY_SET_OPT_USEASLIST);
6598         }
6599     }
6600     for (i = spath->number - 1; i; i--) {
6601         if (!ret->number) {
6602             /* nothing found */
6603             break;
6604         }
6605 
6606         ret_aux = ly_set_new();
6607         if (!ret_aux) {
6608             LOGMEM(schema->module->ctx);
6609             goto error;
6610         }
6611         for (j = 0; j < ret->number; j++) {
6612             LY_TREE_FOR(ret->set.d[j]->child, iter) {
6613                 if (iter->schema == spath->set.s[i - 1]) {
6614                     ly_set_add(ret_aux, iter, LY_SET_OPT_USEASLIST);
6615                 }
6616             }
6617         }
6618         ly_set_free(ret);
6619         ret = ret_aux;
6620     }
6621 
6622     ly_set_free(spath);
6623     return ret;
6624 
6625 error:
6626     ly_set_free(ret);
6627     ly_set_free(spath);
6628 
6629     return NULL;
6630 }
6631 
6632 API int
lyd_find_sibling(const struct lyd_node * siblings,const struct lyd_node * target,struct lyd_node ** match)6633 lyd_find_sibling(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
6634 {
6635     /* argument checks */
6636     if (!target || !match) {
6637         LOGARG;
6638         return -1;
6639     }
6640     if (target->schema->nodetype == LYS_LIST) {
6641         if (!((struct lys_node_list *)target->schema)->keys_size) {
6642             LOGERR(lyd_node_module(target)->ctx, LY_EINVAL, "Invalid arguments - key-less list (%s()).", __func__);
6643             return -1;
6644         } else if (!lyd_list_has_keys((struct lyd_node *)target)) {
6645             LOGERR(lyd_node_module(target)->ctx, LY_EINVAL, "Invalid arguments - list without keys (%s()).", __func__);
6646             return -1;
6647         }
6648     }
6649     if ((target->schema->nodetype == LYS_LEAFLIST) && !(target->schema->flags & LYS_CONFIG_W)) {
6650         LOGERR(lyd_node_module(target)->ctx, LY_EINVAL, "Invalid arguments - non-configuration leaf-list (%s()).", __func__);
6651         return -1;
6652     }
6653 
6654     if (!siblings) {
6655         /* no data */
6656         *match = NULL;
6657         return 0;
6658     }
6659 
6660     /* find first sibling */
6661     if (siblings->parent) {
6662         siblings = siblings->parent->child;
6663     } else {
6664         while (siblings->prev->next) {
6665             siblings = siblings->prev;
6666         }
6667     }
6668 
6669 #ifdef LY_ENABLED_CACHE
6670     struct lyd_node **match_p;
6671 
6672     if (siblings->parent && siblings->parent->ht) {
6673         assert(target->hash);
6674 
6675         /* find by hash */
6676         if (!lyht_find(siblings->parent->ht, &target, target->hash, (void **)&match_p)) {
6677             siblings = *match_p;
6678         } else {
6679             /* not found */
6680             siblings = NULL;
6681         }
6682     } else
6683 #endif
6684     {
6685         /* no hashes or no hash table */
6686         for (; siblings; siblings = siblings->next) {
6687             if (siblings->schema != target->schema) {
6688                 continue;
6689             }
6690 
6691             if (target->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
6692                 if (lyd_list_equal((struct lyd_node *)target, (struct lyd_node *)siblings, 0)) {
6693                     /* a match */
6694                     break;
6695                 }
6696             } else {
6697                 /* schema match is enough for other nodes */
6698                 break;
6699             }
6700         }
6701     }
6702 
6703     *match = (struct lyd_node *)siblings;
6704     return 0;
6705 }
6706 
6707 API int
lyd_find_sibling_set(const struct lyd_node * siblings,const struct lyd_node * target,struct ly_set ** set)6708 lyd_find_sibling_set(const struct lyd_node *siblings, const struct lyd_node *target, struct ly_set **set)
6709 {
6710     struct lyd_node *match;
6711 
6712     /* argument checks */
6713     if (!target || !set) {
6714         LOGARG;
6715         return -1;
6716     }
6717 
6718     *set = ly_set_new();
6719     LY_CHECK_ERR_RETURN(!*set, LOGMEM(lyd_node_module(target)->ctx), -1);
6720 
6721     if (!siblings) {
6722         /* no data */
6723         return 0;
6724     }
6725 
6726     /* find first sibling */
6727     if (siblings->parent) {
6728         siblings = siblings->parent->child;
6729     } else {
6730         while (siblings->prev->next) {
6731             siblings = siblings->prev;
6732         }
6733     }
6734 
6735     if (((target->schema->nodetype == LYS_LIST) && !((struct lys_node_list *)target->schema)->keys_size)
6736             || ((target->schema->nodetype == LYS_LEAFLIST) && !(target->schema->flags & LYS_CONFIG_W))) {
6737 
6738         /* handle key-less lists and state leaf-lists ourselves because there can be more matching instances */
6739 #ifdef LY_ENABLED_CACHE
6740         struct lyd_node **match_p;
6741 
6742         if (siblings->parent && siblings->parent->ht) {
6743             assert(target->hash);
6744 
6745             /* find by hash */
6746             if (!lyht_find(siblings->parent->ht, &target, target->hash, (void **)&match_p)) {
6747                 match = *match_p;
6748             } else {
6749                 /* not found */
6750                 match = NULL;
6751             }
6752             while (match) {
6753                 /* add all found nodes into the set */
6754                 if (ly_set_add(*set, match, LY_SET_OPT_USEASLIST) == -1) {
6755                     goto error;
6756                 }
6757 
6758                 /* find next instance */
6759                 if (lyht_find_next(siblings->parent->ht, &match, match->hash, (void **)&match_p)) {
6760                     match = NULL;
6761                 } else {
6762                     match = *match_p;
6763                 }
6764             }
6765         } else
6766 #endif
6767         {
6768             /* no hashes or no hash table */
6769             for (; siblings; siblings = siblings->next) {
6770                 if (siblings->schema != target->schema) {
6771                     continue;
6772                 }
6773 
6774                 if (lyd_list_equal((struct lyd_node *)target, (struct lyd_node *)siblings, 0)) {
6775                     /* a match */
6776                     if (ly_set_add(*set, (struct lyd_node *)siblings, LY_SET_OPT_USEASLIST) == -1) {
6777                         goto error;
6778                     }
6779                 }
6780             }
6781         }
6782     } else {
6783         /* use another function */
6784         if (lyd_find_sibling(siblings, target, &match)) {
6785             goto error;
6786         }
6787         if (match && (ly_set_add(*set, match, LY_SET_OPT_USEASLIST) == -1)) {
6788             goto error;
6789         }
6790     }
6791 
6792     return 0;
6793 
6794 error:
6795     ly_set_free(*set);
6796     return -1;
6797 }
6798 
6799 static char *
lyd_find_sibling_val_key_value(char ** next_key,struct lys_node * key)6800 lyd_find_sibling_val_key_value(char **next_key, struct lys_node *key)
6801 {
6802     char *ptr, *ptr2, *val, quot;
6803 
6804     ptr = *next_key;
6805 
6806     /* "[" */
6807     if (ptr[0] != '[') {
6808         goto error;
6809     }
6810     ++ptr;
6811 
6812     /* optional module name, we are not checking it */
6813     for (ptr2 = ptr; ptr2[0] && (ptr2[0] != '=') && (ptr2[0] != ':'); ++ptr2);
6814     if (!ptr2[0]) {
6815         goto error;
6816     } else if (ptr2[0] == ':') {
6817         ptr = ptr2 + 1;
6818     }
6819 
6820     /* key name */
6821     if (strncmp(ptr, key->name, strlen(key->name))) {
6822         goto error;
6823     }
6824     ptr += strlen(key->name);
6825 
6826     /* "=" */
6827     if (ptr[0] != '=') {
6828         goto error;
6829     }
6830     ++ptr;
6831 
6832     /* quote */
6833     if ((ptr[0] != '\'') && (ptr[0] != '\"')) {
6834         goto error;
6835     }
6836     quot = ptr[0];
6837     ++ptr;
6838 
6839     /* value, terminate it */
6840     val = ptr;
6841     if (!(ptr2 = strchr(ptr, quot))) {
6842         goto error;
6843     }
6844     ptr2[0] = '\0';
6845 
6846     /* \0, was quote */
6847     ptr = ptr2 + 1;
6848 
6849     /* "]" */
6850     if (ptr[0] != ']') {
6851         goto error;
6852     }
6853     ++ptr;
6854 
6855     *next_key = ptr;
6856     return val;
6857 
6858 error:
6859     LOGERR(lys_node_module(key)->ctx, LY_EINVAL, "Invalid arguments - keys at \"%s\" (%s()).",
6860            ptr, __func__);
6861     return NULL;
6862 }
6863 
6864 API int
lyd_find_sibling_val(const struct lyd_node * siblings,const struct lys_node * schema,const char * key_or_value,struct lyd_node ** match)6865 lyd_find_sibling_val(const struct lyd_node *siblings, const struct lys_node *schema, const char *key_or_value,
6866         struct lyd_node **match)
6867 {
6868     struct lyd_node *target = NULL, *node;
6869     struct lys_node *key;
6870     uint8_t i;
6871     char *keys = NULL, *val, *next_key;
6872 
6873     /* argument checks */
6874     if (!schema) {
6875         LOGARG;
6876         return -1;
6877     }
6878     switch (schema->nodetype) {
6879     case LYS_CONTAINER:
6880     case LYS_LEAF:
6881     case LYS_ANYXML:
6882     case LYS_ANYDATA:
6883     case LYS_NOTIF:
6884     case LYS_RPC:
6885     case LYS_ACTION:
6886         /* no argument check necessary */
6887         break;
6888     case LYS_LEAFLIST:
6889         if (!(schema->flags & LYS_CONFIG_W)) {
6890             LOGERR(lys_node_module(schema)->ctx, LY_EINVAL, "Invalid arguments - non-configuration leaf-list (%s()).", __func__);
6891             return -1;
6892         } else if (!key_or_value) {
6893             LOGERR(lys_node_module(schema)->ctx, LY_EINVAL, "Invalid arguments - no value for a leaf-list (%s()).", __func__);
6894             return -1;
6895         }
6896         break;
6897     case LYS_LIST:
6898         if (!((struct lys_node_list *)schema)->keys_size) {
6899             LOGERR(lys_node_module(schema)->ctx, LY_EINVAL, "Invalid arguments - key-less list (%s()).", __func__);
6900             return -1;
6901         } else if (!key_or_value) {
6902             LOGERR(lys_node_module(schema)->ctx, LY_EINVAL, "Invalid arguments - no keys for a list (%s()).", __func__);
6903             return -1;
6904         }
6905         break;
6906     default:
6907         LOGERR(lys_node_module(schema)->ctx, LY_EINVAL, "Invalid arguments - schema type %s (%s()).",
6908                strnodetype(schema->nodetype), __func__);
6909         return -1;
6910     }
6911 
6912     if (!siblings) {
6913         /* no data */
6914         *match = NULL;
6915         return 0;
6916     }
6917 
6918     /* create data node */
6919     switch (schema->nodetype) {
6920     case LYS_CONTAINER:
6921     case LYS_ANYXML:
6922     case LYS_ANYDATA:
6923     case LYS_NOTIF:
6924     case LYS_RPC:
6925     case LYS_ACTION:
6926         /* used attributes: schema, hash */
6927         target = _lyd_new(NULL, schema, 0);
6928         LY_CHECK_RETURN(!target, -1);
6929         break;
6930     case LYS_LEAF:
6931         /* used attributes: schema, hash */
6932         target = lyd_create_leaf(schema, NULL, 0, 1);
6933         LY_CHECK_RETURN(!target, -1);
6934         break;
6935     case LYS_LEAFLIST:
6936         /* used attributes: schema, hash, value_str */
6937         target = lyd_create_leaf(schema, key_or_value, 0, 0);
6938         LY_CHECK_RETURN(!target, -1);
6939         break;
6940     case LYS_LIST:
6941         /* used attributes: schema, hash, child (all keys) */
6942         target = _lyd_new(NULL, schema, 0);
6943         LY_CHECK_RETURN(!target, -1);
6944 
6945         /* create all keys */
6946         keys = strdup(key_or_value);
6947         LY_CHECK_ERR_GOTO(!keys, LOGMEM(lys_node_module(schema)->ctx), error);
6948         next_key = keys;
6949         for (i = 0; i < ((struct lys_node_list *)schema)->keys_size; ++i) {
6950             /* find key schema */
6951             key = (struct lys_node *)((struct lys_node_list *)schema)->keys[i];
6952 
6953             /* find key value */
6954             val = lyd_find_sibling_val_key_value(&next_key, key);
6955             LY_CHECK_GOTO(!val, error);
6956 
6957             /* create and insert key */
6958             node = lyd_create_leaf(key, val, 0, 0);
6959             if (!node || lyd_insert(target, node)) {
6960                 lyd_free(node);
6961                 goto error;
6962             }
6963         }
6964         break;
6965     default:
6966         /* unreachable */
6967         LOGARG;
6968         goto error;
6969     }
6970 
6971     /* find it */
6972     if (lyd_find_sibling(siblings, target, match)) {
6973         goto error;
6974     }
6975 
6976     free(keys);
6977     lyd_free(target);
6978     return 0;
6979 
6980 error:
6981     free(keys);
6982     lyd_free(target);
6983     return -1;
6984 }
6985 
6986 API struct lyd_node *
lyd_first_sibling(struct lyd_node * node)6987 lyd_first_sibling(struct lyd_node *node)
6988 {
6989     FUN_IN;
6990 
6991     struct lyd_node *start;
6992 
6993     if (!node) {
6994         return NULL;
6995     }
6996 
6997     /* get the first sibling */
6998     if (node->parent) {
6999         start = node->parent->child;
7000     } else {
7001         for (start = node; start->prev->next; start = start->prev);
7002     }
7003 
7004     return start;
7005 }
7006 
7007 API struct ly_set *
ly_set_new(void)7008 ly_set_new(void)
7009 {
7010     FUN_IN;
7011 
7012     struct ly_set *new;
7013 
7014     new = calloc(1, sizeof(struct ly_set));
7015     LY_CHECK_ERR_RETURN(!new, LOGMEM(NULL), NULL);
7016     return new;
7017 }
7018 
7019 API void
ly_set_free(struct ly_set * set)7020 ly_set_free(struct ly_set *set)
7021 {
7022     FUN_IN;
7023 
7024     if (!set) {
7025         return;
7026     }
7027 
7028     free(set->set.g);
7029     free(set);
7030 }
7031 
7032 API int
ly_set_contains(const struct ly_set * set,void * node)7033 ly_set_contains(const struct ly_set *set, void *node)
7034 {
7035     FUN_IN;
7036 
7037     unsigned int i;
7038 
7039     if (!set) {
7040         return -1;
7041     }
7042 
7043     for (i = 0; i < set->number; i++) {
7044         if (set->set.g[i] == node) {
7045             /* object found */
7046             return i;
7047         }
7048     }
7049 
7050     /* object not found */
7051     return -1;
7052 }
7053 
7054 API struct ly_set *
ly_set_dup(const struct ly_set * set)7055 ly_set_dup(const struct ly_set *set)
7056 {
7057     FUN_IN;
7058 
7059     struct ly_set *new;
7060 
7061     if (!set) {
7062         return NULL;
7063     }
7064 
7065     new = calloc(1, sizeof *new);
7066     LY_CHECK_ERR_RETURN(!new, LOGMEM(NULL), NULL);
7067     new->number = set->number;
7068     new->size = set->size;
7069 
7070     /* is there anything to copy? */
7071     if (set->size) {
7072         new->set.g = malloc(new->size * sizeof *(new->set.g));
7073         LY_CHECK_ERR_RETURN(!new->set.g, LOGMEM(NULL); free(new), NULL);
7074         assert(set->set.g);
7075         memcpy(new->set.g, set->set.g, new->size * sizeof *(new->set.g));
7076     }
7077 
7078     return new;
7079 }
7080 
7081 API int
ly_set_add(struct ly_set * set,void * node,int options)7082 ly_set_add(struct ly_set *set, void *node, int options)
7083 {
7084     FUN_IN;
7085 
7086     unsigned int i;
7087     void **new;
7088 
7089     if (!set) {
7090         LOGARG;
7091         return -1;
7092     }
7093 
7094     if (!(options & LY_SET_OPT_USEASLIST)) {
7095         /* search for duplication */
7096         for (i = 0; i < set->number; i++) {
7097             if (set->set.g[i] == node) {
7098                 /* already in set */
7099                 return i;
7100             }
7101         }
7102     }
7103 
7104     if (set->size == set->number) {
7105         new = realloc(set->set.g, (set->size + 8) * sizeof *(set->set.g));
7106         LY_CHECK_ERR_RETURN(!new, LOGMEM(NULL), -1);
7107         set->size += 8;
7108         set->set.g = new;
7109     }
7110 
7111     set->set.g[set->number++] = node;
7112 
7113     return set->number - 1;
7114 }
7115 
7116 API int
ly_set_merge(struct ly_set * trg,struct ly_set * src,int options)7117 ly_set_merge(struct ly_set *trg, struct ly_set *src, int options)
7118 {
7119     FUN_IN;
7120 
7121     unsigned int i, ret;
7122     void **new;
7123 
7124     if (!trg) {
7125         LOGARG;
7126         return -1;
7127     }
7128 
7129     if (!src) {
7130         return 0;
7131     }
7132 
7133     if (!(options & LY_SET_OPT_USEASLIST)) {
7134         /* remove duplicates */
7135         i = 0;
7136         while (i < src->number) {
7137             if (ly_set_contains(trg, src->set.g[i]) > -1) {
7138                 ly_set_rm_index(src, i);
7139             } else {
7140                 ++i;
7141             }
7142         }
7143     }
7144 
7145     /* allocate more memory if needed */
7146     if (trg->size < trg->number + src->number) {
7147         new = realloc(trg->set.g, (trg->number + src->number) * sizeof *(trg->set.g));
7148         LY_CHECK_ERR_RETURN(!new, LOGMEM(NULL), -1);
7149         trg->size = trg->number + src->number;
7150         trg->set.g = new;
7151     }
7152 
7153     /*
7154      * copy contents from src into trg
7155      * don't copy anything if there's nothing to copy, memcpy doesn't want NULL as second argument
7156      */
7157     if (src->number > 0) {
7158         memcpy(trg->set.g + trg->number, src->set.g, src->number * sizeof *(src->set.g));
7159     }
7160     ret = src->number;
7161     trg->number += ret;
7162 
7163     /* cleanup */
7164     ly_set_free(src);
7165     return ret;
7166 }
7167 
7168 API int
ly_set_rm_index(struct ly_set * set,unsigned int index)7169 ly_set_rm_index(struct ly_set *set, unsigned int index)
7170 {
7171     FUN_IN;
7172 
7173     if (!set || (index + 1) > set->number) {
7174         LOGARG;
7175         return EXIT_FAILURE;
7176     }
7177 
7178     if (index == set->number - 1) {
7179         /* removing last item in set */
7180         set->set.g[index] = NULL;
7181     } else {
7182         /* removing item somewhere in a middle, so put there the last item */
7183         set->set.g[index] = set->set.g[set->number - 1];
7184         set->set.g[set->number - 1] = NULL;
7185     }
7186     set->number--;
7187 
7188     return EXIT_SUCCESS;
7189 }
7190 
7191 API int
ly_set_rm(struct ly_set * set,void * node)7192 ly_set_rm(struct ly_set *set, void *node)
7193 {
7194     FUN_IN;
7195 
7196     unsigned int i;
7197 
7198     if (!set || !node) {
7199         LOGARG;
7200         return EXIT_FAILURE;
7201     }
7202 
7203     /* get index */
7204     for (i = 0; i < set->number; i++) {
7205         if (set->set.g[i] == node) {
7206             break;
7207         }
7208     }
7209     if (i == set->number) {
7210         /* node is not in set */
7211         LOGARG;
7212         return EXIT_FAILURE;
7213     }
7214 
7215     return ly_set_rm_index(set, i);
7216 }
7217 
7218 API int
ly_set_clean(struct ly_set * set)7219 ly_set_clean(struct ly_set *set)
7220 {
7221     FUN_IN;
7222 
7223     if (!set) {
7224         return EXIT_FAILURE;
7225     }
7226 
7227     free(set->set.g);
7228     set->set.g = NULL;
7229     set->size = 0;
7230     set->number = 0;
7231     return EXIT_SUCCESS;
7232 }
7233 
7234 API int
lyd_wd_default(struct lyd_node_leaf_list * node)7235 lyd_wd_default(struct lyd_node_leaf_list *node)
7236 {
7237     FUN_IN;
7238 
7239     struct lys_node_leaf *leaf;
7240     struct lys_node_leaflist *llist;
7241     struct lyd_node *iter;
7242     struct lys_tpdf *tpdf;
7243     const char *dflt = NULL, **dflts = NULL;
7244     uint8_t dflts_size = 0, c, i;
7245 
7246     if (!node || !(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
7247         return 0;
7248     }
7249 
7250     if (node->dflt) {
7251         return 1;
7252     }
7253 
7254     if (node->schema->nodetype == LYS_LEAF) {
7255         leaf = (struct lys_node_leaf *)node->schema;
7256 
7257         /* get know if there is a default value */
7258         if (leaf->dflt) {
7259             /* leaf has a default value */
7260             dflt = leaf->dflt;
7261         } else if (!(leaf->flags & LYS_MAND_TRUE)) {
7262             /* get the default value from the type */
7263             for (tpdf = leaf->type.der; tpdf && !dflt; tpdf = tpdf->type.der) {
7264                 dflt = tpdf->dflt;
7265             }
7266         }
7267         if (!dflt) {
7268             /* no default value */
7269             return 0;
7270         }
7271 
7272         /* compare the default value with the value of the leaf */
7273         if (!ly_strequal(dflt, node->value_str, 1)) {
7274             return 0;
7275         }
7276     } else if (node->schema->module->version >= LYS_VERSION_1_1) { /* LYS_LEAFLIST */
7277         llist = (struct lys_node_leaflist *)node->schema;
7278 
7279         /* get know if there is a default value */
7280         if (llist->dflt_size) {
7281             /* there are default values */
7282             dflts_size = llist->dflt_size;
7283             dflts = llist->dflt;
7284         } else if (!llist->min) {
7285             /* get the default value from the type */
7286             for (tpdf = llist->type.der; tpdf && !dflts; tpdf = tpdf->type.der) {
7287                 if (tpdf->dflt) {
7288                     dflts = &tpdf->dflt;
7289                     dflts_size = 1;
7290                     break;
7291                 }
7292             }
7293         }
7294 
7295         if (!dflts_size) {
7296             /* no default values to use */
7297             return 0;
7298         }
7299 
7300         /* compare the default value with the value of the leaf */
7301         /* first, find the first leaf-list's sibling */
7302         iter = (struct lyd_node *)node;
7303         if (iter->parent) {
7304             iter = iter->parent->child;
7305         } else {
7306             for (; iter->prev->next; iter = iter->prev);
7307         }
7308         for (c = 0; iter; iter = iter->next) {
7309             if (iter->schema != node->schema) {
7310                 continue;
7311             }
7312             if (c == dflts_size) {
7313                 /* to many leaf-list instances */
7314                 return 0;
7315             }
7316 
7317             if (llist->flags & LYS_USERORDERED) {
7318                 /* we have strict order */
7319                 if (!ly_strequal(dflts[c], ((struct lyd_node_leaf_list *)iter)->value_str, 1)) {
7320                     return 0;
7321                 }
7322             } else {
7323                 /* node's value is supposed to match with one of the default values */
7324                 for (i = 0; i < dflts_size; i++) {
7325                     if (ly_strequal(dflts[i], ((struct lyd_node_leaf_list *)iter)->value_str, 1)) {
7326                         break;
7327                     }
7328                 }
7329                 if (i == dflts_size) {
7330                     /* values do not match */
7331                     return 0;
7332                 }
7333             }
7334             c++;
7335         }
7336         if (c != dflts_size) {
7337             /* different sets of leaf-list instances */
7338             return 0;
7339         }
7340     } else {
7341         return 0;
7342     }
7343 
7344     /* all checks ok */
7345     return 1;
7346 }
7347 
7348 int
unres_data_diff_new(struct unres_data * unres,struct lyd_node * subtree,struct lyd_node * parent,int created)7349 unres_data_diff_new(struct unres_data *unres, struct lyd_node *subtree, struct lyd_node *parent, int created)
7350 {
7351     char *parent_xpath = NULL;
7352 
7353     if (created) {
7354         return lyd_difflist_add(unres->diff, &unres->diff_size, unres->diff_idx++, LYD_DIFF_CREATED, NULL, subtree);
7355     } else {
7356         if (parent) {
7357             parent_xpath = lyd_path(parent);
7358             LY_CHECK_ERR_RETURN(!parent_xpath, LOGMEM(lyd_node_module(subtree)->ctx), -1);
7359         }
7360         return lyd_difflist_add(unres->diff, &unres->diff_size, unres->diff_idx++, LYD_DIFF_DELETED,
7361                                 subtree, (struct lyd_node *)parent_xpath);
7362     }
7363 }
7364 
7365 void
unres_data_diff_rem(struct unres_data * unres,unsigned int idx)7366 unres_data_diff_rem(struct unres_data *unres, unsigned int idx)
7367 {
7368     if (unres->diff->type[idx] == LYD_DIFF_DELETED) {
7369         lyd_free_withsiblings(unres->diff->first[idx]);
7370         free(unres->diff->second[idx]);
7371     }
7372 
7373     /* replace by last real value */
7374     if (idx < unres->diff_idx - 1) {
7375         unres->diff->type[idx] = unres->diff->type[unres->diff_idx - 1];
7376         unres->diff->first[idx] = unres->diff->first[unres->diff_idx - 1];
7377         unres->diff->second[idx] = unres->diff->second[unres->diff_idx - 1];
7378     }
7379 
7380     /* move the end */
7381     assert(unres->diff->type[unres->diff_idx] == LYD_DIFF_END);
7382     unres->diff->type[unres->diff_idx - 1] = unres->diff->type[unres->diff_idx];
7383     --unres->diff_idx;
7384 }
7385 
7386 API void
lyd_free_val_diff(struct lyd_difflist * diff)7387 lyd_free_val_diff(struct lyd_difflist *diff)
7388 {
7389     FUN_IN;
7390 
7391     uint32_t i;
7392 
7393     if (!diff) {
7394         return;
7395     }
7396 
7397     for (i = 0; diff->type[i] != LYD_DIFF_END; ++i) {
7398         switch (diff->type[i]) {
7399         case LYD_DIFF_CREATED:
7400             free(diff->first[i]);
7401             lyd_free_withsiblings(diff->second[i]);
7402             break;
7403         case LYD_DIFF_DELETED:
7404             lyd_free_withsiblings(diff->first[i]);
7405             free(diff->second[i]);
7406             break;
7407         default:
7408             /* what to do? */
7409             break;
7410         }
7411     }
7412 
7413     lyd_free_diff(diff);
7414 }
7415 
7416 static int
lyd_wd_add_leaf(struct lyd_node ** tree,struct lyd_node * last_parent,struct lys_node_leaf * leaf,struct unres_data * unres,int check_when_must)7417 lyd_wd_add_leaf(struct lyd_node **tree, struct lyd_node *last_parent, struct lys_node_leaf *leaf, struct unres_data *unres,
7418                 int check_when_must)
7419 {
7420     struct lyd_node *dummy = NULL, *current;
7421     struct lys_tpdf *tpdf;
7422     const char *dflt = NULL;
7423     int ret;
7424 
7425     /* get know if there is a default value */
7426     if (leaf->dflt) {
7427         /* leaf has a default value */
7428         dflt = leaf->dflt;
7429     } else if (!(leaf->flags & LYS_MAND_TRUE)) {
7430         /* get the default value from the type */
7431         for (tpdf = leaf->type.der; tpdf && !dflt; tpdf = tpdf->type.der) {
7432             dflt = tpdf->dflt;
7433         }
7434     }
7435     if (!dflt) {
7436         /* no default value */
7437         return EXIT_SUCCESS;
7438     }
7439 
7440     /* create the node */
7441     if (!(dummy = lyd_new_dummy(*tree, last_parent, (struct lys_node*)leaf, dflt, 1))) {
7442         goto error;
7443     }
7444 
7445     if (unres->store_diff) {
7446         /* remember this subtree in the diff */
7447         if (unres_data_diff_new(unres, dummy, NULL, 1)) {
7448             goto error;
7449         }
7450     }
7451 
7452     if (!dummy->parent && (*tree)) {
7453         /* connect dummy nodes into the data tree (at the end of top level nodes) */
7454         if (lyd_insert_sibling(tree, dummy)) {
7455             goto error;
7456         }
7457     }
7458     for (current = dummy; ; current = current->child) {
7459         /* remember the created data in unres */
7460         if (check_when_must) {
7461             if ((current->when_status & LYD_WHEN) && unres_data_add(unres, current, UNRES_WHEN) == -1) {
7462                 goto error;
7463             }
7464             if (check_when_must == 2) {
7465                 ret = resolve_applies_must(current);
7466                 if ((ret & 0x1) && (unres_data_add(unres, current, UNRES_MUST) == -1)) {
7467                     goto error;
7468                 }
7469                 if ((ret & 0x2) && (unres_data_add(unres, current, UNRES_MUST_INOUT) == -1)) {
7470                     goto error;
7471                 }
7472             }
7473         }
7474 
7475         /* clear dummy-node flag */
7476         current->validity &= ~LYD_VAL_INUSE;
7477 
7478         if (current->schema == (struct lys_node *)leaf) {
7479             break;
7480         }
7481     }
7482     /* update parent's default flag if needed */
7483     lyd_wd_update_parents(dummy);
7484 
7485     /* if necessary, remember the created data value in unres */
7486     if (((struct lyd_node_leaf_list *)current)->value_type == LY_TYPE_LEAFREF) {
7487         if (unres_data_add(unres, current, UNRES_LEAFREF)) {
7488             goto error;
7489         }
7490     } else if (((struct lyd_node_leaf_list *)current)->value_type == LY_TYPE_INST) {
7491         if (unres_data_add(unres, current, UNRES_INSTID)) {
7492             goto error;
7493         }
7494     }
7495 
7496     if (!(*tree)) {
7497         *tree = dummy;
7498     }
7499     return EXIT_SUCCESS;
7500 
7501 error:
7502     lyd_free(dummy);
7503     return EXIT_FAILURE;
7504 }
7505 
7506 static int
lyd_wd_add_leaflist(struct lyd_node ** tree,struct lyd_node * last_parent,struct lys_node_leaflist * llist,struct unres_data * unres,int check_when_must)7507 lyd_wd_add_leaflist(struct lyd_node **tree, struct lyd_node *last_parent, struct lys_node_leaflist *llist,
7508                     struct unres_data *unres, int check_when_must)
7509 {
7510     struct lyd_node *dummy, *current, *first = NULL;
7511     struct lys_tpdf *tpdf;
7512     const char **dflt = NULL;
7513     uint8_t dflt_size = 0;
7514     int i, ret;
7515 
7516     if (llist->module->version < LYS_VERSION_1_1) {
7517         /* default values on leaf-lists are allowed from YANG 1.1 */
7518         return EXIT_SUCCESS;
7519     }
7520 
7521     /* get know if there is a default value */
7522     if (llist->dflt_size) {
7523         /* there are default values */
7524         dflt_size = llist->dflt_size;
7525         dflt = llist->dflt;
7526     } else if (!llist->min) {
7527         /* get the default value from the type */
7528         for (tpdf = llist->type.der; tpdf && !dflt; tpdf = tpdf->type.der) {
7529             if (tpdf->dflt) {
7530                 dflt = &tpdf->dflt;
7531                 dflt_size = 1;
7532                 break;
7533             }
7534         }
7535     }
7536 
7537     if (!dflt_size) {
7538         /* no default values to use */
7539         return EXIT_SUCCESS;
7540     }
7541 
7542     for (i = 0; i < dflt_size; i++) {
7543         /* create the node */
7544         if (!(dummy = lyd_new_dummy(*tree, last_parent, (struct lys_node*)llist, dflt[i], 1))) {
7545             goto error;
7546         }
7547 
7548         if (unres->store_diff) {
7549             /* remember this subtree in the diff */
7550             if (unres_data_diff_new(unres, dummy, NULL, 1)) {
7551                 goto error;
7552             }
7553         }
7554 
7555         if (!first) {
7556             first = dummy;
7557         } else if (!dummy->parent) {
7558             /* interconnect with the rest of leaf-lists */
7559             first->prev->next = dummy;
7560             dummy->prev = first->prev;
7561             first->prev = dummy;
7562         }
7563 
7564         for (current = dummy; ; current = current->child) {
7565             /* remember the created data in unres */
7566             if (check_when_must) {
7567                 if ((current->when_status & LYD_WHEN) && unres_data_add(unres, current, UNRES_WHEN) == -1) {
7568                     goto error;
7569                 }
7570                 if (check_when_must == 2) {
7571                     ret = resolve_applies_must(current);
7572                     if ((ret & 0x1) && (unres_data_add(unres, current, UNRES_MUST) == -1)) {
7573                         goto error;
7574                     }
7575                     if ((ret & 0x2) && (unres_data_add(unres, current, UNRES_MUST_INOUT) == -1)) {
7576                         goto error;
7577                     }
7578                 }
7579             }
7580 
7581             /* clear dummy-node flag */
7582             current->validity &= ~LYD_VAL_INUSE;
7583 
7584             if (current->schema == (struct lys_node *)llist) {
7585                 break;
7586             }
7587         }
7588 
7589         /* if necessary, remember the created data value in unres */
7590         if (((struct lyd_node_leaf_list *)current)->value_type == LY_TYPE_LEAFREF) {
7591             if (unres_data_add(unres, current, UNRES_LEAFREF)) {
7592                 goto error;
7593             }
7594         } else if (((struct lyd_node_leaf_list *)current)->value_type == LY_TYPE_INST) {
7595             if (unres_data_add(unres, current, UNRES_INSTID)) {
7596                 goto error;
7597             }
7598         }
7599     }
7600 
7601     /* insert into the tree */
7602     if (first && !first->parent && (*tree)) {
7603         /* connect dummy nodes into the data tree (at the end of top level nodes) */
7604         if (lyd_insert_sibling(tree, first)) {
7605             goto error;
7606         }
7607     } else if (!(*tree)) {
7608         *tree = first;
7609     }
7610 
7611     /* update parent's default flag if needed */
7612     lyd_wd_update_parents(first);
7613 
7614     return EXIT_SUCCESS;
7615 
7616 error:
7617     lyd_free_withsiblings(first);
7618     return EXIT_FAILURE;
7619 }
7620 
7621 static void
lyd_wd_leaflist_cleanup(struct ly_set * set,struct unres_data * unres)7622 lyd_wd_leaflist_cleanup(struct ly_set *set, struct unres_data *unres)
7623 {
7624     unsigned int i;
7625 
7626     assert(set);
7627 
7628     /* if there is an instance without the dflt flag, we have to
7629      * remove all instances with the flag - an instance could be
7630      * explicitely added, so the default leaflists were invalidated */
7631     for (i = 0; i < set->number; i++) {
7632         if (!set->set.d[i]->dflt) {
7633             break;
7634         }
7635     }
7636     if (i < set->number) {
7637         for (i = 0; i < set->number; i++) {
7638             if (set->set.d[i]->dflt) {
7639                 /* remove this default instance */
7640                 if (unres->store_diff) {
7641                     /* just move it to diff if is being generated */
7642                     unres_data_diff_new(unres, set->set.d[i], set->set.d[i]->parent, 0);
7643                     lyd_unlink(set->set.d[i]);
7644                 } else {
7645                     lyd_free(set->set.d[i]);
7646                 }
7647             }
7648         }
7649     }
7650 }
7651 
7652 /**
7653  * @brief Process (add/clean flags) default nodes in the schema subtree
7654  *
7655  * @param[in,out] root Pointer to the root node of the complete data tree, the root node can be NULL if the data tree
7656  *                     is empty
7657  * @param[in] last_parent The closest parent in the data tree to the currently processed \p schema node
7658  * @param[in] subroot  The root node of a data subtree, the node is instance of the \p schema node, NULL in case the
7659  *                     schema node is not instantiated in the data tree
7660  * @param[in] schema The schema node to be processed
7661  * @param[in] toplevel Flag for processing top level schema nodes when \p last_parent and \p subroot are consider as
7662  *                     unknown
7663  * @param[in] options  Parser options to know the data tree type, see @ref parseroptions.
7664  * @param[in] unres    Unresolved data list, the newly added default nodes may need to add some unresolved items
7665  * @return EXIT_SUCCESS or EXIT_FAILURE
7666  */
7667 static int
lyd_wd_add_subtree(struct lyd_node ** root,struct lyd_node * last_parent,struct lyd_node * subroot,struct lys_node * schema,int toplevel,int options,struct unres_data * unres)7668 lyd_wd_add_subtree(struct lyd_node **root, struct lyd_node *last_parent, struct lyd_node *subroot,
7669                    struct lys_node *schema, int toplevel, int options, struct unres_data *unres)
7670 {
7671     struct ly_set *present = NULL;
7672     struct lys_node *siter, *siter_prev;
7673     struct lyd_node *iter;
7674     int i, check_when_must, storing_diff = 0;
7675 
7676     assert(root);
7677 
7678     if ((options & LYD_OPT_TYPEMASK) && (schema->flags & LYS_CONFIG_R)) {
7679         /* non LYD_OPT_DATA tree, status data are not expected here */
7680         return EXIT_SUCCESS;
7681     }
7682 
7683     if (options & (LYD_OPT_NOTIF_FILTER | LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG)) {
7684         check_when_must = 0; /* check neither */
7685     } else if (options & LYD_OPT_TRUSTED) {
7686         check_when_must = 1; /* check only when */
7687     } else {
7688         check_when_must = 2; /* check both when and must */
7689     }
7690 
7691     if (toplevel && (schema->nodetype & (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER))) {
7692         /* search for the schema node instance */
7693         present = ly_set_new();
7694         if (!present) {
7695             goto error;
7696         }
7697         if ((*root) && lyd_get_node_siblings(*root, schema, present)) {
7698             /* there are some instances */
7699             for (i = 0; i < (signed)present->number; i++) {
7700                 if (schema->nodetype & LYS_LEAFLIST) {
7701                     lyd_wd_leaflist_cleanup(present, unres);
7702                 } else if (schema->nodetype != LYS_LEAF) {
7703                     if (lyd_wd_add_subtree(root, present->set.d[i], present->set.d[i], schema, 0, options, unres)) {
7704                         goto error;
7705                     }
7706                 } /* else LYS_LEAF - nothing to do */
7707             }
7708         } else {
7709             /* no instance */
7710             if (lyd_wd_add_subtree(root, last_parent, NULL, schema, 0, options, unres)) {
7711                 goto error;
7712             }
7713         }
7714 
7715         ly_set_free(present);
7716         return EXIT_SUCCESS;
7717     }
7718 
7719     /* skip disabled parts of schema */
7720     if (!subroot) {
7721         /* go through all the uses and check whether they are enabled */
7722         for (siter = schema->parent; siter && (siter->nodetype & (LYS_USES | LYS_CHOICE)); siter = siter->parent) {
7723             if (lys_is_disabled(siter, 0)) {
7724                 /* ignore disabled uses nodes */
7725                 return EXIT_SUCCESS;
7726             }
7727         }
7728 
7729         /* check augment state */
7730         if (siter && siter->nodetype == LYS_AUGMENT) {
7731             if (lys_is_disabled(siter, 0)) {
7732                 /* ignore disabled augment */
7733                 return EXIT_SUCCESS;
7734             }
7735         }
7736 
7737         /* check the node itself */
7738         if (lys_is_disabled(schema, 0)) {
7739             /* ignore disabled data */
7740             return EXIT_SUCCESS;
7741         }
7742     }
7743 
7744     /* go recursively */
7745     switch (schema->nodetype) {
7746     case LYS_LIST:
7747         if (!subroot) {
7748             /* stop recursion */
7749             break;
7750         }
7751         /* falls through */
7752     case LYS_CONTAINER:
7753         if (!subroot) {
7754             /* container does not exists, continue only in case of non presence container */
7755             if (((struct lys_node_container *)schema)->presence) {
7756                 /* stop recursion */
7757                 break;
7758             }
7759             /* always create empty NP container even if there is no default node,
7760              * because accroding to RFC, the empty NP container is always part of
7761              * accessible tree (e.g. for evaluating when and must conditions) */
7762             subroot = _lyd_new(last_parent, schema, 1);
7763             /* useless to set mand flag */
7764             subroot->validity &= ~LYD_VAL_MAND;
7765 
7766             if (unres->store_diff) {
7767                 /* remember this container in the diff */
7768                 if (unres_data_diff_new(unres, subroot, NULL, 1)) {
7769                     goto error;
7770                 }
7771 
7772                 /* do not store diff for recursive calls, created values will be connected to this one */
7773                 storing_diff = 1;
7774                 unres->store_diff = 0;
7775             }
7776 
7777             if (!last_parent) {
7778                 if (*root) {
7779                     lyd_insert_common((*root)->parent, root, subroot, 0);
7780                 } else {
7781                     *root = subroot;
7782                 }
7783             }
7784             last_parent = subroot;
7785 
7786             /* remember the created container in unres */
7787             if (check_when_must) {
7788                 if ((subroot->when_status & LYD_WHEN) && unres_data_add(unres, subroot, UNRES_WHEN) == -1) {
7789                     goto error;
7790                 }
7791                 if (check_when_must == 2) {
7792                     i = resolve_applies_must(subroot);
7793                     if ((i & 0x1) && (unres_data_add(unres, subroot, UNRES_MUST) == -1)) {
7794                         goto error;
7795                     }
7796                     if ((i & 0x2) && (unres_data_add(unres, subroot, UNRES_MUST_INOUT) == -1)) {
7797                         goto error;
7798                     }
7799                 }
7800             }
7801         } else if (!((struct lys_node_container *)schema)->presence) {
7802             /* fix default flag on existing containers - set it on all non-presence containers and in case we will
7803              * have in recursion function some non-default node, it will unset it */
7804             subroot->dflt = 1;
7805         }
7806         /* falls through */
7807     case LYS_CASE:
7808     case LYS_USES:
7809     case LYS_INPUT:
7810     case LYS_OUTPUT:
7811     case LYS_NOTIF:
7812 
7813         /* recursion */
7814         present = ly_set_new();
7815         if (!present) {
7816             goto error;
7817         }
7818         LY_TREE_FOR(schema->child, siter) {
7819             if (siter->nodetype & (LYS_CHOICE | LYS_USES)) {
7820                 /* go into without searching for data instance */
7821                 if (lyd_wd_add_subtree(root, last_parent, subroot, siter, toplevel, options, unres)) {
7822                     goto error;
7823                 }
7824             } else if (siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) {
7825                 /* search for the schema node instance */
7826                 if (subroot && lyd_get_node_siblings(subroot->child, siter, present)) {
7827                     /* there are some instances in the data root */
7828                     if (siter->nodetype & LYS_LEAFLIST) {
7829                         /* already have some leaflists, check that they are all
7830                          * default, if not, remove the default leaflists */
7831                         lyd_wd_leaflist_cleanup(present, unres);
7832                     } else if (siter->nodetype != LYS_LEAF) {
7833                         /* recursion */
7834                         for (i = 0; i < (signed)present->number; i++) {
7835                             if (lyd_wd_add_subtree(root, present->set.d[i], present->set.d[i], siter, toplevel, options,
7836                                                    unres)) {
7837                                 goto error;
7838                             }
7839                         }
7840                     } /* else LYS_LEAF - nothing to do */
7841 
7842                     /* fix default flag (2nd part) - for non-default node with default parent, unset the default flag
7843                      * from the parents (starting from subroot node) */
7844                     if (subroot->dflt) {
7845                         for (i = 0; i < (signed)present->number; i++) {
7846                             if (!present->set.d[i]->dflt) {
7847                                 for (iter = subroot; iter && iter->dflt; iter = iter->parent) {
7848                                     iter->dflt = 0;
7849                                 }
7850                                 break;
7851                             }
7852                         }
7853                     }
7854                     ly_set_clean(present);
7855                 } else {
7856                     /* no instance */
7857                     if (lyd_wd_add_subtree(root, last_parent, NULL, siter, toplevel, options, unres)) {
7858                         goto error;
7859                     }
7860                 }
7861             }
7862         }
7863 
7864         if (storing_diff) {
7865             /* continue generating the diff in functions above this one */
7866             unres->store_diff = 1;
7867         }
7868         break;
7869     case LYS_LEAF:
7870     case LYS_LEAFLIST:
7871         if (subroot) {
7872             /* default shortcase of a choice */
7873             present = ly_set_new();
7874             if (!present) {
7875                 goto error;
7876             }
7877             lyd_get_node_siblings(subroot->child, schema, present);
7878             if (present->number) {
7879                 /* the shortcase leaf(-list) exists, stop the processing and fix default flags */
7880                 if (subroot->dflt) {
7881                     for (i = 0; i < (signed)present->number; i++) {
7882                         if (!present->set.d[i]->dflt) {
7883                             for (iter = subroot; iter && iter->dflt; iter = iter->parent) {
7884                                 iter->dflt = 0;
7885                             }
7886                             break;
7887                         }
7888                     }
7889                 }
7890                 break;
7891             }
7892         }
7893         if (schema->nodetype == LYS_LEAF) {
7894             if (lyd_wd_add_leaf(root, last_parent, (struct lys_node_leaf*)schema, unres, check_when_must)) {
7895                 return EXIT_FAILURE;
7896             }
7897         } else { /* LYS_LEAFLIST */
7898             if (lyd_wd_add_leaflist(root, last_parent, (struct lys_node_leaflist*)schema, unres, check_when_must)) {
7899                 goto error;
7900             }
7901         }
7902         break;
7903     case LYS_CHOICE:
7904         /* get existing node in the data root from the choice */
7905         iter = NULL;
7906         if ((toplevel && (*root)) || (!toplevel && subroot)) {
7907             LY_TREE_FOR(toplevel ? (*root) : subroot->child, iter) {
7908                 for (siter = lys_parent(iter->schema), siter_prev = iter->schema;
7909                         siter && (siter->nodetype & (LYS_CASE | LYS_USES | LYS_CHOICE));
7910                         siter_prev = siter, siter = lys_parent(siter)) {
7911                     if (siter == schema) {
7912                         /* we have the choice instance */
7913                         break;
7914                     }
7915                 }
7916                 if (siter == schema) {
7917                     /* we have the choice instance;
7918                      * the condition must be the same as in the loop because of
7919                      * choice's sibling nodes that break the loop, so siter is not NULL,
7920                      * but it is not the same as schema */
7921                     break;
7922                 }
7923             }
7924         }
7925         if (!iter) {
7926             if (((struct lys_node_choice *)schema)->dflt) {
7927                 /* there is a default case */
7928                 if (lyd_wd_add_subtree(root, last_parent, subroot, ((struct lys_node_choice *)schema)->dflt,
7929                                        toplevel, options, unres)) {
7930                     goto error;
7931                 }
7932             }
7933         } else {
7934             /* one of the choice's cases is instantiated, continue into this case */
7935             /* since iter != NULL, siter must be also != NULL and we also know siter_prev
7936              * which points to the child of schema leading towards the instantiated data */
7937             assert(siter && siter_prev);
7938             if (lyd_wd_add_subtree(root, last_parent, subroot, siter_prev, toplevel, options, unres)) {
7939                 goto error;
7940             }
7941         }
7942         break;
7943     default:
7944         /* LYS_ANYXML, LYS_ANYDATA, LYS_USES, LYS_GROUPING - do nothing */
7945         break;
7946     }
7947 
7948     ly_set_free(present);
7949     return EXIT_SUCCESS;
7950 
7951 error:
7952     ly_set_free(present);
7953     return EXIT_FAILURE;
7954 }
7955 
7956 /**
7957  * @brief Covering function to process (add/clean) default nodes in the data tree
7958  * @param[in,out] root Pointer to the root node of the complete data tree, the root node can be NULL if the data tree
7959  *                     is empty
7960  * @param[in] ctx      Context for the case the data tree is empty (in that case \p ctx must not be NULL)
7961  * @param[in] options  Parser options to know the data tree type, see @ref parseroptions.
7962  * @param[in] unres    Unresolved data list, the newly added default nodes may need to add some unresolved items
7963  * @return EXIT_SUCCESS or EXIT_FAILURE
7964  */
7965 static int
lyd_wd_add(struct lyd_node ** root,struct ly_ctx * ctx,const struct lys_module ** modules,int mod_count,struct unres_data * unres,int options)7966 lyd_wd_add(struct lyd_node **root, struct ly_ctx *ctx, const struct lys_module **modules, int mod_count,
7967            struct unres_data *unres, int options)
7968 {
7969     struct lys_node *siter;
7970     int i;
7971 
7972     assert(root && !(options & LYD_OPT_ACT_NOTIF));
7973     assert(*root || ctx);
7974     assert(!(options & LYD_OPT_NOSIBLINGS) || *root);
7975 
7976     if (options & (LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG)) {
7977         /* no change supposed */
7978         return EXIT_SUCCESS;
7979     }
7980 
7981     if (!ctx) {
7982         ctx = (*root)->schema->module->ctx;
7983     }
7984 
7985     if (!(options & LYD_OPT_TYPEMASK) || (options & LYD_OPT_CONFIG)) {
7986         if (options & LYD_OPT_NOSIBLINGS) {
7987             if (lyd_wd_add_subtree(root, NULL, NULL, (*root)->schema, 1, options, unres)) {
7988                 return EXIT_FAILURE;
7989             }
7990         } else if (modules && mod_count) {
7991             for (i = 0; i < mod_count; ++i) {
7992                 LY_TREE_FOR(modules[i]->data, siter) {
7993                     if (!(siter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA |
7994                                              LYS_USES))) {
7995                         continue;
7996                     }
7997                     if (lyd_wd_add_subtree(root, NULL, NULL, siter, 1, options, unres)) {
7998                         return EXIT_FAILURE;
7999                     }
8000                 }
8001             }
8002         } else {
8003             for (i = 0; i < ctx->models.used; i++) {
8004                 /* skip not implemented and disabled modules */
8005                 if (!ctx->models.list[i]->implemented || ctx->models.list[i]->disabled) {
8006                     continue;
8007                 }
8008                 LY_TREE_FOR(ctx->models.list[i]->data, siter) {
8009                     if (!(siter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA |
8010                                              LYS_USES))) {
8011                         continue;
8012                     }
8013                     if (lyd_wd_add_subtree(root, NULL, NULL, siter, 1, options, unres)) {
8014                         return EXIT_FAILURE;
8015                     }
8016                 }
8017             }
8018         }
8019     } else if (options & (LYD_OPT_NOTIF | LYD_OPT_NOTIF_FILTER)) {
8020         if (!(*root) || ((*root)->schema->nodetype != LYS_NOTIF)) {
8021             LOGERR(ctx, LY_EINVAL, "Subtree is not a single notification.");
8022             return EXIT_FAILURE;
8023         }
8024         if (lyd_wd_add_subtree(root, *root, *root, (*root)->schema, 0, options, unres)) {
8025             return EXIT_FAILURE;
8026         }
8027     } else if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) {
8028         if (!(*root) || !((*root)->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
8029             LOGERR(ctx, LY_EINVAL, "Subtree is not a single RPC/action/reply.");
8030             return EXIT_FAILURE;
8031         }
8032         if (options & LYD_OPT_RPC) {
8033             for (siter = (*root)->schema->child; siter && siter->nodetype != LYS_INPUT; siter = siter->next);
8034         } else { /* LYD_OPT_RPCREPLY */
8035             for (siter = (*root)->schema->child; siter && siter->nodetype != LYS_OUTPUT; siter = siter->next);
8036         }
8037         if (siter) {
8038             if (lyd_wd_add_subtree(root, *root, *root, siter, 0, options, unres)) {
8039                 return EXIT_FAILURE;
8040             }
8041         }
8042     } else if (options & LYD_OPT_DATA_TEMPLATE) {
8043         if (lyd_wd_add_subtree(root, NULL, NULL, (*root)->schema, 1, options, unres)) {
8044             return EXIT_FAILURE;
8045         }
8046     } else {
8047         LOGINT(ctx);
8048         return EXIT_FAILURE;
8049     }
8050 
8051     return EXIT_SUCCESS;
8052 }
8053 
8054 int
lyd_defaults_add_unres(struct lyd_node ** root,int options,struct ly_ctx * ctx,const struct lys_module ** modules,int mod_count,const struct lyd_node * data_tree,struct lyd_node * act_notif,struct unres_data * unres,int wd)8055 lyd_defaults_add_unres(struct lyd_node **root, int options, struct ly_ctx *ctx, const struct lys_module **modules,
8056                        int mod_count, const struct lyd_node *data_tree, struct lyd_node *act_notif,
8057                        struct unres_data *unres, int wd)
8058 {
8059     struct lyd_node *msg_sibling = NULL, *msg_parent = NULL, *data_tree_sibling = NULL, *data_tree_parent = NULL;
8060     struct lys_node *msg_op = NULL;
8061     struct ly_set *set;
8062     int ret = EXIT_FAILURE;
8063 
8064     assert(root && (*root || ctx) && unres && !(options & LYD_OPT_ACT_NOTIF));
8065 
8066     if (!ctx) {
8067         ctx = (*root)->schema->module->ctx;
8068     }
8069 
8070     if ((options & LYD_OPT_NOSIBLINGS) && !(*root)) {
8071         LOGERR(ctx, LY_EINVAL, "Cannot add default values for one module (LYD_OPT_NOSIBLINGS) without any data.");
8072         return EXIT_FAILURE;
8073     }
8074 
8075     if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
8076         if (!(*root)) {
8077             LOGERR(ctx, LY_EINVAL, "Cannot add default values to RPC, RPC reply, and notification without at least the empty container.");
8078             return EXIT_FAILURE;
8079         }
8080         if ((options & LYD_OPT_RPC) && !act_notif && ((*root)->schema->nodetype != LYS_RPC)) {
8081             LOGERR(ctx, LY_EINVAL, "Not valid RPC/action data.");
8082             return EXIT_FAILURE;
8083         }
8084         if ((options & LYD_OPT_RPCREPLY) && !act_notif && ((*root)->schema->nodetype != LYS_RPC)) {
8085             LOGERR(ctx, LY_EINVAL, "Not valid reply data.");
8086             return EXIT_FAILURE;
8087         }
8088         if ((options & LYD_OPT_NOTIF) && !act_notif && ((*root)->schema->nodetype != LYS_NOTIF)) {
8089             LOGERR(ctx, LY_EINVAL, "Not valid notification data.");
8090             return EXIT_FAILURE;
8091         }
8092 
8093         /* remember the operation/notification schema */
8094         msg_op = act_notif ? act_notif->schema : (*root)->schema;
8095     } else if (*root && (*root)->parent) {
8096         /* we have inner node, so it will be considered as
8097          * a root of subtree where to add default nodes and
8098          * no of its siblings will be affected */
8099         options |= LYD_OPT_NOSIBLINGS;
8100     }
8101 
8102     /* add missing default nodes */
8103     if (wd && lyd_wd_add((act_notif ? &act_notif : root), ctx, modules, mod_count, unres, options)) {
8104         return EXIT_FAILURE;
8105     }
8106 
8107     /* check leafrefs and/or instids if any */
8108     if (unres && unres->count) {
8109         if (!(*root)) {
8110             LOGINT(ctx);
8111             return EXIT_FAILURE;
8112         }
8113 
8114         /* temporarily link the additional data tree to the RPC/action/notification */
8115         if (data_tree && (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF))) {
8116             /* duplicate the message tree - if it gets deleted we would not be able to positively identify it */
8117             msg_parent = NULL;
8118             msg_sibling = *root;
8119 
8120             if (act_notif) {
8121                 /* fun case */
8122                 data_tree_parent = NULL;
8123                 data_tree_sibling = (struct lyd_node *)data_tree;
8124                 while (data_tree_sibling) {
8125                     while (data_tree_sibling) {
8126                         if ((data_tree_sibling->schema == msg_sibling->schema)
8127                                 && ((msg_sibling->schema->nodetype != LYS_LIST)
8128                                     || lyd_list_equal(data_tree_sibling, msg_sibling, 0))) {
8129                             /* match */
8130                             break;
8131                         }
8132 
8133                         data_tree_sibling = data_tree_sibling->next;
8134                     }
8135 
8136                     if (data_tree_sibling) {
8137                         /* prepare for the new data_tree iteration */
8138                         data_tree_parent = data_tree_sibling;
8139                         data_tree_sibling = data_tree_sibling->child;
8140 
8141                         /* find new action sibling to search for later (skip list keys) */
8142                         msg_parent = msg_sibling;
8143                         assert(msg_sibling->child);
8144                         for (msg_sibling = msg_sibling->child;
8145                                 msg_sibling->schema->nodetype == LYS_LEAF;
8146                                 msg_sibling = msg_sibling->next) {
8147                             assert(msg_sibling->next);
8148                         }
8149                         if (msg_sibling->schema->nodetype & (LYS_ACTION | LYS_NOTIF)) {
8150                             /* we are done */
8151                             assert(act_notif->parent);
8152                             assert(act_notif->parent->schema == data_tree_parent->schema);
8153                             assert(msg_sibling == act_notif);
8154                             break;
8155                         }
8156                     }
8157                 }
8158 
8159                 /* loop ended after the first iteration, set the values correctly */
8160                 if (!data_tree_parent) {
8161                     data_tree_sibling = (struct lyd_node *)data_tree;
8162                 }
8163 
8164             } else {
8165                 /* easy case */
8166                 data_tree_parent = NULL;
8167                 data_tree_sibling = (struct lyd_node *)data_tree;
8168             }
8169 
8170             /* unlink msg_sibling if needed (won't do anything otherwise) */
8171             lyd_unlink_internal(msg_sibling, 0);
8172 
8173             /* now we can insert msg_sibling into data_tree_parent or next to data_tree_sibling */
8174             assert(data_tree_parent || data_tree_sibling);
8175             if (data_tree_parent) {
8176                 if (lyd_insert_common(data_tree_parent, NULL, msg_sibling, 0)) {
8177                     goto unlink_datatree;
8178                 }
8179             } else {
8180                 assert(!data_tree_sibling->parent);
8181                 if (lyd_insert_nextto(data_tree_sibling->prev, msg_sibling, 0, 0)) {
8182                     goto unlink_datatree;
8183                 }
8184             }
8185         }
8186 
8187         if (resolve_unres_data(ctx, unres, root, options)) {
8188             goto unlink_datatree;
8189         }
8190 
8191         /* we are done */
8192         ret = EXIT_SUCCESS;
8193 
8194         /* check that the operation/notification tree was not removed */
8195         if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
8196             set = NULL;
8197             if (data_tree) {
8198                 set = lyd_find_instance(data_tree_parent ? data_tree_parent : data_tree_sibling, msg_op);
8199                 assert(set && ((set->number == 0) || (set->number == 1)));
8200             } else if (*root) {
8201                 set = lyd_find_instance(*root, msg_op);
8202                 assert(set && ((set->number == 0) || (set->number == 1)));
8203             }
8204             if (!set || !set->number) {
8205                 /* it was removed, handle specially */
8206                 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, msg_op, "Operation/notification not supported because of the current configuration.");
8207                 ret = EXIT_FAILURE;
8208             }
8209             ly_set_free(set);
8210         }
8211 
8212 unlink_datatree:
8213         /* put the trees back in order */
8214         if (data_tree && (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF))) {
8215             /* unlink and insert it back, if there is a parent  */
8216             lyd_unlink_internal(msg_sibling, 0);
8217             if (msg_parent) {
8218                 lyd_insert_common(msg_parent, NULL, msg_sibling, 0);
8219             }
8220         }
8221     } else {
8222         /* we are done */
8223         ret = EXIT_SUCCESS;
8224     }
8225 
8226     return ret;
8227 }
8228 
8229 API struct lys_module *
lyd_node_module(const struct lyd_node * node)8230 lyd_node_module(const struct lyd_node *node)
8231 {
8232     FUN_IN;
8233 
8234     if (!node) {
8235         return NULL;
8236     }
8237 
8238     return node->schema->module->type ? ((struct lys_submodule *)node->schema->module)->belongsto : node->schema->module;
8239 }
8240 
8241 API double
lyd_dec64_to_double(const struct lyd_node * node)8242 lyd_dec64_to_double(const struct lyd_node *node)
8243 {
8244     FUN_IN;
8245 
8246     if (!node || !(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))
8247             || (((struct lys_node_leaf *)node->schema)->type.base != LY_TYPE_DEC64)) {
8248         LOGARG;
8249         return 0;
8250     }
8251 
8252     return atof(((struct lyd_node_leaf_list *)node)->value_str);
8253 }
8254 
8255 API const struct lys_type *
lyd_leaf_type(const struct lyd_node_leaf_list * leaf)8256 lyd_leaf_type(const struct lyd_node_leaf_list *leaf)
8257 {
8258     FUN_IN;
8259 
8260     struct lys_type *type;
8261 
8262     if (!leaf || !(leaf->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
8263         return NULL;
8264     }
8265 
8266     type = &((struct lys_node_leaf *)leaf->schema)->type;
8267 
8268     do {
8269         if (type->base == LY_TYPE_LEAFREF) {
8270             type = &type->info.lref.target->type;
8271         } else if (type->base == LY_TYPE_UNION) {
8272             if (type->info.uni.has_ptr_type && leaf->validity) {
8273                 /* we don't know what it will be after resolution (validation) */
8274                 LOGVAL(leaf->schema->module->ctx, LYE_SPEC, LY_VLOG_LYD, leaf,
8275                        "Unable to determine the type of value \"%s\" from union type \"%s\" prior to validation.",
8276                        leaf->value_str, type->der->name);
8277                 return NULL;
8278             }
8279 
8280             if (resolve_union((struct lyd_node_leaf_list *)leaf, type, 0, 0, &type)) {
8281                 /* resolve union failed */
8282                 return NULL;
8283             }
8284         }
8285     } while (type->base == LY_TYPE_LEAFREF);
8286 
8287     return type;
8288 }
8289 
8290 #ifdef LY_ENABLED_LYD_PRIV
8291 
8292 API void *
lyd_set_private(const struct lyd_node * node,void * priv)8293 lyd_set_private(const struct lyd_node *node, void *priv)
8294 {
8295     FUN_IN;
8296 
8297     void *prev;
8298 
8299     if (!node) {
8300         LOGARG;
8301         return NULL;
8302     }
8303 
8304     prev = node->priv;
8305     ((struct lyd_node *)node)->priv = priv;
8306 
8307     return prev;
8308 }
8309 
8310 #endif
8311 
8312 API struct lyd_node *
lyd_find_path_hash_based(struct lyd_node * data_tree,const struct ly_ctx * ctx,const char * path,int output)8313 lyd_find_path_hash_based(struct lyd_node *data_tree, const struct ly_ctx *ctx, const char *path, int output)
8314 {
8315     FUN_IN;
8316 
8317     const char *id;
8318     struct lyd_node *node, *parent = NULL;
8319     int parsed = 0;
8320     int options = 0;
8321 
8322     if (!path || (!data_tree && !ctx)
8323             || (!data_tree && (path[0] != '/'))) {
8324         LOGARG;
8325         return NULL;
8326     }
8327 
8328     /* The only relevant option is LYD_PATH_OPT_OUTPUT  */
8329     if (output)
8330         options = LYD_PATH_OPT_OUTPUT;
8331 
8332 
8333     if (!ctx) {
8334         ctx = data_tree->schema->module->ctx;
8335     }
8336 
8337     id = path;
8338 
8339     if (data_tree) {
8340         if (path[0] == '/') {
8341             /* absolute path, go through all the siblings and try to find the right parent, if exists,
8342              * first go through all the next siblings keeping the original order, for positional predicates */
8343             for (node = data_tree; !parsed && node; node = node->next) {
8344                 parent = resolve_partial_json_data_nodeid(id, NULL, node, options, &parsed);
8345             }
8346             if (!parsed) {
8347                 for (node = data_tree->prev; !parsed && node->next; node = node->prev) {
8348                     parent = resolve_partial_json_data_nodeid(id, NULL, node, options, &parsed);
8349                 }
8350             }
8351         } else {
8352             /* relative path, use only the provided data tree root */
8353             parent = resolve_partial_json_data_nodeid(id, NULL, data_tree, options, &parsed);
8354         }
8355         if (parsed == -1) {
8356             return NULL;
8357         }
8358     }
8359 
8360     return parent;
8361 }
8362