1102644Snectar/*
2233294Sstas * Copyright (c) 2002 Kungliga Tekniska H��gskolan
3102644Snectar * (Royal Institute of Technology, Stockholm, Sweden).
4102644Snectar * All rights reserved.
5233294Sstas *
6102644Snectar * Redistribution and use in source and binary forms, with or without
7102644Snectar * modification, are permitted provided that the following conditions
8102644Snectar * are met:
9233294Sstas *
10102644Snectar * 1. Redistributions of source code must retain the above copyright
11102644Snectar *    notice, this list of conditions and the following disclaimer.
12233294Sstas *
13102644Snectar * 2. Redistributions in binary form must reproduce the above copyright
14102644Snectar *    notice, this list of conditions and the following disclaimer in the
15102644Snectar *    documentation and/or other materials provided with the distribution.
16233294Sstas *
17102644Snectar * 3. Neither the name of the Institute nor the names of its contributors
18102644Snectar *    may be used to endorse or promote products derived from this software
19102644Snectar *    without specific prior written permission.
20233294Sstas *
21102644Snectar * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22102644Snectar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23102644Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24102644Snectar * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25102644Snectar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26102644Snectar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27102644Snectar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28102644Snectar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29102644Snectar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30102644Snectar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31102644Snectar * SUCH DAMAGE.
32102644Snectar */
33102644Snectar
34102644Snectar#include <config.h>
35102644Snectar
36102644Snectar#include "ndbm_wrap.h"
37233294Sstas#if defined(HAVE_DBHEADER)
38233294Sstas#include <db.h>
39233294Sstas#elif defined(HAVE_DB5_DB_H)
40233294Sstas#include <db5/db.h>
41233294Sstas#elif defined(HAVE_DB4_DB_H)
42102644Snectar#include <db4/db.h>
43102644Snectar#elif defined(HAVE_DB3_DB_H)
44102644Snectar#include <db3/db.h>
45102644Snectar#else
46102644Snectar#include <db.h>
47102644Snectar#endif
48102644Snectar
49102644Snectar#include <stdio.h>
50102644Snectar#include <stdlib.h>
51102644Snectar#include <string.h>
52102644Snectar#include <fcntl.h>
53102644Snectar
54178825Sdfr/* XXX undefine open so this works on Solaris with large file support */
55178825Sdfr#undef open
56102644Snectar
57102644Snectar#define DBT2DATUM(DBT, DATUM) do { (DATUM)->dptr = (DBT)->data; (DATUM)->dsize = (DBT)->size; } while(0)
58102644Snectar#define DATUM2DBT(DATUM, DBT) do { (DBT)->data = (DATUM)->dptr; (DBT)->size = (DATUM)->dsize; } while(0)
59102644Snectar#define RETURN(X) return ((X) == 0) ? 0 : -1
60102644Snectar
61102644Snectar#ifdef HAVE_DB3
62102644Snectarstatic DBC *cursor;
63102644Snectar#endif
64102644Snectar
65102644Snectar#define D(X) ((DB*)(X))
66102644Snectar
67233294SstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
68102644Snectardbm_close (DBM *db)
69102644Snectar{
70102644Snectar#ifdef HAVE_DB3
71102644Snectar    D(db)->close(D(db), 0);
72102644Snectar    cursor = NULL;
73102644Snectar#else
74102644Snectar    D(db)->close(D(db));
75102644Snectar#endif
76102644Snectar}
77102644Snectar
78233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
79102644Snectardbm_delete (DBM *db, datum dkey)
80102644Snectar{
81102644Snectar    DBT key;
82102644Snectar    DATUM2DBT(&dkey, &key);
83102644Snectar#ifdef HAVE_DB3
84102644Snectar    RETURN(D(db)->del(D(db), NULL, &key, 0));
85102644Snectar#else
86102644Snectar    RETURN(D(db)->del(D(db), &key, 0));
87102644Snectar#endif
88102644Snectar}
89102644Snectar
90102644Snectardatum
91102644Snectardbm_fetch (DBM *db, datum dkey)
92102644Snectar{
93102644Snectar    datum dvalue;
94102644Snectar    DBT key, value;
95102644Snectar    DATUM2DBT(&dkey, &key);
96233294Sstas    if(D(db)->get(D(db),
97102644Snectar#ifdef HAVE_DB3
98233294Sstas	       NULL,
99102644Snectar#endif
100178825Sdfr	       &key, &value, 0) != 0) {
101102644Snectar	dvalue.dptr = NULL;
102178825Sdfr	dvalue.dsize = 0;
103178825Sdfr    }
104102644Snectar    else
105102644Snectar	DBT2DATUM(&value, &dvalue);
106102644Snectar
107102644Snectar    return dvalue;
108102644Snectar}
109102644Snectar
110102644Snectarstatic datum
111102644Snectardbm_get (DB *db, int flags)
112102644Snectar{
113102644Snectar    DBT key, value;
114102644Snectar    datum datum;
115102644Snectar#ifdef HAVE_DB3
116233294Sstas    if(cursor == NULL)
117102644Snectar	db->cursor(db, NULL, &cursor, 0);
118178825Sdfr    if(cursor->c_get(cursor, &key, &value, flags) != 0) {
119102644Snectar	datum.dptr = NULL;
120178825Sdfr	datum.dsize = 0;
121233294Sstas    } else
122102644Snectar	DBT2DATUM(&value, &datum);
123102644Snectar#else
124102644Snectar    db->seq(db, &key, &value, flags);
125233294Sstas    DBT2DATUM(&value, &datum);
126102644Snectar#endif
127102644Snectar    return datum;
128102644Snectar}
129102644Snectar
130102644Snectar#ifndef DB_FIRST
131102644Snectar#define DB_FIRST	R_FIRST
132102644Snectar#define DB_NEXT		R_NEXT
133102644Snectar#define DB_NOOVERWRITE	R_NOOVERWRITE
134102644Snectar#define DB_KEYEXIST	1
135102644Snectar#endif
136102644Snectar
137233294SstasROKEN_LIB_FUNCTION datum ROKEN_LIB_CALL
138102644Snectardbm_firstkey (DBM *db)
139102644Snectar{
140102644Snectar    return dbm_get(D(db), DB_FIRST);
141102644Snectar}
142102644Snectar
143233294SstasROKEN_LIB_FUNCTION datum ROKEN_LIB_CALL
144102644Snectardbm_nextkey (DBM *db)
145102644Snectar{
146102644Snectar    return dbm_get(D(db), DB_NEXT);
147102644Snectar}
148102644Snectar
149233294SstasROKEN_LIB_FUNCTION DBM* ROKEN_LIB_CALL
150102644Snectardbm_open (const char *file, int flags, mode_t mode)
151102644Snectar{
152233294Sstas#ifdef HAVE_DB3
153233294Sstas    int myflags = 0;
154233294Sstas#endif
155102644Snectar    DB *db;
156102644Snectar    char *fn = malloc(strlen(file) + 4);
157102644Snectar    if(fn == NULL)
158102644Snectar	return NULL;
159102644Snectar    strcpy(fn, file);
160102644Snectar    strcat(fn, ".db");
161102644Snectar#ifdef HAVE_DB3
162102644Snectar    if (flags & O_CREAT)
163102644Snectar	myflags |= DB_CREATE;
164102644Snectar
165102644Snectar    if (flags & O_EXCL)
166102644Snectar	myflags |= DB_EXCL;
167102644Snectar
168102644Snectar    if (flags & O_RDONLY)
169102644Snectar	myflags |= DB_RDONLY;
170102644Snectar
171102644Snectar    if (flags & O_TRUNC)
172102644Snectar	myflags |= DB_TRUNCATE;
173102644Snectar    if(db_create(&db, NULL, 0) != 0) {
174102644Snectar	free(fn);
175102644Snectar	return NULL;
176102644Snectar    }
177127808Snectar
178127808Snectar#if (DB_VERSION_MAJOR > 3) && (DB_VERSION_MINOR > 0)
179127808Snectar    if(db->open(db, NULL, fn, NULL, DB_BTREE, myflags, mode) != 0) {
180127808Snectar#else
181102644Snectar    if(db->open(db, fn, NULL, DB_BTREE, myflags, mode) != 0) {
182127808Snectar#endif
183102644Snectar	free(fn);
184102644Snectar	db->close(db, 0);
185102644Snectar	return NULL;
186102644Snectar    }
187102644Snectar#else
188102644Snectar    db = dbopen(fn, flags, mode, DB_BTREE, NULL);
189102644Snectar#endif
190102644Snectar    free(fn);
191102644Snectar    return (DBM*)db;
192102644Snectar}
193102644Snectar
194233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
195102644Snectardbm_store (DBM *db, datum dkey, datum dvalue, int flags)
196102644Snectar{
197102644Snectar    int ret;
198102644Snectar    DBT key, value;
199102644Snectar    int myflags = 0;
200102644Snectar    if((flags & DBM_REPLACE) == 0)
201102644Snectar	myflags |= DB_NOOVERWRITE;
202102644Snectar    DATUM2DBT(&dkey, &key);
203233294Sstas    DATUM2DBT(&dvalue, &value);
204233294Sstas    ret = D(db)->put(D(db),
205102644Snectar#ifdef HAVE_DB3
206233294Sstas		     NULL,
207102644Snectar#endif
208102644Snectar&key, &value, myflags);
209102644Snectar    if(ret == DB_KEYEXIST)
210102644Snectar	return 1;
211102644Snectar    RETURN(ret);
212102644Snectar}
213102644Snectar
214233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
215102644Snectardbm_error (DBM *db)
216102644Snectar{
217102644Snectar    return 0;
218102644Snectar}
219102644Snectar
220233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
221102644Snectardbm_clearerr (DBM *db)
222102644Snectar{
223102644Snectar    return 0;
224102644Snectar}
225102644Snectar
226