diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c index 62ca7e89..be9d445e 100644 --- a/apps/cli/cli_generate.c +++ b/apps/cli/cli_generate.c @@ -90,6 +90,7 @@ You can see which CLISPEC it generates via clixon_cli -D 2: #include #include #include +#include // XXX #include /* cligen */ @@ -103,6 +104,23 @@ You can see which CLISPEC it generates via clixon_cli -D 2: #include "cli_autocli.h" #include "cli_generate.h" +/*! mount helper + * + * @param[in] yspec + * @retval name First name ib cvec + */ +static char* +cli_get_mntpoint(yang_stmt *yspec) +{ + cvec *cvv = NULL; + cg_var *cv = NULL; + + if ((cvv = yang_cvec_get(yspec)) != NULL && + (cv = cvec_i(cvv, 0)) != NULL) + return cv_name_get(cv); + return NULL; +} + /*! Create cligen variable expand entry with api-pathfmt format string as argument * * Add api-fmt as first argument to callback, eg: @@ -134,10 +152,11 @@ cli_expand_var_generate(clixon_handle h, char *api_path_fmt = NULL; int extvalue = 0; yang_stmt *yspec; - cg_var *cv = NULL; + char *mntpoint = NULL; - if ((yspec = ys_spec(ys)) != NULL) - cv = yang_cv_get(yspec); + if ((yspec = ys_spec(ys)) != NULL){ + mntpoint = cli_get_mntpoint(yspec); + } if (yang_extension_value(ys, "hide", CLIXON_AUTOCLI_NS, &extvalue, NULL) < 0) goto done; if (extvalue || yang_find(ys, Y_STATUS, "deprecated") != NULL) @@ -152,8 +171,8 @@ cli_expand_var_generate(clixon_handle h, cprintf(cb, " %s(\"candidate\",\"%s\"", GENERATE_EXPAND_XMLDB, api_path_fmt); - if (cv){ /* Add optional mountpoint */ - cprintf(cb, ",\"%s%s\"", MTPOINT_PREFIX, cv_string_get(cv)); + if (mntpoint){ /* Add optional mountpoint */ + cprintf(cb, ",\"%s%s\"", MTPOINT_PREFIX, mntpoint); } cprintf(cb, ")>"); retval = 1; @@ -184,15 +203,16 @@ cli_callback_generate(clixon_handle h, int retval = -1; char *api_path_fmt = NULL; yang_stmt *yspec; - cg_var *cv = NULL; + char *mntpoint = NULL; - if ((yspec = ys_spec(ys)) != NULL) - cv = yang_cv_get(yspec); + if ((yspec = ys_spec(ys)) != NULL){ + mntpoint = cli_get_mntpoint(yspec); + } if (yang2api_path_fmt(ys, 0, &api_path_fmt) < 0) goto done; cprintf(cb, ",%s(\"%s\"", GENERATE_CALLBACK, api_path_fmt); - if (cv){ /* Add optional mountpoint */ - cprintf(cb, ",\"%s%s\"", MTPOINT_PREFIX, cv_string_get(cv)); + if (mntpoint){ /* Add optional mountpoint */ + cprintf(cb, ",\"%s%s\"", MTPOINT_PREFIX, mntpoint); } cprintf(cb, ")"); retval = 0; diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index 3f539788..d73e709f 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -263,6 +263,7 @@ int yang_cv_set(yang_stmt *ys, cg_var *cv); cvec *yang_cvec_get(yang_stmt *ys); int yang_cvec_set(yang_stmt *ys, cvec *cvv); cg_var *yang_cvec_add(yang_stmt *ys, enum cv_type type, char *name); +int yang_cvec_rm(yang_stmt *ys, char *name); uint16_t yang_flag_get(yang_stmt *ys, uint16_t flag); int yang_flag_set(yang_stmt *ys, uint16_t flag); int yang_flag_reset(yang_stmt *ys, uint16_t flag); @@ -285,7 +286,7 @@ int yang_stats(yang_stmt *y, enum rfc_6020 keyw, uint64_t *nrp, size_t *s /* Other functions */ yang_stmt *yspec_new(clixon_handle h, char *name); -yang_stmt *yspec_new_shared(clixon_handle h, char *name, yang_stmt *yspec0); +yang_stmt *yspec_new_shared(clixon_handle h, char *name, char *domain, yang_stmt *yspec0); yang_stmt *ys_new(enum rfc_6020 keyw); yang_stmt *ys_prune(yang_stmt *yp, int i); int ys_prune_self(yang_stmt *ys); diff --git a/lib/clixon/clixon_yang_schema_mount.h b/lib/clixon/clixon_yang_schema_mount.h index 59718eeb..3809fe92 100644 --- a/lib/clixon/clixon_yang_schema_mount.h +++ b/lib/clixon/clixon_yang_schema_mount.h @@ -59,7 +59,7 @@ int yang_schema_mount_point(yang_stmt *y); int yang_mount_get(yang_stmt *yu, char *xpath, yang_stmt **yspec); int yang_mount_get_yspec_any(yang_stmt *y, yang_stmt **yspec); int yang_mount_set(yang_stmt *yu, char *xpath, yang_stmt *yspec); -int xml_yang_mount_get(clixon_handle h, cxobj *x, validate_level *vl, yang_stmt **yspec); +int xml_yang_mount_get(clixon_handle h, cxobj *x, validate_level *vl, char **xpathp, yang_stmt **yspec); int xml_yang_mount_set(clixon_handle h, cxobj *x, yang_stmt *yspec); int yang_mount_xtop2xmnt(cxobj *xtop, cvec **cvvp); int yang_mount_yspec2ymnt(yang_stmt *yspec, cvec **cvvp); @@ -67,5 +67,6 @@ int yang_schema_mount_statedata(clixon_handle h, yang_stmt *yspec, char *xpath, int yang_schema_mount_statistics(clixon_handle h, cxobj *xt, int modules, cbuf *cb); int yang_schema_yanglib_parse_mount(clixon_handle h, cxobj *xt); int yang_schema_get_child(clixon_handle h, cxobj *x1, cxobj *x1c, yang_stmt **yc); +int yang_schema_yspec_rm(clixon_handle h, cxobj *xmnt); #endif /* _CLIXON_YANG_SCHEMA_MOUNT_H_ */ diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index 8af9e6d6..9040725d 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -1020,7 +1020,7 @@ text_modify(clixon_handle h, } if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){ /* Check if xc is unresolved mountpoint, ie no yang mount binding yet */ - if ((ismount = xml_yang_mount_get(h, x1c, NULL, &mount_yspec)) < 0) + if ((ismount = xml_yang_mount_get(h, x1c, NULL, NULL, &mount_yspec)) < 0) goto done; if (ismount && mount_yspec == NULL && !xml_flag(x1c, XML_FLAG_ANYDATA)){ diff --git a/lib/src/clixon_string.c b/lib/src/clixon_string.c index ec2c119a..81976033 100644 --- a/lib/src/clixon_string.c +++ b/lib/src/clixon_string.c @@ -81,7 +81,7 @@ * @param[out] nvec Number of entries in returned vector * @retval vec Vector of strings. NULL terminated. Free after use * @retval NULL Error * - * @see clicon_strsplit + * @see clixon_strsplit */ char ** clicon_strsep(char *string, diff --git a/lib/src/clixon_validate.c b/lib/src/clixon_validate.c index 6485db11..9669e709 100644 --- a/lib/src/clixon_validate.c +++ b/lib/src/clixon_validate.c @@ -1027,7 +1027,7 @@ xml_yang_validate_add(clixon_handle h, validate_level vl = VL_NONE; if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){ - if ((ret = xml_yang_mount_get(h, xt, &vl, NULL)) < 0) + if ((ret = xml_yang_mount_get(h, xt, &vl, NULL, NULL)) < 0) goto done; /* Check if validate beyond mountpoints */ if (ret == 1 && vl == VL_NONE) @@ -1253,7 +1253,7 @@ xml_yang_validate_all(clixon_handle h, int inext; if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){ - if ((ret = xml_yang_mount_get(h, xt, &vl, NULL)) < 0) + if ((ret = xml_yang_mount_get(h, xt, &vl, NULL, NULL)) < 0) goto done; /* Check if validate beyond mountpoints */ if (ret == 1 && vl == VL_NONE) diff --git a/lib/src/clixon_xml_bind.c b/lib/src/clixon_xml_bind.c index 0f5e36bd..807abae2 100644 --- a/lib/src/clixon_xml_bind.c +++ b/lib/src/clixon_xml_bind.c @@ -464,7 +464,7 @@ xml_bind_yang0_opt(clixon_handle h, ybc = YB_PARENT; if (h && clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){ yspec1 = NULL; - if ((ret = xml_yang_mount_get(h, xt, NULL, &yspec1)) < 0) + if ((ret = xml_yang_mount_get(h, xt, NULL, NULL, &yspec1)) < 0) // XXX read här goto done; if (ret == 0) yspec1 = yspec; @@ -474,14 +474,14 @@ xml_bind_yang0_opt(clixon_handle h, else if (h == NULL) goto ok; /* treat as anydata */ else{ - if ((ret = yang_schema_yanglib_parse_mount(h, xt)) < 0) + if ((ret = yang_schema_yanglib_parse_mount(h, xt)) < 0) // XXX malloc + freed här goto done; if (ret == 0){ /* Special flag if mount-point but no yanglib */ xml_flag_set(xt, XML_FLAG_ANYDATA); goto ok; } /* Try again */ - if ((ret = xml_yang_mount_get(h, xt, NULL, &yspec1)) < 0) + if ((ret = xml_yang_mount_get(h, xt, NULL, NULL, &yspec1)) < 0) goto done; if (yspec1) ybc = YB_MODULE; diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index ad2da873..a41e29d4 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -395,6 +395,31 @@ yang_cvec_add(yang_stmt *ys, return cv; } +/*! Remove old value to yang cvec + * + * @param[in] ys Yang statement + * @param[in] name Name of variable + * @retval 0 OK + * @retval -1 Error + */ +int +yang_cvec_rm(yang_stmt *ys, + char *name) +{ + cvec *cvv; + cg_var *cv; + + if ((cvv = yang_cvec_get(ys)) != NULL && + (cv = cvec_find(cvv, name)) != NULL){ + if (cvec_len(cvv) <= 1){ + yang_cvec_set(ys, NULL); + } + else + cvec_del(cvv, cv); + } + return 0; +} + /*! Get yang stmt flags, used for internal algorithms * * @param[in] ys Yang statement @@ -839,6 +864,7 @@ yspec_new(clixon_handle h, yang_stmt * yspec_new_shared(clixon_handle h, char *name, + char *domain, yang_stmt *yspec0) { yang_stmt *yspec1 = NULL; @@ -848,7 +874,7 @@ yspec_new_shared(clixon_handle h, yspec1 = yspec0; } else { - if ((yspec1 = yspec_new(h, name)) == NULL) + if ((yspec1 = yspec_new(h, domain)) == NULL) goto done; yang_flag_set(yspec1, YANG_FLAG_SPEC_MOUNT); clixon_debug(CLIXON_DBG_YANG, "new yang-spec: %p", yspec1); diff --git a/lib/src/clixon_yang_internal.h b/lib/src/clixon_yang_internal.h index 58f780b6..0d239a87 100644 --- a/lib/src/clixon_yang_internal.h +++ b/lib/src/clixon_yang_internal.h @@ -94,7 +94,6 @@ struct yang_stmt { Y_REVISION (uint32) Y_REVISION_DATE (uint32) Y_UNKNOWN (optional argument) - Y_SPEC: mount-point xpath Y_ENUM: value */ cvec *ys_cvec; /* List of stmt-specific variables diff --git a/lib/src/clixon_yang_schema_mount.c b/lib/src/clixon_yang_schema_mount.c index 93647ca6..e100e578 100644 --- a/lib/src/clixon_yang_schema_mount.c +++ b/lib/src/clixon_yang_schema_mount.c @@ -261,21 +261,9 @@ yang_mount_set(yang_stmt *y, yang_stmt *yspec) { int retval = -1; - cg_var *cv2; - if ((cv2 = cv_new(CGV_STRING)) == NULL){ - clixon_err(OE_YANG, errno, "cv_new"); - goto done; - } - if (cv_string_set(cv2, xpath) == NULL){ - clixon_err(OE_UNIX, errno, "cv_string_set"); - goto done; - } - /* tag yspec with key/xpath */ - yang_cv_set(yspec, cv2); yang_flag_set(y, YANG_FLAG_MOUNTPOINT); /* Cache value */ retval = 0; - done: return retval; } @@ -344,6 +332,7 @@ yang_mount_xmnt2ymnt_xpath(clixon_handle h, * @param[in] h Clixon handle * @param[in] xmnt XML mount-point * @param[out] vallevel Do or dont do full RFC 7950 validation if given + * @param[out] xpathp malloced xpath in canonical form (if ret is 1) * @param[out] yspec YANG stmt spec of mount-point (if ret is 1) * @retval 1 x is a mount-point: yspec may be set * @retval 0 x is not a mount-point @@ -353,6 +342,7 @@ int xml_yang_mount_get(clixon_handle h, cxobj *xmnt, validate_level *vl, + char **xpathp, yang_stmt **yspec) { int retval = -1; @@ -369,6 +359,10 @@ xml_yang_mount_get(clixon_handle h, goto done; if (yspec && yang_mount_get(ymnt, xpath, yspec) < 0) goto done; + if (xpathp){ + *xpathp = xpath; + xpath = NULL; + } retval = 1; done: if (xpath) @@ -737,12 +731,10 @@ yang_schema_mount_statistics(clixon_handle h, while ((cv = cvec_each(cvv, cv)) != NULL) { if ((xmnt = cv_void_get(cv)) == NULL) continue; - if ((ret = xml_yang_mount_get(h, xmnt, NULL, &yspec)) < 0) + if ((ret = xml_yang_mount_get(h, xmnt, NULL, &xpath, &yspec)) < 0) goto done; if (ret == 0) continue; - if (xml2xpath(xmnt, NULL, 1, 0, &xpath) < 0) - goto done; cprintf(cb, "mountpoint: "); xml_chardata_cbuf_append(cb, 0, xpath); cprintf(cb, ""); @@ -753,7 +745,7 @@ yang_schema_mount_statistics(clixon_handle h, while ((cv1 = cvec_each(cvv, cv1)) != NULL) { if (cv == cv1) continue; - if ((ret = xml_yang_mount_get(h, cv_void_get(cv1), NULL, &yspec1)) < 0) + if ((ret = xml_yang_mount_get(h, cv_void_get(cv1), NULL, NULL, &yspec1)) < 0) goto done; if (yspec1 && yspec == yspec1) break; @@ -844,7 +836,7 @@ yang_schema_find_share(clixon_handle h, continue; /* Find and return yspec */ *yspecp = NULL; - if ((ret = xml_yang_mount_get(h, xmnt, NULL, yspecp)) < 0) + if ((ret = xml_yang_mount_get(h, xmnt, NULL, NULL, yspecp)) < 0) goto done; if (ret == 1 && *yspecp != NULL) break; @@ -903,14 +895,16 @@ yang_schema_yanglib_parse_mount(clixon_handle h, if (yang_schema_find_share(h, xt, xyanglib, &yspec0) < 0) goto done; } - if ((yspec1 = yspec_new_shared(h, xpath, yspec0)) < 0) + if ((yspec1 = yspec_new_shared(h, xpath, domain, yspec0)) < 0) goto done; /* Either yspec0 = NULL and yspec1 is new, or yspec0 == yspec1 != NULL (shared) */ if (yspec0 == NULL && yspec1 != NULL){ if ((ret = yang_lib2yspec(h, xyanglib, xpath, domain, yspec1)) < 0) goto done; - if (ret == 0) + if (ret == 0){ + ys_prune_self(yspec1); /* remove from tree, free in done code */ goto anydata; + } } if (xml_yang_mount_set(h, xt, yspec1) < 0) goto done; @@ -953,7 +947,7 @@ yang_schema_get_child(clixon_handle h, int ret; x1cname = xml_name(x1c); - if ((ret = xml_yang_mount_get(h, x1, NULL, &yspec1)) < 0) + if ((ret = xml_yang_mount_get(h, x1, NULL, NULL, &yspec1)) < 0) goto done; if (ret == 1 && yspec1 != NULL){ if (ys_module_by_xml(yspec1, x1c, &ymod1) <0) @@ -971,3 +965,31 @@ yang_schema_get_child(clixon_handle h, retval = 0; goto done; } + +/*! Remove xpath from yspec cvec list, remove yspec if empty + * + * @param[in] h Clixon handle + * @param[in] xmnt XML mount-point + */ +int +yang_schema_yspec_rm(clixon_handle h, + cxobj *xmnt) +{ + /* Remove mountpoint from yspec cvec */ + int retval = -1; + yang_stmt *yspec = NULL; + char *xpath = NULL; + int ret; + + if ((ret = xml_yang_mount_get(h, xmnt, NULL, &xpath, &yspec)) < 0) + goto done; + if (ret == 1 && xpath != NULL && yspec != NULL){ + if (yang_cvec_rm(yspec, xpath) < 0) + goto done; + } + retval = 0; + done: + if (xpath) + free(xpath); + return retval; +} diff --git a/test/test_yang_mount_isolate.sh b/test/test_yang_mount_isolate.sh index 41e9285f..579eb042 100755 --- a/test/test_yang_mount_isolate.sh +++ b/test/test_yang_mount_isolate.sh @@ -200,9 +200,6 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" " new "get yang-lib at mountpoint" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" ">" "xmylabelclixon-exampleurn:example:clixonymylabelclixon-exampleurn:example:clixon" -new "check there is statistics from mountpoint" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" 'mountpoint: /top/mylist\[name="x"\]/root' - new "Add data to mounts" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "xx1" "" "" diff --git a/test/test_yang_mount_schema.sh b/test/test_yang_mount_schema.sh index 4d6f93ab..fed93477 100755 --- a/test/test_yang_mount_schema.sh +++ b/test/test_yang_mount_schema.sh @@ -218,7 +218,7 @@ new "get yang-lib at mountpoint" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" ">" "xmylabelclixon-mount0urn:example:mount0ymylabelclixon-mount0urn:example:mount0" new "check there is statistics from mountpoint" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" 'mountpoint: /top/mylist\[name="x"\]/root' +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "mountpoint: /ex:top/ex:mylist\[ex:name='x'\]/ex:root" new "Add data to mounts" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "xx1" "" ""