add libxattr

Sat, 18 Mar 2023 15:52:35 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 18 Mar 2023 15:52:35 +0100
changeset 480
9f69e4b8b695
parent 479
2a42ba73ecdd
child 481
31affbf33911

add libxattr

src/server/util/libxattr.c file | annotate | diff | comparison | revisions
src/server/util/libxattr.h file | annotate | diff | comparison | revisions
src/server/util/objs.mk file | annotate | diff | comparison | revisions
src/server/webdav/xattrbackend.c file | annotate | diff | comparison | revisions
src/server/webdav/xattrbackend.h file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/util/libxattr.c	Sat Mar 18 15:52:35 2023 +0100
@@ -0,0 +1,576 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2018 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "libxattr.h"
+
+#include <errno.h>
+#include <sys/types.h>
+
+#include <string.h>
+
+#define LIST_BUF_LEN 1024
+#define LIST_ARRAY_LEN 8
+#define ATTR_BUF_LEN 1024
+
+#define ARRAY_ADD(array, pos, len, obj) if(pos >= len) { \
+        len *= 2; /* TODO: missing error handling for realloc() */ \
+        array = realloc(array, len * sizeof(char*)); \
+    } \
+    array[pos] = obj; \
+    pos++;
+
+static void* libxattr_malloc(void *unused, size_t size) {
+    return malloc(size);
+}
+
+static void libxattr_free(void *unused, void *ptr) {
+    free(ptr);
+}
+
+
+#ifdef __linux__
+#define XATTR_SUPPORTED
+#include <sys/xattr.h>
+
+static char ** parse_xattrlist(char *buf, ssize_t length, ssize_t *nelm) {
+    size_t arraylen = LIST_ARRAY_LEN;
+    size_t arraypos = 0;
+    char **array = malloc(LIST_ARRAY_LEN * sizeof(char*));
+    
+    char *begin = buf;
+    char *name = NULL;
+    for(int i=0;i<length;i++) {
+        if(!name && buf[i] == '.') {
+            int nslen = (buf+i-begin);
+            //printf("%.*s\n", nslen, begin);
+            name = buf + i + 1;
+        }
+        if(buf[i] == '\0') {
+            char *attrname = strdup(name);
+            ARRAY_ADD(array, arraypos, arraylen, attrname);
+            begin = buf + i + 1;
+            name = 0;
+        }
+    }
+    
+    if(arraypos == 0) {
+        free(array);
+        array = NULL;
+    }
+    
+    *nelm = arraypos;
+    return array;
+}
+
+char ** xattr_list(const char *path, ssize_t *nelm) {
+    char *list = malloc(LIST_BUF_LEN);
+    ssize_t len = listxattr(path, list, LIST_BUF_LEN);
+    if(len == -1) {
+        switch(errno) {
+            case ERANGE: {
+                // buffer too, get size of attribute list
+                ssize_t newlen = listxattr(path, NULL, 0);
+                if(newlen > 0) {
+                    // second try
+                    list = realloc(list, newlen);
+                    len = listxattr(path, list, newlen);
+                    if(len != -1) {
+                        // this time it worked
+                        break;
+                    }
+                }
+            }
+            default: {
+                free(list);
+                *nelm = -1;
+                return NULL;
+            }
+        }
+    }
+    
+    char **ret = parse_xattrlist(list, len, nelm);
+    free(list);
+    return ret;
+}
+
+static char* name2nsname(const char *name) {
+    // add the 'user' namespace to the name
+    size_t namelen = strlen(name);
+    char *attrname = malloc(8 + namelen);
+    if(!attrname) {
+        return NULL;
+    }
+    memcpy(attrname, "user.", 5);
+    memcpy(attrname+5, name, namelen + 1);
+    return attrname;
+}
+
+char * xattr_get_alloc(
+        void *pool,
+        libxattr_malloc_func malloc_func,
+        libxattr_free_func free_func,
+        const char *path,
+        const char *attr,
+        ssize_t *len)
+{
+    char *buf = malloc_func(pool, ATTR_BUF_LEN);
+    if(!buf) {
+        *len = -1;
+        return NULL;
+    }
+    
+    char *attrname = name2nsname(attr);
+    if(!attrname) {
+        free_func(pool, buf);
+        *len = -1;
+        return NULL;
+    }
+    
+    ssize_t vlen = getxattr(path, attrname, buf, ATTR_BUF_LEN - 1);
+    if(vlen < 0) {
+        switch(errno) {
+            case ERANGE: {
+                ssize_t attrlen = getxattr(path, attrname, NULL, 0);
+                if(attrlen > 0) {
+                    free_func(pool, buf);
+                    buf = malloc_func(pool, attrlen + 1);
+                    if(!buf) {
+                        free(attrname);
+                        *len = -1;
+                        return NULL;
+                    }
+                    vlen = getxattr(path, attrname, buf, attrlen);
+                    if(vlen > 0) {
+                        break;
+                    }
+                }
+            }
+            default: {
+                *len = -1;
+                free_func(pool, buf);
+                free(attrname);
+                return NULL;
+            }
+        }
+    }
+    buf[vlen] = 0;
+    
+    free(attrname);
+    *len = vlen;
+    return buf;
+}
+
+int xattr_set(const char *path, const char *name, const void *value, size_t len) {
+    char *attrname = name2nsname(name);
+    int ret = setxattr(path, attrname, value, len, 0);
+    free(attrname);
+    return ret;
+}
+
+int xattr_remove(const char *path, const char *name) {
+    char *attrname = name2nsname(name);
+    int ret = removexattr(path, attrname);
+    free(attrname);
+    return ret;
+}
+
+#endif /* Linux */
+
+#ifdef __APPLE__
+#define XATTR_SUPPORTED
+#include <sys/xattr.h>
+
+static char ** parse_xattrlist(char *buf, ssize_t length, ssize_t *nelm) {
+    size_t arraylen = LIST_ARRAY_LEN;
+    size_t arraypos = 0;
+    char **array = malloc(LIST_ARRAY_LEN * sizeof(char*));
+    
+    char *name = buf;
+    for(int i=0;i<length;i++) {
+        if(buf[i] == '\0') {
+            char *attrname = strdup(name);
+            ARRAY_ADD(array, arraypos, arraylen, attrname);
+            name = buf + i + 1;
+        }
+    }
+    
+    if(arraypos == 0) {
+        free(array);
+        array = NULL;
+    }
+    
+    *nelm = arraypos;
+    return array;
+}
+
+char ** xattr_list(const char *path, ssize_t *nelm) {
+    char *list = malloc(LIST_BUF_LEN);
+    ssize_t len = listxattr(path, list, LIST_BUF_LEN, 0);
+    if(len == -1) {
+        switch(errno) {
+            case ERANGE: {
+                // buffer too, get size of attribute list
+                ssize_t newlen = listxattr(path, NULL, 0, 0);
+                if(newlen > 0) {
+                    // second try
+                    list = realloc(list, newlen);
+                    len = listxattr(path, list, newlen, 0);
+                    if(len != -1) {
+                        // this time it worked
+                        break;
+                    }
+                }
+            }
+            default: {
+                free(list);
+                *nelm = -1;
+                return NULL;
+            }
+        }
+    }
+    
+    char **ret = parse_xattrlist(list, len, nelm);
+    free(list);
+    return ret;
+}
+
+char * xattr_get_alloc(
+        void *pool,
+        libxattr_malloc_func malloc_func,
+        libxattr_free_func free_func,
+        const char *path,
+        const char *attr,
+        ssize_t *len)
+{
+    // get attribute length
+    ssize_t attrlen = getxattr(path, attr, NULL, 0, 0, 0);
+    if(attrlen < 0) {
+        *len = -1;
+        return NULL;
+    }
+    
+    char *buf = malloc_func(pool, attrlen + 1);
+    if(!buf) {
+        *len = -1;
+        return NULL;
+    }
+    
+    ssize_t vlen = getxattr(path, attr, buf, attrlen, 0, 0);
+    if(vlen < 0) {
+        *len = -1;
+        free_func(pool, buf);
+        return NULL;
+    }
+    buf[attrlen] = 0;
+    
+    *len = vlen;
+    return buf;
+}
+
+int xattr_set(const char *path, const char *name, const void *value, size_t len) {
+    int ret = setxattr(path, name, value, len, 0, 0);
+    return ret;
+}
+
+int xattr_remove(const char *path, const char *name) {
+    return removexattr(path, name, 0);
+}
+
+#endif /* Apple */
+
+#ifdef __sun
+#define XATTR_SUPPORTED
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+
+static int open_attrfile(const char *path, const char *attr, int oflag) {
+    int file = open(path, O_RDONLY);
+    if(file == -1) {
+        return -1;
+    }
+    
+    int attrfile = openat(file, attr, oflag, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+    close(file);
+    return attrfile;
+}
+
+char ** xattr_list(const char *path, ssize_t *nelm) {
+    *nelm = -1;
+    
+    int attrdir = open_attrfile(path, ".", O_RDONLY|O_XATTR);
+    if(attrdir == -1) {
+        return NULL;
+    }
+    
+    DIR *dir = fdopendir(attrdir);
+    if(!dir) {
+        close(attrdir);
+        return NULL;
+    }
+    
+    size_t arraylen = LIST_ARRAY_LEN;
+    size_t arraypos = 0;
+    char **array = malloc(LIST_ARRAY_LEN * sizeof(char*));
+    
+    struct dirent *ent;
+    while((ent = readdir(dir)) != NULL) {
+        if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "SUNWattr_ro") || !strcmp(ent->d_name, "SUNWattr_rw")) {
+            continue;
+        }
+        char *name = strdup(ent->d_name);
+        ARRAY_ADD(array, arraypos, arraylen, name);
+    }
+    closedir(dir);
+    
+    *nelm = arraypos;
+    return array;
+}
+
+char * xattr_get_alloc(
+        void *pool,
+        libxattr_malloc_func malloc_func,
+        libxattr_free_func free_func,
+        const char *path,
+        const char *attr,
+        ssize_t *len)
+{
+    *len = -1;
+    
+    int attrfile = open_attrfile(path, attr, O_RDONLY|O_XATTR);
+    if(attrfile == -1) {
+        return NULL;
+    }
+    
+    struct stat s;
+    if(fstat(attrfile, &s)) {
+        close(attrfile);
+        return NULL;
+    }
+    
+    size_t bufsize = (size_t)s.st_size;
+    char *buf = malloc_func(pool, bufsize);
+    
+    char *b = buf;
+    size_t cur = 0;
+    while(cur < bufsize) {
+        ssize_t r = read(attrfile, buf + cur, bufsize - cur);
+        if(r <= 0) {
+            break;
+        }
+        cur += r;
+    }
+    
+    close(attrfile);
+    if(cur != bufsize) {
+        free_func(pool, buf);
+        return NULL;
+    }
+    
+    *len = (ssize_t)bufsize;
+    return buf;    
+}
+
+int xattr_set(const char *path, const char *name, const void *value, size_t len) {
+    int attrfile = open_attrfile(path, name, O_CREAT|O_WRONLY|O_XATTR|O_TRUNC);
+    if(attrfile == -1) {
+        return -1;
+    }
+    
+    const char *p = value;
+    size_t remaining = len;
+    while(remaining > 0) {
+        ssize_t w = write(attrfile, p, remaining);
+        if(w <= 0) {
+            break;
+        }
+        p += w;
+        remaining -= w;
+    }
+    
+    close(attrfile);
+    
+    return remaining > 0 ? -1 : 0;
+}
+
+int xattr_remove(const char *path, const char *name) {
+    int attrdir = open_attrfile(path, ".", O_RDONLY|O_XATTR);
+    if(attrdir == -1) {
+        return -1;
+    }
+    
+    int ret = unlinkat(attrdir, name, 0);
+    close(attrdir);
+    return ret;
+}
+
+#endif /* Sun */
+
+
+#ifdef __FreeBSD__
+#define XATTR_SUPPORTED
+
+#include <sys/types.h>
+#include <sys/extattr.h>
+
+static char ** parse_xattrlist(char *buf, ssize_t length, ssize_t *nelm) {
+    size_t arraylen = LIST_ARRAY_LEN;
+    size_t arraypos = 0;
+    char **array = malloc(LIST_ARRAY_LEN * sizeof(char*));
+    
+    char *name = buf;
+    for(int i=0;i<length;i++) {
+        char namelen = buf[i];
+        char *name = buf + i + 1;
+        char *attrname = malloc(namelen + 1);
+        memcpy(attrname, name, namelen);
+        attrname[namelen] = 0;
+        ARRAY_ADD(array, arraypos, arraylen, attrname);
+        i += namelen;
+    }
+    
+    if(arraypos == 0) {
+        free(array);
+        array = NULL;
+    }
+    
+    *nelm = arraypos;
+    return array;
+}
+
+char ** xattr_list(const char *path, ssize_t *nelm) {
+    *nelm = -1;
+    ssize_t lslen = extattr_list_file(path, EXTATTR_NAMESPACE_USER, NULL, 0);
+    if(lslen <= 0) {
+        if(lslen == 0) {
+            *nelm = 0;
+        }
+        return NULL;
+    }
+    
+    char *list = malloc(lslen);
+    ssize_t len = extattr_list_file(path, EXTATTR_NAMESPACE_USER, list, lslen);
+    if(len == -1) {
+        free(list);
+        return NULL;
+    }
+    
+    char **ret = parse_xattrlist(list, len, nelm);
+    free(list);
+    return ret;
+}
+
+char * xattr_get_alloc(
+        void *pool,
+        libxattr_malloc_func malloc_func,
+        libxattr_free_func free_func,
+        const char *path,
+        const char *attr,
+        ssize_t *len)
+{
+    // get attribute length
+    ssize_t attrlen = extattr_get_file(path, EXTATTR_NAMESPACE_USER, attr, NULL, 0);
+    if(attrlen < 0) {
+        *len = -1;
+        return NULL;
+    }
+    
+    char *buf = malloc_func(pool, attrlen + 1);
+    ssize_t vlen = extattr_get_file(path, EXTATTR_NAMESPACE_USER, attr, buf, attrlen);
+    if(vlen < 0) {
+        *len = -1;
+        free_func(pool, buf);
+        return NULL;
+    }
+    buf[attrlen] = 0;
+    
+    *len = vlen;
+    return buf;
+}
+
+int xattr_set(const char *path, const char *name, const void *value, size_t len) {
+    int ret = extattr_set_file(path, EXTATTR_NAMESPACE_USER, name, value, len);
+    return ret;
+}
+
+int xattr_remove(const char *path, const char *name) {
+    return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, name);
+}
+
+#endif /* FreeBSD */
+
+
+#ifndef XATTR_SUPPORTED
+
+char ** xattr_list(const char *path, ssize_t *nelm) {
+    *nelm = -1;
+    return NULL;
+}
+
+char * xattr_get_alloc(
+        void *pool,
+        libxattr_malloc_func malloc_func,
+        libxattr_free_func free_func,
+        const char *path,
+        const char *attr,
+        ssize_t *len)
+{
+    *len = -1;
+    return NULL;
+}
+
+int xattr_set(const char *path, const char *name, const void *value, size_t len) {
+    return -1;
+}
+
+int xattr_remove(const char *path, const char *name) {
+    return -1;
+}
+
+#endif /* unsupported platform */
+
+
+char * xattr_get(const char *path, const char *attr, ssize_t *len) { 
+    return xattr_get_alloc(NULL, libxattr_malloc, libxattr_free, path, attr, len);
+}
+
+void xattr_free_list(char **attrnames, ssize_t nelm) {
+    if(attrnames) {
+        for(int i=0;i<nelm;i++) {
+            free(attrnames[i]);
+        }
+        free(attrnames);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/util/libxattr.h	Sat Mar 18 15:52:35 2023 +0100
@@ -0,0 +1,66 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2018 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBXATTR_H
+#define LIBXATTR_H
+
+#include <sys/types.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+typedef void*(*libxattr_malloc_func)(void *pool, size_t size);
+typedef void(*libxattr_free_func)(void *pool, void *ptr);
+
+    
+char ** xattr_list(const char *path, ssize_t *nelm);
+
+char * xattr_get(const char *path, const char *attr, ssize_t *len);
+
+char * xattr_get_alloc(
+        void *pool,
+        libxattr_malloc_func malloc_func,
+        libxattr_free_func free_func,
+        const char *path,
+        const char *attr,
+        ssize_t *len);
+
+int xattr_set(const char *path, const char *name, const void *value, size_t len);
+
+int xattr_remove(const char *path, const char *name);
+
+void xattr_free_list(char **attrnames, ssize_t nelm);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBXATTR_H */
+
--- a/src/server/util/objs.mk	Sat Mar 18 14:16:05 2023 +0100
+++ b/src/server/util/objs.mk	Sat Mar 18 15:52:35 2023 +0100
@@ -43,6 +43,7 @@
 UTILOBJ += util.o
 UTILOBJ += date.o
 UTILOBJ += writer.o
+UTILOBJ += libxattr.o
 
 UTILOBJS = $(UTILOBJ:%=$(UTIL_OBJPRE)%)
 UTILSOURCE = $(UTILOBJ:%.o=util/%.c)
--- a/src/server/webdav/xattrbackend.c	Sat Mar 18 14:16:05 2023 +0100
+++ b/src/server/webdav/xattrbackend.c	Sat Mar 18 15:52:35 2023 +0100
@@ -29,6 +29,9 @@
 
 #include "xattrbackend.h"
 
+#include "../util/util.h"
+#include "../util/libxattr.h"
+
 
 static WebdavBackend webdav_xattr_backend = {
     webdav_xattr_propfind_init,
@@ -61,6 +64,7 @@
     }
     
     // TODO: config
+    repo->xattr_name = "webdav_properties";
     
     return repo;
 }
@@ -93,6 +97,22 @@
         const char *href,
         WebdavPList **outplist)
 {
+    // make sure the sys vfs is used, because currently only
+    // native sysfs xattr is supported
+    if(rq->rq->vfs) {
+        log_ereport(LOG_FAILURE, "webdav-propfind: xattr backend unsupported with non-native VFS");
+        return 1;
+    }
+    
+    XAttrPropfind *xprop = pool_malloc(rq->sn->pool, sizeof(XAttrPropfind));
+    if(!xprop) {
+        return 1;
+    }
+    rq->userdata = xprop;
+    
+    xprop->base_href = href;
+    xprop->base_path = path;
+    
     return 0;
 }
 
@@ -103,6 +123,47 @@
         WebdavResource *resource,
         struct stat *s)
 {
+    Session *sn = request->sn;
+    Request *rq = request->rq;
+    
+    WebdavXAttrBackend *xdav = request->dav->instance;
+    WebdavXAttrRepository *repo = xdav->repo;
+    XAttrPropfind *xprop = request->userdata;
+    
+    const char *path;
+    char *path_dp = NULL;
+    if(!parent) {
+        // use base path
+        path = xprop->base_path;
+    } else {
+        size_t base_href_len = strlen(xprop->base_href);
+        size_t base_path_len = strlen(xprop->base_path);
+        char *res_path = resource->href + base_href_len;
+        size_t res_path_len = strlen(res_path);
+        
+        path_dp = pool_malloc(sn->pool, base_path_len + res_path_len + 2);
+        memcpy(path_dp, xprop->base_path, base_path_len);
+        int s = 0;
+        if(path_dp[base_path_len-1] != '/' && res_path[0] != '/') {
+            path_dp[base_path_len] = '/';
+            s = 1;
+        }
+        memcpy(path_dp + base_path_len + s, res_path, res_path_len);
+        path_dp[base_path_len + s + res_path_len] = 0;
+        
+        path = path_dp;
+    }
+    
+    ssize_t xattr_data_len = 0;
+    char *xattr_data = xattr_get_alloc(
+            sn->pool,
+            (libxattr_malloc_func)pool_malloc,
+            (libxattr_free_func)pool_free,
+            path,
+            repo->xattr_name,
+            &xattr_data_len);
+    
+    
     return 0;
 }
 
--- a/src/server/webdav/xattrbackend.h	Sat Mar 18 14:16:05 2023 +0100
+++ b/src/server/webdav/xattrbackend.h	Sat Mar 18 15:52:35 2023 +0100
@@ -37,12 +37,17 @@
 #endif
 
 typedef struct WebdavXAttrRepository {
-    int a;
+    char *xattr_name;
 } WebdavXAttrRepository;
     
 typedef struct WebdavXAttrBackend {
     WebdavXAttrRepository *repo;
 } WebdavXAttrBackend;
+
+typedef struct XAttrPropfind {
+    const char *base_href;
+    const char *base_path;
+} XAttrPropfind;
     
 int webdav_init_xattr_backend(void);
 

mercurial