/*
* Copyright (C) 1991, Andrew Molitor. All rights reserved.
* $Id: vms_dbm.c,v 1.2 1995/11/22 23:33:17 root Exp $
*/
/*
* #define DEBUG
*/
/*
* This a a dbm emulation module for VMS, using indexed files to do
* the database thang. It emulates new dbm.
*
*/
#include "autoconf.h"
#include <ssdef.h>
#include <rms.h>
#include "vms_dbm.h"
static char dbmbuff[MAX_RECORD];
DBM *
dbm_open(filename, flags, mode)
char *filename;
int flags; /*
* Ignored.
*/
int mode; /*
* Ignored.
*/
{
DBM *newdb;
char *name;
int status;
/*
* Make a new DBM struct
*/
#ifdef DEBUG
printf("Opening DB file %s\n", filename);
#endif
newdb = (DBM *) malloc(sizeof(struct rmsblocks));
if (newdb == (DBM *) 0) {
return ((DBM *) 0);
}
name = (char *)malloc(strlen(filename) + 1);
if (name == (char *)0) {
free((char *)newdb);
return ((DBM *) 0);
}
strcpy(name, filename);
/*
* Fill it in with stuff
*/
/*
* FAB
*/
newdb->fab = cc$rms_fab;
(newdb->fab).fab$l_fna = name;
(newdb->fab).fab$l_xab = &(newdb->xab);
(newdb->fab).fab$b_fns = strlen(name);
(newdb->fab).fab$b_bks = BUCKET_SIZE;
(newdb->fab).fab$b_org = FAB$C_IDX;
(newdb->fab).fab$w_mrs = MAX_RECORD;
(newdb->fab).fab$b_rfm = FAB$C_VAR;
(newdb->fab).fab$l_fop = FAB$M_CIF;
(newdb->fab).fab$b_fac = FAB$M_PUT | FAB$M_GET | FAB$M_UPD | FAB$M_DEL;
/*
* RAB
*/
newdb->rab = cc$rms_rab;
(newdb->rab).rab$l_fab = &(newdb->fab);
(newdb->rab).rab$b_rac = RAB$C_KEY;
(newdb->rab).rab$l_rop = RAB$V_UIF | RAB$V_LIM;
(newdb->rab).rab$l_ubf = dbmbuff;
(newdb->rab).rab$w_usz = MAX_RECORD;
/*
* XAB
*/
newdb->xab = cc$rms_xabkey;
(newdb->xab).xab$b_dtp = XAB$C_STG;
(newdb->xab).xab$w_pos = 0;
(newdb->xab).xab$b_siz = KEY_SIZE;
(newdb->xab).xab$b_ref = 0;
/*
* Try to open it
*/
status = sys$create(&(newdb->fab));
if ((status & 1) == 0) { /*
* Failed open, try to create it
*/
#ifdef DEBUG
printf("$open failed, status %d.\n", status);
#endif
goto bag;
}
/*
* We're poppin'. Connect the rab up.
*/
status = sys$connect(&(newdb->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$connect failed, status %d\n", status);
#endif
goto bag;
}
/*
* Ready to go, we hope
*/
#ifdef DEBUG
printf("Succeeded.\n");
#endif
return (newdb);
bag:
free((char *)newdb);
free((char *)name);
return ((DBM *) 0);
}
dbm_close(db)
DBM *db;
{
sys$close(&(db->fab));
free((db->fab).fab$l_fna);
free((char *)db);
}
datum
dbm_fetch(db, key)
DBM *db;
datum key;
{
int status;
int i;
datum answer;
char keybuff[KEY_SIZE];
char *p, *s;
/*
* Fill in the key part of the rab
*/
p = keybuff;
s = key.dptr;
for (i = 0; i < KEY_SIZE && i < key.dsize; i++)
*p++ = *s++;
while (i++ < KEY_SIZE)
*p++ = '\0';
(db->rab).rab$l_kbf = keybuff;
(db->rab).rab$b_ksz = KEY_SIZE;
/*
* Now go get it
*/
status = sys$get(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$get failed, status %d\n", status);
#endif
goto bag;
}
answer.dsize = (db->rab).rab$w_rsz - KEY_SIZE;
answer.dptr = malloc(answer.dsize);
if (answer.dptr == (char *)0) {
goto bag;
}
bcopy((db->rab).rab$l_rbf + KEY_SIZE, answer.dptr, answer.dsize);
return (answer);
bag:
answer.dptr = (char *)0;
answer.dsize = 0;
return (answer);
}
dbm_store(db, key, content, flags)
DBM *db;
datum key;
datum content;
int flags; /*
* Ignored
*/
{
int status;
int i;
char *p, *s;
/*
* Build the record
*/
#ifdef DEBUG
printf("dbm_store: data size = %d\n", content.dsize);
#endif
/*
* Fill in KEY_SIZE bytes of key
*/
p = dbmbuff;
s = key.dptr;
for (i = 0; i < key.dsize && i < KEY_SIZE; i++)
*p++ = *s++;
while (i++ < KEY_SIZE)
*p++ = '\0';
bcopy(content.dptr, dbmbuff + KEY_SIZE, content.dsize);
(db->rab).rab$l_rbf = dbmbuff;
(db->rab).rab$w_rsz = content.dsize + KEY_SIZE;
(db->rab).rab$l_kbf = dbmbuff;
(db->rab).rab$b_ksz = KEY_SIZE;
#ifdef DEBUG
printf("Searching for record %s, size = %d\n",
dbmbuff, (db->rab).rab$w_rsz);
#endif
status = sys$find(&(db->rab));
if (status == RMS$_NORMAL) {
status = sys$update(&(db->rab));
} else if (status == RMS$_RNF) {
#ifdef DEBUG
printf("Record not found. Trying $put %d\n", status);
#endif
status = sys$put(&(db->rab));
}
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$update/$put failed. status code %d\n", status);
#endif
return (1);
}
return (0);
}
dbm_delete(db, key)
DBM *db;
datum key;
{
int status;
int i;
datum answer;
char keybuff[KEY_SIZE];
char *p, *s;
/*
* Fill in the key part of the rab
*/
p = keybuff;
s = key.dptr;
for (i = 0; i < KEY_SIZE && i < key.dsize; i++)
*p++ = *s++;
while (i++ < KEY_SIZE)
*p++ = '\0';
(db->rab).rab$l_kbf = keybuff;
(db->rab).rab$b_ksz = KEY_SIZE;
/*
* Now go KILL it
*/
status = sys$find(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$find in delete() failed, status %d\n", status);
#endif
return (1);
}
status = sys$delete(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$delete failed, status %d\n", status);
#endif
return (1);
}
return (0);
}
datum
dbm_firstkey(db)
DBM *db;
{
int status;
datum answer;
status = sys$rewind(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$rewind failed, status == %d\n", status);
#endif
goto bag;
}
/*
* Set the file to sequential access
*/
(db->rab).rab$b_rac = RAB$C_SEQ;
status = sys$get(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$get in firstkey() failed. status = %d\n", status);
#endif
goto bag;
}
/*
* Save the key away
*/
bcopy((db->rab).rab$l_rbf, db->currkey, KEY_SIZE);
/*
* Put the file back to random access.
*/
(db->rab).rab$b_rac = RAB$C_KEY;
answer.dptr = db->currkey;
answer.dsize = strlen(db->currkey);
return (answer);
bag:
(db->rab).rab$b_rac = RAB$C_KEY;
answer.dptr = (char *)0;
answer.dsize = 0;
return (answer);
}
datum
dbm_nextkey(db)
DBM *db;
{
int status;
datum answer;
(db->rab).rab$l_kbf = db->currkey;
(db->rab).rab$b_ksz = KEY_SIZE;
/*
* Seek over to the current record
*/
status = sys$find(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$find in nextkey() failed. Status = %d\n", status);
#endif
goto bag;
}
/*
* set file sequential
*/
(db->rab).rab$b_rac = RAB$C_SEQ;
/*
* Skip one
*/
status = sys$find(&(db->rab));
if (status == RMS$_EOF) { /*
* We're done!
*/
#ifdef DEBUG
printf("EOF detected in nextkey.\n");
#endif
status = sys$rewind(&(db->rab));
#ifdef DEBUG
if ((status & 1) == 0) {
printf("$rewind at EOF, in nextkey(), failed. status = %d\n", status);
}
#endif
goto bag;
}
status = sys$get(&(db->rab));
if ((status & 1) == 0) {
#ifdef DEBUG
printf("$get in nextkey() failed. status = %d\n", status);
#endif
goto bag;
}
/*
* Save the key away
*/
bcopy((db->rab).rab$l_rbf, db->currkey, KEY_SIZE);
/*
* Put the file back to random access.
*/
(db->rab).rab$b_rac = RAB$C_KEY;
answer.dptr = db->currkey;
answer.dsize = strlen(db->currkey);
return (answer);
bag:
answer.dptr = (char *)0;
answer.dsize = 0;
/*
* Put the file back to random access.
*/
(db->rab).rab$b_rac = RAB$C_KEY;
return (answer);
}