Mercurial > dovecot > core-2.2
view src/lib-dict/dict-cdb.c @ 21390:2e2563132d5f
Updated copyright notices to include the year 2017.
author | Stephan Bosch <stephan.bosch@dovecot.fi> |
---|---|
date | Wed, 11 Jan 2017 02:51:13 +0100 |
parents | 564a32262929 |
children | af8d96508fad |
line wrap: on
line source
/* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */ #include "lib.h" #ifdef BUILD_CDB #include "dict-private.h" #include <string.h> #include <cdb.h> #include <unistd.h> #include <fcntl.h> #define CDB_WITH_NULL 1 #define CDB_WITHOUT_NULL 2 struct cdb_dict { struct dict dict; struct cdb cdb; char *path; int fd, flag; }; static void cdb_dict_deinit(struct dict *_dict); static int cdb_dict_init(struct dict *driver, const char *uri, enum dict_data_type value_type ATTR_UNUSED, const char *username ATTR_UNUSED, const char *base_dir ATTR_UNUSED, struct dict **dict_r, const char **error_r) { struct cdb_dict *dict; dict = i_new(struct cdb_dict, 1); dict->dict = *driver; dict->path = i_strdup(uri); dict->flag = CDB_WITH_NULL | CDB_WITHOUT_NULL; /* initialize cdb to 0 (unallocated) */ memset(&dict->cdb, 0, sizeof(struct cdb)); dict->fd = open(dict->path, O_RDONLY); if (dict->fd == -1) { *error_r = t_strdup_printf("open(%s) failed: %m", dict->path); cdb_dict_deinit(&dict->dict); return -1; } #ifdef TINYCDB_VERSION if (cdb_init(&dict->cdb, dict->fd) < 0) { *error_r = t_strdup_printf("cdb_init(%s) failed: %m", dict->path); cdb_dict_deinit(&dict->dict); return -1; } #else cdb_init(&dict->cdb, dict->fd); #endif *dict_r = &dict->dict; return 0; } static void cdb_dict_deinit(struct dict *_dict) { struct cdb_dict *dict = (struct cdb_dict *)_dict; /* we can safely deinit unallocated cdb */ cdb_free(&dict->cdb); if (dict->fd != -1) { if (close(dict->fd) < 0) i_error("close(%s) failed: %m", dict->path); } i_free(dict->path); i_free(dict); } static int cdb_dict_lookup(struct dict *_dict, pool_t pool, const char *key, const char **value_r) { struct cdb_dict *dict = (struct cdb_dict *)_dict; unsigned datalen; int ret = 0; char *data; /* keys and values may be null terminated... */ if ((dict->flag & CDB_WITH_NULL) != 0) { ret = cdb_find(&dict->cdb, key, (unsigned)strlen(key)+1); if (ret > 0) dict->flag &= ~CDB_WITHOUT_NULL; } /* ...or not */ if (ret == 0 && (dict->flag & CDB_WITHOUT_NULL) != 0) { ret = cdb_find(&dict->cdb, key, (unsigned)strlen(key)); if (ret > 0) dict->flag &= ~CDB_WITH_NULL; } if (ret <= 0) { *value_r = NULL; /* something bad with db */ if (ret < 0) { i_error("cdb_find(%s) failed: %m", dict->path); return -1; } /* found nothing */ return 0; } datalen = cdb_datalen(&dict->cdb); data = p_malloc(pool, datalen + 1); if (cdb_read(&dict->cdb, data, datalen, cdb_datapos(&dict->cdb)) < 0) { i_error("cdb_read(%s) failed: %m", dict->path); return -1; } *value_r = data; return 1; } struct dict dict_driver_cdb = { .name = "cdb", { .init = cdb_dict_init, .deinit = cdb_dict_deinit, .lookup = cdb_dict_lookup, } }; #endif