/* This file is part of Eclat. Copyright (C) 2012-2021 Sergey Poznyakoff. Eclat is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Eclat is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Eclat. If not, see . */ #include "libeclat.h" #include #include #include #include struct gdbm_map { char *name; GDBM_FILE file; struct grecs_locus locus; int nullflag; }; static struct grecs_keyword gdbm_map_kw[] = { { "type", "'gdbm", "Set map type", grecs_type_null }, { "key", "", "key expression", grecs_type_null }, { "file", NULL, "Database file name", grecs_type_string, GRECS_DFLT, NULL, offsetof(struct gdbm_map, name) }, { "null", NULL, "Count terminating null as part of the key", grecs_type_bool, GRECS_DFLT, NULL, offsetof(struct gdbm_map, nullflag) }, { NULL } }; static void gdbm_map_free(int dbg, void *data) { struct gdbm_map *gdbm_map = data; free(gdbm_map->name); free(gdbm_map); } static void gdbm_map_confhelp() { static struct grecs_keyword gdbm_map_top[] = { { "map", "name: string", "Configuration for a GDBM map", grecs_type_section, GRECS_INAC, NULL, 0, NULL, NULL, gdbm_map_kw }, { NULL } }; grecs_print_statement_array(gdbm_map_top, 1, 0, stdout); } static int gdbm_map_config(int dbg, struct grecs_node *node, void *data) { struct gdbm_map *gdbm_map, **return_gdbm_map = data; struct grecs_node *p; int i; gdbm_map = grecs_zalloc(sizeof(*gdbm_map)); for (i = 0; gdbm_map_kw[i].ident; i++) gdbm_map_kw[i].varptr = gdbm_map; if (grecs_tree_process(node->down, gdbm_map_kw)) { gdbm_map_free(dbg, gdbm_map); return eclat_map_failure; } if (!gdbm_map->name) { grecs_error(&node->locus, 0, "file not specified"); gdbm_map_free(dbg, gdbm_map); return eclat_map_failure; } if (eclat_get_string_node(node, "file", 0, &p)) abort(); gdbm_map->locus = p->locus; *return_gdbm_map = gdbm_map; return eclat_map_ok; } static int gdbm_map_open(int dbg, void *data) { struct gdbm_map *gdbm_map = data; gdbm_map->file = gdbm_open(gdbm_map->name, 512, GDBM_READER, 0, NULL); if (gdbm_map->file == NULL) { err("cannot open database: %s", gdbm_strerror(gdbm_errno)); return eclat_map_failure; } return eclat_map_ok; } static int gdbm_map_close(int dbg, void *data) { struct gdbm_map *gdbm_map = data; gdbm_close(gdbm_map->file); return eclat_map_ok; } static int gdbm_map_get(int dbg, int dir, void *data, const char *key, char **return_value) { struct gdbm_map *gdbm_map = data; datum keydat, content; if (dir == MAP_REV) return eclat_map_bad_dir; keydat.dptr = (char*)key; keydat.dsize = strlen(key) + (gdbm_map->nullflag ? 1 : 0); gdbm_errno = 0; content = gdbm_fetch(gdbm_map->file, keydat); if (content.dptr == NULL) { if (gdbm_errno == GDBM_ITEM_NOT_FOUND) return eclat_map_not_found; err("%s: %s", gdbm_map->name, gdbm_strerror(gdbm_errno)); return eclat_map_failure; } *return_value = grecs_malloc(content.dsize + 1); memcpy(*return_value, content.dptr, content.dsize); (*return_value)[content.dsize] = 0; free (content.dptr); return eclat_map_ok; } struct eclat_map_drv eclat_map_drv_gdbm = { "gdbm", gdbm_map_config, gdbm_map_open, gdbm_map_close, gdbm_map_get, gdbm_map_free, gdbm_map_confhelp };