1166124Srafan/**************************************************************************** 2166124Srafan * Copyright (c) 2006 Free Software Foundation, Inc. * 3166124Srafan * * 4166124Srafan * Permission is hereby granted, free of charge, to any person obtaining a * 5166124Srafan * copy of this software and associated documentation files (the * 6166124Srafan * "Software"), to deal in the Software without restriction, including * 7166124Srafan * without limitation the rights to use, copy, modify, merge, publish, * 8166124Srafan * distribute, distribute with modifications, sublicense, and/or sell * 9166124Srafan * copies of the Software, and to permit persons to whom the Software is * 10166124Srafan * furnished to do so, subject to the following conditions: * 11166124Srafan * * 12166124Srafan * The above copyright notice and this permission notice shall be included * 13166124Srafan * in all copies or substantial portions of the Software. * 14166124Srafan * * 15166124Srafan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16166124Srafan * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17166124Srafan * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18166124Srafan * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19166124Srafan * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20166124Srafan * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21166124Srafan * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22166124Srafan * * 23166124Srafan * Except as contained in this notice, the name(s) of the above copyright * 24166124Srafan * holders shall not be used in advertising or otherwise to promote the * 25166124Srafan * sale, use or other dealings in this Software without prior written * 26166124Srafan * authorization. * 27166124Srafan ****************************************************************************/ 28166124Srafan 29166124Srafan/**************************************************************************** 30166124Srafan * Author: Thomas E. Dickey 2006 * 31166124Srafan ****************************************************************************/ 32166124Srafan 33166124Srafan#include <curses.priv.h> 34166124Srafan#include <tic.h> 35166124Srafan#include <hashed_db.h> 36166124Srafan 37166124Srafan#if USE_HASHED_DB 38166124Srafan 39166124SrafanMODULE_ID("$Id: hashed_db.c,v 1.13 2006/08/19 19:48:38 tom Exp $") 40166124Srafan 41166124Srafan#if HASHED_DB_API >= 2 42166124Srafanstatic DBC *cursor; 43166124Srafan#endif 44166124Srafan 45166124Srafan/* 46166124Srafan * Open the database. 47166124Srafan */ 48166124SrafanNCURSES_EXPORT(DB *) 49166124Srafan_nc_db_open(const char *path, bool modify) 50166124Srafan{ 51166124Srafan DB *result = 0; 52166124Srafan 53166124Srafan#if HASHED_DB_API >= 4 54166124Srafan db_create(&result, NULL, 0); 55166124Srafan result->open(result, 56166124Srafan NULL, 57166124Srafan path, 58166124Srafan NULL, 59166124Srafan DB_HASH, 60166124Srafan modify ? DB_CREATE : DB_RDONLY, 61166124Srafan 0644); 62166124Srafan#elif HASHED_DB_API >= 3 63166124Srafan db_create(&result, NULL, 0); 64166124Srafan result->open(result, 65166124Srafan path, 66166124Srafan NULL, 67166124Srafan DB_HASH, 68166124Srafan modify ? DB_CREATE : DB_RDONLY, 69166124Srafan 0644); 70166124Srafan#elif HASHED_DB_API >= 2 71166124Srafan int code; 72166124Srafan 73166124Srafan if ((code = db_open(path, 74166124Srafan DB_HASH, 75166124Srafan modify ? DB_CREATE : DB_RDONLY, 76166124Srafan 0644, 77166124Srafan (DB_ENV *) 0, 78166124Srafan (DB_INFO *) 0, 79166124Srafan &result)) != 0) { 80166124Srafan T(("cannot open %s: %s", path, strerror(code))); 81166124Srafan result = 0; 82166124Srafan } else { 83166124Srafan T(("opened %s", path)); 84166124Srafan } 85166124Srafan#else 86166124Srafan result = dbopen(path, 87166124Srafan modify ? (O_CREAT | O_RDWR) : O_RDONLY, 88166124Srafan 0644, 89166124Srafan DB_HASH, 90166124Srafan NULL); 91166124Srafan if (result != 0) { 92166124Srafan T(("opened %s", path)); 93166124Srafan } 94166124Srafan#endif 95166124Srafan return result; 96166124Srafan} 97166124Srafan 98166124Srafan/* 99166124Srafan * Close the database. Do not attempt to use the 'db' handle after this call. 100166124Srafan */ 101166124SrafanNCURSES_EXPORT(int) 102166124Srafan_nc_db_close(DB * db) 103166124Srafan{ 104166124Srafan int result; 105166124Srafan 106166124Srafan#if HASHED_DB_API >= 2 107166124Srafan result = db->close(db, 0); 108166124Srafan#else 109166124Srafan result = db->close(db); 110166124Srafan#endif 111166124Srafan return result; 112166124Srafan} 113166124Srafan 114166124Srafan/* 115166124Srafan * Write a record to the database. 116166124Srafan * 117166124Srafan * Returns 0 on success. 118166124Srafan * 119166124Srafan * FIXME: the FreeBSD cap_mkdb program assumes the database could have 120166124Srafan * duplicates. There appears to be no good reason for that (review/fix). 121166124Srafan */ 122166124SrafanNCURSES_EXPORT(int) 123166124Srafan_nc_db_put(DB * db, DBT * key, DBT * data) 124166124Srafan{ 125166124Srafan int result; 126166124Srafan#if HASHED_DB_API >= 2 127166124Srafan /* remove any pre-existing value, since we do not want duplicates */ 128166124Srafan (void) db->del(db, NULL, key, 0); 129166124Srafan result = db->put(db, NULL, key, data, DB_NOOVERWRITE); 130166124Srafan#else 131166124Srafan result = db->put(db, key, data, R_NOOVERWRITE); 132166124Srafan#endif 133166124Srafan return result; 134166124Srafan} 135166124Srafan 136166124Srafan/* 137166124Srafan * Read a record from the database. 138166124Srafan * 139166124Srafan * Returns 0 on success. 140166124Srafan */ 141166124SrafanNCURSES_EXPORT(int) 142166124Srafan_nc_db_get(DB * db, DBT * key, DBT * data) 143166124Srafan{ 144166124Srafan int result; 145166124Srafan 146166124Srafan memset(data, 0, sizeof(*data)); 147166124Srafan#if HASHED_DB_API >= 2 148166124Srafan result = db->get(db, NULL, key, data, 0); 149166124Srafan#else 150166124Srafan result = db->get(db, key, data, 0); 151166124Srafan#endif 152166124Srafan return result; 153166124Srafan} 154166124Srafan 155166124Srafan/* 156166124Srafan * Read the first record from the database, ignoring order. 157166124Srafan * 158166124Srafan * Returns 0 on success. 159166124Srafan */ 160166124SrafanNCURSES_EXPORT(int) 161166124Srafan_nc_db_first(DB * db, DBT * key, DBT * data) 162166124Srafan{ 163166124Srafan int result; 164166124Srafan 165166124Srafan memset(key, 0, sizeof(*key)); 166166124Srafan memset(data, 0, sizeof(*data)); 167166124Srafan#if HASHED_DB_API >= 2 168166124Srafan if ((result = db->cursor(db, NULL, &cursor, 0)) == 0) { 169166124Srafan result = cursor->c_get(cursor, key, data, DB_FIRST); 170166124Srafan } 171166124Srafan#else 172166124Srafan result = db->seq(db, key, data, 0); 173166124Srafan#endif 174166124Srafan return result; 175166124Srafan} 176166124Srafan 177166124Srafan/* 178166124Srafan * Read the next record from the database, ignoring order. 179166124Srafan * 180166124Srafan * Returns 0 on success. 181166124Srafan */ 182166124SrafanNCURSES_EXPORT(int) 183166124Srafan_nc_db_next(DB * db, DBT * key, DBT * data) 184166124Srafan{ 185166124Srafan int result; 186166124Srafan 187166124Srafan#if HASHED_DB_API >= 2 188166124Srafan (void) db; 189166124Srafan if (cursor != 0) { 190166124Srafan result = cursor->c_get(cursor, key, data, DB_NEXT); 191166124Srafan } else { 192166124Srafan result = -1; 193166124Srafan } 194166124Srafan#else 195166124Srafan result = db->seq(db, key, data, 0); 196166124Srafan#endif 197166124Srafan return result; 198166124Srafan} 199166124Srafan 200166124Srafan/* 201166124Srafan * Check if a record is a terminfo index record. Index records are those that 202166124Srafan * contain only an alias pointing to a list of aliases. 203166124Srafan */ 204166124SrafanNCURSES_EXPORT(bool) 205166124Srafan_nc_db_have_index(DBT * key, DBT * data, char **buffer, int *size) 206166124Srafan{ 207166124Srafan bool result = FALSE; 208166124Srafan int used = data->size - 1; 209166124Srafan char *have = (char *) data->data; 210166124Srafan 211166124Srafan (void) key; 212166124Srafan if (*have++ == 2) { 213166124Srafan result = TRUE; 214166124Srafan } 215166124Srafan /* 216166124Srafan * Update params in any case for consistency with _nc_db_have_data(). 217166124Srafan */ 218166124Srafan *buffer = have; 219166124Srafan *size = used; 220166124Srafan return result; 221166124Srafan} 222166124Srafan 223166124Srafan/* 224166124Srafan * Check if a record is the terminfo data record. Ignore index records, e.g., 225166124Srafan * those that contain only an alias pointing to a list of aliases. 226166124Srafan */ 227166124SrafanNCURSES_EXPORT(bool) 228166124Srafan_nc_db_have_data(DBT * key, DBT * data, char **buffer, int *size) 229166124Srafan{ 230166124Srafan bool result = FALSE; 231166124Srafan int used = data->size - 1; 232166124Srafan char *have = (char *) data->data; 233166124Srafan 234166124Srafan if (*have++ == 0) { 235166124Srafan if (data->size > key->size 236166124Srafan && IS_TIC_MAGIC(have)) { 237166124Srafan result = TRUE; 238166124Srafan } 239166124Srafan } 240166124Srafan /* 241166124Srafan * Update params in any case to make it simple to follow a index record 242166124Srafan * to the data record. 243166124Srafan */ 244166124Srafan *buffer = have; 245166124Srafan *size = used; 246166124Srafan return result; 247166124Srafan} 248166124Srafan 249166124Srafan#else 250166124Srafan 251166124Srafanextern 252166124SrafanNCURSES_EXPORT(void) 253166124Srafan_nc_hashed_db(void); 254166124Srafan 255166124SrafanNCURSES_EXPORT(void) 256166124Srafan_nc_hashed_db(void) 257166124Srafan{ 258166124Srafan} 259166124Srafan 260166124Srafan#endif /* USE_HASHED_DB */ 261