diff options
Diffstat (limited to 'contrib/global/lib/dbop.c')
-rw-r--r-- | contrib/global/lib/dbop.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/contrib/global/lib/dbop.c b/contrib/global/lib/dbop.c new file mode 100644 index 000000000000..9bd98f328624 --- /dev/null +++ b/contrib/global/lib/dbop.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 1996, 1997, 1998 Shigio Yamaguchi. All rights reserved. + * + * Redilogibution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redilogibutions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redilogibutions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the dilogibution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Shigio Yamaguchi. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * dbop.c 12-Nov-98 + * + */ +#include <sys/types.h> +#include <sys/stat.h> + +#include <assert.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "dbop.h" +#include "die.h" +#include "test.h" + +static DBT key; /* key of record */ +static DBT dat; /* data of record */ +/* + * dbop_open: open db database. + * + * i) dbname database name + * i) mode 0: read only, 1: create, 2: modify + * i) perm file permission + * i) flags + * DBOP_DUP: allow duplicate records. + * DBOP_REMOVE: remove on closed. + * r) descripter for dbop_xxx() + */ +DBOP * +dbop_open(dbname, mode, perm, flags) +const char *dbname; +int mode; +int perm; +int flags; +{ + DB *db; + int rw = 0; + DBOP *dbop; + BTREEINFO info; + + /* + * setup argments. + */ + switch (mode) { + case 0: + rw = O_RDONLY; + break; + case 1: + rw = O_RDWR|O_CREAT|O_TRUNC; + break; + case 2: + rw = O_RDWR; + break; + default: + assert(0); + } + memset(&info, 0, sizeof(info)); + if (flags & DBOP_DUP) + info.flags |= R_DUP; + info.cachesize = 500000; + + /* + * if unlink do job normally, those who already open tag file can use + * it until closing. + */ + if (mode == 1 && test("f", dbname)) + (void)unlink(dbname); + db = dbopen(dbname, rw, 0600, DB_BTREE, &info); + if (!db) + return NULL; + if (!(dbop = (DBOP *)malloc(sizeof(DBOP)))) + die("short of memory."); + strcpy(dbop->dbname, dbname); + dbop->db = db; + dbop->openflags = flags; + dbop->perm = (mode == 1) ? perm : 0; + dbop->lastkey = NULL; + dbop->lastdat = NULL; + + return dbop; +} +/* + * dbop_get: get data by a key. + * + * i) dbop descripter + * i) name name + * r) pointer to data + */ +char * +dbop_get(dbop, name) +DBOP *dbop; +const char *name; +{ + DB *db = dbop->db; + int status; + + key.data = (char *)name; + key.size = strlen(name)+1; + + status = (*db->get)(db, &key, &dat, 0); + dbop->lastkey = (char *)key.data; + dbop->lastdat = (char *)dat.data; + switch (status) { + case RET_SUCCESS: + break; + case RET_ERROR: + die("cannot read from database."); + case RET_SPECIAL: + return (NULL); + } + return((char *)dat.data); +} +/* + * dbop_put: put data by a key. + * + * i) dbop descripter + * i) name key + * i) data data + */ +void +dbop_put(dbop, name, data) +DBOP *dbop; +const char *name; +const char *data; +{ + DB *db = dbop->db; + int status; + + if (strlen(name) > MAXKEYLEN) + die("primary key too long."); + key.data = (char *)name; + key.size = strlen(name)+1; + dat.data = (char *)data; + dat.size = strlen(data)+1; + + status = (*db->put)(db, &key, &dat, 0); + switch (status) { + case RET_SUCCESS: + break; + case RET_ERROR: + case RET_SPECIAL: + die("cannot write to database."); + } +} +/* + * dbop_del: delete record by a key. + * + * i) dbop descripter + * i) name key + */ +void +dbop_del(dbop, name) +DBOP *dbop; +const char *name; +{ + DB *db = dbop->db; + int status; + + if (name) { + key.data = (char *)name; + key.size = strlen(name)+1; + status = (*db->del)(db, &key, 0); + } else + status = (*db->del)(db, &key, R_CURSOR); + if (status == RET_ERROR) + die("cannot delete record."); +} +/* + * dbop_first: get first record. + * + * i) dbop dbop descripter + * i) name key + * !=NULL: indexed read by key + * ==NULL: sequential read + * i) flags following dbop_next call take over this. + * DBOP_KEY read key part + * DBOP_PREFIX prefix read + * only valied when sequential read + * r) data + */ +char * +dbop_first(dbop, name, flags) +DBOP *dbop; +const char *name; +int flags; +{ + DB *db = dbop->db; + int status; + + if (flags & DBOP_PREFIX && !name) + flags &= ~DBOP_PREFIX; + if (name) { + if (strlen(name) > MAXKEYLEN) + die("primary key too long."); + strcpy(dbop->key, name); + key.data = (char *)name; + key.size = strlen(name); + /* + * includes NULL character unless prefix read. + */ + if (!(flags & DBOP_PREFIX)) + key.size++; + dbop->keylen = key.size; + status = (*db->seq)(db, &key, &dat, R_CURSOR); + } else { + dbop->keylen = dbop->key[0] = 0; + /* skip META records */ + for (status = (*db->seq)(db, &key, &dat, R_FIRST); + status == RET_SUCCESS; + status = (*db->seq)(db, &key, &dat, R_NEXT)) { + int c = (flags & DBOP_KEY) ? *((char *)key.data) : *((char *)dat.data); + if (c != ' ') + break; + } + } + dbop->lastkey = (char *)key.data; + dbop->lastdat = (char *)dat.data; + switch (status) { + case RET_SUCCESS: + break; + case RET_ERROR: + die("dbop_first failed."); + case RET_SPECIAL: + return (NULL); + } + dbop->ioflags = flags; + if (flags & DBOP_PREFIX) { + if (strncmp((char *)key.data, dbop->key, dbop->keylen)) + return NULL; + } else if (dbop->keylen) { + if (strcmp((char *)key.data, dbop->key)) + return NULL; + } + if (flags & DBOP_KEY) { + strcpy(dbop->prev, (char *)key.data); + return (char *)key.data; + } + return ((char *)dat.data); +} +/* + * dbop_next: get next record. + * + * i) dbop dbop descripter + * r) data + * + * Db_next always skip meta records. + */ +char * +dbop_next(dbop) +DBOP *dbop; +{ + DB *db = dbop->db; + int flags = dbop->ioflags; + int status; + + while ((status = (*db->seq)(db, &key, &dat, R_NEXT)) == RET_SUCCESS) { + assert(dat.data != NULL); + if (flags & DBOP_KEY && *((char *)key.data) == ' ') + continue; + else if (*((char *)dat.data) == ' ') + continue; + if (flags & DBOP_KEY) { + if (!strcmp(dbop->prev, (char *)key.data)) + continue; + if (strlen((char *)key.data) > MAXKEYLEN) + die("primary key too long."); + strcpy(dbop->prev, (char *)key.data); + } + dbop->lastkey = (char *)key.data; + dbop->lastdat = (char *)dat.data; + if (flags & DBOP_PREFIX) { + if (strncmp((char *)key.data, dbop->key, dbop->keylen)) + return NULL; + } else if (dbop->keylen) { + if (strcmp((char *)key.data, dbop->key)) + return NULL; + } + return (flags & DBOP_KEY) ? (char *)key.data : (char *)dat.data; + } + if (status == RET_ERROR) + die("dbop_next failed."); + return NULL; +} +/* + * dbop_close: close db + * + * i) dbop dbop descripter + */ +void +dbop_close(dbop) +DBOP *dbop; +{ + DB *db = dbop->db; + + (void)db->close(db); + if (dbop->openflags & DBOP_REMOVE) + (void)unlink(dbop->dbname); + else if (dbop->perm && chmod(dbop->dbname, dbop->perm) < 0) + die("cannot change file mode."); + (void)free(dbop); +} |