1 /**
2 * @file parser_lyb.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief LYB data parser for libyang
5 *
6 * Copyright (c) 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 #include <assert.h>
16 #include <errno.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <inttypes.h>
20
21 #include "libyang.h"
22 #include "common.h"
23 #include "context.h"
24 #include "parser.h"
25 #include "tree_internal.h"
26
27 #define LYB_HAVE_READ_GOTO(r, d, go) if (r < 0) goto go; d += r;
28 #define LYB_HAVE_READ_RETURN(r, d, ret) if (r < 0) return ret; d += r;
29
30 static int
lyb_read(const char * data,uint8_t * buf,size_t count,struct lyb_state * lybs)31 lyb_read(const char *data, uint8_t *buf, size_t count, struct lyb_state *lybs)
32 {
33 int ret = 0, i, empty_chunk_i;
34 size_t to_read;
35 uint8_t meta_buf[LYB_META_BYTES];
36
37 assert(data && lybs);
38
39 while (1) {
40 /* check for fully-read (empty) data chunks */
41 to_read = count;
42 empty_chunk_i = -1;
43 for (i = 0; i < lybs->used; ++i) {
44 /* we want the innermost chunks resolved first, so replace previous empty chunks,
45 * also ignore chunks that are completely finished, there is nothing for us to do */
46 if ((lybs->written[i] <= to_read) && lybs->position[i]) {
47 /* empty chunk, do not read more */
48 to_read = lybs->written[i];
49 empty_chunk_i = i;
50 }
51 }
52
53 if ((empty_chunk_i == -1) && !count) {
54 break;
55 }
56
57 /* we are actually reading some data, not just finishing another chunk */
58 if (to_read) {
59 if (buf) {
60 memcpy(buf, data + ret, to_read);
61 }
62
63 for (i = 0; i < lybs->used; ++i) {
64 /* decrease all written counters */
65 lybs->written[i] -= to_read;
66 assert(lybs->written[i] <= LYB_SIZE_MAX);
67 }
68 /* decrease count/buf */
69 count -= to_read;
70 if (buf) {
71 buf += to_read;
72 }
73
74 ret += to_read;
75 }
76
77 if (empty_chunk_i > -1) {
78 /* read the next chunk meta information */
79 memcpy(meta_buf, data + ret, LYB_META_BYTES);
80 lybs->written[empty_chunk_i] = meta_buf[0];
81 lybs->inner_chunks[empty_chunk_i] = meta_buf[1];
82
83 /* remember whether there is a following chunk or not */
84 lybs->position[empty_chunk_i] = (lybs->written[empty_chunk_i] == LYB_SIZE_MAX ? 1 : 0);
85
86 ret += LYB_META_BYTES;
87 }
88 }
89
90 return ret;
91 }
92
93 static int
lyb_read_number(void * num,size_t num_size,size_t bytes,const char * data,struct lyb_state * lybs)94 lyb_read_number(void *num, size_t num_size, size_t bytes, const char *data, struct lyb_state *lybs)
95 {
96 int r, ret = 0;
97 uint64_t buf = 0;
98
99 ret += (r = lyb_read(data, (uint8_t *)&buf, bytes, lybs));
100 LYB_HAVE_READ_RETURN(r, data, -1);
101
102 /* correct byte order */
103 buf = le64toh(buf);
104
105 switch (num_size) {
106 case 1:
107 *((uint8_t *)num) = buf;
108 break;
109 case 2:
110 *((uint16_t *)num) = buf;
111 break;
112 case 4:
113 *((uint32_t *)num) = buf;
114 break;
115 case 8:
116 *((uint64_t *)num) = buf;
117 break;
118 default:
119 LOGINT(lybs->ctx);
120 return -1;
121 }
122
123 return ret;
124 }
125
126 static int
lyb_read_enum(uint64_t * enum_idx,uint32_t count,const char * data,struct lyb_state * lybs)127 lyb_read_enum(uint64_t *enum_idx, uint32_t count, const char *data, struct lyb_state *lybs)
128 {
129 size_t bytes;
130
131 if (count < (1 << 8)) {
132 bytes = 1;
133 } else if (count < (1 << 16)) {
134 bytes = 2;
135 } else if (count < (1 << 24)) {
136 bytes = 3;
137 } else {
138 bytes = 4;
139 }
140
141 /* enum is always read into a uint64_t buffer */
142 *enum_idx = 0;
143 return lyb_read_number(enum_idx, sizeof *enum_idx, bytes, data, lybs);
144 }
145
146 static int
lyb_read_string(const char * data,char ** str,int with_length,struct lyb_state * lybs)147 lyb_read_string(const char *data, char **str, int with_length, struct lyb_state *lybs)
148 {
149 int next_chunk = 0, r, ret = 0;
150 size_t len = 0, cur_len;
151
152 if (with_length) {
153 ret += (r = lyb_read_number(&len, sizeof len, 2, data, lybs));
154 LYB_HAVE_READ_GOTO(r, data, error);
155 } else {
156 /* read until the end of this subtree */
157 len = lybs->written[lybs->used - 1];
158 if (lybs->position[lybs->used - 1]) {
159 next_chunk = 1;
160 }
161 }
162
163 *str = malloc((len + 1) * sizeof **str);
164 LY_CHECK_ERR_RETURN(!*str, LOGMEM(lybs->ctx), -1);
165
166 ret += (r = lyb_read(data, (uint8_t *)*str, len, lybs));
167 LYB_HAVE_READ_GOTO(r, data, error);
168
169 while (next_chunk) {
170 cur_len = lybs->written[lybs->used - 1];
171 if (lybs->position[lybs->used - 1]) {
172 next_chunk = 1;
173 } else {
174 next_chunk = 0;
175 }
176
177 *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
178 LY_CHECK_ERR_RETURN(!*str, LOGMEM(lybs->ctx), -1);
179
180 ret += (r = lyb_read(data, ((uint8_t *)*str) + len, cur_len, lybs));
181 LYB_HAVE_READ_GOTO(r, data, error);
182
183 len += cur_len;
184 }
185
186 ((char *)*str)[len] = '\0';
187 return ret;
188
189 error:
190 free((char *)*str);
191 *str = NULL;
192 return -1;
193 }
194
195 static void
lyb_read_stop_subtree(struct lyb_state * lybs)196 lyb_read_stop_subtree(struct lyb_state *lybs)
197 {
198 if (lybs->written[lybs->used - 1]) {
199 LOGINT(lybs->ctx);
200 }
201
202 --lybs->used;
203 }
204
205 static int
lyb_read_start_subtree(const char * data,struct lyb_state * lybs)206 lyb_read_start_subtree(const char *data, struct lyb_state *lybs)
207 {
208 uint8_t meta_buf[LYB_META_BYTES];
209
210 if (lybs->used == lybs->size) {
211 lybs->size += LYB_STATE_STEP;
212 lybs->written = ly_realloc(lybs->written, lybs->size * sizeof *lybs->written);
213 lybs->position = ly_realloc(lybs->position, lybs->size * sizeof *lybs->position);
214 lybs->inner_chunks = ly_realloc(lybs->inner_chunks, lybs->size * sizeof *lybs->inner_chunks);
215 LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position || !lybs->inner_chunks, LOGMEM(lybs->ctx), -1);
216 }
217
218 memcpy(meta_buf, data, LYB_META_BYTES);
219
220 ++lybs->used;
221 lybs->written[lybs->used - 1] = meta_buf[0];
222 lybs->inner_chunks[lybs->used - 1] = meta_buf[LYB_SIZE_BYTES];
223 lybs->position[lybs->used - 1] = (lybs->written[lybs->used - 1] == LYB_SIZE_MAX ? 1 : 0);
224
225 return LYB_META_BYTES;
226 }
227
228 static int
lyb_parse_model(const char * data,const struct lys_module ** mod,int options,struct lyb_state * lybs)229 lyb_parse_model(const char *data, const struct lys_module **mod, int options, struct lyb_state *lybs)
230 {
231 int r, ret = 0;
232 char *mod_name = NULL, mod_rev[11];
233 uint16_t rev;
234
235 /* model name */
236 ret += (r = lyb_read_string(data, &mod_name, 1, lybs));
237 LYB_HAVE_READ_GOTO(r, data, error);
238
239 /* revision */
240 ret += (r = lyb_read_number(&rev, sizeof rev, 2, data, lybs));
241 LYB_HAVE_READ_GOTO(r, data, error);
242
243 if (rev) {
244 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, rev & 0x001Fu);
245 *mod = ly_ctx_get_module(lybs->ctx, mod_name, mod_rev, 0);
246 if ((options & LYD_OPT_LYB_MOD_UPDATE) && !(*mod)) {
247 /* try to use an updated module */
248 *mod = ly_ctx_get_module(lybs->ctx, mod_name, NULL, 1);
249 if (*mod && (!(*mod)->implemented || !(*mod)->rev_size || (strcmp((*mod)->rev[0].date, mod_rev) < 0))) {
250 /* not an implemented module in a newer revision */
251 *mod = NULL;
252 }
253 }
254 } else {
255 *mod = ly_ctx_get_module(lybs->ctx, mod_name, NULL, 0);
256 }
257 if (lybs->ctx->data_clb) {
258 if (!*mod) {
259 *mod = lybs->ctx->data_clb(lybs->ctx, mod_name, NULL, 0, lybs->ctx->data_clb_data);
260 } else if (!(*mod)->implemented) {
261 *mod = lybs->ctx->data_clb(lybs->ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, lybs->ctx->data_clb_data);
262 }
263 }
264
265 if (!*mod) {
266 LOGERR(lybs->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
267 mod_name, rev ? "@" : "", rev ? mod_rev : "");
268 goto error;
269 } else if (!(*mod)->implemented) {
270 LOGERR(lybs->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
271 mod_name, rev ? "@" : "", rev ? mod_rev : "");
272 goto error;
273 }
274
275 free(mod_name);
276 return ret;
277
278 error:
279 free(mod_name);
280 return -1;
281 }
282
283 static struct lyd_node *
lyb_new_node(const struct lys_node * schema,int options)284 lyb_new_node(const struct lys_node *schema, int options)
285 {
286 struct lyd_node *node;
287
288 switch (schema->nodetype) {
289 case LYS_CONTAINER:
290 case LYS_LIST:
291 case LYS_NOTIF:
292 case LYS_RPC:
293 case LYS_ACTION:
294 node = calloc(sizeof(struct lyd_node), 1);
295 break;
296 case LYS_LEAF:
297 case LYS_LEAFLIST:
298 node = calloc(sizeof(struct lyd_node_leaf_list), 1);
299 break;
300 case LYS_ANYDATA:
301 case LYS_ANYXML:
302 node = calloc(sizeof(struct lyd_node_anydata), 1);
303 break;
304 default:
305 return NULL;
306 }
307 LY_CHECK_ERR_RETURN(!node, LOGMEM(schema->module->ctx), NULL);
308
309 /* fill basic info */
310 node->schema = (struct lys_node *)schema;
311 if (resolve_applies_when(schema, 0, NULL)) {
312 node->when_status = LYD_WHEN;
313
314 if (options & LYD_OPT_TRUSTED) {
315 /* this data are considered trusted so if this node exists, it means its when must have been true */
316 node->when_status |= LYD_WHEN_TRUE;
317 }
318 }
319 node->prev = node;
320
321 return node;
322 }
323
324 static int
lyb_parse_anydata(struct lyd_node * node,const char * data,struct lyb_state * lybs)325 lyb_parse_anydata(struct lyd_node *node, const char *data, struct lyb_state *lybs)
326 {
327 int r, ret = 0;
328 char *str = NULL;
329 struct lyd_node_anydata *any = (struct lyd_node_anydata *)node;
330
331 /* read value type */
332 ret += (r = lyb_read(data, (uint8_t *)&any->value_type, sizeof any->value_type, lybs));
333 LYB_HAVE_READ_RETURN(r, data, -1);
334
335 /* read anydata content */
336 if (any->value_type == LYD_ANYDATA_DATATREE) {
337 /* invalid situation */
338 LOGINT(node->schema->module->ctx);
339 return -1;
340 } else if (any->value_type == LYD_ANYDATA_LYB) {
341 ret += (r = lyb_read_string(data, &any->value.mem, 0, lybs));
342 LYB_HAVE_READ_RETURN(r, data, -1);
343 } else {
344 ret += (r = lyb_read_string(data, &str, 0, lybs));
345 LYB_HAVE_READ_RETURN(r, data, -1);
346
347 /* add to dictionary */
348 any->value.str = lydict_insert_zc(node->schema->module->ctx, str);
349 }
350
351 return ret;
352 }
353
354 /* generally, fill lyd_val value union */
355 static int
lyb_parse_val_1(struct lys_type * type,LY_DATA_TYPE value_type,uint8_t value_flags,const char * data,const char ** value_str,lyd_val * value,struct lyb_state * lybs)356 lyb_parse_val_1(struct lys_type *type, LY_DATA_TYPE value_type, uint8_t value_flags, const char *data,
357 const char **value_str, lyd_val *value, struct lyb_state *lybs)
358 {
359 int r, ret;
360 size_t i;
361 char *str = NULL;
362 uint8_t byte;
363 uint64_t num;
364
365 if (value_flags & LY_VALUE_USER) {
366 /* just read value_str */
367 ret = lyb_read_string(data, &str, 0, lybs);
368 if (ret > -1) {
369 *value_str = lydict_insert_zc(lybs->ctx, str);
370 }
371 return ret;
372 }
373
374 /* find the correct structure, go through leafrefs and typedefs */
375 switch (value_type) {
376 case LY_TYPE_ENUM:
377 for (; type->base == LY_TYPE_LEAFREF; type = &type->info.lref.target->type);
378 for (; !type->info.enums.count; type = &type->der->type);
379 break;
380 case LY_TYPE_BITS:
381 for (; type->base == LY_TYPE_LEAFREF; type = &type->info.lref.target->type);
382 for (; !type->info.bits.count; type = &type->der->type);
383 break;
384 default:
385 break;
386 }
387
388 switch (value_type) {
389 case LY_TYPE_INST:
390 case LY_TYPE_IDENT:
391 case LY_TYPE_UNION:
392 /* we do not actually fill value now, but value_str */
393 ret = lyb_read_string(data, &str, 0, lybs);
394 if (ret > -1) {
395 *value_str = lydict_insert_zc(lybs->ctx, str);
396 }
397 break;
398 case LY_TYPE_BINARY:
399 case LY_TYPE_STRING:
400 case LY_TYPE_UNKNOWN:
401 /* read string */
402 ret = lyb_read_string(data, &str, 0, lybs);
403 if (ret > -1) {
404 value->string = lydict_insert_zc(lybs->ctx, str);
405 }
406 break;
407 case LY_TYPE_BITS:
408 value->bit = calloc(type->info.bits.count, sizeof *value->bit);
409 LY_CHECK_ERR_RETURN(!value->bit, LOGMEM(lybs->ctx), -1);
410
411 /* read values */
412 ret = 0;
413 for (i = 0; i < type->info.bits.count; ++i) {
414 if (i % 8 == 0) {
415 /* read another byte */
416 ret += (r = lyb_read(data + ret, &byte, sizeof byte, lybs));
417 if (r < 0) {
418 return -1;
419 }
420 }
421
422 if (byte & (0x01 << (i % 8))) {
423 /* bit is set */
424 value->bit[i] = &type->info.bits.bit[i];
425 }
426 }
427 break;
428 case LY_TYPE_BOOL:
429 /* read byte */
430 ret = lyb_read(data, &byte, sizeof byte, lybs);
431 if ((ret > 0) && byte) {
432 value->bln = 1;
433 }
434 break;
435 case LY_TYPE_EMPTY:
436 /* nothing to read */
437 ret = 0;
438 break;
439 case LY_TYPE_ENUM:
440 num = 0;
441 ret = lyb_read_enum(&num, type->info.enums.count, data, lybs);
442 if (ret > 0) {
443 assert(num < type->info.enums.count);
444 value->enm = &type->info.enums.enm[num];
445 }
446 break;
447 case LY_TYPE_INT8:
448 case LY_TYPE_UINT8:
449 ret = lyb_read_number(&value->uint8, sizeof value->uint8, 1, data, lybs);
450 break;
451 case LY_TYPE_INT16:
452 case LY_TYPE_UINT16:
453 ret = lyb_read_number(&value->uint16, sizeof value->uint16, 2, data, lybs);
454 break;
455 case LY_TYPE_INT32:
456 case LY_TYPE_UINT32:
457 ret = lyb_read_number(&value->uint32, sizeof value->uint32, 4, data, lybs);
458 break;
459 case LY_TYPE_DEC64:
460 case LY_TYPE_INT64:
461 case LY_TYPE_UINT64:
462 ret = lyb_read_number(&value->uint64, sizeof value->uint64, 8, data, lybs);
463 break;
464 default:
465 return -1;
466 }
467
468 return ret;
469 }
470
471 /* generally, fill value_str */
472 static int
lyb_parse_val_2(struct lys_type * type,struct lyd_node_leaf_list * leaf,struct lyd_attr * attr,struct unres_data * unres)473 lyb_parse_val_2(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, struct unres_data *unres)
474 {
475 struct ly_ctx *ctx;
476 struct lys_module *mod;
477 struct lys_type *rtype = NULL;
478 char num_str[22], *str;
479 int64_t frac, num;
480 uint32_t i, str_len;
481 uint8_t *value_flags, dig;
482 const char **value_str;
483 LY_DATA_TYPE value_type;
484 lyd_val *value;
485
486 if (leaf) {
487 ctx = leaf->schema->module->ctx;
488 mod = lys_node_module(leaf->schema);
489
490 value = &leaf->value;
491 value_str = &leaf->value_str;
492 value_flags = &leaf->value_flags;
493 value_type = leaf->value_type;
494 } else {
495 ctx = attr->annotation->module->ctx;
496 mod = lys_main_module(attr->annotation->module);
497
498 value = &attr->value;
499 value_str = &attr->value_str;
500 value_flags = &attr->value_flags;
501 value_type = attr->value_type;
502 }
503
504 if (*value_flags & LY_VALUE_USER) {
505 /* unfortunately, we need to also fill the value properly, so just parse it again */
506 *value_flags &= ~LY_VALUE_USER;
507 if (!lyp_parse_value(type, value_str, NULL, leaf, attr, NULL, 1, (leaf ? leaf->dflt : 0))) {
508 return -1;
509 }
510
511 if (!(*value_flags & LY_VALUE_USER)) {
512 LOGWRN(ctx, "Value \"%s\" was stored as a user type, but it is not in the current context.", value_str);
513 }
514 return 0;
515 }
516
517 /* we are parsing leafref/ptr union stored as the target type,
518 * so we first parse it into string and then resolve the leafref/ptr union */
519 if ((type->base == LY_TYPE_LEAFREF) || (type->base == LY_TYPE_INST)
520 || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type)) {
521 if ((value_type == LY_TYPE_INST) || (value_type == LY_TYPE_IDENT) || (value_type == LY_TYPE_UNION)) {
522 /* we already have a string */
523 goto parse_reference;
524 }
525 }
526
527 /* find the correct structure, go through leafrefs and typedefs */
528 switch (value_type) {
529 case LY_TYPE_BITS:
530 for (rtype = type; rtype->base == LY_TYPE_LEAFREF; rtype = &rtype->info.lref.target->type);
531 for (; !rtype->info.bits.count; rtype = &rtype->der->type);
532 break;
533 case LY_TYPE_DEC64:
534 for (rtype = type; rtype->base == LY_TYPE_LEAFREF; rtype = &type->info.lref.target->type);
535 break;
536 default:
537 break;
538 }
539
540 switch (value_type) {
541 case LY_TYPE_IDENT:
542 /* fill the identity pointer now */
543 value->ident = resolve_identref(type, *value_str, (struct lyd_node *)leaf, mod, (leaf ? leaf->dflt : 0));
544 if (!value->ident) {
545 return -1;
546 }
547 break;
548 case LY_TYPE_INST:
549 /* unresolved instance-identifier, keep value NULL */
550 value->instance = NULL;
551 break;
552 case LY_TYPE_BINARY:
553 case LY_TYPE_STRING:
554 case LY_TYPE_UNKNOWN:
555 /* just re-assign it */
556 *value_str = value->string;
557 break;
558 case LY_TYPE_BITS:
559 /* print the set bits */
560 str = malloc(1);
561 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
562 str[0] = '\0';
563 str_len = 0;
564 for (i = 0; i < rtype->info.bits.count; ++i) {
565 if (value->bit[i]) {
566 str = ly_realloc(str, str_len + strlen(value->bit[i]->name) + (str_len ? 1 : 0) + 1);
567 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
568
569 str_len += sprintf(str + str_len, "%s%s", str_len ? " " : "", value->bit[i]->name);
570 }
571 }
572
573 *value_str = lydict_insert_zc(ctx, str);
574 break;
575 case LY_TYPE_BOOL:
576 *value_str = lydict_insert(ctx, (value->bln ? "true" : "false"), 0);
577 break;
578 case LY_TYPE_EMPTY:
579 *value_str = lydict_insert(ctx, "", 0);
580 break;
581 case LY_TYPE_UNION:
582 if (attr) {
583 /* we do not support union type attribute */
584 LOGINT(ctx);
585 return -1;
586 }
587
588 if (resolve_union(leaf, type, 1, 2, NULL)) {
589 return -1;
590 }
591 break;
592 case LY_TYPE_ENUM:
593 /* print the value */
594 *value_str = lydict_insert(ctx, value->enm->name, 0);
595 break;
596 case LY_TYPE_INT8:
597 sprintf(num_str, "%d", value->int8);
598 *value_str = lydict_insert(ctx, num_str, 0);
599 break;
600 case LY_TYPE_UINT8:
601 sprintf(num_str, "%u", value->uint8);
602 *value_str = lydict_insert(ctx, num_str, 0);
603 break;
604 case LY_TYPE_INT16:
605 sprintf(num_str, "%d", value->int16);
606 *value_str = lydict_insert(ctx, num_str, 0);
607 break;
608 case LY_TYPE_UINT16:
609 sprintf(num_str, "%u", value->uint16);
610 *value_str = lydict_insert(ctx, num_str, 0);
611 break;
612 case LY_TYPE_INT32:
613 sprintf(num_str, "%d", value->int32);
614 *value_str = lydict_insert(ctx, num_str, 0);
615 break;
616 case LY_TYPE_UINT32:
617 sprintf(num_str, "%u", value->uint32);
618 *value_str = lydict_insert(ctx, num_str, 0);
619 break;
620 case LY_TYPE_INT64:
621 sprintf(num_str, "%"PRId64, value->int64);
622 *value_str = lydict_insert(ctx, num_str, 0);
623 break;
624 case LY_TYPE_UINT64:
625 sprintf(num_str, "%"PRIu64, value->uint64);
626 *value_str = lydict_insert(ctx, num_str, 0);
627 break;
628 case LY_TYPE_DEC64:
629 num = value->dec64 / (int64_t)rtype->info.dec64.div;
630 frac = value->dec64 % (int64_t)rtype->info.dec64.div;
631 dig = rtype->info.dec64.dig;
632
633 /* frac should always be positive, remove trailing zeros */
634 if (frac < 0) {
635 frac *= -1;
636 }
637 while ((dig > 1) && !(frac % 10)) {
638 frac /= 10;
639 --dig;
640 }
641
642 /* handle special case of int64_t not supporting printing -0 */
643 sprintf(num_str, "%s%"PRId64".%.*"PRId64, (num == 0) && (value->dec64 < 0) ? "-" : "", num, dig, frac);
644 *value_str = lydict_insert(ctx, num_str, 0);
645 break;
646 default:
647 return -1;
648 }
649
650 if ((type->base == LY_TYPE_LEAFREF) || (type->base == LY_TYPE_INST)
651 || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type)) {
652 parse_reference:
653 assert(*value_str);
654
655 if (attr) {
656 /* we do not support reference types of attributes */
657 LOGINT(ctx);
658 return -1;
659 }
660
661 if (type->base == LY_TYPE_INST) {
662 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_INSTID)) {
663 return -1;
664 }
665 } else if (type->base == LY_TYPE_LEAFREF) {
666 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_LEAFREF)) {
667 return -1;
668 }
669 } else {
670 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_UNION)) {
671 return -1;
672 }
673 }
674 }
675
676 return 0;
677 }
678
679 static int
lyb_parse_value(struct lys_type * type,struct lyd_node_leaf_list * leaf,struct lyd_attr * attr,const char * data,struct unres_data * unres,struct lyb_state * lybs)680 lyb_parse_value(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, const char *data,
681 struct unres_data *unres, struct lyb_state *lybs)
682 {
683 int r, ret = 0;
684 uint8_t start_byte;
685
686 const char **value_str;
687 lyd_val *value;
688 LY_DATA_TYPE *value_type;
689 uint8_t *value_flags;
690
691 assert((leaf || attr) && (!leaf || !attr));
692
693 if (leaf) {
694 value_str = &leaf->value_str;
695 value = &leaf->value;
696 value_type = &leaf->value_type;
697 value_flags = &leaf->value_flags;
698 } else {
699 value_str = &attr->value_str;
700 value = &attr->value;
701 value_type = &attr->value_type;
702 value_flags = &attr->value_flags;
703 }
704
705 /* read value type and flags on the first byte */
706 ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
707 LYB_HAVE_READ_RETURN(r, data, -1);
708
709 /* fill value type, flags */
710 *value_type = start_byte & 0x1F;
711 if (start_byte & 0x80) {
712 assert(leaf);
713 leaf->dflt = 1;
714 }
715 if (start_byte & 0x40) {
716 *value_flags |= LY_VALUE_USER;
717 }
718 if (start_byte & 0x20) {
719 *value_flags |= LY_VALUE_UNRES;
720 }
721
722 ret += (r = lyb_parse_val_1(type, *value_type, *value_flags, data, value_str, value, lybs));
723 LYB_HAVE_READ_RETURN(r, data, -1);
724
725 /* union is handled specially */
726 if ((type->base == LY_TYPE_UNION) && !(*value_flags & LY_VALUE_USER)) {
727 assert(*value_type == LY_TYPE_STRING);
728
729 *value_str = value->string;
730 value->string = NULL;
731 *value_type = LY_TYPE_UNION;
732 }
733
734 ret += (r = lyb_parse_val_2(type, leaf, attr, unres));
735 LYB_HAVE_READ_RETURN(r, data, -1);
736
737 return ret;
738 }
739
740 static int
lyb_parse_attr_name(const struct lys_module * mod,const char * data,struct lys_ext_instance_complex ** ext,int options,struct lyb_state * lybs)741 lyb_parse_attr_name(const struct lys_module *mod, const char *data, struct lys_ext_instance_complex **ext, int options,
742 struct lyb_state *lybs)
743 {
744 int r, ret = 0, pos, i, j, k;
745 const struct lys_submodule *submod = NULL;
746 char *attr_name = NULL;
747
748 /* attr name */
749 ret += (r = lyb_read_string(data, &attr_name, 1, lybs));
750 LYB_HAVE_READ_RETURN(r, data, -1);
751
752 /* search module */
753 pos = -1;
754 for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
755 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
756 if (j == -1) {
757 break;
758 }
759 if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
760 pos = i + j;
761 break;
762 }
763 }
764
765 /* try submodules */
766 if (pos == -1) {
767 for (k = 0; k < mod->inc_size; ++k) {
768 submod = mod->inc[k].submodule;
769 for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
770 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
771 if (j == -1) {
772 break;
773 }
774 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
775 pos = i + j;
776 break;
777 }
778 }
779 }
780 }
781
782 if (pos == -1) {
783 *ext = NULL;
784 } else {
785 *ext = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] : (struct lys_ext_instance_complex *)mod->ext[pos];
786 }
787
788 if (!*ext && (options & LYD_OPT_STRICT)) {
789 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find annotation \"%s\" in \"%s\".", attr_name, mod->name);
790 free(attr_name);
791 return -1;
792 }
793
794 free(attr_name);
795 return ret;
796 }
797
798 static int
lyb_parse_attributes(struct lyd_node * node,const char * data,int options,struct unres_data * unres,struct lyb_state * lybs)799 lyb_parse_attributes(struct lyd_node *node, const char *data, int options, struct unres_data *unres, struct lyb_state *lybs)
800 {
801 int r, ret = 0;
802 uint8_t i, count = 0;
803 const struct lys_module *mod;
804 struct lys_type **type;
805 struct lyd_attr *attr = NULL;
806 struct lys_ext_instance_complex *ext;
807
808 /* read number of attributes stored */
809 ret += (r = lyb_read(data, &count, 1, lybs));
810 LYB_HAVE_READ_GOTO(r, data, error);
811
812 /* read attributes */
813 for (i = 0; i < count; ++i) {
814 ret += (r = lyb_read_start_subtree(data, lybs));
815 LYB_HAVE_READ_GOTO(r, data, error);
816
817 /* find model */
818 ret += (r = lyb_parse_model(data, &mod, options, lybs));
819 LYB_HAVE_READ_GOTO(r, data, error);
820
821 if (mod) {
822 /* annotation name */
823 ret += (r = lyb_parse_attr_name(mod, data, &ext, options, lybs));
824 LYB_HAVE_READ_GOTO(r, data, error);
825 }
826
827 if (!mod || !ext) {
828 /* unknown attribute, skip it */
829 do {
830 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
831 LYB_HAVE_READ_GOTO(r, data, error);
832 } while (lybs->written[lybs->used - 1]);
833 goto stop_subtree;
834 }
835
836 /* allocate new attribute */
837 if (!attr) {
838 assert(!node->attr);
839
840 attr = calloc(1, sizeof *attr);
841 LY_CHECK_ERR_GOTO(!attr, LOGMEM(lybs->ctx), error);
842
843 node->attr = attr;
844 } else {
845 attr->next = calloc(1, sizeof *attr);
846 LY_CHECK_ERR_GOTO(!attr->next, LOGMEM(lybs->ctx), error);
847
848 attr = attr->next;
849 }
850
851 /* attribute annotation */
852 attr->annotation = ext;
853
854 /* attribute name */
855 attr->name = lydict_insert(lybs->ctx, attr->annotation->arg_value, 0);
856
857 /* get the type */
858 type = (struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, attr->annotation, NULL);
859 if (!type || !(*type)) {
860 goto error;
861 }
862
863 /* attribute value */
864 ret += (r = lyb_parse_value(*type, NULL, attr, data, unres, lybs));
865 LYB_HAVE_READ_GOTO(r, data, error);
866
867 stop_subtree:
868 lyb_read_stop_subtree(lybs);
869 }
870
871 return ret;
872
873 error:
874 lyd_free_attr(lybs->ctx, node, node->attr, 1);
875 return -1;
876 }
877
878 static int
lyb_is_schema_hash_match(struct lys_node * sibling,LYB_HASH * hash,uint8_t hash_count)879 lyb_is_schema_hash_match(struct lys_node *sibling, LYB_HASH *hash, uint8_t hash_count)
880 {
881 LYB_HASH sibling_hash;
882 uint8_t i;
883
884 /* compare all the hashes starting from collision ID 0 */
885 for (i = 0; i < hash_count; ++i) {
886 sibling_hash = lyb_hash(sibling, i);
887 if (sibling_hash != hash[i]) {
888 return 0;
889 }
890 }
891
892 return 1;
893 }
894
895 static int
lyb_parse_schema_hash(const struct lys_node * sparent,const struct lys_module * mod,const char * data,const char * yang_data_name,int options,struct lys_node ** snode,struct lyb_state * lybs)896 lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data, const char *yang_data_name,
897 int options, struct lys_node **snode, struct lyb_state *lybs)
898 {
899 int r, ret = 0;
900 uint8_t i, j;
901 struct lys_node *sibling;
902 LYB_HASH hash[LYB_HASH_BITS - 1];
903
904 assert((sparent || mod) && (!sparent || !mod));
905
906 /* read the first hash */
907 ret += (r = lyb_read(data, &hash[0], sizeof *hash, lybs));
908 LYB_HAVE_READ_RETURN(r, data, -1);
909
910 /* based on the first hash read all the other ones, if any */
911 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
912 if (i > LYB_HASH_BITS) {
913 return -1;
914 }
915 }
916
917 /* move the first hash on its accurate position */
918 hash[i] = hash[0];
919
920 /* read the rest of hashes */
921 for (j = i; j; --j) {
922 ret += (r = lyb_read(data, &hash[j - 1], sizeof *hash, lybs));
923 LYB_HAVE_READ_RETURN(r, data, -1);
924
925 /* correct collision ID */
926 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
927 /* preceded with zeros */
928 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
929 }
930
931 /* handle yang data templates */
932 if ((options & LYD_OPT_DATA_TEMPLATE) && yang_data_name && mod) {
933 sparent = lyp_get_yang_data_template(mod, yang_data_name, strlen(yang_data_name));
934 if (!sparent) {
935 sibling = NULL;
936 goto finish;
937 }
938 }
939
940 /* handle RPC/action input/output */
941 if (sparent && (sparent->nodetype & (LYS_RPC | LYS_ACTION))) {
942 sibling = NULL;
943 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, NULL, LYS_GETNEXT_WITHINOUT))) {
944 if ((sibling->nodetype == LYS_INPUT) && (options & LYD_OPT_RPC)) {
945 break;
946 }
947 if ((sibling->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPCREPLY)) {
948 break;
949 }
950 }
951 if (!sibling) {
952 /* fail */
953 goto finish;
954 }
955
956 /* use only input/output children nodes */
957 sparent = sibling;
958 }
959
960 /* find our node with matching hashes */
961 sibling = NULL;
962 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, mod, 0))) {
963 /* skip schema nodes from models not present during printing */
964 if (lyb_has_schema_model(sibling, lybs->models, lybs->mod_count) && lyb_is_schema_hash_match(sibling, hash, i + 1)) {
965 /* match found */
966 break;
967 }
968 }
969
970 finish:
971 *snode = sibling;
972 if (!sibling && (options & LYD_OPT_STRICT)) {
973 if (mod) {
974 LOGVAL(lybs->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".",
975 mod->name);
976 } else {
977 LOGVAL(lybs->ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".",
978 sparent->name);
979 }
980 return -1;
981 }
982
983 return ret;
984 }
985
986 static int
lyb_skip_subtree(const char * data,struct lyb_state * lybs)987 lyb_skip_subtree(const char *data, struct lyb_state *lybs)
988 {
989 int r, ret = 0;
990
991 do {
992 /* first skip any meta information inside */
993 r = lybs->inner_chunks[lybs->used - 1] * LYB_META_BYTES;
994 data += r;
995 ret += r;
996
997 /* then read data */
998 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
999 LYB_HAVE_READ_RETURN(r, data, -1);
1000 } while (lybs->written[lybs->used - 1]);
1001
1002 return ret;
1003 }
1004
1005 static int
lyb_parse_subtree(const char * data,struct lyd_node * parent,struct lyd_node ** first_sibling,const char * yang_data_name,int options,struct unres_data * unres,struct lyb_state * lybs)1006 lyb_parse_subtree(const char *data, struct lyd_node *parent, struct lyd_node **first_sibling, const char *yang_data_name,
1007 int options, struct unres_data *unres, struct lyb_state *lybs)
1008 {
1009 int r, ret = 0;
1010 struct lyd_node *node = NULL, *iter;
1011 const struct lys_module *mod;
1012 struct lys_node *snode;
1013
1014 assert((parent && !first_sibling) || (!parent && first_sibling));
1015
1016 /* register a new subtree */
1017 ret += (r = lyb_read_start_subtree(data, lybs));
1018 LYB_HAVE_READ_GOTO(r, data, error);
1019
1020 if (!parent) {
1021 /* top-level, read module name */
1022 ret += (r = lyb_parse_model(data, &mod, options, lybs));
1023 LYB_HAVE_READ_GOTO(r, data, error);
1024
1025 if (mod) {
1026 /* read hash, find the schema node starting from mod, possibly yang_data_name */
1027 r = lyb_parse_schema_hash(NULL, mod, data, yang_data_name, options, &snode, lybs);
1028 }
1029 } else {
1030 mod = lyd_node_module(parent);
1031
1032 /* read hash, find the schema node starting from parent schema */
1033 r = lyb_parse_schema_hash(parent->schema, NULL, data, NULL, options, &snode, lybs);
1034 }
1035 ret += r;
1036 LYB_HAVE_READ_GOTO(r, data, error);
1037
1038 if (!mod || !snode) {
1039 /* unknown data subtree, skip it whole */
1040 ret += (r = lyb_skip_subtree(data, lybs));
1041 LYB_HAVE_READ_GOTO(r, data, error);
1042 goto stop_subtree;
1043 }
1044
1045 /*
1046 * read the node
1047 */
1048 node = lyb_new_node(snode, options);
1049 if (!node) {
1050 goto error;
1051 }
1052
1053 ret += (r = lyb_parse_attributes(node, data, options, unres, lybs));
1054 LYB_HAVE_READ_GOTO(r, data, error);
1055
1056 /* read node content */
1057 switch (snode->nodetype) {
1058 case LYS_CONTAINER:
1059 case LYS_LIST:
1060 case LYS_NOTIF:
1061 case LYS_RPC:
1062 case LYS_ACTION:
1063 /* nothing to read */
1064 break;
1065 case LYS_LEAF:
1066 case LYS_LEAFLIST:
1067 ret += (r = lyb_parse_value(&((struct lys_node_leaf *)node->schema)->type, (struct lyd_node_leaf_list *)node,
1068 NULL, data, unres, lybs));
1069 LYB_HAVE_READ_GOTO(r, data, error);
1070 break;
1071 case LYS_ANYXML:
1072 case LYS_ANYDATA:
1073 ret += (r = lyb_parse_anydata(node, data, lybs));
1074 LYB_HAVE_READ_GOTO(r, data, error);
1075 break;
1076 default:
1077 goto error;
1078 }
1079
1080 /* insert into data tree, manually */
1081 if (parent) {
1082 if (!parent->child) {
1083 /* only child */
1084 parent->child = node;
1085 } else {
1086 /* last child */
1087 parent->child->prev->next = node;
1088 node->prev = parent->child->prev;
1089 parent->child->prev = node;
1090 }
1091 node->parent = parent;
1092 } else if (*first_sibling) {
1093 /* last sibling */
1094 (*first_sibling)->prev->next = node;
1095 node->prev = (*first_sibling)->prev;
1096 (*first_sibling)->prev = node;
1097 } else {
1098 /* only sibling */
1099 *first_sibling = node;
1100 }
1101
1102 /* read all descendants */
1103 while (lybs->written[lybs->used - 1]) {
1104 ret += (r = lyb_parse_subtree(data, node, NULL, NULL, options, unres, lybs));
1105 LYB_HAVE_READ_GOTO(r, data, error);
1106 }
1107
1108 /* make containers default if should be */
1109 if ((node->schema->nodetype == LYS_CONTAINER) && !((struct lys_node_container *)node->schema)->presence) {
1110 LY_TREE_FOR(node->child, iter) {
1111 if (!iter->dflt) {
1112 break;
1113 }
1114 }
1115
1116 if (!iter) {
1117 node->dflt = 1;
1118 }
1119 }
1120
1121 #ifdef LY_ENABLED_CACHE
1122 /* calculate the hash and insert it into parent (list with keys is handled when its keys are inserted) */
1123 if ((node->schema->nodetype != LYS_LIST) || !((struct lys_node_list *)node->schema)->keys_size) {
1124 lyd_hash(node);
1125 lyd_insert_hash(node);
1126 }
1127 #endif
1128
1129 stop_subtree:
1130 /* end the subtree */
1131 lyb_read_stop_subtree(lybs);
1132
1133 return ret;
1134
1135 error:
1136 lyd_free(node);
1137 if (first_sibling && (*first_sibling == node)) {
1138 *first_sibling = NULL;
1139 }
1140 return -1;
1141 }
1142
1143 static int
lyb_parse_data_models(const char * data,int options,struct lyb_state * lybs)1144 lyb_parse_data_models(const char *data, int options, struct lyb_state *lybs)
1145 {
1146 int i, r, ret = 0;
1147
1148 /* read model count */
1149 ret += (r = lyb_read_number(&lybs->mod_count, sizeof lybs->mod_count, 2, data, lybs));
1150 LYB_HAVE_READ_RETURN(r, data, -1);
1151
1152 if (lybs->mod_count) {
1153 lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
1154 LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(lybs->ctx), -1);
1155
1156 /* read modules */
1157 for (i = 0; i < lybs->mod_count; ++i) {
1158 ret += (r = lyb_parse_model(data, &lybs->models[i], options, lybs));
1159 LYB_HAVE_READ_RETURN(r, data, -1);
1160 }
1161 }
1162
1163 return ret;
1164 }
1165
1166 static int
lyb_parse_magic_number(const char * data,struct lyb_state * lybs)1167 lyb_parse_magic_number(const char *data, struct lyb_state *lybs)
1168 {
1169 int r, ret = 0;
1170 char magic_byte = 0;
1171
1172 ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1173 LYB_HAVE_READ_RETURN(r, data, -1);
1174 if (magic_byte != 'l') {
1175 LOGERR(lybs->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
1176 return -1;
1177 }
1178
1179 ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1180 LYB_HAVE_READ_RETURN(r, data, -1);
1181 if (magic_byte != 'y') {
1182 LOGERR(lybs->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
1183 return -1;
1184 }
1185
1186 ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1187 LYB_HAVE_READ_RETURN(r, data, -1);
1188 if (magic_byte != 'b') {
1189 LOGERR(lybs->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
1190 return -1;
1191 }
1192
1193 return ret;
1194 }
1195
1196 static int
lyb_parse_header(const char * data,struct lyb_state * lybs)1197 lyb_parse_header(const char *data, struct lyb_state *lybs)
1198 {
1199 int ret = 0;
1200 uint8_t byte = 0;
1201
1202 /* TODO version, any flags? */
1203 ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
1204
1205 return ret;
1206 }
1207
1208 struct lyd_node *
lyd_parse_lyb(struct ly_ctx * ctx,const char * data,int options,const struct lyd_node * data_tree,const char * yang_data_name,int * parsed)1209 lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *data_tree,
1210 const char *yang_data_name, int *parsed)
1211 {
1212 int r = 0, ret = 0;
1213 struct lyd_node *node = NULL, *next, *act_notif = NULL;
1214 struct unres_data *unres = NULL;
1215 struct lyb_state lybs;
1216
1217 if (!ctx || !data) {
1218 LOGARG;
1219 return NULL;
1220 }
1221
1222 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1223 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
1224 lybs.inner_chunks = malloc(LYB_STATE_STEP * sizeof *lybs.inner_chunks);
1225 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position || !lybs.inner_chunks, LOGMEM(ctx), finish);
1226 lybs.used = 0;
1227 lybs.size = LYB_STATE_STEP;
1228 lybs.models = NULL;
1229 lybs.mod_count = 0;
1230 lybs.ctx = ctx;
1231
1232 unres = calloc(1, sizeof *unres);
1233 LY_CHECK_ERR_GOTO(!unres, LOGMEM(ctx), finish);
1234
1235 /* read magic number */
1236 ret += (r = lyb_parse_magic_number(data, &lybs));
1237 LYB_HAVE_READ_GOTO(r, data, finish);
1238
1239 /* read header */
1240 ret += (r = lyb_parse_header(data, &lybs));
1241 LYB_HAVE_READ_GOTO(r, data, finish);
1242
1243 /* read used models */
1244 ret += (r = lyb_parse_data_models(data, options, &lybs));
1245 LYB_HAVE_READ_GOTO(r, data, finish);
1246
1247 /* read subtree(s) */
1248 while (data[0]) {
1249 ret += (r = lyb_parse_subtree(data, NULL, &node, yang_data_name, options, unres, &lybs));
1250 if (r < 0) {
1251 lyd_free_withsiblings(node);
1252 node = NULL;
1253 goto finish;
1254 }
1255 data += r;
1256 }
1257
1258 /* read the last zero, parsing finished */
1259 ++ret;
1260 r = ret;
1261
1262 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1263 if (lyd_merge(node, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
1264 LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
1265 lyd_free_withsiblings(node);
1266 node = NULL;
1267 goto finish;
1268 }
1269 }
1270
1271 /* resolve any unresolved instance-identifiers */
1272 if (unres->count) {
1273 if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
1274 LY_TREE_DFS_BEGIN(node, next, act_notif) {
1275 if (act_notif->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1276 break;
1277 }
1278 LY_TREE_DFS_END(node, next, act_notif);
1279 }
1280 }
1281 if (lyd_defaults_add_unres(&node, options, ctx, NULL, 0, data_tree, act_notif, unres, 0)) {
1282 lyd_free_withsiblings(node);
1283 node = NULL;
1284 goto finish;
1285 }
1286 }
1287
1288 finish:
1289 free(lybs.written);
1290 free(lybs.position);
1291 free(lybs.inner_chunks);
1292 free(lybs.models);
1293 if (unres) {
1294 free(unres->node);
1295 free(unres->type);
1296 free(unres);
1297 }
1298
1299 if (parsed) {
1300 *parsed = r;
1301 }
1302 return node;
1303 }
1304
1305 API int
lyd_lyb_data_length(const char * data)1306 lyd_lyb_data_length(const char *data)
1307 {
1308 FUN_IN;
1309
1310 struct lyb_state lybs;
1311 int r = 0, ret = 0, i;
1312 size_t len;
1313 uint8_t buf[LYB_SIZE_MAX];
1314
1315 if (!data) {
1316 return -1;
1317 }
1318
1319 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1320 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
1321 lybs.inner_chunks = malloc(LYB_STATE_STEP * sizeof *lybs.inner_chunks);
1322 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position || !lybs.inner_chunks, LOGMEM(NULL), finish);
1323 lybs.used = 0;
1324 lybs.size = LYB_STATE_STEP;
1325 lybs.models = NULL;
1326 lybs.mod_count = 0;
1327 lybs.ctx = NULL;
1328
1329 /* read magic number */
1330 ret += (r = lyb_parse_magic_number(data, &lybs));
1331 LYB_HAVE_READ_GOTO(r, data, finish);
1332
1333 /* read header */
1334 ret += (r = lyb_parse_header(data, &lybs));
1335 LYB_HAVE_READ_GOTO(r, data, finish);
1336
1337 /* read model count */
1338 ret += (r = lyb_read_number(&lybs.mod_count, sizeof lybs.mod_count, 2, data, &lybs));
1339 LYB_HAVE_READ_GOTO(r, data, finish);
1340
1341 /* read all models */
1342 for (i = 0; i < lybs.mod_count; ++i) {
1343 /* module name length */
1344 len = 0;
1345 ret += (r = lyb_read_number(&len, sizeof len, 2, data, &lybs));
1346 LYB_HAVE_READ_GOTO(r, data, finish);
1347
1348 /* model name */
1349 ret += (r = lyb_read(data, buf, len, &lybs));
1350 LYB_HAVE_READ_GOTO(r, data, finish);
1351
1352 /* revision */
1353 ret += (r = lyb_read(data, buf, 2, &lybs));
1354 LYB_HAVE_READ_GOTO(r, data, finish);
1355 }
1356
1357 while (data[0]) {
1358 /* register a new subtree */
1359 ret += (r = lyb_read_start_subtree(data, &lybs));
1360 LYB_HAVE_READ_GOTO(r, data, finish);
1361
1362 /* skip it */
1363 ret += (r = lyb_skip_subtree(data, &lybs));
1364 LYB_HAVE_READ_GOTO(r, data, finish);
1365
1366 /* subtree finished */
1367 lyb_read_stop_subtree(&lybs);
1368 }
1369
1370 /* read the last zero, parsing finished */
1371 ++ret;
1372
1373 finish:
1374 free(lybs.written);
1375 free(lybs.position);
1376 free(lybs.inner_chunks);
1377 free(lybs.models);
1378 return ret;
1379 }
1380