summaryrefslogtreecommitdiff
path: root/src/cstore/cstore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/cstore/cstore.cpp')
-rw-r--r--src/cstore/cstore.cpp503
1 files changed, 239 insertions, 264 deletions
diff --git a/src/cstore/cstore.cpp b/src/cstore/cstore.cpp
index 39c57cd..f32e6ec 100644
--- a/src/cstore/cstore.cpp
+++ b/src/cstore/cstore.cpp
@@ -23,6 +23,7 @@
#include <fcntl.h>
#include <algorithm>
#include <sstream>
+#include <memory>
// for debian's version comparison algorithm
#define APT_COMPATIBILITY 986
@@ -121,22 +122,19 @@ Cstore::createCstore(const string& session_id, string& env)
bool
Cstore::validateTmplPath(const vector<string>& path_comps, bool validate_vals)
{
- vtw_def def;
// if we can get parsed tmpl, path is valid
- return get_parsed_tmpl(path_comps, validate_vals, def);
+ auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, validate_vals));
+ return (def.get() != 0);
}
-/* same as above but return parsed template.
- * def: (output) parsed template.
+/* same as above but return parsed template. return 0 if invalid/failed.
* note: if last path component is "value" (i.e., def.is_value), parsed
* template is actually at "full path - 1". see get_parsed_tmpl() for details.
*/
-bool
-Cstore::validateTmplPath(const vector<string>& path_comps, bool validate_vals,
- vtw_def& def)
+Ctemplate *
+Cstore::parseTmpl(const vector<string>& path_comps, bool validate_vals)
{
- // if we can get parsed tmpl, path is valid
- return get_parsed_tmpl(path_comps, validate_vals, def);
+ return get_parsed_tmpl(path_comps, validate_vals);
}
/* get parsed template of specified path as a string-string map
@@ -147,7 +145,6 @@ bool
Cstore::getParsedTmpl(const vector<string>& path_comps,
Cstore::MapT<string, string>& tmap, bool allow_val)
{
- vtw_def def;
/* currently this function is used outside actual CLI operations, mainly
* from the perl API. since value validation is from the original CLI
* implementation, it doesn't seem to behave correctly in such cases,
@@ -155,54 +152,55 @@ Cstore::getParsedTmpl(const vector<string>& path_comps,
*
* anyway, not validating values in the following call.
*/
- if (!get_parsed_tmpl(path_comps, false, def)) {
+ auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false));
+ if (!def.get()) {
return false;
}
- if (!allow_val && def.is_value) {
+ if (!allow_val && def->isValue()) {
/* note: !allow_val means specified path must terminate at an actual
* "node", not a "value". so this fails since path ends in value.
* this emulates the original perl API behavior.
*/
return false;
}
- if (def.is_value) {
+ if (def->isValue()) {
tmap["is_value"] = "1";
}
// make the map
- if (def.def_type != ERROR_TYPE) {
- tmap["type"] = type_to_name(def.def_type);
+ if (!def->isTypeless(1)) {
+ tmap["type"] = def->getTypeName(1);
}
- if (def.def_type2 != ERROR_TYPE) {
- tmap["type2"] = type_to_name(def.def_type2);
+ if (!def->isTypeless(2)) {
+ tmap["type2"] = def->getTypeName(2);
}
- if (def.def_node_help) {
- tmap["help"] = def.def_node_help;
+ if (def->getNodeHelp()) {
+ tmap["help"] = def->getNodeHelp();
}
- if (def.multi) {
+ if (def->isMulti()) {
tmap["multi"] = "1";
- if (def.def_multi > 0) {
+ if (def->getMultiLimit() > 0) {
ostringstream s;
- s << def.def_multi;
+ s << def->getMultiLimit();
tmap["limit"] = s.str();
}
- } else if (def.tag) {
+ } else if (def->isTag()) {
tmap["tag"] = "1";
- if (def.def_tag > 0) {
+ if (def->getTagLimit() > 0) {
ostringstream s;
- s << def.def_tag;
+ s << def->getTagLimit();
tmap["limit"] = s.str();
}
- } else if (def.def_default) {
- tmap["default"] = def.def_default;
+ } else if (def->getDefault()) {
+ tmap["default"] = def->getDefault();
}
- if (def.def_enumeration) {
- tmap["enum"] = def.def_enumeration;
+ if (def->getEnumeration()) {
+ tmap["enum"] = def->getEnumeration();
}
- if (def.def_allowed) {
- tmap["allowed"] = def.def_allowed;
+ if (def->getAllowed()) {
+ tmap["allowed"] = def->getAllowed();
}
- if (def.def_val_help) {
- tmap["val_help"] = def.def_val_help;
+ if (def->getValHelp()) {
+ tmap["val_help"] = def->getValHelp();
}
return true;
}
@@ -223,19 +221,23 @@ Cstore::tmplGetChildNodes(const vector<string>& path_comps,
}
/* delete specified "logical path" from "working config".
- * def: parsed template corresponding to logical path path_comps.
* return true if successful. otherwise return false.
- * note: assume specified path has been validated
- * (i.e., validateDeletePath()).
*/
bool
-Cstore::deleteCfgPath(const vector<string>& path_comps, const vtw_def& def)
+Cstore::deleteCfgPath(const vector<string>& path_comps)
{
ASSERT_IN_SESSION;
+ string terr;
+ auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
+ if (!def.get()) {
+ output_user("%s\n", terr.c_str());
+ return false;
+ }
+
if (!cfg_path_exists(path_comps, false, true)) {
output_user("Nothing to delete (the specified %s does not exist)\n",
- (!def.is_value || def.tag) ? "node" : "value");
+ (!def->isValue() || def->isTag()) ? "node" : "value");
// treat as success
return true;
}
@@ -247,11 +249,11 @@ Cstore::deleteCfgPath(const vector<string>& path_comps, const vtw_def& def)
* 2. no default value
* => remove config path
*/
- if (def.def_default) {
+ if (def->getDefault()) {
// case 1. construct path for value file.
SAVE_PATHS;
append_cfg_path(path_comps);
- if (def.is_value) {
+ if (def->isValue()) {
// last comp is "value". need to go up 1 level.
pop_cfg_path();
}
@@ -261,7 +263,7 @@ Cstore::deleteCfgPath(const vector<string>& path_comps, const vtw_def& def)
* also deactivated. note that unmark_deactivated() succeeds if it's
* not marked deactivated. also mark "changed".
*/
- bool ret = (write_value(def.def_default) && mark_display_default()
+ bool ret = (write_value(def->getDefault()) && mark_display_default()
&& unmark_deactivated() && mark_changed_with_ancestors());
if (!ret) {
output_user("Failed to set default value during delete\n");
@@ -287,15 +289,15 @@ Cstore::deleteCfgPath(const vector<string>& path_comps, const vtw_def& def)
bool ret = false;
SAVE_PATHS;
append_cfg_path(path_comps);
- if (!def.is_value) {
+ if (!def->isValue()) {
// sub-case (2)
ret = remove_node();
} else {
// last comp is value
- if (def.tag) {
+ if (def->isTag()) {
// sub-case (1c)
ret = remove_tag();
- } else if (def.multi) {
+ } else if (def->isMulti()) {
// sub-case (1b)
pop_cfg_path();
ret = remove_value_from_multi(path_comps[path_comps.size() - 1]);
@@ -325,17 +327,17 @@ Cstore::validateSetPath(const vector<string>& path_comps)
ASSERT_IN_SESSION;
// if we can get parsed tmpl, path is valid
- vtw_def def;
string terr;
- if (!get_parsed_tmpl(path_comps, true, def, terr)) {
+ auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, true, terr));
+ if (!def.get()) {
output_user("%s\n", terr.c_str());
return false;
}
bool ret = true;
SAVE_PATHS;
- if (!def.is_value) {
- if (def.def_type != ERROR_TYPE) {
+ if (!def->isValue()) {
+ if (!def->isTypeless()) {
/* disallow setting value node without value
* note: different from old behavior, which only disallow setting a
* single-value node without value. now all value nodes
@@ -353,7 +355,7 @@ Cstore::validateSetPath(const vector<string>& path_comps)
*/
append_cfg_path(path_comps);
append_tmpl_path(path_comps);
- if (!validate_val(&def, "")) {
+ if (!validate_val(def.get(), "")) {
ret = false;
}
}
@@ -362,22 +364,6 @@ Cstore::validateSetPath(const vector<string>& path_comps)
return ret;
}
-/* check if specified "logical path" is valid for "delete" operation
- * return true if valid. otherwise return false.
- */
-bool
-Cstore::validateDeletePath(const vector<string>& path_comps, vtw_def& def)
-{
- ASSERT_IN_SESSION;
-
- string terr;
- if (!get_parsed_tmpl(path_comps, false, def, terr)) {
- output_user("%s\n", terr.c_str());
- return false;
- }
- return true;
-}
-
/* check if specified "logical path" is valid for "activate" operation
* return true if valid. otherwise return false.
*/
@@ -386,8 +372,8 @@ Cstore::validateActivatePath(const vector<string>& path_comps)
{
ASSERT_IN_SESSION;
- vtw_def def;
- if (!validate_act_deact(path_comps, "activate", def)) {
+ auto_ptr<Ctemplate> def(validate_act_deact(path_comps, "activate"));
+ if (!def.get()) {
return false;
}
if (!cfgPathMarkedDeactivated(path_comps)) {
@@ -396,7 +382,7 @@ Cstore::validateActivatePath(const vector<string>& path_comps)
return false;
}
bool ret = true;
- if (def.is_value && def.tag && def.def_tag > 0) {
+ if (def->isTagValue() && def->getTagLimit() > 0) {
// we are activating a tag, and there is a limit on number of tags.
vector<string> cnodes;
SAVE_PATHS;
@@ -404,10 +390,10 @@ Cstore::validateActivatePath(const vector<string>& path_comps)
string t = pop_cfg_path();
// get child nodes, excluding deactivated ones.
get_all_child_node_names(cnodes, false, false);
- if (def.def_tag <= cnodes.size()) {
+ if (def->getTagLimit() <= cnodes.size()) {
// limit exceeded
output_user("Cannot activate \"%s\": number of values exceeds limit "
- "(%d allowed)\n", t.c_str(), def.def_tag);
+ "(%d allowed)\n", t.c_str(), def->getTagLimit());
ret = false;
}
RESTORE_PATHS;
@@ -423,8 +409,8 @@ Cstore::validateDeactivatePath(const vector<string>& path_comps)
{
ASSERT_IN_SESSION;
- vtw_def def;
- return validate_act_deact(path_comps, "deactivate", def);
+ auto_ptr<Ctemplate> def(validate_act_deact(path_comps, "deactivate"));
+ return (def.get() != 0);
}
/* check if specified "logical path" is valid for "edit" operation.
@@ -437,9 +423,9 @@ Cstore::getEditEnv(const vector<string>& path_comps, string& env)
{
ASSERT_IN_SESSION;
- vtw_def def;
string terr;
- if (!get_parsed_tmpl(path_comps, false, def, terr)) {
+ auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
+ if (!def.get()) {
output_user("%s\n", terr.c_str());
return false;
}
@@ -448,8 +434,7 @@ Cstore::getEditEnv(const vector<string>& path_comps, string& env)
* OR
* (2) "typeless node"
*/
- if (!(def.is_value && def.tag)
- && !(!def.is_value && def.def_type == ERROR_TYPE)) {
+ if (!def->isTagValue() && !def->isTypeless()) {
// neither "tag value" nor "typeless node"
output_user("The \"edit\" command cannot be issued "
"at the specified level\n");
@@ -502,19 +487,16 @@ Cstore::getEditUpEnv(string& env)
return false;
}
- /* get_parsed_tmpl() does not allow empty path, so use one component
- * from current paths.
- */
- vtw_def def;
string terr;
vector<string> path_comps;
- if (!get_parsed_tmpl(path_comps, false, def, terr)) {
+ auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
+ if (!def.get()) {
// this should not happen since it's using existing levels
output_user("%s\n", terr.c_str());
return false;
}
SAVE_PATHS;
- if (def.is_value && def.tag) {
+ if (def->isTagValue()) {
// edit level is at "tag value". go up 1 extra level.
pop_cfg_path();
pop_tmpl_path();
@@ -574,9 +556,13 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
bool ret = false;
SAVE_PATHS;
do {
- vtw_def def;
+ bool is_typeless = true;
+ bool is_leaf_value = false;
+ bool is_value = false;
+ auto_ptr<Ctemplate> def;
if (pcomps.size() > 0) {
- if (!get_parsed_tmpl(pcomps, false, def)) {
+ def.reset(get_parsed_tmpl(pcomps, false));
+ if (!def.get()) {
// invalid path
break;
}
@@ -586,16 +572,20 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
}
append_cfg_path(pcomps);
append_tmpl_path(pcomps);
+ is_typeless = def->isTypeless();
+ is_leaf_value = def->isLeafValue();
+ is_value = def->isValue();
} else {
- // we are at root. simulate a typeless node.
- def.def_type = ERROR_TYPE;
- def.tag = def.multi = def.is_value = 0;
+ /* we are at root. default values simulate a typeless node so nop.
+ * note that in this case def is "empty", so must ensure that it's
+ * not used.
+ */
}
/* at this point, cfg and tmpl paths are constructed up to the comp
* before last_comp, and def is parsed.
*/
- if (def.is_value && !def.tag) {
+ if (is_leaf_value) {
// invalid path (this means the comp before last_comp is a leaf value)
break;
}
@@ -605,7 +595,7 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
string comp_help;
vector<pair<string, string> > help_pairs;
bool last_comp_val = true;
- if (def.def_type == ERROR_TYPE || def.is_value) {
+ if (is_typeless || is_value) {
/* path so far is at a typeless node OR a tag value (tag already
* checked above):
* completions: from tmpl children.
@@ -615,6 +605,9 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
*
* note: for such completions, we filter non-existent nodes if
* necessary.
+ *
+ * also, the "root" node case above will reach this block, so
+ * must not use def in this block.
*/
vector<string> ufvec;
if (exists_only) {
@@ -638,9 +631,9 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
for (size_t i = 0; i < comp_vals.size(); i++) {
pair<string, string> hpair(comp_vals[i], "");
push_tmpl_path(hpair.first);
- vtw_def cdef;
- if (tmpl_parse(cdef) && cdef.def_node_help) {
- hpair.second = cdef.def_node_help;
+ auto_ptr<Ctemplate> cdef(tmpl_parse());
+ if (cdef.get() && cdef->getNodeHelp()) {
+ hpair.second = cdef->getNodeHelp();
} else {
hpair.second = "<No help text available>";
}
@@ -653,9 +646,11 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
/* path so far is at a "value node".
* note: follow the original implementation and don't filter
* non-existent values for such completions
+ *
+ * also, cannot be "root" node if we reach here, so def can be used.
*/
// first, handle completions.
- if (def.tag) {
+ if (def->isTag()) {
// it's a "tag node". get completions from tag values.
get_all_child_node_names(comp_vals, false, true);
} else {
@@ -667,7 +662,7 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
* "enumeration"
* "$VAR(@) in ..."
*/
- if (def.def_enumeration || def.def_allowed) {
+ if (def->getEnumeration() || def->getAllowed()) {
/* do "enumeration" or "allowed".
* note: emulate original implementation and set up COMP_WORDS and
* COMP_CWORD environment variables. these are needed by some
@@ -682,10 +677,10 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
cmd_str += (" '" + comps[i] + "'");
}
cmd_str += "); ";
- if (def.def_enumeration) {
- cmd_str += (C_ENUM_SCRIPT_DIR + "/" + def.def_enumeration);
+ if (def->getEnumeration()) {
+ cmd_str += (C_ENUM_SCRIPT_DIR + "/" + def->getEnumeration());
} else {
- string astr = def.def_allowed;
+ string astr = def->getAllowed();
shell_escape_squotes(astr);
cmd_str += "_cstore_internal_allowed () { eval '";
cmd_str += astr;
@@ -711,10 +706,10 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
* shell into an array of values.
*/
free(buf);
- } else if (def.actions[syntax_act].vtw_list_head) {
+ } else if (def->getActions(syntax_act)->vtw_list_head) {
// look for "self ref in values" from syntax
const valstruct *vals = get_syntax_self_in_valstruct(
- def.actions[syntax_act].vtw_list_head);
+ def->getActions(syntax_act)->vtw_list_head);
if (vals) {
if (vals->cnt == 0 && vals->val) {
comp_vals.push_back(vals->val);
@@ -729,23 +724,23 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
}
// now handle help.
- if (def.def_comp_help) {
+ if (def->getCompHelp()) {
// "comp_help" exists.
- comp_help = def.def_comp_help;
+ comp_help = def->getCompHelp();
shell_escape_squotes(comp_help);
}
- if (def.def_val_help) {
+ if (def->getValHelp()) {
// has val_help. first separate individual lines.
size_t start = 0, i = 0;
vector<string> vhelps;
- for (i = 0; def.def_val_help[i]; i++) {
- if (def.def_val_help[i] == '\n') {
- vhelps.push_back(string(&(def.def_val_help[start]), i - start));
+ for (i = 0; (def->getValHelp())[i]; i++) {
+ if ((def->getValHelp())[i] == '\n') {
+ vhelps.push_back(string(&((def->getValHelp())[start]), i - start));
start = i + 1;
}
}
if (start < i) {
- vhelps.push_back(string(&(def.def_val_help[start]), i - start));
+ vhelps.push_back(string(&((def->getValHelp())[start]), i - start));
}
// process each line
@@ -753,15 +748,15 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
size_t sc;
if ((sc = vhelps[i].find(';')) == vhelps[i].npos) {
// no ';'
- if (i == 0 && def.def_type != ERROR_TYPE) {
+ if (i == 0 && !def->isTypeless(1)) {
// first val_help. pair with "type".
help_pairs.push_back(pair<string, string>(
- type_to_name(def.def_type), vhelps[i]));
+ def->getTypeName(1), vhelps[i]));
}
- if (i == 1 && def.def_type2 != ERROR_TYPE) {
- // second val_help. pair with "type2".
+ if (i == 1 && !def->isTypeless(2)) {
+ // second val_help. pair with second "type".
help_pairs.push_back(pair<string, string>(
- type_to_name(def.def_type2), vhelps[i]));
+ def->getTypeName(2), vhelps[i]));
}
} else {
// ';' at index sc
@@ -770,13 +765,17 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
vhelps[i].substr(sc + 1)));
}
}
- } else if (def.def_type && def.def_node_help) {
+ } else if (!def->isTypeless(1) && def->getNodeHelp()) {
// simple case. just use "type" and "help"
- help_pairs.push_back(pair<string, string>(type_to_name(def.def_type),
- def.def_node_help));
+ help_pairs.push_back(pair<string, string>(def->getTypeName(1),
+ def->getNodeHelp()));
}
}
+ /* from this point on cannot use def (since the "root" node case
+ * can reach here).
+ */
+
// this var is the array of possible completions
env = (C_ENV_SHAPI_COMP_VALS + "=(");
for (size_t i = 0; i < comp_vals.size(); i++) {
@@ -896,61 +895,6 @@ Cstore::validateMoveArgs(const vector<string>& args)
return ret;
}
-/* check if specified "arguments" is valid for "comment" operation
- * return true if valid. otherwise return false.
- */
-bool
-Cstore::validateCommentArgs(const vector<string>& args, vtw_def& def)
-{
- ASSERT_IN_SESSION;
-
- /* separate path from comment.
- * follow the original implementation: the last arg is the comment, and
- * everything else is part of the path.
- */
- vector<string> path_comps(args);
- string comment = args.back();
- path_comps.pop_back();
-
- // check the path
- string terr;
- if (!get_parsed_tmpl(path_comps, false, def, terr)) {
- output_user("%s\n", terr.c_str());
- return false;
- }
- // here we want to include deactivated nodes
- if (!cfg_path_exists(path_comps, false, true)) {
- output_user("The specified config node does not exist\n");
- return false;
- }
- if (def.is_value && !def.tag) {
- /* XXX differ from the original implementation, which allows commenting
- * on a "value" BUT silently "promote" the comment to the parent
- * "node". this will probably create confusion for the user.
- *
- * just disallow such cases here.
- */
- output_user("Cannot comment on config values\n");
- return false;
- }
- if (def.tag && !def.is_value) {
- /* XXX follow original implementation and disallow comment on a
- * "tag node". this is because "show" does not display such
- * comments (see bug 5794).
- */
- output_user("Cannot add comment at this level\n");
- return false;
- }
- if (comment.find_first_of('*') != string::npos) {
- // don't allow '*'. this is due to config files using C-style /**/
- // comments. this probably belongs to lower-level, but we are enforcing
- // it here.
- output_user("Cannot use the '*' character in a comment\n");
- return false;
- }
- return true;
-}
-
/* perform rename in "working config" according to specified args.
* return true if successful. otherwise return false.
* note: assume args are already validated (i.e., validateRenameArgs()).
@@ -1000,15 +944,56 @@ Cstore::copyCfgPath(const vector<string>& args)
* return true if valid. otherwise return false.
*/
bool
-Cstore::commentCfgPath(const vector<string>& args, const vtw_def& def)
+Cstore::commentCfgPath(const vector<string>& args)
{
ASSERT_IN_SESSION;
- // separate path from comment
+ /* separate path from comment.
+ * follow the original implementation: the last arg is the comment, and
+ * everything else is part of the path.
+ */
vector<string> path_comps(args);
string comment = args.back();
path_comps.pop_back();
+ // check the path
+ string terr;
+ auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
+ if (!def.get()) {
+ output_user("%s\n", terr.c_str());
+ return false;
+ }
+ // here we want to include deactivated nodes
+ if (!cfg_path_exists(path_comps, false, true)) {
+ output_user("The specified config node does not exist\n");
+ return false;
+ }
+ if (def->isLeafValue()) {
+ /* XXX differ from the original implementation, which allows commenting
+ * on a "value" BUT silently "promote" the comment to the parent
+ * "node". this will probably create confusion for the user.
+ *
+ * just disallow such cases here.
+ */
+ output_user("Cannot comment on config values\n");
+ return false;
+ }
+ if (def->isTagNode()) {
+ /* XXX follow original implementation and disallow comment on a
+ * "tag node". this is because "show" does not display such
+ * comments (see bug 5794).
+ */
+ output_user("Cannot add comment at this level\n");
+ return false;
+ }
+ if (comment.find_first_of('*') != string::npos) {
+ // don't allow '*'. this is due to config files using C-style /**/
+ // comments. this probably belongs to lower-level, but we are enforcing
+ // it here.
+ output_user("Cannot use the '*' character in a comment\n");
+ return false;
+ }
+
SAVE_PATHS;
append_cfg_path(path_comps);
bool ret;
@@ -1344,8 +1329,8 @@ Cstore::cfgPathGetValueDA(const vector<string>& path_comps, string& value,
ASSERT_IN_SESSION;
}
- vtw_def def;
- if (!get_parsed_tmpl(path_comps, false, def)) {
+ auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false));
+ if (!def.get()) {
// invalid node
return false;
}
@@ -1355,7 +1340,7 @@ Cstore::cfgPathGetValueDA(const vector<string>& path_comps, string& value,
* original API will return a single string that includes all values.
* this new function will return failure in such cases.
*/
- if (def.is_value || def.multi || def.tag || def.def_type == ERROR_TYPE) {
+ if (!def->isSingleLeafNode()) {
// specified path is not a single-value node
return false;
}
@@ -1405,8 +1390,8 @@ Cstore::cfgPathGetValuesDA(const vector<string>& path_comps,
ASSERT_IN_SESSION;
}
- vtw_def def;
- if (!get_parsed_tmpl(path_comps, false, def)) {
+ auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false));
+ if (!def.get()) {
// invalid node
return false;
}
@@ -1416,7 +1401,7 @@ Cstore::cfgPathGetValuesDA(const vector<string>& path_comps,
* original API will return the node's value. this new function
* will return failure in such cases.
*/
- if (def.is_value || !def.multi || def.tag || def.def_type == ERROR_TYPE) {
+ if (!def->isMultiLeafNode()) {
// specified path is not a multi-value node
return false;
}
@@ -1551,8 +1536,8 @@ Cstore::cfgPathDefault(const vector<string>& path_comps, bool active_cfg)
bool
Cstore::cfgPathEffective(const vector<string>& path_comps)
{
- vtw_def def;
- if (!validateTmplPath(path_comps, false, def)) {
+ auto_ptr<Ctemplate> def(parseTmpl(path_comps, false));
+ if (!def.get()) {
// invalid path
return false;
}
@@ -1573,10 +1558,10 @@ Cstore::cfgPathEffective(const vector<string>& path_comps)
append_cfg_path(path_comps);
if (!in_active && in_work) {
// check if case (2)
- ret = marked_committed(def, true);
+ ret = marked_committed(def.get(), true);
} else if (in_active && !in_work) {
// check if case (3)
- ret = !marked_committed(def, false);
+ ret = !marked_committed(def.get(), false);
}
RESTORE_PATHS;
@@ -1765,15 +1750,12 @@ Cstore::setVarRef(const string& ref_str, const string& value, bool to_active)
bool ret = false;
if (vref.getSetPath(pcomps)) {
reset_paths();
- vtw_def def;
- if (get_parsed_tmpl(pcomps, false, def)) {
- if (!def.is_value && !def.tag && !def.multi
- && def.def_type != ERROR_TYPE) {
- // currently only support single-value node
- append_cfg_path(pcomps);
- if (write_value(value, to_active)) {
- ret = true;
- }
+ auto_ptr<Ctemplate> def(get_parsed_tmpl(pcomps, false));
+ if (def.get() && def->isSingleLeafNode()) {
+ // currently only support single-value node
+ append_cfg_path(pcomps);
+ if (write_value(value, to_active)) {
+ ret = true;
}
}
}
@@ -1859,9 +1841,7 @@ Cstore::loadFile(const char *filename)
// "apply" the changes to the working config
for (size_t i = 0; i < del_list.size(); i++) {
- vtw_def def;
- if (!validateDeletePath(del_list[i], def)
- || !deleteCfgPath(del_list[i], def)) {
+ if (!deleteCfgPath(del_list[i])) {
print_str_vec("Delete [", "] failed\n", del_list[i], "'");
}
}
@@ -1871,9 +1851,7 @@ Cstore::loadFile(const char *filename)
}
}
for (size_t i = 0; i < com_list.size(); i++) {
- vtw_def def;
- if (!validateCommentArgs(com_list[i], def)
- || !commentCfgPath(com_list[i], def)) {
+ if (!commentCfgPath(com_list[i])) {
print_str_vec("Comment [", "] failed\n", com_list[i], "'");
}
}
@@ -2043,23 +2021,23 @@ Cstore::append_tmpl_path(const vector<string>& path_comps, bool& is_tag)
* then template at the path is parsed.
* path_comps: vector of path components.
* validate_vals: whether to validate all "values" along specified path.
- * def: (output) parsed template.
* error: (output) error message if failed.
- * return false if invalid template path. otherwise return true.
+ * return parsed template if successful. otherwise return 0.
* note:
- * also, if last path component is value (i.e., def.is_value), the template
+ * also, if last path component is value (i.e., isValue()), the template
* parsed is actually at "full path - 1".
*/
-bool
+Ctemplate *
Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
- vtw_def& def, string& error)
+ string& error)
{
+ Ctemplate *rtmpl = 0;
// default error message
error = "The specified configuration node is not valid";
if (tmpl_path_at_root() && path_comps.size() == 0) {
// empty path not valid
- return false;
+ return rtmpl;
}
/* note: this function may be invoked recursively (depth 1) when
@@ -2088,7 +2066,6 @@ Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
}
}
}
- bool ret = false;
do {
/* cases for template path:
* (1) valid path ending in "actual node", i.e., typeless node, tag node,
@@ -2125,7 +2102,7 @@ Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
* pop it.
*/
pop_tmpl_path();
- if (!validate_val(NULL, (*pcomps)[i])) {
+ if (!validate_val(0, (*pcomps)[i])) {
// invalid value
error = "Value validation failed";
valid = false;
@@ -2154,19 +2131,20 @@ Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
* we haven't done anything yet.
*/
if (pcomps->size() > 1) {
- if (tmpl_parse(def)) {
- if (def.tag || def.multi || def.def_type != ERROR_TYPE) {
+ auto_ptr<Ctemplate> ttmpl(tmpl_parse());
+ if (ttmpl.get()) {
+ if (ttmpl->isTag() || ttmpl->isMulti() || !ttmpl->isTypeless()) {
// case (2). last component is "value".
if (validate_vals) {
// validate value
- if (!validate_val(&def, (*pcomps)[pcomps->size() - 1])) {
+ if (!validate_val(ttmpl.get(), (*pcomps)[pcomps->size() - 1])) {
// invalid value
error = "Value validation failed";
break;
}
}
- def.is_value = 1;
- ret = true;
+ rtmpl = ttmpl.release();
+ rtmpl->setIsValue(true);
break;
}
}
@@ -2181,12 +2159,11 @@ Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
// no need to push cfg path (only needed for validate_val())
if (tmpl_node_exists()) {
// case (1). last component is "node".
- if (!tmpl_parse(def)) {
+ if (!(rtmpl = tmpl_parse())) {
exit_internal("failed to parse tmpl [%s]\n",
tmpl_path_to_str().c_str());
}
- def.is_value = 0;
- ret = true;
+ rtmpl->setIsValue(false);
break;
}
// case (3) (fall through)
@@ -2196,21 +2173,21 @@ Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
} else {
restore_paths(not_validating);
}
- return ret;
+ return rtmpl;
}
/* check if specified "logical path" is valid for "activate" or
* "deactivate" operation.
- * return true if valid. otherwise return false.
+ * return parsed template if valid. otherwise return 0.
*/
-bool
-Cstore::validate_act_deact(const vector<string>& path_comps, const string& op,
- vtw_def& def)
+Ctemplate *
+Cstore::validate_act_deact(const vector<string>& path_comps, const string& op)
{
string terr;
- if (!get_parsed_tmpl(path_comps, false, def, terr)) {
+ auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
+ if (!def.get()) {
output_user("%s\n", terr.c_str());
- return false;
+ return 0;
}
{
/* XXX this is a temporary workaround for bug 5708, which should be
@@ -2218,24 +2195,25 @@ Cstore::validate_act_deact(const vector<string>& path_comps, const string& op,
* resolved (see bug for more details). once those are resolved,
* this workaround should be removed and the bug fixed properly.
*/
- if (!def.tag && def.def_type != ERROR_TYPE) {
+ if (!def->isTag() && !def->isTypeless()) {
output_user("Cannot %s a leaf configuration node\n", op.c_str());
- return false;
+ return 0;
}
}
- if (def.is_value && !def.tag) {
+ if (def->isLeafValue()) {
/* last component is a value of a single- or multi-value node (i.e.,
* a leaf value) => not allowed
*/
output_user("Cannot %s a leaf configuration value\n", op.c_str());
- return false;
+ return 0;
}
if (!cfg_path_exists(path_comps, false, true)) {
output_user("Nothing to %s (the specified %s does not exist)\n",
- op.c_str(), (!def.is_value || def.tag) ? "node" : "value");
- return false;
+ op.c_str(),
+ (!def->isValue() || def->isTag()) ? "node" : "value");
+ return 0;
}
- return true;
+ return def.release();
}
/* check if specified args is valid for "rename" or "copy" operation.
@@ -2262,13 +2240,13 @@ Cstore::validate_rename_copy(const vector<string>& args, const string& op)
vector<string> ppath;
ppath.push_back(otagnode);
ppath.push_back(otagval);
- vtw_def def;
string terr;
- if (!get_parsed_tmpl(ppath, false, def, terr)) {
+ auto_ptr<Ctemplate> def(get_parsed_tmpl(ppath, false, terr));
+ if (!def.get()) {
output_user("%s\n", terr.c_str());
return false;
}
- if (!def.is_value || !def.tag) {
+ if (!def->isTagValue()) {
// can only rename "tagnode tagvalue"
output_user("Cannot %s under \"%s\"\n", op.c_str(), otagnode.c_str());
return false;
@@ -2287,7 +2265,8 @@ Cstore::validate_rename_copy(const vector<string>& args, const string& op)
ntagnode.c_str(), ntagval.c_str());
return false;
}
- if (!get_parsed_tmpl(ppath, true, def, terr)) {
+ def.reset(get_parsed_tmpl(ppath, true, terr));
+ if (!def.get()) {
output_user("%s\n", terr.c_str());
return false;
}
@@ -2359,7 +2338,7 @@ bool
Cstore::set_cfg_path(const vector<string>& path_comps, bool output)
{
vector<string> ppath;
- vtw_def def;
+ auto_ptr<Ctemplate> def;
bool ret = true;
bool path_exists = true;
// do the set from the top down
@@ -2369,7 +2348,8 @@ Cstore::set_cfg_path(const vector<string>& path_comps, bool output)
ppath.push_back(path_comps[i]);
// get template at this level
- if (!get_parsed_tmpl(ppath, false, def)) {
+ def.reset(get_parsed_tmpl(ppath, false));
+ if (!def.get()) {
output_internal("paths[%s,%s]\n", cfg_path_to_str().c_str(),
tmpl_path_to_str().c_str());
for (size_t i = 0; i < ppath.size(); i++) {
@@ -2388,16 +2368,16 @@ Cstore::set_cfg_path(const vector<string>& path_comps, bool output)
append_cfg_path(ppath);
append_tmpl_path(ppath);
- if (!def.is_value) {
+ if (!def->isValue()) {
// this level is a "node"
if (!add_node() || !create_default_children()) {
ret = false;
break;
}
- } else if (def.tag) {
+ } else if (def->isTag()) {
// this level is a "tag value".
// add the tag, taking the max tag limit into consideration.
- if (!add_tag(def) || !create_default_children()) {
+ if (!add_tag(def->getTagLimit()) || !create_default_children()) {
ret = false;
break;
}
@@ -2405,10 +2385,10 @@ Cstore::set_cfg_path(const vector<string>& path_comps, bool output)
// this level is a "value" of a single-/multi-value node.
// go up 1 level to get the node.
pop_cfg_path();
- if (def.multi) {
+ if (def->isMulti()) {
// value of multi-value node.
// add the value, taking the max multi limit into consideration.
- if (!add_value_to_multi(def, ppath.back())) {
+ if (!add_value_to_multi(def->getMultiLimit(), ppath.back())) {
ret = false;
break;
}
@@ -2428,7 +2408,7 @@ Cstore::set_cfg_path(const vector<string>& path_comps, bool output)
}
RESTORE_PATHS; // if "break" was hit
- if (ret && def.is_value && def.def_default) {
+ if (ret && def->isValue() && def->getDefault()) {
/* a node with default has been explicitly set. needs to be marked
* as non-default for display purposes.
*
@@ -2681,15 +2661,15 @@ Cstore::cfg_value_exists(const string& value, bool active_cfg)
* not the value.
*/
bool
-Cstore::validate_val(const vtw_def *def, const string& value)
+Cstore::validate_val(const Ctemplate *def, const string& value)
{
- vtw_def ndef;
+ auto_ptr<Ctemplate> ndef;
if (!def) {
- if (!tmpl_parse(ndef)) {
+ ndef.reset(tmpl_parse());
+ if (!(def = ndef.get())) {
exit_internal("failed to parse tmpl [%s]\n", tmpl_path_to_str().c_str());
}
- def = &ndef;
- if (def->def_type == ERROR_TYPE) {
+ if (def->isTypeless()) {
// not a value node
exit_internal("validating non-value node [%s]\n",
tmpl_path_to_str().c_str());
@@ -2701,7 +2681,7 @@ Cstore::validate_val(const vtw_def *def, const string& value)
char *vbuf = (char *) malloc(vlen + 1);
strncpy(vbuf, value.c_str(), vlen + 1);
vbuf[vlen] = 0;
- bool ret = validate_val_impl((vtw_def *) def, vbuf);
+ bool ret = validate_val_impl(def, vbuf);
free(vbuf);
return ret;
}
@@ -2712,7 +2692,7 @@ Cstore::validate_val(const vtw_def *def, const string& value)
* already exists.
*/
bool
-Cstore::add_tag(const vtw_def& def)
+Cstore::add_tag(unsigned int tlimit)
{
string t = pop_cfg_path();
vector<string> cnodes;
@@ -2720,23 +2700,18 @@ Cstore::add_tag(const vtw_def& def)
get_all_child_node_names(cnodes, false, false);
bool ret = false;
do {
- if (def.def_tag > 0 && def.def_tag <= cnodes.size()) {
+ if (tlimit > 0 && tlimit <= cnodes.size()) {
// limit exceeded
output_user("Cannot set node \"%s\": number of values exceeds limit"
- "(%d allowed)\n", t.c_str(), def.def_tag);
+ "(%d allowed)\n", t.c_str(), tlimit);
break;
}
- /* XXX the following is the original logic, which is wrong since def_tag
- * is unsigned.
+ /* XXX the original implementation contains special case where the
+ * previous tag should be replaced. this is probably unnecessary since
+ * "rename" can be used for tag node anyway. also the implementation
+ * used -1 as the limit for the special case, which can't work since
+ * the limit is unsigned. ignore the special case for now.
*/
- if (def.def_tag < 0 && cnodes.size() == 1) {
- /* XXX special case in the original implementation where the previous
- * tag should be replaced. this is probably unnecessary since
- * "rename" can be used for tag node anyway.
- */
- ret = rename_child_node(cnodes[0], t);
- break;
- }
// neither of the above. just add the tag.
ret = add_child_node(t);
} while (0);
@@ -2750,7 +2725,7 @@ Cstore::add_tag(const vtw_def& def)
* not configured for the node.
*/
bool
-Cstore::add_value_to_multi(const vtw_def& def, const string& value)
+Cstore::add_value_to_multi(unsigned int mlimit, const string& value)
{
// get current values
vector<string> vvec;
@@ -2770,10 +2745,10 @@ Cstore::add_value_to_multi(const vtw_def& def, const string& value)
*
* for now just apply the limit for anything >= 1.
*/
- if (def.def_multi >= 1 && vvec.size() >= def.def_multi) {
+ if (mlimit >= 1 && vvec.size() >= mlimit) {
// limit exceeded
output_user("Cannot set value \"%s\": number of values exceeded "
- "(%d allowed)\n", value.c_str(), def.def_multi);
+ "(%d allowed)\n", value.c_str(), mlimit);
return false;
}
@@ -2817,12 +2792,12 @@ Cstore::create_default_children()
bool ret = true;
for (size_t i = 0; i < tcnodes.size(); i++) {
push_tmpl_path(tcnodes[i]);
- vtw_def def;
- if (tmpl_node_exists() && tmpl_parse(def)) {
- if (def.def_default) {
+ if (tmpl_node_exists()) {
+ auto_ptr<Ctemplate> def(tmpl_parse());
+ if (def.get() && def->getDefault()) {
// has default value. set it.
push_cfg_path(tcnodes[i]);
- if (!add_node() || !write_value(def.def_default)
+ if (!add_node() || !write_value(def->getDefault())
|| !mark_display_default()) {
ret = false;
}