2 * Copyright (c) 1996, 1997, 1998 Shigio Yamaguchi. All rights reserved.
4 * Redilogibution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redilogibutions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redilogibutions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the dilogibution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Shigio Yamaguchi.
15 * 4. Neither the name of the author nor the names of any co-contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/types.h>
47 static DBT key; /* key of record */
48 static DBT dat; /* data of record */
50 * dbop_open: open db database.
52 * i) dbname database name
53 * i) mode 0: read only, 1: create, 2: modify
54 * i) perm file permission
56 * DBOP_DUP: allow duplicate records.
57 * DBOP_REMOVE: remove on closed.
58 * r) descripter for dbop_xxx()
61 dbop_open(dbname, mode, perm, flags)
80 rw = O_RDWR|O_CREAT|O_TRUNC;
88 memset(&info, 0, sizeof(info));
91 info.cachesize = 500000;
94 * if unlink do job normally, those who already open tag file can use
97 if (mode == 1 && test("f", dbname))
99 db = dbopen(dbname, rw, 0600, DB_BTREE, &info);
102 if (!(dbop = (DBOP *)malloc(sizeof(DBOP))))
103 die("short of memory.");
104 strcpy(dbop->dbname, dbname);
106 dbop->openflags = flags;
107 dbop->perm = (mode == 1) ? perm : 0;
108 dbop->lastkey = NULL;
109 dbop->lastdat = NULL;
114 * dbop_get: get data by a key.
128 key.data = (char *)name;
129 key.size = strlen(name)+1;
131 status = (*db->get)(db, &key, &dat, 0);
132 dbop->lastkey = (char *)key.data;
133 dbop->lastdat = (char *)dat.data;
138 die("cannot read from database.");
142 return((char *)dat.data);
145 * dbop_put: put data by a key.
152 dbop_put(dbop, name, data)
160 if (strlen(name) > MAXKEYLEN)
161 die("primary key too long.");
162 key.data = (char *)name;
163 key.size = strlen(name)+1;
164 dat.data = (char *)data;
165 dat.size = strlen(data)+1;
167 status = (*db->put)(db, &key, &dat, 0);
173 die("cannot write to database.");
177 * dbop_del: delete record by a key.
191 key.data = (char *)name;
192 key.size = strlen(name)+1;
193 status = (*db->del)(db, &key, 0);
195 status = (*db->del)(db, &key, R_CURSOR);
196 if (status == RET_ERROR)
197 die("cannot delete record.");
200 * dbop_first: get first record.
202 * i) dbop dbop descripter
204 * !=NULL: indexed read by key
205 * ==NULL: sequential read
206 * i) flags following dbop_next call take over this.
207 * DBOP_KEY read key part
208 * DBOP_PREFIX prefix read
209 * only valied when sequential read
213 dbop_first(dbop, name, flags)
221 if (flags & DBOP_PREFIX && !name)
222 flags &= ~DBOP_PREFIX;
224 if (strlen(name) > MAXKEYLEN)
225 die("primary key too long.");
226 strcpy(dbop->key, name);
227 key.data = (char *)name;
228 key.size = strlen(name);
230 * includes NULL character unless prefix read.
232 if (!(flags & DBOP_PREFIX))
234 dbop->keylen = key.size;
235 status = (*db->seq)(db, &key, &dat, R_CURSOR);
237 dbop->keylen = dbop->key[0] = 0;
238 /* skip META records */
239 for (status = (*db->seq)(db, &key, &dat, R_FIRST);
240 status == RET_SUCCESS;
241 status = (*db->seq)(db, &key, &dat, R_NEXT)) {
242 int c = (flags & DBOP_KEY) ? *((char *)key.data) : *((char *)dat.data);
247 dbop->lastkey = (char *)key.data;
248 dbop->lastdat = (char *)dat.data;
253 die("dbop_first failed.");
257 dbop->ioflags = flags;
258 if (flags & DBOP_PREFIX) {
259 if (strncmp((char *)key.data, dbop->key, dbop->keylen))
261 } else if (dbop->keylen) {
262 if (strcmp((char *)key.data, dbop->key))
265 if (flags & DBOP_KEY) {
266 strcpy(dbop->prev, (char *)key.data);
267 return (char *)key.data;
269 return ((char *)dat.data);
272 * dbop_next: get next record.
274 * i) dbop dbop descripter
277 * Db_next always skip meta records.
284 int flags = dbop->ioflags;
287 while ((status = (*db->seq)(db, &key, &dat, R_NEXT)) == RET_SUCCESS) {
288 assert(dat.data != NULL);
289 if (flags & DBOP_KEY && *((char *)key.data) == ' ')
291 else if (*((char *)dat.data) == ' ')
293 if (flags & DBOP_KEY) {
294 if (!strcmp(dbop->prev, (char *)key.data))
296 if (strlen((char *)key.data) > MAXKEYLEN)
297 die("primary key too long.");
298 strcpy(dbop->prev, (char *)key.data);
300 dbop->lastkey = (char *)key.data;
301 dbop->lastdat = (char *)dat.data;
302 if (flags & DBOP_PREFIX) {
303 if (strncmp((char *)key.data, dbop->key, dbop->keylen))
305 } else if (dbop->keylen) {
306 if (strcmp((char *)key.data, dbop->key))
309 return (flags & DBOP_KEY) ? (char *)key.data : (char *)dat.data;
311 if (status == RET_ERROR)
312 die("dbop_next failed.");
316 * dbop_close: close db
318 * i) dbop dbop descripter
327 if (dbop->openflags & DBOP_REMOVE)
328 (void)unlink(dbop->dbname);
329 else if (dbop->perm && chmod(dbop->dbname, dbop->perm) < 0)
330 die("cannot change file mode.");