blob: 2756bb72868d196b500f5c3fe80a7163ee7e9ee7 [file] [log] [blame]
Michal Vasko60ea6352020-06-29 13:39:39 +02001/**
2 * @file parser_lyb.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief LYB data parser for libyang
5 *
6 * Copyright (c) 2020 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 "lyb.h"
16
17#include <assert.h>
Radek Krejciad97c5f2020-06-30 09:19:28 +020018#include <stdint.h>
Michal Vasko60ea6352020-06-29 13:39:39 +020019#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include "common.h"
24#include "compat.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020025#include "context.h"
26#include "dict.h"
Radek Krejci47fab892020-11-05 17:02:41 +010027#include "hash_table.h"
28#include "in.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020029#include "in_internal.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020030#include "log.h"
Radek Krejci7931b192020-06-25 17:05:03 +020031#include "parser_data.h"
32#include "parser_internal.h"
Radek Krejci77114102021-03-10 15:21:57 +010033#include "set.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020034#include "tree.h"
Radek Krejci47fab892020-11-05 17:02:41 +010035#include "tree_data.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020036#include "tree_data_internal.h"
Radek Krejci859a15a2021-03-05 20:56:59 +010037#include "tree_edit.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020038#include "tree_schema.h"
39#include "validation.h"
Michal Vasko6b5cb2a2020-11-11 19:11:21 +010040#include "xml.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020041
Michal Vasko02ed9d82021-07-15 14:58:04 +020042static LY_ERR _lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
43 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
44 struct ly_set *parsed, struct lyd_ctx **lydctx_p);
45
Radek Krejci1798aae2020-07-14 13:26:06 +020046void
47lylyb_ctx_free(struct lylyb_ctx *ctx)
48{
49 LY_ARRAY_COUNT_TYPE u;
50
51 LY_ARRAY_FREE(ctx->subtrees);
52 LY_ARRAY_FREE(ctx->models);
53
54 LY_ARRAY_FOR(ctx->sib_hts, u) {
55 lyht_free(ctx->sib_hts[u].ht);
56 }
57 LY_ARRAY_FREE(ctx->sib_hts);
58
59 free(ctx);
60}
61
62void
63lyd_lyb_ctx_free(struct lyd_ctx *lydctx)
64{
65 struct lyd_lyb_ctx *ctx = (struct lyd_lyb_ctx *)lydctx;
66
67 lyd_ctx_free(lydctx);
68 lylyb_ctx_free(ctx->lybctx);
69 free(ctx);
70}
71
Michal Vasko60ea6352020-06-29 13:39:39 +020072/**
73 * @brief Read YANG data from LYB input. Metadata are handled transparently and not returned.
74 *
75 * @param[in] buf Destination buffer.
76 * @param[in] count Number of bytes to read.
77 * @param[in] lybctx LYB context.
78 */
79static void
Radek Krejci1798aae2020-07-14 13:26:06 +020080lyb_read(uint8_t *buf, size_t count, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +020081{
Michal Vaskofd69e1d2020-07-03 11:57:17 +020082 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +020083 struct lyd_lyb_subtree *empty;
84 size_t to_read;
85 uint8_t meta_buf[LYB_META_BYTES];
86
87 assert(lybctx);
88
89 while (1) {
90 /* check for fully-read (empty) data chunks */
91 to_read = count;
92 empty = NULL;
93 LY_ARRAY_FOR(lybctx->subtrees, u) {
94 /* we want the innermost chunks resolved first, so replace previous empty chunks,
95 * also ignore chunks that are completely finished, there is nothing for us to do */
96 if ((lybctx->subtrees[u].written <= to_read) && lybctx->subtrees[u].position) {
97 /* empty chunk, do not read more */
98 to_read = lybctx->subtrees[u].written;
99 empty = &lybctx->subtrees[u];
100 }
101 }
102
103 if (!empty && !count) {
104 break;
105 }
106
107 /* we are actually reading some data, not just finishing another chunk */
108 if (to_read) {
109 if (buf) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200110 ly_in_read(lybctx->in, buf, to_read);
111 } else {
112 ly_in_skip(lybctx->in, to_read);
Michal Vasko60ea6352020-06-29 13:39:39 +0200113 }
114
115 LY_ARRAY_FOR(lybctx->subtrees, u) {
116 /* decrease all written counters */
117 lybctx->subtrees[u].written -= to_read;
118 assert(lybctx->subtrees[u].written <= LYB_SIZE_MAX);
119 }
120 /* decrease count/buf */
121 count -= to_read;
122 if (buf) {
123 buf += to_read;
124 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200125 }
126
127 if (empty) {
128 /* read the next chunk meta information */
Michal Vasko63f3d842020-07-08 10:10:14 +0200129 ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +0200130 empty->written = meta_buf[0];
131 empty->inner_chunks = meta_buf[1];
132
133 /* remember whether there is a following chunk or not */
134 empty->position = (empty->written == LYB_SIZE_MAX ? 1 : 0);
Michal Vasko60ea6352020-06-29 13:39:39 +0200135 }
136 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200137}
138
139/**
140 * @brief Read a number.
141 *
142 * @param[in] num Destination buffer.
143 * @param[in] num_size Size of @p num.
144 * @param[in] bytes Number of bytes to read.
145 * @param[in] lybctx LYB context.
146 */
147static void
Radek Krejci1798aae2020-07-14 13:26:06 +0200148lyb_read_number(void *num, size_t num_size, size_t bytes, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200149{
150 uint64_t buf = 0;
151
152 lyb_read((uint8_t *)&buf, bytes, lybctx);
153
154 /* correct byte order */
155 buf = le64toh(buf);
156
157 switch (num_size) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100158 case sizeof(uint8_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200159 *((uint8_t *)num) = buf;
160 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100161 case sizeof(uint16_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200162 *((uint16_t *)num) = buf;
163 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100164 case sizeof(uint32_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200165 *((uint32_t *)num) = buf;
166 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100167 case sizeof(uint64_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200168 *((uint64_t *)num) = buf;
169 break;
170 default:
171 LOGINT(lybctx->ctx);
172 }
173}
174
175/**
176 * @brief Read a string.
177 *
178 * @param[in] str Destination buffer, is allocated.
179 * @param[in] with_length Whether the string is preceded with its length or it ends at the end of this subtree.
180 * @param[in] lybctx LYB context.
181 * @return LY_ERR value.
182 */
183static LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +0200184lyb_read_string(char **str, ly_bool with_length, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200185{
Radek Krejci857189e2020-09-01 13:26:36 +0200186 ly_bool next_chunk = 0;
Michal Vasko60ea6352020-06-29 13:39:39 +0200187 size_t len = 0, cur_len;
188
189 *str = NULL;
190
191 if (with_length) {
192 lyb_read_number(&len, sizeof len, 2, lybctx);
193 } else {
194 /* read until the end of this subtree */
195 len = LYB_LAST_SUBTREE(lybctx).written;
196 if (LYB_LAST_SUBTREE(lybctx).position) {
197 next_chunk = 1;
198 }
199 }
200
201 *str = malloc((len + 1) * sizeof **str);
202 LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
203
204 lyb_read((uint8_t *)*str, len, lybctx);
205
206 while (next_chunk) {
207 cur_len = LYB_LAST_SUBTREE(lybctx).written;
208 if (LYB_LAST_SUBTREE(lybctx).position) {
209 next_chunk = 1;
210 } else {
211 next_chunk = 0;
212 }
213
214 *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
215 LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
216
217 lyb_read(((uint8_t *)*str) + len, cur_len, lybctx);
218
219 len += cur_len;
220 }
221
Michal Vaskocebbae52021-05-31 11:11:36 +0200222 (*str)[len] = '\0';
Michal Vasko60ea6352020-06-29 13:39:39 +0200223 return LY_SUCCESS;
224}
225
226/**
aPiecekea304e32021-08-18 09:13:47 +0200227 * @brief Read the term node.
228 *
aPiecekaa5b70a2021-08-30 08:33:25 +0200229 * @param[in] term Compiled term node.
aPiecekea304e32021-08-18 09:13:47 +0200230 * @param[out] term_value Set to term node value in dynamically
231 * allocated memory. The caller must release it.
232 * @param[out] term_value_len Value length in bytes. The zero byte is
233 * always included and is not counted.
234 * @param[in,out] lybctx LYB context.
235 * @return LY_ERR value.
236 */
237static LY_ERR
aPiecekaa5b70a2021-08-30 08:33:25 +0200238lyb_read_term(const struct lysc_node_leaf *term, uint8_t **term_value,
239 uint32_t *term_value_len, struct lylyb_ctx *lybctx)
aPiecekea304e32021-08-18 09:13:47 +0200240{
241 uint32_t allocated_size;
aPiecekaa5b70a2021-08-30 08:33:25 +0200242 int32_t lyb_data_len;
243 struct lysc_type_leafref *type_lf;
aPiecekea304e32021-08-18 09:13:47 +0200244
aPiecekaa5b70a2021-08-30 08:33:25 +0200245 assert(term && term_value && term_value_len && lybctx);
aPiecekea304e32021-08-18 09:13:47 +0200246
aPiecekaa5b70a2021-08-30 08:33:25 +0200247 /* Find out the size from @ref howtoDataLYB. */
248 if (term->type->basetype == LY_TYPE_LEAFREF) {
249 /* Leafref itself is ignored, the target is loaded directly. */
250 type_lf = (struct lysc_type_leafref *)term->type;
251 lyb_data_len = type_lf->realtype->plugin->lyb_data_len;
252 } else {
253 lyb_data_len = term->type->plugin->lyb_data_len;
254 }
255
256 if (lyb_data_len < 0) {
257 /* Parse value size. */
258 lyb_read_number(term_value_len, sizeof *term_value_len,
259 sizeof *term_value_len, lybctx);
260 } else {
261 /* Data size is fixed. */
262 *term_value_len = lyb_data_len;
263 }
aPiecekea304e32021-08-18 09:13:47 +0200264
265 /* Allocate memory. */
266 allocated_size = *term_value_len + 1;
267 *term_value = malloc(allocated_size * sizeof **term_value);
268 LY_CHECK_ERR_RET(!*term_value, LOGMEM(lybctx->ctx), LY_EMEM);
269
270 if (*term_value_len > 0) {
271 /* Parse value. */
272 lyb_read(*term_value, *term_value_len, lybctx);
273 }
274
275 /* Add extra zero byte regardless of whether it is string or not. */
276 (*term_value)[allocated_size - 1] = 0;
277
278 return LY_SUCCESS;
279}
280
281/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200282 * @brief Stop the current subtree - change LYB context state.
283 *
284 * @param[in] lybctx LYB context.
285 * @return LY_ERR value.
286 */
287static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200288lyb_read_stop_subtree(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200289{
290 if (LYB_LAST_SUBTREE(lybctx).written) {
291 LOGINT_RET(lybctx->ctx);
292 }
293
294 LY_ARRAY_DECREMENT(lybctx->subtrees);
295 return LY_SUCCESS;
296}
297
298/**
299 * @brief Start a new subtree - change LYB context state but also read the expected metadata.
300 *
301 * @param[in] lybctx LYB context.
302 * @return LY_ERR value.
303 */
304static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200305lyb_read_start_subtree(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200306{
307 uint8_t meta_buf[LYB_META_BYTES];
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200308 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200309
Radek Krejcic7d13e32020-12-09 12:32:24 +0100310 u = LY_ARRAY_COUNT(lybctx->subtrees);
Michal Vasko60ea6352020-06-29 13:39:39 +0200311 if (u == lybctx->subtree_size) {
312 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->subtrees, u + LYB_SUBTREE_STEP, LY_EMEM);
313 lybctx->subtree_size = u + LYB_SUBTREE_STEP;
314 }
315
Michal Vasko63f3d842020-07-08 10:10:14 +0200316 LY_CHECK_RET(ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES));
Michal Vasko60ea6352020-06-29 13:39:39 +0200317
318 LY_ARRAY_INCREMENT(lybctx->subtrees);
319 LYB_LAST_SUBTREE(lybctx).written = meta_buf[0];
320 LYB_LAST_SUBTREE(lybctx).inner_chunks = meta_buf[LYB_SIZE_BYTES];
321 LYB_LAST_SUBTREE(lybctx).position = (LYB_LAST_SUBTREE(lybctx).written == LYB_SIZE_MAX ? 1 : 0);
322
Michal Vasko60ea6352020-06-29 13:39:39 +0200323 return LY_SUCCESS;
324}
325
326/**
327 * @brief Parse YANG model info.
328 *
329 * @param[in] lybctx LYB context.
330 * @param[out] mod Parsed module.
331 * @return LY_ERR value.
332 */
333static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200334lyb_parse_model(struct lylyb_ctx *lybctx, uint32_t parse_options, const struct lys_module **mod)
Michal Vasko60ea6352020-06-29 13:39:39 +0200335{
336 LY_ERR ret = LY_SUCCESS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100337 char *mod_name = NULL, mod_rev[LY_REV_SIZE];
Michal Vasko60ea6352020-06-29 13:39:39 +0200338 uint16_t rev;
339
340 /* model name */
341 ret = lyb_read_string(&mod_name, 1, lybctx);
342 LY_CHECK_GOTO(ret, cleanup);
343
344 /* revision */
345 lyb_read_number(&rev, sizeof rev, 2, lybctx);
346
347 if (!mod_name[0]) {
348 /* opaq node, no module */
349 *mod = NULL;
350 goto cleanup;
351 }
352
353 if (rev) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100354 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & LYB_REV_YEAR_MASK) >> LYB_REV_YEAR_SHIFT) + LYB_REV_YEAR_OFFSET,
355 (rev & LYB_REV_MONTH_MASK) >> LYB_REV_MONTH_SHIFT, rev & LYB_REV_DAY_MASK);
Michal Vasko60ea6352020-06-29 13:39:39 +0200356 *mod = ly_ctx_get_module(lybctx->ctx, mod_name, mod_rev);
Radek Krejci1798aae2020-07-14 13:26:06 +0200357 if ((parse_options & LYD_PARSE_LYB_MOD_UPDATE) && !(*mod)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200358 /* try to use an updated module */
359 *mod = ly_ctx_get_module_implemented(lybctx->ctx, mod_name);
360 if (*mod && (!(*mod)->revision || (strcmp((*mod)->revision, mod_rev) < 0))) {
361 /* not an implemented module in a newer revision */
362 *mod = NULL;
363 }
364 }
365 } else {
366 *mod = ly_ctx_get_module_latest(lybctx->ctx, mod_name);
367 }
368 /* TODO data_clb supported?
369 if (lybctx->ctx->data_clb) {
370 if (!*mod) {
371 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, NULL, 0, lybctx->ctx->data_clb_data);
372 } else if (!(*mod)->implemented) {
373 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, lybctx->ctx->data_clb_data);
374 }
375 }*/
376
377 if (!*mod || !(*mod)->implemented) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200378 if (parse_options & LYD_PARSE_STRICT) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200379 if (!*mod) {
380 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
Michal Vasko69730152020-10-09 16:30:07 +0200381 mod_name, rev ? "@" : "", rev ? mod_rev : "");
Michal Vasko60ea6352020-06-29 13:39:39 +0200382 } else if (!(*mod)->implemented) {
383 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
Michal Vasko69730152020-10-09 16:30:07 +0200384 mod_name, rev ? "@" : "", rev ? mod_rev : "");
Michal Vasko60ea6352020-06-29 13:39:39 +0200385 }
386 ret = LY_EINVAL;
387 goto cleanup;
388 }
389
390 }
391
Michal Vasko85d9edc2021-04-22 09:15:05 +0200392 if (*mod) {
393 /* fill cached hashes, if not already */
394 lyb_cache_module_hash(*mod);
395 }
Michal Vasko11f76c82021-04-15 14:36:14 +0200396
Michal Vasko60ea6352020-06-29 13:39:39 +0200397cleanup:
398 free(mod_name);
399 return ret;
400}
401
402/**
403 * @brief Parse YANG node metadata.
404 *
405 * @param[in] lybctx LYB context.
Michal Vasko60ea6352020-06-29 13:39:39 +0200406 * @param[out] meta Parsed metadata.
407 * @return LY_ERR value.
408 */
409static LY_ERR
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200410lyb_parse_metadata(struct lyd_lyb_ctx *lybctx, struct lyd_meta **meta)
Michal Vasko60ea6352020-06-29 13:39:39 +0200411{
412 LY_ERR ret = LY_SUCCESS;
Radek Krejci857189e2020-09-01 13:26:36 +0200413 ly_bool dynamic;
Michal Vasko60ea6352020-06-29 13:39:39 +0200414 uint8_t i, count = 0;
Michal Vasko1e5d5612020-07-03 13:29:26 +0200415 char *meta_name = NULL, *meta_value;
Michal Vasko60ea6352020-06-29 13:39:39 +0200416 const struct lys_module *mod;
417
418 /* read number of attributes stored */
Radek Krejci1798aae2020-07-14 13:26:06 +0200419 lyb_read(&count, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200420
421 /* read attributes */
422 for (i = 0; i < count; ++i) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200423 ret = lyb_read_start_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200424 LY_CHECK_GOTO(ret, cleanup);
425
426 /* find model */
Michal Vaskoe0665742021-02-11 11:08:44 +0100427 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
Michal Vasko60ea6352020-06-29 13:39:39 +0200428 LY_CHECK_GOTO(ret, cleanup);
429
430 if (!mod) {
431 /* skip it */
432 do {
Radek Krejci1798aae2020-07-14 13:26:06 +0200433 lyb_read(NULL, LYB_LAST_SUBTREE(lybctx->lybctx).written, lybctx->lybctx);
434 } while (LYB_LAST_SUBTREE(lybctx->lybctx).written);
Michal Vasko60ea6352020-06-29 13:39:39 +0200435 goto stop_subtree;
436 }
437
438 /* meta name */
Radek Krejci1798aae2020-07-14 13:26:06 +0200439 ret = lyb_read_string(&meta_name, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200440 LY_CHECK_GOTO(ret, cleanup);
441
442 /* meta value */
Radek Krejci1798aae2020-07-14 13:26:06 +0200443 ret = lyb_read_string(&meta_value, 0, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200444 LY_CHECK_GOTO(ret, cleanup);
445 dynamic = 1;
446
447 /* create metadata */
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200448 ret = lyd_parser_create_meta((struct lyd_ctx *)lybctx, NULL, meta, mod, meta_name, strlen(meta_name), meta_value,
Radek Krejci8df109d2021-04-23 12:19:08 +0200449 ly_strlen(meta_value), &dynamic, LY_VALUE_JSON, NULL, LYD_HINT_DATA);
Michal Vasko60ea6352020-06-29 13:39:39 +0200450
451 /* free strings */
452 free(meta_name);
453 meta_name = NULL;
454 if (dynamic) {
455 free(meta_value);
456 dynamic = 0;
457 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200458
Radek Krejci1798aae2020-07-14 13:26:06 +0200459 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200460
461stop_subtree:
Radek Krejci1798aae2020-07-14 13:26:06 +0200462 ret = lyb_read_stop_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200463 LY_CHECK_GOTO(ret, cleanup);
464 }
465
466cleanup:
467 free(meta_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200468 if (ret) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200469 lyd_free_meta_siblings(*meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200470 *meta = NULL;
471 }
472 return ret;
473}
474
475/**
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100476 * @brief Parse format-specific prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200477 *
478 * @param[in] lybctx LYB context.
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100479 * @param[in] format Prefix data format.
480 * @param[out] prefix_data Parsed prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200481 * @return LY_ERR value.
482 */
483static LY_ERR
Radek Krejci8df109d2021-04-23 12:19:08 +0200484lyb_parse_prefix_data(struct lylyb_ctx *lybctx, LY_VALUE_FORMAT format, void **prefix_data)
Michal Vasko60ea6352020-06-29 13:39:39 +0200485{
486 LY_ERR ret = LY_SUCCESS;
487 uint8_t count, i;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100488 struct ly_set *set = NULL;
489 struct lyxml_ns *ns = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200490
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100491 switch (format) {
Radek Krejci8df109d2021-04-23 12:19:08 +0200492 case LY_VALUE_XML:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100493 /* read count */
494 lyb_read(&count, 1, lybctx);
495 if (!count) {
496 return LY_SUCCESS;
497 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200498
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100499 /* read all NS elements */
500 LY_CHECK_GOTO(ret = ly_set_new(&set), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200501
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100502 for (i = 0; i < count; ++i) {
503 ns = calloc(1, sizeof *ns);
Michal Vasko60ea6352020-06-29 13:39:39 +0200504
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100505 /* prefix */
506 LY_CHECK_GOTO(ret = lyb_read_string(&ns->prefix, 1, lybctx), cleanup);
507
508 /* namespace */
509 LY_CHECK_GOTO(ret = lyb_read_string(&ns->uri, 1, lybctx), cleanup);
510
511 LY_CHECK_GOTO(ret = ly_set_add(set, ns, 1, NULL), cleanup);
512 ns = NULL;
513 }
514
515 *prefix_data = set;
516 break;
Radek Krejci8df109d2021-04-23 12:19:08 +0200517 case LY_VALUE_JSON:
Radek Krejcif9943642021-04-26 10:18:21 +0200518 case LY_VALUE_LYB:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100519 /* nothing stored */
520 break;
521 default:
522 LOGINT(lybctx->ctx);
523 ret = LY_EINT;
524 break;
Michal Vasko60ea6352020-06-29 13:39:39 +0200525 }
526
527cleanup:
528 if (ret) {
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100529 ly_free_prefix_data(format, set);
530 if (ns) {
531 free(ns->prefix);
532 free(ns->uri);
533 free(ns);
534 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200535 }
536 return ret;
537}
538
539/**
540 * @brief Parse opaque attributes.
541 *
542 * @param[in] lybctx LYB context.
543 * @param[out] attr Parsed attributes.
544 * @return LY_ERR value.
545 */
546static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200547lyb_parse_attributes(struct lylyb_ctx *lybctx, struct lyd_attr **attr)
Michal Vasko60ea6352020-06-29 13:39:39 +0200548{
549 LY_ERR ret = LY_SUCCESS;
550 uint8_t count, i;
Michal Vasko486e4f92021-07-01 13:12:32 +0200551 struct lyd_attr *attr2 = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200552 char *prefix = NULL, *module_name = NULL, *name = NULL, *value = NULL;
Radek Krejci857189e2020-09-01 13:26:36 +0200553 ly_bool dynamic = 0;
Radek Krejci8df109d2021-04-23 12:19:08 +0200554 LY_VALUE_FORMAT format = 0;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100555 void *val_prefix_data = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200556
557 /* read count */
558 lyb_read(&count, 1, lybctx);
559
560 /* read attributes */
561 for (i = 0; i < count; ++i) {
562 ret = lyb_read_start_subtree(lybctx);
563 LY_CHECK_GOTO(ret, cleanup);
564
Michal Vasko0fdcd242020-11-11 19:12:30 +0100565 /* prefix, may be empty */
Michal Vasko60ea6352020-06-29 13:39:39 +0200566 ret = lyb_read_string(&prefix, 1, lybctx);
567 LY_CHECK_GOTO(ret, cleanup);
568 if (!prefix[0]) {
569 free(prefix);
570 prefix = NULL;
571 }
572
573 /* namespace, may be empty */
Radek Krejci1798aae2020-07-14 13:26:06 +0200574 ret = lyb_read_string(&module_name, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200575 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci1798aae2020-07-14 13:26:06 +0200576 if (!module_name[0]) {
577 free(module_name);
578 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200579 }
580
581 /* name */
582 ret = lyb_read_string(&name, 1, lybctx);
583 LY_CHECK_GOTO(ret, cleanup);
584
Michal Vasko60ea6352020-06-29 13:39:39 +0200585 /* format */
Michal Vasko403beac2021-08-24 08:27:52 +0200586 lyb_read_number(&format, sizeof format, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200587
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100588 /* value prefixes */
589 ret = lyb_parse_prefix_data(lybctx, format, &val_prefix_data);
590 LY_CHECK_GOTO(ret, cleanup);
591
Michal Vasko60ea6352020-06-29 13:39:39 +0200592 /* value */
593 ret = lyb_read_string(&value, 0, lybctx);
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100594 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200595 dynamic = 1;
596
597 /* attr2 is always changed to the created attribute */
Michal Vasko501af032020-11-11 20:27:44 +0100598 ret = lyd_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), prefix, ly_strlen(prefix), module_name,
Michal Vaskobb512792021-07-01 13:12:49 +0200599 ly_strlen(module_name), value, ly_strlen(value), &dynamic, format, val_prefix_data, LYD_HINT_DATA);
Michal Vasko60ea6352020-06-29 13:39:39 +0200600 LY_CHECK_GOTO(ret, cleanup);
601
602 free(prefix);
603 prefix = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200604 free(module_name);
605 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200606 free(name);
607 name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200608 assert(!dynamic);
609 value = NULL;
610
611 if (!*attr) {
612 *attr = attr2;
613 }
614
615 ret = lyb_read_stop_subtree(lybctx);
616 LY_CHECK_GOTO(ret, cleanup);
617 }
618
619cleanup:
620 free(prefix);
Radek Krejci1798aae2020-07-14 13:26:06 +0200621 free(module_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200622 free(name);
623 if (dynamic) {
624 free(value);
625 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200626 if (ret) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200627 lyd_free_attr_siblings(lybctx->ctx, *attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200628 *attr = NULL;
629 }
630 return ret;
631}
632
633/**
634 * @brief Check whether a schema node matches a hash(es).
635 *
636 * @param[in] sibling Schema node to check.
637 * @param[in] hash Hash array to check.
638 * @param[in] hash_count Number of hashes in @p hash.
639 * @return non-zero if matches,
640 * @return 0 if not.
641 */
642static int
643lyb_is_schema_hash_match(struct lysc_node *sibling, LYB_HASH *hash, uint8_t hash_count)
644{
645 LYB_HASH sibling_hash;
646 uint8_t i;
647
648 /* compare all the hashes starting from collision ID 0 */
649 for (i = 0; i < hash_count; ++i) {
Michal Vasko11f76c82021-04-15 14:36:14 +0200650 sibling_hash = lyb_get_hash(sibling, i);
Michal Vasko60ea6352020-06-29 13:39:39 +0200651 if (sibling_hash != hash[i]) {
652 return 0;
653 }
654 }
655
656 return 1;
657}
658
659/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200660 * @brief Parse schema node hash.
661 *
662 * @param[in] lybctx LYB context.
663 * @param[in] sparent Schema parent, must be set if @p mod is not.
664 * @param[in] mod Module of the top-level node, must be set if @p sparent is not.
665 * @param[out] snode Parsed found schema node, may be NULL if opaque.
666 * @return LY_ERR value.
667 */
668static LY_ERR
669lyb_parse_schema_hash(struct lyd_lyb_ctx *lybctx, const struct lysc_node *sparent, const struct lys_module *mod,
Radek Krejci0f969882020-08-21 16:56:47 +0200670 const struct lysc_node **snode)
Michal Vasko60ea6352020-06-29 13:39:39 +0200671{
672 LY_ERR ret;
673 uint8_t i, j;
674 const struct lysc_node *sibling;
675 LYB_HASH hash[LYB_HASH_BITS - 1];
Radek Krejci1deb5be2020-08-26 16:43:36 +0200676 uint32_t getnext_opts;
Michal Vasko60ea6352020-06-29 13:39:39 +0200677
678 *snode = NULL;
Michal Vasko7b1ad1a2020-11-02 15:41:27 +0100679 getnext_opts = lybctx->int_opts & LYD_INTOPT_REPLY ? LYS_GETNEXT_OUTPUT : 0;
Michal Vasko60ea6352020-06-29 13:39:39 +0200680
681 /* read the first hash */
Radek Krejci1798aae2020-07-14 13:26:06 +0200682 lyb_read(&hash[0], sizeof *hash, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200683
684 if (!hash[0]) {
685 /* opaque node */
686 return LY_SUCCESS;
687 }
688
689 /* based on the first hash read all the other ones, if any */
690 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
691 if (i > LYB_HASH_BITS) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200692 LOGINT_RET(lybctx->lybctx->ctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200693 }
694 }
695
696 /* move the first hash on its accurate position */
697 hash[i] = hash[0];
698
699 /* read the rest of hashes */
700 for (j = i; j; --j) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200701 lyb_read(&hash[j - 1], sizeof *hash, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200702
703 /* correct collision ID */
704 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
705 /* preceded with zeros */
706 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
707 }
708
709 /* find our node with matching hashes */
710 sibling = NULL;
Radek Krejcif16e2542021-02-17 15:39:23 +0100711 while (1) {
712 if (!sparent && lybctx->ext) {
713 sibling = lys_getnext_ext(sibling, sparent, lybctx->ext, getnext_opts);
714 } else {
715 sibling = lys_getnext(sibling, sparent, mod ? mod->compiled : NULL, getnext_opts);
716 }
717 if (!sibling) {
718 break;
719 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200720 /* skip schema nodes from models not present during printing */
Michal Vasko69730152020-10-09 16:30:07 +0200721 if (lyb_has_schema_model(sibling, lybctx->lybctx->models) &&
722 lyb_is_schema_hash_match((struct lysc_node *)sibling, hash, i + 1)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200723 /* match found */
724 break;
725 }
726 }
727
Michal Vaskoe0665742021-02-11 11:08:44 +0100728 if (!sibling && (lybctx->parse_opts & LYD_PARSE_STRICT)) {
Radek Krejcif16e2542021-02-17 15:39:23 +0100729 if (lybctx->ext) {
730 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a node from \"%s\" extension instance node.",
731 lybctx->ext->def->name);
732 } else if (mod) {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100733 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a top-level node"
Michal Vasko69730152020-10-09 16:30:07 +0200734 " from \"%s\".", mod->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200735 } else {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100736 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a child node"
Michal Vasko69730152020-10-09 16:30:07 +0200737 " of \"%s\".", sparent->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200738 }
739 return LY_EVALID;
Radek Krejci1798aae2020-07-14 13:26:06 +0200740 } else if (sibling && (ret = lyd_parser_check_schema((struct lyd_ctx *)lybctx, sibling))) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200741 return ret;
742 }
743
744 *snode = sibling;
745 return LY_SUCCESS;
746}
747
748/**
749 * @brief Read until the end of the current subtree.
750 *
751 * @param[in] lybctx LYB context.
752 */
753static void
Radek Krejci1798aae2020-07-14 13:26:06 +0200754lyb_skip_subtree(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200755{
Michal Vasko60ea6352020-06-29 13:39:39 +0200756 do {
757 /* first skip any meta information inside */
Michal Vasko63f3d842020-07-08 10:10:14 +0200758 ly_in_skip(lybctx->in, LYB_LAST_SUBTREE(lybctx).inner_chunks * LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +0200759
760 /* then read data */
761 lyb_read(NULL, LYB_LAST_SUBTREE(lybctx).written, lybctx);
762 } while (LYB_LAST_SUBTREE(lybctx).written);
763}
764
765/**
Michal Vasko02ed9d82021-07-15 14:58:04 +0200766 * @brief Parse the context of anydata/anyxml node.
767 *
768 * @param[in] ctx libyang context.
769 * @param[in] data LYB data to parse.
770 * @param[out] tree Parsed tree.
771 * @return LY_ERR value.
772 */
773static LY_ERR
774lyb_parse_any_content(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree)
775{
776 LY_ERR ret;
777 uint32_t prev_lo;
778 struct ly_in *in;
779 struct lyd_ctx *lydctx = NULL;
780
781 *tree = NULL;
782
783 LY_CHECK_RET(ly_in_new_memory(data, &in));
784
785 /* turn logging off */
786 prev_lo = ly_log_options(0);
787
Michal Vasko56d88602021-07-15 16:37:59 +0200788 ret = _lyd_parse_lyb(ctx, NULL, NULL, tree, in, LYD_PARSE_ONLY | LYD_PARSE_OPAQ | LYD_PARSE_STRICT, 0,
Michal Vasko02ed9d82021-07-15 14:58:04 +0200789 LYD_INTOPT_ANY | LYD_INTOPT_WITH_SIBLINGS, NULL, &lydctx);
790
791 /* turn logging on again */
792 ly_log_options(prev_lo);
793
794 ly_in_free(in, 0);
Michal Vasko1391e792021-08-23 12:15:44 +0200795 if (lydctx) {
796 lydctx->free(lydctx);
797 }
Michal Vasko02ed9d82021-07-15 14:58:04 +0200798 if (ret) {
799 lyd_free_siblings(*tree);
800 *tree = NULL;
801 }
802 return ret;
803}
804
805/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200806 * @brief Parse LYB subtree.
807 *
808 * @param[in] lybctx LYB context.
809 * @param[in] parent Data parent of the subtree, must be set if @p first is not.
810 * @param[in,out] first First top-level sibling, must be set if @p parent is not.
811 * @return LY_ERR value.
812 */
813static LY_ERR
Michal Vaskoe0665742021-02-11 11:08:44 +0100814lyb_parse_subtree_r(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p, struct ly_set *parsed)
Michal Vasko60ea6352020-06-29 13:39:39 +0200815{
816 LY_ERR ret = LY_SUCCESS;
817 struct lyd_node *node = NULL, *tree;
818 const struct lys_module *mod;
819 const struct lysc_node *snode = NULL;
820 struct lyd_meta *meta = NULL, *m;
Radek Krejci1798aae2020-07-14 13:26:06 +0200821 struct lyd_attr *attr = NULL, *a;
Michal Vasko60ea6352020-06-29 13:39:39 +0200822 LYD_ANYDATA_VALUETYPE value_type;
Radek Krejci1798aae2020-07-14 13:26:06 +0200823 char *value = NULL, *name = NULL, *prefix = NULL, *module_key = NULL;
aPiecekea304e32021-08-18 09:13:47 +0200824 uint8_t *term_value = NULL;
Michal Vasko9afe3df2021-02-05 16:33:50 +0100825 const char *val_dict;
Radek Krejci857189e2020-09-01 13:26:36 +0200826 ly_bool dynamic = 0;
Radek Krejci8df109d2021-04-23 12:19:08 +0200827 LY_VALUE_FORMAT format = 0;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100828 void *val_prefix_data = NULL;
aPiecekea304e32021-08-18 09:13:47 +0200829 uint32_t flags, term_value_len;
Radek Krejci1798aae2020-07-14 13:26:06 +0200830 const struct ly_ctx *ctx = lybctx->lybctx->ctx;
Michal Vasko60ea6352020-06-29 13:39:39 +0200831
832 /* register a new subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +0200833 LY_CHECK_GOTO(ret = lyb_read_start_subtree(lybctx->lybctx), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200834
Michal Vaskof4b4d002021-08-23 12:16:02 +0200835 if (!parent || !parent->schema) {
836 /* top-level or opaque, read module name */
Michal Vaskoe0665742021-02-11 11:08:44 +0100837 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
Michal Vasko60ea6352020-06-29 13:39:39 +0200838 LY_CHECK_GOTO(ret, cleanup);
839
840 /* read hash, find the schema node starting from mod */
841 ret = lyb_parse_schema_hash(lybctx, NULL, mod, &snode);
842 LY_CHECK_GOTO(ret, cleanup);
843 } else {
844 /* read hash, find the schema node starting from parent schema */
845 ret = lyb_parse_schema_hash(lybctx, parent->schema, NULL, &snode);
846 LY_CHECK_GOTO(ret, cleanup);
847 }
848
Michal Vaskoe0665742021-02-11 11:08:44 +0100849 if (!snode && !(lybctx->parse_opts & LYD_PARSE_OPAQ)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200850 /* unknown data, skip them */
Radek Krejci1798aae2020-07-14 13:26:06 +0200851 lyb_skip_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200852 goto stop_subtree;
Radek Krejci0f969882020-08-21 16:56:47 +0200853 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200854
855 /* create metadata/attributes */
856 if (snode) {
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200857 ret = lyb_parse_metadata(lybctx, &meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200858 LY_CHECK_GOTO(ret, cleanup);
859 } else {
Radek Krejci1798aae2020-07-14 13:26:06 +0200860 ret = lyb_parse_attributes(lybctx->lybctx, &attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200861 LY_CHECK_GOTO(ret, cleanup);
862 }
863
Michal Vaskoc5e866a2020-11-04 17:09:26 +0100864 /* read flags */
865 lyb_read_number(&flags, sizeof flags, sizeof flags, lybctx->lybctx);
866
Michal Vasko60ea6352020-06-29 13:39:39 +0200867 if (!snode) {
868 /* parse prefix */
Radek Krejci1798aae2020-07-14 13:26:06 +0200869 ret = lyb_read_string(&prefix, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200870 LY_CHECK_GOTO(ret, cleanup);
871
Radek Krejci1798aae2020-07-14 13:26:06 +0200872 /* parse module key */
873 ret = lyb_read_string(&module_key, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200874 LY_CHECK_GOTO(ret, cleanup);
875
876 /* parse name */
Radek Krejci1798aae2020-07-14 13:26:06 +0200877 ret = lyb_read_string(&name, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200878 LY_CHECK_GOTO(ret, cleanup);
879
Michal Vaskoffc92bf2021-06-21 08:15:14 +0200880 /* parse value */
881 ret = lyb_read_string(&value, 1, lybctx->lybctx);
882 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
883 dynamic = 1;
884
Michal Vasko60ea6352020-06-29 13:39:39 +0200885 /* parse format */
Michal Vasko403beac2021-08-24 08:27:52 +0200886 lyb_read_number(&format, sizeof format, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200887
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100888 /* parse value prefixes */
889 ret = lyb_parse_prefix_data(lybctx->lybctx, format, &val_prefix_data);
890 LY_CHECK_GOTO(ret, cleanup);
891
Michal Vasko60ea6352020-06-29 13:39:39 +0200892 /* create node */
Michal Vasko501af032020-11-11 20:27:44 +0100893 ret = lyd_create_opaq(ctx, name, strlen(name), prefix, ly_strlen(prefix), module_key, ly_strlen(module_key),
894 value, strlen(value), &dynamic, format, val_prefix_data, 0, &node);
Michal Vasko60ea6352020-06-29 13:39:39 +0200895 LY_CHECK_GOTO(ret, cleanup);
896
897 /* process children */
Radek Krejci1798aae2020-07-14 13:26:06 +0200898 while (LYB_LAST_SUBTREE(lybctx->lybctx).written) {
Michal Vaskoe0665742021-02-11 11:08:44 +0100899 ret = lyb_parse_subtree_r(lybctx, node, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200900 LY_CHECK_GOTO(ret, cleanup);
901 }
902 } else if (snode->nodetype & LYD_NODE_TERM) {
903 /* parse value */
aPiecekaa5b70a2021-08-30 08:33:25 +0200904 ret = lyb_read_term((struct lysc_node_leaf *)snode, &term_value,
905 &term_value_len, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200906 LY_CHECK_GOTO(ret, cleanup);
907 dynamic = 1;
908
909 /* create node */
aPiecekea304e32021-08-18 09:13:47 +0200910 ret = lyd_parser_create_term((struct lyd_ctx *)lybctx, snode,
911 term_value, term_value_len, &dynamic, LY_VALUE_LYB,
Michal Vasko69730152020-10-09 16:30:07 +0200912 NULL, LYD_HINT_DATA, &node);
Michal Vasko60ea6352020-06-29 13:39:39 +0200913 if (dynamic) {
aPiecekea304e32021-08-18 09:13:47 +0200914 free(term_value);
Michal Vasko60ea6352020-06-29 13:39:39 +0200915 dynamic = 0;
916 }
aPiecekea304e32021-08-18 09:13:47 +0200917 term_value = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200918 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200919 } else if (snode->nodetype & LYD_NODE_INNER) {
920 /* create node */
921 ret = lyd_create_inner(snode, &node);
922 LY_CHECK_GOTO(ret, cleanup);
923
924 /* process children */
Radek Krejci1798aae2020-07-14 13:26:06 +0200925 while (LYB_LAST_SUBTREE(lybctx->lybctx).written) {
Michal Vaskoe0665742021-02-11 11:08:44 +0100926 ret = lyb_parse_subtree_r(lybctx, node, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200927 LY_CHECK_GOTO(ret, cleanup);
928 }
929
Michal Vaskoe0665742021-02-11 11:08:44 +0100930 if (!(lybctx->parse_opts & LYD_PARSE_ONLY)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200931 /* new node validation, autodelete CANNOT occur, all nodes are new */
Michal Vaskoe0665742021-02-11 11:08:44 +0100932 ret = lyd_validate_new(lyd_node_child_p(node), snode, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200933 LY_CHECK_GOTO(ret, cleanup);
934
935 /* add any missing default children */
Radek Krejci4f2e3e52021-03-30 14:20:28 +0200936 ret = lyd_new_implicit_r(node, lyd_node_child_p(node), NULL, NULL, &lybctx->node_when, &lybctx->node_exts,
Michal Vaskoc43c8ab2021-03-05 13:32:44 +0100937 &lybctx->node_types, (lybctx->val_opts & LYD_VALIDATE_NO_STATE) ? LYD_IMPLICIT_NO_STATE : 0, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200938 LY_CHECK_GOTO(ret, cleanup);
939 }
940
Michal Vasko751cb4d2020-07-14 12:25:28 +0200941 if (snode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200942 /* rememeber the RPC/action/notification */
Radek Krejci1798aae2020-07-14 13:26:06 +0200943 lybctx->op_node = node;
Michal Vasko60ea6352020-06-29 13:39:39 +0200944 }
945 } else if (snode->nodetype & LYD_NODE_ANY) {
946 /* parse value type */
Michal Vasko403beac2021-08-24 08:27:52 +0200947 lyb_read_number(&value_type, sizeof value_type, sizeof value_type, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200948 if (value_type == LYD_ANYDATA_DATATREE) {
949 /* invalid situation */
Radek Krejci1798aae2020-07-14 13:26:06 +0200950 LOGINT(ctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200951 goto cleanup;
952 }
953
954 /* read anydata content */
Radek Krejci1798aae2020-07-14 13:26:06 +0200955 ret = lyb_read_string(&value, 0, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200956 LY_CHECK_GOTO(ret, cleanup);
957 dynamic = 1;
958
959 if (value_type == LYD_ANYDATA_LYB) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200960 /* try to parse LYB into a data tree */
Michal Vasko02ed9d82021-07-15 14:58:04 +0200961 if (!lyb_parse_any_content(ctx, value, &tree)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200962 /* successfully parsed */
963 free(value);
964 value = (char *)tree;
965 value_type = LYD_ANYDATA_DATATREE;
966 }
967 }
968
Michal Vasko9afe3df2021-02-05 16:33:50 +0100969 /* create the node */
970 switch (value_type) {
971 case LYD_ANYDATA_LYB:
972 case LYD_ANYDATA_DATATREE:
973 /* use the value directly */
974 ret = lyd_create_any(snode, value, value_type, 1, &node);
975 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200976
Michal Vasko9afe3df2021-02-05 16:33:50 +0100977 dynamic = 0;
978 value = NULL;
979 break;
980 case LYD_ANYDATA_STRING:
981 case LYD_ANYDATA_XML:
982 case LYD_ANYDATA_JSON:
983 /* value is expected to be in the dictionary */
984 ret = lydict_insert_zc(ctx, value, &val_dict);
985 LY_CHECK_GOTO(ret, cleanup);
986 dynamic = 0;
987 value = NULL;
988
989 /* use the value in the dictionary */
990 ret = lyd_create_any(snode, val_dict, value_type, 1, &node);
991 if (ret) {
992 lydict_remove(ctx, val_dict);
993 goto cleanup;
994 }
995 break;
996 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200997 }
998 assert(node);
999
Michal Vaskoc5e866a2020-11-04 17:09:26 +01001000 /* set flags */
1001 node->flags = flags;
Michal Vasko60ea6352020-06-29 13:39:39 +02001002
1003 /* add metadata/attributes */
1004 if (snode) {
1005 LY_LIST_FOR(meta, m) {
1006 m->parent = node;
1007 }
1008 node->meta = meta;
1009 meta = NULL;
1010 } else {
1011 assert(!node->schema);
1012 LY_LIST_FOR(attr, a) {
1013 a->parent = (struct lyd_node_opaq *)node;
1014 }
1015 ((struct lyd_node_opaq *)node)->attr = attr;
1016 attr = NULL;
1017 }
1018
Michal Vaskob104f112020-07-17 09:54:54 +02001019 /* insert, keep first pointer correct */
Michal Vasko6ee6f432021-07-16 09:49:14 +02001020 lyd_insert_node(parent, first_p, node, lybctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0);
Michal Vaskoe0665742021-02-11 11:08:44 +01001021 while (!parent && (*first_p)->prev->next) {
1022 *first_p = (*first_p)->prev;
1023 }
1024
1025 /* rememeber a successfully parsed node */
1026 if (parsed) {
1027 ly_set_add(parsed, node, 1, NULL);
Michal Vaskob104f112020-07-17 09:54:54 +02001028 }
Michal Vasko60ea6352020-06-29 13:39:39 +02001029 node = NULL;
1030
1031stop_subtree:
1032 /* end the subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +02001033 ret = lyb_read_stop_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001034 LY_CHECK_GOTO(ret, cleanup);
1035
1036cleanup:
1037 free(prefix);
Radek Krejci1798aae2020-07-14 13:26:06 +02001038 free(module_key);
Michal Vasko60ea6352020-06-29 13:39:39 +02001039 free(name);
1040 if (dynamic) {
1041 free(value);
1042 }
Michal Vasko60ea6352020-06-29 13:39:39 +02001043
Michal Vasko3a41dff2020-07-15 14:30:28 +02001044 lyd_free_meta_siblings(meta);
Radek Krejci011e4aa2020-09-04 15:22:31 +02001045 lyd_free_attr_siblings(ctx, attr);
Michal Vasko60ea6352020-06-29 13:39:39 +02001046 lyd_free_tree(node);
1047 return ret;
1048}
1049
1050/**
1051 * @brief Parse used YANG data models.
1052 *
1053 * @param[in] lybctx LYB context.
1054 * @return LY_ERR value.
1055 */
1056static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001057lyb_parse_data_models(struct lylyb_ctx *lybctx, uint32_t parse_options)
Michal Vasko60ea6352020-06-29 13:39:39 +02001058{
1059 LY_ERR ret;
1060 uint32_t count;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001061 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +02001062
1063 /* read model count */
1064 lyb_read_number(&count, sizeof count, 2, lybctx);
1065
1066 if (count) {
1067 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->models, count, LY_EMEM);
1068
1069 /* read modules */
1070 for (u = 0; u < count; ++u) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001071 ret = lyb_parse_model(lybctx, parse_options, &lybctx->models[u]);
Michal Vasko60ea6352020-06-29 13:39:39 +02001072 LY_CHECK_RET(ret);
1073 LY_ARRAY_INCREMENT(lybctx->models);
1074 }
1075 }
1076
1077 return LY_SUCCESS;
1078}
1079
1080/**
1081 * @brief Parse LYB magic number.
1082 *
1083 * @param[in] lybctx LYB context.
1084 * @return LY_ERR value.
1085 */
1086static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001087lyb_parse_magic_number(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001088{
1089 char magic_byte = 0;
1090
1091 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1092 if (magic_byte != 'l') {
1093 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
1094 return LY_EINVAL;
1095 }
1096
1097 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1098 if (magic_byte != 'y') {
1099 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
1100 return LY_EINVAL;
1101 }
1102
1103 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1104 if (magic_byte != 'b') {
1105 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
1106 return LY_EINVAL;
1107 }
1108
1109 return LY_SUCCESS;
1110}
1111
1112/**
1113 * @brief Parse LYB header.
1114 *
1115 * @param[in] lybctx LYB context.
1116 * @return LY_ERR value.
1117 */
1118static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001119lyb_parse_header(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001120{
1121 uint8_t byte = 0;
1122
1123 /* version, future flags */
1124 lyb_read((uint8_t *)&byte, sizeof byte, lybctx);
1125
1126 if ((byte & LYB_VERSION_MASK) != LYB_VERSION_NUM) {
1127 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid LYB format version \"0x%02x\", expected \"0x%02x\".",
Michal Vasko69730152020-10-09 16:30:07 +02001128 byte & LYB_VERSION_MASK, LYB_VERSION_NUM);
Michal Vasko60ea6352020-06-29 13:39:39 +02001129 return LY_EINVAL;
1130 }
1131
1132 return LY_SUCCESS;
1133}
1134
Michal Vasko02ed9d82021-07-15 14:58:04 +02001135static LY_ERR
1136_lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1137 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
Radek Krejcif16e2542021-02-17 15:39:23 +01001138 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
Michal Vasko60ea6352020-06-29 13:39:39 +02001139{
Michal Vaskoe0665742021-02-11 11:08:44 +01001140 LY_ERR rc = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001141 struct lyd_lyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001142
Michal Vaskoe0665742021-02-11 11:08:44 +01001143 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1144 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
Radek Krejci7931b192020-06-25 17:05:03 +02001145
Radek Krejci1798aae2020-07-14 13:26:06 +02001146 lybctx = calloc(1, sizeof *lybctx);
1147 LY_CHECK_ERR_RET(!lybctx, LOGMEM(ctx), LY_EMEM);
1148 lybctx->lybctx = calloc(1, sizeof *lybctx->lybctx);
Michal Vaskoe0665742021-02-11 11:08:44 +01001149 LY_CHECK_ERR_GOTO(!lybctx->lybctx, LOGMEM(ctx); rc = LY_EMEM, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001150
Radek Krejci1798aae2020-07-14 13:26:06 +02001151 lybctx->lybctx->in = in;
1152 lybctx->lybctx->ctx = ctx;
Michal Vaskoe0665742021-02-11 11:08:44 +01001153 lybctx->parse_opts = parse_opts;
1154 lybctx->val_opts = val_opts;
Michal Vaskoe0665742021-02-11 11:08:44 +01001155 lybctx->int_opts = int_opts;
Michal Vasko02ed9d82021-07-15 14:58:04 +02001156 lybctx->free = lyd_lyb_ctx_free;
Radek Krejcif16e2542021-02-17 15:39:23 +01001157 lybctx->ext = ext;
Michal Vaskoe0665742021-02-11 11:08:44 +01001158
1159 /* find the operation node if it exists already */
1160 LY_CHECK_GOTO(rc = lyd_parser_find_operation(parent, int_opts, &lybctx->op_node), cleanup);
1161
Michal Vasko60ea6352020-06-29 13:39:39 +02001162 /* read magic number */
Michal Vaskoe0665742021-02-11 11:08:44 +01001163 rc = lyb_parse_magic_number(lybctx->lybctx);
1164 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001165
1166 /* read header */
Michal Vaskoe0665742021-02-11 11:08:44 +01001167 rc = lyb_parse_header(lybctx->lybctx);
1168 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001169
1170 /* read used models */
Michal Vaskoe0665742021-02-11 11:08:44 +01001171 rc = lyb_parse_data_models(lybctx->lybctx, lybctx->parse_opts);
1172 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001173
1174 /* read subtree(s) */
Radek Krejci1798aae2020-07-14 13:26:06 +02001175 while (lybctx->lybctx->in->current[0]) {
Michal Vaskoe0665742021-02-11 11:08:44 +01001176 rc = lyb_parse_subtree_r(lybctx, parent, first_p, parsed);
1177 LY_CHECK_GOTO(rc, cleanup);
1178
1179 if (!(int_opts & LYD_INTOPT_WITH_SIBLINGS)) {
1180 break;
1181 }
1182 }
1183
1184 if ((int_opts & LYD_INTOPT_NO_SIBLINGS) && lybctx->lybctx->in->current[0]) {
1185 LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling node.");
1186 rc = LY_EVALID;
1187 goto cleanup;
1188 }
1189 if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY)) && !lybctx->op_node) {
1190 LOGVAL(ctx, LYVE_DATA, "Missing the operation node.");
1191 rc = LY_EVALID;
1192 goto cleanup;
Michal Vasko60ea6352020-06-29 13:39:39 +02001193 }
1194
1195 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001196 ly_in_skip(lybctx->lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001197
Michal Vasko60ea6352020-06-29 13:39:39 +02001198cleanup:
Michal Vaskoe0665742021-02-11 11:08:44 +01001199 /* there should be no unres stored if validation should be skipped */
1200 assert(!(parse_opts & LYD_PARSE_ONLY) || (!lybctx->node_types.count && !lybctx->meta_types.count &&
1201 !lybctx->node_when.count));
1202
1203 if (rc) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001204 lyd_lyb_ctx_free((struct lyd_ctx *)lybctx);
Radek Krejci1798aae2020-07-14 13:26:06 +02001205 } else {
Michal Vaskoe0665742021-02-11 11:08:44 +01001206 *lydctx_p = (struct lyd_ctx *)lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001207 }
Michal Vaskoe0665742021-02-11 11:08:44 +01001208 return rc;
Michal Vasko60ea6352020-06-29 13:39:39 +02001209}
1210
Michal Vasko02ed9d82021-07-15 14:58:04 +02001211LY_ERR
1212lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1213 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
1214 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
1215{
1216 uint32_t int_opts;
1217
1218 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1219 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
1220
1221 switch (data_type) {
1222 case LYD_TYPE_DATA_YANG:
1223 int_opts = LYD_INTOPT_WITH_SIBLINGS;
1224 break;
1225 case LYD_TYPE_RPC_YANG:
1226 int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
1227 break;
1228 case LYD_TYPE_NOTIF_YANG:
1229 int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
1230 break;
1231 case LYD_TYPE_REPLY_YANG:
1232 int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
1233 break;
1234 default:
1235 LOGINT(ctx);
1236 return LY_EINT;
1237 }
1238
1239 return _lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, parsed, lydctx_p);
1240}
1241
Michal Vasko60ea6352020-06-29 13:39:39 +02001242API int
1243lyd_lyb_data_length(const char *data)
1244{
1245 LY_ERR ret = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001246 struct lylyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001247 int count, i;
1248 size_t len;
1249 uint8_t buf[LYB_SIZE_MAX];
1250
1251 if (!data) {
1252 return -1;
1253 }
1254
Radek Krejci1798aae2020-07-14 13:26:06 +02001255 lybctx = calloc(1, sizeof *lybctx);
1256 LY_CHECK_ERR_RET(!lybctx, LOGMEM(NULL), LY_EMEM);
1257 ret = ly_in_new_memory(data, &lybctx->in);
Michal Vasko63f3d842020-07-08 10:10:14 +02001258 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001259
1260 /* read magic number */
Radek Krejci1798aae2020-07-14 13:26:06 +02001261 ret = lyb_parse_magic_number(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001262 LY_CHECK_GOTO(ret, cleanup);
1263
1264 /* read header */
Radek Krejci1798aae2020-07-14 13:26:06 +02001265 ret = lyb_parse_header(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001266 LY_CHECK_GOTO(ret, cleanup);
1267
1268 /* read model count */
Radek Krejci1798aae2020-07-14 13:26:06 +02001269 lyb_read_number(&count, sizeof count, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001270
1271 /* read all models */
1272 for (i = 0; i < count; ++i) {
1273 /* module name length */
1274 len = 0;
Radek Krejci1798aae2020-07-14 13:26:06 +02001275 lyb_read_number(&len, sizeof len, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001276
1277 /* model name */
Radek Krejci1798aae2020-07-14 13:26:06 +02001278 lyb_read(buf, len, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001279
1280 /* revision */
Radek Krejci1798aae2020-07-14 13:26:06 +02001281 lyb_read(buf, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001282 }
1283
Radek Krejci1798aae2020-07-14 13:26:06 +02001284 while (lybctx->in->current[0]) {
Michal Vasko60ea6352020-06-29 13:39:39 +02001285 /* register a new subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +02001286 ret = lyb_read_start_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001287 LY_CHECK_GOTO(ret, cleanup);
1288
1289 /* skip it */
Radek Krejci1798aae2020-07-14 13:26:06 +02001290 lyb_skip_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001291
1292 /* subtree finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001293 ret = lyb_read_stop_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001294 LY_CHECK_GOTO(ret, cleanup);
1295 }
1296
1297 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001298 ly_in_skip(lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001299
1300cleanup:
Radek Krejci1798aae2020-07-14 13:26:06 +02001301 count = lybctx->in->current - lybctx->in->start;
Michal Vasko63f3d842020-07-08 10:10:14 +02001302
Radek Krejci1798aae2020-07-14 13:26:06 +02001303 ly_in_free(lybctx->in, 0);
1304 lylyb_ctx_free(lybctx);
1305
Michal Vasko63f3d842020-07-08 10:10:14 +02001306 return ret ? -1 : count;
Michal Vasko60ea6352020-06-29 13:39:39 +02001307}