--- a/dav/sync.c Sun Apr 16 14:12:24 2023 +0200 +++ b/dav/sync.c Fri Apr 21 21:25:32 2023 +0200 @@ -36,9 +36,10 @@ #include <utime.h> #include <libxml/xmlerror.h> #include <sys/types.h> -#include <ucx/string.h> -#include <ucx/utils.h> -#include <ucx/properties.h> +#include <cx/string.h> +#include <cx/utils.h> +#include <cx/hash_map.h> +#include <cx/printf.h> #include <dirent.h> #include <math.h> @@ -355,12 +356,12 @@ 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; + CxIterator i = cxListIterator(filter->include); + cx_foreach(regex_t*, pattern, i) { 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) { + CxIterator e = cxListIterator(filter->exclude); + cx_foreach(regex_t*, expat, e) { + if (regexec(expat, res_path, 0, NULL, 0) == 0) { return 1; } } @@ -373,7 +374,7 @@ 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)); + cxmutstr rpath = cx_mutstr(util_concat_path(dir->path, res_path)); if (util_path_isrelated(dir->trash, rpath.ptr)) { free(rpath.ptr); return 1; @@ -407,12 +408,11 @@ } DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_PROPS_NS, "tags"); - UcxList *res_tags = parse_dav_xml_taglist(tagsprop); + CxList *res_tags = parse_dav_xml_taglist(tagsprop); int ret = matches_tagfilter(res_tags, tagfilter); - ucx_list_free_content(res_tags, (ucx_destructor) free_dav_tag); - ucx_list_free(res_tags); + cxListDestroy(res_tags); return ret; } @@ -436,14 +436,11 @@ } DavBool changed = 0; - UcxList *res_tags = sync_get_file_tags(dir, res, &changed, NULL); + CxList *res_tags = sync_get_file_tags(dir, res, &changed, NULL); int ret = matches_tagfilter(res_tags, tagfilter); - UCX_FOREACH(elm, res_tags) { - DavTag *t = elm->data; - free_dav_tag(t); - } - ucx_list_free(res_tags); + CxIterator i = cxListIterator(res_tags); + cxListDestroy(res_tags); return ret; } @@ -510,7 +507,7 @@ } static void localres_keep(SyncDatabase *db, const char *path) { - LocalResource *local = ucx_map_cstr_remove(db->resources, path); + LocalResource *local = cxMapRemoveAndGet(db->resources, cx_hash_key_str(path)); if(local) { local->keep = TRUE; } @@ -528,21 +525,23 @@ return 1; } -void res2map(DavResource *root, UcxMap *map) { - UcxList *stack = ucx_list_prepend(NULL, root->children); - while(stack) { - DavResource *res = stack->data; - stack = ucx_list_remove(stack, stack); +void res2map(DavResource *root, CxMap *map) { + CxList *stack = cxLinkedListCreateSimple(CX_STORE_POINTERS); + cxListInsert(stack, 0, root->children); + while(stack->size > 0) { + DavResource *res = cxListAt(stack, 0); + cxListRemove(stack, 0); while(res) { - ucx_map_cstr_put(map, res->path, res); + cxMapPut(map, cx_hash_key_str(res->path), res); if(res->children) { - stack = ucx_list_prepend(stack, res->children); + cxListInsert(stack, 0, res->children); } res = res->next; } } + cxListDestroy(stack); } int cmd_pull(CmdArgs *a, DavBool incoming) { @@ -575,7 +574,7 @@ return -1; } - Repository *repo = get_repository(sstr(dir->repository)); + Repository *repo = get_repository(cx_str(dir->repository)); if(!repo) { fprintf(stderr, "Unknown repository %s\n", dir->repository); return -1; @@ -588,13 +587,13 @@ } remove_deleted_conflicts(dir, db); - UcxMap *hashes = NULL; + CxMap *hashes = NULL; if(SYNC_HASHING(dir)) { hashes = create_hash_index(db); } DavSession *sn = create_session(a, ctx, repo, dir->collection); - ucx_mempool_reg_destr(sn->mp, db, (ucx_destructor)destroy_db); + util_regdestr(sn->mp, db, (cx_destructor_func)destroy_db); if (cmd_getoption(a, "verbose")) { curl_easy_setopt(sn->handle, CURLOPT_VERBOSE, 1L); curl_easy_setopt(sn->handle, CURLOPT_STDERR, stderr); @@ -664,31 +663,32 @@ int sync_error = 0; int sync_conflict = 0; - UcxList *res_modified = NULL; - UcxList *res_new = NULL; - UcxList *res_moved = NULL; // type: MovedFile - UcxList *res_link = NULL; - UcxList *res_conflict = NULL; - UcxList *res_mkdir = NULL; - UcxList *res_metadata = NULL; - UcxList *res_broken = NULL; - UcxMap *lres_removed = ucx_map_new(16); // type: LocalResource* + CxList *res_modified = cxLinkedListCreateSimple(CX_STORE_POINTERS); + CxList *res_new = cxLinkedListCreateSimple(CX_STORE_POINTERS); + CxList *res_moved = cxLinkedListCreateSimple(CX_STORE_POINTERS); // type: MovedFile + CxList *res_link = cxLinkedListCreateSimple(CX_STORE_POINTERS); + CxList *res_conflict = cxLinkedListCreateSimple(CX_STORE_POINTERS); + CxList *res_mkdir = cxLinkedListCreateSimple(CX_STORE_POINTERS); + CxList *res_metadata = cxLinkedListCreateSimple(CX_STORE_POINTERS); + CxList *res_broken = cxLinkedListCreateSimple(CX_STORE_POINTERS); + CxMap *lres_removed = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 16); // type: LocalResource* //UcxMap *svrres = ucx_map_new(db->resources->count); - UcxMap *dbres = ucx_map_clone(db->resources, NULL, NULL); - - UcxList *stack = ucx_list_prepend(NULL, ls->children); - while(stack) { - DavResource *res = stack->data; - stack = ucx_list_remove(stack, stack); + CxMap *dbres = NULL; // TODO: ucx_map_clone(db->resources, NULL, NULL); + + CxList *stack = cxLinkedListCreateSimple(CX_STORE_POINTERS); + cxListInsert(stack, 0, ls->children); + while(stack->size > 0) { + DavResource *res = cxListAt(stack, 0); + cxListRemove(stack, 0); while(res) { DavBool res_filtered = FALSE; if (res_matches_dir_filter(dir, res->path)) { res_filtered = TRUE; } else { - UCX_FOREACH(elm, dir->filter.tags) { - SyncTagFilter *tf = elm->data; + CxIterator iter = cxListIterator(dir->filter.tags); + cx_foreach(SyncTagFilter *, tf, iter) { if(!res_matches_tags(res, tf)) { res_filtered = TRUE; break; @@ -714,7 +714,7 @@ if(status && !strcmp(status, "broken")) { res = res->next; localres_keep(db, res->path); - res_broken = ucx_list_append(res_broken, res); + cxListAdd(res_broken, res); continue; } @@ -723,28 +723,28 @@ switch(change) { case REMOTE_NO_CHANGE: break; case REMOTE_CHANGE_MODIFIED: { - res_modified = ucx_list_append(res_modified, res); + cxListAdd(res_modified, res); break; } case REMOTE_CHANGE_NEW: { - res_new = ucx_list_append(res_new, res); + cxListAdd(res_new, res); break; } case REMOTE_CHANGE_DELETED: break; // never happens case REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED: { - res_conflict = ucx_list_append(res_conflict, res); + cxListAdd(res_conflict, res); break; } case REMOTE_CHANGE_METADATA: { - res_metadata = ucx_list_append(res_metadata, res); + cxListAdd(res_metadata, res); break; } case REMOTE_CHANGE_MKDIR: { - res_mkdir = ucx_list_append(res_mkdir, res); + cxListAdd(res_mkdir, res); break; } case REMOTE_CHANGE_LINK: { - res_link = ucx_list_append(res_link, res); + cxListAdd(res_link, res); break; } } @@ -752,10 +752,10 @@ // remove every server resource from dbres // all remaining elements are the resources that are removed // on the server - ucx_map_cstr_remove(dbres, res->path); + cxMapRemove(dbres, cx_hash_key_str(res->path)); if(!dav_get_property_ns(res, DAV_NS, "split") && res->children) { - stack = ucx_list_prepend(stack, res->children); + cxListInsert(stack, 0, res->children); } res = res->next; } @@ -764,16 +764,15 @@ // find deleted resources // svrres currently contains all resources from the server // and will replace the current db->resources map later - UcxMapIterator i = ucx_map_iterator(dbres); - LocalResource *local; - UCX_MAP_FOREACH(key, local, i) { + CxIterator i = cxMapIteratorValues(dbres); + cx_foreach(LocalResource *, local, i) { if (res_matches_dir_filter(dir, local->path)) { continue; } if(!local->keep) { - ucx_map_cstr_put(lres_removed, local->path, local); - if(lres_removed->count > lres_removed->size * 2) { - ucx_map_rehash(lres_removed); + cxMapPut(lres_removed, cx_hash_key_str(local->path), local); + if(lres_removed->size > lres_removed->size * 2) { + cxMapRehash(lres_removed); } } } @@ -783,31 +782,25 @@ // // the first thing we need are all directories to put the files in - UCX_FOREACH(elm, res_mkdir) { - DavResource *res = elm->data; + i = cxListIterator(res_mkdir); + cx_foreach(DavResource *, res, i) { if(sync_get_collection(a, dir, res, db)) { sync_error++; } } // we need a map for all conflicts for fast lookups - UcxMap *conflicts = ucx_map_new(ucx_list_size(res_conflict)+16); - UCX_FOREACH(elm, res_conflict) { - DavResource *res = elm->data; - ucx_map_cstr_put(conflicts, res->path, res); + CxMap *conflicts = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, res_conflict->size+16); + i = cxListIterator(res_conflict); + cx_foreach(DavResource *, res, i) { + cxMapPut(conflicts, cx_hash_key_str(res->path), res); } if(SYNC_HASHING(dir)) { // check for moved/copied files - UcxList *elm = res_new; - UcxList *prev = NULL; - UcxList *next = NULL; SYS_STAT s; - for(;elm;elm=next) { - DavResource *res = elm->data; - prev = elm->prev; - next = elm->next; - + CxMutIterator mut_iter = cxListMutIterator(res_new); + cx_foreach(DavResource *, res, mut_iter) { if(dav_get_property_ns(res, DAV_PROPS_NS, "link")) { continue; } @@ -817,7 +810,7 @@ continue; } - LocalResource *local = ucx_map_cstr_get(hashes, hash); + LocalResource *local = cxMapGet(hashes, cx_hash_key_str(hash)); if(!local) { continue; } @@ -833,35 +826,28 @@ MovedFile *mf = malloc(sizeof(MovedFile)); mf->content = local; mf->resource = res; - if(ucx_map_cstr_remove(lres_removed, local->path)) { + if(cxMapRemoveAndGet(lres_removed, cx_hash_key_str(local->path))) { mf->copy = FALSE; } else { mf->copy = TRUE; } - res_moved = ucx_list_append(res_moved, mf); + cxListAdd(res_moved, mf); // remove item from res_new - if(prev) { - prev->next = next; - } else { - res_new = next; - } - if(next) { - next->prev = prev; - } + cxIteratorFlagRemoval(mut_iter); } } // do copy/move operations - UCX_FOREACH(elm, res_moved) { - MovedFile *mf = elm->data; + i = cxListIterator(res_moved); + cx_foreach(MovedFile *, mf, i) { if(sync_shutdown) { break; } DavBool issplit = dav_get_property_ns(mf->resource, DAV_NS, "split") ? 1 : 0; - if(ucx_map_cstr_get(conflicts, mf->resource->path)) { + if(cxMapGet(conflicts, cx_hash_key_str(mf->resource->path))) { rename_conflict_file(dir, db, mf->resource->path, issplit); sync_conflict++; } @@ -874,36 +860,45 @@ } // download all new, modified and conflict files - UcxList *download = ucx_list_concat(res_modified, res_conflict); - download = ucx_list_concat(res_new, download); - download = ucx_list_concat(download, res_link); - UCX_FOREACH(elm, download) { - DavResource *res = elm->data; + for(int n=0;n<4;n++) { + CxList *ls; + if(n == 0) { + ls = res_new; + } else if(n == 1) { + ls = res_modified; + } else if(n == 2) { + ls = res_conflict; + } else { + ls = res_link; + } + CxIterator iter = cxListIterator(ls); + cx_foreach(DavResource *, res, iter) { + if(sync_shutdown) { + break; + } + + DavBool issplit = dav_get_property_ns(res, DAV_NS, "split") ? 1 : 0; + if(cxMapGet(conflicts, cx_hash_key_str(res->path))) { + rename_conflict_file(dir, db, res->path, issplit); + sync_conflict++; + } + + // download the resource + if(sync_get_resource(a, dir, res->path, res, db, TRUE, &sync_success)) { + fprintf(stderr, "resource download failed: %s\n", res->path); + sync_error++; + } + } + } + + // update metadata + i = cxListIterator(res_metadata); + cx_foreach(DavResource *, res, i) { if(sync_shutdown) { break; } - DavBool issplit = dav_get_property_ns(res, DAV_NS, "split") ? 1 : 0; - if(ucx_map_cstr_get(conflicts, res->path)) { - rename_conflict_file(dir, db, res->path, issplit); - sync_conflict++; - } - - // download the resource - if(sync_get_resource(a, dir, res->path, res, db, TRUE, &sync_success)) { - fprintf(stderr, "resource download failed: %s\n", res->path); - sync_error++; - } - } - - // update metadata - UCX_FOREACH(elm, res_metadata) { - DavResource *res = elm->data; - if(sync_shutdown) { - break; - } - - LocalResource *local = ucx_map_cstr_get(db->resources, res->path); + LocalResource *local = cxMapGet(db->resources, cx_hash_key_str(res->path)); if(local) { printf("update: %s\n", res->path); char *res_path = resource_local_path(res); @@ -929,36 +924,35 @@ } } - UcxList *rmdirs = NULL; - UcxMapIterator mi = ucx_map_iterator(lres_removed); + CxList *rmdirs = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)resource_pathlen_cmp, CX_STORE_POINTERS); + i = cxMapIteratorValues(lres_removed); LocalResource *removed_res; - UcxKey key; - UCX_MAP_FOREACH(key, removed_res, mi) { + cx_foreach(LocalResource *, removed_res, i) { if(sync_shutdown) { break; } int ret = sync_remove_local_resource(dir, removed_res); if(ret == -1) { - rmdirs = ucx_list_append(rmdirs, removed_res); + cxListAdd(rmdirs, removed_res); } else if(ret == 0) { - LocalResource *local = ucx_map_cstr_remove(db->resources, removed_res->path); + LocalResource *local = cxMapRemoveAndGet(db->resources, cx_hash_key_str(removed_res->path)); if(local) { local_resource_free(local); } sync_delete++; } } - ucx_map_free(lres_removed); + cxMapDestroy(lres_removed); // sort dir list, we need to delete dirs with higher depth first - rmdirs = ucx_list_sort(rmdirs, (cmp_func)resource_pathlen_cmp, NULL); + cxListSort(rmdirs); // delete dirs - UCX_FOREACH(elm, rmdirs) { - LocalResource *local_dir = elm->data; + i = cxListIterator(rmdirs); + cx_foreach(LocalResource *, local_dir, i) { if(!sync_remove_local_directory(dir, local_dir)) { // dir successfully removed, now remove the related db entry - LocalResource *local = ucx_map_cstr_remove(db->resources, local_dir->path); + LocalResource *local = cxMapRemoveAndGet(db->resources, cx_hash_key_str(local_dir->path)); if(local) { local_resource_free(local); } @@ -1030,7 +1024,7 @@ RemoteChangeType type = cmd_getoption(a, "conflict") ? REMOTE_CHANGE_MODIFIED : REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; - LocalResource *local = ucx_map_cstr_get(db->resources, res->path); + LocalResource *local = cxMapGet(db->resources, cx_hash_key_str(res->path)); char *local_path = create_local_path(dir, res->path); char *link = SYNC_SYMLINK(dir) ? @@ -1081,9 +1075,9 @@ nochange = TRUE; } } else if(local->etag) { - sstr_t e = sstr(etag); - if(sstrprefix(e, S("W/"))) { - e = sstrsubs(e, 2); + cxstring e = cx_str(etag); + if(cx_strprefix(e, CX_STR("W/"))) { + e = cx_strsubs(e, 2); } if(!strcmp(e.ptr, local->etag)) { // resource is already up-to-date on the client @@ -1164,7 +1158,7 @@ // check if tags have changed if(dir->tagconfig) { DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_PROPS_NS, "tags"); - UcxList *remote_tags = NULL; + CxList *remote_tags = NULL; if(tagsprop) { remote_tags = parse_dav_xml_taglist(tagsprop); } @@ -1213,7 +1207,7 @@ local = calloc(1, sizeof(LocalResource)); local->path = strdup(res->path); - ucx_map_cstr_put(db->resources, local->path, local); + cxMapPut(db->resources, cx_hash_key_str(local->path), local); } // update local res @@ -1245,7 +1239,7 @@ local->size = s->st_size; } -static UcxList* sync_download_changed_parts( +static CxList* sync_download_changed_parts( DavResource *res, LocalResource *local, FILE *out, @@ -1254,7 +1248,8 @@ int64_t *truncate_file, int *err) { - UcxList *updates = NULL; + CxList *updates = cxLinkedListCreateSimple(CX_STORE_POINTERS); + updates->simple_destructor = (cx_destructor_func)filepart_free; size_t local_numparts = local ? local->numparts : 0; fseeko(out, 0, SEEK_END); @@ -1262,7 +1257,7 @@ int error = 0; - UcxBuffer *buf = ucx_buffer_new(NULL, blocksize, 0); + CxBuffer *buf = cxBufferCreate(NULL, blocksize, cxDefaultAllocator, 0); int64_t maxsize = -1; @@ -1306,7 +1301,7 @@ } buf->pos = 0; buf->size = 0; - if(dav_get_content(part, buf,(dav_write_func)ucx_buffer_write)) { + if(dav_get_content(part, buf,(dav_write_func)cxBufferWrite)) { fprintf(stderr, "Error: cannot download part: %s\n", part->name); error = 1; break; @@ -1321,7 +1316,7 @@ update->block = partnum; update->etag = etag ? strdup(etag) : NULL; update->hash = dav_create_hash(buf->space, buf->size); - updates = ucx_list_append(updates, update); + cxListAdd(updates, update); block_end = offset+buf->size; } else { @@ -1343,11 +1338,11 @@ part = part->next; } - ucx_buffer_free(buf); + cxBufferFree(buf); if(error) { *err = 1; - ucx_list_free_content(updates, (ucx_destructor)filepart_free); + cxListDestroy(updates); return NULL; } @@ -1373,7 +1368,7 @@ return 1; } - ucx_stream_copy(in, out, (read_func)fread, (write_func)fwrite); + cx_stream_copy(in, out, (cx_read_func)fread, (cx_write_func)fwrite); fclose(in); fclose(out); @@ -1415,7 +1410,7 @@ } else { // reuse previous LocalResource (content) // remove it from db->resources, change path and put it back - local = ucx_map_cstr_remove(db->resources, content->path); + local = cxMapRemoveAndGet(db->resources, cx_hash_key_str(content->path)); if(!local) { // can't happen, but handle it nevertheless local = content; @@ -1423,7 +1418,7 @@ free(content->path); local->path = strdup(res->path); } - ucx_map_cstr_put(db->resources, local->path, local); + cxMapPut(db->resources, cx_hash_key_str(local->path), local); if(sync_store_metadata(dir, new_path, local, res)) { fprintf(stderr, "Cannot store metadata: %s\n", res->path); @@ -1463,7 +1458,7 @@ char *link = SYNC_SYMLINK(dir) ? dav_get_string_property_ns(res, DAV_PROPS_NS, "link") : NULL; - LocalResource *local = ucx_map_cstr_get(db->resources, path); + LocalResource *local = cxMapGet(db->resources, cx_hash_key_str(path)); char *local_path; if(link) { @@ -1488,7 +1483,7 @@ } issplit = TRUE; } - UcxList *part_updates = NULL; + CxList *part_updates = NULL; uint64_t blockcount = 0; char *content_hash = NULL; @@ -1590,7 +1585,7 @@ // new local resource local = calloc(1, sizeof(LocalResource)); local->path = strdup(path); - ucx_map_cstr_put(db->resources, local->path, local); + cxMapPut(db->resources, cx_hash_key_str(local->path), local); } if(sync_store_metadata(dir, local_path, local, res)) { @@ -1673,11 +1668,11 @@ } // if it doesn't exist in the db, create an entry for the dir - LocalResource *local = ucx_map_cstr_get(db->resources, res->path); + LocalResource *local = cxMapGet(db->resources, cx_hash_key_str(res->path)); if(!local) { local = calloc(1, sizeof(LocalResource)); local->path = strdup(res->path); - ucx_map_cstr_put(db->resources, local->path, local); + cxMapPut(db->resources, cx_hash_key_str(local->path), local); } local->isdirectory = 1; @@ -1770,14 +1765,14 @@ int loop = 1; do { char *res_parent = util_parent_path(path); - char *res_name = util_resource_name(path); + const char *res_name = util_resource_name(path); - sstr_t new_path = ucx_sprintf( + cxmutstr new_path = cx_asprintf( "%sorig.%d.%s", parent, rev, res_name); - sstr_t new_res_path = ucx_sprintf( + cxmutstr new_res_path = cx_asprintf( "%sorig.%d.%s", res_parent, rev, @@ -1799,7 +1794,7 @@ LocalResource *conflict = calloc(1, sizeof(LocalResource)); conflict->path = strdup(new_res_path.ptr); conflict->conflict_source = strdup(path); - ucx_map_cstr_put(db->conflict, new_res_path.ptr, conflict); + cxMapPut(db->conflict, cx_hash_key_str(new_res_path.ptr), conflict); } } } @@ -1817,8 +1812,7 @@ char *new_path = NULL; char *parent = util_parent_path(path); for (int i=0;;i++) { - sstr_t np = ucx_asprintf( - ucx_default_allocator(), + cxmutstr np = cx_asprintf( "%sdownload%d-%s", parent, i, @@ -1841,8 +1835,7 @@ void move_to_trash(SyncDirectory *dir, char *path) { char *new_path = NULL; for (int i=0;;i++) { - sstr_t np = ucx_asprintf( - ucx_default_allocator(), + cxmutstr np = cx_asprintf( "%s%d-%s", dir->trash, i, @@ -1876,7 +1869,7 @@ } static int res_isconflict(SyncDatabase *db, LocalResource *res) { - return ucx_map_cstr_get(db->conflict, res->path) ? 1 : 0; + return cxMapGet(db->conflict, cx_hash_key_str(res->path)) ? 1 : 0; } int cmd_push(CmdArgs *a, DavBool outgoing, DavBool archive) { @@ -1917,7 +1910,7 @@ return -1; } - Repository *repo = get_repository(sstr(dir->repository)); + Repository *repo = get_repository(cx_str(dir->repository)); if(!repo) { fprintf(stderr, "Unkown repository %s\n", dir->name); return -1; @@ -1931,7 +1924,7 @@ remove_deleted_conflicts(dir, db); DavSession *sn = create_session(a, ctx, repo, dir->collection); - ucx_mempool_reg_destr(sn->mp, db, (ucx_destructor)destroy_db); + util_regdestr(sn->mp, db, (cx_destructor_func)destroy_db); if (cmd_getoption(a, "verbose")) { curl_easy_setopt(sn->handle, CURLOPT_VERBOSE, 1L); curl_easy_setopt(sn->handle, CURLOPT_STDERR, stderr); @@ -1953,9 +1946,9 @@ return -1; } - UcxMap *svrres = NULL; + CxMap *svrres = NULL; if(restore) { - svrres = ucx_map_new(1024); + svrres = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 1024); res2map(root, svrres); } @@ -1981,7 +1974,7 @@ DavBool remove_file = cmd_getoption(a, "remove") ? 1 : 0; - UcxMap *db_hashes = NULL; + CxMap *db_hashes = NULL; if(SYNC_HASHING(dir)) { db_hashes = create_hash_index(db); } @@ -1991,23 +1984,24 @@ int sync_conflict = 0; int sync_error = 0; - UcxList *ls_new = NULL; - UcxList *ls_modified = NULL; - UcxList *ls_conflict = NULL; - UcxList *ls_update = NULL; - UcxList *ls_delete = NULL; - UcxList *ls_move = NULL; - UcxList *ls_copy = NULL; - UcxList *ls_mkcol = NULL; + CxList *ls_new = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)resource_path_cmp, CX_STORE_POINTERS); + CxList *ls_modified = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)resource_path_cmp, CX_STORE_POINTERS); + CxList *ls_conflict = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)resource_path_cmp, CX_STORE_POINTERS); + CxList *ls_update = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)resource_path_cmp, CX_STORE_POINTERS); + CxList *ls_delete = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)resource_path_cmp, CX_STORE_POINTERS); + CxList *ls_move = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)resource_path_cmp, CX_STORE_POINTERS); + CxList *ls_copy = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)resource_path_cmp, CX_STORE_POINTERS); + CxList *ls_mkcol = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)resource_path_cmp, CX_STORE_POINTERS); + // upload all changed files //UcxList *resources = cmd_getoption(a, "read") ? // read_changes(dir, db) : local_scan(dir, db); - UcxList *resources = local_scan(dir, db); - UcxMap *resources_map = ucx_map_new(ucx_list_size(resources)+16); - - UCX_FOREACH(elm, resources) { - LocalResource *local_res = elm->data; + CxList *resources = local_scan(dir, db); + CxMap *resources_map = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, resources->size+16); + + CxIterator iter = cxListIterator(resources); + cx_foreach(LocalResource *, local_res, iter) { // ignore all files, that are excluded by a static filter (sync.xml) // static include/exclude filter @@ -2015,22 +2009,25 @@ continue; } // static tag filter - UCX_FOREACH(elm, dir->filter.tags) { - SyncTagFilter *tf = elm->data; - if(!localres_matches_tags(dir, local_res, tf)) { - continue; + if(dir->filter.tags) { + CxIterator tag_iter = cxListIterator(dir->filter.tags); + cx_foreach(SyncTagFilter *, tf, tag_iter) { + if(!localres_matches_tags(dir, local_res, tf)) { + continue; + } } } + // we need a fast file lookup map later to detect deleted files - ucx_map_cstr_put(resources_map, local_res->path, local_res); + cxMapPut(resources_map, cx_hash_key_str(local_res->path), local_res); // dynamic tag filter if(!localres_matches_tags(dir, local_res, tagfilter)) { if(!remove_file) { - LocalResource *dbres = ucx_map_cstr_get( + LocalResource *dbres = cxMapGet( db->resources, - local_res->path); + cx_hash_key_str(local_res->path)); if(dbres) { // this makes sure the file will not be deleted later dbres->keep = TRUE; @@ -2041,7 +2038,7 @@ // skip conflict backups silently if(res_isconflict(db, local_res)) { - ls_conflict = ucx_list_append(ls_conflict, local_res); + cxListAdd(ls_conflict, local_res); continue; } @@ -2054,14 +2051,14 @@ restore_modified); if(is_changed) { if(local_res->isdirectory) { - ls_mkcol = ucx_list_append(ls_mkcol, local_res); + cxListAdd(ls_mkcol, local_res); } else if(local_res->isnew) { - ls_new = ucx_list_append(ls_new, local_res); + cxListAdd(ls_new, local_res); } else { - ls_modified = ucx_list_append(ls_modified, local_res); + cxListAdd(ls_modified, local_res); } } else if(local_res->metadata_updated) { - ls_update = ucx_list_append(ls_update, local_res); + cxListAdd(ls_update, local_res); } if(local_res->isnew) { @@ -2077,13 +2074,9 @@ if(SYNC_STORE_HASH(dir)) { // calculate hashes of all new files and check if a file // was moved or is a copy - UcxList *elm = ls_new; - while(elm) { - LocalResource *local = elm->data; - UcxList *prev = elm->prev; - UcxList *next = elm->next; + CxMutIterator mut_iter = cxListMutIterator(ls_new); + cx_foreach(LocalResource *, local, mut_iter) { if(local->isdirectory || local->link_target) { - elm = elm->next; continue; } @@ -2091,78 +2084,70 @@ char *hash = util_file_hash(local_path); local->hash = hash; // check if a file with this hash already exists - LocalResource *origin = ucx_map_cstr_get(db_hashes, hash); + LocalResource *origin = cxMapGet(db_hashes, cx_hash_key_str(hash)); if(origin) { local->origin = local_resource_copy(origin, origin->path); // the file is a copied/moved file // check if the file is in the resources_map, because then // it still exists - if(ucx_map_cstr_get(resources_map, origin->path)) { - ls_copy = ucx_list_append(ls_copy, local); + if(cxMapGet(resources_map, cx_hash_key_str(origin->path))) { + cxListAdd(ls_copy, local); } else { - ls_move = ucx_list_append(ls_move, local); + cxListAdd(ls_move, local); // put file in resources_map to prevent deletion - ucx_map_cstr_put(resources_map, origin->path, local); + cxMapPut(resources_map, cx_hash_key_str(origin->path), local); } // remove list elemend from ls_new - if(prev) { - prev->next = next; - } else { - ls_new = next; - } - if(next) { - next->prev = prev; - } + cxIteratorFlagRemoval(mut_iter); } free(local_path); - - elm = next; } } // find all deleted files and cleanup the database - UcxMapIterator i = ucx_map_iterator(db->resources); + iter = cxMapIterator(db->resources); LocalResource *local; - UcxList *removed_res = NULL; - UCX_MAP_FOREACH(key, local, i) { + CxList *removed_res = cxLinkedListCreateSimple(CX_STORE_POINTERS); + cx_foreach(CxMapEntry *, entry, iter) { + LocalResource *local = entry->value; // all filtered files should be removed from the database if(res_matches_dir_filter(dir, local->path+1)) { - ucx_map_cstr_remove(db->resources, local->path); + cxMapRemove(db->resources, local->path); continue; } - UCX_FOREACH(elm, dir->filter.tags) { - SyncTagFilter *tf = elm->data; + CxIterator tag_iter = cxListIterator(dir->filter.tags); + cx_foreach(SyncTagFilter *, tf, tag_iter) { if(!localres_matches_tags(dir, local, tf)) { - ucx_map_cstr_remove(db->resources, local->path); + cxMapRemove(db->resources, local->path); continue; } } - if(!ucx_map_get(resources_map, key)) { + if(!cxMapGet(resources_map, *entry->key)) { // The current LocalResource is in the database but doesn't exist // in the filesystem anymore. This means the file was deleted // and should be deleted on the server if(!archive) { - ls_delete = ucx_list_append(ls_delete, local); + cxListAdd(ls_delete, local); } else { - removed_res = ucx_list_prepend(removed_res, local); + cxListInsert(removed_res, 0, local); } } } - UCX_FOREACH(elm, removed_res) { - LocalResource *local = elm->data; - ucx_map_cstr_remove(db->resources, local->path); - } - - ls_new = ucx_list_sort(ls_new, (cmp_func)resource_path_cmp, NULL); - ls_modified = ucx_list_sort(ls_modified, (cmp_func)resource_path_cmp, NULL); - ls_conflict = ucx_list_sort(ls_conflict, (cmp_func)resource_path_cmp, NULL); - ls_update = ucx_list_sort(ls_update, (cmp_func)resource_path_cmp, NULL); - ls_delete = ucx_list_sort(ls_delete, (cmp_func)resource_path_cmp, NULL); - ls_move = ucx_list_sort(ls_move, (cmp_func)resource_path_cmp, NULL); - ls_copy = ucx_list_sort(ls_copy, (cmp_func)resource_path_cmp, NULL); - ls_mkcol = ucx_list_sort(ls_mkcol, (cmp_func)resource_path_cmp, NULL); + iter = cxListIterator(removed_res); + cx_foreach(LocalResource *, local, iter) { + cxMapRemove(db->resources, local->path); + } + + cxListSort(ls_new); + cxListSort(ls_modified); + cxListSort(ls_conflict); + cxListSort(ls_update); + cxListSort(ls_delete); + cxListSort(ls_move); + cxListSort(ls_copy); + cxListSort(ls_mkcol); if(outgoing) { print_outgoing( @@ -2186,8 +2171,11 @@ int error = 0; // create collections - for(UcxList *elm=ls_mkcol;elm && !sync_shutdown;elm=elm->next) { - LocalResource *local_res = elm->data; + iter = cxListIterator(ls_mkcol); + cx_foreach(LocalResource *, local_res, iter) { + if(sync_shutdown) { + break; + } DavResource *res = dav_resource_new(sn, local_res->path); if(!res) { @@ -2227,8 +2215,9 @@ // remove old db entry (if it exists) // and add add new entry - LocalResource *dbres = ucx_map_cstr_remove(db->resources, local_res->path); - ucx_map_cstr_put(db->resources, local_res->path, local_res); + // TODO: free?? + LocalResource *dbres = cxMapGet(db->resources, cx_hash_key_str(local_res->path)); + cxMapPut(db->resources, cx_hash_key_str(local_res->path), local_res); } dav_resource_free(res); @@ -2240,163 +2229,176 @@ copy = FALSE; ls_copy = ls_move; } - for(UcxList *elm=ls_copy;elm && !sync_shutdown;elm=elm->next) { - LocalResource *local = elm->data; - - int err = 0; - DavResource *res = dav_resource_new(sn, local->path); - if(dav_exists(res)) { - printf("conflict: %s\n", local->path); - local->last_modified = 0; - nullfree(local->etag); - local->etag = NULL; - nullfree(local->hash); - local->hash = NULL; - local->skipped = TRUE; - sync_conflict++; - } else { - DavResource *origin_res = dav_resource_new(sn, local->origin->path); - int origin_changed = remote_resource_is_changed( - sn, - dir, - db, - origin_res, - local->origin, - NULL); - if(origin_changed) { - // upload with put - ls_modified = ucx_list_prepend(ls_modified, local); + iter = cxListIterator(ls_copy); + for(int i=0;i<2;i++) { + cx_foreach(LocalResource*, local, iter) { + if(sync_shutdown) { + break; + } + + int err = 0; + DavResource *res = dav_resource_new(sn, local->path); + if(dav_exists(res)) { + printf("conflict: %s\n", local->path); + local->last_modified = 0; + nullfree(local->etag); + local->etag = NULL; + nullfree(local->hash); + local->hash = NULL; + local->skipped = TRUE; + sync_conflict++; } else { - printf("%s: %s -> %s\n", copy ? "copy":"move", local->origin->path, local->path); - err = sync_move_remote_resource( + DavResource *origin_res = dav_resource_new(sn, local->origin->path); + int origin_changed = remote_resource_is_changed( + sn, dir, db, origin_res, - local, - copy, - &sync_success); + local->origin, + NULL); + if(origin_changed) { + // upload with put + cxListInsert(ls_modified, 0, local); + } else { + printf("%s: %s -> %s\n", copy ? "copy":"move", local->origin->path, local->path); + err = sync_move_remote_resource( + dir, + db, + origin_res, + local, + copy, + &sync_success); + } } - } - - if(err) { - sync_error++; - print_resource_error(sn, res->path); - ret = -1; - error = 1; - } else { - LocalResource *dbres = ucx_map_cstr_remove(db->resources, local->path); - ucx_map_cstr_put(db->resources, local->path, local); - } - - if(copy && !elm->next) { - // finished copy, begin move - elm->next = ls_move; - copy = FALSE; - } + + if(err) { + sync_error++; + print_resource_error(sn, res->path); + ret = -1; + error = 1; + } else { + LocalResource *dbres = cxMapGet(db->resources, cx_hash_key_str(local->path)); + cxMapPut(db->resources, cx_hash_key_str(local->path), local); + } + } + copy = FALSE; + iter = cxListIterator(ls_move); } // upload changed files - ls_modified = ucx_list_concat(ls_new, ls_modified); - - for(UcxList *elm=ls_modified;elm && !sync_shutdown;elm=elm->next) { - LocalResource *local_res = elm->data; - int err = 0; - - DavResource *res = dav_resource_new(sn, local_res->path); - if(!res) { - print_resource_error(sn, local_res->path); - ret = -1; - sync_error++; - } else { - DavBool equal = FALSE; - DavBool res_conflict = FALSE; - int changed = remote_resource_is_changed(sn, dir, db, res, local_res, &equal); - if(equal) { - char *etag = dav_get_string_property(res, "D:getetag"); - if(local_res->metadata_updated) { - ls_update = ucx_list_prepend(ls_update, local_res); - } else if(etag) { - // update etag in db - if(local_res->etag) { - free(local_res->etag); + //ls_modified = ucx_list_concat(ls_new, ls_modified); + iter = cxListIterator(ls_new); + for(int i=0;i<2;i++) { + cx_foreach(LocalResource*, local_res, iter) { + if(sync_shutdown) { + break; + } + + int err = 0; + + DavResource *res = dav_resource_new(sn, local_res->path); + if(!res) { + print_resource_error(sn, local_res->path); + ret = -1; + sync_error++; + } else { + DavBool equal = FALSE; + DavBool res_conflict = FALSE; + int changed = remote_resource_is_changed(sn, dir, db, res, local_res, &equal); + if(equal) { + char *etag = dav_get_string_property(res, "D:getetag"); + if(local_res->metadata_updated) { + cxListInsert(ls_update, 0, local_res); + } else if(etag) { + // update etag in db + if(local_res->etag) { + free(local_res->etag); + } + local_res->etag = strdup(etag); } - local_res->etag = strdup(etag); + } else if(cdt && changed) { + printf("conflict: %s\n", local_res->path); + local_res->last_modified = 0; + nullfree(local_res->etag); + local_res->etag = NULL; + nullfree(local_res->hash); + local_res->hash = NULL; + local_res->skipped = TRUE; + sync_conflict++; + + if(local_res->link_target) { + free(local_res->link_target); + local_res->link_target = local_res->link_target_db; + local_res->link_target_db = NULL; + } + + res_conflict = TRUE; + } else { + if(local_res->link_target) { + printf( + "link: %s -> %s\n", + local_res->path, + local_res->link_target); + } else { + printf("put: %s\n", local_res->path); + } + if(sync_put_resource(dir, res, local_res, &sync_success)) { + sync_error++; + print_resource_error(sn, res->path); + ret = -1; + error = 1; + + err = 1; + } } - } else if(cdt && changed) { - printf("conflict: %s\n", local_res->path); - local_res->last_modified = 0; - nullfree(local_res->etag); - local_res->etag = NULL; - nullfree(local_res->hash); - local_res->hash = NULL; - local_res->skipped = TRUE; - sync_conflict++; - - if(local_res->link_target) { - free(local_res->link_target); - local_res->link_target = local_res->link_target_db; - local_res->link_target_db = NULL; - } - - res_conflict = TRUE; - } else { - if(local_res->link_target) { - printf( - "link: %s -> %s\n", - local_res->path, - local_res->link_target); - } else { - printf("put: %s\n", local_res->path); - } - if(sync_put_resource(dir, res, local_res, &sync_success)) { - sync_error++; - print_resource_error(sn, res->path); - ret = -1; - error = 1; - - err = 1; + + if(!err) { + LocalResource *dbres = cxMapRemoveAndGet(db->resources, cx_hash_key_str(local_res->path)); + // in case of a conflict, don't store the resource + // in the db, if it is new + if(!res_conflict || dbres) { + cxMapPut(db->resources, cx_hash_key_str(local_res->path), local_res); + } } } - - if(!err) { - LocalResource *dbres = ucx_map_cstr_remove(db->resources, local_res->path); - // in case of a conflict, don't store the resource - // in the db, if it is new - if(!res_conflict || dbres) { - ucx_map_cstr_put(db->resources, local_res->path, local_res); - } - } - } - - dav_resource_free(res); + + dav_resource_free(res); + } + iter = cxListIterator(ls_modified); } // metadata updates - for(UcxList *elm=ls_update;elm && !sync_shutdown;elm=elm->next) { - LocalResource *local_res = elm->data; + iter = cxListIterator(ls_update); + cx_foreach(LocalResource *, local_res, iter) { + if(sync_shutdown) { + break; + } DavResource *res = dav_resource_new(sn, local_res->path); if(local_res->metadata_updated) { printf("update: %s\n", local_res->path); if(!sync_update_metadata(dir, sn, res, local_res)) { - LocalResource *dbres = ucx_map_cstr_remove(db->resources, local_res->path); - ucx_map_cstr_put(db->resources, local_res->path, local_res); + LocalResource *dbres = cxMapGet(db->resources, cx_hash_key_str(local_res->path)); + cxMapPut(db->resources, cx_hash_key_str(local_res->path), local_res); } } } // delete all removed files - ls_delete = ucx_list_sort(ls_delete, (cmp_func)resource_pathlen_cmp, NULL); - - UcxList *cols = NULL; - UcxList **col_list = &cols; - UcxList *deletelist = ls_delete; + cxListSort(ls_delete); + + CxList *cols = cxLinkedListCreateSimple(CX_STORE_POINTERS); + CxList *col_list = cols; + CxList *deletelist = ls_delete; for(int i=0;i<2;i++) { // the first iteration deletes everything from ls_delete except // all collections, which are stored in cols // in the second run all collections will be deleted - for(UcxList *elm=deletelist;elm && !sync_shutdown;elm=elm->next) { - LocalResource *local = elm->data; + iter = cxListIterator(deletelist); + cx_foreach(LocalResource *, local, iter) { + if(sync_shutdown) { + break; + } if(local->keep) { continue; } @@ -2407,7 +2409,7 @@ break; } } else { - LocalResource *dbres = ucx_map_cstr_remove(db->resources, local->path); + LocalResource *dbres = cxMapRemoveAndGet(db->resources, cx_hash_key_str(local->path)); //local_resource_free(dbres); } } @@ -2477,14 +2479,14 @@ } SyncDirectory *dir = NULL; - UcxMap *files = NULL; + CxMap *files = NULL; if(syncdir) { dir = scfg_get_dir(syncdir); } LocalResource nres; if(a->argc > 0) { - files = ucx_map_new(a->argc+8); + files = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, a->argc+8); // get all specified files and check the syncdir SyncDirectory *sd = NULL; for(int i=0;i<a->argc;i++) { @@ -2503,7 +2505,7 @@ } } - ucx_map_cstr_put(files, f.path, &nres); + cxMapPut(files, cx_hash_key_str(f.path), &nres); } dir = sd; } @@ -2536,16 +2538,16 @@ } remove_deleted_conflicts(dir, db); - UcxList *modified = NULL; - UcxList *deleted = NULL; + CxList *modified = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)localres_cmp_path, CX_STORE_POINTERS); + CxList *deleted = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)localres_cmp_path, CX_STORE_POINTERS); // iterate over all db resources and check if any resource is // modified or deleted - UcxMapIterator i = ucx_map_iterator(files ? files : db->resources); - LocalResource *resource; - UCX_MAP_FOREACH(key, resource, i) { + CxIterator i = cxMapIterator(files ? files : db->resources); + cx_foreach(CxMapEntry *, entry, i) { + LocalResource *resource = entry->value; if(resource == &nres) { - resource = ucx_map_get(db->resources, key); + resource = cxMapGet(db->resources, *entry->key); if(!resource) { continue; } @@ -2556,7 +2558,7 @@ if(sys_stat(file_path, &s)) { if(errno == ENOENT) { if(restore_removed) { - deleted = ucx_list_prepend(deleted, resource); + cxListAdd(deleted, resource); } } else { fprintf(stderr, "Cannot stat file: %s\n", file_path); @@ -2564,11 +2566,11 @@ } } else { if(files) { - modified = ucx_list_prepend(modified, resource); + cxListAdd(modified, resource); } else if(!resource->isdirectory && !S_ISDIR(s.st_mode)) { if(resource->last_modified != s.st_mtime || resource->size != s.st_size) { if(restore_modified) { - modified = ucx_list_prepend(modified, resource); + cxListAdd(modified, resource); } } } @@ -2578,19 +2580,19 @@ } if(files) { - ucx_map_free(files); + cxMapDestroy(files); } int ret = 0; // create DavSession - Repository *repo = get_repository(sstr(dir->repository)); + Repository *repo = get_repository(cx_str(dir->repository)); if(!repo) { fprintf(stderr, "Unkown repository %s\n", dir->name); return -1; } DavSession *sn = create_session(a, ctx, repo, dir->collection); - ucx_mempool_reg_destr(sn->mp, db, (ucx_destructor)destroy_db); + util_regdestr(sn->mp, db, (cx_destructor_func)destroy_db); if (cmd_getoption(a, "verbose")) { curl_easy_setopt(sn->handle, CURLOPT_VERBOSE, 1L); curl_easy_setopt(sn->handle, CURLOPT_STDERR, stderr); @@ -2619,70 +2621,74 @@ int sync_success = 0; int sync_error = 0; - UcxList *resources = ucx_list_concat(modified, deleted); - resources = ucx_list_sort(resources, (cmp_func)localres_cmp_path, NULL); - - UCX_FOREACH(elm, resources) { - LocalResource *resource = elm->data; - - DavResource *res = dav_get(sn, resource->path, "D:getetag,idav:status,idav:version-collection,idav:split,`idav:content-hash`,idavprops:tags,idavprops:finfo,idavprops:xattributes,idavprops:link"); - if(!res) { - printf("skip: %s\n", resource->path); - continue; - } - char *status = dav_get_string_property(res, "idav:status"); - if(status && !strcmp(status, "broken")) { - fprintf(stderr, "Resource %s broken\n", res->path); - continue; - } - - DavResource *vres = NULL; - DavBool update_local_entry = TRUE; - if(version) { - if(dir->versioning->type == VERSIONING_SIMPLE) { - vres = versioning_simple_find(res, version); - } else if(dir->versioning->type == VERSIONING_DELTAV) { - vres = versioning_deltav_find(res, version); + // TODO: old code sorted both modified and deleted, is this necessary? + //UcxList *resources = ucx_list_concat(modified, deleted); + //resources = ucx_list_sort(resources, (cmp_func)localres_cmp_path, NULL); + cxListSort(deleted); + + CxIterator iter = cxListIterator(modified); + for(int i=0;i<2;i++) { + cx_foreach(LocalResource *, resource, iter) { + DavResource *res = dav_get(sn, resource->path, "D:getetag,idav:status,idav:version-collection,idav:split,`idav:content-hash`,idavprops:tags,idavprops:finfo,idavprops:xattributes,idavprops:link"); + if(!res) { + printf("skip: %s\n", resource->path); + continue; } - if(!vres) { - fprintf(stderr, "Cannot find specified version for resource %s\n", res->path); - ret = 1; - break; + char *status = dav_get_string_property(res, "idav:status"); + if(status && !strcmp(status, "broken")) { + fprintf(stderr, "Resource %s broken\n", res->path); + continue; } - - // By restoring an old version of a file, the local dir is not - // in sync with the server anymore. Mark this file to change - // the metadata later, to make sure, the file will be detected - // as locally modified, on the next push/pull - update_local_entry = FALSE; - } else { - vres = res; - } - - // download the resource - if(!sync_shutdown) { - if(resource->isdirectory) { - char *local_path = create_local_path(dir, res->path); - if(sys_mkdir(local_path) && errno != EEXIST) { - fprintf(stderr, - "Cannot create directory %s: %s", - local_path, strerror(errno)); + + DavResource *vres = NULL; + DavBool update_local_entry = TRUE; + if(version) { + if(dir->versioning->type == VERSIONING_SIMPLE) { + vres = versioning_simple_find(res, version); + } else if(dir->versioning->type == VERSIONING_DELTAV) { + vres = versioning_deltav_find(res, version); + } + if(!vres) { + fprintf(stderr, "Cannot find specified version for resource %s\n", res->path); + ret = 1; + break; } - free(local_path); + + // By restoring an old version of a file, the local dir is not + // in sync with the server anymore. Mark this file to change + // the metadata later, to make sure, the file will be detected + // as locally modified, on the next push/pull + update_local_entry = FALSE; } else { - if(sync_get_resource(a, dir, res->path, vres, db, update_local_entry, &sync_success)) { - fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path); - sync_error++; - } else if(!update_local_entry) { - LocalResource *lr = ucx_map_cstr_get(db->resources, res->path); - if(lr) { - lr->last_modified = 0; - nullfree(lr->hash); - lr->hash = NULL; - } // else should not happen + vres = res; + } + + // download the resource + if(!sync_shutdown) { + if(resource->isdirectory) { + char *local_path = create_local_path(dir, res->path); + if(sys_mkdir(local_path) && errno != EEXIST) { + fprintf(stderr, + "Cannot create directory %s: %s", + local_path, strerror(errno)); + } + free(local_path); + } else { + if(sync_get_resource(a, dir, res->path, vres, db, update_local_entry, &sync_success)) { + fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path); + sync_error++; + } else if(!update_local_entry) { + LocalResource *lr = cxMapGet(db->resources, cx_hash_key_str(res->path)); + if(lr) { + lr->last_modified = 0; + nullfree(lr->hash); + lr->hash = NULL; + } // else should not happen + } } } } + iter = cxListIterator(deleted); } // unlock repository @@ -2730,25 +2736,25 @@ void print_outgoing( CmdArgs *args, - UcxList *ls_new, - UcxList *ls_modified, - UcxList *ls_conflict, - UcxList *ls_update, - UcxList *ls_delete, - UcxList *ls_move, - UcxList *ls_copy, - UcxList *ls_mkcol) + CxList *ls_new, + CxList *ls_modified, + CxList *ls_conflict, + CxList *ls_update, + CxList *ls_delete, + CxList *ls_move, + CxList *ls_copy, + CxList *ls_mkcol) { int64_t total_size = 0; - size_t len_new = ucx_list_size(ls_new); - size_t len_mod = ucx_list_size(ls_modified); - size_t len_cnf = ucx_list_size(ls_conflict); - size_t len_upd = ucx_list_size(ls_update); - size_t len_del = ucx_list_size(ls_delete); - size_t len_mov = ucx_list_size(ls_move); - size_t len_cpy = ucx_list_size(ls_copy); - size_t len_mkc = ucx_list_size(ls_mkcol); + size_t len_new = ls_new->size; + size_t len_mod = ls_modified->size; + size_t len_cnf = ls_conflict->size; + size_t len_upd = ls_update->size; + size_t len_del = ls_delete->size; + size_t len_mov = ls_move->size; + size_t len_cpy = ls_copy->size; + size_t len_mkc = ls_mkcol->size; size_t total = len_new + len_mod + len_cnf + len_upd + len_del + len_mov + len_cpy + len_mkc; if(total == 0) { @@ -2761,32 +2767,32 @@ if(ls_mkcol) { printf("Directories:\n"); - UCX_FOREACH(elm, ls_mkcol) { - LocalResource *res = elm->data; + CxIterator i = cxListIterator(ls_mkcol); + cx_foreach(LocalResource *, res, i) { printf(" %-49s\n", res->path+1); total_size += res->size; } } if(ls_new) { printf("New:\n"); - UCX_FOREACH(elm, ls_new) { - LocalResource *res = elm->data; - print_outgoging_file(elm->data); + CxIterator i = cxListIterator(ls_new); + cx_foreach(LocalResource *, res, i) { + print_outgoging_file(res); total_size += res->size; } } if(ls_modified) { printf("Modified:\n"); - UCX_FOREACH(elm, ls_modified) { - LocalResource *res = elm->data; - print_outgoging_file(elm->data); + CxIterator i = cxListIterator(ls_modified); + cx_foreach(LocalResource *, res, i) { + print_outgoging_file(res); total_size += res->size; } } if(ls_update) { printf("Update:\n"); - UCX_FOREACH(elm, ls_update) { - LocalResource *res = elm->data; + CxIterator i = cxListIterator(ls_update); + cx_foreach(LocalResource *, res, i) { char *lastmodified = util_date_str(res->last_modified); printf(" %-49s %12s\n", res->path+1, lastmodified); free(lastmodified); @@ -2794,29 +2800,29 @@ } if(ls_delete) { printf("Delete:\n"); - UCX_FOREACH(elm, ls_delete) { - LocalResource *res = elm->data; + CxIterator i = cxListIterator(ls_delete); + cx_foreach(LocalResource *, res, i) { printf(" %s\n", res->path+1); } } if(ls_copy) { printf("Copy:\n"); - UCX_FOREACH(elm, ls_copy) { - LocalResource *res = elm->data; + CxIterator i = cxListIterator(ls_copy); + cx_foreach(LocalResource *, res, i) { printf("%s -> %s\n", res->origin->path+1, res->path); } } if(ls_move) { printf("Move:\n"); - UCX_FOREACH(elm, ls_move) { - LocalResource *res = elm->data; + CxIterator i = cxListIterator(ls_move); + cx_foreach(LocalResource *, res, i) { printf("%s -> %s\n", res->origin->path+1, res->path); } } if(ls_conflict) { printf("Conflict\n"); - UCX_FOREACH(elm, ls_conflict) { - LocalResource *res = elm->data; + CxIterator i = cxListIterator(ls_conflict); + cx_foreach(LocalResource *, res, i) { printf(" %s\n", res->path+1); } } @@ -2836,17 +2842,18 @@ free(total_size_str); } -UcxList* local_scan(SyncDirectory *dir, SyncDatabase *db) { - UcxList *resources = NULL; +CxList* local_scan(SyncDirectory *dir, SyncDatabase *db) { + CxList *resources = cxLinkedListCreateSimple(CX_STORE_POINTERS); char *path = strdup("/"); - UcxList *stack = ucx_list_prepend(NULL, path); - while(stack) { + CxList *stack = cxLinkedListCreateSimple(CX_STORE_POINTERS); + cxListInsert(stack, 0, path); + while(stack->size > 0) { // get a directory path from the stack and read all entries // if an entry is a directory, put it on the stack - char *p = stack->data; - stack = ucx_list_remove(stack, stack); + char *p = cxListAt(stack, 0); + cxListRemove(stack, 0); char *local_path = create_local_path(dir, p); SYS_DIR local_dir = sys_opendir(local_path); @@ -2864,11 +2871,11 @@ LocalResource *res = local_resource_new(dir, db, new_path); if(res) { if(res->isdirectory) { - resources = ucx_list_append(resources, res); - stack = ucx_list_prepend(stack, new_path); + cxListAdd(resources, res); + cxListInsert(stack, 0, new_path); free_new_path = FALSE; } else { - resources = ucx_list_append(resources, res); + cxListAdd(resources, res); } } if(free_new_path) { @@ -2885,50 +2892,6 @@ return resources; } -UcxList* read_changes(SyncDirectory *dir, SyncDatabase *db) { - UcxProperties *parser = ucx_properties_new(); - parser->delimiter = ':'; - - UcxList *resources = NULL; - sstr_t name; - sstr_t value; - - char buf[STDIN_BUF_SIZE]; - size_t r; - while(!feof(stdin)) { - r = fread(buf, 1, STDIN_BUF_SIZE, stdin); - ucx_properties_fill(parser, buf, r); - while(ucx_properties_next(parser, &name, &value)) { - if(value.length == 0) { - fprintf(stderr, "Wrong input\n"); - continue; - } - if(value.ptr[0] == '"' - && value.length > 2 - && value.ptr[value.length - 1] == '"') - { - value.ptr[value.length - 1] = '\0'; - value.ptr++; - value.length -= 2; - } - value = sstrdup(value); - - if(!sstrcmp(name, S("put"))) { - LocalResource *res = local_resource_new(dir, db, value.ptr); - if(res) { - resources = ucx_list_append(resources, res); - } - } else if(!sstrcmp(name, S("remove"))) { - ucx_map_sstr_remove(db->resources, value); - } - - free(value.ptr); - } - } - ucx_properties_free(parser); - - return resources; -} LocalResource* local_resource_new(SyncDirectory *dir, SyncDatabase *db, char *path) { char *file_path = create_local_path(dir, path); @@ -3051,11 +3014,11 @@ SyncDirectory *dir, SyncDatabase *db, LocalResource *res, - UcxMap *svrres, + CxMap *svrres, DavBool restore_removed, DavBool restore_modified) { - LocalResource *db_res = ucx_map_cstr_get(db->resources, res->path); + LocalResource *db_res = cxMapGet(db->resources, cx_hash_key_str(res->path)); res->tags_updated = 0; if(db_res) { // copy some metadata from db_res, that localscan does not deliver @@ -3088,7 +3051,7 @@ // check if the file must be restored on the server if(svrres) { - DavResource *remote = ucx_map_cstr_get(svrres, res->path); + DavResource *remote = cxMapGet(svrres, cx_hash_key_str(res->path)); if(restore_removed && !remote) { return 1; } @@ -3110,7 +3073,7 @@ res->tags_updated = 1; res->metadata_updated = 1; } else if(dir->tagconfig && dir->tagconfig->detect_changes ) { - UcxBuffer *tags = sync_get_file_tag_data(dir, res); + CxBuffer *tags = sync_get_file_tag_data(dir, res); if(tags) { if(db_res->tags_hash) { char *hash = dav_create_hash(tags->space, tags->size); @@ -3268,9 +3231,9 @@ // the resource is on the server and the client has no etag ret = 1; } else if(etag) { - sstr_t e = sstr(etag); - if(sstrprefix(e, S("W/"))) { - e = sstrsubs(e, 2); + cxstring e = cx_str(etag); + if(cx_strprefix(e, CX_STR("W/"))) { + e = cx_strsubs(e, 2); } if(strcmp(e.ptr, res->etag)) { ret = 1; @@ -3306,11 +3269,11 @@ return; } - scstr_t e = scstr(etag); - if(sstrprefix(e, S("W/"))) { - e = scstrsubs(e, 2); - } - local->etag = sstrdup(e).ptr; + cxstring e = cx_str(etag); + if(cx_strprefix(e, CX_STR("W/"))) { + e = cx_strsubs(e, 2); + } + local->etag = cx_strdup(e).ptr; } char* resource_local_path(DavResource *res) { @@ -3334,9 +3297,9 @@ return 0; } else if(local->blocksize > 0) { local_blocksize = (size_t)local->blocksize; - } else { - UCX_FOREACH(elm, dir->splitconfig) { - SplitConfig *sc = elm->data; + } else if(dir->splitconfig) { + CxIterator i = cxListIterator(dir->splitconfig); + cx_foreach(SplitConfig *, sc, i) { if(sc->filter) { if(res_matches_filter(sc->filter, local->path)) { continue; @@ -3462,38 +3425,6 @@ return ret; } -int sync_tags_equal(UcxList *tags1, UcxList *tags2) { - if(!tags1) { - return tags2 ? 0 : 1; - } - if(!tags2) { - return tags1 ? 0 : 1; - } - - UcxMap *map1 = ucx_map_new(32); - UCX_FOREACH(elm, tags1) { - DavTag *t = elm->data; - ucx_map_cstr_put(map1, t->name, t); - } - - int equal = 1; - int i = 0; - UCX_FOREACH(elm, tags2) { - DavTag *t = elm->data; - if(!ucx_map_cstr_get(map1, t->name)) { - equal = 0; - break; - } - i++; - } - - if(i != map1->count) { - equal = 0; - } - ucx_map_free(map1); - return equal; -} - int sync_store_metadata(SyncDirectory *dir, const char *path, LocalResource *local, DavResource *res) { int ret = 0; @@ -3545,12 +3476,12 @@ // create a map of all currently available local attributes ssize_t nelm = 0; char **list = xattr_list(path, &nelm); - UcxMap *current_xattr = NULL; + CxMap *current_xattr = NULL; if(nelm > 0) { - current_xattr = ucx_map_new(nelm + 8); + current_xattr = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, nelm + 8); for(int i=0;i<nelm;i++) { // use the xattr name as key and store any value - ucx_map_cstr_put(current_xattr, list[i], list[i]); + cxMapPut(current_xattr, cx_hash_key_str(list[i]), list[i]); } } if(list) { @@ -3560,7 +3491,7 @@ // store extended attributes size_t nattr = xattr ? xattr->nattr : 0; for(int i=0;i<nattr;i++) { - sstr_t value = xattr->values[i]; + cxmutstr value = xattr->values[i]; if(xattr_set(path, xattr->names[i], value.ptr, value.length)) { fprintf(stderr, "Cannot store xattr '%s' for file: %s\n", @@ -3572,7 +3503,7 @@ // to detect which xattributes are removed, we remove all new // attributes from the map and all remaining attributes must // be removed with xattr_remove - char *value = ucx_map_cstr_remove(current_xattr, xattr->names[i]); + char *value = cxMapRemoveAndGet(current_xattr, cx_hash_key_str(xattr->names[i])); if(value) { free(value); } @@ -3580,13 +3511,13 @@ } if(current_xattr) { - UcxMapIterator i = ucx_map_iterator(current_xattr); + CxIterator i = cxMapIteratorValues(current_xattr); char *value = NULL; - UCX_MAP_FOREACH(key, value, i) { + cx_foreach(char *, value, i) { (void)xattr_remove(path, value); // don't print error free(value); } - ucx_map_free(current_xattr); + cxMapDestroy(current_xattr); } return 0; @@ -3598,7 +3529,7 @@ } char *remote_hash = NULL; - UcxList *tags = NULL; + CxList *tags = NULL; if(dir->tagconfig) { DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_PROPS_NS, "tags"); if(tagsprop) { @@ -3609,7 +3540,7 @@ DavBool store_tags = FALSE; DavBool tags_changed = FALSE; - UcxList *local_tags = sync_get_file_tags(dir, local, &tags_changed, NULL); + CxList *local_tags = sync_get_file_tags(dir, local, &tags_changed, NULL); if(tags_changed) { switch(dir->tagconfig->conflict) { case TAG_NO_CONFLICT: { @@ -3626,7 +3557,7 @@ break; } case TAG_MERGE: { - UcxList *new_tags = merge_tags(local_tags, tags); + CxList *new_tags = merge_tags(local_tags, tags); // TODO: free tags and local_tags tags = new_tags; store_tags = TRUE; @@ -3636,7 +3567,7 @@ } } } else { - if(!sync_tags_equal(tags, local_tags)) { + if(!compare_taglists(tags, local_tags)) { store_tags = TRUE; } // TODO: free local_tags @@ -3661,10 +3592,10 @@ return ret; } -int sync_store_tags_local(SyncDirectory *dir, LocalResource *local, const char *path, UcxList *tags) { +int sync_store_tags_local(SyncDirectory *dir, LocalResource *local, const char *path, CxList *tags) { int ret = 0; if(dir->tagconfig->store == TAG_STORE_XATTR) { - UcxBuffer *data = NULL; + CxBuffer *data = NULL; if(tags) { switch(dir->tagconfig->local_format) { default: break; @@ -3704,7 +3635,7 @@ } else { free(data_hash); } - ucx_buffer_free(data); + cxBufferFree(data); } else { ret = -1; } @@ -3724,14 +3655,14 @@ return ret; } -UcxBuffer* sync_get_file_tag_data(SyncDirectory *dir, LocalResource *res) { +CxBuffer* sync_get_file_tag_data(SyncDirectory *dir, LocalResource *res) { if(!dir->tagconfig) { return NULL; } if(res->cached_tags) { return res->cached_tags; } - UcxBuffer *buf = NULL; + CxBuffer *buf = NULL; if(dir->tagconfig->store == TAG_STORE_XATTR) { ssize_t tag_length = 0; char *local_path = create_local_path(dir, local_resource_path(res)); @@ -3742,7 +3673,7 @@ free(local_path); if(tag_length > 0) { - buf = ucx_buffer_new(tag_data, (size_t)tag_length, UCX_BUFFER_AUTOFREE); + buf = cxBufferCreate(tag_data, (size_t)tag_length, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS); buf->size = (size_t)tag_length; } } @@ -3750,10 +3681,10 @@ return buf; } -UcxList* sync_get_file_tags(SyncDirectory *dir, LocalResource *res, DavBool *changed, char **newhash) { +CxList* sync_get_file_tags(SyncDirectory *dir, LocalResource *res, DavBool *changed, char **newhash) { if(changed) *changed = FALSE; - UcxList *tags = NULL; + CxList *tags = NULL; if(!res) { return NULL; @@ -3766,7 +3697,7 @@ *changed = TRUE; } if(dir->tagconfig->store == TAG_STORE_XATTR) { - UcxBuffer *tag_buf = res->cached_tags ? + CxBuffer *tag_buf = res->cached_tags ? res->cached_tags : sync_get_file_tag_data(dir, res); @@ -4011,7 +3942,7 @@ // this macro is only a workaround for a netbeans bug #define LOG10 log10 -static UcxList* upload_parts( +static CxList* upload_parts( LocalResource *local, DavResource *res, FILE *in, @@ -4067,7 +3998,8 @@ return NULL; } - UcxMap *updated_parts_map = ucx_map_new((nblocks/2)+64); + CxMap *updated_parts_map = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, (nblocks/2)+64); + updated_parts_map->simple_destructor = (cx_destructor_func)filepart_free; int blockindex = 0; int uploaded_parts = 0; @@ -4121,7 +4053,7 @@ FilePart *f = calloc(1, sizeof(FilePart)); f->block = blockindex; f->hash = block_hash; - ucx_map_cstr_put(updated_parts_map, name, f); + cxMapPut(updated_parts_map, cx_hash_key_str(name), f); } dav_resource_free(part); uploaded_parts++; @@ -4138,8 +4070,7 @@ free(buffer); if(*err) { - ucx_map_free_content(updated_parts_map, (ucx_destructor)filepart_free); - ucx_map_free(updated_parts_map); + cxMapDestroy(updated_parts_map); return NULL; } @@ -4151,18 +4082,17 @@ // get etags from uploaded resources // also delete everything, that is not part of the file - UcxList *updated_parts = NULL; + CxList *updated_parts = cxLinkedListCreateSimple(CX_STORE_POINTERS); DavResource *parts = dav_query(res->session, "select D:getetag from %s order by name", res->path); if(!parts) { print_resource_error(res->session, parts->path); *err = 1; - ucx_map_free_content(updated_parts_map, (ucx_destructor)filepart_free); - ucx_map_free(updated_parts_map); + cxMapDestroy(updated_parts_map); return NULL; } DavResource *part = parts->children; while(part) { - FilePart *fp = ucx_map_cstr_remove(updated_parts_map, part->name); + FilePart *fp = cxMapRemoveAndGet(updated_parts_map, cx_hash_key_str(part->name)); // every part we uploaded is in the map // if we get parts that are not in the map, someone else uploaded it if(fp) { @@ -4173,7 +4103,7 @@ } fp->etag = strdup(etag); - updated_parts = ucx_list_append(updated_parts, fp); + cxListAdd(updated_parts, fp); } // else { wtf is wrong with this resource } } else { uint64_t name_partnum = 0; @@ -4200,14 +4130,13 @@ } dav_resource_free_all(parts); - ucx_map_free_content(updated_parts_map, (ucx_destructor)filepart_free); - ucx_map_free(updated_parts_map); + cxMapDestroy(updated_parts_map); *err = 0; return updated_parts; } -void update_parts(LocalResource *local, UcxList *updates, uint64_t numparts) { +void update_parts(LocalResource *local, CxList *updates, uint64_t numparts) { size_t old_num = local->numparts; if(old_num > numparts) { // free old parts @@ -4226,8 +4155,12 @@ local->numparts = numparts; } - UCX_FOREACH(elm, updates) { - FilePart *p = elm->data; + if(!updates) { + return; + } + + CxIterator i = cxListIterator(updates); + cx_foreach(FilePart *, p, i) { if(p->block > numparts) { // just make sure things don't explode in case some weird stuff // is going on @@ -4285,7 +4218,7 @@ DavBool issplit = split_blocksize == 0 ? FALSE : TRUE; int split_err = 0; - UcxList *parts = NULL; + CxList *parts = NULL; uint64_t blockcount = 0; if(islink) { @@ -4455,7 +4388,7 @@ LocalResource *local_origin = local->origin; if(!copy) { - ucx_map_cstr_remove(db->resources, local_origin->path); + cxMapRemove(db->resources, cx_hash_key_str(local_origin->path)); } // set resource metadata @@ -4496,7 +4429,7 @@ DavSession *sn, LocalResource *local_res, int *counter, - UcxList **cols) + CxList *cols) { DavResource *res = dav_get(sn, local_res->path, "D:getetag,idav:split"); if(!res) { @@ -4508,7 +4441,7 @@ if(res->iscollection) { DavXmlNode *split = dav_get_property_ns(res, DAV_NS, "split"); if(cols) { - *cols = ucx_list_append(*cols, local_res); + cxListAdd(cols, local_res); } else if(split || !res->children) { printf("delete: %s\n", res->path); if(dav_delete(res)) { @@ -4582,7 +4515,7 @@ // get local tags DavBool changed = 0; char *tags_hash = NULL; - UcxList *tags = sync_get_file_tags(dir, local, &changed, &tags_hash); + CxList *tags = sync_get_file_tags(dir, local, &changed, &tags_hash); char *new_remote_hash = nullstrdup(tags_hash); if(changed || local->tags_updated) { DavBool store_tags = TRUE; @@ -4594,7 +4527,7 @@ if(dav_load_prop(res, &p, 1) && sn->error != DAV_NOT_FOUND) { print_resource_error(sn, res->path); } - UcxList *remote_tags = NULL; + CxList *remote_tags = NULL; DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_PROPS_NS, "tags"); if(tagsprop) { remote_tags = parse_dav_xml_taglist(tagsprop); @@ -4613,7 +4546,7 @@ break; } case TAG_MERGE: { - UcxList *new_tags = merge_tags(tags, remote_tags); + CxList *new_tags = merge_tags(tags, remote_tags); free_taglist(tags); tags = new_tags; @@ -4706,12 +4639,11 @@ } void remove_deleted_conflicts(SyncDirectory *dir, SyncDatabase *db) { - char **dc = calloc(sizeof(void*), db->conflict->count); + char **dc = calloc(sizeof(void*), db->conflict->size); int numdc = 0; - UcxMapIterator i = ucx_map_iterator(db->conflict); - LocalResource *res; - UCX_MAP_FOREACH(key, res, i) { + CxIterator i = cxMapIteratorValues(db->conflict); + cx_foreach(LocalResource *, res, i) { char *path = create_local_path(dir, res->path); SYS_STAT s; if(sys_stat(path, &s)) { @@ -4727,18 +4659,16 @@ } for(int i=0;i<numdc;i++) { - ucx_map_cstr_remove(db->conflict, dc[i]); + cxMapRemove(db->conflict, cx_hash_key_str(dc[i])); } free(dc); } static void resolve_skipped(SyncDatabase *db) { - UcxKey k; - LocalResource *res; - UcxMapIterator i = ucx_map_iterator(db->resources); + CxIterator i = cxMapIteratorValues(db->resources); int skipped = 0; - UCX_MAP_FOREACH(k, res, i) { + cx_foreach(LocalResource *, res, i) { if(res->skipped) { skipped++; fprintf(stderr, "skipped from push: %s\n", res->path); @@ -4777,9 +4707,9 @@ int ret = 0; // remove conflicts - int num_conflict = db->conflict->count; - ucx_map_free_content(db->conflict, (ucx_destructor)local_resource_free); - ucx_map_clear(db->conflict); + int num_conflict = db->conflict->size; + //ucx_map_free_content(db->conflict, (ucx_destructor)local_resource_free); + cxMapClear(db->conflict); // store db if(store_db(db, dir->database, dir->db_settings)) { @@ -4829,9 +4759,8 @@ int ret = 0; // delete all conflict files - UcxMapIterator i = ucx_map_iterator(db->conflict); - LocalResource *res; - UCX_MAP_FOREACH(key, res, i) { + CxIterator i = cxMapIterator(db->conflict); + cx_foreach(LocalResource*, res, i) { printf("delete: %s\n", res->path); char *path = create_local_path(dir, res->path); if(sys_unlink(path)) { @@ -4844,8 +4773,8 @@ } free(path); } - ucx_map_free_content(db->conflict, (ucx_destructor)local_resource_free); - ucx_map_clear(db->conflict); + //ucx_map_free_content(db->conflict, (ucx_destructor)local_resource_free); + cxMapClear(db->conflict); // store db if(store_db(db, dir->database, dir->db_settings)) { @@ -4893,30 +4822,28 @@ remove_deleted_conflicts(dir, db); // get all conflict sources - UcxMapIterator i = ucx_map_iterator(db->conflict); - LocalResource *res; - UcxList* conflict_sources = NULL; - UCX_MAP_FOREACH(key, res, i) { - conflict_sources = ucx_list_append(conflict_sources, res->conflict_source); + CxIterator i = cxMapIteratorValues(db->conflict); + CxList* conflict_sources = cxLinkedListCreateSimple(CX_STORE_POINTERS); + cx_foreach(LocalResource *, res, i) { + cxListAdd(conflict_sources, res->conflict_source); } // print unique conflict sources - conflict_sources = ucx_list_sort(conflict_sources, ucx_cmp_str, NULL); - UCX_FOREACH(elem, conflict_sources) { - char* path = elem->data; - if(cmd_getoption(a, "verbose")) { - int confl_count = 1; - while(elem->next && !strcmp(elem->next->data, path)) { - elem = elem->next; - ++confl_count; - } - printf("%s (%d)\n", path, confl_count); - } else { - printf("%s\n", path); - while(elem->next && !strcmp(elem->next->data, path)) { - elem = elem->next; - } - } + // TODO: set cmpfunc at map creation + conflict_sources->cmpfunc = (cx_compare_func)strcmp; + cxListSort(conflict_sources); + i = cxListIterator(conflict_sources); + char *prev = ""; + cx_foreach(char *, path, i) { + // TODO: implement verbose print if(cmd_getoption(a, "verbose")) + // printf("%s (%d)\n", path, confl_count); + if(!strcmp(path, prev)) { + continue; + } + + printf("%s\n", path); + + prev = path; } // cleanup @@ -5029,7 +4956,7 @@ fprintf(stderr, "No versioning configured for syncdir %s\n", dir->name); } - Repository *repo = get_repository(sstr(dir->repository)); + Repository *repo = get_repository(cx_str(dir->repository)); if(!repo) { fprintf(stderr, "Unknown repository %s\n", dir->repository); return -1; @@ -5043,7 +4970,7 @@ remove_deleted_conflicts(dir, db); DavSession *sn = create_session(a, ctx, repo, dir->collection); - ucx_mempool_reg_destr(sn->mp, db, (ucx_destructor)destroy_db); + util_regdestr(sn->mp, db, (cx_destructor_func)destroy_db); if (cmd_getoption(a, "verbose")) { curl_easy_setopt(sn->handle, CURLOPT_VERBOSE, 1L); curl_easy_setopt(sn->handle, CURLOPT_STDERR, stderr); @@ -5079,23 +5006,23 @@ } DavResource *child = vcol->children; - UcxList *children = NULL; + CxList *children = cxLinkedListCreate(cxDefaultAllocator, (cx_compare_func)strcmp, CX_STORE_POINTERS); while(child) { - children = ucx_list_append(children, child); + cxListAdd(children, child); child = child->next; } - children = ucx_list_sort(children, ucx_cmp_str, NULL); + cxListSort(children); DavBool first = 1; - UCX_FOREACH(elm, children) { - DavResource *c = elm->data; + CxIterator i = cxListIterator(children); + cx_foreach(DavResource *, c, i) { if(!first) { putchar('\n'); } print_resource_version(c, c->name); first = 0; } - ucx_list_free(children); + cxListDestroy(children); } while(0); } else if(dir->versioning->type == VERSIONING_DELTAV) { DavResource *versions = dav_versiontree(res, NULL); @@ -5271,6 +5198,10 @@ } int cmd_tagop(CmdArgs *args, int cmd) { + // TODO: port to ucx 3 + return 1; +#if 0 + SyncFile file; int ret = 0; char *path = args->argv[0]; @@ -5293,13 +5224,13 @@ } LocalResource *newres = NULL; - LocalResource *localres = ucx_map_cstr_get(db->resources, file.path); + LocalResource *localres = cxMapGet(db->resources, cx_hash_key_str(file.path)); if(!localres) { newres = calloc(1, sizeof(LocalResource)); newres->path = strdup(file.path); localres = newres; } - UcxList *tags = NULL; + CxList *tags = NULL; DavBool store_tags = FALSE; if(cmd != CMD_TAG_SET) { @@ -5307,7 +5238,7 @@ char *tagcolor = NULL; // TODO: get color tags = sync_get_file_tags(file.dir, localres, NULL, NULL); - UcxList *x = NULL; + CxList *x = NULL; UCX_FOREACH(elm, tags) { DavTag *t = elm->data; if(cmd == CMD_TAG_LIST) { @@ -5374,6 +5305,7 @@ free(file.path); return ret; +#endif } int isfileindir(SyncDirectory *dir, const char *path, SyncFile *f) { @@ -5406,16 +5338,16 @@ // TODO: normalize path DavBool not_in_dir = 0; - scstr_t fp = scstr(fullpath); - scstr_t dp = scstr(dir->path); + cxstring fp = cx_str(fullpath); + cxstring dp = cx_str(dir->path); if(fp.length == dp.length) { - if(sstrcmp(fp, dp)) { + if(cx_strcmp(fp, dp)) { not_in_dir = 1; } } else if(fp.length < dp.length) { not_in_dir = 1; } else { - if(!sstrprefix(fp, dp)) { + if(!cx_strprefix(fp, dp)) { not_in_dir = 1; } else { if(dp.ptr[dp.length-1] == '/') { @@ -5466,10 +5398,8 @@ } else { SyncDirectory *target = NULL; - UcxMapIterator i = scfg_directory_iterator(); - UcxKey k; - SyncDirectory *dir; - UCX_MAP_FOREACH(key, dir, i) { + CxIterator i = scfg_directory_iterator(); + cx_foreach(SyncDirectory *, dir, i) { if(isfileindir(dir, path, f)) { if(target) { return 5; @@ -5500,11 +5430,17 @@ int cmd_add_directory(CmdArgs *args) { + /* if(!get_repositories()) { fprintf(stderr, "No repositories available. Run 'dav add-repository' first.\n"); fprintf(stderr, "Abort\n"); return -1; } + */ + + // TODO: port to ucx 3 + return 1; +#if 0 printf("Each sync directory must have an unique name.\n"); char *name = assistant_getcfg("name"); @@ -5525,10 +5461,9 @@ } printf("Specify webdav repository.\n"); - UcxList *repos = get_repositories(); + CxIterator repos = get_repositories(); int i = 0; - UCX_FOREACH(elm, repos) { - Repository *r = elm->data; + cx_foreach(Repository *, r, repos) { printf("%d) %s\n", i, r->name); i++; } @@ -5590,12 +5525,12 @@ free(db); return ret; +#endif } int cmd_list_dirs() { - UcxMapIterator iter = scfg_directory_iterator(); - SyncDirectory *dir; - UCX_MAP_FOREACH(key, dir, iter) { + CxIterator iter = scfg_directory_iterator(); + cx_foreach(SyncDirectory *, dir, iter) { printf("%s\n", dir->name); } return 0; @@ -5604,19 +5539,18 @@ int cmd_check_repositories(CmdArgs *a) { int ret = EXIT_SUCCESS; - UcxList *reponames = NULL; + CxList *reponames = cxLinkedListCreateSimple(CX_STORE_POINTERS); { - UcxMapIterator iter = scfg_directory_iterator(); - SyncDirectory *dir; - UCX_MAP_FOREACH(key, dir, iter) { - reponames = ucx_list_append(reponames, dir->repository); - } - } - - UCX_FOREACH(listelem, reponames) { - char *reponame = listelem->data; + CxIterator iter = scfg_directory_iterator(); + cx_foreach(SyncDirectory *, dir, iter) { + cxListAdd(reponames, dir->repository); + } + } + + CxIterator iter = cxListIterator(reponames); + cx_foreach(char *, reponame, iter) { printf("Checking %s... ", reponame); - Repository* repo = get_repository(sstr(reponame)); + Repository* repo = get_repository(cx_str(reponame)); if (!repo) { printf(" not found in config.xml!\n"); ret = EXIT_FAILURE; @@ -5640,13 +5574,13 @@ } } - ucx_list_free(reponames); + cxListDestroy(reponames); return ret; } char* create_locktoken_file(const char *syncdirname, const char *locktoken) { - sstr_t fname = ucx_sprintf("locktoken-%s.txt", syncdirname); + cxmutstr fname = cx_asprintf("locktoken-%s.txt", syncdirname); char *path = config_file_path(fname.ptr); free(fname.ptr);