# HG changeset patch # User Olaf Wintermann # Date 1659872803 -7200 # Node ID 47bc686fafe40a3607a3e35eba9f667582036b22 # Parent 570026d3a68592691793eb71c23a62a6d1814c0f add new dav config element diff -r 570026d3a685 -r 47bc686fafe4 doc/development/postgresql_vfs.sql --- a/doc/development/postgresql_vfs.sql Sun May 15 08:56:00 2022 +0200 +++ b/doc/development/postgresql_vfs.sql Sun Aug 07 13:46:43 2022 +0200 @@ -1,4 +1,3 @@ - create table Resource ( resource_id serial primary key, parent_id int references Resource(resource_id), diff -r 570026d3a685 -r 47bc686fafe4 src/server/config/serverconfig.c --- a/src/server/config/serverconfig.c Sun May 15 08:56:00 2022 +0200 +++ b/src/server/config/serverconfig.c Sun Aug 07 13:46:43 2022 +0200 @@ -293,7 +293,7 @@ ConfigNode* serverconfig_get_node(ConfigNode *parent, ConfigNodeType type, scstr_t name) { UCX_FOREACH(elm, parent->children) { ConfigNode *node = elm->data; - if(node->type == type && !sstrcmp(node->name, name)) { + if(node->type == type && !sstrcasecmp(node->name, name)) { return node; } } @@ -305,7 +305,7 @@ UCX_FOREACH(elm, parent->children) { ConfigNode *node = elm->data; - if(node->type == type && !sstrcmp(node->name, name)) { + if(node->type == type && !sstrcasecmp(node->name, name)) { nodes = ucx_list_append(nodes, node); } } diff -r 570026d3a685 -r 47bc686fafe4 src/server/daemon/config.c --- a/src/server/daemon/config.c Sun May 15 08:56:00 2022 +0200 +++ b/src/server/daemon/config.c Sun Aug 07 13:46:43 2022 +0200 @@ -276,6 +276,14 @@ return NULL; } } + + list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("Dav")); + UCX_FOREACH(elm, list) { + ConfigNode *scfgobj = elm->data; + if(cfg_handle_dav(serverconfig, scfgobj)) { + return NULL; + } + } // set VirtualServer for all listeners UcxList *ls = serverconfig->listeners; @@ -668,6 +676,97 @@ return 0; } +int cfg_handle_dav(ServerConfiguration *cfg, ConfigNode *obj) { + UcxList *backends = NULL; // list of ConfigArg* + UcxAllocator a = util_pool_allocator(cfg->pool); + int init_error; + + // get a list of all DavBackends + UCX_FOREACH(elm, obj->children) { + ConfigNode *node = elm->data; + if(!sstrcasecmp(node->name, SC("DavBackend"))) { + if(node->type == CONFIG_NODE_DIRECTIVE) { + if(ucx_list_size(node->args) == 1) { + ConfigArg *arg = node->args->data; + backends = ucx_list_append(backends, arg); + } else { + log_ereport(LOG_MISCONFIG, "DavBackend must have only one value"); + ucx_list_free(backends); + return 1; + } + } else { + log_ereport(LOG_MISCONFIG, "DavBackend must be a directive"); + ucx_list_free(backends); + return 1; + } + } + } + + int ret = 0; + WebdavRepository *repository = pool_malloc(cfg->pool, sizeof(WebdavRepository)); + repository->vfs = NULL; + repository->vfsInitData = NULL; + repository->davBackends = NULL; + + // initialize backends + UCX_FOREACH(elm, backends) { + // the DavBackend value should contain the dav class name + ConfigArg *backendArg = elm->data; + + WebdavType *dav = webdav_get_type((scstr_t){backendArg->value.ptr, backendArg->value.length}); + if(!dav) { + log_ereport(LOG_MISCONFIG, "Unknown webdav backend type '%s'", backendArg->value.ptr); + ret = 1; + break; + } + + // call backend init + // init_data can be NULL, errors will be indicated by init_error + void *init_data = webdav_init_backend(cfg, cfg->pool, dav, obj, &init_error); + if(init_error) { + log_ereport(LOG_FAILURE, "Failed to initialize webdav backend %s", backendArg->value.ptr); + ret = 1; + break; + } + + WebdavBackendInitData *davInit = pool_malloc(cfg->pool, sizeof(WebdavBackendInitData)); + if(!davInit) { + log_ereport(LOG_FAILURE, "Failed to initialize webdav backend %s: OOM", backendArg->value.ptr); + ret = 1; + break; + } + davInit->davType = dav; + davInit->davInitData = init_data; + + repository->davBackends = ucx_list_append_a(&a, repository->davBackends, davInit); + } + + // initialize vfs + scstr_t vfs_class = serverconfig_directive_value(obj, SC("VFS")); + if(vfs_class.length > 0) { + VfsType *vfs = vfs_get_type((scstr_t){vfs_class.ptr, vfs_class.length}); + if(vfs) { + repository->vfs = vfs; + repository->vfsInitData = vfs_init_backend(cfg, cfg->pool, vfs, obj, &init_error); + ret = init_error; + } else { + log_ereport(LOG_FAILURE, "Unknown vfs type '%s'", vfs_class.ptr); + ret = 1; + } + } + + scstr_t object = serverconfig_directive_value(obj, SC("Object")); + if(object.length > 0) { + repository->object = sstrdup_a(&a, object); + if(repository->object.length != object.length) { + // OOM + log_ereport(LOG_FAILURE, "Cannot create webdav repository: OOM"); + ret = 1; + } + } + + return ret; +} static int convert_objconf(ServerConfiguration *scfg, ObjectConfig *cfg, HTTPObjectConfig *conf, sstr_t file) { pool_handle_t *pool = conf->pool; diff -r 570026d3a685 -r 47bc686fafe4 src/server/daemon/config.h --- a/src/server/daemon/config.h Sun May 15 08:56:00 2022 +0200 +++ b/src/server/daemon/config.h Sun Aug 07 13:46:43 2022 +0200 @@ -43,6 +43,9 @@ #include "acldata.h" #include "keyfile_auth.h" #include "log.h" +#include "vfs.h" + +#include "../webdav/webdav.h" #include #include @@ -54,8 +57,11 @@ #endif typedef struct mime_map MimeMap; + +typedef struct WebdavRepository WebdavRepository; +typedef struct WebdavBackendInitData WebdavBackendInitData; -typedef struct _server_configuration { +struct ServerConfiguration { pool_handle_t *pool; UcxAllocator *a; @@ -69,8 +75,19 @@ sstr_t tmp; sstr_t user; uint32_t ref; // reference counter -} ServerConfiguration; +}; +struct WebdavRepository { + VfsType *vfs; + void *vfsInitData; + UcxList *davBackends; // list of WebdavBackendInitData* + sstr_t object; +}; + +struct WebdavBackendInitData { + WebdavType *davType; + void *davInitData; +}; struct mime_map { UcxMap *map; @@ -98,6 +115,8 @@ int cfg_handle_vs(ServerConfiguration *cfg, ConfigNode *obj); +int cfg_handle_dav(ServerConfiguration *cfg, ConfigNode *obj); + ServerConfiguration* load_server_conf(char *file); void cfg_ref(ServerConfiguration *cfg); void cfg_unref(ServerConfiguration *cfg); diff -r 570026d3a685 -r 47bc686fafe4 src/server/daemon/resourcepool.c --- a/src/server/daemon/resourcepool.c Sun May 15 08:56:00 2022 +0200 +++ b/src/server/daemon/resourcepool.c Sun Aug 07 13:46:43 2022 +0200 @@ -122,7 +122,7 @@ ResourceDataPrivate *resource = NULL; // was this resource already used by this request? - if(request->resources) { + if(request && request->resources) { resource = ucx_map_cstr_get(request->resources, name); if(resource) { return &resource->data; @@ -170,17 +170,19 @@ // for cleanup later int err = 0; if(resource) { - if(!request->resources) { - request->resources = ucx_map_new_a(&session->allocator, 8); - } - - if(request->resources) { - if(ucx_map_cstr_put(request->resources, name, resource)) { + if(request) { + if(!request->resources) { + request->resources = ucx_map_new_a(&session->allocator, 8); + } + + if(request->resources) { + if(ucx_map_cstr_put(request->resources, name, resource)) { + err = 1; + } + } else { err = 1; } - } else { - err = 1; - } + } // else: lookup is outside of any request context if(respool->type->prepare(respool->data, resource->resdata)) { err = -1; diff -r 570026d3a685 -r 47bc686fafe4 src/server/daemon/vfs.c --- a/src/server/daemon/vfs.c Sun May 15 08:56:00 2022 +0200 +++ b/src/server/daemon/vfs.c Sun Aug 07 13:46:43 2022 +0200 @@ -87,7 +87,7 @@ return 0; } -int vfs_register_type(const char *name, vfs_create_func vfsCreate) { +int vfs_register_type(const char *name, vfs_init_func vfsInit, vfs_create_func vfsCreate) { WS_ASSERT(name); if(!vfs_type_map) { @@ -95,18 +95,42 @@ return 1; } } - return ucx_map_cstr_put(vfs_type_map, name, vfsCreate); + + VfsType *vfsType = malloc(sizeof(VfsType)); + if(!vfsType) { + return 1; + } + vfsType->init = vfsInit; + vfsType->create = vfsCreate; + + return ucx_map_cstr_put(vfs_type_map, name, vfsType); +} + +VfsType* vfs_get_type(scstr_t vfs_class) { + return ucx_map_sstr_get(vfs_type_map, vfs_class); } +void* vfs_init_backend(ServerConfiguration *cfg, pool_handle_t *pool, VfsType *vfs_class, WSConfigNode *config, int *error) { + *error = 0; + if(vfs_class->init) { + void *initData = vfs_class->init(cfg, pool, config); + if(!initData) { + *error = 1; + } + return initData; + } else { + return NULL; + } +} -VFS* vfs_create(Session *sn, Request *rq, const char *vfs_class, pblock *pb) { - vfs_create_func createVFS = ucx_map_cstr_get(vfs_type_map, vfs_class); - if(!createVFS) { +VFS* vfs_create(Session *sn, Request *rq, const char *vfs_class, pblock *pb, void *initData) { + VfsType *vfsType = ucx_map_cstr_get(vfs_type_map, vfs_class); + if(!vfsType) { log_ereport(LOG_MISCONFIG, "vfs_create: unkown VFS type %s", vfs_class); return NULL; } - return createVFS(sn, rq, pb); + return vfsType->create(sn, rq, pb, initData); } VFSContext* vfs_request_context(Session *sn, Request *rq) { diff -r 570026d3a685 -r 47bc686fafe4 src/server/daemon/vfs.h --- a/src/server/daemon/vfs.h Sun May 15 08:56:00 2022 +0200 +++ b/src/server/daemon/vfs.h Sun Aug 07 13:46:43 2022 +0200 @@ -32,10 +32,17 @@ #include "../public/vfs.h" #include "acl.h" +#include + #ifdef __cplusplus extern "C" { #endif +typedef struct VfsType { + vfs_init_func init; + vfs_create_func create; +} VfsType; + typedef struct SysVFSDir { DIR *dir; struct dirent *cur; @@ -48,6 +55,9 @@ typedef enum VFSAioOp VFSAioOp; int vfs_init(void); +VfsType* vfs_get_type(scstr_t vfs_class); + +void* vfs_init_backend(ServerConfiguration *cfg, pool_handle_t *pool, VfsType *vfs_class, WSConfigNode *config, int *error); typedef int(*vfs_op_f)(VFSContext *, const char *); typedef int(*sys_op_f)(VFSContext *, const char *, SysACL *); diff -r 570026d3a685 -r 47bc686fafe4 src/server/plugins/postgresql/Makefile --- a/src/server/plugins/postgresql/Makefile Sun May 15 08:56:00 2022 +0200 +++ b/src/server/plugins/postgresql/Makefile Sun Aug 07 13:46:43 2022 +0200 @@ -36,6 +36,7 @@ SRC += service.c SRC += vfs.c SRC += webdav.c +SRC += config.c TEST_SRC = pgtest.c diff -r 570026d3a685 -r 47bc686fafe4 src/server/plugins/postgresql/config.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/plugins/postgresql/config.c Sun Aug 07 13:46:43 2022 +0200 @@ -0,0 +1,66 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2022 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. + */ + +#include "config.h" + +#include "../../util/util.h" + +PgRepository* pg_init_repo(pool_handle_t *pool, WSConfigNode *config) { + UcxAllocator a = util_pool_allocator(pool); + + ConfigNode *pg = serverconfig_get_node(config, CONFIG_NODE_OBJECT, SC("Postgresql")); + if(!pg) { + log_ereport(LOG_MISCONFIG, "pg_init_repo: missing postgresql config object"); + return NULL; + } + + scstr_t cfg_respool = serverconfig_directive_value(pg, SC("ResourcePool")); + scstr_t cfg_rootid = serverconfig_directive_value(pg, SC("RootId")); + scstr_t cfg_dav = serverconfig_directive_value(pg, SC("PGDavConfig")); + + // minimum requirement is a resource pool + if(cfg_respool.length == 0) { + return NULL; + } + + // check rootid + int64_t root_id = 1; + if(cfg_rootid.length > 0) { + if(!util_strtoint(cfg_rootid.ptr, &root_id)) { + log_ereport(LOG_MISCONFIG, "pg_init_repo: RootId parameter is not an integer: %s", cfg_rootid.ptr); + return NULL; + } + } + + PgRepository *repo = pool_malloc(pool, sizeof(PgRepository)); + ZERO(repo, sizeof(PgRepository)); + + repo->resourcepool = sstrdup_a(&a, cfg_respool); + + return repo; +} diff -r 570026d3a685 -r 47bc686fafe4 src/server/plugins/postgresql/config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/plugins/postgresql/config.h Sun Aug 07 13:46:43 2022 +0200 @@ -0,0 +1,61 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2022 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 WS_PG_CONFIG_H +#define WS_PG_CONFIG_H + +#include "../../public/nsapi.h" +#include "../../public/webdav.h" + +#include "../../daemon/config.h" +#include "../../config/serverconfig.h" + +#include + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct PgRepository { + int64_t root_resource_id; + sstr_t resourcepool; +} PgRepository; + +PgRepository* pg_init_repo(pool_handle_t *pool, WSConfigNode *config); + +#ifdef __cplusplus +} +#endif + +#endif /* WS_PG_CONFIG_H */ + diff -r 570026d3a685 -r 47bc686fafe4 src/server/plugins/postgresql/init.c --- a/src/server/plugins/postgresql/init.c Sun May 15 08:56:00 2022 +0200 +++ b/src/server/plugins/postgresql/init.c Sun Aug 07 13:46:43 2022 +0200 @@ -52,11 +52,11 @@ } int pg_register_vfs(pblock *pb) { - return vfs_register_type("postgresql", pg_vfs_create); + return vfs_register_type("postgresql", pg_vfs_init, pg_vfs_create); } int pg_register_webdav_backend(pblock *pb) { - if(webdav_register_backend("postgresql", pg_webdav_create)) { + if(webdav_register_backend("postgresql", pg_webdav_init, pg_webdav_create)) { return 1; } return 0; diff -r 570026d3a685 -r 47bc686fafe4 src/server/plugins/postgresql/vfs.c --- a/src/server/plugins/postgresql/vfs.c Sun May 15 08:56:00 2022 +0200 +++ b/src/server/plugins/postgresql/vfs.c Sun Aug 07 13:46:43 2022 +0200 @@ -27,6 +27,7 @@ */ #include "vfs.h" +#include "config.h" #include @@ -140,7 +141,12 @@ // params: $1: resource_id static const char *sql_delete_res = "delete from Resource where parent_id is not null and resource_id = $1;"; -VFS* pg_vfs_create(Session *sn, Request *rq, pblock *pb) { + +void* pg_vfs_init(ServerConfiguration *cfg, pool_handle_t *pool, WSConfigNode *config) { + return pg_init_repo(pool, config); +} + +VFS* pg_vfs_create(Session *sn, Request *rq, pblock *pb, void *initData) { // resourcepool is required char *resource_pool = pblock_findval("resourcepool", pb); if(!resource_pool) { diff -r 570026d3a685 -r 47bc686fafe4 src/server/plugins/postgresql/vfs.h --- a/src/server/plugins/postgresql/vfs.h Sun May 15 08:56:00 2022 +0200 +++ b/src/server/plugins/postgresql/vfs.h Sun Aug 07 13:46:43 2022 +0200 @@ -44,6 +44,7 @@ typedef struct PgVFS { ResourceData *pg_resource; PGconn *connection; + int64_t root_resource_id; } PgVFS; typedef struct PgFile { @@ -64,7 +65,9 @@ int nrows; } PgDir; -VFS* pg_vfs_create(Session *sn, Request *rq, pblock *pb); +void* pg_vfs_init(ServerConfiguration *cfg, pool_handle_t *pool, WSConfigNode *config); + +VFS* pg_vfs_create(Session *sn, Request *rq, pblock *pb, void *initData); VFS* pg_vfs_create_from_resourcedata(Session *sn, Request *rq, ResourceData *resdata); diff -r 570026d3a685 -r 47bc686fafe4 src/server/plugins/postgresql/webdav.c --- a/src/server/plugins/postgresql/webdav.c Sun May 15 08:56:00 2022 +0200 +++ b/src/server/plugins/postgresql/webdav.c Sun Aug 07 13:46:43 2022 +0200 @@ -28,6 +28,7 @@ #include "webdav.h" #include "vfs.h" +#include "config.h" #include "../../util/util.h" #include "../../util/pblock.h" @@ -269,7 +270,11 @@ delete from Property where resource_id = $1 and xmlns = $2 and pname = $3"; -WebdavBackend* pg_webdav_create(Session *sn, Request *rq, pblock *pb) { +void* pg_webdav_init(ServerConfiguration *cfg, pool_handle_t *pool, WSConfigNode *config) { + return pg_init_repo(pool, config); +} + +WebdavBackend* pg_webdav_create(Session *sn, Request *rq, pblock *pb, void *initData) { // resourcepool is required char *resource_pool = pblock_findval("resourcepool", pb); if(!resource_pool) { diff -r 570026d3a685 -r 47bc686fafe4 src/server/plugins/postgresql/webdav.h --- a/src/server/plugins/postgresql/webdav.h Sun May 15 08:56:00 2022 +0200 +++ b/src/server/plugins/postgresql/webdav.h Sun Aug 07 13:46:43 2022 +0200 @@ -44,6 +44,7 @@ typedef struct PgWebdavBackend { ResourceData *pg_resource; PGconn *connection; + int64_t root_resource_id; } PgWebdavBackend; typedef struct PgPropfind { @@ -54,7 +55,8 @@ int nrows; } PgPropfind; -WebdavBackend* pg_webdav_create(Session *sn, Request *rq, pblock *pb); +void* pg_webdav_init(ServerConfiguration *cfg, pool_handle_t *pool, WSConfigNode *config); +WebdavBackend* pg_webdav_create(Session *sn, Request *rq, pblock *pb, void *initData); WebdavBackend* pg_webdav_create_from_resdata(Session *sn, Request *rq, ResourceData *resdata); WebdavBackend* pg_webdav_prop_create(Session *sn, Request *rq, pblock *pb); diff -r 570026d3a685 -r 47bc686fafe4 src/server/public/nsapi.h --- a/src/server/public/nsapi.h Sun May 15 08:56:00 2022 +0200 +++ b/src/server/public/nsapi.h Sun Aug 07 13:46:43 2022 +0200 @@ -691,6 +691,15 @@ typedef struct VFS VFS; typedef struct VFSContext VFSContext; +enum WSConfigNodeType { + WS_CONFIG_NODE_OBJECT = 0, + WS_CONFIG_NODE_DIRECTIVE +}; + +typedef struct ServerConfiguration ServerConfiguration; +typedef struct ConfigNode WSConfigNode; +typedef enum WSConfigNodeType WSConfigNodeType; + #ifndef PR_AF_INET typedef union PRNetAddr PRNetAddr; #endif diff -r 570026d3a685 -r 47bc686fafe4 src/server/public/vfs.h --- a/src/server/public/vfs.h Sun May 15 08:56:00 2022 +0200 +++ b/src/server/public/vfs.h Sun Aug 07 13:46:43 2022 +0200 @@ -110,17 +110,18 @@ void (*close)(VFS_DIR dir); }; -typedef VFS*(*vfs_create_func)(Session *sn, Request *rq, pblock *pb); +typedef void*(*vfs_init_func)(ServerConfiguration *cfg, pool_handle_t *pool, WSConfigNode *config); +typedef VFS*(*vfs_create_func)(Session *sn, Request *rq, pblock *pb, void *initData); /* * registers a new VFS */ -int vfs_register_type(const char *name, vfs_create_func vfsCreate); +int vfs_register_type(const char *name, vfs_init_func vfsInit, vfs_create_func vfsCreate); /* * Create a new VFS instance */ -VFS* vfs_create(Session *sn, Request *rq, const char *vfs_class, pblock *pb); +VFS* vfs_create(Session *sn, Request *rq, const char *vfs_class, pblock *pb, void *initData); /* * creates a VFSContext for a Request diff -r 570026d3a685 -r 47bc686fafe4 src/server/public/webdav.h --- a/src/server/public/webdav.h Sun May 15 08:56:00 2022 +0200 +++ b/src/server/public/webdav.h Sun Aug 07 13:46:43 2022 +0200 @@ -92,7 +92,8 @@ #define WS_WEBDAV_PROPPATCH_USE_VFS 0x02 -typedef WebdavBackend*(*webdav_create_func)(Session *sn, Request *rq, pblock *pb); +typedef void*(*webdav_init_func)(ServerConfiguration *cfg, pool_handle_t *pool, WSConfigNode *config); +typedef WebdavBackend*(*webdav_create_func)(Session *sn, Request *rq, pblock *pb, void *initData); enum WebdavValueType { WS_VALUE_NO_TYPE = 0, @@ -392,9 +393,9 @@ /* * register a webdav backend */ -int webdav_register_backend(const char *name, webdav_create_func vfsCreate); +int webdav_register_backend(const char *name, webdav_init_func webdavInit, webdav_create_func webdavCreate); -WebdavBackend* webdav_create(Session *sn, Request *rq, const char *dav_class, pblock *pb); +WebdavBackend* webdav_create(Session *sn, Request *rq, const char *dav_class, pblock *pb, void *initData); /* * gets the requested depth diff -r 570026d3a685 -r 47bc686fafe4 src/server/safs/nametrans.c --- a/src/server/safs/nametrans.c Sun May 15 08:56:00 2022 +0200 +++ b/src/server/safs/nametrans.c Sun Aug 07 13:46:43 2022 +0200 @@ -40,7 +40,7 @@ char *vfsclass = pblock_findkeyval(pb_key_vfsclass, pb); if(!vfsclass) return 0; - VFS *vfs = vfs_create(sn, rq, vfsclass, pb); + VFS *vfs = vfs_create(sn, rq, vfsclass, pb, NULL); if(!vfs) { return 1; } @@ -52,7 +52,7 @@ char *davclass = pblock_findkeyval(pb_key_davclass, pb); if(!davclass) return 0; - WebdavBackend *dav = webdav_create(sn, rq, davclass, pb); + WebdavBackend *dav = webdav_create(sn, rq, davclass, pb, NULL); rq->davCollection = dav; return 0; diff -r 570026d3a685 -r 47bc686fafe4 src/server/webdav/webdav.c --- a/src/server/webdav/webdav.c Sun May 15 08:56:00 2022 +0200 +++ b/src/server/webdav/webdav.c Sun Aug 07 13:46:43 2022 +0200 @@ -85,19 +85,38 @@ default_backend.instance = NULL; } -int webdav_register_backend(const char *name, webdav_create_func webdavCreate) { - return ucx_map_cstr_put(webdav_type_map, name, webdavCreate); +int webdav_register_backend(const char *name, webdav_init_func webdavInit, webdav_create_func webdavCreate) { + WebdavType *webdavType = malloc(sizeof(WebdavType)); + webdavType->init = webdavInit; + webdavType->create = webdavCreate; + return ucx_map_cstr_put(webdav_type_map, name, webdavType); +} + +WebdavType* webdav_get_type(scstr_t dav_class) { + return ucx_map_sstr_get(webdav_type_map, dav_class); } +void* webdav_init_backend(ServerConfiguration *cfg, pool_handle_t *pool, WebdavType *dav_class, WSConfigNode *config, int *error) { + *error = 0; + if(dav_class->init) { + void *initData = dav_class->init(cfg, pool, config); + if(!initData) { + *error = 1; + } + return initData; + } else { + return NULL; + } +} -WebdavBackend* webdav_create(Session *sn, Request *rq, const char *dav_class, pblock *pb) { - webdav_create_func createDav = ucx_map_cstr_get(webdav_type_map, dav_class); - if(!createDav) { +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); + if(!webdavType) { log_ereport(LOG_MISCONFIG, "webdav_create: unkown dav type %s", dav_class); return NULL; } - return createDav(sn, rq, pb); + return webdavType->create(sn, rq, pb, initData); } static WSBool webdav_is_initialized = FALSE; diff -r 570026d3a685 -r 47bc686fafe4 src/server/webdav/webdav.h --- a/src/server/webdav/webdav.h Sun May 15 08:56:00 2022 +0200 +++ b/src/server/webdav/webdav.h Sun Aug 07 13:46:43 2022 +0200 @@ -33,18 +33,25 @@ #include #include +#include #ifdef __cplusplus extern "C" { #endif - +typedef struct WebdavType { + webdav_init_func init; + webdav_create_func create; +} WebdavType; typedef struct DefaultWebdavData { WebdavVFSProperties vfsproperties; } DefaultWebdavData; - +WebdavType* webdav_get_type(scstr_t dav_class); + +void* webdav_init_backend(ServerConfiguration *cfg, pool_handle_t *pool, WebdavType *dav_class, WSConfigNode *config, int *error); + int webdav_init(pblock *pb, Session *sn, Request *rq); int webdav_service(pblock *pb, Session *sn, Request *rq);