show.c 8.6 KB

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