/* Initialization */
-#define SEC_FLAG_DYNAMIC 0x80000000 // contains a dynamic attribute
-#define SEC_FLAG_UNKNOWN 0x40000000 // ignore unknown entriies
-#define SEC_FLAG_NUMBER 0x3fffffff // number of entries
+#define SEC_FLAG_DYNAMIC 0x80000000 // contains a dynamic attribute
+#define SEC_FLAG_UNKNOWN 0x40000000 // ignore unknown entriies
+#define SEC_FLAG_DIRTY 0x20000000 // its item has been written to
+#define SEC_FLAG_NUMBER 0x1fffffff // number of entries
static struct cf_section sections; // root section
static void
inspect_section(struct cf_section *sec)
{
- sec->flags = 0;
+ sec->flags = SEC_FLAG_DIRTY;
struct cf_item *ci;
for (ci=sec->cfg; ci->cls; ci++)
if (ci->cls == CC_SECTION) {
cf_init_section(sec->cfg[i].name, sec->cfg[i].u.sec, ptr + (addr_int_t) sec->cfg[i].ptr);
else if (sec->cfg[i].cls == CC_LIST)
clist_init(sec->cfg[i].ptr);
- byte *msg = sec->init(ptr);
- if (msg)
- die("Cannot initialize section %s: %s", name, msg);
+ if (sec->init) {
+ byte *msg = sec->init(ptr);
+ if (msg)
+ die("Cannot initialize section %s: %s", name, msg);
+ }
}
static void
if (initialized++)
return;
sections.flags |= SEC_FLAG_UNKNOWN;
- for (struct cf_item *ci=sections.cfg; ci->cls; ci++)
- cf_init_section(ci->name, ci->u.sec, NULL);
+ cf_init_section("top-level", §ions, NULL);
+}
+
+static int
+commit_section(byte *name, struct cf_section *sec, void *ptr)
+{
+ struct cf_item *ci;
+ for (ci=sec->cfg; ci->cls; ci++)
+ if (ci->cls == CC_SECTION)
+ if (commit_section(ci->name, ci->u.sec, ptr + (addr_int_t) ci->ptr))
+ return 1;
+ else if (ci->cls == CC_LIST) {
+ struct cnode *n;
+ CLIST_WALK(n, * (clist*) (ptr + (addr_int_t) ci->ptr))
+ if (commit_section(ci->name, ci->u.sec, n))
+ return 1;
+ }
+ if (sec->flags & SEC_FLAG_DIRTY) {
+ /* XXX: The flag is associated to a class whereas instances are those who
+ * get dirty. This means that all other instances of the same class will
+ * be committed as well. I don't see a way to easily allocate the flag
+ * somewhere else. */
+ sec->flags &= ~SEC_FLAG_DIRTY;
+ if (sec->commit) {
+ byte *msg = sec->commit(ptr);
+ if (msg)
+ log(L_ERROR, "Cannot commit section %s: %s", name, msg);
+ return 1;
+ }
+ }
+ return 0;
}
static struct cf_item *
*msg = cf_printf("Item %s is not a section", name);
return NULL;
}
+ curr_sec->flags |= SEC_FLAG_DIRTY; // XXX: it is set even when just reading via cf_find_item()
curr_sec = ci->u.sec;
name = c;
}
log(L_ERROR, "Unterminated block");
return 1;
}
+ if (commit_section("top-level", §ions, NULL))
+ return 1;
return 0;
}