blob: c177faa7c99da22c0261bf0bbdb0bcf24179a8fd [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 Krejcida04f4a2015-05-21 12:54:09 +020030
Radek Krejcid9f7ec52016-02-11 16:27:01 +010031#define YANG_FAKEMODULE_PATH "../models/yang@2016-02-11.h"
Michal Vasko8d054e42015-08-03 12:42:06 +020032#define IETF_INET_TYPES_PATH "../models/ietf-inet-types@2013-07-15.h"
Michal Vasko21181c42015-08-03 13:46:45 +020033#define IETF_YANG_TYPES_PATH "../models/ietf-yang-types@2013-07-15.h"
Radek Krejcibd9e8d22016-02-03 14:11:48 +010034#define IETF_YANG_LIB_PATH "../models/ietf-yang-library@2016-02-01.h"
35#define IETF_YANG_LIB_REV "2016-02-01"
Michal Vasko8d054e42015-08-03 12:42:06 +020036
Radek Krejcid9f7ec52016-02-11 16:27:01 +010037#include YANG_FAKEMODULE_PATH
Michal Vasko8d054e42015-08-03 12:42:06 +020038#include IETF_INET_TYPES_PATH
Michal Vasko21181c42015-08-03 13:46:45 +020039#include IETF_YANG_TYPES_PATH
Michal Vasko8d054e42015-08-03 12:42:06 +020040#include IETF_YANG_LIB_PATH
41
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020042API struct ly_ctx *
43ly_ctx_new(const char *search_dir)
Radek Krejcida04f4a2015-05-21 12:54:09 +020044{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020045 struct ly_ctx *ctx;
Michal Vasko70b6d692015-08-03 14:05:59 +020046 char *cwd;
Radek Krejcida04f4a2015-05-21 12:54:09 +020047
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020048 ctx = calloc(1, sizeof *ctx);
49 if (!ctx) {
50 LOGMEM;
51 return NULL;
52 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020054 /* dictionary */
55 lydict_init(&ctx->dict);
Radek Krejcida04f4a2015-05-21 12:54:09 +020056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020057 /* models list */
58 ctx->models.list = calloc(16, sizeof *ctx->models.list);
Michal Vasko253035f2015-12-17 16:58:13 +010059 if (!ctx->models.list) {
60 LOGMEM;
61 free(ctx);
62 return NULL;
63 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020064 ctx->models.used = 0;
65 ctx->models.size = 16;
66 if (search_dir) {
67 cwd = get_current_dir_name();
68 if (chdir(search_dir)) {
69 LOGERR(LY_ESYS, "Unable to use search directory \"%s\" (%s)",
70 search_dir, strerror(errno));
71 free(cwd);
Radek Krejcifa0b5e02016-02-04 13:57:03 +010072 ly_ctx_destroy(ctx, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020073 return NULL;
74 }
75 ctx->models.search_path = get_current_dir_name();
Radek Krejci15412ca2016-03-03 11:16:52 +010076 if (chdir(cwd)) {
77 LOGWRN("Unable to return back to working directory \"%s\" (%s)",
78 cwd, strerror(errno));
79 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020080 free(cwd);
81 }
Michal Vasko14719b22015-08-03 12:47:55 +020082 ctx->models.module_set_id = 1;
83
Radek Krejcid9f7ec52016-02-11 16:27:01 +010084 /* load (fake) YANG module */
85 if (!lys_parse_mem(ctx, (char *)yang_2016_02_11_yin, LYS_IN_YIN)) {
86 ly_ctx_destroy(ctx, NULL);
87 return NULL;
88 }
89
Michal Vasko8d054e42015-08-03 12:42:06 +020090 /* load ietf-inet-types */
Radek Krejcid9f7ec52016-02-11 16:27:01 +010091 if (!lys_parse_mem(ctx, (char *)ietf_inet_types_2013_07_15_yin, LYS_IN_YIN)) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +010092 ly_ctx_destroy(ctx, NULL);
Michal Vasko8d054e42015-08-03 12:42:06 +020093 return NULL;
94 }
95
96 /* load ietf-yang-types */
Radek Krejcid9f7ec52016-02-11 16:27:01 +010097 if (!lys_parse_mem(ctx, (char *)ietf_yang_types_2013_07_15_yin, LYS_IN_YIN)) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +010098 ly_ctx_destroy(ctx, NULL);
Michal Vasko8d054e42015-08-03 12:42:06 +020099 return NULL;
100 }
101
102 /* load ietf-yang-library */
Radek Krejcid9f7ec52016-02-11 16:27:01 +0100103 if (!lys_parse_mem(ctx, (char *)ietf_yang_library_2016_02_01_yin, LYS_IN_YIN)) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +0100104 ly_ctx_destroy(ctx, NULL);
Michal Vasko8d054e42015-08-03 12:42:06 +0200105 return NULL;
106 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200107
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200108 return ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200109}
110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200111API void
Michal Vasko60ba9a62015-07-03 14:42:31 +0200112ly_ctx_set_searchdir(struct ly_ctx *ctx, const char *search_dir)
113{
114 char *cwd;
115
116 if (!ctx) {
117 return;
118 }
119
120 if (search_dir) {
121 cwd = get_current_dir_name();
122 if (chdir(search_dir)) {
123 LOGERR(LY_ESYS, "Unable to use search directory \"%s\" (%s)",
124 search_dir, strerror(errno));
125 free(cwd);
126 return;
127 }
Michal Vasko3eff9322015-11-10 11:02:30 +0100128 free(ctx->models.search_path);
Michal Vasko60ba9a62015-07-03 14:42:31 +0200129 ctx->models.search_path = get_current_dir_name();
Michal Vasko3eff9322015-11-10 11:02:30 +0100130
Radek Krejci15412ca2016-03-03 11:16:52 +0100131 if (chdir(cwd)) {
132 LOGWRN("Unable to return back to working directory \"%s\" (%s)",
133 cwd, strerror(errno));
134 }
Michal Vasko60ba9a62015-07-03 14:42:31 +0200135 free(cwd);
136 } else {
137 free(ctx->models.search_path);
138 ctx->models.search_path = NULL;
139 }
140}
141
Radek Krejcib081d8d2015-10-21 16:29:07 +0200142API const char *
Michal Vasko1e62a092015-12-01 12:27:20 +0100143ly_ctx_get_searchdir(const struct ly_ctx *ctx)
Radek Krejci5a797572015-10-21 15:45:45 +0200144{
145 return ctx->models.search_path;
146}
147
Michal Vasko60ba9a62015-07-03 14:42:31 +0200148API void
Radek Krejcifa0b5e02016-02-04 13:57:03 +0100149ly_ctx_destroy(struct ly_ctx *ctx, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +0200150{
Michal Vasko627975a2016-02-11 11:39:03 +0100151 int i;
152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200153 if (!ctx) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200154 return;
155 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200156
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200157 /* models list */
Michal Vasko627975a2016-02-11 11:39:03 +0100158 for (i = 0; i < ctx->models.used; ++i) {
159 lys_free(ctx->models.list[i], private_destructor, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200160 }
161 free(ctx->models.search_path);
162 free(ctx->models.list);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200164 /* dictionary */
165 lydict_clean(&ctx->dict);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200167 free(ctx);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200168}
169
Michal Vasko1e62a092015-12-01 12:27:20 +0100170API const struct lys_submodule *
Radek Krejci62f0da72016-03-07 11:35:43 +0100171ly_ctx_get_submodule2(const struct lys_module *main_module, const char *submodule)
172{
173 struct lys_submodule *result;
174 int i;
175
176 if (!main_module || !submodule) {
177 ly_errno = LY_EINVAL;
178 return NULL;
179 }
180
181 /* search in submodules list */
182 for (i = 0; i < main_module->inc_size; i++) {
183 result = main_module->inc[i].submodule;
184 if (result && ly_strequal(submodule, result->name, 0)) {
185 return result;
186 }
187 }
188
189 return NULL;
190}
191
192API const struct lys_submodule *
Radek Krejcia7533f22016-03-07 07:37:45 +0100193ly_ctx_get_submodule(const struct ly_ctx *ctx, const char *module, const char *revision, const char *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +0200194{
Radek Krejcie7973552016-03-07 08:12:01 +0100195 const struct lys_module *mainmod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200196
Radek Krejcia7533f22016-03-07 07:37:45 +0100197 if (!module || !submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200198 ly_errno = LY_EINVAL;
199 return NULL;
200 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200201
Radek Krejcie7973552016-03-07 08:12:01 +0100202 mainmod = ly_ctx_get_module(ctx, module, revision);
203 if (!mainmod) {
Radek Krejcia7533f22016-03-07 07:37:45 +0100204 ly_errno = LY_EINVAL;
205 return NULL;
206 }
Radek Krejcic071c542016-01-27 14:57:51 +0100207
Radek Krejci62f0da72016-03-07 11:35:43 +0100208 return ly_ctx_get_submodule2(mainmod, submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +0200209}
210
Michal Vasko1e62a092015-12-01 12:27:20 +0100211static const struct lys_module *
212ly_ctx_get_module_by(const struct ly_ctx *ctx, const char *key, int offset, const char *revision)
Radek Krejciefaeba32015-05-27 14:30:57 +0200213{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200214 int i;
Radek Krejcib8048692015-08-05 13:36:34 +0200215 struct lys_module *result = NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +0200216
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200217 if (!ctx || !key) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200218 ly_errno = LY_EINVAL;
219 return NULL;
220 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200221
Radek Krejcidce51452015-06-16 15:20:08 +0200222 for (i = 0; i < ctx->models.used; i++) {
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200223 /* use offset to get address of the pointer to string (char**), remember that offset is in
224 * bytes, so we have to cast the pointer to the module to (char*), finally, we want to have
225 * string not the pointer to string
226 */
227 if (!ctx->models.list[i] || strcmp(key, *(char**)(((char*)ctx->models.list[i]) + offset))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200228 continue;
229 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200230
Radek Krejcif647e612015-07-30 11:36:07 +0200231 if (!revision) {
232 /* compare revisons and remember the newest one */
233 if (result) {
234 if (!ctx->models.list[i]->rev_size) {
235 /* the current have no revision, keep the previous with some revision */
236 continue;
237 }
238 if (result->rev_size && strcmp(ctx->models.list[i]->rev[0].date, result->rev[0].date) < 0) {
239 /* the previous found matching module has a newer revision */
240 continue;
241 }
242 }
243
244 /* remember the current match and search for newer version */
245 result = ctx->models.list[i];
246 } else {
247 if (ctx->models.list[i]->rev_size && !strcmp(revision, ctx->models.list[i]->rev[0].date)) {
248 /* matching revision */
Michal Vasko97586502015-08-12 14:32:18 +0200249 result = ctx->models.list[i];
250 break;
Radek Krejcif647e612015-07-30 11:36:07 +0200251 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200252 }
253 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200254
Radek Krejcif647e612015-07-30 11:36:07 +0200255 return result;
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200256
257}
258
Michal Vasko1e62a092015-12-01 12:27:20 +0100259API const struct lys_module *
260ly_ctx_get_module_by_ns(const struct ly_ctx *ctx, const char *ns, const char *revision)
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200261{
262 return ly_ctx_get_module_by(ctx, ns, offsetof(struct lys_module, ns), revision);
263}
264
Michal Vasko1e62a092015-12-01 12:27:20 +0100265API const struct lys_module *
266ly_ctx_get_module(const struct ly_ctx *ctx, const char *name, const char *revision)
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200267{
268 return ly_ctx_get_module_by(ctx, name, offsetof(struct lys_module, name), revision);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200269}
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200270
Radek Krejci21601a32016-03-07 11:39:27 +0100271API const struct lys_module *
272ly_ctx_get_module_older(const struct ly_ctx *ctx, const struct lys_module *module)
273{
274 int i;
275 const struct lys_module *result = NULL, *iter;
276
277 if (!ctx || !module || !module->rev_size) {
278 ly_errno = LY_EINVAL;
279 return NULL;
280 }
281
282
283 for (i = 0; i < ctx->models.used; i++) {
284 iter = ctx->models.list[i];
285 if (iter == module || !iter->rev_size) {
286 /* iter is the module itself or iter has no revision */
287 continue;
288 }
289 if (!ly_strequal(module->name, iter->name, 0)) {
290 /* different module */
291 continue;
292 }
293 if (strcmp(iter->rev[0].date, module->rev[0].date) < 0) {
294 /* iter is older than module */
295 if (result) {
296 if (strcmp(iter->rev[0].date, result->rev[0].date) > 0) {
297 /* iter is newer than current result */
298 result = iter;
299 }
300 } else {
301 result = iter;
302 }
303 }
304 }
305
306 return result;
307}
308
Michal Vasko99b0aad2015-12-01 12:28:51 +0100309API void
310ly_ctx_set_module_clb(struct ly_ctx *ctx, ly_module_clb clb, void *user_data)
Michal Vasko82465962015-11-10 11:03:11 +0100311{
Michal Vasko99b0aad2015-12-01 12:28:51 +0100312 ctx->module_clb = clb;
313 ctx->module_clb_data = user_data;
314}
315
316API ly_module_clb
317ly_ctx_get_module_clb(const struct ly_ctx *ctx, void **user_data)
318{
319 if (user_data) {
320 *user_data = ctx->module_clb_data;
321 }
322 return ctx->module_clb;
323}
324
325API const struct lys_module *
326ly_ctx_load_module(struct ly_ctx *ctx, const char *name, const char *revision)
327{
Michal Vasko5a721fd2016-02-16 12:16:48 +0100328 const struct lys_module *module;
Michal Vasko99b0aad2015-12-01 12:28:51 +0100329 char *module_data;
Michal Vaskod3e975b2016-03-03 15:40:21 +0100330 void (*module_data_free)(void *module_data) = NULL;
Michal Vasko99b0aad2015-12-01 12:28:51 +0100331 LYS_INFORMAT format = LYS_IN_UNKNOWN;
Michal Vasko82465962015-11-10 11:03:11 +0100332
333 if (!ctx || !name) {
334 ly_errno = LY_EINVAL;
335 return NULL;
336 }
337
Michal Vasko99b0aad2015-12-01 12:28:51 +0100338 if (ctx->module_clb) {
339 module_data = ctx->module_clb(name, revision, ctx->module_clb_data, &format, &module_data_free);
340 if (!module_data) {
341 LOGERR(LY_EVALID, "User module retrieval callback failed!");
342 return NULL;
Michal Vasko82465962015-11-10 11:03:11 +0100343 }
Michal Vasko5a721fd2016-02-16 12:16:48 +0100344 module = lys_parse_mem(ctx, module_data, format);
Michal Vasko99b0aad2015-12-01 12:28:51 +0100345 if (module_data_free) {
346 module_data_free(module_data);
Michal Vasko82465962015-11-10 11:03:11 +0100347 }
Michal Vasko99b0aad2015-12-01 12:28:51 +0100348 } else {
Michal Vasko5a721fd2016-02-16 12:16:48 +0100349 module = lyp_search_file(ctx, NULL, name, revision, NULL);
Michal Vasko82465962015-11-10 11:03:11 +0100350 }
351
Michal Vasko5a721fd2016-02-16 12:16:48 +0100352 return module;
Michal Vasko82465962015-11-10 11:03:11 +0100353}
354
Radek Krejci96a10da2015-07-30 11:00:14 +0200355API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +0100356ly_ctx_get_module_names(const struct ly_ctx *ctx)
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200357{
Radek Krejcic215afb2016-03-07 11:32:55 +0100358 int i, j, k;
Radek Krejci96a10da2015-07-30 11:00:14 +0200359 const char **result = NULL;
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200360
361 if (!ctx) {
362 ly_errno = LY_EINVAL;
363 return NULL;
364 }
365
Michal Vaskoe2ea44b2015-07-07 11:31:48 +0200366 result = malloc((ctx->models.used+1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +0100367 if (!result) {
368 LOGMEM;
369 return NULL;
370 }
Michal Vaskoe2ea44b2015-07-07 11:31:48 +0200371
Radek Krejcic215afb2016-03-07 11:32:55 +0100372 for (i = j = 0; i < ctx->models.used; i++) {
373 /* avoid duplicities when multiple revisions of the same module are present */
374 for (k = j - 1; k >= 0; k--) {
375 if (ly_strequal(result[k], ctx->models.list[i]->name, 1)) {
376 break;
377 }
378 }
379 if (k < 0) {
380 /* no duplication found */
381 result[j] = ctx->models.list[i]->name;
382 j++;
383 }
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200384 }
Radek Krejcic215afb2016-03-07 11:32:55 +0100385 result[j] = NULL;
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200386
387 return result;
Michal Vaskofa8c8282015-07-03 15:14:59 +0200388}
389
Michal Vaskod7957c02016-04-01 10:27:26 +0200390API const struct lys_module *
391ly_ctx_get_module_iter(const struct ly_ctx *ctx, uint32_t *idx)
392{
393 if (!ctx || !idx) {
394 ly_errno = LY_EINVAL;
395 return NULL;
396 }
397
398 if (*idx >= (unsigned)ctx->models.used) {
399 return NULL;
400 }
401
402 return ctx->models.list[(*idx)++];
403}
404
Radek Krejci96a10da2015-07-30 11:00:14 +0200405API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +0100406ly_ctx_get_submodule_names(const struct ly_ctx *ctx, const char *module_name)
Michal Vaskofa8c8282015-07-03 15:14:59 +0200407{
408 int i;
Radek Krejci96a10da2015-07-30 11:00:14 +0200409 const char **result = NULL;
Michal Vasko1e62a092015-12-01 12:27:20 +0100410 const struct lys_module *mod;
Michal Vaskofa8c8282015-07-03 15:14:59 +0200411
412 if (!ctx) {
413 ly_errno = LY_EINVAL;
414 return NULL;
415 }
416
Radek Krejci96a10da2015-07-30 11:00:14 +0200417 mod = ly_ctx_get_module(ctx, module_name, NULL);
Michal Vaskofa8c8282015-07-03 15:14:59 +0200418 if (!mod) {
Radek Krejci96a10da2015-07-30 11:00:14 +0200419 LOGERR(LY_EVALID, "Data model \"%s\" not loaded", module_name);
Michal Vaskofa8c8282015-07-03 15:14:59 +0200420 return NULL;
421 }
422
423 result = malloc((mod->inc_size+1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +0100424 if (!result) {
425 LOGMEM;
426 return NULL;
427 }
Michal Vaskofa8c8282015-07-03 15:14:59 +0200428
Radek Krejcic071c542016-01-27 14:57:51 +0100429 for (i = 0; i < mod->inc_size && mod->inc[i].submodule; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +0200430 result[i] = mod->inc[i].submodule->name;
Michal Vaskofa8c8282015-07-03 15:14:59 +0200431 }
432 result[i] = NULL;
433
434 return result;
435}
Michal Vasko209a6222015-10-16 09:51:07 +0200436
437static int
438ylib_feature(struct lyd_node *parent, struct lys_module *cur_mod)
439{
440 int i, j;
441
442 /* module features */
443 for (i = 0; i < cur_mod->features_size; ++i) {
444 if (!(cur_mod->features[i].flags & LYS_FENABLED)) {
445 continue;
446 }
447
Michal Vasko3e671b52015-10-23 16:23:15 +0200448 if (!lyd_new_leaf(parent, NULL, "feature", cur_mod->features[i].name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200449 return EXIT_FAILURE;
450 }
451 }
452
453 /* submodule features */
Radek Krejcic071c542016-01-27 14:57:51 +0100454 for (i = 0; i < cur_mod->inc_size && cur_mod->inc[i].submodule; ++i) {
Michal Vasko209a6222015-10-16 09:51:07 +0200455 for (j = 0; j < cur_mod->inc[i].submodule->features_size; ++j) {
456 if (!(cur_mod->inc[i].submodule->features[j].flags & LYS_FENABLED)) {
457 continue;
458 }
459
Michal Vasko3e671b52015-10-23 16:23:15 +0200460 if (!lyd_new_leaf(parent, NULL, "feature", cur_mod->inc[i].submodule->features[j].name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200461 return EXIT_FAILURE;
462 }
463 }
464 }
465
466 return EXIT_SUCCESS;
467}
468
469static int
Michal Vaskoff006c12016-02-17 11:15:19 +0100470ylib_deviation(struct lyd_node *parent, struct lys_module *cur_mod)
Michal Vasko97d8c6d2016-02-12 11:05:48 +0100471{
Michal Vaskoff006c12016-02-17 11:15:19 +0100472 int i;
Michal Vasko97d8c6d2016-02-12 11:05:48 +0100473 const char *revision;
Michal Vasko209a6222015-10-16 09:51:07 +0200474 struct lyd_node *cont;
475
Michal Vaskoff006c12016-02-17 11:15:19 +0100476 for (i = 0; i < cur_mod->imp_size; ++i) {
477 /* marks a deviating module */
478 if (cur_mod->imp[i].external == 2) {
479 revision = (cur_mod->imp[i].module->rev_size ? cur_mod->imp[i].module->rev[0].date : "");
Michal Vasko209a6222015-10-16 09:51:07 +0200480
Michal Vaskoff006c12016-02-17 11:15:19 +0100481 cont = lyd_new(parent, NULL, "deviation");
482 if (!cont) {
483 return EXIT_FAILURE;
Michal Vasko209a6222015-10-16 09:51:07 +0200484 }
Michal Vasko209a6222015-10-16 09:51:07 +0200485
Michal Vaskoff006c12016-02-17 11:15:19 +0100486 if (!lyd_new_leaf(cont, NULL, "name", cur_mod->imp[i].module->name)) {
487 return EXIT_FAILURE;
488 }
489 if (!lyd_new_leaf(cont, NULL, "revision", revision)) {
490 return EXIT_FAILURE;
Michal Vasko209a6222015-10-16 09:51:07 +0200491 }
492 }
493 }
494
495 return EXIT_SUCCESS;
496}
497
498static int
499ylib_submodules(struct lyd_node *parent, struct lys_module *cur_mod)
500{
501 int i;
Radek Krejcia77904e2016-02-25 16:23:45 +0100502 char *str;
Radek Krejci6e05cea2015-12-10 16:34:37 +0100503 struct lyd_node *cont, *item;
504
505 if (cur_mod->inc_size) {
506 cont = lyd_new(parent, NULL, "submodules");
507 }
Michal Vasko209a6222015-10-16 09:51:07 +0200508
Radek Krejcic071c542016-01-27 14:57:51 +0100509 for (i = 0; i < cur_mod->inc_size && cur_mod->inc[i].submodule; ++i) {
Radek Krejci6e05cea2015-12-10 16:34:37 +0100510 item = lyd_new(cont, NULL, "submodule");
511 if (!item) {
Michal Vasko209a6222015-10-16 09:51:07 +0200512 return EXIT_FAILURE;
513 }
514
Radek Krejci6e05cea2015-12-10 16:34:37 +0100515 if (!lyd_new_leaf(item, NULL, "name", cur_mod->inc[i].submodule->name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200516 return EXIT_FAILURE;
517 }
Radek Krejci6e05cea2015-12-10 16:34:37 +0100518 if (!lyd_new_leaf(item, NULL, "revision", (cur_mod->inc[i].submodule->rev_size ?
Michal Vasko3e671b52015-10-23 16:23:15 +0200519 cur_mod->inc[i].submodule->rev[0].date : ""))) {
Michal Vasko209a6222015-10-16 09:51:07 +0200520 return EXIT_FAILURE;
521 }
Radek Krejcia77904e2016-02-25 16:23:45 +0100522 if (cur_mod->inc[i].submodule->filepath) {
Radek Krejci95aa2012016-03-03 11:21:09 +0100523 if (asprintf(&str, "file://%s", cur_mod->inc[i].submodule->filepath) == -1) {
Radek Krejcia77904e2016-02-25 16:23:45 +0100524 LOGMEM;
525 return EXIT_FAILURE;
Radek Krejci6e65af92016-03-07 12:48:19 +0100526 } else if (!lyd_new_leaf(item, NULL, "schema", str)) {
Radek Krejci19f9ede2016-02-25 16:29:21 +0100527 free(str);
Radek Krejcia77904e2016-02-25 16:23:45 +0100528 return EXIT_FAILURE;
529 }
Radek Krejci19f9ede2016-02-25 16:29:21 +0100530 free(str);
Michal Vasko209a6222015-10-16 09:51:07 +0200531 }
532 }
533
534 return EXIT_SUCCESS;
535}
536
537API struct lyd_node *
538ly_ctx_info(struct ly_ctx *ctx)
539{
540 int i;
541 char id[8];
Radek Krejcia77904e2016-02-25 16:23:45 +0100542 char *str;
Michal Vasko1e62a092015-12-01 12:27:20 +0100543 const struct lys_module *mod;
Michal Vasko209a6222015-10-16 09:51:07 +0200544 struct lyd_node *root, *cont;
545
Michal Vasko7eccc6c2016-03-24 14:56:33 +0100546 if (!ctx) {
547 ly_errno = LY_EINVAL;
548 return NULL;
549 }
550
Radek Krejcibd9e8d22016-02-03 14:11:48 +0100551 mod = ly_ctx_get_module(ctx, "ietf-yang-library", IETF_YANG_LIB_REV);
552 if (!mod || !mod->data) {
553 LOGINT;
Michal Vasko209a6222015-10-16 09:51:07 +0200554 return NULL;
555 }
556
Radek Krejcibd9e8d22016-02-03 14:11:48 +0100557 root = lyd_new(NULL, mod, "modules-state");
Michal Vasko209a6222015-10-16 09:51:07 +0200558 if (!root) {
559 return NULL;
560 }
561
562 for (i = 0; i < ctx->models.used; ++i) {
563 cont = lyd_new(root, NULL, "module");
564 if (!cont) {
565 lyd_free(root);
566 return NULL;
567 }
568
Michal Vasko3e671b52015-10-23 16:23:15 +0200569 if (!lyd_new_leaf(cont, NULL, "name", ctx->models.list[i]->name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200570 lyd_free(root);
571 return NULL;
572 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200573 if (!lyd_new_leaf(cont, NULL, "revision", (ctx->models.list[i]->rev_size ?
Michal Vasko209a6222015-10-16 09:51:07 +0200574 ctx->models.list[i]->rev[0].date : ""))) {
575 lyd_free(root);
576 return NULL;
577 }
Radek Krejcia77904e2016-02-25 16:23:45 +0100578 if (ctx->models.list[i]->filepath) {
Radek Krejci15412ca2016-03-03 11:16:52 +0100579 if (asprintf(&str, "file://%s", ctx->models.list[i]->filepath) == -1) {
Radek Krejcia77904e2016-02-25 16:23:45 +0100580 LOGMEM;
581 lyd_free(root);
582 return NULL;
583 } else if (!lyd_new_leaf(cont, NULL, "schema", str)) {
Radek Krejci19f9ede2016-02-25 16:29:21 +0100584 free(str);
Radek Krejcia77904e2016-02-25 16:23:45 +0100585 lyd_free(root);
586 return NULL;
587 }
Radek Krejci19f9ede2016-02-25 16:29:21 +0100588 free(str);
Michal Vasko209a6222015-10-16 09:51:07 +0200589 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200590 if (!lyd_new_leaf(cont, NULL, "namespace", ctx->models.list[i]->ns)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200591 lyd_free(root);
592 return NULL;
593 }
594 if (ylib_feature(cont, ctx->models.list[i])) {
595 lyd_free(root);
596 return NULL;
597 }
Michal Vaskoff006c12016-02-17 11:15:19 +0100598 if (ylib_deviation(cont, ctx->models.list[i])) {
Michal Vasko209a6222015-10-16 09:51:07 +0200599 lyd_free(root);
600 return NULL;
601 }
602 if (ctx->models.list[i]->implemented
Radek Krejcibd9e8d22016-02-03 14:11:48 +0100603 && !lyd_new_leaf(cont, NULL, "conformance-type", "implement")) {
Michal Vasko209a6222015-10-16 09:51:07 +0200604 lyd_free(root);
605 return NULL;
606 }
607 if (!ctx->models.list[i]->implemented
Radek Krejcibd9e8d22016-02-03 14:11:48 +0100608 && !lyd_new_leaf(cont, NULL, "conformance-type", "import")) {
Michal Vasko209a6222015-10-16 09:51:07 +0200609 lyd_free(root);
610 return NULL;
611 }
612 if (ylib_submodules(cont, ctx->models.list[i])) {
613 lyd_free(root);
614 return NULL;
615 }
616 }
617
618 sprintf(id, "%u", ctx->models.module_set_id);
Michal Vasko3e671b52015-10-23 16:23:15 +0200619 if (!lyd_new_leaf(root, mod, "module-set-id", id)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200620 lyd_free(root);
621 return NULL;
622 }
623
Radek Krejci03b71f72016-03-16 11:10:09 +0100624 if (lyd_validate(&root, 0)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200625 lyd_free(root);
626 return NULL;
627 }
628
629 return root;
630}
Michal Vasko3edeaf72016-02-11 13:17:43 +0100631
632API const struct lys_node *
Michal Vasko3547c532016-03-14 09:40:50 +0100633ly_ctx_get_node(struct ly_ctx *ctx, const struct lys_node *start, const char *nodeid)
Michal Vasko3edeaf72016-02-11 13:17:43 +0100634{
Michal Vaskoe733d682016-03-14 09:08:27 +0100635 const struct lys_node *node;
Michal Vasko3edeaf72016-02-11 13:17:43 +0100636
Michal Vasko3547c532016-03-14 09:40:50 +0100637 if (!ctx || !nodeid || ((nodeid[0] != '/') && !start)) {
Michal Vasko3edeaf72016-02-11 13:17:43 +0100638 ly_errno = LY_EINVAL;
639 return NULL;
640 }
641
Michal Vaskoe733d682016-03-14 09:08:27 +0100642 /* sets error and everything */
Michal Vasko3547c532016-03-14 09:40:50 +0100643 node = resolve_json_schema_nodeid(nodeid, ctx, start);
Michal Vasko3edeaf72016-02-11 13:17:43 +0100644
Michal Vaskoe733d682016-03-14 09:08:27 +0100645 return node;
Michal Vasko3edeaf72016-02-11 13:17:43 +0100646}