kly.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  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 from node
  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. // Get extension by name from type
  60. bool_t klysc_type_ext(const struct lysc_type *type,
  61. const char *module, const char *name, const char **argument)
  62. {
  63. if (!type)
  64. return BOOL_FALSE;
  65. if (klysc_ext(type->exts, module, name, argument))
  66. return BOOL_TRUE;
  67. return BOOL_FALSE;
  68. }
  69. // Get extension by name from node or type
  70. bool_t klysc_node_or_type_ext(const struct lysc_node *node,
  71. const char *module, const char *name, const char **argument)
  72. {
  73. struct lysc_type *type = NULL;
  74. if (!node)
  75. return BOOL_FALSE;
  76. if (klysc_node_ext(node, module, name, argument))
  77. return BOOL_TRUE;
  78. switch (node->nodetype) {
  79. case LYS_LEAF:
  80. type = ((struct lysc_node_leaf *)node)->type;
  81. break;
  82. case LYS_LEAFLIST:
  83. type = ((struct lysc_node_leaflist *)node)->type;
  84. break;
  85. default:
  86. return BOOL_FALSE;
  87. }
  88. if (klysc_type_ext(type, module, name, argument))
  89. return BOOL_TRUE;
  90. return BOOL_FALSE;
  91. }
  92. bool_t klysc_node_ext_is_password(const struct lysc_node *node)
  93. {
  94. return klysc_node_ext(node, "klish", "password", NULL);
  95. }
  96. const char *klysc_node_ext_completion(const struct lysc_node *node)
  97. {
  98. const char *xpath = NULL;
  99. klysc_node_or_type_ext(node, "klish", "completion", &xpath);
  100. return xpath;
  101. }
  102. const char *klysc_node_ext_default(const struct lysc_node *node)
  103. {
  104. const char *dflt = NULL;
  105. klysc_node_ext(node, "klish", "default", &dflt);
  106. return dflt;
  107. }
  108. // Get value from data lyd node
  109. char *klyd_node_value(const struct lyd_node *node)
  110. {
  111. const struct lysc_node *schema = NULL;
  112. const struct lysc_type *type = NULL;
  113. const char *origin_value = NULL;
  114. char *space = NULL;
  115. char *escaped = NULL;
  116. char *result = NULL;
  117. if (!node)
  118. return NULL;
  119. schema = node->schema;
  120. if (!(schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)))
  121. return NULL;
  122. if (schema->nodetype & LYS_LEAF)
  123. type = ((const struct lysc_node_leaf *)schema)->type;
  124. else
  125. type = ((const struct lysc_node_leaflist *)schema)->type;
  126. if (type->basetype != LY_TYPE_IDENT) {
  127. origin_value = lyd_get_value(node);
  128. } else {
  129. // Identity
  130. const struct lyd_value *value = NULL;
  131. value = &((const struct lyd_node_term *)node)->value;
  132. origin_value = value->ident->name;
  133. }
  134. escaped = faux_str_c_esc(origin_value);
  135. // String with space must have quotes
  136. space = strchr(origin_value, ' ');
  137. if (space) {
  138. result = faux_str_sprintf("\"%s\"", escaped);
  139. faux_str_free(escaped);
  140. } else {
  141. result = escaped;
  142. }
  143. return result;
  144. }
  145. // Don't use standard lys_find_child() because it checks given module to be
  146. // equal to found node's module. So augmented nodes will not be found.
  147. const struct lysc_node *klysc_find_child(const struct lysc_node *node,
  148. const char *name)
  149. {
  150. const struct lysc_node *iter = NULL;
  151. if (!node)
  152. return NULL;
  153. LY_LIST_FOR(node, iter) {
  154. if (!(iter->nodetype & SRP_NODETYPE_CONF))
  155. continue;
  156. if (!(iter->flags & LYS_CONFIG_W))
  157. continue;
  158. // Special case. LYS_CHOICE and LYS_CASE must search for
  159. // specified name inside themselfs.
  160. if (iter->nodetype & (LYS_CHOICE | LYS_CASE)) {
  161. const struct lysc_node *node_in = NULL;
  162. node_in = klysc_find_child(lysc_node_child(iter), name);
  163. if (node_in)
  164. return node_in;
  165. continue;
  166. }
  167. if (!faux_str_cmp(iter->name, name))
  168. return iter;
  169. }
  170. return NULL;
  171. }
  172. static struct lysc_ident *klysc_find_ident(struct lysc_ident *ident, const char *name)
  173. {
  174. LY_ARRAY_COUNT_TYPE u = 0;
  175. if (!ident)
  176. return NULL;
  177. if (!ident->derived) {
  178. if (!faux_str_cmp(name, ident->name))
  179. return ident;
  180. return NULL;
  181. }
  182. LY_ARRAY_FOR(ident->derived, u) {
  183. struct lysc_ident *identity = klysc_find_ident(ident->derived[u], name);
  184. if (identity)
  185. return identity;
  186. }
  187. return NULL;
  188. }
  189. const char *klysc_identityref_prefix(struct lysc_type_identityref *type,
  190. const char *name)
  191. {
  192. LY_ARRAY_COUNT_TYPE u = 0;
  193. assert(type);
  194. LY_ARRAY_FOR(type->bases, u) {
  195. struct lysc_ident *identity = klysc_find_ident(type->bases[u], name);
  196. if (identity)
  197. return identity->module->name;
  198. }
  199. return NULL;
  200. }
  201. // Get module name by internal prefix. Sysrepo requests use module names but not
  202. // prefixes.
  203. static const char *module_by_prefix(const struct lysp_module *parsed, const char *prefix)
  204. {
  205. LY_ARRAY_COUNT_TYPE u = 0;
  206. if (!parsed)
  207. return NULL;
  208. if (!prefix)
  209. return NULL;
  210. // Try prefix of module itself
  211. if (faux_str_cmp(prefix, parsed->mod->prefix) == 0)
  212. return parsed->mod->name;
  213. // Try imported modules
  214. LY_ARRAY_FOR(parsed->imports, u) {
  215. const struct lysp_import *import = &parsed->imports[u];
  216. if (faux_str_cmp(prefix, import->prefix) == 0)
  217. return import->name;
  218. }
  219. return NULL;
  220. }
  221. static char *remap_xpath_prefixes(const char *orig_xpath, const struct lysp_module *parsed)
  222. {
  223. char *remaped = NULL;
  224. const char *pos = orig_xpath;
  225. const char *start = orig_xpath;
  226. char *cached_prefix = NULL;
  227. char *cached_module = NULL;
  228. if (!orig_xpath)
  229. return NULL;
  230. while (*pos != '\0') {
  231. if (*pos == '/') {
  232. faux_str_catn(&remaped, start, pos - start + 1);
  233. start = pos + 1;
  234. } else if (*pos == ':') {
  235. if (pos != start) {
  236. char *prefix = faux_str_dupn(start, pos - start);
  237. if (cached_prefix && (faux_str_cmp(prefix, cached_prefix) == 0)) {
  238. faux_str_cat(&remaped, cached_module);
  239. faux_str_free(prefix);
  240. } else {
  241. const char *module = module_by_prefix(parsed, prefix);
  242. if (module) {
  243. faux_str_cat(&remaped, module);
  244. faux_str_free(cached_prefix);
  245. faux_str_free(cached_module);
  246. cached_prefix = prefix;
  247. cached_module = faux_str_dup(module);
  248. } else {
  249. faux_str_cat(&remaped, prefix);
  250. faux_str_free(prefix);
  251. }
  252. }
  253. }
  254. faux_str_cat(&remaped, ":");
  255. start = pos + 1;
  256. }
  257. pos++;
  258. }
  259. if (start != pos)
  260. faux_str_catn(&remaped, start, pos - start);
  261. faux_str_free(cached_prefix);
  262. faux_str_free(cached_module);
  263. return remaped;
  264. }
  265. static const char *cut_front_ups(const char *orig_xpath, size_t *up_num)
  266. {
  267. const char *xpath = orig_xpath;
  268. const char *needle = "../";
  269. size_t needle_len = strlen(needle);
  270. size_t num = 0;
  271. if (!xpath)
  272. return NULL;
  273. while (faux_str_cmpn(xpath, needle, needle_len) == 0) {
  274. num++;
  275. xpath += needle_len;
  276. }
  277. if (up_num)
  278. *up_num = num;
  279. return xpath;
  280. }
  281. static char *cut_trailing_components(const char *orig_xpath, size_t up_num)
  282. {
  283. const char *xpath = NULL;
  284. char *res = NULL;
  285. size_t num = 0;
  286. if (!orig_xpath)
  287. return NULL;
  288. xpath = orig_xpath + strlen(orig_xpath);
  289. while (xpath >= orig_xpath) {
  290. if (*xpath == '/')
  291. num++;
  292. if (num == up_num) {
  293. res = faux_str_dupn(orig_xpath, xpath - orig_xpath + 1);
  294. break;
  295. }
  296. xpath--;
  297. }
  298. return res;
  299. }
  300. char *klysc_leafref_xpath(const struct lysc_node *node,
  301. const struct lysc_type *type, const char *node_path)
  302. {
  303. char *compl_xpath = NULL;
  304. const struct lysc_type_leafref *leafref = NULL;
  305. const char *orig_xpath = NULL;
  306. char *remaped_xpath = NULL;
  307. const char *tmp = NULL;
  308. size_t up_num = 0;
  309. if (!type)
  310. return NULL;
  311. if (!node)
  312. return NULL;
  313. if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST)))
  314. return NULL;
  315. if (type->basetype != LY_TYPE_LEAFREF)
  316. return NULL;
  317. leafref = (const struct lysc_type_leafref *)type;
  318. orig_xpath = lyxp_get_expr(leafref->path);
  319. if (!orig_xpath)
  320. return NULL;
  321. remaped_xpath = remap_xpath_prefixes(orig_xpath, node->module->parsed);
  322. if (remaped_xpath[0] == '/') // Absolute path
  323. return remaped_xpath;
  324. // Relative path
  325. if (!node_path) {
  326. faux_str_free(remaped_xpath);
  327. return NULL;
  328. }
  329. tmp = cut_front_ups(remaped_xpath, &up_num);
  330. compl_xpath = cut_trailing_components(node_path, up_num);
  331. if (!compl_xpath) {
  332. faux_str_free(remaped_xpath);
  333. return NULL;
  334. }
  335. faux_str_cat(&compl_xpath, tmp);
  336. faux_str_free(remaped_xpath);
  337. return compl_xpath;
  338. }
  339. size_t klyd_visible_child_num(const struct lyd_node *node)
  340. {
  341. const struct lyd_node *nodes_list = NULL;
  342. const struct lyd_node *iter = NULL;
  343. size_t num = 0;
  344. if (!node)
  345. return 0;
  346. nodes_list = lyd_child(node);
  347. if(!nodes_list)
  348. return 0;
  349. LY_LIST_FOR(nodes_list, iter) {
  350. if (iter->flags & LYD_DEFAULT)
  351. continue;
  352. if (!(iter->schema->nodetype & SRP_NODETYPE_CONF))
  353. continue;
  354. if (!(iter->schema->flags & LYS_CONFIG_W)) // config is true
  355. continue;
  356. if (iter->schema->flags & LYS_KEY)
  357. continue;
  358. num++;
  359. }
  360. return num;
  361. }