/* Copyright (C) 1991, Andrew Molitor. All rights reserved. */ /* #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 "copyright.h" #ifndef lint static char *RCSid = "$Id: vms_dbm.c,v 1.7 1995/03/21 00:01:39 ambar Exp $"; USE(RCSid); #endif #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); }