kly.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. #include <stdlib.h>
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <assert.h>
  6. #include <syslog.h>
  7. #include <faux/faux.h>
  8. #include <faux/str.h>
  9. #include <faux/list.h>
  10. #include <faux/argv.h>
  11. #include <sysrepo.h>
  12. #include <sysrepo/xpath.h>
  13. #include <sysrepo/values.h>
  14. #include <libyang/tree_edit.h>
  15. #include "private.h"
  16. #include "pline.h"
  17. int klysc_key_compare(const void *first, const void *second)
  18. {
  19. const klysc_key_t *f = (const klysc_key_t *)first;
  20. const klysc_key_t *s = (const klysc_key_t *)second;
  21. return strcmp(f->node->name, s->node->name);
  22. }
  23. int klysc_key_kcompare(const void *key, const void *list_item)
  24. {
  25. const char *f = (const char *)key;
  26. const klysc_key_t *s = (const klysc_key_t *)list_item;
  27. return strcmp(f, s->node->name);
  28. }
  29. // Get extension by name from schema node
  30. static bool_t klysc_ext(const struct lysc_ext_instance *exts,
  31. const char *module, const char *name, const char **argument)
  32. {
  33. LY_ARRAY_COUNT_TYPE u = 0;
  34. if (!exts)
  35. return BOOL_FALSE;
  36. LY_ARRAY_FOR(exts, u) {
  37. const struct lysc_ext_instance *ext = &exts[u];
  38. //syslog(LOG_ERR, "mod: %s, ext: %s", ext->def->module->name, ext->def->name);
  39. if (faux_str_cmp(ext->def->module->name, module) != 0)
  40. continue;
  41. if (faux_str_cmp(ext->def->name, name) != 0)
  42. continue;
  43. if (argument)
  44. *argument = ext->argument;
  45. return BOOL_TRUE;
  46. }
  47. return BOOL_FALSE;
  48. }
  49. // Get extension by name
  50. bool_t klysc_node_ext(const struct lysc_node *node,
  51. const char *module, const char *name, const char **argument)
  52. {
  53. if (!node)
  54. return BOOL_FALSE;
  55. if (klysc_ext(node->exts, module, name, argument))
  56. return BOOL_TRUE;
  57. return BOOL_FALSE;
  58. }
  59. bool_t klysc_node_ext_is_password(const struct lysc_node *node)
  60. {
  61. return klysc_node_ext(node, "klish", "password", NULL);
  62. }
  63. const char *klysc_node_ext_completion(const struct lysc_node *node)
  64. {
  65. const char *xpath = NULL;
  66. klysc_node_ext(node, "klish", "completion", &xpath);
  67. return xpath;
  68. }
  69. const char *klysc_node_ext_default(const struct lysc_node *node)
  70. {
  71. const char *dflt = NULL;
  72. klysc_node_ext(node, "klish", "default", &dflt);
  73. return dflt;
  74. }
  75. // Get value from data lyd node
  76. char *klyd_node_value(const struct lyd_node *node)
  77. {
  78. const struct lysc_node *schema = NULL;
  79. const struct lysc_type *type = NULL;
  80. const char *origin_value = NULL;
  81. char *space = NULL;
  82. char *escaped = NULL;
  83. char *result = NULL;
  84. if (!node)
  85. return NULL;
  86. schema = node->schema;
  87. if (!(schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)))
  88. return NULL;
  89. if (schema->nodetype & LYS_LEAF)
  90. type = ((const struct lysc_node_leaf *)schema)->type;
  91. else
  92. type = ((const struct lysc_node_leaflist *)schema)->type;
  93. if (type->basetype != LY_TYPE_IDENT) {
  94. origin_value = lyd_get_value(node);
  95. } else {
  96. // Identity
  97. const struct lyd_value *value = NULL;
  98. value = &((const struct lyd_node_term *)node)->value;
  99. origin_value = value->ident->name;
  100. }
  101. escaped = faux_str_c_esc(origin_value);
  102. // String with space must have quotes
  103. space = strchr(origin_value, ' ');
  104. if (space) {
  105. result = faux_str_sprintf("\"%s\"", escaped);
  106. faux_str_free(escaped);
  107. } else {
  108. result = escaped;
  109. }
  110. return result;
  111. }
  112. // Don't use standard lys_find_child() because it checks given module to be
  113. // equal to found node's module. So augmented nodes will not be found.
  114. const struct lysc_node *klysc_find_child(const struct lysc_node *node,
  115. const char *name)
  116. {
  117. const struct lysc_node *iter = NULL;
  118. if (!node)
  119. return NULL;
  120. LY_LIST_FOR(node, iter) {
  121. if (!(iter->nodetype & SRP_NODETYPE_CONF))
  122. continue;
  123. if (!(iter->flags & LYS_CONFIG_W))
  124. continue;
  125. // Special case. LYS_CHOICE and LYS_CASE must search for
  126. // specified name inside themselfs.
  127. if (iter->nodetype & (LYS_CHOICE | LYS_CASE)) {
  128. const struct lysc_node *node_in = NULL;
  129. node_in = klysc_find_child(lysc_node_child(iter), name);
  130. if (node_in)
  131. return node_in;
  132. continue;
  133. }
  134. if (!faux_str_cmp(iter->name, name))
  135. return iter;
  136. }
  137. return NULL;
  138. }
  139. static struct lysc_ident *klysc_find_ident(struct lysc_ident *ident, const char *name)
  140. {
  141. LY_ARRAY_COUNT_TYPE u = 0;
  142. if (!ident)
  143. return NULL;
  144. if (!ident->derived) {
  145. if (!faux_str_cmp(name, ident->name))
  146. return ident;
  147. return NULL;
  148. }
  149. LY_ARRAY_FOR(ident->derived, u) {
  150. struct lysc_ident *identity = klysc_find_ident(ident->derived[u], name);
  151. if (identity)
  152. return identity;
  153. }
  154. return NULL;
  155. }
  156. const char *klysc_identityref_prefix(struct lysc_type_identityref *type,
  157. const char *name)
  158. {
  159. LY_ARRAY_COUNT_TYPE u = 0;
  160. assert(type);
  161. LY_ARRAY_FOR(type->bases, u) {
  162. struct lysc_ident *identity = klysc_find_ident(type->bases[u], name);
  163. if (identity)
  164. return identity->module->name;
  165. }
  166. return NULL;
  167. }
  168. // Get module name by internal prefix. Sysrepo requests use module names but not
  169. // prefixes.
  170. static const char *module_by_prefix(const struct lysp_module *parsed, const char *prefix)
  171. {
  172. LY_ARRAY_COUNT_TYPE u = 0;
  173. if (!parsed)
  174. return NULL;
  175. if (!prefix)
  176. return NULL;
  177. // Try prefix of module itself
  178. if (faux_str_cmp(prefix, parsed->mod->prefix) == 0)
  179. return parsed->mod->name;
  180. // Try imported modules
  181. LY_ARRAY_FOR(parsed->imports, u) {
  182. const struct lysp_import *import = &parsed->imports[u];
  183. if (faux_str_cmp(prefix, import->prefix) == 0)
  184. return import->name;
  185. }
  186. return NULL;
  187. }
  188. static char *remap_xpath_prefixes(const char *orig_xpath, const struct lysp_module *parsed)
  189. {
  190. char *remaped = NULL;
  191. const char *pos = orig_xpath;
  192. const char *start = orig_xpath;
  193. char *cached_prefix = NULL;
  194. char *cached_module = NULL;
  195. if (!orig_xpath)
  196. return NULL;
  197. while (*pos != '\0') {
  198. if (*pos == '/') {
  199. faux_str_catn(&remaped, start, pos - start + 1);
  200. start = pos + 1;
  201. } else if (*pos == ':') {
  202. if (pos != start) {
  203. char *prefix = faux_str_dupn(start, pos - start);
  204. if (cached_prefix && (faux_str_cmp(prefix, cached_prefix) == 0)) {
  205. faux_str_cat(&remaped, cached_module);
  206. faux_str_free(prefix);
  207. } else {
  208. const char *module = module_by_prefix(parsed, prefix);
  209. if (module) {
  210. faux_str_cat(&remaped, module);
  211. faux_str_free(cached_prefix);
  212. faux_str_free(cached_module);
  213. cached_prefix = prefix;
  214. cached_module = faux_str_dup(module);
  215. } else {
  216. faux_str_cat(&remaped, prefix);
  217. faux_str_free(prefix);
  218. }
  219. }
  220. }
  221. faux_str_cat(&remaped, ":");
  222. start = pos + 1;
  223. }
  224. pos++;
  225. }
  226. if (start != pos)
  227. faux_str_catn(&remaped, start, pos - start);
  228. faux_str_free(cached_prefix);
  229. faux_str_free(cached_module);
  230. return remaped;
  231. }
  232. static const char *cut_front_ups(const char *orig_xpath, size_t *up_num)
  233. {
  234. const char *xpath = orig_xpath;
  235. const char *needle = "../";
  236. size_t needle_len = strlen(needle);
  237. size_t num = 0;
  238. if (!xpath)
  239. return NULL;
  240. while (faux_str_cmpn(xpath, needle, needle_len) == 0) {
  241. num++;
  242. xpath += needle_len;
  243. }
  244. if (up_num)
  245. *up_num = num;
  246. return xpath;
  247. }
  248. static char *cut_trailing_components(const char *orig_xpath, size_t up_num)
  249. {
  250. const char *xpath = NULL;
  251. char *res = NULL;
  252. size_t num = 0;
  253. if (!orig_xpath)
  254. return NULL;
  255. xpath = orig_xpath + strlen(orig_xpath);
  256. while (xpath >= orig_xpath) {
  257. if (*xpath == '/')
  258. num++;
  259. if (num == up_num) {
  260. res = faux_str_dupn(orig_xpath, xpath - orig_xpath + 1);
  261. break;
  262. }
  263. xpath--;
  264. }
  265. return res;
  266. }
  267. char *klysc_leafref_xpath(const struct lysc_node *node, const char *node_path)
  268. {
  269. char *compl_xpath = NULL;
  270. const struct lysc_type *type = NULL;
  271. const struct lysc_type_leafref *leafref = NULL;
  272. const char *orig_xpath = NULL;
  273. char *remaped_xpath = NULL;
  274. const char *tmp = NULL;
  275. size_t up_num = 0;
  276. if (!node)
  277. return NULL;
  278. if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST)))
  279. return NULL;
  280. if (node->nodetype & LYS_LEAF)
  281. type = ((const struct lysc_node_leaf *)node)->type;
  282. else
  283. type = ((const struct lysc_node_leaflist *)node)->type;
  284. if (type->basetype != LY_TYPE_LEAFREF)
  285. return NULL;
  286. leafref = (const struct lysc_type_leafref *)type;
  287. orig_xpath = lyxp_get_expr(leafref->path);
  288. if (!orig_xpath)
  289. return NULL;
  290. remaped_xpath = remap_xpath_prefixes(orig_xpath, node->module->parsed);
  291. if (remaped_xpath[0] == '/') // Absolute path
  292. return remaped_xpath;
  293. // Relative path
  294. if (!node_path) {
  295. faux_str_free(remaped_xpath);
  296. return NULL;
  297. }
  298. tmp = cut_front_ups(remaped_xpath, &up_num);
  299. compl_xpath = cut_trailing_components(node_path, up_num);
  300. if (!compl_xpath) {
  301. faux_str_free(remaped_xpath);
  302. return NULL;
  303. }
  304. faux_str_cat(&compl_xpath, tmp);
  305. faux_str_free(remaped_xpath);
  306. return compl_xpath;
  307. }