/*
	A tool to open and traverse the dbm database that goes with
	your game, and dump out a raw report of where every object lives in
	the chunkfile, and how many bytes it takes up.
*/
#include "autoconf.h"
#include "config.h"

#include <sys/types.h>
#include <sys/file.h>
#include <stdio.h>

#ifdef HAVE_NDBM
#include <ndbm.h>
#else
#ifdef HAVE_DBM
#include <dbm.h>
#else
#include "myndbm.h"
#endif
#endif

/* This struct should match the one in udb_ochunk.c */

  struct hrec {
      off_t off;           /* Where it lives in the chunkfile */
      int siz;             /* How long it really is, in bytes */
      unsigned int blox;   /* How manu blocks it owns now     */
  };

#ifdef	HAVE_DBM
static int dbp = 0;

#else
static DBM *dbp = (DBM *) NULL;

#endif

int
main(ac, av)
int ac;
char *av[];
{
    int obj;
    datum key, dat;
    struct hrec hbuf;

    if(ac != 2) {
	fprintf(stderr, "usage: %s <database name>\n");
	exit (0);
    }
    /* open hash table */
#ifdef	HAVE_DBM
    if ((dbp = dbminit(av[1])) < 0) {
	fprintf(stderr, "Can't open dbm database %s\n", av[1]);
	exit (0);
    }
#else
    if ((dbp = dbm_open(av[1], O_RDONLY, 0600)) == (DBM *) NULL) {
	fprintf(stderr, "Can't open dbm database %s\n", av[1]);
	exit (0);
    }
#endif

#ifdef	HAVE_DBM
    key = firstkey();
#else
    key = dbm_firstkey(dbp);
#endif
    while (key.dptr != (char *) NULL) {
#ifdef	HAVE_DBM
	dat = fetch(key);
#else
	dat = dbm_fetch(dbp, key);
#endif
	if (dat.dptr == (char *) NULL) {
	    fprintf(stderr,"dbm database %s inconsistent\n", av[1]);
	    exit (0);
	}
	bcopy(dat.dptr, (char *) &hbuf, sizeof(hbuf));	/* alignment */
	bcopy(key.dptr, (char *) &obj, sizeof(obj));

	printf("Object %d resides at offset %d and takes %d bytes\n",
		obj, hbuf.off, hbuf.siz);

#ifdef	HAVE_DBM
	key = nextkey(key);
#else
	key = dbm_nextkey(dbp);
#endif
    }

    exit (1);
}
