executor/src/fauxdbm.c

283 lines
5.2 KiB
C

/* Copyright 1998 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_faux_dbm[] = "$Id: fauxdbm.c 63 2004-12-24 18:19:43Z ctm $";
#endif
/*
* The original plan was to use the Registry to simulate dbm, but
* upon sober reflection, that was decided against, since a fried
* registry equals a dead machine. Instead, we're implementing an
* incredibly hokey subset of the functionality that is tailored to
* the specific way ROMlib calls the dbm routines. Maybe we'll port
* the BSD dbm routines sometime.
*/
#include "rsys/common.h"
#if defined(CYGWIN32) || defined (MSDOS)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "rsys/fauxdbm.h"
PUBLIC DBM *
dbm_open (const char *name, int flags, int mode)
{
DBM *retval;
char *open_mode;
FILE *fp;
retval = NULL;
if (flags == O_RDONLY)
open_mode = "rb";
else
open_mode = "a+b";
fp = fopen (name, open_mode);
if (fp != NULL)
{
retval = malloc (sizeof *retval);
retval->fp = fp;
}
return retval;
}
PUBLIC datum
dbm_firstkey (DBM *file)
{
datum retval;
if (!file)
{
retval.dptr = 0;
retval.dsize = 0;
}
else
{
rewind (file->fp);
retval = dbm_nextkey (file);
}
return retval;
}
#define KEY_ID "key" /* 4 bytes long, counting NUL */
#define CONTENT_ID "content" /* 8 bytes long, counting NUL */
PRIVATE void
read_datum (DBM *file)
{
if (file)
{
char *p;
p = file->buf;
if (fread (p, 4, 1, file->fp) != 1)
*(uint32 *)p = 0;
else
{
int to_read;
to_read = sizeof KEY_ID + *(uint32 *)p;
p += 4;
while (to_read % 4)
++to_read;
if (p + to_read - file->buf <= (int) sizeof file->buf)
{
fread (p, to_read, 1, file->fp);
p += to_read;
if (fread (p, 4, 1, file->fp) != 1)
*(uint32 *)p = 0;
else
{
to_read = sizeof CONTENT_ID + *(uint32 *)p;
p += 4;
while (to_read % 4)
++to_read;
if (p + to_read - file->buf <= (int) sizeof file->buf)
fread (p, to_read, 1, file->fp);
}
}
}
}
}
PUBLIC datum
dbm_nextkey (DBM *file)
{
datum retval;
if (!file)
{
retval.dptr = 0;
retval.dsize = 0;
}
else
{
read_datum (file);
retval.dsize = *(uint32 *) file->buf;
if (retval.dsize)
retval.dptr = file->buf + sizeof (uint32) + sizeof KEY_ID;
else
retval.dptr = 0;
}
return retval;
}
PUBLIC datum
dbm_fetch (DBM *file, datum key)
{
datum retval;
int keysize;
int offset;
keysize = *(uint32 *)file->buf;
offset = sizeof (uint32) + sizeof (KEY_ID) + keysize;
while (offset % 4)
++offset;
retval.dsize = *(uint32 *)(file->buf + offset);
if (retval.dsize)
retval.dptr = file->buf + offset + sizeof (uint32) + sizeof CONTENT_ID;
else
retval.dptr = 0;
return retval;
}
#define RAW_LENGTH(datum, id) (sizeof (uint32) + sizeof (id) + datum.dsize)
#define PADDING(n) \
({ \
int _n = n; \
_n % 4 ? 4 - _n % 4 : 0; \
})
PRIVATE void
buf_from_datum (char **opp, datum d, const char *tag)
{
char *op;
op = *opp;
*(uint32 *) op = (uint32) d.dsize;
op += sizeof (uint32);
memcpy (op, tag, strlen (tag) + 1);
op += strlen (tag) + 1;
memcpy (op, d.dptr, d.dsize);
op += d.dsize;
while ((op - *opp) % 4)
++op;
*opp = op;
}
PUBLIC int
dbm_store (DBM *file, datum key, datum content, int flags)
{
int retval;
retval = -1;
if (file)
{
int key_raw_length, content_raw_length;
int key_padding , content_padding;
key_raw_length = RAW_LENGTH (key , KEY_ID);
content_raw_length = RAW_LENGTH (content, CONTENT_ID);
key_padding = PADDING (key_raw_length);
content_padding = PADDING (content_raw_length);
if (key_raw_length + key_padding + content_raw_length + content_padding
<= (int) sizeof file->buf)
{
char *op;
op = file->buf;
buf_from_datum (&op, key , KEY_ID);
buf_from_datum (&op, content, CONTENT_ID);
if (fwrite (file->buf, op - file->buf, 1, file->fp) == 1)
retval = 0;
}
}
return retval;
}
PUBLIC void
dbm_close (DBM *file)
{
if (file)
{
fclose (file->fp);
free (file);
}
}
#if 0
#define XXX(datum, size) \
do \
{ \
int i; \
char *p; \
\
datum.dsize = size; \
datum.dptr = alloca (size); \
p = datum.dptr; \
for (i = 0; i < size; ++i) \
*p++ = '0' + size; \
} \
while (0)
int
main (void)
{
DBM *db;
db = dbm_open ("/tmp/test.fauxdb", O_CREAT|O_RDWR, (LONGINT) 0666);
if (db)
{
int keysize;
for (keysize = 1; keysize < 10; ++keysize)
{
int contentsize;
for (contentsize = 0; contentsize <= 10; ++contentsize)
{
datum key, content;
XXX (key, keysize);
XXX (content, contentsize);
dbm_store (db, key, content, DBM_REPLACE);
}
}
dbm_close (db);
}
db = dbm_open ("/tmp/test.fauxdb", O_RDONLY, 0);
if (db)
{
datum key, content;
int i;
i = 0;
key = dbm_firstkey (db);
while (key.dptr)
{
if (i++ % 3)
content = dbm_fetch (db, key);
key = dbm_nextkey (db);
}
}
return 0;
}
#endif
#endif