blob: c16b1c3567d08d57d4c93a469702142f47e7e52b [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
Radek Krejcif0e1ba52020-05-22 15:14:35 +020061ly_in_new_fd(int fd, struct ly_in **in)
62{
63 size_t length;
64 char *addr;
65
66 LY_CHECK_ARG_RET(NULL, fd >= 0, in, LY_EINVAL);
67
68 LY_CHECK_RET(ly_mmap(NULL, fd, &length, (void **)&addr));
69 if (!addr) {
70 LOGERR(NULL, LY_EINVAL, "Empty input file.");
71 return LY_EINVAL;
72 }
73
74 *in = calloc(1, sizeof **in);
75 LY_CHECK_ERR_RET(!*in, LOGMEM(NULL); ly_munmap(addr, length), LY_EMEM);
76
77 (*in)->type = LY_IN_FD;
78 (*in)->method.fd = fd;
Michal Vasko63f3d842020-07-08 10:10:14 +020079 (*in)->current = (*in)->start = (*in)->func_start = addr;
Radek Krejcid54412f2020-12-17 20:25:35 +010080 (*in)->line = 1;
Radek Krejcif0e1ba52020-05-22 15:14:35 +020081 (*in)->length = length;
82
83 return LY_SUCCESS;
84}
85
Jan Kundrátc53a7ec2021-12-09 16:01:19 +010086LIBYANG_API_DEF int
Radek Krejcif0e1ba52020-05-22 15:14:35 +020087ly_in_fd(struct ly_in *in, int fd)
88{
89 int prev_fd;
90 size_t length;
91 const char *addr;
92
93 LY_CHECK_ARG_RET(NULL, in, in->type == LY_IN_FD, -1);
94
95 prev_fd = in->method.fd;
96
97 if (fd != -1) {
98 LY_CHECK_RET(ly_mmap(NULL, fd, &length, (void **)&addr), -1);
99 if (!addr) {
100 LOGERR(NULL, LY_EINVAL, "Empty input file.");
101 return -1;
102 }
103
Michal Vasko22df3f02020-08-24 13:29:22 +0200104 ly_munmap((char *)in->start, in->length);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200105
106 in->method.fd = fd;
107 in->current = in->start = addr;
Radek Krejcid54412f2020-12-17 20:25:35 +0100108 in->line = 1;
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200109 in->length = length;
110 }
111
112 return prev_fd;
113}
114
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100115LIBYANG_API_DEF LY_ERR
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200116ly_in_new_file(FILE *f, struct ly_in **in)
117{
118 LY_CHECK_ARG_RET(NULL, f, in, LY_EINVAL);
119
120 LY_CHECK_RET(ly_in_new_fd(fileno(f), in));
121
122 /* convert the LY_IN_FD input handler into the LY_IN_FILE */
123 (*in)->type = LY_IN_FILE;
124 (*in)->method.f = f;
125
126 return LY_SUCCESS;
127}
128
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100129LIBYANG_API_DEF FILE *
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200130ly_in_file(struct ly_in *in, FILE *f)
131{
132 FILE *prev_f;
133
134 LY_CHECK_ARG_RET(NULL, in, in->type == LY_IN_FILE, NULL);
135
136 prev_f = in->method.f;
137
138 if (f) {
139 /* convert LY_IN_FILE handler into LY_IN_FD to be able to update it via ly_in_fd() */
140 in->type = LY_IN_FD;
141 in->method.fd = fileno(prev_f);
142 if (ly_in_fd(in, fileno(f)) == -1) {
143 in->type = LY_IN_FILE;
144 in->method.f = prev_f;
145 return NULL;
146 }
147
148 /* if success, convert the result back */
149 in->type = LY_IN_FILE;
150 in->method.f = f;
151 }
152
153 return prev_f;
154}
155
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100156LIBYANG_API_DEF LY_ERR
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200157ly_in_new_memory(const char *str, struct ly_in **in)
158{
159 LY_CHECK_ARG_RET(NULL, str, in, LY_EINVAL);
160
161 *in = calloc(1, sizeof **in);
162 LY_CHECK_ERR_RET(!*in, LOGMEM(NULL), LY_EMEM);
163
164 (*in)->type = LY_IN_MEMORY;
Michal Vasko63f3d842020-07-08 10:10:14 +0200165 (*in)->start = (*in)->current = (*in)->func_start = str;
Radek Krejcid54412f2020-12-17 20:25:35 +0100166 (*in)->line = 1;
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200167
168 return LY_SUCCESS;
169}
170
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100171LIBYANG_API_DEF const char *
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200172ly_in_memory(struct ly_in *in, const char *str)
173{
174 const char *data;
175
176 LY_CHECK_ARG_RET(NULL, in, in->type == LY_IN_MEMORY, NULL);
177
178 data = in->current;
179
180 if (str) {
181 in->start = in->current = str;
Radek Krejcid54412f2020-12-17 20:25:35 +0100182 in->line = 1;
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200183 }
184
185 return data;
186}
187
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100188LIBYANG_API_DEF LY_ERR
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200189ly_in_reset(struct ly_in *in)
190{
191 LY_CHECK_ARG_RET(NULL, in, LY_EINVAL);
192
Michal Vasko63f3d842020-07-08 10:10:14 +0200193 in->current = in->func_start = in->start;
Radek Krejcid54412f2020-12-17 20:25:35 +0100194 in->line = 1;
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200195 return LY_SUCCESS;
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
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100321LIBYANG_API_DEF void
Radek Krejci857189e2020-09-01 13:26:36 +0200322ly_in_free(struct ly_in *in, ly_bool destroy)
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200323{
324 if (!in) {
325 return;
326 } else if (in->type == LY_IN_ERROR) {
327 LOGINT(NULL);
328 return;
329 }
330
331 if (destroy) {
332 if (in->type == LY_IN_MEMORY) {
Michal Vasko22df3f02020-08-24 13:29:22 +0200333 free((char *)in->start);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200334 } else {
Michal Vasko22df3f02020-08-24 13:29:22 +0200335 ly_munmap((char *)in->start, in->length);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200336
337 if (in->type == LY_IN_FILE) {
338 fclose(in->method.f);
339 } else {
340 close(in->method.fd);
341
342 if (in->type == LY_IN_FILEPATH) {
343 free(in->method.fpath.filepath);
344 }
345 }
346 }
347 } else if (in->type != LY_IN_MEMORY) {
Michal Vasko22df3f02020-08-24 13:29:22 +0200348 ly_munmap((char *)in->start, in->length);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200349
350 if (in->type == LY_IN_FILEPATH) {
351 close(in->method.fpath.fd);
352 free(in->method.fpath.filepath);
353 }
354 }
355
356 free(in);
357}
Michal Vasko63f3d842020-07-08 10:10:14 +0200358
359LY_ERR
360ly_in_read(struct ly_in *in, void *buf, size_t count)
361{
362 if (in->length && (in->length - (in->current - in->start) < count)) {
363 /* EOF */
364 return LY_EDENIED;
365 }
366
Michal Vasko08e9b112021-06-11 15:41:17 +0200367 if (count) {
368 memcpy(buf, in->current, count);
369 }
Michal Vasko63f3d842020-07-08 10:10:14 +0200370 in->current += count;
371 return LY_SUCCESS;
372}
373
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100374LIBYANG_API_DEF size_t
Michal Vasko63f3d842020-07-08 10:10:14 +0200375ly_in_parsed(const struct ly_in *in)
376{
377 return in->current - in->func_start;
378}
379
380LY_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);
Radek Krejci4f2e3e52021-03-30 14:20:28 +0200398 ly_set_erase(&lydctx->node_exts, NULL);
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 Vaskofeca4fb2020-10-05 08:58:40 +0200528 void *prefix_data, uint32_t hints)
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 Vasko871a0252020-11-11 18:35:24 +0100539 hints, 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}