/*
* $Id: dbm_support.c,v 1.6 2002/10/17 20:02:29 ljb Exp $
* originally Id: dbm_support.c,v 1.11 1998/06/25 19:47:56 gerald Exp
*/
#include "config.h"
#ifdef USE_GDBM
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "mrt.h"
#include "trace.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <signal.h>
#include "config_file.h"
#include <fcntl.h>
#include "irrd.h"
extern trace_t *default_trace;
#include <gdbm.h>
/* irr_initialize_dbm_file
* It does not exist on disk, we need to create it
*/
GDBM_FILE irr_initialize_dbm_file (char *name) {
char file[BUFSIZE];
int value = 3000;
GDBM_FILE db;
sprintf (file, "%s/%s.dbm", IRR.database_dir, name);
/* if it's there, get rid of it. *.dbm could be corrupt or
* otherwise tainted.
*/
unlink (file);
if ((db = gdbm_open(file, 512, GDBM_NEWDB | GDBM_FAST, 0666, 0)) == NULL) {
trace (ERROR, default_trace, "Fatal error, could not open dbm file for %s\n", name);
return (NULL);
}
gdbm_setopt(db, GDBM_CACHESIZE, &value, sizeof(int));
trace (NORM, default_trace, "Initialized DBM (GDB) file for %s\n", name);
return (db);
}
/* irr_dbm_delete
* Delete a dbm entry
*/
int irr_dbm_delete (GDBM_FILE db, char *key, char *name) {
datum keydatum;
keydatum.dptr = key;
keydatum.dsize = strlen (key);
if (gdbm_delete (db, keydatum) < 0) {
trace (ERROR, default_trace, "DBM delete failed for %s\n", name);
return (-1);
}
return (1);
}
hash_item_t *irr_dbm_fetch (GDBM_FILE db, char *key) {
datum keydatum, answer;
hash_item_t *hash_item;
keydatum.dptr = key;
keydatum.dsize = strlen (key);
answer = gdbm_fetch(db, keydatum);
if (answer.dptr != NULL) {
hash_item = New (hash_item_t);
hash_item->value = malloc (answer.dsize);
memcpy (hash_item->value, answer.dptr, answer.dsize);
Delete (answer.dptr);
return (hash_item);
}
return (NULL);
}
/* irr_dbm_store
*/
int irr_dbm_store (GDBM_FILE db, u_char *key, u_char *value, int len,
char *name) {
datum key_datum, value_datum;
key_datum.dptr = key;
key_datum.dsize = strlen (key);
value_datum.dptr = value;
value_datum.dsize = len;
if (gdbm_store(db, key_datum, value_datum, GDBM_REPLACE) < 0) {
trace (ERROR, default_trace, "DBM store failed for %s\n", name);
return (-1);
}
return (1);
}
/*
* irr_open_dbm_file
* In the new IRRd way of doing things (coming soon),
* we try to open dbm file on disk first. If it exists,
* we don't bother building indicies if we are in use_disk mode.
* If we are using memory, we -- of course -- need to build indicies
* in memory.
*/
int irr_open_dbm_file (irr_database_t *database) {
char file[BUFSIZE], file_spec[BUFSIZE], *key;
hash_spec_t *hspec = NULL;
irr_hash_string_t *hash_string = NULL;
/*int value = 1000;*/
GDBM_FILE db, db_spec;
int time;
struct stat sbuf;
FILE *fp;
sprintf (file, "%s/%s.dbm", IRR.database_dir, database->name);
if ((db = gdbm_open(file, 512, GDBM_READER | GDBM_FAST | GDBM_WRITER, 0666, 0))
== NULL) {
trace (NORM, default_trace,
"Could not open dbm file for %s. Assuming we are running for first time\n",
database->name);
return (0);
}
trace (NORM, default_trace, "Opened existing DBM (GDB) file for %s\n",
database->name);
sprintf (file_spec, "%s/%s_spec.dbm", IRR.database_dir, database->name);
if ((db_spec =
gdbm_open(file_spec, 512,
GDBM_READER | GDBM_FAST | GDBM_WRITER, 0666, 0)) == NULL) {
trace (ERROR, default_trace,
"Could not open spec dbm file for %s\n", database->name);
return (0);
}
/* open database.db ASCII file */
sprintf (file, "%s/%s.db", IRR.database_dir, database->name);
if ((fp = fopen (file, "r+")) == NULL) {
trace (NORM, default_trace, "**** ERROR **** Could not open %s (%s)!\n",
file, strerror (errno));
return (0);
}
fseek (fp, 0, SEEK_SET);
database->db_fp = fp;
database->dbm = db;
database->dbm_spec = db_spec;
scan_irr_serial (database);
/* set master syntax type. We should really check all database
* agree...
* JW: not necessary. We now allow mixed db syntax types.
*/
IRR.database_syntax = database->db_syntax;
/* get the *.dbm last modification time as the 'last loaded' time */
sprintf (file, "%s/%s.dbm", IRR.database_dir, database->name);
if ((fp = fopen (file, "r")) != NULL) {
char timebuf[32];
fstat(fileno (fp), &sbuf);
database->time_loaded = sbuf.st_mtime;
#ifdef HAVE_LIBPTHREAD
ctime_r ( &database->time_loaded, timebuf);
#else
strcpy (timebuf, ctime (&database->time_loaded));
#endif /* HAVE_LIBPTHREAD */
timebuf[strlen (timebuf) -1] = '\0';
trace (NORM, default_trace, "setting db creation time (%s)...\n", timebuf);
fclose (fp);
}
else
trace (NORM, default_trace, "could not set db creation time :(\n");
return (1);
}
/* turn on fast indexing. This is fast, but dangerous if IRRd crashes... */
int dbm_fast (irr_database_t *database) {
int true = 1;
if (IRR.use_disk) {
gdbm_setopt(database->dbm, GDBM_FASTMODE, &true, sizeof(int));
gdbm_setopt(database->dbm_spec, GDBM_FASTMODE, &true, sizeof(int));
}
return (1);
}
/* turn off fast indexing. We now ask GDBM to commit everything to disk */
int dbm_slow (irr_database_t *database) {
int false = 0;
if (IRR.use_disk) {
gdbm_setopt(database->dbm, GDBM_FASTMODE, &false, sizeof(int));
gdbm_setopt(database->dbm_spec, GDBM_FASTMODE, &false, sizeof(int));
}
return (1);
}
#endif /* USE_GDBM */
syntax highlighted by Code2HTML, v. 0.9.1