blob: f11f8684fc69a8ad50e7e1bcb1349e3151b6936f [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 *
171ly_ctx_get_submodule(const struct lys_module *module, const char *name, const char *revision)
Radek Krejciefaeba32015-05-27 14:30:57 +0200172{
Radek Krejcib8048692015-08-05 13:36:34 +0200173 struct lys_submodule *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200174 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +0200175
Radek Krejci63a91a92015-07-29 13:31:04 +0200176 if (!module || !name) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200177 ly_errno = LY_EINVAL;
178 return NULL;
179 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200180
Radek Krejcic071c542016-01-27 14:57:51 +0100181 /* make sure that the provided module is not submodule */
Michal Vasko6c629ac2016-02-15 14:08:23 +0100182 module = lys_module(module);
Radek Krejcic071c542016-01-27 14:57:51 +0100183
184 /* search in submodules list */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200185 for (i = 0; i < module->inc_size; i++) {
186 result = module->inc[i].submodule;
Radek Krejcic071c542016-01-27 14:57:51 +0100187 if (!result || strcmp(name, result->name)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200188 continue;
189 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200191 if (!revision || (result->rev_size && !strcmp(revision, result->rev[0].date))) {
192 return result;
193 }
194 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200195
Radek Krejci63a91a92015-07-29 13:31:04 +0200196 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +0200197}
198
Michal Vasko1e62a092015-12-01 12:27:20 +0100199static const struct lys_module *
200ly_ctx_get_module_by(const struct ly_ctx *ctx, const char *key, int offset, const char *revision)
Radek Krejciefaeba32015-05-27 14:30:57 +0200201{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200202 int i;
Radek Krejcib8048692015-08-05 13:36:34 +0200203 struct lys_module *result = NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +0200204
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200205 if (!ctx || !key) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200206 ly_errno = LY_EINVAL;
207 return NULL;
208 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200209
Radek Krejcidce51452015-06-16 15:20:08 +0200210 for (i = 0; i < ctx->models.used; i++) {
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200211 /* use offset to get address of the pointer to string (char**), remember that offset is in
212 * bytes, so we have to cast the pointer to the module to (char*), finally, we want to have
213 * string not the pointer to string
214 */
215 if (!ctx->models.list[i] || strcmp(key, *(char**)(((char*)ctx->models.list[i]) + offset))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200216 continue;
217 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200218
Radek Krejcif647e612015-07-30 11:36:07 +0200219 if (!revision) {
220 /* compare revisons and remember the newest one */
221 if (result) {
222 if (!ctx->models.list[i]->rev_size) {
223 /* the current have no revision, keep the previous with some revision */
224 continue;
225 }
226 if (result->rev_size && strcmp(ctx->models.list[i]->rev[0].date, result->rev[0].date) < 0) {
227 /* the previous found matching module has a newer revision */
228 continue;
229 }
230 }
231
232 /* remember the current match and search for newer version */
233 result = ctx->models.list[i];
234 } else {
235 if (ctx->models.list[i]->rev_size && !strcmp(revision, ctx->models.list[i]->rev[0].date)) {
236 /* matching revision */
Michal Vasko97586502015-08-12 14:32:18 +0200237 result = ctx->models.list[i];
238 break;
Radek Krejcif647e612015-07-30 11:36:07 +0200239 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200240 }
241 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200242
Radek Krejcif647e612015-07-30 11:36:07 +0200243 return result;
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200244
245}
246
Michal Vasko1e62a092015-12-01 12:27:20 +0100247API const struct lys_module *
248ly_ctx_get_module_by_ns(const struct ly_ctx *ctx, const char *ns, const char *revision)
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200249{
250 return ly_ctx_get_module_by(ctx, ns, offsetof(struct lys_module, ns), revision);
251}
252
Michal Vasko1e62a092015-12-01 12:27:20 +0100253API const struct lys_module *
254ly_ctx_get_module(const struct ly_ctx *ctx, const char *name, const char *revision)
Radek Krejcifd4e6e32015-08-10 15:00:51 +0200255{
256 return ly_ctx_get_module_by(ctx, name, offsetof(struct lys_module, name), revision);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200257}
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200258
Michal Vasko99b0aad2015-12-01 12:28:51 +0100259API void
260ly_ctx_set_module_clb(struct ly_ctx *ctx, ly_module_clb clb, void *user_data)
Michal Vasko82465962015-11-10 11:03:11 +0100261{
Michal Vasko99b0aad2015-12-01 12:28:51 +0100262 ctx->module_clb = clb;
263 ctx->module_clb_data = user_data;
264}
265
266API ly_module_clb
267ly_ctx_get_module_clb(const struct ly_ctx *ctx, void **user_data)
268{
269 if (user_data) {
270 *user_data = ctx->module_clb_data;
271 }
272 return ctx->module_clb;
273}
274
275API const struct lys_module *
276ly_ctx_load_module(struct ly_ctx *ctx, const char *name, const char *revision)
277{
Michal Vasko5a721fd2016-02-16 12:16:48 +0100278 const struct lys_module *module;
Michal Vasko99b0aad2015-12-01 12:28:51 +0100279 char *module_data;
280 void (*module_data_free)(char *module_data) = NULL;
281 LYS_INFORMAT format = LYS_IN_UNKNOWN;
Michal Vasko82465962015-11-10 11:03:11 +0100282
283 if (!ctx || !name) {
284 ly_errno = LY_EINVAL;
285 return NULL;
286 }
287
Michal Vasko99b0aad2015-12-01 12:28:51 +0100288 if (ctx->module_clb) {
289 module_data = ctx->module_clb(name, revision, ctx->module_clb_data, &format, &module_data_free);
290 if (!module_data) {
291 LOGERR(LY_EVALID, "User module retrieval callback failed!");
292 return NULL;
Michal Vasko82465962015-11-10 11:03:11 +0100293 }
Michal Vasko5a721fd2016-02-16 12:16:48 +0100294 module = lys_parse_mem(ctx, module_data, format);
Michal Vasko99b0aad2015-12-01 12:28:51 +0100295 if (module_data_free) {
296 module_data_free(module_data);
297 } else {
298 free(module_data);
Michal Vasko82465962015-11-10 11:03:11 +0100299 }
Michal Vasko99b0aad2015-12-01 12:28:51 +0100300 } else {
Michal Vasko5a721fd2016-02-16 12:16:48 +0100301 module = lyp_search_file(ctx, NULL, name, revision, NULL);
Michal Vasko82465962015-11-10 11:03:11 +0100302 }
303
Michal Vasko5a721fd2016-02-16 12:16:48 +0100304 return module;
Michal Vasko82465962015-11-10 11:03:11 +0100305}
306
Radek Krejci96a10da2015-07-30 11:00:14 +0200307API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +0100308ly_ctx_get_module_names(const struct ly_ctx *ctx)
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200309{
310 int i;
Radek Krejci96a10da2015-07-30 11:00:14 +0200311 const char **result = NULL;
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200312
313 if (!ctx) {
314 ly_errno = LY_EINVAL;
315 return NULL;
316 }
317
Michal Vaskoe2ea44b2015-07-07 11:31:48 +0200318 result = malloc((ctx->models.used+1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +0100319 if (!result) {
320 LOGMEM;
321 return NULL;
322 }
Michal Vaskoe2ea44b2015-07-07 11:31:48 +0200323
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200324 for (i = 0; i < ctx->models.used; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +0200325 result[i] = ctx->models.list[i]->name;
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200326 }
Michal Vaskoe2ea44b2015-07-07 11:31:48 +0200327 result[i] = NULL;
Michal Vasko3ec07dc2015-06-30 15:51:30 +0200328
329 return result;
Michal Vaskofa8c8282015-07-03 15:14:59 +0200330}
331
Radek Krejci96a10da2015-07-30 11:00:14 +0200332API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +0100333ly_ctx_get_submodule_names(const struct ly_ctx *ctx, const char *module_name)
Michal Vaskofa8c8282015-07-03 15:14:59 +0200334{
335 int i;
Radek Krejci96a10da2015-07-30 11:00:14 +0200336 const char **result = NULL;
Michal Vasko1e62a092015-12-01 12:27:20 +0100337 const struct lys_module *mod;
Michal Vaskofa8c8282015-07-03 15:14:59 +0200338
339 if (!ctx) {
340 ly_errno = LY_EINVAL;
341 return NULL;
342 }
343
Radek Krejci96a10da2015-07-30 11:00:14 +0200344 mod = ly_ctx_get_module(ctx, module_name, NULL);
Michal Vaskofa8c8282015-07-03 15:14:59 +0200345 if (!mod) {
Radek Krejci96a10da2015-07-30 11:00:14 +0200346 LOGERR(LY_EVALID, "Data model \"%s\" not loaded", module_name);
Michal Vaskofa8c8282015-07-03 15:14:59 +0200347 return NULL;
348 }
349
350 result = malloc((mod->inc_size+1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +0100351 if (!result) {
352 LOGMEM;
353 return NULL;
354 }
Michal Vaskofa8c8282015-07-03 15:14:59 +0200355
Radek Krejcic071c542016-01-27 14:57:51 +0100356 for (i = 0; i < mod->inc_size && mod->inc[i].submodule; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +0200357 result[i] = mod->inc[i].submodule->name;
Michal Vaskofa8c8282015-07-03 15:14:59 +0200358 }
359 result[i] = NULL;
360
361 return result;
362}
Michal Vasko209a6222015-10-16 09:51:07 +0200363
364static int
365ylib_feature(struct lyd_node *parent, struct lys_module *cur_mod)
366{
367 int i, j;
368
369 /* module features */
370 for (i = 0; i < cur_mod->features_size; ++i) {
371 if (!(cur_mod->features[i].flags & LYS_FENABLED)) {
372 continue;
373 }
374
Michal Vasko3e671b52015-10-23 16:23:15 +0200375 if (!lyd_new_leaf(parent, NULL, "feature", cur_mod->features[i].name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200376 return EXIT_FAILURE;
377 }
378 }
379
380 /* submodule features */
Radek Krejcic071c542016-01-27 14:57:51 +0100381 for (i = 0; i < cur_mod->inc_size && cur_mod->inc[i].submodule; ++i) {
Michal Vasko209a6222015-10-16 09:51:07 +0200382 for (j = 0; j < cur_mod->inc[i].submodule->features_size; ++j) {
383 if (!(cur_mod->inc[i].submodule->features[j].flags & LYS_FENABLED)) {
384 continue;
385 }
386
Michal Vasko3e671b52015-10-23 16:23:15 +0200387 if (!lyd_new_leaf(parent, NULL, "feature", cur_mod->inc[i].submodule->features[j].name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200388 return EXIT_FAILURE;
389 }
390 }
391 }
392
393 return EXIT_SUCCESS;
394}
395
396static int
Michal Vaskoff006c12016-02-17 11:15:19 +0100397ylib_deviation(struct lyd_node *parent, struct lys_module *cur_mod)
Michal Vasko97d8c6d2016-02-12 11:05:48 +0100398{
Michal Vaskoff006c12016-02-17 11:15:19 +0100399 int i;
Michal Vasko97d8c6d2016-02-12 11:05:48 +0100400 const char *revision;
Michal Vasko209a6222015-10-16 09:51:07 +0200401 struct lyd_node *cont;
402
Michal Vaskoff006c12016-02-17 11:15:19 +0100403 for (i = 0; i < cur_mod->imp_size; ++i) {
404 /* marks a deviating module */
405 if (cur_mod->imp[i].external == 2) {
406 revision = (cur_mod->imp[i].module->rev_size ? cur_mod->imp[i].module->rev[0].date : "");
Michal Vasko209a6222015-10-16 09:51:07 +0200407
Michal Vaskoff006c12016-02-17 11:15:19 +0100408 cont = lyd_new(parent, NULL, "deviation");
409 if (!cont) {
410 return EXIT_FAILURE;
Michal Vasko209a6222015-10-16 09:51:07 +0200411 }
Michal Vasko209a6222015-10-16 09:51:07 +0200412
Michal Vaskoff006c12016-02-17 11:15:19 +0100413 if (!lyd_new_leaf(cont, NULL, "name", cur_mod->imp[i].module->name)) {
414 return EXIT_FAILURE;
415 }
416 if (!lyd_new_leaf(cont, NULL, "revision", revision)) {
417 return EXIT_FAILURE;
Michal Vasko209a6222015-10-16 09:51:07 +0200418 }
419 }
420 }
421
422 return EXIT_SUCCESS;
423}
424
425static int
426ylib_submodules(struct lyd_node *parent, struct lys_module *cur_mod)
427{
428 int i;
Radek Krejcia77904e2016-02-25 16:23:45 +0100429 char *str;
Radek Krejci6e05cea2015-12-10 16:34:37 +0100430 struct lyd_node *cont, *item;
431
432 if (cur_mod->inc_size) {
433 cont = lyd_new(parent, NULL, "submodules");
434 }
Michal Vasko209a6222015-10-16 09:51:07 +0200435
Radek Krejcic071c542016-01-27 14:57:51 +0100436 for (i = 0; i < cur_mod->inc_size && cur_mod->inc[i].submodule; ++i) {
Radek Krejci6e05cea2015-12-10 16:34:37 +0100437 item = lyd_new(cont, NULL, "submodule");
438 if (!item) {
Michal Vasko209a6222015-10-16 09:51:07 +0200439 return EXIT_FAILURE;
440 }
441
Radek Krejci6e05cea2015-12-10 16:34:37 +0100442 if (!lyd_new_leaf(item, NULL, "name", cur_mod->inc[i].submodule->name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200443 return EXIT_FAILURE;
444 }
Radek Krejci6e05cea2015-12-10 16:34:37 +0100445 if (!lyd_new_leaf(item, NULL, "revision", (cur_mod->inc[i].submodule->rev_size ?
Michal Vasko3e671b52015-10-23 16:23:15 +0200446 cur_mod->inc[i].submodule->rev[0].date : ""))) {
Michal Vasko209a6222015-10-16 09:51:07 +0200447 return EXIT_FAILURE;
448 }
Radek Krejcia77904e2016-02-25 16:23:45 +0100449 if (cur_mod->inc[i].submodule->filepath) {
Radek Krejci95aa2012016-03-03 11:21:09 +0100450 if (asprintf(&str, "file://%s", cur_mod->inc[i].submodule->filepath) == -1) {
Radek Krejcia77904e2016-02-25 16:23:45 +0100451 LOGMEM;
452 return EXIT_FAILURE;
453 } else if (!lyd_new_leaf(cont, NULL, "schema", str)) {
Radek Krejci19f9ede2016-02-25 16:29:21 +0100454 free(str);
Radek Krejcia77904e2016-02-25 16:23:45 +0100455 return EXIT_FAILURE;
456 }
Radek Krejci19f9ede2016-02-25 16:29:21 +0100457 free(str);
Michal Vasko209a6222015-10-16 09:51:07 +0200458 }
459 }
460
461 return EXIT_SUCCESS;
462}
463
464API struct lyd_node *
465ly_ctx_info(struct ly_ctx *ctx)
466{
467 int i;
468 char id[8];
Radek Krejcia77904e2016-02-25 16:23:45 +0100469 char *str;
Michal Vasko1e62a092015-12-01 12:27:20 +0100470 const struct lys_module *mod;
Michal Vasko209a6222015-10-16 09:51:07 +0200471 struct lyd_node *root, *cont;
472
Radek Krejcibd9e8d22016-02-03 14:11:48 +0100473 mod = ly_ctx_get_module(ctx, "ietf-yang-library", IETF_YANG_LIB_REV);
474 if (!mod || !mod->data) {
475 LOGINT;
Michal Vasko209a6222015-10-16 09:51:07 +0200476 return NULL;
477 }
478
Radek Krejcibd9e8d22016-02-03 14:11:48 +0100479 root = lyd_new(NULL, mod, "modules-state");
Michal Vasko209a6222015-10-16 09:51:07 +0200480 if (!root) {
481 return NULL;
482 }
483
484 for (i = 0; i < ctx->models.used; ++i) {
485 cont = lyd_new(root, NULL, "module");
486 if (!cont) {
487 lyd_free(root);
488 return NULL;
489 }
490
Michal Vasko3e671b52015-10-23 16:23:15 +0200491 if (!lyd_new_leaf(cont, NULL, "name", ctx->models.list[i]->name)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200492 lyd_free(root);
493 return NULL;
494 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200495 if (!lyd_new_leaf(cont, NULL, "revision", (ctx->models.list[i]->rev_size ?
Michal Vasko209a6222015-10-16 09:51:07 +0200496 ctx->models.list[i]->rev[0].date : ""))) {
497 lyd_free(root);
498 return NULL;
499 }
Radek Krejcia77904e2016-02-25 16:23:45 +0100500 if (ctx->models.list[i]->filepath) {
Radek Krejci15412ca2016-03-03 11:16:52 +0100501 if (asprintf(&str, "file://%s", ctx->models.list[i]->filepath) == -1) {
Radek Krejcia77904e2016-02-25 16:23:45 +0100502 LOGMEM;
503 lyd_free(root);
504 return NULL;
505 } else if (!lyd_new_leaf(cont, NULL, "schema", str)) {
Radek Krejci19f9ede2016-02-25 16:29:21 +0100506 free(str);
Radek Krejcia77904e2016-02-25 16:23:45 +0100507 lyd_free(root);
508 return NULL;
509 }
Radek Krejci19f9ede2016-02-25 16:29:21 +0100510 free(str);
Michal Vasko209a6222015-10-16 09:51:07 +0200511 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200512 if (!lyd_new_leaf(cont, NULL, "namespace", ctx->models.list[i]->ns)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200513 lyd_free(root);
514 return NULL;
515 }
516 if (ylib_feature(cont, ctx->models.list[i])) {
517 lyd_free(root);
518 return NULL;
519 }
Michal Vaskoff006c12016-02-17 11:15:19 +0100520 if (ylib_deviation(cont, ctx->models.list[i])) {
Michal Vasko209a6222015-10-16 09:51:07 +0200521 lyd_free(root);
522 return NULL;
523 }
524 if (ctx->models.list[i]->implemented
Radek Krejcibd9e8d22016-02-03 14:11:48 +0100525 && !lyd_new_leaf(cont, NULL, "conformance-type", "implement")) {
Michal Vasko209a6222015-10-16 09:51:07 +0200526 lyd_free(root);
527 return NULL;
528 }
529 if (!ctx->models.list[i]->implemented
Radek Krejcibd9e8d22016-02-03 14:11:48 +0100530 && !lyd_new_leaf(cont, NULL, "conformance-type", "import")) {
Michal Vasko209a6222015-10-16 09:51:07 +0200531 lyd_free(root);
532 return NULL;
533 }
534 if (ylib_submodules(cont, ctx->models.list[i])) {
535 lyd_free(root);
536 return NULL;
537 }
538 }
539
540 sprintf(id, "%u", ctx->models.module_set_id);
Michal Vasko3e671b52015-10-23 16:23:15 +0200541 if (!lyd_new_leaf(root, mod, "module-set-id", id)) {
Michal Vasko209a6222015-10-16 09:51:07 +0200542 lyd_free(root);
543 return NULL;
544 }
545
546 if (lyd_validate(root, 0)) {
547 lyd_free(root);
548 return NULL;
549 }
550
551 return root;
552}
Michal Vasko3edeaf72016-02-11 13:17:43 +0100553
554API const struct lys_node *
555ly_ctx_get_node(struct ly_ctx *ctx, const char *nodeid)
556{
557 const struct lys_node *ret;
558
559 if (!ctx || !nodeid) {
560 ly_errno = LY_EINVAL;
561 return NULL;
562 }
563
564 if (resolve_json_absolute_schema_nodeid(nodeid, ctx, &ret)) {
565 ly_errno = LY_EINVAL;
566 return NULL;
567 }
568
569 return ret;
570}