diff options
author | Michael Larson <slioch@slioch.vyatta.com> | 2010-04-13 11:50:23 -0700 |
---|---|---|
committer | Michael Larson <slioch@slioch.vyatta.com> | 2010-04-13 11:50:23 -0700 |
commit | 7c03bbb617c8e8c5bc9a553f25b79d43a8e40623 (patch) | |
tree | 322afdeb7acdd3126011910bfa115cd7bc388b4e | |
parent | 3ea2bdb717ceb9ef1f2843e3416ccf6ad0a54583 (diff) | |
download | vyatta-cfg-7c03bbb617c8e8c5bc9a553f25b79d43a8e40623.tar.gz vyatta-cfg-7c03bbb617c8e8c5bc9a553f25b79d43a8e40623.zip |
fix for bug 2176.
Embedded leaf nodes can now be supported in the cli structure. In additional an arbritrary limit can be set on the number of multinode values allowed.
Format in the node.def is:
tag: [u32]
or
multi: [u32]
For the special case of a leaf node the value for u32 is 1. In this case the operation applied to the node is to replace the node with the set value. This generates a
delete of the old tree structure from the embedded leaf and a set of the new tree structure from the embedded leaf.
-rwxr-xr-x | etc/bash_completion.d/20vyatta-cfg | 4 | ||||
-rw-r--r-- | src/cli_parse.y | 39 | ||||
-rw-r--r-- | src/cli_val.h | 2 | ||||
-rw-r--r-- | src/commit2.c | 2 | ||||
-rw-r--r-- | src/common/defs.h | 1 | ||||
-rw-r--r-- | src/common/unionfs.c | 9 | ||||
-rw-r--r-- | src/set.c | 57 |
7 files changed, 110 insertions, 4 deletions
diff --git a/etc/bash_completion.d/20vyatta-cfg b/etc/bash_completion.d/20vyatta-cfg index d08c9d8..4463ee3 100755 --- a/etc/bash_completion.d/20vyatta-cfg +++ b/etc/bash_completion.d/20vyatta-cfg @@ -633,8 +633,8 @@ vyatta_parse_tmpl () s/^\([^;]\+\);.*$/\1 )/ s/[ ]*,[ ]*/ /gp } - s/^tag:/vyatta_cfg_tag=1/p - s/^multi:/vyatta_cfg_multi=1/p + s/^tag:.*/vyatta_cfg_tag=1/p + s/^multi:.*/vyatta_cfg_multi=1/p s/^type:[ ]\+\([^ ;]\+\)\(;.*\)\?/vyatta_cfg_type=\1/p ' $1` diff --git a/src/cli_parse.y b/src/cli_parse.y index dd3d7d2..89c6638 100644 --- a/src/cli_parse.y +++ b/src/cli_parse.y @@ -89,8 +89,45 @@ otherinput: type EOL ; tag: /* empty */ - | TAG EOL {parse_defp->tag = TRUE;} + | TAG EOL {parse_defp->tag = TRUE;} + | TAG VALUE { + parse_defp->tag = TRUE; + char *tmp = $2.val; + long long int cval = 0; + char *endp = NULL; + errno = 0; + cval = strtoll(tmp, &endp, 10); + if (($2.val_type != INT_TYPE) + || (errno == ERANGE + && (cval == LLONG_MAX || cval == LLONG_MIN)) + || (errno != 0 && cval == 0) + || (*endp != '\0') || (cval < 0) || (cval > UINT_MAX)) { + yy_cli_parse_error((const char *) + "Tag must be <u32>\n"); + } else { + parse_defp->def_tag = cval; + } + } | MULTI EOL {parse_defp->multi = TRUE;} + | MULTI VALUE + { + parse_defp->multi = TRUE; + char *tmp = $2.val; + long long int cval = 0; + char *endp = NULL; + errno = 0; + cval = strtoll(tmp, &endp, 10); + if (($2.val_type != INT_TYPE) + || (errno == ERANGE + && (cval == LLONG_MAX || cval == LLONG_MIN)) + || (errno != 0 && cval == 0) + || (*endp != '\0') || (cval < 0) || (cval > UINT_MAX)) { + yy_cli_parse_error((const char *) + "Tag must be <u32>\n"); + } else { + parse_defp->def_multi = cval; + } + } ; type: TYPE TYPE_DEF SEMI STRING diff --git a/src/cli_val.h b/src/cli_val.h index e8fbe83..9b3bcda 100644 --- a/src/cli_val.h +++ b/src/cli_val.h @@ -106,6 +106,8 @@ typedef struct { char *def_node_help; char *def_default; unsigned int def_priority; + unsigned int def_tag; + unsigned int def_multi; boolean tag; boolean multi; vtw_list actions[top_act]; diff --git a/src/commit2.c b/src/commit2.c index 3143e51..1b22bf8 100644 --- a/src/commit2.c +++ b/src/commit2.c @@ -816,7 +816,7 @@ dump_func(GNode *node, gpointer data) fprintf(out," [VALUE]"); } if (((struct VyattaNode*)gp)->_config._multi == TRUE) { - fprintf(out," [MULTI]"); + fprintf(out," [MULTI(%d)]",((struct VyattaNode*)gp)->_config._limit); } if (((struct VyattaNode*)gp)->_config._def.actions[syntax_act].vtw_list_head && ((struct VyattaNode*)gp)->_config._def.actions[syntax_act].vtw_list_head->vtw_node_aux == 0) { diff --git a/src/common/defs.h b/src/common/defs.h index 934364a..8c68c1d 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -55,6 +55,7 @@ struct Config { boolean _multi; int _priority; + int _limit; vtw_def _def; //keep this here char* _help; char* _default; diff --git a/src/common/unionfs.c b/src/common/unionfs.c index b573d17..2220d73 100644 --- a/src/common/unionfs.c +++ b/src/common/unionfs.c @@ -225,6 +225,15 @@ retrieve_data(char* rel_data_path, GNode *node, char* root, NODE_OPERATION op) } //either multi or tag--shouldn't have made a difference, but arkady was confused. vn->_config._multi = (def.tag | def.multi); + if (def.def_tag > 0) { + vn->_config._limit = def.def_tag; + } + else if (def.def_multi > 0) { + vn->_config._limit = def.def_multi; + } + else { + vn->_config._limit = 0; + } } } @@ -91,6 +91,63 @@ boolean set_validate(vtw_def *defp, char *valp, boolean empty_val) } return TRUE; } + + //apply limit count here, needs to be defined as a tag,multi and have a value set + if ((defp->tag || defp->multi) && (defp->def_tag > 0 || defp->def_multi > 0)) { + //get count of siblings + + char path[2048]; + char val[2048]; + char last_val[2048]; + char *pos = rindex(m_path.path,'/'); + if (pos != NULL) { + int offset = pos - m_path.path; + + strncpy(path,m_path.path,offset); + path[offset] = '\0'; + + strncpy(val,m_path.path + offset + 1, strlen(m_path.path) - offset - 1); + val[strlen(m_path.path) - offset - 1] = '\0'; + + // fprintf(out_stream,"val: %s, offset: %d, path: %s\n",val,offset,m_path.path); + + int file_count = 0; + struct dirent* entry; + DIR* dirp = opendir(path); /* There should be error handling after this */ + if (dirp != NULL) { + while ((entry = readdir(dirp)) != NULL) { + if (strcmp(entry->d_name,".") != 0 && + strcmp(entry->d_name,"..") != 0) { + strcpy(last_val,entry->d_name); + file_count++; + } + } + closedir(dirp); + + if (defp->tag && file_count == 1 && defp->def_tag == 1) { + //this is the special case, where the previous value should be deleted here... + char command[8192]; + //let unionfs handle the diff + sprintf(command, "mv %s/%s %s/%s", path,last_val,path,val); + system(command); + } + + if (defp->tag) { + if (defp->def_tag > 1 && file_count >= defp->def_tag) { + fprintf(out_stream,"Number of values exceeded for %s, allowed: %d, actual: %d\n",val,defp->def_tag,file_count); + return FALSE; + } + } + else { + if (defp->def_multi > 1 && file_count >= defp->def_multi) { + fprintf(out_stream,"Number of values exceeded for %s, allowed: %d, actual: %d\n",val,defp->def_multi,file_count); + return FALSE; + } + } + } + } + } + res = validate_value(defp, valp); return res; } |