diff options
-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; } |