diff -r 99a34860c105 -r d938228c382e src/server/webdav/webdav.c --- a/src/server/webdav/webdav.c Wed Nov 02 19:19:01 2022 +0100 +++ b/src/server/webdav/webdav.c Sun Nov 06 15:53:32 2022 +0100 @@ -30,8 +30,11 @@ #include #include -#include -#include +#include +#include +#include +#include +#include #include "webdav.h" @@ -53,14 +56,14 @@ * key: http method name (string) * value: SAF fptr */ -static UcxMap *method_handler_map; +static CxMap *method_handler_map; /* * webdav backend types * key: backend name (string) * value: WebdavBackend* */ -static UcxMap *webdav_type_map; +static CxMap *webdav_type_map; static WebdavBackend default_backend; @@ -89,11 +92,11 @@ WebdavType *webdavType = malloc(sizeof(WebdavType)); webdavType->init = webdavInit; webdavType->create = webdavCreate; - return ucx_map_cstr_put(webdav_type_map, name, webdavType); + return cxMapPut(webdav_type_map, cx_hash_key_str(name), webdavType); } -WebdavType* webdav_get_type(scstr_t dav_class) { - return ucx_map_sstr_get(webdav_type_map, dav_class); +WebdavType* webdav_get_type(cxstring dav_class) { + return cxMapGet(webdav_type_map, cx_hash_key_bytes((unsigned const char *)dav_class.ptr, dav_class.length)); } void* webdav_init_backend(ServerConfiguration *cfg, pool_handle_t *pool, WebdavType *dav_class, WSConfigNode *config, int *error) { @@ -110,7 +113,7 @@ } WebdavBackend* webdav_create(Session *sn, Request *rq, const char *dav_class, pblock *pb, void *initData) { - WebdavType *webdavType = ucx_map_cstr_get(webdav_type_map, dav_class); + WebdavType *webdavType = cxMapGet(webdav_type_map, cx_hash_key_str(dav_class)); if(!webdavType) { log_ereport(LOG_MISCONFIG, "webdav_create: unkown dav type %s", dav_class); return NULL; @@ -127,43 +130,43 @@ } webdav_is_initialized = TRUE; - webdav_type_map = ucx_map_new(8); + webdav_type_map = cxHashMapCreate(cxDefaultAllocator, 8); if(!webdav_type_map) { return REQ_ABORTED; } - method_handler_map = ucx_map_new(64); + method_handler_map = cxHashMapCreate(cxDefaultAllocator, 64); if(!method_handler_map) { return REQ_ABORTED; } init_default_backend(); - ucx_map_cstr_put(webdav_type_map, "default", &default_backend); + cxMapPut(webdav_type_map, cx_hash_key_str("default"), &default_backend); - ucx_map_cstr_put(method_handler_map, "OPTIONS", webdav_options); - ucx_map_cstr_put(method_handler_map, "PROPFIND", webdav_propfind); - ucx_map_cstr_put(method_handler_map, "PROPPATCH", webdav_proppatch); - ucx_map_cstr_put(method_handler_map, "MKCOL", webdav_mkcol); - ucx_map_cstr_put(method_handler_map, "POST", webdav_post); - ucx_map_cstr_put(method_handler_map, "DELETE", webdav_delete); - ucx_map_cstr_put(method_handler_map, "PUT", webdav_put); - ucx_map_cstr_put(method_handler_map, "COPY", webdav_copy); - ucx_map_cstr_put(method_handler_map, "MOVE", webdav_move); - ucx_map_cstr_put(method_handler_map, "LOCK", webdav_lock); - ucx_map_cstr_put(method_handler_map, "UNLOCK", webdav_unlock); - ucx_map_cstr_put(method_handler_map, "REPORT", webdav_report); - ucx_map_cstr_put(method_handler_map, "ACL", webdav_acl); + cxMapPut(method_handler_map, cx_hash_key_str("OPTIONS"), webdav_options); + cxMapPut(method_handler_map, cx_hash_key_str("PROPFIND"), webdav_propfind); + cxMapPut(method_handler_map, cx_hash_key_str("PROPPATCH"), webdav_proppatch); + cxMapPut(method_handler_map, cx_hash_key_str("MKCOL"), webdav_mkcol); + cxMapPut(method_handler_map, cx_hash_key_str("POST"), webdav_post); + cxMapPut(method_handler_map, cx_hash_key_str("DELETE"), webdav_delete); + cxMapPut(method_handler_map, cx_hash_key_str("PUT"), webdav_put); + cxMapPut(method_handler_map, cx_hash_key_str("COPY"), webdav_copy); + cxMapPut(method_handler_map, cx_hash_key_str("MOVE"), webdav_move); + cxMapPut(method_handler_map, cx_hash_key_str("LOCK"), webdav_lock); + cxMapPut(method_handler_map, cx_hash_key_str("UNLOCK"), webdav_unlock); + cxMapPut(method_handler_map, cx_hash_key_str("REPORT"), webdav_report); + cxMapPut(method_handler_map, cx_hash_key_str("ACL"), webdav_acl); - ucx_map_cstr_put(method_handler_map, "SEARCH", webdav_search); + cxMapPut(method_handler_map, cx_hash_key_str("SEARCH"), webdav_search); - ucx_map_cstr_put(method_handler_map, "VERSION-CONTROL", webdav_version_control); - ucx_map_cstr_put(method_handler_map, "CHECKOUT", webdav_checkout); - ucx_map_cstr_put(method_handler_map, "CHECKIN", webdav_checkin); - ucx_map_cstr_put(method_handler_map, "UNCHECKOUT", webdav_uncheckout); - ucx_map_cstr_put(method_handler_map, "MKWORKSPACE", webdav_mkworkspace); - ucx_map_cstr_put(method_handler_map, "UPDATE", webdav_update); - ucx_map_cstr_put(method_handler_map, "LABEL", webdav_label); - ucx_map_cstr_put(method_handler_map, "MERGE", webdav_merge); + cxMapPut(method_handler_map, cx_hash_key_str("VERSION-CONTROL"), webdav_version_control); + cxMapPut(method_handler_map, cx_hash_key_str("CHECKOUT"), webdav_checkout); + cxMapPut(method_handler_map, cx_hash_key_str("CHECKIN"), webdav_checkin); + cxMapPut(method_handler_map, cx_hash_key_str("UNCHECKOUT"), webdav_uncheckout); + cxMapPut(method_handler_map, cx_hash_key_str("MKWORKSPACE"), webdav_mkworkspace); + cxMapPut(method_handler_map, cx_hash_key_str("UPDATE"), webdav_update); + cxMapPut(method_handler_map, cx_hash_key_str("LABEL"), webdav_label); + cxMapPut(method_handler_map, cx_hash_key_str("MERGE"), webdav_merge); dav_namespace.href = (xmlChar*)"DAV:"; dav_namespace.prefix = (xmlChar*)"D"; @@ -191,7 +194,7 @@ } char *method = pblock_findkeyval(pb_key_method, rq->reqpb); - FuncPtr saf = (FuncPtr)ucx_map_cstr_get(method_handler_map, method); + FuncPtr saf = (FuncPtr)cxMapGet(method_handler_map, cx_hash_key_str(method)); if(!saf) { return REQ_NOACTION; } @@ -199,33 +202,30 @@ return saf(pb, sn, rq); } -UcxBuffer* rqbody2buffer(Session *sn, Request *rq) { +int rqbody2buffer(Session *sn, Request *rq, CxBuffer *buf) { if(!sn->inbuf) { //request body required, set http response code protocol_status(sn, rq, 400, NULL); - return NULL; + return 1; } - UcxBuffer *buf = ucx_buffer_new( - NULL, - sn->inbuf->maxsize, - UCX_BUFFER_AUTOEXTEND); - if(!buf) { + CxAllocator *a = pool_allocator(sn->pool); + if(cxBufferInit(buf, NULL, sn->inbuf->maxsize, a, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS)) { protocol_status(sn, rq, 500, NULL); - return NULL; + return 1; } char in[2048]; int r; while((r = netbuf_getbytes(sn->inbuf, in, 2048)) > 0) { - if(ucx_buffer_write(in, 1, r, buf) != r) { + if(cxBufferWrite(in, 1, r, buf) != r) { protocol_status(sn, rq, 500, NULL); - ucx_buffer_free(buf); - return NULL; + cxBufferDestroy(buf); + return 1; } } - return buf; + return 0; } int webdav_options(pblock *pb, Session *sn, Request *rq) { @@ -254,8 +254,8 @@ } } - UcxBuffer *reqbody = rqbody2buffer(sn, rq); - if(!reqbody) { + CxBuffer reqbody; + if(rqbody2buffer(sn, rq, &reqbody)) { return REQ_ABORTED; } @@ -263,10 +263,10 @@ WebdavPropfindRequest *propfind = propfind_parse( sn, rq, - reqbody->space, - reqbody->size, + reqbody.space, + reqbody.size, &error); - ucx_buffer_free(reqbody); + cxBufferDestroy(&reqbody); if(!propfind) { log_ereport(LOG_FAILURE, "webdav-propfind: %s", propfind_error2str(error)); return REQ_ABORTED; @@ -318,13 +318,14 @@ WebdavPropfindRequest *propfind, const char *path, const char *uri, - UcxList **out_req) + WebdavPropfindRequestList **out_req) { pool_handle_t *pool = propfind->sn->pool; - UcxAllocator *a = session_get_allocator(propfind->sn); + CxAllocator *a = pool_allocator(pool); // list of individual WebdavPropfindRequest objects for each Backend - UcxList *requestObjects = NULL; + WebdavPropfindRequestList *requestObjectsBegin = NULL; + WebdavPropfindRequestList *requestObjectsEnd = NULL; // new properties after init, start with clone of original plist WebdavPList *newProp = webdav_plist_clone(pool, propfind->properties); @@ -347,10 +348,18 @@ pReq->dav = davList; // add new WebdavPropfindRequest object to list for later use - requestObjects = ucx_list_append_a(a, requestObjects, pReq); - if(!requestObjects) { + WebdavPropfindRequestList *reqListElm = pool_malloc(pool, sizeof(WebdavPropfindRequestList)); + if(!reqListElm) { return REQ_ABORTED; // OOM } + reqListElm->propfind = pReq; + reqListElm->next = NULL; + cx_linked_list_add( + (void**)&requestObjectsBegin, + (void**)&requestObjectsEnd, + -1, + offsetof(WebdavPropfindRequestList, next), + reqListElm); // create plist copy as out-plist for init newProp = webdav_plist_clone(pool, newProp); @@ -366,7 +375,7 @@ davList = davList->next; } - *out_req = requestObjects; + *out_req = requestObjectsBegin; return REQ_PROCEED; } @@ -385,7 +394,7 @@ uint32_t settings = dav->settings; // list of individual WebdavPropfindRequest objects for each Backend - UcxList *requestObjects = NULL; + WebdavPropfindRequestList *requestObjects = NULL; // Initialize all Webdav Backends if(webdav_propfind_init(dav, propfind, path, uri, &requestObjects)) { @@ -480,8 +489,8 @@ } } - UcxBuffer *reqbody = rqbody2buffer(sn, rq); - if(!reqbody) { + CxBuffer reqbody; + if(rqbody2buffer(sn, rq, &reqbody)) { // most likely OOM return REQ_ABORTED; } @@ -490,10 +499,10 @@ WebdavProppatchRequest *proppatch = proppatch_parse( sn, rq, - reqbody->space, - reqbody->size, + reqbody.space, + reqbody.size, &error); - ucx_buffer_free(reqbody); + cxBufferDestroy(&reqbody); if(!proppatch) { log_ereport(LOG_FAILURE, "webdav-proppatch: %s", proppatch_error2str(error)); return REQ_ABORTED; @@ -587,14 +596,16 @@ typedef struct DeleteFile { char *path; struct stat s; + struct DeleteFile *prev; + struct DeleteFile *next; } DeleteFile; typedef struct DeleteLists { - UcxAllocator *a; - UcxList *dirs_begin; - UcxList *dirs_end; - UcxList *files_begin; - UcxList *files_end; + CxAllocator *a; + DeleteFile *dirs_begin; + DeleteFile *dirs_end; + DeleteFile *files_begin; + DeleteFile *files_end; } DeleteOp; static int deletelist_add( @@ -608,19 +619,20 @@ DeleteOp *op = userdata; // create object for this file - DeleteFile *file = almalloc(op->a, sizeof(DeleteFile)); + DeleteFile *file = cxMalloc(op->a, sizeof(DeleteFile)); if(!file) { return 1; } - file->path = sstrdup_a(op->a, sstr((char*)path)).ptr; + file->path = cx_strdup_a(op->a, cx_str((char*)path)).ptr; if(!file->path) { return 1; } file->s = *s; + file->next = NULL; // determine which list to use - UcxList **begin; - UcxList **end; + DeleteFile **begin; + DeleteFile **end; if(S_ISDIR(s->st_mode)) { begin = &op->dirs_begin; end = &op->dirs_end; @@ -630,19 +642,10 @@ } // add file to list - UcxList *elm = ucx_list_append_a(op->a, NULL, file); - if(!elm) { - alfree(op->a, file->path); // at least do some cleanup, although it - alfree(op->a, file); // isn't really necessary - return 1; - } - if(*begin == NULL) { - *begin = elm; - *end = elm; - } else { - ucx_list_concat(*end, elm); - *end = elm; - } + cx_linked_list_add( + (void**)begin, (void**)end, + offsetof(DeleteFile, prev), offsetof(DeleteFile, next), + file); return 0; } @@ -651,7 +654,7 @@ { DeleteOp del; ZERO(&del, sizeof(DeleteOp)); - del.a = session_get_allocator(op->sn); + del.a = pool_allocator(op->sn->pool); // get a list of all files if(webdav_op_iterate_children(op->vfs, -1, NULL, op->path, @@ -664,22 +667,18 @@ DeleteFile root; root.path = op->path; root.s = *op->stat; - UcxList root_elm; - root_elm.data = &root; - root_elm.prev = NULL; - root_elm.next = del.dirs_begin; + root.prev = NULL; + root.next = del.dirs_begin; if(del.dirs_begin) { - del.dirs_begin->prev = &root_elm; - del.dirs_begin = &root_elm; + del.dirs_begin->prev = &root; } else { - del.dirs_begin = &root_elm; - del.dirs_end = &root_elm; + del.dirs_end = &root; } + del.dirs_begin = &root; // delete files first - UCX_FOREACH(elm, del.files_begin) { - DeleteFile *file = elm->data; + for(DeleteFile *file=del.files_begin;file;file=file->next) { WebdavVFSOperation sub = webdav_vfs_sub_op(op, file->path, &file->s); if(webdav_vfs_op_do(&sub, WEBDAV_VFS_DELETE)) { return 1; @@ -687,8 +686,7 @@ } // delete directories, reverse order - for(UcxList *elm=del.dirs_end;elm;elm=elm->prev) { - DeleteFile *file = elm->data; + for(DeleteFile *file=del.dirs_end;file;file=file->prev) { WebdavVFSOperation sub = webdav_vfs_sub_op(op, file->path, &file->s); if(webdav_vfs_op_do(&sub, WEBDAV_VFS_DELETE)) { return 1; @@ -913,18 +911,16 @@ /* ------------------------------ Utils ------------------------------ */ -UcxKey webdav_property_key(const char *ns, const char *name) { - UcxKey key; - sstr_t data = ucx_sprintf("%s\n%s", name, ns); - key.data = data.ptr; +CxHashKey webdav_property_key(const char *ns, const char *name) { + CxHashKey key; + cxmutstr data = cx_asprintf("%s\n%s", name, ns); + key.data.str = data.ptr; key.len = data.length; - key.hash = ucx_hash(data.ptr, data.length); + cx_hash_murmur(&key); return key; } - - /* ------------------------------ public API ------------------------------ */ int webdav_getdepth(Request *rq) {