--- a/dav/scfg.c Mon Nov 07 19:32:17 2016 +0100 +++ b/dav/scfg.c Fri Nov 11 15:03:19 2016 +0100 @@ -38,6 +38,15 @@ #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) + +#define print_error(...) \ + do {\ + fprintf(stderr, "Error (sync.xml): " __VA_ARGS__); \ + fprintf(stderr, "Abort.\n"); \ + } while(0); +#define print_warning(...) \ + fprintf(stderr, "Warning (sync.xml): " __VA_ARGS__); + #ifdef _WIN32 #define ENV_HOME getenv("USERPROFILE") #else @@ -71,7 +80,8 @@ switch(errno) { case ENOENT: { if(create_default_sync_config(file)) { - return -1; + /* this recursion is safe: ENOENT cannot occur again */ + return load_sync_config(); } break; } @@ -85,21 +95,20 @@ xmlDoc *doc = xmlReadFile(file, NULL, 0); if(!doc) { - fprintf(stderr, "Broken configuration file\n"); + fprintf(stderr, "Cannot load sync.xml\n"); free(file); return -1; } int ret = 0; xmlNode *node = xmlDocGetRootElement(doc)->children; - while(node) { + while(node && !ret) { if(node->type == XML_ELEMENT_NODE) { if(xstreq(node->name, "directory")) { - if(scfg_load_directory(node)) { - ret = 1; - ucx_map_free(directories); - break; - } + ret = scfg_load_directory(node); + } else { + print_error("unknown config element: %s\n", node->name); + ret = 1; } } node = node->next; @@ -126,12 +135,21 @@ while(node) { if(node->type == XML_ELEMENT_NODE) { char *value = util_xml_get_text(node); - if(!value) { + if(xstreq(node->name, "include")) { + if(value) { + *include = add_regex_pattern(*include, value); + } + } else if(xstreq(node->name, "exclude")) { + if(value) { + *exclude = add_regex_pattern(*exclude, value); + } + } else { + print_error("unknown filter config element: %s\n", node->name); return 1; - } else if(xstreq(node->name, "include")) { - *include = add_regex_pattern(*include, value); - } else if(xstreq(node->name, "exclude")) { - *exclude = add_regex_pattern(*exclude, value); + } + if(!value) { + print_error("missing value for filter: %s\n", node->name); + return 1; } } @@ -159,9 +177,16 @@ while(node) { if(node->type == XML_ELEMENT_NODE) { char *value = util_xml_get_text(node); + /* every key needs a value */ if(!value) { - // next - } else if(xstreq(node->name, "name")) { + /* TODO: maybe this should only be reported, if the key is valid + * But this makes the code very ugly. + */ + print_error("missing value for directory element: %s\n", + node->name); + return 1; + } + if(xstreq(node->name, "name")) { name = value; } else if(xstreq(node->name, "path")) { path = value; @@ -173,7 +198,7 @@ repository = value; } else if(xstreq(node->name, "filter")) { if(scfg_load_filter(node, &include, &exclude)) { - return -1; + return 1; } } else if(xstreq(node->name, "database")) { database = value; @@ -182,8 +207,8 @@ if(util_strtoint(value, &i) && i >= 0) { max_retry = (int)i; } else { - fprintf(stderr, "Warning: sync.xml: unsigned integer value " - "expected in <max-retry> element\n"); + print_warning("unsigned integer value " + "expected in <max-retry> element\n"); } } else if(xstreq(node->name, "backup-on-pull")) { backuppull = util_getboolean(value); @@ -191,26 +216,30 @@ lockpull = util_getboolean(value); } else if(xstreq(node->name, "lock-push")) { lockpush = util_getboolean(value); + } else { + print_error("unknown directory config element: %s\n", + node->name); + return 1; } } node = node->next; } if(!name) { - fprintf(stderr, "Missing name element for directory\n"); - return -1; + print_error("missing name element for directory\n"); + return 1; } if(!path) { - fprintf(stderr, "Missing path element for directory\n"); - return -1; + print_error("missing path element for directory %s\n", name); + return 1; } if(!repository) { - fprintf(stderr, "Missing repository element for directory\n"); - return -1; + print_error("missing repository element for directory %s\n", name); + return 1; } if(!database) { - fprintf(stderr, "Missing database element for directory\n"); - return -1; + print_error("missing database element for directory %s\n", name); + return 1; } SyncDirectory *dir = malloc(sizeof(SyncDirectory)); @@ -426,34 +455,36 @@ void free_sync_config() { - UcxMapIterator i = ucx_map_iterator(directories); - SyncDirectory *dir; - UCX_MAP_FOREACH(elm, dir, i) { - free(dir->name); - free(dir->path); - free(dir->repository); - free(dir->database); - - if(dir->collection) { - free(dir->collection); - } - if(dir->trash) { - free(dir->trash); + if(directories) { + UcxMapIterator i = ucx_map_iterator(directories); + SyncDirectory *dir; + UCX_MAP_FOREACH(elm, dir, i) { + free(dir->name); + free(dir->path); + free(dir->repository); + free(dir->database); + + if(dir->collection) { + free(dir->collection); + } + if(dir->trash) { + free(dir->trash); + } + + UCX_FOREACH(elm, dir->include) { + regfree(elm->data); + free(elm->data); + } + ucx_list_free(dir->include); + UCX_FOREACH(elm, dir->exclude) { + regfree(elm->data); + free(elm->data); + } + ucx_list_free(dir->exclude); + + free(dir); } - - UCX_FOREACH(elm, dir->include) { - regfree(elm->data); - free(elm->data); - } - ucx_list_free(dir->include); - UCX_FOREACH(elm, dir->exclude) { - regfree(elm->data); - free(elm->data); - } - ucx_list_free(dir->exclude); - - free(dir); + + ucx_map_free(directories); } - - ucx_map_free(directories); }