# HG changeset patch # User Mike Becker # Date 1478872999 -3600 # Node ID 6b8e287269fc1e1fa654a87262cf6f7574f5c03f # Parent 7534cb97b9ab72eb9cdd4a1ada6c579fe8a29fb3 improves config error reporting and adds check (check-config) command + dav-sync no longer aborts on missing sync.xml diff -r 7534cb97b9ab -r 6b8e287269fc dav/config.c --- a/dav/config.c Mon Nov 07 19:32:17 2016 +0100 +++ b/dav/config.c Fri Nov 11 15:03:19 2016 +0100 @@ -35,11 +35,20 @@ #include #include "config.h" +#include "main.h" #include #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) #define xstrEQ(a,b) !xmlStrcasecmp(BAD_CAST a, BAD_CAST b) +#define print_error(...) \ + do {\ + fprintf(stderr, "Error (config.xml): " __VA_ARGS__); \ + fprintf(stderr, "Abort.\n"); \ + } while(0); +#define print_warning(...) \ + fprintf(stderr, "Warning (config.xml): " __VA_ARGS__); + #ifdef _WIN32 #define ENV_HOME getenv("USERPROFILE") #else @@ -48,8 +57,6 @@ static UcxMap *repos; static UcxMap *keys; -static Proxy *http_proxy; -static Proxy *https_proxy; int check_config_dir(void) { char *file = util_concat_path(ENV_HOME, ".dav"); @@ -73,15 +80,13 @@ xmlFreeDoc(doc); } -void load_config(DavContext *ctx) { +int load_config(DavContext *ctx) { context = ctx; // TODO: free the config somewhere repos = ucx_map_new(16); keys = ucx_map_new(16); - http_proxy = calloc(1, sizeof(Proxy)); - https_proxy = calloc(1, sizeof(Proxy)); if(check_config_dir()) { - return; + return 1; } char *file = util_concat_path(ENV_HOME, ".dav/config.xml"); @@ -97,64 +102,72 @@ perror("Cannot load config.xml"); } } - return; + return 1; } xmlDoc *doc = xmlReadFile(file, NULL, 0); free(file); if(!doc) { fprintf(stderr, "Cannot load config.xml\n"); - return; + return 1; } xmlNode *xml_root = xmlDocGetRootElement(doc); xmlNode *node = xml_root->children; - while(node) { + int ret = 0; + while(node && !ret) { if(node->type == XML_ELEMENT_NODE) { if(xstreq(node->name, "repository")) { - load_repository(node); + ret = load_repository(node); } else if(xstreq(node->name, "key")) { - load_key(node); + ret = load_key(node); } else if (xstreq(node->name, "http-proxy")) { - load_proxy(node, HTTP_PROXY); + ret = load_proxy(ctx->http_proxy, node, HTTP_PROXY); } else if (xstreq(node->name, "https-proxy")) { - load_proxy(node, HTTPS_PROXY); + ret = load_proxy(ctx->https_proxy, node, HTTPS_PROXY); + } else { + fprintf(stderr, "Unknown config element: %s\n", node->name); + ret = 1; } } node = node->next; } xmlFreeDoc(doc); + return ret; } void free_config(void) { - UcxMapIterator i = ucx_map_iterator(repos); - UcxKey k; - Repository *repo; - UCX_MAP_FOREACH(k, repo, i) { - if(repo->default_key) { - free(repo->default_key); - } - if(repo->name) { - free(repo->name); - } - if(repo->password) { - free(repo->password); + if(repos) { + UcxMapIterator i = ucx_map_iterator(repos); + UcxKey k; + Repository *repo; + UCX_MAP_FOREACH(k, repo, i) { + if(repo->default_key) { + free(repo->default_key); + } + if(repo->name) { + free(repo->name); + } + if(repo->password) { + free(repo->password); + } + if(repo->url) { + free(repo->url); + } + if(repo->user) { + free(repo->user); + } + if(repo->cert) { + free(repo->cert); + } + free(repo); } - if(repo->url) { - free(repo->url); - } - if(repo->user) { - free(repo->user); - } - if(repo->cert) { - free(repo->cert); - } - free(repo); + ucx_map_free(repos); } - ucx_map_free(repos); - - ucx_map_free(keys); + if(keys) { + ucx_map_free(keys); + } } Repository* repository_new(void) { @@ -169,45 +182,48 @@ return repo; } -void load_repository(xmlNode *reponode) { - xmlNode *node = reponode->children; +int load_repository(xmlNode *reponode) { Repository *repo = repository_new(); - while(node) { - if(node->type == XML_ELEMENT_NODE) { - char *name = (char*)node->name; - char *value = util_xml_get_text(node); - if(value) { - if(repo_add_config(repo, name, value)) { - fprintf( - stderr, - "Unkown repository config element: %s\n", - name); - } + { + xmlNode *node = reponode->children; + int ret = 0; + while(node && !ret) { + if(node->type == XML_ELEMENT_NODE) { + char *name = (char*)node->name; + char *value = util_xml_get_text(node); + ret = repo_add_config(repo, name, value); } + node = node->next; } - node = node->next; + if(ret) { + free(repo); + return 1; + } } if(!repo->name) { - fprintf( - stderr, - "Cannot load config.xml: missing name for repository.\n"); - fprintf(stderr, "Abort.\n"); - exit(-1); + print_error("missing name for repository.\n"); + return 1; } if(!repo->url) { - fprintf( - stderr, - "Cannot load config.xml: " - "missing url for repository '%s'.\n", repo->name); - fprintf(stderr, "Abort.\n"); - exit(-1); + print_error("missing url for repository '%s'.\n", repo->name); + return 1; } ucx_map_cstr_put(repos, repo->name, repo); + return 0; } -int repo_add_config(Repository *repo, char *key, char *value) { +int repo_add_config(Repository *repo, char *key, char *value) { + /* every key needs a value */ + if(!value) { + /* TODO: maybe this should only be reported, if the key is valid + * But this makes the code very ugly. + */ + print_error("missing value for config element: %s\n", key); + return 1; + } + if(xstreq(key, "name")) { repo->name = strdup(value); } else if(xstreq(key, "url")) { @@ -263,7 +279,7 @@ #endif #endif else { - fprintf(stderr, "Unknown ssl version: %s\n", value); + print_warning("unknown ssl version: %s\n", value); } } else if(xstreq(key, "authmethods")) { repo->authmethods = CURLAUTH_NONE; @@ -284,56 +300,76 @@ } else if(xstrEQ(value, "none")) { /* skip */ } else { - fprintf(stderr, "Unknown authentication method: %s\n", value); + print_warning("unknown authentication method: %s\n", value); } meth = strtok(NULL, delims); } free(meths); } else { - return -1; + print_error("unkown repository config element: %s\n", key); + return 1; } return 0; } -void load_proxy(xmlNode *proxynode, int type) { - Proxy *proxy; +int load_proxy(DavProxy *proxy, xmlNode *proxynode, int type) { const char *stype; - if (type == HTTPS_PROXY) { - proxy = https_proxy; + if(type == HTTPS_PROXY) { stype = "https"; - } else if (type == HTTP_PROXY) { - proxy = http_proxy; + } else if(type == HTTP_PROXY) { stype = "http"; } + if(!proxy) { + print_error("no memory reserved for %s proxy.\n", stype); + return 1; + } + xmlNode *node = proxynode->children; - while(node) { + int ret = 0; + while(node && !ret) { if(node->type == XML_ELEMENT_NODE) { char *value = util_xml_get_text(node); - if(!value) { - // next - } else if(xstreq(node->name, "url")) { - proxy->url = strdup(value); + int reportmissingvalue = 0; + if(xstreq(node->name, "url")) { + if(!(reportmissingvalue = !value)) { + proxy->url = strdup(value); + } } else if(xstreq(node->name, "user")) { - proxy->user = strdup(value); + if(!(reportmissingvalue = !value)) { + proxy->username = strdup(value); + } } else if(xstreq(node->name, "password")) { - proxy->password = util_base64decode(value); + if(!(reportmissingvalue = !value)) { + proxy->password = util_base64decode(value); + } } else if(xstreq(node->name, "no")) { - proxy->no = strdup(value); + if(!(reportmissingvalue = !value)) { + proxy->no_proxy = strdup(value); + } + } else { + print_error("invalid element for proxy config: %s\n", + node->name); + ret = 1; + } + if (reportmissingvalue) { + print_error("missing value for proxy configuration " + "element '%s'.\n", node->name); + ret = 1; } } node = node->next; } - if(!proxy->url) { - fprintf(stderr, - "Cannot load config.xml: missing url for %s proxy.\n", stype); - fprintf(stderr, "Abort.\n"); - exit(-1); + if(!ret && !proxy->url) { + print_error("missing url for %s proxy.\n", stype); + return 1; } + + return ret; } -void load_key(xmlNode *keynode) { +int load_key(xmlNode *keynode) { xmlNode *node = keynode->children; Key *key = calloc(1, sizeof(Key)); key->type = KEY_AES256; @@ -353,7 +389,7 @@ key->data = key_data.ptr; key->length = key_data.length; } else { - fprintf(stderr, "Error: Cannot key from file: %s\n", value); + print_error("cannot get key from file: %s\n", value); error = 1; } } else if(xstreq(node->name, "type")) { @@ -362,7 +398,7 @@ } else if(!strcmp(value, "aes256")) { key->type = KEY_AES256; } else { - fprintf(stderr, "Error: unknown key type %s\n", value); + print_error("unknown key type %s\n", value); error = 1; } } @@ -373,27 +409,19 @@ if(!error && key->name) { error = 0; + size_t expected_length = 0; if(key->type == KEY_AES128) { - if(key->length < 16) { - fprintf( - stderr, - "Error: Key %s is too small (%zu < 16)\n", - key->name, - key->length); - error = 1; - } - key->length = 16; + expected_length = 16; } if(key->type == KEY_AES256) { - if(key->length < 32) { - fprintf( - stderr, - "Error: Key %s is too small (%zu < 32)\n", - key->name, - key->length); - error = 1; - } - key->length = 32; + expected_length = 32; + } + if(key->length < expected_length) { + print_error("key %s is too small (%zu < %zu)\n", + key->name, + key->length, + expected_length); + error = 1; } // add key to context @@ -409,6 +437,9 @@ free(key->data); } free(key); + return 1; + } else { + return 0; } } @@ -473,15 +504,6 @@ return ucx_map_cstr_get(keys, name); } -Proxy* get_http_proxy(void) { - return http_proxy; -} - -Proxy* get_https_proxy(void) { - return https_proxy; -} - - int add_repository(Repository *repo) { char *file = util_concat_path(ENV_HOME, ".dav/config.xml"); xmlDoc *doc = xmlReadFile(file, NULL, 0); diff -r 7534cb97b9ab -r 6b8e287269fc dav/config.h --- a/dav/config.h Mon Nov 07 19:32:17 2016 +0100 +++ b/dav/config.h Fri Nov 11 15:03:19 2016 +0100 @@ -66,19 +66,12 @@ int ssl_version; unsigned long authmethods; }; - -struct Proxy { - char *url; - char *user; - char *password; - char *no; -}; -void load_config(DavContext *ctx); +int load_config(DavContext *ctx); void free_config(void); -void load_repository(xmlNode *reponode); -void load_key(xmlNode *keynode); -void load_proxy(xmlNode *proxynode, int type); +int load_repository(xmlNode *reponode); +int load_key(xmlNode *keynode); +int load_proxy(DavProxy*, xmlNode *proxynode, int type); sstr_t load_key_file(char *filename); Repository* repository_new(void); @@ -88,8 +81,6 @@ int get_repository_flags(Repository *repo); DavSession *repository_session(Repository *repo); Key* get_key(char *name); -Proxy* get_http_proxy(void); -Proxy* get_https_proxy(void); int add_repository(Repository *repo); int list_repositories(void); diff -r 7534cb97b9ab -r 6b8e287269fc dav/main.c --- a/dav/main.c Mon Nov 07 19:32:17 2016 +0100 +++ b/dav/main.c Fri Nov 11 15:03:19 2016 +0100 @@ -66,20 +66,6 @@ } int main(int argc, char **argv) { - xmlGenericErrorFunc fnc = xmlerrorfnc; - initGenericErrorDefaultFunc(&fnc); - ctx = dav_context_new(); - dav_add_namespace(ctx, "apache", "http://apache.org/dav/props/"); - load_config(ctx); - printxmlerror = 0; -#ifdef DO_THE_TEST - test(); - return 0; -#endif - - memcpy(ctx->http_proxy, get_http_proxy(), sizeof(Proxy)); - memcpy(ctx->https_proxy, get_https_proxy(), sizeof(Proxy)); - if(argc < 2) { fprintf(stderr, "Missing command\n"); print_usage(argv[0]); @@ -94,46 +80,66 @@ return -1; } - - int ret = -1; - if(!strcasecmp(cmd, "list") || !strcasecmp(cmd, "ls")) { - ret = cmd_list(args); - } else if(!strcasecmp(cmd, "get")) { - ret = cmd_get(args); - } else if(!strcasecmp(cmd, "put")) { - ret = cmd_put(args); - } else if( - !strcasecmp(cmd, "remove") || - !strcasecmp(cmd, "rm") || - !strcasecmp(cmd, "delete")) - { - ret = cmd_remove(args); - } else if(!strcasecmp(cmd, "mkdir") || !strcasecmp(cmd, "mkcol")) { - ret = cmd_mkdir(args); - } else if(!strcasecmp(cmd, "copy") || !strcasecmp(cmd, "cp")) { - ret = cmd_move(args, true); - } else if(!strcasecmp(cmd, "move") || !strcasecmp(cmd, "mv")) { - ret = cmd_move(args, false); - } else if(!strcasecmp(cmd, "date")) { - ret = cmd_date(args); - } else if(!strcasecmp(cmd, "set-property")) { - ret = cmd_set_property(args); - } else if(!strcasecmp(cmd, "get-property")) { - ret = cmd_get_property(args); - } else if(!strcasecmp(cmd, "lock")) { - ret = cmd_lock(args); - } else if(!strcasecmp(cmd, "unlock")) { - ret = cmd_unlock(args); - } else if(!strcasecmp(cmd, "info")) { - ret = cmd_info(args); - } else if(!strcasecmp(cmd, "add-repository")) { - ret = cmd_add_repository(args); - } else if(!strcasecmp(cmd, "list-repositories")) { - ret = list_repositories(); - } else if(!strcasecmp(cmd, "version") || !strcasecmp(cmd, "-version") || !strcasecmp(cmd, "--version")) { - fprintf(stderr, "dav %s\n", DAV_VERSION); - } else { - print_usage(argv[0]); + xmlGenericErrorFunc fnc = xmlerrorfnc; + initGenericErrorDefaultFunc(&fnc); + ctx = dav_context_new(); + dav_add_namespace(ctx, "apache", "http://apache.org/dav/props/"); + int cfgret = load_config(ctx); + int ret = EXIT_FAILURE; + printxmlerror = 0; +#ifdef DO_THE_TEST + test(); + return 0; +#endif + if(!strcmp(cmd, "check") || !strcmp(cmd, "check-config")) { + if(!cfgret) { + fprintf(stdout, "Configuration OK.\n"); + ret = EXIT_SUCCESS; + } else { + /* no output, the warnings are written by load_config */ + ret = EXIT_FAILURE; + } + } else if(!cfgret) { + if(!strcasecmp(cmd, "list") || !strcasecmp(cmd, "ls")) { + ret = cmd_list(args); + } else if(!strcasecmp(cmd, "get")) { + ret = cmd_get(args); + } else if(!strcasecmp(cmd, "put")) { + ret = cmd_put(args); + } else if( + !strcasecmp(cmd, "remove") || + !strcasecmp(cmd, "rm") || + !strcasecmp(cmd, "delete")) + { + ret = cmd_remove(args); + } else if(!strcasecmp(cmd, "mkdir") || !strcasecmp(cmd, "mkcol")) { + ret = cmd_mkdir(args); + } else if(!strcasecmp(cmd, "copy") || !strcasecmp(cmd, "cp")) { + ret = cmd_move(args, true); + } else if(!strcasecmp(cmd, "move") || !strcasecmp(cmd, "mv")) { + ret = cmd_move(args, false); + } else if(!strcasecmp(cmd, "date")) { + ret = cmd_date(args); + } else if(!strcasecmp(cmd, "set-property")) { + ret = cmd_set_property(args); + } else if(!strcasecmp(cmd, "get-property")) { + ret = cmd_get_property(args); + } else if(!strcasecmp(cmd, "lock")) { + ret = cmd_lock(args); + } else if(!strcasecmp(cmd, "unlock")) { + ret = cmd_unlock(args); + } else if(!strcasecmp(cmd, "info")) { + ret = cmd_info(args); + } else if(!strcasecmp(cmd, "add-repository")) { + ret = cmd_add_repository(args); + } else if(!strcasecmp(cmd, "list-repositories")) { + ret = list_repositories(); + } else if(!strcasecmp(cmd, "version") || !strcasecmp(cmd, "-version") + || !strcasecmp(cmd, "--version")) { + fprintf(stderr, "dav %s\n", DAV_VERSION); + } else { + print_usage(argv[0]); + } } dav_context_destroy(ctx); @@ -195,6 +201,7 @@ fprintf(stderr, "Config commands:\n"); fprintf(stderr, " add-repository\n"); fprintf(stderr, " list-repositories\n"); + fprintf(stderr, " check (or check-config)\n"); fprintf(stderr, "\n"); fprintf(stderr, "Instead of an url you can pass a repository name " diff -r 7534cb97b9ab -r 6b8e287269fc dav/scfg.c --- 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 element\n"); + print_warning("unsigned integer value " + "expected in 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); } diff -r 7534cb97b9ab -r 6b8e287269fc dav/sync.c --- a/dav/sync.c Mon Nov 07 19:32:17 2016 +0100 +++ b/dav/sync.c Fri Nov 11 15:03:19 2016 +0100 @@ -73,49 +73,48 @@ } int ret = EXIT_FAILURE; - int loadcfg = 1; - if(!strcasecmp(cmd, "version") || !strcasecmp(cmd, "-version") || !strcasecmp(cmd, "--version")) { + if(!strcasecmp(cmd, "version") || !strcasecmp(cmd, "-version") + || !strcasecmp(cmd, "--version")) { fprintf(stderr, "dav-sync %s\n", DAV_VERSION); - loadcfg = 0; cmd_args_free(args); return -1; } - if(loadcfg) { - xmlGenericErrorFunc fnc = xmlerrorfnc; - initGenericErrorDefaultFunc(&fnc); - ctx = dav_context_new(); - load_config(ctx); - - // copy proxy config - memcpy(ctx->http_proxy, get_http_proxy(), sizeof(Proxy)); - memcpy(ctx->https_proxy, get_https_proxy(), sizeof(Proxy)); - - if(load_sync_config()) { - cmd_args_free(args); - dav_context_destroy(ctx); - return EXIT_FAILURE; - } - } + xmlGenericErrorFunc fnc = xmlerrorfnc; + initGenericErrorDefaultFunc(&fnc); + ctx = dav_context_new(); + int cfgret = load_config(ctx) || load_sync_config(); - if(!strcmp(cmd, "pull")) { - ret = cmd_pull(args); - } else if(!strcmp(cmd, "push")) { - ret = cmd_push(args); - } else if(!strcmp(cmd, "resolve-conflicts")) { - ret = cmd_resolve_conflicts(args); - } else if(!strcmp(cmd, "delete-conflicts")) { - ret = cmd_delete_conflicts(args); - } else if(!strcmp(cmd, "trash-info")) { - ret = cmd_trash_info(args); - } else if(!strcmp(cmd, "empty-trash")) { - ret = cmd_empty_trash(args); - } else if(!strcmp(cmd, "add-directory")) { - ret = cmd_add_directory(args); - } else if(!strcmp(cmd, "list-directories")) { - ret = list_syncdirs(); - } else { - print_usage(argv[0]); + if(!strcmp(cmd, "check") || !strcmp(cmd, "check-config")) { + if(!cfgret) { + fprintf(stdout, "Configuration OK.\n"); + ret = EXIT_SUCCESS; + } else { + /* no output, the warnings are written by load_config */ + ret = EXIT_FAILURE; + } + } else if(!cfgret) { + if(!strcmp(cmd, "pull")) { + ret = cmd_pull(args); + } else if(!strcmp(cmd, "push")) { + ret = cmd_push(args); + } else if(!strcmp(cmd, "resolve-conflicts")) { + ret = cmd_resolve_conflicts(args); + } else if(!strcmp(cmd, "delete-conflicts")) { + ret = cmd_delete_conflicts(args); + } else if(!strcmp(cmd, "trash-info")) { + ret = cmd_trash_info(args); + } else if(!strcmp(cmd, "empty-trash")) { + ret = cmd_empty_trash(args); + } else if(!strcmp(cmd, "add-directory")) { + ret = cmd_add_directory(args); + } else if(!strcmp(cmd, "list-directories")) { + ret = list_syncdirs(); + } else if(!strcmp(cmd, "check-repositories")) { + ret = cmd_check_repositories(); + } else { + print_usage(argv[0]); + } } // cleanup @@ -151,7 +150,9 @@ fprintf(stderr, "Config commands:\n"); fprintf(stderr, " add-directory\n"); - fprintf(stderr, " list-directories\n\n"); + fprintf(stderr, " list-directories\n"); + fprintf(stderr, " check (or check-config)\n"); + fprintf(stderr, " check-repositories\n\n"); } static int res_matches_filter(SyncDirectory *dir, char *res_path) { @@ -1633,3 +1634,8 @@ return ret; } + +int cmd_check_repositories() { + fprintf(stderr, "Not implemented.\n"); + return EXIT_FAILURE; +} diff -r 7534cb97b9ab -r 6b8e287269fc dav/sync.h --- a/dav/sync.h Mon Nov 07 19:32:17 2016 +0100 +++ b/dav/sync.h Fri Nov 11 15:03:19 2016 +0100 @@ -88,6 +88,8 @@ int cmd_empty_trash(CmdArgs *args); int cmd_add_directory(CmdArgs *args); +int cmd_check_repositories(); + #ifdef __cplusplus } #endif