Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 1 | /** |
| 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 Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 23 | #include <stdlib.h> |
| 24 | #include <string.h> |
| 25 | #include <sys/types.h> |
| 26 | #include <sys/stat.h> |
| 27 | #include <unistd.h> |
| 28 | #include <errno.h> |
| 29 | #include <fcntl.h> |
| 30 | |
| 31 | #include "common.h" |
| 32 | #include "context.h" |
| 33 | #include "dict.h" |
Radek Krejci | bc9cf93 | 2015-07-30 11:09:39 +0200 | [diff] [blame] | 34 | #include "tree_internal.h" |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 35 | |
Michal Vasko | 8d054e4 | 2015-08-03 12:42:06 +0200 | [diff] [blame^] | 36 | #define IETF_YANG_TYPES_PATH "../models/ietf-yang-types@2013-07-15.h" |
| 37 | #define IETF_INET_TYPES_PATH "../models/ietf-inet-types@2013-07-15.h" |
| 38 | #define IETF_YANG_LIB_PATH "../models/ietf-yang-library@2015-07-03.h" |
| 39 | |
| 40 | #include IETF_YANG_TYPES_PATH |
| 41 | #include IETF_INET_TYPES_PATH |
| 42 | #include IETF_YANG_LIB_PATH |
| 43 | |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 44 | API struct ly_ctx * |
| 45 | ly_ctx_new(const char *search_dir) |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 46 | { |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 47 | struct ly_ctx *ctx; |
| 48 | char *cwd; |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 49 | |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 50 | ctx = calloc(1, sizeof *ctx); |
| 51 | if (!ctx) { |
| 52 | LOGMEM; |
| 53 | return NULL; |
| 54 | } |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 55 | |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 56 | /* dictionary */ |
| 57 | lydict_init(&ctx->dict); |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 58 | |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 59 | /* models list */ |
| 60 | ctx->models.list = calloc(16, sizeof *ctx->models.list); |
| 61 | ctx->models.used = 0; |
| 62 | ctx->models.size = 16; |
| 63 | if (search_dir) { |
| 64 | cwd = get_current_dir_name(); |
| 65 | if (chdir(search_dir)) { |
| 66 | LOGERR(LY_ESYS, "Unable to use search directory \"%s\" (%s)", |
| 67 | search_dir, strerror(errno)); |
| 68 | free(cwd); |
| 69 | ly_ctx_destroy(ctx); |
| 70 | return NULL; |
| 71 | } |
| 72 | ctx->models.search_path = get_current_dir_name(); |
| 73 | chdir(cwd); |
| 74 | free(cwd); |
| 75 | } |
Michal Vasko | 8d054e4 | 2015-08-03 12:42:06 +0200 | [diff] [blame^] | 76 | /* load ietf-inet-types */ |
| 77 | ctx->models.list[0] = lys_parse(ctx, (char *)ietf_inet_types_2013_07_15_yin, LYS_IN_YIN); |
| 78 | if (!ctx->models.list[0]) { |
| 79 | ly_ctx_destroy(ctx); |
| 80 | return NULL; |
| 81 | } |
| 82 | |
| 83 | /* load ietf-yang-types */ |
| 84 | ctx->models.list[1] = lys_parse(ctx, (char *)ietf_yang_types_2013_07_15_yin, LYS_IN_YIN); |
| 85 | if (!ctx->models.list[1]) { |
| 86 | ly_ctx_destroy(ctx); |
| 87 | return NULL; |
| 88 | } |
| 89 | |
| 90 | /* load ietf-yang-library */ |
| 91 | ctx->models.list[2] = lys_parse(ctx, (char *)ietf_yang_library_2015_07_03_yin, LYS_IN_YIN); |
| 92 | if (!ctx->models.list[2]) { |
| 93 | ly_ctx_destroy(ctx); |
| 94 | return NULL; |
| 95 | } |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 96 | |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 97 | return ctx; |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 98 | } |
| 99 | |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 100 | API void |
Michal Vasko | 60ba9a6 | 2015-07-03 14:42:31 +0200 | [diff] [blame] | 101 | ly_ctx_set_searchdir(struct ly_ctx *ctx, const char *search_dir) |
| 102 | { |
| 103 | char *cwd; |
| 104 | |
| 105 | if (!ctx) { |
| 106 | return; |
| 107 | } |
| 108 | |
| 109 | if (search_dir) { |
| 110 | cwd = get_current_dir_name(); |
| 111 | if (chdir(search_dir)) { |
| 112 | LOGERR(LY_ESYS, "Unable to use search directory \"%s\" (%s)", |
| 113 | search_dir, strerror(errno)); |
| 114 | free(cwd); |
| 115 | return; |
| 116 | } |
| 117 | ctx->models.search_path = get_current_dir_name(); |
| 118 | chdir(cwd); |
| 119 | free(cwd); |
| 120 | } else { |
| 121 | free(ctx->models.search_path); |
| 122 | ctx->models.search_path = NULL; |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | API void |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 127 | ly_ctx_destroy(struct ly_ctx *ctx) |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 128 | { |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 129 | if (!ctx) { |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 130 | return; |
| 131 | } |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 132 | |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 133 | /* models list */ |
Radek Krejci | dce5145 | 2015-06-16 15:20:08 +0200 | [diff] [blame] | 134 | while (ctx->models.used) { |
Radek Krejci | 912da45 | 2015-07-29 14:10:06 +0200 | [diff] [blame] | 135 | lys_free(ctx->models.list[0]); |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 136 | } |
| 137 | free(ctx->models.search_path); |
| 138 | free(ctx->models.list); |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 139 | |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 140 | /* dictionary */ |
| 141 | lydict_clean(&ctx->dict); |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 142 | |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 143 | free(ctx); |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 144 | } |
| 145 | |
Michal Vasko | c425a6b | 2015-07-03 15:46:29 +0200 | [diff] [blame] | 146 | API struct ly_submodule * |
Radek Krejci | 63a91a9 | 2015-07-29 13:31:04 +0200 | [diff] [blame] | 147 | ly_ctx_get_submodule(struct ly_module *module, const char *name, const char *revision) |
Radek Krejci | efaeba3 | 2015-05-27 14:30:57 +0200 | [diff] [blame] | 148 | { |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 149 | struct ly_submodule *result; |
| 150 | int i; |
Radek Krejci | efaeba3 | 2015-05-27 14:30:57 +0200 | [diff] [blame] | 151 | |
Radek Krejci | 63a91a9 | 2015-07-29 13:31:04 +0200 | [diff] [blame] | 152 | if (!module || !name) { |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 153 | ly_errno = LY_EINVAL; |
| 154 | return NULL; |
| 155 | } |
Radek Krejci | efaeba3 | 2015-05-27 14:30:57 +0200 | [diff] [blame] | 156 | |
Radek Krejci | e98bb4b | 2015-07-30 14:21:41 +0200 | [diff] [blame] | 157 | /* TODO search also for submodules not directly available from the main module */ |
| 158 | |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 159 | /* search in modules included by the main module */ |
| 160 | if (module->type) { |
| 161 | module = ((struct ly_submodule *)module)->belongsto; |
| 162 | } |
| 163 | for (i = 0; i < module->inc_size; i++) { |
| 164 | result = module->inc[i].submodule; |
| 165 | if (strcmp(name, result->name)) { |
| 166 | continue; |
| 167 | } |
Radek Krejci | ce7fb78 | 2015-05-29 16:52:34 +0200 | [diff] [blame] | 168 | |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 169 | if (!revision || (result->rev_size && !strcmp(revision, result->rev[0].date))) { |
| 170 | return result; |
| 171 | } |
| 172 | } |
Radek Krejci | ce7fb78 | 2015-05-29 16:52:34 +0200 | [diff] [blame] | 173 | |
Radek Krejci | 63a91a9 | 2015-07-29 13:31:04 +0200 | [diff] [blame] | 174 | return NULL; |
Radek Krejci | efaeba3 | 2015-05-27 14:30:57 +0200 | [diff] [blame] | 175 | } |
| 176 | |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 177 | API struct ly_module * |
Radek Krejci | 63a91a9 | 2015-07-29 13:31:04 +0200 | [diff] [blame] | 178 | ly_ctx_get_module(struct ly_ctx *ctx, const char *name, const char *revision) |
Radek Krejci | efaeba3 | 2015-05-27 14:30:57 +0200 | [diff] [blame] | 179 | { |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 180 | int i; |
| 181 | struct ly_module *result = NULL; |
Radek Krejci | efaeba3 | 2015-05-27 14:30:57 +0200 | [diff] [blame] | 182 | |
Radek Krejci | 63a91a9 | 2015-07-29 13:31:04 +0200 | [diff] [blame] | 183 | if (!ctx || !name) { |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 184 | ly_errno = LY_EINVAL; |
| 185 | return NULL; |
| 186 | } |
Radek Krejci | efaeba3 | 2015-05-27 14:30:57 +0200 | [diff] [blame] | 187 | |
Radek Krejci | dce5145 | 2015-06-16 15:20:08 +0200 | [diff] [blame] | 188 | for (i = 0; i < ctx->models.used; i++) { |
Radek Krejci | f647e61 | 2015-07-30 11:36:07 +0200 | [diff] [blame] | 189 | if (!ctx->models.list[i] || strcmp(name, ctx->models.list[i]->name)) { |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 190 | continue; |
| 191 | } |
Radek Krejci | efaeba3 | 2015-05-27 14:30:57 +0200 | [diff] [blame] | 192 | |
Radek Krejci | f647e61 | 2015-07-30 11:36:07 +0200 | [diff] [blame] | 193 | if (!revision) { |
| 194 | /* compare revisons and remember the newest one */ |
| 195 | if (result) { |
| 196 | if (!ctx->models.list[i]->rev_size) { |
| 197 | /* the current have no revision, keep the previous with some revision */ |
| 198 | continue; |
| 199 | } |
| 200 | if (result->rev_size && strcmp(ctx->models.list[i]->rev[0].date, result->rev[0].date) < 0) { |
| 201 | /* the previous found matching module has a newer revision */ |
| 202 | continue; |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | /* remember the current match and search for newer version */ |
| 207 | result = ctx->models.list[i]; |
| 208 | } else { |
| 209 | if (ctx->models.list[i]->rev_size && !strcmp(revision, ctx->models.list[i]->rev[0].date)) { |
| 210 | /* matching revision */ |
| 211 | return result; |
| 212 | } |
Radek Krejci | 6e4ffbb | 2015-06-16 10:34:41 +0200 | [diff] [blame] | 213 | } |
| 214 | } |
Radek Krejci | efaeba3 | 2015-05-27 14:30:57 +0200 | [diff] [blame] | 215 | |
Radek Krejci | f647e61 | 2015-07-30 11:36:07 +0200 | [diff] [blame] | 216 | return result; |
Radek Krejci | da04f4a | 2015-05-21 12:54:09 +0200 | [diff] [blame] | 217 | } |
Michal Vasko | 3ec07dc | 2015-06-30 15:51:30 +0200 | [diff] [blame] | 218 | |
Radek Krejci | 96a10da | 2015-07-30 11:00:14 +0200 | [diff] [blame] | 219 | API const char ** |
Michal Vasko | 3ec07dc | 2015-06-30 15:51:30 +0200 | [diff] [blame] | 220 | ly_ctx_get_module_names(struct ly_ctx *ctx) |
| 221 | { |
| 222 | int i; |
Radek Krejci | 96a10da | 2015-07-30 11:00:14 +0200 | [diff] [blame] | 223 | const char **result = NULL; |
Michal Vasko | 3ec07dc | 2015-06-30 15:51:30 +0200 | [diff] [blame] | 224 | |
| 225 | if (!ctx) { |
| 226 | ly_errno = LY_EINVAL; |
| 227 | return NULL; |
| 228 | } |
| 229 | |
Michal Vasko | e2ea44b | 2015-07-07 11:31:48 +0200 | [diff] [blame] | 230 | result = malloc((ctx->models.used+1) * sizeof *result); |
| 231 | |
Michal Vasko | 3ec07dc | 2015-06-30 15:51:30 +0200 | [diff] [blame] | 232 | for (i = 0; i < ctx->models.used; i++) { |
Radek Krejci | 96a10da | 2015-07-30 11:00:14 +0200 | [diff] [blame] | 233 | result[i] = ctx->models.list[i]->name; |
Michal Vasko | 3ec07dc | 2015-06-30 15:51:30 +0200 | [diff] [blame] | 234 | } |
Michal Vasko | e2ea44b | 2015-07-07 11:31:48 +0200 | [diff] [blame] | 235 | result[i] = NULL; |
Michal Vasko | 3ec07dc | 2015-06-30 15:51:30 +0200 | [diff] [blame] | 236 | |
| 237 | return result; |
Michal Vasko | fa8c828 | 2015-07-03 15:14:59 +0200 | [diff] [blame] | 238 | } |
| 239 | |
Radek Krejci | 96a10da | 2015-07-30 11:00:14 +0200 | [diff] [blame] | 240 | API const char ** |
| 241 | ly_ctx_get_submodule_names(struct ly_ctx *ctx, const char *module_name) |
Michal Vasko | fa8c828 | 2015-07-03 15:14:59 +0200 | [diff] [blame] | 242 | { |
| 243 | int i; |
Radek Krejci | 96a10da | 2015-07-30 11:00:14 +0200 | [diff] [blame] | 244 | const char **result = NULL; |
Michal Vasko | fa8c828 | 2015-07-03 15:14:59 +0200 | [diff] [blame] | 245 | struct ly_module *mod; |
| 246 | |
| 247 | if (!ctx) { |
| 248 | ly_errno = LY_EINVAL; |
| 249 | return NULL; |
| 250 | } |
| 251 | |
Radek Krejci | 96a10da | 2015-07-30 11:00:14 +0200 | [diff] [blame] | 252 | mod = ly_ctx_get_module(ctx, module_name, NULL); |
Michal Vasko | fa8c828 | 2015-07-03 15:14:59 +0200 | [diff] [blame] | 253 | if (!mod) { |
Radek Krejci | 96a10da | 2015-07-30 11:00:14 +0200 | [diff] [blame] | 254 | LOGERR(LY_EVALID, "Data model \"%s\" not loaded", module_name); |
Michal Vasko | fa8c828 | 2015-07-03 15:14:59 +0200 | [diff] [blame] | 255 | return NULL; |
| 256 | } |
| 257 | |
| 258 | result = malloc((mod->inc_size+1) * sizeof *result); |
| 259 | |
| 260 | for (i = 0; i < mod->inc_size; i++) { |
Radek Krejci | 96a10da | 2015-07-30 11:00:14 +0200 | [diff] [blame] | 261 | result[i] = mod->inc[i].submodule->name; |
Michal Vasko | fa8c828 | 2015-07-03 15:14:59 +0200 | [diff] [blame] | 262 | } |
| 263 | result[i] = NULL; |
| 264 | |
| 265 | return result; |
| 266 | } |