blob: b893dd27de4c004fe43c77a1cdf1690e35e36876 [file] [log] [blame]
Radek Krejcif0e1ba52020-05-22 15:14:35 +02001/**
Michal Vaskoafac7822020-10-20 14:22:26 +02002 * @file in.c
Radek Krejcif0e1ba52020-05-22 15:14:35 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vaskoafac7822020-10-20 14:22:26 +02004 * @brief libyang input functions.
Radek Krejcif0e1ba52020-05-22 15:14:35 +02005 *
Michal Vaskoafac7822020-10-20 14:22:26 +02006 * Copyright (c) 2015 - 2020 CESNET, z.s.p.o.
Radek Krejcif0e1ba52020-05-22 15:14:35 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#define _GNU_SOURCE
Radek Krejcif8dc59a2020-11-25 13:47:44 +010016#define _POSIX_C_SOURCE 200809L /* strdup, strndup */
17
18#ifdef __APPLE__
19#define _DARWIN_C_SOURCE /* F_GETPATH */
20#endif
Radek Krejcif0e1ba52020-05-22 15:14:35 +020021
Radek Krejcid43298b2021-03-25 16:17:15 +010022#if defined (__NetBSD__) || defined (__OpenBSD__)
Christian Hopps6f326212021-03-23 12:37:29 -040023/* realpath */
Christian Hoppsf9b87412021-04-12 16:56:15 -040024#define _XOPEN_SOURCE 1
25#define _XOPEN_SOURCE_EXTENDED 1
Christian Hopps6f326212021-03-23 12:37:29 -040026#endif
27
Michal Vaskoafac7822020-10-20 14:22:26 +020028#include "in.h"
29#include "in_internal.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020030
Radek Krejcif0e1ba52020-05-22 15:14:35 +020031#include <errno.h>
32#include <fcntl.h>
33#include <limits.h>
Radek Krejci47fab892020-11-05 17:02:41 +010034#include <stdint.h>
Radek Krejcif0e1ba52020-05-22 15:14:35 +020035#include <stdio.h>
Radek Krejcica376bd2020-06-11 16:04:06 +020036#include <stdlib.h>
Radek Krejcif0e1ba52020-05-22 15:14:35 +020037#include <string.h>
Radek Krejcica376bd2020-06-11 16:04:06 +020038#include <unistd.h>
Radek Krejcif0e1ba52020-05-22 15:14:35 +020039
Radek Krejcica376bd2020-06-11 16:04:06 +020040#include "common.h"
Michal Vasko5aa44c02020-06-29 11:47:02 +020041#include "compat.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020042#include "dict.h"
43#include "log.h"
Radek Krejci1798aae2020-07-14 13:26:06 +020044#include "parser_data.h"
Radek Krejcif0e1ba52020-05-22 15:14:35 +020045#include "parser_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010046#include "set.h"
Radek Krejci77114102021-03-10 15:21:57 +010047#include "tree.h"
Radek Krejci47fab892020-11-05 17:02:41 +010048#include "tree_data.h"
Radek Krejci1798aae2020-07-14 13:26:06 +020049#include "tree_data_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010050#include "tree_schema.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020051#include "tree_schema_internal.h"
Radek Krejcif0e1ba52020-05-22 15:14:35 +020052
Jan Kundrátc53a7ec2021-12-09 16:01:19 +010053LIBYANG_API_DEF LY_IN_TYPE
Radek Krejcif0e1ba52020-05-22 15:14:35 +020054ly_in_type(const struct ly_in *in)
55{
56 LY_CHECK_ARG_RET(NULL, in, LY_IN_ERROR);
57 return in->type;
58}
59
Jan Kundrátc53a7ec2021-12-09 16:01:19 +010060LIBYANG_API_DEF LY_ERR
Michal Vaskoddd76592022-01-17 13:34:48 +010061ly_in_reset(struct ly_in *in)
62{
63 LY_CHECK_ARG_RET(NULL, in, LY_EINVAL);
64
65 in->current = in->func_start = in->start;
66 in->line = 1;
67 return LY_SUCCESS;
68}
69
70LIBYANG_API_DEF LY_ERR
Radek Krejcif0e1ba52020-05-22 15:14:35 +020071ly_in_new_fd(int fd, struct ly_in **in)
72{
73 size_t length;
74 char *addr;
75
76 LY_CHECK_ARG_RET(NULL, fd >= 0, in, LY_EINVAL);
77
78 LY_CHECK_RET(ly_mmap(NULL, fd, &length, (void **)&addr));
79 if (!addr) {
80 LOGERR(NULL, LY_EINVAL, "Empty input file.");
81 return LY_EINVAL;
82 }
83
84 *in = calloc(1, sizeof **in);
85 LY_CHECK_ERR_RET(!*in, LOGMEM(NULL); ly_munmap(addr, length), LY_EMEM);
86
87 (*in)->type = LY_IN_FD;
88 (*in)->method.fd = fd;
Michal Vasko63f3d842020-07-08 10:10:14 +020089 (*in)->current = (*in)->start = (*in)->func_start = addr;
Radek Krejcid54412f2020-12-17 20:25:35 +010090 (*in)->line = 1;
Radek Krejcif0e1ba52020-05-22 15:14:35 +020091 (*in)->length = length;
92
93 return LY_SUCCESS;
94}
95
Jan Kundrátc53a7ec2021-12-09 16:01:19 +010096LIBYANG_API_DEF int
Radek Krejcif0e1ba52020-05-22 15:14:35 +020097ly_in_fd(struct ly_in *in, int fd)
98{
99 int prev_fd;
100 size_t length;
101 const char *addr;
102
103 LY_CHECK_ARG_RET(NULL, in, in->type == LY_IN_FD, -1);
104
105 prev_fd = in->method.fd;
106
107 if (fd != -1) {
108 LY_CHECK_RET(ly_mmap(NULL, fd, &length, (void **)&addr), -1);
109 if (!addr) {
110 LOGERR(NULL, LY_EINVAL, "Empty input file.");
111 return -1;
112 }
113
Michal Vasko22df3f02020-08-24 13:29:22 +0200114 ly_munmap((char *)in->start, in->length);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200115
116 in->method.fd = fd;
117 in->current = in->start = addr;
Radek Krejcid54412f2020-12-17 20:25:35 +0100118 in->line = 1;
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200119 in->length = length;
120 }
121
122 return prev_fd;
123}
124
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100125LIBYANG_API_DEF LY_ERR
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200126ly_in_new_file(FILE *f, struct ly_in **in)
127{
128 LY_CHECK_ARG_RET(NULL, f, in, LY_EINVAL);
129
130 LY_CHECK_RET(ly_in_new_fd(fileno(f), in));
131
132 /* convert the LY_IN_FD input handler into the LY_IN_FILE */
133 (*in)->type = LY_IN_FILE;
134 (*in)->method.f = f;
135
136 return LY_SUCCESS;
137}
138
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100139LIBYANG_API_DEF FILE *
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200140ly_in_file(struct ly_in *in, FILE *f)
141{
142 FILE *prev_f;
143
144 LY_CHECK_ARG_RET(NULL, in, in->type == LY_IN_FILE, NULL);
145
146 prev_f = in->method.f;
147
148 if (f) {
149 /* convert LY_IN_FILE handler into LY_IN_FD to be able to update it via ly_in_fd() */
150 in->type = LY_IN_FD;
151 in->method.fd = fileno(prev_f);
152 if (ly_in_fd(in, fileno(f)) == -1) {
153 in->type = LY_IN_FILE;
154 in->method.f = prev_f;
155 return NULL;
156 }
157
158 /* if success, convert the result back */
159 in->type = LY_IN_FILE;
160 in->method.f = f;
161 }
162
163 return prev_f;
164}
165
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100166LIBYANG_API_DEF LY_ERR
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200167ly_in_new_memory(const char *str, struct ly_in **in)
168{
169 LY_CHECK_ARG_RET(NULL, str, in, LY_EINVAL);
170
171 *in = calloc(1, sizeof **in);
172 LY_CHECK_ERR_RET(!*in, LOGMEM(NULL), LY_EMEM);
173
174 (*in)->type = LY_IN_MEMORY;
Michal Vasko63f3d842020-07-08 10:10:14 +0200175 (*in)->start = (*in)->current = (*in)->func_start = str;
Radek Krejcid54412f2020-12-17 20:25:35 +0100176 (*in)->line = 1;
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200177
178 return LY_SUCCESS;
179}
180
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100181LIBYANG_API_DEF const char *
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200182ly_in_memory(struct ly_in *in, const char *str)
183{
184 const char *data;
185
186 LY_CHECK_ARG_RET(NULL, in, in->type == LY_IN_MEMORY, NULL);
187
188 data = in->current;
189
190 if (str) {
191 in->start = in->current = str;
Radek Krejcid54412f2020-12-17 20:25:35 +0100192 in->line = 1;
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200193 }
194
195 return data;
196}
197
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100198LIBYANG_API_DEF LY_ERR
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200199ly_in_new_filepath(const char *filepath, size_t len, struct ly_in **in)
200{
Radek Krejci0f969882020-08-21 16:56:47 +0200201 LY_ERR ret;
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200202 char *fp;
203 int fd;
204
205 LY_CHECK_ARG_RET(NULL, filepath, in, LY_EINVAL);
206
207 if (len) {
208 fp = strndup(filepath, len);
209 } else {
210 fp = strdup(filepath);
211 }
212
213 fd = open(fp, O_RDONLY);
Michal Vaskof2eb8af2020-07-14 12:22:40 +0200214 LY_CHECK_ERR_RET(fd == -1, LOGERR(NULL, LY_ESYS, "Failed to open file \"%s\" (%s).", fp, strerror(errno)); free(fp),
Michal Vasko69730152020-10-09 16:30:07 +0200215 LY_ESYS);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200216
217 LY_CHECK_ERR_RET(ret = ly_in_new_fd(fd, in), free(fp), ret);
218
219 /* convert the LY_IN_FD input handler into the LY_IN_FILE */
220 (*in)->type = LY_IN_FILEPATH;
221 (*in)->method.fpath.fd = fd;
222 (*in)->method.fpath.filepath = fp;
223
224 return LY_SUCCESS;
225}
226
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100227LIBYANG_API_DEF const char *
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200228ly_in_filepath(struct ly_in *in, const char *filepath, size_t len)
229{
230 int fd, prev_fd;
231 char *fp = NULL;
232
233 LY_CHECK_ARG_RET(NULL, in, in->type == LY_IN_FILEPATH, filepath ? NULL : ((void *)-1));
234
235 if (!filepath) {
236 return in->method.fpath.filepath;
237 }
238
239 if (len) {
240 fp = strndup(filepath, len);
241 } else {
242 fp = strdup(filepath);
243 }
244
245 /* replace filepath */
246 fd = open(fp, O_RDONLY);
247 LY_CHECK_ERR_RET(!fd, LOGERR(NULL, LY_ESYS, "Failed to open file \"%s\" (%s).", fp, strerror(errno)); free(fp), NULL);
248
249 /* convert LY_IN_FILEPATH handler into LY_IN_FD to be able to update it via ly_in_fd() */
250 in->type = LY_IN_FD;
251 prev_fd = ly_in_fd(in, fd);
252 LY_CHECK_ERR_RET(prev_fd == -1, in->type = LY_IN_FILEPATH; free(fp), NULL);
253
254 /* and convert the result back */
255 in->type = LY_IN_FILEPATH;
256 close(prev_fd);
257 free(in->method.fpath.filepath);
258 in->method.fpath.fd = fd;
259 in->method.fpath.filepath = fp;
260
261 return NULL;
262}
263
264void
265lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
266{
267 char path[PATH_MAX];
Michal Vasko69730152020-10-09 16:30:07 +0200268
Michal Vasko5aa44c02020-06-29 11:47:02 +0200269#ifndef __APPLE__
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200270 char proc_path[32];
271 int len;
Michal Vasko5aa44c02020-06-29 11:47:02 +0200272#endif
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200273
274 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
275 if (*filepath) {
276 /* filepath already set */
277 return;
278 }
279
280 switch (in->type) {
281 case LY_IN_FILEPATH:
282 if (realpath(in->method.fpath.filepath, path) != NULL) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200283 lydict_insert(ctx, path, 0, filepath);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200284 } else {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200285 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200286 }
287
288 break;
289 case LY_IN_FD:
290#ifdef __APPLE__
291 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200292 lydict_insert(ctx, path, 0, filepath);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200293 }
Jan Kundrátca643df2021-12-10 16:47:27 +0100294#elif defined _WIN32
295 HANDLE h = _get_osfhandle(in->method.fd);
296 FILE_NAME_INFO info;
297 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
298 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
299 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
300 lydict_insert(ctx, buf, len, filepath);
301 }
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200302#else
303 /* get URI if there is /proc */
304 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
305 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200306 lydict_insert(ctx, path, len, filepath);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200307 }
308#endif
309 break;
310 case LY_IN_MEMORY:
311 case LY_IN_FILE:
312 /* nothing to do */
313 break;
314 default:
315 LOGINT(ctx);
316 break;
317 }
318
319}
320
Michal Vaskoddd76592022-01-17 13:34:48 +0100321LIBYANG_API_DEF size_t
322ly_in_parsed(const struct ly_in *in)
323{
324 return in->current - in->func_start;
325}
326
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100327LIBYANG_API_DEF void
Radek Krejci857189e2020-09-01 13:26:36 +0200328ly_in_free(struct ly_in *in, ly_bool destroy)
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200329{
330 if (!in) {
331 return;
332 } else if (in->type == LY_IN_ERROR) {
333 LOGINT(NULL);
334 return;
335 }
336
337 if (destroy) {
338 if (in->type == LY_IN_MEMORY) {
Michal Vasko22df3f02020-08-24 13:29:22 +0200339 free((char *)in->start);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200340 } else {
Michal Vasko22df3f02020-08-24 13:29:22 +0200341 ly_munmap((char *)in->start, in->length);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200342
343 if (in->type == LY_IN_FILE) {
344 fclose(in->method.f);
345 } else {
346 close(in->method.fd);
347
348 if (in->type == LY_IN_FILEPATH) {
349 free(in->method.fpath.filepath);
350 }
351 }
352 }
353 } else if (in->type != LY_IN_MEMORY) {
Michal Vasko22df3f02020-08-24 13:29:22 +0200354 ly_munmap((char *)in->start, in->length);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200355
356 if (in->type == LY_IN_FILEPATH) {
357 close(in->method.fpath.fd);
358 free(in->method.fpath.filepath);
359 }
360 }
361
362 free(in);
363}
Michal Vasko63f3d842020-07-08 10:10:14 +0200364
365LY_ERR
366ly_in_read(struct ly_in *in, void *buf, size_t count)
367{
368 if (in->length && (in->length - (in->current - in->start) < count)) {
369 /* EOF */
370 return LY_EDENIED;
371 }
372
Michal Vasko08e9b112021-06-11 15:41:17 +0200373 if (count) {
374 memcpy(buf, in->current, count);
375 }
Michal Vasko63f3d842020-07-08 10:10:14 +0200376 in->current += count;
377 return LY_SUCCESS;
378}
379
Michal Vasko63f3d842020-07-08 10:10:14 +0200380LY_ERR
381ly_in_skip(struct ly_in *in, size_t count)
382{
383 if (in->length && (in->length - (in->current - in->start) < count)) {
384 /* EOF */
385 return LY_EDENIED;
386 }
387
388 in->current += count;
389 return LY_SUCCESS;
390}
Radek Krejci1798aae2020-07-14 13:26:06 +0200391
392void
393lyd_ctx_free(struct lyd_ctx *lydctx)
394{
Michal Vasko32711382020-12-03 14:14:31 +0100395 ly_set_erase(&lydctx->node_types, NULL);
396 ly_set_erase(&lydctx->meta_types, NULL);
397 ly_set_erase(&lydctx->node_when, NULL);
Michal Vaskoddd76592022-01-17 13:34:48 +0100398 ly_set_erase(&lydctx->ext_val, free);
Radek Krejci1798aae2020-07-14 13:26:06 +0200399}
400
401LY_ERR
Michal Vaskoe0665742021-02-11 11:08:44 +0100402lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, struct lyd_node **op)
403{
404 const struct lyd_node *iter;
405
406 *op = NULL;
407
408 if (!parent) {
409 /* no parent, nothing to look for */
410 return LY_SUCCESS;
411 }
412
413 /* we need to find the operation node if it already exists */
414 for (iter = parent; iter; iter = lyd_parent(iter)) {
415 if (iter->schema && (iter->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
416 break;
417 }
418 }
419
420 if (!iter) {
421 /* no operation found */
422 return LY_SUCCESS;
423 }
424
425 if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
426 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
427 lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
428 return LY_EINVAL;
429 } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
430 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
431 iter->schema->name);
432 return LY_EINVAL;
433 } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
434 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
435 iter->schema->name);
436 return LY_EINVAL;
437 } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
438 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
439 iter->schema->name);
440 return LY_EINVAL;
441 }
442
443 *op = (struct lyd_node *)iter;
444 return LY_SUCCESS;
445}
446
447LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200448lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
449{
Michal Vaskoe0665742021-02-11 11:08:44 +0100450 LY_ERR rc = LY_SUCCESS;
Radek Krejci2efc45b2020-12-22 16:25:44 +0100451
Radek Krejciddace2c2021-01-08 11:30:56 +0100452 LOG_LOCSET(snode, NULL, NULL, NULL);
Radek Krejci1798aae2020-07-14 13:26:06 +0200453
Michal Vasko02ed9d82021-07-15 14:58:04 +0200454 if (lydctx->int_opts & LYD_INTOPT_ANY) {
455 /* nothing to check, everything is allowed */
456 goto cleanup;
457 }
458
Michal Vaskoe0665742021-02-11 11:08:44 +0100459 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
Michal Vasko224e7772021-02-18 14:22:33 +0100460 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
Michal Vaskoe0665742021-02-11 11:08:44 +0100461 rc = LY_EVALID;
Radek Krejci2efc45b2020-12-22 16:25:44 +0100462 goto cleanup;
Radek Krejci1798aae2020-07-14 13:26:06 +0200463 }
464
Michal Vaskoe0665742021-02-11 11:08:44 +0100465 if (snode->nodetype == LYS_RPC) {
Michal Vasko2552ea32020-12-08 15:32:34 +0100466 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200467 if (lydctx->op_node) {
Michal Vaskoe0665742021-02-11 11:08:44 +0100468 goto error_node_dup;
Radek Krejci1798aae2020-07-14 13:26:06 +0200469 }
470 } else {
Michal Vaskoe0665742021-02-11 11:08:44 +0100471 goto error_node_inval;
472 }
473 } else if (snode->nodetype == LYS_ACTION) {
474 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
475 if (lydctx->op_node) {
476 goto error_node_dup;
477 }
478 } else {
479 goto error_node_inval;
Radek Krejci1798aae2020-07-14 13:26:06 +0200480 }
481 } else if (snode->nodetype == LYS_NOTIF) {
482 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
483 if (lydctx->op_node) {
Michal Vaskoe0665742021-02-11 11:08:44 +0100484 goto error_node_dup;
Radek Krejci1798aae2020-07-14 13:26:06 +0200485 }
486 } else {
Michal Vaskoe0665742021-02-11 11:08:44 +0100487 goto error_node_inval;
Radek Krejci1798aae2020-07-14 13:26:06 +0200488 }
489 }
490
Michal Vaskoe0665742021-02-11 11:08:44 +0100491 /* success */
492 goto cleanup;
493
494error_node_dup:
495 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
496 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
497 lydctx->op_node->schema->name);
498 rc = LY_EVALID;
499 goto cleanup;
500
501error_node_inval:
502 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
503 snode->name);
504 rc = LY_EVALID;
Radek Krejci2efc45b2020-12-22 16:25:44 +0100505
506cleanup:
Radek Krejciddace2c2021-01-08 11:30:56 +0100507 LOG_LOCBACK(1, 0, 0, 0);
Michal Vaskoe0665742021-02-11 11:08:44 +0100508 return rc;
Radek Krejci1798aae2020-07-14 13:26:06 +0200509}
510
511LY_ERR
Radek Krejci09c77442021-04-26 11:10:34 +0200512lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
Radek Krejci8df109d2021-04-23 12:19:08 +0200513 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
Radek Krejci1798aae2020-07-14 13:26:06 +0200514{
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200515 ly_bool incomplete;
Radek Krejci1798aae2020-07-14 13:26:06 +0200516
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200517 LY_CHECK_RET(lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node));
518
Michal Vaskoe0665742021-02-11 11:08:44 +0100519 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
Michal Vasko32711382020-12-03 14:14:31 +0100520 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
Radek Krejci1798aae2020-07-14 13:26:06 +0200521 }
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200522 return LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +0200523}
524
525LY_ERR
526lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
Radek Krejcif9943642021-04-26 10:18:21 +0200527 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
Michal Vaskoddd76592022-01-17 13:34:48 +0100528 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
Radek Krejci1798aae2020-07-14 13:26:06 +0200529{
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200530 ly_bool incomplete;
Michal Vaskob68571a2020-11-06 17:18:41 +0100531 struct lyd_meta *first = NULL;
532
533 if (meta && *meta) {
534 /* remember the first metadata */
535 first = *meta;
536 }
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200537
538 LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
Michal Vaskoddd76592022-01-17 13:34:48 +0100539 hints, ctx_node, 0, &incomplete));
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200540
Michal Vaskoe0665742021-02-11 11:08:44 +0100541 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
Michal Vasko32711382020-12-03 14:14:31 +0100542 LY_CHECK_RET(ly_set_add(&lydctx->meta_types, *meta, 1, NULL));
Radek Krejci1798aae2020-07-14 13:26:06 +0200543 }
Michal Vaskob68571a2020-11-06 17:18:41 +0100544
545 if (first) {
546 /* always return the first metadata */
547 *meta = first;
548 }
549
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200550 return LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +0200551}