/* loc.c: Interface to dbm index of object locations. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <ndbm.h>
#include <fcntl.h>
#include "log.h"
#ifdef S_IRUSR
#define READ_WRITE (S_IRUSR | S_IWUSR)
#define READ_WRITE_EXECUTE (S_IRUSR | S_IWUSR | S_IXUSR)
#else
#define READ_WRITE 0600
#define READ_WRITE_EXECUTE 0700
#endif
static DBM *dbp;
struct hbuf {
off_t offset;
int size;
};
void loc_open(char *name, int new)
{
if (new)
dbp = dbm_open(name, O_TRUNC | O_RDWR | O_CREAT, READ_WRITE);
else
dbp = dbm_open(name, O_RDWR, READ_WRITE);
if (!dbp)
fail_to_start("Cannot open dbm database file.");
}
void loc_close(void)
{
dbm_close(dbp);
}
void loc_sync(void)
{
/* Only way to do this with ndbm is close and re-open. */
dbm_close(dbp);
dbp = dbm_open("binary/index", O_RDWR | O_CREAT, READ_WRITE);
if (!dbp)
panic("Cannot reopen dbm database file.");
}
int loc_retrieve(char *name, off_t *offset, int *size)
{
datum key, dat;
struct hbuf hbuf;
/* Get the key from the database. */
key.dptr = name;
key.dsize = strlen(name) + 1;
dat = dbm_fetch(dbp, key);
if (!dat.dptr)
return 0;
/* Translate the result into offset and size. */
memcpy(&hbuf, dat.dptr, sizeof(hbuf));
*offset = hbuf.offset;
*size = hbuf.size;
return 1;
}
int loc_store(char *name, off_t offset, int size)
{
datum key, dat;
struct hbuf hbuf;
/* Set up key and data structures. */
key.dptr = name;
key.dsize = strlen(name) + 1;
hbuf.offset = offset;
hbuf.size = size;
dat.dptr = (char *) &hbuf;
dat.dsize = sizeof(hbuf);
if (dbm_store(dbp, key, dat, DBM_REPLACE)) {
write_log("ERROR: Failed to store key %s.", name);
return 0;
}
return 1;
}
int loc_remove(char *name)
{
datum key;
/* Remove the key from the database. */
key.dptr = name;
key.dsize = strlen(name) + 1;
if (dbm_delete(dbp, key)) {
write_log("ERROR: Failed to delete key %s.", name);
return 0;
}
return 1;
}
char *loc_first(void)
{
datum key;
key = dbm_firstkey(dbp);
return key.dptr;
}
char *loc_next(void)
{
datum key;
key = dbm_nextkey(dbp);
return key.dptr;
}