# HG changeset patch # User Olaf Wintermann # Date 1679220850 -3600 # Node ID b02da778362eef703bd162ba340417cc17a47dc9 # Parent 31affbf33911f7f004289c59f873276dfb3e41a8 implement propfind for webdav xattr backend diff -r 31affbf33911 -r b02da778362e src/server/webdav/xattrbackend.c --- a/src/server/webdav/xattrbackend.c Sat Mar 18 19:33:06 2023 +0100 +++ b/src/server/webdav/xattrbackend.c Sun Mar 19 11:14:10 2023 +0100 @@ -137,11 +137,13 @@ { Session *sn = request->sn; Request *rq = request->rq; + CxAllocator *a = pool_allocator(sn->pool); WebdavXAttrBackend *xdav = request->dav->instance; WebdavXAttrRepository *repo = xdav->repo; XAttrPropfind *xprop = request->userdata; + // get resource path const char *path; char *path_dp = NULL; if(!parent) { @@ -175,18 +177,83 @@ repo->xattr_name, &xattr_data_len); - if(xattr_data) { - + if(!xattr_data) { + // no properties for this resource + return 0; } + CxMap *pmap = webdav_xattr_parse_data(a, xattr_data, xattr_data_len, path); + pool_free(sn->pool, xattr_data); + if(!pmap) { + return 1; + } - return 0; + int err; + if(request->allprop || request->propname) { + err = webdav_xattr_propfind_allprop(request, resource, a, pmap); + } else { + err = webdav_xattr_propfind_get_requested_properties(request, resource, a, pmap); + } + + return err; } int webdav_xattr_propfind_finish(WebdavPropfindRequest *rq) { return 0; } +// helper functions for propfind_do + +int webdav_xattr_propfind_get_requested_properties( + WebdavPropfindRequest *request, + WebdavResource *resource, + CxAllocator *a, + CxMap *pmap) +{ + WebdavPListIterator i = webdav_plist_iterator(&request->properties); + WebdavPList *cur; + while(webdav_plist_iterator_next(&i, &cur)) { + WebdavProperty *reqprop = cur->property; + + CxHashKey key = webdav_property_key_a( + a, + (const char*)reqprop->namespace->href, + (const char*)reqprop->name); + if(!key.data.str) { + return 1; + } + + WebdavProperty *prop = cxMapGet(pmap, key); + if(prop) { + if(resource->addproperty(resource, prop, 200)) { + return 1; + } + } + } + + return 0; +} + +int webdav_xattr_propfind_allprop( + WebdavPropfindRequest *request, + WebdavResource *resource, + CxAllocator *a, + CxMap *pmap) +{ + CxIterator i = cxMapIteratorValues(pmap); + cx_foreach(WebdavProperty*, prop, i) { + if(request->propname) { + prop->vtype = WS_VALUE_NO_TYPE; + } + if(resource->addproperty(resource, prop, 200)) { + return 1; + } + } + return 0; +} + + + int webdav_xattr_proppatch_do( WebdavProppatchRequest *request, WebdavResource *response, @@ -200,6 +267,15 @@ WebdavXAttrBackend *xdav = request->dav->instance; WebdavXAttrRepository *repo = xdav->repo; + + char *path = pblock_findkeyval(pb_key_path, rq->vars); + + // How xattr proppatch works: + // 1. get existing property data from the file's xattr + // 2. do set/remove operations to the existing data + // 3. write new property data to the xattr (webdav_xattr_proppatch_finish) + + // TODO: proppatch file lock (in-process userspace lock) XAttrProppatch *xprop = pool_malloc(sn->pool, sizeof(XAttrProppatch)); if(!xprop) { @@ -207,8 +283,6 @@ } request->userdata = xprop; - char *path = pblock_findkeyval(pb_key_path, rq->vars); - // get existing property data ssize_t xattr_data_len = 0; char *xattr_data = xattr_get_alloc( @@ -222,6 +296,7 @@ CxMap *pmap; if(xattr_data) { pmap = webdav_xattr_parse_data(a, xattr_data, xattr_data_len, path); + pool_free(sn->pool, xattr_data); } else { // empty map pmap = cxHashMapCreate(a, request->setcount + 8); @@ -229,6 +304,7 @@ if(!pmap) { return 1; } + xprop->properties = pmap; // remove properties WebdavPListIterator i = webdav_plist_iterator(removeInOut); @@ -276,19 +352,7 @@ webdav_plist_iterator_remove_current(&i); } - //printf("\n\n%.*s\n\n", (int)buf.size, buf.space); - //fflush(stdout); - - int ret = 0; - cxmutstr new_data = webdav_xattr_serialze_map(a, pmap); - if(new_data.ptr) { - xattr_set(path, repo->xattr_name, new_data.ptr, new_data.length); - } else { - cxMapDestroy(pmap); - ret = 1; - } - - return ret; + return 0; } int webdav_xattr_proppatch_finish( @@ -297,6 +361,29 @@ VFSFile *file, WSBool commit) { + Session *sn = request->sn; + Request *rq = request->rq; + CxAllocator *a = pool_allocator(sn->pool); + + WebdavXAttrBackend *xdav = request->dav->instance; + WebdavXAttrRepository *repo = xdav->repo; + + XAttrProppatch *xprop = request->userdata; + + char *path = pblock_findkeyval(pb_key_path, rq->vars); + + int ret = 0; + if(commit) { + cxmutstr new_data = webdav_xattr_serialze_map(a, xprop->properties); + if(new_data.ptr) { + if(xattr_set(path, repo->xattr_name, new_data.ptr, new_data.length)) { + ret = 1; + } + } else { + ret = 1; + } + } + return 0; } diff -r 31affbf33911 -r b02da778362e src/server/webdav/xattrbackend.h --- a/src/server/webdav/xattrbackend.h Sat Mar 18 19:33:06 2023 +0100 +++ b/src/server/webdav/xattrbackend.h Sun Mar 19 11:14:10 2023 +0100 @@ -91,6 +91,17 @@ VFSFile *file, WSBool commit); +int webdav_xattr_propfind_get_requested_properties( + WebdavPropfindRequest *request, + WebdavResource *resource, + CxAllocator *a, + CxMap *pmap); + +int webdav_xattr_propfind_allprop( + WebdavPropfindRequest *request, + WebdavResource *resource, + CxAllocator *a, + CxMap *pmap); /* properties xattr data */