return ret;
}
+static bool conf_value_compare(struct conf_value *old, struct conf_value *new)
+{
+ if (old == NULL || new == NULL) {
+ return false;
+ }
+
+ if (old->type != new->type) {
+ return false;
+ }
+
+ switch (old->type) {
+ case CONF_STRING:
+ if (old->data.string == NULL && new->data.string == NULL) {
+ return true;
+ }
+ if (old->data.string != NULL && new->data.string != NULL) {
+ if (strcmp(old->data.string, new->data.string) == 0) {
+ return true;
+ }
+ }
+ break;
+
+ case CONF_INTEGER:
+ if (old->data.integer == new->data.integer) {
+ return true;
+ }
+ break;
+
+ case CONF_BOOLEAN:
+ if (old->data.boolean == new->data.boolean) {
+ return true;
+ }
+ break;
+ }
+
+ return false;
+}
+
static int conf_value_copy(TALLOC_CTX *mem_ctx,
struct conf_value *src,
struct conf_value *dst)
return ret;
}
+static bool conf_option_same_value(struct conf_option *opt,
+ struct conf_value *new_value)
+{
+ return conf_value_compare(opt->value, new_value);
+}
+
static int conf_option_new_value(struct conf_option *opt,
struct conf_value *new_value,
enum conf_update_mode mode)
int ret;
bool ok;
- ok = conf_option_validate(opt, new_value, mode);
- if (!ok) {
- D_ERR("conf: validation for option \"%s\" failed\n",
- opt->name);
- return EINVAL;
+ if (opt->new_value != &opt->default_value) {
+ TALLOC_FREE(opt->new_value);
}
- TALLOC_FREE(opt->new_value);
- opt->new_value = talloc_zero(opt, struct conf_value);
- if (opt->new_value == NULL) {
- return ENOMEM;
- }
+ if (new_value == &opt->default_value) {
+ /*
+ * This happens only during load/reload. Set the value to
+ * default value, so if the config option is dropped from
+ * config file, then it get's reset to default.
+ */
+ opt->new_value = &opt->default_value;
+ } else {
+ ok = conf_option_validate(opt, new_value, mode);
+ if (!ok) {
+ D_ERR("conf: validation for option \"%s\" failed\n",
+ opt->name);
+ return EINVAL;
+ }
- opt->new_value->type = opt->value->type;
- ret = conf_value_copy(opt, new_value, opt->new_value);
- if (ret != 0) {
- return ret;
+ opt->new_value = talloc_zero(opt, struct conf_value);
+ if (opt->new_value == NULL) {
+ return ENOMEM;
+ }
+
+ opt->new_value->type = opt->value->type;
+ ret = conf_value_copy(opt, new_value, opt->new_value);
+ if (ret != 0) {
+ return ret;
+ }
}
conf_option_set_ptr_value(opt);
- if (mode == CONF_MODE_API) {
- opt->temporary_modified = true;
- } else {
- opt->temporary_modified = false;
+ if (new_value != &opt->default_value) {
+ if (mode == CONF_MODE_API) {
+ opt->temporary_modified = true;
+ } else {
+ opt->temporary_modified = false;
+ }
}
return 0;
}
+static int conf_option_new_default_value(struct conf_option *opt,
+ enum conf_update_mode mode)
+{
+ return conf_option_new_value(opt, &opt->default_value, mode);
+}
+
static void conf_option_default(struct conf_option *opt)
{
if (! opt->default_set) {
static void conf_option_reset(struct conf_option *opt)
{
- TALLOC_FREE(opt->new_value);
+ if (opt->new_value != &opt->default_value) {
+ TALLOC_FREE(opt->new_value);
+ }
conf_option_set_ptr_value(opt);
}
conf_option_set_ptr_value(opt);
}
+static void conf_option_reset_temporary(struct conf_option *opt)
+{
+ opt->temporary_modified = false;
+}
+
static bool conf_option_is_default(struct conf_option *opt)
{
return (opt->value == &opt->default_value);
}
}
+static int conf_all_temporary_default(struct conf_context *conf,
+ enum conf_update_mode mode)
+{
+ struct conf_section *s;
+ struct conf_option *opt;
+ int ret;
+
+ for (s = conf->section; s != NULL; s = s->next) {
+ for (opt = s->option; opt != NULL; opt = opt->next) {
+ ret = conf_option_new_default_value(opt, mode);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
static void conf_all_reset(struct conf_context *conf)
{
struct conf_section *s;
for (s = conf->section; s != NULL; s = s->next) {
for (opt = s->option; opt != NULL; opt = opt->next) {
conf_option_update(opt);
+ conf_option_reset_temporary(opt);
}
}
}
{
struct conf_load_state state;
FILE *fp;
+ int ret;
bool ok;
fp = fopen(conf->filename, "r");
.mode = (conf->reload ? CONF_MODE_RELOAD : CONF_MODE_LOAD),
};
+ ret = conf_all_temporary_default(conf, state.mode);
+ if (ret != 0) {
+ return ret;
+ }
+
ok = tini_parse(fp,
false,
conf_load_section,
TALLOC_CTX *tmp_ctx;
struct conf_value value;
int ret;
+ bool ok;
if (state->s == NULL) {
if (state->conf->ignore_unknown) {
return false;
}
+ ok = conf_option_same_value(opt, &value);
+ if (ok) {
+ goto done;
+ }
+
ret = conf_option_new_value(opt, &value, state->mode);
if (ret != 0) {
talloc_free(tmp_ctx);
return false;
}
+done:
talloc_free(tmp_ctx);
return true;
return ENOENT;
}
+ ok = conf_option_same_value(opt, value);
+ if (ok) {
+ return 0;
+ }
+
ret = conf_option_new_value(opt, value, CONF_MODE_API);
if (ret != 0) {
conf_option_reset(opt);
assert(b2_val == false);
assert(is_default == false);
+ conf_dump(conf, stdout);
+
conf_set_defaults(conf);
assert(strcmp(s_val, "default") == 0);
status = conf_valid(conf);
assert(status == true);
+ ret = conf_set_string(conf, "section1", "key1", "default");
+ assert(ret == 0);
+
ret = conf_set_string(conf, "section1", "key1", "foobar");
assert(ret == EINVAL);
+ ret = conf_set_integer(conf, "section1", "key2", 10);
+ assert(ret == 0);
+
ret = conf_set_integer(conf, "section1", "key2", 20);
assert(ret == EINVAL);
+ ret = conf_set_boolean(conf, "section1", "key3", true);
+ assert(ret == 0);
+
ret = conf_set_boolean(conf, "section1", "key3", false);
assert(ret == EINVAL);
exit(ret);
}
+static void test11(const char *filename)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(NULL);
+ char reload[PATH_MAX];
+ struct conf_context *conf;
+ int ret;
+ bool status;
+
+ ret = snprintf(reload, sizeof(reload), "%s.reload", filename);
+ assert(ret < sizeof(reload));
+
+ ret = conf_init(mem_ctx, &conf);
+ assert(ret == 0);
+ assert(conf != NULL);
+
+ conf_define_section(conf, "section1", NULL);
+
+ conf_define_string(conf, "section1", "key1", "value1", NULL);
+ conf_define_integer(conf, "section1", "key2", 10, NULL);
+ conf_define_boolean(conf, "section1", "key3", true, NULL);
+
+ status = conf_valid(conf);
+ assert(status == true);
+
+ ret = conf_load(conf, filename, false);
+ assert(ret == 0);
+
+ ret = rename(reload, filename);
+ assert(ret == 0);
+
+ ret = conf_reload(conf);
+ assert(ret == 0);
+
+ conf_dump(conf, stdout);
+
+ talloc_free(mem_ctx);
+ exit(ret);
+}
+
int main(int argc, const char **argv)
{
int num;
test9(argv[2], false);
break;
+ case 11:
+ test11(argv[2]);
+ break;
}
return 0;