blob: 305c9229d3d72a7fe003d879fb55a110e7fbf16c [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file context.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief context implementation for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * 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
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
14
15#define _GNU_SOURCE
Radek Krejcifd4e6e32015-08-10 15:00:51 +020016#include <stddef.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020017#include <stdlib.h>
18#include <string.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <unistd.h>
22#include <errno.h>
23#include <fcntl.h>
24
25#include "common.h"
26#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020027#include "dict_private.h"
Michal Vasko209a6222015-10-16 09:51:07 +020028#include "parser.h"
Radek Krejcibc9cf932015-07-30 11:09:39 +020029#include "tree_internal.h"
Radek Krejci83a4bac2017-02-07 15:53:04 +010030#include "resolve.h"
Radek Krejcida04f4a2015-05-21 12:54:09 +020031
Radek Krejci858ad952017-01-04 11:16:32 +010032/*
33 * counter for references to the extensions plugins (for the number of contexts)
34 * located in extensions.c
35 */
36extern unsigned int ext_plugins_ref;
37
Radek Krejci532e5e92017-02-22 12:59:24 +010038#define IETF_YANG_METADATA_PATH "../models/ietf-yang-metadata@2016-08-05.h"
39#define YANG_PATH "../models/yang@2017-02-20.h"
Michal Vasko8d054e42015-08-03 12:42:06 +020040#define IETF_INET_TYPES_PATH "../models/ietf-inet-types@2013-07-15.h"
Michal Vasko21181c42015-08-03 13:46:45 +020041#define IETF_YANG_TYPES_PATH "../models/ietf-yang-types@2013-07-15.h"
Radek Krejcid9723912016-09-16 17:06:06 +020042#define IETF_YANG_LIB_PATH "../models/ietf-yang-library@2016-06-21.h"
43#define IETF_YANG_LIB_REV "2016-06-21"
Michal Vasko8d054e42015-08-03 12:42:06 +020044
Radek Krejci532e5e92017-02-22 12:59:24 +010045#include IETF_YANG_METADATA_PATH
46#include YANG_PATH
Michal Vasko8d054e42015-08-03 12:42:06 +020047#include IETF_INET_TYPES_PATH
Michal Vasko21181c42015-08-03 13:46:45 +020048#include IETF_YANG_TYPES_PATH
Michal Vasko8d054e42015-08-03 12:42:06 +020049#include IETF_YANG_LIB_PATH
50
Radek Krejci03203412016-06-23 15:20:53 +020051static struct internal_modules_s {
52 const char *name;
53 const char *revision;
54 const char *data;
55 uint8_t implemented;
56 LYS_INFORMAT format;
Michal Vasko2d051a12017-04-21 09:28:57 +020057} internal_modules[LY_INTERNAL_MODULE_COUNT] = {
Radek Krejci532e5e92017-02-22 12:59:24 +010058 {"ietf-yang-metadata", "2016-08-05", (const char*)ietf_yang_metadata_2016_08_05_yin, 0, LYS_IN_YIN},
59 {"yang", "2017-02-20", (const char*)yang_2017_02_20_yin, 1, LYS_IN_YIN},
Radek Krejci03203412016-06-23 15:20:53 +020060 {"ietf-inet-types", "2013-07-15", (const char*)ietf_inet_types_2013_07_15_yin, 0, LYS_IN_YIN},
61 {"ietf-yang-types", "2013-07-15", (const char*)ietf_yang_types_2013_07_15_yin, 0, LYS_IN_YIN},
Radek Krejcid9723912016-09-16 17:06:06 +020062 {"ietf-yang-library", "2016-06-21", (const char*)ietf_yang_library_2016_06_21_yin, 1, LYS_IN_YIN}
Radek Krejci03203412016-06-23 15:20:53 +020063};
64
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020065API struct ly_ctx *
66ly_ctx_new(const char *search_dir)
Radek Krejcida04f4a2015-05-21 12:54:09 +020067{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020068 struct ly_ctx *ctx;
Michal Vasko7d7de952016-05-02 17:13:14 +020069 struct lys_module *module;
Michal Vasko70b6d692015-08-03 14:05:59 +020070 char *cwd;
Radek Krejci03203412016-06-23 15:20:53 +020071 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +020072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020073 ctx = calloc(1, sizeof *ctx);
74 if (!ctx) {
75 LOGMEM;
76 return NULL;
77 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020079 /* dictionary */
80 lydict_init(&ctx->dict);
Radek Krejcida04f4a2015-05-21 12:54:09 +020081
Radek Krejci858ad952017-01-04 11:16:32 +010082 /* plugins */
Radek Krejci858ad952017-01-04 11:16:32 +010083 lyext_load_plugins();
84
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020085 /* models list */
86 ctx->models.list = calloc(16, sizeof *ctx->models.list);
Michal Vasko253035f2015-12-17 16:58:13 +010087 if (!ctx->models.list) {
88 LOGMEM;
89 free(ctx);
90 return NULL;
91 }
Radek Krejci37d02632017-02-21 14:14:11 +010092 ext_plugins_ref++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020093 ctx->models.used = 0;
94 ctx->models.size = 16;
95 if (search_dir) {
96 cwd = get_current_dir_name();
97 if (chdir(search_dir)) {
98 LOGERR(LY_ESYS, "Unable to use search directory \"%s\" (%s)",
99 search_dir, strerror(errno));
100 free(cwd);
Radek Krejcifa0b5e02016-02-04 13:57:03 +0100101 ly_ctx_destroy(ctx, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200102 return NULL;
103 }
Radek Krejcida9f8392017-03-25 19:40:56 -0500104 ctx->models.search_paths = malloc(2 * sizeof *ctx->models.search_paths);
105 ctx->models.search_paths[0] = get_current_dir_name();
106 ctx->models.search_paths[1] = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +0100107 if (chdir(cwd)) {
108 LOGWRN("Unable to return back to working directory \"%s\" (%s)",
109 cwd, strerror(errno));
110 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200111 free(cwd);
112 }
Michal Vasko14719b22015-08-03 12:47:55 +0200113 ctx->models.module_set_id = 1;
114
Radek Krejci03203412016-06-23 15:20:53 +0200115 /* load internal modules */
Michal Vasko2d051a12017-04-21 09:28:57 +0200116 for (i = 0; i < LY_INTERNAL_MODULE_COUNT; i++) {
Radek Krejci03203412016-06-23 15:20:53 +0200117 module = (struct lys_module *)lys_parse_mem(ctx, internal_modules[i].data, internal_modules[i].format);
118 if (!module) {
119 ly_ctx_destroy(ctx, NULL);
120 return NULL;
121 }
122 module->implemented = internal_modules[i].implemented;
Michal Vasko8d054e42015-08-03 12:42:06 +0200123 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200125 return ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200126}
127
Radek Krejci69333c92017-03-17 16:14:43 +0100128static struct ly_ctx *
129ly_ctx_new_yl_common(const char *search_dir, const char *input, LYD_FORMAT format,
130 struct lyd_node* (*parser_func)(struct ly_ctx*, const char*, LYD_FORMAT, int,...))
131{
132 unsigned int u;
133 struct lyd_node *module, *node;
134 const char *name, *revision;
Radek Krejci5cb217d2017-03-25 16:07:52 -0500135 struct ly_set features = {0, 0, {NULL}};
Radek Krejci69333c92017-03-17 16:14:43 +0100136 const struct lys_module *mod;
137 struct lyd_node *yltree = NULL;
138 struct ly_ctx *ctx = NULL;
139
140 /* create empty (with internal modules including ietf-yang-library) context */
141 ctx = ly_ctx_new(search_dir);
142 if (!ctx) {
143 goto error;
144 }
145
146 /* parse yang library data tree */
147 yltree = parser_func(ctx, input, format, LYD_OPT_DATA, NULL);
148 if (!yltree) {
149 goto error;
150 }
151
152 /* process the data tree */
153 LY_TREE_FOR(yltree->child, module) {
154 if (module->schema->nodetype == LYS_LEAF) {
155 /* module-set-id - ignore it */
156 continue;
157 }
158
159 /* initiate */
160 name = NULL;
161 revision = NULL;
162 ly_set_clean(&features);
163
164 LY_TREE_FOR(module->child, node) {
165 if (!strcmp(node->schema->name, "name")) {
166 name = ((struct lyd_node_leaf_list*)node)->value_str;
167 } else if (!strcmp(node->schema->name, "revision")) {
168 revision = ((struct lyd_node_leaf_list*)node)->value_str;
169 } else if (!strcmp(node->schema->name, "feature")) {
170 ly_set_add(&features, node, LY_SET_OPT_USEASLIST);
171 } else if (!strcmp(node->schema->name, "conformance-type") &&
172 ((struct lyd_node_leaf_list*)node)->value.enm->value) {
173 /* imported module - skip it, it will be loaded as a side effect
174 * of loading another module */
175 goto next_module;
176 }
177 }
178
179 /* use the gathered data to load the module */
180 mod = ly_ctx_load_module(ctx, name, revision);
181 if (!mod) {
182 LOGERR(LY_EINVAL, "Unable to load module specified by yang library data.");
183 goto error;
184 }
185
186 /* set features */
187 for (u = 0; u < features.number; u++) {
188 lys_features_enable(mod, ((struct lyd_node_leaf_list*)features.set.d[u])->value_str);
189 }
190
191next_module:;
192 }
193
194 if (0) {
195 /* skip context destroy in case of success */
196error:
197 ly_ctx_destroy(ctx, NULL);
198 ctx = NULL;
199 }
200
201 /* cleanup */
202 if (yltree) {
203 /* yang library data tree */
204 lyd_free_withsiblings(yltree);
205 }
206
207 return ctx;
208}
209
210API struct ly_ctx *
211ly_ctx_new_ylpath(const char *search_dir, const char *path, LYD_FORMAT format)
212{
213 return ly_ctx_new_yl_common(search_dir, path, format, lyd_parse_path);
214}
215
216API struct ly_ctx *
217ly_ctx_new_ylmem(const char *search_dir, const char *data, LYD_FORMAT format)
218{
219 return ly_ctx_new_yl_common(search_dir, data, format, lyd_parse_mem);
220}
221
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200222API void
Radek Krejci819dd4b2017-03-07 15:35:48 +0100223ly_ctx_set_allimplemented(struct ly_ctx *ctx)
224{
225 if (!ctx) {
226 return;
227 }
228
229 ctx->models.flags |= LY_CTX_ALLIMPLEMENTED;
230}
231
232API void
233ly_ctx_unset_allimplemented(struct ly_ctx *ctx)
234{
235 if (!ctx) {
236 return;
237 }
238
239 ctx->models.flags &= ~LY_CTX_ALLIMPLEMENTED;
240}
241
242API void
Michal Vasko60ba9a62015-07-03 14:42:31 +0200243ly_ctx_set_searchdir(struct ly_ctx *ctx, const char *search_dir)
244{
245 char *cwd;
Radek Krejcida9f8392017-03-25 19:40:56 -0500246 int index = 0;
247 void *r;
Michal Vasko60ba9a62015-07-03 14:42:31 +0200248
249 if (!ctx) {
250 return;
251 }
252
253 if (search_dir) {
254 cwd = get_current_dir_name();
255 if (chdir(search_dir)) {
256 LOGERR(LY_ESYS, "Unable to use search directory \"%s\" (%s)",
257 search_dir, strerror(errno));
258 free(cwd);
259 return;
260 }
Radek Krejcida9f8392017-03-25 19:40:56 -0500261
262 if (!ctx->models.search_paths) {
263 ctx->models.search_paths = malloc(2 * sizeof *ctx->models.search_paths);
264 index = 0;
265 } else {
266 for (index = 0; ctx->models.search_paths[index]; index++);
267 r = realloc(ctx->models.search_paths, (index + 2) * sizeof *ctx->models.search_paths);
268 if (!r) {
269 LOGMEM;
Radek Krejcic10366a2017-03-26 12:05:39 -0500270 free(cwd);
Radek Krejcida9f8392017-03-25 19:40:56 -0500271 return;
272 }
273 ctx->models.search_paths = r;
274 }
275 ctx->models.search_paths[index] = get_current_dir_name();
276 ctx->models.search_paths[index + 1] = NULL;
Michal Vasko3eff9322015-11-10 11:02:30 +0100277
Radek Krejci15412ca2016-03-03 11:16:52 +0100278 if (chdir(cwd)) {
279 LOGWRN("Unable to return back to working directory \"%s\" (%s)",
280 cwd, strerror(errno));
281 }
Michal Vasko60ba9a62015-07-03 14:42:31 +0200282 free(cwd);
Michal Vasko60ba9a62015-07-03 14:42:31 +0200283 }
284}
285
Radek Krejcib081d8d2015-10-21 16:29:07 +0200286API const char *
Michal Vasko1e62a092015-12-01 12:27:20 +0100287ly_ctx_get_searchdir(const struct ly_ctx *ctx)
Radek Krejci5a797572015-10-21 15:45:45 +0200288{
Radek Krejciee554172016-12-14 10:29:06 +0100289 if (!ctx) {
290 ly_errno = LY_EINVAL;
291 return NULL;
292 }
Radek Krejcida9f8392017-03-25 19:40:56 -0500293 return ctx->models.search_paths ? ctx->models.search_paths[0] : NULL;
294}
295
296API void
297ly_ctx_unset_searchdirs(struct ly_ctx *ctx)
298{
299 int i;
300
301 if (!ctx->models.search_paths) {
302 return;
303 }
304
305 for (i = 0; ctx->models.search_paths[i]; i++) {
306 free(ctx->models.search_paths[i]);
307 }
308 free(ctx->models.search_paths);
309 ctx->models.search_paths = NULL;
Radek Krejci5a797572015-10-21 15:45:45 +0200310}
311
Michal Vasko60ba9a62015-07-03 14:42:31 +0200312API void
Radek Krejcifa0b5e02016-02-04 13:57:03 +0100313ly_ctx_destroy(struct ly_ctx *ctx, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +0200314{
Radek Krejcida9f8392017-03-25 19:40:56 -0500315 int i;
316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200317 if (!ctx) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200318 return;
319 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200321 /* models list */
Radek Krejcic436a232017-02-08 14:43:11 +0100322 for (; ctx->models.used > 0; ctx->models.used--) {
Radek Krejcifc8411a2017-02-03 10:26:05 +0100323 /* remove the applied deviations and augments */
Radek Krejcic436a232017-02-08 14:43:11 +0100324 lys_sub_module_remove_devs_augs(ctx->models.list[ctx->models.used - 1]);
Radek Krejcifc8411a2017-02-03 10:26:05 +0100325 /* remove the module */
Radek Krejcic436a232017-02-08 14:43:11 +0100326 lys_free(ctx->models.list[ctx->models.used - 1], private_destructor, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200327 }
Radek Krejcida9f8392017-03-25 19:40:56 -0500328 if (ctx->models.search_paths) {
329 for(i = 0; ctx->models.search_paths[i]; i++) {
330 free(ctx->models.search_paths[i]);
331 }
332 free(ctx->models.search_paths);
333 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200334 free(ctx->models.list);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200336 /* dictionary */
337 lydict_clean(&ctx->dict);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200338
Radek Krejci858ad952017-01-04 11:16:32 +0100339 /* plugins - will be removed only if this is the last context */
340 ext_plugins_ref--;
341 lyext_clean_plugins();
342
Radek Krejci8b76a4a2016-10-26 10:02:32 +0200343 /* clean the error list */
Radek Krejci00a0e712016-10-26 10:24:46 +0200344 ly_err_clean(0);
Radek Krejci8b76a4a2016-10-26 10:02:32 +0200345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200346 free(ctx);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200347}
348
Michal Vasko1e62a092015-12-01 12:27:20 +0100349API const struct lys_submodule *
Radek Krejci62f0da72016-03-07 11:35:43 +0100350ly_ctx_get_submodule2(const struct lys_module *main_module, const char *submodule)
351{
Radek Krejcid4c1d0f2017-01-19 16:11:38 +0100352 const struct lys_submodule *result;
Radek Krejci62f0da72016-03-07 11:35:43 +0100353 int i;
354
355 if (!main_module || !submodule) {
356 ly_errno = LY_EINVAL;
357 return NULL;
358 }
359
360 /* search in submodules list */
361 for (i = 0; i < main_module->inc_size; i++) {
362 result = main_module->inc[i].submodule;
Radek Krejcid4c1d0f2017-01-19 16:11:38 +0100363 if (ly_strequal(submodule, result->name, 0)) {
Radek Krejci62f0da72016-03-07 11:35:43 +0100364 return result;
365 }
Radek Krejcid4c1d0f2017-01-19 16:11:38 +0100366
367 /* in YANG 1.1 all the submodules must be included in the main module, so we are done.
368 * YANG 1.0 allows (is unclear about denying it) to include a submodule only in another submodule
369 * but when libyang parses such a module it adds the include into the main module so we are also done.
370 */
Radek Krejci62f0da72016-03-07 11:35:43 +0100371 }
372
Radek Krejcid4c1d0f2017-01-19 16:11:38 +0100373
Radek Krejci62f0da72016-03-07 11:35:43 +0100374 return NULL;
375}
376
377API const struct lys_submodule *
Michal Vaskof6d94c62016-04-05 11:21:54 +0200378ly_ctx_get_submodule(const struct ly_ctx *ctx, const char *module, const char *revision, const char *submodule,
379 const char *sub_revision)
Radek Krejciefaeba32015-05-27 14:30:57 +0200380{
Radek Krejcie7973552016-03-07 08:12:01 +0100381 const struct lys_module *mainmod;
Michal Vaskof6d94c62016-04-05 11:21:54 +0200382 const struct lys_submodule *ret = NULL, *submod;
383 uint32_t idx = 0;
Radek Krejciefaeba32015-05-27 14:30:57 +0200384
Michal Vaskof6d94c62016-04-05 11:21:54 +0200385 if (!ctx || !submodule || (revision && !module)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200386 ly_errno = LY_EINVAL;
387 return NULL;
388 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200389
Michal Vaskof6d94c62016-04-05 11:21:54 +0200390 while ((mainmod = ly_ctx_get_module_iter(ctx, &idx))) {
391 if (module && strcmp(mainmod->name, module)) {
392 /* main module name does not match */
393 continue;
394 }
395
396 if (revision && (!mainmod->rev || strcmp(revision, mainmod->rev[0].date))) {
397 /* main module revision does not match */
398 continue;
399 }
400
401 submod = ly_ctx_get_submodule2(mainmod, submodule);
402 if (!submod) {
403 continue;
404 }
405
406 if (!sub_revision) {
407 /* store only if newer */
408 if (ret) {
409 if (submod->rev && (!ret->rev || (strcmp(submod->rev[0].date, ret->rev[0].date) > 0))) {
410 ret = submod;
411 }
412 } else {
413 ret = submod;
414 }
415 } else {
416 /* store only if revision matches, we are done if it does */
417 if (!submod->rev) {
418 continue;
419 } else if (!strcmp(sub_revision, submod->rev[0].date)) {
420 ret = submod;
421 break;
422 }
423 }
Radek Krejcia7533f22016-03-07 07:37:45 +0100424 }
Radek Krejcic071c542016-01-27 14:57:51 +0100425
Michal Vaskof6d94c62016-04-05 11:21:54 +0200426 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +0200427}
428
Michal Vasko1e62a092015-12-01 12:27:20 +0100429static const struct lys_module *
Radek Krejci0ec51da2016-12-14 16:42:03 +0100430ly_ctx_get_module_by(const struct ly_ctx *ctx, const char *key, int offset, const char *revision, int with_disabled)
Radek Krejciefaeba32015-05-27 14:30:57 +0200431{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200432 int i;
Radek Krejcib8048692015-08-05 13:36:34 +0200433 struct lys_module *result = NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +0200434
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200435 if (!ctx || !key) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200436 ly_errno = LY_EINVAL;
437 return NULL;
438 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200439
Radek Krejcidce51452015-06-16 15:20:08 +0200440 for (i = 0; i < ctx->models.used; i++) {
Radek Krejci0ec51da2016-12-14 16:42:03 +0100441 if (!with_disabled && ctx->models.list[i]->disabled) {
442 /* skip the disabled modules */
443 continue;
444 }
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200445 /* use offset to get address of the pointer to string (char**), remember that offset is in
446 * bytes, so we have to cast the pointer to the module to (char*), finally, we want to have
447 * string not the pointer to string
448 */
449 if (!ctx->models.list[i] || strcmp(key, *(char**)(((char*)ctx->models.list[i]) + offset))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200450 continue;
451 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200452
Radek Krejcif647e612015-07-30 11:36:07 +0200453 if (!revision) {
454 /* compare revisons and remember the newest one */
455 if (result) {
456 if (!ctx->models.list[i]->rev_size) {
457 /* the current have no revision, keep the previous with some revision */
458 continue;
459 }
460 if (result->rev_size && strcmp(ctx->models.list[i]->rev[0].date, result->rev[0].date) < 0) {
461 /* the previous found matching module has a newer revision */
462 continue;
463 }
464 }
465
466 /* remember the current match and search for newer version */
467 result = ctx->models.list[i];
468 } else {
469 if (ctx->models.list[i]->rev_size && !strcmp(revision, ctx->models.list[i]->rev[0].date)) {
470 /* matching revision */
Michal Vasko97586502015-08-12 14:32:18 +0200471 result = ctx->models.list[i];
472 break;
Radek Krejcif647e612015-07-30 11:36:07 +0200473 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200474 }
475 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200476
Radek Krejcif647e612015-07-30 11:36:07 +0200477 return result;
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200478
479}
480
Michal Vasko1e62a092015-12-01 12:27:20 +0100481API const struct lys_module *
482ly_ctx_get_module_by_ns(const struct ly_ctx *ctx, const char *ns, const char *revision)
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200483{
Radek Krejci0ec51da2016-12-14 16:42:03 +0100484 return ly_ctx_get_module_by(ctx, ns, offsetof(struct lys_module, ns), revision, 0);
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200485}
486
Michal Vasko1e62a092015-12-01 12:27:20 +0100487API const struct lys_module *
488ly_ctx_get_module(const struct ly_ctx *ctx, const char *name, const char *revision)
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200489{
Radek Krejci0ec51da2016-12-14 16:42:03 +0100490 return ly_ctx_get_module_by(ctx, name, offsetof(struct lys_module, name), revision, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200491}
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200492
Radek Krejci21601a32016-03-07 11:39:27 +0100493API const struct lys_module *
494ly_ctx_get_module_older(const struct ly_ctx *ctx, const struct lys_module *module)
495{
496 int i;
497 const struct lys_module *result = NULL, *iter;
498
499 if (!ctx || !module || !module->rev_size) {
500 ly_errno = LY_EINVAL;
501 return NULL;
502 }
503
504
505 for (i = 0; i < ctx->models.used; i++) {
506 iter = ctx->models.list[i];
Radek Krejci0ec51da2016-12-14 16:42:03 +0100507 if (iter->disabled) {
508 /* skip the disabled modules */
509 continue;
510 }
Radek Krejci21601a32016-03-07 11:39:27 +0100511 if (iter == module || !iter->rev_size) {
512 /* iter is the module itself or iter has no revision */
513 continue;
514 }
515 if (!ly_strequal(module->name, iter->name, 0)) {
516 /* different module */
517 continue;
518 }
519 if (strcmp(iter->rev[0].date, module->rev[0].date) < 0) {
520 /* iter is older than module */
521 if (result) {
522 if (strcmp(iter->rev[0].date, result->rev[0].date) > 0) {
523 /* iter is newer than current result */
524 result = iter;
525 }
526 } else {
527 result = iter;
528 }
529 }
530 }
531
532 return result;
533}
534
Michal Vasko99b0aad2015-12-01 12:28:51 +0100535API void
Michal Vaskoca28aab2017-01-13 13:50:12 +0100536ly_ctx_set_module_imp_clb(struct ly_ctx *ctx, ly_module_imp_clb clb, void *user_data)
Michal Vasko82465962015-11-10 11:03:11 +0100537{
Michal Vaskoad9f92a2017-04-06 09:49:07 +0200538 if (!ctx) {
539 ly_errno = LY_EINVAL;
540 return;
541 }
542
Michal Vaskof53187d2017-01-13 13:23:14 +0100543 ctx->imp_clb = clb;
544 ctx->imp_clb_data = user_data;
Michal Vasko99b0aad2015-12-01 12:28:51 +0100545}
546
Michal Vaskof53187d2017-01-13 13:23:14 +0100547API ly_module_imp_clb
Michal Vaskoca28aab2017-01-13 13:50:12 +0100548ly_ctx_get_module_imp_clb(const struct ly_ctx *ctx, void **user_data)
Michal Vasko99b0aad2015-12-01 12:28:51 +0100549{
Radek Krejciee554172016-12-14 10:29:06 +0100550 if (!ctx) {
551 ly_errno = LY_EINVAL;
552 return NULL;
553 }
554
Michal Vasko99b0aad2015-12-01 12:28:51 +0100555 if (user_data) {
Michal Vaskof53187d2017-01-13 13:23:14 +0100556 *user_data = ctx->imp_clb_data;
Michal Vasko99b0aad2015-12-01 12:28:51 +0100557 }
Michal Vaskof53187d2017-01-13 13:23:14 +0100558 return ctx->imp_clb;
559}
560
561API void
Michal Vaskoca28aab2017-01-13 13:50:12 +0100562ly_ctx_set_module_data_clb(struct ly_ctx *ctx, ly_module_data_clb clb, void *user_data)
Michal Vaskof53187d2017-01-13 13:23:14 +0100563{
Michal Vaskoad9f92a2017-04-06 09:49:07 +0200564 if (!ctx) {
565 ly_errno = LY_EINVAL;
566 return;
567 }
568
Michal Vaskof53187d2017-01-13 13:23:14 +0100569 ctx->data_clb = clb;
570 ctx->data_clb_data = user_data;
571}
572
573API ly_module_data_clb
Michal Vaskoca28aab2017-01-13 13:50:12 +0100574ly_ctx_get_module_data_clb(const struct ly_ctx *ctx, void **user_data)
Michal Vaskof53187d2017-01-13 13:23:14 +0100575{
Michal Vaskoad9f92a2017-04-06 09:49:07 +0200576 if (!ctx) {
577 ly_errno = LY_EINVAL;
578 return NULL;
579 }
580
Michal Vaskof53187d2017-01-13 13:23:14 +0100581 if (user_data) {
582 *user_data = ctx->data_clb_data;
583 }
584 return ctx->data_clb;
Michal Vasko99b0aad2015-12-01 12:28:51 +0100585}
586
Radek Krejcibf4e4652016-10-21 15:44:13 +0200587const struct lys_module *
Michal Vasko84475152016-07-25 16:16:25 +0200588ly_ctx_load_sub_module(struct ly_ctx *ctx, struct lys_module *module, const char *name, const char *revision,
Michal Vasko58e5f3e2016-07-28 11:06:34 +0200589 int implement, struct unres_schema *unres)
Michal Vasko99b0aad2015-12-01 12:28:51 +0100590{
Radek Krejcibf4e4652016-10-21 15:44:13 +0200591 const struct lys_module *mod;
Michal Vasko99b0aad2015-12-01 12:28:51 +0100592 char *module_data;
Radek Krejci03203412016-06-23 15:20:53 +0200593 int i;
Michal Vaskod3e975b2016-03-03 15:40:21 +0100594 void (*module_data_free)(void *module_data) = NULL;
Michal Vasko99b0aad2015-12-01 12:28:51 +0100595 LYS_INFORMAT format = LYS_IN_UNKNOWN;
Michal Vasko82465962015-11-10 11:03:11 +0100596
Michal Vasko84475152016-07-25 16:16:25 +0200597 if (!module) {
Radek Krejcibf4e4652016-10-21 15:44:13 +0200598 /* exception for internal modules */
Michal Vasko2d051a12017-04-21 09:28:57 +0200599 for (i = 0; i < LY_INTERNAL_MODULE_COUNT; i++) {
Michal Vasko84475152016-07-25 16:16:25 +0200600 if (ly_strequal(name, internal_modules[i].name, 0)) {
601 if (!revision || ly_strequal(revision, internal_modules[i].revision, 0)) {
602 /* return internal module */
603 return (struct lys_module *)ly_ctx_get_module(ctx, name, revision);
604 }
Radek Krejci03203412016-06-23 15:20:53 +0200605 }
606 }
Radek Krejcibf4e4652016-10-21 15:44:13 +0200607 if (revision) {
Radek Krejci0ec51da2016-12-14 16:42:03 +0100608 /* try to get the schema with the specific revision from the context,
609 * include the disabled modules in the search to avoid their duplication,
610 * they are enabled by the subsequent call to lys_set_implemented() */
Michal Vasko2d051a12017-04-21 09:28:57 +0200611 for (i = LY_INTERNAL_MODULE_COUNT, mod = NULL; i < ctx->models.used; i++) {
Radek Krejci0ec51da2016-12-14 16:42:03 +0100612 mod = ctx->models.list[i]; /* shortcut */
613 if (ly_strequal(name, mod->name, 0) && mod->rev_size && !strcmp(revision, mod->rev[0].date)) {
614 break;
615 }
616 mod = NULL;
617 }
Radek Krejcibf4e4652016-10-21 15:44:13 +0200618 if (mod) {
619 /* we get such a module, make it implemented */
620 if (lys_set_implemented(mod)) {
621 /* the schema cannot be implemented */
622 mod = NULL;
623 }
624 return mod;
625 }
626 }
Radek Krejci03203412016-06-23 15:20:53 +0200627 }
628
Michal Vaskof53187d2017-01-13 13:23:14 +0100629 if (ctx->imp_clb) {
Michal Vasko84475152016-07-25 16:16:25 +0200630 if (module) {
631 mod = lys_main_module(module);
Michal Vaskof53187d2017-01-13 13:23:14 +0100632 module_data = ctx->imp_clb(mod->name, (mod->rev_size ? mod->rev[0].date : NULL), name, revision, ctx->imp_clb_data, &format, &module_data_free);
Michal Vasko84475152016-07-25 16:16:25 +0200633 } else {
Michal Vaskof53187d2017-01-13 13:23:14 +0100634 module_data = ctx->imp_clb(name, revision, NULL, NULL, ctx->imp_clb_data, &format, &module_data_free);
Michal Vasko84475152016-07-25 16:16:25 +0200635 }
Michal Vasko99b0aad2015-12-01 12:28:51 +0100636 if (!module_data) {
Radek Krejcibf4e4652016-10-21 15:44:13 +0200637 if (module || revision) {
638 /* we already know that the specified revision is not present in context, and we have no other
639 * option in case of submodules */
640 LOGERR(LY_ESYS, "User module retrieval callback failed!");
641 return NULL;
642 } else {
643 /* get the newest revision from the context */
Radek Krejci0ec51da2016-12-14 16:42:03 +0100644 mod = ly_ctx_get_module_by(ctx, name, offsetof(struct lys_module, name), revision, 1);
645 if (mod && mod->disabled) {
646 /* enable the required module */
647 lys_set_enabled(mod);
648 }
649 return mod;
Radek Krejcibf4e4652016-10-21 15:44:13 +0200650 }
Michal Vasko82465962015-11-10 11:03:11 +0100651 }
Michal Vasko84475152016-07-25 16:16:25 +0200652
653 if (module) {
Michal Vasko5b998712017-01-26 10:34:06 +0100654 mod = (struct lys_module *)lys_sub_parse_mem(module, module_data, format, unres);
Michal Vasko84475152016-07-25 16:16:25 +0200655 } else {
Michal Vasko29245662017-04-18 15:56:31 +0200656 mod = (struct lys_module *)lys_parse_mem_(ctx, module_data, format, 0, implement);
Michal Vasko84475152016-07-25 16:16:25 +0200657 }
658
Michal Vasko99b0aad2015-12-01 12:28:51 +0100659 if (module_data_free) {
660 module_data_free(module_data);
Michal Vasko82465962015-11-10 11:03:11 +0100661 }
Michal Vasko99b0aad2015-12-01 12:28:51 +0100662 } else {
Michal Vasko58e5f3e2016-07-28 11:06:34 +0200663 mod = lyp_search_file(ctx, module, name, revision, implement, unres);
Michal Vasko82465962015-11-10 11:03:11 +0100664 }
665
Michal Vasko84475152016-07-25 16:16:25 +0200666 return mod;
667}
668
669API const struct lys_module *
670ly_ctx_load_module(struct ly_ctx *ctx, const char *name, const char *revision)
671{
672 if (!ctx || !name) {
673 ly_errno = LY_EINVAL;
674 return NULL;
675 }
676
Michal Vasko58e5f3e2016-07-28 11:06:34 +0200677 return ly_ctx_load_sub_module(ctx, NULL, name, revision, 1, NULL);
Michal Vasko82465962015-11-10 11:03:11 +0100678}
679
Radek Krejci85a54be2016-10-20 12:39:56 +0200680/*
681 * mods - set of removed modules, if NULL all modules are supposed to be removed so any backlink is invalid
682 */
Michal Vasko4be5fa22017-02-07 10:12:32 +0100683static void
684ctx_modules_undo_backlinks(struct ly_ctx *ctx, struct ly_set *mods)
Radek Krejci85a54be2016-10-20 12:39:56 +0200685{
686 int o;
687 uint8_t j;
688 unsigned int u, v;
689 struct lys_module *mod;
690 struct lys_node *elem, *next;
691 struct lys_node_leaf *leaf;
692
693 /* maintain backlinks (start with internal ietf-yang-library which have leafs as possible targets of leafrefs */
Michal Vasko2d051a12017-04-21 09:28:57 +0200694 for (o = LY_INTERNAL_MODULE_COUNT - 1; o < ctx->models.used; o++) {
Radek Krejci85a54be2016-10-20 12:39:56 +0200695 mod = ctx->models.list[o]; /* shortcut */
696
697 /* 1) features */
698 for (j = 0; j < mod->features_size; j++) {
699 if (!mod->features[j].depfeatures) {
700 continue;
701 }
702 for (v = 0; v < mod->features[j].depfeatures->number; v++) {
703 if (!mods || ly_set_contains(mods, ((struct lys_feature *)mod->features[j].depfeatures->set.g[v])->module) != -1) {
704 /* depending feature is in module to remove */
705 ly_set_rm_index(mod->features[j].depfeatures, v);
706 v--;
707 }
708 }
709 if (!mod->features[j].depfeatures->number) {
710 /* all backlinks removed */
711 ly_set_free(mod->features[j].depfeatures);
712 mod->features[j].depfeatures = NULL;
713 }
714 }
Michal Vasko4be5fa22017-02-07 10:12:32 +0100715
716 /* 2) identities */
Radek Krejci85a54be2016-10-20 12:39:56 +0200717 for (u = 0; u < mod->ident_size; u++) {
718 if (!mod->ident[u].der) {
719 continue;
720 }
721 for (v = 0; v < mod->ident[u].der->number; v++) {
722 if (!mods || ly_set_contains(mods, ((struct lys_ident *)mod->ident[u].der->set.g[v])->module) != -1) {
723 /* derived identity is in module to remove */
724 ly_set_rm_index(mod->ident[u].der, v);
725 v--;
726 }
727 }
728 if (!mod->ident[u].der->number) {
729 /* all backlinks removed */
730 ly_set_free(mod->ident[u].der);
731 mod->ident[u].der = NULL;
732 }
733 }
734
Michal Vasko4be5fa22017-02-07 10:12:32 +0100735 /* 3) leafrefs */
Radek Krejci85a54be2016-10-20 12:39:56 +0200736 for (elem = next = mod->data; elem; elem = next) {
737 if (elem->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
738 leaf = (struct lys_node_leaf *)elem; /* shortcut */
739 if (leaf->backlinks) {
740 if (!mods) {
741 /* remove all backlinks */
742 ly_set_free(leaf->backlinks);
743 leaf->backlinks = NULL;
744 } else {
745 for (v = 0; v < leaf->backlinks->number; v++) {
746 if (ly_set_contains(mods, leaf->backlinks->set.s[v]->module) != -1) {
747 /* derived identity is in module to remove */
748 ly_set_rm_index(leaf->backlinks, v);
749 v--;
750 }
751 }
752 if (!leaf->backlinks->number) {
753 /* all backlinks removed */
754 ly_set_free(leaf->backlinks);
755 leaf->backlinks = NULL;
756 }
757 }
758 }
759 }
760
761 /* select next element to process */
762 next = elem->child;
763 /* child exception for leafs, leaflists, anyxml and groupings */
764 if (elem->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_GROUPING)) {
765 next = NULL;
766 }
767 if (!next) {
768 /* no children, try siblings */
769 next = elem->next;
770 }
771 while (!next) {
772 /* parent is already processed, go to its sibling */
773 elem = lys_parent(elem);
774 if (!elem) {
775 /* we are done, no next element to process */
776 break;
777 }
778 /* no siblings, go back through parents */
779 next = elem->next;
780 }
781 }
782 }
Michal Vasko4be5fa22017-02-07 10:12:32 +0100783}
Radek Krejci85a54be2016-10-20 12:39:56 +0200784
Michal Vasko4be5fa22017-02-07 10:12:32 +0100785static int
Radek Krejci83a4bac2017-02-07 15:53:04 +0100786ctx_modules_redo_backlinks(struct ly_set *mods)
Michal Vasko4be5fa22017-02-07 10:12:32 +0100787{
Radek Krejci83a4bac2017-02-07 15:53:04 +0100788 unsigned int i, j, k, s;
789 struct lys_module *mod;
790 struct lys_node *next, *elem;
791 struct lys_type *type;
792 struct lys_feature *feat;
Michal Vasko4be5fa22017-02-07 10:12:32 +0100793
Michal Vasko4be5fa22017-02-07 10:12:32 +0100794 for (i = 0; i < mods->number; ++i) {
Radek Krejci83a4bac2017-02-07 15:53:04 +0100795 mod = (struct lys_module *)mods->set.g[i]; /* shortcut */
Michal Vasko4be5fa22017-02-07 10:12:32 +0100796
Radek Krejci83a4bac2017-02-07 15:53:04 +0100797 /* identities */
798 for (j = 0; j < mod->ident_size; j++) {
799 for (k = 0; k < mod->ident[j].base_size; k++) {
800 resolve_identity_backlink_update(&mod->ident[j], mod->ident[j].base[k]);
801 }
802 }
Michal Vasko4be5fa22017-02-07 10:12:32 +0100803
Radek Krejci83a4bac2017-02-07 15:53:04 +0100804 /* features */
805 for (j = 0; j < mod->features_size; j++) {
806 for (k = 0; k < mod->features[j].iffeature_size; k++) {
807 resolve_iffeature_getsizes(&mod->features[j].iffeature[k], NULL, &s);
808 while (s--) {
809 feat = mod->features[j].iffeature[k].features[s]; /* shortcut */
810 if (!feat->depfeatures) {
811 feat->depfeatures = ly_set_new();
812 }
813 ly_set_add(feat->depfeatures, &mod->features[j], LY_SET_OPT_USEASLIST);
814 }
815 }
816 }
817
818 /* leafrefs */
819 LY_TREE_DFS_BEGIN(mod->data, next, elem) {
Michal Vaskofa3d2f72017-04-10 13:30:44 +0200820 if (elem->nodetype == LYS_GROUPING) {
821 goto next_sibling;
822 }
823
Radek Krejci83a4bac2017-02-07 15:53:04 +0100824 if (elem->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
825 type = &((struct lys_node_leaf *)elem)->type; /* shortcut */
826 if (type->base == LY_TYPE_LEAFREF) {
827 lys_leaf_add_leafref_target(type->info.lref.target, elem);
828 }
829 }
830
Michal Vaskofa3d2f72017-04-10 13:30:44 +0200831 /* select element for the next run - children first */
832 next = elem->child;
833
834 /* child exception for leafs, leaflists and anyxml without children */
835 if (elem->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
836 next = NULL;
837 }
838 if (!next) {
839next_sibling:
840 /* no children */
841 if (elem == mod->data) {
842 /* we are done, (START) has no children */
843 break;
844 }
845 /* try siblings */
846 next = elem->next;
847 }
848 while (!next) {
849 /* parent is already processed, go to its sibling */
850 elem = lys_parent(elem);
851
852 /* no siblings, go back through parents */
853 if (lys_parent(elem) == lys_parent(mod->data)) {
854 /* we are done, no next element to process */
855 break;
856 }
857 next = elem->next;
858 }
Radek Krejci83a4bac2017-02-07 15:53:04 +0100859 }
Michal Vasko4be5fa22017-02-07 10:12:32 +0100860 }
861
862 return 0;
Radek Krejci85a54be2016-10-20 12:39:56 +0200863}
864
Radek Krejci8c107fe2016-10-17 16:00:18 +0200865API int
Radek Krejci0ec51da2016-12-14 16:42:03 +0100866lys_set_disabled(const struct lys_module *module)
867{
868 struct ly_ctx *ctx; /* shortcut */
869 struct lys_module *mod;
870 struct ly_set *mods;
871 uint8_t j, imported;
872 int i, o;
873 unsigned int u;
874
875 if (!module) {
876 ly_errno = LY_EINVAL;
877 return EXIT_FAILURE;
878 } else if (module->disabled) {
879 /* already disabled module */
880 return EXIT_SUCCESS;
881 }
882 mod = (struct lys_module *)module;
883 ctx = mod->ctx;
884
885 /* avoid disabling internal modules */
Michal Vasko2d051a12017-04-21 09:28:57 +0200886 for (i = 0; i < LY_INTERNAL_MODULE_COUNT; i++) {
Radek Krejci0ec51da2016-12-14 16:42:03 +0100887 if (mod == ctx->models.list[i]) {
Michal Vasko2d051a12017-04-21 09:28:57 +0200888 LOGERR(LY_EINVAL, "Internal module \"%s\" cannot be disabled.", mod->name);
Radek Krejci0ec51da2016-12-14 16:42:03 +0100889 return EXIT_FAILURE;
890 }
891 }
892
893 /* disable the module */
894 mod->disabled = 1;
895
896 /* get the complete list of modules to disable because of dependencies,
897 * we are going also to disable all the imported (not implemented) modules
898 * that are not used in any other module */
899 mods = ly_set_new();
900 ly_set_add(mods, mod, 0);
901checkdependency:
Michal Vasko2d051a12017-04-21 09:28:57 +0200902 for (i = LY_INTERNAL_MODULE_COUNT; i < ctx->models.used; i++) {
Radek Krejci0ec51da2016-12-14 16:42:03 +0100903 mod = ctx->models.list[i]; /* shortcut */
904 if (mod->disabled) {
905 /* skip the already disabled modules */
906 continue;
907 }
908
909 /* check depndency of imported modules */
910 for (j = 0; j < mod->imp_size; j++) {
911 for (u = 0; u < mods->number; u++) {
912 if (mod->imp[j].module == mods->set.g[u]) {
913 /* module is importing some module to disable, so it must be also disabled */
914 mod->disabled = 1;
915 ly_set_add(mods, mod, 0);
916 /* we have to start again because some of the already checked modules can
917 * depend on the one we have just decided to disable */
918 goto checkdependency;
919 }
920 }
921 }
922 /* check if the imported module is used in any module supposed to be kept */
923 if (!mod->implemented) {
924 imported = 0;
Michal Vasko2d051a12017-04-21 09:28:57 +0200925 for (o = LY_INTERNAL_MODULE_COUNT; o < ctx->models.used; o++) {
Radek Krejci0ec51da2016-12-14 16:42:03 +0100926 if (ctx->models.list[o]->disabled) {
927 /* skip modules already disabled */
928 continue;
929 }
930 for (j = 0; j < ctx->models.list[o]->imp_size; j++) {
931 if (ctx->models.list[o]->imp[j].module == mod) {
932 /* the module is used in some other module not yet selected to be disabled */
933 imported = 1;
934 goto imported;
935 }
936 }
937 }
938imported:
939 if (!imported) {
940 /* module is not implemented and neither imported by any other module in context
941 * which is supposed to be kept enabled after this operation, so we are going to disable also
942 * this module */
943 mod->disabled = 1;
944 ly_set_add(mods, mod, 0);
945 /* we have to start again, this time not because other module can depend on this one
946 * (we know that there is no such module), but because the module can import module
947 * that could became useless. If there are no imports, we can continue */
948 if (mod->imp_size) {
949 goto checkdependency;
950 }
951 }
952 }
953 }
954
955 /* before removing applied deviations, augments and updating leafrefs, we have to enable the modules
956 * to disable to allow all that operations */
957 for (u = 0; u < mods->number; u++) {
958 ((struct lys_module *)mods->set.g[u])->disabled = 0;
959 }
960
961 /* maintain backlinks (start with internal ietf-yang-library which have leafs as possible targets of leafrefs */
Michal Vasko4be5fa22017-02-07 10:12:32 +0100962 ctx_modules_undo_backlinks(ctx, mods);
Radek Krejci0ec51da2016-12-14 16:42:03 +0100963
964 /* remove the applied deviations and augments */
965 for (u = 0; u < mods->number; u++) {
966 lys_sub_module_remove_devs_augs((struct lys_module *)mods->set.g[u]);
967 }
968
969 /* now again disable the modules to disable */
970 for (u = 0; u < mods->number; u++) {
971 ((struct lys_module *)mods->set.g[u])->disabled = 1;
972 }
973
974 /* free the set */
975 ly_set_free(mods);
976
977 /* update the module-set-id */
978 ctx->models.module_set_id++;
979
980 return EXIT_SUCCESS;
981}
982
983static void
984lys_set_enabled_(struct ly_set *mods, struct lys_module *mod)
985{
986 unsigned int i;
987
988 ly_set_add(mods, mod, 0);
989 mod->disabled = 0;
990
991 /* go recursively */
992 for (i = 0; i < mod->imp_size; i++) {
993 if (!mod->imp[i].module->disabled) {
994 continue;
995 }
996
997 lys_set_enabled_(mods, mod->imp[i].module);
998 }
999}
1000
1001API int
1002lys_set_enabled(const struct lys_module *module)
1003{
1004 struct ly_ctx *ctx; /* shortcut */
1005 struct lys_module *mod;
1006 struct ly_set *mods, *disabled;
1007 int i;
1008 unsigned int u, v;
1009
1010 if (!module) {
1011 ly_errno = LY_EINVAL;
1012 return EXIT_FAILURE;
1013 } else if (!module->disabled) {
1014 /* already enabled module */
1015 return EXIT_SUCCESS;
1016 }
1017 mod = (struct lys_module *)module;
1018 ctx = mod->ctx;
1019
1020 /* avoid disabling internal modules */
Michal Vasko2d051a12017-04-21 09:28:57 +02001021 for (i = 0; i < LY_INTERNAL_MODULE_COUNT; i++) {
Radek Krejci0ec51da2016-12-14 16:42:03 +01001022 if (mod == ctx->models.list[i]) {
1023 LOGERR(LY_EINVAL, "Internal module \"%s\" cannot be removed.", mod->name);
1024 return EXIT_FAILURE;
1025 }
1026 }
1027
1028 mods = ly_set_new();
1029 disabled = ly_set_new();
1030
1031 /* enable the module, including its dependencies */
1032 lys_set_enabled_(mods, mod);
1033
1034 /* we will go through the all disabled modules in the context, if the module has no dependency (import)
1035 * that is still disabled AND at least one of its imported module is from the set we are enabling now,
1036 * it is going to be also enabled. This way we try to revert everething that was possibly done by
1037 * lys_set_disabled(). */
1038checkdependency:
Michal Vasko2d051a12017-04-21 09:28:57 +02001039 for (i = LY_INTERNAL_MODULE_COUNT; i < ctx->models.used; i++) {
Radek Krejci0ec51da2016-12-14 16:42:03 +01001040 mod = ctx->models.list[i]; /* shortcut */
1041 if (!mod->disabled || ly_set_contains(disabled, mod) != -1) {
1042 /* skip the enabled modules */
1043 continue;
1044 }
1045
1046 /* check imported modules */
1047 for (u = 0; u < mod->imp_size; u++) {
1048 if (mod->imp[u].module->disabled) {
1049 /* it has disabled dependency so it must stay disabled */
1050 break;
1051 }
1052 }
1053 if (u < mod->imp_size) {
1054 /* it has disabled dependency, continue with the next module in the context */
1055 continue;
1056 }
1057
1058 /* get know if at least one of the imported modules is being enabled this time */
1059 for (u = 0; u < mod->imp_size; u++) {
1060 for (v = 0; v < mods->number; v++) {
1061 if (mod->imp[u].module == mods->set.g[v]) {
1062 /* yes, it is, so they are connected and we are going to enable it as well,
1063 * it is not necessary to call recursive lys_set_enable_() because we already
1064 * know that there is no disabled import to enable */
1065 mod->disabled = 0;
1066 ly_set_add(mods, mod, 0);
1067 /* we have to start again because some of the already checked modules can
1068 * depend on the one we have just decided to enable */
1069 goto checkdependency;
1070 }
1071 }
1072 }
1073
1074 /* this module is disabled, but it does not depend on any other disabled module and none
1075 * of its imports was not enabled in this call. No future enabling of the disabled module
1076 * will change this so we can remember the module and skip it next time we will have to go
1077 * through the all context because of the checkdependency goto.
1078 */
1079 ly_set_add(disabled, mod, 0);
1080 }
1081
1082 /* maintain backlinks (start with internal ietf-yang-library which have leafs as possible targets of leafrefs */
Radek Krejci83a4bac2017-02-07 15:53:04 +01001083 ctx_modules_redo_backlinks(mods);
Radek Krejci0ec51da2016-12-14 16:42:03 +01001084
1085 /* re-apply the deviations and augments */
1086 for (v = 0; v < mods->number; v++) {
1087 lys_sub_module_apply_devs_augs((struct lys_module *)mods->set.g[v]);
1088 }
1089
1090 /* free the sets */
1091 ly_set_free(mods);
1092 ly_set_free(disabled);
1093
1094 /* update the module-set-id */
1095 ctx->models.module_set_id++;
1096
1097 return EXIT_SUCCESS;
1098}
1099
1100API int
1101ly_ctx_remove_module(const struct lys_module *module,
Radek Krejci8c107fe2016-10-17 16:00:18 +02001102 void (*private_destructor)(const struct lys_node *node, void *priv))
1103{
Radek Krejci0ec51da2016-12-14 16:42:03 +01001104 struct ly_ctx *ctx; /* shortcut */
Radek Krejci8c107fe2016-10-17 16:00:18 +02001105 struct lys_module *mod = NULL;
1106 struct ly_set *mods;
1107 uint8_t j, imported;
1108 int i, o;
1109 unsigned int u;
1110
Radek Krejci0ec51da2016-12-14 16:42:03 +01001111 if (!module) {
Radek Krejci8c107fe2016-10-17 16:00:18 +02001112 ly_errno = LY_EINVAL;
1113 return EXIT_FAILURE;
1114 }
1115
Radek Krejci0ec51da2016-12-14 16:42:03 +01001116 mod = (struct lys_module *)module;
1117 ctx = mod->ctx;
1118
Radek Krejci8c107fe2016-10-17 16:00:18 +02001119 /* avoid removing internal modules ... */
Michal Vasko2d051a12017-04-21 09:28:57 +02001120 for (i = 0; i < LY_INTERNAL_MODULE_COUNT; i++) {
Radek Krejci8c107fe2016-10-17 16:00:18 +02001121 if (mod == ctx->models.list[i]) {
Radek Krejci0ec51da2016-12-14 16:42:03 +01001122 LOGERR(LY_EINVAL, "Internal module \"%s\" cannot be removed.", mod->name);
Radek Krejci8c107fe2016-10-17 16:00:18 +02001123 return EXIT_FAILURE;
1124 }
1125 }
1126 /* ... and hide the module from the further processing of the context modules list */
Michal Vasko2d051a12017-04-21 09:28:57 +02001127 for (i = LY_INTERNAL_MODULE_COUNT; i < ctx->models.used; i++) {
Radek Krejci8c107fe2016-10-17 16:00:18 +02001128 if (mod == ctx->models.list[i]) {
1129 ctx->models.list[i] = NULL;
1130 break;
1131 }
1132 }
1133
1134 /* get the complete list of modules to remove because of dependencies,
1135 * we are going also to remove all the imported (not implemented) modules
1136 * that are not used in any other module */
1137 mods = ly_set_new();
1138 ly_set_add(mods, mod, 0);
1139checkdependency:
Michal Vasko2d051a12017-04-21 09:28:57 +02001140 for (i = LY_INTERNAL_MODULE_COUNT; i < ctx->models.used; i++) {
Radek Krejci8c107fe2016-10-17 16:00:18 +02001141 mod = ctx->models.list[i]; /* shortcut */
1142 if (!mod) {
1143 /* skip modules already selected for removing */
1144 continue;
1145 }
1146
1147 /* check depndency of imported modules */
1148 for (j = 0; j < mod->imp_size; j++) {
1149 for (u = 0; u < mods->number; u++) {
1150 if (mod->imp[j].module == mods->set.g[u]) {
1151 /* module is importing some module to remove, so it must be also removed */
1152 ly_set_add(mods, mod, 0);
1153 ctx->models.list[i] = NULL;
1154 /* we have to start again because some of the already checked modules can
1155 * depend on the one we have just decided to remove */
1156 goto checkdependency;
1157 }
1158 }
1159 }
1160 /* check if the imported module is used in any module supposed to be kept */
1161 if (!mod->implemented) {
1162 imported = 0;
Michal Vasko2d051a12017-04-21 09:28:57 +02001163 for (o = LY_INTERNAL_MODULE_COUNT; o < ctx->models.used; o++) {
Radek Krejci8c107fe2016-10-17 16:00:18 +02001164 if (!ctx->models.list[o]) {
1165 /* skip modules already selected for removing */
1166 continue;
1167 }
1168 for (j = 0; j < ctx->models.list[o]->imp_size; j++) {
1169 if (ctx->models.list[o]->imp[j].module == mod) {
1170 /* the module is used in some other module not yet selected to be deleted */
1171 imported = 1;
1172 goto imported;
1173 }
1174 }
1175 }
1176imported:
1177 if (!imported) {
1178 /* module is not implemented and neither imported by any other module in context
1179 * which is supposed to be kept after this operation, so we are going to remove also
1180 * this useless module */
1181 ly_set_add(mods, mod, 0);
1182 ctx->models.list[i] = NULL;
1183 /* we have to start again, this time not because other module can depend on this one
Radek Krejci0ec51da2016-12-14 16:42:03 +01001184 * (we know that there is no such module), but because the module can import module
Radek Krejci8c107fe2016-10-17 16:00:18 +02001185 * that could became useless. If there are no imports, we can continue */
1186 if (mod->imp_size) {
1187 goto checkdependency;
1188 }
1189 }
1190 }
1191 }
1192
Radek Krejci8c107fe2016-10-17 16:00:18 +02001193
1194 /* consolidate the modules list */
Michal Vasko2d051a12017-04-21 09:28:57 +02001195 for (i = o = LY_INTERNAL_MODULE_COUNT; i < ctx->models.used; i++) {
Radek Krejci8c107fe2016-10-17 16:00:18 +02001196 if (ctx->models.list[o]) {
1197 /* used cell */
1198 o++;
1199 } else {
1200 /* the current output cell is empty, move here an input cell */
1201 ctx->models.list[o] = ctx->models.list[i];
1202 ctx->models.list[i] = NULL;
1203 }
1204 }
1205 /* get the last used cell to get know the number of used */
1206 while (!ctx->models.list[o]) {
1207 o--;
1208 }
1209 ctx->models.used = o + 1;
1210 ctx->models.module_set_id++;
1211
Radek Krejci85a54be2016-10-20 12:39:56 +02001212 /* maintain backlinks (start with internal ietf-yang-library which have leafs as possible targets of leafrefs */
Michal Vasko4be5fa22017-02-07 10:12:32 +01001213 ctx_modules_undo_backlinks(ctx, mods);
Radek Krejci85a54be2016-10-20 12:39:56 +02001214
1215 /* free the modules */
1216 for (u = 0; u < mods->number; u++) {
Radek Krejcib2541a32016-12-12 16:45:57 +01001217 /* remove the applied deviations and augments */
1218 lys_sub_module_remove_devs_augs((struct lys_module *)mods->set.g[u]);
Radek Krejci85a54be2016-10-20 12:39:56 +02001219 /* remove the module */
1220 lys_free((struct lys_module *)mods->set.g[u], private_destructor, 0);
1221 }
1222 ly_set_free(mods);
1223
Radek Krejci8c107fe2016-10-17 16:00:18 +02001224 return EXIT_SUCCESS;
1225}
1226
Radek Krejci85a54be2016-10-20 12:39:56 +02001227API void
1228ly_ctx_clean(struct ly_ctx *ctx, void (*private_destructor)(const struct lys_node *node, void *priv))
1229{
Radek Krejci85a54be2016-10-20 12:39:56 +02001230 if (!ctx) {
1231 return;
1232 }
1233
1234 /* models list */
Michal Vasko2d051a12017-04-21 09:28:57 +02001235 for (; ctx->models.used > LY_INTERNAL_MODULE_COUNT; ctx->models.used--) {
Radek Krejcifc8411a2017-02-03 10:26:05 +01001236 /* remove the applied deviations and augments */
Radek Krejcic436a232017-02-08 14:43:11 +01001237 lys_sub_module_remove_devs_augs(ctx->models.list[ctx->models.used - 1]);
Radek Krejcifc8411a2017-02-03 10:26:05 +01001238 /* remove the module */
Radek Krejcic436a232017-02-08 14:43:11 +01001239 lys_free(ctx->models.list[ctx->models.used - 1], private_destructor, 0);
Radek Krejcifc8411a2017-02-03 10:26:05 +01001240 /* clean it for safer future use */
Radek Krejcic436a232017-02-08 14:43:11 +01001241 ctx->models.list[ctx->models.used - 1] = NULL;
Radek Krejci85a54be2016-10-20 12:39:56 +02001242 }
Radek Krejci85a54be2016-10-20 12:39:56 +02001243 ctx->models.module_set_id++;
1244
Radek Krejci83a4bac2017-02-07 15:53:04 +01001245 /* maintain backlinks (actually done only with ietf-yang-library since its leafs can be target of leafref) */
Michal Vasko4be5fa22017-02-07 10:12:32 +01001246 ctx_modules_undo_backlinks(ctx, NULL);
Radek Krejci85a54be2016-10-20 12:39:56 +02001247}
1248
Michal Vaskod7957c02016-04-01 10:27:26 +02001249API const struct lys_module *
1250ly_ctx_get_module_iter(const struct ly_ctx *ctx, uint32_t *idx)
1251{
1252 if (!ctx || !idx) {
1253 ly_errno = LY_EINVAL;
1254 return NULL;
1255 }
1256
Radek Krejci0ec51da2016-12-14 16:42:03 +01001257 for ( ; *idx < (unsigned)ctx->models.used; (*idx)++) {
1258 if (!ctx->models.list[(*idx)]->disabled) {
1259 return ctx->models.list[(*idx)++];
1260 }
1261 }
1262
1263 return NULL;
1264}
1265
1266API const struct lys_module *
1267ly_ctx_get_disabled_module_iter(const struct ly_ctx *ctx, uint32_t *idx)
1268{
1269 if (!ctx || !idx) {
1270 ly_errno = LY_EINVAL;
Michal Vaskod7957c02016-04-01 10:27:26 +02001271 return NULL;
1272 }
1273
Radek Krejci0ec51da2016-12-14 16:42:03 +01001274 for ( ; *idx < (unsigned)ctx->models.used; (*idx)++) {
1275 if (ctx->models.list[(*idx)]->disabled) {
1276 return ctx->models.list[(*idx)++];
1277 }
1278 }
1279
1280 return NULL;
Michal Vaskod7957c02016-04-01 10:27:26 +02001281}
1282
Michal Vasko209a6222015-10-16 09:51:07 +02001283static int
1284ylib_feature(struct lyd_node *parent, struct lys_module *cur_mod)
1285{
1286 int i, j;
1287
1288 /* module features */
1289 for (i = 0; i < cur_mod->features_size; ++i) {
1290 if (!(cur_mod->features[i].flags & LYS_FENABLED)) {
1291 continue;
1292 }
1293
Michal Vasko3e671b52015-10-23 16:23:15 +02001294 if (!lyd_new_leaf(parent, NULL, "feature", cur_mod->features[i].name)) {
Michal Vasko209a6222015-10-16 09:51:07 +02001295 return EXIT_FAILURE;
1296 }
1297 }
1298
1299 /* submodule features */
Radek Krejcic071c542016-01-27 14:57:51 +01001300 for (i = 0; i < cur_mod->inc_size && cur_mod->inc[i].submodule; ++i) {
Michal Vasko209a6222015-10-16 09:51:07 +02001301 for (j = 0; j < cur_mod->inc[i].submodule->features_size; ++j) {
1302 if (!(cur_mod->inc[i].submodule->features[j].flags & LYS_FENABLED)) {
1303 continue;
1304 }
1305
Michal Vasko3e671b52015-10-23 16:23:15 +02001306 if (!lyd_new_leaf(parent, NULL, "feature", cur_mod->inc[i].submodule->features[j].name)) {
Michal Vasko209a6222015-10-16 09:51:07 +02001307 return EXIT_FAILURE;
1308 }
1309 }
1310 }
1311
1312 return EXIT_SUCCESS;
1313}
1314
1315static int
Michal Vaskoff006c12016-02-17 11:15:19 +01001316ylib_deviation(struct lyd_node *parent, struct lys_module *cur_mod)
Michal Vasko97d8c6d2016-02-12 11:05:48 +01001317{
Michal Vasko89563fc2016-07-28 16:19:35 +02001318 uint32_t i = 0, j;
1319 const struct lys_module *mod;
Michal Vasko209a6222015-10-16 09:51:07 +02001320 struct lyd_node *cont;
Michal Vasko89563fc2016-07-28 16:19:35 +02001321 const char *ptr;
Michal Vasko209a6222015-10-16 09:51:07 +02001322
Michal Vasko89563fc2016-07-28 16:19:35 +02001323 if (cur_mod->deviated) {
1324 while ((mod = ly_ctx_get_module_iter(cur_mod->ctx, &i))) {
1325 if (mod == cur_mod) {
1326 continue;
Michal Vasko209a6222015-10-16 09:51:07 +02001327 }
Michal Vasko209a6222015-10-16 09:51:07 +02001328
Michal Vasko89563fc2016-07-28 16:19:35 +02001329 for (j = 0; j < mod->deviation_size; ++j) {
1330 ptr = strstr(mod->deviation[j].target_name, cur_mod->name);
1331 if (ptr && ptr[strlen(cur_mod->name)] == ':') {
1332 cont = lyd_new(parent, NULL, "deviation");
1333 if (!cont) {
1334 return EXIT_FAILURE;
1335 }
1336
1337 if (!lyd_new_leaf(cont, NULL, "name", mod->name)) {
1338 return EXIT_FAILURE;
1339 }
1340 if (!lyd_new_leaf(cont, NULL, "revision", (mod->rev_size ? mod->rev[0].date : ""))) {
1341 return EXIT_FAILURE;
1342 }
Michal Vasko0c2215b2016-08-25 14:18:43 +02001343
1344 break;
Michal Vasko89563fc2016-07-28 16:19:35 +02001345 }
Michal Vasko209a6222015-10-16 09:51:07 +02001346 }
1347 }
1348 }
1349
1350 return EXIT_SUCCESS;
1351}
1352
1353static int
1354ylib_submodules(struct lyd_node *parent, struct lys_module *cur_mod)
1355{
1356 int i;
Radek Krejcia77904e2016-02-25 16:23:45 +01001357 char *str;
Radek Krejcid9723912016-09-16 17:06:06 +02001358 struct lyd_node *item;
Michal Vasko209a6222015-10-16 09:51:07 +02001359
Radek Krejcic071c542016-01-27 14:57:51 +01001360 for (i = 0; i < cur_mod->inc_size && cur_mod->inc[i].submodule; ++i) {
Radek Krejcid9723912016-09-16 17:06:06 +02001361 item = lyd_new(parent, NULL, "submodule");
Radek Krejci6e05cea2015-12-10 16:34:37 +01001362 if (!item) {
Michal Vasko209a6222015-10-16 09:51:07 +02001363 return EXIT_FAILURE;
1364 }
1365
Radek Krejci6e05cea2015-12-10 16:34:37 +01001366 if (!lyd_new_leaf(item, NULL, "name", cur_mod->inc[i].submodule->name)) {
Michal Vasko209a6222015-10-16 09:51:07 +02001367 return EXIT_FAILURE;
1368 }
Radek Krejci6e05cea2015-12-10 16:34:37 +01001369 if (!lyd_new_leaf(item, NULL, "revision", (cur_mod->inc[i].submodule->rev_size ?
Michal Vasko3e671b52015-10-23 16:23:15 +02001370 cur_mod->inc[i].submodule->rev[0].date : ""))) {
Michal Vasko209a6222015-10-16 09:51:07 +02001371 return EXIT_FAILURE;
1372 }
Radek Krejcia77904e2016-02-25 16:23:45 +01001373 if (cur_mod->inc[i].submodule->filepath) {
Radek Krejci95aa2012016-03-03 11:21:09 +01001374 if (asprintf(&str, "file://%s", cur_mod->inc[i].submodule->filepath) == -1) {
Radek Krejcia77904e2016-02-25 16:23:45 +01001375 LOGMEM;
1376 return EXIT_FAILURE;
Radek Krejci6e65af92016-03-07 12:48:19 +01001377 } else if (!lyd_new_leaf(item, NULL, "schema", str)) {
Radek Krejci19f9ede2016-02-25 16:29:21 +01001378 free(str);
Radek Krejcia77904e2016-02-25 16:23:45 +01001379 return EXIT_FAILURE;
1380 }
Radek Krejci19f9ede2016-02-25 16:29:21 +01001381 free(str);
Michal Vasko209a6222015-10-16 09:51:07 +02001382 }
1383 }
1384
1385 return EXIT_SUCCESS;
1386}
1387
1388API struct lyd_node *
1389ly_ctx_info(struct ly_ctx *ctx)
1390{
1391 int i;
1392 char id[8];
Radek Krejcia77904e2016-02-25 16:23:45 +01001393 char *str;
Michal Vasko1e62a092015-12-01 12:27:20 +01001394 const struct lys_module *mod;
Michal Vasko209a6222015-10-16 09:51:07 +02001395 struct lyd_node *root, *cont;
1396
Michal Vasko7eccc6c2016-03-24 14:56:33 +01001397 if (!ctx) {
1398 ly_errno = LY_EINVAL;
1399 return NULL;
1400 }
1401
Radek Krejcibd9e8d22016-02-03 14:11:48 +01001402 mod = ly_ctx_get_module(ctx, "ietf-yang-library", IETF_YANG_LIB_REV);
1403 if (!mod || !mod->data) {
1404 LOGINT;
Michal Vasko209a6222015-10-16 09:51:07 +02001405 return NULL;
1406 }
1407
Radek Krejcibd9e8d22016-02-03 14:11:48 +01001408 root = lyd_new(NULL, mod, "modules-state");
Michal Vasko209a6222015-10-16 09:51:07 +02001409 if (!root) {
1410 return NULL;
1411 }
1412
1413 for (i = 0; i < ctx->models.used; ++i) {
Radek Krejci0ec51da2016-12-14 16:42:03 +01001414 if (ctx->models.list[i]->disabled) {
1415 /* skip the disabled modules */
1416 continue;
1417 }
1418
Michal Vasko209a6222015-10-16 09:51:07 +02001419 cont = lyd_new(root, NULL, "module");
1420 if (!cont) {
1421 lyd_free(root);
1422 return NULL;
1423 }
1424
Michal Vasko3e671b52015-10-23 16:23:15 +02001425 if (!lyd_new_leaf(cont, NULL, "name", ctx->models.list[i]->name)) {
Michal Vasko209a6222015-10-16 09:51:07 +02001426 lyd_free(root);
1427 return NULL;
1428 }
Michal Vasko3e671b52015-10-23 16:23:15 +02001429 if (!lyd_new_leaf(cont, NULL, "revision", (ctx->models.list[i]->rev_size ?
Michal Vasko209a6222015-10-16 09:51:07 +02001430 ctx->models.list[i]->rev[0].date : ""))) {
1431 lyd_free(root);
1432 return NULL;
1433 }
Radek Krejcia77904e2016-02-25 16:23:45 +01001434 if (ctx->models.list[i]->filepath) {
Radek Krejci15412ca2016-03-03 11:16:52 +01001435 if (asprintf(&str, "file://%s", ctx->models.list[i]->filepath) == -1) {
Radek Krejcia77904e2016-02-25 16:23:45 +01001436 LOGMEM;
1437 lyd_free(root);
1438 return NULL;
1439 } else if (!lyd_new_leaf(cont, NULL, "schema", str)) {
Radek Krejci19f9ede2016-02-25 16:29:21 +01001440 free(str);
Radek Krejcia77904e2016-02-25 16:23:45 +01001441 lyd_free(root);
1442 return NULL;
1443 }
Radek Krejci19f9ede2016-02-25 16:29:21 +01001444 free(str);
Michal Vasko209a6222015-10-16 09:51:07 +02001445 }
Michal Vasko3e671b52015-10-23 16:23:15 +02001446 if (!lyd_new_leaf(cont, NULL, "namespace", ctx->models.list[i]->ns)) {
Michal Vasko209a6222015-10-16 09:51:07 +02001447 lyd_free(root);
1448 return NULL;
1449 }
1450 if (ylib_feature(cont, ctx->models.list[i])) {
1451 lyd_free(root);
1452 return NULL;
1453 }
Michal Vaskoff006c12016-02-17 11:15:19 +01001454 if (ylib_deviation(cont, ctx->models.list[i])) {
Michal Vasko209a6222015-10-16 09:51:07 +02001455 lyd_free(root);
1456 return NULL;
1457 }
1458 if (ctx->models.list[i]->implemented
Radek Krejcibd9e8d22016-02-03 14:11:48 +01001459 && !lyd_new_leaf(cont, NULL, "conformance-type", "implement")) {
Michal Vasko209a6222015-10-16 09:51:07 +02001460 lyd_free(root);
1461 return NULL;
1462 }
1463 if (!ctx->models.list[i]->implemented
Radek Krejcibd9e8d22016-02-03 14:11:48 +01001464 && !lyd_new_leaf(cont, NULL, "conformance-type", "import")) {
Michal Vasko209a6222015-10-16 09:51:07 +02001465 lyd_free(root);
1466 return NULL;
1467 }
1468 if (ylib_submodules(cont, ctx->models.list[i])) {
1469 lyd_free(root);
1470 return NULL;
1471 }
1472 }
1473
1474 sprintf(id, "%u", ctx->models.module_set_id);
Michal Vasko3e671b52015-10-23 16:23:15 +02001475 if (!lyd_new_leaf(root, mod, "module-set-id", id)) {
Michal Vasko209a6222015-10-16 09:51:07 +02001476 lyd_free(root);
1477 return NULL;
1478 }
1479
Michal Vaskocdb90172016-09-13 09:34:36 +02001480 if (lyd_validate(&root, LYD_OPT_NOSIBLINGS, NULL)) {
Michal Vasko209a6222015-10-16 09:51:07 +02001481 lyd_free(root);
1482 return NULL;
1483 }
1484
1485 return root;
1486}
Michal Vasko3edeaf72016-02-11 13:17:43 +01001487
1488API const struct lys_node *
Michal Vasko3547c532016-03-14 09:40:50 +01001489ly_ctx_get_node(struct ly_ctx *ctx, const struct lys_node *start, const char *nodeid)
Michal Vasko3edeaf72016-02-11 13:17:43 +01001490{
Michal Vaskoe733d682016-03-14 09:08:27 +01001491 const struct lys_node *node;
Michal Vasko3edeaf72016-02-11 13:17:43 +01001492
Michal Vasko3547c532016-03-14 09:40:50 +01001493 if (!ctx || !nodeid || ((nodeid[0] != '/') && !start)) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01001494 ly_errno = LY_EINVAL;
1495 return NULL;
1496 }
1497
Michal Vaskoe733d682016-03-14 09:08:27 +01001498 /* sets error and everything */
Michal Vasko8d26e5c2016-09-08 10:03:49 +02001499 node = resolve_json_nodeid(nodeid, ctx, start);
Michal Vasko3edeaf72016-02-11 13:17:43 +01001500
Michal Vaskoe733d682016-03-14 09:08:27 +01001501 return node;
Michal Vasko3edeaf72016-02-11 13:17:43 +01001502}