xmldb api cleanup
This commit is contained in:
parent
caccfe8f2d
commit
cf3cf351c8
16 changed files with 177 additions and 361 deletions
|
|
@ -486,7 +486,7 @@ from_client_load(clicon_handle h,
|
||||||
send_msg_err(s, OE_UNIX, 0, "rm %s %s", filename, strerror(errno));
|
send_msg_err(s, OE_UNIX, 0, "rm %s %s", filename, strerror(errno));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (db_init(dbname) < 0)
|
if (xmldb_init(dbname) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -559,7 +559,7 @@ from_client_initdb(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (db_init(filename1) < 0)
|
if (xmldb_init(filename1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Change mode if shared candidate. XXXX full rights for all is no good */
|
/* Change mode if shared candidate. XXXX full rights for all is no good */
|
||||||
if (strcmp(filename1, candidate_db) == 0)
|
if (strcmp(filename1, candidate_db) == 0)
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ rundb_init(clicon_handle h, char *running_db)
|
||||||
clicon_err(OE_UNIX, errno, "unlink");
|
clicon_err(OE_UNIX, errno, "unlink");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (db_init(running_db) < 0)
|
if (xmldb_init(running_db) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -404,9 +404,6 @@ cli_validate(clicon_handle h, cvec *vars, cg_var *arg)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! Completion callback primarily intended for automatically generated data model
|
/*! Completion callback primarily intended for automatically generated data model
|
||||||
*
|
*
|
||||||
* Returns an expand-type list of commands as used by cligen 'expand'
|
* Returns an expand-type list of commands as used by cligen 'expand'
|
||||||
|
|
@ -434,7 +431,7 @@ cli_validate(clicon_handle h, cvec *vars, cg_var *arg)
|
||||||
* Assume callback given in a cligen spec: a <x:int expand_dbvar_auto("arg")
|
* Assume callback given in a cligen spec: a <x:int expand_dbvar_auto("arg")
|
||||||
* @param[in] h clicon handle
|
* @param[in] h clicon handle
|
||||||
* @param[in] name Name of this function (eg "expand_dbvar-auto")
|
* @param[in] name Name of this function (eg "expand_dbvar-auto")
|
||||||
* @param[in] cvec The command so far. Eg: cvec [0]:"a 5 b"; [1]: x=5;
|
* @param[in] cvv The command so far. Eg: cvec [0]:"a 5 b"; [1]: x=5;
|
||||||
* @param[in] arg Argument given at the callback "<db> <xmlkeyfmt>"
|
* @param[in] arg Argument given at the callback "<db> <xmlkeyfmt>"
|
||||||
* @param[out] len len of return commands & helptxt
|
* @param[out] len len of return commands & helptxt
|
||||||
* @param[out] commands vector of function pointers to callback functions
|
* @param[out] commands vector of function pointers to callback functions
|
||||||
|
|
@ -459,10 +456,11 @@ expand_dbvar_dbxml(void *h,
|
||||||
char *dbstr;
|
char *dbstr;
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
char *xk = NULL;
|
char *xk = NULL;
|
||||||
|
cxobj **xvec = NULL;
|
||||||
int i;
|
int i;
|
||||||
int i0;
|
int i0;
|
||||||
struct db_pair *pairs;
|
size_t xlen;
|
||||||
int npairs;
|
yang_spec *yspec;
|
||||||
|
|
||||||
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
|
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
|
||||||
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
||||||
|
|
@ -488,23 +486,28 @@ expand_dbvar_dbxml(void *h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
xkfmt = vec[1];
|
xkfmt = vec[1];
|
||||||
/* xkfmt = "/test/kalle/%s/lasse" --> "^/test/kalle/.* /lasse$" */
|
/* xkfmt = /interface/%s/address/%s
|
||||||
if (xmlkeyfmt2key2(xkfmt, cvv, &xk) < 0)
|
--> ^/interface/eth0/address/.*$
|
||||||
goto done;
|
--> /interface/[name=eth0]/address
|
||||||
if ((npairs = db_regexp(dbname, xk, __FUNCTION__, &pairs, 0)) < 0)
|
*/
|
||||||
|
if (xmlkeyfmt2xpath(xkfmt, cvv, &xk) < 0)
|
||||||
|
goto done;
|
||||||
|
yspec = clicon_dbspec_yang(h);
|
||||||
|
if (xmldb_get_vec(dbname, xk, yspec, &xt, &xvec, &xlen) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
i0 = *nr;
|
i0 = *nr;
|
||||||
*nr += npairs;
|
*nr += xlen;
|
||||||
if ((*commands = realloc(*commands, sizeof(char *) * (*nr))) == NULL) {
|
if ((*commands = realloc(*commands, sizeof(char *) * (*nr))) == NULL) {
|
||||||
clicon_err(OE_UNDEF, errno, "realloc: %s", strerror (errno));
|
clicon_err(OE_UNDEF, errno, "realloc: %s", strerror (errno));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
for (i = 0; i < npairs; i++)
|
for (i = 0; i < xlen; i++)
|
||||||
(*commands)[i0+i] = strdup(pairs[i].dp_val);
|
(*commands)[i0+i] = strdup(xml_body(xvec[i]));
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
unchunk_group(__FUNCTION__);
|
unchunk_group(__FUNCTION__);
|
||||||
|
if (xvec)
|
||||||
|
free(xvec);
|
||||||
if (xt)
|
if (xt)
|
||||||
xml_free(xt);
|
xml_free(xt);
|
||||||
if (xk)
|
if (xk)
|
||||||
|
|
@ -512,221 +515,6 @@ expand_dbvar_dbxml(void *h,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
}
|
}
|
||||||
#ifdef NOTUSED
|
|
||||||
|
|
||||||
/*! Expand based on database key and variable value (of that key)
|
|
||||||
*
|
|
||||||
* Return an expand-type list of commands as used by cligen 'expand'
|
|
||||||
* functionality.
|
|
||||||
* arg is a string: "<dbname> <keypattern> <variable>".
|
|
||||||
* <dbname> is either running or candidate
|
|
||||||
* <keypattern> matches a set of database keys
|
|
||||||
* <variable> is name of a variable occuring in the cli command string
|
|
||||||
* Example: "candidate ^Create.*$" GroupName"
|
|
||||||
* (See also expand_db_variable().
|
|
||||||
*
|
|
||||||
* Assume callback given in a cligen spec: a <x:int expand_dbvar_auto("arg")
|
|
||||||
* @param[in] h clicon handle
|
|
||||||
* @param[in] name Name of this function (eg "expand_dbvar")
|
|
||||||
* @param[in] vars The command so far. Eg: cvec [0]:"a 5 b"; [1]: x=5;
|
|
||||||
* @param[in] arg Argument given at the callback ("arg")
|
|
||||||
* @param[out] nr len of return commands & helptxt
|
|
||||||
* @param[out] commands vector of function pointers to callback functions
|
|
||||||
* @param[out] helptexts vector of pointers to helptexts
|
|
||||||
* @see expand_db_variable But this function is more generic and can be called
|
|
||||||
* as cligen callback
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
expand_dbvar(void *h,
|
|
||||||
char *name,
|
|
||||||
cvec *vars,
|
|
||||||
cg_var *arg,
|
|
||||||
int *nr,
|
|
||||||
char ***commands,
|
|
||||||
char ***helptexts)
|
|
||||||
{
|
|
||||||
char *dbname;
|
|
||||||
int nvec;
|
|
||||||
char **vec = NULL;
|
|
||||||
int retval = -1;
|
|
||||||
char *str;
|
|
||||||
char *dbstr, *keystr, *varstr;
|
|
||||||
|
|
||||||
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((vec = clicon_strsplit(cv_string_get(arg), " ", &nvec, __FUNCTION__)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (nvec != 3){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "format error \"%s\" - expected <dbname> <key> <variable>",
|
|
||||||
str);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
dbstr = vec[0];
|
|
||||||
keystr = vec[1];
|
|
||||||
varstr = vec[2];
|
|
||||||
if (strcmp(dbstr, "running") == 0)
|
|
||||||
dbname = clicon_running_db(h);
|
|
||||||
else
|
|
||||||
if (strcmp(dbstr, "candidate") == 0)
|
|
||||||
dbname = clicon_candidate_db(h);
|
|
||||||
else{
|
|
||||||
clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (dbname == NULL){
|
|
||||||
clicon_err(OE_FATAL, 0, "dbname not set");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((retval = expand_db_variable(h, dbname, keystr, varstr, nr, commands)) < 0)
|
|
||||||
goto done;
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
unchunk_group(__FUNCTION__);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Expand database variable
|
|
||||||
* Given a database, a basekey (pattern) and a variable, return an expand-type
|
|
||||||
* list of commands as used by cligen 'expand' functionality.
|
|
||||||
* @see expand_dbvar
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
expand_db_variable(clicon_handle h,
|
|
||||||
char *dbname,
|
|
||||||
char *basekey,
|
|
||||||
char *variable,
|
|
||||||
int *nr,
|
|
||||||
char ***commands)
|
|
||||||
{
|
|
||||||
char *key;
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
int retval = -1;
|
|
||||||
cvec *cvv;
|
|
||||||
cg_var *cv = NULL;
|
|
||||||
char **tmp;
|
|
||||||
char *val = NULL;
|
|
||||||
cvec **cvvp = NULL;
|
|
||||||
size_t len = 0;
|
|
||||||
|
|
||||||
/* adhoc to detect regexp keys. If so, dont call db_gen_rxkey */
|
|
||||||
if (index(basekey, '^') == NULL){
|
|
||||||
if ((key = db_gen_rxkey(basekey, __FUNCTION__)) == NULL)
|
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
key = chunkdup(basekey, strlen(basekey)+1, __FUNCTION__);
|
|
||||||
|
|
||||||
if (clicon_dbitems(dbname, key, &cvvp, &len) < 0)
|
|
||||||
goto quit;
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
cvv = cvvp[i];
|
|
||||||
cv = NULL;
|
|
||||||
while ((cv = cvec_each(cvv, cv)) != NULL) {
|
|
||||||
if (strcmp(cv_name_get(cv), variable) != 0)
|
|
||||||
continue;
|
|
||||||
if ((val = cv2str_dup(cv)) == NULL)
|
|
||||||
goto quit;
|
|
||||||
/* Check if value already in vector? No duplicates */
|
|
||||||
for (j=0; j<*nr; j++)
|
|
||||||
if (strcmp(val, (*commands)[j]) == 0)
|
|
||||||
break;
|
|
||||||
if (j<*nr){
|
|
||||||
free(val);
|
|
||||||
val = NULL;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ((tmp = realloc(*commands, sizeof(char *) * ((*nr)+1))) == NULL) {
|
|
||||||
clicon_err(OE_UNDEF, errno, "realloc: %s", strerror (errno));
|
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
*commands = tmp;
|
|
||||||
(*commands)[*nr] = val;
|
|
||||||
val = NULL;
|
|
||||||
(*nr)++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
retval = 0;
|
|
||||||
quit:
|
|
||||||
if (cvvp)
|
|
||||||
clicon_dbitems_free(cvvp, len);
|
|
||||||
unchunk_group(__FUNCTION__);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Pattern match in candidate_db
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
expand_db_symbol(clicon_handle h,
|
|
||||||
char *symbol,
|
|
||||||
int element,
|
|
||||||
int *nr,
|
|
||||||
char ***commands)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
char **tmp;
|
|
||||||
cvec **cvvp = NULL;
|
|
||||||
cvec *cvv;
|
|
||||||
size_t len = 0;
|
|
||||||
int i;
|
|
||||||
char *key;
|
|
||||||
int nvec;
|
|
||||||
int n;
|
|
||||||
char **vec = NULL;
|
|
||||||
char str[128];
|
|
||||||
char *dbname;
|
|
||||||
|
|
||||||
if ((dbname = clicon_running_db(h)) == NULL){
|
|
||||||
clicon_err(OE_FATAL, 0, "running db not set");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
snprintf(str, sizeof(str), "^%s\\..", symbol);
|
|
||||||
if (clicon_rpc_dbitems(h, dbname, str, NULL, NULL, &cvvp, &len) < 0)
|
|
||||||
goto done;
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
cvv = cvvp[i];
|
|
||||||
key = cvec_name_get(cvv);
|
|
||||||
if ((vec = clicon_strsplit(key, ".", &nvec, __FUNCTION__)) == NULL){
|
|
||||||
clicon_err(OE_UNDEF, errno, "clicon_strsplit");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* Check if already exists */
|
|
||||||
for (n=0; n<*nr; n++)
|
|
||||||
if (strcmp((*commands)[n], vec[element]) == 0)
|
|
||||||
break; /* Already exists */
|
|
||||||
if (n<*nr)
|
|
||||||
continue;
|
|
||||||
/* Allocate new pointer */
|
|
||||||
if ((tmp = realloc(*commands, sizeof(char *) * ((*nr)+1))) == NULL) {
|
|
||||||
clicon_err(OE_UNDEF, errno, "realloc: %s", strerror (errno));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
*commands = tmp;
|
|
||||||
/* Duplicate string */
|
|
||||||
if (((*commands)[*nr] = strdup(vec[element])) == NULL) {
|
|
||||||
clicon_err(OE_UNDEF, errno, "strdup: %s", strerror (errno));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
(*nr)++;
|
|
||||||
}
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
unchunk_group(__FUNCTION__) ;
|
|
||||||
if (cvvp)
|
|
||||||
clicon_dbitems_free(cvvp, len);
|
|
||||||
if (retval < 0 && *commands){
|
|
||||||
while ((*nr) >= 0)
|
|
||||||
free((*commands)[(*nr)--]);
|
|
||||||
free (*commands);
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
#endif /* NOTUSED */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* expand_dir
|
* expand_dir
|
||||||
|
|
@ -1165,7 +953,7 @@ load_config_file(clicon_handle h, cvec *cvv, cg_var *arg)
|
||||||
clicon_err(OE_UNIX, 0, "rm %s %s", filename, strerror(errno));
|
clicon_err(OE_UNIX, 0, "rm %s %s", filename, strerror(errno));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (db_init(dbname) < 0)
|
if (xmldb_init(dbname) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((fd = open(filename, O_RDONLY)) < 0){
|
if ((fd = open(filename, O_RDONLY)) < 0){
|
||||||
|
|
@ -1316,7 +1104,7 @@ delete_all(clicon_handle h, cvec *cvv, cg_var *arg)
|
||||||
clicon_err(OE_FATAL, errno, "unlink(%s)", dbname);
|
clicon_err(OE_FATAL, errno, "unlink(%s)", dbname);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (db_init(dbname) < 0)
|
if (xmldb_init(dbname) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@
|
||||||
#define GENERATE_CALLBACK "cli_set"
|
#define GENERATE_CALLBACK "cli_set"
|
||||||
|
|
||||||
/* variable expand function */
|
/* variable expand function */
|
||||||
#define GENERATE_EXPAND_LVEC "expand_dbvar_auto"
|
|
||||||
#define GENERATE_EXPAND_XMLDB "expand_dbvar_dbxml"
|
#define GENERATE_EXPAND_XMLDB "expand_dbvar_dbxml"
|
||||||
|
|
||||||
/*=====================================================================
|
/*=====================================================================
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* Command line options to be passed to getopt(3) */
|
||||||
#define CLI_OPTS "hD:f:F:1u:d:m:cP:qpGLl:"
|
#define CLI_OPTS "hD:f:F:1u:d:m:cP:qpGLl:"
|
||||||
|
|
||||||
|
/*! terminate cli application */
|
||||||
static int
|
static int
|
||||||
cli_terminate(clicon_handle h)
|
cli_terminate(clicon_handle h)
|
||||||
{
|
{
|
||||||
|
|
@ -71,9 +72,7 @@ cli_terminate(clicon_handle h)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*! Unlink pidfile and quit
|
||||||
* cli_sig_term
|
|
||||||
* Unlink pidfile and quit
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
cli_sig_term(int arg)
|
cli_sig_term(int arg)
|
||||||
|
|
@ -83,8 +82,7 @@ cli_sig_term(int arg)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*! Setup signal handlers
|
||||||
* Setup signal handlers
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
cli_signal_init (clicon_handle h)
|
cli_signal_init (clicon_handle h)
|
||||||
|
|
@ -93,6 +91,9 @@ cli_signal_init (clicon_handle h)
|
||||||
set_signal(SIGTERM, cli_sig_term, NULL);
|
set_signal(SIGTERM, cli_sig_term, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Interactive CLI command loop
|
||||||
|
* @see cligen_loop
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
cli_interactive(clicon_handle h)
|
cli_interactive(clicon_handle h)
|
||||||
{
|
{
|
||||||
|
|
@ -366,7 +367,7 @@ main(int argc, char **argv)
|
||||||
clicon_option_str_set(h, "CLICON_CANDIDATE_DB", private_db);
|
clicon_option_str_set(h, "CLICON_CANDIDATE_DB", private_db);
|
||||||
|
|
||||||
if (!cli_send2backend(h))
|
if (!cli_send2backend(h))
|
||||||
if (db_init(running_db) < 0){
|
if (xmldb_init(running_db) < 0){
|
||||||
fprintf (stderr, "FATAL: Could not init running_db. (Run as root?)\n");
|
fprintf (stderr, "FATAL: Could not init running_db. (Run as root?)\n");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,13 +86,9 @@ int cli_start_shell(clicon_handle h, cvec *vars, cg_var *argv);
|
||||||
int cli_quit(clicon_handle h, cvec *vars, cg_var *arg);
|
int cli_quit(clicon_handle h, cvec *vars, cg_var *arg);
|
||||||
int cli_commit(clicon_handle h, cvec *vars, cg_var *arg);
|
int cli_commit(clicon_handle h, cvec *vars, cg_var *arg);
|
||||||
int cli_validate(clicon_handle h, cvec *vars, cg_var *arg);
|
int cli_validate(clicon_handle h, cvec *vars, cg_var *arg);
|
||||||
int expand_dbvar(void *h, char *name, cvec *vars, cg_var *arg,
|
|
||||||
int *nr, char ***commands, char ***helptexts);
|
|
||||||
int expand_dbvar_auto(void *h, char *name, cvec *vars, cg_var *arg,
|
|
||||||
int *nr, char ***commands, char ***helptexts);
|
|
||||||
int expand_db_variable(clicon_handle h, char *dbname, char *basekey, char *variable, int *nr, char ***commands);
|
|
||||||
int expand_db_symbol(clicon_handle h, char *symbol, int element, int *nr, char ***commands);
|
|
||||||
int expand_dir(char *dir, int *nr, char ***commands, mode_t flags, int detail);
|
int expand_dir(char *dir, int *nr, char ***commands, mode_t flags, int detail);
|
||||||
|
int expand_dbvar_dbxml(void *h, char *name, cvec *cvv, cg_var *arg,
|
||||||
|
int *nr, char ***commands, char ***helptexts);
|
||||||
int compare_dbs(clicon_handle h, cvec *vars, cg_var *arg);
|
int compare_dbs(clicon_handle h, cvec *vars, cg_var *arg);
|
||||||
|
|
||||||
int load_config_file(clicon_handle h, cvec *vars, cg_var *arg);
|
int load_config_file(clicon_handle h, cvec *vars, cg_var *arg);
|
||||||
|
|
|
||||||
|
|
@ -52,41 +52,17 @@
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* Command line options to be passed to getopt(3) */
|
||||||
#define DBCTRL_OPTS "hDd:pbn:r:m:Zi"
|
#define DBCTRL_OPTS "hDd:pbn:r:m:Zi"
|
||||||
|
|
||||||
/*! Write database contents to file, xml database variant
|
|
||||||
* @param[in] dbspec If set make a sanity check if key dont match (just)
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
dump_database(FILE *f,
|
|
||||||
char *dbname,
|
|
||||||
char *rxkey)
|
|
||||||
{
|
|
||||||
int retval = 0;
|
|
||||||
int npairs;
|
|
||||||
struct db_pair *pairs;
|
|
||||||
|
|
||||||
/* Default is match all */
|
|
||||||
if (rxkey == NULL)
|
|
||||||
rxkey = "^.*$";
|
|
||||||
|
|
||||||
/* Get all keys/values for vector */
|
|
||||||
if ((npairs = db_regexp(dbname, rxkey, __FUNCTION__, &pairs, 0)) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
for (npairs--; npairs >= 0; npairs--)
|
|
||||||
fprintf(f, "%s %s\n", pairs[npairs].dp_key,
|
|
||||||
pairs[npairs].dp_val?pairs[npairs].dp_val:"");
|
|
||||||
unchunk_group(__FUNCTION__);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* remove_entry
|
* remove_entry
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
remove_entry(char *dbname, char *key)
|
remove_entry(char *dbname, char *key)
|
||||||
{
|
{
|
||||||
return db_del(dbname, key);
|
#ifdef NOTYET /* This assumes direct access to database */
|
||||||
|
return db_del(dbname, key);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -219,7 +195,7 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
yspec = clicon_dbspec_yang(h);
|
yspec = clicon_dbspec_yang(h);
|
||||||
if (dumpdb){
|
if (dumpdb){
|
||||||
if (dump_database(stdout, dbname, matchkey)) {
|
if (xmldb_dump(stdout, dbname, matchkey)) {
|
||||||
fprintf(stderr, "Match error\n");
|
fprintf(stderr, "Match error\n");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -230,10 +206,14 @@ main(int argc, char **argv)
|
||||||
if (rment)
|
if (rment)
|
||||||
if (remove_entry(dbname, rmkey) < 0)
|
if (remove_entry(dbname, rmkey) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (zapdb) /* remove databases */
|
if (zapdb) /* remove databases */
|
||||||
unlink(dbname);
|
/* XXX This assumes direct access to database */
|
||||||
|
if (unlink(dbname) < 0){
|
||||||
|
clicon_err(OE_FATAL, errno, "unlink %s", dbname);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
if (initdb)
|
if (initdb)
|
||||||
if (db_init(dbname) < 0)
|
if (xmldb_init(dbname) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
|
||||||
|
|
@ -402,31 +402,6 @@ get_edit_opts(cxobj *xn,
|
||||||
*
|
*
|
||||||
* @note delete/remove not implemented
|
* @note delete/remove not implemented
|
||||||
*
|
*
|
||||||
* Call graph, client to backend and formats
|
|
||||||
* netconf_input_cb # client
|
|
||||||
* read
|
|
||||||
* process_incoming_packet # (char*)
|
|
||||||
* clicon_xml_parse_string # (xml)
|
|
||||||
* netconf_rpc_dispatch
|
|
||||||
* netconf_edit_config # client
|
|
||||||
* clicon_xml2file # (file)
|
|
||||||
* clicon_rpc_load
|
|
||||||
* from_client # backend
|
|
||||||
* from_client_load
|
|
||||||
* db_init # replace?
|
|
||||||
* load_xml_to_db
|
|
||||||
* clicon_xml_parse_file #(xml)
|
|
||||||
* xml2db
|
|
||||||
* xml2cvec_key #(cvec)
|
|
||||||
* clicon_dbput
|
|
||||||
* cvec2lvec #(lvec)
|
|
||||||
* db_set
|
|
||||||
* dpopen
|
|
||||||
* dpput #(db)
|
|
||||||
* dpclose
|
|
||||||
* Which means that for a single edit, the following format conversions are made:
|
|
||||||
* char*->xml->file->xml->cvec->lvec->db
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_edit_config(clicon_handle h,
|
netconf_edit_config(clicon_handle h,
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,8 @@ transaction_commit(clicon_handle h,
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
/* Get all added i/fs */
|
/* Get all added i/fs */
|
||||||
vec = xpath_vec_flag(target, "//interface", XML_FLAG_ADD, &len);
|
if (xpath_vec_flag(target, "//interface", XML_FLAG_ADD, &vec, &len) < 0)
|
||||||
|
return -1;
|
||||||
for (i=0; i<len; i++) /* Loop over added i/fs */
|
for (i=0; i<len; i++) /* Loop over added i/fs */
|
||||||
clicon_xml2file(stdout, vec[i], 0, 1); /* Print the added interface */
|
clicon_xml2file(stdout, vec[i], 0, 1); /* Print the added interface */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@
|
||||||
#include <clixon/clixon_queue.h>
|
#include <clixon/clixon_queue.h>
|
||||||
#include <clixon/clixon_hash.h>
|
#include <clixon/clixon_hash.h>
|
||||||
#include <clixon/clixon_handle.h>
|
#include <clixon/clixon_handle.h>
|
||||||
#include <clixon/clixon_qdb.h>
|
|
||||||
#include <clixon/clixon_yang.h>
|
#include <clixon/clixon_yang.h>
|
||||||
#include <clixon/clixon_yang_type.h>
|
#include <clixon/clixon_yang_type.h>
|
||||||
#include <clixon/clixon_chunk.h>
|
#include <clixon/clixon_chunk.h>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
*/
|
*/
|
||||||
int yang2xmlkeyfmt(yang_stmt *ys, char **xkfmt);
|
int yang2xmlkeyfmt(yang_stmt *ys, char **xkfmt);
|
||||||
int xmlkeyfmt2key(char *xkfmt, cvec *cvv, char **xk);
|
int xmlkeyfmt2key(char *xkfmt, cvec *cvv, char **xk);
|
||||||
int xmlkeyfmt2key2(char *xkfmt, cvec *cvv, char **xk);
|
int xmlkeyfmt2xpath(char *xkfmt, cvec *cvv, char **xk);
|
||||||
int xmlkey2xml(char *xkey, yang_spec *yspec, char **xml);
|
int xmlkey2xml(char *xkey, yang_spec *yspec, char **xml);
|
||||||
int xmldb_get(char *dbname, char *xpath,
|
int xmldb_get(char *dbname, char *xpath,
|
||||||
yang_spec *yspec, cxobj **xtop);
|
yang_spec *yspec, cxobj **xtop);
|
||||||
|
|
@ -38,5 +38,7 @@ int xmldb_put( char *dbname, cxobj *xt,
|
||||||
yang_spec *yspec, enum operation_type op);
|
yang_spec *yspec, enum operation_type op);
|
||||||
int xmldb_put_xkey(char *dbname, char *xkey, char *val, yang_spec *yspec,
|
int xmldb_put_xkey(char *dbname, char *xkey, char *val, yang_spec *yspec,
|
||||||
enum operation_type op);
|
enum operation_type op);
|
||||||
|
int xmldb_dump(FILE *f, char *dbname, char *rxkey);
|
||||||
|
int xmldb_init(char *file);
|
||||||
|
|
||||||
#endif /* _CLIXON_XML_DB_H */
|
#endif /* _CLIXON_XML_DB_H */
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@
|
||||||
*/
|
*/
|
||||||
cxobj *xpath_first(cxobj *xn_top, char *xpath);
|
cxobj *xpath_first(cxobj *xn_top, char *xpath);
|
||||||
cxobj *xpath_each(cxobj *xn_top, char *xpath, cxobj *prev);
|
cxobj *xpath_each(cxobj *xn_top, char *xpath, cxobj *prev);
|
||||||
cxobj **xpath_vec(cxobj *xn_top, char *xpath, size_t *xv_len);
|
int xpath_vec(cxobj *xn_top, char *xpath, cxobj ***vec, size_t *xv_len);
|
||||||
cxobj **xpath_vec_flag(cxobj *cxtop, char *xpath, uint16_t flags, size_t *veclen);
|
int xpath_vec_flag(cxobj *cxtop, char *xpath, uint16_t flags,
|
||||||
|
cxobj ***vec, size_t *veclen);
|
||||||
|
|
||||||
#endif /* _CLIXON_XSL_H */
|
#endif /* _CLIXON_XSL_H */
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,7 @@ yang2xmlkeyfmt(yang_stmt *ys, char **xkfmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Transform an xml key format and a vector of values to an XML key
|
/*! Transform an xml key format and a vector of values to an XML key
|
||||||
|
* Used for actual key, eg in clicon_rpc_change(), xmldb_put_xkey()
|
||||||
* Example:
|
* Example:
|
||||||
* xmlkeyfmt: /aaa/%s
|
* xmlkeyfmt: /aaa/%s
|
||||||
* cvv: key=17
|
* cvv: key=17
|
||||||
|
|
@ -188,6 +189,7 @@ xmlkeyfmt2key(char *xkfmt,
|
||||||
char *str;
|
char *str;
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
|
#if 1
|
||||||
j = 0; /* Count % */
|
j = 0; /* Count % */
|
||||||
for (i=0; i<strlen(xkfmt); i++)
|
for (i=0; i<strlen(xkfmt); i++)
|
||||||
if (xkfmt[i] == '%')
|
if (xkfmt[i] == '%')
|
||||||
|
|
@ -200,6 +202,7 @@ xmlkeyfmt2key(char *xkfmt,
|
||||||
cv_string_get(cvec_i(cvv, 0)));
|
cv_string_get(cvec_i(cvv, 0)));
|
||||||
// goto done;
|
// goto done;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if ((cb = cbuf_new()) == NULL)
|
if ((cb = cbuf_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
j = 1; /* j==0 is cli string */
|
j = 1; /* j==0 is cli string */
|
||||||
|
|
@ -233,20 +236,33 @@ xmlkeyfmt2key(char *xkfmt,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Transform an xml key format and a vector of values to an XML key
|
||||||
|
* Used to input xmldb_get() or xmldb_get_vec
|
||||||
|
* Add .* in last %s position.
|
||||||
|
* Example:
|
||||||
|
* xmlkeyfmt: /interface/%s/address/%s
|
||||||
|
* cvv: name=eth0
|
||||||
|
* xmlkey: /interface/[name=eth0]/address
|
||||||
|
* @param[in] xkfmt XML key format
|
||||||
|
* @param[in] cvv cligen variable vector, one for every wildchar in xkfmt
|
||||||
|
* @param[out] xk XPATH
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
xmlkeyfmt2key2(char *xkfmt,
|
xmlkeyfmt2xpath(char *xkfmt,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
char **xk)
|
char **xk)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char c;
|
char c;
|
||||||
int esc=0;
|
int esc=0;
|
||||||
cbuf *cb = NULL;
|
cbuf *cb = NULL;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
char *str;
|
char *str;
|
||||||
|
cg_var *cv;
|
||||||
|
int skip = 0;
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check: count '%' */
|
||||||
#if 1
|
#if 1
|
||||||
j = 0; /* Count % */
|
j = 0; /* Count % */
|
||||||
for (i=0; i<strlen(xkfmt); i++)
|
for (i=0; i<strlen(xkfmt); i++)
|
||||||
|
|
@ -263,7 +279,6 @@ xmlkeyfmt2key2(char *xkfmt,
|
||||||
#endif
|
#endif
|
||||||
if ((cb = cbuf_new()) == NULL)
|
if ((cb = cbuf_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
cprintf(cb, "^");
|
|
||||||
j = 1; /* j==0 is cli string */
|
j = 1; /* j==0 is cli string */
|
||||||
for (i=0; i<strlen(xkfmt); i++){
|
for (i=0; i<strlen(xkfmt); i++){
|
||||||
c = xkfmt[i];
|
c = xkfmt[i];
|
||||||
|
|
@ -271,27 +286,40 @@ xmlkeyfmt2key2(char *xkfmt,
|
||||||
esc = 0;
|
esc = 0;
|
||||||
if (c!='s')
|
if (c!='s')
|
||||||
continue;
|
continue;
|
||||||
if (j == cvec_len(cvv)){
|
if (j == cvec_len(cvv)){ /* last element */
|
||||||
if ((str = strdup(".*")) == NULL){
|
skip++;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
/* XXX: remove preceding '/' :
|
||||||
|
a/[x=y] -> a[x=y] */
|
||||||
|
if ((str = strdup(cbuf_get(cb))) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
str[strlen(str)-1] = '\0';
|
||||||
else
|
cbuf_reset(cb);
|
||||||
if ((str = cv2str_dup(cvec_i(cvv, j++))) == NULL){
|
cprintf(cb, "%s", str);
|
||||||
|
free(str);
|
||||||
|
|
||||||
|
cv = cvec_i(cvv, j++);
|
||||||
|
if ((str = cv2str_dup(cv)) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "cv2str_dup");
|
clicon_err(OE_UNIX, errno, "cv2str_dup");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
cprintf(cb, "%s", str);
|
cprintf(cb, "[%s=%s]", cv_name_get(cv), str);
|
||||||
free(str);
|
free(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else /* regular char */
|
||||||
if (c == '%')
|
if (c == '%')
|
||||||
esc++;
|
esc++;
|
||||||
else
|
else{
|
||||||
cprintf(cb, "%c", c);
|
if (skip)
|
||||||
|
skip=0;
|
||||||
|
else
|
||||||
|
cprintf(cb, "%c", c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cprintf(cb, "$");
|
|
||||||
if ((*xk = strdup(cbuf_get(cb))) == NULL){
|
if ((*xk = strdup(cbuf_get(cb))) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -435,6 +463,7 @@ xml_tree_prune_unmarked(cxobj *xt,
|
||||||
/*!
|
/*!
|
||||||
* @param[in] xkey xmlkey
|
* @param[in] xkey xmlkey
|
||||||
* @param[out] xt XML tree as result
|
* @param[out] xt XML tree as result
|
||||||
|
* XXX cannot handle top-level list
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
get(char *dbname,
|
get(char *dbname,
|
||||||
|
|
@ -637,7 +666,6 @@ xml_default(cxobj *x,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Get content of database using xpath. return a single tree
|
/*! Get content of database using xpath. return a single tree
|
||||||
* The function returns a minimal tree that includes all sub-trees that match
|
* The function returns a minimal tree that includes all sub-trees that match
|
||||||
* xpath.
|
* xpath.
|
||||||
|
|
@ -691,7 +719,9 @@ xmldb_get(char *dbname,
|
||||||
* 2. only read necessary parts,...?
|
* 2. only read necessary parts,...?
|
||||||
*/
|
*/
|
||||||
if (xpath){
|
if (xpath){
|
||||||
if ((xvec = xpath_vec(xt, xpath, &len)) != NULL){
|
if (xpath_vec(xt, xpath, &xvec, &len) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xvec != NULL){
|
||||||
/* Prune everything except nodes in xvec and how to get there
|
/* Prune everything except nodes in xvec and how to get there
|
||||||
* Alt: Create a new subtree from xt with that property,...(no)
|
* Alt: Create a new subtree from xt with that property,...(no)
|
||||||
*/
|
*/
|
||||||
|
|
@ -737,7 +767,7 @@ xmldb_get(char *dbname,
|
||||||
* cxobj **xvec;
|
* cxobj **xvec;
|
||||||
* size_t xlen;
|
* size_t xlen;
|
||||||
* yang_spec *yspec = clicon_dbspec_yang(h);
|
* yang_spec *yspec = clicon_dbspec_yang(h);
|
||||||
* if (xmldb_get_vec(dbname, "/interfaces/interface[name="eth*"]", yspec,
|
* if (xmldb_get_vec(dbname, "/interfaces/interface[name="eth"]", yspec,
|
||||||
* &xt, &xvec, &xlen) < 0)
|
* &xt, &xvec, &xlen) < 0)
|
||||||
* err;
|
* err;
|
||||||
* for (i=0; i<xlen; i++){
|
* for (i=0; i<xlen; i++){
|
||||||
|
|
@ -781,7 +811,7 @@ xmldb_get_vec(char *dbname,
|
||||||
xt) < 0)
|
xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((*xvec = xpath_vec(xt, xpath, xlen)) == NULL)
|
if (xpath_vec(xt, xpath, xvec, xlen) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_apply(xt, CX_ELMNT, xml_default, NULL) < 0)
|
if (xml_apply(xt, CX_ELMNT, xml_default, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -797,6 +827,8 @@ xmldb_get_vec(char *dbname,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! Get value of the "operation" attribute and change op if given
|
/*! Get value of the "operation" attribute and change op if given
|
||||||
* @param[in] xn XML node
|
* @param[in] xn XML node
|
||||||
* @param[out] op "operation" attribute may change operation
|
* @param[out] op "operation" attribute may change operation
|
||||||
|
|
@ -1126,7 +1158,6 @@ xmldb_put_xkey(char *dbname,
|
||||||
if (db_del(dbname, pairs[i].dp_key) < 0)
|
if (db_del(dbname, pairs[i].dp_key) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -1143,6 +1174,41 @@ xmldb_put_xkey(char *dbname,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Raw dump of database, just keys and values, no xml interpretation
|
||||||
|
* param[in] f File
|
||||||
|
* param[in] dbname Name of database
|
||||||
|
* param[in] rxkey Key regexp, eg "^.*$"
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmldb_dump(FILE *f,
|
||||||
|
char *dbname,
|
||||||
|
char *rxkey)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
int npairs;
|
||||||
|
struct db_pair *pairs;
|
||||||
|
|
||||||
|
/* Default is match all */
|
||||||
|
if (rxkey == NULL)
|
||||||
|
rxkey = "^.*$";
|
||||||
|
|
||||||
|
/* Get all keys/values for vector */
|
||||||
|
if ((npairs = db_regexp(dbname, rxkey, __FUNCTION__, &pairs, 0)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (npairs--; npairs >= 0; npairs--)
|
||||||
|
fprintf(f, "%s %s\n", pairs[npairs].dp_key,
|
||||||
|
pairs[npairs].dp_val?pairs[npairs].dp_val:"");
|
||||||
|
unchunk_group(__FUNCTION__);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xmldb_init(char *file)
|
||||||
|
{
|
||||||
|
return db_init(file);
|
||||||
|
}
|
||||||
|
|
||||||
#if 1 /* Test program */
|
#if 1 /* Test program */
|
||||||
/*
|
/*
|
||||||
* Turn this on to get an xpath test program
|
* Turn this on to get an xpath test program
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,6 @@
|
||||||
#include "clixon_yang.h"
|
#include "clixon_yang.h"
|
||||||
#include "clixon_yang_type.h"
|
#include "clixon_yang_type.h"
|
||||||
#include "clixon_options.h"
|
#include "clixon_options.h"
|
||||||
#include "clixon_qdb.h"
|
|
||||||
#include "clixon_xml.h"
|
#include "clixon_xml.h"
|
||||||
#include "clixon_xsl.h"
|
#include "clixon_xsl.h"
|
||||||
#include "clixon_log.h"
|
#include "clixon_log.h"
|
||||||
|
|
|
||||||
|
|
@ -149,8 +149,9 @@ xpath_print(FILE *f, struct xpath_element *xplist)
|
||||||
struct xpath_element *xe;
|
struct xpath_element *xe;
|
||||||
|
|
||||||
for (xe=xplist; xe; xe=xe->xe_next)
|
for (xe=xplist; xe; xe=xe->xe_next)
|
||||||
fprintf(f, "\t:%s %s\n", axis_type2str(xe->xe_type),
|
fprintf(f, "\t:%s %s %s\n", axis_type2str(xe->xe_type),
|
||||||
xe->xe_str?xe->xe_str:"");
|
xe->xe_str?xe->xe_str:"",
|
||||||
|
xe->xe_predicate?xe->xe_predicate:"");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -334,7 +335,7 @@ recursive_find(cxobj *xn,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
xpath_expr(char *e,
|
xpath_expr(char *e00,
|
||||||
uint16_t flags,
|
uint16_t flags,
|
||||||
cxobj ***vec0,
|
cxobj ***vec0,
|
||||||
size_t *vec0len)
|
size_t *vec0len)
|
||||||
|
|
@ -350,7 +351,14 @@ xpath_expr(char *e,
|
||||||
int oplen;
|
int oplen;
|
||||||
char *tag;
|
char *tag;
|
||||||
char *val;
|
char *val;
|
||||||
|
char *e0;
|
||||||
|
char *e;
|
||||||
|
|
||||||
|
if ((e0 = strdup(e00)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
e = e0;
|
||||||
if (*e == '@'){ /* @ attribute */
|
if (*e == '@'){ /* @ attribute */
|
||||||
e++;
|
e++;
|
||||||
e_v=e;
|
e_v=e;
|
||||||
|
|
@ -418,6 +426,8 @@ xpath_expr(char *e,
|
||||||
*vec0len = veclen;
|
*vec0len = veclen;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (e0)
|
||||||
|
free(e0);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -603,7 +613,7 @@ xpath_exec(char *xpath,
|
||||||
goto done;
|
goto done;
|
||||||
if (xpath_parse(xpath, &xplist) < 0)
|
if (xpath_parse(xpath, &xplist) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (0)
|
if (debug > 1)
|
||||||
xpath_print(stderr, xplist);
|
xpath_print(stderr, xplist);
|
||||||
if (xpath_find(xplist, 0, vec1, vec1len, flags, vec2, vec2len) < 0)
|
if (xpath_find(xplist, 0, vec1, vec1len, flags, vec2, vec2len) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -767,9 +777,10 @@ xpath_each(cxobj *cxtop,
|
||||||
* See xpath1() on details for subset.
|
* See xpath1() on details for subset.
|
||||||
* @param[in] cxtop xml-tree where to search
|
* @param[in] cxtop xml-tree where to search
|
||||||
* @param[in] xpath string with XPATH syntax
|
* @param[in] xpath string with XPATH syntax
|
||||||
|
* @param[out] vec vector of xml-trees. Vector must be free():d after use
|
||||||
* @param[out] xv_len returns length of vector in return value
|
* @param[out] xv_len returns length of vector in return value
|
||||||
* @retval vec vector of xml-trees. Vector must be free():d after use
|
* @retval 0 OK
|
||||||
* @retval NULL NULL on error.
|
* @retval -1 error.
|
||||||
*
|
*
|
||||||
* @code
|
* @code
|
||||||
* cxobj **xv;
|
* cxobj **xv;
|
||||||
|
|
@ -786,34 +797,30 @@ xpath_each(cxobj *cxtop,
|
||||||
* trees need not be.
|
* trees need not be.
|
||||||
* @see also xpath_first, xpath_each.
|
* @see also xpath_first, xpath_each.
|
||||||
*/
|
*/
|
||||||
cxobj **
|
int
|
||||||
xpath_vec(cxobj *cxtop,
|
xpath_vec(cxobj *cxtop,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
size_t *veclen)
|
cxobj ***vec,
|
||||||
|
size_t *veclen)
|
||||||
{
|
{
|
||||||
cxobj **vec=NULL;
|
*vec = NULL;
|
||||||
|
|
||||||
*veclen = 0;
|
*veclen = 0;
|
||||||
if (xpath_choice(cxtop, xpath, 0, &vec, (size_t*)veclen) < 0)
|
return xpath_choice(cxtop, xpath, 0, vec, veclen);
|
||||||
return NULL;
|
|
||||||
return vec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A restricted xpath that returns a vector of matches (only nodes marked with flags)
|
/* A restricted xpath that returns a vector of matches (only nodes marked with flags)
|
||||||
* @param[in] flags Set of flags that return nodes must match (0 if all)
|
* @param[in] flags Set of flags that return nodes must match (0 if all)
|
||||||
*/
|
*/
|
||||||
cxobj **
|
int
|
||||||
xpath_vec_flag(cxobj *cxtop,
|
xpath_vec_flag(cxobj *cxtop,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
uint16_t flags,
|
uint16_t flags,
|
||||||
|
cxobj ***vec,
|
||||||
size_t *veclen)
|
size_t *veclen)
|
||||||
{
|
{
|
||||||
cxobj **vec=NULL;
|
*vec=NULL;
|
||||||
|
|
||||||
*veclen = 0;
|
*veclen = 0;
|
||||||
if (xpath_choice(cxtop, xpath, flags, &vec, (size_t*)veclen) < 0)
|
return xpath_choice(cxtop, xpath, flags, vec, veclen);
|
||||||
return NULL;
|
|
||||||
return vec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -852,7 +859,9 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
if ((xv = xpath_vec(x, argv[1], &xlen)) != NULL) {
|
if (xpath_vec(x, argv[1], &xv, &xlen) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xv)
|
||||||
for (i=0; i<xlen; i++){
|
for (i=0; i<xlen; i++){
|
||||||
xn = xv[i];
|
xn = xv[i];
|
||||||
fprintf(stdout, "[%d]:\n", i);
|
fprintf(stdout, "[%d]:\n", i);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue