diff --git a/lib/clixon/clixon_file.h b/lib/clixon/clixon_file.h index 8219ff22..fcb7ce54 100644 --- a/lib/clixon/clixon_file.h +++ b/lib/clixon/clixon_file.h @@ -43,6 +43,9 @@ int clicon_file_dirent(const char *dir, struct dirent **ent, const char *regexp, mode_t type); +int clicon_files_recursive(const char *dir, const char *regexp, + char **dp, int *nent); + int clicon_file_copy(char *src, char *target); #endif /* _CLIXON_FILE_H_ */ diff --git a/lib/src/clixon_file.c b/lib/src/clixon_file.c index 6c0b4707..4adbe705 100644 --- a/lib/src/clixon_file.c +++ b/lib/src/clixon_file.c @@ -62,6 +62,86 @@ #include "clixon_log.h" #include "clixon_file.h" +static int +clicon_file_string_sort(const void *arg1, + const void *arg2) +{ + char *str1 = *(char **)arg1; + char *str2 = *(char **)arg2; + + return strcmp(str1, str2); +} + +int +clicon_files_recursive(const char *dir, + const char *regexp, + char **dp, + int *nent) +{ + struct dirent *dent = NULL; + char path[MAXPATHLEN]; + DIR *dirp = NULL; + regex_t re; + int res; + char errbuf[128]; + + if (regexp && (res = regcomp(&re, regexp, REG_EXTENDED)) != 0) { + regerror(res, &re, errbuf, sizeof(errbuf)); + clicon_err(OE_DB, 0, "regcomp: %s", errbuf); + return -1; + } + + if (!(dirp = opendir(dir))) { + return *nent; + } + + while ((dent = readdir(dirp)) != NULL) { + if (dent->d_type == DT_DIR) { + /* If we find a directory we might want to enter it, unless it + is the current directory (.) or parent (..) */ + if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) { + continue; + } + + /* Build the new directory and enter it. */ + sprintf(path, "%s/%s", dir, dent->d_name); + *nent = clicon_files_recursive(path, regexp, dp, nent); + } else if (dent->d_type == DT_REG) { + /* If we encounter a file, match it against the regexp and + add it to the list of found files.*/ + if (regexp) { + if (regexec(&re, dent->d_name, (size_t)0, NULL, *nent) != 0) + continue; + } + + /* Add room for the new file. */ + if ((dp = (char **)realloc(dp, sizeof(char *) * (*nent + 1))) == NULL) { + clicon_err(OE_UNIX, errno, "realloc"); + *nent = -1; + goto quit; + } + + if ((dp[*nent] = (char *)malloc(1 + sizeof(char) * strlen(dir) + + strlen(dent->d_name))) == NULL) { + clicon_err(OE_UNIX, errno, "malloc"); + *nent = -1; + goto quit; + } + + sprintf(dp[*nent], "%s/%s", dir, dent->d_name); + (*nent)++; + } + } + + qsort(dp, *nent, sizeof(char *), clicon_file_string_sort); + + quit: + if (dirp) + closedir(dirp); + + return *nent; +} + /*! qsort "compar" for directory alphabetically sorting, see qsort(3) */ static int diff --git a/lib/src/clixon_yang_parse_lib.c b/lib/src/clixon_yang_parse_lib.c index 5dc3b9cc..ceff764c 100644 --- a/lib/src/clixon_yang_parse_lib.c +++ b/lib/src/clixon_yang_parse_lib.c @@ -903,57 +903,69 @@ yang_parse_find_match(clicon_handle h, cbuf *fbuf) { int retval = -1; - struct dirent *dp = NULL; + char **dp = NULL; int ndp; cbuf *regex = NULL; cxobj *x; cxobj *xc; char *dir; + int nent = 0; + int i = 0; /* get clicon config file in xml form */ if ((x = clicon_conf_xml(h)) == NULL) - goto ok; + goto ok; if ((regex = cbuf_new()) == NULL){ - clicon_err(OE_YANG, errno, "cbuf_new"); - goto done; + clicon_err(OE_YANG, errno, "cbuf_new"); + goto done; } /* RFC 6020: The name of the file SHOULD be of the form: * module-or-submodule-name ['@' revision-date] ( '.yang' / '.yin' ) * revision-date ::= 4DIGIT "-" 2DIGIT "-" 2DIGIT */ if (revision) - cprintf(regex, "^%s@%s(.yang)$", module, revision); + cprintf(regex, "^%s@%s(.yang)$", module, revision); else - cprintf(regex, "^%s(@[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])?(.yang)$", - module); + cprintf(regex, "^%s(@[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])?(.yang)$", + module); xc = NULL; + while ((xc = xml_child_each(x, xc, CX_ELMNT)) != NULL) { - /* Skip if not yang dir */ - if (strcmp(xml_name(xc), "CLICON_YANG_DIR") != 0 && - strcmp(xml_name(xc), "CLICON_YANG_MAIN_DIR") != 0) - continue; - dir = xml_body(xc); - /* get all matching files in this directory */ - if ((ndp = clicon_file_dirent(dir, - &dp, - cbuf_get(regex), - S_IFREG)) < 0) - goto done; - /* Entries are sorted, last entry should be most recent date - */ - if (ndp != 0){ - cprintf(fbuf, "%s/%s", dir, dp[ndp-1].d_name); - retval = 1; - goto done; - } + /* Skip if not yang dir */ + if (strcmp(xml_name(xc), "CLICON_YANG_DIR") != 0 && + strcmp(xml_name(xc), "CLICON_YANG_MAIN_DIR") != 0) + continue; + dir = xml_body(xc); + + /* get all matching files in this directory */ + dp = (char **)malloc(sizeof(char *)); + if ((ndp = clicon_files_recursive(dir, + cbuf_get(regex), + dp, + &nent)) < 0) { + goto done; + } + + /* Entries are sorted, last entry should be most recent date + */ + if (ndp != 0){ + cprintf(fbuf, "%s", dp[ndp-1]); + + for (i = 0; i < nent; i++) + if (dp[i]) + free(dp[i]); + + retval = 1; + goto done; + } } - ok: +ok: retval = 0; - done: +done: if (regex) - cbuf_free(regex); + cbuf_free(regex); if (dp) - free(dp); + free(dp); return retval; } @@ -1656,8 +1668,8 @@ yang_spec_load_dir(clicon_handle h, /* Load all yang files in dir */ for (i = 0; i < ndp; i++) { /* base = module name [+ @rev ] + .yang */ - if (oldbase) - free(oldbase); + if (oldbase) + free(oldbase); oldbase = base; base = NULL; revf = 0; diff --git a/test/test_cli_auto_genmodel.sh b/test/test_cli_auto_genmodel.sh index 70593aa9..5f7b7d22 100755 --- a/test/test_cli_auto_genmodel.sh +++ b/test/test_cli_auto_genmodel.sh @@ -33,14 +33,12 @@ if [ ! -d "$OPENCONFIG" ]; then if [ "$s" = $0 ]; then exit 0; else return 0; fi fi -OCDIR=$OPENCONFIG/release/models - cat < $cfg $cfg /usr/local/share/clixon $dir - $OCDIR/ + $OPENCONFIG/ $dir /usr/local/lib/$APPNAME/backend $clidir diff --git a/test/test_openconfig.sh b/test/test_openconfig.sh index f7c23e2c..bbaf2487 100755 --- a/test/test_openconfig.sh +++ b/test/test_openconfig.sh @@ -23,46 +23,12 @@ if [ ! -d "$OPENCONFIG" ]; then if [ "$s" = $0 ]; then exit 0; else return 0; fi fi -OCDIR=$OPENCONFIG/release/models - cat < $cfg $cfg ietf-netconf:startup /usr/local/share/clixon - $OCDIR - $OCDIR/acl - $OCDIR/aft - $OCDIR/bfd - $OCDIR/bgp - $OCDIR/catalog - $OCDIR/firewall - $OCDIR/interfaces - $OCDIR/isis - $OCDIR/lacp - $OCDIR/lldp - $OCDIR/local-routing - $OCDIR/macsec - $OCDIR/mpls - $OCDIR/multicast - $OCDIR/network-instance - $OCDIR/openflow - $OCDIR/optical-transport - $OCDIR/ospf - $OCDIR/platform - $OCDIR/policy - $OCDIR/policy-forwarding - $OCDIR/probes - $OCDIR/qos - $OCDIR/relay-agent - $OCDIR/rib - $OCDIR/segment-routing - $OCDIR/stp - $OCDIR/system - $OCDIR/telemetry - $OCDIR/types - $OCDIR/vlan - $OCDIR/wifi + $OPENCONFIG /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli $APPNAME @@ -73,7 +39,7 @@ cat < $cfg EOF -files=$(find $OCDIR -name "*.yang") +files=$(find $OPENCONFIG -name "*.yang") # Count nr of modules (exclude submodule) Assume "module" or "submodule" # first word on first line let ms=0; # Nr of modules diff --git a/test/test_openconfig_interfaces.sh b/test/test_openconfig_interfaces.sh index 2ca02831..d1302a76 100755 --- a/test/test_openconfig_interfaces.sh +++ b/test/test_openconfig_interfaces.sh @@ -17,18 +17,12 @@ if [ ! -d "$OPENCONFIG" ]; then if [ "$s" = $0 ]; then exit 0; else return 0; fi fi -OCDIR=$OPENCONFIG/release/models - cat < $cfg $cfg ietf-netconf:startup /usr/local/share/clixon - $OCDIR - $OCDIR/interfaces - $OCDIR/types - $OCDIR/vlan - $OCDIR/platform + $OPENCONFIG $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli diff --git a/test/test_upgrade_repair.sh b/test/test_upgrade_repair.sh index 728578eb..dfc701bf 100755 --- a/test/test_upgrade_repair.sh +++ b/test/test_upgrade_repair.sh @@ -59,7 +59,7 @@ cat < $cfg $cfg ietf-netconf:startup /usr/local/share/clixon - $dir + $dir $dir /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/lib/example/backend