Alternative yang spec option -y added to all applications

This commit is contained in:
Olof hagsand 2017-04-04 21:37:42 +02:00
parent 236b661e43
commit c59869a44e
10 changed files with 86 additions and 167 deletions

View file

@ -30,6 +30,8 @@
# ***** END LICENSE BLOCK ***** # ***** END LICENSE BLOCK *****
- Alternative yang spec option -y added to all applications
- Many clicon special string functions have been removed
- The netconf support has been extended with lock/unlock - The netconf support has been extended with lock/unlock
- clicon_rpc_call() has been removed and should be replaced by extending the - clicon_rpc_call() has been removed and should be replaced by extending the
internal netconf protocol. internal netconf protocol.

View file

@ -57,6 +57,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <libgen.h>
/* cligen */ /* cligen */
#include <cligen/cligen.h> #include <cligen/cligen.h>
@ -141,7 +142,8 @@ usage(char *argv0, clicon_handle h)
" -r\t\tReload running database\n" " -r\t\tReload running database\n"
" -p \t\tPrint database yang specification\n" " -p \t\tPrint database yang specification\n"
" -t \t\tPrint alternate spec translation (eg if YANG print KEY, if KEY print YANG)\n" " -t \t\tPrint alternate spec translation (eg if YANG print KEY, if KEY print YANG)\n"
" -g <group>\tClient membership required to this group (default: %s)\n", " -g <group>\tClient membership required to this group (default: %s)\n"
"\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n",
argv0, argv0,
plgdir ? plgdir : "none", plgdir ? plgdir : "none",
confsock ? confsock : "none", confsock ? confsock : "none",
@ -426,9 +428,15 @@ main(int argc, char **argv)
case 't' : /* Print alternative dbspec format (eg if YANG, print KEY) */ case 't' : /* Print alternative dbspec format (eg if YANG, print KEY) */
printalt++; printalt++;
break; break;
case 'y' : /* yang module */ case 'y' :{ /* yang module */
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg); /* Set revision to NULL, extract dir and module */
char *str = strdup(optarg);
char *dir = dirname(str);
hash_del(clicon_options(h), (char*)"CLICON_YANG_MODULE_REVISION");
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", basename(optarg));
clicon_option_str_set(h, "CLICON_YANG_DIR", strdup(dir));
break; break;
}
default: default:
usage(argv[0], h); usage(argv[0], h);
break; break;

View file

@ -595,8 +595,7 @@ load_config_filev(clicon_handle h,
{ {
int ret = -1; int ret = -1;
struct stat st; struct stat st;
char **vecp = NULL; char *filename = NULL;
char *filename;
int replace; int replace;
cg_var *cv; cg_var *cv;
char *opstr; char *opstr;
@ -628,11 +627,10 @@ load_config_filev(clicon_handle h,
clicon_err(OE_PLUGIN, 0, "No such var name: %s", varstr); clicon_err(OE_PLUGIN, 0, "No such var name: %s", varstr);
goto done; goto done;
} }
if ((vecp = clicon_realpath(NULL, cv_string_get(cv), __FUNCTION__)) == NULL){ if ((filename = realpath(cv_string_get(cv), NULL)) == NULL){
cli_output(stderr, "Failed to resolve filename\n"); cli_output(stderr, "Failed to resolve filename\n");
goto done; goto done;
} }
filename = vecp[0];
if (stat(filename, &st) < 0){ if (stat(filename, &st) < 0){
clicon_err(OE_UNIX, 0, "load_config: stat(%s): %s", clicon_err(OE_UNIX, 0, "load_config: stat(%s): %s",
filename, strerror(errno)); filename, strerror(errno));
@ -668,14 +666,8 @@ load_config_filev(clicon_handle h,
// } // }
ret = 0; ret = 0;
done: done:
unchunk_group(__FUNCTION__); if (filename)
if (vecp){ free(filename);
if (vecp[0])
free(vecp[0]);
if (vecp[1])
free(vecp[1]);
free(vecp);
}
if (xt) if (xt)
xml_free(xt); xml_free(xt);
if (fd != -1) if (fd != -1)
@ -704,8 +696,7 @@ save_config_filev(clicon_handle h,
cvec *argv) cvec *argv)
{ {
int retval = -1; int retval = -1;
char **vecp; char *filename = NULL;
char *filename;
cg_var *cv; cg_var *cv;
char *dbstr; char *dbstr;
char *varstr; char *varstr;
@ -732,11 +723,10 @@ save_config_filev(clicon_handle h,
clicon_err(OE_PLUGIN, 0, "No such var name: %s", varstr); clicon_err(OE_PLUGIN, 0, "No such var name: %s", varstr);
goto done; goto done;
} }
if ((vecp = clicon_realpath(NULL, cv_string_get(cv), __FUNCTION__)) == NULL){ if ((filename = realpath(cv_string_get(cv), NULL)) == NULL){
cli_output(stderr, "Failed to resolve filename\n"); cli_output(stderr, "Failed to resolve filename\n");
goto done; goto done;
} }
filename = vecp[0];
if (clicon_rpc_get_config(h, dbstr,"/", &xt) < 0) if (clicon_rpc_get_config(h, dbstr,"/", &xt) < 0)
goto done; goto done;
if ((f = fopen(filename, "wb")) == NULL){ if ((f = fopen(filename, "wb")) == NULL){
@ -748,7 +738,8 @@ save_config_filev(clicon_handle h,
retval = 0; retval = 0;
/* Fall through */ /* Fall through */
done: done:
unchunk_group(__FUNCTION__); if (filename)
free(filename);
if (xt) if (xt)
xml_free(xt); xml_free(xt);
if (f != NULL) if (f != NULL)

View file

@ -54,6 +54,7 @@
#include <sys/param.h> #include <sys/param.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <assert.h> #include <assert.h>
#include <libgen.h>
/* cligen */ /* cligen */
#include <cligen/cligen.h> #include <cligen/cligen.h>
@ -69,7 +70,7 @@
#include "cli_handle.h" #include "cli_handle.h"
/* 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:qpGLl:" #define CLI_OPTS "hD:f:F:1u:d:m:qpGLl:y:"
/*! terminate cli application */ /*! terminate cli application */
static int static int
@ -150,7 +151,8 @@ usage(char *argv0, clicon_handle h)
"\t-p \t\tPrint database yang specification\n" "\t-p \t\tPrint database yang specification\n"
"\t-G \t\tPrint CLI syntax generated from dbspec (if CLICON_CLI_GENMODEL enabled)\n" "\t-G \t\tPrint CLI syntax generated from dbspec (if CLICON_CLI_GENMODEL enabled)\n"
"\t-L \t\tDebug print dynamic CLI syntax including completions and expansions\n" "\t-L \t\tDebug print dynamic CLI syntax including completions and expansions\n"
"\t-l <s|e|o> \tLog on (s)yslog, std(e)rr or std(o)ut (stderr is default)\n", "\t-l <s|e|o> \tLog on (s)yslog, std(e)rr or std(o)ut (stderr is default)\n"
"\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n",
argv0, argv0,
confsock ? confsock : "none", confsock ? confsock : "none",
plgdir ? plgdir : "none" plgdir ? plgdir : "none"
@ -288,6 +290,15 @@ main(int argc, char **argv)
case 'L' : /* Debug print dynamic CLI syntax */ case 'L' : /* Debug print dynamic CLI syntax */
logclisyntax++; logclisyntax++;
break; break;
case 'y' :{ /* yang module */
/* Set revision to NULL, extract dir and module */
char *str = strdup(optarg);
char *dir = dirname(str);
hash_del(clicon_options(h), (char*)"CLICON_YANG_MODULE_REVISION");
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", basename(optarg));
clicon_option_str_set(h, "CLICON_YANG_DIR", strdup(dir));
break;
}
default: default:
usage(argv[0], h); usage(argv[0], h);
break; break;

View file

@ -56,6 +56,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <assert.h> #include <assert.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <libgen.h>
/* cligen */ /* cligen */
#include <cligen/cligen.h> #include <cligen/cligen.h>
@ -70,7 +71,7 @@
#include "netconf_rpc.h" #include "netconf_rpc.h"
/* Command line options to be passed to getopt(3) */ /* Command line options to be passed to getopt(3) */
#define NETCONF_OPTS "hDqf:d:S" #define NETCONF_OPTS "hDqf:d:Sy:"
/*! Process incoming packet /*! Process incoming packet
* @param[in] h Clicon handle * @param[in] h Clicon handle
@ -286,7 +287,8 @@ usage(clicon_handle h,
"\t-q\t\tQuiet: dont send hello prompt\n" "\t-q\t\tQuiet: dont send hello prompt\n"
"\t-f <file>\tConfiguration file (mandatory)\n" "\t-f <file>\tConfiguration file (mandatory)\n"
"\t-d <dir>\tSpecify netconf plugin directory dir (default: %s)\n" "\t-d <dir>\tSpecify netconf plugin directory dir (default: %s)\n"
"\t-S\t\tLog on syslog\n", "\t-S\t\tLog on syslog\n"
"\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n",
argv0, argv0,
netconfdir netconfdir
); );
@ -359,6 +361,15 @@ main(int argc, char **argv)
usage(h, argv[0]); usage(h, argv[0]);
clicon_option_str_set(h, "CLICON_NETCONF_DIR", optarg); clicon_option_str_set(h, "CLICON_NETCONF_DIR", optarg);
break; break;
case 'y' :{ /* yang module */
/* Set revision to NULL, extract dir and module */
char *str = strdup(optarg);
char *dir = dirname(str);
hash_del(clicon_options(h), (char*)"CLICON_YANG_MODULE_REVISION");
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", basename(optarg));
clicon_option_str_set(h, "CLICON_YANG_DIR", strdup(dir));
break;
}
default: default:
usage(h, argv[0]); usage(h, argv[0]);
break; break;

View file

@ -59,6 +59,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <libgen.h>
/* cligen */ /* cligen */
#include <cligen/cligen.h> #include <cligen/cligen.h>
@ -71,7 +72,7 @@
#include "restconf_methods.h" #include "restconf_methods.h"
/* Command line options to be passed to getopt(3) */ /* Command line options to be passed to getopt(3) */
#define RESTCONF_OPTS "hDf:p:" #define RESTCONF_OPTS "hDf:p:y:"
/* Should be discovered via "/.well-known/host-meta" /* Should be discovered via "/.well-known/host-meta"
resource ([RFC6415]) */ resource ([RFC6415]) */
@ -243,7 +244,8 @@ usage(clicon_handle h,
"\t-h \t\tHelp\n" "\t-h \t\tHelp\n"
"\t-D \t\tDebug. Log to syslog\n" "\t-D \t\tDebug. Log to syslog\n"
"\t-f <file>\tConfiguration file (mandatory)\n" "\t-f <file>\tConfiguration file (mandatory)\n"
"\t-d <dir>\tSpecify restconf plugin directory dir (default: %s)\n", "\t-d <dir>\tSpecify restconf plugin directory dir (default: %s)\n"
"\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n",
argv0, argv0,
restconfdir restconfdir
); );
@ -264,6 +266,7 @@ main(int argc,
char *sockpath; char *sockpath;
char *path; char *path;
clicon_handle h; clicon_handle h;
char *yangspec=NULL;
/* In the startup, logs to stderr & debug flag set later */ /* In the startup, logs to stderr & debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, CLICON_LOG_SYSLOG); clicon_log_init(__PROGRAM__, LOG_INFO, CLICON_LOG_SYSLOG);
@ -289,6 +292,9 @@ main(int argc,
usage(h, argv[0]); usage(h, argv[0]);
clicon_option_str_set(h, "CLICON_RESTCONF_DIR", optarg); clicon_option_str_set(h, "CLICON_RESTCONF_DIR", optarg);
break; break;
case 'y' : /* yang module */
yangspec = optarg;
break;
default: default:
usage(h, argv[0]); usage(h, argv[0]);
break; break;
@ -312,6 +318,15 @@ main(int argc,
if (clicon_options_main(h) < 0) if (clicon_options_main(h) < 0)
goto done; goto done;
/* Overwrite yang module with -y option */
if (yangspec){
/* Set revision to NULL, extract dir and module */
char *str = strdup(yangspec);
char *dir = dirname(str);
hash_del(clicon_options(h), (char*)"CLICON_YANG_MODULE_REVISION");
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", basename(yangspec));
clicon_option_str_set(h, "CLICON_YANG_DIR", strdup(dir));
}
/* Initialize plugins group */ /* Initialize plugins group */
if (restconf_plugin_load(h) < 0) if (restconf_plugin_load(h) < 0)
return -1; return -1;

View file

@ -37,8 +37,6 @@
#define _CLIXON_FILE_H_ #define _CLIXON_FILE_H_
char **clicon_realpath(const char *cwd, char *path, const char *label);
int clicon_file_dirent(const char *dir, struct dirent **ent, int clicon_file_dirent(const char *dir, struct dirent **ent,
const char *regexp, mode_t type, const char *label); const char *regexp, mode_t type, const char *label);

View file

@ -62,108 +62,6 @@
#include "clixon_string.h" #include "clixon_string.h"
#include "clixon_file.h" #include "clixon_file.h"
/*! Resolve the real path of a given 'path', following symbolic links and '../'.
* If 'path' relative, it will be resolved based on the currnt working
* directory 'cwd'. The response is a 2 entry vector of strings. The first
* entry is the resolved path and the second is the part of the path which
* actually exist.
* @retval vec
*/
char **
clicon_realpath(const char *cwd,
char *path,
const char *label)
{
char **ret = NULL;
char *rest;
char **vec = NULL;
char **vec2;
int nvec, nvec2;
char *p;
char *rp = NULL;
char *ptr;
int i;
struct passwd *pwd;
char cwdbuf[PATH_MAX];
/* Prepend 'cwd' if not absolute */
if (path[0] == '/')
p = path;
else {
if (cwd == NULL || strlen(cwd) == 0)
cwd = getcwd(cwdbuf, sizeof(cwdbuf));
else if (cwd[0] == '~') {
if((pwd = getpwuid(getuid())) == NULL)
goto catch;
cwd = pwd->pw_dir;
}
p = chunk_sprintf(__FUNCTION__, "%s%s/%s",
(cwd[0]=='/' ? "" : "/"), cwd, path);
}
if (p == NULL)
goto catch;
/* Make a local copy of 'path' */
if ((path = chunkdup(p, strlen(p)+1, __FUNCTION__)) == NULL)
goto catch;
/* Find the smallest portion of the path that exist and run realpath() */
while(strlen(p) && ((rp = realpath(p, NULL)) == NULL)) {
if((ptr = strrchr(p, '/')) == NULL)
break;
*ptr = '\0';
}
if(rp == NULL)
goto catch;
/* Use the result of realpath() and the rest of 'path' untouched, to
form a new path */
rest = path + strlen(p);
ptr = chunk_sprintf(__FUNCTION__, "%s%s", rp, rest);
p = ptr;
/* Split path based on '/'. Loop through vector from the end and copy
each entry into a new vector, skipping '..' and it's previous directory
as well as all '.' */
if ((vec = clicon_strsep(p, "/", &nvec)) == NULL)
goto catch;
if ((vec2 = malloc(nvec * sizeof(char *))) == NULL)
goto catch;
nvec2 = i = nvec;
while(--i >= 0) {
if(strcmp(vec[i], "..") == 0)
i--; /* Skip previous */
else if(strcmp(vec[i], ".") == 0)
/* do nothing */ ;
else
vec2[--nvec2] = vec[i];
}
/* Create resulting vector */
if ((ret = malloc(sizeof(char *) * 2)) != NULL) {
if((ret[0] = clicon_strjoin(nvec-nvec2, &vec2[nvec2], "/")) == NULL) {
free(ret);
ret = NULL;
}
if ((ret[1] = strdup(rp)) == NULL) {
free(ret[0]);
free(ret);
ret = NULL;
}
}
catch:
if(rp)
free(rp);
if(vec)
free(vec);
if(vec2)
free(vec2);
unchunk_group(__FUNCTION__);
return ret;
}
/* /*
* qsort function * qsort function
*/ */
@ -354,24 +252,3 @@ clicon_file_copy(char *src,
} }
#ifdef NOTUSED
/*
* (un)lock a whole file.
* Arguments:
* fd - File descriptor
* cmd - F_GETLK, F_SETLK, F_SETLKW
* type - F_RDLCK, F_WRLCK, F_UNLCK
*/
int
file_lock(int fd, int cmd, int type)
{
struct flock lock;
lock.l_type = type;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
return fcntl(fd, cmd, &lock);
}
#endif

View file

@ -65,7 +65,7 @@
* @param[in] string String to be split * @param[in] string String to be split
* @param[in] delim String of delimiter characters * @param[in] delim String of delimiter characters
* @param[out] nvec Number of entries in returned vector * @param[out] nvec Number of entries in returned vector
* @retval vec Vector of strings. Free after use * @retval vec Vector of strings. NULL terminated. Free after use
* @retval NULL Error * * @retval NULL Error *
*/ */
char ** char **
@ -78,6 +78,7 @@ clicon_strsep(char *string,
char *p; char *p;
int nvec = 1; int nvec = 1;
int i; int i;
size_t siz;
char *s; char *s;
char *d; char *d;
@ -89,11 +90,13 @@ clicon_strsep(char *string,
s++; s++;
} }
/* alloc vector and append copy of string */ /* alloc vector and append copy of string */
if ((vec = (char**)malloc(nvec* sizeof(char*) + strlen(string)+1)) == NULL){ siz = (nvec+1)* sizeof(char*) + strlen(string)+1;
if ((vec = (char**)malloc(siz)) == NULL){
clicon_err(OE_UNIX, errno, "malloc"); clicon_err(OE_UNIX, errno, "malloc");
goto done; goto done;
} }
ptr = (char*)vec + nvec* sizeof(char*); /* this is where ptr starts */ memset(vec, 0, siz);
ptr = (char*)vec + (nvec+1)* sizeof(char*); /* this is where ptr starts */
strncpy(ptr, string, strlen(string)+1); strncpy(ptr, string, strlen(string)+1);
i = 0; i = 0;
while ((p = strsep(&ptr, delim)) != NULL) while ((p = strsep(&ptr, delim)) != NULL)
@ -190,10 +193,10 @@ main(int argc, char **argv)
return 0; return 0;
} }
str0 = argv[1]; str0 = argv[1];
if ((vec = clicon_strsep("a b\tc", " \t", &nvec)) == NULL) if ((vec = clicon_strsep(str0, " \t", &nvec)) == NULL)
return -1; return -1;
fprintf(stderr, "nvec: %d\n", nvec); fprintf(stderr, "nvec: %d\n", nvec);
for (i=0; i<nvec; i++) for (i=0; i<nvec+1; i++)
fprintf(stderr, "vec[%d]: %s\n", i, vec[i]); fprintf(stderr, "vec[%d]: %s\n", i, vec[i]);
if ((str1 = clicon_strjoin(nvec, vec, " ")) == NULL) if ((str1 = clicon_strjoin(nvec, vec, " ")) == NULL)
return -1; return -1;

View file

@ -292,6 +292,7 @@ xml_yang_validate(cxobj *xt,
yang_stmt *yc; yang_stmt *yc;
int i; int i;
yang_stmt *ys; yang_stmt *ys;
char *body;
/* if not given by argument (overide) use default link */ /* if not given by argument (overide) use default link */
ys = ys0?ys0:xml_spec(xt); ys = ys0?ys0:xml_spec(xt);
@ -321,17 +322,19 @@ xml_yang_validate(cxobj *xt,
/* In the union case, value is parsed as generic REST type, /* In the union case, value is parsed as generic REST type,
* needs to be reparsed when concrete type is selected * needs to be reparsed when concrete type is selected
*/ */
if (cv_parse(xml_body(xt), cv) <0){ if ((body = xml_body(xt)) != NULL){
clicon_err(OE_UNIX, errno, "cv_parse"); if (cv_parse(body, cv) <0){
goto done; clicon_err(OE_UNIX, errno, "cv_parse");
} goto done;
if ((ys_cv_validate(cv, ys, &reason)) != 1){ }
clicon_err(OE_DB, 0, if ((ys_cv_validate(cv, ys, &reason)) != 1){
"validation of %s failed %s", clicon_err(OE_DB, 0,
ys->ys_argument, reason?reason:""); "validation of %s failed %s",
if (reason) ys->ys_argument, reason?reason:"");
free(reason); if (reason)
goto done; free(reason);
goto done;
}
} }
break; break;
default: default: