blob: dfa6bf7e11b04e77e7bcf9cc8bfb82baf116839c [file] [log] [blame]
Radek Krejci3f5e3db2018-10-11 15:57:47 +02001/**
2 * @file tree_schema.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Schema tree implementation
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
Radek Krejci86d106e2018-10-18 09:53:19 +020014#define _DEFAULT_SOURCE
15
16#include <errno.h>
17#include <fcntl.h>
18#include <linux/limits.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <sys/stat.h>
22#include <sys/types.h>
23#include <unistd.h>
Radek Krejci3f5e3db2018-10-11 15:57:47 +020024
25#include "libyang.h"
26#include "common.h"
Radek Krejci86d106e2018-10-18 09:53:19 +020027#include "context.h"
Radek Krejci70853c52018-10-15 14:46:16 +020028#include "tree_schema_internal.h"
Radek Krejci3f5e3db2018-10-11 15:57:47 +020029
Radek Krejcie53a8dc2018-10-17 12:52:40 +020030#define FREE_ARRAY(CTX, ARRAY, FUNC) {uint64_t c__; LY_ARRAY_FOR(ARRAY, c__){FUNC(CTX, LY_ARRAY_INDEX(ARRAY, c__), dict);}free(ARRAY);}
Radek Krejcidd4e8d42018-10-16 14:55:43 +020031#define FREE_MEMBER(CTX, MEMBER, FUNC) if (MEMBER) {FUNC(CTX, MEMBER, dict);free(MEMBER);}
32#define FREE_STRING(CTX, STRING) if (dict && STRING) {lydict_remove(CTX, STRING);}
Radek Krejci6f7feb62018-10-12 15:23:02 +020033
Radek Krejcidd4e8d42018-10-16 14:55:43 +020034static void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp, int dict);
35static void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node, int dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +020036
Radek Krejci86d106e2018-10-18 09:53:19 +020037#define LYSC_CTX_BUFSIZE 4086
38struct lysc_ctx {
39 struct lysc_module *mod;
40 uint16_t path_len;
41 char path[LYSC_CTX_BUFSIZE];
42};
43
Radek Krejci6f7feb62018-10-12 15:23:02 +020044static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +020045lysp_stmt_free(struct ly_ctx *ctx, struct lysp_stmt *stmt, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +020046{
47 struct lysp_stmt *child, *next;
48
49 FREE_STRING(ctx, stmt->stmt);
50 FREE_STRING(ctx, stmt->arg);
51
52 LY_LIST_FOR_SAFE(stmt->child, next, child) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +020053 lysp_stmt_free(ctx, child, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +020054 }
55
56 free(stmt);
57}
58
59static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +020060lysp_ext_instance_free(struct ly_ctx *ctx, struct lysp_ext_instance *ext, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +020061{
62 struct lysp_stmt *stmt, *next;
63
64 FREE_STRING(ctx, ext->name);
65 FREE_STRING(ctx, ext->argument);
66
67 LY_LIST_FOR_SAFE(ext->child, next, stmt) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +020068 lysp_stmt_free(ctx, stmt, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +020069 }
70}
71
72static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +020073lysp_import_free(struct ly_ctx *ctx, struct lysp_import *import, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +020074{
Radek Krejci6f7feb62018-10-12 15:23:02 +020075 FREE_STRING(ctx, import->name);
76 FREE_STRING(ctx, import->prefix);
77 FREE_STRING(ctx, import->dsc);
78 FREE_STRING(ctx, import->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +020079 FREE_ARRAY(ctx, import->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +020080}
81
82static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +020083lysp_include_free(struct ly_ctx *ctx, struct lysp_include *include, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +020084{
Radek Krejci6f7feb62018-10-12 15:23:02 +020085 FREE_STRING(ctx, include->name);
86 FREE_STRING(ctx, include->dsc);
87 FREE_STRING(ctx, include->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +020088 FREE_ARRAY(ctx, include->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +020089}
90
91static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +020092lysp_revision_free(struct ly_ctx *ctx, struct lysp_revision *rev, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +020093{
Radek Krejci6f7feb62018-10-12 15:23:02 +020094 FREE_STRING(ctx, rev->dsc);
95 FREE_STRING(ctx, rev->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +020096 FREE_ARRAY(ctx, rev->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +020097}
98
99static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200100lysp_ext_free(struct ly_ctx *ctx, struct lysp_ext *ext, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200101{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200102 FREE_STRING(ctx, ext->name);
103 FREE_STRING(ctx, ext->argument);
104 FREE_STRING(ctx, ext->dsc);
105 FREE_STRING(ctx, ext->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200106 FREE_ARRAY(ctx, ext->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200107}
108
109static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200110lysp_feature_free(struct ly_ctx *ctx, struct lysp_feature *feat, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200111{
112 unsigned int u;
113 FREE_STRING(ctx, feat->name);
114 for (u = 0; feat->iffeatures && feat->iffeatures[u]; ++u) {
115 FREE_STRING(ctx, feat->iffeatures[u]);
116 }
117 free(feat->iffeatures);
118 FREE_STRING(ctx, feat->dsc);
119 FREE_STRING(ctx, feat->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200120 FREE_ARRAY(ctx, feat->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200121}
122
123static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200124lysp_ident_free(struct ly_ctx *ctx, struct lysp_ident *ident, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200125{
126 unsigned int u;
127 FREE_STRING(ctx, ident->name);
128 for (u = 0; ident->iffeatures && ident->iffeatures[u]; ++u) {
129 FREE_STRING(ctx, ident->iffeatures[u]);
130 }
131 free(ident->iffeatures);
132 for (u = 0; ident->bases && ident->bases[u]; ++u) {
133 FREE_STRING(ctx, ident->bases[u]);
134 }
135 free(ident->bases);
136 FREE_STRING(ctx, ident->dsc);
137 FREE_STRING(ctx, ident->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200138 FREE_ARRAY(ctx, ident->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200139}
140
141static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200142lysp_restr_free(struct ly_ctx *ctx, struct lysp_restr *restr, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200143{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200144 FREE_STRING(ctx, restr->arg);
145 FREE_STRING(ctx, restr->emsg);
146 FREE_STRING(ctx, restr->eapptag);
147 FREE_STRING(ctx, restr->dsc);
148 FREE_STRING(ctx, restr->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200149 FREE_ARRAY(ctx, restr->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200150}
151
152static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200153lysp_type_enum_free(struct ly_ctx *ctx, struct lysp_type_enum *item, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200154{
155 unsigned int u;
156 FREE_STRING(ctx, item->name);
157 FREE_STRING(ctx, item->dsc);
158 FREE_STRING(ctx, item->ref);
159 for (u = 0; item->iffeatures && item->iffeatures[u]; ++u) {
160 FREE_STRING(ctx, item->iffeatures[u]);
161 }
162 free(item->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200163 FREE_ARRAY(ctx, item->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200164}
165
166static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200167lysp_type_free(struct ly_ctx *ctx, struct lysp_type *type, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200168{
169 unsigned int u;
170 FREE_STRING(ctx, type->name);
171 FREE_MEMBER(ctx, type->range, lysp_restr_free);
172 FREE_MEMBER(ctx, type->length, lysp_restr_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200173 FREE_ARRAY(ctx, type->patterns, lysp_restr_free);
174 FREE_ARRAY(ctx, type->enums, lysp_type_enum_free);
175 FREE_ARRAY(ctx, type->bits, lysp_type_enum_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200176 FREE_STRING(ctx, type->path);
177 for (u = 0; type->bases && type->bases[u]; ++u) {
178 FREE_STRING(ctx, type->bases[u]);
179 }
180 free(type->bases);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200181 FREE_ARRAY(ctx, type->types, lysp_type_free);
182 FREE_ARRAY(ctx, type->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200183}
184
185static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200186lysp_tpdf_free(struct ly_ctx *ctx, struct lysp_tpdf *tpdf, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200187{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200188 FREE_STRING(ctx, tpdf->name);
189 FREE_STRING(ctx, tpdf->units);
190 FREE_STRING(ctx, tpdf->dflt);
191 FREE_STRING(ctx, tpdf->dsc);
192 FREE_STRING(ctx, tpdf->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200193 FREE_ARRAY(ctx, tpdf->exts, lysp_ext_instance_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200194 lysp_type_free(ctx, &tpdf->type, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200195}
196
197static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200198lysp_action_inout_free(struct ly_ctx *ctx, struct lysp_action_inout *inout, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200199{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200200 struct lysp_node *node, *next;
201
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200202 FREE_ARRAY(ctx, inout->musts, lysp_restr_free);
203 FREE_ARRAY(ctx, inout->typedefs, lysp_tpdf_free);
204 FREE_ARRAY(ctx, inout->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200205 LY_LIST_FOR_SAFE(inout->data, next, node) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200206 lysp_node_free(ctx, node, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200207 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200208 FREE_ARRAY(ctx, inout->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200209
210}
211
212static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200213lysp_action_free(struct ly_ctx *ctx, struct lysp_action *action, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200214{
215 unsigned int u;
216 FREE_STRING(ctx, action->name);
217 FREE_STRING(ctx, action->dsc);
218 FREE_STRING(ctx, action->ref);
219 for (u = 0; action->iffeatures && action->iffeatures[u]; ++u) {
220 FREE_STRING(ctx, action->iffeatures[u]);
221 }
222 free(action->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200223 FREE_ARRAY(ctx, action->typedefs, lysp_tpdf_free);
224 FREE_ARRAY(ctx, action->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200225 FREE_MEMBER(ctx, action->input, lysp_action_inout_free);
226 FREE_MEMBER(ctx, action->output, lysp_action_inout_free);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200227 FREE_ARRAY(ctx, action->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200228}
229
230static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200231lysp_notif_free(struct ly_ctx *ctx, struct lysp_notif *notif, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200232{
233 unsigned int u;
234 struct lysp_node *node, *next;
235
236 FREE_STRING(ctx, notif->name);
237 FREE_STRING(ctx, notif->dsc);
238 FREE_STRING(ctx, notif->ref);
239 for (u = 0; notif->iffeatures && notif->iffeatures[u]; ++u) {
240 FREE_STRING(ctx, notif->iffeatures[u]);
241 }
242 free(notif->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200243 FREE_ARRAY(ctx, notif->musts, lysp_restr_free);
244 FREE_ARRAY(ctx, notif->typedefs, lysp_tpdf_free);
245 FREE_ARRAY(ctx, notif->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200246 LY_LIST_FOR_SAFE(notif->data, next, node) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200247 lysp_node_free(ctx, node, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200248 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200249 FREE_ARRAY(ctx, notif->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200250}
251
252static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200253lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200254{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200255 struct lysp_node *node, *next;
256
257 FREE_STRING(ctx, grp->name);
258 FREE_STRING(ctx, grp->dsc);
259 FREE_STRING(ctx, grp->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200260 FREE_ARRAY(ctx, grp->typedefs, lysp_tpdf_free);
261 FREE_ARRAY(ctx, grp->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200262 LY_LIST_FOR_SAFE(grp->data, next, node) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200263 lysp_node_free(ctx, node, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200264 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200265 FREE_ARRAY(ctx, grp->actions, lysp_action_free);
266 FREE_ARRAY(ctx, grp->notifs, lysp_notif_free);
267 FREE_ARRAY(ctx, grp->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200268}
269
270static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200271lysp_when_free(struct ly_ctx *ctx, struct lysp_when *when, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200272{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200273 FREE_STRING(ctx, when->cond);
274 FREE_STRING(ctx, when->dsc);
275 FREE_STRING(ctx, when->ref);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200276 FREE_ARRAY(ctx, when->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200277}
278
279static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200280lysp_augment_free(struct ly_ctx *ctx, struct lysp_augment *augment, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200281{
282 unsigned int u;
283 struct lysp_node *node, *next;
284
285 FREE_STRING(ctx, augment->nodeid);
286 FREE_STRING(ctx, augment->dsc);
287 FREE_STRING(ctx, augment->ref);
288 FREE_MEMBER(ctx, augment->when, lysp_when_free);
289 for (u = 0; augment->iffeatures && augment->iffeatures[u]; ++u) {
290 FREE_STRING(ctx, augment->iffeatures[u]);
291 }
292 free(augment->iffeatures);
293 LY_LIST_FOR_SAFE(augment->child, next, node) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200294 lysp_node_free(ctx, node, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200295 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200296 FREE_ARRAY(ctx, augment->actions, lysp_action_free);
297 FREE_ARRAY(ctx, augment->notifs, lysp_notif_free);
298 FREE_ARRAY(ctx, augment->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200299}
300
301static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200302lysp_deviate_free(struct ly_ctx *ctx, struct lysp_deviate *d, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200303{
304 unsigned int u;
305 struct lysp_deviate_add *add = (struct lysp_deviate_add*)d;
306 struct lysp_deviate_rpl *rpl = (struct lysp_deviate_rpl*)d;
307
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200308 FREE_ARRAY(ctx, d->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200309 switch(d->mod) {
310 case LYS_DEV_NOT_SUPPORTED:
311 /* nothing to do */
312 break;
313 case LYS_DEV_ADD:
314 case LYS_DEV_DELETE: /* compatible for dynamically allocated data */
315 FREE_STRING(ctx, add->units);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200316 FREE_ARRAY(ctx, add->musts, lysp_restr_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200317 for (u = 0; add->uniques && add->uniques[u]; ++u) {
318 FREE_STRING(ctx, add->uniques[u]);
319 }
320 free(add->uniques);
321 for (u = 0; add->dflts && add->dflts[u]; ++u) {
322 FREE_STRING(ctx, add->dflts[u]);
323 }
324 free(add->dflts);
325 break;
326 case LYS_DEV_REPLACE:
327 FREE_MEMBER(ctx, rpl->type, lysp_type_free);
328 FREE_STRING(ctx, rpl->units);
329 FREE_STRING(ctx, rpl->dflt);
330 break;
331 default:
332 LOGINT(ctx);
333 break;
334 }
335}
336
337static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200338lysp_deviation_free(struct ly_ctx *ctx, struct lysp_deviation *dev, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200339{
Radek Krejci6f7feb62018-10-12 15:23:02 +0200340 struct lysp_deviate *next, *iter;
341
342 FREE_STRING(ctx, dev->nodeid);
343 FREE_STRING(ctx, dev->dsc);
344 FREE_STRING(ctx, dev->ref);
345 LY_LIST_FOR_SAFE(dev->deviates, next, iter) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200346 lysp_deviate_free(ctx, iter, dict);
Michal Vasko8447f6a2018-10-15 10:56:16 +0200347 free(iter);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200348 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200349 FREE_ARRAY(ctx, dev->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200350}
351
352static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200353lysp_refine_free(struct ly_ctx *ctx, struct lysp_refine *ref, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200354{
355 unsigned int u;
356 FREE_STRING(ctx, ref->nodeid);
357 FREE_STRING(ctx, ref->dsc);
358 FREE_STRING(ctx, ref->ref);
359 for (u = 0; ref->iffeatures && ref->iffeatures[u]; ++u) {
360 FREE_STRING(ctx, ref->iffeatures[u]);
361 }
362 free(ref->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200363 FREE_ARRAY(ctx, ref->musts, lysp_restr_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200364 FREE_STRING(ctx, ref->presence);
365 for (u = 0; ref->dflts && ref->dflts[u]; ++u) {
366 FREE_STRING(ctx, ref->dflts[u]);
367 }
368 free(ref->dflts);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200369 FREE_ARRAY(ctx, ref->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200370}
371
372static void
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200373lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node, int dict)
Radek Krejci6f7feb62018-10-12 15:23:02 +0200374{
375 unsigned int u;
376 struct lysp_node *child, *next;
377
378 FREE_STRING(ctx, node->name);
379 FREE_STRING(ctx, node->dsc);
380 FREE_STRING(ctx, node->ref);
381 FREE_MEMBER(ctx, node->when, lysp_when_free);
382 for (u = 0; node->iffeatures && node->iffeatures[u]; ++u) {
383 FREE_STRING(ctx, node->iffeatures[u]);
384 }
385 free(node->iffeatures);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200386 FREE_ARRAY(ctx, node->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200387
388 switch(node->nodetype) {
389 case LYS_CONTAINER:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200390 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->musts, lysp_restr_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200391 FREE_STRING(ctx, ((struct lysp_node_container*)node)->presence);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200392 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->typedefs, lysp_tpdf_free);
393 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200394 LY_LIST_FOR_SAFE(((struct lysp_node_container*)node)->child, next, child) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200395 lysp_node_free(ctx, child, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200396 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200397 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->actions, lysp_action_free);
398 FREE_ARRAY(ctx, ((struct lysp_node_container*)node)->notifs, lysp_notif_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200399 break;
400 case LYS_LEAF:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200401 FREE_ARRAY(ctx, ((struct lysp_node_leaf*)node)->musts, lysp_restr_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200402 lysp_type_free(ctx, &((struct lysp_node_leaf*)node)->type, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200403 FREE_STRING(ctx, ((struct lysp_node_leaf*)node)->units);
404 FREE_STRING(ctx, ((struct lysp_node_leaf*)node)->dflt);
405 break;
406 case LYS_LEAFLIST:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200407 FREE_ARRAY(ctx, ((struct lysp_node_leaflist*)node)->musts, lysp_restr_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200408 lysp_type_free(ctx, &((struct lysp_node_leaflist*)node)->type, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200409 FREE_STRING(ctx, ((struct lysp_node_leaflist*)node)->units);
410 for (u = 0; ((struct lysp_node_leaflist*)node)->dflts && ((struct lysp_node_leaflist*)node)->dflts[u]; ++u) {
411 FREE_STRING(ctx, ((struct lysp_node_leaflist*)node)->dflts[u]);
412 }
413 free(((struct lysp_node_leaflist*)node)->dflts);
414 break;
415 case LYS_LIST:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200416 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->musts, lysp_restr_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200417 FREE_STRING(ctx, ((struct lysp_node_list*)node)->key);
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200418 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->typedefs, lysp_tpdf_free);
419 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200420 LY_LIST_FOR_SAFE(((struct lysp_node_list*)node)->child, next, child) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200421 lysp_node_free(ctx, child, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200422 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200423 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->actions, lysp_action_free);
424 FREE_ARRAY(ctx, ((struct lysp_node_list*)node)->notifs, lysp_notif_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200425 for (u = 0; ((struct lysp_node_list*)node)->uniques && ((struct lysp_node_list*)node)->uniques[u]; ++u) {
426 FREE_STRING(ctx, ((struct lysp_node_list*)node)->uniques[u]);
427 }
428 free(((struct lysp_node_list*)node)->uniques);
429 break;
430 case LYS_CHOICE:
431 LY_LIST_FOR_SAFE(((struct lysp_node_choice*)node)->child, next, child) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200432 lysp_node_free(ctx, child, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200433 }
434 FREE_STRING(ctx, ((struct lysp_node_choice*)node)->dflt);
435 break;
436 case LYS_CASE:
437 LY_LIST_FOR_SAFE(((struct lysp_node_case*)node)->child, next, child) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200438 lysp_node_free(ctx, child, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200439 }
440 break;
441 case LYS_ANYDATA:
442 case LYS_ANYXML:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200443 FREE_ARRAY(ctx, ((struct lysp_node_anydata*)node)->musts, lysp_restr_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200444 break;
445 case LYS_USES:
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200446 FREE_ARRAY(ctx, ((struct lysp_node_uses*)node)->refines, lysp_refine_free);
447 FREE_ARRAY(ctx, ((struct lysp_node_uses*)node)->augments, lysp_augment_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200448 break;
449 default:
450 LOGINT(ctx);
451 }
452
453 free(node);
454}
455
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200456static void
457lysp_module_free_(struct lysp_module *module, int dict)
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200458{
459 struct ly_ctx *ctx;
Radek Krejci6f7feb62018-10-12 15:23:02 +0200460 struct lysp_node *node, *next;
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200461
462 LY_CHECK_ARG_RET(NULL, module,);
463 ctx = module->ctx;
464
Radek Krejci6f7feb62018-10-12 15:23:02 +0200465 FREE_STRING(ctx, module->name);
466 FREE_STRING(ctx, module->filepath);
467 FREE_STRING(ctx, module->ns); /* or belongs-to */
468 FREE_STRING(ctx, module->prefix);
469
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200470 FREE_ARRAY(ctx, module->imports, lysp_import_free);
471 FREE_ARRAY(ctx, module->includes, lysp_include_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200472
473 FREE_STRING(ctx, module->org);
474 FREE_STRING(ctx, module->contact);
475 FREE_STRING(ctx, module->dsc);
476 FREE_STRING(ctx, module->ref);
477
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200478 FREE_ARRAY(ctx, module->revs, lysp_revision_free);
479 FREE_ARRAY(ctx, module->extensions, lysp_ext_free);
480 FREE_ARRAY(ctx, module->features, lysp_feature_free);
481 FREE_ARRAY(ctx, module->identities, lysp_ident_free);
482 FREE_ARRAY(ctx, module->typedefs, lysp_tpdf_free);
483 FREE_ARRAY(ctx, module->groupings, lysp_grp_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200484 LY_LIST_FOR_SAFE(module->data, next, node) {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200485 lysp_node_free(ctx, node, dict);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200486 }
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200487 FREE_ARRAY(ctx, module->augments, lysp_augment_free);
488 FREE_ARRAY(ctx, module->rpcs, lysp_action_free);
489 FREE_ARRAY(ctx, module->notifs, lysp_notif_free);
490 FREE_ARRAY(ctx, module->deviations, lysp_deviation_free);
491 FREE_ARRAY(ctx, module->exts, lysp_ext_instance_free);
Radek Krejci6f7feb62018-10-12 15:23:02 +0200492
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200493 free(module);
494}
495
496API void
497lysp_module_free(struct lysp_module *module)
498{
499 lysp_module_free_(module, 1);
500}
501
502static void
503lysc_feature_free(struct ly_ctx *ctx, struct lysc_feature *feat, int dict)
504{
505 FREE_STRING(ctx, feat->name);
506
507}
508
509static void
510lysc_module_free_(struct lysc_module *module, int dict)
511{
512 struct ly_ctx *ctx;
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200513
514 LY_CHECK_ARG_RET(NULL, module,);
515 ctx = module->ctx;
516
517 FREE_STRING(ctx, module->name);
518 FREE_STRING(ctx, module->ns);
519 FREE_STRING(ctx, module->prefix);
520
521
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200522 FREE_ARRAY(ctx, module->features, lysc_feature_free);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200523
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200524
525 free(module);
526}
Radek Krejci70853c52018-10-15 14:46:16 +0200527
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200528API void
Radek Krejci86d106e2018-10-18 09:53:19 +0200529lysc_module_free(struct lysc_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv))
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200530{
531 lysc_module_free_(module, 1);
532}
533
Radek Krejci86d106e2018-10-18 09:53:19 +0200534void
535lys_module_free(struct lys_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv))
Radek Krejci70853c52018-10-15 14:46:16 +0200536{
Radek Krejci86d106e2018-10-18 09:53:19 +0200537 if (!module) {
538 return;
539 }
Radek Krejci70853c52018-10-15 14:46:16 +0200540
Radek Krejci86d106e2018-10-18 09:53:19 +0200541 lysc_module_free(module->compiled, private_destructor);
542 lysp_module_free(module->parsed);
543 free(module);
544}
545
546static LY_ERR
547lys_compile_iffeature(struct lysc_ctx *ctx, const char *iff_p, struct lysc_iffeature **iffeatures)
548{
549 struct lysc_iffeature *iff;
550
551 if ((ctx->mod->version != 2) && ((iff_p[0] == '(') || strchr(iff_p, ' '))) {
552 LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path,LY_VCODE_INVAL, strlen(iff_p), iff_p, "if-feature");
553 return LY_EVALID;
Radek Krejci70853c52018-10-15 14:46:16 +0200554 }
Radek Krejci86d106e2018-10-18 09:53:19 +0200555
556 LYSP_ARRAY_NEW_RET(ctx->mod->ctx, *iffeatures, iff, LY_EMEM);
557
Radek Krejci70853c52018-10-15 14:46:16 +0200558 return LY_SUCCESS;
559}
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200560
561static LY_ERR
Radek Krejci86d106e2018-10-18 09:53:19 +0200562lys_compile_feature(struct lysc_ctx *ctx, struct lysp_feature *feature_p, int options, struct lysc_feature **features)
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200563{
564 struct lysc_feature *feature;
Radek Krejci86d106e2018-10-18 09:53:19 +0200565 unsigned int u;
566 LY_ERR ret;
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200567
Radek Krejci86d106e2018-10-18 09:53:19 +0200568 LYSP_ARRAY_NEW_RET(ctx->mod->ctx, *features, feature, LY_EMEM);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200569
570 if (options & LYSC_OPT_FREE_SP) {
571 /* just switch the pointers */
572 feature->name = feature_p->name;
573 } else {
574 /* keep refcounts correct for lysp_module_free() */
Radek Krejci86d106e2018-10-18 09:53:19 +0200575 feature->name = lydict_insert(ctx->mod->ctx, feature_p->name, 0);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200576 }
577 feature->flags = feature_p->flags;
578
Radek Krejci86d106e2018-10-18 09:53:19 +0200579 for (u = 0; feature_p->iffeatures && feature_p->iffeatures[u]; ++u) {
580 ret = lys_compile_iffeature(ctx, feature_p->iffeatures[u], &feature->iffeatures);
581 LY_CHECK_RET(ret);
582 }
583
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200584 return LY_SUCCESS;
585}
586
587LY_ERR
588lys_compile(struct lysp_module *sp, int options, struct lysc_module **sc)
589{
Radek Krejci86d106e2018-10-18 09:53:19 +0200590 struct lysc_ctx ctx = {0};
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200591 struct lysc_module *mod_c;
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200592 void *p;
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200593 LY_ERR ret;
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200594
595 LY_CHECK_ARG_RET(NULL, sc, sp, sp->ctx, LY_EINVAL);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200596
597 if (sp->submodule) {
Radek Krejci86d106e2018-10-18 09:53:19 +0200598 LOGERR(sp->ctx, LY_EINVAL, "Submodules (%s) are not supposed to be compiled, compile only the main modules.", sp->name);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200599 return LY_EINVAL;
600 }
601
Radek Krejci86d106e2018-10-18 09:53:19 +0200602 ctx.mod = mod_c = calloc(1, sizeof *mod_c);
603 LY_CHECK_ERR_RET(!mod_c, LOGMEM(sp->ctx), LY_EMEM);
604 mod_c->ctx = sp->ctx;
605 mod_c->version = sp->version;
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200606
607 if (options & LYSC_OPT_FREE_SP) {
608 /* just switch the pointers */
609 mod_c->name = sp->name;
610 mod_c->ns = sp->ns;
611 mod_c->prefix = sp->prefix;
612 } else {
613 /* keep refcounts correct for lysp_module_free() */
Radek Krejci86d106e2018-10-18 09:53:19 +0200614 mod_c->name = lydict_insert(sp->ctx, sp->name, 0);
615 mod_c->ns = lydict_insert(sp->ctx, sp->ns, 0);
616 mod_c->prefix = lydict_insert(sp->ctx, sp->prefix, 0);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200617 }
618
619 if (sp->features) {
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200620 LY_ARRAY_FOR(sp->features, struct lysp_feature, p) {
Radek Krejci86d106e2018-10-18 09:53:19 +0200621 ret = lys_compile_feature(&ctx, p, options, &mod_c->features);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200622 LY_CHECK_GOTO(ret != LY_SUCCESS, error);
623 }
624 }
625
626 if (options & LYSC_OPT_FREE_SP) {
627 lysp_module_free_(sp, 0);
628 }
629
630 (*sc) = mod_c;
631 return LY_SUCCESS;
632
633error:
634
635 if (options & LYSC_OPT_FREE_SP) {
636 lysc_module_free_(mod_c, 0);
637 } else {
638 lysc_module_free_(mod_c, 1);
639 }
640 return ret;
641}
Radek Krejci86d106e2018-10-18 09:53:19 +0200642
643const struct lys_module *
644lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, const char *revision, int implement)
645{
646 struct lys_module *mod = NULL;
647 LY_ERR ret;
648
649 LY_CHECK_ARG_RET(ctx, ctx, data, NULL);
650
651 mod = calloc(1, sizeof *mod);
652 LY_CHECK_ERR_RET(!mod, LOGMEM(ctx), NULL);
653
654 switch (format) {
655 case LYS_IN_YIN:
656 /* TODO not yet supported
657 mod = yin_read_module(ctx, data, revision, implement);
658 */
659 break;
660 case LYS_IN_YANG:
661 ret = yang_parse(ctx, data, &mod->parsed);
662 LY_CHECK_RET(ret, NULL);
663 break;
664 default:
665 LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
666 break;
667 }
668
669 if (implement) {
670 mod->parsed->implemented = 1;
671 }
672
673 if (revision) {
674 /* check revision of the parsed model */
675 if (!mod->parsed->revs || strcmp(revision, LY_ARRAY_INDEX(mod->parsed->revs, 0, struct lysp_revision)->rev)) {
676 LOGERR(ctx, LY_EINVAL, "Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
677 mod->parsed->name, LY_ARRAY_INDEX(mod->parsed->revs, 0, struct lysp_revision)->rev, revision);
678 lysp_module_free(mod->parsed);
679 free(mod);
680 return NULL;
681 }
682 }
683
684 /* check for duplicity in the context */
685
686 /* add into context */
687 ly_set_add(&ctx->list, mod, LY_SET_OPT_USEASLIST);
688
689#if 0
690 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
691 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
692 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
693 * the anotation definitions available in the internal schema structure. There is another hack in schema
694 * printers to do not print this internally added annotation. */
695 if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
696 if (lyp_add_ietf_netconf_annotations(mod)) {
697 lys_free(mod, NULL, 1, 1);
698 return NULL;
699 }
700 }
701#endif
702
703 return mod;
704}
705
706API const struct lys_module *
707lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
708{
709 return lys_parse_mem_(ctx, data, format, NULL, 1);
710}
711
712static void
713lys_parse_set_filename(struct ly_ctx *ctx, const char **filename, int fd)
714{
715#ifdef __APPLE__
716 char path[MAXPATHLEN];
717#else
718 int len;
719 char path[PATH_MAX], proc_path[32];
720#endif
721
722#ifdef __APPLE__
723 if (fcntl(fd, F_GETPATH, path) != -1) {
724 *filename = lydict_insert(ctx, path, 0);
725 }
726#else
727 /* get URI if there is /proc */
728 sprintf(proc_path, "/proc/self/fd/%d", fd);
729 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
730 *filename = lydict_insert(ctx, path, len);
731 }
732#endif
733}
734
735const struct lys_module *
736lys_parse_fd_(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, const char *revision, int implement)
737{
738 const struct lys_module *mod;
739 size_t length;
740 char *addr;
741
742 LY_CHECK_ARG_RET(ctx, ctx, NULL);
743 if (fd < 0) {
744 LOGARG(ctx, fd);
745 return NULL;
746 }
747
748 LY_CHECK_RET(ly_mmap(ctx, fd, &length, (void **)&addr), NULL);
749 if (!addr) {
750 LOGERR(ctx, LY_EINVAL, "Empty schema file.");
751 return NULL;
752 }
753
754 mod = lys_parse_mem_(ctx, addr, format, revision, implement);
755 ly_munmap(addr, length);
756
757 if (mod && !mod->parsed->filepath) {
758 lys_parse_set_filename(ctx, &mod->parsed->filepath, fd);
759 }
760
761 return mod;
762}
763
764API const struct lys_module *
765lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
766{
767 return lys_parse_fd_(ctx, fd, format, NULL, 1);
768}
769
770API const struct lys_module *
771lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
772{
773 int fd;
774 const struct lys_module *mod;
775 const char *rev, *dot, *filename;
776 size_t len;
777
778 LY_CHECK_ARG_RET(ctx, ctx, path, NULL);
779
780 fd = open(path, O_RDONLY);
781 LY_CHECK_ERR_RET(fd == -1, LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno)), NULL);
782
783 mod = lys_parse_fd(ctx, fd, format);
784 close(fd);
785 LY_CHECK_RET(!mod, NULL);
786
787 /* check that name and revision match filename */
788 filename = strrchr(path, '/');
789 if (!filename) {
790 filename = path;
791 } else {
792 filename++;
793 }
794 rev = strchr(filename, '@');
795 dot = strrchr(filename, '.');
796
797 /* name */
798 len = strlen(mod->parsed->name);
799 if (strncmp(filename, mod->parsed->name, len) ||
800 ((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
801 LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, mod->parsed->name);
802 }
803 if (rev) {
804 len = dot - ++rev;
805 if (!mod->parsed->revs || len != 10 || strncmp(LY_ARRAY_INDEX(mod->parsed->revs, 0, struct lysp_revision)->rev, rev, len)) {
806 LOGWRN(ctx, "File name \"%s\" does not match module revision \"%s\".", filename,
807 mod->parsed->revs ? LY_ARRAY_INDEX(mod->parsed->revs, 0, struct lysp_revision)->rev : "none");
808 }
809 }
810
811 if (!mod->parsed->filepath) {
812 /* store URI */
813 char rpath[PATH_MAX];
814 if (realpath(path, rpath) != NULL) {
815 mod->parsed->filepath = lydict_insert(ctx, rpath, 0);
816 } else {
817 mod->parsed->filepath = lydict_insert(ctx, path, 0);
818 }
819 }
820
821 return mod;
822}
823