show.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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. static void show_container(const struct lyd_node *node, size_t level,
  18. enum diff_op op, pline_opts_t *opts);
  19. static void show_list(const struct lyd_node *node, size_t level,
  20. enum diff_op op, pline_opts_t *opts);
  21. static void show_leaf(const struct lyd_node *node, size_t level,
  22. enum diff_op op, pline_opts_t *opts);
  23. static void show_leaflist(const struct lyd_node *node, size_t level,
  24. enum diff_op op, pline_opts_t *opts);
  25. static void show_node(const struct lyd_node *node, size_t level,
  26. enum diff_op op, pline_opts_t *opts);
  27. static enum diff_op str2diff_op(const char *str);
  28. static const char *diff_prefix(enum diff_op op, pline_opts_t *opts)
  29. {
  30. bool_t c = opts->colorize;
  31. if (DIFF_OP_CREATE == op)
  32. return c ? "\x1b[32m+" : "+";
  33. else if (DIFF_OP_DELETE == op)
  34. return c ? "\x1b[31m-" : "-";
  35. else if (DIFF_OP_REPLACE == op)
  36. return c ? "\x1b[33m=" : "=";
  37. return "";
  38. }
  39. static const char *diff_suffix(enum diff_op op, pline_opts_t *opts)
  40. {
  41. if (opts->colorize && (DIFF_OP_NONE != op))
  42. return "\x1b[0m";
  43. return "";
  44. }
  45. static void show_container(const struct lyd_node *node, size_t level,
  46. enum diff_op op, pline_opts_t *opts)
  47. {
  48. char begin_bracket[3] = {' ', opts->begin_bracket, '\0'};
  49. if (!node)
  50. return;
  51. printf("%s%*s%s%s%s\n",
  52. diff_prefix(op, opts),
  53. (int)(level * opts->indent), "",
  54. node->schema->name,
  55. opts->show_brackets ? begin_bracket : "",
  56. diff_suffix(op, opts));
  57. show_subtree(lyd_child(node), level + 1, op, opts);
  58. if (opts->show_brackets) {
  59. printf("%s%*s%c%s\n",
  60. diff_prefix(op, opts),
  61. (int)(level * opts->indent), "",
  62. opts->end_bracket,
  63. diff_suffix(op, opts));
  64. }
  65. }
  66. static void show_list(const struct lyd_node *node, size_t level,
  67. enum diff_op op, pline_opts_t *opts)
  68. {
  69. char begin_bracket[3] = {' ', opts->begin_bracket, '\0'};
  70. const struct lyd_node *iter = NULL;
  71. bool_t first_key = BOOL_TRUE;
  72. if (!node)
  73. return;
  74. printf("%s%*s%s",
  75. diff_prefix(op, opts),
  76. (int)(level * opts->indent), "",
  77. node->schema->name);
  78. LY_LIST_FOR(lyd_child(node), iter) {
  79. char *value = NULL;
  80. if (!(iter->schema->nodetype & LYS_LEAF))
  81. continue;
  82. if (!(iter->schema->flags & LYS_KEY))
  83. continue;
  84. if (opts->keys_w_stmt && (!first_key || (first_key &&
  85. (opts->first_key_w_stmt ||
  86. (opts->default_keys && klysc_node_ext_default(iter->schema))))))
  87. printf(" %s", iter->schema->name);
  88. value = klyd_node_value(iter);
  89. printf(" %s", value);
  90. faux_str_free(value);
  91. first_key = BOOL_FALSE;
  92. }
  93. printf("%s%s\n",
  94. opts->show_brackets ? begin_bracket : "",
  95. diff_suffix(op, opts));
  96. show_subtree(lyd_child(node), level + 1, op, opts);
  97. if (opts->show_brackets) {
  98. printf("%s%*s%c%s\n",
  99. diff_prefix(op, opts),
  100. (int)(level * opts->indent), "",
  101. opts->end_bracket,
  102. diff_suffix(op, opts));
  103. }
  104. }
  105. static void show_leaf(const struct lyd_node *node, size_t level,
  106. enum diff_op op, pline_opts_t *opts)
  107. {
  108. struct lysc_node_leaf *leaf = (struct lysc_node_leaf *)node;
  109. if (!node)
  110. return;
  111. if (node->schema->flags & LYS_KEY)
  112. return;
  113. printf("%s%*s%s",
  114. diff_prefix(op, opts),
  115. (int)(level * opts->indent), "",
  116. node->schema->name);
  117. leaf = (struct lysc_node_leaf *)node->schema;
  118. if (leaf->type->basetype != LY_TYPE_EMPTY) {
  119. if (opts->hide_passwords &&
  120. klysc_node_ext_is_password(node->schema)) {
  121. printf(" <hidden>");
  122. } else {
  123. char *value = klyd_node_value(node);
  124. printf(" %s", value);
  125. faux_str_free(value);
  126. }
  127. }
  128. printf("%s%s\n",
  129. opts->show_semicolons ? ";" : "",
  130. diff_suffix(op, opts));
  131. }
  132. static void show_leaflist(const struct lyd_node *node, size_t level,
  133. enum diff_op op, pline_opts_t *opts)
  134. {
  135. char *value = NULL;
  136. if (!node)
  137. return;
  138. value = klyd_node_value(node);
  139. printf("%s%*s%s %s%s%s\n",
  140. diff_prefix(op, opts),
  141. (int)(level * opts->indent), "",
  142. node->schema->name,
  143. value,
  144. opts->show_semicolons ? ";" : "",
  145. diff_suffix(op, opts));
  146. faux_str_free(value);
  147. }
  148. static void show_node(const struct lyd_node *node, size_t level,
  149. enum diff_op op, pline_opts_t *opts)
  150. {
  151. const struct lysc_node *schema = NULL;
  152. struct lyd_meta *meta = NULL;
  153. enum diff_op cur_op = op;
  154. if (!node)
  155. return;
  156. if (node->flags & LYD_DEFAULT)
  157. return;
  158. schema = node->schema;
  159. if (!schema)
  160. return;
  161. if (!(schema->nodetype & SRP_NODETYPE_CONF))
  162. return;
  163. if (!(schema->flags & LYS_CONFIG_W))
  164. return;
  165. meta = lyd_find_meta(node->meta, NULL, "yang:operation");
  166. if (meta)
  167. cur_op = str2diff_op(lyd_get_meta_value(meta));
  168. // Container
  169. if (schema->nodetype & LYS_CONTAINER) {
  170. show_container(node, level, cur_op, opts);
  171. // List
  172. } else if (schema->nodetype & LYS_LIST) {
  173. show_list(node, level, cur_op, opts);
  174. // Leaf
  175. } else if (schema->nodetype & LYS_LEAF) {
  176. show_leaf(node, level, cur_op, opts);
  177. // Leaf-list
  178. } else if (schema->nodetype & LYS_LEAFLIST) {
  179. show_leaflist(node, level, cur_op, opts);
  180. } else {
  181. return;
  182. }
  183. }
  184. static void show_sorted_list(faux_list_t *list, size_t level,
  185. enum diff_op op, pline_opts_t *opts)
  186. {
  187. faux_list_node_t *iter = NULL;
  188. const struct lyd_node *lyd = NULL;
  189. if (!list)
  190. return;
  191. iter = faux_list_head(list);
  192. while ((lyd = (const struct lyd_node *)faux_list_each(&iter)))
  193. show_node(lyd, level, op, opts);
  194. }
  195. static char *list_keys_str(const struct lyd_node *node)
  196. {
  197. char *keys = NULL;
  198. const struct lyd_node *iter = NULL;
  199. if (!node)
  200. return NULL;
  201. if (node->schema->nodetype != LYS_LIST)
  202. return NULL;
  203. LY_LIST_FOR(lyd_child(node), iter) {
  204. if (!(iter->schema->nodetype & LYS_LEAF))
  205. continue;
  206. if (!(iter->schema->flags & LYS_KEY))
  207. continue;
  208. if (keys)
  209. faux_str_cat(&keys, " ");
  210. faux_str_cat(&keys, lyd_get_value(iter));
  211. }
  212. return keys;
  213. }
  214. static int list_compare(const void *first, const void *second)
  215. {
  216. int rc = 0;
  217. const struct lyd_node *f = (const struct lyd_node *)first;
  218. const struct lyd_node *s = (const struct lyd_node *)second;
  219. char *f_keys = list_keys_str(f);
  220. char *s_keys = list_keys_str(s);
  221. rc = faux_str_numcmp(f_keys, s_keys);
  222. faux_str_free(f_keys);
  223. faux_str_free(s_keys);
  224. return rc;
  225. }
  226. static int leaflist_compare(const void *first, const void *second)
  227. {
  228. const struct lyd_node *f = (const struct lyd_node *)first;
  229. const struct lyd_node *s = (const struct lyd_node *)second;
  230. return faux_str_numcmp(lyd_get_value(f), lyd_get_value(s));
  231. }
  232. void show_subtree(const struct lyd_node *nodes_list, size_t level,
  233. enum diff_op op, pline_opts_t *opts)
  234. {
  235. const struct lyd_node *iter = NULL;
  236. faux_list_t *list = NULL;
  237. const struct lysc_node *saved_lysc = NULL;
  238. if(!nodes_list)
  239. return;
  240. LY_LIST_FOR(nodes_list, iter) {
  241. if (saved_lysc) {
  242. if (saved_lysc == iter->schema) {
  243. faux_list_add(list, (void *)iter);
  244. continue;
  245. }
  246. show_sorted_list(list, level, op, opts);
  247. faux_list_free(list);
  248. list = NULL;
  249. saved_lysc = NULL;
  250. }
  251. if (((LYS_LIST == iter->schema->nodetype) ||
  252. (LYS_LEAFLIST == iter->schema->nodetype)) &&
  253. (iter->schema->flags & LYS_ORDBY_SYSTEM)) {
  254. saved_lysc = iter->schema;
  255. if (LYS_LIST == iter->schema->nodetype) {
  256. list = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  257. list_compare, NULL, NULL);
  258. } else { // LEAFLIST
  259. list = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  260. leaflist_compare, NULL, NULL);
  261. }
  262. faux_list_add(list, (void *)iter);
  263. continue;
  264. }
  265. show_node(iter, level, op, opts);
  266. }
  267. if (list) {
  268. show_sorted_list(list, level, op, opts);
  269. faux_list_free(list);
  270. }
  271. }
  272. bool_t show_xpath(sr_session_ctx_t *sess, const char *xpath, pline_opts_t *opts)
  273. {
  274. sr_data_t *data = NULL;
  275. struct lyd_node *nodes_list = NULL;
  276. assert(sess);
  277. if (xpath) {
  278. if (sr_get_subtree(sess, xpath, 0, &data) != SR_ERR_OK)
  279. return BOOL_FALSE;
  280. nodes_list = lyd_child(data->tree);
  281. } else {
  282. if (sr_get_data(sess, "/*", 0, 0, 0, &data) != SR_ERR_OK)
  283. return BOOL_FALSE;
  284. nodes_list = data->tree;
  285. }
  286. show_subtree(nodes_list, 0, DIFF_OP_NONE, opts);
  287. sr_release_data(data);
  288. return BOOL_TRUE;
  289. }
  290. static enum diff_op str2diff_op(const char *str)
  291. {
  292. if (!strcmp(str, "create"))
  293. return DIFF_OP_CREATE;
  294. else if (!strcmp(str, "delete"))
  295. return DIFF_OP_DELETE;
  296. else if (!strcmp(str, "replace"))
  297. return DIFF_OP_REPLACE;
  298. return DIFF_OP_NONE;
  299. }