# HG changeset patch # User Olaf Wintermann # Date 1553256451 -3600 # Node ID 9a4857d6444e020edd184df7dd4ebcd4d6cffd53 # Parent 5b9f20aa88c2d98187bb6c7cc9a38f0d17400e22 adds dav-sync splitconfig parser diff -r 5b9f20aa88c2 -r 9a4857d6444e dav/scfg.c --- a/dav/scfg.c Thu Mar 21 10:51:14 2019 +0100 +++ b/dav/scfg.c Fri Mar 22 13:07:31 2019 +0100 @@ -250,6 +250,85 @@ return tagconfig; } +static SplitConfig* parse_split(xmlNode *node) { + char *pattern = 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; + } else if(xstreq(c->name, "minsize")) { + minsize = value; + } else if(xstreq(c->name, "blocksize")) { + blocksize = value; + } + c = c->next; + } + + uint64_t sz = 0; + if(!blocksize) { + fprintf(stderr, "splitconfig: no blocksize specified\n"); + return NULL; + } + size_t bsz_len = strlen(blocksize); + if(bsz_len < 2) { + fprintf(stderr, "splitconfig: blocksize too small\n"); + return NULL; + } + + if(!util_szstrtouint(blocksize, &sz)) { + fprintf(stderr, "splitconfig: blocksize is not a number\n"); + return NULL; + } + + if(!pattern && !minsize) { + fprintf(stderr, "splitconfig: pattern or minsize must be specified\n"); + return NULL; + } + + int64_t minsz = -1; + if(minsize) { + uint64_t m; + if(!util_szstrtouint(minsize, &m)) { + fprintf(stderr, "splitconfig: minsize is not a number\n"); + return NULL; + } + minsz = (int64_t)m; + } + + SplitConfig *sc = calloc(1, sizeof(SplitConfig)); + sc->pattern = pattern ? strdup(pattern) : NULL; + sc->minsize = minsz; + sc->blocksize = (size_t)sz; + return sc; +} + +static UcxList* parse_splitconfig(xmlNode *node, int *error) { + UcxList *splitconfig = NULL; + int err = 0; + xmlNode *c = node->children; + while(c) { + if(c->type == XML_ELEMENT_NODE && xstreq(c->name, "split")) { + SplitConfig *sc = parse_split(c); + if(sc) { + splitconfig = ucx_list_append(splitconfig, sc); + } else { + err = 1; + break; + } + } + c = c->next; + } + + if(error) { + *error = err; + } + return splitconfig; +} + static Versioning* parse_versioning_config(xmlNode *node) { Versioning v; v.always = FALSE; @@ -299,6 +378,7 @@ UcxList *include = NULL; UcxList *exclude = NULL; UcxList *tagfilter = NULL; + UcxList *splitconfig = NULL; int max_retry = 0; int allow_cmd = SYNC_CMD_PULL | SYNC_CMD_PUSH | SYNC_CMD_ARCHIVE | SYNC_CMD_RESTORE; @@ -341,6 +421,12 @@ database = value; } else if(xstreq(node->name, "tagconfig")) { tagconfig = parse_tagconfig(node); + } else if(xstreq(node->name, "splitconfig")) { + int err = 0; + splitconfig = parse_splitconfig(node, &err); + if(err) { + return 1; + } } else if(xstreq(node->name, "metadata")) { char *error = NULL; metadata = parse_finfo_settings(value, &error); diff -r 5b9f20aa88c2 -r 9a4857d6444e dav/scfg.h --- a/dav/scfg.h Thu Mar 21 10:51:14 2019 +0100 +++ b/dav/scfg.h Fri Mar 22 13:07:31 2019 +0100 @@ -49,8 +49,9 @@ #define DEFAULT_TAG_XATTR "tags" #define MACOS_TAG_XATTR "com.apple.metadata:_kMDItemUserTags" -typedef struct TagConfig TagConfig; -typedef struct Versioning Versioning; +typedef struct TagConfig TagConfig; +typedef struct Versioning Versioning; +typedef struct SplitConfig SplitConfig; typedef struct SyncDirectory { char *name; @@ -64,6 +65,7 @@ UcxList *include; UcxList *exclude; UcxList *tagfilter; + UcxList *splitconfig; uint32_t metadata; int max_retry; int allow_cmd; @@ -74,6 +76,23 @@ uint32_t db_settings; } SyncDirectory; +struct SplitConfig { + /* + * path regex pattern or NULL + */ + char *pattern; + + /* + * 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, diff -r 5b9f20aa88c2 -r 9a4857d6444e libidav/utils.c --- a/libidav/utils.c Thu Mar 21 10:51:14 2019 +0100 +++ b/libidav/utils.c Fri Mar 22 13:07:31 2019 +0100 @@ -224,6 +224,51 @@ } } +int util_szstrtouint(const char *str, uint64_t *value) { + char *end; + errno = 0; + size_t len = strlen(str); + uint64_t val = strtoull(str, &end, 0); + if(end == str+len) { + *value = val; + return 1; + } else if(end == str+len-1) { + uint64_t mul = 1; + switch(end[0]) { + case 'k': + case 'K': mul = 1024; break; + case 'm': + case 'M': mul = 1024*1024; break; + case 'g': + case 'G': mul = 1024*1024*1024; break; + default: return 0; + } + + uint64_t result = 0; + if(util_uint_mul(val, mul, &result)) { + return 0; + } + *value = result; + return 1; + } + return 0; +} + +int util_uint_mul(uint64_t a, uint64_t b, uint64_t *result) { + if(a == 0 || b == 0) { + *result = 0; + return 0; + } + uint64_t r = a * b; + if(r / b == a) { + *result = r; + return 0; + } else { + *result = 0; + return 1; + } +} + char* util_url_base(char *url) { sstr_t u = sstr(url); int len = u.length; diff -r 5b9f20aa88c2 -r 9a4857d6444e libidav/utils.h --- a/libidav/utils.h Thu Mar 21 10:51:14 2019 +0100 +++ b/libidav/utils.h Fri Mar 22 13:07:31 2019 +0100 @@ -80,6 +80,9 @@ int util_getboolean(char *v); int util_strtouint(char *str, uint64_t *value); int util_strtoint(char *str, int64_t *value); +int util_szstrtouint(const char *str, uint64_t *value); + +int util_uint_mul(uint64_t a, uint64_t b, uint64_t *result); char* util_xml_get_text(const xmlNode *elm);