# HG changeset patch # User Olaf Wintermann # Date 1569754633 -7200 # Node ID fefe4b6f1048c5ac72eea0bde92b40d2c7c80859 # Parent 8bf1d9688698c39515cab8022d5cc81ca05a5de6 change split config diff -r 8bf1d9688698 -r fefe4b6f1048 dav/scfg.c --- a/dav/scfg.c Sat Sep 28 09:24:30 2019 +0200 +++ b/dav/scfg.c Sun Sep 29 12:57:13 2019 +0200 @@ -164,6 +164,36 @@ return 0; } +Filter* parse_filter(xmlNode *node) { + UcxList *include = NULL; + UcxList *exclude = NULL; + UcxList *tags = NULL; + + if(scfg_load_filter(node, &include, &exclude, &tags)) { + return NULL; + } + + Filter *filter = malloc(sizeof(Filter)); + filter->include = include; + filter->exclude = exclude; + filter->tags = tags; +} + +void init_default_filter(Filter *filter) { + if(!filter->include) { + regex_t *matchall = malloc(sizeof(regex_t)); + regcomp(matchall, ".*", REG_NOSUB); + filter->include = ucx_list_append(NULL, matchall); + } + /* + if(!filter->exclude) { + regex_t *matchnothing = malloc(sizeof(regex_t)); + regcomp(matchnothing, "///", REG_NOSUB); + filter->exclude = ucx_list_append(NULL, matchnothing); + } + */ +} + static TagFormat str2tagformat(const char *str) { if(!strcmp(str, "text")) { return TAG_FORMAT_TEXT; @@ -250,19 +280,24 @@ } static SplitConfig* parse_split(xmlNode *node) { - char *pattern = NULL; + Filter *filter = NULL; char *minsize = NULL; char *blocksize = NULL; xmlNode *c = node->children; while(c) { - char *value = util_xml_get_text(c); - if(xstreq(c->name, "pattern")) { - pattern = value; + if(xstreq(c->name, "filter")) { + filter = parse_filter(node); + if(filter->tags) { + fprintf(stderr, "splitconfig: tag filter not supported\n"); + free_filter(*filter); + free(filter); + return NULL; + } } else if(xstreq(c->name, "minsize")) { - minsize = value; + minsize = util_xml_get_text(c); } else if(xstreq(c->name, "blocksize")) { - blocksize = value; + blocksize = util_xml_get_text(c); } c = c->next; } @@ -283,8 +318,8 @@ return NULL; } - if(!pattern && !minsize) { - fprintf(stderr, "splitconfig: pattern or minsize must be specified\n"); + if(!filter && !minsize) { + fprintf(stderr, "splitconfig: filter or minsize must be specified\n"); return NULL; } @@ -299,13 +334,8 @@ } SplitConfig *sc = calloc(1, sizeof(SplitConfig)); - if(pattern) { - regex_t *regex = malloc(sizeof(regex_t)); - if (regcomp(regex, pattern, REG_EXTENDED|REG_NOSUB)) { - fprintf(stderr, "Invalid regular expression (%s)\n", pattern); - } else { - sc->pattern = regex; - } + if(filter) { + init_default_filter(filter); } sc->minsize = minsz; sc->blocksize = (size_t)sz; @@ -609,21 +639,10 @@ dir->db_settings |= DB_STORE_OWNER; } - if (include) { - dir->include = include; - } else { - regex_t *matchall = malloc(sizeof(regex_t)); - regcomp(matchall, ".*", REG_NOSUB); - dir->include = ucx_list_append(NULL, matchall); - } - if (exclude) { - dir->exclude = exclude; - } else { - regex_t *matchnothing = malloc(sizeof(regex_t)); - regcomp(matchnothing, "///", REG_NOSUB); - dir->exclude = ucx_list_append(NULL, matchnothing); - } - dir->tagfilter = tagfilter; + dir->filter.include = include; + dir->filter.exclude = exclude; + dir->filter.tags = tagfilter; + init_default_filter(&dir->filter); if (trash && sstrtrim(sstr(trash)).length > 0) { if (trash[0] == '/' || trash[0] == '$') { @@ -856,6 +875,18 @@ return dbname; } +void free_filter(Filter filter) { + UCX_FOREACH(elm, filter.include) { + regfree(elm->data); + free(elm->data); + } + ucx_list_free(filter.include); + UCX_FOREACH(elm, filter.exclude) { + regfree(elm->data); + free(elm->data); + } + ucx_list_free(filter.exclude); +} void free_sync_config() { if(directories) { @@ -874,16 +905,7 @@ 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_filter(dir->filter); free(dir); } diff -r 8bf1d9688698 -r fefe4b6f1048 dav/scfg.h --- a/dav/scfg.h Sat Sep 28 09:24:30 2019 +0200 +++ b/dav/scfg.h Sun Sep 29 12:57:13 2019 +0200 @@ -64,6 +64,7 @@ typedef struct TagConfig TagConfig; typedef struct Versioning Versioning; typedef struct SplitConfig SplitConfig; +typedef struct Filter Filter; enum PushStrategy { PUSH_STRATEGY_METADATA = 0, @@ -71,6 +72,12 @@ }; typedef enum PushStrategy PushStrategy; +struct Filter { + UcxList *include; + UcxList *exclude; + UcxList *tags; +}; + typedef struct SyncDirectory { char *name; char *path; @@ -80,9 +87,7 @@ char *database; TagConfig *tagconfig; Versioning *versioning; - UcxList *include; - UcxList *exclude; - UcxList *tagfilter; + Filter filter; UcxList *splitconfig; uint32_t metadata; int max_retry; @@ -100,22 +105,21 @@ struct SplitConfig { /* - * path regex pattern or NULL + * resource filter or NULL */ - regex_t *pattern; - + Filter *filter; /* * minimum file size for activating file splitting * a value of -1 means no size restriction */ int64_t minsize; - /* * split files into blocks with this size */ size_t blocksize; }; + enum TagFormat { TAG_FORMAT_TEXT = 0, TAG_FORMAT_CSV, @@ -173,6 +177,8 @@ char* generate_db_name(char *basename); +void free_filter(Filter filter); + void free_sync_config(); diff -r 8bf1d9688698 -r fefe4b6f1048 dav/sync.c --- a/dav/sync.c Sat Sep 28 09:24:30 2019 +0200 +++ b/dav/sync.c Sun Sep 29 12:57:13 2019 +0200 @@ -299,7 +299,24 @@ return local_path; } -static int res_matches_filter(SyncDirectory *dir, char *res_path) { +static int res_matches_filter(Filter *filter, char *res_path) { + // include/exclude filter + UCX_FOREACH(inc, filter->include) { + regex_t* pattern = (regex_t*) inc->data; + if (regexec(pattern, res_path, 0, NULL, 0) == 0) { + UCX_FOREACH(exc, filter->exclude) { + regex_t* pattern = (regex_t*) exc->data; + if (regexec(pattern, res_path, 0, NULL, 0) == 0) { + return 1; + } + } + return 0; + } + } + return 1; +} + +static int res_matches_dir_filter(SyncDirectory *dir, char *res_path) { // trash filter if (dir->trash) { sstr_t rpath = sstr(util_concat_path(dir->path, res_path)); @@ -317,20 +334,7 @@ } } - // include/exclude filter - UCX_FOREACH(inc, dir->include) { - regex_t* pattern = (regex_t*) inc->data; - if (regexec(pattern, res_path, 0, NULL, 0) == 0) { - UCX_FOREACH(exc, dir->exclude) { - regex_t* pattern = (regex_t*) exc->data; - if (regexec(pattern, res_path, 0, NULL, 0) == 0) { - return 1; - } - } - return 0; - } - } - return 1; + return res_matches_filter(&dir->filter, res_path); } static int res_matches_tags(DavResource *res, SyncTagFilter *tagfilter) { @@ -629,10 +633,10 @@ while(res) { DavBool res_filtered = FALSE; - if (res_matches_filter(dir, res->path)) { + if (res_matches_dir_filter(dir, res->path)) { res_filtered = TRUE; } else { - UCX_FOREACH(elm, dir->tagfilter) { + UCX_FOREACH(elm, dir->filter.tags) { SyncTagFilter *tf = elm->data; if(!res_matches_tags(res, tf)) { res_filtered = TRUE; @@ -712,7 +716,7 @@ UcxMapIterator i = ucx_map_iterator(dbres); LocalResource *local; UCX_MAP_FOREACH(key, local, i) { - if (res_matches_filter(dir, local->path)) { + if (res_matches_dir_filter(dir, local->path)) { continue; } if(!local->keep) { @@ -1854,11 +1858,11 @@ // ignore all files, that are excluded by a static filter (sync.xml) // static include/exclude filter - if(res_matches_filter(dir, local_res->path+1)) { + if(res_matches_dir_filter(dir, local_res->path+1)) { continue; } // static tag filter - UCX_FOREACH(elm, dir->tagfilter) { + UCX_FOREACH(elm, dir->filter.tags) { SyncTagFilter *tf = elm->data; if(!localres_matches_tags(dir, local_res, tf)) { continue; @@ -1970,11 +1974,11 @@ UcxList *removed_res = NULL; UCX_MAP_FOREACH(key, local, i) { // all filtered files should be removed from the database - if(res_matches_filter(dir, local->path+1)) { + if(res_matches_dir_filter(dir, local->path+1)) { ucx_map_cstr_remove(db->resources, local->path); continue; } - UCX_FOREACH(elm, dir->tagfilter) { + UCX_FOREACH(elm, dir->filter.tags) { SyncTagFilter *tf = elm->data; if(!localres_matches_tags(dir, local, tf)) { ucx_map_cstr_remove(db->resources, local->path); @@ -2989,8 +2993,8 @@ } else { UCX_FOREACH(elm, dir->splitconfig) { SplitConfig *sc = elm->data; - if(sc->pattern) { - if(regexec(sc->pattern, local->path, 0, NULL, 0) != 0) { + if(sc->filter) { + if(res_matches_filter(sc->filter, local->path)) { continue; } }