blob: 2c23246eaef98ae798e67877587ca350d21eaae0 [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 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
22#define _GNU_SOURCE
Radek Krejcifd4e6e32015-08-10 15:00:51 +020023#include <stddef.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020024#include <stdlib.h>
25#include <string.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <unistd.h>
29#include <errno.h>
30#include <fcntl.h>
31
32#include "common.h"
33#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020034#include "dict_private.h"
Michal Vasko209a6222015-10-16 09:51:07 +020035#include "parser.h"
Radek Krejcibc9cf932015-07-30 11:09:39 +020036#include "tree_internal.h"
Radek Krejcida04f4a2015-05-21 12:54:09 +020037
Michal Vasko8d054e42015-08-03 12:42:06 +020038#define IETF_INET_TYPES_PATH "../models/ietf-inet-types@2013-07-15.h"
Michal Vasko21181c42015-08-03 13:46:45 +020039#define IETF_YANG_TYPES_PATH "../models/ietf-yang-types@2013-07-15.h"
Michal Vasko8d054e42015-08-03 12:42:06 +020040#define IETF_YANG_LIB_PATH "../models/ietf-yang-library@2015-07-03.h"
41
Michal Vasko8d054e42015-08-03 12:42:06 +020042#include IETF_INET_TYPES_PATH
Michal Vasko21181c42015-08-03 13:46:45 +020043#include IETF_YANG_TYPES_PATH
Michal Vasko8d054e42015-08-03 12:42:06 +020044#include IETF_YANG_LIB_PATH
45
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020046API struct ly_ctx *
47ly_ctx_new(const char *search_dir)
Radek Krejcida04f4a2015-05-21 12:54:09 +020048{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020049 struct ly_ctx *ctx;
Michal Vasko70b6d692015-08-03 14:05:59 +020050 char *cwd;
Radek Krejcida04f4a2015-05-21 12:54:09 +020051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020052 ctx = calloc(1, sizeof *ctx);
53 if (!ctx) {
54 LOGMEM;
55 return NULL;
56 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020058 /* dictionary */
59 lydict_init(&ctx->dict);
Radek Krejcida04f4a2015-05-21 12:54:09 +020060
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020061 /* models list */
62 ctx->models.list = calloc(16, sizeof *ctx->models.list);
63 ctx->models.used = 0;
64 ctx->models.size = 16;
65 if (search_dir) {
66 cwd = get_current_dir_name();
67 if (chdir(search_dir)) {
68 LOGERR(LY_ESYS, "Unable to use search directory \"%s\" (%s)",
69 search_dir, strerror(errno));
70 free(cwd);
71 ly_ctx_destroy(ctx);
72 return NULL;
73 }
74 ctx->models.search_path = get_current_dir_name();
75 chdir(cwd);
76 free(cwd);
77 }
Michal Vasko14719b22015-08-03 12:47:55 +020078 ctx->models.module_set_id = 1;
79
Michal Vasko8d054e42015-08-03 12:42:06 +020080 /* load ietf-inet-types */
Michal Vasko1e62a092015-12-01 12:27:20 +010081 ctx->models.list[0] = (struct lys_module *)lys_parse(ctx, (char *)ietf_inet_types_2013_07_15_yin, LYS_IN_YIN);
Michal Vasko8d054e42015-08-03 12:42:06 +020082 if (!ctx->models.list[0]) {
83 ly_ctx_destroy(ctx);
84 return NULL;
85 }
86
87 /* load ietf-yang-types */
Michal Vasko1e62a092015-12-01 12:27:20 +010088 ctx->models.list[1] = (struct lys_module *)lys_parse(ctx, (char *)ietf_yang_types_2013_07_15_yin, LYS_IN_YIN);
Michal Vasko8d054e42015-08-03 12:42:06 +020089 if (!ctx->models.list[1]) {
90 ly_ctx_destroy(ctx);
91 return NULL;
92 }
93
94 /* load ietf-yang-library */
Michal Vasko1e62a092015-12-01 12:27:20 +010095 ctx->models.list[2] = (struct lys_module *)lys_parse(ctx, (char *)ietf_yang_library_2015_07_03_yin, LYS_IN_YIN);
Michal Vasko8d054e42015-08-03 12:42:06 +020096 if (!ctx->models.list[2]) {
97 ly_ctx_destroy(ctx);
98 return NULL;
99 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200101 return ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200102}
103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200104API void
Michal Vasko60ba9a62015-07-03 14:42:31 +0200105ly_ctx_set_searchdir(struct ly_ctx *ctx, const char *search_dir)
106{
107 char *cwd;
108
109 if (!ctx) {
110 return;
111 }
112
113 if (search_dir) {
114 cwd = get_current_dir_name();
115 if (chdir(search_dir)) {
116 LOGERR(LY_ESYS, "Unable to use search directory \"%s\" (%s)",
117 search_dir, strerror(errno));
118 free(cwd);
119 return;
120 }
Michal Vasko3eff9322015-11-10 11:02:30 +0100121 free(ctx->models.search_path);
Michal Vasko60ba9a62015-07-03 14:42:31 +0200122 ctx->models.search_path = get_current_dir_name();
Michal Vasko3eff9322015-11-10 11:02:30 +0100123
Michal Vasko60ba9a62015-07-03 14:42:31 +0200124 chdir(cwd);
125 free(cwd);
126 } else {
127 free(ctx->models.search_path);
128 ctx->models.search_path = NULL;
129 }
130}
131
Radek Krejcib081d8d2015-10-21 16:29:07 +0200132API const char *
Michal Vasko1e62a092015-12-01 12:27:20 +0100133ly_ctx_get_searchdir(const struct ly_ctx *ctx)
Radek Krejci5a797572015-10-21 15:45:45 +0200134{
135 return ctx->models.search_path;
136}
137
Michal Vasko60ba9a62015-07-03 14:42:31 +0200138API void
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200139ly_ctx_destroy(struct ly_ctx *ctx)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200140{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200141 if (!ctx) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200142 return;
143 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200145 /* models list */
Radek Krejcidce51452015-06-16 15:20:08 +0200146 while (ctx->models.used) {
Michal Vasko13b15832015-08-19 11:04:48 +0200147 lys_free(ctx->models.list[0], 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200148 }
149 free(ctx->models.search_path);
150 free(ctx->models.list);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200151
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200152 /* dictionary */
153 lydict_clean(&ctx->dict);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200155 free(ctx);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200156}
157
Michal Vasko1e62a092015-12-01 12:27:20 +0100158API const struct lys_submodule *
159ly_ctx_get_submodule(const struct lys_module *module, const char *name, const char *revision)
Radek Krejciefaeba32015-05-27 14:30:57 +0200160{
Radek Krejcib8048692015-08-05 13:36:34 +0200161 struct lys_submodule *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200162 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +0200163
Radek Krejci63a91a92015-07-29 13:31:04 +0200164 if (!module || !name) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200165 ly_errno = LY_EINVAL;
166 return NULL;
167 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200168
Radek Krejcie98bb4b2015-07-30 14:21:41 +0200169 /* TODO search also for submodules not directly available from the main module */
170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200171 /* search in modules included by the main module */
172 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +0200173 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200174 }
175 for (i = 0; i < module->inc_size; i++) {
176 result = module->inc[i].submodule;
177 if (strcmp(name, result->name)) {
178 continue;
179 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200181 if (!revision || (result->rev_size && !strcmp(revision, result->rev[0].date))) {
182 return result;
183 }
184 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200185
Radek Krejci63a91a92015-07-29 13:31:04 +0200186 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +0200187}
188
Michal Vasko1e62a092015-12-01 12:27:20 +0100189static const struct lys_module *
190ly_ctx_get_module_by(const struct ly_ctx *ctx, const char *key, int offset, const char *revision)
Radek Krejciefaeba32015-05-27 14:30:57 +0200191{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200192 int i;
Radek Krejcib8048692015-08-05 13:36:34 +0200193 struct lys_module *result = NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +0200194
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200195 if (!ctx || !key) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200196 ly_errno = LY_EINVAL;
197 return NULL;
198 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200199
Radek Krejcidce51452015-06-16 15:20:08 +0200200 for (i = 0; i < ctx->models.used; i++) {
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200201 /* use offset to get address of the pointer to string (char**), remember that offset is in
202 * bytes, so we have to cast the pointer to the module to (char*), finally, we want to have
203 * string not the pointer to string
204 */
205 if (!ctx->models.list[i] || strcmp(key, *(char**)(((char*)ctx->models.list[i]) + offset))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200206 continue;
207 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200208
Radek Krejcif647e612015-07-30 11:36:07 +0200209 if (!revision) {
210 /* compare revisons and remember the newest one */
211 if (result) {
212 if (!ctx->models.list[i]->rev_size) {
213 /* the current have no revision, keep the previous with some revision */
214 continue;
215 }
216 if (result->rev_size && strcmp(ctx->models.list[i]->rev[0].date, result->rev[0].date) < 0) {
217 /* the previous found matching module has a newer revision */
218 continue;
219 }
220 }
221
222 /* remember the current match and search for newer version */
223 result = ctx->models.list[i];
224 } else {
225 if (ctx->models.list[i]->rev_size && !strcmp(revision, ctx->models.list[i]->rev[0].date)) {
226 /* matching revision */
Michal Vasko97586502015-08-12 14:32:18 +0200227 result = ctx->models.list[i];
228 break;
Radek Krejcif647e612015-07-30 11:36:07 +0200229 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200230 }
231 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200232
Radek Krejcif647e612015-07-30 11:36:07 +0200233 return result;
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200234
235}
236
Michal Vasko1e62a092015-12-01 12:27:20 +0100237API const struct lys_module *
238ly_ctx_get_module_by_ns(const struct ly_ctx *ctx, const char *ns, const char *revision)
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200239{
240 return ly_ctx_get_module_by(ctx, ns, offsetof(struct lys_module, ns), revision);
241}
242
Michal Vasko1e62a092015-12-01 12:27:20 +0100243API const struct lys_module *
244ly_ctx_get_module(const struct ly_ctx *ctx, const char *name, const char *revision)
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200245{
246 return ly_ctx_get_module_by(ctx, name, offsetof(struct lys_module, name), revision);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200247}
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200248
Michal Vasko82465962015-11-10 11:03:11 +0100249API struct lys_module *
250ly_ctx_load_module(struct ly_ctx *ctx, const char *dir, const char *name, const char *revision)
251{
252 struct lys_module *module;
253 char *cwd = NULL;
254
255 if (!ctx || !name) {
256 ly_errno = LY_EINVAL;
257 return NULL;
258 }
259
260 if (dir) {
261 cwd = get_current_dir_name();
262 if (chdir(dir) == -1) {
263 LOGWRN("Unable to change working directory to \"%s\" (%s).", dir, strerror(errno));
264 free(cwd);
265 cwd = NULL;
266 }
267 }
268
269 module = lyp_search_file(ctx, NULL, name, revision);
270
271 /* did we change the working directory? */
272 if (cwd) {
273 if (chdir(cwd) == -1) {
274 /* should seriously not happen */
275 LOGINT;
276 }
277 free(cwd);
278 }
279
280 return module;
281}
282
Radek Krejci96a10da2015-07-30 11:00:14 +0200283API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +0100284ly_ctx_get_module_names(const struct ly_ctx *ctx)
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200285{
286 int i;
Radek Krejci96a10da2015-07-30 11:00:14 +0200287 const char **result = NULL;
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200288
289 if (!ctx) {
290 ly_errno = LY_EINVAL;
291 return NULL;
292 }
293
Michal Vaskoe2ea44b2015-07-07 11:31:48 +0200294 result = malloc((ctx->models.used+1) * sizeof *result);
295
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200296 for (i = 0; i < ctx->models.used; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +0200297 result[i] = ctx->models.list[i]->name;
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200298 }
Michal Vaskoe2ea44b2015-07-07 11:31:48 +0200299 result[i] = NULL;
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200300
301 return result;
Michal Vaskofa8c8282015-07-03 15:14:59 +0200302}
303
Radek Krejci96a10da2015-07-30 11:00:14 +0200304API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +0100305ly_ctx_get_submodule_names(const struct ly_ctx *ctx, const char *module_name)
Michal Vaskofa8c8282015-07-03 15:14:59 +0200306{
307 int i;
Radek Krejci96a10da2015-07-30 11:00:14 +0200308 const char **result = NULL;
Michal Vasko1e62a092015-12-01 12:27:20 +0100309 const struct lys_module *mod;
Michal Vaskofa8c8282015-07-03 15:14:59 +0200310
311 if (!ctx) {
312 ly_errno = LY_EINVAL;
313 return NULL;
314 }
315
Radek Krejci96a10da2015-07-30 11:00:14 +0200316 mod = ly_ctx_get_module(ctx, module_name, NULL);
Michal Vaskofa8c8282015-07-03 15:14:59 +0200317 if (!mod) {
Radek Krejci96a10da2015-07-30 11:00:14 +0200318 LOGERR(LY_EVALID, "Data model \"%s\" not loaded", module_name);
Michal Vaskofa8c8282015-07-03 15:14:59 +0200319 return NULL;
320 }
321
322 result = malloc((mod->inc_size+1) * sizeof *result);
323
324 for (i = 0; i < mod->inc_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +0200325 result[i] = mod->inc[i].submodule->name;
Michal Vaskofa8c8282015-07-03 15:14:59 +0200326 }
327 result[i] = NULL;
328
329 return result;
330}
Michal Vasko209a6222015-10-16 09:51:07 +0200331
Michal Vasko1e62a092015-12-01 12:27:20 +0100332API const struct lys_node *
333ly_ctx_get_node(const struct ly_ctx *ctx, const char *nodeid)
Michal Vaskof7a03dc2015-10-22 16:09:06 +0200334{
Michal Vasko1e62a092015-12-01 12:27:20 +0100335 const struct lys_node *ret;
336 const struct lys_module *module;
Michal Vaskof7a03dc2015-10-22 16:09:06 +0200337 char *mod_name;
338 int parsed;
339
340 if (!ctx || !nodeid) {
341 ly_errno = LY_EINVAL;
342 return NULL;
343 }
344
345 if ((nodeid[0] != '/') || ((parsed = parse_identifier(nodeid + 1)) < 1)) {
346 ly_errno = LY_EINVAL;
347 return NULL;
348 }
349
350 /* get the correct module */
351 mod_name = strndup(nodeid + 1, parsed);
352 module = ly_ctx_get_module(ctx, mod_name, NULL);
353 free(mod_name);
354 if (!module) {
355 ly_errno = LY_EINVAL;
356 return NULL;
357 }
358
359 /* now we can parse the whole schema */
360 if (resolve_schema_nodeid(nodeid, NULL, module, LYS_AUGMENT, &ret)) {
361 ly_errno = LY_EINVAL;
362 return NULL;
363 }
364
365 return ret;
366}
367
Michal Vasko209a6222015-10-16 09:51:07 +0200368static int
369ylib_feature(struct lyd_node *parent, struct lys_module *cur_mod)
370{
371 int i, j;
372
373 /* module features */
374 for (i = 0; i < cur_mod->features_size; ++i) {
375 if (!(cur_mod->features[i].flags & LYS_FENABLED)) {
376 continue;
377 }
378
Michal Vasko3e671b52015-10-23 16:23:15 +0200379 if (!lyd_new_leaf(parent, NULL, "feature", cur_mod->features[i].name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200380 return EXIT_FAILURE;
381 }
382 }
383
384 /* submodule features */
385 for (i = 0; i < cur_mod->inc_size; ++i) {
386 for (j = 0; j < cur_mod->inc[i].submodule->features_size; ++j) {
387 if (!(cur_mod->inc[i].submodule->features[j].flags & LYS_FENABLED)) {
388 continue;
389 }
390
Michal Vasko3e671b52015-10-23 16:23:15 +0200391 if (!lyd_new_leaf(parent, NULL, "feature", cur_mod->inc[i].submodule->features[j].name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200392 return EXIT_FAILURE;
393 }
394 }
395 }
396
397 return EXIT_SUCCESS;
398}
399
400static int
401ylib_deviation(struct lyd_node *parent, struct lys_module *cur_mod, struct ly_ctx *ctx)
402{
403 int i, j, k;
404 struct lys_module *target_module, *mod_iter;
405 struct lyd_node *cont;
406
407 for (i = 0; i < ctx->models.used; ++i) {
408 mod_iter = ctx->models.list[i];
409 for (k = 0; k < mod_iter->deviation_size; ++k) {
410 if (mod_iter->deviation[k].target->module->type) {
411 target_module = ((struct lys_submodule *)mod_iter->deviation[k].target->module)->belongsto;
412 } else {
413 target_module = mod_iter->deviation[k].target->module;
414 }
415
416 /* we found a module deviating our module */
417 if (target_module == cur_mod) {
418 cont = lyd_new(parent, NULL, "deviation");
419 if (!cont) {
420 return EXIT_FAILURE;
421 }
422
Michal Vasko3e671b52015-10-23 16:23:15 +0200423 if (!lyd_new_leaf(cont, NULL, "name", mod_iter->name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200424 return EXIT_FAILURE;
425 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200426 if (!lyd_new_leaf(cont, NULL, "revision", (mod_iter->rev_size ? mod_iter->rev[0].date : ""))) {
Michal Vasko209a6222015-10-16 09:51:07 +0200427 return EXIT_FAILURE;
428 }
429 }
430 }
431
432 for (j = 0; j < mod_iter->inc_size; ++j) {
433 for (k = 0; k < mod_iter->inc[j].submodule->deviation_size; ++k) {
434 if (mod_iter->inc[j].submodule->deviation[k].target->module->type) {
435 target_module = ((struct lys_submodule *)
436 mod_iter->inc[j].submodule->deviation[k].target->module)->belongsto;
437 } else {
438 target_module = mod_iter->inc[j].submodule->deviation[k].target->module;
439 }
440
441 /* we found a submodule deviating our module */
442 if (target_module == cur_mod) {
443 cont = lyd_new(parent, NULL, "deviation");
444 if (!cont) {
445 return EXIT_FAILURE;
446 }
447
Michal Vasko3e671b52015-10-23 16:23:15 +0200448 if (!lyd_new_leaf(cont, NULL, "name", mod_iter->inc[j].submodule->name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200449 return EXIT_FAILURE;
450 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200451 if (!lyd_new_leaf(cont, NULL, "revision",
Michal Vasko209a6222015-10-16 09:51:07 +0200452 (mod_iter->inc[j].submodule->rev_size ?
453 mod_iter->inc[j].submodule->rev[0].date : ""))) {
454 return EXIT_FAILURE;
455 }
456 }
457 }
458 }
459 }
460
461 return EXIT_SUCCESS;
462}
463
464static int
465ylib_submodules(struct lyd_node *parent, struct lys_module *cur_mod)
466{
467 int i;
468 struct lyd_node *cont;
469
470 for (i = 0; i < cur_mod->inc_size; ++i) {
471 cont = lyd_new(parent, NULL, "submodule");
472 if (!cont) {
473 return EXIT_FAILURE;
474 }
475
Michal Vasko3e671b52015-10-23 16:23:15 +0200476 if (!lyd_new_leaf(cont, NULL, "name", cur_mod->inc[i].submodule->name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200477 return EXIT_FAILURE;
478 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200479 if (!lyd_new_leaf(cont, NULL, "revision", (cur_mod->inc[i].submodule->rev_size ?
480 cur_mod->inc[i].submodule->rev[0].date : ""))) {
Michal Vasko209a6222015-10-16 09:51:07 +0200481 return EXIT_FAILURE;
482 }
483 if (cur_mod->inc[i].submodule->uri
Michal Vasko3e671b52015-10-23 16:23:15 +0200484 && !lyd_new_leaf(cont, NULL, "schema", cur_mod->inc[i].submodule->uri)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200485 return EXIT_FAILURE;
486 }
487 }
488
489 return EXIT_SUCCESS;
490}
491
492API struct lyd_node *
493ly_ctx_info(struct ly_ctx *ctx)
494{
495 int i;
496 char id[8];
Michal Vasko1e62a092015-12-01 12:27:20 +0100497 const struct lys_module *mod;
Michal Vasko209a6222015-10-16 09:51:07 +0200498 struct lyd_node *root, *cont;
499
500 mod = ly_ctx_get_module(ctx, "ietf-yang-library", NULL);
501 if (!mod) {
502 mod = lyp_search_file(ctx, NULL, "ietf-yang-library", NULL);
503 }
504 if (!mod || !mod->data || strcmp(mod->data->next->name, "modules")) {
505 return NULL;
506 }
507
508 root = lyd_new(NULL, mod, "modules");
509 if (!root) {
510 return NULL;
511 }
512
513 for (i = 0; i < ctx->models.used; ++i) {
514 cont = lyd_new(root, NULL, "module");
515 if (!cont) {
516 lyd_free(root);
517 return NULL;
518 }
519
Michal Vasko3e671b52015-10-23 16:23:15 +0200520 if (!lyd_new_leaf(cont, NULL, "name", ctx->models.list[i]->name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200521 lyd_free(root);
522 return NULL;
523 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200524 if (!lyd_new_leaf(cont, NULL, "revision", (ctx->models.list[i]->rev_size ?
Michal Vasko209a6222015-10-16 09:51:07 +0200525 ctx->models.list[i]->rev[0].date : ""))) {
526 lyd_free(root);
527 return NULL;
528 }
529 if (ctx->models.list[i]->uri
Michal Vasko3e671b52015-10-23 16:23:15 +0200530 && !lyd_new_leaf(cont, NULL, "schema", ctx->models.list[i]->uri)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200531 lyd_free(root);
532 return NULL;
533 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200534 if (!lyd_new_leaf(cont, NULL, "namespace", ctx->models.list[i]->ns)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200535 lyd_free(root);
536 return NULL;
537 }
538 if (ylib_feature(cont, ctx->models.list[i])) {
539 lyd_free(root);
540 return NULL;
541 }
542 if (ylib_deviation(cont, ctx->models.list[i], ctx)) {
543 lyd_free(root);
544 return NULL;
545 }
546 if (ctx->models.list[i]->implemented
Michal Vasko3e671b52015-10-23 16:23:15 +0200547 && !lyd_new_leaf(cont, NULL, "conformance", "implement")) {
Michal Vasko209a6222015-10-16 09:51:07 +0200548 lyd_free(root);
549 return NULL;
550 }
551 if (!ctx->models.list[i]->implemented
Michal Vasko3e671b52015-10-23 16:23:15 +0200552 && !lyd_new_leaf(cont, NULL, "conformance", "import")) {
Michal Vasko209a6222015-10-16 09:51:07 +0200553 lyd_free(root);
554 return NULL;
555 }
556 if (ylib_submodules(cont, ctx->models.list[i])) {
557 lyd_free(root);
558 return NULL;
559 }
560 }
561
562 sprintf(id, "%u", ctx->models.module_set_id);
Michal Vasko3e671b52015-10-23 16:23:15 +0200563 if (!lyd_new_leaf(root, mod, "module-set-id", id)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200564 lyd_free(root);
565 return NULL;
566 }
567
568 if (lyd_validate(root, 0)) {
569 lyd_free(root);
570 return NULL;
571 }
572
573 return root;
574}