* C-API: Added xpath_first_localonly() as an xpath function that skips prefix and namespace checks.
* Added experimental code for optizing XPath search using binary search. * Enable with XPATH_LIST_OPTIMIZE * Changed `clicon_rpc_generate_error(msg, xerr)` to `clicon_rpc_generate_error(xerr, msg, arg)`
This commit is contained in:
parent
ab46ce9820
commit
7ad16bd84b
56 changed files with 602 additions and 227 deletions
|
|
@ -3,6 +3,10 @@
|
||||||
## 4.3.0 (Expected: December 2019)
|
## 4.3.0 (Expected: December 2019)
|
||||||
|
|
||||||
### Minor changes
|
### Minor changes
|
||||||
|
* C-API: Added `xpath_first_localonly()` as an xpath function that skips prefix and namespace checks.
|
||||||
|
* Added experimental code for optizing XPath search using binary search.
|
||||||
|
* Enable with XPATH_LIST_OPTIMIZE
|
||||||
|
* Removed most assert.h includes
|
||||||
* Added "canonical" global namespace context: `nsctx_global`
|
* Added "canonical" global namespace context: `nsctx_global`
|
||||||
* This is a normalized XML prefix:namespace pair vector computed from all loaded Yang modules. Useful when writing XML and XPATH expressions in callbacks.
|
* This is a normalized XML prefix:namespace pair vector computed from all loaded Yang modules. Useful when writing XML and XPATH expressions in callbacks.
|
||||||
* Get it with `clicon_nsctx_global_get(h)`
|
* Get it with `clicon_nsctx_global_get(h)`
|
||||||
|
|
@ -17,7 +21,9 @@
|
||||||
* Optional yang files are loaded only if configured with `--enable-optyangs` (flipped logic and changed from `disable-stdyangs`). NOTE: you must do this to run examples and tests.
|
* Optional yang files are loaded only if configured with `--enable-optyangs` (flipped logic and changed from `disable-stdyangs`). NOTE: you must do this to run examples and tests.
|
||||||
* Optional yang files can be installed in a separate dir with `--with-opt-yang-installdir=DIR` (renamed from `with-std-yang-installdir`)
|
* Optional yang files can be installed in a separate dir with `--with-opt-yang-installdir=DIR` (renamed from `with-std-yang-installdir`)
|
||||||
* C-API
|
* C-API
|
||||||
* Added namespace-context parameter `nsc` to `xpath_first` and `xpath_vec`, (`xpath_vec_nsc` and xpath_first_nsc` are removed).
|
* Changed `clicon_rpc_generate_error(msg, xerr)` to `clicon_rpc_generate_error(xerr, msg, arg)`
|
||||||
|
* Added namespace-context parameter `nsc` to `xpath_first` and `xpath_vec`, (`xpath_vec_nsc` and
|
||||||
|
xpath_first_nsc` are removed).
|
||||||
* Added clicon_handle as parameter to all `clicon_connect_` functions to get better error message
|
* Added clicon_handle as parameter to all `clicon_connect_` functions to get better error message
|
||||||
* Added nsc parameter to `xmldb_get()`
|
* Added nsc parameter to `xmldb_get()`
|
||||||
* The multi-namespace augment state may rearrange the XML namespace attributes.
|
* The multi-namespace augment state may rearrange the XML namespace attributes.
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,6 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
|
|
|
||||||
|
|
@ -216,8 +216,8 @@ nacm_load_external(clicon_handle h)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (yspec) /* The clixon yang-spec is not used after this */
|
// XXX if (yspec) /* The clixon yang-spec is not used after this */
|
||||||
yspec_free(yspec);
|
// XXX yspec_free(yspec);
|
||||||
if (f)
|
if (f)
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,6 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,6 @@
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
@ -70,7 +69,6 @@
|
||||||
|
|
||||||
#include "cli_common.h"
|
#include "cli_common.h"
|
||||||
|
|
||||||
|
|
||||||
/*! Register log notification stream
|
/*! Register log notification stream
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] stream Event stream. CLICON is predefined, others are application-defined
|
* @param[in] stream Event stream. CLICON is predefined, others are application-defined
|
||||||
|
|
@ -715,13 +713,13 @@ compare_dbs(clicon_handle h,
|
||||||
if (clicon_rpc_get_config(h, NULL, "running", "/", NULL, &xc1) < 0)
|
if (clicon_rpc_get_config(h, NULL, "running", "/", NULL, &xc1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xc1, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(xc1, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Get configuration", xerr);
|
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (clicon_rpc_get_config(h, NULL, "candidate", "/", NULL, &xc2) < 0)
|
if (clicon_rpc_get_config(h, NULL, "candidate", "/", NULL, &xc2) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xc2, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(xc2, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Get configuration", xerr);
|
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (compare_xmls(xc1, xc2, astext) < 0) /* astext? */
|
if (compare_xmls(xc1, xc2, astext) < 0) /* astext? */
|
||||||
|
|
@ -885,7 +883,7 @@ save_config_file(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Get configuration", xerr);
|
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* get-config returns a <data> tree. Save as <config> tree so it can be used
|
/* get-config returns a <data> tree. Save as <config> tree so it can be used
|
||||||
|
|
@ -1225,7 +1223,7 @@ cli_copy_config(clicon_handle h,
|
||||||
if (clicon_rpc_get_config(h, NULL, db, cbuf_get(cb), nsc, &x1) < 0)
|
if (clicon_rpc_get_config(h, NULL, db, cbuf_get(cb), nsc, &x1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(x1, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(x1, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Get configuration", xerr);
|
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
@ -76,6 +75,8 @@
|
||||||
This is an example yang module:
|
This is an example yang module:
|
||||||
module m {
|
module m {
|
||||||
container x {
|
container x {
|
||||||
|
namespace "urn:example:m";
|
||||||
|
prefix m;
|
||||||
list m1 {
|
list m1 {
|
||||||
key "a";
|
key "a";
|
||||||
leaf a {
|
leaf a {
|
||||||
|
|
@ -88,12 +89,11 @@ module m {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
You can see which CLISPEC it generates via clixon_cli -D 1:
|
You can see which CLISPEC it generates via clixon_cli -D 2:
|
||||||
Jan 2 11:17:58: yang2cli: buf
|
x,cli_set("/example:x");{
|
||||||
} x,cli_set("/x");{
|
m1 a (<a:string>|<a:string expand_dbvar("candidate","/example:x/m1=%s/a")>),overwrite_me("/example:x/m1=%s/");
|
||||||
m1 (<a:string>|<a:string expand_dbvar("candidate /x/m1/%s/a")>),cli_set("/x/m1/%s");
|
|
||||||
{
|
{
|
||||||
b (<b:string>|<b:string expand_dbvar("candidate /x/m1/%s/b")>),cli_set("/x/m1/%s/b");
|
b (<b:string>|<b:string expand_dbvar("candidate","/example:x/m1=%s/b")>),overwrite_me("/example:x/m1=%s/b");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -464,7 +464,6 @@ cli_handler_err(FILE *f)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Evaluate a matched command
|
/*! Evaluate a matched command
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] cmd The command string
|
* @param[in] cmd The command string
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,6 @@
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
@ -158,7 +157,7 @@ expand_dbvar(void *h,
|
||||||
if (clicon_rpc_get_config(h, NULL, dbstr, xpath, nsc, &xt) < 0) /* XXX */
|
if (clicon_rpc_get_config(h, NULL, dbstr, xpath, nsc, &xt) < 0) /* XXX */
|
||||||
goto done;
|
goto done;
|
||||||
if ((xe = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
if ((xe = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Get configuration", xe);
|
clicon_rpc_generate_error(xe, "Get configuration", NULL);
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
xcur = xt; /* default top-of-tree */
|
xcur = xt; /* default top-of-tree */
|
||||||
|
|
@ -175,7 +174,7 @@ expand_dbvar(void *h,
|
||||||
if ((ret = api_path2xml(api_path, yspec, xtop, YC_DATANODE, 0, &xbot, &y, &xerr)) < 0)
|
if ((ret = api_path2xml(api_path, yspec, xtop, YC_DATANODE, 0, &xbot, &y, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
clicon_rpc_generate_error("Expand datastore symbol", xerr);
|
clicon_rpc_generate_error(xerr, "Expand datastore symbol", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -487,7 +486,7 @@ cli_show_config1(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Get configuration", xerr);
|
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
||||||
|
|
@ -635,7 +634,7 @@ show_conf_xpath(clicon_handle h,
|
||||||
if (clicon_rpc_get_config(h, NULL, str, xpath, nsc, &xt) < 0)
|
if (clicon_rpc_get_config(h, NULL, str, xpath, nsc, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Get configuration", xerr);
|
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -738,7 +737,7 @@ cli_show_auto1(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Get configuration", xerr);
|
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((xp = xpath_first(xt, nsc, "%s", xpath)) != NULL)
|
if ((xp = xpath_first(xt, nsc, "%s", xpath)) != NULL)
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,6 @@ Mapping netconf error-tag -> status code
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
@ -110,7 +109,7 @@ example_client_rpc(clicon_handle h,
|
||||||
if (clicon_rpc_netconf_xml(h, xrpc, &xret, NULL) < 0)
|
if (clicon_rpc_netconf_xml(h, xrpc, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Get configuration", xerr);
|
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Print result */
|
/* Print result */
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,3 +58,9 @@
|
||||||
* on the top-level for the modules involved in the netconf operation.
|
* on the top-level for the modules involved in the netconf operation.
|
||||||
*/
|
*/
|
||||||
#define IDENTITYREF_KLUDGE
|
#define IDENTITYREF_KLUDGE
|
||||||
|
|
||||||
|
/*! Optimize special list key searches in XPATH finds
|
||||||
|
* Identify xpaths that search for exactly a list key, eg: "y[k=3]" and then call
|
||||||
|
* binary search. This only works if "y" has proper yang binding and is sorted by system
|
||||||
|
*/
|
||||||
|
#undef XPATH_LIST_OPTIMIZE
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ int clicon_rpc_msg(clicon_handle h, struct clicon_msg *msg, cxobj **xret0,
|
||||||
int *sock0);
|
int *sock0);
|
||||||
int clicon_rpc_netconf(clicon_handle h, char *xmlst, cxobj **xret, int *sp);
|
int clicon_rpc_netconf(clicon_handle h, char *xmlst, cxobj **xret, int *sp);
|
||||||
int clicon_rpc_netconf_xml(clicon_handle h, cxobj *xml, cxobj **xret, int *sp);
|
int clicon_rpc_netconf_xml(clicon_handle h, cxobj *xml, cxobj **xret, int *sp);
|
||||||
int clicon_rpc_generate_error(const char *format, cxobj *xerr);
|
int clicon_rpc_generate_error(cxobj *xerr, const char *fmt, const char *arg);
|
||||||
int clicon_rpc_get_config(clicon_handle h, char *username, char *db, char *xpath, cvec *nsc, cxobj **xret);
|
int clicon_rpc_get_config(clicon_handle h, char *username, char *db, char *xpath, cvec *nsc, cxobj **xret);
|
||||||
int clicon_rpc_edit_config(clicon_handle h, char *db, enum operation_type op,
|
int clicon_rpc_edit_config(clicon_handle h, char *db, enum operation_type op,
|
||||||
char *xml);
|
char *xml);
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,8 @@ int clicon_str2int(const map_str2int *mstab, char *str);
|
||||||
int clicon_str2int_search(const map_str2int *mstab, char *str, int upper);
|
int clicon_str2int_search(const map_str2int *mstab, char *str, int upper);
|
||||||
int nodeid_split(char *nodeid, char **prefix, char **id);
|
int nodeid_split(char *nodeid, char **prefix, char **id);
|
||||||
char *clixon_trim(char *str);
|
char *clixon_trim(char *str);
|
||||||
|
int clicon_strcmp(char *s1, char *s2);
|
||||||
|
|
||||||
#ifndef HAVE_STRNDUP
|
#ifndef HAVE_STRNDUP
|
||||||
char *clicon_strndup (const char *, size_t);
|
char *clicon_strndup (const char *, size_t);
|
||||||
#endif /* ! HAVE_STRNDUP */
|
#endif /* ! HAVE_STRNDUP */
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,6 @@ int xml_sort(cxobj *x0, void *arg);
|
||||||
int xml_insert(cxobj *xp, cxobj *xc, enum insert_type ins, char *key_val, cvec *nsckey);
|
int xml_insert(cxobj *xp, cxobj *xc, enum insert_type ins, char *key_val, cvec *nsckey);
|
||||||
int xml_sort_verify(cxobj *x, void *arg);
|
int xml_sort_verify(cxobj *x, void *arg);
|
||||||
int match_base_child(cxobj *x0, cxobj *x1c, yang_stmt *yc, cxobj **x0cp);
|
int match_base_child(cxobj *x0, cxobj *x1c, yang_stmt *yc, cxobj **x0cp);
|
||||||
cxobj *xml_binsearch(cxobj *xp, char *name, char *keyname, char *keyval);
|
int xml_binsearch(cxobj *xp, char *name, char *keyname, char *keyval, cxobj **xret);
|
||||||
|
|
||||||
#endif /* _CLIXON_XML_SORT_H */
|
#endif /* _CLIXON_XML_SORT_H */
|
||||||
|
|
|
||||||
|
|
@ -101,10 +101,13 @@ enum xp_type{
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! XPATH Parsing generates a tree of nodes that is later traversed
|
/*! XPATH Parsing generates a tree of nodes that is later traversed
|
||||||
|
* That is, a tree-structured XPATH.
|
||||||
|
* Note that the structure follows XPATH 1.0 closely. The drawback wit this is that the tree gets
|
||||||
|
* very deep very quickly, even for simple XPATHs.
|
||||||
*/
|
*/
|
||||||
struct xpath_tree{
|
struct xpath_tree{
|
||||||
enum xp_type xs_type;
|
enum xp_type xs_type;
|
||||||
int xs_int; /* step-> axis-type */
|
int xs_int; /* step-> axis_type */
|
||||||
double xs_double;
|
double xs_double;
|
||||||
char *xs_strnr; /* original string xs_double: numeric value */
|
char *xs_strnr; /* original string xs_double: numeric value */
|
||||||
char *xs_s0;
|
char *xs_s0;
|
||||||
|
|
@ -122,9 +125,10 @@ char* xpath_tree_int2str(int nodetype);
|
||||||
int xpath_tree_print_cb(cbuf *cb, xpath_tree *xs);
|
int xpath_tree_print_cb(cbuf *cb, xpath_tree *xs);
|
||||||
int xpath_tree_print(FILE *f, xpath_tree *xs);
|
int xpath_tree_print(FILE *f, xpath_tree *xs);
|
||||||
int xpath_tree2cbuf(xpath_tree *xs, cbuf *xpathcb);
|
int xpath_tree2cbuf(xpath_tree *xs, cbuf *xpathcb);
|
||||||
|
int xpath_tree_eq(xpath_tree *xt1, xpath_tree *xt2, cvec *match);
|
||||||
int xpath_tree_free(xpath_tree *xs);
|
int xpath_tree_free(xpath_tree *xs);
|
||||||
int xpath_parse(char *xpath, xpath_tree **xptree);
|
int xpath_parse(char *xpath, xpath_tree **xptree);
|
||||||
int xpath_vec_ctx(cxobj *xcur, cvec *nsc, char *xpath, xp_ctx **xrp);
|
int xpath_vec_ctx(cxobj *xcur, cvec *nsc, char *xpath, int localonly, xp_ctx **xrp);
|
||||||
|
|
||||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||||
int xpath_vec_bool(cxobj *xcur, cvec *nsc, char *xpformat, ...) __attribute__ ((format (printf, 3, 4)));
|
int xpath_vec_bool(cxobj *xcur, cvec *nsc, char *xpformat, ...) __attribute__ ((format (printf, 3, 4)));
|
||||||
|
|
@ -144,9 +148,11 @@ int xpath_vec_flag(cxobj *xcur, cvec *nsc, char *xpformat, uint16_t flags,
|
||||||
*/
|
*/
|
||||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||||
cxobj *xpath_first(cxobj *xcur, cvec *nsc, char *xpformat, ...) __attribute__ ((format (printf, 3, 4)));
|
cxobj *xpath_first(cxobj *xcur, cvec *nsc, char *xpformat, ...) __attribute__ ((format (printf, 3, 4)));
|
||||||
|
cxobj *xpath_first_localonly(cxobj *xcur, char *xpformat, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
int xpath_vec(cxobj *xcur, cvec *nsc, char *xpformat, cxobj ***vec, size_t *veclen, ...) __attribute__ ((format (printf, 3, 6)));
|
int xpath_vec(cxobj *xcur, cvec *nsc, char *xpformat, cxobj ***vec, size_t *veclen, ...) __attribute__ ((format (printf, 3, 6)));
|
||||||
#else
|
#else
|
||||||
cxobj *xpath_first(cxobj *xcur, cvec *nsc, char *xpformat, ...);
|
cxobj *xpath_first(cxobj *xcur, cvec *nsc, char *xpformat, ...);
|
||||||
|
cxobj *xpath_first_localonly(cxobj *xcur, char *xpformat, ...);
|
||||||
int xpath_vec(cxobj *xcur, cvec *nsc, char *xpformat, cxobj ***vec, size_t *veclen, ...);
|
int xpath_vec(cxobj *xcur, cvec *nsc, char *xpformat, cxobj ***vec, size_t *veclen, ...);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,8 @@ extern const map_str2int ctxmap[];
|
||||||
int ctx_free(xp_ctx *xc);
|
int ctx_free(xp_ctx *xc);
|
||||||
xp_ctx *ctx_dup(xp_ctx *xc);
|
xp_ctx *ctx_dup(xp_ctx *xc);
|
||||||
int ctx_nodeset_replace(xp_ctx *xc, cxobj **vec, size_t veclen);
|
int ctx_nodeset_replace(xp_ctx *xc, cxobj **vec, size_t veclen);
|
||||||
int ctx_print(cbuf *cb, int id, xp_ctx *xc, char *str);
|
int ctx_print_cb(cbuf *cb, xp_ctx *xc, int indent, char *str);
|
||||||
|
int ctx_print(FILE *f, xp_ctx *xc, char *str);
|
||||||
int ctx2boolean(xp_ctx *xc);
|
int ctx2boolean(xp_ctx *xc);
|
||||||
int ctx2string(xp_ctx *xc, char **str0);
|
int ctx2string(xp_ctx *xc, char **str0);
|
||||||
int ctx2number(xp_ctx *xc, double *n0);
|
int ctx2number(xp_ctx *xc, double *n0);
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,6 @@ object.
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
@ -1360,13 +1359,13 @@ netconf_err2cb(cxobj *xerr,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
|
|
||||||
if ((x=xpath_first(xerr, NULL, "error-type"))!=NULL)
|
if ((x=xpath_first(xerr, NULL, "//error-type"))!=NULL)
|
||||||
cprintf(cberr, "%s ", xml_body(x));
|
cprintf(cberr, "%s ", xml_body(x));
|
||||||
if ((x=xpath_first(xerr, NULL, "error-tag"))!=NULL)
|
if ((x=xpath_first(xerr, NULL, "//error-tag"))!=NULL)
|
||||||
cprintf(cberr, "%s ", xml_body(x));
|
cprintf(cberr, "%s ", xml_body(x));
|
||||||
if ((x=xpath_first(xerr, NULL, "error-message"))!=NULL)
|
if ((x=xpath_first(xerr, NULL, "//error-message"))!=NULL)
|
||||||
cprintf(cberr, "%s ", xml_body(x));
|
cprintf(cberr, "%s ", xml_body(x));
|
||||||
if ((x=xpath_first(xerr, NULL, "error-info"))!=NULL)
|
if ((x=xpath_first(xerr, NULL, "//error-info"))!=NULL)
|
||||||
clicon_xml2cbuf(cberr, xml_child_i(x,0), 0, 0, -1);
|
clicon_xml2cbuf(cberr, xml_child_i(x,0), 0, 0, -1);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
|
||||||
|
|
@ -225,13 +225,18 @@ clicon_rpc_netconf_xml(clicon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Generate and log clicon error function call from Netconf error message
|
/*! Generate clicon error from Netconf error message
|
||||||
* @param[in] prefix Print this string (if given) before: "<prefix>: <error>"
|
*
|
||||||
* @param[in] xerr Netconf error message on the level: <rpc-error>
|
* Get a text error message from netconf error message and generate error on the form:
|
||||||
|
* <msg>: "<arg>": <netconf-error> or <msg>: <netconf-error>
|
||||||
|
* @param[in] xerr Netconf error xml tree on the form: <rpc-error>
|
||||||
|
* @param[in] format Format string
|
||||||
|
* @param[in] arg String argument to format (optional)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_rpc_generate_error(const char *prefix,
|
clicon_rpc_generate_error(cxobj *xerr,
|
||||||
cxobj *xerr)
|
const char *msg,
|
||||||
|
const char *arg)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cbuf *cb = NULL;
|
cbuf *cb = NULL;
|
||||||
|
|
@ -242,10 +247,12 @@ clicon_rpc_generate_error(const char *prefix,
|
||||||
}
|
}
|
||||||
if (netconf_err2cb(xerr, cb) < 0)
|
if (netconf_err2cb(xerr, cb) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (prefix)
|
if (arg){
|
||||||
clicon_log(LOG_ERR, "%s: %s", prefix, cbuf_get(cb));
|
cprintf(cb, "%s: \"%s\": ", msg, arg);
|
||||||
else
|
clicon_err(OE_CFG, EINVAL, "%s", cbuf_get(cb));
|
||||||
clicon_log(LOG_ERR, "%s", cbuf_get(cb));
|
}
|
||||||
|
else /* XXX: should really be clicon_err but dont do it yet for backward compatability */
|
||||||
|
clicon_log(LOG_ERR, "%s: %s", msg, cbuf_get(cb));
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (cb)
|
if (cb)
|
||||||
|
|
@ -273,7 +280,7 @@ clicon_rpc_generate_error(const char *prefix,
|
||||||
* if (clicon_rpc_get_config(h, NULL, "running", "/hello/world", nsc, &xt) < 0)
|
* if (clicon_rpc_get_config(h, NULL, "running", "/hello/world", nsc, &xt) < 0)
|
||||||
* err;
|
* err;
|
||||||
* if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
* if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
* clicon_rpc_generate_error("", xerr);
|
* clicon_rpc_generate_error(xerr, "msg", "/hello/world");
|
||||||
* err;
|
* err;
|
||||||
* }
|
* }
|
||||||
* if (xt)
|
* if (xt)
|
||||||
|
|
@ -395,7 +402,7 @@ clicon_rpc_edit_config(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Editing configuration", xerr);
|
clicon_rpc_generate_error(xerr, "Editing configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -442,7 +449,7 @@ clicon_rpc_copy_config(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Copying configuration", xerr);
|
clicon_rpc_generate_error(xerr, "Copying configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -482,7 +489,7 @@ clicon_rpc_delete_config(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Deleting configuration", xerr);
|
clicon_rpc_generate_error(xerr, "Deleting configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -518,7 +525,7 @@ clicon_rpc_lock(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Locking configuration", xerr);
|
clicon_rpc_generate_error(xerr, "Locking configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -553,7 +560,7 @@ clicon_rpc_unlock(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Configuration unlock", xerr);
|
clicon_rpc_generate_error(xerr, "Configuration unlock", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -587,7 +594,7 @@ clicon_rpc_unlock(clicon_handle h,
|
||||||
* if (clicon_rpc_get(h, "/hello/world", nsc, CONTENT_ALL, -1, &xt) < 0)
|
* if (clicon_rpc_get(h, "/hello/world", nsc, CONTENT_ALL, -1, &xt) < 0)
|
||||||
* err;
|
* err;
|
||||||
* if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
* if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
* clicon_rpc_generate_error(xerr);
|
* clicon_rpc_generate_error(xerr, "clicon_rpc_get", NULL);
|
||||||
* err;
|
* err;
|
||||||
* }
|
* }
|
||||||
* if (xt)
|
* if (xt)
|
||||||
|
|
@ -694,7 +701,7 @@ clicon_rpc_close_session(clicon_handle h)
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Close session", xerr);
|
clicon_rpc_generate_error(xerr, "Close session", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -730,7 +737,7 @@ clicon_rpc_kill_session(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Kill session", xerr);
|
clicon_rpc_generate_error(xerr, "Kill session", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -765,7 +772,7 @@ clicon_rpc_validate(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(CLIXON_ERRSTR_VALIDATE_FAILED, xerr);
|
clicon_rpc_generate_error(xerr, CLIXON_ERRSTR_VALIDATE_FAILED, NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -798,7 +805,7 @@ clicon_rpc_commit(clicon_handle h)
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(CLIXON_ERRSTR_COMMIT_FAILED, xerr);
|
clicon_rpc_generate_error(xerr, CLIXON_ERRSTR_COMMIT_FAILED, NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -831,7 +838,7 @@ clicon_rpc_discard_changes(clicon_handle h)
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Discard changes", xerr);
|
clicon_rpc_generate_error(xerr, "Discard changes", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -877,7 +884,7 @@ clicon_rpc_create_subscription(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, s0) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, s0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Create subscription", xerr);
|
clicon_rpc_generate_error(xerr, "Create subscription", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -912,7 +919,7 @@ clicon_rpc_debug(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Debug",xerr);
|
clicon_rpc_generate_error(xerr, "Debug", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xpath_first(xret, NULL, "//rpc-reply/ok") == NULL){
|
if (xpath_first(xret, NULL, "//rpc-reply/ok") == NULL){
|
||||||
|
|
@ -955,7 +962,7 @@ clicon_hello_req(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error("Hello", xerr);
|
clicon_rpc_generate_error(xerr, "Hello", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((x = xpath_first(xret, NULL, "hello/session-id")) == NULL){
|
if ((x = xpath_first(xret, NULL, "hello/session-id")) == NULL){
|
||||||
|
|
|
||||||
|
|
@ -692,6 +692,26 @@ clixon_trim(char *str)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! check string equals (NULL is equal)
|
||||||
|
* @param[in] s1 String 1
|
||||||
|
* @param[in] s2 String 2
|
||||||
|
* @retval 0 Equal
|
||||||
|
* @retval -1 Not equal
|
||||||
|
* @retval 1 Not equal
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clicon_strcmp(char *s1,
|
||||||
|
char *s2)
|
||||||
|
{
|
||||||
|
if (s1 == NULL && s2 == NULL)
|
||||||
|
return 0;
|
||||||
|
if (s1 == NULL) /* empty string first */
|
||||||
|
return -1;
|
||||||
|
if (s2 == NULL)
|
||||||
|
return 1;
|
||||||
|
return strcmp(s1, s2);
|
||||||
|
}
|
||||||
|
|
||||||
/*! strndup() for systems without it, such as xBSD
|
/*! strndup() for systems without it, such as xBSD
|
||||||
*/
|
*/
|
||||||
#ifndef HAVE_STRNDUP
|
#ifndef HAVE_STRNDUP
|
||||||
|
|
@ -717,7 +737,6 @@ clicon_strndup(const char *str,
|
||||||
#endif /* ! HAVE_STRNDUP */
|
#endif /* ! HAVE_STRNDUP */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn this on for uni-test programs
|
* Turn this on for uni-test programs
|
||||||
* Usage: clixon_string join
|
* Usage: clixon_string join
|
||||||
|
|
|
||||||
|
|
@ -1059,8 +1059,8 @@ xml_find(cxobj *x_up,
|
||||||
|
|
||||||
while ((x = xml_child_each(x_up, x, -1)) != NULL)
|
while ((x = xml_child_each(x_up, x, -1)) != NULL)
|
||||||
if (strcmp(name, xml_name(x)) == 0)
|
if (strcmp(name, xml_name(x)) == 0)
|
||||||
return x;
|
break; /* x is set */
|
||||||
return NULL;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Append xc as child to xp. Remove xc from previous parent.
|
/*! Append xc as child to xp. Remove xc from previous parent.
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ changelog_rename(clicon_handle h,
|
||||||
clicon_err(OE_XML, 0, "tag required");
|
clicon_err(OE_XML, 0, "tag required");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xpath_vec_ctx(xw, nsc, tag, &xctx) < 0)
|
if (xpath_vec_ctx(xw, nsc, tag, 0, &xctx) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ctx2string(xctx, &str) < 0)
|
if (ctx2string(xctx, &str) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -258,7 +258,7 @@ changelog_op(clicon_handle h,
|
||||||
xw = wvec[i];
|
xw = wvec[i];
|
||||||
/* If 'when' exists and is false, skip this target */
|
/* If 'when' exists and is false, skip this target */
|
||||||
if (whenxpath){
|
if (whenxpath){
|
||||||
if (xpath_vec_ctx(xw, nsc, whenxpath, &xctx) < 0)
|
if (xpath_vec_ctx(xw, nsc, whenxpath, 0, &xctx) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((ret = ctx2boolean(xctx)) < 0)
|
if ((ret = ctx2boolean(xctx)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,14 @@ xml_cmp(cxobj *x1,
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_cv_cache(x2, &cv2) < 0) /* error case */
|
if (xml_cv_cache(x2, &cv2) < 0) /* error case */
|
||||||
goto done;
|
goto done;
|
||||||
equal = cv_cmp(cv1, cv2);
|
if (cv1 != NULL && cv2 != NULL)
|
||||||
|
equal = cv_cmp(cv1, cv2);
|
||||||
|
else if (cv1 == NULL && cv2 == NULL)
|
||||||
|
equal = 0;
|
||||||
|
else if (cv1 == NULL)
|
||||||
|
equal = -1;
|
||||||
|
else
|
||||||
|
equal = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Y_LIST: /* Match with key values
|
case Y_LIST: /* Match with key values
|
||||||
|
|
@ -309,10 +316,9 @@ xml_cmp(cxobj *x1,
|
||||||
else{
|
else{
|
||||||
if (xml_cv_cache(x1b, &cv1) < 0) /* error case */
|
if (xml_cv_cache(x1b, &cv1) < 0) /* error case */
|
||||||
goto done;
|
goto done;
|
||||||
// assert(cv1);
|
|
||||||
if (xml_cv_cache(x2b, &cv2) < 0) /* error case */
|
if (xml_cv_cache(x2b, &cv2) < 0) /* error case */
|
||||||
goto done;
|
goto done;
|
||||||
// assert(cv2);
|
assert(cv1 && cv2);
|
||||||
if ((equal = cv_cmp(cv1, cv2)) != 0)
|
if ((equal = cv_cmp(cv1, cv2)) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -831,15 +837,26 @@ match_base_child(cxobj *x0,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Experimental API for binary search
|
/*! Experimental API for binary search
|
||||||
|
* @param[in] xp Parent xml node.
|
||||||
|
* @param[in] name Node name of child (list)
|
||||||
|
* @param[in] keyname Yang list key name
|
||||||
|
* @param[in] keyval XML key value
|
||||||
|
* @param[out] xret Found XML object, NULL if not founs
|
||||||
|
* @retval 0 OK, see xret
|
||||||
|
* @retval -1 Error
|
||||||
|
* Multiple keys?
|
||||||
|
* Can extend to leaf-list?
|
||||||
*/
|
*/
|
||||||
cxobj *
|
int
|
||||||
xml_binsearch(cxobj *xp,
|
xml_binsearch(cxobj *xp,
|
||||||
char *name,
|
char *name,
|
||||||
char *keyname,
|
char *keyname,
|
||||||
char *keyval)
|
char *keyval,
|
||||||
|
cxobj **xretp)
|
||||||
{
|
{
|
||||||
|
int retval = -1;
|
||||||
cxobj *xc = NULL;
|
cxobj *xc = NULL;
|
||||||
cxobj *xa = NULL;
|
// cxobj *xa = NULL;
|
||||||
cxobj *xret = NULL;
|
cxobj *xret = NULL;
|
||||||
yang_stmt *yp;
|
yang_stmt *yp;
|
||||||
yang_stmt *yc;
|
yang_stmt *yc;
|
||||||
|
|
@ -852,15 +869,22 @@ xml_binsearch(cxobj *xp,
|
||||||
clicon_err(OE_YANG, ENOENT, "yang not found");
|
clicon_err(OE_YANG, ENOENT, "yang not found");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((xc = xml_new(name, xp, yc)) == NULL)
|
if (xml_parse_va(&xc, yc, "<%s><%s>%s</%s></%s>", name, keyname, keyval, keyname, name) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new(keyname, xc, NULL)) == NULL)
|
if (xml_rootchild(xc, 0, &xc) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_value_set(xa, keyval) < 0)
|
#if 0
|
||||||
|
if (xml_apply0(xc, CX_ELMNT, xml_spec_populate, ys_spec(yc)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
#else
|
||||||
|
if (xml_spec_set(xc, yc) < 0)
|
||||||
|
goto done;
|
||||||
|
#endif
|
||||||
xret = xml_search(xp, xc, yc);
|
xret = xml_search(xp, xc, yc);
|
||||||
|
*xretp = xret; /* XXX possibly use *xretp directly */
|
||||||
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (xc)
|
if (xc)
|
||||||
xml_free(xc);
|
xml_free(xc);
|
||||||
return xret;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,9 +66,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
@ -306,6 +306,84 @@ xpath_tree2cbuf(xpath_tree *xs,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Check if two xpath-trees (parsed xpaths) ar equal
|
||||||
|
*
|
||||||
|
* @param[in] xt1 XPath parse 1
|
||||||
|
* @param[in] xt2 XPath parse 2
|
||||||
|
* @param[in,out] mv Match vector consisting of <name,val> pairs
|
||||||
|
* @retval 0 If equal
|
||||||
|
* @retval -1 If not equal
|
||||||
|
* The function returns 0 if the two trees are equal, otherwise -1
|
||||||
|
* But the "mv" parameter is a way to add pattern matching to some variables
|
||||||
|
* On input, mv contains a vector of CLIgen string variables with names that may match string
|
||||||
|
* fields s0 and s1 in an xpath_tree. If the names match the values of s0 or s1, the field is
|
||||||
|
* considered equal and is stored as value in the CLIgen variable vector.
|
||||||
|
* Example:
|
||||||
|
* xt1: _x[_y='_z']
|
||||||
|
* xt2: y[k='3']
|
||||||
|
* match[in]: {_x, _y, _z}
|
||||||
|
* match[out]: {_x:y, _y:k, _z:3}
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xpath_tree_eq(xpath_tree *xt1,
|
||||||
|
xpath_tree *xt2,
|
||||||
|
cvec *match)
|
||||||
|
{
|
||||||
|
int retval = -1; /* not equal */
|
||||||
|
xpath_tree *xc1;
|
||||||
|
xpath_tree *xc2;
|
||||||
|
cg_var *cv;
|
||||||
|
|
||||||
|
/* node itself */
|
||||||
|
if (xt1->xs_type != xt2->xs_type)
|
||||||
|
goto neq;
|
||||||
|
if (xt1->xs_int != xt2->xs_int)
|
||||||
|
goto neq;
|
||||||
|
if (xt1->xs_double != xt2->xs_double)
|
||||||
|
goto neq;
|
||||||
|
if (clicon_strcmp(xt1->xs_s0, xt2->xs_s0)){
|
||||||
|
if (xt1->xs_s0 && xt2->xs_s0 &&
|
||||||
|
(cv = cvec_find(match, xt1->xs_s0)) != NULL){
|
||||||
|
cv_string_set(cv, xt2->xs_s0);
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
goto neq;
|
||||||
|
}
|
||||||
|
if (clicon_strcmp(xt1->xs_s1, xt2->xs_s1)){
|
||||||
|
if (xt1->xs_s1 && xt2->xs_s1 &&
|
||||||
|
(cv = cvec_find(match, xt1->xs_s1)) != NULL){
|
||||||
|
cv_string_set(cv, xt2->xs_s1);
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
goto neq;
|
||||||
|
}
|
||||||
|
xc1 = xt1->xs_c0;
|
||||||
|
xc2 = xt2->xs_c0;
|
||||||
|
if (xc1 == NULL && xc2 == NULL)
|
||||||
|
;
|
||||||
|
else{
|
||||||
|
if (xc1 == NULL || xc2 == NULL)
|
||||||
|
goto neq;
|
||||||
|
if (xpath_tree_eq(xc1, xc2, match))
|
||||||
|
goto neq;
|
||||||
|
}
|
||||||
|
xc1 = xt1->xs_c1;
|
||||||
|
xc2 = xt2->xs_c1;
|
||||||
|
if (xc1 == NULL && xc2 == NULL)
|
||||||
|
;
|
||||||
|
else{
|
||||||
|
if (xc1 == NULL || xc2 == NULL)
|
||||||
|
goto neq;
|
||||||
|
if (xpath_tree_eq(xc1, xc2, match))
|
||||||
|
goto neq;
|
||||||
|
}
|
||||||
|
ok:
|
||||||
|
retval = 0; /* equal */
|
||||||
|
neq:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Free a xpath_tree
|
/*! Free a xpath_tree
|
||||||
* @param[in] xs XPATH tree
|
* @param[in] xs XPATH tree
|
||||||
* @see xpath_parse creates a xpath_tree
|
* @see xpath_parse creates a xpath_tree
|
||||||
|
|
@ -387,12 +465,13 @@ xpath_parse(char *xpath,
|
||||||
* @param[in] xcur XML-tree where to search
|
* @param[in] xcur XML-tree where to search
|
||||||
* @param[in] nsc External XML namespace context, or NULL
|
* @param[in] nsc External XML namespace context, or NULL
|
||||||
* @param[in] xpath String with XPATH 1.0 syntax
|
* @param[in] xpath String with XPATH 1.0 syntax
|
||||||
|
* @param[in] localonly Skip prefix and namespace tests (non-standard)
|
||||||
* @param[out] xrp Return XPATH context
|
* @param[out] xrp Return XPATH context
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @code
|
* @code
|
||||||
* xp_ctx *xc = NULL;
|
* xp_ctx *xc = NULL;
|
||||||
* if (xpath_vec_ctx(x, NULL, xpath, &xc) < 0)
|
* if (xpath_vec_ctx(x, NULL, xpath, 0, &xc) < 0)
|
||||||
* err;
|
* err;
|
||||||
* if (xc)
|
* if (xc)
|
||||||
* ctx_free(xc);
|
* ctx_free(xc);
|
||||||
|
|
@ -402,6 +481,7 @@ int
|
||||||
xpath_vec_ctx(cxobj *xcur,
|
xpath_vec_ctx(cxobj *xcur,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
|
int localonly,
|
||||||
xp_ctx **xrp)
|
xp_ctx **xrp)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -415,7 +495,7 @@ xpath_vec_ctx(cxobj *xcur,
|
||||||
xc.xc_initial = xcur;
|
xc.xc_initial = xcur;
|
||||||
if (cxvec_append(xcur, &xc.xc_nodeset, &xc.xc_size) < 0)
|
if (cxvec_append(xcur, &xc.xc_nodeset, &xc.xc_size) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xp_eval(&xc, xptree, nsc, xrp) < 0)
|
if (xp_eval(&xc, xptree, nsc, localonly, xrp) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xc.xc_nodeset){
|
if (xc.xc_nodeset){
|
||||||
free(xc.xc_nodeset);
|
free(xc.xc_nodeset);
|
||||||
|
|
@ -475,7 +555,66 @@ xpath_first(cxobj *xcur,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if (xpath_vec_ctx(xcur, nsc, xpath, &xr) < 0)
|
if (xpath_vec_ctx(xcur, nsc, xpath, 0, &xr) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xr && xr->xc_type == XT_NODESET && xr->xc_size)
|
||||||
|
cx = xr->xc_nodeset[0];
|
||||||
|
done:
|
||||||
|
if (xr)
|
||||||
|
ctx_free(xr);
|
||||||
|
if (xpath)
|
||||||
|
free(xpath);
|
||||||
|
return cx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! XPath nodeset function where prefixes are skipped, only first matching is returned
|
||||||
|
*
|
||||||
|
* Reason for skipping prefix/namespace check may be with incomplete tree, for example.
|
||||||
|
* @param[in] xcur XML tree where to search
|
||||||
|
* @param[in] xpformat Format string for XPATH syntax
|
||||||
|
* @retval xml-tree XML tree of first match
|
||||||
|
* @retval NULL Error or not found
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* cxobj *x;
|
||||||
|
* cvec *nsc; // namespace context
|
||||||
|
* if ((x = xpath_first_localonly(xtop, "//symbol/foo")) != NULL) {
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* @note the returned pointer points into the original tree so should not be freed after use.
|
||||||
|
* @note return value does not see difference between error and not found
|
||||||
|
* @note Prefixes and namespaces are ignored so this is NOT according to standard
|
||||||
|
* @see also xpath_first.
|
||||||
|
*/
|
||||||
|
cxobj *
|
||||||
|
xpath_first_localonly(cxobj *xcur,
|
||||||
|
char *xpformat,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
cxobj *cx = NULL;
|
||||||
|
va_list ap;
|
||||||
|
size_t len;
|
||||||
|
char *xpath = NULL;
|
||||||
|
xp_ctx *xr = NULL;
|
||||||
|
|
||||||
|
va_start(ap, xpformat);
|
||||||
|
len = vsnprintf(NULL, 0, xpformat, ap);
|
||||||
|
va_end(ap);
|
||||||
|
/* allocate a message string exactly fitting the message length */
|
||||||
|
if ((xpath = malloc(len+1)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* second round: compute write message from reason and args */
|
||||||
|
va_start(ap, xpformat);
|
||||||
|
if (vsnprintf(xpath, len+1, xpformat, ap) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "vsnprintf");
|
||||||
|
va_end(ap);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
if (xpath_vec_ctx(xcur, NULL, xpath, 1, &xr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xr && xr->xc_type == XT_NODESET && xr->xc_size)
|
if (xr && xr->xc_type == XT_NODESET && xr->xc_size)
|
||||||
cx = xr->xc_nodeset[0];
|
cx = xr->xc_nodeset[0];
|
||||||
|
|
@ -541,7 +680,7 @@ xpath_vec(cxobj *xcur,
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
*vec=NULL;
|
*vec=NULL;
|
||||||
*veclen = 0;
|
*veclen = 0;
|
||||||
if (xpath_vec_ctx(xcur, nsc, xpath, &xr) < 0)
|
if (xpath_vec_ctx(xcur, nsc, xpath, 0, &xr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xr && xr->xc_type == XT_NODESET){
|
if (xr && xr->xc_type == XT_NODESET){
|
||||||
*vec = xr->xc_nodeset;
|
*vec = xr->xc_nodeset;
|
||||||
|
|
@ -616,7 +755,7 @@ xpath_vec_flag(cxobj *xcur,
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
*vec=NULL;
|
*vec=NULL;
|
||||||
*veclen = 0;
|
*veclen = 0;
|
||||||
if (xpath_vec_ctx(xcur, nsc, xpath, &xr) < 0)
|
if (xpath_vec_ctx(xcur, nsc, xpath, 0, &xr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xr && xr->xc_type == XT_NODESET){
|
if (xr && xr->xc_type == XT_NODESET){
|
||||||
for (i=0; i<xr->xc_size; i++){
|
for (i=0; i<xr->xc_size; i++){
|
||||||
|
|
@ -672,7 +811,7 @@ xpath_vec_bool(cxobj *xcur,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if (xpath_vec_ctx(xcur, nsc, xpath, &xr) < 0)
|
if (xpath_vec_ctx(xcur, nsc, xpath, 0, &xr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xr)
|
if (xr)
|
||||||
retval = ctx2boolean(xr);
|
retval = ctx2boolean(xr);
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <math.h> /* NaN */
|
#include <math.h> /* NaN */
|
||||||
|
|
@ -113,21 +112,28 @@ ctx_dup(xp_ctx *xc0)
|
||||||
return xc;
|
return xc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Print XPATH context */
|
/*! Print XPATH context to CLIgen buf
|
||||||
|
* @param[in] cb CLIgen buf to print to
|
||||||
|
* @param[in] xc XPATH evaluation context
|
||||||
|
* @param[in] ind Indentation margin
|
||||||
|
* @param[in] str Prefix string in printout
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
ctx_print(cbuf *cb,
|
ctx_print_cb(cbuf *cb,
|
||||||
int id,
|
xp_ctx *xc,
|
||||||
xp_ctx *xc,
|
int ind,
|
||||||
char *str)
|
char *str)
|
||||||
{
|
{
|
||||||
static int ident = 0;
|
static int indent = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (id<0)
|
if (ind<0)
|
||||||
ident += id;
|
indent += ind;
|
||||||
cprintf(cb, "%*s%s ", ident, "", str?str:"");
|
cprintf(cb, "%*s%s ", indent, "", str?str:"");
|
||||||
if (id>0)
|
if (ind>0)
|
||||||
ident += id;
|
indent += ind;
|
||||||
if (xc){
|
if (xc){
|
||||||
cprintf(cb, "%s: ", (char*)clicon_int2str(ctxmap, xc->xc_type));
|
cprintf(cb, "%s: ", (char*)clicon_int2str(ctxmap, xc->xc_type));
|
||||||
switch (xc->xc_type){
|
switch (xc->xc_type){
|
||||||
|
|
@ -149,6 +155,32 @@ ctx_print(cbuf *cb,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Print XPATH context
|
||||||
|
* @param[in] f File to print to
|
||||||
|
* @param[in] xc XPATH evaluation context
|
||||||
|
* @param[in] str Prefix string in printout
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ctx_print(FILE *f,
|
||||||
|
xp_ctx *xc,
|
||||||
|
char *str)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
ctx_print_cb(cb, xc, 0, str);
|
||||||
|
fprintf(f, "%s", cbuf_get(cb));
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Convert xpath context to boolean according to boolean() function in XPATH spec
|
/*! Convert xpath context to boolean according to boolean() function in XPATH spec
|
||||||
* @param[in] xc XPATH context
|
* @param[in] xc XPATH context
|
||||||
* @retval 0 False
|
* @retval 0 False
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@
|
||||||
#include "clixon_handle.h"
|
#include "clixon_handle.h"
|
||||||
#include "clixon_yang.h"
|
#include "clixon_yang.h"
|
||||||
#include "clixon_xml.h"
|
#include "clixon_xml.h"
|
||||||
|
#include "clixon_xml_sort.h"
|
||||||
#include "clixon_xml_nsctx.h"
|
#include "clixon_xml_nsctx.h"
|
||||||
#include "clixon_xpath_ctx.h"
|
#include "clixon_xpath_ctx.h"
|
||||||
#include "clixon_xpath.h"
|
#include "clixon_xpath.h"
|
||||||
|
|
@ -105,7 +106,7 @@ const map_str2int xpopmap[] = {
|
||||||
{NULL, -1}
|
{NULL, -1}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*! Eval an XPATH nodetest
|
||||||
* @retval -1 Error XXX: retval -1 not properly handled
|
* @retval -1 Error XXX: retval -1 not properly handled
|
||||||
* @retval 0 No match
|
* @retval 0 No match
|
||||||
* @retval 1 Match
|
* @retval 1 Match
|
||||||
|
|
@ -169,10 +170,37 @@ nodetest_eval_node(cxobj *x,
|
||||||
done: /* retval set in preceding statement */
|
done: /* retval set in preceding statement */
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Eval an XPATH nodetest but skip prefix and namespace tests
|
||||||
|
* This is NOT according to standard
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
nodetest_eval_node_localonly(cxobj *x,
|
||||||
|
xpath_tree *xs,
|
||||||
|
cvec *nsc)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *name1 = xml_name(x);
|
||||||
|
char *name2 = NULL;
|
||||||
|
|
||||||
|
/* Namespaces is s0, name is s1 */
|
||||||
|
if (strcmp(xs->xs_s1, "*")==0)
|
||||||
|
return 1;
|
||||||
|
name2 = xs->xs_s1;
|
||||||
|
/* Before going into namespaces, check name equality and filter out noteq */
|
||||||
|
if (strcmp(name1, name2) != 0){
|
||||||
|
retval = 0; /* no match */
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
done: /* retval set in preceding statement */
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Make a nodetest
|
/*! Make a nodetest
|
||||||
|
* @param[in] x XML node
|
||||||
* @param[in] xs XPATH stack of type XP_NODE or XP_NODE_FN
|
* @param[in] xs XPATH stack of type XP_NODE or XP_NODE_FN
|
||||||
* @param[in] nsc XML Namespace context
|
* @param[in] nsc XML Namespace context
|
||||||
|
* @param[in] localonly Skip prefix and namespace tests (non-standard)
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @retval 0 No match
|
* @retval 0 No match
|
||||||
* @retval 1 Match
|
* @retval 1 Match
|
||||||
|
|
@ -182,13 +210,18 @@ nodetest_eval_node(cxobj *x,
|
||||||
static int
|
static int
|
||||||
nodetest_eval(cxobj *x,
|
nodetest_eval(cxobj *x,
|
||||||
xpath_tree *xs,
|
xpath_tree *xs,
|
||||||
cvec *nsc)
|
cvec *nsc,
|
||||||
|
int localonly)
|
||||||
{
|
{
|
||||||
int retval = 0; /* NB: no match is default (not error) */
|
int retval = 0; /* NB: no match is default (not error) */
|
||||||
char *fn;
|
char *fn;
|
||||||
|
|
||||||
if (xs->xs_type == XP_NODE)
|
if (xs->xs_type == XP_NODE){
|
||||||
retval = nodetest_eval_node(x, xs, nsc);
|
if (localonly)
|
||||||
|
retval = nodetest_eval_node_localonly(x, xs, nsc);
|
||||||
|
else
|
||||||
|
retval = nodetest_eval_node(x, xs, nsc);
|
||||||
|
}
|
||||||
else if (xs->xs_type == XP_NODE_FN){
|
else if (xs->xs_type == XP_NODE_FN){
|
||||||
fn = xs->xs_s0;
|
fn = xs->xs_s0;
|
||||||
if (strcmp(fn, "node")==0)
|
if (strcmp(fn, "node")==0)
|
||||||
|
|
@ -206,6 +239,7 @@ nodetest_eval(cxobj *x,
|
||||||
* @param[in] node_type
|
* @param[in] node_type
|
||||||
* @param[in] flags
|
* @param[in] flags
|
||||||
* @param[in] nsc XML Namespace context
|
* @param[in] nsc XML Namespace context
|
||||||
|
* @param[in] localonly Skip prefix and namespace tests (non-standard)
|
||||||
* @param[out] vec0
|
* @param[out] vec0
|
||||||
* @param[out] vec0len
|
* @param[out] vec0len
|
||||||
*/
|
*/
|
||||||
|
|
@ -215,6 +249,7 @@ nodetest_recursive(cxobj *xn,
|
||||||
int node_type,
|
int node_type,
|
||||||
uint16_t flags,
|
uint16_t flags,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
|
int localonly,
|
||||||
cxobj ***vec0,
|
cxobj ***vec0,
|
||||||
size_t *vec0len)
|
size_t *vec0len)
|
||||||
{
|
{
|
||||||
|
|
@ -225,14 +260,14 @@ nodetest_recursive(cxobj *xn,
|
||||||
|
|
||||||
xsub = NULL;
|
xsub = NULL;
|
||||||
while ((xsub = xml_child_each(xn, xsub, node_type)) != NULL) {
|
while ((xsub = xml_child_each(xn, xsub, node_type)) != NULL) {
|
||||||
if (nodetest_eval(xsub, nodetest, nsc) == 1){
|
if (nodetest_eval(xsub, nodetest, nsc, localonly) == 1){
|
||||||
clicon_debug(2, "%s %x %x", __FUNCTION__, flags, xml_flag(xsub, flags));
|
clicon_debug(2, "%s %x %x", __FUNCTION__, flags, xml_flag(xsub, flags));
|
||||||
if (flags==0x0 || xml_flag(xsub, flags))
|
if (flags==0x0 || xml_flag(xsub, flags))
|
||||||
if (cxvec_append(xsub, &vec, &veclen) < 0)
|
if (cxvec_append(xsub, &vec, &veclen) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
// continue; /* Dont go deeper */
|
// continue; /* Dont go deeper */
|
||||||
}
|
}
|
||||||
if (nodetest_recursive(xsub, nodetest, node_type, flags, nsc, &vec, &veclen) < 0)
|
if (nodetest_recursive(xsub, nodetest, node_type, flags, nsc, localonly, &vec, &veclen) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -242,11 +277,113 @@ nodetest_recursive(cxobj *xn,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef XPATH_LIST_OPTIMIZE
|
||||||
|
/*! Pattern matching to find fastpath
|
||||||
|
*
|
||||||
|
* @param[in] xt XPath tree
|
||||||
|
* @param[in] xv XML base node
|
||||||
|
* @param[out] xp XML found node (retval == 1)
|
||||||
|
* @param[out] key
|
||||||
|
* @param[out] keyval
|
||||||
|
* @retval 0 Match
|
||||||
|
* @retval -1 No match
|
||||||
|
XPath:
|
||||||
|
y[k=3] # corresponds to: <name>[<keyname>=<keyval>]
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xpath_list_optimize(xpath_tree *xt,
|
||||||
|
cxobj *xv,
|
||||||
|
cxobj **xp)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
xpath_tree *xmtop = NULL; /* pattern match tree top */
|
||||||
|
xpath_tree *xm = NULL;
|
||||||
|
cg_var *cv0;
|
||||||
|
cg_var *cv1;
|
||||||
|
cg_var *cv2;
|
||||||
|
cvec *match = NULL;
|
||||||
|
char *name;
|
||||||
|
char *keyname;
|
||||||
|
char *keyval;
|
||||||
|
yang_stmt *yp;
|
||||||
|
yang_stmt *yc;
|
||||||
|
|
||||||
|
/* Parse */
|
||||||
|
if (xpath_parse("_x[_y='_z']", &xmtop) < 0) /* XXX: "y[k=3]" */
|
||||||
|
goto done;
|
||||||
|
/* Go down two steps */
|
||||||
|
if (xmtop && (xm = xmtop->xs_c0) && (xm = xm->xs_c0))
|
||||||
|
;
|
||||||
|
if (xm == NULL)
|
||||||
|
goto ok;
|
||||||
|
/* Create a cvec match vector and initialize variables */
|
||||||
|
if ((match = cvec_new(3)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cvec_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cv0 = cvec_i(match, 0);
|
||||||
|
cv_name_set(cv0, "_x");
|
||||||
|
cv_type_set(cv0, CGV_STRING);
|
||||||
|
cv1 = cvec_i(match, 1);
|
||||||
|
cv_name_set(cv1, "_y");
|
||||||
|
cv_type_set(cv1, CGV_STRING);
|
||||||
|
cv2 = cvec_i(match, 2);
|
||||||
|
cv_name_set(cv2, "_z");
|
||||||
|
cv_type_set(cv2, CGV_STRING);
|
||||||
|
|
||||||
|
/* Check if equal */
|
||||||
|
if (xpath_tree_eq(xm, xt, match) != 0)
|
||||||
|
goto ok; /* no match */
|
||||||
|
/* Extract variables XXX strdups */
|
||||||
|
name = cv_string_get(cv0);
|
||||||
|
keyname = cv_string_get(cv1);
|
||||||
|
keyval = cv_string_get(cv2);
|
||||||
|
assert(name && keyname && keyval);
|
||||||
|
/* Check yang and that only a list with key as index is a special case can do bin search */
|
||||||
|
if ((yp = xml_spec(xv)) == NULL)
|
||||||
|
goto ok;
|
||||||
|
if ((yc = yang_find(yp, 0, name)) == NULL)
|
||||||
|
goto ok;
|
||||||
|
if (yang_keyword_get(yc) != Y_LIST)
|
||||||
|
goto ok;
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
cvec *cvv = NULL;
|
||||||
|
if ((cvv = yang_cvec_get(yc)) == NULL)
|
||||||
|
goto ok;
|
||||||
|
if (cvec_len(cvv) != 1)
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
if ((ret = yang_key_match(yc, keyname)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret != 1)
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (xml_binsearch(xv, name, keyname, keyval, xp) < 0)
|
||||||
|
goto done;
|
||||||
|
retval = 1; /* match */
|
||||||
|
done:
|
||||||
|
if (match)
|
||||||
|
cvec_free(match);
|
||||||
|
if (xmtop)
|
||||||
|
xpath_tree_free(xmtop);
|
||||||
|
return retval;
|
||||||
|
ok: /* no match, not special case */
|
||||||
|
retval = 0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
#endif /* XPATH_LIST_OPTIMIZE */
|
||||||
|
|
||||||
/*! Evaluate xpath step rule of an XML tree
|
/*! Evaluate xpath step rule of an XML tree
|
||||||
*
|
*
|
||||||
* @param[in] xc0 Incoming context
|
* @param[in] xc0 Incoming context
|
||||||
* @param[in] xs XPATH node tree
|
* @param[in] xs XPATH node tree
|
||||||
* @param[in] nsc XML Namespace context
|
* @param[in] nsc XML Namespace context
|
||||||
|
* @param[in] localonly Skip prefix and namespace tests (non-standard)
|
||||||
* @param[out] xrp Resulting context
|
* @param[out] xrp Resulting context
|
||||||
*
|
*
|
||||||
* - A node test that is a QName is true if and only if the type of the node (see [5 Data Model])
|
* - A node test that is a QName is true if and only if the type of the node (see [5 Data Model])
|
||||||
|
|
@ -259,6 +396,7 @@ static int
|
||||||
xp_eval_step(xp_ctx *xc0,
|
xp_eval_step(xp_ctx *xc0,
|
||||||
xpath_tree *xs,
|
xpath_tree *xs,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
|
int localonly,
|
||||||
xp_ctx **xrp)
|
xp_ctx **xrp)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -270,6 +408,9 @@ xp_eval_step(xp_ctx *xc0,
|
||||||
size_t veclen = 0;
|
size_t veclen = 0;
|
||||||
xpath_tree *nodetest = xs->xs_c0;
|
xpath_tree *nodetest = xs->xs_c0;
|
||||||
xp_ctx *xc = NULL;
|
xp_ctx *xc = NULL;
|
||||||
|
#ifdef XPATH_LIST_OPTIMIZE
|
||||||
|
int ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Create new xc */
|
/* Create new xc */
|
||||||
if ((xc = ctx_dup(xc0)) == NULL)
|
if ((xc = ctx_dup(xc0)) == NULL)
|
||||||
|
|
@ -285,7 +426,7 @@ xp_eval_step(xp_ctx *xc0,
|
||||||
if (xc->xc_descendant){
|
if (xc->xc_descendant){
|
||||||
for (i=0; i<xc->xc_size; i++){
|
for (i=0; i<xc->xc_size; i++){
|
||||||
xv = xc->xc_nodeset[i];
|
xv = xc->xc_nodeset[i];
|
||||||
if (nodetest_recursive(xv, nodetest, CX_ELMNT, 0x0, nsc, &vec, &veclen) < 0)
|
if (nodetest_recursive(xv, nodetest, CX_ELMNT, 0x0, nsc, localonly, &vec, &veclen) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
xc->xc_descendant = 0;
|
xc->xc_descendant = 0;
|
||||||
|
|
@ -297,17 +438,33 @@ xp_eval_step(xp_ctx *xc0,
|
||||||
if (cxvec_append(xc->xc_initial, &vec, &veclen) < 0)
|
if (cxvec_append(xc->xc_initial, &vec, &veclen) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else for (i=0; i<xc->xc_size; i++){
|
else for (i=0; i<xc->xc_size; i++){
|
||||||
xv = xc->xc_nodeset[i];
|
xv = xc->xc_nodeset[i];
|
||||||
x = NULL;
|
x = NULL;
|
||||||
while ((x = xml_child_each(xv, x, CX_ELMNT)) != NULL) {
|
#ifdef XPATH_LIST_OPTIMIZE
|
||||||
/* xs->xs_c0 is nodetest */
|
/* Identify XPATH special cases and if match, use binary search.
|
||||||
if (nodetest == NULL || nodetest_eval(x, nodetest, nsc) == 1){
|
* it returns: -1 fatal error, quit
|
||||||
if (cxvec_append(x, &vec, &veclen) < 0)
|
* 0: not special case, do normal processing
|
||||||
goto done;
|
* 1: special case, use x (found if != NULL)
|
||||||
|
*/
|
||||||
|
if ((ret = xpath_list_optimize(xs, xv, &x)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 1){
|
||||||
|
fprintf(stderr, "XPATH_LIST_OPTIMIZE\n");
|
||||||
|
if (x)
|
||||||
|
if (cxvec_append(x, &vec, &veclen) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
while ((x = xml_child_each(xv, x, CX_ELMNT)) != NULL) {
|
||||||
|
/* xs->xs_c0 is nodetest */
|
||||||
|
if (nodetest == NULL || nodetest_eval(x, nodetest, nsc, localonly) == 1){
|
||||||
|
if (cxvec_append(x, &vec, &veclen) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ctx_nodeset_replace(xc, vec, veclen);
|
ctx_nodeset_replace(xc, vec, veclen);
|
||||||
break;
|
break;
|
||||||
|
|
@ -315,7 +472,7 @@ xp_eval_step(xp_ctx *xc0,
|
||||||
case A_DESCENDANT_OR_SELF:
|
case A_DESCENDANT_OR_SELF:
|
||||||
for (i=0; i<xc->xc_size; i++){
|
for (i=0; i<xc->xc_size; i++){
|
||||||
xv = xc->xc_nodeset[i];
|
xv = xc->xc_nodeset[i];
|
||||||
if (nodetest_recursive(xv, xs->xs_c0, CX_ELMNT, 0x0, nsc, &vec, &veclen) < 0)
|
if (nodetest_recursive(xv, xs->xs_c0, CX_ELMNT, 0x0, nsc, localonly, &vec, &veclen) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
ctx_nodeset_replace(xc, vec, veclen);
|
ctx_nodeset_replace(xc, vec, veclen);
|
||||||
|
|
@ -354,7 +511,7 @@ xp_eval_step(xp_ctx *xc0,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (xs->xs_c1){
|
if (xs->xs_c1){
|
||||||
if (xp_eval(xc, xs->xs_c1, nsc, xrp) < 0)
|
if (xp_eval(xc, xs->xs_c1, nsc, localonly, xrp) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
@ -375,6 +532,7 @@ xp_eval_step(xp_ctx *xc0,
|
||||||
* @param[in] xc Incoming context
|
* @param[in] xc Incoming context
|
||||||
* @param[in] xs XPATH node tree
|
* @param[in] xs XPATH node tree
|
||||||
* @param[in] nsc XML Namespace context
|
* @param[in] nsc XML Namespace context
|
||||||
|
* @param[in] localonly Skip prefix and namespace tests (non-standard)
|
||||||
* @param[out] xrp Resulting context
|
* @param[out] xrp Resulting context
|
||||||
*
|
*
|
||||||
* A predicate filters a node-set with respect to an axis to produce a new
|
* A predicate filters a node-set with respect to an axis to produce a new
|
||||||
|
|
@ -396,6 +554,7 @@ static int
|
||||||
xp_eval_predicate(xp_ctx *xc,
|
xp_eval_predicate(xp_ctx *xc,
|
||||||
xpath_tree *xs,
|
xpath_tree *xs,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
|
int localonly,
|
||||||
xp_ctx **xrp)
|
xp_ctx **xrp)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -411,7 +570,7 @@ xp_eval_predicate(xp_ctx *xc,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else{ /* eval previous predicates */
|
else{ /* eval previous predicates */
|
||||||
if (xp_eval(xc, xs->xs_c0, nsc, &xr0) < 0)
|
if (xp_eval(xc, xs->xs_c0, nsc, localonly, &xr0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xs->xs_c1){
|
if (xs->xs_c1){
|
||||||
|
|
@ -440,7 +599,7 @@ xp_eval_predicate(xp_ctx *xc,
|
||||||
* evaluated with that node as the context node */
|
* evaluated with that node as the context node */
|
||||||
if (cxvec_append(x, &xcc->xc_nodeset, &xcc->xc_size) < 0)
|
if (cxvec_append(x, &xcc->xc_nodeset, &xcc->xc_size) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xp_eval(xcc, xs->xs_c1, nsc, &xrc) < 0)
|
if (xp_eval(xcc, xs->xs_c1, nsc, localonly, &xrc) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xcc)
|
if (xcc)
|
||||||
ctx_free(xcc);
|
ctx_free(xcc);
|
||||||
|
|
@ -860,6 +1019,7 @@ xp_union(xp_ctx *xc1,
|
||||||
* @param[in] xc Incoming context
|
* @param[in] xc Incoming context
|
||||||
* @param[in] xs XPATH node tree
|
* @param[in] xs XPATH node tree
|
||||||
* @param[in] nsc XML Namespace context
|
* @param[in] nsc XML Namespace context
|
||||||
|
* @param[in] localonly Skip prefix and namespace tests (non-standard)
|
||||||
* @param[out] xrp Resulting context
|
* @param[out] xrp Resulting context
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
|
@ -868,6 +1028,7 @@ int
|
||||||
xp_eval(xp_ctx *xc,
|
xp_eval(xp_ctx *xc,
|
||||||
xpath_tree *xs,
|
xpath_tree *xs,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
|
int localonly,
|
||||||
xp_ctx **xrp)
|
xp_ctx **xrp)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -877,16 +1038,8 @@ xp_eval(xp_ctx *xc,
|
||||||
xp_ctx *xr2 = NULL;
|
xp_ctx *xr2 = NULL;
|
||||||
int use_xr0 = 0; /* In 2nd child use transitively result of 1st child */
|
int use_xr0 = 0; /* In 2nd child use transitively result of 1st child */
|
||||||
|
|
||||||
if (debug>1){
|
if (debug)
|
||||||
cbuf *cb;
|
ctx_print(stderr, xc, xpath_tree_int2str(xs->xs_type));
|
||||||
if ((cb = cbuf_new()) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
ctx_print(cb, +2, xc, xpath_tree_int2str(xs->xs_type));
|
|
||||||
clicon_debug(2, "%s", cbuf_get(cb));
|
|
||||||
cbuf_free(cb);
|
|
||||||
}
|
|
||||||
/* Pre-actions before check first child c0
|
/* Pre-actions before check first child c0
|
||||||
*/
|
*/
|
||||||
switch (xs->xs_type){
|
switch (xs->xs_type){
|
||||||
|
|
@ -908,12 +1061,12 @@ xp_eval(xp_ctx *xc,
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case XP_STEP: /* XP_NODE is first argument -not called explicitly */
|
case XP_STEP: /* XP_NODE is first argument -not called explicitly */
|
||||||
if (xp_eval_step(xc, xs, nsc, xrp) < 0)
|
if (xp_eval_step(xc, xs, nsc, localonly, xrp) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
break;
|
break;
|
||||||
case XP_PRED:
|
case XP_PRED:
|
||||||
if (xp_eval_predicate(xc, xs, nsc, xrp) < 0)
|
if (xp_eval_predicate(xc, xs, nsc, localonly, xrp) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
break;
|
break;
|
||||||
|
|
@ -923,7 +1076,7 @@ xp_eval(xp_ctx *xc,
|
||||||
/* Eval first child c0
|
/* Eval first child c0
|
||||||
*/
|
*/
|
||||||
if (xs->xs_c0){
|
if (xs->xs_c0){
|
||||||
if (xp_eval(xc, xs->xs_c0, nsc, &xr0) < 0)
|
if (xp_eval(xc, xs->xs_c0, nsc, localonly, &xr0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Actions between first and second child
|
/* Actions between first and second child
|
||||||
|
|
@ -1001,7 +1154,7 @@ xp_eval(xp_ctx *xc,
|
||||||
* Note, some operators like locationpath, need transitive context (use_xr0)
|
* Note, some operators like locationpath, need transitive context (use_xr0)
|
||||||
*/
|
*/
|
||||||
if (xs->xs_c1)
|
if (xs->xs_c1)
|
||||||
if (xp_eval(use_xr0?xr0:xc, xs->xs_c1, nsc, &xr1) < 0)
|
if (xp_eval(use_xr0?xr0:xc, xs->xs_c1, nsc, localonly, &xr1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Actions after second child
|
/* Actions after second child
|
||||||
*/
|
*/
|
||||||
|
|
@ -1041,16 +1194,8 @@ xp_eval(xp_ctx *xc,
|
||||||
xr0 = NULL;
|
xr0 = NULL;
|
||||||
}
|
}
|
||||||
ok:
|
ok:
|
||||||
if (debug){
|
if (debug)
|
||||||
cbuf *cb;
|
ctx_print(stderr, *xrp, xpath_tree_int2str(xs->xs_type));
|
||||||
if ((cb = cbuf_new()) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
ctx_print(cb, -2, *xrp, xpath_tree_int2str(xs->xs_type));
|
|
||||||
clicon_debug(2, "%s", cbuf_get(cb));
|
|
||||||
cbuf_free(cb);
|
|
||||||
}
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (xr2)
|
if (xr2)
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,6 @@ extern const map_str2int xpopmap[];
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
int xp_eval(xp_ctx *xc, xpath_tree *xs, cvec *nsc, xp_ctx **xrp);
|
int xp_eval(xp_ctx *xc, xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
|
||||||
|
|
||||||
#endif /* _CLIXON_XPATH_EVAL_H */
|
#endif /* _CLIXON_XPATH_EVAL_H */
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,10 @@ digit [0-9]
|
||||||
integer {digit}+
|
integer {digit}+
|
||||||
real ({digit}+[.]{digit}*)|({digit}*[.]{digit}+)
|
real ({digit}+[.]{digit}*)|({digit}*[.]{digit}+)
|
||||||
|
|
||||||
|
namestart [A-Z_a-z]
|
||||||
|
namechar [A-Z_a-z\-\.0-9]
|
||||||
|
ncname {namestart}{namechar}*
|
||||||
|
|
||||||
%x TOKEN
|
%x TOKEN
|
||||||
%s QLITERAL
|
%s QLITERAL
|
||||||
%s ALITERAL
|
%s ALITERAL
|
||||||
|
|
@ -141,9 +145,9 @@ real ({digit}+[.]{digit}*)|({digit}*[.]{digit}+)
|
||||||
<TOKEN>\" { BEGIN(QLITERAL); return QUOTE; }
|
<TOKEN>\" { BEGIN(QLITERAL); return QUOTE; }
|
||||||
<TOKEN>\' { BEGIN(ALITERAL); return APOST; }
|
<TOKEN>\' { BEGIN(ALITERAL); return APOST; }
|
||||||
<TOKEN>\-?({integer}|{real}) { clixon_xpath_parselval.string = strdup(yytext); return NUMBER; }
|
<TOKEN>\-?({integer}|{real}) { clixon_xpath_parselval.string = strdup(yytext); return NUMBER; }
|
||||||
<TOKEN>[0-9A-Za-z_\-]+ { clixon_xpath_parselval.string = strdup(yytext);
|
<TOKEN>{ncname} { clixon_xpath_parselval.string = strdup(yytext);
|
||||||
return NAME; /* rather be catch-all */
|
return NAME; /* rather be catch-all */
|
||||||
}
|
}
|
||||||
<TOKEN>. { fprintf(stderr,"LEXICAL ERROR\n"); return -1; }
|
<TOKEN>. { fprintf(stderr,"LEXICAL ERROR\n"); return -1; }
|
||||||
|
|
||||||
<QLITERAL>\" { BEGIN(TOKEN); return QUOTE; }
|
<QLITERAL>\" { BEGIN(TOKEN); return QUOTE; }
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Test matrching of Unix peer credentials with NACM users
|
# Test matching of Unix peer credentials with NACM users
|
||||||
# Use raw unix socket instead of clients (cli/netconf/restconf) since they do
|
# Use raw unix socket instead of clients (cli/netconf/restconf) since they do
|
||||||
# magic things with the username and here it needs to be handled explicitly.
|
# magic things with the username and here it needs to be handled explicitly.
|
||||||
# test matrix:
|
# test matrix:
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,9 @@ fi
|
||||||
new "xml simple CDATA"
|
new "xml simple CDATA"
|
||||||
expecteofx "$clixon_util_xml -o" 0 '<a><![CDATA[a text]]></a>' '<a><![CDATA[a text]]></a>'
|
expecteofx "$clixon_util_xml -o" 0 '<a><![CDATA[a text]]></a>' '<a><![CDATA[a text]]></a>'
|
||||||
|
|
||||||
|
new "xml CDATA right square bracket: ]"
|
||||||
|
expecteofx "$clixon_util_xml -o" 0 "<a><![CDATA[]]]></a>" "<a><![CDATA[]]]></a>"
|
||||||
|
|
||||||
new "xml simple CDATA to json"
|
new "xml simple CDATA to json"
|
||||||
expecteofx "$clixon_util_xml -o -j" 0 '<a><![CDATA[a text]]></a>' '{"a":"a text"}'
|
expecteofx "$clixon_util_xml -o -j" 0 '<a><![CDATA[a text]]></a>' '{"a":"a text"}'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Test: XPATH tests
|
# XPATH tests
|
||||||
#PROG="valgrind --leak-check=full --show-leak-kinds=all ../util/clixon_util_xpath"
|
|
||||||
|
|
||||||
# Magic line must be first in script (see README.md)
|
# Magic line must be first in script (see README.md)
|
||||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
@ -12,11 +11,11 @@ xml=$dir/xml.xml
|
||||||
xml2=$dir/xml2.xml
|
xml2=$dir/xml2.xml
|
||||||
xml3=$dir/xml3.xml
|
xml3=$dir/xml3.xml
|
||||||
ydir=$dir/yang
|
ydir=$dir/yang
|
||||||
|
|
||||||
if [ ! -d $ydir ]; then
|
if [ ! -d $ydir ]; then
|
||||||
mkdir $ydir
|
mkdir $ydir
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
cat <<EOF > $xml
|
cat <<EOF > $xml
|
||||||
<aaa>
|
<aaa>
|
||||||
<bbb x="hello">
|
<bbb x="hello">
|
||||||
|
|
@ -82,6 +81,7 @@ cat <<EOF > $xml3
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
new "xpath /"
|
new "xpath /"
|
||||||
|
echo "$clixon_util_xpath -f $xml -p /"
|
||||||
expecteof "$clixon_util_xpath -f $xml -p /" 0 "" "^nodeset:0:<aaa><bbb x=\"hello\"><ccc>42</ccc></bbb><bbb x=\"bye\"><ccc>99</ccc></bbb><ddd><ccc>22</ccc></ddd></aaa>$"
|
expecteof "$clixon_util_xpath -f $xml -p /" 0 "" "^nodeset:0:<aaa><bbb x=\"hello\"><ccc>42</ccc></bbb><bbb x=\"bye\"><ccc>99</ccc></bbb><ddd><ccc>22</ccc></ddd></aaa>$"
|
||||||
|
|
||||||
new "xpath /aaa"
|
new "xpath /aaa"
|
||||||
|
|
@ -208,54 +208,4 @@ expecteof "$clixon_util_xpath -f $xml3 -p bbb[ccc='fie']" 0 "" "^nodeset:$"
|
||||||
new "xpath derived-from-or-self"
|
new "xpath derived-from-or-self"
|
||||||
expecteof "$clixon_util_xpath -f $xml3 -p 'derived-from-or-self(../../change-operation,modify)'" 0 "" "derived-from-or-self"
|
expecteof "$clixon_util_xpath -f $xml3 -p 'derived-from-or-self(../../change-operation,modify)'" 0 "" "derived-from-or-self"
|
||||||
|
|
||||||
# canonical namespace xpath tests
|
|
||||||
# need yang modules
|
|
||||||
cat <<EOF > $ydir/a.yang
|
|
||||||
module a{
|
|
||||||
namespace "urn:example:a";
|
|
||||||
prefix a;
|
|
||||||
container x{
|
|
||||||
leaf xa{
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
cat <<EOF > $ydir/b.yang
|
|
||||||
module b{
|
|
||||||
namespace "urn:example:b";
|
|
||||||
prefix b;
|
|
||||||
container y{
|
|
||||||
leaf ya{
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
new "xpath canonical form (already canonical)"
|
|
||||||
expectpart "$($clixon_util_xpath -c -y $ydir -p /a:x/b:y -n a:urn:example:a -n b:urn:example:b)" 0 '/a:x/b:y' '0 : a = "urn:example:a"' '1 : b = "urn:example:b"'
|
|
||||||
|
|
||||||
new "xpath canonical form (default)"
|
|
||||||
expectpart "$($clixon_util_xpath -c -y $ydir -p /x/b:y -n null:urn:example:a -n b:urn:example:b)" 0 '/a:x/b:y' '0 : a = "urn:example:a"' '1 : b = "urn:example:b"'
|
|
||||||
|
|
||||||
new "xpath canonical form (other)"
|
|
||||||
expectpart "$($clixon_util_xpath -c -y $ydir -p /i:x/j:y -n i:urn:example:a -n j:urn:example:b)" 0 '/a:x/b:y' '0 : a = "urn:example:a"' '1 : b = "urn:example:b"'
|
|
||||||
|
|
||||||
new "xpath canonical form predicate 1"
|
|
||||||
expectpart "$($clixon_util_xpath -c -y $ydir -p "/i:x[j:y='e1']" -n i:urn:example:a -n j:urn:example:b)" 0 "/a:x\[b:y='e1'\]" '0 : a = "urn:example:a"' '1 : b = "urn:example:b"'
|
|
||||||
|
|
||||||
new "xpath canonical form predicate self"
|
|
||||||
expectpart "$($clixon_util_xpath -c -y $ydir -p "/i:x[.='42']" -n i:urn:example:a -n j:urn:example:b)" 0 "/a:x\[.='42'\]" '0 : a = "urn:example:a"'
|
|
||||||
|
|
||||||
new "xpath canonical form descendants"
|
|
||||||
expectpart "$($clixon_util_xpath -c -y $ydir -p "//x[.='42']" -n null:urn:example:a -n j:urn:example:b)" 0 "//a:x\[.='42'\]" '0 : a = "urn:example:a"'
|
|
||||||
|
|
||||||
new "xpath canonical form (no default should fail)"
|
|
||||||
expectpart "$($clixon_util_xpath -c -y $ydir -p /x/j:y -n i:urn:example:a -n j:urn:example:b)" 255
|
|
||||||
|
|
||||||
new "xpath canonical form (wrong namespace should fail)"
|
|
||||||
expectpart "$($clixon_util_xpath -c -y $ydir -p /i:x/j:y -n i:urn:example:c -n j:urn:example:b)" 255
|
|
||||||
|
|
||||||
rm -rf $dir
|
rm -rf $dir
|
||||||
|
|
|
||||||
65
test/test_xpath_canonical.sh
Executable file
65
test/test_xpath_canonical.sh
Executable file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Test xpath canonical namespace context form
|
||||||
|
|
||||||
|
# Magic line must be first in script (see README.md)
|
||||||
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
||||||
|
: ${clixon_util_xpath:=clixon_util_xpath}
|
||||||
|
|
||||||
|
ydir=$dir/yang
|
||||||
|
|
||||||
|
if [ ! -d $ydir ]; then
|
||||||
|
mkdir $ydir
|
||||||
|
fi
|
||||||
|
|
||||||
|
# canonical namespace xpath tests
|
||||||
|
# need yang modules
|
||||||
|
cat <<EOF > $ydir/a.yang
|
||||||
|
module a{
|
||||||
|
namespace "urn:example:a";
|
||||||
|
prefix a;
|
||||||
|
container x{
|
||||||
|
leaf xa{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat <<EOF > $ydir/b.yang
|
||||||
|
module b{
|
||||||
|
namespace "urn:example:b";
|
||||||
|
prefix b;
|
||||||
|
container y{
|
||||||
|
leaf ya{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "xpath canonical form (already canonical)"
|
||||||
|
expectpart "$($clixon_util_xpath -c -y $ydir -p /a:x/b:y -n a:urn:example:a -n b:urn:example:b)" 0 '/a:x/b:y' '0 : a = "urn:example:a"' '1 : b = "urn:example:b"'
|
||||||
|
|
||||||
|
new "xpath canonical form (default)"
|
||||||
|
expectpart "$($clixon_util_xpath -c -y $ydir -p /x/b:y -n null:urn:example:a -n b:urn:example:b)" 0 '/a:x/b:y' '0 : a = "urn:example:a"' '1 : b = "urn:example:b"'
|
||||||
|
|
||||||
|
new "xpath canonical form (other)"
|
||||||
|
expectpart "$($clixon_util_xpath -c -y $ydir -p /i:x/j:y -n i:urn:example:a -n j:urn:example:b)" 0 '/a:x/b:y' '0 : a = "urn:example:a"' '1 : b = "urn:example:b"'
|
||||||
|
|
||||||
|
new "xpath canonical form predicate 1"
|
||||||
|
expectpart "$($clixon_util_xpath -c -y $ydir -p "/i:x[j:y='e1']" -n i:urn:example:a -n j:urn:example:b)" 0 "/a:x\[b:y='e1'\]" '0 : a = "urn:example:a"' '1 : b = "urn:example:b"'
|
||||||
|
|
||||||
|
new "xpath canonical form predicate self"
|
||||||
|
expectpart "$($clixon_util_xpath -c -y $ydir -p "/i:x[.='42']" -n i:urn:example:a -n j:urn:example:b)" 0 "/a:x\[.='42'\]" '0 : a = "urn:example:a"'
|
||||||
|
|
||||||
|
new "xpath canonical form descendants"
|
||||||
|
expectpart "$($clixon_util_xpath -c -y $ydir -p "//x[.='42']" -n null:urn:example:a -n j:urn:example:b)" 0 "//a:x\[.='42'\]" '0 : a = "urn:example:a"'
|
||||||
|
|
||||||
|
new "xpath canonical form (no default should fail)"
|
||||||
|
expectpart "$($clixon_util_xpath -c -y $ydir -p /x/j:y -n i:urn:example:a -n j:urn:example:b)" 255
|
||||||
|
|
||||||
|
new "xpath canonical form (wrong namespace should fail)"
|
||||||
|
expectpart "$($clixon_util_xpath -c -y $ydir -p /i:x/j:y -n i:urn:example:c -n j:urn:example:b)" 255
|
||||||
|
|
||||||
|
rm -rf $dir
|
||||||
|
|
@ -45,7 +45,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
@ -196,7 +195,7 @@ main(int argc,
|
||||||
if ((ret = json_parse_file(fd, yspec, &xt, &xerr)) < 0)
|
if ((ret = json_parse_file(fd, yspec, &xt, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
clicon_rpc_generate_error("util_xml", xerr);
|
clicon_rpc_generate_error(xerr, "util_xml", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ See https://www.w3.org/TR/xpath/
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
@ -318,7 +317,7 @@ main(int argc,
|
||||||
x = x0;
|
x = x0;
|
||||||
|
|
||||||
/* Parse XPATH (use nsc == NULL to indicate dont use) */
|
/* Parse XPATH (use nsc == NULL to indicate dont use) */
|
||||||
if (xpath_vec_ctx(x, nsc, xpath, &xc) < 0)
|
if (xpath_vec_ctx(x, nsc, xpath, 0, &xc) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
/* Print results */
|
/* Print results */
|
||||||
cb = cbuf_new();
|
cb = cbuf_new();
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue