2 OpenChange Storage Abstraction Layer library
6 Note: init and load functions have been copied from
7 samba4/source4/param/util.c initially wrote by Jelmer.
9 Copyright (C) Jelmer Vernooij 2005-2007
10 Copyright (C) Julien Kerihuel 2009
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/types.h>
31 #include "mapistore.h"
32 #include "mapistore_errors.h"
33 #include "mapistore_private.h"
34 #include <libmapi/dlinklist.h>
37 #include <util/debug.h>
40 \file mapistore_backend.c
42 \brief mapistore backends management API
46 static struct mstore_backend {
47 struct mapistore_backend *backend;
54 \details Register mapistore backends
56 \param _backend pointer to the mapistore backend to register
58 \return MAPISTORE_SUCCESS on success
60 _PUBLIC_ extern int mapistore_backend_register(const void *_backend)
62 const struct mapistore_backend *backend = _backend;
64 backends = realloc_p(backends, struct mstore_backend, num_backends + 1);
66 smb_panic("out of memory in mapistore_backend_register");
69 backends[num_backends].backend = smb_xmemdup(backend, sizeof (*backend));
70 backends[num_backends].backend->name = smb_xstrdup(backend->name);
74 DEBUG(3, ("MAPISTORE backend '%s' registered\n", backend->name));
76 return MAPISTORE_SUCCESS;
81 \details Return the full path where mapistore backends are
84 \return Pointer to the full path where backends are installed.
86 _PUBLIC_ const char *mapistore_backend_get_installdir(void)
88 return MAPISTORE_BACKEND_INSTALLDIR;
93 \details Obtain the backend init function from a shared library
96 \param path full path to the backend shared library
98 \return Pointer to the initialization function on success,
101 static init_backend_fn load_backend(const char *path)
106 handle = dlopen(path, RTLD_NOW);
107 if (handle == NULL) {
108 DEBUG(0, ("Unable to open %s: %s\n", path, dlerror()));
112 init_fn = dlsym(handle, MAPISTORE_INIT_MODULE);
114 if (init_fn == NULL) {
115 DEBUG(0, ("Unable to find %s() in %s: %s\n",
116 MAPISTORE_INIT_MODULE, path, dlerror()));
117 DEBUG(1, ("Loading mapistore backend '%s' failed\n", path));
122 return (init_backend_fn) init_fn;
127 \details Load backends from specified directory
129 \param mem_ctx pointer to the memory context
130 \param pointer to the backends shared library folder
132 \return allocated array of functions pointers to initialization
133 functions on success, otherwise NULL.
135 static init_backend_fn *load_backends(TALLOC_CTX *mem_ctx, const char *path)
138 struct dirent *entry;
141 init_backend_fn *ret;
143 ret = talloc_array(mem_ctx, init_backend_fn, 2);
152 while ((entry = readdir(dir))) {
153 if (ISDOT(entry->d_name) || ISDOTDOT(entry->d_name)) {
157 filename = talloc_asprintf(mem_ctx, "%s/%s", path, entry->d_name);
158 ret[success] = load_backend(filename);
160 ret = talloc_realloc(mem_ctx, ret, init_backend_fn, success + 2);
165 talloc_free(filename);
175 \details Load the initialization functions from backends DSO
177 \param mem_ctx pointer to the memory context
178 \param path pointer to the backend's DSO folder
180 \return allocated array of functions pointers to initialization
181 functions on success, otherwise NULL.
183 _PUBLIC_ init_backend_fn *mapistore_backend_load(TALLOC_CTX *mem_ctx, const char *path)
186 path = mapistore_backend_get_installdir();
189 return load_backends(mem_ctx, path);
194 \details Run specified initialization functions.
196 \param fns pointer to an array of mapistore backends initialization
199 \return true on success, otherwise false
201 _PUBLIC_ bool mapistore_backend_run_init(init_backend_fn *fns)
210 for (i = 0; fns[i]; i++) {
211 ret &= (bool)fns[i]();
219 \details Initialize mapistore backends
221 \param mem_ctx pointer to the memory context
222 \param path pointer to folder where mapistore backends are
225 \return MAPISTORE_SUCCESS on success, otherwise
226 MAPISTORE_ERR_BACKEND_INIT
228 int mapistore_backend_init(TALLOC_CTX *mem_ctx, const char *path)
230 init_backend_fn *ret;
235 ret = mapistore_backend_load(mem_ctx, path);
236 status = mapistore_backend_run_init(ret);
239 for (i = 0; i < num_backends; i++) {
240 if (backends[i].backend) {
241 DEBUG(3, ("MAPISTORE backend '%s' loaded\n", backends[i].backend->name));
242 retval = backends[i].backend->init();
246 return (status != true) ? MAPISTORE_SUCCESS : MAPISTORE_ERR_BACKEND_INIT;
251 \details Create backend context
253 \param mem_ctx pointer to the memory context
254 \param namespace the backend namespace
255 \param uri the backend parameters which can be passes inline
257 \return a valid backend_context pointer on success, otherwise NULL
259 struct backend_context *mapistore_backend_create_context(TALLOC_CTX *mem_ctx, const char *namespace,
262 struct backend_context *context;
265 void *private_data = NULL;
268 DEBUG(0, ("namespace is %s and backend_uri is '%s'\n", namespace, uri));
269 for (i = 0; i < num_backends; i++) {
270 if (backends[i].backend->namespace &&
271 !strcmp(namespace, backends[i].backend->namespace)) {
273 retval = backends[i].backend->create_context(mem_ctx, uri, &private_data);
274 if (retval != MAPISTORE_SUCCESS) {
281 if (found == false) {
282 DEBUG(0, ("MAPISTORE: no backend with namespace '%s' is available\n", namespace));
286 context = talloc_zero(mem_ctx, struct backend_context);
287 context->backend = backends[i].backend;
288 context->private_data = private_data;
289 talloc_steal(context, context->private_data);
296 \details Delete a context from the specified backend
298 \param bctx pointer to the backend context
300 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
302 _PUBLIC_ int mapistore_backend_delete_context(struct backend_context *bctx)
304 if (!bctx->backend->delete_context) return MAPISTORE_ERROR;
306 return bctx->backend->delete_context(bctx->private_data);